void cdc_acmd_write(USBD* usbd, CDC_ACMD* cdc_acmd) { if (!cdc_acmd->DTR || !cdc_acmd->tx_idle || cdc_acmd->suspended) return; unsigned int to_write; if (cdc_acmd->tx_size == 0) cdc_acmd->tx_size = stream_get_size(cdc_acmd->tx_stream); to_write = cdc_acmd->tx_size; if (to_write > cdc_acmd->data_ep_size) to_write = cdc_acmd->data_ep_size; if (to_write) { cdc_acmd->tx_size -= to_write; if (stream_read(cdc_acmd->tx_stream_handle, io_data(cdc_acmd->tx), to_write)) { cdc_acmd->tx_idle = false; cdc_acmd->tx->data_size = to_write; usbd_usb_ep_write(usbd, cdc_acmd->data_ep, cdc_acmd->tx); } //just in case of driver failure else stream_listen(cdc_acmd->tx_stream, USBD_IFACE(cdc_acmd->data_iface, 0), HAL_USBD_IFACE); } else stream_listen(cdc_acmd->tx_stream, USBD_IFACE(cdc_acmd->data_iface, 0), HAL_USBD_IFACE); }
static void hidd_kbd_send_report(USBD* usbd, HIDD_KBD* hidd) { uint8_t* report = io_data(hidd->io); if (report == NULL) return; report[0] = hidd->kbd.modifier; report[1] = 0; hidd->io->data_size = 2; if (hidd->boot_protocol) io_data_append(hidd->io, &hidd->kbd.keys, 6); else io_data_append(hidd->io, &hidd->kbd.leds, sizeof(BOOT_KEYBOARD) - 2); usbd_usb_ep_write(usbd, hidd->in_ep, hidd->io); }
static void mscd_write_csw(USBD* usbd, MSCD* mscd) { CSW* csw = io_data(mscd->control); csw->dCSWSignature = MSC_CSW_SIGNATURE; csw->dCSWTag = mscd->tag; csw->dCSWDataResidue = mscd->residue; csw->bCSWStatus = mscd->csw_status; mscd->control->data_size = sizeof(CSW); usbd_usb_ep_write(usbd, mscd->ep_num, mscd->control); mscd->state = MSCD_STATE_CSW; #if (USBD_MSC_DEBUG_IO) printf("USB_MSC: dCSWTag: %d\n", csw->dCSWTag); printf("USB_MSC: dCSWDataResidue: %d\n", csw->dCSWDataResidue); printf("USB_MSC: bCSWStatus: %d\n", csw->bCSWStatus); #endif //USBD_MSC_DEBUG_IO }
static void mscd_request_processed(USBD* usbd, MSCD* mscd) { //need ZLP if data transfer is not fully complete if (mscd->residue && (((mscd->cbw->dCBWDataTransferLength - mscd->residue) % mscd->ep_size) == 0)) { mscd->control->data_size = 0; if (MSC_CBW_FLAG_DATA_IN(mscd->cbw->bmCBWFlags)) usbd_usb_ep_write(usbd, mscd->ep_num, mscd->control); else { //some hardware required to be multiple of MPS usbd_usb_ep_read(usbd, mscd->ep_num, mscd->control, mscd->ep_size); } mscd->state = MSCD_STATE_ZLP; } else mscd_write_csw(usbd, mscd); }
void mscd_host_cb(void* param, unsigned int id, SCSIS_RESPONSE response, unsigned int size) { MSCD* mscd = param; switch (response) { case SCSIS_RESPONSE_READ: if (size > mscd->residue) size = mscd->residue; mscd->residue -= size; //some hardware required to be multiple of MPS usbd_usb_ep_read(mscd->usbd, mscd->ep_num, mscd->data, (size + mscd->ep_size - 1) & ~(mscd->ep_size - 1)); break; case SCSIS_RESPONSE_WRITE: if (mscd->data->data_size > mscd->residue) mscd->data->data_size = mscd->residue; mscd->residue -= mscd->data->data_size; usbd_usb_ep_write(mscd->usbd, mscd->ep_num, mscd->data); break; case SCSIS_RESPONSE_PASS: mscd->csw_status = MSC_CSW_COMMAND_PASSED; mscd_request_processed(mscd->usbd, mscd); break; case SCSIS_RESPONSE_FAIL: mscd->csw_status = MSC_CSW_COMMAND_FAILED; mscd_request_processed(mscd->usbd, mscd); break; case SCSIS_RESPONSE_NEED_IO: if (mscd->io_owner < 0) { mscd->io_owner = id; scsis_host_give_io(MSCD_SCSI(mscd)[id], mscd->data); } else mscd->io_busy_mask |= 1 << id; break; case SCSIS_RESPONSE_RELEASE_IO: mscd_release_io(mscd); break; default: break; } }
void cdc_acmd_notify_serial_state(USBD* usbd, CDC_ACMD* cdc_acmd, unsigned int state) { if (cdc_acmd->notify_busy) { cdc_acmd->notify_state = state; cdc_acmd->notify_pending = true; return; } SETUP* setup = io_data(cdc_acmd->notify); setup->bmRequestType = BM_REQUEST_DIRECTION_DEVICE_TO_HOST | BM_REQUEST_TYPE_CLASS | BM_REQUEST_RECIPIENT_INTERFACE; setup->bRequest = CDC_SERIAL_STATE; setup->wValue = 0; setup->wIndex = 1; setup->wLength = 2; uint16_t* serial_state = (uint16_t*)(io_data(cdc_acmd->notify) + sizeof(SETUP)); *serial_state = state; cdc_acmd->notify->data_size = sizeof(SETUP) + 2; usbd_usb_ep_write(usbd, cdc_acmd->control_ep, cdc_acmd->notify); cdc_acmd->notify_busy = true; }