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