From owner-freebsd-usb@FreeBSD.ORG Tue Aug 15 15:00:33 2006 Return-Path: X-Original-To: freebsd-usb@hub.freebsd.org Delivered-To: freebsd-usb@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 570E916A4DE for ; Tue, 15 Aug 2006 15:00:33 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 789E843D46 for ; Tue, 15 Aug 2006 15:00:32 +0000 (GMT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.13.4/8.13.4) with ESMTP id k7FF0WV3031316 for ; Tue, 15 Aug 2006 15:00:32 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.13.4/8.13.4/Submit) id k7FF0WuM031310; Tue, 15 Aug 2006 15:00:32 GMT (envelope-from gnats) Resent-Date: Tue, 15 Aug 2006 15:00:32 GMT Resent-Message-Id: <200608151500.k7FF0WuM031310@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-usb@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Naoyuki Tai Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 928EB16A4E2 for ; Tue, 15 Aug 2006 14:52:18 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (www.freebsd.org [216.136.204.117]) by mx1.FreeBSD.org (Postfix) with ESMTP id 97D5E43D66 for ; Tue, 15 Aug 2006 14:52:17 +0000 (GMT) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (localhost [127.0.0.1]) by www.freebsd.org (8.13.1/8.13.1) with ESMTP id k7FEqHm0050638 for ; Tue, 15 Aug 2006 14:52:17 GMT (envelope-from nobody@www.freebsd.org) Received: (from nobody@localhost) by www.freebsd.org (8.13.1/8.13.1/Submit) id k7FEqH3d050636; Tue, 15 Aug 2006 14:52:17 GMT (envelope-from nobody) Message-Id: <200608151452.k7FEqH3d050636@www.freebsd.org> Date: Tue, 15 Aug 2006 14:52:17 GMT From: Naoyuki Tai To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-2.3 Cc: Subject: usb/102096: /usr/sbin/usbd does not handle multiple devices in one event X-BeenThere: freebsd-usb@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: FreeBSD support for USB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 15 Aug 2006 15:00:33 -0000 >Number: 102096 >Category: usb >Synopsis: /usr/sbin/usbd does not handle multiple devices in one event >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-usb >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Tue Aug 15 15:00:31 GMT 2006 >Closed-Date: >Last-Modified: >Originator: Naoyuki Tai >Release: FreeBSD 5.5 >Organization: >Environment: FreeBSD nile.smartfruit.com 5.5-RELEASE FreeBSD 5.5-RELEASE #0: Sun Aug 13 04:03:03 EDT 2006 root@nile.smartfruit.com:/usr/obj/usr/src/sys/NILE i386 >Description: /usr/sbin/usbd does not handle an event with multiple devices. This happens when a hub or KVM switch with multiple devices (such as keyboard and mouse) is connected to a USB port. The problem has been around since the beginning of usbd, and reported the problem years ago. One time, the patch I reported has been applied, and fixed. FreeBSD 5.5's usbd.c regressed, unfortunately. The problem is that, the USB event may report more than one device in it but the usbd.c only handles the first device and ignores the rest. >How-To-Repeat: Connect a USB based KVM to a FreeBSD computer. Similary, you can connect a mouse and keyboard to a hub, then connect the hub to a computer. >Fix: --- usbd.c.orig Tue Aug 15 10:23:07 2006 +++ usbd.c Tue Aug 15 10:25:02 2006 @@ -843,84 +843,105 @@ void process_event_queue(int fd) { - struct usb_event event; + struct usb_event events; int error; int len; action_match_t action_match; + int i; + struct usb_event the_event; + struct usb_device_info* devinfo; + struct usb_device_info* the_devinfo; for (;;) { - len = read(fd, &event, sizeof(event)); + len = read(fd, &events, sizeof(events)); if (len == -1) { if (errno == EWOULDBLOCK) { /* no more events */ break; } else { fprintf(stderr,"%s: Could not read event, %s\n", - __progname, strerror(errno)); + __progname, strerror(errno)); exit(1); } } if (len == 0) break; - if (len != sizeof(event)) { + if (len != sizeof(events)) { fprintf(stderr, "partial read on %s\n", USBDEV); exit(1); } /* we seem to have gotten a valid event */ - if (verbose) - print_event(&event); + devinfo = &events.u.ue_device; + for (i = 0; i < USB_MAX_DEVNAMES; i++) { + if (devinfo->udi_devnames[i][0] == '\0') + break; + + memcpy(&the_event, &events, sizeof(the_event)); + the_devinfo = &the_event.u.ue_device; + + if (i > 0) + memcpy(the_devinfo->udi_devnames[0], the_devinfo->udi_devnames[i], USB_MAX_DEVNAMELEN); + the_devinfo->udi_devnames[1][0] = '\0'; - /* handle the event appropriately */ - switch (event.ue_type) { - case USB_EVENT_CTRLR_ATTACH: - if (verbose) - printf("USB_EVENT_CTRLR_ATTACH\n"); - break; - case USB_EVENT_CTRLR_DETACH: if (verbose) - printf("USB_EVENT_CTRLR_DETACH\n"); - break; - case USB_EVENT_DEVICE_ATTACH: - case USB_EVENT_DEVICE_DETACH: - if (find_action(&event.u.ue_device, &action_match) == 0) - /* nothing found */ - break; + print_event(&the_event); - if (verbose >= 2) - print_action(action_match.action, 0); + if (verbose >=2) { + printf(" === match attempt: %s\n", the_devinfo->udi_devnames[0]); + } + + /* handle the event appropriately */ + switch (the_event.ue_type) { + case USB_EVENT_CTRLR_ATTACH: + if (verbose) + printf("USB_EVENT_CTRLR_ATTACH\n"); + break; + case USB_EVENT_CTRLR_DETACH: + if (verbose) + printf("USB_EVENT_CTRLR_DETACH\n"); + break; + case USB_EVENT_DEVICE_ATTACH: + case USB_EVENT_DEVICE_DETACH: + if (find_action(&the_event.u.ue_device, &action_match) == 0) + /* nothing found */ + break; - if (action_match.devname) { if (verbose >= 2) - printf("%s: Setting DEVNAME='%s'\n", - __progname, action_match.devname); + print_action(action_match.action, 0); - error = setenv("DEVNAME", action_match.devname, 1); - if (error) - fprintf(stderr, "%s: setenv(\"DEVNAME\", \"%s\",1) failed, %s\n", - __progname, action_match.devname, strerror(errno)); + if (action_match.devname) { + if (verbose >= 2) + printf("%s: Setting DEVNAME='%s'\n", + __progname, action_match.devname); + + error = setenv("DEVNAME", action_match.devname, 1); + if (error) + fprintf(stderr, "%s: setenv(\"DEVNAME\", \"%s\",1) failed, %s\n", + __progname, action_match.devname, strerror(errno)); + } + + if (USB_EVENT_IS_ATTACH(the_event.ue_type) && + action_match.action->attach) + execute_command(action_match.action->attach); + if (USB_EVENT_IS_DETACH(the_event.ue_type) && + action_match.action->detach) + execute_command(action_match.action->detach); + break; + case USB_EVENT_DRIVER_ATTACH: + if (verbose) + printf("USB_EVENT_DRIVER_ATTACH\n"); + break; + case USB_EVENT_DRIVER_DETACH: + if (verbose) + printf("USB_EVENT_DRIVER_DETACH\n"); + break; + default: + printf("Unknown USB event %d\n", the_event.ue_type); } - - if (USB_EVENT_IS_ATTACH(event.ue_type) && - action_match.action->attach) - execute_command(action_match.action->attach); - if (USB_EVENT_IS_DETACH(event.ue_type) && - action_match.action->detach) - execute_command(action_match.action->detach); - break; - case USB_EVENT_DRIVER_ATTACH: - if (verbose) - printf("USB_EVENT_DRIVER_ATTACH\n"); - break; - case USB_EVENT_DRIVER_DETACH: - if (verbose) - printf("USB_EVENT_DRIVER_DETACH\n"); - break; - default: - printf("Unknown USB event %d\n", event.ue_type); } - } + } } >Release-Note: >Audit-Trail: >Unformatted: