display device identifier string for user with info usb (Lonnie Mendez)
[qemu] / usb-linux.c
1 /*
2  * Linux host USB redirector
3  *
4  * Copyright (c) 2005 Fabrice Bellard
5  * 
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 #include "vl.h"
25
26 #if defined(__linux__)
27 #include <dirent.h>
28 #include <sys/ioctl.h>
29 #include <linux/usbdevice_fs.h>
30 #include <linux/version.h>
31
32 /* We redefine it to avoid version problems */
33 struct usb_ctrltransfer {
34     uint8_t  bRequestType;
35     uint8_t  bRequest;
36     uint16_t wValue;
37     uint16_t wIndex;
38     uint16_t wLength;
39     uint32_t timeout;
40     void *data;
41 };
42
43 typedef int USBScanFunc(void *opaque, int bus_num, int addr, int class_id,
44                         int vendor_id, int product_id, 
45                         const char *product_name, int speed);
46 static int usb_host_find_device(int *pbus_num, int *paddr, 
47                                 char *product_name, int product_name_size,
48                                 const char *devname);
49
50 //#define DEBUG
51
52 #define USBDEVFS_PATH "/proc/bus/usb"
53 #define PRODUCT_NAME_SZ 32
54
55 typedef struct USBHostDevice {
56     USBDevice dev;
57     int fd;
58 } USBHostDevice;
59
60 static void usb_host_handle_reset(USBDevice *dev, int destroy)
61 {
62 #if 0
63     USBHostDevice *s = (USBHostDevice *)dev;
64     /* USBDEVFS_RESET, but not the first time as it has already be
65        done by the host OS */
66     ioctl(s->fd, USBDEVFS_RESET);
67 #endif
68
69
70 static int usb_host_handle_control(USBDevice *dev,
71                                    int request,
72                                    int value,
73                                    int index,
74                                    int length,
75                                    uint8_t *data)
76 {
77     USBHostDevice *s = (USBHostDevice *)dev;
78     struct usb_ctrltransfer ct;
79     int ret;
80
81     if (request == (DeviceOutRequest | USB_REQ_SET_ADDRESS)) {
82         /* specific SET_ADDRESS support */
83         dev->addr = value;
84         return 0;
85     } else {
86         ct.bRequestType = request >> 8;
87         ct.bRequest = request;
88         ct.wValue = value;
89         ct.wIndex = index;
90         ct.wLength = length;
91         ct.timeout = 50;
92         ct.data = data;
93         ret = ioctl(s->fd, USBDEVFS_CONTROL, &ct);
94         if (ret < 0) {
95             switch(errno) {
96             case ETIMEDOUT:
97                 return USB_RET_NAK;
98             default:
99                 return USB_RET_STALL;
100             }
101         } else {
102             return ret;
103         }
104    }
105 }
106
107 static int usb_host_handle_data(USBDevice *dev, int pid, 
108                                 uint8_t devep,
109                                 uint8_t *data, int len)
110 {
111     USBHostDevice *s = (USBHostDevice *)dev;
112     struct usbdevfs_bulktransfer bt;
113     int ret;
114
115     /* XXX: optimize and handle all data types by looking at the
116        config descriptor */
117     if (pid == USB_TOKEN_IN)
118         devep |= 0x80;
119     bt.ep = devep;
120     bt.len = len;
121     bt.timeout = 50;
122     bt.data = data;
123     ret = ioctl(s->fd, USBDEVFS_BULK, &bt);
124     if (ret < 0) {
125         switch(errno) {
126         case ETIMEDOUT:
127             return USB_RET_NAK;
128         case EPIPE:
129         default:
130 #ifdef DEBUG
131             printf("handle_data: errno=%d\n", errno);
132 #endif
133             return USB_RET_STALL;
134         }
135     } else {
136         return ret;
137     }
138 }
139
140 /* XXX: exclude high speed devices or implement EHCI */
141 USBDevice *usb_host_device_open(const char *devname)
142 {
143     int fd, interface, ret, i;
144     USBHostDevice *dev;
145     struct usbdevfs_connectinfo ci;
146     uint8_t descr[1024];
147     char buf[1024];
148     int descr_len, dev_descr_len, config_descr_len, nb_interfaces;
149     int bus_num, addr;
150     char product_name[PRODUCT_NAME_SZ];
151
152     if (usb_host_find_device(&bus_num, &addr, 
153                              product_name, sizeof(product_name),
154                              devname) < 0) 
155         return NULL;
156     
157     snprintf(buf, sizeof(buf), USBDEVFS_PATH "/%03d/%03d", 
158              bus_num, addr);
159     fd = open(buf, O_RDWR);
160     if (fd < 0) {
161         perror(buf);
162         return NULL;
163     }
164
165     /* read the config description */
166     descr_len = read(fd, descr, sizeof(descr));
167     if (descr_len <= 0) {
168         perror("read descr");
169         goto fail;
170     }
171     
172     i = 0;
173     dev_descr_len = descr[0];
174     if (dev_descr_len > descr_len)
175         goto fail;
176     i += dev_descr_len;
177     config_descr_len = descr[i];
178     if (i + config_descr_len > descr_len)
179         goto fail;
180     nb_interfaces = descr[i + 4];
181     if (nb_interfaces != 1) {
182         /* NOTE: currently we grab only one interface */
183         fprintf(stderr, "usb_host: only one interface supported\n");
184         goto fail;
185     }
186
187 #ifdef USBDEVFS_DISCONNECT
188     /* earlier Linux 2.4 do not support that */
189     {
190         struct usbdevfs_ioctl ctrl;
191         ctrl.ioctl_code = USBDEVFS_DISCONNECT;
192         ctrl.ifno = 0;
193         ret = ioctl(fd, USBDEVFS_IOCTL, &ctrl);
194         if (ret < 0 && errno != ENODATA) {
195             perror("USBDEVFS_DISCONNECT");
196             goto fail;
197         }
198     }
199 #endif
200
201     /* XXX: only grab if all interfaces are free */
202     interface = 0;
203     ret = ioctl(fd, USBDEVFS_CLAIMINTERFACE, &interface);
204     if (ret < 0) {
205         if (errno == EBUSY) {
206             fprintf(stderr, "usb_host: device already grabbed\n");
207         } else {
208             perror("USBDEVFS_CLAIMINTERFACE");
209         }
210     fail:
211         close(fd);
212         return NULL;
213     }
214
215     ret = ioctl(fd, USBDEVFS_CONNECTINFO, &ci);
216     if (ret < 0) {
217         perror("USBDEVFS_CONNECTINFO");
218         goto fail;
219     }
220
221 #ifdef DEBUG
222     printf("host USB device %d.%d grabbed\n", bus_num, addr);
223 #endif    
224
225     dev = qemu_mallocz(sizeof(USBHostDevice));
226     if (!dev)
227         goto fail;
228     dev->fd = fd;
229     if (ci.slow)
230         dev->dev.speed = USB_SPEED_LOW;
231     else
232         dev->dev.speed = USB_SPEED_HIGH;
233     dev->dev.handle_packet = usb_generic_handle_packet;
234
235     dev->dev.handle_reset = usb_host_handle_reset;
236     dev->dev.handle_control = usb_host_handle_control;
237     dev->dev.handle_data = usb_host_handle_data;
238
239     if (product_name[0] == '\0')
240         snprintf(dev->dev.devname, sizeof(dev->dev.devname),
241                  "host:%s", devname);
242     else
243         pstrcpy(dev->dev.devname, sizeof(dev->dev.devname),
244                 product_name);
245
246     return (USBDevice *)dev;
247 }
248
249 static int get_tag_value(char *buf, int buf_size,
250                          const char *str, const char *tag, 
251                          const char *stopchars)
252 {
253     const char *p;
254     char *q;
255     p = strstr(str, tag);
256     if (!p)
257         return -1;
258     p += strlen(tag);
259     while (isspace(*p))
260         p++;
261     q = buf;
262     while (*p != '\0' && !strchr(stopchars, *p)) {
263         if ((q - buf) < (buf_size - 1))
264             *q++ = *p;
265         p++;
266     }
267     *q = '\0';
268     return q - buf;
269 }
270
271 static int usb_host_scan(void *opaque, USBScanFunc *func)
272 {
273     FILE *f;
274     char line[1024];
275     char buf[1024];
276     int bus_num, addr, speed, device_count, class_id, product_id, vendor_id;
277     int ret;
278     char product_name[512];
279     
280     f = fopen(USBDEVFS_PATH "/devices", "r");
281     if (!f) {
282         term_printf("Could not open %s\n", USBDEVFS_PATH "/devices");
283         return 0;
284     }
285     device_count = 0;
286     bus_num = addr = speed = class_id = product_id = vendor_id = 0;
287     ret = 0;
288     for(;;) {
289         if (fgets(line, sizeof(line), f) == NULL)
290             break;
291         if (strlen(line) > 0)
292             line[strlen(line) - 1] = '\0';
293         if (line[0] == 'T' && line[1] == ':') {
294             if (device_count && (vendor_id || product_id)) {
295                 /* New device.  Add the previously discovered device.  */
296                 ret = func(opaque, bus_num, addr, class_id, vendor_id, 
297                            product_id, product_name, speed);
298                 if (ret)
299                     goto the_end;
300             }
301             if (get_tag_value(buf, sizeof(buf), line, "Bus=", " ") < 0)
302                 goto fail;
303             bus_num = atoi(buf);
304             if (get_tag_value(buf, sizeof(buf), line, "Dev#=", " ") < 0)
305                 goto fail;
306             addr = atoi(buf);
307             if (get_tag_value(buf, sizeof(buf), line, "Spd=", " ") < 0)
308                 goto fail;
309             if (!strcmp(buf, "480"))
310                 speed = USB_SPEED_HIGH;
311             else if (!strcmp(buf, "1.5"))
312                 speed = USB_SPEED_LOW;
313             else
314                 speed = USB_SPEED_FULL;
315             product_name[0] = '\0';
316             class_id = 0xff;
317             device_count++;
318             product_id = 0;
319             vendor_id = 0;
320         } else if (line[0] == 'P' && line[1] == ':') {
321             if (get_tag_value(buf, sizeof(buf), line, "Vendor=", " ") < 0)
322                 goto fail;
323             vendor_id = strtoul(buf, NULL, 16);
324             if (get_tag_value(buf, sizeof(buf), line, "ProdID=", " ") < 0)
325                 goto fail;
326             product_id = strtoul(buf, NULL, 16);
327         } else if (line[0] == 'S' && line[1] == ':') {
328             if (get_tag_value(buf, sizeof(buf), line, "Product=", "") < 0)
329                 goto fail;
330             pstrcpy(product_name, sizeof(product_name), buf);
331         } else if (line[0] == 'D' && line[1] == ':') {
332             if (get_tag_value(buf, sizeof(buf), line, "Cls=", " (") < 0)
333                 goto fail;
334             class_id = strtoul(buf, NULL, 16);
335         }
336     fail: ;
337     }
338     if (device_count && (vendor_id || product_id)) {
339         /* Add the last device.  */
340         ret = func(opaque, bus_num, addr, class_id, vendor_id, 
341                    product_id, product_name, speed);
342     }
343  the_end:
344     fclose(f);
345     return ret;
346 }
347
348 typedef struct FindDeviceState {
349     int vendor_id;
350     int product_id;
351     int bus_num;
352     int addr;
353     char product_name[PRODUCT_NAME_SZ];
354 } FindDeviceState;
355
356 static int usb_host_find_device_scan(void *opaque, int bus_num, int addr, 
357                                      int class_id,
358                                      int vendor_id, int product_id, 
359                                      const char *product_name, int speed)
360 {
361     FindDeviceState *s = opaque;
362     if ((vendor_id == s->vendor_id &&
363         product_id == s->product_id) ||
364         (bus_num == s->bus_num &&
365         addr == s->addr)) {
366         pstrcpy(s->product_name, PRODUCT_NAME_SZ, product_name);
367         s->bus_num = bus_num;
368         s->addr = addr;
369         return 1;
370     } else {
371         return 0;
372     }
373 }
374
375 /* the syntax is : 
376    'bus.addr' (decimal numbers) or 
377    'vendor_id:product_id' (hexa numbers) */
378 static int usb_host_find_device(int *pbus_num, int *paddr, 
379                                 char *product_name, int product_name_size,
380                                 const char *devname)
381 {
382     const char *p;
383     int ret;
384     FindDeviceState fs;
385
386     p = strchr(devname, '.');
387     if (p) {
388         *pbus_num = strtoul(devname, NULL, 0);
389         *paddr = strtoul(p + 1, NULL, 0);
390         fs.bus_num = *pbus_num;
391         fs.addr = *paddr;
392         ret = usb_host_scan(&fs, usb_host_find_device_scan);
393         if (ret)
394             pstrcpy(product_name, product_name_size, fs.product_name);
395         return 0;
396     }
397     p = strchr(devname, ':');
398     if (p) {
399         fs.vendor_id = strtoul(devname, NULL, 16);
400         fs.product_id = strtoul(p + 1, NULL, 16);
401         ret = usb_host_scan(&fs, usb_host_find_device_scan);
402         if (ret) {
403             *pbus_num = fs.bus_num;
404             *paddr = fs.addr;
405             pstrcpy(product_name, product_name_size, fs.product_name);
406             return 0;
407         }
408     }
409     return -1;
410 }
411
412 /**********************/
413 /* USB host device info */
414
415 struct usb_class_info {
416     int class;
417     const char *class_name;
418 };
419
420 static const struct usb_class_info usb_class_info[] = {
421     { USB_CLASS_AUDIO, "Audio"},
422     { USB_CLASS_COMM, "Communication"},
423     { USB_CLASS_HID, "HID"},
424     { USB_CLASS_HUB, "Hub" },
425     { USB_CLASS_PHYSICAL, "Physical" },
426     { USB_CLASS_PRINTER, "Printer" },
427     { USB_CLASS_MASS_STORAGE, "Storage" },
428     { USB_CLASS_CDC_DATA, "Data" },
429     { USB_CLASS_APP_SPEC, "Application Specific" },
430     { USB_CLASS_VENDOR_SPEC, "Vendor Specific" },
431     { USB_CLASS_STILL_IMAGE, "Still Image" },
432     { USB_CLASS_CSCID,  "Smart Card" },
433     { USB_CLASS_CONTENT_SEC, "Content Security" },
434     { -1, NULL }
435 };
436
437 static const char *usb_class_str(uint8_t class)
438 {
439     const struct usb_class_info *p;
440     for(p = usb_class_info; p->class != -1; p++) {
441         if (p->class == class)
442             break;
443     }
444     return p->class_name;
445 }
446
447 void usb_info_device(int bus_num, int addr, int class_id,
448                      int vendor_id, int product_id, 
449                      const char *product_name,
450                      int speed)
451 {
452     const char *class_str, *speed_str;
453
454     switch(speed) {
455     case USB_SPEED_LOW: 
456         speed_str = "1.5"; 
457         break;
458     case USB_SPEED_FULL: 
459         speed_str = "12"; 
460         break;
461     case USB_SPEED_HIGH: 
462         speed_str = "480"; 
463         break;
464     default:
465         speed_str = "?"; 
466         break;
467     }
468
469     term_printf("  Device %d.%d, speed %s Mb/s\n", 
470                 bus_num, addr, speed_str);
471     class_str = usb_class_str(class_id);
472     if (class_str) 
473         term_printf("    %s:", class_str);
474     else
475         term_printf("    Class %02x:", class_id);
476     term_printf(" USB device %04x:%04x", vendor_id, product_id);
477     if (product_name[0] != '\0')
478         term_printf(", %s", product_name);
479     term_printf("\n");
480 }
481
482 static int usb_host_info_device(void *opaque, int bus_num, int addr, 
483                                 int class_id,
484                                 int vendor_id, int product_id, 
485                                 const char *product_name,
486                                 int speed)
487 {
488     usb_info_device(bus_num, addr, class_id, vendor_id, product_id,
489                     product_name, speed);
490     return 0;
491 }
492
493 void usb_host_info(void)
494 {
495     usb_host_scan(NULL, usb_host_info_device);
496 }
497
498 #else
499
500 void usb_host_info(void)
501 {
502     term_printf("USB host devices not supported\n");
503 }
504
505 /* XXX: modify configure to compile the right host driver */
506 USBDevice *usb_host_device_open(const char *devname)
507 {
508     return NULL;
509 }
510
511 #endif