📄 ptpcam.c
字号:
/* ptpcam.c * * Copyright (C) 2001-2005 Mariusz Woloszyn <emsi@ipartners.pl> * * This program 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. * * This program 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 this program; 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 <errno.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <getopt.h>#include <unistd.h>#include <sys/types.h>#include <utime.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/mman.h>#include <usb.h>#ifdef ENABLE_NLS# include <libintl.h># undef _# define _(String) dgettext (GETTEXT_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#include "ptpcam.h"/* some defines comes here *//* USB interface class */#ifndef USB_CLASS_PTP#define USB_CLASS_PTP 6#endif/* USB control message data phase direction */#ifndef USB_DP_HTD#define USB_DP_HTD (0x00 << 7) /* host to device */#endif#ifndef USB_DP_DTH#define USB_DP_DTH (0x01 << 7) /* device to host */#endif/* PTP class specific requests */#ifndef USB_REQ_DEVICE_RESET#define USB_REQ_DEVICE_RESET 0x66#endif#ifndef USB_REQ_GET_DEVICE_STATUS#define USB_REQ_GET_DEVICE_STATUS 0x67#endif/* USB Feature selector HALT */#ifndef USB_FEATURE_HALT#define USB_FEATURE_HALT 0x00#endif/* OUR APPLICATION USB URB (2MB) ;) */#define PTPCAM_USB_URB 2097152#define USB_TIMEOUT 4000#define USB_CAPTURE_TIMEOUT 20000/* one global variable (yes, I know it sucks) */short verbose=0;/* the other one, it sucks definitely ;) */int ptpcam_usb_timeout = USB_TIMEOUT;voidusage(){ printf("USAGE: ptpcam [OPTION]\n\n");}voidhelp(){ printf("USAGE: ptpcam [OPTION]\n\n"); printf("Options:\n" " --bus=BUS-NUMBER USB bus number\n" " --dev=DEV-NUMBER USB assigned device number\n" " -r, --reset Reset the device\n" " -l, --list-devices List all PTP devices\n" " -i, --info Show device info\n" " -o, --list-operations List supported operations\n" " -p, --list-properties List all PTP device properties\n" " " "(e.g. focus mode, focus distance, etc.)\n" " -s, --show-property=NUMBER Display property details " "(or set its value,\n" " if used in conjunction with --val)\n" " --set-property=NUMBER Set property value (--val required)\n" " --val=VALUE Property value\n" " -L, --list-files List all files\n" " -g, --get-file=HANDLE Get file by given handler\n" " -G, --get-all-files Get all files\n" " --overwrite Force file overwrite while saving" "to disk\n" " -d, --delete-object=HANDLE Delete object (file) by given handle\n" " -D, --delete-all-files Delete all files form camera\n" " -c, --capture Initiate capture\n" " --loop-capture=N Perform N times capture/get/delete\n" " -f, --force Talk to non PTP devices\n" " -v, --verbose Be verbose (print more debug)\n" " -h, --help Print this help message\n" "\n");}static shortptp_read_func (unsigned char *bytes, unsigned int size, void *data){ int result=-1; PTP_USB *ptp_usb=(PTP_USB *)data; int toread=0; signed long int rbytes=size; do { bytes+=toread; if (rbytes>PTPCAM_USB_URB) toread = PTPCAM_USB_URB; else toread = rbytes; result=USB_BULK_READ(ptp_usb->handle, ptp_usb->inep,(char *)bytes, toread,ptpcam_usb_timeout); /* sometimes retry might help */ if (result==0) result=USB_BULK_READ(ptp_usb->handle, ptp_usb->inep,(char *)bytes, toread,ptpcam_usb_timeout); if (result < 0) break; rbytes-=PTPCAM_USB_URB; } while (rbytes>0); if (result >= 0) { return (PTP_RC_OK); } else { if (verbose) perror("usb_bulk_read"); return PTP_ERROR_IO; }}static shortptp_write_func (unsigned char *bytes, unsigned int size, void *data){ int result; PTP_USB *ptp_usb=(PTP_USB *)data; result=USB_BULK_WRITE(ptp_usb->handle,ptp_usb->outep,(char *)bytes,size,ptpcam_usb_timeout); if (result >= 0) return (PTP_RC_OK); else { if (verbose) perror("usb_bulk_write"); return PTP_ERROR_IO; }}static shortptp_check_int (unsigned char *bytes, unsigned int size, void *data){ int result; PTP_USB *ptp_usb=(PTP_USB *)data; if (verbose) printf ("Awaiting event...\n"); 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) { return (PTP_RC_OK); } else { if (verbose) perror("ptp_check_int"); return PTP_ERROR_IO; }}voiddebug (void *data, const char *format, va_list args);voiddebug (void *data, const char *format, va_list args){ if (verbose<2) return; vfprintf (stderr, format, args); fprintf (stderr,"\n"); fflush(stderr);}voiderror (void *data, const char *format, va_list args);voiderror (void *data, const char *format, va_list args){/* if (!verbose) return; */ vfprintf (stderr, format, args); fprintf (stderr,"\n"); fflush(stderr);}voidinit_ptp_usb (PTPParams* params, PTP_USB* ptp_usb, struct usb_device* dev){ usb_dev_handle *device_handle; params->write_func=ptp_write_func; params->read_func=ptp_read_func; params->check_int_func=ptp_check_int; params->check_int_fast_func=ptp_check_int; params->error_func=error; params->debug_func=debug; params->sendreq_func=ptp_usb_sendreq; params->senddata_func=ptp_usb_senddata; params->getresp_func=ptp_usb_getresp; params->getdata_func=ptp_usb_getdata; params->data=ptp_usb; params->transaction_id=0; params->byteorder = PTP_DL_LE; if ((device_handle=usb_open(dev))){ if (!device_handle) { perror("usb_open()"); exit(0); } ptp_usb->handle=device_handle; usb_claim_interface(device_handle, dev->config->interface->altsetting->bInterfaceNumber); }}voidclear_stall(PTP_USB* ptp_usb, struct usb_device* dev){ uint16_t status=0; int ret; /* check the inep status */ ret=usb_get_endpoint_status(ptp_usb,ptp_usb->inep,&status); if (ret<0) perror ("inep: usb_get_endpoint_status()"); /* and clear the HALT condition if happend */ else if (status) { printf("Resetting input pipe!\n"); ret=usb_clear_stall_feature(ptp_usb,ptp_usb->inep); /*usb_clear_halt(ptp_usb->handle,ptp_usb->inep); */ if (ret<0)perror ("usb_clear_stall_feature()"); } status=0; /* check the outep status */ ret=usb_get_endpoint_status(ptp_usb,ptp_usb->outep,&status); if (ret<0) perror ("outep: usb_get_endpoint_status()"); /* and clear the HALT condition if happend */ else if (status) { printf("Resetting output pipe!\n"); ret=usb_clear_stall_feature(ptp_usb,ptp_usb->outep); /*usb_clear_halt(ptp_usb->handle,ptp_usb->outep); */ if (ret<0)perror ("usb_clear_stall_feature()"); } /*usb_clear_halt(ptp_usb->handle,ptp_usb->intep); */}voidclose_usb(PTP_USB* ptp_usb, struct usb_device* dev){ clear_stall(ptp_usb, dev); usb_release_interface(ptp_usb->handle, dev->config->interface->altsetting->bInterfaceNumber); usb_close(ptp_usb->handle);}struct usb_bus*init_usb(){ usb_init(); usb_find_busses(); usb_find_devices(); return (usb_get_busses());}/* find_device() returns the pointer to a usb_device structure matching given busn, devicen numbers. If any or both of arguments are 0 then the first matching PTP device structure is returned. */struct usb_device*find_device (int busn, int devicen, short force);struct usb_device*find_device (int busn, int devn, short force){ struct usb_bus *bus; struct usb_device *dev; bus=init_usb(); for (; bus; bus = bus->next) for (dev = bus->devices; dev; dev = dev->next) if ((dev->config->interface->altsetting->bInterfaceClass== USB_CLASS_PTP)||force) if (dev->descriptor.bDeviceClass!=USB_CLASS_HUB) { int curbusn, curdevn; curbusn=strtol(bus->dirname,NULL,10); curdevn=strtol(dev->filename,NULL,10); if (devn==0) { if (busn==0) return dev; if (curbusn==busn) return dev; } else { if ((busn==0)&&(curdevn==devn)) return dev; if ((curbusn==busn)&&(curdevn==devn)) return dev; } } return NULL;}voidfind_endpoints(struct usb_device *dev, int* inep, int* outep, int* intep);voidfind_endpoints(struct usb_device *dev, int* inep, int* outep, int* intep){ int i,n; struct usb_endpoint_descriptor *ep; ep = dev->config->interface->altsetting->endpoint; n=dev->config->interface->altsetting->bNumEndpoints; for (i=0;i<n;i++) { if (ep[i].bmAttributes==USB_ENDPOINT_TYPE_BULK) { if ((ep[i].bEndpointAddress&USB_ENDPOINT_DIR_MASK)== USB_ENDPOINT_DIR_MASK) { *inep=ep[i].bEndpointAddress; if (verbose) printf ("Found inep: 0x%02x\n",*inep); } if ((ep[i].bEndpointAddress&USB_ENDPOINT_DIR_MASK)==0) { *outep=ep[i].bEndpointAddress; if (verbose) printf ("Found outep: 0x%02x\n",*outep); } } else if (ep[i].bmAttributes==USB_ENDPOINT_TYPE_INTERRUPT){ if ((ep[i].bEndpointAddress&USB_ENDPOINT_DIR_MASK)== USB_ENDPOINT_DIR_MASK) { *intep=ep[i].bEndpointAddress; if (verbose) printf ("Found intep: 0x%02x\n",*intep); } } }}intopen_camera (int busn, int devn, short force, PTP_USB *ptp_usb, PTPParams *params, struct usb_device **dev){#ifdef DEBUG printf("dev %i\tbus %i\n",devn,busn);#endif *dev=find_device(busn,devn,force); if (*dev==NULL) { fprintf(stderr,"could not find any device matching given " "bus/dev numbers\n"); exit(-1); } find_endpoints(*dev,&ptp_usb->inep,&ptp_usb->outep,&ptp_usb->intep); init_ptp_usb(params, ptp_usb, *dev); if (ptp_opensession(params,1)!=PTP_RC_OK) { fprintf(stderr,"ERROR: Could not open session!\n"); close_usb(ptp_usb, *dev); return -1; } return 0;}voidclose_camera (PTP_USB *ptp_usb, PTPParams *params, struct usb_device *dev){ if (ptp_closesession(params)!=PTP_RC_OK) fprintf(stderr,"ERROR: Could not close session!\n"); close_usb(ptp_usb, dev);}voidlist_devices(short force){ struct usb_bus *bus; struct usb_device *dev; int found=0; bus=init_usb(); for (; bus; bus = bus->next) for (dev = bus->devices; dev; dev = dev->next) { /* if it's a PTP device try to talk to it */ if ((dev->config->interface->altsetting->bInterfaceClass== USB_CLASS_PTP)||force) if (dev->descriptor.bDeviceClass!=USB_CLASS_HUB) { int n; struct usb_endpoint_descriptor *ep; PTPParams params; PTP_USB ptp_usb; PTPDeviceInfo deviceinfo; if (!found){ printf("\nListing devices...\n"); printf("bus/dev\tvendorID/prodID\tdevice model\n"); found=1; } ep = dev->config->interface->altsetting->endpoint; n=dev->config->interface->altsetting->bNumEndpoints; find_endpoints(dev,&ptp_usb.inep,&ptp_usb.outep, &ptp_usb.intep); init_ptp_usb(¶ms, &ptp_usb, dev); CC(ptp_opensession (¶ms,1), "Could not open session!\n" "Try to reset the camera.\n"); CC(ptp_getdeviceinfo (¶ms, &deviceinfo), "Could not get device info!\n"); printf("%s/%s\t0x%04X/0x%04X\t%s\n", bus->dirname, dev->filename, dev->descriptor.idVendor, dev->descriptor.idProduct, deviceinfo.Model); CC(ptp_closesession(¶ms), "Could not close session!\n"); close_usb(&ptp_usb, dev); } } if (!found) printf("\nFound no PTP devices\n"); printf("\n");}voidshow_info (int busn, int devn, short force){ PTPParams params; PTP_USB ptp_usb; struct usb_device *dev; printf("\nCamera information\n"); printf("==================\n"); if (open_camera(busn, devn, force, &ptp_usb, ¶ms, &dev)<0) return; CR(ptp_getdeviceinfo (¶ms, ¶ms.deviceinfo), "Could not get device info\n"); printf("Model: %s\n",params.deviceinfo.Model); printf(" manufacturer: %s\n",params.deviceinfo.Manufacturer);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -