mirror of
https://git.planet-casio.com/Lephenixnoir/gint.git
synced 2025-05-24 04:25:10 +02:00
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.
This commit is contained in:
parent
aee67a76f3
commit
911691461f
3 changed files with 61 additions and 69 deletions
|
@ -1,6 +1,7 @@
|
||||||
#include <gint/usb.h>
|
#include <gint/usb.h>
|
||||||
#include "usb_private.h"
|
#include "usb_private.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
//---
|
//---
|
||||||
// Endpoint assignment
|
// Endpoint assignment
|
||||||
|
@ -15,32 +16,37 @@ GCONSTRUCTOR static void usb_alloc(void)
|
||||||
conf_ep = malloc(32 * sizeof *conf_ep);
|
conf_ep = malloc(32 * sizeof *conf_ep);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* usb_configure_endpoint(): Get endpoint data for a concrete address */
|
endpoint_t *usb_get_endpoint_by_global_address(int global_address)
|
||||||
endpoint_t *usb_configure_endpoint(int endpoint)
|
|
||||||
{
|
{
|
||||||
/* Refuse access to endpoint 0, which is for the DCP */
|
global_address = (uint8_t)global_address;
|
||||||
if(endpoint < 0 || ((endpoint & 0x0f) == 0)) return NULL;
|
|
||||||
|
|
||||||
int dir = (endpoint & 0x80) ? 0x10 : 0;
|
/* Accept only valid non-DCP endpoints */
|
||||||
endpoint &= 0x7f;
|
if((global_address & 0x70) || !(global_address & 0x0f))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
if(endpoint <= 0 || endpoint > 15) return NULL;
|
int dir = (global_address & 0x80) ? 0x10 : 0;
|
||||||
return &conf_ep[dir + endpoint];
|
return &conf_ep[dir + (global_address & 0x0f)];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* usb_configure_address(): Get the concrete endpoint address */
|
endpoint_t *usb_get_endpoint_by_local_address(usb_interface_t const *intf,
|
||||||
int usb_configure_address(usb_interface_t const *intf, int address)
|
int local_address)
|
||||||
{
|
{
|
||||||
int dir = address & 0x80;
|
|
||||||
int base = address & 0x0f;
|
|
||||||
|
|
||||||
for(int i = 0; i < 32; i++)
|
for(int i = 0; i < 32; i++)
|
||||||
{
|
{
|
||||||
if(conf_ep[i].intf != intf) continue;
|
endpoint_t *ep = &conf_ep[i];
|
||||||
if((conf_ep[i].dc->bEndpointAddress & 0x0f) != base) continue;
|
if(ep->intf == intf && ep->dc->bEndpointAddress == local_address)
|
||||||
return (i & 0x0f) | dir;
|
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)
|
int usb_configure_solve(usb_interface_t const **interfaces)
|
||||||
{
|
{
|
||||||
/* Reset the previous configuration */
|
/* Reset the previous configuration */
|
||||||
for(int i = 0; i < 16; i++)
|
memset(conf_if, 0, 16 * sizeof *conf_if);
|
||||||
{
|
memset(conf_ep, 0, 32 * sizeof *conf_ep);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Next interface number to assign */
|
/* Next interface number to assign */
|
||||||
int next_interface = 0;
|
int next_interface = 0;
|
||||||
|
@ -112,22 +108,26 @@ int usb_configure_solve(usb_interface_t const **interfaces)
|
||||||
uint8_t const *dc = intf->dc[k];
|
uint8_t const *dc = intf->dc[k];
|
||||||
if(dc[1] != USB_DC_ENDPOINT) continue;
|
if(dc[1] != USB_DC_ENDPOINT) continue;
|
||||||
|
|
||||||
/* If the same endpoint with a different direction has
|
/* If the endpoint number has already been assigned in the other
|
||||||
already been assigned, use that */
|
direction, keep the same global endpoint number. */
|
||||||
int address = usb_configure_address(intf, dc[2]);
|
endpoint_t *dual_ep = usb_get_endpoint_by_local_address(intf,
|
||||||
if(address == -1)
|
dc[2] ^ 0x80);
|
||||||
{
|
|
||||||
if(next_endpoint >= 16)
|
int address;
|
||||||
|
if(dual_ep)
|
||||||
|
address = dual_ep->global_address ^ 0x80;
|
||||||
|
else if(next_endpoint >= 16)
|
||||||
return USB_OPEN_TOO_MANY_ENDPOINTS;
|
return USB_OPEN_TOO_MANY_ENDPOINTS;
|
||||||
|
else
|
||||||
address = (next_endpoint++) | (dc[2] & 0x80);
|
address = (next_endpoint++) | (dc[2] & 0x80);
|
||||||
}
|
|
||||||
|
|
||||||
int pipe = find_pipe(dc[3] & 0x03);
|
int pipe = find_pipe(dc[3] & 0x03);
|
||||||
if(pipe < 0) return USB_OPEN_TOO_MANY_ENDPOINTS;
|
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->intf = intf;
|
||||||
ep->dc = (void *)dc;
|
ep->dc = (void *)dc;
|
||||||
|
ep->global_address = address;
|
||||||
ep->pipe = pipe;
|
ep->pipe = pipe;
|
||||||
ep->bufnmb = 0;
|
ep->bufnmb = 0;
|
||||||
ep->bufsize = 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];
|
usb_interface_endpoint_t *params = &intf->params[k];
|
||||||
|
|
||||||
int a = usb_configure_address(intf, params->endpoint);
|
endpoint_t *ep = usb_get_endpoint_by_local_address(intf,
|
||||||
endpoint_t *ep = usb_configure_endpoint(a);
|
params->endpoint);
|
||||||
if(!ep) return USB_OPEN_INVALID_PARAMS;
|
if(!ep) return USB_OPEN_INVALID_PARAMS;
|
||||||
|
|
||||||
uint bufsize = params->buffer_size >> 6;
|
uint bufsize = params->buffer_size >> 6;
|
||||||
|
@ -217,11 +217,8 @@ usb_interface_t const * const *usb_configure_interfaces(void)
|
||||||
// API for interfaces
|
// 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_get_endpoint_by_local_address(intf, address);
|
||||||
endpoint_t const *ep = usb_configure_endpoint(concrete_address);
|
return ep ? ep->pipe : -1;
|
||||||
if(!ep) return -1;
|
|
||||||
|
|
||||||
return ep->pipe;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,8 +113,9 @@ static void write_configuration_descriptor(int wLength)
|
||||||
else if(dc[1] == USB_DC_ENDPOINT)
|
else if(dc[1] == USB_DC_ENDPOINT)
|
||||||
{
|
{
|
||||||
usb_dc_endpoint_t edc = *(usb_dc_endpoint_t *)dc;
|
usb_dc_endpoint_t edc = *(usb_dc_endpoint_t *)dc;
|
||||||
edc.bEndpointAddress =
|
endpoint_t *e = usb_get_endpoint_by_local_address(interfaces[i],
|
||||||
usb_configure_address(interfaces[i], dc[2]);
|
edc.bEndpointAddress);
|
||||||
|
edc.bEndpointAddress = e->global_address;
|
||||||
dcp_write(&edc, edc.bLength);
|
dcp_write(&edc, edc.bLength);
|
||||||
}
|
}
|
||||||
/* Forward other descriptors */
|
/* Forward other descriptors */
|
||||||
|
|
|
@ -52,15 +52,16 @@ void usb_configure(void);
|
||||||
void usb_configure_clear_pipes(void);
|
void usb_configure_clear_pipes(void);
|
||||||
|
|
||||||
/* endpoint_t: Driver information for each open endpoint in the device
|
/* endpoint_t: Driver information for each open endpoint in the device
|
||||||
|
|
||||||
There is one such structure for all 16 configurable endpoints, for each
|
There is one such structure for all 16 configurable endpoints, for each
|
||||||
direction (totaling 32). endpoint_get() is used to query the structure by
|
direction (totaling 32). use_get_endpoint_*() is used to query the
|
||||||
endpoint number (including the IN/OUT bit). */
|
structure by endpoint address (including the IN/OUT bit). */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* Which interface this endpoint belongs to */
|
/* Which interface this endpoint belongs to */
|
||||||
usb_interface_t const *intf;
|
usb_interface_t const *intf;
|
||||||
/* Associated endpoint descriptor */
|
/* Associated endpoint descriptor. This contains the local address. */
|
||||||
usb_dc_endpoint_t const *dc;
|
usb_dc_endpoint_t const *dc;
|
||||||
|
/* Global address (endpoint number + direction) */
|
||||||
|
uint8_t global_address;
|
||||||
/* Associated pipe, must be a number from 1..9 */
|
/* Associated pipe, must be a number from 1..9 */
|
||||||
uint8_t pipe;
|
uint8_t pipe;
|
||||||
/* Allocated pipe buffer area; this is valid for pipes 1..5. The
|
/* 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_configure_interfaces(): List configured interfaces */
|
||||||
usb_interface_t const * const *usb_configure_interfaces(void);
|
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
|
/* Returns the endpoint information structure for the endpoint identified by a
|
||||||
interface-numbered endpoint. The value is defined if an interface-provided
|
local (interface) address, NULL if the address is unused. */
|
||||||
endpoint descriptor with bEndpointAddress equal to either (address) or
|
endpoint_t *usb_get_endpoint_by_local_address(usb_interface_t const *intf,
|
||||||
(address ^ 0x80) has been processed.
|
int local_address);
|
||||||
|
|
||||||
This function is used both to access endpoint data for an interface-provided
|
/* Returns the endpoint information structure for the endpoint identified by a
|
||||||
endpoint number, and to ensure that two interface-provided enpoint numbers
|
bound pipe. Returns NULL if the pipe is unused. */
|
||||||
with same base and opposing directions are assigned the same concrete
|
endpoint_t *usb_get_endpoint_by_pipe(int pipe);
|
||||||
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);
|
|
||||||
|
|
||||||
//---
|
//---
|
||||||
// Pipe operations
|
// Pipe operations
|
||||||
|
|
Loading…
Add table
Reference in a new issue