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 *-------------------------------------------------------------------------*/
27 static __u32 getPortStatusAndChange (hci_t * hci);
28 static void setPortStatus (hci_t * hci, __u16 bitPos);
29 static void setPortChange (hci_t * hci, __u16 bitPos);
30 static void clrPortStatus (hci_t * hci, __u16 bitPos);
31 static void clrPortChange (hci_t * hci, __u16 bitPos);
32 static int USBReset (hci_t * hci);
33 static int cc_to_error (int cc);
35 /*-------------------------------------------------------------------------*
37 *-------------------------------------------------------------------------*/
39 /* Device descriptor */
40 static __u8 root_hub_dev_des[] = {
41 0x12, /* __u8 bLength; */
42 0x01, /* __u8 bDescriptorType; Device */
43 0x10, /* __u16 bcdUSB; v1.1 */
45 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */
46 0x00, /* __u8 bDeviceSubClass; */
47 0x00, /* __u8 bDeviceProtocol; */
48 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */
49 0x00, /* __u16 idVendor; */
51 0x00, /* __u16 idProduct; */
53 0x00, /* __u16 bcdDevice; */
55 0x00, /* __u8 iManufacturer; */
56 0x02, /* __u8 iProduct; */
57 0x01, /* __u8 iSerialNumber; */
58 0x01 /* __u8 bNumConfigurations; */
61 /* Configuration descriptor */
62 static __u8 root_hub_config_des[] = {
63 0x09, /* __u8 bLength; */
64 0x02, /* __u8 bDescriptorType; Configuration */
65 0x19, /* __u16 wTotalLength; */
67 0x01, /* __u8 bNumInterfaces; */
68 0x01, /* __u8 bConfigurationValue; */
69 0x00, /* __u8 iConfiguration; */
70 0x40, /* __u8 bmAttributes;
71 Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup,
73 0x00, /* __u8 MaxPower; */
76 0x09, /* __u8 if_bLength; */
77 0x04, /* __u8 if_bDescriptorType; Interface */
78 0x00, /* __u8 if_bInterfaceNumber; */
79 0x00, /* __u8 if_bAlternateSetting; */
80 0x01, /* __u8 if_bNumEndpoints; */
81 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */
82 0x00, /* __u8 if_bInterfaceSubClass; */
83 0x00, /* __u8 if_bInterfaceProtocol; */
84 0x00, /* __u8 if_iInterface; */
87 0x07, /* __u8 ep_bLength; */
88 0x05, /* __u8 ep_bDescriptorType; Endpoint */
89 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */
90 0x03, /* __u8 ep_bmAttributes; Interrupt */
91 0x02, /* __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */
93 0xff /* __u8 ep_bInterval; 255 ms */
96 /* [Hub class-specific descriptor is constructed dynamically] */
97 /* copied from "dynamic source". (hne) */
98 static __u8 root_hub_hub_des[] =
100 0x09, /* __u8 bLength; */
101 0x29, /* __u8 bDescriptorType; Hub-descriptor */
102 0x01, /* __u8 bNbrPorts; */
103 0x00, /* __u16 wHubCharacteristics; */
105 0x50, /* __u8 bPwrOn2pwrGood; 100ms for port reset */
106 0x00, /* __u8 bHubContrCurrent; 0 mA */
107 0xfc, /* ??? HNE */ /* __u8 DeviceRemovable; *** 7 Ports max *** */ /* which port is attachable (HNE) */
108 0xff /* __u8 PortPwrCtrlMask; *** 7 ports max *** */
112 /***************************************************************************
113 * Function Name : rh_send_irq
115 * This function examine the port change in the virtual root hub.
117 * Note: This function assumes only one port exist in the root hub.
119 * Input: hci = data structure for the host controller
120 * rh_data = The pointer to port change data
121 * rh_len = length of the data in bytes
123 * Return: length of data
124 **************************************************************************/
125 static int rh_send_irq (hci_t * hci, void *rh_data, int rh_len)
133 DBGFUNC ("enter rh_send_irq: \n");
135 /* Assuming the root hub has one port. This value need to change if
136 * there are more than one port for the root hub
141 /* The root hub status is not implemented, it basically has two fields:
142 * -- Local Power Status
143 * -- Over Current Indicator
144 * -- Local Power Change
145 * -- Over Current Indicator
147 * Right now, It is assume the power is good and no changes
152 ret = *(__u8 *) data;
154 /* Has the port status change within the root hub: It checks for
155 * -- Port Connect Status change
156 * -- Port Enable Change
159 for (i = 0; i < num_ports; i++) {
160 *(__u8 *) (data + (i + 1) / 8) |=
161 (((getPortStatusAndChange (hci) >> 16) & (PORT_CONNECT_STAT | PORT_ENABLE_STAT)) ? 1 : 0) << ((i + 1) % 8);
162 ret += *(__u8 *) (data + (i + 1) / 8);
164 /* After the port change is read, it should be reset so the next time
165 * is it doesn't trigger a change again */
171 memcpy (rh_data, data, min (len, (int)min (rh_len, (int)sizeof (data))));
177 /***************************************************************************
178 * Function Name : rh_int_timer_do
180 * This function is called when the timer expires. It gets the the port
181 * change data and pass along to the upper protocol.
183 * Note: The virtual root hub interrupt pipe are polled by the timer
184 * every "interval" ms
186 * Input: ptr = ptr to the urb
189 **************************************************************************/
190 static void rh_int_timer_do (unsigned long ptr)
193 struct urb *urb = (struct urb *) ptr;
194 hci_t *hci = urb->dev->bus->hcpriv;
196 DBGFUNC ("enter rh_int_timer_do\n");
199 len = rh_send_irq (hci, urb->transfer_buffer,
200 urb->transfer_buffer_length);
202 urb->actual_length = len;
204 urb_print (urb, "RET-t(rh)",
205 usb_pipeout (urb->pipe));
213 /* re-activate the timer */
214 rh_init_int_timer (urb);
217 /***************************************************************************
218 * Function Name : rh_init_int_timer
220 * This function creates a timer that act as interrupt pipe in the
223 * Note: The virtual root hub's interrupt pipe are polled by the timer
224 * every "interval" ms
226 * Input: urb = USB request block
229 **************************************************************************/
230 static int rh_init_int_timer (struct urb * urb)
232 hci_t *hci = urb->dev->bus->hcpriv;
233 hci->rh.interval = urb->interval;
235 init_timer (&hci->rh.rh_int_timer);
236 hci->rh.rh_int_timer.function = rh_int_timer_do;
237 hci->rh.rh_int_timer.data = (unsigned long) urb;
238 hci->rh.rh_int_timer.expires = jiffies + (HZ * (urb->interval < 30 ? 30 : urb->interval)) / 1000;
239 add_timer (&hci->rh.rh_int_timer);
244 /*-------------------------------------------------------------------------*/
247 #define OK(x) len = (x); break
249 /***************************************************************************
250 * Function Name : rh_submit_urb
252 * This function handles all USB request to the the virtual root hub
254 * Input: urb = USB request block
257 **************************************************************************/
258 static int rh_submit_urb (struct urb * urb)
260 struct usb_device *usb_dev = urb->dev;
261 hci_t *hci = usb_dev->bus->hcpriv;
262 unsigned int pipe = urb->pipe;
263 struct usb_ctrlrequest *cmd = (struct usb_ctrlrequest *) urb->setup_packet;
264 void *data = urb->transfer_buffer;
265 int leni = urb->transfer_buffer_length;
267 int status = TD_CC_NOERROR;
269 __u8 *data_buf = (__u8 *) datab;
276 DBGFUNC ("enter rh_submit_urb\n");
277 if (usb_pipeint (pipe)) {
280 hci->rh.interval = urb->interval;
281 rh_init_int_timer (urb);
282 urb->status = cc_to_error (TD_CC_NOERROR);
287 bmRType_bReq = cmd->bRequestType | (cmd->bRequest << 8);
288 wValue = le16_to_cpu (cmd->wValue);
289 wIndex = le16_to_cpu (cmd->wIndex);
290 wLength = le16_to_cpu (cmd->wLength);
292 DBG ("rh_submit_urb, req = %d(%x) len=%d",
293 bmRType_bReq, bmRType_bReq, wLength);
295 switch (bmRType_bReq) {
296 /* Request Destination:
297 without flags: Device,
298 RH_INTERFACE: interface,
299 RH_ENDPOINT: endpoint,
300 RH_CLASS means HUB here,
301 RH_OTHER | RH_CLASS almost ever means HUB_PORT here
305 *(__u16 *) data_buf = cpu_to_le16 (1);
308 case RH_GET_STATUS | RH_INTERFACE:
309 *(__u16 *) data_buf = cpu_to_le16 (0);
312 case RH_GET_STATUS | RH_ENDPOINT:
313 *(__u16 *) data_buf = cpu_to_le16 (0);
316 case RH_GET_STATUS | RH_CLASS:
317 *(__u32 *) data_buf = cpu_to_le32 (0);
320 case RH_GET_STATUS | RH_OTHER | RH_CLASS:
321 *(__u32 *) data_buf =
322 cpu_to_le32 (getPortStatusAndChange (hci));
325 case RH_CLEAR_FEATURE | RH_ENDPOINT:
327 case (RH_ENDPOINT_STALL):
332 case RH_CLEAR_FEATURE | RH_CLASS:
334 case RH_C_HUB_LOCAL_POWER:
337 case (RH_C_HUB_OVER_CURRENT):
338 /* Over Current Not Implemented */
343 case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
345 case (RH_PORT_ENABLE):
346 clrPortStatus (hci, PORT_ENABLE_STAT);
349 case (RH_PORT_SUSPEND):
350 clrPortStatus (hci, PORT_SUSPEND_STAT);
353 case (RH_PORT_POWER):
354 clrPortStatus (hci, PORT_POWER_STAT);
357 case (RH_C_PORT_CONNECTION):
358 clrPortChange (hci, PORT_CONNECT_STAT);
361 case (RH_C_PORT_ENABLE):
362 clrPortChange (hci, PORT_ENABLE_STAT);
365 case (RH_C_PORT_SUSPEND):
366 clrPortChange (hci, PORT_SUSPEND_STAT);
369 case (RH_C_PORT_OVER_CURRENT):
370 clrPortChange (hci, PORT_OVER_CURRENT_STAT);
373 case (RH_C_PORT_RESET):
374 clrPortChange (hci, PORT_RESET_STAT);
379 case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
381 case (RH_PORT_SUSPEND):
382 setPortStatus (hci, PORT_SUSPEND_STAT);
385 case (RH_PORT_RESET):
386 setPortStatus (hci, PORT_RESET_STAT);
389 PORT_CONNECT_CHANGE | PORT_ENABLE_CHANGE
390 | PORT_SUSPEND_CHANGE |
391 PORT_OVER_CURRENT_CHANGE);
392 setPortChange (hci, PORT_RESET_CHANGE);
393 clrPortStatus (hci, PORT_RESET_STAT);
394 setPortStatus (hci, PORT_ENABLE_STAT);
398 case (RH_PORT_POWER):
399 setPortStatus (hci, PORT_POWER_STAT);
402 case (RH_PORT_ENABLE):
403 setPortStatus (hci, PORT_ENABLE_STAT);
409 hci->rh.devnum = wValue;
412 case RH_GET_DESCRIPTOR:
413 DBGVERBOSE ("rh_submit_urb: RH_GET_DESCRIPTOR, wValue = 0x%x\n", wValue);
414 switch ((wValue & 0xff00) >> 8) {
415 case (0x01): /* device descriptor */
416 len = min (leni, min ((__u16)sizeof (root_hub_dev_des), wLength));
417 data_buf = root_hub_dev_des;
420 case (0x02): /* configuration descriptor */
421 len = min (leni, min ((__u16)sizeof (root_hub_config_des), wLength));
422 data_buf = root_hub_config_des;
425 case (0x03): /* string descriptors */
426 len = usb_root_hub_string (wValue & 0xff, (int) (long) 0,
427 "SL811HS", data, wLength);
430 OK (min (leni, len));
434 status = SL11H_STATMASK_STALL;
438 case RH_GET_DESCRIPTOR | RH_CLASS:
439 len = min_t(unsigned int, leni,
440 min_t(unsigned int, sizeof (root_hub_hub_des), wLength));
441 memcpy (data_buf, root_hub_hub_des, len);
444 case RH_GET_CONFIGURATION:
445 *(__u8 *) data_buf = 0x01;
448 case RH_SET_CONFIGURATION:
452 DBGERR ("unsupported root hub command");
453 status = SL11H_STATMASK_STALL;
456 len = min (len, leni);
457 if (data != data_buf)
458 memcpy (data, data_buf, len);
459 urb->actual_length = len;
460 urb->status = cc_to_error (status);
471 /***************************************************************************
472 * Function Name : rh_unlink_urb
474 * This function unlinks the URB
476 * Input: urb = USB request block
479 **************************************************************************/
480 static int rh_unlink_urb (struct urb * urb)
482 hci_t *hci = urb->dev->bus->hcpriv;
484 DBGFUNC ("enter rh_unlink_urb\n");
485 if (hci->rh.urb == urb) {
487 del_timer (&hci->rh.rh_int_timer);
492 usb_put_dev (urb->dev);
494 Can not found this function, copy from old source and other source.
495 usbnet.c us this to. Its a macro to usb_dec_dev_use. (hne)
497 usb_dec_dev_use(urb->dev);
499 if (urb->transfer_flags & USB_ASYNC_UNLINK) {
500 urb->status = -ECONNRESET;
505 urb->status = -ENOENT;
510 /***************************************************************************
511 * Function Name : rh_connect_rh
513 * This function connect the virtual root hub to the USB stack
515 * Input: urb = USB request block
518 **************************************************************************/
519 static int rh_connect_rh (hci_t * hci)
521 struct usb_device *usb_dev;
524 usb_dev = usb_alloc_dev (NULL, hci->bus);
528 hci->bus->root_hub = usb_dev;
529 usb_connect (usb_dev);
530 if (usb_new_device (usb_dev) != 0) {
531 usb_free_dev (usb_dev);