/** * This function is called by the Gadget Driver for each EP to be * configured for the current configuration (SET_CONFIGURATION). * * This function initializes the dwc_otg_ep_t data structure, and then * calls dwc_otg_ep_activate. */ static int ep_enable(struct usb_ep *usb_ep, const struct usb_endpoint_descriptor *ep_desc) { int retval; DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, usb_ep, ep_desc); if (!usb_ep || !ep_desc || ep_desc->bDescriptorType != USB_DT_ENDPOINT) { DWC_WARN("%s, bad ep or descriptor\n", __func__); return -EINVAL; } if (usb_ep == &gadget_wrapper->ep0) { DWC_WARN("%s, bad ep(0)\n", __func__); return -EINVAL; } /* Check FIFO size? */ if (!ep_desc->wMaxPacketSize) { DWC_WARN("%s, bad %s maxpacket\n", __func__, usb_ep->name); return -ERANGE; } if (!gadget_wrapper->driver || gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) { DWC_WARN("%s, bogus device state\n", __func__); return -ESHUTDOWN; } retval = dwc_otg_pcd_ep_enable(gadget_wrapper->pcd, (const uint8_t *)ep_desc, (void *)usb_ep); if (retval) { DWC_WARN("dwc_otg_pcd_ep_enable failed\n"); return -EINVAL; } usb_ep->maxpacket = le16_to_cpu(ep_desc->wMaxPacketSize); return 0; }
/** * This function initialized the usb_ep structures to there default * state. * * @param d Pointer on gadget_wrapper. */ void gadget_add_eps(struct gadget_wrapper *d) { static const char *names[] = { "ep0", "ep1in", "ep2in", "ep3in", "ep4in", "ep5in", "ep6in", "ep7in", "ep8in", "ep9in", "ep10in", "ep11in", "ep12in", "ep13in", "ep14in", "ep15in", "ep1out", "ep2out", "ep3out", "ep4out", "ep5out", "ep6out", "ep7out", "ep8out", "ep9out", "ep10out", "ep11out", "ep12out", "ep13out", "ep14out", "ep15out" }; int i; struct usb_ep *ep; DWC_DEBUGPL(DBG_PCDV, "%s\n", __func__); INIT_LIST_HEAD(&d->gadget.ep_list); d->gadget.ep0 = &d->ep0; d->gadget.speed = USB_SPEED_UNKNOWN; INIT_LIST_HEAD(&d->gadget.ep0->ep_list); /** * Initialize the EP0 structure. */ ep = &d->ep0; /* Init the usb_ep structure. */ ep->name = names[0]; ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops; /** * @todo NGS: What should the max packet size be set to * here? Before EP type is set? */ ep->maxpacket = MAX_PACKET_SIZE; dwc_otg_pcd_ep_enable(d->pcd, NULL, ep); list_add_tail(&ep->ep_list, &d->gadget.ep_list); /** * Initialize the EP structures. */ for (i = 0; i < 15; i++) { ep = &d->in_ep[i]; /* Init the usb_ep structure. */ ep->name = names[i + 1]; ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops; /** * @todo NGS: What should the max packet size be set to * here? Before EP type is set? */ ep->maxpacket = MAX_PACKET_SIZE; list_add_tail(&ep->ep_list, &d->gadget.ep_list); } for (i = 0; i < 15; i++) { ep = &d->out_ep[i]; /* Init the usb_ep structure. */ ep->name = names[15 + i + 1]; ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops; /** * @todo NGS: What should the max packet size be set to * here? Before EP type is set? */ ep->maxpacket = MAX_PACKET_SIZE; list_add_tail(&ep->ep_list, &d->gadget.ep_list); } /* remove ep0 from the list. There is a ep0 pointer. */ list_del_init(&d->ep0.ep_list); d->ep0.maxpacket = MAX_EP0_SIZE; }
static int _setup(dwc_otg_pcd_t *pcd, uint8_t *bytes) { DWC_DEBUGPL(DBG_PCD, "%s(): enter \n", __func__); const usb_device_request_t *ctrlReq = (usb_device_request_t *)bytes; int value = 0; int idx; usb_device_request_t ctrlConvertedReq; usb_device_request_t *ctrl = &ctrlConvertedReq; ctrl->bmRequestType = (uByte)(ctrlReq->bmRequestType); ctrl->bRequest = (uByte)(ctrlReq->bRequest); ctrl->wValue[0] = ctrlReq->wValue[0]; ctrl->wValue[1] = ctrlReq->wValue[1]; ctrl->wIndex[0] = ctrlReq->wIndex[0]; ctrl->wIndex[1] = ctrlReq->wIndex[1]; ctrl->wLength[0] = ctrlReq->wLength[0]; ctrl->wLength[1] = ctrlReq->wLength[1]; /* * usually this stores reply data in the pre-allocated ep0 buffer, * but config change events will reconfigure hardware. */ static_data->dl_req.data.zero = 0; if (UT_GET_RECIPIENT(ctrl->bmRequestType) == UT_INTERFACE) { if ((UT_GET_DIR(ctrl->bmRequestType) == UT_WRITE) && (UGETW(ctrl->wLength) > 0)) { static_data->dl_req.data.buf = &static_data->ep0_buffer[0]; DWC_MEMCPY(&static_data->dl_req.out_req, ctrl, sizeof(*ctrl)); static_data->dl_req.data.length = DWC_MIN(UGETW( ctrl->wLength), static_data->ep0_buffer_size); // either shorter than asked, or multiple of the MPS require ZLP. static_data->dl_req.data.zero = ((value < UGETW(ctrl->wLength)) && ((value % pcd->ep0.dwc_ep. maxpacket) == 0)) ? 1 : 0; // Elaborate when getting the time. dwc_otg_pcd_ep_queue( pcd, /*void* ep_hanlde */ NULL, static_data->dl_req.data.buf, (dwc_dma_t)static_data->dl_req. data.buf, static_data->dl_req.data.length, static_data->dl_req.data.zero, /*void* req_handle */ &static_data ->dl_req, 0); } else { static_data->dl_req.data.buf = &static_data->ep0_buffer[0]; if (static_data->usb_class_handler(ctrl, &value, &static_data->dl_req .data.buf) != 0) { value = -DWC_E_NOT_SUPPORTED; } } } else { switch (ctrl->bRequest) { case UR_GET_DESCRIPTOR: __DWC_ERROR("ctrl->Length = %d \n", UGETW(ctrl->wLength)); switch (UGETW(ctrl->wValue) >> 8) { case UDESC_DEVICE: value = DWC_MIN(UGETW(ctrl->wLength), USB_DEVICE_DESCRIPTOR_SIZE); static_data->dl_req.data.buf = (uint8_t *) static_data-> usb_device_descriptor; break; case UDESC_CONFIG: value = DWC_MIN(UGETW(ctrl->wLength), UGETW(static_data-> usb_config_descriptor-> wTotalLength)); static_data->dl_req.data.buf = (uint8_t *) static_data-> usb_config_descriptor; break; case UDESC_OTHER_SPEED_CONFIGURATION: __DWC_ERROR ( "UDESC_OTHER_SPEED_CONFIGURATION NOT IMPLEMENTED! \n"); break; case UDESC_STRING: /* wIndex == language code. * this driver only handles one language, you can * add string tables for other languages, using * any UTF-8 characters */ idx = UGETW(ctrl->wValue) & 0xFF; __DWC_ERROR("UDESC_STRING idx = %d \n", idx); __DWC_ERROR( "UDESC_STRING bLength = %d \n", &static_data->strings_desc[idx]. bLength); if (idx > static_data->usb_strings_count) { if (idx == 0xEE) { // Microsoft MTP extension value = 0; } else { value = -DWC_E_INVALID; } } else { value = DWC_MIN(UGETW( ctrl->wLength), static_data-> strings_desc[idx]. bLength); static_data->dl_req.data.buf = (uint8_t *) & static_data->strings_desc[idx]; } break; } break; case UR_SET_CONFIG: static_data->usb_config = UGETW(ctrl->wValue); value = 0; { int i; for (i = 0; i < static_data->usb_num_endpoints; i++) { int ret = dwc_otg_pcd_ep_enable( pcd, (const uint8_t *)&static_data->usb_endpoints[ i], static_data ->usb_endpoints[i]. bEndpointAddress); __DWC_WARN( "Enabled endpoint: %x ret: %d\n", static_data->usb_endpoints[i ].bEndpointAddress, ret); } struct usb_event evt; evt.event = USB_EVENT_SET_CONFIG; evt.event_data.config = static_data->usb_config; if (static_data->usb_event_cb) { static_data->usb_event_cb(&evt); } } break; case UR_GET_CONFIG: static_data->dl_req.data.buf = &static_data->usb_config; value = DWC_MIN(UGETW(ctrl->wLength), 1); break; /* until we add altsetting support, or other interfaces, * only 0/0 are possible. pxa2xx only supports 0/0 (poorly) * and already killed pending endpoint I/O. */ case UR_SET_INTERFACE: value = 0; break; case UR_GET_INTERFACE: __DWC_ERROR("UR_GET_INTERFACE NOT IMPLEMENTED! \n"); goto unknown; break; default: unknown: value = -DWC_E_NOT_SUPPORTED; break; } } /* respond with data transfer before status phase? */ __DWC_ERROR("%s(): req.length = %d - max length is 64 \n", __func__, value); if (value >= 0) { static_data->dl_req.data.length = value; // either shorter than asked, or multiple of the MPS require ZLP. static_data->dl_req.data.zero = ((value < UGETW(ctrl->wLength)) && ((value % pcd->ep0.dwc_ep.maxpacket) == 0)) ? 1 : 0; // Elaborate when getting the time. dwc_otg_pcd_ep_queue(pcd, /*void* ep_hanlde */ NULL, static_data->dl_req.data.buf, (dwc_dma_t)static_data->dl_req.data.buf, static_data->dl_req.data.length, static_data->dl_req.data.zero, /*void* req_handle */ NULL, 0); } /* device either stalls (value < 0) or reports success */ return value; }