Created
February 8, 2021 15:54
-
-
Save notro/c80b99f311162dce65e7f8819a5321d9 to your computer and use it in GitHub Desktop.
Add control loopback test
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/usb/device/dev_lowlevel/dev_lowlevel.c b/usb/device/dev_lowlevel/dev_lowlevel.c | |
index cf53170..6facc39 100644 | |
--- a/usb/device/dev_lowlevel/dev_lowlevel.c | |
+++ b/usb/device/dev_lowlevel/dev_lowlevel.c | |
@@ -43,6 +43,8 @@ static volatile bool configured = false; | |
// Global data buffer for EP0 | |
static uint8_t ep0_buf[64]; | |
+// Loopback buffer for ep0 | |
+static uint8_t ep0_test_buf[64]; | |
// Struct defining the device configuration | |
static struct usb_device_configuration dev_config = { | |
@@ -207,7 +209,13 @@ void usb_device_init() { | |
// and when a setup packet is received | |
usb_hw->inte = USB_INTS_BUFF_STATUS_BITS | | |
USB_INTS_BUS_RESET_BITS | | |
- USB_INTS_SETUP_REQ_BITS; | |
+ USB_INTS_SETUP_REQ_BITS | | |
+ USB_INTS_STALL_BITS | | |
+ USB_INTS_ERROR_CRC_BITS | | |
+ USB_INTS_ERROR_BIT_STUFF_BITS | | |
+ USB_INTS_ERROR_RX_OVERFLOW_BITS | | |
+ USB_INTS_ERROR_RX_TIMEOUT_BITS | | |
+ USB_INTS_ERROR_DATA_SEQ_BITS; | |
// Set up endpoints (endpoint control registers) | |
// described by device configuration | |
@@ -241,7 +249,8 @@ void usb_start_transfer(struct usb_endpoint_configuration *ep, uint8_t *buf, uin | |
// For multi packet transfers see the tinyusb port. | |
assert(len <= 64); | |
- printf("Start transfer of len %d on ep addr 0x%x\n", len, ep->descriptor->bEndpointAddress); | |
+ printf("Start transfer of len %d on ep addr 0x%x pid=%u\n", | |
+ len, ep->descriptor->bEndpointAddress, ep->next_pid); | |
// Prepare buffer control register value | |
uint32_t val = len | USB_BUF_CTRL_AVAIL; | |
@@ -376,9 +385,15 @@ void usb_set_device_configuration(volatile struct usb_setup_packet *pkt) { | |
*/ | |
void usb_handle_setup_packet(void) { | |
volatile struct usb_setup_packet *pkt = (volatile struct usb_setup_packet *) &usb_dpram->setup_packet; | |
- uint8_t req_direction = pkt->bmRequestType; | |
+ uint8_t req_recipient = pkt->bmRequestType & USB_REQ_TYPE_RECIPIENT_MASK; | |
+ uint8_t req_type = pkt->bmRequestType & USB_REQ_TYPE_TYPE_MASK; | |
+ uint8_t req_direction = pkt->bmRequestType & USB_DIR_IN; | |
uint8_t req = pkt->bRequest; | |
+ printf("%s: bRequest=0x%02x bmRequestType=0x%x %s wLength=%u\n", | |
+ __func__, pkt->bRequest, pkt->bmRequestType, | |
+ req_direction == USB_DIR_IN ? "IN" : "OUT", pkt->wLength); | |
+ | |
// Reset PID to 1 for EP0 IN | |
usb_get_endpoint_configuration(EP0_IN_ADDR)->next_pid = 1u; | |
@@ -387,6 +402,14 @@ void usb_handle_setup_packet(void) { | |
usb_set_device_address(pkt); | |
} else if (req == USB_REQUEST_SET_CONFIGURATION) { | |
usb_set_device_configuration(pkt); | |
+ } else if (req_type == USB_REQ_TYPE_TYPE_VENDOR && | |
+ req_recipient == USB_REQ_TYPE_RECIPIENT_INTERFACE && | |
+ req == 0x01) { | |
+ printf("Loopback OUT request (0x%x)\r\n", pkt->bRequest); | |
+ | |
+ usb_get_endpoint_configuration(EP0_OUT_ADDR)->next_pid = 1; | |
+ | |
+ usb_start_transfer(usb_get_endpoint_configuration(EP0_OUT_ADDR), NULL, pkt->wLength); | |
} else { | |
printf("Other OUT request (0x%x)\r\n", pkt->bRequest); | |
} | |
@@ -413,6 +436,12 @@ void usb_handle_setup_packet(void) { | |
default: | |
printf("Unhandled GET_DESCRIPTOR type 0x%x\r\n", descriptor_type); | |
} | |
+ } else if (req_type == USB_REQ_TYPE_TYPE_VENDOR && | |
+ req_recipient == USB_REQ_TYPE_RECIPIENT_INTERFACE && | |
+ req == 0x02) { | |
+ printf("Loopback IN request (0x%x)\r\n", pkt->bRequest); | |
+ usb_start_transfer(usb_get_endpoint_configuration(EP0_IN_ADDR), ep0_test_buf, | |
+ pkt->wLength > 64 ? 64 : pkt->wLength); | |
} else { | |
printf("Other IN request (0x%x)\r\n", pkt->bRequest); | |
} | |
@@ -442,7 +471,7 @@ static void usb_handle_ep_buff_done(struct usb_endpoint_configuration *ep) { | |
*/ | |
static void usb_handle_buff_done(uint ep_num, bool in) { | |
uint8_t ep_addr = ep_num | (in ? USB_DIR_IN : 0); | |
- printf("EP %d (in = %d) done\n", ep_num, in); | |
+ printf("EP %d (in = %d, addr=0x%x) done\n", ep_num, in, ep_addr); | |
for (uint i = 0; i < USB_NUM_ENDPOINTS; i++) { | |
struct usb_endpoint_configuration *ep = &dev_config.endpoints[i]; | |
if (ep->descriptor && ep->handler) { | |
@@ -486,6 +515,39 @@ void isr_usbctrl(void) { | |
uint32_t status = usb_hw->ints; | |
uint32_t handled = 0; | |
+ printf("\n%s (status=0x%x) [\n", __func__, status); | |
+ | |
+ if (status & USB_INTS_ERROR_DATA_SEQ_BITS) { | |
+ printf("DATA SEQ error (wrong PID)\n"); | |
+ handled |= USB_INTS_ERROR_DATA_SEQ_BITS; | |
+ usb_hw_clear->sie_status = USB_SIE_STATUS_DATA_SEQ_ERROR_BITS; | |
+ } | |
+ if (status & USB_INTS_STALL_BITS) { | |
+ printf("STALL error\n"); | |
+ handled |= USB_INTS_STALL_BITS; | |
+ usb_hw_clear->sie_status = USB_SIE_STATUS_STALL_REC_BITS; | |
+ } | |
+ if (status & USB_INTS_ERROR_RX_TIMEOUT_BITS) { | |
+ printf("RX TIMEOUT error\n"); | |
+ handled |= USB_INTS_ERROR_RX_TIMEOUT_BITS; | |
+ usb_hw_clear->sie_status = USB_SIE_STATUS_RX_TIMEOUT_BITS; | |
+ } | |
+ if (status & USB_INTS_ERROR_RX_OVERFLOW_BITS) { | |
+ printf("RX OVERFLOW error\n"); | |
+ handled |= USB_INTS_ERROR_RX_OVERFLOW_BITS; | |
+ usb_hw_clear->sie_status = USB_SIE_STATUS_RX_OVERFLOW_BITS; | |
+ } | |
+ if (status & USB_INTS_ERROR_BIT_STUFF_BITS) { | |
+ printf("BIT STUFF error\n"); | |
+ handled |= USB_INTS_ERROR_BIT_STUFF_BITS; | |
+ usb_hw_clear->sie_status = USB_SIE_STATUS_BIT_STUFF_ERROR_BITS; | |
+ } | |
+ if (status & USB_INTS_ERROR_CRC_BITS) { | |
+ printf("CRC error\n"); | |
+ handled |= USB_INTS_ERROR_CRC_BITS; | |
+ usb_hw_clear->sie_status = USB_SIE_STATUS_CRC_ERROR_BITS; | |
+ } | |
+ | |
// Setup packet received | |
if (status & USB_INTS_SETUP_REQ_BITS) { | |
handled |= USB_INTS_SETUP_REQ_BITS; | |
@@ -511,6 +573,8 @@ void isr_usbctrl(void) { | |
if (status ^ handled) { | |
panic("Unhandled IRQ 0x%x\n", (uint) (status ^ handled)); | |
} | |
+ | |
+ printf("]\n"); | |
} | |
/** | |
@@ -521,6 +585,7 @@ void isr_usbctrl(void) { | |
* @param len the length that was sent | |
*/ | |
void ep0_in_handler(uint8_t *buf, uint16_t len) { | |
+ printf("%s: len=%u\n", __func__, len); | |
if (should_set_address) { | |
// Set actual device address in hardware | |
usb_hw->dev_addr_ctrl = dev_addr; | |
@@ -528,12 +593,18 @@ void ep0_in_handler(uint8_t *buf, uint16_t len) { | |
} else { | |
// Receive a zero length status packet from the host on EP0 OUT | |
struct usb_endpoint_configuration *ep = usb_get_endpoint_configuration(EP0_OUT_ADDR); | |
+ ep->next_pid = 1; | |
usb_start_transfer(ep, NULL, 0); | |
} | |
} | |
void ep0_out_handler(uint8_t *buf, uint16_t len) { | |
- ; | |
+ printf("%s: len=%u\n", __func__, len); | |
+ if (len) { | |
+ memcpy(ep0_test_buf, buf, len > 64 ? 64 : len); | |
+ struct usb_endpoint_configuration *ep = usb_get_endpoint_configuration(EP0_IN_ADDR); | |
+ usb_start_transfer(ep, NULL, 0); | |
+ } | |
} | |
// Device specific functions | |
diff --git a/usb/device/dev_lowlevel/dev_lowlevel_loopback.py b/usb/device/dev_lowlevel/dev_lowlevel_loopback.py | |
old mode 100755 | |
new mode 100644 | |
index 82bf478..9c7c7ac | |
--- a/usb/device/dev_lowlevel/dev_lowlevel_loopback.py | |
+++ b/usb/device/dev_lowlevel/dev_lowlevel_loopback.py | |
@@ -45,4 +45,18 @@ test_string = "Hello World!" | |
outep.write(test_string) | |
from_device = inep.read(len(test_string)) | |
-print("Device Says: {}".format(''.join([chr(x) for x in from_device]))) | |
+print("Bulk Endpoint Says: {}".format(''.join([chr(x) for x in from_device]))) | |
+ | |
+typ_vendor_int_in = usb.util.build_request_type( | |
+ usb.util.CTRL_IN, | |
+ usb.util.CTRL_TYPE_VENDOR, | |
+ usb.util.CTRL_RECIPIENT_INTERFACE) | |
+typ_vendor_int_out = usb.util.build_request_type( | |
+ usb.util.CTRL_OUT, | |
+ usb.util.CTRL_TYPE_VENDOR, | |
+ usb.util.CTRL_RECIPIENT_INTERFACE) | |
+ | |
+dev.ctrl_transfer(typ_vendor_int_out, 0x01, 0, 0, test_string) | |
+from_device = dev.ctrl_transfer(typ_vendor_int_in, 0x02, 0, 0, len(test_string)) | |
+ | |
+print("Control Endpoint Says: {}".format(''.join([chr(x) for x in from_device]))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment