* ptp-pack.c: fixed a bug in ptp_unpack_DI(), totallen could be bigger than uint8_t * library.c: added camera summary git-svn-id: https://svn.code.sf.net/p/gphoto/code/trunk/libgphoto2@6015 67ed7778-7388-44ab-90cf-0a291f65f57c
785 lines
20 KiB
C
785 lines
20 KiB
C
/* ptp.c
|
|
*
|
|
* Copyright (C) 2001 Mariusz Woloszyn <emsi@ipartners.pl>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
* Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include <config.h>
|
|
#include "ptp.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#ifdef ENABLE_NLS
|
|
# include <libintl.h>
|
|
# undef _
|
|
# define _(String) dgettext (PACKAGE, String)
|
|
# ifdef gettext_noop
|
|
# define N_(String) gettext_noop (String)
|
|
# else
|
|
# define N_(String) (String)
|
|
# endif
|
|
#else
|
|
# define textdomain(String) (String)
|
|
# define gettext(String) (String)
|
|
# define dgettext(Domain,Message) (Message)
|
|
# define dcgettext(Domain,Message,Type) (Message)
|
|
# define bindtextdomain(Domain,Directory) (Domain)
|
|
# define _(String) (String)
|
|
# define N_(String) (String)
|
|
#endif
|
|
|
|
#define CHECK_PTP_RC(result) {uint16_t r=(result); if (r!=PTP_RC_OK) return r;}
|
|
|
|
#define PTP_CNT_INIT(cnt) {memset(&cnt,0,sizeof(cnt));}
|
|
|
|
static void
|
|
ptp_debug (PTPParams *params, const char *format, ...)
|
|
{
|
|
va_list args;
|
|
|
|
va_start (args, format);
|
|
if (params->debug_func)
|
|
params->debug_func (params->data, format, args);
|
|
else
|
|
vfprintf (stderr, format, args);
|
|
va_end (args);
|
|
}
|
|
|
|
static void
|
|
ptp_error (PTPParams *params, const char *format, ...)
|
|
{
|
|
va_list args;
|
|
|
|
va_start (args, format);
|
|
if (params->error_func)
|
|
params->error_func (params->data, format, args);
|
|
else
|
|
vfprintf (stderr, format, args);
|
|
va_end (args);
|
|
}
|
|
|
|
// Pack / unpack functions
|
|
|
|
#include "ptp-pack.c"
|
|
|
|
// send / receive functions
|
|
|
|
uint16_t
|
|
ptp_usb_sendreq (PTPParams* params, PTPContainer* req)
|
|
{
|
|
uint16_t ret;
|
|
PTPUSBBulkContainer usbreq;
|
|
|
|
/* build appropriate USB container */
|
|
usbreq.length=htod32(PTP_USB_BULK_REQ_LEN);
|
|
usbreq.type=htod16(PTP_USB_CONTAINER_COMMAND);
|
|
usbreq.code=htod16(req->Code);
|
|
usbreq.trans_id=htod32(req->Transaction_ID);
|
|
usbreq.payload.params.param1=htod32(req->Param1);
|
|
usbreq.payload.params.param2=htod32(req->Param2);
|
|
usbreq.payload.params.param3=htod32(req->Param3);
|
|
usbreq.payload.params.param4=htod32(req->Param4);
|
|
usbreq.payload.params.param5=htod32(req->Param5);
|
|
/* send it to responder */
|
|
ret=params->write_func((unsigned char *)&usbreq,PTP_USB_BULK_REQ_LEN,
|
|
params->data);
|
|
if (ret!=PTP_RC_OK) {
|
|
ret = PTP_ERROR_IO;
|
|
ptp_error (params,
|
|
"PTP: request code 0x%4x sending req error 0x%.2x",
|
|
req->Code,ret);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
uint16_t
|
|
ptp_usb_senddata (PTPParams* params, PTPContainer* ptp,
|
|
unsigned char *data, unsigned int size)
|
|
{
|
|
uint16_t ret;
|
|
PTPUSBBulkContainer usbdata;
|
|
|
|
/* build appropriate USB container */
|
|
usbdata.length=htod32(PTP_USB_BULK_HDR_LEN+size);
|
|
usbdata.type=htod16(PTP_USB_CONTAINER_DATA);
|
|
usbdata.code=htod16(ptp->Code);
|
|
usbdata.trans_id=htod32(ptp->Transaction_ID);
|
|
memcpy(usbdata.payload.data,data,
|
|
(size<PTP_USB_BULK_PAYLOAD_LEN)?size:PTP_USB_BULK_PAYLOAD_LEN);
|
|
/* send first part of data */
|
|
ret=params->write_func((unsigned char *)&usbdata, PTP_USB_BULK_HDR_LEN+
|
|
((size<PTP_USB_BULK_PAYLOAD_LEN)?size:PTP_USB_BULK_PAYLOAD_LEN),
|
|
params->data);
|
|
if (ret!=PTP_RC_OK) {
|
|
ret = PTP_ERROR_IO;
|
|
ptp_error (params,
|
|
"PTP: request code 0x%4x sending data error 0x%.2x",
|
|
ptp->Code,ret);
|
|
return ret;
|
|
}
|
|
if (size<=PTP_USB_BULK_PAYLOAD_LEN) return ret;
|
|
/* if everything OK send the rest */
|
|
ret=params->write_func (data+PTP_USB_BULK_PAYLOAD_LEN,
|
|
size-PTP_USB_BULK_PAYLOAD_LEN, params->data);
|
|
if (ret!=PTP_RC_OK) {
|
|
ret = PTP_ERROR_IO;
|
|
ptp_error (params,
|
|
"PTP: request code 0x%4x sending data error 0x%.2x",
|
|
ptp->Code,ret);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
uint16_t
|
|
ptp_usb_getdata (PTPParams* params, PTPContainer* ptp,
|
|
unsigned char **data)
|
|
{
|
|
uint16_t ret;
|
|
PTPUSBBulkContainer usbdata;
|
|
|
|
PTP_CNT_INIT(usbdata);
|
|
if (*data!=NULL) return PTP_ERROR_BADPARAM;
|
|
do {
|
|
unsigned int len;
|
|
/* read first(?) part of data */
|
|
ret=params->read_func((unsigned char *)&usbdata,
|
|
sizeof(usbdata), params->data);
|
|
if (ret!=PTP_RC_OK) {
|
|
ret = PTP_ERROR_IO;
|
|
break;
|
|
} else
|
|
if (dtoh16(usbdata.type)!=PTP_USB_CONTAINER_DATA) {
|
|
ret = PTP_ERROR_DATA_EXPECTED;
|
|
break;
|
|
} else
|
|
if (dtoh16(usbdata.code)!=ptp->Code) {
|
|
ret = dtoh16(usbdata.code);
|
|
break;
|
|
}
|
|
/* evaluate data length */
|
|
len=dtoh32(usbdata.length)-PTP_USB_BULK_HDR_LEN;
|
|
/* allocate memory for data */
|
|
*data=calloc(len,1);
|
|
/* copy first part of data to 'data' */
|
|
memcpy(*data,usbdata.payload.data,len);
|
|
/* is that all of data? */
|
|
if (len+PTP_USB_BULK_HDR_LEN<=sizeof(usbdata)) break;
|
|
/* if not finaly read the rest of it */
|
|
ret=params->read_func(((unsigned char *)(*data))+
|
|
PTP_USB_BULK_PAYLOAD_LEN,
|
|
len-PTP_USB_BULK_PAYLOAD_LEN,
|
|
params->data);
|
|
} while (0);
|
|
if (ret!=PTP_RC_OK) {
|
|
ptp_error (params,
|
|
"PTP: request code %4x container receive error %4x",
|
|
ptp->Code, ret);
|
|
ret = PTP_ERROR_IO;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
uint16_t
|
|
ptp_usb_getresp (PTPParams* params, PTPContainer* resp)
|
|
{
|
|
uint16_t ret;
|
|
PTPUSBBulkContainer usbresp;
|
|
|
|
PTP_CNT_INIT(usbresp);
|
|
/* read response, it should never be longer than sizeof(usbresp) */
|
|
ret=params->read_func((unsigned char *)&usbresp,
|
|
sizeof(usbresp), params->data);
|
|
|
|
if (ret!=PTP_RC_OK) {
|
|
ret = PTP_ERROR_IO;
|
|
} else
|
|
if (dtoh16(usbresp.type)!=PTP_USB_CONTAINER_RESPONSE) {
|
|
ret = PTP_ERROR_RESP_EXPECTED;
|
|
} else
|
|
if (dtoh16(usbresp.code)!=resp->Code) {
|
|
ret = dtoh16(usbresp.code);
|
|
}
|
|
if (ret!=PTP_RC_OK) {
|
|
ptp_error (params,
|
|
"PTP: request code 0x%4x getting resp error 0x%4x",
|
|
resp->Code, ret);
|
|
return ret;
|
|
}
|
|
/* build an appropriate PTPContainer */
|
|
resp->Code=dtoh16(usbresp.code);
|
|
resp->SessionID=params->session_id;
|
|
resp->Transaction_ID=dtoh32(usbresp.trans_id);
|
|
resp->Param1=dtoh32(usbresp.payload.params.param1);
|
|
resp->Param2=dtoh32(usbresp.payload.params.param2);
|
|
resp->Param3=dtoh32(usbresp.payload.params.param3);
|
|
resp->Param4=dtoh32(usbresp.payload.params.param4);
|
|
resp->Param5=dtoh32(usbresp.payload.params.param5);
|
|
return ret;
|
|
}
|
|
|
|
// major PTP functions
|
|
|
|
// Transaction data phase description
|
|
#define PTP_DP_NODATA 0x0000 // No Data Phase
|
|
#define PTP_DP_SENDDATA 0x0001 // sending data
|
|
#define PTP_DP_GETDATA 0x0002 // geting data
|
|
#define PTP_DP_DATA_MASK 0x00ff // data phase mask
|
|
|
|
// Number of PTP Request phase parameters
|
|
#define PTP_RQ_PARAM0 0x0000 // zero parameters
|
|
#define PTP_RQ_PARAM1 0x0100 // one parameter
|
|
#define PTP_RQ_PARAM2 0x0200 // two parameters
|
|
#define PTP_RQ_PARAM3 0x0300 // three parameters
|
|
#define PTP_RQ_PARAM4 0x0400 // four parameters
|
|
#define PTP_RQ_PARAM5 0x0500 // five parameters
|
|
|
|
/**
|
|
* ptp_transaction:
|
|
* params: PTPParams*
|
|
* PTPContainer* ptp - general ptp container
|
|
* uint16_t flags - lower 8 bits - data phase description
|
|
* unsigned int sendlen - senddata phase data length
|
|
* char** data - send or receive data buffer pointer
|
|
*
|
|
* Performs PTP transaction. ptp is a PTPContainer with appropriate fields
|
|
* filled in (i.e. operation code and parameters). It's up to caller to do
|
|
* so.
|
|
* The flags decide thether the transaction has a data phase and what is its
|
|
* direction (send or receive).
|
|
* If transaction is sending data the sendlen should contain its length in
|
|
* bytes, otherwise it's ignored.
|
|
* The data should contain an address of a pointer to data going to be sent
|
|
* or is filled with such a pointer address if data are received depending
|
|
* od dataphase direction (send or received) or is beeing ignored (no
|
|
* dataphase).
|
|
* The memory for a pointer should be preserved by the caller, if data are
|
|
* beeing retreived the appropriate amount of memory is beeing allocated
|
|
* (the caller should handle that!).
|
|
*
|
|
* Return values: Some PTP_RC_* code.
|
|
* Upon success PTPContainer* ptp contains PTP Response Phase container with
|
|
* all fields filled in.
|
|
**/
|
|
static uint16_t
|
|
ptp_transaction (PTPParams* params, PTPContainer* ptp,
|
|
uint16_t flags, unsigned int sendlen, char** data)
|
|
{
|
|
if ((params==NULL) || (ptp==NULL))
|
|
return PTP_ERROR_BADPARAM;
|
|
|
|
ptp->Transaction_ID=params->transaction_id++;
|
|
ptp->SessionID=params->session_id;
|
|
// send request
|
|
CHECK_PTP_RC(params->sendreq_func (params, ptp));
|
|
// is there a dataphase?
|
|
switch (flags&PTP_DP_DATA_MASK) {
|
|
case PTP_DP_SENDDATA:
|
|
CHECK_PTP_RC(params->senddata_func(params, ptp,
|
|
*data, sendlen));
|
|
break;
|
|
case PTP_DP_GETDATA:
|
|
CHECK_PTP_RC(params->getdata_func(params, ptp,
|
|
(unsigned char**)data));
|
|
break;
|
|
case PTP_DP_NODATA:
|
|
break;
|
|
default:
|
|
return PTP_ERROR_BADPARAM;
|
|
}
|
|
// get response
|
|
CHECK_PTP_RC(params->getresp_func(params, ptp));
|
|
return PTP_RC_OK;
|
|
}
|
|
|
|
// Enets handling functions
|
|
|
|
// PTP Events wait for or check mode
|
|
#define PTP_EVENT_CHECK 0x0000 // waits for
|
|
#define PTP_EVENT_CHECK_FAST 0x0001 // checks
|
|
|
|
static inline uint16_t
|
|
ptp_usb_event (PTPParams* params, PTPContainer* event, int wait)
|
|
{
|
|
uint16_t ret;
|
|
PTPUSBEventContainer usbevent;
|
|
|
|
if ((params==NULL) || (event==NULL))
|
|
return PTP_ERROR_BADPARAM;
|
|
|
|
switch(wait) {
|
|
case PTP_EVENT_CHECK:
|
|
ret=params->check_int_func((unsigned char*)&usbevent,
|
|
sizeof(usbevent), params->data);
|
|
break;
|
|
case PTP_EVENT_CHECK_FAST:
|
|
ret=params->check_int_fast_func((unsigned char*)
|
|
&usbevent, sizeof(usbevent), params->data);
|
|
break;
|
|
default:
|
|
ret=PTP_ERROR_BADPARAM;
|
|
}
|
|
if (ret!=PTP_RC_OK) {
|
|
ret = PTP_ERROR_IO;
|
|
ptp_error (params,
|
|
"PTP: reading event an error 0x%4x occured", ret);
|
|
/* reading event error is nonfatal (for example timeout) */
|
|
}
|
|
/* if we read anything over interrupt endpoint it must be an event */
|
|
/* build an appropriate PTPContainer */
|
|
PTP_CNT_INIT(event);
|
|
event->Code=dtoh16(usbevent.code);
|
|
event->SessionID=params->session_id;
|
|
event->Transaction_ID=dtoh32(usbevent.trans_id);
|
|
event->Param1=dtoh32(usbevent.param1);
|
|
event->Param2=dtoh32(usbevent.param2);
|
|
event->Param3=dtoh32(usbevent.param3);
|
|
|
|
return ret;
|
|
}
|
|
|
|
uint16_t
|
|
ptp_usb_event_check (PTPParams* params, PTPContainer* event) {
|
|
|
|
return ptp_usb_event (params, event, PTP_EVENT_CHECK_FAST);
|
|
}
|
|
|
|
uint16_t
|
|
ptp_usb_event_wait (PTPParams* params, PTPContainer* event) {
|
|
|
|
return ptp_usb_event (params, event, PTP_EVENT_CHECK);
|
|
}
|
|
|
|
/**
|
|
* PTP operation functions
|
|
*
|
|
* all ptp_ functions should take integer parameters
|
|
* in host byte order!
|
|
**/
|
|
|
|
|
|
/**
|
|
* ptp_getdeviceinfo:
|
|
* params: PTPParams*
|
|
*
|
|
* Gets device info dataset and fills deviceinfo structure.
|
|
*
|
|
* Return values: Some PTP_RC_* code.
|
|
**/
|
|
uint16_t
|
|
ptp_getdeviceinfo (PTPParams* params, PTPDeviceInfo* deviceinfo)
|
|
{
|
|
uint16_t ret;
|
|
PTPContainer ptp;
|
|
char* di=NULL;
|
|
|
|
PTP_CNT_INIT(ptp);
|
|
ptp.Code=PTP_OC_GetDeviceInfo;
|
|
ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &di);
|
|
ptp_unpack_DI(params, di, deviceinfo);
|
|
free(di);
|
|
return ret;
|
|
}
|
|
|
|
|
|
/**
|
|
* ptp_opensession:
|
|
* params: PTPParams*
|
|
* session - session number
|
|
*
|
|
* Establishes a new session.
|
|
*
|
|
* Return values: Some PTP_RC_* code.
|
|
**/
|
|
uint16_t
|
|
ptp_opensession (PTPParams* params, uint32_t session)
|
|
{
|
|
uint16_t ret;
|
|
PTPContainer ptp;
|
|
|
|
ptp_debug(params,"PTP: Opening session");
|
|
|
|
/* SessonID field of the operation dataset should be set allways
|
|
set to 0 for OpenSession request */
|
|
params->session_id=0x00000000;
|
|
/* TransactionID should be set to 0 also */
|
|
params->transaction_id=0x0000000;
|
|
|
|
PTP_CNT_INIT(ptp);
|
|
ptp.Code=PTP_OC_OpenSession;
|
|
ptp.Param1=session;
|
|
ret=ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL);
|
|
/* now set the global session id to current session number */
|
|
params->session_id=session;
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* ptp_closesession:
|
|
* params: PTPParams*
|
|
*
|
|
* Closes session.
|
|
*
|
|
* Return values: Some PTP_RC_* code.
|
|
**/
|
|
uint16_t
|
|
ptp_closesession (PTPParams* params)
|
|
{
|
|
PTPContainer ptp;
|
|
|
|
ptp_debug(params,"PTP: Closing session");
|
|
|
|
PTP_CNT_INIT(ptp);
|
|
ptp.Code=PTP_OC_CloseSession;
|
|
return ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL);
|
|
}
|
|
|
|
/**
|
|
* ptp_getststorageids:
|
|
* params: PTPParams*
|
|
*
|
|
* Gets array of StorageiDs and fills the storageids structure.
|
|
*
|
|
* Return values: Some PTP_RC_* code.
|
|
**/
|
|
uint16_t
|
|
ptp_getstorageids (PTPParams* params, PTPStorageIDs* storageids)
|
|
{
|
|
uint16_t ret;
|
|
PTPContainer ptp;
|
|
char* sids=NULL;
|
|
|
|
PTP_CNT_INIT(ptp);
|
|
ptp.Code=PTP_OC_GetStorageIDs;
|
|
ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &sids);
|
|
ptp_unpack_SIDs(params, sids, storageids);
|
|
free(sids);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* ptp_getststorageinfo:
|
|
* params: PTPParams*
|
|
* storageid - StorageID
|
|
*
|
|
* Gets StorageInfo dataset of desired storage and fills storageinfo
|
|
* structure.
|
|
*
|
|
* Return values: Some PTP_RC_* code.
|
|
**/
|
|
uint16_t
|
|
ptp_getstorageinfo (PTPParams* params, uint32_t storageid,
|
|
PTPStorageInfo* storageinfo)
|
|
{
|
|
uint16_t ret;
|
|
PTPContainer ptp;
|
|
char* si=NULL;
|
|
|
|
PTP_CNT_INIT(ptp);
|
|
ptp.Code=PTP_OC_GetStorageInfo;
|
|
ptp.Param1=storageid;
|
|
ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &si);
|
|
ptp_unpack_SI(params, si, storageinfo);
|
|
free(si);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* ptp_getobjecthandles:
|
|
* params: PTPParams*
|
|
* storage - StorageID
|
|
* objectformatcode - ObjectFormatCode (optional)
|
|
* associationOH - ObjectHandle of Association for
|
|
* wich a list of children is desired
|
|
* (optional)
|
|
* objecthandles - pointer to structute
|
|
*
|
|
* Fills objecthandles with structure returned by device.
|
|
*
|
|
* Return values: Some PTP_RC_* code.
|
|
**/
|
|
uint16_t
|
|
ptp_getobjecthandles (PTPParams* params, uint32_t storage,
|
|
uint32_t objectformatcode, uint32_t associationOH,
|
|
PTPObjectHandles* objecthandles)
|
|
{
|
|
uint16_t ret;
|
|
PTPContainer ptp;
|
|
char* oh=NULL;
|
|
|
|
PTP_CNT_INIT(ptp);
|
|
ptp.Code=PTP_OC_GetObjectHandles;
|
|
ptp.Param1=storage;
|
|
ptp.Param2=objectformatcode;
|
|
ptp.Param3=associationOH;
|
|
ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &oh);
|
|
ptp_unpack_OH(params, oh, objecthandles);
|
|
free(oh);
|
|
return ret;
|
|
}
|
|
|
|
uint16_t
|
|
ptp_getobjectinfo (PTPParams* params, uint32_t handle,
|
|
PTPObjectInfo* objectinfo)
|
|
{
|
|
uint16_t ret;
|
|
PTPContainer ptp;
|
|
char* oi=NULL;
|
|
|
|
PTP_CNT_INIT(ptp);
|
|
ptp.Code=PTP_OC_GetObjectInfo;
|
|
ptp.Param1=handle;
|
|
ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &oi);
|
|
ptp_unpack_OI(params, oi, objectinfo);
|
|
free(oi);
|
|
return ret;
|
|
}
|
|
|
|
uint16_t
|
|
ptp_getobject (PTPParams* params, uint32_t handle, char** object)
|
|
{
|
|
PTPContainer ptp;
|
|
|
|
PTP_CNT_INIT(ptp);
|
|
ptp.Code=PTP_OC_GetObject;
|
|
ptp.Param1=handle;
|
|
return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, object);
|
|
}
|
|
|
|
|
|
uint16_t
|
|
ptp_getthumb (PTPParams* params, uint32_t handle, char** object)
|
|
{
|
|
PTPContainer ptp;
|
|
|
|
PTP_CNT_INIT(ptp);
|
|
ptp.Code=PTP_OC_GetThumb;
|
|
ptp.Param1=handle;
|
|
return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, object);
|
|
}
|
|
|
|
/**
|
|
* ptp_deleteobject:
|
|
* params: PTPParams*
|
|
* handle - object handle
|
|
* ofc - object format code (optional)
|
|
*
|
|
* Deletes desired objects.
|
|
*
|
|
* Return values: Some PTP_RC_* code.
|
|
**/
|
|
uint16_t
|
|
ptp_deleteobject (PTPParams* params, uint32_t handle,
|
|
uint32_t ofc)
|
|
{
|
|
PTPContainer ptp;
|
|
|
|
PTP_CNT_INIT(ptp);
|
|
ptp.Code=PTP_OC_DeleteObject;
|
|
ptp.Param1=handle;
|
|
ptp.Param2=ofc;
|
|
return ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL);
|
|
}
|
|
|
|
/**
|
|
* ptp_sendobjectinfo:
|
|
* params: PTPParams*
|
|
* uint32_t* store - destination StorageID on Responder
|
|
* uint32_t* parenthandle - Parent ObjectHandle on responder
|
|
* uint32_t* handle - see Return values
|
|
* PTPObjectInfo* objectinfo- ObjectInfo that is to be sent
|
|
*
|
|
* Sends ObjectInfo of file that is to be sent via SendFileObject.
|
|
*
|
|
* Return values: Some PTP_RC_* code.
|
|
* Upon success : uint32_t* store - Responder StorageID in which
|
|
* object will be stored
|
|
* uint32_t* parenthandle- Responder Parent ObjectHandle
|
|
* in which the object will be stored
|
|
* uint32_t* handle - Responder's reserved ObjectHandle
|
|
* for the incoming object
|
|
**/
|
|
uint16_t
|
|
ptp_sendobjectinfo (PTPParams* params, uint32_t* store,
|
|
uint32_t* parenthandle, uint32_t* handle,
|
|
PTPObjectInfo* objectinfo)
|
|
{
|
|
uint16_t ret;
|
|
PTPContainer ptp;
|
|
char* oidata=NULL;
|
|
uint32_t size;
|
|
|
|
PTP_CNT_INIT(ptp);
|
|
ptp.Code=PTP_OC_SendObjectInfo;
|
|
ptp.Param1=*store;
|
|
ptp.Param2=*parenthandle;
|
|
|
|
size=ptp_pack_OI(params, objectinfo, &oidata);
|
|
ret=ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &oidata);
|
|
free(oidata);
|
|
*store=ptp.Param1;
|
|
*parenthandle=ptp.Param2;
|
|
*handle=ptp.Param3;
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* ptp_sendobject:
|
|
* params: PTPParams*
|
|
* char* object - contains the object that is to be sent
|
|
* uint32_t size - object size
|
|
*
|
|
* Sends object to Responder.
|
|
*
|
|
* Return values: Some PTP_RC_* code.
|
|
*
|
|
*/
|
|
uint16_t
|
|
ptp_sendobject (PTPParams* params, char* object, uint32_t size)
|
|
{
|
|
PTPContainer ptp;
|
|
|
|
PTP_CNT_INIT(ptp);
|
|
ptp.Code=PTP_OC_SendObject;
|
|
|
|
return ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &object);
|
|
}
|
|
|
|
|
|
/**
|
|
* ptp_initiatecapture:
|
|
* params: PTPParams*
|
|
* storageid - destination StorageID on Responder
|
|
* ofc - object format code
|
|
*
|
|
* Causes device to initiate the capture of one or more new data objects
|
|
* according to its current device properties, storing the data into store
|
|
* indicated by storageid. If storageid is 0x00000000, the object(s) will
|
|
* be stored in a store that is determined by the capturing device.
|
|
* The capturing of new data objects is an asynchronous operation.
|
|
*
|
|
* Return values: Some PTP_RC_* code.
|
|
**/
|
|
|
|
uint16_t
|
|
ptp_initiatecapture (PTPParams* params, uint32_t storageid,
|
|
uint32_t ofc)
|
|
{
|
|
PTPContainer ptp;
|
|
|
|
PTP_CNT_INIT(ptp);
|
|
ptp.Code=PTP_OC_InitiateCapture;
|
|
ptp.Param1=storageid;
|
|
ptp.Param2=ofc;
|
|
return ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL);
|
|
}
|
|
|
|
|
|
/**
|
|
* ptp_ek_sendfileobjectinfo:
|
|
* params: PTPParams*
|
|
* uint32_t* store - destination StorageID on Responder
|
|
* uint32_t* parenthandle - Parent ObjectHandle on responder
|
|
* uint32_t* handle - see Return values
|
|
* PTPObjectInfo* objectinfo- ObjectInfo that is to be sent
|
|
*
|
|
* Sends ObjectInfo of file that is to be sent via SendFileObject.
|
|
*
|
|
* Return values: Some PTP_RC_* code.
|
|
* Upon success : uint32_t* store - Responder StorageID in which
|
|
* object will be stored
|
|
* uint32_t* parenthandle- Responder Parent ObjectHandle
|
|
* in which the object will be stored
|
|
* uint32_t* handle - Responder's reserved ObjectHandle
|
|
* for the incoming object
|
|
**/
|
|
uint16_t
|
|
ptp_ek_sendfileobjectinfo (PTPParams* params, uint32_t* store,
|
|
uint32_t* parenthandle, uint32_t* handle,
|
|
PTPObjectInfo* objectinfo)
|
|
{
|
|
uint16_t ret;
|
|
PTPContainer ptp;
|
|
char* oidata=NULL;
|
|
uint32_t size;
|
|
|
|
PTP_CNT_INIT(ptp);
|
|
ptp.Code=PTP_OC_EK_SendFileObjectInfo;
|
|
ptp.Param1=*store;
|
|
ptp.Param2=*parenthandle;
|
|
|
|
size=ptp_pack_OI(params, objectinfo, &oidata);
|
|
ret=ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &oidata);
|
|
free(oidata);
|
|
*store=ptp.Param1;
|
|
*parenthandle=ptp.Param2;
|
|
*handle=ptp.Param3;
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* ptp_ek_sendfileobject:
|
|
* params: PTPParams*
|
|
* char* object - contains the object that is to be sent
|
|
* uint32_t size - object size
|
|
*
|
|
* Sends object to Responder.
|
|
*
|
|
* Return values: Some PTP_RC_* code.
|
|
*
|
|
*/
|
|
uint16_t
|
|
ptp_ek_sendfileobject (PTPParams* params, char* object, uint32_t size)
|
|
{
|
|
PTPContainer ptp;
|
|
|
|
PTP_CNT_INIT(ptp);
|
|
ptp.Code=PTP_OC_EK_SendFileObject;
|
|
|
|
return ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &object);
|
|
}
|
|
|
|
|
|
/* devinfo testing functions */
|
|
|
|
int
|
|
ptp_operation_issupported(PTPParams* params, uint16_t operation)
|
|
{
|
|
int i=0;
|
|
|
|
for (;i<params->deviceinfo.OperationsSupported_len;i++) {
|
|
if (params->deviceinfo.OperationsSupported[i]==operation)
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
int
|
|
ptp_property_issupported(PTPParams* params, uint16_t property)
|
|
{
|
|
int i=0;
|
|
|
|
for (;i<params->deviceinfo.DevicePropertiesSupported_len;i++) {
|
|
if (params->deviceinfo.DevicePropertiesSupported[i]==property)
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|