]> xenbits.xensource.com Git - qemu-xen-unstable.git/commitdiff
usb-host: claim port
authorGerd Hoffmann <kraxel@redhat.com>
Wed, 24 Aug 2011 11:34:17 +0000 (13:34 +0200)
committerGerd Hoffmann <kraxel@redhat.com>
Wed, 7 Sep 2011 07:58:12 +0000 (09:58 +0200)
When configured to pass through a specific host port (using hostbus and
hostport properties), try to claim the port if supported by the kernel.
That will avoid any kernel drivers binding to devices plugged into that
port.  It will not stop any userspace apps (such as usb_modeswitch)
access the device via usbfs though.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
trace-events
usb-linux.c

index e473aef829e64cd6ffe8dbdd20caf5aad2ae42c2..a6e0cb4c4813339171b95f31472841fe93887f54 100644 (file)
@@ -263,6 +263,7 @@ usb_host_ep_stop_iso(int bus, int addr, int ep) "dev %d:%d, ep %d"
 usb_host_reset(int bus, int addr) "dev %d:%d"
 usb_host_auto_scan_enabled(void)
 usb_host_auto_scan_disabled(void)
+usb_host_claim_port(int bus, int hub, int port) "bus %d, hub addr %d, port %d"
 
 # hw/scsi-bus.c
 scsi_req_alloc(int target, int lun, int tag) "target %d lun %d tag %d"
index a9030238476ddc40b46357cce44953c3b74ce6ac..ce0eaddefb30e3b10e13153eecb8d7a4264f9ab8 100644 (file)
@@ -115,6 +115,7 @@ struct USBAutoFilter {
 typedef struct USBHostDevice {
     USBDevice dev;
     int       fd;
+    int       hub_fd;
 
     uint8_t   descr[8192];
     int       descr_len;
@@ -525,6 +526,9 @@ static void usb_host_handle_destroy(USBDevice *dev)
     USBHostDevice *s = (USBHostDevice *)dev;
 
     usb_host_close(s);
+    if (s->hub_fd != -1) {
+        close(s->hub_fd);
+    }
     QTAILQ_REMOVE(&hostdevs, s, next);
     qemu_remove_exit_notifier(&s->exit);
 }
@@ -1266,10 +1270,63 @@ static int usb_host_initfn(USBDevice *dev)
 
     dev->auto_attach = 0;
     s->fd = -1;
+    s->hub_fd = -1;
+
     QTAILQ_INSERT_TAIL(&hostdevs, s, next);
     s->exit.notify = usb_host_exit_notifier;
     qemu_add_exit_notifier(&s->exit);
     usb_host_auto_check(NULL);
+
+#ifdef USBDEVFS_CLAIM_PORT
+    if (s->match.bus_num != 0 && s->match.port != NULL) {
+        char *h, hub_name[64], line[1024];
+        int hub_addr, portnr, ret;
+
+        snprintf(hub_name, sizeof(hub_name), "%d-%s",
+                 s->match.bus_num, s->match.port);
+
+        /* try strip off last ".$portnr" to get hub */
+        h = strrchr(hub_name, '.');
+        if (h != NULL) {
+            portnr = atoi(h+1);
+            *h = '\0';
+        } else {
+            /* no dot in there -> it is the root hub */
+            snprintf(hub_name, sizeof(hub_name), "usb%d",
+                     s->match.bus_num);
+            portnr = atoi(s->match.port);
+        }
+
+        if (!usb_host_read_file(line, sizeof(line), "devnum",
+                                hub_name)) {
+            goto out;
+        }
+        if (sscanf(line, "%d", &hub_addr) != 1) {
+            goto out;
+        }
+
+        if (!usb_host_device_path) {
+            goto out;
+        }
+        snprintf(line, sizeof(line), "%s/%03d/%03d",
+                 usb_host_device_path, s->match.bus_num, hub_addr);
+        s->hub_fd = open(line, O_RDWR | O_NONBLOCK);
+        if (s->hub_fd < 0) {
+            goto out;
+        }
+
+        ret = ioctl(s->hub_fd, USBDEVFS_CLAIM_PORT, &portnr);
+        if (ret < 0) {
+            close(s->hub_fd);
+            s->hub_fd = -1;
+            goto out;
+        }
+
+        trace_usb_host_claim_port(s->match.bus_num, hub_addr, portnr);
+    }
+out:
+#endif
+
     return 0;
 }