User-specified MTP Commands to PFS Devices

This document describes PFS_ExecuteCommand(), the QNX PFS driver access function provided with the QNX Aviage Multimedia Interface for PlaysForSure. This function provides client application developers:

PFS_ExecuteCommand()

Support user-specified MTP commands to a PFS device

Synopsis

#include <pfs_userx.h>

MTP_RESULT PFS_ExecuteCommand( int fd,
                               OPCODE opCode,
                               int nSendParams,
                               MTP_UINT32 *pSendParams,
                               int handleParamNumber,
                               int nSendDataBytes,
                               MTP_UINT8 *pSendDataBytes,
                               int *pnRecvParams,
                               MTP_UINT32 *pRecvParams,
                               int *pnRecvDataBytes,
                               MTP_UINT8 *pRecvDataBytes,
                               RESPONSECODE *pResponseCode );

Arguments

fd
An open file descriptor that determines the PFS device to which the command is sent. The opened file must be a file in the PFS file system.
opCode
The 16-bit MTP operation code (see MTP specification).
nSendParams
The number of 32-bit operation parameters to send with the designated operation code. The maximum value is 5.
pSendParams
The address of an array of 32-bit operation parameters. This address is the source of the operation parameters. The number of operation parameters is indicated by nSendParams. If nSendParams is 0, then pSendParams may be NULL.
handleParamNumber
Use this parameter to have one of the operation parameters automatically set to the MTP object handle associated with the open file. Set to 0 to disable this feature. Set to 1 to cause the first operation parameter to be overwritten by the MTP handle (in general, pSendParms[handleParamNumber-1] = handle).
nSendDataBytes
The number of data bytes to send in the transfer phase. If there is no data to send, set to 0.
pSendDataBytes
The address of the buffer with the data bytes to send in the data transfer phase. If there is no data to send, this argument must be set to NULL.
pnRecvParams
A pointer to an integer specifying the maximum number of parameters expected. During input, this number is the maximum number of receive parameters expected. During output, this argument is updated to the actual number of parameters received. The maximum value for this parameter is 5.
pRecvParams
The address of an array to hold the received 32-bit response parameters. The the number of bytes written in this array is four times either the maximum number of parameters expected or the actual number of parameters received, whichever is less.
pnRecvDataBytes
A pointer to an integer specifying the maximum number of data bytes expected in the data transfer phase of the operation. During input, this number is the maximum number of data bytes to receive. During output, this number is updated to the actual number of data bytes transfer to the receive buffer. If there is no data to receive, this argument must be set to NULL.
pRecvDataBytes
The address of the buffer to receive data transferred from the PFS device. If there is no data to receive, this argument must be set to NULL.
pResponseCode
A pointer to the location where the response code received from the device is written.

Library

pfs_userx.h

Description

The function PFS_ExecuteCommand() allows applications to execute atomic MTP on PFS devices. An atomic MTP command is executed as a single transaction, which consists of the following:

  1. Send the operation code and parameters to the device.
  2. Optionally, transfer data to or from the device.
  3. Receive a response code and response parameters from the device.

PFS_ExecuteCommand() is not intended for reading of media content (i.e. execute OPCODE_GETOBJECT), and its data transfers are expected to be less than 64 kilobytes. To read media content, use the POSIX read() function.


Note:
  • The source for PFS_ExecuteCommand() is available with the function, in the file pfs_readme.txt.
  • PFS_ExecuteCommand() is not included in any QNX object libraries.

Events

None delivered.

Blocking and validation

This function validates that at least one of the data buffers (read or write) is set to NULL. It executes to completion.

Returns

MTP_RESULT_OK
Success.
MTP_ERROR_*
An error occurred. See MTP error codes below for more information.
< 0
An error occurred in a call to the system function MsgSendv(), indicating a communication error with the PFS driver (return is -errno).

MTP error codes

PFS_ExecuteCommand() relays to the client application any errors it receives from the PFS driver. The function does some parameter validation, and only explicitly returns the MTP_ERROR_INVALIDARG error code; all other error codes are generated by either the PFS driver or the PFS device itself.

The enumerated values listed below define the most common errors returned or relayed by PFS_ExecuteCommand(). For a complete list, see the MTP specification.

Classification

QNX Neutrino

Safety

Examples

The following examples show how you can use PFS_ExecuteCommand() to execute:

#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <sys/iomsg.h>
#include <fcntl.h>
#include "pfs_userx.h"

#ifndef MTP_RESULT_OK
#define MTP_RESULT_OK 0
#endif

int main(int argc, char *argv[])
{
    char         *music = "/fs/pfs0/Music";
    int           i, n, fd;
    MTP_RESULT    hr;
    MTP_UINT32    send_params[5];
    MTP_UINT32    recv_params[5];
    MTP_UINT32    nRecvParams = 1;
    MTP_UINT32    nRecvDataBytes = 0;
    MTP_UINT8    *pSendDataBytes;
    MTP_UINT8    *pRecvDataBytes;
    RESPONSECODE ResponseCode = 0;

MTP command with no data transfer



    // example 1: no data transfer, get number of objects under Music folder
    fd = open(music, O_RDONLY);
    if (fd > 0) {

        send_params[0] = 0xffffffff;  // StorageID
        send_params[1] = 0;           // ObjectFormat
        send_params[2] = 0;           // ObjectHandle (pararameter 3 to be overwritten with handle)
        nRecvParams = 1;

        hr = PFS_ExecuteCommand(fd, 0x1006,    // OPCODE_GETNUMOBJECTS

                            3,            // number of 32- bit send parameters
                            send_params,  // address of array of 32-bit send parameters

                            3,            // operation parameter to contain the object handle

                            0,            // number of data bytes to send in transfer phase
                            NULL,         // address of buffer with data bytes to send

                            &nRecvParams, // input: maximum number of receive parameters expected,
                                          // output: actual received
                            recv_params,  // address of array to hold response parameters

                            NULL,     // input: max data bytes to receive, output: actual received
                            NULL,     // address of buffer to receive data

                            &ResponseCode);     // the response code received

        printf("\nexample 1: hr=%d, RC=%04x, num_recv_parms=%d, num_objects=%d\n",
                hr, ResponseCode, nRecvParams, recv_params[0]);
        close(fd);
    }

MTP command with a transfer from the device



    // example 2: receive data, get object handles from Music directory
    fd = open(music, O_RDONLY);
    pRecvDataBytes = (MTP_UINT8 *) alloca(n = sizeof(MTP_UINT32) * 1000);
    if (pRecvDataBytes != NULL && fd > 0) {

        send_params[0] = 0xffffffff;  // StorageID
        send_params[1] = 0;           // ObjectFormat
        send_params[2] = 0;           // ObjectHandle (pararameter 3 to be overwritten with handle)
        nRecvParams = 0;
        nRecvDataBytes = n;

        hr = PFS_ExecuteCommand(fd, 0x1007,   // OPCODE_GETOBJECTHANDLES

                            3,                // number of 32-bit send parameters
                            send_params,      // address of array of 32-bit send parameters

                            3,                // operation parameter to contain the object handle

                            0,                // number of data bytes to send in transfer phase
                            NULL,             // address of buffer with data bytes to send

                            NULL,             // input: maximum number of receive parameters expected,
                                              // output: actual received
                            NULL,             // address of array to hold response parameters

                            &nRecvDataBytes,  // input: maximum data bytes to receive, output:
                                              // actual received
                            pRecvDataBytes,   // address of buffer to receive data

                            &ResponseCode);   // the response code received

        printf("\nexample 2: hr=%d, RC=%04x, num_recv_bytes=%d\n", hr, ResponseCode, nRecvDataBytes);
        n = (nRecvDataBytes - sizeof(MTP_UINT32)) / sizeof(MTP_UINT32);
        if (hr == MTP_RESULT_OK && n != 0 && n == pRecvDataBytes[0]) {
            for (i = 1; i <= n; ++i)
                printf("\n  %3d %#10x", i, ((MTP_UINT32 *) pRecvDataBytes)[i]);
        }
        printf("\n");
        close(fd);
    }

MTP command with a transfer to the device



    // example 3: send data, update the "Friendly Name" device property
    fd = open(music, O_RDONLY);
    n = 5;  // write five UNICODE16 characters
    pSendDataBytes = (MTP_UINT8 *) alloca(2*(n+1));
    if (pSendDataBytes != NULL && fd > 0) {

        send_params[0] =  0xD402;       // DEVICEPROPCODE_DEVICEFRIENDLYNAME
        pSendDataBytes[0] =  n;         // "NAME" with null has total of 5 characters
        pSendDataBytes[1] = 'N';        // 16-bit characters
        pSendDataBytes[2] =  0;         // - high bits are zero
        pSendDataBytes[3] = 'A';
        pSendDataBytes[4] =  0;
        pSendDataBytes[5] = 'M';
        pSendDataBytes[6] =  0;
        pSendDataBytes[7] = 'E';
        pSendDataBytes[8] =  0;
        pSendDataBytes[9] =  0;         // 16-bit null
        pSendDataBytes[10] = 0;

        hr = PFS_ExecuteCommand(fd, 0x1016,   // OPCODE_SETDEVICEPROPVALUE

                            1,                // number of 32-bit send parameters
                            send_params,      // address of array of 32-bit send parameters

                            0,                // operation parameter to contain the object handle

                            1+2*n,            // number of data bytes to send in transfer phase
                            pSendDataBytes,   // address of buffer with data bytes to send

                            NULL,             // input: maximum number of receive parameters expected,
                                              // output: actual received
                            NULL,             // address of array to hold response parameters

                            NULL,             // input: maximum data bytes to receive, output: actual received
                            NULL,             // address of buffer to receive data

                            &ResponseCode);   // the response code received

        printf("\nexample 3: hr=%d, RC=%04x\n", hr, ResponseCode);
        close(fd);
    }
    return 0;
}