📄 ptp.c
字号:
/* ptp.c * * Copyright (C) 2001-2005 Mariusz Woloszyn <emsi@ipartners.pl> * * This file is part of libptp2. * * libptp2 is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libptp2 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with libptp2; 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 voidptp_debug (PTPParams *params, const char *format, ...){ va_list args; va_start (args, format); if (params->debug_func!=NULL) params->debug_func (params->data, format, args); else { vfprintf (stderr, format, args); fprintf (stderr,"\n"); fflush (stderr); } va_end (args);} static voidptp_error (PTPParams *params, const char *format, ...){ va_list args; va_start (args, format); if (params->error_func!=NULL) params->error_func (params->data, format, args); else { vfprintf (stderr, format, args); fprintf (stderr,"\n"); fflush (stderr); } va_end (args);}/* Pack / unpack functions */#include "ptp-pack.c"/* send / receive functions */uint16_tptp_usb_sendreq (PTPParams* params, PTPContainer* req){ static uint16_t ret; static PTPUSBBulkContainer usbreq; PTP_CNT_INIT(usbreq); /* build appropriate USB container */ usbreq.length=htod32(PTP_USB_BULK_REQ_LEN- (sizeof(uint32_t)*(5-req->Nparam))); 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-(sizeof(uint32_t)*(5-req->Nparam)), params->data); 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); */ } return ret;}uint16_tptp_usb_senddata (PTPParams* params, PTPContainer* ptp, unsigned char *data, unsigned int size){ static uint16_t ret; static 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%04x sending data error 0x%04x", 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%04x sending data error 0x%04x", ptp->Code,ret); */ } return ret;}uint16_tptp_usb_getdata (PTPParams* params, PTPContainer* ptp, unsigned char **data){ static uint16_t ret; static PTPUSBBulkContainer usbdata; PTP_CNT_INIT(usbdata);#if 0 if (*data!=NULL) return PTP_ERROR_BADPARAM;#endif do { static uint32_t 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 if not allocated already */ if (*data==NULL) *data=calloc(1,len); /* copy first part of data to 'data' */ memcpy(*data,usbdata.payload.data, PTP_USB_BULK_PAYLOAD_LEN<len? PTP_USB_BULK_PAYLOAD_LEN: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); if (ret!=PTP_RC_OK) { ret = PTP_ERROR_IO; break; } } while (0);/* if (ret!=PTP_RC_OK) { ptp_error (params, "PTP: request code 0x%04x getting data error 0x%04x", ptp->Code, ret); }*/ return ret;}uint16_tptp_usb_getresp (PTPParams* params, PTPContainer* resp){ static uint16_t ret; static 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%04x getting resp error 0x%04x", 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 /* receiving 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 whether 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_tptp_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, (unsigned char*)*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 */#define CHECK_INT(usbevent, size) { \ switch(wait) { \ case PTP_EVENT_CHECK: \ result+=params->check_int_func((unsigned char*)&usbevent+result, \ size-result, params->data); \ break; \ case PTP_EVENT_CHECK_FAST: \ result+=params->check_int_fast_func((unsigned char*)&usbevent+result, \ size-result, params->data); \ break; \ default: \ return PTP_ERROR_BADPARAM; \ }\ } static inline uint16_tptp_usb_event (PTPParams* params, PTPContainer* event, int wait){ int result=0, size=0; static PTPUSBEventContainer usbevent; PTP_CNT_INIT(usbevent); if ((params==NULL) || (event==NULL)) return PTP_ERROR_BADPARAM; CHECK_INT(usbevent, PTP_USB_INT_PACKET_LEN); if (result<0) return PTP_ERROR_IO; size=dtoh32(usbevent.length); while (result<size) { CHECK_INT(usbevent, size); if (result<0) return PTP_ERROR_IO; } /* if we read anything over interrupt endpoint it must be an event */ /* build an appropriate PTPContainer */ 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 PTP_RC_OK;}uint16_tptp_usb_event_check (PTPParams* params, PTPContainer* event) { ptp_debug(params,"PTP: Checking for Event"); return ptp_usb_event (params, event, PTP_EVENT_CHECK_FAST);}uint16_tptp_usb_event_wait (PTPParams* params, PTPContainer* event) { ptp_debug(params,"PTP: Waiting for 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_tptp_getdeviceinfo (PTPParams* params, PTPDeviceInfo* deviceinfo){ uint16_t ret; PTPContainer ptp; char* di=NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -