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;
562 usb_dev = usb_alloc_dev (NULL, hci->bus, 0);
566 hci->bus->root_hub = usb_dev;
568 usb_dev->bus->devnum_next = usb_dev->devnum + 1;
569 set_bit (usb_dev->devnum, usb_dev->bus->devmap.devicemap);
571 if (usb_new_device (usb_dev) != 0) {
572 usb_put_dev (usb_dev);