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_send(struct xusb *xusb, char *buf, int len, int timeout) { int ret; dump_packet(LOG_DEBUG, DBG_MASK, __FUNCTION__, buf, len); if(EP_OUT(xusb) & USB_ENDPOINT_IN) { ERR("%s called with an input endpoint 0x%x\n", __FUNCTION__, EP_OUT(xusb)); return -EINVAL; } ret = usb_bulk_write(xusb->handle, EP_OUT(xusb), buf, len, timeout); if(ret < 0) { /* * If the device was gone, it may be the * result of renumeration. Ignore it. */ if(ret != -ENODEV) { ERR("bulk_write to endpoint 0x%x failed: (%d) %s\n", EP_OUT(xusb), ret, usb_strerror()); dump_packet(LOG_ERR, DBG_MASK, "xbus_send[ERR]", buf, len); //exit(2); } else { DBG("bulk_write to endpoint 0x%x got ENODEV\n", EP_OUT(xusb)); xusb_close(xusb); } return ret; } else if(ret != len) { ERR("bulk_write to endpoint 0x%x short write: (%d) %s\n", EP_OUT(xusb), ret, usb_strerror()); dump_packet(LOG_ERR, DBG_MASK, "xbus_send[ERR]", buf, len); return -EFAULT; } return ret; }
int xusb_send(struct xusb *xusb, char *buf, int len, int timeout) { int ret; int retries = 0; dump_packet(LOG_DEBUG, DBG_MASK, __func__, buf, len); if (EP_OUT(xusb) & USB_ENDPOINT_IN) { ERR("%s called with an input endpoint 0x%x\n", __func__, EP_OUT(xusb)); return -EINVAL; } retry_write: ret = usb_bulk_write(xusb->handle, EP_OUT(xusb), buf, len, timeout); if (ret < 0) { /* * If the device was gone, it may be the * result of renumeration. Ignore it. */ if (ret != -ENODEV) { ERR("bulk_write to endpoint 0x%x failed: (%d) %s\n", EP_OUT(xusb), ret, usb_strerror()); dump_packet(LOG_ERR, DBG_MASK, "xusb_send[ERR]", buf, len); /*exit(2);*/ } else { DBG("bulk_write to endpoint 0x%x got ENODEV\n", EP_OUT(xusb)); xusb_close(xusb); } return ret; } if (!ret) { ERR("bulk_write to endpoint 0x%x short write[%d]: (%d)\n", EP_OUT(xusb), retries, ret); if (retries++ > MAX_RETRIES) return -EFAULT; usleep(100); goto retry_write; } if (ret != len) { ERR("bulk_write to endpoint 0x%x short write: (%d) %s\n", EP_OUT(xusb), ret, usb_strerror()); dump_packet(LOG_ERR, DBG_MASK, "xusb_send[ERR]", buf, len); return -EFAULT; } 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; }
void on_storage_request_buffers(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_allocate_buffer_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_read(usbd_get_usb(msc->usbd), EP_OUT(msc->ep_num), msc->current_buf, block_size); } #if (USB_MSC_DEBUG_FLOW) printf("USB_MSC: RX %d\n\r", size); #endif }
void on_msc_received(EP_CLASS ep, void* param) { USB_MSC* msc = (USB_MSC*)param; unsigned int block_size; switch (msc->state) { case MSC_STATE_CBW: memcpy(&msc->cbw, msc->current_buf, CBW_SIZE); queue_release_buffer(msc->queue, msc->current_buf); msc->current_buf = NULL; msc->scsi_requested = 0; msc->scsi_transferred = 0; event_set(msc->event); break; case MSC_STATE_DATA: queue_push(msc->queue, msc->current_buf); msc->current_buf = NULL; if (msc->scsi_transferred < msc->scsi_requested) { ASSERT(!queue_is_full(msc->queue)); msc->current_buf = queue_allocate_buffer_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_read(usbd_get_usb(msc->usbd), EP_OUT(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; default: break; } }
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); } } }