/* Requests on the control endpoint (aka EP0) */ static void ep0_rx(void) { uint16_t req = ep0_buf_rx[0]; /* bRequestType | bRequest */ /* interface specific requests */ if ((req & USB_RECIP_MASK) == USB_RECIP_INTERFACE) { uint8_t iface = ep0_buf_rx[1] & 0xff; if (iface < USB_IFACE_COUNT) usb_iface_request[iface](ep0_buf_rx, ep0_buf_tx); return; } /* TODO check setup bit ? */ if (req == (USB_DIR_IN | (USB_REQ_GET_DESCRIPTOR << 8))) { uint8_t type = ep0_buf_rx[1] >> 8; uint8_t idx = ep0_buf_rx[1] & 0xff; const uint8_t *str_desc; switch (type) { case USB_DT_DEVICE: /* Setup : Get device descriptor */ memcpy_usbram(ep0_buf_tx, (void *)&dev_desc, sizeof(dev_desc)); btable_ep[0].tx_count = sizeof(dev_desc); STM32_TOGGLE_EP(0, EP_TX_RX_MASK, EP_TX_RX_VALID, EP_STATUS_OUT /*null OUT transaction */); break; case USB_DT_CONFIGURATION: /* Setup : Get configuration desc */ memcpy_usbram(ep0_buf_tx, __usb_desc, USB_DESC_SIZE); /* set the real descriptor size */ ep0_buf_tx[1] = USB_DESC_SIZE; btable_ep[0].tx_count = MIN(ep0_buf_rx[3], USB_DESC_SIZE); STM32_TOGGLE_EP(0, EP_TX_RX_MASK, EP_TX_RX_VALID, EP_STATUS_OUT /*null OUT transaction */); break; case USB_DT_STRING: /* Setup : Get string descriptor */ if (idx >= USB_STR_COUNT) { /* The string does not exist : STALL */ STM32_TOGGLE_EP(0, EP_TX_RX_MASK, EP_RX_VALID | EP_TX_STALL, 0); return; /* don't remove the STALL */ } str_desc = usb_strings[idx]; memcpy_usbram(ep0_buf_tx, str_desc, str_desc[0]); btable_ep[0].tx_count = MIN(ep0_buf_rx[3], str_desc[0]); STM32_TOGGLE_EP(0, EP_TX_RX_MASK, EP_TX_RX_VALID, EP_STATUS_OUT /*null OUT transaction */); break; case USB_DT_DEVICE_QUALIFIER: /* Get device qualifier desc */ /* Not high speed : STALL next IN used as handshake */ STM32_TOGGLE_EP(0, EP_TX_RX_MASK, EP_RX_VALID | EP_TX_STALL, 0); break; default: /* unhandled descriptor */ goto unknown_req; } } else if (req == (USB_DIR_IN | (USB_REQ_GET_STATUS << 8))) {
void set_keyboard_report(uint64_t rpt) { /* Prevent the interrupt handler from sending the data (which would use * an incomplete buffer). */ hid_ep_data_ready = 0; hid_current_buf = hid_current_buf ? 0 : 1; memcpy_to_usbram((void *) usb_sram_addr(hid_ep_buf[hid_current_buf]), &rpt, sizeof(rpt)); /* Tell the interrupt handler to send the next buffer. */ hid_ep_data_ready = 1; if ((STM32_USB_EP(USB_EP_HID_KEYBOARD) & EP_TX_MASK) == EP_TX_VALID) { /* Endpoint is busy: we sneak in an address change to give us a * chance to send the most updated report. However, there is no * guarantee that this buffer is the one actually sent, so we * keep hid_ep_data_ready = 1, which will send a duplicated * report. */ btable_ep[USB_EP_HID_KEYBOARD].tx_addr = usb_sram_addr(hid_ep_buf[hid_current_buf]); hid_ep_data_ready = 1; } else if (atomic_read_clear(&hid_ep_data_ready)) { /* Endpoint is not busy, and interrupt handler did not just * send our last buffer: swap buffer, enable TX. */ btable_ep[USB_EP_HID_KEYBOARD].tx_addr = usb_sram_addr(hid_ep_buf[hid_current_buf]); STM32_TOGGLE_EP(USB_EP_HID_KEYBOARD, EP_TX_MASK, EP_TX_VALID, 0); } }
static void hid_keyboard_tx(void) { hid_tx(USB_EP_HID_KEYBOARD); if (hid_ep_data_ready) { /* swap buffer, enable TX */ btable_ep[USB_EP_HID_KEYBOARD].tx_addr = usb_sram_addr(hid_ep_buf[hid_current_buf]); STM32_TOGGLE_EP(USB_EP_HID_KEYBOARD, EP_TX_MASK, EP_TX_VALID, 0); } hid_ep_data_ready = 0; }
static int hid_iface_request(usb_uint *ep0_buf_rx, usb_uint *ep0_buf_tx) { if ((ep0_buf_rx[0] == (USB_DIR_IN | USB_RECIP_INTERFACE | (USB_REQ_GET_DESCRIPTOR << 8))) && (ep0_buf_rx[1] == (USB_HID_DT_REPORT << 8))) { /* Setup : HID specific : Get Report descriptor */ memcpy_to_usbram(ep0_buf_tx, report_desc, sizeof(report_desc)); btable_ep[0].tx_count = MIN(ep0_buf_rx[3], sizeof(report_desc)); STM32_TOGGLE_EP(0, EP_TX_RX_MASK, EP_TX_RX_VALID, EP_STATUS_OUT); CPRINTF("RPT %04x[l %04x]\n", STM32_USB_EP(0), ep0_buf_rx[3]); return 0; } return 1; }
void set_keyboard_report(uint64_t rpt) { memcpy_to_usbram((void *) usb_sram_addr(hid_ep_buf), &rpt, sizeof(rpt)); /* enable TX */ STM32_TOGGLE_EP(USB_EP_HID, EP_TX_MASK, EP_TX_VALID, 0); }
static void con_ep_tx(void) { /* clear IT */ STM32_TOGGLE_EP(USB_EP_CONSOLE, 0, 0, 0); }