1 /*
2 * Linux specific functions
3 *
4 * Copyright (C) 2003 Olaf Kirch <okir@suse.de>
5 *
6 * These functions need to be re-implemented for every
7 * new platform.
8 */
9
10 #include "internal.h"
11 #if defined (__linux__) && !defined (sunray)
12 #include <sys/types.h>
13 #include <sys/sysmacros.h>
14 #include <sys/stat.h>
15 #include <sys/ioctl.h>
16 #include <sys/poll.h>
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <sys/file.h>
20 #include <dirent.h>
21 #include <string.h>
22 #include <stdio.h>
23 #include <stdarg.h>
24 #include <signal.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <fcntl.h>
28 #include <errno.h>
29 #include <limits.h>
30 #ifdef ENABLE_LIBUSB
31 #include <usb.h>
32 #endif
33 #include <openct/driver.h>
34
35 /* imported from linux kernel header include/linux/usbdevice_fs.h */
36
37 #define USBDEVICE_SUPER_MAGIC 0x9fa2
38
39 /* usbdevfs ioctl codes */
40
41 struct usbdevfs_ctrltransfer {
42 uint8_t bRequestType;
43 uint8_t bRequest;
44 uint16_t wValue;
45 uint16_t wIndex;
46 uint16_t wLength;
47 uint32_t timeout; /* in milliseconds */
48 void *data;
49 };
50
51 struct usbdevfs_bulktransfer {
52 unsigned int ep;
53 unsigned int len;
54 unsigned int timeout; /* in milliseconds */
55 void *data;
56 };
57
58 struct usbdevfs_setinterface {
59 unsigned int interface;
60 unsigned int altsetting;
61 };
62
63 struct usbdevfs_disconnectsignal {
64 unsigned int signr;
65 void *context;
66 };
67
68 #define USBDEVFS_MAXDRIVERNAME 255
69
70 struct usbdevfs_getdriver {
71 unsigned int interface;
72 char driver[USBDEVFS_MAXDRIVERNAME + 1];
73 };
74
75 struct usbdevfs_connectinfo {
76 unsigned int devnum;
77 unsigned char slow;
78 };
79
80 #define USBDEVFS_URB_SHORT_NOT_OK 1
81 #define USBDEVFS_URB_ISO_ASAP 2
82
83 #define USBDEVFS_URB_TYPE_ISO 0
84 #define USBDEVFS_URB_TYPE_INTERRUPT 1
85 #define USBDEVFS_URB_TYPE_CONTROL 2
86 #define USBDEVFS_URB_TYPE_BULK 3
87
88 struct usbdevfs_iso_packet_desc {
89 unsigned int length;
90 unsigned int actual_length;
91 unsigned int status;
92 };
93
94 struct usbdevfs_urb {
95 unsigned char type;
96 unsigned char endpoint;
97 int status;
98 unsigned int flags;
99 void *buffer;
100 int buffer_length;
101 int actual_length;
102 int start_frame;
103 int number_of_packets;
104 int error_count;
105 unsigned int signr; /* signal to be sent on error, -1 if none should be sent */
106 void *usercontext;
107 struct usbdevfs_iso_packet_desc iso_frame_desc[0];
108 };
109
110 /* ioctls for talking directly to drivers */
111 struct usbdevfs_ioctl {
112 int ifno; /* interface 0..N ; negative numbers reserved */
113 int ioctl_code; /* MUST encode size + direction of data so the
114 * macros in <asm/ioctl.h> give correct values */
115 void *data; /* param buffer (in, or out) */
116 };
117
118 /* You can do most things with hubs just through control messages,
119 * except find out what device connects to what port. */
120 struct usbdevfs_hub_portinfo {
121 char nports; /* number of downstream ports in this hub */
122 char port [127]; /* e.g. port 3 connects to device 27 */
123 };
124
125 #define USBDEVFS_CONTROL _IOWR('U', 0, struct usbdevfs_ctrltransfer)
126 #define USBDEVFS_BULK _IOWR('U', 2, struct usbdevfs_bulktransfer)
127 #define USBDEVFS_RESETEP _IOR('U', 3, unsigned int)
128 #define USBDEVFS_SETINTERFACE _IOR('U', 4, struct usbdevfs_setinterface)
129 #define USBDEVFS_SETCONFIGURATION _IOR('U', 5, unsigned int)
130 #define USBDEVFS_GETDRIVER _IOW('U', 8, struct usbdevfs_getdriver)
131 #define USBDEVFS_SUBMITURB _IOR('U', 10, struct usbdevfs_urb)
132 #define USBDEVFS_DISCARDURB _IO('U', 11)
133 #define USBDEVFS_REAPURB _IOW('U', 12, void *)
134 #define USBDEVFS_REAPURBNDELAY _IOW('U', 13, void *)
135 #define USBDEVFS_DISCSIGNAL _IOR('U', 14, struct usbdevfs_disconnectsignal)
136 #define USBDEVFS_CLAIMINTERFACE _IOR('U', 15, unsigned int)
137 #define USBDEVFS_RELEASEINTERFACE _IOR('U', 16, unsigned int)
138 #define USBDEVFS_CONNECTINFO _IOW('U', 17, struct usbdevfs_connectinfo)
139 #define USBDEVFS_IOCTL _IOWR('U', 18, struct usbdevfs_ioctl)
140 #define USBDEVFS_HUB_PORTINFO _IOR('U', 19, struct usbdevfs_hub_portinfo)
141 #define USBDEVFS_RESET _IO('U', 20)
142 #define USBDEVFS_CLEAR_HALT _IOR('U', 21, unsigned int)
143 #define USBDEVFS_DISCONNECT _IO('U', 22)
144 #define USBDEVFS_CONNECT _IO('U', 23)
145
146 /* end of import from usbdevice_fs.h */
147
148 #define USB_DISCONNECT_SIGNAL (SIGRTMIN)
149
150 /*
151 * Poll for presence of USB device
152 */
ifd_sysdep_usb_poll_presence(ifd_device_t * dev,struct pollfd * pfd)153 int ifd_sysdep_usb_poll_presence(ifd_device_t * dev, struct pollfd *pfd)
154 {
155 if (pfd->revents & POLLHUP)
156 return 0;
157 pfd->fd = dev->fd;
158 pfd->events = POLLHUP;
159 return 1;
160 }
161
162 /*
163 * Event fd to use.
164 */
ifd_sysdep_usb_get_eventfd(ifd_device_t * dev,short * events)165 int ifd_sysdep_usb_get_eventfd(ifd_device_t * dev, short *events)
166 {
167 *events = POLLOUT;
168 return dev->fd;
169 }
170
171 /*
172 * USB control command
173 */
ifd_sysdep_usb_control(ifd_device_t * dev,unsigned int requesttype,unsigned int request,unsigned int value,unsigned int idx,void * data,size_t len,long timeout)174 int ifd_sysdep_usb_control(ifd_device_t * dev, unsigned int requesttype,
175 unsigned int request, unsigned int value,
176 unsigned int idx, void *data, size_t len,
177 long timeout)
178 {
179 struct usbdevfs_ctrltransfer ctrl;
180 int rc;
181
182 ctrl.bRequestType = requesttype;
183 ctrl.bRequest = request;
184 ctrl.wValue = value;
185 ctrl.wIndex = idx;
186 ctrl.wLength = len;
187 ctrl.data = data;
188 ctrl.timeout = timeout;
189
190 if ((rc = ioctl(dev->fd, USBDEVFS_CONTROL, &ctrl)) < 0) {
191 ct_error("usb_control failed: %m");
192 return IFD_ERROR_COMM_ERROR;
193 }
194
195 return rc;
196 }
197
ifd_sysdep_usb_set_configuration(ifd_device_t * dev,int config)198 int ifd_sysdep_usb_set_configuration(ifd_device_t * dev, int config)
199 {
200 if (ioctl(dev->fd, USBDEVFS_SETCONFIGURATION, &config) < 0) {
201 ct_error("usb_setconfig failed: %m");
202 return IFD_ERROR_COMM_ERROR;
203 }
204 return 0;
205 }
206
ifd_sysdep_usb_set_interface(ifd_device_t * dev,int ifc,int alt)207 int ifd_sysdep_usb_set_interface(ifd_device_t * dev, int ifc, int alt)
208 {
209 struct usbdevfs_setinterface set;
210
211 set.interface = ifc;
212 set.altsetting = alt;
213 if (ioctl(dev->fd, USBDEVFS_SETINTERFACE, &set) < 0) {
214 ct_error("usb_setinterface failed: %m");
215 return IFD_ERROR_COMM_ERROR;
216 }
217 return 0;
218 }
219
ifd_sysdep_usb_claim_interface(ifd_device_t * dev,int interface)220 int ifd_sysdep_usb_claim_interface(ifd_device_t * dev, int interface)
221 {
222 if (ioctl(dev->fd, USBDEVFS_CLAIMINTERFACE, &interface) < 0) {
223 ct_error("usb_claiminterface failed: %m");
224 return IFD_ERROR_COMM_ERROR;
225 }
226 return 0;
227 }
228
ifd_sysdep_usb_release_interface(ifd_device_t * dev,int interface)229 int ifd_sysdep_usb_release_interface(ifd_device_t * dev, int interface)
230 {
231 if (ioctl(dev->fd, USBDEVFS_RELEASEINTERFACE, &interface) < 0) {
232 ct_error("usb_releaseinterface failed: %m");
233 return IFD_ERROR_COMM_ERROR;
234 }
235 return 0;
236 }
237
ifd_sysdep_usb_reset(ifd_device_t * dev)238 int ifd_sysdep_usb_reset(ifd_device_t * dev)
239 {
240 if (ioctl(dev->fd, USBDEVFS_RESET, NULL) < 0) {
241 ct_error("usb_reset failed: %m");
242 return IFD_ERROR_COMM_ERROR;
243 }
244 return 0;
245 }
246
247 /*
248 * USB bulk transfer
249 */
ifd_sysdep_usb_bulk(ifd_device_t * dev,int ep,void * buffer,size_t len,long timeout)250 int ifd_sysdep_usb_bulk(ifd_device_t * dev, int ep, void *buffer, size_t len,
251 long timeout)
252 {
253 struct usbdevfs_bulktransfer bulk;
254 int rc;
255
256 bulk.ep = ep;
257 bulk.data = buffer;
258 bulk.len = len;
259 bulk.timeout = timeout;
260 if ((rc = ioctl(dev->fd, USBDEVFS_BULK, &bulk)) < 0) {
261 ct_error("usb_bulk failed: %m");
262 return IFD_ERROR_COMM_ERROR;
263 }
264
265 return rc;
266 }
267
268 /*
269 * USB URB capture
270 */
271 struct ifd_usb_capture {
272 struct usbdevfs_urb urb;
273 int type;
274 int endpoint;
275 size_t maxpacket;
276 };
277
usb_submit_urb(int fd,struct ifd_usb_capture * cap)278 static int usb_submit_urb(int fd, struct ifd_usb_capture *cap)
279 {
280 /* Fill in the URB details */
281 ifd_debug(6, "submit urb %p", &cap->urb);
282 memset(&cap->urb, 0, sizeof(cap->urb));
283 cap->urb.type = cap->type;
284 cap->urb.endpoint = cap->endpoint;
285 cap->urb.buffer = (caddr_t) (cap + 1);
286 cap->urb.buffer_length = cap->maxpacket;
287 return ioctl(fd, USBDEVFS_SUBMITURB, &cap->urb);
288 }
289
ifd_sysdep_usb_begin_capture(ifd_device_t * dev,int type,int endpoint,size_t maxpacket,ifd_usb_capture_t ** capret)290 int ifd_sysdep_usb_begin_capture(ifd_device_t * dev, int type, int endpoint,
291 size_t maxpacket, ifd_usb_capture_t ** capret)
292 {
293 ifd_usb_capture_t *cap;
294
295 cap = (ifd_usb_capture_t *) calloc(1, sizeof(*cap) + maxpacket);
296 if (!cap) {
297 ct_error("out of memory");
298 return IFD_ERROR_NO_MEMORY;
299 }
300
301 cap->type = type;
302 cap->endpoint = endpoint;
303 cap->maxpacket = maxpacket;
304
305 if (usb_submit_urb(dev->fd, cap) < 0) {
306 ct_error("usb_submiturb failed: %m");
307 ifd_sysdep_usb_end_capture(dev, cap);
308 return IFD_ERROR_COMM_ERROR;
309 }
310
311 *capret = cap;
312 return 0;
313 }
314
ifd_sysdep_usb_capture_event(ifd_device_t * dev,ifd_usb_capture_t * cap,void * buffer,size_t len)315 int ifd_sysdep_usb_capture_event(ifd_device_t * dev, ifd_usb_capture_t * cap,
316 void *buffer, size_t len)
317 {
318 struct usbdevfs_urb *purb;
319 size_t copied = 0;
320 int rc = 0;
321
322 purb = NULL;
323 rc = ioctl(dev->fd, USBDEVFS_REAPURBNDELAY, &purb);
324 if (rc < 0) {
325 if (errno == EAGAIN)
326 return 0;
327 ct_error("usb_reapurb failed: %m");
328 return IFD_ERROR_COMM_ERROR;
329 }
330
331 if (purb != &cap->urb) {
332 ifd_debug(2, "reaped usb urb %p", purb);
333 return 0;
334 }
335
336 if (purb->status == -1) {
337 return IFD_ERROR_COMM_ERROR;
338 }
339
340 if (purb->actual_length) {
341 ifd_debug(6, "usb reapurb: len=%u",
342 purb->actual_length);
343 if ((copied = purb->actual_length) > len)
344 copied = len;
345 if (copied && buffer)
346 memcpy(buffer, purb->buffer, copied);
347 }
348 else {
349 usleep(10000);
350 }
351
352 /* Re-submit URB */
353 usb_submit_urb(dev->fd, cap);
354
355 return copied;
356 }
357
ifd_sysdep_usb_capture(ifd_device_t * dev,ifd_usb_capture_t * cap,void * buffer,size_t len,long timeout)358 int ifd_sysdep_usb_capture(ifd_device_t * dev, ifd_usb_capture_t * cap,
359 void *buffer, size_t len, long timeout)
360 {
361 struct timeval begin;
362 size_t copied;
363 int rc = 0;
364
365 /* Loop until we've reaped the response to the
366 * URB we sent */
367 copied = 0;
368 gettimeofday(&begin, NULL);
369 do {
370 struct pollfd pfd;
371 long wait;
372
373 if ((wait = timeout - ifd_time_elapsed(&begin)) <= 0)
374 return IFD_ERROR_TIMEOUT;
375
376 pfd.fd = dev->fd;
377 pfd.events = POLLOUT;
378 if (poll(&pfd, 1, wait) != 1)
379 continue;
380
381 rc = ifd_sysdep_usb_capture_event(dev, cap, buffer, len);
382 if (rc < 0) {
383 return rc;
384 }
385 copied = (size_t)rc;
386 } while (!copied);
387
388 return copied;
389 }
390
ifd_sysdep_usb_end_capture(ifd_device_t * dev,ifd_usb_capture_t * cap)391 int ifd_sysdep_usb_end_capture(ifd_device_t * dev, ifd_usb_capture_t * cap)
392 {
393 int rc = 0;
394
395 if (ioctl(dev->fd, USBDEVFS_DISCARDURB, &cap->urb) < 0
396 && errno != EINVAL) {
397 ct_error("usb_discardurb failed: %m");
398 rc = IFD_ERROR_COMM_ERROR;
399 }
400 /* Discarding an URB will place it in the queue of completed
401 * request, with urb->status == -1. So if we don't reap this
402 * URB now, the next call to REAPURB will return this one,
403 * clobbering random memory.
404 */
405 (void)ioctl(dev->fd, USBDEVFS_REAPURBNDELAY, &cap->urb);
406 free(cap);
407 return rc;
408 }
409
ifd_sysdep_usb_open(const char * device)410 int ifd_sysdep_usb_open(const char *device)
411 {
412 struct usbdevfs_disconnectsignal ds;
413 struct sigaction act;
414 int fd = -1;
415 int ret = -1;
416
417 fd = open(device, O_RDWR);
418 if (fd == -1) {
419 goto cleanup;
420 }
421
422 /*
423 * The following will send signal
424 * to the process when device is disconnected
425 * even if the signal is ignored the blocking
426 * call will exit.
427 * <linux.2.6.28 - This code will have no affect.
428 * =linux-2.6.28 - CONFIG_USB_DEVICEFS must be on.
429 * >=linux-2.6.29 - works.
430 */
431 memset(&act, 0, sizeof(act));
432 act.sa_handler = SIG_IGN;
433 if (sigaction(USB_DISCONNECT_SIGNAL, &act, NULL) == -1) {
434 goto cleanup;
435 }
436
437 memset(&ds, 0, sizeof(ds));
438 ds.signr = USB_DISCONNECT_SIGNAL;
439 if (ioctl(fd, USBDEVFS_DISCSIGNAL, &ds) == -1) {
440 goto cleanup;
441 }
442
443 ret = fd;
444 fd = -1;
445
446 cleanup:
447 if (fd != -1) {
448 close(fd);
449 }
450
451 return ret;
452 }
453
454 #ifndef ENABLE_LIBUSB
read_number(const char * read_format,const char * format,...)455 static int read_number (const char *read_format, const char *format, ...) {
456 va_list args;
457 char full[PATH_MAX];
458 FILE *fp = NULL;
459 int n = -1;
460
461 va_start(args, format);
462 vsnprintf (full, sizeof(full), format, args);
463 va_end(args);
464
465 if ((fp = fopen (full, "r")) == NULL) {
466 goto out;
467 }
468
469 fscanf (fp, read_format, &n);
470
471 out:
472 if (fp != NULL) {
473 fclose (fp);
474 }
475
476 return n;
477 }
478 #endif
479
480 /*
481 * Scan all usb devices to see if there is one we support
482 */
ifd_scan_usb(void)483 int ifd_scan_usb(void)
484 {
485 #ifdef ENABLE_LIBUSB
486 ifd_devid_t id;
487 struct usb_bus *bus;
488 struct usb_device *dev;
489
490 usb_init();
491 usb_find_busses();
492 usb_find_devices();
493
494 id.type = IFD_DEVICE_TYPE_USB;
495 id.num = 2;
496 for (bus = usb_busses; bus; bus = bus->next) {
497 for (dev = bus->devices; dev; dev = dev->next) {
498 const char *driver = NULL;
499 char typedev[PATH_MAX];
500 struct stat buf;
501
502 id.val[0] = dev->descriptor.idVendor;
503 id.val[1] = dev->descriptor.idProduct;
504
505 /* if we don't find a driver with vendor/product
506 * then check for the interface type (ccid) and use
507 * driver ccid... */
508
509 if (!(driver = ifd_driver_for_id(&id))) {
510 /* no driver found, check for interface class */
511 int conf;
512 for (conf = 0; conf < dev->descriptor.bNumConfigurations;
513 conf++) {
514 int interf;
515 for (interf = 0; interf < dev->config[conf].bNumInterfaces;
516 interf++) {
517 int alt;
518 for (alt = 0; alt < dev->config[conf].interface[interf].num_altsetting; alt++) {
519 if (dev->config[conf].interface[interf].altsetting[alt].bInterfaceClass == 0x0b) {
520 driver = "ccid";
521 }
522 }
523 }
524 }
525 }
526
527 if (driver != NULL) {
528 snprintf(typedev, sizeof(typedev),
529 "/dev/bus/usb/%s/%s",
530 bus->dirname, dev->filename);
531 if (stat(typedev, &buf) == 0) {
532 snprintf(typedev, sizeof(typedev),
533 "usb:/dev/bus/usb/%s/%s",
534 bus->dirname, dev->filename);
535 ifd_spawn_handler(driver, typedev, -1);
536 } else {
537 snprintf(typedev, sizeof(typedev),
538 "usb:/proc/bus/usb/%s/%s",
539 bus->dirname, dev->filename);
540 ifd_spawn_handler(driver, typedev, -1);
541 }
542 }
543 }
544 }
545 #else
546 const char *base = "/sys/bus/usb/devices";
547 DIR *dir = NULL;
548 struct dirent *ent;
549
550 if ((dir = opendir (base)) == NULL) {
551 goto out;
552 }
553
554 while ((ent = readdir (dir)) != NULL) {
555 if (ent->d_name[0] != '.') {
556 int idProduct = -1;
557 int idVendor = -1;
558 int busnum = -1;
559 int devnum = -1;
560
561 idProduct = read_number ("%x", "%s/%s/%s", base, ent->d_name, "idProduct");
562 idVendor = read_number ("%x", "%s/%s/%s", base, ent->d_name, "idVendor");
563 busnum = read_number ("%d", "%s/%s/%s", base, ent->d_name, "busnum");
564 devnum = read_number ("%d", "%s/%s/%s", base, ent->d_name, "devnum");
565
566 ifd_debug (6, "coldplug: %s usb: %04x:%04x bus: %03d:%03d\n", ent->d_name, idProduct, idVendor, busnum, devnum);
567
568 if (idProduct != -1 && idVendor != -1 && busnum != -1 && devnum != -1) {
569 const char *driver = NULL;
570 ifd_devid_t id;
571
572 id.type = IFD_DEVICE_TYPE_USB;
573 id.num = 2;
574 id.val[0] = idVendor;
575 id.val[1] = idProduct;
576
577 if ((driver = ifd_driver_for_id(&id)) == NULL) {
578 DIR *dir1 = NULL;
579 struct dirent *ent1;
580
581 if ((dir1 = opendir (base)) != NULL) {
582 while ((ent1 = readdir (dir1)) != NULL && driver == NULL) {
583 /* skip all none bus elements */
584 if (strncmp (ent->d_name, ent1->d_name, strlen (ent->d_name))) {
585 continue;
586 }
587
588 if (
589 read_number (
590 "%x",
591 "%s/%s/%s/%s",
592 base,
593 ent->d_name,
594 ent1->d_name,
595 "bInterfaceClass"
596 ) == 0x0b
597 ) {
598 driver = "ccid";
599 }
600 }
601 closedir (dir1);
602 }
603 }
604
605 if (driver != NULL) {
606 char typedev[1024];
607
608 snprintf(typedev, sizeof(typedev),
609 "usb:/dev/bus/usb/%03d/%03d",
610 busnum, devnum);
611 ifd_spawn_handler(driver, typedev, -1);
612 }
613 }
614 }
615 }
616
617 out:
618 if (dir != NULL) {
619 closedir (dir);
620 }
621 #endif
622 return 0;
623 }
624
625 #endif /* __linux__ */
626