1 //<MStar Software>
2 //******************************************************************************
3 // MStar Software
4 // Copyright (c) 2010 - 2012 MStar Semiconductor, Inc. All rights reserved.
5 // All software, firmware and related documentation herein ("MStar Software") are
6 // intellectual property of MStar Semiconductor, Inc. ("MStar") and protected by
7 // law, including, but not limited to, copyright law and international treaties.
8 // Any use, modification, reproduction, retransmission, or republication of all
9 // or part of MStar Software is expressly prohibited, unless prior written
10 // permission has been granted by MStar.
11 //
12 // By accessing, browsing and/or using MStar Software, you acknowledge that you
13 // have read, understood, and agree, to be bound by below terms ("Terms") and to
14 // comply with all applicable laws and regulations:
15 //
16 // 1. MStar shall retain any and all right, ownership and interest to MStar
17 // Software and any modification/derivatives thereof.
18 // No right, ownership, or interest to MStar Software and any
19 // modification/derivatives thereof is transferred to you under Terms.
20 //
21 // 2. You understand that MStar Software might include, incorporate or be
22 // supplied together with third party`s software and the use of MStar
23 // Software may require additional licenses from third parties.
24 // Therefore, you hereby agree it is your sole responsibility to separately
25 // obtain any and all third party right and license necessary for your use of
26 // such third party`s software.
27 //
28 // 3. MStar Software and any modification/derivatives thereof shall be deemed as
29 // MStar`s confidential information and you agree to keep MStar`s
30 // confidential information in strictest confidence and not disclose to any
31 // third party.
32 //
33 // 4. MStar Software is provided on an "AS IS" basis without warranties of any
34 // kind. Any warranties are hereby expressly disclaimed by MStar, including
35 // without limitation, any warranties of merchantability, non-infringement of
36 // intellectual property rights, fitness for a particular purpose, error free
37 // and in conformity with any international standard. You agree to waive any
38 // claim against MStar for any loss, damage, cost or expense that you may
39 // incur related to your use of MStar Software.
40 // In no event shall MStar be liable for any direct, indirect, incidental or
41 // consequential damages, including without limitation, lost of profit or
42 // revenues, lost or damage of data, and unauthorized system use.
43 // You agree that this Section 4 shall still apply without being affected
44 // even if MStar Software has been modified by MStar in accordance with your
45 // request or instruction for your use, except otherwise agreed by both
46 // parties in writing.
47 //
48 // 5. If requested, MStar may from time to time provide technical supports or
49 // services in relation with MStar Software to you for your use of
50 // MStar Software in conjunction with your or your customer`s product
51 // ("Services").
52 // You understand and agree that, except otherwise agreed by both parties in
53 // writing, Services are provided on an "AS IS" basis and the warranty
54 // disclaimer set forth in Section 4 above shall apply.
55 //
56 // 6. Nothing contained herein shall be construed as by implication, estoppels
57 // or otherwise:
58 // (a) conferring any license or right to use MStar name, trademark, service
59 // mark, symbol or any other identification;
60 // (b) obligating MStar or any of its affiliates to furnish any person,
61 // including without limitation, you and your customers, any assistance
62 // of any kind whatsoever, or any information; or
63 // (c) conferring any license or right under any intellectual property right.
64 //
65 // 7. These terms shall be governed by and construed in accordance with the laws
66 // of Taiwan, R.O.C., excluding its conflict of law rules.
67 // Any and all dispute arising out hereof or related hereto shall be finally
68 // settled by arbitration referred to the Chinese Arbitration Association,
69 // Taipei in accordance with the ROC Arbitration Law and the Arbitration
70 // Rules of the Association by three (3) arbitrators appointed in accordance
71 // with the said Rules.
72 // The place of arbitration shall be in Taipei, Taiwan and the language shall
73 // be English.
74 // The arbitration award shall be final and binding to both parties.
75 //
76 //******************************************************************************
77 //<MStar Software>
78
79 #include <MsCommon.h>
80 #include <cyg/hal/hal_if.h>
81
82 #include "include/drvConfig.h"
83
84 #ifdef CONFIG_DEBUG
85 #define DEBUG
86 #else
87 #undef DEBUG
88 #endif
89
90 #include "include/drvCompiler.h"
91 #include "include/drvErrno.h"
92 #include "include/drvPorts.h"
93 #include "include/drvPCIMEM.h"
94 #include "include/drvTimer.h"
95 #include "include/drvList.h"
96
97 #include "include/drvUSB.h"
98 #include "drvHCD.h"
99 #include "include/drvCPE_AMBA.h"
100 #include "drvEHCI.h"
101
102 #if 1
103
104 char usb_string_buf[64];
105
106 struct usb_api_data {
107 //wait_queue_head_t wqh;
108 int done;
109 };
110
usb_api_blocking_completion(struct urb * urb,struct pt_regs * regs)111 static void usb_api_blocking_completion(struct urb *urb, struct pt_regs *regs)
112 {
113 struct usb_api_data *awd = (struct usb_api_data *)urb->context;
114
115
116 if (urb->SetDMABuf != NULL)
117 {
118 //MsOS_FreeMemory(urb->SetDMABuf, gs32NonCachedPoolID_MIU0 );
119 Usb_FreeNonCachedMemory(urb->SetDMABuf);
120
121 urb->SetDMABuf = NULL;
122 }
123
124 if (urb->TxDMABuf != NULL)
125 {
126 if (usb_pipein(urb->pipe))
127 {
128 #ifdef DEBUG_PERFORMANCE
129 if (urb->transfer_buffer_length >= 512)
130 diag_printf("usb_api_blocking_completion: copy length: 0x%lx \n", urb->transfer_buffer_length);
131 #endif
132 memcpy(urb->transfer_buffer, urb->TxDMABuf, urb->transfer_buffer_length);
133 }
134 //MsOS_FreeMemory(urb->TxDMABuf,gs32NonCachedPoolID_MIU0 );
135 Usb_FreeNonCachedMemory(urb->TxDMABuf);
136
137 urb->TxDMABuf = NULL;
138 }
139
140 awd->done = 1;
141 wmb();
142
143 wake_up(&awd->wqh);
144 }
145
usb_start_wait_urb(struct urb * urb,int timeout,int * actual_length)146 static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
147 {
148 struct usb_api_data awd;
149 int status;
150 U32 d_cnt=0;
151
152 DECLARE_WAITQUEUE(wait, current);
153 init_waitqueue_head(&awd.wqh);
154
155 awd.done = 0;
156
157 set_current_state(TASK_UNINTERRUPTIBLE);
158 add_wait_queue(&awd.wqh, &wait);
159
160 urb->context = &awd;
161 status = usb_submit_urb(urb, GFP_ATOMIC);
162 if (status) {
163
164 usb_free_urb(urb);
165
166 set_current_state(TASK_RUNNING);
167 remove_wait_queue(&awd.wqh, &wait);
168 return status;
169 }
170
171 while ( timeout && (awd.done == 0) )
172 {
173 if ( d_cnt > (U32) timeout)
174 {
175 timeout =0;
176 break;
177 }
178 else
179 {
180 //mdelay(1);//tick base is 1 ms
181 HAL_DELAY_US(1000);
182 d_cnt+=1;
183 }
184 set_current_state(TASK_UNINTERRUPTIBLE);
185 rmb();
186 }
187 //dbg("Done(%d) or time-out,tick is %ld\n",awd.done,jiffies);
188
189 set_current_state(TASK_RUNNING);
190 remove_wait_queue(&awd.wqh, &wait);
191
192 if (!timeout && !awd.done) {
193 if (urb->status != -EINPROGRESS) { /* No callback?!! */
194 printk(KERN_ERR "usb: raced timeout, "
195 "pipe 0x%x status %d time left %d\n",
196 urb->pipe, urb->status, timeout);
197 status = urb->status;
198 } else {
199 struct usb_hcd * hcd = urb->dev->bus->hcpriv;
200 diag_printf("usb_control/bulk_msg: timeout... %d \n", urb->status);
201
202 diag_printf("<usb_start_wait_urb> set Bad Device...............................................\n");
203 hcd->isBadDevice = TRUE;
204 hcd->badDeviceCnt++;
205
206 if (usb_unlink_urb(urb) == -ETIMEDOUT)
207 {
208 diag_printf("timeout retry\n");
209 usb_unlink_urb(urb);
210 }
211 diag_printf("unllnk urb ok\n");
212 status = -ETIMEDOUT;
213 }
214 } else
215 status = urb->status;
216
217 if (actual_length)
218 *actual_length = urb->actual_length;
219
220 usb_free_urb(urb);
221 return status;
222 }
223
usb_internal_control_msg(struct usb_device * usb_dev,unsigned int pipe,struct usb_ctrlrequest * cmd,void * data,int len,int timeout)224 int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe,
225 struct usb_ctrlrequest *cmd, void *data, int len, int timeout)
226 {
227 struct urb *urb;
228 int retv;
229 int length;
230
231 urb = usb_alloc_urb(0, GFP_NOIO);
232 if (!urb)
233 return -ENOMEM;
234
235 usb_fill_control_urb(urb, usb_dev, pipe, (unsigned char*)cmd, data, len,
236 usb_api_blocking_completion, 0);
237 retv = usb_start_wait_urb(urb, timeout, &length);
238 if (retv < 0)
239 {
240 diag_printf("usb_start_wait_urb retv:%d \n",-retv);
241 return retv;
242 }
243 else
244 return length;
245 }
246
usb_control_msg(struct usb_device * dev,unsigned int pipe,unsigned char request,unsigned char requesttype,unsigned short value,unsigned short index,void * data,unsigned short size,int timeout)247 int usb_control_msg(struct usb_device *dev, unsigned int pipe, unsigned char request, unsigned char requesttype,
248 unsigned short value, unsigned short index, void *data, unsigned short size, int timeout)
249 {
250 struct usb_ctrlrequest *dr = (struct usb_ctrlrequest*) kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO);
251 int ret;
252 U32 addr_t;
253
254 if (!dr)
255 return -ENOMEM;
256
257 addr_t = (U32)dr;
258 dr->bRequestType= requesttype;
259 dr->bRequest = request;
260 dr->wValue = CPUToLE16(value);
261 dr->wIndex = CPUToLE16(index);
262 dr->wLength = CPUToLE16(size);
263
264 ret = usb_internal_control_msg(dev, pipe, dr, data, size, timeout);
265
266 kfree((void *)addr_t);
267
268 return ret;
269 }
270
271
usb_bulk_msg(struct usb_device * usb_dev,unsigned int pipe,void * data,int len,int * actual_length,int timeout)272 int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
273 void *data, int len, int *actual_length, int timeout)
274 {
275 struct urb *urb;
276
277 if (len < 0)
278 return -EINVAL;
279
280 urb=usb_alloc_urb(0, GFP_KERNEL);
281 if (!urb)
282 return -ENOMEM;
283
284 usb_fill_bulk_urb(urb, usb_dev, pipe, data, len,
285 usb_api_blocking_completion, 0);
286
287 return usb_start_wait_urb(urb,timeout,actual_length);
288 }
289
usb_get_descriptor(struct usb_device * dev,unsigned char type,unsigned char index,void * buf,int size)290 int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char index, void *buf, int size)
291 {
292 int ii = 5;
293 int relt;
294
295 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
296 memset(buf,0,size);
297
298 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
299 while (ii--) {
300 if ((relt = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
301 USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
302 (type << 8) + index, 0, buf, size,
303 HZ * USB_CTRL_GET_TIMEOUT)) > 0
304 || relt == -EPIPE)
305 break;
306 }
307 return relt;
308 }
309
usb_get_string(struct usb_device * dev,unsigned short langid,unsigned char index,void * buf,int size)310 int usb_get_string(struct usb_device *dev, unsigned short langid, unsigned char index, void *buf, int size)
311 {
312 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
313 return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
314 USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
315 (USB_DT_STRING << 8) + index, langid, buf, size,
316 HZ * USB_CTRL_GET_TIMEOUT);
317 }
318
usb_get_device_descriptor(struct usb_device * dev)319 int usb_get_device_descriptor(struct usb_device *dev)
320 {
321 int ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor,
322 sizeof(dev->descriptor));
323 if (ret >= 0) {
324 dev->descriptor.bcdUSB = LE16ToCPU(dev->descriptor.bcdUSB);
325 dev->descriptor.idVendor = LE16ToCPU(dev->descriptor.idVendor);
326 dev->descriptor.idProduct = LE16ToCPU(dev->descriptor.idProduct);
327 dev->descriptor.bcdDevice = LE16ToCPU(dev->descriptor.bcdDevice);
328 }
329 return ret;
330 }
331
usb_get_status(struct usb_device * dev,int type,int target,void * data)332 int usb_get_status(struct usb_device *dev, int type, int target, void *data)
333 {
334 return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
335 USB_REQ_GET_STATUS, USB_DIR_IN | type, 0, target, data, 2,
336 HZ * USB_CTRL_GET_TIMEOUT);
337 }
338
usb_clear_halt(struct usb_device * dev,int pipe)339 int usb_clear_halt(struct usb_device *dev, int pipe)
340 {
341 int result;
342 int endp = usb_pipeendpoint(pipe);
343
344 if (usb_pipein (pipe))
345 endp |= USB_DIR_IN;
346
347 result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
348 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, endp, NULL, 0,
349 HZ * USB_CTRL_SET_TIMEOUT);
350
351 if (result < 0)
352 return result;
353
354 usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0);
355 usb_endpoint_running(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
356
357 return 0;
358 }
359
usb_disable_endpoint(struct usb_device * dev,U32 epaddr)360 void usb_disable_endpoint(struct usb_device *dev, U32 epaddr)
361 {
362 if (dev && dev->bus && dev->bus->op && dev->bus->op->disable)
363 dev->bus->op->disable(dev, epaddr);
364 else {
365 U32 epnum = epaddr & USB_ENDPOINT_NUMBER_MASK;
366
367 if (usb_endpoint_out(epaddr)) {
368 usb_endpoint_halt(dev, epnum, 1);
369 dev->epmaxpacketout[epnum] = 0;
370 } else {
371 usb_endpoint_halt(dev, epnum, 0);
372 dev->epmaxpacketin[epnum] = 0;
373 }
374 }
375 }
376
usb_disable_interface(struct usb_device * dev,struct usb_interface * intf)377 void usb_disable_interface(struct usb_device *dev, struct usb_interface *intf)
378 {
379 struct usb_host_interface *hintf =
380 &intf->altsetting[intf->act_altsetting];
381 int i;
382
383 for (i = 0; i < hintf->desc.bNumEndpoints; ++i) {
384 usb_disable_endpoint(dev,
385 hintf->endpoint[i].desc.bEndpointAddress);
386 }
387 }
388
usb_disable_device(struct usb_device * dev,int skip_ep0)389 void usb_disable_device(struct usb_device *dev, int skip_ep0)
390 {
391 int i;
392
393 dbg("nuking URBs for device %s", dev->dev.bus_id);
394 for (i = skip_ep0; i < 16; ++i) {
395 usb_disable_endpoint(dev, i);
396 usb_disable_endpoint(dev, i + USB_DIR_IN);
397 }
398 }
399
400
usb_enable_endpoint(struct usb_device * dev,struct usb_endpoint_descriptor * epd)401 void usb_enable_endpoint(struct usb_device *dev,
402 struct usb_endpoint_descriptor *epd)
403 {
404 int maxsize = epd->wMaxPacketSize;
405 unsigned int eptaddr = epd->bEndpointAddress;
406 unsigned int eptnum = eptaddr & USB_ENDPOINT_NUMBER_MASK;
407 int is_control = ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
408 USB_ENDPOINT_XFER_CONTROL);
409
410 if (usb_endpoint_out(eptaddr) || is_control) {
411 usb_endpoint_running(dev, eptnum, 1);
412 usb_settoggle(dev, eptnum, 1, 0);
413 dev->epmaxpacketout[eptnum] = maxsize;
414 }
415 if (!usb_endpoint_out(eptaddr) || is_control) {
416 usb_endpoint_running(dev, eptnum, 0);
417 usb_settoggle(dev, eptnum, 0, 0);
418 dev->epmaxpacketin[eptnum] = maxsize;
419 }
420 }
421
usb_enable_interface(struct usb_device * dev,struct usb_interface * intf)422 void usb_enable_interface(struct usb_device *dev,
423 struct usb_interface *intf)
424 {
425 struct usb_host_interface *hintf =
426 &intf->altsetting[intf->act_altsetting];
427 int i;
428
429 for (i = 0; i < hintf->desc.bNumEndpoints; ++i)
430 usb_enable_endpoint(dev, &hintf->endpoint[i].desc);
431 }
432
usb_set_interface(struct usb_device * dev,int interface,int alternate)433 int usb_set_interface(struct usb_device *dev, int interface, int alternate)
434 {
435 struct usb_interface *iface;
436 int ret;
437 int manual = 0;
438
439 iface = usb_ifnum_to_if(dev, interface);
440 if (!iface) {
441 usb_warn("Invalid interface %d", interface);
442 return -EINVAL;
443 }
444
445 if (alternate < 0 || alternate >= iface->num_altsetting)
446 return -EINVAL;
447
448 ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
449 USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE,
450 iface->altsetting[alternate]
451 .desc.bAlternateSetting,
452 interface, NULL, 0, HZ * 5);
453
454 if (ret == -EPIPE && iface->num_altsetting == 1) {
455 dbg("manual set interface for iface %d, alt %d",
456 interface, alternate);
457 manual = 1;
458 } else if (ret < 0)
459 return ret;
460
461 usb_disable_interface(dev, iface);
462
463 iface->act_altsetting = alternate;
464
465 if (manual) {
466 struct usb_host_interface *iface_as =
467 &iface->altsetting[alternate];
468 int ii;
469
470 for (ii = 0; ii < iface_as->desc.bNumEndpoints; ii++) {
471 unsigned int epaddr =
472 iface_as->endpoint[ii].desc.bEndpointAddress;
473 unsigned int pipe =
474 __create_pipe(dev, USB_ENDPOINT_NUMBER_MASK & epaddr)
475 | (usb_endpoint_out(epaddr) ? USB_DIR_OUT : USB_DIR_IN);
476
477 usb_clear_halt(dev, pipe);
478 }
479 }
480
481 usb_enable_interface(dev, iface);
482
483 return 0;
484 }
485
usb_set_configuration(struct usb_device * dev,int configuration)486 int usb_set_configuration(struct usb_device *dev, int configuration)
487 {
488 int i, ret;
489 struct usb_host_config *cp = NULL;
490
491 for (i=0; i<dev->descriptor.bNumConfigurations; i++) {
492 if (dev->config[i].desc.bConfigurationValue == configuration) {
493 cp = &dev->config[i];
494 break;
495 }
496 }
497 if ((!cp && configuration != 0) || (cp && configuration == 0)) {
498 usb_warn("selecting invalid configuration %d", configuration);
499 return -EINVAL;
500 }
501
502 if (dev->state != USB_STATE_ADDRESS)
503 usb_disable_device (dev, 1); // Skip ep0
504 dev->toggle[0] = dev->toggle[1] = 0;
505 dev->halted[0] = dev->halted[1] = 0;
506 dev->state = USB_STATE_ADDRESS;
507
508 if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
509 USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
510 NULL, 0, HZ * USB_CTRL_SET_TIMEOUT)) < 0)
511 return ret;
512 if (configuration)
513 dev->state = USB_STATE_CONFIGURED;
514 dev->actconfig = cp;
515
516 for (i = 0; i < cp->desc.bNumInterfaces; ++i) {
517 struct usb_interface *intf = cp->interface[i];
518
519 intf->act_altsetting = 0;
520 usb_enable_interface(dev, intf);
521 }
522
523 // Add string
524 if (dev->descriptor.iProduct)
525 {
526 usb_string(dev, dev->descriptor.iProduct, usb_string_buf, 64);
527 dev->product = usb_string_buf;
528 }
529 else
530 dev->product = NULL;
531 diag_printf("USB device product string (index 2) = %s\n", dev->product);
532
533 return 0;
534 }
535
536
usb_string(struct usb_device * dev,int index,char * buf,size_t size)537 int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
538 {
539 #if 1
540
541 unsigned char *tbuf;
542 int err, len;
543 U32 u, idx;
544 if ( (int)size <= 0 || !buf || !index)
545 return -EINVAL;
546 buf[0] = 0;
547 tbuf = (unsigned char*) kmalloc(256, GFP_KERNEL);
548 if (!tbuf)
549 return -ENOMEM;
550
551 /* get langid for strings if it's not yet known */
552 if (!dev->have_langid) {
553 err = usb_get_string(dev, 0, 0, tbuf, 4);
554 if (err < 0) {
555 dbg("error getting string descriptor 0 (error=%d)", err);
556 goto errout;
557 } else if (err < 4 || tbuf[0] < 4) {
558 dbg("string descriptor 0 too short%s","");
559 err = -EINVAL;
560 goto errout;
561 } else {
562 dev->have_langid = -1;
563 dev->string_langid = tbuf[2] | (tbuf[3]<< 8);
564 /* always use the first langid listed */
565 dbg("USB device number %d default language ID 0x%x",
566 dev->devnum, dev->string_langid);
567 }
568 }
569
570 err = usb_get_string(dev, dev->string_langid, index, tbuf, 2);
571 if(err<2)
572 goto errout;
573 len=tbuf[0];
574
575 err = usb_get_string(dev, dev->string_langid, index, tbuf, len);
576 if (err < 0)
577 goto errout;
578
579 size--;
580 for (idx = 0, u = 2; u < (U32) err; u += 2) {
581 if (idx >= size)
582 break;
583 if (tbuf[u+1])
584 buf[idx++] = '?';
585 else
586 buf[idx++] = tbuf[u];
587 }
588 buf[idx] = 0;
589 err = idx;
590
591 errout:
592 kfree(tbuf);
593 return err;
594 #else
595 return 0;
596 #endif
597 }
598
599
usb_reset_configuration(struct usb_device * dev)600 int usb_reset_configuration(struct usb_device *dev)
601 {
602 int i, retval;
603 struct usb_host_config *config;
604
605 for (i = 1; i < 16; ++i) {
606 usb_disable_endpoint(dev, i);
607 usb_disable_endpoint(dev, i + USB_DIR_IN);
608 }
609
610 config = dev->actconfig;
611 retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
612 USB_REQ_SET_CONFIGURATION, 0,
613 config->desc.bConfigurationValue, 0,
614 NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
615 if (retval < 0)
616 return retval;
617
618 dev->toggle[0] = dev->toggle[1] = 0;
619 dev->halted[0] = dev->halted[1] = 0;
620
621 for (i = 0; i < config->desc.bNumInterfaces; i++) {
622 struct usb_interface *intf = config->interface[i];
623 intf->act_altsetting = 0;
624 usb_enable_interface(dev, intf);
625 }
626 return 0;
627 }
628 #endif //#ifdef
629
630