]> rtime.felk.cvut.cz Git - lisovros/qemu_apohw.git/blob - usb-bsd.c
Merge remote-tracking branch 'pmaydell/arm-devs.for-upstream' into staging
[lisovros/qemu_apohw.git] / usb-bsd.c
1 /*
2  * BSD host USB redirector
3  *
4  * Copyright (c) 2006 Lonnie Mendez
5  * Portions of code and concepts borrowed from
6  * usb-linux.c and libusb's bsd.c and are copyright their respective owners.
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a copy
9  * of this software and associated documentation files (the "Software"), to deal
10  * in the Software without restriction, including without limitation the rights
11  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12  * copies of the Software, and to permit persons to whom the Software is
13  * furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in
16  * all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24  * THE SOFTWARE.
25  */
26
27 #include "qemu-common.h"
28 #include "monitor.h"
29 #include "hw/usb.h"
30
31 /* usb.h declares these */
32 #undef USB_SPEED_HIGH
33 #undef USB_SPEED_FULL
34 #undef USB_SPEED_LOW
35
36 #include <sys/ioctl.h>
37 #ifndef __DragonFly__
38 #include <dev/usb/usb.h>
39 #else
40 #include <bus/usb/usb.h>
41 #endif
42
43 /* This value has maximum potential at 16.
44  * You should also set hw.usb.debug to gain
45  * more detailed view.
46  */
47 //#define DEBUG
48 #define UGEN_DEBUG_LEVEL 0
49
50
51 typedef int USBScanFunc(void *opaque, int bus_num, int addr, int class_id,
52                         int vendor_id, int product_id,
53                         const char *product_name, int speed);
54 static int usb_host_find_device(int *pbus_num, int *paddr,
55                                 const char *devname);
56
57 typedef struct USBHostDevice {
58     USBDevice dev;
59     int ep_fd[USB_MAX_ENDPOINTS];
60     int devfd;
61     char devpath[32];
62 } USBHostDevice;
63
64
65 static int ensure_ep_open(USBHostDevice *dev, int ep, int mode)
66 {
67     char buf[32];
68     int fd;
69
70     /* Get the address for this endpoint */
71     ep = UE_GET_ADDR(ep);
72
73     if (dev->ep_fd[ep] < 0) {
74 #if defined(__FreeBSD__) || defined(__DragonFly__)
75         snprintf(buf, sizeof(buf) - 1, "%s.%d", dev->devpath, ep);
76 #else
77         snprintf(buf, sizeof(buf) - 1, "%s.%02d", dev->devpath, ep);
78 #endif
79         /* Try to open it O_RDWR first for those devices which have in and out
80          * endpoints with the same address (eg 0x02 and 0x82)
81          */
82         fd = open(buf, O_RDWR);
83         if (fd < 0 && errno == ENXIO)
84             fd = open(buf, mode);
85         if (fd < 0) {
86 #ifdef DEBUG
87             printf("ensure_ep_open: failed to open device endpoint %s: %s\n",
88                    buf, strerror(errno));
89 #endif
90         }
91         dev->ep_fd[ep] = fd;
92     }
93
94     return dev->ep_fd[ep];
95 }
96
97 static void ensure_eps_closed(USBHostDevice *dev)
98 {
99     int epnum = 1;
100
101     if (!dev)
102         return;
103
104     while (epnum < USB_MAX_ENDPOINTS) {
105         if (dev->ep_fd[epnum] >= 0) {
106             close(dev->ep_fd[epnum]);
107             dev->ep_fd[epnum] = -1;
108         }
109         epnum++;
110     }
111 }
112
113 static void usb_host_handle_reset(USBDevice *dev)
114 {
115 #if 0
116     USBHostDevice *s = (USBHostDevice *)dev;
117 #endif
118 }
119
120 /* XXX:
121  * -check device states against transfer requests
122  *  and return appropriate response
123  */
124 static int usb_host_handle_control(USBDevice *dev,
125                                    USBPacket *p,
126                                    int request,
127                                    int value,
128                                    int index,
129                                    int length,
130                                    uint8_t *data)
131 {
132     USBHostDevice *s = (USBHostDevice *)dev;
133     struct usb_ctl_request req;
134     struct usb_alt_interface aiface;
135     int ret, timeout = 50;
136
137     if ((request >> 8) == UT_WRITE_DEVICE &&
138         (request & 0xff) == UR_SET_ADDRESS) {
139
140         /* specific SET_ADDRESS support */
141         dev->addr = value;
142         return 0;
143     } else if ((request >> 8) == UT_WRITE_DEVICE &&
144                (request & 0xff) == UR_SET_CONFIG) {
145
146         ensure_eps_closed(s); /* can't do this without all eps closed */
147
148         ret = ioctl(s->devfd, USB_SET_CONFIG, &value);
149         if (ret < 0) {
150 #ifdef DEBUG
151             printf("handle_control: failed to set configuration - %s\n",
152                    strerror(errno));
153 #endif
154             return USB_RET_STALL;
155         }
156
157         return 0;
158     } else if ((request >> 8) == UT_WRITE_INTERFACE &&
159                (request & 0xff) == UR_SET_INTERFACE) {
160
161         aiface.uai_interface_index = index;
162         aiface.uai_alt_no = value;
163
164         ensure_eps_closed(s); /* can't do this without all eps closed */
165         ret = ioctl(s->devfd, USB_SET_ALTINTERFACE, &aiface);
166         if (ret < 0) {
167 #ifdef DEBUG
168             printf("handle_control: failed to set alternate interface - %s\n",
169                    strerror(errno));
170 #endif
171             return USB_RET_STALL;
172         }
173
174         return 0;
175     } else {
176         req.ucr_request.bmRequestType = request >> 8;
177         req.ucr_request.bRequest = request & 0xff;
178         USETW(req.ucr_request.wValue, value);
179         USETW(req.ucr_request.wIndex, index);
180         USETW(req.ucr_request.wLength, length);
181         req.ucr_data = data;
182         req.ucr_flags = USBD_SHORT_XFER_OK;
183
184         ret = ioctl(s->devfd, USB_SET_TIMEOUT, &timeout);
185 #if defined(__NetBSD__) || defined(__OpenBSD__)
186         if (ret < 0 && errno != EINVAL) {
187 #else
188         if (ret < 0) {
189 #endif
190 #ifdef DEBUG
191             printf("handle_control: setting timeout failed - %s\n",
192                    strerror(errno));
193 #endif
194         }
195
196         ret = ioctl(s->devfd, USB_DO_REQUEST, &req);
197         /* ugen returns EIO for usbd_do_request_ no matter what
198          * happens with the transfer */
199         if (ret < 0) {
200 #ifdef DEBUG
201             printf("handle_control: error after request - %s\n",
202                    strerror(errno));
203 #endif
204             return USB_RET_NAK; // STALL
205         } else {
206             return req.ucr_actlen;
207         }
208     }
209 }
210
211 static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
212 {
213     USBHostDevice *s = (USBHostDevice *)dev;
214     int ret, fd, mode;
215     int one = 1, shortpacket = 0, timeout = 50;
216     sigset_t new_mask, old_mask;
217     uint8_t devep = p->devep;
218
219     /* protect data transfers from SIGALRM signal */
220     sigemptyset(&new_mask);
221     sigaddset(&new_mask, SIGALRM);
222     sigprocmask(SIG_BLOCK, &new_mask, &old_mask);
223
224     if (p->pid == USB_TOKEN_IN) {
225         devep |= 0x80;
226         mode = O_RDONLY;
227         shortpacket = 1;
228     } else {
229         mode = O_WRONLY;
230     }
231
232     fd = ensure_ep_open(s, devep, mode);
233     if (fd < 0) {
234         sigprocmask(SIG_SETMASK, &old_mask, NULL);
235         return USB_RET_NODEV;
236     }
237
238     if (ioctl(fd, USB_SET_TIMEOUT, &timeout) < 0) {
239 #ifdef DEBUG
240         printf("handle_data: failed to set timeout - %s\n",
241                strerror(errno));
242 #endif
243     }
244
245     if (shortpacket) {
246         if (ioctl(fd, USB_SET_SHORT_XFER, &one) < 0) {
247 #ifdef DEBUG
248             printf("handle_data: failed to set short xfer mode - %s\n",
249                    strerror(errno));
250 #endif
251             sigprocmask(SIG_SETMASK, &old_mask, NULL);
252         }
253     }
254
255     if (p->pid == USB_TOKEN_IN)
256         ret = readv(fd, p->iov.iov, p->iov.niov);
257     else
258         ret = writev(fd, p->iov.iov, p->iov.niov);
259
260     sigprocmask(SIG_SETMASK, &old_mask, NULL);
261
262     if (ret < 0) {
263 #ifdef DEBUG
264         printf("handle_data: error after %s data - %s\n",
265                pid == USB_TOKEN_IN ? "reading" : "writing", strerror(errno));
266 #endif
267         switch(errno) {
268         case ETIMEDOUT:
269         case EINTR:
270             return USB_RET_NAK;
271         default:
272             return USB_RET_STALL;
273         }
274     } else {
275         return ret;
276     }
277 }
278
279 static void usb_host_handle_destroy(USBDevice *opaque)
280 {
281     USBHostDevice *s = (USBHostDevice *)opaque;
282     int i;
283
284     for (i = 0; i < USB_MAX_ENDPOINTS; i++)
285         if (s->ep_fd[i] >= 0)
286             close(s->ep_fd[i]);
287
288     if (s->devfd < 0)
289         return;
290
291     close(s->devfd);
292
293     g_free(s);
294 }
295
296 static int usb_host_initfn(USBDevice *dev)
297 {
298     return 0;
299 }
300
301 USBDevice *usb_host_device_open(const char *devname)
302 {
303     struct usb_device_info bus_info, dev_info;
304     USBDevice *d = NULL, *ret = NULL;
305     USBHostDevice *dev;
306     char ctlpath[PATH_MAX + 1];
307     char buspath[PATH_MAX + 1];
308     int bfd, dfd, bus, address, i;
309     int ugendebug = UGEN_DEBUG_LEVEL;
310
311     if (usb_host_find_device(&bus, &address, devname) < 0) {
312         goto fail;
313     }
314
315     snprintf(buspath, PATH_MAX, "/dev/usb%d", bus);
316
317     bfd = open(buspath, O_RDWR);
318     if (bfd < 0) {
319 #ifdef DEBUG
320         printf("usb_host_device_open: failed to open usb bus - %s\n",
321                strerror(errno));
322 #endif
323         goto fail;
324     }
325
326     bus_info.udi_addr = address;
327     if (ioctl(bfd, USB_DEVICEINFO, &bus_info) < 0) {
328 #ifdef DEBUG
329         printf("usb_host_device_open: failed to grab bus information - %s\n",
330                strerror(errno));
331 #endif
332         goto fail_bfd;
333     }
334
335 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
336     snprintf(ctlpath, PATH_MAX, "/dev/%s", bus_info.udi_devnames[0]);
337 #else
338     snprintf(ctlpath, PATH_MAX, "/dev/%s.00", bus_info.udi_devnames[0]);
339 #endif
340
341     dfd  = open(ctlpath, O_RDWR);
342     if (dfd < 0) {
343         dfd = open(ctlpath, O_RDONLY);
344         if (dfd < 0) {
345 #ifdef DEBUG
346             printf("usb_host_device_open: failed to open usb device %s - %s\n",
347                    ctlpath, strerror(errno));
348 #endif
349         }
350         goto fail_dfd;
351     }
352
353     if (ioctl(dfd, USB_GET_DEVICEINFO, &dev_info) < 0) {
354 #ifdef DEBUG
355         printf("usb_host_device_open: failed to grab device info - %s\n",
356                strerror(errno));
357 #endif
358         goto fail_dfd;
359     }
360
361     d = usb_create(NULL /* FIXME */, "usb-host");
362     dev = DO_UPCAST(USBHostDevice, dev, d);
363
364     if (dev_info.udi_speed == 1) {
365         dev->dev.speed = USB_SPEED_LOW - 1;
366         dev->dev.speedmask = USB_SPEED_MASK_LOW;
367     } else {
368         dev->dev.speed = USB_SPEED_FULL - 1;
369         dev->dev.speedmask = USB_SPEED_MASK_FULL;
370     }
371
372     if (strncmp(dev_info.udi_product, "product", 7) != 0) {
373         pstrcpy(dev->dev.product_desc, sizeof(dev->dev.product_desc),
374                 dev_info.udi_product);
375     } else {
376         snprintf(dev->dev.product_desc, sizeof(dev->dev.product_desc),
377                  "host:%s", devname);
378     }
379
380     pstrcpy(dev->devpath, sizeof(dev->devpath), "/dev/");
381     pstrcat(dev->devpath, sizeof(dev->devpath), dev_info.udi_devnames[0]);
382
383     /* Mark the endpoints as not yet open */
384     for (i = 0; i < USB_MAX_ENDPOINTS; i++) {
385         dev->ep_fd[i] = -1;
386     }
387
388     ioctl(dfd, USB_SETDEBUG, &ugendebug);
389
390     ret = (USBDevice *)dev;
391
392 fail_dfd:
393     close(dfd);
394 fail_bfd:
395     close(bfd);
396 fail:
397     return ret;
398 }
399
400 static struct USBDeviceInfo usb_host_dev_info = {
401     .product_desc   = "USB Host Device",
402     .qdev.name      = "usb-host",
403     .qdev.size      = sizeof(USBHostDevice),
404     .init           = usb_host_initfn,
405     .handle_packet  = usb_generic_handle_packet,
406     .handle_reset   = usb_host_handle_reset,
407     .handle_control = usb_host_handle_control,
408     .handle_data    = usb_host_handle_data,
409     .handle_destroy = usb_host_handle_destroy,
410 };
411
412 static void usb_host_register_devices(void)
413 {
414     usb_qdev_register(&usb_host_dev_info);
415 }
416 device_init(usb_host_register_devices)
417
418 static int usb_host_scan(void *opaque, USBScanFunc *func)
419 {
420     struct usb_device_info bus_info;
421     struct usb_device_info dev_info;
422     uint16_t vendor_id, product_id, class_id, speed;
423     int bfd, dfd, bus, address;
424     char busbuf[20], devbuf[20], product_name[256];
425     int ret = 0;
426
427     for (bus = 0; bus < 10; bus++) {
428
429         snprintf(busbuf, sizeof(busbuf) - 1, "/dev/usb%d", bus);
430         bfd = open(busbuf, O_RDWR);
431         if (bfd < 0)
432             continue;
433
434         for (address = 1; address < 127; address++) {
435
436             bus_info.udi_addr = address;
437             if (ioctl(bfd, USB_DEVICEINFO, &bus_info) < 0)
438                 continue;
439
440             /* only list devices that can be used by generic layer */
441             if (strncmp(bus_info.udi_devnames[0], "ugen", 4) != 0)
442                 continue;
443
444 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
445             snprintf(devbuf, sizeof(devbuf) - 1, "/dev/%s", bus_info.udi_devnames[0]);
446 #else
447             snprintf(devbuf, sizeof(devbuf) - 1, "/dev/%s.00", bus_info.udi_devnames[0]);
448 #endif
449
450             dfd = open(devbuf, O_RDONLY);
451             if (dfd < 0) {
452 #ifdef DEBUG
453                 printf("usb_host_scan: couldn't open device %s - %s\n", devbuf,
454                        strerror(errno));
455 #endif
456                 continue;
457             }
458
459             if (ioctl(dfd, USB_GET_DEVICEINFO, &dev_info) < 0)
460                 printf("usb_host_scan: couldn't get device information for %s - %s\n",
461                        devbuf, strerror(errno));
462
463             /* XXX: might need to fixup endianness of word values before copying over */
464
465             vendor_id = dev_info.udi_vendorNo;
466             product_id = dev_info.udi_productNo;
467             class_id = dev_info.udi_class;
468             speed = dev_info.udi_speed;
469
470             if (strncmp(dev_info.udi_product, "product", 7) != 0)
471                 pstrcpy(product_name, sizeof(product_name),
472                         dev_info.udi_product);
473             else
474                 product_name[0] = '\0';
475
476             ret = func(opaque, bus, address, class_id, vendor_id,
477                        product_id, product_name, speed);
478
479             close(dfd);
480
481             if (ret)
482                 goto the_end;
483         }
484
485         close(bfd);
486     }
487
488 the_end:
489     return ret;
490 }
491
492 typedef struct FindDeviceState {
493     int vendor_id;
494     int product_id;
495     int bus_num;
496     int addr;
497 } FindDeviceState;
498
499 static int usb_host_find_device_scan(void *opaque, int bus_num, int addr,
500                                      int class_id,
501                                      int vendor_id, int product_id,
502                                      const char *product_name, int speed)
503 {
504     FindDeviceState *s = opaque;
505     if (vendor_id == s->vendor_id &&
506         product_id == s->product_id) {
507         s->bus_num = bus_num;
508         s->addr = addr;
509         return 1;
510      } else {
511         return 0;
512      }
513 }
514
515
516 /* the syntax is :
517    'bus.addr' (decimal numbers) or
518    'vendor_id:product_id' (hexa numbers) */
519 static int usb_host_find_device(int *pbus_num, int *paddr,
520                                 const char *devname)
521 {
522     const char *p;
523     int ret;
524     FindDeviceState fs;
525
526     p = strchr(devname, '.');
527     if (p) {
528         *pbus_num = strtoul(devname, NULL, 0);
529         *paddr = strtoul(p + 1, NULL, 0);
530         return 0;
531     }
532     p = strchr(devname, ':');
533     if (p) {
534         fs.vendor_id = strtoul(devname, NULL, 16);
535         fs.product_id = strtoul(p + 1, NULL, 16);
536         ret = usb_host_scan(&fs, usb_host_find_device_scan);
537         if (ret) {
538             *pbus_num = fs.bus_num;
539             *paddr = fs.addr;
540             return 0;
541         }
542      }
543      return -1;
544 }
545
546 /**********************/
547 /* USB host device info */
548
549 struct usb_class_info {
550     int class;
551     const char *class_name;
552 };
553
554 static const struct usb_class_info usb_class_info[] = {
555     { USB_CLASS_AUDIO, "Audio"},
556     { USB_CLASS_COMM, "Communication"},
557     { USB_CLASS_HID, "HID"},
558     { USB_CLASS_HUB, "Hub" },
559     { USB_CLASS_PHYSICAL, "Physical" },
560     { USB_CLASS_PRINTER, "Printer" },
561     { USB_CLASS_MASS_STORAGE, "Storage" },
562     { USB_CLASS_CDC_DATA, "Data" },
563     { USB_CLASS_APP_SPEC, "Application Specific" },
564     { USB_CLASS_VENDOR_SPEC, "Vendor Specific" },
565     { USB_CLASS_STILL_IMAGE, "Still Image" },
566     { USB_CLASS_CSCID, "Smart Card" },
567     { USB_CLASS_CONTENT_SEC, "Content Security" },
568     { -1, NULL }
569 };
570
571 static const char *usb_class_str(uint8_t class)
572 {
573     const struct usb_class_info *p;
574     for (p = usb_class_info; p->class != -1; p++) {
575         if (p->class == class)
576             break;
577     }
578     return p->class_name;
579 }
580
581 static void usb_info_device(Monitor *mon, int bus_num, int addr, int class_id,
582                             int vendor_id, int product_id,
583                             const char *product_name,
584                             int speed)
585 {
586     const char *class_str, *speed_str;
587
588     switch(speed) {
589     case USB_SPEED_LOW:
590         speed_str = "1.5";
591         break;
592     case USB_SPEED_FULL:
593         speed_str = "12";
594         break;
595     case USB_SPEED_HIGH:
596         speed_str = "480";
597         break;
598     default:
599         speed_str = "?";
600         break;
601     }
602
603     monitor_printf(mon, "  Device %d.%d, speed %s Mb/s\n",
604                    bus_num, addr, speed_str);
605     class_str = usb_class_str(class_id);
606     if (class_str)
607         monitor_printf(mon, "    %s:", class_str);
608     else
609         monitor_printf(mon, "    Class %02x:", class_id);
610     monitor_printf(mon, " USB device %04x:%04x", vendor_id, product_id);
611     if (product_name[0] != '\0')
612         monitor_printf(mon, ", %s", product_name);
613     monitor_printf(mon, "\n");
614 }
615
616 static int usb_host_info_device(void *opaque,
617                                 int bus_num, int addr,
618                                 int class_id,
619                                 int vendor_id, int product_id,
620                                 const char *product_name,
621                                 int speed)
622 {
623     Monitor *mon = opaque;
624
625     usb_info_device(mon, bus_num, addr, class_id, vendor_id, product_id,
626                     product_name, speed);
627     return 0;
628 }
629
630 void usb_host_info(Monitor *mon)
631 {
632     usb_host_scan(mon, usb_host_info_device);
633 }
634
635 /* XXX add this */
636 int usb_host_device_close(const char *devname)
637 {
638     return 0;
639 }