📄 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 <signal.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 5000#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;/* we need it for a proper signal handling :/ */PTPParams* globalparams;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" " --set=PROP-NAME Set property by name (abbreviations allowed)\n" " --val=VALUE Property value (numeric for --set-property and\n" " string or numeric for --set)\n" " --show-all-properties Show all properties values\n" " --show-unknown-properties Show unknown properties values\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" " --nikon-ic, --nic Initiate Nikon Direct Capture (no download!)\n" " --nikon-dc, --ndc Initiate Nikon Direct Capture and download\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");}voidptpcam_siginthandler(int signum){ PTP_USB* ptp_usb=(PTP_USB *)globalparams->data; struct usb_device *dev=usb_device(ptp_usb->handle); if (signum==SIGINT) { /* hey it's not that easy though... but at least we can try! */ printf("Got SIGINT, trying to clean up and close...\n"); usleep(5000); close_camera (ptp_usb, globalparams, dev); exit (-1); }}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; }}/* XXX this one is suposed to return the number of bytes read!!! */static shortptp_check_int (unsigned char *bytes, unsigned int size, void *data){ int result; PTP_USB *ptp_usb=(PTP_USB *)data; 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 (verbose>2) fprintf (stderr, "USB_BULK_READ returned %i, size=%i\n", result, size); if (result >= 0) { return result; } else { if (verbose) perror("ptp_check_int"); return result; }}voidptpcam_debug (void *data, const char *format, va_list args);voidptpcam_debug (void *data, const char *format, va_list args){ if (verbose<2) return; vfprintf (stderr, format, args); fprintf (stderr,"\n"); fflush(stderr);}voidptpcam_error (void *data, const char *format, va_list args);voidptpcam_error (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=ptpcam_error; params->debug_func=ptpcam_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_set_configuration(device_handle, dev->config->bConfigurationValue); usb_claim_interface(device_handle, dev->config->interface->altsetting->bInterfaceNumber); } globalparams=params;}voidclear_stall(PTP_USB* ptp_usb){ 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); usb_release_interface(ptp_usb->handle, dev->config->interface->altsetting->bInterfaceNumber); usb_reset(ptp_usb->handle); 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) 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>1) fprintf(stderr, "Found inep: 0x%02x\n",*inep); } if ((ep[i].bEndpointAddress&USB_ENDPOINT_DIR_MASK)==0) { *outep=ep[i].bEndpointAddress; if (verbose>1) fprintf(stderr, "Found outep: 0x%02x\n",*outep); } } else if ((ep[i].bmAttributes==USB_ENDPOINT_TYPE_INTERRUPT) && ((ep[i].bEndpointAddress&USB_ENDPOINT_DIR_MASK)== USB_ENDPOINT_DIR_MASK)) { *intep=ep[i].bEndpointAddress; if (verbose>1) fprintf(stderr, "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; } if (ptp_getdeviceinfo(params,¶ms->deviceinfo)!=PTP_RC_OK) { fprintf(stderr,"ERROR: Could not get device info!\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) if ((dev->config->interface->altsetting->bInterfaceClass== USB_CLASS_PTP)||force) if (dev->descriptor.bDeviceClass!=USB_CLASS_HUB) { PTPParams params; PTP_USB ptp_usb; PTPDeviceInfo deviceinfo; if (!found){ printf("\nListing devices...\n"); printf("bus/dev\tvendorID/prodID\tdevice model\n"); found=1; } 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; printf("Model: %s\n",params.deviceinfo.Model); printf(" manufacturer: %s\n",params.deviceinfo.Manufacturer); printf(" serial number: '%s'\n",params.deviceinfo.SerialNumber); printf(" device version: %s\n",params.deviceinfo.DeviceVersion); printf(" extension ID: 0x%08lx\n",(long unsigned) params.deviceinfo.VendorExtensionID); printf(" extension description: %s\n", params.deviceinfo.VendorExtensionDesc); printf(" extension version: 0x%04x\n", params.deviceinfo.VendorExtensionVersion); printf("\n"); close_camera(&ptp_usb, ¶ms, dev);}voidcapture_image (int busn, int devn, short force){ PTPParams params;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -