From nobody@FreeBSD.org  Sat Oct 12 19:59:42 2002
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id 038D337B401
	for <freebsd-gnats-submit@FreeBSD.org>; Sat, 12 Oct 2002 19:59:42 -0700 (PDT)
Received: from www.freebsd.org (www.freebsd.org [216.136.204.117])
	by mx1.FreeBSD.org (Postfix) with ESMTP id A25FE43E91
	for <freebsd-gnats-submit@FreeBSD.org>; Sat, 12 Oct 2002 19:59:41 -0700 (PDT)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.12.6/8.12.6) with ESMTP id g9D2xf7R002433
	for <freebsd-gnats-submit@FreeBSD.org>; Sat, 12 Oct 2002 19:59:41 -0700 (PDT)
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.12.6/8.12.6/Submit) id g9D2xfLk002432;
	Sat, 12 Oct 2002 19:59:41 -0700 (PDT)
Message-Id: <200210130259.g9D2xfLk002432@www.freebsd.org>
Date: Sat, 12 Oct 2002 19:59:41 -0700 (PDT)
From: Naoyuki Tai <ntai@smartfruit.com>
To: freebsd-gnats-submit@FreeBSD.org
Subject: /usr/sbin/usbd does not handle an usb event with multiple devices
X-Send-Pr-Version: www-1.0

>Number:         43993
>Category:       bin
>Synopsis:       /usr/sbin/usbd does not handle an usb event with multiple devices
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-usb
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sat Oct 12 20:00:09 PDT 2002
>Closed-Date:    Tue Jan 04 06:46:51 GMT 2005
>Last-Modified:  Tue Jan 04 06:46:51 GMT 2005
>Originator:     Naoyuki Tai
>Release:        4.6 STABLE
>Organization:
N/A
>Environment:
FreeBSD nile.camelsoft.com 4.6-STABLE FreeBSD 4.6-STABLE #4: Fri Jul 12 15:20:13 EDT 2002     ntai@nile.camelsoft.com:/usr/obj/usr/src/sys/NILE  i386
>Description:
When there is a usb event that consists of multiple devices, the usbd only  handles the first device and ignores the rest.
So, if you connect a USB hub or USB KVM with multiple devices already attached to the hub, to the host, usbd handles only one device and drops the rest.
For example, if a hub is connected to a usb keyboard and mouse, and the hub is then connected to the machine, usbd handles the keyboard or the mouse but not both.

>How-To-Repeat:
Connect multiple USB devices to a hub. Disconnect and reconnect the hub. If the hub is capable of sending an usb event with multiple devices, the problem appears.

>Fix:
Following patch to /usr/src/usr.sbin/usbd/usbd.c fixed the problem for me. But, I'm not sure that the patch is neat.

*** usbd.c.orig	Sun Feb 24 09:23:13 2002
--- usbd.c	Sat Oct 12 22:43:14 2002
***************
*** 826,831 ****
--- 826,835 ----
  	int error;
  	int len;
  	action_match_t action_match;
+ 	int i;
+ 	struct usb_event one_event;
+ 	struct usb_device_info *one_devinfo;
+ 	struct usb_device_info *devinfo;
  
  	for (;;) {
  		len = read(fd, &event, sizeof(event));
***************
*** 851,888 ****
  		if (verbose)
  			print_event(&event);
  
! 		/* handle the event appropriately */
! 		switch (event.ue_type) {
! 		case USB_EVENT_ATTACH:
! 		case USB_EVENT_DETACH:
! 			if (find_action(&event.ue_device, &action_match) == 0)
! 				/* nothing found */
  				break;
  
! 			if (verbose >= 2)
! 				print_action(action_match.action, 0);
  
- 			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 (event.ue_type == USB_EVENT_ATTACH && action_match.action->attach)
- 				execute_command(action_match.action->attach);
- 			if (event.ue_type == USB_EVENT_DETACH && action_match.action->detach)
- 				execute_command(action_match.action->detach);
- 
- 			break;
- 		default:
- 			printf("Unknown USB event %d\n", event.ue_type);
  		}
! 	}	
  }
  
  
--- 855,903 ----
  		if (verbose)
  			print_event(&event);
  
! 		devinfo = &event.ue_device;
! 
! 		for (i = 0; i < MAXDEVNAMES; i++) {
! 			if (devinfo->udi_devnames[i][0] == '\0')
  				break;
  
! 			memcpy(&one_event, &event, sizeof(one_event));
! 			one_devinfo = &one_event.ue_device;
! 			memcpy(&one_devinfo->udi_devnames[0], &devinfo->udi_devnames[i], sizeof(one_devinfo->udi_devnames[0]));
! 			one_devinfo->udi_devnames[1][0] = '\0';
! 
! 			/* handle the event appropriately */
! 			switch (one_event.ue_type) {
! 			case USB_EVENT_ATTACH:
! 			case USB_EVENT_DETACH:
! 				if (find_action(&one_event.ue_device, &action_match) == 0)
! 			  		/* nothing found */
! 					break;
  
  				if (verbose >= 2)
! 					print_action(action_match.action, 0);
! 
! 				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 (one_event.ue_type == USB_EVENT_ATTACH && action_match.action->attach)
! 					execute_command(action_match.action->attach);
! 				if (one_event.ue_type == USB_EVENT_DETACH && action_match.action->detach)
! 					execute_command(action_match.action->detach);
! 				break;
! 			default:
! 				printf("Unknown USB event %d\n", one_event.ue_type);
  			}
  		}
! 	}
  }
  
  

>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->joe 
Responsible-Changed-By: kris 
Responsible-Changed-When: Thu Jul 17 17:31:33 PDT 2003 
Responsible-Changed-Why:  
Assign to USB maintainer 

http://www.freebsd.org/cgi/query-pr.cgi?pr=43993 

From: Naoyuki Tai <ntai@smartfruit.com>
To: freebsd-gnats-submit@FreeBSD.org
Cc:  
Subject: Re: bin/43993: [PATCH] /usr/sbin/usbd does not handle an usb event
 with multiple devices
Date: Wed, 29 Sep 2004 02:10:45 -0400

 This is a multi-part message in MIME format.
 --------------050805000001070108080206
 Content-Type: text/plain; charset=us-ascii; format=flowed
 Content-Transfer-Encoding: 7bit
 
 Based on FreeBSD 4.10's usbd.c
 
 
 --------------050805000001070108080206
 Content-Type: text/plain;
  name="usbd.c.patch"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: inline;
  filename="usbd.c.patch"
 
 *** usbd.c.orig	Tue Nov 25 16:13:37 2003
 --- usbd.c	Wed Jun  2 02:07:53 2004
 ***************
 *** 840,865 ****
   void
   process_event_queue(int fd)
   {
 ! 	struct usb_event event;
   	int error;
   	int len;
   	action_match_t action_match;
   
   	for (;;) {
 ! 		len = read(fd, &event, sizeof(event));
   		if (len == -1) {
   			if (errno == EWOULDBLOCK) {
   				/* no more events */
   				break;
   			} else {
   				fprintf(stderr,"%s: Could not read event, %s\n",
 ! 					__progname, strerror(errno));
   				exit(1);
   			}
   		}
   		if (len == 0)
   			break;
 ! 		if (len != sizeof(event)) {
   			fprintf(stderr, "partial read on %s\n", USBDEV);
   			exit(1);
   		}
 --- 840,869 ----
   void
   process_event_queue(int fd)
   {
 ! 	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, &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));
   				exit(1);
   			}
   		}
   		if (len == 0)
   			break;
 ! 		if (len != sizeof(events)) {
   			fprintf(stderr, "partial read on %s\n", USBDEV);
   			exit(1);
   		}
 ***************
 *** 867,923 ****
   		/* we seem to have gotten a valid event */
   
   		if (verbose)
 ! 			print_event(&event);
   
 ! 		/* 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;
   
 ! 			if (verbose >= 2)
 ! 				print_action(action_match.action, 0);
   
 - 			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(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);
   		}
 ! 	}	
   }
   
   
 --- 871,943 ----
   		/* we seem to have gotten a valid event */
   
   		if (verbose)
 ! 			print_event(&events);
   
 ! 		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';
 ! 
 ! 			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 (verbose >= 2)
 ! 					print_action(action_match.action, 0);
   
 ! 				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);
   			}
   		}
 ! 	}
   }
   
   
 
 --------------050805000001070108080206--
 
Responsible-Changed-From-To: joe->freebsd-usb 
Responsible-Changed-By: joe 
Responsible-Changed-When: Wed Nov 10 10:58:30 GMT 2004 
Responsible-Changed-Why:  
Hand this over to the usb mailling list. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=43993 
State-Changed-From-To: open->closed 
State-Changed-By: julian 
State-Changed-When: Tue Jan 4 06:46:16 GMT 2005 
State-Changed-Why:  
Apply the supplied patch. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=43993 
>Unformatted:
