static inline void lpc_usb_open_ep(CORE* core, int num, USB_EP_TYPE type, unsigned int size) { unsigned int i; if (ep_data(core, num) != NULL) { error(ERROR_ALREADY_CONFIGURED); return; } EP* ep = malloc(sizeof(EP)); if (ep == NULL) return; ep->io = NULL; ep->fifo = (void*)USB_FREE_BUF_BASE; ep->io_active = false; ep->mps = size; //find free addr in FIFO for (i = 0; i < USB_EP_COUNT_MAX; ++i) { if (core->usb.in[i]) ep->fifo += ((core->usb.in[i]->mps + 63) & ~63); if (core->usb.out[i]) ep->fifo += ((core->usb.out[i]->mps + 63) & ~63); } num & USB_EP_IN ? (core->usb.in[USB_EP_NUM(num)] = ep) : (core->usb.out[USB_EP_NUM(num)] = ep); if (type == USB_EP_ISOCHRON) *USB_EP_LISTSTS(num, 0) |= USB_EP_LISTST_T; if (USB_EP_NUM(num)) *USB_EP_LISTSTS(num, 0) &= ~USB_EP_LISTST_D; LPC_USB->INTEN |= USB_EP_INT_BIT(num); }
static inline void lpc_usb_close_ep(CORE* core, int num) { if (!lpc_usb_ep_flush(core, num)) return; *USB_EP_LISTSTS(num, 0) |= USB_EP_LISTST_D; LPC_USB->INTEN &= ~USB_EP_INT_BIT(num); EP* ep = ep_data(core, num); free(ep); num & USB_EP_IN ? (core->usb.in[USB_EP_NUM(num)] = NULL) : (core->usb.out[USB_EP_NUM(num)] = NULL); }
static inline void stm32_otg_tx(EXO* exo, int num) { EP* ep = exo->usb.in[USB_EP_NUM(num)]; int size = ep->io->data_size - ep->size; if (size > ep->mps) size = ep->mps; OTG_FS_DEVICE->INEP[USB_EP_NUM(num)].TSIZ = (1 << OTG_FS_DEVICE_ENDPOINT_TSIZ_PKTCNT_POS) | (size << OTG_FS_DEVICE_ENDPOINT_TSIZ_XFRSIZ_POS); OTG_FS_DEVICE->INEP[USB_EP_NUM(num)].CTL |= OTG_FS_DEVICE_ENDPOINT_CTL_EPENA | OTG_FS_DEVICE_ENDPOINT_CTL_CNAK; memcpy4((void*)(OTG_FS_FIFO_BASE + USB_EP_NUM(num) * 0x1000), io_data(ep->io) + ep->size, size); ep->size += size; }
static inline void stm32_otg_close_ep(EXO* exo, int num) { if (!stm32_otg_ep_flush(exo, num)) return; ep_reg_data(num)->CTL &= ~OTG_FS_DEVICE_ENDPOINT_CTL_USBAEP; EP* ep = ep_data(exo, num); ep->mps = 0; if (num & USB_EP_IN) { OTG_FS_DEVICE->AINTMSK &= ~(1 << USB_EP_NUM(num)); OTG_FS_DEVICE->EIPEMPMSK &= ~(1 << USB_EP_NUM(num)); } kfree(ep); num & USB_EP_IN ? (exo->usb.in[USB_EP_NUM(num)] = NULL) : (exo->usb.out[USB_EP_NUM(num)] = NULL); }
void lpc_usb_rx_prepare(CORE* core, int num) { EP* ep = core->usb.out[USB_EP_NUM(num)]; *USB_EP_LISTSTS(num, 0) &= ~(USB_EP_LISTST_OFFSET_MASK | USB_EP_LISTST_NBYTES_MASK); *USB_EP_LISTSTS(num, 0) |= USB_EP_LISTST_OFFSET_SET(ep->fifo) | USB_EP_LISTST_NBYTES_SET(ep->mps); *USB_EP_LISTSTS(num, 0) |= USB_EP_LISTST_A; }
void hidd_kbd_class_configured(USBD* usbd, USB_CONFIGURATION_DESCRIPTOR* cfg) { USB_INTERFACE_DESCRIPTOR* iface; USB_ENDPOINT_DESCRIPTOR* ep; uint8_t in_ep, hid_iface; unsigned in_ep_size; in_ep = in_ep_size = hid_iface = 0; //check control/data ep here for (iface = usb_get_first_interface(cfg); iface != NULL; iface = usb_get_next_interface(cfg, iface)) { if (iface->bInterfaceClass == HID_INTERFACE_CLASS && iface->bInterfaceSubClass == HID_SUBCLASS_BOOT_INTERFACE && iface->bInterfaceProtocol == HID_PROTOCOL_KEYBOARD) { ep = (USB_ENDPOINT_DESCRIPTOR*)usb_interface_get_first_descriptor(cfg, iface, USB_ENDPOINT_DESCRIPTOR_TYPE); if (ep != NULL) { in_ep = USB_EP_NUM(ep->bEndpointAddress); in_ep_size = ep->wMaxPacketSize; hid_iface = iface->bInterfaceNumber; break; } } } //No HID descriptors in interface if (in_ep == 0) return; HIDD_KBD* hidd = (HIDD_KBD*)malloc(sizeof(HIDD_KBD)); if (hidd == NULL) return; hidd->io = io_create(in_ep_size); if (hidd->io == NULL) { hidd_kbd_destroy(hidd); return; } hidd->iface = hid_iface; hidd->in_ep = in_ep; hidd->suspended = false; hidd->over = false; hidd->idle = 0; hidd->boot_protocol = 1; hidd->state = USB_HID_KBD_IDLE; memset(&hidd->kbd, 0x00, sizeof(BOOT_KEYBOARD)); #if (USBD_HID_DEBUG_REQUESTS) printf("Found USB HID device class, EP%d, iface: %d\n", hidd->in_ep, hidd->iface); #endif //USBD_HID_DEBUG_REQUESTS usbd_register_interface(usbd, hidd->iface, &__HIDD_KBD_CLASS, hidd); usbd_register_endpoint(usbd, hidd->iface, hidd->in_ep); usbd_usb_ep_open(usbd, USB_EP_IN | hidd->in_ep, USB_EP_INTERRUPT, in_ep_size); }
static inline void stm32_otg_write(EXO* exo, IPC* ipc) { unsigned int ep_num = USB_EP_NUM(ipc->param1); EP* ep = exo->usb.in[ep_num]; if (stm32_usb_io_prepare(exo, ipc)) { ep->size = 0; ep->io_active = true; stm32_otg_tx(exo, USB_EP_IN | ep_num); } }
static inline void lpc_usb_write(CORE* core, IPC* ipc) { unsigned int num = ipc->param1; EP* ep = core->usb.in[USB_EP_NUM(num)]; if (lpc_usb_io_prepare(core, ipc)) { ep->size = 0; ep->io_active = true; lpc_usb_tx(core, num); } }
static inline void lpc_usb_read(CORE* core, IPC* ipc) { unsigned int num = ipc->param1; EP* ep = core->usb.out[USB_EP_NUM(num)]; if (lpc_usb_io_prepare(core, ipc)) { ep->io->data_size = 0; ep->size = ipc->param3; ep->io_active = true; lpc_usb_rx_prepare(core, num); } }
static inline void stm32_otg_read(EXO* exo, IPC* ipc) { unsigned int ep_num = USB_EP_NUM(ipc->param1); EP* ep = exo->usb.out[ep_num]; __disable_irq(); if (stm32_usb_io_prepare(exo, ipc)) { ep->io->data_size = 0; ep->size = ipc->param3; ep->io_active = true; stm32_otg_rx_prepare(exo, ep_num); } __enable_irq(); }
static inline void lpc_usb_tx(CORE* core, int num) { EP* ep = core->usb.in[USB_EP_NUM(num)]; int size = ep->io->data_size - ep->size; if (size > ep->mps) size = ep->mps; memcpy(ep->fifo, io_data(ep->io) + ep->size, size); ep->size += size; *USB_EP_LISTSTS(num, 0) &= ~(USB_EP_LISTST_OFFSET_MASK | USB_EP_LISTST_NBYTES_MASK); *USB_EP_LISTSTS(num, 0) |= USB_EP_LISTST_OFFSET_SET(ep->fifo) | USB_EP_LISTST_NBYTES_SET(size); *USB_EP_LISTSTS(num, 0) |= USB_EP_LISTST_A; }
static inline void lpc_usb_out(CORE* core, int num) { EP* ep = core->usb.out[USB_EP_NUM(num)]; unsigned int cnt = ep->mps - (((*USB_EP_LISTSTS(num, 0)) & USB_EP_LISTST_NBYTES_MASK) >> USB_EP_LISTST_NBYTES_POS); io_data_append(ep->io, ep->fifo, cnt); if (ep->io->data_size >= ep->size || cnt < ep->mps) { ep->io_active = false; iio_complete(core->usb.device, HAL_IO_CMD(HAL_USB, IPC_READ), num, ep->io); ep->io = NULL; } else lpc_usb_rx_prepare(core, num); }
static inline void lpc_usb_in(CORE* core, int num) { EP* ep = core->usb.in[USB_EP_NUM(num)]; //handle STATUS in for set address if (core->usb.addr && ep->size == 0) { LPC_USB->DEVCMDSTAT |= core->usb.addr; core->usb.addr = 0; } if (ep->size >= ep->io->data_size) { ep->io_active = false; iio_complete(core->usb.device, HAL_IO_CMD(HAL_USB, IPC_WRITE), USB_EP_IN | num, ep->io); ep->io = NULL; } else lpc_usb_tx(core, num); }
static inline void lpc_usb_ep_request(CORE* core, IPC* ipc) { if (USB_EP_NUM(ipc->param1) >= USB_EP_COUNT_MAX) { error(ERROR_INVALID_PARAMS); return; } switch (HAL_ITEM(ipc->cmd)) { case IPC_OPEN: lpc_usb_open_ep(core, ipc->param1, ipc->param2, ipc->param3); break; case IPC_CLOSE: lpc_usb_close_ep(core, ipc->param1); break; case IPC_FLUSH: lpc_usb_ep_flush(core, ipc->param1); break; case USB_EP_SET_STALL: lpc_usb_ep_set_stall(core, ipc->param1); break; case USB_EP_CLEAR_STALL: lpc_usb_ep_clear_stall(core, ipc->param1); break; case USB_EP_IS_STALL: ipc->param2 = lpc_usb_ep_is_stall(ipc->param1); break; case IPC_READ: lpc_usb_read(core, ipc); break; case IPC_WRITE: lpc_usb_write(core, ipc); //posted with io, no return IPC break; default: error(ERROR_NOT_SUPPORTED); break; } }
static void stm32_otg_ep_request(EXO* exo, IPC* ipc) { if (USB_EP_NUM(ipc->param1) >= USB_EP_COUNT_MAX) { kerror(ERROR_INVALID_PARAMS); return; } switch (HAL_ITEM(ipc->cmd)) { case IPC_OPEN: stm32_otg_open_ep(exo, ipc->param1, ipc->param2, ipc->param3); break; case IPC_CLOSE: stm32_otg_close_ep(exo, ipc->param1); break; case IPC_FLUSH: stm32_otg_ep_flush(exo, ipc->param1); break; case USB_EP_SET_STALL: stm32_otg_ep_set_stall(exo, ipc->param1); break; case USB_EP_CLEAR_STALL: stm32_otg_ep_clear_stall(exo, ipc->param1); break; case USB_EP_IS_STALL: ipc->param2 = stm32_otg_ep_is_stall(ipc->param1); break; case IPC_READ: stm32_otg_read(exo, ipc); break; case IPC_WRITE: stm32_otg_write(exo, ipc); break; default: kerror(ERROR_NOT_SUPPORTED); break; } }
static inline EP* ep_data(CORE* core, unsigned int num) { return (num & USB_EP_IN) ? (core->usb.in[USB_EP_NUM(num)]) : (core->usb.out[USB_EP_NUM(num)]); }
void mscd_class_configured(USBD* usbd, USB_CONFIGURATION_DESCRIPTOR* cfg) { USB_INTERFACE_DESCRIPTOR* iface; USB_ENDPOINT_DESCRIPTOR* ep; void* config; int i; unsigned int ep_num, ep_size, iface_num, lun_count; ep_num = 0; //check control/data ep here for (iface = usb_get_first_interface(cfg); iface != NULL; iface = usb_get_next_interface(cfg, iface)) { ep = (USB_ENDPOINT_DESCRIPTOR*)usb_interface_get_first_descriptor(cfg, iface, USB_ENDPOINT_DESCRIPTOR_TYPE); if (ep != NULL && iface->bInterfaceClass == MSC_INTERFACE_CLASS) { ep_num = USB_EP_NUM(ep->bEndpointAddress); ep_size = ep->wMaxPacketSize; iface_num = iface->bInterfaceNumber; break; } } //No MSC interface if (ep_num == 0) return; i = usbd_get_cfg(usbd, iface_num); config = usbd_get_cfg_data(usbd, i); lun_count = 0; if (usbd_get_cfg_data_size(usbd, i) > (int)sizeof(uint32_t)) lun_count = MSC_LUN_COUNT(config); if ((config == NULL) || (usbd_get_cfg_data_size(usbd, i) < (int)((sizeof(SCSI_STORAGE_DESCRIPTOR)) * lun_count + sizeof(uint32_t))) || (lun_count == 0)) { #if (USBD_MSC_DEBUG_ERRORS) printf("MSCD: Failed to read user configuration\n"); #endif //USBD_MSC_DEBUG_ERRORS return; } MSCD* mscd = (MSCD*)malloc(sizeof(MSCD) + sizeof(void*) * lun_count); if (mscd == NULL) return; mscd->iface_num = iface_num; mscd->ep_num = ep_num; mscd->ep_size = ep_size; mscd->usbd = usbd; mscd->control = io_create(ep_size); mscd->data = io_create(USBD_MSC_IO_SIZE + sizeof(STORAGE_STACK)); mscd->lun_count = lun_count; mscd->io_busy_mask = 0x00000000; mscd->io_owner = -1; mscd->cbw = io_data(mscd->control); for (i = 0; i < mscd->lun_count; ++i) MSCD_SCSI(mscd)[i] = scsis_create(mscd_host_cb, mscd, i, MSC_LUN_CONFIGURATION(config, i)); if (mscd->control == NULL || mscd->data == NULL || MSCD_SCSI(mscd)[mscd->lun_count - 1] == NULL) { #if (USBD_MSC_DEBUG_ERRORS) printf("MSCD: Out of memory\n"); #endif //USBD_MSC_DEBUG_ERRORS mscd_destroy(mscd); return; } for (i = 0; i < mscd->lun_count; ++i) scsis_init(MSCD_SCSI(mscd)[i]); #if (USBD_MSC_DEBUG_REQUESTS) printf("Found USB MSCD class, EP%d, size: %d, iface: %d\n", ep_num, ep_size, iface_num); #endif //USBD_MSC_DEBUG_REQUESTS usbd_register_interface(usbd, iface_num, &__MSCD_CLASS, mscd); usbd_register_endpoint(usbd, iface_num, ep_num); usbd_usb_ep_open(usbd, USB_EP_IN | ep_num, USB_EP_BULK, ep_size); usbd_usb_ep_open(usbd, ep_num, USB_EP_BULK, ep_size); mscd_read_cbw(usbd, mscd); }
static inline OTG_FS_DEVICE_ENDPOINT_TypeDef* ep_reg_data(int num) { return (num & USB_EP_IN) ? &(OTG_FS_DEVICE->INEP[USB_EP_NUM(num)]) : &(OTG_FS_DEVICE->OUTEP[USB_EP_NUM(num)]); }
void cdc_acmd_class_configured(USBD* usbd, USB_CONFIGURATION_DESCRIPTOR* cfg) { USB_INTERFACE_DESCRIPTOR* iface; USB_INTERFACE_DESCRIPTOR* diface; CDC_UNION_DESCRIPTOR* u; USB_ENDPOINT_DESCRIPTOR* ep; uint8_t data_ep, data_iface; uint16_t data_ep_size; uint8_t control_ep, control_iface; uint16_t control_ep_size; //check control/data ep here for (iface = usb_get_first_interface(cfg); iface != NULL; iface = usb_get_next_interface(cfg, iface)) { //also skip RNDIS if ((iface->bInterfaceClass != CDC_COMM_INTERFACE_CLASS) || (iface->bInterfaceSubClass != CDC_ACM) || (iface->bInterfaceProtocol == CDC_CP_VENDOR)) continue; #if (USBD_CDC_ACM_DEBUG) printf("Found USB CDC ACM interface: %d\n", iface->bInterfaceNumber); #endif //USBD_CDC_ACM_DEBUG //find union descriptor for (u = usb_interface_get_first_descriptor(cfg, iface, CS_INTERFACE); u != NULL; u = usb_interface_get_next_descriptor(cfg, u, CS_INTERFACE)) { if ((u->bDescriptorSybType == CDC_DESCRIPTOR_UNION) && (u->bControlInterface == iface->bInterfaceNumber) && (u->bFunctionLength > sizeof(CDC_UNION_DESCRIPTOR))) break; } if (u == NULL) { #if (USBD_CDC_ACM_DEBUG) printf("USB CDC ACM: Warning - no UNION descriptor, skipping interface\n"); #endif //USBD_CDC_ACM_DEBUG continue; } data_iface = ((uint8_t*)u)[sizeof(CDC_UNION_DESCRIPTOR)]; diface = usb_find_interface(cfg, data_iface); if (diface == NULL) { #if (USBD_CDC_ACM_DEBUG) printf("USB CDC ACM: Warning no data interface\n"); #endif //USBD_CDC_ACM_DEBUG continue; } #if (USBD_CDC_ACM_DEBUG) printf("Found USB CDC ACM data interface: %d\n", data_iface); #endif //USBD_CDC_ACM_DEBUG ep = (USB_ENDPOINT_DESCRIPTOR*)usb_interface_get_first_descriptor(cfg, diface, USB_ENDPOINT_DESCRIPTOR_TYPE); if (ep == NULL) { #if (USBD_CDC_ACM_DEBUG) printf("USB CDC ACM: Warning no data EP, skipping interface\n"); #endif //USBD_CDC_ACM_DEBUG continue; } data_ep = USB_EP_NUM(ep->bEndpointAddress); data_ep_size = ep->wMaxPacketSize; control_iface = iface->bInterfaceNumber; control_ep = control_ep_size = 0; ep = (USB_ENDPOINT_DESCRIPTOR*)usb_interface_get_first_descriptor(cfg, iface, USB_ENDPOINT_DESCRIPTOR_TYPE); if (ep != NULL) { control_ep = USB_EP_NUM(ep->bEndpointAddress); control_ep_size = ep->wMaxPacketSize; } //configuration is ok, applying CDC_ACMD* cdc_acmd = (CDC_ACMD*)malloc(sizeof(CDC_ACMD)); if (cdc_acmd == NULL) { #if (USBD_CDC_ACM_DEBUG) printf("USB CDC ACM: Out of memory\n"); #endif //USBD_CDC_ACM_DEBUG return; } cdc_acmd->data_iface = data_iface; cdc_acmd->data_ep = data_ep; cdc_acmd->data_ep_size = data_ep_size; cdc_acmd->tx = cdc_acmd->rx = NULL; cdc_acmd->tx_stream = cdc_acmd->rx_stream = cdc_acmd->tx_stream_handle = cdc_acmd->rx_stream_handle = INVALID_HANDLE; cdc_acmd->suspended = false; cdc_acmd->control_iface = control_iface; cdc_acmd->control_ep = control_ep; cdc_acmd->control_ep_size = control_ep_size; cdc_acmd->notify = NULL; cdc_acmd->notify_busy = cdc_acmd->notify_pending = false; #if (USBD_CDC_ACM_FLOW_CONTROL) cdc_acmd->flow_sending = false; cdc_acmd->flow_changed = false; cdc_acmd->break_count = 0; #endif //USBD_CDC_ACM_FLOW_CONTROL #if (USBD_CDC_ACM_TX_STREAM_SIZE) cdc_acmd->tx = io_create(cdc_acmd->data_ep_size); cdc_acmd->tx_stream = stream_create(USBD_CDC_ACM_RX_STREAM_SIZE); cdc_acmd->tx_stream_handle = stream_open(cdc_acmd->tx_stream); if (cdc_acmd->tx == NULL || cdc_acmd->tx_stream_handle == INVALID_HANDLE) { #if (USBD_CDC_ACM_DEBUG) printf("USB CDC ACM: Out of memory\n"); #endif //USBD_CDC_ACM_DEBUG cdc_acmd_destroy(cdc_acmd); return; } cdc_acmd->tx_size = 0; cdc_acmd->tx_idle = true; usbd_usb_ep_open(usbd, USB_EP_IN | cdc_acmd->data_ep, USB_EP_BULK, cdc_acmd->data_ep_size); stream_listen(cdc_acmd->tx_stream, USBD_IFACE(cdc_acmd->data_iface, 0), HAL_USBD_IFACE); #endif //USBD_CDC_ACM_TX_STREAM_SIZE #if (USBD_CDC_ACM_RX_STREAM_SIZE) cdc_acmd->rx = io_create(cdc_acmd->data_ep_size); cdc_acmd->rx_stream = stream_create(USBD_CDC_ACM_RX_STREAM_SIZE); cdc_acmd->rx_stream_handle = stream_open(cdc_acmd->rx_stream); if (cdc_acmd->rx == NULL || cdc_acmd->rx_stream_handle == INVALID_HANDLE) { #if (USBD_CDC_ACM_DEBUG) printf("USB CDC ACM: Out of memory\n"); #endif //USBD_CDC_ACM_DEBUG cdc_acmd_destroy(cdc_acmd); return; } cdc_acmd->rx_free = 0; usbd_usb_ep_open(usbd, cdc_acmd->data_ep, USB_EP_BULK, cdc_acmd->data_ep_size); usbd_usb_ep_read(usbd, cdc_acmd->data_ep, cdc_acmd->rx, cdc_acmd->data_ep_size); #endif //USBD_CDC_ACM_RX_STREAM_SIZE usbd_register_interface(usbd, cdc_acmd->data_iface, &__CDC_ACMD_CLASS, cdc_acmd); usbd_register_endpoint(usbd, cdc_acmd->data_iface, cdc_acmd->data_ep); if (control_ep_size) { if (cdc_acmd->control_ep_size < 16) { #if (USBD_CDC_ACM_DEBUG) printf("USB CDC ACM: Warning - control endpoint is too small(%d), 16 at least required to fit notify", cdc_acmd->control_ep_size); #endif //USBD_CDC_ACM_DEBUG cdc_acmd->notify = io_create(16); } else cdc_acmd->notify = io_create(cdc_acmd->control_ep_size); if (cdc_acmd->notify == NULL) { cdc_acmd_destroy(cdc_acmd); return; } usbd_usb_ep_open(usbd, USB_EP_IN | cdc_acmd->control_ep, USB_EP_INTERRUPT, cdc_acmd->control_ep_size); usbd_register_interface(usbd, cdc_acmd->control_iface, &__CDC_ACMD_CLASS, cdc_acmd); usbd_register_endpoint(usbd, cdc_acmd->control_iface, cdc_acmd->control_ep); cdc_acmd_notify_serial_state(usbd, cdc_acmd, CDC_SERIAL_STATE_DCD | CDC_SERIAL_STATE_DSR); } cdc_acmd->DTR = cdc_acmd->RTS = false; cdc_acmd->baud.baud = 115200; cdc_acmd->baud.data_bits = 8; cdc_acmd->baud.parity = 'N'; cdc_acmd->baud.stop_bits = 1; } }
static inline void stm32_otg_open_ep(EXO* exo, int num, USB_EP_TYPE type, unsigned int size) { if (ep_data(exo, num) != NULL) { kerror(ERROR_ALREADY_CONFIGURED); return; } EP* ep = kmalloc(sizeof(EP)); if (ep == NULL) return; num & USB_EP_IN ? (exo->usb.in[USB_EP_NUM(num)] = ep) : (exo->usb.out[USB_EP_NUM(num)] = ep); ep->io = NULL; ep->mps = 0; ep->io_active = false; int fifo_used, i; //enable, NAK uint32_t ctl = OTG_FS_DEVICE_ENDPOINT_CTL_USBAEP | OTG_FS_DEVICE_ENDPOINT_CTL_SNAK; //setup ep type, DATA0 for bulk/interrupt, EVEN frame for isochronous endpoint switch (type) { case USB_EP_CONTROL: ctl |= OTG_FS_DEVICE_ENDPOINT_CTL_EPTYP_CONTROL; break; case USB_EP_BULK: ctl |= OTG_FS_DEVICE_ENDPOINT_CTL_EPTYP_BULK | OTG_FS_DEVICE_ENDPOINT_CTL_DPID; break; case USB_EP_INTERRUPT: ctl |= OTG_FS_DEVICE_ENDPOINT_CTL_EPTYP_INTERRUPT | OTG_FS_DEVICE_ENDPOINT_CTL_DPID; break; case USB_EP_ISOCHRON: ctl |= OTG_FS_DEVICE_ENDPOINT_CTL_EPTYP_ISOCHRONOUS | OTG_FS_DEVICE_ENDPOINT_CTL_SEVNFRM; break; } if (num & USB_EP_IN) { //setup TX FIFO num for IN endpoint fifo_used = OTG_FS_GENERAL->RXFSIZ & 0xffff; for (i = 0; i < USB_EP_NUM(num); ++i) fifo_used += exo->usb.in[i]->mps / 4; if (USB_EP_NUM(num)) OTG_FS_GENERAL->DIEPTXF[USB_EP_NUM(num) - 1] = ((size / 4) << OTG_FS_GENERAL_TX0FSIZ_TX0FD_POS) | ((fifo_used * 4) | OTG_FS_GENERAL_TX0FSIZ_TX0FSA_POS); else OTG_FS_GENERAL->TX0FSIZ = ((size / 4) << OTG_FS_GENERAL_TX0FSIZ_TX0FD_POS) | ((fifo_used * 4) | OTG_FS_GENERAL_TX0FSIZ_TX0FSA_POS); ctl |= USB_EP_NUM(num) << OTG_FS_DEVICE_ENDPOINT_CTL_TXFNUM_POS; //enable interrupts for XFRCM OTG_FS_DEVICE->AINTMSK |= 1 << USB_EP_NUM(num); } //EP_OUT0 has differrent mps structure if (USB_EP_NUM(num) == 0) { switch (size) { case 8: ctl |= OTG_FS_DEVICE_ENDPOINT_CTL_MPSIZ0_8; break; case 16: ctl |= OTG_FS_DEVICE_ENDPOINT_CTL_MPSIZ0_16; break; case 32: ctl |= OTG_FS_DEVICE_ENDPOINT_CTL_MPSIZ0_32; break; default: ctl |= OTG_FS_DEVICE_ENDPOINT_CTL_MPSIZ0_64; } } else ctl |= size; ep->mps = size; ep_reg_data(num)->CTL = ctl; }
static inline EP* ep_data(EXO* exo, int num) { return (num & USB_EP_IN) ? (exo->usb.in[USB_EP_NUM(num)]) : (exo->usb.out[USB_EP_NUM(num)]); }