00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #ifndef DWC_HOST_ONLY
00034
00056 #include "dwc_otg_os_dep.h"
00057 #include "dwc_otg_pcd_if.h"
00058 #include "dwc_otg_pcd.h"
00059 #include "dwc_otg_driver.h"
00060 #include "dwc_otg_dbg.h"
00061
00062 static struct gadget_wrapper {
00063 dwc_otg_pcd_t *pcd;
00064
00065 struct usb_gadget gadget;
00066 struct usb_gadget_driver *driver;
00067
00068 struct usb_ep ep0;
00069 struct usb_ep in_ep[16];
00070 struct usb_ep out_ep[16];
00071
00072 } *gadget_wrapper;
00073
00074
00075 extern void dump_msg(const u8 * buf, unsigned int length);
00080 static struct dwc_otg_pcd_ep *ep_from_handle(dwc_otg_pcd_t * pcd, void *handle)
00081 {
00082 int i;
00083 if (pcd->ep0.priv == handle) {
00084 return &pcd->ep0;
00085 }
00086
00087 for (i = 0; i < MAX_EPS_CHANNELS - 1; i++) {
00088 if (pcd->in_ep[i].priv == handle)
00089 return &pcd->in_ep[i];
00090 if (pcd->out_ep[i].priv == handle)
00091 return &pcd->out_ep[i];
00092 }
00093
00094 return NULL;
00095 }
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00121 static int ep_enable(struct usb_ep *usb_ep,
00122 const struct usb_endpoint_descriptor *ep_desc)
00123 {
00124 int retval;
00125
00126 DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, usb_ep, ep_desc);
00127
00128 if (!usb_ep || !ep_desc || ep_desc->bDescriptorType != USB_DT_ENDPOINT) {
00129 DWC_WARN("%s, bad ep or descriptor\n", __func__);
00130 return -EINVAL;
00131 }
00132 if (usb_ep == &gadget_wrapper->ep0) {
00133 DWC_WARN("%s, bad ep(0)\n", __func__);
00134 return -EINVAL;
00135 }
00136
00137
00138 if (!ep_desc->wMaxPacketSize) {
00139 DWC_WARN("%s, bad %s maxpacket\n", __func__, usb_ep->name);
00140 return -ERANGE;
00141 }
00142
00143 if (!gadget_wrapper->driver ||
00144 gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {
00145 DWC_WARN("%s, bogus device state\n", __func__);
00146 return -ESHUTDOWN;
00147 }
00148
00149
00150 #if 0
00151 nat = (uint32_t) ep_desc->wMaxPacketSize;
00152 printk(KERN_ALERT "%s: nat (before) =%d\n", __func__, nat);
00153 nat = (nat >> 11) & 0x03;
00154 printk(KERN_ALERT "%s: nat (after) =%d\n", __func__, nat);
00155 #endif
00156 retval = dwc_otg_pcd_ep_enable(gadget_wrapper->pcd,
00157 (const uint8_t *)ep_desc,
00158 (void *)usb_ep);
00159 if (retval) {
00160 DWC_WARN("dwc_otg_pcd_ep_enable failed\n");
00161 return -EINVAL;
00162 }
00163
00164 usb_ep->maxpacket = le16_to_cpu(ep_desc->wMaxPacketSize);
00165
00166 return 0;
00167 }
00168
00177 static int ep_disable(struct usb_ep *usb_ep)
00178 {
00179 int retval;
00180
00181 DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, usb_ep);
00182 if (!usb_ep) {
00183 DWC_DEBUGPL(DBG_PCD, "%s, %s not enabled\n", __func__,
00184 usb_ep ? usb_ep->name : NULL);
00185 return -EINVAL;
00186 }
00187
00188 retval = dwc_otg_pcd_ep_disable(gadget_wrapper->pcd, usb_ep);
00189 if (retval) {
00190 retval = -EINVAL;
00191 }
00192
00193 return retval;
00194 }
00195
00203 static struct usb_request *dwc_otg_pcd_alloc_request(struct usb_ep *ep,
00204 gfp_t gfp_flags)
00205 {
00206 struct usb_request *usb_req;
00207
00208 DWC_DEBUGPL(DBG_PCDV, "%s(%p,%d)\n", __func__, ep, gfp_flags);
00209 if (0 == ep) {
00210 DWC_WARN("%s() %s\n", __func__, "Invalid EP!\n");
00211 return 0;
00212 }
00213 usb_req = kmalloc(sizeof(*usb_req), gfp_flags);
00214 if (0 == usb_req) {
00215 DWC_WARN("%s() %s\n", __func__, "request allocation failed!\n");
00216 return 0;
00217 }
00218 memset(usb_req, 0, sizeof(*usb_req));
00219 usb_req->dma = DWC_DMA_ADDR_INVALID;
00220
00221 return usb_req;
00222 }
00223
00230 static void dwc_otg_pcd_free_request(struct usb_ep *ep, struct usb_request *req)
00231 {
00232 DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, ep, req);
00233
00234 if (0 == ep || 0 == req) {
00235 DWC_WARN("%s() %s\n", __func__,
00236 "Invalid ep or req argument!\n");
00237 return;
00238 }
00239
00240 kfree(req);
00241 }
00242
00243 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
00244
00254 static void *dwc_otg_pcd_alloc_buffer(struct usb_ep *usb_ep, unsigned bytes,
00255 dma_addr_t * dma, gfp_t gfp_flags)
00256 {
00257 void *buf;
00258 dwc_otg_pcd_t *pcd = 0;
00259
00260 pcd = gadget_wrapper->pcd;
00261
00262 DWC_DEBUGPL(DBG_PCDV, "%s(%p,%d,%p,%0x)\n", __func__, usb_ep, bytes,
00263 dma, gfp_flags);
00264
00265
00266 if ((bytes & 0x3UL) != 0) {
00267 DWC_WARN("%s() Buffer size is not a multiple of"
00268 "DWORD size (%d)", __func__, bytes);
00269 }
00270
00271 buf = dma_alloc_coherent(NULL, bytes, dma, gfp_flags);
00272
00273
00274 if (((int)buf & 0x3UL) != 0) {
00275 DWC_WARN("%s() Buffer is not DWORD aligned (%p)",
00276 __func__, buf);
00277 }
00278
00279 return buf;
00280 }
00281
00290 static void dwc_otg_pcd_free_buffer(struct usb_ep *usb_ep, void *buf,
00291 dma_addr_t dma, unsigned bytes)
00292 {
00293 dwc_otg_pcd_t *pcd = 0;
00294
00295 pcd = gadget_wrapper->pcd;
00296
00297 DWC_DEBUGPL(DBG_PCDV, "%s(%p,%0x,%d)\n", __func__, buf, dma, bytes);
00298
00299 dma_free_coherent(NULL, bytes, buf, dma);
00300 }
00301 #endif
00302
00317 static int ep_queue(struct usb_ep *usb_ep, struct usb_request *usb_req,
00318 gfp_t gfp_flags)
00319 {
00320 dwc_otg_pcd_t *pcd;
00321 struct dwc_otg_pcd_ep *ep = NULL;
00322 int retval = 0, is_isoc_ep = 0;
00323 dma_addr_t dma_addr = DWC_DMA_ADDR_INVALID;
00324
00325 DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p,%d)\n",
00326 __func__, usb_ep, usb_req, gfp_flags);
00327
00328 if (!usb_req || !usb_req->complete || !usb_req->buf) {
00329 DWC_WARN("bad params\n");
00330 return -EINVAL;
00331 }
00332
00333 if (!usb_ep) {
00334 DWC_WARN("bad ep\n");
00335 return -EINVAL;
00336 }
00337
00338 pcd = gadget_wrapper->pcd;
00339 if (!gadget_wrapper->driver ||
00340 gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {
00341 DWC_DEBUGPL(DBG_PCDV, "gadget.speed=%d\n",
00342 gadget_wrapper->gadget.speed);
00343 DWC_WARN("bogus device state\n");
00344 return -ESHUTDOWN;
00345 }
00346
00347 DWC_DEBUGPL(DBG_PCD, "%s queue req %p, len %d buf %p\n",
00348 usb_ep->name, usb_req, usb_req->length, usb_req->buf);
00349
00350 usb_req->status = -EINPROGRESS;
00351 usb_req->actual = 0;
00352
00353 ep = ep_from_handle(pcd, usb_ep);
00354 if (ep == NULL)
00355 is_isoc_ep = 0;
00356 else
00357 is_isoc_ep = (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) ? 1 : 0;
00358 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
00359 dma_addr = usb_req->dma;
00360 #else
00361 if (GET_CORE_IF(pcd)->dma_enable) {
00362 struct pci_dev *dev = gadget_wrapper->pcd->otg_dev->os_dep.pcidev;
00363 if (usb_req->length != 0 && usb_req->dma == DWC_DMA_ADDR_INVALID) {
00364 dma_addr = pci_map_single(dev, usb_req->buf, usb_req->length,
00365 ep->dwc_ep.is_in ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
00366 }
00367 }
00368 #endif
00369
00370 #ifdef DWC_UTE_PER_IO
00371 if (is_isoc_ep == 1) {
00372 retval = dwc_otg_pcd_xiso_ep_queue(pcd, usb_ep, usb_req->buf, dma_addr,
00373 usb_req->length, usb_req->zero, usb_req,
00374 gfp_flags == GFP_ATOMIC ? 1 : 0, &usb_req->ext_req);
00375 if (retval)
00376 return -EINVAL;
00377
00378 return 0;
00379 }
00380 #endif
00381 retval = dwc_otg_pcd_ep_queue(pcd, usb_ep, usb_req->buf, dma_addr,
00382 usb_req->length, usb_req->zero, usb_req,
00383 gfp_flags == GFP_ATOMIC ? 1 : 0);
00384 if (retval) {
00385 return -EINVAL;
00386 }
00387
00388 return 0;
00389 }
00390
00394 static int ep_dequeue(struct usb_ep *usb_ep, struct usb_request *usb_req)
00395 {
00396 DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, usb_ep, usb_req);
00397
00398 if (!usb_ep || !usb_req) {
00399 DWC_WARN("bad argument\n");
00400 return -EINVAL;
00401 }
00402 if (!gadget_wrapper->driver ||
00403 gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {
00404 DWC_WARN("bogus device state\n");
00405 return -ESHUTDOWN;
00406 }
00407 if (dwc_otg_pcd_ep_dequeue(gadget_wrapper->pcd, usb_ep, usb_req)) {
00408 return -EINVAL;
00409 }
00410
00411 return 0;
00412 }
00413
00430 static int ep_halt(struct usb_ep *usb_ep, int value)
00431 {
00432 int retval = 0;
00433
00434 DWC_DEBUGPL(DBG_PCD, "HALT %s %d\n", usb_ep->name, value);
00435
00436 if (!usb_ep) {
00437 DWC_WARN("bad ep\n");
00438 return -EINVAL;
00439 }
00440
00441 retval = dwc_otg_pcd_ep_halt(gadget_wrapper->pcd, usb_ep, value);
00442 if (retval == -DWC_E_AGAIN) {
00443 return -EAGAIN;
00444 } else if (retval) {
00445 retval = -EINVAL;
00446 }
00447
00448 return retval;
00449 }
00450
00451 #ifdef DWC_EN_ISOC
00452
00461 static int iso_ep_start(struct usb_ep *usb_ep, struct usb_iso_request *req,
00462 gfp_t gfp_flags)
00463 {
00464 int retval = 0;
00465
00466 if (!req || !req->process_buffer || !req->buf0 || !req->buf1) {
00467 DWC_WARN("bad params\n");
00468 return -EINVAL;
00469 }
00470
00471 if (!usb_ep) {
00472 DWC_PRINTF("bad params\n");
00473 return -EINVAL;
00474 }
00475
00476 req->status = -EINPROGRESS;
00477
00478 retval =
00479 dwc_otg_pcd_iso_ep_start(gadget_wrapper->pcd, usb_ep, req->buf0,
00480 req->buf1, req->dma0, req->dma1,
00481 req->sync_frame, req->data_pattern_frame,
00482 req->data_per_frame,
00483 req->flags & USB_REQ_ISO_ASAP ? -1 : req->
00484 start_frame, req->buf_proc_intrvl, req,
00485 gfp_flags == GFP_ATOMIC ? 1 : 0);
00486
00487 if (retval) {
00488 return -EINVAL;
00489 }
00490
00491 return retval;
00492 }
00493
00497 static int iso_ep_stop(struct usb_ep *usb_ep, struct usb_iso_request *req)
00498 {
00499 int retval = 0;
00500 if (!usb_ep) {
00501 DWC_WARN("bad ep\n");
00502 }
00503
00504 if (!gadget_wrapper->driver ||
00505 gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {
00506 DWC_DEBUGPL(DBG_PCDV, "gadget.speed=%d\n",
00507 gadget_wrapper->gadget.speed);
00508 DWC_WARN("bogus device state\n");
00509 }
00510
00511 dwc_otg_pcd_iso_ep_stop(gadget_wrapper->pcd, usb_ep, req);
00512 if (retval) {
00513 retval = -EINVAL;
00514 }
00515
00516 return retval;
00517 }
00518
00519 static struct usb_iso_request *alloc_iso_request(struct usb_ep *ep,
00520 int packets, gfp_t gfp_flags)
00521 {
00522 struct usb_iso_request *pReq = NULL;
00523 uint32_t req_size;
00524
00525 req_size = sizeof(struct usb_iso_request);
00526 req_size +=
00527 (2 * packets * (sizeof(struct usb_gadget_iso_packet_descriptor)));
00528
00529 pReq = kmalloc(req_size, gfp_flags);
00530 if (!pReq) {
00531 DWC_WARN("Can't allocate Iso Request\n");
00532 return 0;
00533 }
00534 pReq->iso_packet_desc0 = (void *)(pReq + 1);
00535
00536 pReq->iso_packet_desc1 = pReq->iso_packet_desc0 + packets;
00537
00538 return pReq;
00539 }
00540
00541 static void free_iso_request(struct usb_ep *ep, struct usb_iso_request *req)
00542 {
00543 kfree(req);
00544 }
00545
00546 static struct usb_isoc_ep_ops dwc_otg_pcd_ep_ops = {
00547 .ep_ops = {
00548 .enable = ep_enable,
00549 .disable = ep_disable,
00550
00551 .alloc_request = dwc_otg_pcd_alloc_request,
00552 .free_request = dwc_otg_pcd_free_request,
00553
00554 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
00555 .alloc_buffer = dwc_otg_pcd_alloc_buffer,
00556 .free_buffer = dwc_otg_pcd_free_buffer,
00557 #endif
00558
00559 .queue = ep_queue,
00560 .dequeue = ep_dequeue,
00561
00562 .set_halt = ep_halt,
00563 .fifo_status = 0,
00564 .fifo_flush = 0,
00565 },
00566 .iso_ep_start = iso_ep_start,
00567 .iso_ep_stop = iso_ep_stop,
00568 .alloc_iso_request = alloc_iso_request,
00569 .free_iso_request = free_iso_request,
00570 };
00571
00572 #else
00573
00574 static struct usb_ep_ops dwc_otg_pcd_ep_ops = {
00575 .enable = ep_enable,
00576 .disable = ep_disable,
00577
00578 .alloc_request = dwc_otg_pcd_alloc_request,
00579 .free_request = dwc_otg_pcd_free_request,
00580
00581 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
00582 .alloc_buffer = dwc_otg_pcd_alloc_buffer,
00583 .free_buffer = dwc_otg_pcd_free_buffer,
00584 #endif
00585
00586 .queue = ep_queue,
00587 .dequeue = ep_dequeue,
00588
00589 .set_halt = ep_halt,
00590 .fifo_status = 0,
00591 .fifo_flush = 0,
00592
00593 };
00594
00595 #endif
00596
00615 static int get_frame_number(struct usb_gadget *gadget)
00616 {
00617 struct gadget_wrapper *d;
00618
00619 DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, gadget);
00620
00621 if (gadget == 0) {
00622 return -ENODEV;
00623 }
00624
00625 d = container_of(gadget, struct gadget_wrapper, gadget);
00626 return dwc_otg_pcd_get_frame_number(d->pcd);
00627 }
00628
00629 #ifdef CONFIG_USB_DWC_OTG_LPM
00630 static int test_lpm_enabled(struct usb_gadget *gadget)
00631 {
00632 struct gadget_wrapper *d;
00633
00634 d = container_of(gadget, struct gadget_wrapper, gadget);
00635
00636 return dwc_otg_pcd_is_lpm_enabled(d->pcd);
00637 }
00638 #endif
00639
00646 static int wakeup(struct usb_gadget *gadget)
00647 {
00648 struct gadget_wrapper *d;
00649
00650 DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, gadget);
00651
00652 if (gadget == 0) {
00653 return -ENODEV;
00654 } else {
00655 d = container_of(gadget, struct gadget_wrapper, gadget);
00656 }
00657 dwc_otg_pcd_wakeup(d->pcd);
00658 return 0;
00659 }
00660
00661 static const struct usb_gadget_ops dwc_otg_pcd_ops = {
00662 .get_frame = get_frame_number,
00663 .wakeup = wakeup,
00664 #ifdef CONFIG_USB_DWC_OTG_LPM
00665 .lpm_support = test_lpm_enabled,
00666 #endif
00667
00668 };
00669
00670 static int _setup(dwc_otg_pcd_t * pcd, uint8_t * bytes)
00671 {
00672 int retval = -DWC_E_NOT_SUPPORTED;
00673 if (gadget_wrapper->driver && gadget_wrapper->driver->setup) {
00674 retval = gadget_wrapper->driver->setup(&gadget_wrapper->gadget,
00675 (struct usb_ctrlrequest
00676 *)bytes);
00677 }
00678
00679 if (retval == -ENOTSUPP) {
00680 retval = -DWC_E_NOT_SUPPORTED;
00681 } else if (retval < 0) {
00682 retval = -DWC_E_INVALID;
00683 }
00684
00685 return retval;
00686 }
00687
00688 #ifdef DWC_EN_ISOC
00689 static int _isoc_complete(dwc_otg_pcd_t * pcd, void *ep_handle,
00690 void *req_handle, int proc_buf_num)
00691 {
00692 int i, packet_count;
00693 struct usb_gadget_iso_packet_descriptor *iso_packet = 0;
00694 struct usb_iso_request *iso_req = req_handle;
00695
00696 if (proc_buf_num) {
00697 iso_packet = iso_req->iso_packet_desc1;
00698 } else {
00699 iso_packet = iso_req->iso_packet_desc0;
00700 }
00701 packet_count =
00702 dwc_otg_pcd_get_iso_packet_count(pcd, ep_handle, req_handle);
00703 for (i = 0; i < packet_count; ++i) {
00704 int status;
00705 int actual;
00706 int offset;
00707 dwc_otg_pcd_get_iso_packet_params(pcd, ep_handle, req_handle,
00708 i, &status, &actual, &offset);
00709 switch (status) {
00710 case -DWC_E_NO_DATA:
00711 status = -ENODATA;
00712 break;
00713 default:
00714 if (status) {
00715 DWC_PRINTF("unknown status in isoc packet\n");
00716 }
00717
00718 }
00719 iso_packet[i].status = status;
00720 iso_packet[i].offset = offset;
00721 iso_packet[i].actual_length = actual;
00722 }
00723
00724 iso_req->status = 0;
00725 iso_req->process_buffer(ep_handle, iso_req);
00726
00727 return 0;
00728 }
00729 #endif
00730
00731 #ifdef DWC_UTE_PER_IO
00732
00744 static int _xisoc_complete(dwc_otg_pcd_t * pcd, void *ep_handle,
00745 void *req_handle, int32_t status, void *ereq_port)
00746 {
00747 struct dwc_ute_iso_req_ext *ereqorg = NULL;
00748 struct dwc_iso_xreq_port *ereqport = NULL;
00749 struct dwc_ute_iso_packet_descriptor *desc_org = NULL;
00750 int i;
00751 struct usb_request *req;
00752
00753
00754
00755 req = (struct usb_request *)req_handle;
00756 ereqorg = &req->ext_req;
00757 ereqport = (struct dwc_iso_xreq_port *)ereq_port;
00758 desc_org = ereqorg->per_io_frame_descs;
00759
00760 if (req && req->complete) {
00761
00762 for (i = 0; i < ereqport->pio_pkt_count; i++) {
00763 desc_org[i].actual_length =
00764 ereqport->per_io_frame_descs[i].actual_length;
00765 desc_org[i].status =
00766 ereqport->per_io_frame_descs[i].status;
00767 }
00768
00769 switch (status) {
00770 case -DWC_E_SHUTDOWN:
00771 req->status = -ESHUTDOWN;
00772 break;
00773 case -DWC_E_RESTART:
00774 req->status = -ECONNRESET;
00775 break;
00776 case -DWC_E_INVALID:
00777 req->status = -EINVAL;
00778 break;
00779 case -DWC_E_TIMEOUT:
00780 req->status = -ETIMEDOUT;
00781 break;
00782 default:
00783 req->status = status;
00784 }
00785
00786
00787 req->complete(ep_handle, req);
00788 }
00789
00790 return 0;
00791 }
00792 #endif
00793 static int _complete(dwc_otg_pcd_t * pcd, void *ep_handle,
00794 void *req_handle, int32_t status, uint32_t actual)
00795 {
00796 struct usb_request *req = (struct usb_request *)req_handle;
00797 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,27)
00798 struct dwc_otg_pcd_ep *ep = NULL;
00799 #endif
00800 #ifdef PCI_INTERFACE
00801 struct pci_dev *dev = NULL;
00802 #endif
00803
00804 if (req && req->complete) {
00805 switch (status) {
00806 case -DWC_E_SHUTDOWN:
00807 req->status = -ESHUTDOWN;
00808 break;
00809 case -DWC_E_RESTART:
00810 req->status = -ECONNRESET;
00811 break;
00812 case -DWC_E_INVALID:
00813 req->status = -EINVAL;
00814 break;
00815 case -DWC_E_TIMEOUT:
00816 req->status = -ETIMEDOUT;
00817 break;
00818 default:
00819 req->status = status;
00820
00821 }
00822
00823 req->actual = actual;
00824 DWC_SPINUNLOCK(pcd->lock);
00825 req->complete(ep_handle, req);
00826 DWC_SPINLOCK(pcd->lock);
00827 }
00828 #ifdef PCI_INTERFACE
00829 dev = gadget_wrapper->pcd->otg_dev->os_dep.pcidev;
00830 ep = ep_from_handle(pcd, ep_handle);
00831 if (GET_CORE_IF(pcd)->dma_enable) {
00832 if (req->length != 0)
00833 pci_unmap_single(dev, req->dma, req->length,
00834 ep->dwc_ep.
00835 is_in ? PCI_DMA_TODEVICE :
00836 PCI_DMA_FROMDEVICE);
00837 }
00838 #endif
00839
00840 return 0;
00841 }
00842
00843 static int _connect(dwc_otg_pcd_t * pcd, int speed)
00844 {
00845 gadget_wrapper->gadget.speed = speed;
00846 return 0;
00847 }
00848
00849 static int _disconnect(dwc_otg_pcd_t * pcd)
00850 {
00851 if (gadget_wrapper->driver && gadget_wrapper->driver->disconnect) {
00852 gadget_wrapper->driver->disconnect(&gadget_wrapper->gadget);
00853 }
00854 return 0;
00855 }
00856
00857 static int _resume(dwc_otg_pcd_t * pcd)
00858 {
00859 if (gadget_wrapper->driver && gadget_wrapper->driver->resume) {
00860 gadget_wrapper->driver->resume(&gadget_wrapper->gadget);
00861 }
00862
00863 return 0;
00864 }
00865
00866 static int _suspend(dwc_otg_pcd_t * pcd)
00867 {
00868 if (gadget_wrapper->driver && gadget_wrapper->driver->suspend) {
00869 gadget_wrapper->driver->suspend(&gadget_wrapper->gadget);
00870 }
00871 return 0;
00872 }
00873
00877 static int _hnp_changed(dwc_otg_pcd_t * pcd)
00878 {
00879
00880 if (!gadget_wrapper->gadget.is_otg)
00881 return 0;
00882
00883 gadget_wrapper->gadget.b_hnp_enable = get_b_hnp_enable(pcd);
00884 gadget_wrapper->gadget.a_hnp_support = get_a_hnp_support(pcd);
00885 gadget_wrapper->gadget.a_alt_hnp_support = get_a_alt_hnp_support(pcd);
00886 return 0;
00887 }
00888
00889 static int _reset(dwc_otg_pcd_t * pcd)
00890 {
00891 return 0;
00892 }
00893
00894 #ifdef DWC_UTE_CFI
00895 static int _cfi_setup(dwc_otg_pcd_t * pcd, void *cfi_req)
00896 {
00897 int retval = -DWC_E_INVALID;
00898 if (gadget_wrapper->driver->cfi_feature_setup) {
00899 retval =
00900 gadget_wrapper->driver->
00901 cfi_feature_setup(&gadget_wrapper->gadget,
00902 (struct cfi_usb_ctrlrequest *)cfi_req);
00903 }
00904
00905 return retval;
00906 }
00907 #endif
00908
00909 static const struct dwc_otg_pcd_function_ops fops = {
00910 .complete = _complete,
00911 #ifdef DWC_EN_ISOC
00912 .isoc_complete = _isoc_complete,
00913 #endif
00914 .setup = _setup,
00915 .disconnect = _disconnect,
00916 .connect = _connect,
00917 .resume = _resume,
00918 .suspend = _suspend,
00919 .hnp_changed = _hnp_changed,
00920 .reset = _reset,
00921 #ifdef DWC_UTE_CFI
00922 .cfi_setup = _cfi_setup,
00923 #endif
00924 #ifdef DWC_UTE_PER_IO
00925 .xisoc_complete = _xisoc_complete,
00926 #endif
00927 };
00928
00932 static irqreturn_t dwc_otg_pcd_irq(int irq, void *dev)
00933 {
00934 dwc_otg_pcd_t *pcd = dev;
00935 int32_t retval = IRQ_NONE;
00936
00937 retval = dwc_otg_pcd_handle_intr(pcd);
00938 if (retval != 0) {
00939 S3C2410X_CLEAR_EINTPEND();
00940 }
00941 return IRQ_RETVAL(retval);
00942 }
00943
00950 void gadget_add_eps(struct gadget_wrapper *d)
00951 {
00952 static const char *names[] = {
00953
00954 "ep0",
00955 "ep1in",
00956 "ep2in",
00957 "ep3in",
00958 "ep4in",
00959 "ep5in",
00960 "ep6in",
00961 "ep7in",
00962 "ep8in",
00963 "ep9in",
00964 "ep10in",
00965 "ep11in",
00966 "ep12in",
00967 "ep13in",
00968 "ep14in",
00969 "ep15in",
00970 "ep1out",
00971 "ep2out",
00972 "ep3out",
00973 "ep4out",
00974 "ep5out",
00975 "ep6out",
00976 "ep7out",
00977 "ep8out",
00978 "ep9out",
00979 "ep10out",
00980 "ep11out",
00981 "ep12out",
00982 "ep13out",
00983 "ep14out",
00984 "ep15out"
00985 };
00986
00987 int i;
00988 struct usb_ep *ep;
00989 int8_t dev_endpoints;
00990
00991 DWC_DEBUGPL(DBG_PCDV, "%s\n", __func__);
00992
00993 INIT_LIST_HEAD(&d->gadget.ep_list);
00994 d->gadget.ep0 = &d->ep0;
00995 d->gadget.speed = USB_SPEED_UNKNOWN;
00996
00997 INIT_LIST_HEAD(&d->gadget.ep0->ep_list);
00998
01002 ep = &d->ep0;
01003
01004
01005 ep->name = names[0];
01006 ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops;
01007
01012 ep->maxpacket = MAX_PACKET_SIZE;
01013 dwc_otg_pcd_ep_enable(d->pcd, NULL, ep);
01014
01015 list_add_tail(&ep->ep_list, &d->gadget.ep_list);
01016
01020 dev_endpoints = d->pcd->core_if->dev_if->num_in_eps;
01021
01022 for (i = 0; i < dev_endpoints; i++) {
01023 ep = &d->in_ep[i];
01024
01025
01026 ep->name = names[d->pcd->in_ep[i].dwc_ep.num];
01027 ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops;
01028
01033 ep->maxpacket = MAX_PACKET_SIZE;
01034 list_add_tail(&ep->ep_list, &d->gadget.ep_list);
01035 }
01036
01037 dev_endpoints = d->pcd->core_if->dev_if->num_out_eps;
01038
01039 for (i = 0; i < dev_endpoints; i++) {
01040 ep = &d->out_ep[i];
01041
01042
01043 ep->name = names[15 + d->pcd->out_ep[i].dwc_ep.num];
01044 ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops;
01045
01050 ep->maxpacket = MAX_PACKET_SIZE;
01051
01052 list_add_tail(&ep->ep_list, &d->gadget.ep_list);
01053 }
01054
01055
01056 list_del_init(&d->ep0.ep_list);
01057
01058 d->ep0.maxpacket = MAX_EP0_SIZE;
01059 }
01060
01067 static void dwc_otg_pcd_gadget_release(struct device *dev)
01068 {
01069 DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, dev);
01070 }
01071
01072 static struct gadget_wrapper *alloc_wrapper(
01073 #ifdef LM_INTERFACE
01074 struct lm_device *_dev
01075 #elif defined(PCI_INTERFACE)
01076 struct pci_dev *_dev
01077 #endif
01078 )
01079 {
01080 static char pcd_name[] = "dwc_otg_pcd";
01081 #ifdef LM_INTERFACE
01082 dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev);
01083 #elif defined(PCI_INTERFACE)
01084 dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev);
01085 #endif
01086
01087 struct gadget_wrapper *d;
01088 int retval;
01089
01090 d = DWC_ALLOC(sizeof(*d));
01091 if (d == NULL) {
01092 return NULL;
01093 }
01094
01095 memset(d, 0, sizeof(*d));
01096
01097 d->gadget.name = pcd_name;
01098 d->pcd = otg_dev->pcd;
01099
01100 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
01101 strcpy(d->gadget.dev.bus_id, "gadget");
01102 #else
01103 dev_set_name(&d->gadget.dev, "%s", "gadget");
01104 #endif
01105
01106 d->gadget.dev.parent = &_dev->dev;
01107 d->gadget.dev.release = dwc_otg_pcd_gadget_release;
01108 d->gadget.ops = &dwc_otg_pcd_ops;
01109 d->gadget.is_dualspeed = dwc_otg_pcd_is_dualspeed(otg_dev->pcd);
01110 d->gadget.is_otg = dwc_otg_pcd_is_otg(otg_dev->pcd);
01111
01112 d->driver = 0;
01113
01114 retval = device_register(&d->gadget.dev);
01115 if (retval != 0) {
01116 DWC_ERROR("device_register failed\n");
01117 DWC_FREE(d);
01118 return NULL;
01119 }
01120
01121 return d;
01122 }
01123
01124 static void free_wrapper(struct gadget_wrapper *d)
01125 {
01126 if (d->driver) {
01127
01128 DWC_WARN("driver '%s' is still registered\n",
01129 d->driver->driver.name);
01130 usb_gadget_unregister_driver(d->driver);
01131 }
01132
01133 device_unregister(&d->gadget.dev);
01134 DWC_FREE(d);
01135 }
01136
01141 int pcd_init(
01142 #ifdef LM_INTERFACE
01143 struct lm_device *_dev
01144 #elif defined(PCI_INTERFACE)
01145 struct pci_dev *_dev
01146 #endif
01147 )
01148 {
01149 #ifdef LM_INTERFACE
01150 dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev);
01151 #elif defined(PCI_INTERFACE)
01152 dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev);
01153 #endif
01154
01155 int retval = 0;
01156
01157 DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _dev);
01158
01159 otg_dev->pcd = dwc_otg_pcd_init(otg_dev->core_if);
01160
01161 if (!otg_dev->pcd) {
01162 DWC_ERROR("dwc_otg_pcd_init failed\n");
01163 return -ENOMEM;
01164 }
01165
01166 otg_dev->pcd->otg_dev = otg_dev;
01167 gadget_wrapper = alloc_wrapper(_dev);
01168
01169
01170
01171
01172 gadget_add_eps(gadget_wrapper);
01173
01174
01175
01176 DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n", _dev->irq);
01177 retval = request_irq(_dev->irq, dwc_otg_pcd_irq,
01178 IRQF_SHARED | IRQF_DISABLED,
01179 gadget_wrapper->gadget.name, otg_dev->pcd);
01180 if (retval != 0) {
01181 DWC_ERROR("request of irq%d failed\n", _dev->irq);
01182 free_wrapper(gadget_wrapper);
01183 return -EBUSY;
01184 }
01185
01186 dwc_otg_pcd_start(gadget_wrapper->pcd, &fops);
01187
01188 return retval;
01189 }
01190
01194 void pcd_remove(
01195 #ifdef LM_INTERFACE
01196 struct lm_device *_dev
01197 #elif defined(PCI_INTERFACE)
01198 struct pci_dev *_dev
01199 #endif
01200 )
01201 {
01202 #ifdef LM_INTERFACE
01203 dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev);
01204 #elif defined(PCI_INTERFACE)
01205 dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev);
01206 #endif
01207 dwc_otg_pcd_t *pcd = otg_dev->pcd;
01208
01209 DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _dev);
01210
01211
01212
01213
01214 free_irq(_dev->irq, pcd);
01215 dwc_otg_pcd_remove(otg_dev->pcd);
01216 free_wrapper(gadget_wrapper);
01217 otg_dev->pcd = 0;
01218 }
01219
01231 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
01232 int usb_gadget_register_driver(struct usb_gadget_driver *driver)
01233 #else
01234 int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
01235 int (*bind)(struct usb_gadget *))
01236 #endif
01237 {
01238 int retval;
01239
01240 DWC_DEBUGPL(DBG_PCD, "registering gadget driver '%s'\n",
01241 driver->driver.name);
01242
01243 if (!driver || driver->speed == USB_SPEED_UNKNOWN ||
01244 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
01245 !driver->bind ||
01246 #else
01247 !bind ||
01248 #endif
01249 !driver->unbind || !driver->disconnect || !driver->setup) {
01250 DWC_DEBUGPL(DBG_PCDV, "EINVAL\n");
01251 return -EINVAL;
01252 }
01253 if (gadget_wrapper == 0) {
01254 DWC_DEBUGPL(DBG_PCDV, "ENODEV\n");
01255 return -ENODEV;
01256 }
01257 if (gadget_wrapper->driver != 0) {
01258 DWC_DEBUGPL(DBG_PCDV, "EBUSY (%p)\n", gadget_wrapper->driver);
01259 return -EBUSY;
01260 }
01261
01262
01263 gadget_wrapper->driver = driver;
01264 gadget_wrapper->gadget.dev.driver = &driver->driver;
01265
01266 DWC_DEBUGPL(DBG_PCD, "bind to driver %s\n", driver->driver.name);
01267 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
01268 retval = driver->bind(&gadget_wrapper->gadget);
01269 #else
01270 retval = bind(&gadget_wrapper->gadget);
01271 #endif
01272 if (retval) {
01273 DWC_ERROR("bind to driver %s --> error %d\n",
01274 driver->driver.name, retval);
01275 gadget_wrapper->driver = 0;
01276 gadget_wrapper->gadget.dev.driver = 0;
01277 return retval;
01278 }
01279 DWC_DEBUGPL(DBG_ANY, "registered gadget driver '%s'\n",
01280 driver->driver.name);
01281 return 0;
01282 }
01283 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
01284 EXPORT_SYMBOL(usb_gadget_register_driver);
01285 #else
01286 EXPORT_SYMBOL(usb_gadget_probe_driver);
01287 #endif
01288
01294 int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
01295 {
01296
01297
01298 if (gadget_wrapper == 0) {
01299 DWC_DEBUGPL(DBG_ANY, "%s Return(%d): s_pcd==0\n", __func__,
01300 -ENODEV);
01301 return -ENODEV;
01302 }
01303 if (driver == 0 || driver != gadget_wrapper->driver) {
01304 DWC_DEBUGPL(DBG_ANY, "%s Return(%d): driver?\n", __func__,
01305 -EINVAL);
01306 return -EINVAL;
01307 }
01308
01309 driver->unbind(&gadget_wrapper->gadget);
01310 gadget_wrapper->driver = 0;
01311
01312 DWC_DEBUGPL(DBG_ANY, "unregistered driver '%s'\n", driver->driver.name);
01313 return 0;
01314 }
01315
01316 EXPORT_SYMBOL(usb_gadget_unregister_driver);
01317
01318 #endif