void udc_setup_ep(struct usb_device_instance *device, unsigned int id, struct usb_endpoint_instance *endpoint) { if (0 == id) { /* EP0 */ ep0_endpoint = endpoint; ep0_endpoint->endpoint_address = 0xff; ep0_urb = usbd_alloc_urb(device, endpoint); } else if (MAX_ENDPOINT >= id) { int ep_addr; /* Check the direction */ ep_addr = endpoint->endpoint_address; if (USB_DIR_IN == (ep_addr & USB_ENDPOINT_DIR_MASK)) { /* IN */ epinfo[(id * 2) + 1].epsize = endpoint->tx_packetSize; } else { /* OUT */ epinfo[id * 2].epsize = endpoint->rcv_packetSize; } musb_configure_ep(&epinfo[0], ARRAY_SIZE(epinfo)); } else { if (debug_level > 0) serial_printf("ERROR : %s endpoint request %d " "exceeds maximum %d\n", __PRETTY_FUNCTION__, id, MAX_ENDPOINT); } }
int blan_start_recv_endpoint(struct usbd_function_instance *function_instance, int endpoint_index, otg_atomic_t *recv_urbs_started, char *msg) { struct usb_network_private *npd = function_instance->privdata; int i; int hs = usbd_high_speed(function_instance); int alloc_length = usbd_endpoint_transferSize(function_instance, endpoint_index, hs); if (TRACE_VERBOSE) TRACE_MSG4(NTT, "endpoint_index: %d recv_urbs_started: %d alloc_length: %d %s", endpoint_index, otg_atomic_read(recv_urbs_started), alloc_length, msg); while (otg_atomic_read(recv_urbs_started) < npd->max_recv_urbs ) { u8 *os_buffer = NULL; void *os_data = NULL; struct usbd_urb *urb; #ifdef DEBUG_CRC_SEEN if (npd->seen_crc_error) { TRACE_MSG0(NTT, "CRC ERROR NOT RESTARTING"); break; } #endif /* DEBUG_CRC_SEEN */ /* get os buffer - os_buffer is data, os_data is the os data structure */ os_data = net_os_alloc_buffer(function_instance, &os_buffer, alloc_length); /* allocate urb with no buffer */ /*allocate urb without buffer */ urb = usbd_alloc_urb(function_instance, endpoint_index, 0, net_fd_recv_urb2); /* start urb with buffer pointing at the os_buffer in os_data structure */ if (os_buffer && urb) { urb->function_privdata = os_data; urb->buffer = os_buffer; urb->flags |= npd->recv_urb_flags; urb->alloc_length = urb->buffer_length = alloc_length; if (usbd_start_out_urb(urb)) { net_os_dealloc_buffer(function_instance, os_data, os_buffer); urb->function_privdata = NULL; urb->buffer = NULL; usbd_free_urb(urb); } otg_atomic_inc(recv_urbs_started); continue; } TRACE_MSG1(NTT, "recv_urbs_started: %d FAILED EARLY", otg_atomic_read(recv_urbs_started)); if (os_buffer || os_data) net_os_dealloc_buffer(function_instance, os_data, os_buffer); if (urb) urb->buffer = NULL; usbd_free_urb(urb); break; } if (TRACE_VERBOSE) TRACE_MSG1(NTT, "recv_urbs_started: %d", otg_atomic_read(recv_urbs_started)); return 0; }
/* Switch on the UDC */ void udc_enable(struct usb_device_instance *device) { ep0state = EP0_IDLE; /* enable endpoint 0, A, B's Packet Complete Interrupt. */ writel(0xffffffff, UDCICR0); writel(0xa8000000, UDCICR1); /* clear the interrupt status/control registers */ writel(0xffffffff, UDCISR0); writel(0xffffffff, UDCISR1); /* set UDC-enable */ udc_set_mask_UDCCR(UDCCR_UDE); udc_device = device; if (!ep0_urb) ep0_urb = usbd_alloc_urb(udc_device, udc_device->bus->endpoint_array); else usbinfo("ep0_urb %p already allocated", ep0_urb); usbdbg("UDC Enabled\n"); }
/*! net_fd_start_recv_ecm - start recv urb(s) * * @param function_instance - pointer to this function instance * @return none */ int net_fd_start_recv_ecm(struct usbd_function_instance *function_instance) { struct usb_network_private *npd = function_instance->privdata; int i; int network_start_urbs = NETWORK_START_URBS; int hs = usbd_high_speed(function_instance); int endpoint_index = BULK_OUT_A; if (hs) network_start_urbs = NETWORK_START_URBS * 3; for (i = 0; i < network_start_urbs; i++) { struct usbd_urb *urb; BREAK_IF(!(urb = usbd_alloc_urb(function_instance, endpoint_index, usbd_endpoint_transferSize(function_instance, endpoint_index, hs), net_fd_recv_urb))); TRACE_MSG5(NTT,"i: %d urb: %p priv: %p npd: %p function: %p", i, urb, urb->function_privdata, npd, function_instance); //urb->function_privdata = npd; if (usbd_start_out_urb(urb)) { urb->function_privdata = NULL; usbd_free_urb(urb); } } return 0; }
/*! net_fd_start_xmit_nocrc * @brief - start sending a buffer * * @param function_instance - pointer to this function instance * @param buffer buffer containing data to send * @param len - length of data to send * @param data instance data * @return: 0 if all OK * -EINVAL, -EUNATCH, -ENOMEM * rc from usbd_start_in_urb() if that fails (is != 0, may be one of err values above) * Note: -ECOMM is interpreted by calling routine as signal to leave IF stopped. */ int net_fd_start_xmit_nocrc (struct usbd_function_instance *function_instance, u8 *buffer, int len, void *data) { struct usb_network_private *npd = function_instance->privdata; struct usbd_urb *urb = NULL; int rc; int in_pkt_sz; u8 *cp; u32 crc; #ifndef CONFIG_OTG_NETWORK_DOUBLE_IN int xmit_index = 0; int endpoint_index = BULK_IN_A; #else /* CONFIG_OTG_NETWORK_DOUBLE_IN */ int xmit_index = (otg_atomic_read(&npd->xmit_urbs_started[0]) <= otg_atomic_read(&npd->xmit_urbs_started[1])) ? 0 : 1; int endpoint_index = (xmit_index) ? BULK_IN_B : BULK_IN_A; #endif /* CONFIG_OTG_NETWORK_DOUBLE_IN */ TRACE_MSG7(NTT,"npd: %p function: %p flags: %04x len: %d endpoint_index: %d xmit_started: %d %d", npd, function_instance, npd->flags, len, endpoint_index, otg_atomic_read(&npd->xmit_urbs_started[0]), otg_atomic_read(&npd->xmit_urbs_started[1])); in_pkt_sz = usbd_endpoint_wMaxPacketSize(function_instance, endpoint_index, usbd_high_speed(function_instance)); /* allocate urb 5 bytes larger than required */ if (!(urb = usbd_alloc_urb (function_instance, endpoint_index, len + 5 + in_pkt_sz, net_fd_urb_sent_bulk ))) { u8 epa = usbd_endpoint_bEndpointAddress(function_instance, endpoint_index, usbd_high_speed(function_instance)); TRACE_MSG2(NTT,"urb alloc failed len: %d endpoint: %02x", len, epa); printk(KERN_ERR"%s: urb alloc failed len: %d endpoint: %02x\n", __FUNCTION__, len, epa); return -ENOMEM; } urb->actual_length = len; memcpy (urb->buffer, buffer, len); urb->function_privdata = data; urb->actual_length = len; otg_atomic_add(urb->actual_length, &npd->queued_bytes); otg_atomic_inc(&npd->xmit_urbs_started[xmit_index]); if ((rc = usbd_start_in_urb (urb))) { TRACE_MSG1(NTT,"FAILED: %d", rc); printk(KERN_ERR"%s: FAILED: %d\n", __FUNCTION__, rc); urb->function_privdata = NULL; otg_atomic_sub(urb->actual_length, &npd->queued_bytes); otg_atomic_dec(&npd->xmit_urbs_started[xmit_index]); usbd_free_urb (urb); return rc; } return 0; }
/* Switch on the UDC */ void udc_enable (struct usb_device_instance *device) { debug("enable device %p, status %d\n", device, device->status); /* Save the device structure pointer */ udc_device = device; /* Setup ep0 urb */ if (!ep0_urb) ep0_urb = usbd_alloc_urb(udc_device, udc_device->bus->endpoint_array); else serial_printf("udc_enable: ep0_urb already allocated %p\n", ep0_urb); s3c24x0_configure_device(device); }
/* udc_enable * * Grab an EP0 URB, register interest in a subset of USB events */ void udc_enable (struct usb_device_instance *device) { if (udc_state == STATE_ERROR) { return; } udc_device = device; if (!ep_ref[0].urb) { ep_ref[0].urb = usbd_alloc_urb (device, device->bus->endpoint_array); } /* Register interest in all events except SOF, enable transceiver */ usbp->usber = 0x03FF; usbp->usbmr = 0x02F7; return; }
/* Return : EOK if ok, error code on error */ int devi_output_control(void * pHandle, pControlRequest pRequest, void * data, int nLen) { int rc = EOK; struct usbd_urb * pUrb; void * pLocalData = NULL; pModule_data_t pModule = (pModule_data_t)pHandle; if(NULL == pModule -> ep_cntl) return EINVAL; if((pRequest -> dir & URB_DIR_OUT) && (nLen > pModule -> ep_cnt_size)) // Too big buffer return EINVAL; if( pUrb = usbd_alloc_urb( NULL ) ) // Allocate request block { if((pRequest -> dir & URB_DIR_OUT) && (NULL != data) && (nLen > 0) ) memcpy(pModule -> ep_cnt_buf, data, nLen); // Take data to USB -allocated buffer // Setup vendor request block usbd_setup_vendor( pUrb, pRequest -> dir, // Direction pRequest -> req, // Device specific request pRequest -> type | pRequest -> rec, // Type | recipient pRequest -> value, // Request specific pRequest -> index, // Request specific pModule -> ep_cnt_buf, nLen ); rc = usbd_io( pUrb, pModule -> ep_cntl, NULL, pModule, USBD_TIME_INFINITY ) ; // Delete request block usbd_free_urb( pUrb ); if((pRequest -> dir & URB_DIR_IN) && (EOK == rc)) // Take data from USB -allocated buffer memcpy(data, pLocalData, min(nLen, pModule -> ep_cnt_size)); } else rc = ENOMEM; return( rc ); }
/* mpc8xx_udc_assign_urb * * Associate a given urb to an endpoint TX or RX transmit/receive buffers */ static int mpc8xx_udc_assign_urb (int ep, char direction) { struct usb_endpoint_instance *epi = 0; if (ep >= MAX_ENDPOINTS) { goto err; } epi = &udc_device->bus->endpoint_array[ep]; if (!epi) { goto err; } if (!ep_ref[ep].urb) { ep_ref[ep].urb = usbd_alloc_urb (udc_device, udc_device->bus->endpoint_array); if (!ep_ref[ep].urb) { goto err; } } else { ep_ref[ep].urb->actual_length = 0; } switch (direction) { case USB_DIR_IN: epi->tx_urb = ep_ref[ep].urb; break; case USB_DIR_OUT: epi->rcv_urb = ep_ref[ep].urb; break; default: goto err; } return 0; err: udc_state = STATE_ERROR; return -1; }
/*! net_fd_start_xmit_mdlm * @brief - start sending a buffer * * @param function_instance - function instance pointer * @param buffer * @param len * @param data * * @return: 0 if all OK * -EINVAL, -EUNATCH, -ENOMEM * rc from usbd_start_in_urb() if that fails (is != 0, may be one of err values above) * Note: -ECOMM is interpreted by calling routine as signal to leave IF stopped. */ int net_fd_start_xmit_mdlm (struct usbd_function_instance *function_instance, u8 *buffer, int len, void *data) { struct usb_network_private *npd = function_instance->privdata; struct usbd_urb *urb = NULL; int rc; u32 crc; #ifndef CONFIG_OTG_NETWORK_DOUBLE_IN int xmit_index = 0; int endpoint_index = BULK_IN_A; #else /* CONFIG_OTG_NETWORK_DOUBLE_IN */ int xmit_index = (otg_atomic_read(&npd->xmit_urbs_started[0]) <= otg_atomic_read(&npd->xmit_urbs_started[1])) ? 0 : 1; int endpoint_index = (xmit_index) ? BULK_IN_B : BULK_IN_A; #endif /* CONFIG_OTG_NETWORK_DOUBLE_IN */ int in_pkt_sz = usbd_endpoint_wMaxPacketSize(function_instance, xmit_index, usbd_high_speed(function_instance)); if (TRACE_VERBOSE) TRACE_MSG8(NTT,"npd: %p flags: %04x len: %d endpoint_index: %d " "xmit_index: %d xmit_started: %d %d in_pkt_sz: %d", npd, npd->flags, len, endpoint_index, xmit_index, otg_atomic_read(&npd->xmit_urbs_started[0]), otg_atomic_read(&npd->xmit_urbs_started[1]), in_pkt_sz); #if defined(CONFIG_OTG_NETWORK_BLAN_CRC) || defined(CONFIG_OTG_NETWORK_SAFE_CRC) /* allocate urb 5 bytes larger than required */ if (!(urb = usbd_alloc_urb (function_instance, endpoint_index, len + 5 + 4 + in_pkt_sz, net_fd_urb_sent_bulk ))) { u8 epa = usbd_endpoint_bEndpointAddress(function_instance, endpoint_index, usbd_high_speed(function_instance)); TRACE_MSG2(NTT,"urb alloc failed len: %d endpoint: %02x", len, epa); return -ENOMEM; } urb->actual_length = len; /* copy and crc len bytes */ crc = crc32_copy(urb->buffer, buffer, len, CRC32_INIT); if ((urb->actual_length % in_pkt_sz) == (in_pkt_sz - 4)) { /* no longer in Kconfig - change undef to define to active padbyte */ #undef CONFIG_OTG_NETWORK_PADBYTE #ifdef CONFIG_OTG_NETWORK_PADBYTE // add a pad byte if required to ensure a short packet, usbdnet driver // will correctly handle pad byte before or after CRC, but the MCCI driver // wants it before the CRC. crc = crc32_pad(urb->buffer + urb->actual_length, 1, crc); urb->actual_length++; #else /* CONFIG_OTG_NETWORK_PADBYTE */ urb->flags |= USBD_URB_SENDZLP; TRACE_MSG2(NTT,"setting ZLP: urb: %p flags: %x", urb, urb->flags); #endif /* CONFIG_OTG_NETWORK_PADBYTE */ } crc = ~crc; urb->buffer[urb->actual_length++] = crc & 0xff; urb->buffer[urb->actual_length++] = (crc >> 8) & 0xff; urb->buffer[urb->actual_length++] = (crc >> 16) & 0xff; urb->buffer[urb->actual_length++] = (crc >> 24) & 0xff; #if defined(CONFIG_OTG_NETWORK_BLAN_FERMAT) if (npd->fermat) fermat_encode(urb->buffer, urb->actual_length); #endif #else /* defined(CONFIG_OTG_NETWORK_BLAN_CRC) ...*/ /* allocate urb with no buffer */ #ifdef CONFIG_OTG_NETWORK_XMIT_OS if (!(urb = usbd_alloc_urb (function_instance, endpoint_index, 0, net_fd_urb_sent_bulk ))) { u8 epa = usbd_endpoint_bEndpointAddress(function_instance, endpoint_index, usbd_high_speed(function_instance)); TRACE_MSG2(NTT,"urb alloc failed len: %d endpoint: %02x", len, epa); return -ENOMEM; } urb->actual_length = len; urb->buffer = buffer; #else /* CONFIG_OTG_NETWORK_XMIT_OS */ if (!(urb = usbd_alloc_urb (function_instance, endpoint_index, len + 5 + 4 + in_pkt_sz, net_fd_urb_sent_bulk ))) { u8 epa = usbd_endpoint_bEndpointAddress(function_instance, endpoint_index, usbd_high_speed(function_instance)); TRACE_MSG2(NTT,"urb alloc failed len: %d endpoint: %02x", len, epa); printk(KERN_ERR"%s: urb alloc failed len: %d endpoint: %02x\n", __FUNCTION__, len, epa); return -ENOMEM; } urb->actual_length = len; memcpy (urb->buffer, buffer, len); #endif /* CONFIG_OTG_NETWORK_XMIT_OS */ urb->flags |= ((urb->actual_length % in_pkt_sz) == 0) ? USBD_URB_SENDZLP : 0; #endif /* defined(CONFIG_OTG_NETWORK_BLAN_CRC) ...*/ if (TRACE_VERBOSE) TRACE_MSG3(NTT,"urb: %p buf: %p priv: %p", urb, data, urb->function_privdata); urb->function_privdata = data; otg_atomic_add(urb->actual_length, &npd->queued_bytes); otg_atomic_inc(&npd->xmit_urbs_started[xmit_index]); if ((rc = usbd_start_in_urb (urb))) { TRACE_MSG1(NTT,"FAILED: %d", rc); printk(KERN_ERR"%s: FAILED: %d\n", __FUNCTION__, rc); urb->function_privdata = NULL; otg_atomic_sub(urb->actual_length, &npd->queued_bytes); otg_atomic_dec(&npd->xmit_urbs_started[xmit_index]); usbd_free_urb (urb); return rc; } return 0; }
/** * usbd_device_event - called to respond to various usb events * @device: pointer to struct device * @event: event to respond to * * Used by a Bus driver to indicate an event. */ void usbd_device_event_irq (struct usb_device_instance *device, usb_device_event_t event, int data) { struct urb *urb; usb_device_state_t state; if (!device || !device->bus) { dbg_usbe (1, "(%p,%d) NULL device or device->bus", device, event); return; } state = device->device_state; dbg_usbe (3, "-------------------------------------------------------------------------------------"); dbg_usbe (1,"%s", USBD_DEVICE_EVENTS(event)); switch (event) { case DEVICE_UNKNOWN: break; case DEVICE_INIT: device->device_state = STATE_INIT; break; case DEVICE_CREATE: device->device_state = STATE_ATTACHED; break; case DEVICE_HUB_CONFIGURED: device->device_state = STATE_POWERED; break; case DEVICE_RESET: device->device_state = STATE_DEFAULT; device->address = 0; break; case DEVICE_ADDRESS_ASSIGNED: device->device_state = STATE_ADDRESSED; break; case DEVICE_CONFIGURED: device->device_state = STATE_CONFIGURED; break; case DEVICE_DE_CONFIGURED: device->device_state = STATE_ADDRESSED; break; case DEVICE_BUS_INACTIVE: if (device->status != USBD_CLOSING) { device->status = USBD_SUSPENDED; } break; case DEVICE_BUS_ACTIVITY: if (device->status != USBD_CLOSING) { device->status = USBD_OK; } break; case DEVICE_SET_INTERFACE: break; case DEVICE_SET_FEATURE: break; case DEVICE_CLEAR_FEATURE: break; case DEVICE_POWER_INTERRUPTION: device->device_state = STATE_POWERED; break; case DEVICE_HUB_RESET: device->device_state = STATE_ATTACHED; break; case DEVICE_DESTROY: device->device_state = STATE_UNKNOWN; break; case DEVICE_FUNCTION_PRIVATE: break; } dbg_usbe (3, "%s event: %d oldstate: %d newstate: %d status: %d address: %d", device->name, event, state, device->device_state, device->status, device->address);; // tell the bus interface driver if (device->bus && device->bus->driver->ops->device_event) { dbg_usbe (3, "calling bus->event"); device->bus->driver->ops->device_event (device, event, data); } #if 0 if (device->function_instance_array && (device->function_instance_array + port)->function_driver->ops->event) { dbg_usbe (3, "calling function->event"); (device->function_instance_array + port)->function_driver->ops->event (device, event); } #endif if (device->ep0 && device->ep0->function_driver->ops->event) { dbg_usbe (3, "calling ep0->event"); device->ep0->function_driver->ops->event (device, event, data); } #if 0 // tell the bus interface driver if (device->bus && device->bus->driver->ops->device_event) { dbg_usbe (3, "calling bus->event"); device->bus->driver->ops->device_event (device, event); } #endif // dbg_usbe(0, "FINISHED - NO FUNCTION BH"); // return; // XXX // queue an urb to endpoint zero dbg_usbe(1,"queueing event urb"); if ((urb = usbd_alloc_urb (device, device->function_instance_array, 0, 0))) { urb->event = event; urb->data = data; urb_append_irq (&(urb->endpoint->events), urb); usbd_schedule_function_bh (device); } dbg_usbe (5, "FINISHED"); return; }
/* Return : None */ void insertion( struct usbd_connection *pConnection, usbd_device_instance_t *pInstance ) { int rc; struct usbd_device * pDevice; pModule_data_t pModule, * ppModule; if(verbosity) printf("Try to inser device\n"); if( EOK != (rc = usbd_attach( pConnection, pInstance, sizeof(module_data_t **), &pDevice ) )) { char * pMsgTxt = "Error: cannot attach USB device #%i (error code is %i)\n"; fprintf(stderr, pMsgTxt, (int)(pInstance -> devno), rc); slogf(_SLOG_SETCODE(_SLOGC_INPUT, 0), _SLOG_ERROR, pMsgTxt, (int)(pInstance -> devno), rc); return; } ppModule = (pModule_data_t *)usbd_device_extra(pDevice); // Try to find if somebody cares about keyboard reports for(pModule = LIST_FIRST_ITEM(&modList); NULL != pModule; pModule = LIST_NEXT_ITEM(pModule, lst_conn)) { // Check device number if specified if( (USBD_CONNECT_WILDCARD != pModule -> nDev) && (pModule -> nDev != pInstance -> devno)) continue; if( (USBD_CONNECT_WILDCARD != pModule -> nVendor) && (pModule -> nVendor != pInstance -> ident.vendor)) continue; // Wrong vendor - ignore if((USBD_CONNECT_WILDCARD != pModule -> nClass) && (pModule -> nClass != pInstance -> ident.dclass)) continue; if((USBD_CONNECT_WILDCARD != pModule -> nSubClass) && (pModule -> nSubClass != pInstance -> ident.subclass)) continue; pModule -> pInstance = pInstance; pModule -> pDevice = pDevice; if( EOK == parse_descriptors( pModule) ) { if( pModule -> ep_int_buf = usbd_alloc( pModule -> ep_int_size ) ) { if( pModule -> urb = usbd_alloc_urb( NULL ) ) { // Initialize request block usbd_setup_interrupt( pModule -> urb, URB_DIR_IN, pModule -> ep_int_buf, pModule->ep_int_size ); // Initialize Interrupt callback function if( EOK == usbd_io( pModule -> urb, pModule -> ep_int, usb_dev_int, pModule, USBD_TIME_INFINITY ) ) { pModule -> flags |= USB_DEVICE_ON | USB_DEVICE_PRESENT; *ppModule = pModule; if(verbosity) printf("Attach device\n"); return; } else { if(verbosity) printf("Cannot attach device\n"); } } usbd_free( pModule -> ep_int_buf ); } usbd_detach( pDevice ); } } }