2 /*-------------------------------------------------------------------------*/
3 /*-------------------------------------------------------------------------*
4 * SL811HS virtual root hub
6 * based on usb-ohci.c by R. Weissgaerber et al.
7 *-------------------------------------------------------------------------*
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 *-------------------------------------------------------------------------*/
24 /* FIXME: reuse the root hub framework in usbcore, shrinking this code. */
29 static __u32
getPortStatusAndChange (hci_t
* hci
);
30 static void setPortStatus (hci_t
* hci
, __u16 bitPos
);
31 static void setPortChange (hci_t
* hci
, __u16 bitPos
);
32 static void clrPortStatus (hci_t
* hci
, __u16 bitPos
);
33 static void clrPortChange (hci_t
* hci
, __u16 bitPos
);
34 static int USBReset (hci_t
* hci
);
35 static int cc_to_error (int cc
);
37 /*-------------------------------------------------------------------------*
39 *-------------------------------------------------------------------------*/
41 /* Device descriptor */
42 static __u8 root_hub_dev_des
[] = {
43 0x12, /* __u8 bLength; */
44 0x01, /* __u8 bDescriptorType; Device */
45 0x10, /* __u16 bcdUSB; v1.1 */
47 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */
48 0x00, /* __u8 bDeviceSubClass; */
49 0x00, /* __u8 bDeviceProtocol; */
50 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */
51 0x00, /* __u16 idVendor; */
53 0x00, /* __u16 idProduct; */
55 0x00, /* __u16 bcdDevice; */
57 0x00, /* __u8 iManufacturer; */
58 0x02, /* __u8 iProduct; */
59 0x01, /* __u8 iSerialNumber; */
60 0x01 /* __u8 bNumConfigurations; */
63 /* Configuration descriptor */
64 static __u8 root_hub_config_des
[] = {
65 0x09, /* __u8 bLength; */
66 0x02, /* __u8 bDescriptorType; Configuration */
67 0x19, /* __u16 wTotalLength; */
69 0x01, /* __u8 bNumInterfaces; */
70 0x01, /* __u8 bConfigurationValue; */
71 0x00, /* __u8 iConfiguration; */
72 0x40, /* __u8 bmAttributes;
73 Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup,
75 0x00, /* __u8 MaxPower; */
78 0x09, /* __u8 if_bLength; */
79 0x04, /* __u8 if_bDescriptorType; Interface */
80 0x00, /* __u8 if_bInterfaceNumber; */
81 0x00, /* __u8 if_bAlternateSetting; */
82 0x01, /* __u8 if_bNumEndpoints; */
83 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */
84 0x00, /* __u8 if_bInterfaceSubClass; */
85 0x00, /* __u8 if_bInterfaceProtocol; */
86 0x00, /* __u8 if_iInterface; */
89 0x07, /* __u8 ep_bLength; */
90 0x05, /* __u8 ep_bDescriptorType; Endpoint */
91 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */
92 0x03, /* __u8 ep_bmAttributes; Interrupt */
93 0x02, /* __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */
95 0xff /* __u8 ep_bInterval; 255 ms */
98 /* Hub class-specific descriptor is constructed dynamically */
100 /***************************************************************************
101 * Function Name : rh_send_irq
103 * This function examine the port change in the virtual root hub.
105 * Note: This function assumes only one port exist in the root hub.
107 * Input: hci = data structure for the host controller
108 * rh_data = The pointer to port change data
109 * rh_len = length of the data in bytes
111 * Return: length of data
112 **************************************************************************/
113 static int rh_send_irq (hci_t
* hci
, void *rh_data
, int rh_len
)
121 DBGFUNC ("enter rh_send_irq: \n");
123 /* Assuming the root hub has one port. This value need to change if
124 * there are more than one port for the root hub
129 /* The root hub status is not implemented, it basically has two fields:
130 * -- Local Power Status
131 * -- Over Current Indicator
132 * -- Local Power Change
133 * -- Over Current Indicator
135 * Right now, It is assume the power is good and no changes
140 ret
= *(__u8
*) data
;
142 /* Has the port status change within the root hub: It checks for
143 * -- Port Connect Status change
144 * -- Port Enable Change
147 for (i
= 0; i
< num_ports
; i
++) {
148 *(__u8
*) (data
+ (i
+ 1) / 8) |=
149 (((getPortStatusAndChange (hci
) >> 16) & (PORT_CONNECT_STAT
| PORT_ENABLE_STAT
)) ? 1 : 0) << ((i
+ 1) % 8);
150 ret
+= *(__u8
*) (data
+ (i
+ 1) / 8);
152 /* After the port change is read, it should be reset so the next time
153 * is it doesn't trigger a change again */
159 memcpy (rh_data
, data
, min (len
, min (rh_len
, (int)sizeof (data
))));
165 /***************************************************************************
166 * Function Name : rh_int_timer_do
168 * This function is called when the timer expires. It gets the the port
169 * change data and pass along to the upper protocol.
171 * Note: The virtual root hub interrupt pipe are polled by the timer
172 * every "interval" ms
174 * Input: ptr = ptr to the urb
177 **************************************************************************/
178 static void rh_int_timer_do (unsigned long ptr
)
181 struct urb
*urb
= (struct urb
*) ptr
;
182 hci_t
*hci
= urb
->dev
->bus
->hcpriv
;
184 DBGFUNC ("enter rh_int_timer_do\n");
187 len
= rh_send_irq (hci
, urb
->transfer_buffer
,
188 urb
->transfer_buffer_length
);
190 urb
->actual_length
= len
;
192 urb_print (urb
, "RET-t(rh)",
193 usb_pipeout (urb
->pipe
));
196 urb
->complete (urb
, NULL
);
201 /* re-activate the timer */
202 rh_init_int_timer (urb
);
205 /***************************************************************************
206 * Function Name : rh_init_int_timer
208 * This function creates a timer that act as interrupt pipe in the
211 * Note: The virtual root hub's interrupt pipe are polled by the timer
212 * every "interval" ms
214 * Input: urb = USB request block
217 **************************************************************************/
218 static int rh_init_int_timer (struct urb
* urb
)
220 hci_t
*hci
= urb
->dev
->bus
->hcpriv
;
221 hci
->rh
.interval
= urb
->interval
;
223 init_timer (&hci
->rh
.rh_int_timer
);
224 hci
->rh
.rh_int_timer
.function
= rh_int_timer_do
;
225 hci
->rh
.rh_int_timer
.data
= (unsigned long) urb
;
226 hci
->rh
.rh_int_timer
.expires
= jiffies
+ (HZ
* (urb
->interval
< 30 ? 30 : urb
->interval
)) / 1000;
227 add_timer (&hci
->rh
.rh_int_timer
);
232 /*-------------------------------------------------------------------------*/
234 /* for returning string descriptors in UTF-16LE */
235 static int ascii2utf (char *ascii
, __u8
*utf
, int utfmax
)
239 for (retval
= 0; *ascii
&& utfmax
> 1; utfmax
-= 2, retval
+= 2) {
240 *utf
++ = *ascii
++ & 0x7f;
246 static int root_hub_string (int id
, int serial
, char *type
, __u8
*data
, int len
)
250 // assert (len > (2 * (sizeof (buf) + 1)));
251 // assert (strlen (type) <= 8);
255 *data
++ = 4; *data
++ = 3; /* 4 bytes data */
256 *data
++ = 0; *data
++ = 0; /* some language id */
260 } else if (id
== 1) {
261 sprintf (buf
, "%x", serial
);
263 // product description
264 } else if (id
== 2) {
265 sprintf (buf
, "USB %s Root Hub", type
);
267 // id 3 == vendor description
269 // unsupported IDs --> "stall"
273 data
[0] = 2 + ascii2utf (buf
, data
+ 2, len
- 2);
278 /*-------------------------------------------------------------------------*/
281 #define OK(x) len = (x); break
283 /***************************************************************************
284 * Function Name : rh_submit_urb
286 * This function handles all USB request to the the virtual root hub
288 * Input: urb = USB request block
291 **************************************************************************/
292 static int rh_submit_urb (struct urb
* urb
)
294 struct usb_device
*usb_dev
= urb
->dev
;
295 hci_t
*hci
= usb_dev
->bus
->hcpriv
;
296 unsigned int pipe
= urb
->pipe
;
297 struct usb_ctrlrequest
*cmd
= (struct usb_ctrlrequest
*) urb
->setup_packet
;
298 void *data
= urb
->transfer_buffer
;
299 int leni
= urb
->transfer_buffer_length
;
301 int status
= TD_CC_NOERROR
;
303 __u8
*data_buf
= (__u8
*) datab
;
310 DBGFUNC ("enter rh_submit_urb\n");
311 if (usb_pipeint (pipe
)) {
314 hci
->rh
.interval
= urb
->interval
;
315 rh_init_int_timer (urb
);
316 urb
->status
= cc_to_error (TD_CC_NOERROR
);
321 bmRType_bReq
= cmd
->bRequestType
| (cmd
->bRequest
<< 8);
322 wValue
= le16_to_cpu (cmd
->wValue
);
323 wIndex
= le16_to_cpu (cmd
->wIndex
);
324 wLength
= le16_to_cpu (cmd
->wLength
);
326 DBG ("rh_submit_urb, req = %d(%x) len=%d",
327 bmRType_bReq
, bmRType_bReq
, wLength
);
329 switch (bmRType_bReq
) {
330 /* Request Destination:
331 without flags: Device,
332 RH_INTERFACE: interface,
333 RH_ENDPOINT: endpoint,
334 RH_CLASS means HUB here,
335 RH_OTHER | RH_CLASS almost ever means HUB_PORT here
339 *(__u16
*) data_buf
= cpu_to_le16 (1);
342 case RH_GET_STATUS
| RH_INTERFACE
:
343 *(__u16
*) data_buf
= cpu_to_le16 (0);
346 case RH_GET_STATUS
| RH_ENDPOINT
:
347 *(__u16
*) data_buf
= cpu_to_le16 (0);
350 case RH_GET_STATUS
| RH_CLASS
:
351 *(__u32
*) data_buf
= cpu_to_le32 (0);
354 case RH_GET_STATUS
| RH_OTHER
| RH_CLASS
:
355 *(__u32
*) data_buf
=
356 cpu_to_le32 (getPortStatusAndChange (hci
));
359 case RH_CLEAR_FEATURE
| RH_ENDPOINT
:
361 case (RH_ENDPOINT_STALL
):
366 case RH_CLEAR_FEATURE
| RH_CLASS
:
368 case RH_C_HUB_LOCAL_POWER
:
371 case (RH_C_HUB_OVER_CURRENT
):
372 /* Over Current Not Implemented */
377 case RH_CLEAR_FEATURE
| RH_OTHER
| RH_CLASS
:
379 case (RH_PORT_ENABLE
):
380 clrPortStatus (hci
, PORT_ENABLE_STAT
);
383 case (RH_PORT_SUSPEND
):
384 clrPortStatus (hci
, PORT_SUSPEND_STAT
);
387 case (RH_PORT_POWER
):
388 clrPortStatus (hci
, PORT_POWER_STAT
);
391 case (RH_C_PORT_CONNECTION
):
392 clrPortChange (hci
, PORT_CONNECT_STAT
);
395 case (RH_C_PORT_ENABLE
):
396 clrPortChange (hci
, PORT_ENABLE_STAT
);
399 case (RH_C_PORT_SUSPEND
):
400 clrPortChange (hci
, PORT_SUSPEND_STAT
);
403 case (RH_C_PORT_OVER_CURRENT
):
404 clrPortChange (hci
, PORT_OVER_CURRENT_STAT
);
407 case (RH_C_PORT_RESET
):
408 clrPortChange (hci
, PORT_RESET_STAT
);
413 case RH_SET_FEATURE
| RH_OTHER
| RH_CLASS
:
415 case (RH_PORT_SUSPEND
):
416 setPortStatus (hci
, PORT_SUSPEND_STAT
);
419 case (RH_PORT_RESET
):
420 setPortStatus (hci
, PORT_RESET_STAT
);
423 PORT_CONNECT_CHANGE
| PORT_ENABLE_CHANGE
424 | PORT_SUSPEND_CHANGE
|
425 PORT_OVER_CURRENT_CHANGE
);
426 setPortChange (hci
, PORT_RESET_CHANGE
);
427 clrPortStatus (hci
, PORT_RESET_STAT
);
428 setPortStatus (hci
, PORT_ENABLE_STAT
);
432 case (RH_PORT_POWER
):
433 setPortStatus (hci
, PORT_POWER_STAT
);
436 case (RH_PORT_ENABLE
):
437 setPortStatus (hci
, PORT_ENABLE_STAT
);
443 hci
->rh
.devnum
= wValue
;
446 case RH_GET_DESCRIPTOR
:
447 DBGVERBOSE ("rh_submit_urb: RH_GET_DESCRIPTOR, wValue = 0x%x\n", wValue
);
448 switch ((wValue
& 0xff00) >> 8) {
449 case (0x01): /* device descriptor */
450 len
= min (leni
, min ((__u16
)sizeof (root_hub_dev_des
), wLength
));
451 data_buf
= root_hub_dev_des
;
454 case (0x02): /* configuration descriptor */
455 len
= min (leni
, min ((__u16
)sizeof (root_hub_config_des
), wLength
));
456 data_buf
= root_hub_config_des
;
459 case (0x03): /* string descriptors */
460 len
= root_hub_string (wValue
& 0xff, (int) (long) 0,
461 "SL811HS", data
, wLength
);
464 OK (min (leni
, len
));
468 status
= SL11H_STATMASK_STALL
;
472 case RH_GET_DESCRIPTOR
| RH_CLASS
:
473 data_buf
[0] = 9; // min length;
475 data_buf
[2] = 1; // # of downstream port
478 data_buf
[5] = 50; // 100 ms for port reset
479 data_buf
[7] = 0xfc; // which port is attachable
480 if (data_buf
[2] < 7) {
485 len
= min (leni
, min ((__u16
)data_buf
[0], wLength
));
488 case RH_GET_CONFIGURATION
:
489 *(__u8
*) data_buf
= 0x01;
492 case RH_SET_CONFIGURATION
:
496 DBGERR ("unsupported root hub command");
497 status
= SL11H_STATMASK_STALL
;
500 len
= min (len
, leni
);
501 if (data
!= data_buf
)
502 memcpy (data
, data_buf
, len
);
503 urb
->actual_length
= len
;
504 urb
->status
= cc_to_error (status
);
509 urb
->complete (urb
, NULL
);
515 /***************************************************************************
516 * Function Name : rh_unlink_urb
518 * This function unlinks the URB
520 * Input: urb = USB request block
523 **************************************************************************/
524 static int rh_unlink_urb (struct urb
* urb
)
526 hci_t
*hci
= urb
->dev
->bus
->hcpriv
;
528 DBGFUNC ("enter rh_unlink_urb\n");
529 if (hci
->rh
.urb
== urb
) {
531 del_timer (&hci
->rh
.rh_int_timer
);
535 usb_put_dev (urb
->dev
);
537 if (urb
->transfer_flags
& URB_ASYNC_UNLINK
) {
538 urb
->status
= -ECONNRESET
;
540 urb
->complete (urb
, NULL
);
543 urb
->status
= -ENOENT
;
548 /***************************************************************************
549 * Function Name : rh_connect_rh
551 * This function connect the virtual root hub to the USB stack
553 * Input: urb = USB request block
556 **************************************************************************/
557 static int rh_connect_rh (hci_t
* hci
)
559 struct usb_device
*usb_dev
;
563 usb_dev
= usb_alloc_dev (NULL
, hci
->bus
, 0);
568 usb_dev
->bus
->devnum_next
= usb_dev
->devnum
+ 1;
569 set_bit (usb_dev
->devnum
, usb_dev
->bus
->devmap
.devicemap
);
571 down (&usb_bus_list_lock
);
572 hci
->bus
->root_hub
= usb_dev
;
573 retval
= usb_new_device (usb_dev
);
575 hci
->bus
->root_hub
= NULL
;
576 up (&usb_bus_list_lock
);
578 usb_put_dev (usb_dev
);