ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / drivers / usb / host / hc_sl811_rh.c
1
2 /*-------------------------------------------------------------------------*/
3 /*-------------------------------------------------------------------------*
4  * SL811HS virtual root hub
5  *  
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.
12  *
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.
17  *
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
21  *
22  *-------------------------------------------------------------------------*/
23
24 /* FIXME:  reuse the root hub framework in usbcore, shrinking this code.  */
25
26 #ifdef DEBUG
27 #undef DEBUG
28 #endif
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);
36
37 /*-------------------------------------------------------------------------*
38  * Virtual Root Hub 
39  *-------------------------------------------------------------------------*/
40
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 */
46         0x01,
47         0x09,                   /*  __u8  bDeviceClass; HUB_CLASSCODE */
48         0x00,                   /*  __u8  bDeviceSubClass; */
49         0x00,                   /*  __u8  bDeviceProtocol; */
50         0x08,                   /*  __u8  bMaxPacketSize0; 8 Bytes */
51         0x00,                   /*  __u16 idVendor; */
52         0x00,
53         0x00,                   /*  __u16 idProduct; */
54         0x00,
55         0x00,                   /*  __u16 bcdDevice; */
56         0x00,
57         0x00,                   /*  __u8  iManufacturer; */
58         0x02,                   /*  __u8  iProduct; */
59         0x01,                   /*  __u8  iSerialNumber; */
60         0x01                    /*  __u8  bNumConfigurations; */
61 };
62
63 /* Configuration descriptor */
64 static __u8 root_hub_config_des[] = {
65         0x09,                   /*  __u8  bLength; */
66         0x02,                   /*  __u8  bDescriptorType; Configuration */
67         0x19,                   /*  __u16 wTotalLength; */
68         0x00,
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, 
74                                    4..0: resvd */
75         0x00,                   /*  __u8  MaxPower; */
76
77         /* interface */
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; */
87
88         /* endpoint */
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 */
94         0x00,
95         0xff                    /*  __u8  ep_bInterval; 255 ms */
96 };
97
98 /* Hub class-specific descriptor is constructed dynamically */
99
100 /***************************************************************************
101  * Function Name : rh_send_irq
102  * 
103  * This function examine the port change in the virtual root hub.
104  * 
105  * Note: This function assumes only one port exist in the root hub.
106  *
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
110  *
111  * Return: length of data  
112  **************************************************************************/
113 static int rh_send_irq (hci_t * hci, void *rh_data, int rh_len)
114 {
115         int num_ports;
116         int i;
117         int ret;
118         int len;
119         __u8 data[8];
120
121         DBGFUNC ("enter rh_send_irq: \n");
122
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
125          */
126
127         num_ports = 1;
128
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
134          *
135          * Right now, It is assume the power is good and no changes 
136          */
137
138         *(__u8 *) data = 0;
139
140         ret = *(__u8 *) data;
141
142         /* Has the port status change within the root hub: It checks for
143          *      -- Port Connect Status change
144          *      -- Port Enable Change
145          */
146
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);
151
152                 /* After the port change is read, it should be reset so the next time 
153                  * is it doesn't trigger a change again */
154
155         }
156         len = i / 8 + 1;
157
158         if (ret > 0) {
159                 memcpy (rh_data, data, min (len, min (rh_len, (int)sizeof (data))));
160                 return len;
161         }
162         return 0;
163 }
164
165 /***************************************************************************
166  * Function Name : rh_int_timer_do
167  * 
168  * This function is called when the timer expires.  It gets the the port 
169  * change data and pass along to the upper protocol.
170  * 
171  * Note:  The virtual root hub interrupt pipe are polled by the timer
172  *        every "interval" ms
173  *
174  * Input:  ptr = ptr to the urb
175  *
176  * Return: none  
177  **************************************************************************/
178 static void rh_int_timer_do (unsigned long ptr)
179 {
180         int len;
181         struct urb *urb = (struct urb *) ptr;
182         hci_t *hci = urb->dev->bus->hcpriv;
183
184         DBGFUNC ("enter rh_int_timer_do\n");
185
186         if (hci->rh.send) {
187                 len = rh_send_irq (hci, urb->transfer_buffer,
188                                    urb->transfer_buffer_length);
189                 if (len > 0) {
190                         urb->actual_length = len;
191                         if (urb_debug == 2)
192                                 urb_print (urb, "RET-t(rh)",
193                                            usb_pipeout (urb->pipe));
194
195                         if (urb->complete) {
196                                 urb->complete (urb, NULL);
197                         }
198                 }
199         }
200
201         /* re-activate the timer */
202         rh_init_int_timer (urb);
203 }
204
205 /***************************************************************************
206  * Function Name : rh_init_int_timer
207  * 
208  * This function creates a timer that act as interrupt pipe in the
209  * virtual hub.   
210  * 
211  * Note:  The virtual root hub's interrupt pipe are polled by the timer
212  *        every "interval" ms
213  *
214  * Input: urb = USB request block 
215  *
216  * Return: 0  
217  **************************************************************************/
218 static int rh_init_int_timer (struct urb * urb)
219 {
220         hci_t *hci = urb->dev->bus->hcpriv;
221         hci->rh.interval = urb->interval;
222
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);
228
229         return 0;
230 }
231
232 /*-------------------------------------------------------------------------*/
233
234 /* for returning string descriptors in UTF-16LE */
235 static int ascii2utf (char *ascii, __u8 *utf, int utfmax)
236 {
237         int retval;
238
239         for (retval = 0; *ascii && utfmax > 1; utfmax -= 2, retval += 2) {
240                 *utf++ = *ascii++ & 0x7f;
241                 *utf++ = 0;
242         }
243         return retval;
244 }
245
246 static int root_hub_string (int id, int serial, char *type, __u8 *data, int len)
247 {
248         char buf [30];
249
250         // assert (len > (2 * (sizeof (buf) + 1)));
251         // assert (strlen (type) <= 8);
252
253         // language ids
254         if (id == 0) {
255                 *data++ = 4; *data++ = 3;       /* 4 bytes data */
256                 *data++ = 0; *data++ = 0;       /* some language id */
257                 return 4;
258
259         // serial number
260         } else if (id == 1) {
261                 sprintf (buf, "%x", serial);
262
263         // product description
264         } else if (id == 2) {
265                 sprintf (buf, "USB %s Root Hub", type);
266
267         // id 3 == vendor description
268
269         // unsupported IDs --> "stall"
270         } else
271             return 0;
272
273         data [0] = 2 + ascii2utf (buf, data + 2, len - 2);
274         data [1] = 3;
275         return data [0];
276 }
277
278 /*-------------------------------------------------------------------------*/
279
280 /* helper macro */
281 #define OK(x)                   len = (x); break
282
283 /***************************************************************************
284  * Function Name : rh_submit_urb
285  * 
286  * This function handles all USB request to the the virtual root hub
287  * 
288  * Input: urb = USB request block 
289  *
290  * Return: 0  
291  **************************************************************************/
292 static int rh_submit_urb (struct urb * urb)
293 {
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;
300         int len = 0;
301         int status = TD_CC_NOERROR;
302         __u32 datab[4];
303         __u8 *data_buf = (__u8 *) datab;
304
305         __u16 bmRType_bReq;
306         __u16 wValue;
307         __u16 wIndex;
308         __u16 wLength;
309
310         DBGFUNC ("enter rh_submit_urb\n");
311         if (usb_pipeint (pipe)) {
312                 hci->rh.urb = urb;
313                 hci->rh.send = 1;
314                 hci->rh.interval = urb->interval;
315                 rh_init_int_timer (urb);
316                 urb->status = cc_to_error (TD_CC_NOERROR);
317
318                 return 0;
319         }
320
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);
325
326         DBG ("rh_submit_urb, req = %d(%x) len=%d",
327              bmRType_bReq, bmRType_bReq, wLength);
328
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 
336                  */
337
338         case RH_GET_STATUS:
339                 *(__u16 *) data_buf = cpu_to_le16 (1);
340                 OK (2);
341
342         case RH_GET_STATUS | RH_INTERFACE:
343                 *(__u16 *) data_buf = cpu_to_le16 (0);
344                 OK (2);
345
346         case RH_GET_STATUS | RH_ENDPOINT:
347                 *(__u16 *) data_buf = cpu_to_le16 (0);
348                 OK (2);
349
350         case RH_GET_STATUS | RH_CLASS:
351                 *(__u32 *) data_buf = cpu_to_le32 (0);
352                 OK (4);
353
354         case RH_GET_STATUS | RH_OTHER | RH_CLASS:
355                 *(__u32 *) data_buf =
356                     cpu_to_le32 (getPortStatusAndChange (hci));
357                 OK (4);
358
359         case RH_CLEAR_FEATURE | RH_ENDPOINT:
360                 switch (wValue) {
361                 case (RH_ENDPOINT_STALL):
362                         OK (0);
363                 }
364                 break;
365
366         case RH_CLEAR_FEATURE | RH_CLASS:
367                 switch (wValue) {
368                 case RH_C_HUB_LOCAL_POWER:
369                         OK (0);
370
371                 case (RH_C_HUB_OVER_CURRENT):
372                         /* Over Current Not Implemented */
373                         OK (0);
374                 }
375                 break;
376
377         case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
378                 switch (wValue) {
379                 case (RH_PORT_ENABLE):
380                         clrPortStatus (hci, PORT_ENABLE_STAT);
381                         OK (0);
382
383                 case (RH_PORT_SUSPEND):
384                         clrPortStatus (hci, PORT_SUSPEND_STAT);
385                         OK (0);
386
387                 case (RH_PORT_POWER):
388                         clrPortStatus (hci, PORT_POWER_STAT);
389                         OK (0);
390
391                 case (RH_C_PORT_CONNECTION):
392                         clrPortChange (hci, PORT_CONNECT_STAT);
393                         OK (0);
394
395                 case (RH_C_PORT_ENABLE):
396                         clrPortChange (hci, PORT_ENABLE_STAT);
397                         OK (0);
398
399                 case (RH_C_PORT_SUSPEND):
400                         clrPortChange (hci, PORT_SUSPEND_STAT);
401                         OK (0);
402
403                 case (RH_C_PORT_OVER_CURRENT):
404                         clrPortChange (hci, PORT_OVER_CURRENT_STAT);
405                         OK (0);
406
407                 case (RH_C_PORT_RESET):
408                         clrPortChange (hci, PORT_RESET_STAT);
409                         OK (0);
410                 }
411                 break;
412
413         case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
414                 switch (wValue) {
415                 case (RH_PORT_SUSPEND):
416                         setPortStatus (hci, PORT_SUSPEND_STAT);
417                         OK (0);
418
419                 case (RH_PORT_RESET):
420                         setPortStatus (hci, PORT_RESET_STAT);
421                         // USBReset(hci);
422                         clrPortChange (hci,
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);
429
430                         OK (0);
431
432                 case (RH_PORT_POWER):
433                         setPortStatus (hci, PORT_POWER_STAT);
434                         OK (0);
435
436                 case (RH_PORT_ENABLE):
437                         setPortStatus (hci, PORT_ENABLE_STAT);
438                         OK (0);
439                 }
440                 break;
441
442         case RH_SET_ADDRESS:
443                 hci->rh.devnum = wValue;
444                 OK (0);
445
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;
452                         OK (len);
453
454                 case (0x02):    /* configuration descriptor */
455                         len = min (leni, min ((__u16)sizeof (root_hub_config_des), wLength));
456                         data_buf = root_hub_config_des;
457                         OK (len);
458
459                 case (0x03):    /* string descriptors */
460                         len = root_hub_string (wValue & 0xff, (int) (long) 0,
461                                                    "SL811HS", data, wLength);
462                         if (len > 0) {
463                                 data_buf = data;
464                                 OK (min (leni, len));
465                         }
466
467                 default:
468                         status = SL11H_STATMASK_STALL;
469                 }
470                 break;
471
472         case RH_GET_DESCRIPTOR | RH_CLASS:
473                 data_buf[0] = 9;        // min length;
474                 data_buf[1] = 0x29;
475                 data_buf[2] = 1;        // # of downstream port
476                 data_buf[3] = 0;
477                 datab[1] = 0;
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) {
481                         data_buf[8] = 0xff;
482                 } else {
483                 }
484
485                 len = min (leni, min ((__u16)data_buf[0], wLength));
486                 OK (len);
487
488         case RH_GET_CONFIGURATION:
489                 *(__u8 *) data_buf = 0x01;
490                 OK (1);
491
492         case RH_SET_CONFIGURATION:
493                 OK (0);
494
495         default:
496                 DBGERR ("unsupported root hub command");
497                 status = SL11H_STATMASK_STALL;
498         }
499
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);
505
506         urb->hcpriv = NULL;
507         urb->dev = NULL;
508         if (urb->complete) {
509                 urb->complete (urb, NULL);
510         }
511
512         return 0;
513 }
514
515 /***************************************************************************
516  * Function Name : rh_unlink_urb
517  * 
518  * This function unlinks the URB 
519  * 
520  * Input: urb = USB request block 
521  *
522  * Return: 0  
523  **************************************************************************/
524 static int rh_unlink_urb (struct urb * urb)
525 {
526         hci_t *hci = urb->dev->bus->hcpriv;
527
528         DBGFUNC ("enter rh_unlink_urb\n");
529         if (hci->rh.urb == urb) {
530                 hci->rh.send = 0;
531                 del_timer (&hci->rh.rh_int_timer);
532                 hci->rh.urb = NULL;
533
534                 urb->hcpriv = NULL;
535                 usb_put_dev (urb->dev);
536                 urb->dev = NULL;
537                 if (urb->transfer_flags & URB_ASYNC_UNLINK) {
538                         urb->status = -ECONNRESET;
539                         if (urb->complete) {
540                                 urb->complete (urb, NULL);
541                         }
542                 } else
543                         urb->status = -ENOENT;
544         }
545         return 0;
546 }
547
548 /***************************************************************************
549  * Function Name : rh_connect_rh
550  * 
551  * This function connect the virtual root hub to the USB stack 
552  * 
553  * Input: urb = USB request block 
554  *
555  * Return: 0  
556  **************************************************************************/
557 static int rh_connect_rh (hci_t * hci)
558 {
559         struct usb_device *usb_dev;
560
561         hci->rh.devnum = 0;
562         usb_dev = usb_alloc_dev (NULL, hci->bus, 0);
563         if (!usb_dev)
564                 return -ENOMEM;
565
566         hci->bus->root_hub = usb_dev;
567         usb_dev->devnum = 1;
568         usb_dev->bus->devnum_next = usb_dev->devnum + 1;
569         set_bit (usb_dev->devnum, usb_dev->bus->devmap.devicemap);
570
571         if (usb_new_device (usb_dev) != 0) {
572                 usb_put_dev (usb_dev);
573                 return -ENODEV;
574         }
575
576         return 0;
577 }