From 911691461fe9cb2214add122feef1ea56cb25c96 Mon Sep 17 00:00:00 2001 From: Lephe Date: Sat, 4 Mar 2023 10:58:07 +0100 Subject: [PATCH] usb: clarify functions used to access endpoint configuration The previous scheme was really unclear. Now, an endpoint_t carries all of the endpoint info (instead of the global address being implicitly its array index, which couldn't be returned). An _endpoint address_ is the 8-bit value consisting of an endpoint number (bits 0x0f) and a direction (bit 0x80). The _global address_ of an endpoint is the address used to communicate with the host, and it is unique. The _local address_ of an endpoint is the interface-specific numbering that gint provides to allow interfaces to compose without risks of address collisions. The complete data for an endpoint can be queried with the new functions usb_get_endpoint_by_*() which accept global addresses, local addresses, and pipe numbers. --- src/usb/configure.c | 89 +++++++++++++++++++++---------------------- src/usb/setup.c | 5 ++- src/usb/usb_private.h | 36 ++++++++--------- 3 files changed, 61 insertions(+), 69 deletions(-) diff --git a/src/usb/configure.c b/src/usb/configure.c index deba0e0..324b582 100644 --- a/src/usb/configure.c +++ b/src/usb/configure.c @@ -1,6 +1,7 @@ #include #include "usb_private.h" #include +#include //--- // Endpoint assignment @@ -15,32 +16,37 @@ GCONSTRUCTOR static void usb_alloc(void) conf_ep = malloc(32 * sizeof *conf_ep); } -/* usb_configure_endpoint(): Get endpoint data for a concrete address */ -endpoint_t *usb_configure_endpoint(int endpoint) +endpoint_t *usb_get_endpoint_by_global_address(int global_address) { - /* Refuse access to endpoint 0, which is for the DCP */ - if(endpoint < 0 || ((endpoint & 0x0f) == 0)) return NULL; + global_address = (uint8_t)global_address; - int dir = (endpoint & 0x80) ? 0x10 : 0; - endpoint &= 0x7f; + /* Accept only valid non-DCP endpoints */ + if((global_address & 0x70) || !(global_address & 0x0f)) + return NULL; - if(endpoint <= 0 || endpoint > 15) return NULL; - return &conf_ep[dir + endpoint]; + int dir = (global_address & 0x80) ? 0x10 : 0; + return &conf_ep[dir + (global_address & 0x0f)]; } -/* usb_configure_address(): Get the concrete endpoint address */ -int usb_configure_address(usb_interface_t const *intf, int address) +endpoint_t *usb_get_endpoint_by_local_address(usb_interface_t const *intf, + int local_address) { - int dir = address & 0x80; - int base = address & 0x0f; - for(int i = 0; i < 32; i++) { - if(conf_ep[i].intf != intf) continue; - if((conf_ep[i].dc->bEndpointAddress & 0x0f) != base) continue; - return (i & 0x0f) | dir; + endpoint_t *ep = &conf_ep[i]; + if(ep->intf == intf && ep->dc->bEndpointAddress == local_address) + return ep; } - return -1; + return NULL; +} + +endpoint_t *usb_get_endpoint_by_pipe(int pipe) +{ + for(int i = 0; i < 32; i++) { + if(conf_ep[i].pipe == pipe) + return &conf_ep[i]; + } + return NULL; } //--- @@ -80,18 +86,8 @@ static int find_pipe(int type) int usb_configure_solve(usb_interface_t const **interfaces) { /* Reset the previous configuration */ - for(int i = 0; i < 16; i++) - { - conf_if[i] = NULL; - } - for(int i = 0; i < 32; i++) - { - conf_ep[i].intf = NULL; - conf_ep[i].dc = NULL; - conf_ep[i].pipe = 0; - conf_ep[i].bufnmb = 0; - conf_ep[i].bufsize = 0; - } + memset(conf_if, 0, 16 * sizeof *conf_if); + memset(conf_ep, 0, 32 * sizeof *conf_ep); /* Next interface number to assign */ int next_interface = 0; @@ -112,22 +108,26 @@ int usb_configure_solve(usb_interface_t const **interfaces) uint8_t const *dc = intf->dc[k]; if(dc[1] != USB_DC_ENDPOINT) continue; - /* If the same endpoint with a different direction has - already been assigned, use that */ - int address = usb_configure_address(intf, dc[2]); - if(address == -1) - { - if(next_endpoint >= 16) - return USB_OPEN_TOO_MANY_ENDPOINTS; + /* If the endpoint number has already been assigned in the other + direction, keep the same global endpoint number. */ + endpoint_t *dual_ep = usb_get_endpoint_by_local_address(intf, + dc[2] ^ 0x80); + + int address; + if(dual_ep) + address = dual_ep->global_address ^ 0x80; + else if(next_endpoint >= 16) + return USB_OPEN_TOO_MANY_ENDPOINTS; + else address = (next_endpoint++) | (dc[2] & 0x80); - } int pipe = find_pipe(dc[3] & 0x03); if(pipe < 0) return USB_OPEN_TOO_MANY_ENDPOINTS; - endpoint_t *ep = usb_configure_endpoint(address); + endpoint_t *ep = usb_get_endpoint_by_global_address(address); ep->intf = intf; ep->dc = (void *)dc; + ep->global_address = address; ep->pipe = pipe; ep->bufnmb = 0; ep->bufsize = 0; @@ -144,8 +144,8 @@ int usb_configure_solve(usb_interface_t const **interfaces) { usb_interface_endpoint_t *params = &intf->params[k]; - int a = usb_configure_address(intf, params->endpoint); - endpoint_t *ep = usb_configure_endpoint(a); + endpoint_t *ep = usb_get_endpoint_by_local_address(intf, + params->endpoint); if(!ep) return USB_OPEN_INVALID_PARAMS; uint bufsize = params->buffer_size >> 6; @@ -217,11 +217,8 @@ usb_interface_t const * const *usb_configure_interfaces(void) // API for interfaces //--- -int usb_interface_pipe(usb_interface_t const *interface, int endpoint) +int usb_interface_pipe(usb_interface_t const *intf, int address) { - int concrete_address = usb_configure_address(interface, endpoint); - endpoint_t const *ep = usb_configure_endpoint(concrete_address); - if(!ep) return -1; - - return ep->pipe; + endpoint_t const *ep = usb_get_endpoint_by_local_address(intf, address); + return ep ? ep->pipe : -1; } diff --git a/src/usb/setup.c b/src/usb/setup.c index 7197a1f..95184dd 100644 --- a/src/usb/setup.c +++ b/src/usb/setup.c @@ -113,8 +113,9 @@ static void write_configuration_descriptor(int wLength) else if(dc[1] == USB_DC_ENDPOINT) { usb_dc_endpoint_t edc = *(usb_dc_endpoint_t *)dc; - edc.bEndpointAddress = - usb_configure_address(interfaces[i], dc[2]); + endpoint_t *e = usb_get_endpoint_by_local_address(interfaces[i], + edc.bEndpointAddress); + edc.bEndpointAddress = e->global_address; dcp_write(&edc, edc.bLength); } /* Forward other descriptors */ diff --git a/src/usb/usb_private.h b/src/usb/usb_private.h index 02ed9fc..bb594d2 100644 --- a/src/usb/usb_private.h +++ b/src/usb/usb_private.h @@ -52,15 +52,16 @@ void usb_configure(void); void usb_configure_clear_pipes(void); /* endpoint_t: Driver information for each open endpoint in the device - There is one such structure for all 16 configurable endpoints, for each - direction (totaling 32). endpoint_get() is used to query the structure by - endpoint number (including the IN/OUT bit). */ + direction (totaling 32). use_get_endpoint_*() is used to query the + structure by endpoint address (including the IN/OUT bit). */ typedef struct { /* Which interface this endpoint belongs to */ usb_interface_t const *intf; - /* Associated endpoint descriptor */ + /* Associated endpoint descriptor. This contains the local address. */ usb_dc_endpoint_t const *dc; + /* Global address (endpoint number + direction) */ + uint8_t global_address; /* Associated pipe, must be a number from 1..9 */ uint8_t pipe; /* Allocated pipe buffer area; this is valid for pipes 1..5. The @@ -74,25 +75,18 @@ typedef struct { /* usb_configure_interfaces(): List configured interfaces */ usb_interface_t const * const *usb_configure_interfaces(void); -/* usb_configure_address(): Get the concrete endpoint address +/* Returns the endpoint information structure for the endpoint identified by a + global address. Returns NULL if the address is unused. */ +endpoint_t *usb_get_endpoint_by_global_address(int global_address); - This function returns the endpoint address associated with the provided - interface-numbered endpoint. The value is defined if an interface-provided - endpoint descriptor with bEndpointAddress equal to either (address) or - (address ^ 0x80) has been processed. +/* Returns the endpoint information structure for the endpoint identified by a + local (interface) address, NULL if the address is unused. */ +endpoint_t *usb_get_endpoint_by_local_address(usb_interface_t const *intf, + int local_address); - This function is used both to access endpoint data for an interface-provided - endpoint number, and to ensure that two interface-provided enpoint numbers - with same base and opposing directions are assigned the same concrete - endpoint number with its two opposing directions. - - @intf Interface that provided the address - @address Endpoint address (as numbered by the interaface) - -> Returns the assigned endpoint address, or -1 if unassigned. */ -int usb_configure_address(usb_interface_t const *intf, int address); - -/* usb_configure_endpoint(): Get endpoint data for a concrete address */ -endpoint_t *usb_configure_endpoint(int endpoint); +/* Returns the endpoint information structure for the endpoint identified by a + bound pipe. Returns NULL if the pipe is unused. */ +endpoint_t *usb_get_endpoint_by_pipe(int pipe); //--- // Pipe operations