]> Git Repo - qemu.git/blob - usb-bsd.c
usb-ehci: Cleanup itd error handling
[qemu.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->ep->nr;
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(USBBus *guest_bus, 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(guest_bus, "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 void usb_host_class_initfn(ObjectClass *klass, void *data)
401 {
402     USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
403
404     uc->product_desc   = "USB Host Device";
405     uc->init           = usb_host_initfn;
406     uc->handle_reset   = usb_host_handle_reset;
407     uc->handle_control = usb_host_handle_control;
408     uc->handle_data    = usb_host_handle_data;
409     uc->handle_destroy = usb_host_handle_destroy;
410 }
411
412 static TypeInfo usb_host_dev_info = {
413     .name          = "usb-host",
414     .parent        = TYPE_USB_DEVICE,
415     .instance_size = sizeof(USBHostDevice),
416     .class_init    = usb_host_class_initfn,
417 };
418
419 static void usb_host_register_types(void)
420 {
421     type_register_static(&usb_host_dev_info);
422 }
423
424 type_init(usb_host_register_types)
425
426 static int usb_host_scan(void *opaque, USBScanFunc *func)
427 {
428     struct usb_device_info bus_info;
429     struct usb_device_info dev_info;
430     uint16_t vendor_id, product_id, class_id, speed;
431     int bfd, dfd, bus, address;
432     char busbuf[20], devbuf[20], product_name[256];
433     int ret = 0;
434
435     for (bus = 0; bus < 10; bus++) {
436
437         snprintf(busbuf, sizeof(busbuf) - 1, "/dev/usb%d", bus);
438         bfd = open(busbuf, O_RDWR);
439         if (bfd < 0)
440             continue;
441
442         for (address = 1; address < 127; address++) {
443
444             bus_info.udi_addr = address;
445             if (ioctl(bfd, USB_DEVICEINFO, &bus_info) < 0)
446                 continue;
447
448             /* only list devices that can be used by generic layer */
449             if (strncmp(bus_info.udi_devnames[0], "ugen", 4) != 0)
450                 continue;
451
452 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
453             snprintf(devbuf, sizeof(devbuf) - 1, "/dev/%s", bus_info.udi_devnames[0]);
454 #else
455             snprintf(devbuf, sizeof(devbuf) - 1, "/dev/%s.00", bus_info.udi_devnames[0]);
456 #endif
457
458             dfd = open(devbuf, O_RDONLY);
459             if (dfd < 0) {
460 #ifdef DEBUG
461                 printf("usb_host_scan: couldn't open device %s - %s\n", devbuf,
462                        strerror(errno));
463 #endif
464                 continue;
465             }
466
467             if (ioctl(dfd, USB_GET_DEVICEINFO, &dev_info) < 0)
468                 printf("usb_host_scan: couldn't get device information for %s - %s\n",
469                        devbuf, strerror(errno));
470
471             /* XXX: might need to fixup endianness of word values before copying over */
472
473             vendor_id = dev_info.udi_vendorNo;
474             product_id = dev_info.udi_productNo;
475             class_id = dev_info.udi_class;
476             speed = dev_info.udi_speed;
477
478             if (strncmp(dev_info.udi_product, "product", 7) != 0)
479                 pstrcpy(product_name, sizeof(product_name),
480                         dev_info.udi_product);
481             else
482                 product_name[0] = '\0';
483
484             ret = func(opaque, bus, address, class_id, vendor_id,
485                        product_id, product_name, speed);
486
487             close(dfd);
488
489             if (ret)
490                 goto the_end;
491         }
492
493         close(bfd);
494     }
495
496 the_end:
497     return ret;
498 }
499
500 typedef struct FindDeviceState {
501     int vendor_id;
502     int product_id;
503     int bus_num;
504     int addr;
505 } FindDeviceState;
506
507 static int usb_host_find_device_scan(void *opaque, int bus_num, int addr,
508                                      int class_id,
509                                      int vendor_id, int product_id,
510                                      const char *product_name, int speed)
511 {
512     FindDeviceState *s = opaque;
513     if (vendor_id == s->vendor_id &&
514         product_id == s->product_id) {
515         s->bus_num = bus_num;
516         s->addr = addr;
517         return 1;
518      } else {
519         return 0;
520      }
521 }
522
523
524 /* the syntax is :
525    'bus.addr' (decimal numbers) or
526    'vendor_id:product_id' (hexa numbers) */
527 static int usb_host_find_device(int *pbus_num, int *paddr,
528                                 const char *devname)
529 {
530     const char *p;
531     int ret;
532     FindDeviceState fs;
533
534     p = strchr(devname, '.');
535     if (p) {
536         *pbus_num = strtoul(devname, NULL, 0);
537         *paddr = strtoul(p + 1, NULL, 0);
538         return 0;
539     }
540     p = strchr(devname, ':');
541     if (p) {
542         fs.vendor_id = strtoul(devname, NULL, 16);
543         fs.product_id = strtoul(p + 1, NULL, 16);
544         ret = usb_host_scan(&fs, usb_host_find_device_scan);
545         if (ret) {
546             *pbus_num = fs.bus_num;
547             *paddr = fs.addr;
548             return 0;
549         }
550      }
551      return -1;
552 }
553
554 /**********************/
555 /* USB host device info */
556
557 struct usb_class_info {
558     int class;
559     const char *class_name;
560 };
561
562 static const struct usb_class_info usb_class_info[] = {
563     { USB_CLASS_AUDIO, "Audio"},
564     { USB_CLASS_COMM, "Communication"},
565     { USB_CLASS_HID, "HID"},
566     { USB_CLASS_HUB, "Hub" },
567     { USB_CLASS_PHYSICAL, "Physical" },
568     { USB_CLASS_PRINTER, "Printer" },
569     { USB_CLASS_MASS_STORAGE, "Storage" },
570     { USB_CLASS_CDC_DATA, "Data" },
571     { USB_CLASS_APP_SPEC, "Application Specific" },
572     { USB_CLASS_VENDOR_SPEC, "Vendor Specific" },
573     { USB_CLASS_STILL_IMAGE, "Still Image" },
574     { USB_CLASS_CSCID, "Smart Card" },
575     { USB_CLASS_CONTENT_SEC, "Content Security" },
576     { -1, NULL }
577 };
578
579 static const char *usb_class_str(uint8_t class)
580 {
581     const struct usb_class_info *p;
582     for (p = usb_class_info; p->class != -1; p++) {
583         if (p->class == class)
584             break;
585     }
586     return p->class_name;
587 }
588
589 static void usb_info_device(Monitor *mon, int bus_num, int addr, int class_id,
590                             int vendor_id, int product_id,
591                             const char *product_name,
592                             int speed)
593 {
594     const char *class_str, *speed_str;
595
596     switch(speed) {
597     case USB_SPEED_LOW:
598         speed_str = "1.5";
599         break;
600     case USB_SPEED_FULL:
601         speed_str = "12";
602         break;
603     case USB_SPEED_HIGH:
604         speed_str = "480";
605         break;
606     default:
607         speed_str = "?";
608         break;
609     }
610
611     monitor_printf(mon, "  Device %d.%d, speed %s Mb/s\n",
612                    bus_num, addr, speed_str);
613     class_str = usb_class_str(class_id);
614     if (class_str)
615         monitor_printf(mon, "    %s:", class_str);
616     else
617         monitor_printf(mon, "    Class %02x:", class_id);
618     monitor_printf(mon, " USB device %04x:%04x", vendor_id, product_id);
619     if (product_name[0] != '\0')
620         monitor_printf(mon, ", %s", product_name);
621     monitor_printf(mon, "\n");
622 }
623
624 static int usb_host_info_device(void *opaque,
625                                 int bus_num, int addr,
626                                 int class_id,
627                                 int vendor_id, int product_id,
628                                 const char *product_name,
629                                 int speed)
630 {
631     Monitor *mon = opaque;
632
633     usb_info_device(mon, bus_num, addr, class_id, vendor_id, product_id,
634                     product_name, speed);
635     return 0;
636 }
637
638 void usb_host_info(Monitor *mon)
639 {
640     usb_host_scan(mon, usb_host_info_device);
641 }
642
643 /* XXX add this */
644 int usb_host_device_close(const char *devname)
645 {
646     return 0;
647 }
This page took 0.059277 seconds and 4 git commands to generate.