4 * (C) Copyright 1999 Linus Torvalds 5 * (C) Copyright 1999 Johannes Erdfelt 6 * (C) Copyright 1999 Gregory P. Smith 9 #include <linux/kernel.h> 10 #include <linux/sched.h> 11 #include <linux/list.h> 12 #include <linux/malloc.h> 13 #include <linux/smp_lock.h> 14 #include <linux/module.h> 15 #include <linux/spinlock.h> 17 #include <asm/uaccess.h> 23 static spinlock_t hub_event_lock
= SPIN_LOCK_UNLOCKED
; 24 static spinlock_t hub_list_lock
= SPIN_LOCK_UNLOCKED
; 26 staticLIST_HEAD(hub_event_list
);/* List of hubs needing servicing */ 27 staticLIST_HEAD(hub_list
);/* List containing all of the hubs (for cleanup) */ 29 staticDECLARE_WAIT_QUEUE_HEAD(khubd_wait
); 30 static int khubd_pid
=0;/* PID of khubd */ 31 static int khubd_running
=0; 33 static intusb_get_hub_descriptor(struct usb_device
*dev
,void*data
,int size
) 35 returnusb_control_msg(dev
,usb_rcvctrlpipe(dev
,0), 36 USB_REQ_GET_DESCRIPTOR
, USB_DIR_IN
| USB_RT_HUB
, 37 USB_DT_HUB
<<8,0, data
, size
); 40 static intusb_clear_port_feature(struct usb_device
*dev
,int port
,int feature
) 42 returnusb_control_msg(dev
,usb_sndctrlpipe(dev
,0), 43 USB_REQ_CLEAR_FEATURE
, USB_RT_PORT
, feature
, port
, NULL
,0); 46 static intusb_set_port_feature(struct usb_device
*dev
,int port
,int feature
) 48 returnusb_control_msg(dev
,usb_sndctrlpipe(dev
,0), 49 USB_REQ_SET_FEATURE
, USB_RT_PORT
, feature
, port
, NULL
,0); 52 static intusb_get_hub_status(struct usb_device
*dev
,void*data
) 54 /* FIXME: Don't hardcode 4 */ 55 returnusb_control_msg(dev
,usb_rcvctrlpipe(dev
,0), 56 USB_REQ_GET_STATUS
, USB_DIR_IN
| USB_RT_HUB
,0,0, data
,4); 59 static intusb_get_port_status(struct usb_device
*dev
,int port
,void*data
) 61 /* FIXME: Don't hardcode 4 */ 62 returnusb_control_msg(dev
,usb_rcvctrlpipe(dev
,0), 63 USB_REQ_GET_STATUS
, USB_DIR_IN
| USB_RT_PORT
,0, port
, data
,4); 67 * A irq handler returns non-zero to indicate to 68 * the low-level driver that it wants to be re-activated, 69 * or zero to say "I'm done". 71 static inthub_irq(int status
,void*__buffer
,int len
,void*dev_id
) 73 struct usb_hub
*hub
= dev_id
; 81 /* Something happened, let khubd figure it out */ 82 if(waitqueue_active(&khubd_wait
)) { 83 /* Add the hub to the event queue */ 84 spin_lock_irqsave(&hub_event_lock
, flags
); 85 if(hub
->event_list
.next
== &hub
->event_list
) { 86 list_add(&hub
->event_list
, &hub_event_list
); 90 spin_unlock_irqrestore(&hub_event_lock
, flags
); 98 static intusb_hub_configure(struct usb_hub
*hub
) 100 struct usb_device
*dev
= hub
->dev
; 101 unsigned char buffer
[4], *bitmap
; 102 struct usb_hub_descriptor
*descriptor
; 103 struct usb_descriptor_header
*header
; 106 /* Set it to the first configuration */ 107 usb_set_configuration(dev
, dev
->config
[0].bConfigurationValue
); 109 /* Get the length first */ 110 if(usb_get_hub_descriptor(dev
, buffer
,4)) 113 header
= (struct usb_descriptor_header
*)buffer
; 114 bitmap
=kmalloc(header
->bLength
, GFP_KERNEL
); 118 if(usb_get_hub_descriptor(dev
, bitmap
, header
->bLength
)) 121 descriptor
= (struct usb_hub_descriptor
*)bitmap
; 123 hub
->nports
= dev
->maxchild
= descriptor
->bNbrPorts
; 124 printk(KERN_INFO
"hub: %d-port%s detected\n", hub
->nports
, 125 (hub
->nports
==1) ?"":"s"); 127 switch(descriptor
->wHubCharacteristics
& HUB_CHAR_LPSM
) { 129 printk(KERN_INFO
"hub: ganged power switching\n"); 132 printk(KERN_INFO
"hub: individual port power switching\n"); 136 printk(KERN_INFO
"hub: unknown reserved power switching mode\n"); 140 if(descriptor
->wHubCharacteristics
& HUB_CHAR_COMPOUND
) 141 printk(KERN_INFO
"hub: part of a compound device\n"); 143 printk(KERN_INFO
"hub: standalone hub\n"); 145 switch(descriptor
->wHubCharacteristics
& HUB_CHAR_OCPM
) { 147 printk(KERN_INFO
"hub: global over current protection\n"); 150 printk(KERN_INFO
"hub: individual port over current protection\n"); 154 printk(KERN_INFO
"hub: no over current protection\n"); 158 printk(KERN_INFO
"hub: power on to power good time: %dms\n", 159 descriptor
->bPwrOn2PwrGood
*2); 161 printk(KERN_INFO
"hub: hub controller current requirement: %dmA\n", 162 descriptor
->bHubContrCurrent
); 164 for(i
=0; i
< dev
->maxchild
; i
++) 165 printk(KERN_INFO
"hub: port %d is%s removable\n", i
+1, 166 bitmap
[7+ ((i
+1)/8)] & (1<< ((i
+1) %8)) 171 if(usb_get_hub_status(dev
, buffer
)) 174 printk(KERN_INFO
"hub: local power source is %s\n", 175 (buffer
[0] &1) ?"lost (inactive)":"good"); 177 printk(KERN_INFO
"hub: %sover current condition exists\n", 178 (buffer
[0] &2) ?"":"no "); 180 /* Enable power to the ports */ 181 printk(KERN_INFO
"hub: enabling power on all ports\n"); 182 for(i
=0; i
< hub
->nports
; i
++) 183 usb_set_port_feature(dev
, i
+1, USB_PORT_FEAT_POWER
); 188 static inthub_probe(struct usb_device
*dev
) 190 struct usb_interface_descriptor
*interface
; 191 struct usb_endpoint_descriptor
*endpoint
; 195 /* We don't handle multi-config hubs */ 196 if(dev
->descriptor
.bNumConfigurations
!=1) 199 /* We don't handle multi-interface hubs */ 200 if(dev
->config
[0].bNumInterfaces
!=1) 203 interface
= &dev
->config
[0].interface
[0].altsetting
[0]; 206 if(interface
->bInterfaceClass
!= USB_CLASS_HUB
) 209 /* Some hubs have a subclass of 1, which AFAICT according to the */ 210 /* specs is not defined, but it works */ 211 if((interface
->bInterfaceSubClass
!=0) && 212 (interface
->bInterfaceSubClass
!=1)) 215 /* Multiple endpoints? What kind of mutant ninja-hub is this? */ 216 if(interface
->bNumEndpoints
!=1) 219 endpoint
= &interface
->endpoint
[0]; 221 /* Output endpoint? Curiousier and curiousier.. */ 222 if(!(endpoint
->bEndpointAddress
& USB_DIR_IN
)) 225 /* If it's not an interrupt endpoint, we'd better punt! */ 226 if((endpoint
->bmAttributes
&3) !=3) 230 printk(KERN_INFO
"USB hub found\n"); 232 if((hub
=kmalloc(sizeof(*hub
), GFP_KERNEL
)) == NULL
) { 233 printk(KERN_ERR
"couldn't kmalloc hub struct\n"); 237 memset(hub
,0,sizeof(*hub
)); 241 INIT_LIST_HEAD(&hub
->event_list
); 244 /* Record the new hub's existence */ 245 spin_lock_irqsave(&hub_list_lock
, flags
); 246 INIT_LIST_HEAD(&hub
->hub_list
); 247 list_add(&hub
->hub_list
, &hub_list
); 248 spin_unlock_irqrestore(&hub_list_lock
, flags
); 250 if(usb_hub_configure(hub
) >=0) { 251 hub
->irq_handle
=usb_request_irq(dev
,usb_rcvctrlpipe(dev
, 252 endpoint
->bEndpointAddress
), hub_irq
, endpoint
->bInterval
, hub
); 255 wake_up(&khubd_wait
); 261 static voidhub_disconnect(struct usb_device
*dev
) 263 struct usb_hub
*hub
= dev
->private; 266 spin_lock_irqsave(&hub_event_lock
, flags
); 268 /* Delete it and then reset it */ 269 list_del(&hub
->event_list
); 270 INIT_LIST_HEAD(&hub
->event_list
); 271 list_del(&hub
->hub_list
); 272 INIT_LIST_HEAD(&hub
->hub_list
); 274 spin_unlock_irqrestore(&hub_event_lock
, flags
); 276 if(hub
->irq_handle
) { 277 usb_release_irq(hub
->dev
, hub
->irq_handle
); 278 hub
->irq_handle
= NULL
; 281 /* Free the memory */ 285 static voidusb_hub_port_connect_change(struct usb_device
*hub
,int port
) 287 struct usb_device
*usb
; 288 unsigned char buf
[4]; 289 unsigned short portstatus
, portchange
; 291 /* Disconnect anything that may have been there */ 292 usb_disconnect(&hub
->children
[port
]); 295 usb_set_port_feature(hub
, port
+1, USB_PORT_FEAT_RESET
); 297 wait_ms(50);/* FIXME: This is from the *BSD stack, thanks! :) */ 300 if(usb_get_port_status(hub
, port
+1, buf
)) { 301 printk(KERN_ERR
"get_port_status failed\n"); 305 portstatus
=le16_to_cpup((unsigned short*)buf
+0); 306 portchange
=le16_to_cpup((unsigned short*)buf
+1); 308 /* If it's not in CONNECT and ENABLE state, we're done */ 309 if((!(portstatus
& USB_PORT_STAT_CONNECTION
)) && 310 (!(portstatus
& USB_PORT_STAT_ENABLE
))) 311 /* We're done now, we already disconnected the device */ 314 /* Allocate a new device struct for it */ 315 usb
=usb_alloc_dev(hub
, hub
->bus
); 317 printk(KERN_ERR
"couldn't allocate usb_device\n"); 321 usb
->slow
= (portstatus
& USB_PORT_STAT_LOW_SPEED
) ?1:0; 323 hub
->children
[port
] = usb
; 325 /* Find a new device ID for it */ 328 /* Run it through the hoops (find a driver, etc) */ 329 if(usb_new_device(usb
)) { 330 /* Woops, disable the port */ 331 printk(KERN_DEBUG
"hub: disabling port %d\n", 333 usb_clear_port_feature(hub
, port
+1, USB_PORT_FEAT_ENABLE
); 337 static voidusb_hub_events(void) 341 struct list_head
*tmp
; 342 struct usb_device
*dev
; 346 * We restart the list everytime to avoid a deadlock with 347 * deleting hubs downstream from this one. This should be 348 * safe since we delete the hub from the event list. 349 * Not the most efficient, but avoids deadlocks. 352 spin_lock_irqsave(&hub_event_lock
, flags
); 354 if(list_empty(&hub_event_list
)) 357 /* Grab the next entry from the beginning of the list */ 358 tmp
= hub_event_list
.next
; 360 hub
=list_entry(tmp
,struct usb_hub
, event_list
); 366 spin_unlock_irqrestore(&hub_event_lock
, flags
); 368 for(i
=0; i
< hub
->nports
; i
++) { 369 unsigned char buf
[4]; 370 unsigned short portstatus
, portchange
; 372 if(usb_get_port_status(dev
, i
+1, buf
)) { 373 printk(KERN_ERR
"get_port_status failed\n"); 377 portstatus
=le16_to_cpup((unsigned short*)buf
+0); 378 portchange
=le16_to_cpup((unsigned short*)buf
+1); 380 if(portchange
& USB_PORT_STAT_C_CONNECTION
) { 381 printk(KERN_INFO
"hub: port %d connection change\n", 384 usb_clear_port_feature(dev
, i
+1, 385 USB_PORT_FEAT_C_CONNECTION
); 387 usb_hub_port_connect_change(dev
, i
); 390 if(portchange
& USB_PORT_STAT_C_ENABLE
) { 391 printk(KERN_INFO
"hub: port %d enable change\n", 393 usb_clear_port_feature(dev
, i
+1, 394 USB_PORT_FEAT_C_ENABLE
); 397 if(portchange
& USB_PORT_STAT_C_SUSPEND
) 398 printk(KERN_INFO
"hub: port %d suspend change\n", 401 if(portchange
& USB_PORT_STAT_C_OVERCURRENT
) 402 printk(KERN_INFO
"hub: port %d over-current change\n", 405 if(portchange
& USB_PORT_STAT_C_RESET
) { 406 printk(KERN_INFO
"hub: port %d reset change\n", 408 usb_clear_port_feature(dev
, i
+1, 409 USB_PORT_FEAT_C_RESET
); 416 spin_unlock_irqrestore(&hub_event_lock
, flags
); 419 static intusb_hub_thread(void*__hub
) 430 * This thread doesn't need any user-level access, 431 * so get rid of all our resources 437 /* Setup a nice name */ 438 strcpy(current
->comm
,"khubd"); 440 /* Send me a signal to get me die (for debugging) */ 443 interruptible_sleep_on(&khubd_wait
); 444 }while(!signal_pending(current
)); 450 printk("usb_hub_thread exiting\n"); 456 static struct usb_driver hub_driver
= { 464 * This should be a separate module. 466 intusb_hub_init(void) 470 usb_register(&hub_driver
); 472 pid
=kernel_thread(usb_hub_thread
, NULL
, 473 CLONE_FS
| CLONE_FILES
| CLONE_SIGHAND
); 480 /* Fall through if kernel_thread failed */ 481 usb_deregister(&hub_driver
); 486 voidusb_hub_cleanup(void) 490 /* Kill the thread */ 491 ret
=kill_proc(khubd_pid
, SIGTERM
,1); 493 /* Wait 10 seconds */ 496 while(khubd_running
&& --count
) { 497 current
->state
= TASK_INTERRUPTIBLE
; 502 printk(KERN_ERR
"hub: giving up on killing khubd\n"); 506 * Hub resources are freed for us by usb_deregister. It 507 * usb_driver_purge on every device which in turn calls that 508 * devices disconnect function if it is using this driver. 509 * The hub_disconnect function takes care of releasing the 510 * individual hub resources. -greg 512 usb_deregister(&hub_driver
); 513 }/* usb_hub_cleanup() */ 518 returnusb_hub_init(); 521 voidcleanup_module(void)