static vsf_err_t vsfusbd_MSCBOT_ErrHandler(struct vsfusbd_device_t *device, struct vsfusbd_MSCBOT_param_t *param, uint8_t error) { param->CSW.dCSWStatus = error; // OUT: NACK(don't enable_OUT, if OUT is enabled, it will be disabled after data is sent) // IN: if (dCBWDataTransferLength > 0) // send_ZLP // send_CSW if (((param->CBW.bmCBWFlags & USBMSC_CBWFLAGS_DIR_MASK) == USBMSC_CBWFLAGS_DIR_IN) && (param->CBW.dCBWDataTransferLength > 0)) { if (param->scsi_transact != NULL) { param->scsi_transact->data_size = 0; } param->transact.ep = param->ep_in; param->transact.data_size = 0; param->transact.stream = NULL; param->transact.cb.on_finish = vsfusbd_MSCBOT_on_data_finish; param->transact.cb.param = param; return vsfusbd_ep_send(param->device, ¶m->transact); } else { vsfusbd_MSCBOT_SendCSW(device, param); } return VSFERR_NONE; }
static vsf_err_t vsfusbd_MSCBOT_SendCSW(struct vsfusbd_device_t *device, struct vsfusbd_MSCBOT_param_t *param) { struct USBMSC_CSW_t *CSW = ¶m->CSW; uint32_t remain_size; CSW->dCSWSignature = SYS_TO_LE_U32(USBMSC_CSW_SIGNATURE); CSW->dCSWTag = param->CBW.dCBWTag; remain_size = param->CBW.dCBWDataTransferLength; if (param->scsi_transact != NULL) { remain_size -= param->scsi_transact->data_size; vsfscsi_release_transact(param->scsi_transact); } CSW->dCSWDataResidue = SYS_TO_LE_U32(remain_size); param->bufstream.mem.buffer.buffer = (uint8_t *)¶m->CSW; param->bufstream.mem.buffer.size = sizeof(param->CSW); param->bufstream.mem.read = true; param->bufstream.stream.op = &bufstream_op; STREAM_INIT(¶m->bufstream); param->transact.ep = param->ep_in; param->transact.data_size = sizeof(param->CSW); param->transact.stream = (struct vsf_stream_t *)¶m->bufstream; param->transact.cb.on_finish = vsfusbd_MSCBOT_on_idle; param->transact.cb.param = param; return vsfusbd_ep_send(param->device, ¶m->transact); }
static void vsfusbd_CDCData_on_in(void *p) { struct vsfusbd_CDC_param_t *param = (struct vsfusbd_CDC_param_t *)p; struct vsf_stream_t *stream = param->stream_tx; uint32_t size; size = stream_get_data_size(stream); if (size > 0) { param->IN_transact.data_size = size; param->IN_transact.stream = param->stream_tx; param->IN_transact.zlp = true; // stream->callback_rx.on_inout will be overwritten vsfusbd_ep_send(param->device, ¶m->IN_transact); } }
static vsf_err_t versaloon_poll(uint8_t iface, struct vsfusbd_device_t *device) { struct vsfusbd_config_t *config = &device->config[device->configuration]; struct vsfusbd_Versaloon_param_t *param = (struct vsfusbd_Versaloon_param_t *)config->iface[iface].protocol_param; if(cmd_len & 0x80000000) { // A valid USB package has been received LED_USB_ON(); ProcessCommand(&buffer_out[0], cmd_len & 0xFFFF); if(rep_len > 0) { // indicate reply data is valid rep_len |= 0x80000000; } else { // no data to send, set cmd_len to 0 cmd_len = 0; } count_out = 0; // set USB receive pointer to 0 if(rep_len & 0x80000000) // there is valid data to be sent to PC { struct vsfusbd_transact_t *transact = &device->IN_transact[param->ep_in]; struct vsf_buffer_t *buffer = &transact->tbuffer.buffer; buffer->buffer = buffer_out; buffer->size = rep_len & 0xFFFF; transact->pkt.in.zlp = (rep_len & VERSALOON_REP_ZLP) ? true : false; transact->callback.callback = NULL; vsfusbd_ep_send(device, param->ep_in); // reset command length and reply length for next command cmd_len = 0; rep_len = 0; } LED_USB_OFF(); } return VSFERR_NONE; }
static struct vsfsm_state_t * vsfusbd_HID_evt_handler(struct vsfsm_t *sm, vsfsm_evt_t evt) { struct vsfusbd_HID_param_t *param = (struct vsfusbd_HID_param_t *)sm->user_data; struct vsfusbd_device_t *device = param->device; uint8_t i; switch (evt) { case VSFSM_EVT_INIT: if (param->ep_out != 0) { vsfusbd_set_OUT_handler(device, param->ep_out, vsfusbd_HID_OUT_hanlder); device->drv->ep.enable_OUT(param->ep_out); } param->bufstream.mem.read = true; param->bufstream.stream.op = &bufstream_op; param->bufstream.stream.callback_tx.on_connect = NULL; param->bufstream.stream.callback_tx.on_disconnect = NULL; param->bufstream.stream.callback_tx.on_inout = NULL; param->output_state = HID_OUTPUT_STATE_WAIT; param->busy = false; for(i = 0; i < param->num_of_report; i++) { struct vsfusbd_HID_report_t *report = ¶m->reports[i]; report->pos = 0; report->idle_cnt = 0; report->changed = true; } // enable timer param->timer4ms.sm = sm; param->timer4ms.evt = VSFUSBD_HID_EVT_TIMER4MS; param->timer4ms.interval = 4; param->timer4ms.trigger_cnt = -1; vsftimer_enqueue(¶m->timer4ms); break; case VSFUSBD_HID_EVT_TIMER4MS: { struct vsfusbd_HID_report_t *report; uint8_t i; for (i = 0; i < param->num_of_report; i++) { report = ¶m->reports[i]; if ((report->type == USB_HID_REPORT_INPUT) && (report->idle != 0)) { report->idle_cnt++; } } if (param->busy) { break; } } // fall through case VSFUSBD_HID_EVT_INREPORT: { struct vsfusbd_transact_t *transact = ¶m->IN_transact; struct vsfusbd_HID_report_t *report; uint8_t i; for (i = 0; i < param->num_of_report; i++) { report = ¶m->reports[i]; if ((report->type == USB_HID_REPORT_INPUT) && (report->changed || ((report->idle != 0) && (report->idle_cnt >= report->idle)))) { param->bufstream.mem.buffer = report->buffer; stream_init(¶m->stream); stream_connect_tx(¶m->stream); transact->ep = param->ep_in; transact->data_size = report->buffer.size; transact->stream = ¶m->stream; transact->zlp = false; transact->cb.on_finish = vsfusbd_HID_INREPORT_callback; transact->cb.param = param; vsfusbd_ep_send(device, transact); report->changed = false; report->idle_cnt = 0; param->busy = true; break; } } } break; } return NULL; }
static void vsfusbd_MSCBOT_on_cbw(void *p) { struct vsfusbd_MSCBOT_param_t *param = (struct vsfusbd_MSCBOT_param_t *)p; struct vsfusbd_device_t *device = param->device; struct vsfscsi_lun_t *lun; if (param->transact.data_size || (param->CBW.dCBWSignature != USBMSC_CBW_SIGNATURE) || (param->CBW.bCBWCBLength < 1) || (param->CBW.bCBWCBLength > 16)) { vsfusbd_MSCBOT_on_idle(param); return; } if (param->CBW.bCBWLUN > param->scsi_dev.max_lun) { reply_failure: vsfusbd_MSCBOT_ErrHandler(device, param, USBMSC_CSW_FAIL); return; } param->CSW.dCSWStatus = USBMSC_CSW_OK; lun = ¶m->scsi_dev.lun[param->CBW.bCBWLUN]; if (vsfscsi_execute(lun, param->CBW.CBWCB)) { goto reply_failure; } if (param->CBW.dCBWDataTransferLength) { struct vsfusbd_transact_t *transact = ¶m->transact; if (!lun->transact.data_size) { goto reply_failure; } param->scsi_transact = &lun->transact; transact->data_size = param->scsi_transact->data_size; transact->stream = param->scsi_transact->stream; transact->cb.on_finish = vsfusbd_MSCBOT_on_data_finish; transact->cb.param = param; if ((param->CBW.bmCBWFlags & USBMSC_CBWFLAGS_DIR_MASK) == USBMSC_CBWFLAGS_DIR_IN) { transact->ep = param->ep_in; vsfusbd_ep_send(param->device, transact); } else { transact->ep = param->ep_out; vsfusbd_ep_recv(param->device, transact); } } else { if (param->scsi_transact->data_size && param->scsi_transact) { vsfscsi_cancel_transact(param->scsi_transact); param->scsi_transact = NULL; } vsfusbd_MSCBOT_SendCSW(device, param); } }