USB user interface
[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                                 const char *devname);
48
49 //#define DEBUG
50
51 #define USBDEVFS_PATH "/proc/bus/usb"
52
53 typedef struct USBHostDevice {
54     USBDevice dev;
55     int fd;
56 } USBHostDevice;
57
58 static void usb_host_handle_reset(USBDevice *dev)
59 {
60 #if 0
61     USBHostDevice *s = (USBHostDevice *)dev;
62     /* USBDEVFS_RESET, but not the first time as it has already be
63        done by the host OS */
64     ioctl(s->fd, USBDEVFS_RESET);
65 #endif
66
67
68 static int usb_host_handle_control(USBDevice *dev,
69                                    int request,
70                                    int value,
71                                    int index,
72                                    int length,
73                                    uint8_t *data)
74 {
75     USBHostDevice *s = (USBHostDevice *)dev;
76     struct usb_ctrltransfer ct;
77     int ret;
78
79     if (request == (DeviceOutRequest | USB_REQ_SET_ADDRESS)) {
80         /* specific SET_ADDRESS support */
81         dev->addr = value;
82         return 0;
83     } else {
84         ct.bRequestType = request >> 8;
85         ct.bRequest = request;
86         ct.wValue = value;
87         ct.wIndex = index;
88         ct.wLength = length;
89         ct.timeout = 50;
90         ct.data = data;
91         ret = ioctl(s->fd, USBDEVFS_CONTROL, &ct);
92         if (ret < 0) {
93             switch(errno) {
94             case ETIMEDOUT:
95                 return USB_RET_NAK;
96             default:
97                 return USB_RET_STALL;
98             }
99         } else {
100             return ret;
101         }
102    }
103 }
104
105 static int usb_host_handle_data(USBDevice *dev, int pid, 
106                                 uint8_t devep,
107                                 uint8_t *data, int len)
108 {
109     USBHostDevice *s = (USBHostDevice *)dev;
110     struct usbdevfs_bulktransfer bt;
111     int ret;
112
113     /* XXX: optimize and handle all data types by looking at the
114        config descriptor */
115     if (pid == USB_TOKEN_IN)
116         devep |= 0x80;
117     bt.ep = devep;
118     bt.len = len;
119     bt.timeout = 50;
120     bt.data = data;
121     ret = ioctl(s->fd, USBDEVFS_BULK, &bt);
122     if (ret < 0) {
123         switch(errno) {
124         case ETIMEDOUT:
125             return USB_RET_NAK;
126         case EPIPE:
127         default:
128 #ifdef DEBUG
129             printf("handle_data: errno=%d\n", errno);
130 #endif
131             return USB_RET_STALL;
132         }
133     } else {
134         return ret;
135     }
136 }
137
138 /* XXX: exclude high speed devices or implement EHCI */
139 USBDevice *usb_host_device_open(const char *devname)
140 {
141     int fd, interface, ret, i;
142     USBHostDevice *dev;
143     struct usbdevfs_connectinfo ci;
144     uint8_t descr[1024];
145     char buf[1024];
146     int descr_len, dev_descr_len, config_descr_len, nb_interfaces;
147     int bus_num, addr;
148
149     if (usb_host_find_device(&bus_num, &addr, devname) < 0) 
150         return NULL;
151     
152     snprintf(buf, sizeof(buf), USBDEVFS_PATH "/%03d/%03d", 
153              bus_num, addr);
154     fd = open(buf, O_RDWR);
155     if (fd < 0) {
156         perror(buf);
157         return NULL;
158     }
159
160     /* read the config description */
161     descr_len = read(fd, descr, sizeof(descr));
162     if (descr_len <= 0) {
163         perror("read descr");
164         goto fail;
165     }
166     
167     i = 0;
168     dev_descr_len = descr[0];
169     if (dev_descr_len > descr_len)
170         goto fail;
171     i += dev_descr_len;
172     config_descr_len = descr[i];
173     if (i + config_descr_len > descr_len)
174         goto fail;
175     nb_interfaces = descr[i + 4];
176     if (nb_interfaces != 1) {
177         /* NOTE: currently we grab only one interface */
178         fprintf(stderr, "usb_host: only one interface supported\n");
179         goto fail;
180     }
181
182 #ifdef USBDEVFS_DISCONNECT
183     /* earlier Linux 2.4 do not support that */
184     ret = ioctl(fd, USBDEVFS_DISCONNECT);
185     if (ret < 0 && errno != ENODATA) {
186         perror("USBDEVFS_DISCONNECT");
187         goto fail;
188     }
189 #endif
190
191     /* XXX: only grab if all interfaces are free */
192     interface = 0;
193     ret = ioctl(fd, USBDEVFS_CLAIMINTERFACE, &interface);
194     if (ret < 0) {
195         if (errno == EBUSY) {
196             fprintf(stderr, "usb_host: device already grabbed\n");
197         } else {
198             perror("USBDEVFS_CLAIMINTERFACE");
199         }
200     fail:
201         close(fd);
202         return NULL;
203     }
204
205     ret = ioctl(fd, USBDEVFS_CONNECTINFO, &ci);
206     if (ret < 0) {
207         perror("USBDEVFS_CONNECTINFO");
208         goto fail;
209     }
210
211 #ifdef DEBUG
212     printf("host USB device %d.%d grabbed\n", bus_num, addr);
213 #endif    
214
215     dev = qemu_mallocz(sizeof(USBHostDevice));
216     if (!dev)
217         goto fail;
218     dev->fd = fd;
219     if (ci.slow)
220         dev->dev.speed = USB_SPEED_LOW;
221     else
222         dev->dev.speed = USB_SPEED_HIGH;
223     dev->dev.handle_packet = usb_generic_handle_packet;
224
225     dev->dev.handle_reset = usb_host_handle_reset;
226     dev->dev.handle_control = usb_host_handle_control;
227     dev->dev.handle_data = usb_host_handle_data;
228     return (USBDevice *)dev;
229 }
230
231 static int get_tag_value(char *buf, int buf_size,
232                          const char *str, const char *tag, 
233                          const char *stopchars)
234 {
235     const char *p;
236     char *q;
237     p = strstr(str, tag);
238     if (!p)
239         return -1;
240     p += strlen(tag);
241     while (isspace(*p))
242         p++;
243     q = buf;
244     while (*p != '\0' && !strchr(stopchars, *p)) {
245         if ((q - buf) < (buf_size - 1))
246             *q++ = *p;
247         p++;
248     }
249     *q = '\0';
250     return q - buf;
251 }
252
253 static int usb_host_scan(void *opaque, USBScanFunc *func)
254 {
255     FILE *f;
256     char line[1024];
257     char buf[1024];
258     int bus_num, addr, speed, device_count, class_id, product_id, vendor_id;
259     int ret;
260     char product_name[512];
261     
262     f = fopen(USBDEVFS_PATH "/devices", "r");
263     if (!f) {
264         term_printf("Could not open %s\n", USBDEVFS_PATH "/devices");
265         return 0;
266     }
267     device_count = 0;
268     bus_num = addr = speed = class_id = product_id = vendor_id = 0;
269     ret = 0;
270     for(;;) {
271         if (fgets(line, sizeof(line), f) == NULL)
272             break;
273         if (strlen(line) > 0)
274             line[strlen(line) - 1] = '\0';
275         if (line[0] == 'T' && line[1] == ':') {
276             if (device_count) {
277                 ret = func(opaque, bus_num, addr, class_id, vendor_id, 
278                            product_id, product_name, speed);
279                 if (ret)
280                     goto the_end;
281             }
282             if (get_tag_value(buf, sizeof(buf), line, "Bus=", " ") < 0)
283                 goto fail;
284             bus_num = atoi(buf);
285             if (get_tag_value(buf, sizeof(buf), line, "Dev#=", " ") < 0)
286                 goto fail;
287             addr = atoi(buf);
288             if (get_tag_value(buf, sizeof(buf), line, "Spd=", " ") < 0)
289                 goto fail;
290             if (!strcmp(buf, "480"))
291                 speed = USB_SPEED_HIGH;
292             else if (!strcmp(buf, "1.5"))
293                 speed = USB_SPEED_LOW;
294             else
295                 speed = USB_SPEED_FULL;
296             product_name[0] = '\0';
297             class_id = 0xff;
298             device_count++;
299             product_id = 0;
300             vendor_id = 0;
301         } else if (line[0] == 'P' && line[1] == ':') {
302             if (get_tag_value(buf, sizeof(buf), line, "Vendor=", " ") < 0)
303                 goto fail;
304             vendor_id = strtoul(buf, NULL, 16);
305             if (get_tag_value(buf, sizeof(buf), line, "ProdID=", " ") < 0)
306                 goto fail;
307             product_id = strtoul(buf, NULL, 16);
308         } else if (line[0] == 'S' && line[1] == ':') {
309             if (get_tag_value(buf, sizeof(buf), line, "Product=", "") < 0)
310                 goto fail;
311             pstrcpy(product_name, sizeof(product_name), buf);
312         } else if (line[0] == 'D' && line[1] == ':') {
313             if (get_tag_value(buf, sizeof(buf), line, "Cls=", " (") < 0)
314                 goto fail;
315             class_id = strtoul(buf, NULL, 16);
316         }
317     fail: ;
318     }
319     if (device_count) {
320         ret = func(opaque, bus_num, addr, class_id, vendor_id, 
321                    product_id, product_name, speed);
322     }
323  the_end:
324     fclose(f);
325     return ret;
326 }
327
328 typedef struct FindDeviceState {
329     int vendor_id;
330     int product_id;
331     int bus_num;
332     int addr;
333 } FindDeviceState;
334
335 static int usb_host_find_device_scan(void *opaque, int bus_num, int addr, 
336                                      int class_id,
337                                      int vendor_id, int product_id, 
338                                      const char *product_name, int speed)
339 {
340     FindDeviceState *s = opaque;
341     if (vendor_id == s->vendor_id &&
342         product_id == s->product_id) {
343         s->bus_num = bus_num;
344         s->addr = addr;
345         return 1;
346     } else {
347         return 0;
348     }
349 }
350
351 /* the syntax is : 
352    'bus.addr' (decimal numbers) or 
353    'vendor_id:product_id' (hexa numbers) */
354 static int usb_host_find_device(int *pbus_num, int *paddr, 
355                                 const char *devname)
356 {
357     const char *p;
358     int ret;
359     FindDeviceState fs;
360
361     p = strchr(devname, '.');
362     if (p) {
363         *pbus_num = strtoul(devname, NULL, 0);
364         *paddr = strtoul(p + 1, NULL, 0);
365         return 0;
366     }
367     p = strchr(devname, ':');
368     if (p) {
369         fs.vendor_id = strtoul(devname, NULL, 16);
370         fs.product_id = strtoul(p + 1, NULL, 16);
371         ret = usb_host_scan(&fs, usb_host_find_device_scan);
372         if (ret) {
373             *pbus_num = fs.bus_num;
374             *paddr = fs.addr;
375             return 0;
376         }
377     }
378     return -1;
379 }
380
381 /**********************/
382 /* USB host device info */
383
384 struct usb_class_info {
385     int class;
386     const char *class_name;
387 };
388
389 static const struct usb_class_info usb_class_info[] = {
390     { USB_CLASS_AUDIO, "Audio"},
391     { USB_CLASS_COMM, "Communication"},
392     { USB_CLASS_HID, "HID"},
393     { USB_CLASS_HUB, "Hub" },
394     { USB_CLASS_PHYSICAL, "Physical" },
395     { USB_CLASS_PRINTER, "Printer" },
396     { USB_CLASS_MASS_STORAGE, "Storage" },
397     { USB_CLASS_CDC_DATA, "Data" },
398     { USB_CLASS_APP_SPEC, "Application Specific" },
399     { USB_CLASS_VENDOR_SPEC, "Vendor Specific" },
400     { USB_CLASS_STILL_IMAGE, "Still Image" },
401     { USB_CLASS_CSCID,  "Smart Card" },
402     { USB_CLASS_CONTENT_SEC, "Content Security" },
403     { -1, NULL }
404 };
405
406 static const char *usb_class_str(uint8_t class)
407 {
408     const struct usb_class_info *p;
409     for(p = usb_class_info; p->class != -1; p++) {
410         if (p->class == class)
411             break;
412     }
413     return p->class_name;
414 }
415
416 void usb_info_device(int bus_num, int addr, int class_id,
417                      int vendor_id, int product_id, 
418                      const char *product_name,
419                      int speed)
420 {
421     const char *class_str, *speed_str;
422
423     switch(speed) {
424     case USB_SPEED_LOW: 
425         speed_str = "1.5"; 
426         break;
427     case USB_SPEED_FULL: 
428         speed_str = "12"; 
429         break;
430     case USB_SPEED_HIGH: 
431         speed_str = "480"; 
432         break;
433     default:
434         speed_str = "?"; 
435         break;
436     }
437
438     term_printf("  Device %d.%d, speed %s Mb/s\n", 
439                 bus_num, addr, speed_str);
440     class_str = usb_class_str(class_id);
441     if (class_str) 
442         term_printf("    %s:", class_str);
443     else
444         term_printf("    Class %02x:", class_id);
445     term_printf(" USB device %04x:%04x", vendor_id, product_id);
446     if (product_name[0] != '\0')
447         term_printf(", %s", product_name);
448     term_printf("\n");
449 }
450
451 static int usb_host_info_device(void *opaque, int bus_num, int addr, 
452                                 int class_id,
453                                 int vendor_id, int product_id, 
454                                 const char *product_name,
455                                 int speed)
456 {
457     usb_info_device(bus_num, addr, class_id, vendor_id, product_id,
458                     product_name, speed);
459     return 0;
460 }
461
462 void usb_host_info(void)
463 {
464     usb_host_scan(NULL, usb_host_info_device);
465 }
466
467 #else
468
469 void usb_host_info(void)
470 {
471     term_printf("USB host devices not supported\n");
472 }
473
474 /* XXX: modify configure to compile the right host driver */
475 USBDevice *usb_host_device_open(const char *devname)
476 {
477     return NULL;
478 }
479
480 #endif