API changes from libgphoto2.
diff --git a/ChangeLog b/ChangeLog
index d1ed9bb..baa011b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2006-12-29 Marcus Meissner <[email protected]>
+
+ * src/ptp.h: API changes for libgphoto2 to use the file
+ retrieveal functions.
+ * src/ptp.c: dito.
+ * src/libusb-glue.c: changes in libmtp reflecting the new
+ API for libgphoto2.
+
2006-12-28 Linus Walleij <[email protected]>
* configure.ac: making older autotools happy. Bump to 0.1.1.
diff --git a/src/libusb-glue.c b/src/libusb-glue.c
index ce67276..6abaa7b 100644
--- a/src/libusb-glue.c
+++ b/src/libusb-glue.c
@@ -222,9 +222,9 @@
static void find_endpoints(struct usb_device *dev, int* inep, int* inep_maxpacket, int* outep, int* outep_maxpacket, int* intep);
static void clear_stall(PTP_USB* ptp_usb);
static int init_ptp_usb (PTPParams* params, PTP_USB* ptp_usb, struct usb_device* dev);
-static short ptp_write_func (unsigned char *bytes, unsigned int size, void *data);
-static short ptp_read_func (unsigned char *bytes, unsigned int size, void *data, unsigned int *readbytes);
-static short ptp_check_int (unsigned char *bytes, unsigned int size, void *data, unsigned int *rlen);
+static short ptp_write_func (unsigned long,PTPDataHandler*,void *data,unsigned long*);
+static short ptp_read_func (unsigned long,PTPDataHandler*,void *data,unsigned long*);
+static short ptp_check_int (unsigned long,PTPDataHandler*,void *, unsigned long *);
static int usb_clear_stall_feature(PTP_USB* ptp_usb, int ep);
static int usb_get_endpoint_status(PTP_USB* ptp_usb, int ep, uint16_t* status);
@@ -399,34 +399,41 @@
// Based on same function on library.c in libgphoto2
#define CONTEXT_BLOCK_SIZE 0x100000
static short
-ptp_read_func (unsigned char *bytes, unsigned int size, void *data, unsigned int *readbytes)
-{
+ptp_read_func (
+ unsigned long size, PTPDataHandler *handler,void *data,
+ unsigned long *readbytes
+) {
PTP_USB *ptp_usb = (PTP_USB *)data;
- int toread = 0;
+ unsigned long toread = 0;
int result = 0;
- int curread = 0;
+ unsigned long curread = 0, written;
+ unsigned char *bytes;
/* Split into small blocks. Too large blocks (>1x MB) would
* timeout.
*/
+ bytes = malloc(CONTEXT_BLOCK_SIZE);
while (curread < size) {
toread = size - curread;
if (toread > CONTEXT_BLOCK_SIZE)
toread = CONTEXT_BLOCK_SIZE;
-
- result = USB_BULK_READ(ptp_usb->handle, ptp_usb->inep,(char *)(bytes+curread), toread, ptpcam_usb_timeout);
+
+ result = USB_BULK_READ(ptp_usb->handle, ptp_usb->inep, (char*)bytes, toread, ptpcam_usb_timeout);
if (result == 0) {
- result = USB_BULK_READ(ptp_usb->handle, ptp_usb->inep,(char *)(bytes+curread), toread, ptpcam_usb_timeout);
+ result = USB_BULK_READ(ptp_usb->handle, ptp_usb->inep, (char*)bytes, toread, ptpcam_usb_timeout);
}
if (result < 0)
return PTP_ERROR_IO;
#ifdef ENABLE_USB_BULK_DEBUG
printf("<==USB IN\n");
- data_dump_ascii (stdout,(bytes+curread),result,16);
+ data_dump_ascii (stdout,bytes,result,16);
#endif
+ handler->putfunc (NULL, handler->private, result, bytes, &written);
curread += result;
if (result < toread) /* short reads are common */
break;
}
+ if (readbytes) *readbytes = curread;
+ free (bytes);
// Increase counters, call callback
if (ptp_usb->callback_active) {
@@ -445,7 +452,6 @@
}
if (result > 0) {
- *readbytes = curread;
return (PTP_RC_OK);
} else {
return PTP_ERROR_IO;
@@ -454,13 +460,20 @@
// Based on same function on library.c in libgphoto2
static short
-ptp_write_func (unsigned char *bytes, unsigned int size, void *data)
-{
+ptp_write_func (
+ unsigned long size,
+ PTPDataHandler *handler,
+ void *data,
+ unsigned long *written
+) {
PTP_USB *ptp_usb = (PTP_USB *)data;
- int towrite = 0;
+ unsigned long towrite = 0;
int result = 0;
- int curwrite = 0;
+ unsigned long curwrite = 0;
+ unsigned char *bytes;
+ bytes = malloc(CONTEXT_BLOCK_SIZE);
+ if (!bytes) return PTP_ERROR_IO;
/*
* gp_port_write returns (in case of success) the number of bytes
* written. Too large blocks (>5x MB) could timeout.
@@ -469,7 +482,8 @@
towrite = size-curwrite;
if (towrite > CONTEXT_BLOCK_SIZE)
towrite = CONTEXT_BLOCK_SIZE;
- result=USB_BULK_WRITE(ptp_usb->handle,ptp_usb->outep,(char *)(bytes+curwrite),towrite,ptpcam_usb_timeout);
+ handler->getfunc (NULL, handler->private,towrite,bytes,&towrite);
+ result = USB_BULK_WRITE(ptp_usb->handle,ptp_usb->outep,(char*)bytes,towrite,ptpcam_usb_timeout);
#ifdef ENABLE_USB_BULK_DEBUG
printf("USB OUT==>\n");
data_dump_ascii (stdout,(bytes+curwrite),towrite,16);
@@ -480,6 +494,8 @@
if (result < towrite) /* short writes happen */
break;
}
+ free (bytes);
+ if (written) *written = curwrite;
// Increase counters, call callback
if (ptp_usb->callback_active) {
@@ -528,16 +544,21 @@
}
// This is a bit hackish at the moment. I wonder if it even works.
-static short ptp_check_int (unsigned char *bytes, unsigned int size, void *data, unsigned int *rlen)
-{
+static short ptp_check_int (
+ unsigned long size, PTPDataHandler *handler,void *data,
+ unsigned long *readbytes
+) {
PTP_USB *ptp_usb = (PTP_USB *)data;
int result;
+ unsigned char bytes[64];
+
+ if (size>64) return PTP_ERROR_IO;
result=USB_BULK_READ(ptp_usb->handle, ptp_usb->intep,(char *)bytes,size,ptpcam_usb_timeout);
if (result==0)
result = USB_BULK_READ(ptp_usb->handle, ptp_usb->intep,(char *) bytes, size, ptpcam_usb_timeout);
if (result >= 0) {
- *rlen = result;
+ handler->putfunc (NULL, handler->private, result, bytes, readbytes);
return (PTP_RC_OK);
} else {
return PTP_ERROR_IO;
diff --git a/src/ptp.c b/src/ptp.c
index b69af9e..6a253e9 100644
--- a/src/ptp.c
+++ b/src/ptp.c
@@ -20,6 +20,7 @@
* Boston, MA 02111-1307, USA.
*/
+#define _BSD_SOURCE
#include <config.h>
#include "ptp.h"
@@ -52,6 +53,11 @@
#define PTP_CNT_INIT(cnt) {memset(&cnt,0,sizeof(cnt));}
+static uint16_t ptp_exit_recv_memory_handler (PTPDataHandler*,unsigned char**,unsigned long*);
+static uint16_t ptp_init_recv_memory_handler(PTPDataHandler*);
+static uint16_t ptp_init_send_memory_handler(PTPDataHandler*,unsigned char*,unsigned long len);
+static uint16_t ptp_exit_send_memory_handler (PTPDataHandler *handler);
+
static void
ptp_debug (PTPParams *params, const char *format, ...)
{
@@ -97,6 +103,8 @@
{
uint16_t ret;
PTPUSBBulkContainer usbreq;
+ PTPDataHandler memhandler;
+ unsigned long written, towrite;
/* build appropriate USB container */
usbreq.length=htod32(PTP_USB_BULK_REQ_LEN-
@@ -110,15 +118,28 @@
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-(sizeof(uint32_t)*(5-req->Nparam)),
- params->data);
+ towrite = PTP_USB_BULK_REQ_LEN-(sizeof(uint32_t)*(5-req->Nparam));
+ ptp_init_send_memory_handler (&memhandler, (unsigned char*)&usbreq, towrite);
+ ret=params->write_func(
+ towrite,
+ &memhandler,
+ params->data,
+ &written
+ );
+ ptp_exit_send_memory_handler (&memhandler);
if (ret!=PTP_RC_OK) {
ret = PTP_ERROR_IO;
/* ptp_error (params,
"PTP: request code 0x%04x sending req error 0x%04x",
req->Code,ret); */
}
+ if (written != towrite) {
+ ptp_error (params,
+ "PTP: request code 0x%04x sending req wrote only %ld bytes instead of %d",
+ written, towrite
+ );
+ ret = PTP_ERROR_IO;
+ }
return ret;
}
@@ -127,13 +148,14 @@
uint16_t
ptp_usb_senddata (PTPParams* params, PTPContainer* ptp,
- unsigned char *data, unsigned int size,
- int from_fd)
-{
+ unsigned long size, PTPDataHandler *handler
+) {
uint16_t ret;
int wlen, datawlen;
- size_t written;
+ unsigned long written;
PTPUSBBulkContainer usbdata;
+ uint32_t bytes_left_to_transfer;
+ PTPDataHandler memhandler;
/* build appropriate USB container */
usbdata.length = htod32(PTP_USB_BULK_HDR_LEN+size);
@@ -145,19 +167,20 @@
datawlen = 0;
wlen = PTP_USB_BULK_HDR_LEN;
} else {
+ unsigned long gotlen;
/* For all camera devices. */
datawlen = (size<PTP_USB_BULK_PAYLOAD_LEN)?size:PTP_USB_BULK_PAYLOAD_LEN;
wlen = PTP_USB_BULK_HDR_LEN + datawlen;
- if (from_fd == -1) {
- memcpy(usbdata.payload.data, data, datawlen);
- } else {
- written = read(from_fd, usbdata.payload.data, datawlen);
- if (written != datawlen)
- return PTP_ERROR_IO;
- }
+ ret = handler->getfunc(params, handler->private, datawlen, usbdata.payload.data, &gotlen);
+ if (ret != PTP_RC_OK)
+ return ret;
+ if (gotlen != datawlen)
+ return PTP_RC_GeneralError;
}
+ ptp_init_send_memory_handler (&memhandler, (unsigned char *)&usbdata, wlen);
/* send first part of data */
- ret = params->write_func((unsigned char *)&usbdata, wlen, params->data);
+ ret = params->write_func(wlen, &memhandler, params->data, &written);
+ ptp_exit_send_memory_handler (&memhandler);
if (ret!=PTP_RC_OK) {
ret = PTP_ERROR_IO;
/* ptp_error (params,
@@ -167,50 +190,30 @@
}
if (size <= datawlen) return ret;
/* if everything OK send the rest */
- if (from_fd == -1) {
- ret=params->write_func (data + datawlen, size - datawlen, params->data);
- } else {
- uint32_t bytes_to_transfer;
- uint32_t bytes_left_to_transfer;
- void *temp_buf;
-
- written = 0;
- bytes_left_to_transfer = size-datawlen;
-
- temp_buf = malloc(FILE_BUFFER_SIZE);
- if (temp_buf == NULL)
- return PTP_ERROR_IO;
-
- ret = PTP_RC_OK;
- while(bytes_left_to_transfer > 0) {
- if (bytes_left_to_transfer > FILE_BUFFER_SIZE) {
- bytes_to_transfer = FILE_BUFFER_SIZE;
- } else {
- bytes_to_transfer = bytes_left_to_transfer;
- }
- written = read(from_fd, temp_buf, bytes_to_transfer);
- if (written != bytes_to_transfer) {
- ret = PTP_ERROR_IO;
- break;
- }
- ret=params->write_func (temp_buf, bytes_to_transfer, params->data);
- bytes_left_to_transfer -= bytes_to_transfer;
+ bytes_left_to_transfer = size-datawlen;
+ ret = PTP_RC_OK;
+ while(bytes_left_to_transfer > 0) {
+ ret = params->write_func (bytes_left_to_transfer, handler, params->data, &written);
+ if (ret != PTP_RC_OK)
+ break;
+ if (written == 0) {
+ ret = PTP_ERROR_IO;
+ break;
}
- free(temp_buf);
-
+ bytes_left_to_transfer -= written;
}
- if (ret!=PTP_RC_OK) {
+ if (ret!=PTP_RC_OK)
ret = PTP_ERROR_IO;
-/* ptp_error (params,
- "PTP: request code 0x%04x sending data error 0x%04x",
- ptp->Code,ret); */
- }
return ret;
}
static uint16_t ptp_usb_getpacket(PTPParams *params,
- PTPUSBBulkContainer *packet, unsigned int *rlen)
+ PTPUSBBulkContainer *packet, unsigned long *rlen)
{
+ PTPDataHandler memhandler;
+ uint16_t ret;
+ unsigned char *x = NULL;
+
/* read the header and potentially the first data */
if (params->response_packet_size > 0) {
/* If there is a buffered packet, just use it. */
@@ -221,71 +224,28 @@
params->response_packet_size = 0;
/* Here this signifies a "virtual read" */
return PTP_RC_OK;
- } else {
- return params->read_func((unsigned char *)packet,
- sizeof(*packet), params->data, rlen);
}
-}
-
-static uint16_t
-ptp_usb_getdata_tofile(PTPParams* params, PTPUSBBulkContainer *usbdata,
- uint32_t bytes_to_write, int len, int to_fd)
-{
- uint16_t ret = PTP_RC_OK;
- void *temp_buf = usbdata->payload.data;
-
- for (;;) {
- uint32_t written = write(to_fd, temp_buf, bytes_to_write);
- if (written != bytes_to_write) {
- ret = PTP_ERROR_IO;
- break;
- }
-
- len -= written;
- if (len <= 0)
- break;
-
- if (temp_buf == usbdata->payload.data) {
- temp_buf = malloc(FILE_BUFFER_SIZE);
- if (!temp_buf) {
- ret = PTP_ERROR_IO;
- break;
- }
- }
-
- bytes_to_write = (len > FILE_BUFFER_SIZE) ?
- FILE_BUFFER_SIZE : len;
-
- ret = params->read_func(temp_buf, bytes_to_write,
- params->data, &bytes_to_write);
-
- if (ret != PTP_RC_OK) {
- ret = PTP_ERROR_IO;
- break;
- }
+ ptp_init_recv_memory_handler (&memhandler);
+ ret = params->read_func( sizeof(*packet), &memhandler, params->data, rlen);
+ ptp_exit_recv_memory_handler (&memhandler, &x, rlen);
+ if (x) {
+ memcpy (packet, x, *rlen);
+ free (x);
}
-
- if (temp_buf != usbdata->payload.data)
- free(temp_buf);
-
return ret;
}
uint16_t
-ptp_usb_getdata (PTPParams* params, PTPContainer* ptp,
- unsigned char **data, unsigned int *readlen,
- int to_fd)
+ptp_usb_getdata (PTPParams* params, PTPContainer* ptp, PTPDataHandler *handler)
{
uint16_t ret;
PTPUSBBulkContainer usbdata;
+ unsigned char *data;
+ unsigned long written;
PTP_CNT_INIT(usbdata);
-
- if (to_fd == -1 && *data != NULL)
- return PTP_ERROR_BADPARAM;
-
do {
- unsigned int len, rlen;
+ unsigned long len, rlen;
ret = ptp_usb_getpacket(params, &usbdata, &rlen);
if (ret!=PTP_RC_OK) {
@@ -301,31 +261,21 @@
break;
}
if (usbdata.length == 0xffffffffU) {
- /* This only happens for MTP_GetObjPropList */
- uint32_t tsize = PTP_USB_BULK_HS_MAX_PACKET_LEN;
- unsigned char *tdata = malloc(tsize);
- uint32_t curoff = 0;
-
+ /* stuff data directly to passed data handler */
while (1) {
- ret=params->read_func(tdata+curoff,
- PTP_USB_BULK_HS_MAX_PACKET_LEN, params->data, &rlen);
- if (ret!=PTP_RC_OK) {
- ret = PTP_ERROR_IO;
+ unsigned long readdata;
+ int xret;
+
+ xret = params->read_func(
+ PTP_USB_BULK_HS_MAX_PACKET_LEN,
+ handler,
+ params->data,
+ &readdata
+ );
+ if (xret == -1)
+ return PTP_ERROR_IO;
+ if (readdata < PTP_USB_BULK_HS_MAX_PACKET_LEN)
break;
- }
- if (rlen < PTP_USB_BULK_HS_MAX_PACKET_LEN) {
- tsize += rlen;
- break;
- }
- tsize += PTP_USB_BULK_HS_MAX_PACKET_LEN;
- curoff+= PTP_USB_BULK_HS_MAX_PACKET_LEN;
- tdata = realloc(tdata, tsize);
- }
- if (to_fd == -1) {
- *data = tdata;
- } else {
- write (to_fd, tdata, tsize);
- free (tdata);
}
return PTP_RC_OK;
}
@@ -367,36 +317,23 @@
if (dtoh32(usbdata.length) > 12 && (rlen==12))
params->split_header_data = 1;
- if (to_fd == -1) {
- /* Allocate memory for data. */
- *data=calloc(len,1);
- if (!*data) {
- ptp_error (params, "PTP: Out of memory on allocating %d bytes.", len);
- return PTP_ERROR_IO;
- }
- if (readlen)
- *readlen = len;
+ data = malloc(PTP_USB_BULK_HS_MAX_PACKET_LEN);
+ /* Copy first part of data to 'data' */
+ handler->putfunc(
+ params, handler->private, rlen - PTP_USB_BULK_HDR_LEN, usbdata.payload.data,
+ &written
+ );
- /* Copy first part of data to 'data' */
- memcpy(*data,usbdata.payload.data,rlen - PTP_USB_BULK_HDR_LEN);
+ /* Is that all of data? */
+ if (len+PTP_USB_BULK_HDR_LEN<=rlen) break;
- /* Is that all of data? */
- if (len+PTP_USB_BULK_HDR_LEN<=rlen) break;
-
- /* If not read the rest of it. */
- ret=params->read_func(((unsigned char *)(*data))+
- rlen - PTP_USB_BULK_HDR_LEN,
- len-(rlen - PTP_USB_BULK_HDR_LEN),
- params->data, &rlen);
- if (ret!=PTP_RC_OK) {
- ret = PTP_ERROR_IO;
- break;
- }
- } else {
- if (readlen)
- *readlen = len;
- ptp_usb_getdata_tofile(params, &usbdata,
- rlen - PTP_USB_BULK_HDR_LEN, len, to_fd);
+ /* If not read the rest of it. */
+ ret=params->read_func(len - (rlen - PTP_USB_BULK_HDR_LEN),
+ handler,
+ params->data, &rlen);
+ if (ret!=PTP_RC_OK) {
+ ret = PTP_ERROR_IO;
+ break;
}
} while (0);
/*
@@ -412,7 +349,7 @@
ptp_usb_getresp (PTPParams* params, PTPContainer* resp)
{
uint16_t ret;
- unsigned int rlen;
+ unsigned long rlen;
PTPUSBBulkContainer usbresp;
PTP_CNT_INIT(usbresp);
@@ -483,10 +420,10 @@
* all fields filled in.
**/
static uint16_t
-_ptp_transaction (PTPParams* params, PTPContainer* ptp,
- uint16_t flags, unsigned int sendlen, unsigned char** data,
- int fd, unsigned int *recvlen)
-{
+ptp_transaction_new (PTPParams* params, PTPContainer* ptp,
+ uint16_t flags, unsigned int sendlen,
+ PTPDataHandler *handler
+) {
if ((params==NULL) || (ptp==NULL))
return PTP_ERROR_BADPARAM;
@@ -498,11 +435,10 @@
switch (flags&PTP_DP_DATA_MASK) {
case PTP_DP_SENDDATA:
CHECK_PTP_RC(params->senddata_func(params, ptp,
- *data, sendlen, fd));
+ sendlen, handler));
break;
case PTP_DP_GETDATA:
- CHECK_PTP_RC(params->getdata_func(params, ptp,
- (unsigned char**)data, recvlen, fd));
+ CHECK_PTP_RC(params->getdata_func(params, ptp, handler));
break;
case PTP_DP_NODATA:
break;
@@ -520,30 +456,7 @@
}
return ptp->Code;
}
-
-static uint16_t
-ptp_transaction (PTPParams* params, PTPContainer* ptp,
- uint16_t flags, unsigned int sendlen, unsigned char** data,
- unsigned int *recvlen)
-{
- return _ptp_transaction(params, ptp, flags, sendlen, data, -1, recvlen);
-}
-
-static uint16_t
-ptp_transaction_fd (PTPParams* params, PTPContainer* ptp,
- uint16_t flags, unsigned int sendlen,
- int fd, unsigned int *recvlen)
-{
- /*
- * This dummy data needed since _ptp_transaction()
- * will dereference the data argument
- */
- unsigned char *dummydata = NULL;
-
- return _ptp_transaction(params, ptp, flags, sendlen, &dummydata, fd, recvlen);
-}
-
-/* Enets handling functions */
+/* Event handling functions */
/* PTP Events wait for or check mode */
#define PTP_EVENT_CHECK 0x0000 /* waits for */
@@ -553,45 +466,77 @@
ptp_usb_event (PTPParams* params, PTPContainer* event, int wait)
{
uint16_t ret;
- unsigned int rlen;
+ unsigned long rlen, oldrlen;
PTPUSBEventContainer usbevent;
+ unsigned char *x;
+ PTPDataHandler memhandler;
+
PTP_CNT_INIT(usbevent);
if ((params==NULL) || (event==NULL))
return PTP_ERROR_BADPARAM;
-
+ ptp_init_recv_memory_handler (&memhandler);
switch(wait) {
- case PTP_EVENT_CHECK:
- ret=params->check_int_func((unsigned char*)&usbevent,
- sizeof(usbevent), params->data, &rlen);
- break;
- case PTP_EVENT_CHECK_FAST:
- ret=params->check_int_fast_func((unsigned char*)
- &usbevent, sizeof(usbevent), params->data, &rlen);
- break;
- default:
- ret=PTP_ERROR_BADPARAM;
+ case PTP_EVENT_CHECK:
+ ret=params->check_int_func(
+ sizeof(usbevent),
+ &memhandler,
+ params->data,
+ &rlen
+ );
+ break;
+ case PTP_EVENT_CHECK_FAST:
+ ret=params->check_int_fast_func(
+ sizeof(usbevent),
+ &memhandler,
+ params->data,
+ &rlen
+ );
+ break;
+ default:
+ ret=PTP_ERROR_BADPARAM;
+ break;
}
+ ptp_exit_recv_memory_handler (&memhandler, &x, &rlen);
if (ret!=PTP_RC_OK) {
ptp_error (params,
"PTP: reading event an error 0x%04x occurred", ret);
- ret = PTP_ERROR_IO;
- /* reading event error is nonfatal (for example timeout) */
+ return PTP_ERROR_IO;
}
+ if (!x || rlen < 8) {
+ ptp_error (params,
+ "PTP: reading event an short read of %ld bytes occurred", rlen);
+ return PTP_ERROR_IO;
+ }
+ memcpy (&usbevent, x, rlen);
+ free (x);
+
/* Only do the additional reads for "events". Canon IXUS 2 likes to
* send unrelated data.
*/
- if (dtoh16(usbevent.type) == PTP_USB_CONTAINER_EVENT) {
- while (dtoh32(usbevent.length) > rlen) {
- unsigned int newrlen = 0;
+ if ( (dtoh16(usbevent.type) == PTP_USB_CONTAINER_EVENT) &&
+ (dtoh32(usbevent.length) > rlen)
+ ) {
+ unsigned char *x;
- ret=params->check_int_fast_func(((unsigned char*)&usbevent)+rlen,
- dtoh32(usbevent.length)-rlen,params->data,&newrlen
+ oldrlen = rlen;
+ ptp_init_recv_memory_handler (&memhandler);
+ while (dtoh32(usbevent.length) > rlen) {
+ unsigned long newrlen = 0;
+
+ ret=params->check_int_fast_func(
+ dtoh32(usbevent.length)-rlen,
+ &memhandler,
+ params->data,
+ &newrlen
);
if (ret != PTP_RC_OK)
break;
- rlen+=newrlen;
+ rlen += newrlen;
}
+ ptp_exit_recv_memory_handler (&memhandler, &x, &rlen);
+ memcpy (((char*)&usbevent)+oldrlen, x, rlen);
+ free (x);
}
/* if we read anything over interrupt endpoint it must be an event */
/* build an appropriate PTPContainer */
@@ -616,6 +561,192 @@
return ptp_usb_event (params, event, PTP_EVENT_CHECK);
}
+/* memory data get/put handler */
+typedef struct {
+ unsigned char *data;
+ unsigned long size, curoff;
+} PTPMemHandlerPrivate;
+
+static uint16_t
+memory_getfunc(PTPParams* params, void* private,
+ unsigned long wantlen, unsigned char *data,
+ unsigned long *gotlen
+) {
+ PTPMemHandlerPrivate* priv = (PTPMemHandlerPrivate*)private;
+ unsigned long tocopy = wantlen;
+
+ if (priv->curoff + tocopy > priv->size)
+ tocopy = priv->size - priv->curoff;
+ memcpy (data, priv->data + priv->curoff, tocopy);
+ priv->curoff += tocopy;
+ *gotlen = tocopy;
+ return PTP_RC_OK;
+}
+
+static uint16_t
+memory_putfunc(PTPParams* params, void* private,
+ unsigned long sendlen, unsigned char *data,
+ unsigned long *putlen
+) {
+ PTPMemHandlerPrivate* priv = (PTPMemHandlerPrivate*)private;
+
+ if (priv->curoff + sendlen > priv->size) {
+ priv->data = realloc (priv->data, priv->curoff+sendlen);
+ priv->size = priv->curoff + sendlen;
+ }
+ memcpy (priv->data + priv->curoff, data, sendlen);
+ priv->curoff += sendlen;
+ *putlen = sendlen;
+ return PTP_RC_OK;
+}
+
+/* init private struct for receiving data. */
+static uint16_t
+ptp_init_recv_memory_handler(PTPDataHandler *handler) {
+ PTPMemHandlerPrivate* priv;
+ priv = malloc (sizeof(PTPMemHandlerPrivate));
+ handler->private = priv;
+ handler->getfunc = memory_getfunc;
+ handler->putfunc = memory_putfunc;
+ priv->data = NULL;
+ priv->size = 0;
+ priv->curoff = 0;
+ return PTP_RC_OK;
+}
+
+/* init private struct and put data in for sending data.
+ * data is still owned by caller.
+ */
+static uint16_t
+ptp_init_send_memory_handler(PTPDataHandler *handler,
+ unsigned char *data, unsigned long len
+) {
+ PTPMemHandlerPrivate* priv;
+ priv = malloc (sizeof(PTPMemHandlerPrivate));
+ if (!priv)
+ return PTP_RC_GeneralError;
+ handler->private = priv;
+ handler->getfunc = memory_getfunc;
+ handler->putfunc = memory_putfunc;
+ priv->data = data;
+ priv->size = len;
+ priv->curoff = 0;
+ return PTP_RC_OK;
+}
+
+/* free private struct + data */
+static uint16_t
+ptp_exit_send_memory_handler (PTPDataHandler *handler) {
+ PTPMemHandlerPrivate* priv = (PTPMemHandlerPrivate*)handler->private;
+ /* data is owned by caller */
+ free (priv);
+ return PTP_RC_OK;
+}
+
+/* hand over our internal data to caller */
+static uint16_t
+ptp_exit_recv_memory_handler (PTPDataHandler *handler,
+ unsigned char **data, unsigned long *size
+) {
+ PTPMemHandlerPrivate* priv = (PTPMemHandlerPrivate*)handler->private;
+ *data = priv->data;
+ *size = priv->size;
+ free (priv);
+ return PTP_RC_OK;
+}
+
+/* fd data get/put handler */
+typedef struct {
+ int fd;
+} PTPFDHandlerPrivate;
+
+static uint16_t
+fd_getfunc(PTPParams* params, void* private,
+ unsigned long wantlen, unsigned char *data,
+ unsigned long *gotlen
+) {
+ PTPFDHandlerPrivate* priv = (PTPFDHandlerPrivate*)private;
+ int got;
+
+ got = read (priv->fd, data, wantlen);
+ if (got != -1)
+ *gotlen = got;
+ else
+ return PTP_RC_GeneralError;
+ return PTP_RC_OK;
+}
+
+static uint16_t
+fd_putfunc(PTPParams* params, void* private,
+ unsigned long sendlen, unsigned char *data,
+ unsigned long *putlen
+) {
+ int written;
+ PTPFDHandlerPrivate* priv = (PTPFDHandlerPrivate*)private;
+
+ written = write (priv->fd, data, sendlen);
+ if (written != -1)
+ *putlen = written;
+ else
+ return PTP_RC_GeneralError;
+ return PTP_RC_OK;
+}
+
+static uint16_t
+ptp_init_fd_handler(PTPDataHandler *handler, int fd) {
+ PTPFDHandlerPrivate* priv;
+ priv = malloc (sizeof(PTPFDHandlerPrivate));
+ handler->private = priv;
+ handler->getfunc = fd_getfunc;
+ handler->putfunc = fd_putfunc;
+ priv->fd = fd;
+ return PTP_RC_OK;
+}
+
+static uint16_t
+ptp_exit_fd_handler (PTPDataHandler *handler) {
+ PTPFDHandlerPrivate* priv = (PTPFDHandlerPrivate*)handler->private;
+ close (priv->fd);
+ free (priv);
+ return PTP_RC_OK;
+}
+
+/* Old style transaction, based on memory */
+static uint16_t
+ptp_transaction (PTPParams* params, PTPContainer* ptp,
+ uint16_t flags, unsigned int sendlen,
+ unsigned char **data, unsigned int *recvlen
+) {
+ PTPDataHandler handler;
+ uint16_t ret;
+
+ switch (flags & PTP_DP_DATA_MASK) {
+ case PTP_DP_SENDDATA:
+ ptp_init_send_memory_handler (&handler, *data, sendlen);
+ break;
+ case PTP_DP_GETDATA:
+ ptp_init_recv_memory_handler (&handler);
+ break;
+ default:break;
+ }
+ ret = ptp_transaction_new (params, ptp, flags, sendlen, &handler);
+ switch (flags & PTP_DP_DATA_MASK) {
+ case PTP_DP_SENDDATA:
+ ptp_exit_send_memory_handler (&handler);
+ break;
+ case PTP_DP_GETDATA: {
+ unsigned long len;
+ ptp_exit_recv_memory_handler (&handler, data, &len);
+ if (recvlen)
+ *recvlen = len;
+ break;
+ }
+ default:break;
+ }
+ return ret;
+}
+
+
/**
* PTP operation functions
*
@@ -635,16 +766,19 @@
uint16_t
ptp_getdeviceinfo (PTPParams* params, PTPDeviceInfo* deviceinfo)
{
- uint16_t ret;
- unsigned int len;
- PTPContainer ptp;
- unsigned char* di=NULL;
+ uint16_t ret;
+ unsigned long len;
+ PTPContainer ptp;
+ unsigned char* di=NULL;
+ PTPDataHandler handler;
+ ptp_init_recv_memory_handler (&handler);
PTP_CNT_INIT(ptp);
ptp.Code=PTP_OC_GetDeviceInfo;
ptp.Nparam=0;
len=0;
- ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &di, &len);
+ ret=ptp_transaction_new(params, &ptp, PTP_DP_GETDATA, 0, &handler);
+ ptp_exit_recv_memory_handler (&handler, &di, &len);
if (ret == PTP_RC_OK) ptp_unpack_DI(params, di, deviceinfo, len);
free(di);
return ret;
@@ -681,7 +815,7 @@
ptp.Code=PTP_OC_OpenSession;
ptp.Param1=session;
ptp.Nparam=1;
- ret=ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL);
+ ret=ptp_transaction_new(params, &ptp, PTP_DP_NODATA, 0, NULL);
/* now set the global session id to current session number */
params->session_id=session;
return ret;
@@ -711,7 +845,7 @@
PTP_CNT_INIT(ptp);
ptp.Code=PTP_OC_CloseSession;
ptp.Nparam=0;
- return ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL);
+ return ptp_transaction_new(params, &ptp, PTP_DP_NODATA, 0, NULL);
}
/**
@@ -925,6 +1059,29 @@
}
/**
+ * ptp_getobject_to_handler:
+ * params: PTPParams*
+ * handle - Object handle
+ * PTPDataHandler* - pointer datahandler
+ *
+ * Get object 'handle' from device and store the data in newly
+ * allocated 'object'.
+ *
+ * Return values: Some PTP_RC_* code.
+ **/
+uint16_t
+ptp_getobject_to_handler (PTPParams* params, uint32_t handle, PTPDataHandler *handler)
+{
+ PTPContainer ptp;
+
+ PTP_CNT_INIT(ptp);
+ ptp.Code=PTP_OC_GetObject;
+ ptp.Param1=handle;
+ ptp.Nparam=1;
+ return ptp_transaction_new(params, &ptp, PTP_DP_GETDATA, 0, handler);
+}
+
+/**
* ptp_getobject_tofd:
* params: PTPParams*
* handle - Object handle
@@ -938,15 +1095,18 @@
uint16_t
ptp_getobject_tofd (PTPParams* params, uint32_t handle, int fd)
{
- PTPContainer ptp;
- unsigned int len;
+ PTPContainer ptp;
+ PTPDataHandler handler;
+ uint16_t ret;
+ ptp_init_fd_handler (&handler, fd);
PTP_CNT_INIT(ptp);
ptp.Code=PTP_OC_GetObject;
ptp.Param1=handle;
ptp.Nparam=1;
- len=0;
- return ptp_transaction_fd(params, &ptp, PTP_DP_GETDATA, 0, fd, &len);
+ ret = ptp_transaction_new(params, &ptp, PTP_DP_GETDATA, 0, &handler);
+ ptp_exit_fd_handler (&handler);
+ return ret;
}
/**
@@ -1093,6 +1253,29 @@
}
/**
+ * ptp_sendobject_from_handler:
+ * params: PTPParams*
+ * PTPDataHandler* - File descriptor to read() object from
+ * uint32_t size - File/object size
+ *
+ * Sends object from file descriptor by consecutive reads from this
+ * descriptor.
+ *
+ * Return values: Some PTP_RC_* code.
+ **/
+uint16_t
+ptp_sendobject_from_handler (PTPParams* params, PTPDataHandler *handler, uint32_t size)
+{
+ PTPContainer ptp;
+
+ PTP_CNT_INIT(ptp);
+ ptp.Code=PTP_OC_SendObject;
+ ptp.Nparam=0;
+ return ptp_transaction_new(params, &ptp, PTP_DP_SENDDATA, size, handler);
+}
+
+
+/**
* ptp_sendobject_fromfd:
* params: PTPParams*
* fd - File descriptor to read() object from
@@ -1106,13 +1289,17 @@
uint16_t
ptp_sendobject_fromfd (PTPParams* params, int fd, uint32_t size)
{
- PTPContainer ptp;
+ PTPContainer ptp;
+ PTPDataHandler handler;
+ uint16_t ret;
+ ptp_init_fd_handler (&handler, fd);
PTP_CNT_INIT(ptp);
ptp.Code=PTP_OC_SendObject;
ptp.Nparam=0;
-
- return ptp_transaction_fd(params, &ptp, PTP_DP_SENDDATA, size, fd, NULL);
+ ret = ptp_transaction_new(params, &ptp, PTP_DP_SENDDATA, size, &handler);
+ ptp_exit_fd_handler (&handler);
+ return ret;
}
@@ -1386,6 +1573,28 @@
return ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &object, NULL);
}
+/**
+ * ptp_ek_sendfileobject_from_handler:
+ * params: PTPParams*
+ * PTPDataHandler* handler - contains the handler of 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_from_handler (PTPParams* params, PTPDataHandler*handler, uint32_t size)
+{
+ PTPContainer ptp;
+
+ PTP_CNT_INIT(ptp);
+ ptp.Code=PTP_OC_EK_SendFileObject;
+ ptp.Nparam=0;
+ return ptp_transaction_new(params, &ptp, PTP_DP_SENDDATA, size, handler);
+}
+
/*************************************************************************
*
* Canon PTP extensions support
diff --git a/src/ptp.h b/src/ptp.h
index 7748c4f..bc1848f 100644
--- a/src/ptp.h
+++ b/src/ptp.h
@@ -1078,23 +1078,34 @@
typedef struct _PTPParams PTPParams;
-/* raw write functions */
-typedef short (* PTPIOReadFunc) (unsigned char *bytes, unsigned int size,
- void *data, unsigned int *readlen);
-typedef short (* PTPIOWriteFunc)(unsigned char *bytes, unsigned int size,
- void *data);
+
+typedef uint16_t (* PTPDataGetFunc) (PTPParams* params, void* private,
+ unsigned long wantlen,
+ unsigned char *data, unsigned long *gotlen);
+
+typedef uint16_t (* PTPDataPutFunc) (PTPParams* params, void* private,
+ unsigned long sendlen,
+ unsigned char *data, unsigned long *putlen);
+typedef struct _PTPDataHandler {
+ PTPDataGetFunc getfunc;
+ PTPDataPutFunc putfunc;
+ void *private;
+} PTPDataHandler;
+
+/* PTP <-> lowlevel IO layer read/write functions */
+typedef short (* PTPIOReadFunc) (unsigned long size, PTPDataHandler*, void*, unsigned long*readlen);
+typedef short (* PTPIOWriteFunc)(unsigned long size, PTPDataHandler*, void *data, unsigned long *written);
/*
* This functions take PTP oriented arguments and send them over an
* appropriate data layer doing byteorder conversion accordingly.
*/
typedef uint16_t (* PTPIOSendReq) (PTPParams* params, PTPContainer* req);
typedef uint16_t (* PTPIOSendData) (PTPParams* params, PTPContainer* ptp,
- unsigned char *data, unsigned int size,
- int from_fd);
+ unsigned long size, PTPDataHandler*getter);
+
typedef uint16_t (* PTPIOGetResp) (PTPParams* params, PTPContainer* resp);
typedef uint16_t (* PTPIOGetData) (PTPParams* params, PTPContainer* ptp,
- unsigned char **data, unsigned int *recvlen,
- int to_fd);
+ PTPDataHandler *putter);
/* debug functions */
typedef void (* PTPErrorFunc) (void *data, const char *format, va_list args)
#if (__GNUC__ >= 3)
@@ -1176,24 +1187,20 @@
/* last, but not least - ptp functions */
uint16_t ptp_usb_sendreq (PTPParams* params, PTPContainer* req);
uint16_t ptp_usb_senddata (PTPParams* params, PTPContainer* ptp,
- unsigned char *data, unsigned int size,
- int from_fd);
+ unsigned long size, PTPDataHandler *handler);
uint16_t ptp_usb_getresp (PTPParams* params, PTPContainer* resp);
uint16_t ptp_usb_getdata (PTPParams* params, PTPContainer* ptp,
- unsigned char **data, unsigned int *readlen,
- int to_fd);
+ PTPDataHandler *handler);
uint16_t ptp_usb_event_check (PTPParams* params, PTPContainer* event);
uint16_t ptp_usb_event_wait (PTPParams* params, PTPContainer* event);
int ptp_ptpip_connect (PTPParams* params, const char *port);
uint16_t ptp_ptpip_sendreq (PTPParams* params, PTPContainer* req);
uint16_t ptp_ptpip_senddata (PTPParams* params, PTPContainer* ptp,
- unsigned char *data, unsigned int size,
- int to_fd);
+ unsigned long size, PTPDataHandler *handler);
uint16_t ptp_ptpip_getresp (PTPParams* params, PTPContainer* resp);
uint16_t ptp_ptpip_getdata (PTPParams* params, PTPContainer* ptp,
- unsigned char **data, unsigned int *readlen,
- int to_fd);
+ PTPDataHandler *handler);
uint16_t ptp_ptpip_event_wait (PTPParams* params, PTPContainer* event);
uint16_t ptp_ptpip_event_check (PTPParams* params, PTPContainer* event);
@@ -1223,6 +1230,7 @@
uint16_t ptp_getobject (PTPParams *params, uint32_t handle,
unsigned char** object);
uint16_t ptp_getobject_tofd (PTPParams* params, uint32_t handle, int fd);
+uint16_t ptp_getobject_to_handler (PTPParams* params, uint32_t handle, PTPDataHandler*);
uint16_t ptp_getpartialobject (PTPParams* params, uint32_t handle, uint32_t offset,
uint32_t maxbytes, unsigned char** object);
uint16_t ptp_getthumb (PTPParams *params, uint32_t handle,
@@ -1237,6 +1245,7 @@
uint16_t ptp_sendobject (PTPParams* params, unsigned char* object,
uint32_t size);
uint16_t ptp_sendobject_fromfd (PTPParams* params, int fd, uint32_t size);
+uint16_t ptp_sendobject_from_handler (PTPParams* params, PTPDataHandler*, uint32_t size);
uint16_t ptp_initiatecapture (PTPParams* params, uint32_t storageid,
uint32_t ofc);
@@ -1273,6 +1282,8 @@
PTPObjectInfo* objectinfo);
uint16_t ptp_ek_sendfileobject (PTPParams* params, unsigned char* object,
uint32_t size);
+uint16_t ptp_ek_sendfileobject_from_handler (PTPParams* params, PTPDataHandler*,
+ uint32_t size);
/* Canon PTP extensions */
uint16_t ptp_canon_9012 (PTPParams* params);