blob: f81017e18833f6caa34ee26428f45658462121cb [file] [log] [blame]
Linus Walleijeb8c6fe2006-02-03 09:46:22 +00001/*
Linus Walleij15e344f2006-03-06 15:15:00 +00002 * libusb-glue.c
Linus Walleijeb8c6fe2006-02-03 09:46:22 +00003 *
Linus Walleij15e344f2006-03-06 15:15:00 +00004 * Created by Richard Low on 24/12/2005. (as mtp-utils.c)
Linus Walleija5483642006-03-09 09:20:38 +00005 * Modified by Linus Walleij 2006-03-06
6 * (Notice that Anglo-Saxons use little-endian dates and Swedes use big-endian dates.)
Linus Walleijeb8c6fe2006-02-03 09:46:22 +00007 *
8 * This file adds some utils (many copied from ptpcam.c from libptp2) to
9 * use MTP devices. Include mtp-utils.h to use any of the ptp/mtp functions.
10 *
11 */
12#include "ptp.h"
13#include <errno.h>
14#include <stdio.h>
15#include <stdlib.h>
16#include <string.h>
17#include <getopt.h>
18#include <unistd.h>
19#include <sys/types.h>
20#include <utime.h>
21#include <sys/stat.h>
22#include <fcntl.h>
23#include <sys/mman.h>
24#include <usb.h>
25
Linus Walleij15e344f2006-03-06 15:15:00 +000026#include "libmtp.h"
27#include "libusb-glue.h"
Linus Walleijb02a0662006-04-25 08:05:09 +000028// #include "ptp-pack.h"
Linus Walleijeb8c6fe2006-02-03 09:46:22 +000029
30/* OUR APPLICATION USB URB (2MB) ;) */
31#define PTPCAM_USB_URB 2097152
32
33/* this must not be too short - the original 4000 was not long
34 enough for big file transfers. I imagine the player spends a
35 bit of time gearing up to receiving lots of data. This also makes
36 connecting/disconnecting more reliable */
37#define USB_TIMEOUT 10000
38#define USB_CAPTURE_TIMEOUT 20000
39
40/* USB control message data phase direction */
41#ifndef USB_DP_HTD
42#define USB_DP_HTD (0x00 << 7) /* host to device */
43#endif
44#ifndef USB_DP_DTH
45#define USB_DP_DTH (0x01 << 7) /* device to host */
46#endif
47
48/* USB Feature selector HALT */
49#ifndef USB_FEATURE_HALT
50#define USB_FEATURE_HALT 0x00
51#endif
52
Linus Walleija5483642006-03-09 09:20:38 +000053/*
Linus Walleije8c54642006-03-28 09:45:00 +000054 * MTP device list, trying real bad to get all devices into
55 * this list by stealing from everyone I know.
Linus Walleija5483642006-03-09 09:20:38 +000056 */
Linus Walleij6fd2f082006-03-28 07:19:22 +000057static const LIBMTP_device_entry_t mtp_device_table[] = {
Linus Walleije8c54642006-03-28 09:45:00 +000058 /* Creative devices */
Linus Walleij6fd2f082006-03-28 07:19:22 +000059 { "Creative Zen Vision", 0x041e, 0x411f, NULL },
60 { "Creative Portable Media Center", 0x041e, 0x4123, NULL },
61 { "Creative Zen Xtra (MTP mode)", 0x041e, 0x4128, NULL },
62 { "Second generation Dell DJ", 0x041e, 0x412f, NULL },
63 { "Creative Zen Micro (MTP mode)", 0x041e, 0x4130, NULL },
64 { "Creative Zen Touch (MTP mode)", 0x041e, 0x4131, NULL },
65 { "Creative Zen Sleek (MTP mode)", 0x041e, 0x4137, NULL },
66 { "Creative Zen MicroPhoto", 0x041e, 0x413c, NULL },
67 { "Creative Zen Sleek Photo", 0x041e, 0x413d, NULL },
68 { "Creative Zen Vision:M", 0x041e, 0x413e, NULL },
Linus Walleijea08c2b2006-04-21 08:26:06 +000069 /* Contributed by anonymous person on SourceForge */
Linus Walleija06a2792006-04-21 07:52:26 +000070 { "Samsung YP-T7J", 0x04e8, 0x5047, NULL },
Linus Walleije8c54642006-03-28 09:45:00 +000071 /*
72 * Copied in from libgphoto2's libptp2 adaption "library.c"
73 * carefully trying to pick only the MTP devices.
74 * Greetings to Marcus Meissner! (we should merge our
75 * projects some day...)
76 */
Linus Walleija06a2792006-04-21 07:52:26 +000077 { "Philipps HDD6320", 0x0471, 0x01eb, NULL},
Linus Walleij6fd2f082006-03-28 07:19:22 +000078 { "iRiver T10", 0x4102, 0x1113, NULL },
Linus Walleije8c54642006-03-28 09:45:00 +000079 { "iRiver U10", 0x4102, 0x1116, NULL },
Linus Walleij6fd2f082006-03-28 07:19:22 +000080 { "iRiver T10", 0x4102, 0x1117, NULL },
Linus Walleije8c54642006-03-28 09:45:00 +000081 { "iRiver T20", 0x4102, 0x1118, NULL },
82 { "iRiver T30", 0x4102, 0x1119, NULL },
Linus Walleija06a2792006-04-21 07:52:26 +000083 { "iRiver H10", 0x4102, 0x2102, NULL },
84 { "Dell DJ Itty", 0x413c, 0x4500, NULL},
Linus Walleije8c54642006-03-28 09:45:00 +000085 { "Toshiba Gigabeat", 0x0930, 0x000c, NULL}
Linus Walleija5483642006-03-09 09:20:38 +000086};
Linus Walleij6fd2f082006-03-28 07:19:22 +000087static const int mtp_device_table_size = sizeof(mtp_device_table) / sizeof(LIBMTP_device_entry_t);
Linus Walleija5483642006-03-09 09:20:38 +000088
Linus Walleijeb8c6fe2006-02-03 09:46:22 +000089int ptpcam_usb_timeout = USB_TIMEOUT;
90
91void close_usb(PTP_USB* ptp_usb, uint8_t interfaceNumber);
92struct usb_device* find_device (int busn, int devicen, short force);
Linus Walleije8c54642006-03-28 09:45:00 +000093void find_endpoints(struct usb_device *dev, int* inep, int* inep_maxpacket, int* outep, int* outep_maxpacket, int* intep);
Linus Walleijeb8c6fe2006-02-03 09:46:22 +000094void clear_stall(PTP_USB* ptp_usb);
95void init_ptp_usb (PTPParams* params, PTP_USB* ptp_usb, struct usb_device* dev);
96static short ptp_write_func (unsigned char *bytes, unsigned int size, void *data);
Linus Walleijb02a0662006-04-25 08:05:09 +000097static short ptp_read_func (unsigned char *bytes, unsigned int size, void *data, unsigned int *readbytes);
98static short ptp_check_int (unsigned char *bytes, unsigned int size, void *data, unsigned int *rlen);
Linus Walleijeb8c6fe2006-02-03 09:46:22 +000099int usb_clear_stall_feature(PTP_USB* ptp_usb, int ep);
100int usb_get_endpoint_status(PTP_USB* ptp_usb, int ep, uint16_t* status);
101
Linus Walleij6fd2f082006-03-28 07:19:22 +0000102int get_device_list(LIBMTP_device_entry_t ** const devices, int * const numdevs)
103{
104 *devices = (LIBMTP_device_entry_t *) &mtp_device_table;
105 *numdevs = mtp_device_table_size;
106 return 0;
107}
108
Linus Walleijb02a0662006-04-25 08:05:09 +0000109#define CONTEXT_BLOCK_SIZE 100000
110static short
111ptp_read_func (unsigned char *bytes, unsigned int size, void *data, unsigned int *readbytes)
Linus Walleijeb8c6fe2006-02-03 09:46:22 +0000112{
Linus Walleijb02a0662006-04-25 08:05:09 +0000113 PTP_USB *ptp_usb = (PTP_USB *)data;
114 //Camera *camera = ((PTPData *)data)->camera;
115 int toread, result, curread = 0;
116 int usecontext = (size > CONTEXT_BLOCK_SIZE);
117 int progressid = 0;
118 //GPContext *context = ((PTPData *)data)->context;
119
120 /* Split into small blocks. Too large blocks (>1x MB) would
121 * timeout.
122 */
123 //if (usecontext)
124 // progressid = gp_context_progress_start (context, (size/CONTEXT_BLOCK_SIZE), _("Downloading..."));
125 while (curread < size) {
126 int oldsize = curread;
127
128 toread = size - curread;
129 if (toread > 4096)
130 toread = 4096;
131
132 result = USB_BULK_READ(ptp_usb->handle, ptp_usb->inep,(char *)(bytes+curread), toread, ptpcam_usb_timeout);
133 // result = gp_port_read (camera->port, (char*)(bytes + curread), toread);
134 if (result == 0) {
135 result = USB_BULK_READ(ptp_usb->handle, ptp_usb->inep,(char *)(bytes+curread), toread, ptpcam_usb_timeout);
136 // result = gp_port_read (camera->port, (char*)(bytes + curread), toread);
137 }
Linus Walleijeb8c6fe2006-02-03 09:46:22 +0000138 if (result < 0)
139 break;
Linus Walleijb02a0662006-04-25 08:05:09 +0000140 curread += result;
141 //if (usecontext && (oldsize/CONTEXT_BLOCK_SIZE < curread/CONTEXT_BLOCK_SIZE))
142 // gp_context_progress_update (context, progressid, curread/CONTEXT_BLOCK_SIZE);
143 if (result < toread) /* short reads are common */
144 break;
Linus Walleijeb8c6fe2006-02-03 09:46:22 +0000145 }
Linus Walleijb02a0662006-04-25 08:05:09 +0000146 //if (usecontext)
147 // gp_context_progress_stop (context, progressid);
148 if (result > 0) {
149 *readbytes = curread;
150 return (PTP_RC_OK);
Linus Walleijeb8c6fe2006-02-03 09:46:22 +0000151 } else {
Linus Walleijb02a0662006-04-25 08:05:09 +0000152 // return (translate_gp_result (result));
153 return PTP_ERROR_IO;
Linus Walleijeb8c6fe2006-02-03 09:46:22 +0000154 }
155}
156
Linus Walleijb02a0662006-04-25 08:05:09 +0000157static short
158ptp_write_func (unsigned char *bytes, unsigned int size, void *data)
159{
160 PTP_USB *ptp_usb = (PTP_USB *)data;
161 //Camera *camera = ((PTPData *)data)->camera;
162 int towrite, result, curwrite = 0;
163 int progressid = 0;
164 int usecontext = (size > CONTEXT_BLOCK_SIZE);
165 //GPContext *context = ((PTPData *)data)->context;
166
167 /*
168 * gp_port_write returns (in case of success) the number of bytes
169 * write. Too large blocks (>5x MB) could timeout.
170 */
171 //if (usecontext)
172 // progressid = gp_context_progress_start (context, (size/CONTEXT_BLOCK_SIZE), _("Uploading..."));
173 while (curwrite < size) {
174 int oldsize = curwrite;
175
176 towrite = size-curwrite;
177 if (towrite > 4096)
178 towrite = 4096;
179 result=USB_BULK_WRITE(ptp_usb->handle,ptp_usb->outep,(char *)(bytes+curwrite),towrite,ptpcam_usb_timeout);
180 // result = gp_port_write (camera->port, (char*)(bytes + curwrite), towrite);
181 if (result < 0)
182 break;
183 curwrite += result;
184 //if (usecontext && (oldsize/CONTEXT_BLOCK_SIZE < curwrite/CONTEXT_BLOCK_SIZE))
185 // gp_context_progress_update (context, progressid, curwrite/CONTEXT_BLOCK_SIZE);
186 if (result < towrite) /* short writes happen */
187 break;
188 }
189 //if (usecontext)
190 // gp_context_progress_stop (context, progressid);
191 // Should load wMaxPacketsize from endpoint first. But works fine for all EPs.
192 if ((size % 512) == 0)
193 result=USB_BULK_WRITE(ptp_usb->handle,ptp_usb->outep,(char *)"x",0,ptpcam_usb_timeout);
194 // gp_port_write (camera->port, "x", 0);
195 if (result < 0)
196 return PTP_ERROR_IO;
197 //return (translate_gp_result (result));
198 return PTP_RC_OK;
199}
200
201static short ptp_check_int (unsigned char *bytes, unsigned int size, void *data, unsigned int *rlen)
202{
203 int result;
204 PTP_USB *ptp_usb=(PTP_USB *)data;
205
206 result=USB_BULK_READ(ptp_usb->handle, ptp_usb->intep,(char *)bytes,size,ptpcam_usb_timeout);
207 if (result==0)
208 result = USB_BULK_READ(ptp_usb->handle, ptp_usb->intep,(char *) bytes, size, ptpcam_usb_timeout);
209 if (result >= 0) {
210 *rlen = result;
211 return (PTP_RC_OK);
212 } else {
213 return PTP_ERROR_IO;
214 }
215}
216
Linus Walleijeb8c6fe2006-02-03 09:46:22 +0000217void init_ptp_usb (PTPParams* params, PTP_USB* ptp_usb, struct usb_device* dev)
218{
219 usb_dev_handle *device_handle;
220
221 params->write_func=ptp_write_func;
222 params->read_func=ptp_read_func;
223 params->check_int_func=ptp_check_int;
224 params->check_int_fast_func=ptp_check_int;
225 params->error_func=NULL;
226 params->debug_func=NULL;
227 params->sendreq_func=ptp_usb_sendreq;
228 params->senddata_func=ptp_usb_senddata;
229 params->getresp_func=ptp_usb_getresp;
230 params->getdata_func=ptp_usb_getdata;
231 params->data=ptp_usb;
232 params->transaction_id=0;
233 params->byteorder = PTP_DL_LE;
234
235 if ((device_handle=usb_open(dev))){
236 if (!device_handle) {
237 perror("usb_open()");
238 exit(0);
239 }
240 ptp_usb->handle=device_handle;
241 usb_claim_interface(device_handle,
242 dev->config->interface->altsetting->bInterfaceNumber);
243 }
244}
245
246void clear_stall(PTP_USB* ptp_usb)
247{
248 uint16_t status=0;
249 int ret;
250
251 /* check the inep status */
252 ret=usb_get_endpoint_status(ptp_usb,ptp_usb->inep,&status);
253 if (ret<0) perror ("inep: usb_get_endpoint_status()");
254 /* and clear the HALT condition if happend */
255 else if (status) {
256 printf("Resetting input pipe!\n");
257 ret=usb_clear_stall_feature(ptp_usb,ptp_usb->inep);
258 /*usb_clear_halt(ptp_usb->handle,ptp_usb->inep); */
259 if (ret<0)perror ("usb_clear_stall_feature()");
260 }
261 status=0;
262
263 /* check the outep status */
264 ret=usb_get_endpoint_status(ptp_usb,ptp_usb->outep,&status);
265 if (ret<0) perror ("outep: usb_get_endpoint_status()");
266 /* and clear the HALT condition if happend */
267 else if (status) {
268 printf("Resetting output pipe!\n");
269 ret=usb_clear_stall_feature(ptp_usb,ptp_usb->outep);
270 /*usb_clear_halt(ptp_usb->handle,ptp_usb->outep); */
271 if (ret<0)perror ("usb_clear_stall_feature()");
272 }
273
274 /*usb_clear_halt(ptp_usb->handle,ptp_usb->intep); */
275}
276
277void close_usb(PTP_USB* ptp_usb, uint8_t interfaceNumber)
278{
279 clear_stall(ptp_usb);
Linus Walleija5483642006-03-09 09:20:38 +0000280 // Added to clear some stuff on the OUT endpoint
281 // TODO: is this good on the Mac too?
282 usb_resetep(ptp_usb->handle, ptp_usb->outep);
Linus Walleijeb8c6fe2006-02-03 09:46:22 +0000283 usb_release_interface(ptp_usb->handle, interfaceNumber);
Linus Walleija5483642006-03-09 09:20:38 +0000284 // Brutally reset device
285 // TODO: is this good on the Mac too?
286 usb_reset(ptp_usb->handle);
Linus Walleijeb8c6fe2006-02-03 09:46:22 +0000287 usb_close(ptp_usb->handle);
288}
289
290
291struct usb_bus*
292init_usb()
293{
294 usb_init();
295 usb_find_busses();
296 usb_find_devices();
297 return (usb_get_busses());
298}
299
300/*
301 find_device() returns the pointer to a usb_device structure matching
302 given busn, devicen numbers. If any or both of arguments are 0 then the
303 first matching PTP device structure is returned.
304 */
305struct usb_device* find_device (int busn, int devn, short force)
306{
307 struct usb_bus *bus;
308 struct usb_device *dev;
309
310 bus=init_usb();
311 for (; bus; bus = bus->next)
312 for (dev = bus->devices; dev; dev = dev->next)
313 /* somtimes dev->config is null, not sure why... */
314 if (dev->config != NULL)
315 if (dev->descriptor.bDeviceClass!=USB_CLASS_HUB)
316 {
317 int curbusn, curdevn;
318
319 curbusn=strtol(bus->dirname,NULL,10);
320 curdevn=strtol(dev->filename,NULL,10);
321
322 if (devn==0) {
323 if (busn==0) return dev;
324 if (curbusn==busn) return dev;
325 } else {
326 if ((busn==0)&&(curdevn==devn)) return dev;
327 if ((curbusn==busn)&&(curdevn==devn)) return dev;
328 }
329 }
330 return NULL;
331}
332
Linus Walleij6946ac52006-03-21 06:51:22 +0000333/**
334 * This function scans through the device list to see if there are
335 * some devices to connect to. The table at the top of this file is
336 * used to identify potential devices.
337 */
Linus Walleijeb8c6fe2006-02-03 09:46:22 +0000338uint16_t connect_first_device(PTPParams *params, PTP_USB *ptp_usb, uint8_t *interfaceNumber)
339{
Linus Walleij6946ac52006-03-21 06:51:22 +0000340 struct usb_bus *bus;
341 struct usb_device *dev;
342
343 bus = init_usb();
344 for (; bus; bus = bus->next) {
345 for (dev = bus->devices; dev; dev = dev->next) {
346 int i;
347
348 // Loop over the list of supported devices
349 for (i = 0; i < mtp_device_table_size; i++) {
Linus Walleij6fd2f082006-03-28 07:19:22 +0000350 LIBMTP_device_entry_t const *mtp_device = &mtp_device_table[i];
Linus Walleijeb8c6fe2006-02-03 09:46:22 +0000351
Linus Walleij6946ac52006-03-21 06:51:22 +0000352 if (dev->descriptor.bDeviceClass != USB_CLASS_HUB &&
353 dev->descriptor.idVendor == mtp_device->vendor_id &&
354 dev->descriptor.idProduct == mtp_device->product_id ) {
355 uint16_t ret=0;
356 int n;
357 struct usb_endpoint_descriptor *ep;
358 PTPDeviceInfo deviceinfo;
359
360 printf("Found device \"%s\" on USB bus...\n", mtp_device->name);
361 ep = dev->config->interface->altsetting->endpoint;
362 n=dev->config->interface->altsetting->bNumEndpoints;
363
Linus Walleije8c54642006-03-28 09:45:00 +0000364 find_endpoints(dev,&(ptp_usb->inep),&(ptp_usb->inep_maxpacket),&(ptp_usb->outep),&(ptp_usb->outep_maxpacket),&(ptp_usb->intep));
Linus Walleijb02a0662006-04-25 08:05:09 +0000365 printf("Init PTP USB...\n");
Linus Walleij6946ac52006-03-21 06:51:22 +0000366 init_ptp_usb(params, ptp_usb, dev);
367
368 ret = ptp_opensession(params,1);
Linus Walleijb02a0662006-04-25 08:05:09 +0000369 printf("Session open (%d)...\n", ret);
370 if (ret == PTP_RC_InvalidTransactionID) {
371 params->transaction_id += 10;
372 ret = ptp_opensession(params,1);
373 }
374 if (ret != PTP_RC_SessionAlreadyOpened && ret != PTP_RC_OK) {
375 printf("Could not open session! (Return code %d)\n Try to reset the device.\n", ret);
Linus Walleij6946ac52006-03-21 06:51:22 +0000376 usb_release_interface(ptp_usb->handle,dev->config->interface->altsetting->bInterfaceNumber);
377 continue;
378 }
Linus Walleijb02a0662006-04-25 08:05:09 +0000379 /* It is actually permissible to call this before opening the session */
Linus Walleij6946ac52006-03-21 06:51:22 +0000380 ret = ptp_getdeviceinfo(params, &deviceinfo);
381 if (ret != PTP_RC_OK) {
382 printf("Could not get device info!\n");
383 usb_release_interface(ptp_usb->handle,dev->config->interface->altsetting->bInterfaceNumber);
384 return PTP_CD_RC_ERROR_CONNECTING;
385 }
Linus Walleijb02a0662006-04-25 08:05:09 +0000386 /* Print out some verbose information */
387 if (1) {
388 int i;
389
390 printf("Device info:\n");
391 printf("Manufacturer: %s\n", params->deviceinfo.Manufacturer);
392 printf(" Model: %s\n", params->deviceinfo.Model);
393 printf(" Device version: %s\n", params->deviceinfo.DeviceVersion);
394 printf(" Serial number: %s\n", params->deviceinfo.SerialNumber);
395 printf("Vendor extension ID: 0x%08x\n", params->deviceinfo.VendorExtensionID);
396 printf("Vendor extension description: %s\n", params->deviceinfo.VendorExtensionDesc);
397 printf("Supported operations:\n");
398 for (i=0;i<params->deviceinfo.OperationsSupported_len;i++) {
399 printf(" 0x%04x\n", params->deviceinfo.OperationsSupported[i]);
400 }
401 printf("Events supported:\n");
402 for (i=0;i<params->deviceinfo.EventsSupported_len;i++) {
403 printf(" 0x%04x\n", params->deviceinfo.EventsSupported[i]);
404 }
405 printf("Device Properties Supported:\n");
406 for (i=0;i<params->deviceinfo.DevicePropertiesSupported_len;i++) {
407 printf(" 0x%04x\n", params->deviceinfo.DevicePropertiesSupported[i]);
408 }
409 }
Linus Walleij6946ac52006-03-21 06:51:22 +0000410
411 /* we're connected, return ok */
412 *interfaceNumber = dev->config->interface->altsetting->bInterfaceNumber;
413
414 return PTP_CD_RC_CONNECTED;
Linus Walleijeb8c6fe2006-02-03 09:46:22 +0000415 }
Linus Walleij6946ac52006-03-21 06:51:22 +0000416 }
417 }
418 }
419 /* none found */
420 return PTP_CD_RC_NO_DEVICES;
Linus Walleijeb8c6fe2006-02-03 09:46:22 +0000421}
422
Linus Walleije8c54642006-03-28 09:45:00 +0000423void find_endpoints(struct usb_device *dev, int* inep, int* inep_maxpacket, int* outep, int *outep_maxpacket, int* intep)
Linus Walleijeb8c6fe2006-02-03 09:46:22 +0000424{
425 int i,n;
426 struct usb_endpoint_descriptor *ep;
427
428 ep = dev->config->interface->altsetting->endpoint;
429 n=dev->config->interface->altsetting->bNumEndpoints;
430
431 for (i=0;i<n;i++) {
432 if (ep[i].bmAttributes==USB_ENDPOINT_TYPE_BULK) {
433 if ((ep[i].bEndpointAddress&USB_ENDPOINT_DIR_MASK)==
434 USB_ENDPOINT_DIR_MASK)
435 {
436 *inep=ep[i].bEndpointAddress;
Linus Walleije8c54642006-03-28 09:45:00 +0000437 *inep_maxpacket=ep[i].wMaxPacketSize;
Linus Walleijeb8c6fe2006-02-03 09:46:22 +0000438 }
439 if ((ep[i].bEndpointAddress&USB_ENDPOINT_DIR_MASK)==0)
440 {
441 *outep=ep[i].bEndpointAddress;
Linus Walleije8c54642006-03-28 09:45:00 +0000442 *inep_maxpacket=ep[i].wMaxPacketSize;
Linus Walleijeb8c6fe2006-02-03 09:46:22 +0000443 }
444 } else if (ep[i].bmAttributes==USB_ENDPOINT_TYPE_INTERRUPT){
445 if ((ep[i].bEndpointAddress&USB_ENDPOINT_DIR_MASK)==
446 USB_ENDPOINT_DIR_MASK)
447 {
448 *intep=ep[i].bEndpointAddress;
449 }
450 }
451 }
452}
453
454
455int open_device (int busn, int devn, short force, PTP_USB *ptp_usb, PTPParams *params, struct usb_device **dev)
456{
457#ifdef DEBUG
458 printf("dev %i\tbus %i\n",devn,busn);
459#endif
460
461 *dev=find_device(busn,devn,force);
462 if (*dev==NULL) {
463 fprintf(stderr,"could not find any device matching given "
464 "bus/dev numbers\n");
465 exit(-1);
466 }
Linus Walleije8c54642006-03-28 09:45:00 +0000467 find_endpoints(*dev,&ptp_usb->inep,&ptp_usb->inep_maxpacket,&ptp_usb->outep,&ptp_usb->outep_maxpacket,&ptp_usb->intep);
Linus Walleijeb8c6fe2006-02-03 09:46:22 +0000468
469 init_ptp_usb(params, ptp_usb, *dev);
470 if (ptp_opensession(params,1)!=PTP_RC_OK) {
471 fprintf(stderr,"ERROR: Could not open session!\n");
472 close_usb(ptp_usb, (*dev)->config->interface->altsetting->bInterfaceNumber);
473 return -1;
474 }
475 return 0;
476}
477
478void close_device (PTP_USB *ptp_usb, PTPParams *params, uint8_t interfaceNumber)
479{
480 if (ptp_closesession(params)!=PTP_RC_OK)
481 fprintf(stderr,"ERROR: Could not close session!\n");
482 close_usb(ptp_usb, interfaceNumber);
483}
484
485int usb_clear_stall_feature(PTP_USB* ptp_usb, int ep)
486{
487
488 return (usb_control_msg(ptp_usb->handle,
489 USB_RECIP_ENDPOINT, USB_REQ_CLEAR_FEATURE, USB_FEATURE_HALT,
490 ep, NULL, 0, 3000));
491}
492
493int usb_get_endpoint_status(PTP_USB* ptp_usb, int ep, uint16_t* status)
494{
495 return (usb_control_msg(ptp_usb->handle,
496 USB_DP_DTH|USB_RECIP_ENDPOINT, USB_REQ_GET_STATUS,
497 USB_FEATURE_HALT, ep, (char *)status, 2, 3000));
498}