// read a block of bytes to a buffer int usb_serial_read(void *buffer, uint32_t size) { uint8_t *p = (uint8_t *)buffer; uint32_t qty, count=0; while (size) { if (!usb_configuration) break; if (!rx_packet) { rx: rx_packet = usb_rx(CDC_RX_ENDPOINT); if (!rx_packet) break; if (rx_packet->len == 0) { usb_free(rx_packet); goto rx; } } qty = rx_packet->len - rx_packet->index; if (qty > size) qty = size; memcpy(p, rx_packet->buf + rx_packet->index, qty); p += qty; count += qty; size -= qty; rx_packet->index += qty; if (rx_packet->index >= rx_packet->len) { usb_free(rx_packet); rx_packet = NULL; } } return count; }
void fcBuffers::handleUSB() { /* * Look for incoming USB packets, and file them appropriately. * Our framebuffer and LUT buffers are arrays of references to USB packets * which we hold until a new packet arrives to replace them. */ bool handledAnyPackets = false; while (1) { usb_packet_t *packet = usb_rx(FC_OUT_ENDPOINT); if (!packet) { break; } handledAnyPackets = true; unsigned control = packet->buf[0]; unsigned type = control & TYPE_BITS; unsigned final = control & FINAL_BIT; unsigned index = control & INDEX_BITS; switch (type) { case TYPE_FRAMEBUFFER: fbNew->store(index, packet); if (final) { finalizeFramebuffer(); } break; case TYPE_LUT: lutNew.store(index, packet); if (final) { finalizeLUT(); } break; case TYPE_CONFIG: flags = packet->buf[1]; usb_free(packet); break; default: usb_free(packet); break; } } if (flags & CFLAG_NO_ACTIVITY_LED) { // LED under manual control digitalWrite(LED_BUILTIN, flags & CFLAG_LED_CONTROL); } else { // Use the built-in LED as a USB activity indicator. digitalWrite(LED_BUILTIN, handledAnyPackets); } }
void ledStorePacket(ledPacketBuffer *const pBuffer, usb_packet_t *const packet) { if (pBuffer->pCounter < NUM_BUFFS_PER_FRAME) { // Store a packet, holding a reference to it. usb_packet_t *prev = pBuffer->packets[pBuffer->pCounter]; pBuffer->packets[pBuffer->pCounter] = packet; usb_free(prev); pBuffer->pByteCount += packet->len; pBuffer->pCounter++; } else { // Error; ignore this packet. usb_free(packet); } }
// discard any buffered input void usb_serial_flush_input(void) { usb_packet_t *rx; if (!usb_configuration) return; if (rx_packet) { usb_free(rx_packet); rx_packet = NULL; } while (1) { rx = usb_rx(CDC_RX_ENDPOINT); if (!rx) break; usb_free(rx); } }
bool fcBuffers::handleUSB(usb_packet_t *packet) { unsigned control = packet->buf[0]; unsigned type = control & TYPE_BITS; unsigned final = control & FINAL_BIT; unsigned index = control & INDEX_BITS; switch (type) { case TYPE_FRAMEBUFFER: // Framebuffer updates are synchronized; if we're waiting to finalize fbNew, // don't accept any new packets until that buffer becomes available. if (pendingFinalizeFrame) { return false; } fbNew->store(index, packet); if (final) { pendingFinalizeFrame = true; } break; case TYPE_LUT: // LUT accesses are not synchronized lutNew.store(index, packet); if (final) { // Finalize the LUT on the main thread, it's less async than doing it in the ISR. pendingFinalizeLUT = true; } break; case TYPE_CONFIG: // Config changes take effect immediately. flags = packet->buf[1]; usb_free(packet); break; default: usb_free(packet); break; } // Handled this packet handledAnyPacketsThisFrame = true; return true; }
// get the next character, or -1 if nothing received int usb_serial_getchar() { unsigned int i; int c; if ( !rx_packet ) { if ( !usb_configuration ) return -1; rx_packet = usb_rx( CDC_RX_ENDPOINT ); if ( !rx_packet ) return -1; } i = rx_packet->index; c = rx_packet->buf[i++]; if ( i >= rx_packet->len ) { usb_free( rx_packet ); rx_packet = NULL; } else { rx_packet->index = i; } return c; }
/*------------------------------------------------------------------------* * usb_pc_free_mem - free DMA memory * * This function is NULL safe. *------------------------------------------------------------------------*/ void usb_pc_free_mem(struct usb_page_cache *pc) { if (pc != NULL && pc->buffer != NULL) { usb_free(pc->tag); pc->buffer = NULL; } }
static inline void ehci_qtd_free(struct ehci_hcd *ehci, struct ehci_qtd *qtd) { if ((qtd->qtd_dma & (USB_IRAM_BASE_ADDR & 0xFFF00000)) == (USB_IRAM_BASE_ADDR & 0xFFF00000)) usb_free(qtd->qtd_dma); else dma_pool_free(ehci->qtd_pool, qtd, qtd->qtd_dma); --g_debug_qtd_allocated; }
static void usb_serial_receive(void) { if (!usb_configuration) return; if (rx_packet) return; while (1) { rx_packet = usb_rx(CDC_RX_ENDPOINT); if (rx_packet == NULL) return; if (rx_packet->len > 0) return; usb_free(rx_packet); rx_packet = NULL; } }
int usb_rawhid_recv(void *buffer, uint32_t timeout) { usb_packet_t *rx_packet; uint32_t begin = millis(); while (1) { if (!usb_configuration) return -1; rx_packet = usb_rx(RAWHID_RX_ENDPOINT); if (rx_packet) break; if (millis() - begin > timeout || !timeout) return 0; yield(); } memcpy(buffer, rx_packet->buf, RAWHID_RX_SIZE); usb_free(rx_packet); return RAWHID_RX_SIZE; }
// get the next character, or -1 if nothing received int usb_serial_getchar(void) { unsigned int i; int c; usb_serial_receive(); if (!rx_packet) return -1; i = rx_packet->index; c = rx_packet->buf[i++]; if (i >= rx_packet->len) { usb_free(rx_packet); rx_packet = NULL; } else { rx_packet->index = i; } return c; }
// Called from usb_free, but only when usb_rx_memory_needed > 0, indicating // receive endpoints are starving for memory. The intention is to give // endpoints needing receive memory priority over the user's code, which is // likely calling usb_malloc to obtain memory for transmitting. When the // user is creating data very quickly, their consumption could starve reception // without this prioritization. The packet buffer (input) is assigned to the // first endpoint needing memory. // void usb_rx_memory(usb_packet_t *packet) { unsigned int i; const uint8_t *cfg; cfg = usb_endpoint_config_table; //serial_print("rx_mem:"); __disable_irq(); for (i=1; i < NUM_ENDPOINTS; i++) { if (*cfg++ & USB_ENDPT_EPRXEN) { if (table[index(i, RX, EVEN)].desc == 0) { table[index(i, RX, EVEN)].addr = packet->buf; table[index(i, RX, EVEN)].desc = BDT_DESC(64, 0); usb_rx_memory_needed--; __enable_irq(); //serial_phex(i); //serial_print(",even\n"); return; } if (table[index(i, RX, ODD)].desc == 0) { table[index(i, RX, ODD)].addr = packet->buf; table[index(i, RX, ODD)].desc = BDT_DESC(64, 1); usb_rx_memory_needed--; __enable_irq(); //serial_phex(i); //serial_print(",odd\n"); return; } } } __enable_irq(); // we should never reach this point. If we get here, it means // usb_rx_memory_needed was set greater than zero, but no memory // was actually needed. usb_rx_memory_needed = 0; usb_free(packet); return; }
static void qh_destroy(struct ehci_qh *qh) { struct ehci_hcd *ehci = qh->ehci; /* clean qtds first, and know this is not linked */ if (!list_empty(&qh->qtd_list) || qh->qh_next.ptr) { ehci_dbg(ehci, "unused qh not empty!\n"); BUG(); } if (qh->dummy) ehci_qtd_free(ehci, qh->dummy); int i; for (i = 0; i < IRAM_NTD; i++) { if (ehci->usb_address[i] == (qh->hw_info1 & 0x7F)) ehci->usb_address[i] = 0; } if ((qh->qh_dma & (USB_IRAM_BASE_ADDR & 0xFFF00000)) == (USB_IRAM_BASE_ADDR & 0xFFF00000)) usb_free(qh->qh_dma); else dma_pool_free(ehci->qh_pool, qh, qh->qh_dma); --g_debug_qH_allocated; }
static int msm72k_probe(struct platform_device *pdev) { struct resource *res; struct usb_info *ui; int irq; int ret; INFO("msm72k_probe\n"); ui = kzalloc(sizeof(struct usb_info), GFP_KERNEL); if (!ui) return -ENOMEM; ui->pdev = pdev; if (pdev->dev.platform_data) { struct msm_hsusb_platform_data *pdata = pdev->dev.platform_data; ui->phy_reset = pdata->phy_reset; ui->phy_init_seq = pdata->phy_init_seq; } irq = platform_get_irq(pdev, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res || (irq < 0)) return usb_free(ui, -ENODEV); ui->addr = ioremap(res->start, 4096); if (!ui->addr) return usb_free(ui, -ENOMEM); ui->buf = dma_alloc_coherent(&pdev->dev, 4096, &ui->dma, GFP_KERNEL); if (!ui->buf) return usb_free(ui, -ENOMEM); ui->pool = dma_pool_create("msm72k_udc", NULL, 32, 32, 0); if (!ui->pool) return usb_free(ui, -ENOMEM); INFO("msm72k_probe() io=%p, irq=%d, dma=%p(%x)\n", ui->addr, irq, ui->buf, ui->dma); ui->clk = clk_get(&pdev->dev, "usb_hs_clk"); if (IS_ERR(ui->clk)) return usb_free(ui, PTR_ERR(ui->clk)); ui->pclk = clk_get(&pdev->dev, "usb_hs_pclk"); if (IS_ERR(ui->pclk)) return usb_free(ui, PTR_ERR(ui->pclk)); /* FIXME: dmb cannot be called from interrupt context * for the first time; Need to verify on how it needs * to be fixed */ dmb(); ret = request_irq(irq, usb_interrupt, 0, pdev->name, ui); if (ret) return usb_free(ui, ret); enable_irq_wake(irq); ui->irq = irq; ui->gadget.ops = &msm72k_ops; ui->gadget.is_dualspeed = 1; device_initialize(&ui->gadget.dev); strcpy(ui->gadget.dev.bus_id, "gadget"); ui->gadget.dev.parent = &pdev->dev; ui->gadget.dev.dma_mask = pdev->dev.dma_mask; the_usb_info = ui; usb_debugfs_init(ui); usb_prepare(ui); return 0; }
void FlightSimClass::update(void) { uint8_t len, maxlen, type, *p, *end; union { uint8_t b[4]; long l; float f; } data; usb_packet_t *rx_packet; uint16_t id; while (1) { if (!usb_configuration) break; rx_packet = usb_rx(FLIGHTSIM_RX_ENDPOINT); if (!rx_packet) break; p = rx_packet->buf; end = p + 64; maxlen = 64; do { len = p[0]; if (len < 2 || len > maxlen) break; switch (p[1]) { case 0x02: // write data if (len < 10) break; id = p[2] | (p[3] << 8); type = p[4]; if (type == 1) { FlightSimInteger *item = FlightSimInteger::find(id); if (!item) break; #ifdef KINETISK data.l = *(long *)(p + 6); #else data.b[0] = p[6]; data.b[1] = p[7]; data.b[2] = p[8]; data.b[3] = p[9]; #endif item->update(data.l); } else if (type == 2) { FlightSimFloat *item = FlightSimFloat::find(id); if (!item) break; #ifdef KINETISK data.f = *(float *)(p + 6); #else data.b[0] = p[6]; data.b[1] = p[7]; data.b[2] = p[8]; data.b[3] = p[9]; #endif item->update(data.f); /// JB } else if (type == 3) { FlightSimEvent *item = FlightSimEvent::find(id); if (!item) break; #ifdef KINETISK data.l = *(long *)(p + 6); #else data.b[0] = p[6]; data.b[1] = p[7]; data.b[2] = p[8]; data.b[3] = p[9]; #endif item->update(data.f); } else if (type == 4) { FlightSimData *item = FlightSimData::find(id); if (!item) break; item->update(((char*)p)+6,len-6); /// JB End } break; case 0x03: // enable/disable if (len < 4) break; switch (p[2]) { case 1: request_id_messages = 1; /* no break */ case 2: enable(); frameCount++; break; case 3: disable(); } } p += len; maxlen -= len; } while (p < end); usb_free(rx_packet); } if (enabled && request_id_messages) { request_id_messages = 0; for (FlightSimCommand *p = FlightSimCommand::first; p; p = p->next) { p->identify(); } /// JB for (FlightSimEvent *p = FlightSimEvent::first; p; p = p->next) { p->identify(); } for (FlightSimData *p = FlightSimData::first; p; p=p->next) { p->identify(); } /// JB End for (FlightSimInteger *p = FlightSimInteger::first; p; p = p->next) { p->identify(); // TODO: send any dirty data } for (FlightSimFloat *p = FlightSimFloat::first; p; p = p->next) { p->identify(); // TODO: send any dirty data } } }
static int msm72k_probe(struct platform_device *pdev) { struct resource *res; struct usb_info *ui; int irq; int ret; INFO("msm72k_probe\n"); ui = kzalloc(sizeof(struct usb_info), GFP_KERNEL); if (!ui) return -ENOMEM; spin_lock_init(&ui->lock); ui->pdev = pdev; if (pdev->dev.platform_data) { struct msm_hsusb_platform_data *pdata = pdev->dev.platform_data; ui->phy_reset = pdata->phy_reset; ui->phy_init_seq = pdata->phy_init_seq; ui->usb_connected = pdata->usb_connected; } irq = platform_get_irq(pdev, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res || (irq < 0)) return usb_free(ui, -ENODEV); ui->addr = ioremap(res->start, 4096); if (!ui->addr) return usb_free(ui, -ENOMEM); ui->buf = dma_alloc_coherent(&pdev->dev, 4096, &ui->dma, GFP_KERNEL); if (!ui->buf) return usb_free(ui, -ENOMEM); ui->pool = dma_pool_create("msm72k_udc", NULL, 32, 32, 0); if (!ui->pool) return usb_free(ui, -ENOMEM); INFO("msm72k_probe() io=%p, irq=%d, dma=%p(%x)\n", ui->addr, irq, ui->buf, ui->dma); ui->clk = clk_get(&pdev->dev, "usb_hs_clk"); if (IS_ERR(ui->clk)) return usb_free(ui, PTR_ERR(ui->clk)); ui->pclk = clk_get(&pdev->dev, "usb_hs_pclk"); if (IS_ERR(ui->pclk)) return usb_free(ui, PTR_ERR(ui->pclk)); ui->otgclk = clk_get(&pdev->dev, "usb_otg_clk"); if (IS_ERR(ui->otgclk)) ui->otgclk = NULL; ui->coreclk = clk_get(&pdev->dev, "usb_hs_core_clk"); if (IS_ERR(ui->coreclk)) ui->coreclk = NULL; ui->ebi1clk = clk_get(NULL, "ebi1_clk"); if (IS_ERR(ui->ebi1clk)) return usb_free(ui, PTR_ERR(ui->ebi1clk)); /* clear interrupts before requesting irq */ if (ui->coreclk) clk_enable(ui->coreclk); clk_enable(ui->clk); clk_enable(ui->pclk); if (ui->otgclk) clk_enable(ui->otgclk); writel(0, USB_USBINTR); writel(0, USB_OTGSC); if (ui->coreclk) clk_disable(ui->coreclk); if (ui->otgclk) clk_disable(ui->otgclk); clk_disable(ui->pclk); clk_disable(ui->clk); ret = request_irq(irq, usb_interrupt, 0, pdev->name, ui); if (ret) return usb_free(ui, ret); enable_irq_wake(irq); ui->irq = irq; ui->gadget.ops = &msm72k_ops; ui->gadget.is_dualspeed = 1; device_initialize(&ui->gadget.dev); dev_set_name(&ui->gadget.dev, "gadget"); ui->gadget.dev.parent = &pdev->dev; ui->gadget.dev.dma_mask = pdev->dev.dma_mask; the_usb_info = ui; usb_debugfs_init(ui); usb_prepare(ui); return 0; }
static void usb_setup(void) { const uint8_t *data = NULL; uint32_t datalen = 0; const usb_descriptor_list_t *list; uint32_t size; volatile uint8_t *reg; uint8_t epconf; const uint8_t *cfg; int i; switch (setup.wRequestAndType) { case 0x0500: // SET_ADDRESS break; case 0x0900: // SET_CONFIGURATION //serial_print("configure\n"); usb_configuration = setup.wValue; reg = &USB0_ENDPT1; cfg = usb_endpoint_config_table; // clear all BDT entries, free any allocated memory... for (i=4; i < NUM_ENDPOINTS*4; i++) { if (table[i].desc & BDT_OWN) { usb_free((usb_packet_t *)((uint8_t *)(table[i].addr) - 8)); table[i].desc = 0; } } usb_rx_memory_needed = 0; for (i=1; i < NUM_ENDPOINTS; i++) { epconf = *cfg++; *reg = epconf; reg += 4; if (epconf & USB_ENDPT_EPRXEN) { usb_packet_t *p; p = usb_malloc(); if (p) { table[index(i, RX, EVEN)].addr = p->buf; table[index(i, RX, EVEN)].desc = BDT_DESC(64, 0); } else { table[index(i, RX, EVEN)].desc = 0; usb_rx_memory_needed++; } p = usb_malloc(); if (p) { table[index(i, RX, ODD)].addr = p->buf; table[index(i, RX, ODD)].desc = BDT_DESC(64, 1); } else { table[index(i, RX, ODD)].desc = 0; usb_rx_memory_needed++; } } table[index(i, TX, EVEN)].desc = 0; table[index(i, TX, ODD)].desc = 0; } break; case 0x0880: // GET_CONFIGURATION reply_buffer[0] = usb_configuration; datalen = 1; data = reply_buffer; break; case 0x0080: // GET_STATUS (device) reply_buffer[0] = 0; reply_buffer[1] = 0; datalen = 2; data = reply_buffer; break; case 0x0082: // GET_STATUS (endpoint) if (setup.wIndex > NUM_ENDPOINTS) { // TODO: do we need to handle IN vs OUT here? endpoint0_stall(); return; } reply_buffer[0] = 0; reply_buffer[1] = 0; if (*(uint8_t *)(&USB0_ENDPT0 + setup.wIndex * 4) & 0x02) reply_buffer[0] = 1; data = reply_buffer; datalen = 2; break; case 0x0102: // CLEAR_FEATURE (endpoint) i = setup.wIndex & 0x7F; if (i > NUM_ENDPOINTS || setup.wValue != 0) { // TODO: do we need to handle IN vs OUT here? endpoint0_stall(); return; } (*(uint8_t *)(&USB0_ENDPT0 + setup.wIndex * 4)) &= ~0x02; // TODO: do we need to clear the data toggle here? break; case 0x0302: // SET_FEATURE (endpoint) i = setup.wIndex & 0x7F; if (i > NUM_ENDPOINTS || setup.wValue != 0) { // TODO: do we need to handle IN vs OUT here? endpoint0_stall(); return; } (*(uint8_t *)(&USB0_ENDPT0 + setup.wIndex * 4)) |= 0x02; // TODO: do we need to clear the data toggle here? break; case 0x0680: // GET_DESCRIPTOR case 0x0681: //serial_print("desc:"); //serial_phex16(setup.wValue); //serial_print("\n"); for (list = usb_descriptor_list; 1; list++) { if (list->addr == NULL) break; //if (setup.wValue == list->wValue && //(setup.wIndex == list->wIndex) || ((setup.wValue >> 8) == 3)) { if (setup.wValue == list->wValue && setup.wIndex == list->wIndex) { data = list->addr; datalen = list->length; #if 0 serial_print("Desc found, "); serial_phex32((uint32_t)data); serial_print(","); serial_phex16(datalen); serial_print(","); serial_phex(data[0]); serial_phex(data[1]); serial_phex(data[2]); serial_phex(data[3]); serial_phex(data[4]); serial_phex(data[5]); serial_print("\n"); #endif goto send; } } //serial_print("desc: not found\n"); endpoint0_stall(); return; #if defined(CDC_STATUS_INTERFACE) case 0x2221: // CDC_SET_CONTROL_LINE_STATE usb_cdc_line_rtsdtr = setup.wValue; //serial_print("set control line state\n"); break; case 0x2021: // CDC_SET_LINE_CODING //serial_print("set coding, waiting...\n"); return; #endif // TODO: this does not work... why? #if defined(SEREMU_INTERFACE) || defined(KEYBOARD_INTERFACE) case 0x0921: // HID SET_REPORT //serial_print(":)\n"); return; case 0x0A21: // HID SET_IDLE break; // case 0xC940: #endif default: endpoint0_stall(); return; } send: //serial_print("setup send "); //serial_phex32(data); //serial_print(","); //serial_phex16(datalen); //serial_print("\n"); if (datalen > setup.wLength) datalen = setup.wLength; size = datalen; if (size > EP0_SIZE) size = EP0_SIZE; endpoint0_transmit(data, size); data += size; datalen -= size; if (datalen == 0 && size < EP0_SIZE) return; size = datalen; if (size > EP0_SIZE) size = EP0_SIZE; endpoint0_transmit(data, size); data += size; datalen -= size; if (datalen == 0 && size < EP0_SIZE) return; ep0_tx_ptr = data; ep0_tx_len = datalen; }
void usb_isr(void) { uint8_t status, stat, t; //serial_print("isr"); //status = USB0_ISTAT; //serial_phex(status); //serial_print("\n"); restart: status = USB0_ISTAT; if ((status & USB_INTEN_SOFTOKEN /* 04 */ )) { if (usb_configuration) { t = usb_reboot_timer; if (t) { usb_reboot_timer = --t; if (!t) _reboot_Teensyduino_(); } #ifdef CDC_DATA_INTERFACE t = usb_cdc_transmit_flush_timer; if (t) { usb_cdc_transmit_flush_timer = --t; if (t == 0) usb_serial_flush_callback(); } #endif #if SEREMU_INTERFACE t = usb_seremu_transmit_flush_timer; if (t) { usb_seremu_transmit_flush_timer = --t; if (t == 0) usb_seremu_flush_callback(); } #endif } USB0_ISTAT = USB_INTEN_SOFTOKEN; } if ((status & USB_ISTAT_TOKDNE /* 08 */ )) { uint8_t endpoint; stat = USB0_STAT; //serial_print("token: ep="); //serial_phex(stat >> 4); //serial_print(stat & 0x08 ? ",tx" : ",rx"); //serial_print(stat & 0x04 ? ",odd\n" : ",even\n"); endpoint = stat >> 4; if (endpoint == 0) { usb_control(stat); } else { bdt_t *b = stat2bufferdescriptor(stat); usb_packet_t *packet = (usb_packet_t *)((uint8_t *)(b->addr) - 8); #if 0 serial_print("ep:"); serial_phex(endpoint); serial_print(", pid:"); serial_phex(BDT_PID(b->desc)); serial_print(((uint32_t)b & 8) ? ", odd" : ", even"); serial_print(", count:"); serial_phex(b->desc >> 16); serial_print("\n"); #endif endpoint--; // endpoint is index to zero-based arrays if (stat & 0x08) { // transmit usb_free(packet); packet = tx_first[endpoint]; if (packet) { //serial_print("tx packet\n"); tx_first[endpoint] = packet->next; b->addr = packet->buf; switch (tx_state[endpoint]) { case TX_STATE_BOTH_FREE_EVEN_FIRST: tx_state[endpoint] = TX_STATE_ODD_FREE; break; case TX_STATE_BOTH_FREE_ODD_FIRST: tx_state[endpoint] = TX_STATE_EVEN_FREE; break; case TX_STATE_EVEN_FREE: case TX_STATE_ODD_FREE: default: tx_state[endpoint] = TX_STATE_NONE_FREE; break; } b->desc = BDT_DESC(packet->len, ((uint32_t)b & 8) ? DATA1 : DATA0); } else { //serial_print("tx no packet\n"); switch (tx_state[endpoint]) { case TX_STATE_BOTH_FREE_EVEN_FIRST: case TX_STATE_BOTH_FREE_ODD_FIRST: break; case TX_STATE_EVEN_FREE: tx_state[endpoint] = TX_STATE_BOTH_FREE_EVEN_FIRST; break; case TX_STATE_ODD_FREE: tx_state[endpoint] = TX_STATE_BOTH_FREE_ODD_FIRST; break; default: tx_state[endpoint] = ((uint32_t)b & 8) ? TX_STATE_ODD_FREE : TX_STATE_EVEN_FREE; break; } } } else { // receive packet->len = b->desc >> 16; packet->index = 0; packet->next = NULL; if (rx_first[endpoint] == NULL) { //serial_print("rx 1st, epidx="); //serial_phex(endpoint); //serial_print(", packet="); //serial_phex32((uint32_t)packet); //serial_print("\n"); rx_first[endpoint] = packet; } else { //serial_print("rx Nth, epidx="); //serial_phex(endpoint); //serial_print(", packet="); //serial_phex32((uint32_t)packet); //serial_print("\n"); rx_last[endpoint]->next = packet; } rx_last[endpoint] = packet; // TODO: implement a per-endpoint maximum # of allocated packets // so a flood of incoming data on 1 endpoint doesn't starve // the others if the user isn't reading it regularly packet = usb_malloc(); if (packet) { b->addr = packet->buf; b->desc = BDT_DESC(64, ((uint32_t)b & 8) ? DATA1 : DATA0); } else { //serial_print("starving "); //serial_phex(endpoint + 1); //serial_print(((uint32_t)b & 8) ? ",odd\n" : ",even\n"); b->desc = 0; usb_rx_memory_needed++; } } } USB0_ISTAT = USB_ISTAT_TOKDNE; goto restart; }
static int msm72k_probe(struct platform_device *pdev) { struct usb_info *ui; struct msm_hsusb_gadget_platform_data *pdata; struct msm_otg *otg; int retval; INFO("msm72k_probe\n"); ui = kzalloc(sizeof(struct usb_info), GFP_KERNEL); if (!ui) return -ENOMEM; ui->pdev = pdev; if (pdev->dev.platform_data) { pdata = pdev->dev.platform_data; ui->phy_reset = pdata->phy_reset; ui->phy_init_seq = pdata->phy_init_seq; ui->chg_init = pdata->chg_init; ui->chg_connected = pdata->chg_connected; ui->chg_vbus_draw = pdata->chg_vbus_draw; ui->usb_connected = pdata->usb_connected; } if (ui->chg_init) ui->chg_init(1); ui->buf = dma_alloc_coherent(&pdev->dev, 4096, &ui->dma, GFP_KERNEL); if (!ui->buf) return usb_free(ui, -ENOMEM); ui->pool = dma_pool_create("msm72k_udc", NULL, 32, 32, 0); if (!ui->pool) return usb_free(ui, -ENOMEM); /* FIXME: dmb cannot be called from interrupt context * for the first time; Need to verify on how it needs * to be fixed */ dmb(); ui->xceiv = otg_get_transceiver(); if (!ui->xceiv) return usb_free(ui, -ENODEV); otg = to_msm_otg(ui->xceiv); ui->addr = otg->regs; ui->gadget.ops = &msm72k_ops; ui->gadget.is_dualspeed = 1; device_initialize(&ui->gadget.dev); strcpy(ui->gadget.dev.bus_id, "gadget"); ui->gadget.dev.parent = &pdev->dev; ui->gadget.dev.dma_mask = pdev->dev.dma_mask; the_usb_info = ui; pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY, DRIVER_NAME, PM_QOS_DEFAULT_VALUE); pm_qos_add_requirement(PM_QOS_SYSTEM_BUS_FREQ, DRIVER_NAME, PM_QOS_DEFAULT_VALUE); usb_debugfs_init(ui); usb_prepare(ui); retval = otg_set_peripheral(ui->xceiv, &ui->gadget); if (retval) { pr_err("%s: Cannot bind the transceiver, retval:(%d)\n", __func__, retval); return usb_free(ui, retval); } return 0; }