int xusb_recv(struct xusb *xusb, char *buf, size_t len, int timeout) { int ret; int retries = 0; if (EP_IN(xusb) & USB_ENDPOINT_OUT) { ERR("%s called with an output endpoint 0x%x\n", __func__, EP_IN(xusb)); return -EINVAL; } retry_read: ret = usb_bulk_read(xusb->handle, EP_IN(xusb), buf, len, timeout); if (ret < 0) { DBG("bulk_read from endpoint 0x%x failed: (%d) %s\n", EP_IN(xusb), ret, usb_strerror()); memset(buf, 0, len); return ret; } if (!ret) { ERR("bulk_read to endpoint 0x%x short read[%d]: (%d)\n", EP_IN(xusb), retries, ret); if (retries++ > MAX_RETRIES) return -EFAULT; usleep(100); goto retry_read; } dump_packet(LOG_DEBUG, DBG_MASK, __func__, buf, ret); return ret; }
void on_msc_sent(EP_CLASS ep, void *param) { USB_MSC* msc = (USB_MSC*)param; unsigned int block_size; switch (msc->state) { case MSC_STATE_DATA: queue_release_buffer(msc->queue, msc->current_buf); msc->current_buf = NULL; if (msc->scsi_transferred < msc->scsi_requested) { ASSERT(!queue_is_empty(msc->queue)); msc->current_buf = queue_pull_ms(msc->queue, INFINITE); block_size = msc->scsi_requested - msc->scsi_transferred; if (block_size > msc->block_size) block_size = msc->block_size; msc->scsi_transferred += block_size; usb_write(usbd_get_usb(msc->usbd), EP_IN(msc->ep_num), msc->current_buf, block_size); } else event_set(msc->event); break; case MSC_STATE_CSW: msc->state = MSC_STATE_CSW_SENT; msc_send_csw(msc); break; case MSC_STATE_CSW_SENT: msc->state = MSC_STATE_CBW; //same buffer will be used for next cbw usb_read(usbd_get_usb(msc->usbd), EP_OUT(msc->ep_num), msc->current_buf, CBW_SIZE); break; default: break; } }
int xusb_recv(struct xusb *xusb, char *buf, size_t len, int timeout) { int ret; if(EP_IN(xusb) & USB_ENDPOINT_OUT) { ERR("%s called with an output endpoint 0x%x\n", __FUNCTION__, EP_IN(xusb)); return -EINVAL; } ret = usb_bulk_read(xusb->handle, EP_IN(xusb), buf, len, timeout); if(ret < 0) { DBG("bulk_read from endpoint 0x%x failed: (%d) %s\n", EP_IN(xusb), ret, usb_strerror()); memset(buf, 0, len); return ret; } dump_packet(LOG_DEBUG, DBG_MASK, __FUNCTION__, buf, ret); return ret; }
int xusb_claim_interface(struct xusb *xusb) { const struct usb_device_descriptor *dev_desc; int ret; assert(xusb); xusb_open(xusb); /* If it's not open yet... */ if (usb_claim_interface(xusb->handle, xusb->interface_num) != 0) { ERR("usb_claim_interface %d in '%s': %s\n", xusb->interface_num, xusb->devpath_tail, usb_strerror()); return 0; } xusb->is_claimed = 1; xusb_fill_strings(xusb); dev_desc = &xusb->dev->descriptor; DBG("ID=%04X:%04X Manufacturer=[%s] Product=[%s] " "SerialNumber=[%s] Interface=[%s]\n", dev_desc->idVendor, dev_desc->idProduct, xusb->iManufacturer, xusb->iProduct, xusb->iSerialNumber, xusb->iInterface); if (xtalk_option_use_clear_halt()) { DBG("Using clear_halt()\n"); if (usb_clear_halt(xusb->handle, EP_OUT(xusb)) != 0) { ERR("Clearing output endpoint: %s\n", usb_strerror()); return 0; } if (usb_clear_halt(xusb->handle, EP_IN(xusb)) != 0) { ERR("Clearing input endpoint: %s\n", usb_strerror()); return 0; } } ret = xusb_flushread(xusb); if (ret < 0) { ERR("xusb_flushread failed: %d\n", ret); return 0; } return 1; }
static inline void msc_send_csw(USB_MSC* msc) { ASSERT(!queue_is_full(msc->queue)); msc->current_buf = queue_allocate_buffer_ms(msc->queue, INFINITE); CSW* csw = (CSW*)msc->current_buf; csw->bCSWStatus = msc->csw_status; csw->dCSWSignature = CBW_MAGIC; csw->dCSWTag = msc->cbw.dCBWTag; csw->dCSWDataResidue = msc->scsi_transferred; usb_write(usbd_get_usb(msc->usbd), EP_IN(msc->ep_num), msc->current_buf, CSW_SIZE); #if (USB_MSC_DEBUG_FLOW) printf("USB_MSC: TX CSW\n\r"); #endif #if (USB_DEBUG_ERRORS) if (csw->bCSWStatus == CSW_STATUS_ERROR) printf("MSC phase error\n\r"); #endif }
void on_storage_buffer_filled(void* param, unsigned int size) { USB_MSC* msc = (USB_MSC*)param; unsigned int block_size; CRITICAL_ENTER; msc->scsi_requested += size; CRITICAL_LEAVE; if (event_is_set(msc->event)) { event_clear(msc->event); msc->current_buf = queue_pull_ms(msc->queue, INFINITE); block_size = msc->scsi_requested - msc->scsi_transferred; if (block_size > msc->block_size) block_size = msc->block_size; msc->scsi_transferred += block_size; usb_write(usbd_get_usb(msc->usbd), EP_IN(msc->ep_num), msc->current_buf, block_size); } #if (USB_MSC_DEBUG_FLOW) printf("USB_MSC: TX %d\n\r", size); #endif }
void usb_msc_thread(void* param) { USB_MSC* msc = (USB_MSC*)param; for (;;) { event_wait_ms(msc->event, INFINITE); msc->state = MSC_STATE_DATA; //process received CBW if (msc->cbw.dCBWSignature == CBW_MAGIC && msc->cbw.bCBWCBLength <= MAX_CB_SIZE) { msc->csw_status = CSW_STATUS_OK; #if (USB_MSC_DEBUG_FLOW) printf("USB_MSC: dCBWTag: %08x\n\r", msc->cbw.dCBWTag); printf("USB_MSC: dCBWDataTransferLength: %08x\n\r", msc->cbw.dCBWDataTransferLength); printf("USB_MSC: dCBWDataFlags: %02x\n\r", msc->cbw.bmCBWFlags); printf("USB_MSC: dCBWLUN: %02x\n\r", msc->cbw.bCBWLUN); printf("USB_MSC: dCBWCB:"); int i; for (i = 0; i < msc->cbw.bCBWCBLength; ++i) printf(" %02x", msc->cbw.CBWCB[i]); printf(" (%d)\n\r", msc->cbw.bCBWCBLength); #endif if (!scsi_cmd(msc->scsi, (char*)msc->cbw.CBWCB, msc->cbw.bCBWCBLength)) msc->csw_status = CSW_STATUS_FAILED; //wait for transfer completed in any case event_wait_ms(msc->event, INFINITE); } //CBW invalid, phase ERROR else { #if (USB_DEBUG_ERRORS) printf("Invalid CBW\n\r"); #endif msc->csw_status = CSW_STATUS_ERROR; } event_clear(msc->event); msc->state = MSC_STATE_CSW; //need zlp? if ((msc->scsi_transferred % msc->ep_size) == 0 && msc->cbw.dCBWDataTransferLength != 0 && msc->scsi_transferred < msc->cbw.dCBWDataTransferLength) { if (msc->cbw.bmCBWFlags & 0x80) usb_write(usbd_get_usb(msc->usbd), EP_IN(msc->ep_num), NULL, 0); else usb_read(usbd_get_usb(msc->usbd), EP_OUT(msc->ep_num), NULL, 0); #if (USB_MSC_DEBUG_FLOW) if (msc->cbw.bmCBWFlags & 0x80) printf("USB_MSC: TX ZLP\n\r"); else printf("USB_MSC: RX ZLP\n\r"); #endif } //send csw directly else { if (msc->cbw.bmCBWFlags & 0x80) on_msc_sent(EP_IN(msc->ep_num), msc); else on_msc_received(EP_OUT(msc->ep_num), msc); } } }