mirror of
https://git.planet-casio.com/Lephenixnoir/gint.git
synced 2024-12-28 04:23:36 +01:00
usb: improve driver with updated knowledge and prepare reading
* Finish updating the register list * Use RTC-based timeouts to not involve more interrupts * Be a lot more conservative about PID=BUF * Start setting up parameters and checking invariants for future bidirectional communications
This commit is contained in:
parent
cf2b86deaa
commit
18e0db3886
7 changed files with 177 additions and 150 deletions
|
@ -125,7 +125,7 @@ typedef struct {
|
|||
that the precision of the delay is limited by the speed at which the
|
||||
keyboard is scanned, which is nowhere near microsecond-level. By
|
||||
default (128 Hz) the precision is about 7.8 ms. */
|
||||
keydev_repeat_profile_t repeater;
|
||||
keydev_repeat_profile_t repeater;
|
||||
|
||||
} GPACKEDENUM keydev_transform_t;
|
||||
|
||||
|
@ -204,8 +204,8 @@ typedef struct {
|
|||
/* Event queue (circular buffer) */
|
||||
key_event_t queue[KEYBOARD_QUEUE_SIZE];
|
||||
|
||||
/* Parameters for the standard repeat function */
|
||||
int rep_standard_first, rep_standard_next;
|
||||
/* Parameters for the standard repeat function */
|
||||
int rep_standard_first, rep_standard_next;
|
||||
|
||||
} keydev_t;
|
||||
|
||||
|
|
|
@ -190,7 +190,9 @@ typedef volatile struct
|
|||
/* Module function selection registers.
|
||||
WARNING: These are the SH7724 bits, not necessarily the SH7305! */
|
||||
word_union(MSELCRA,
|
||||
uint16_t :16;
|
||||
uint16_t :8;
|
||||
uint16_t UNKNOWN_USB :2;
|
||||
uint16_t :6;
|
||||
);
|
||||
word_union(MSELCRB,
|
||||
uint16_t XTAL_USB :2;
|
||||
|
|
|
@ -11,6 +11,19 @@ extern "C" {
|
|||
|
||||
#include <gint/defs/types.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
word_union(TRE,
|
||||
uint16_t :6;
|
||||
uint16_t TRENB :1; /* Transaction Counter Enable */
|
||||
uint16_t TRCLR :1; /* Transaction Counter Clear */
|
||||
uint16_t :8;
|
||||
);
|
||||
word_union(TRN,
|
||||
uint16_t TRCNT :16; /* Transaction Counter */
|
||||
);
|
||||
} sh7305_usb_pipetr;
|
||||
|
||||
typedef volatile struct
|
||||
{
|
||||
/* System Configuration Control Register */
|
||||
|
@ -192,7 +205,19 @@ typedef volatile struct
|
|||
uint16_t VALID :1; /* USB Request Reception */
|
||||
uint16_t CTSQ :3; /* Control Transfer Stage */
|
||||
);
|
||||
pad(4);
|
||||
word_union(INTSTS1,
|
||||
uint16_t _1 :1; /* Unknown role */
|
||||
uint16_t BCHG :1; /* Bus Change */
|
||||
uint16_t :1;
|
||||
uint16_t DTCH :1; /* Disconnection Detection */
|
||||
uint16_t ATTCH :1; /* Connection Detection */
|
||||
uint16_t :4;
|
||||
uint16_t EOFERR :1; /* EOF Error Detection */
|
||||
uint16_t SIGN :1; /* Setup Transaction Error */
|
||||
uint16_t SACK :1; /* Setup Transaction Normal Response */
|
||||
uint16_t :4;
|
||||
);
|
||||
pad(2);
|
||||
|
||||
/* BRDY Interrupt Status Register */
|
||||
uint16_t BRDYSTS;
|
||||
|
@ -333,53 +358,8 @@ typedef volatile struct
|
|||
);
|
||||
pad(14);
|
||||
|
||||
/* PIPEn Transaction Counter Enable Registers and */
|
||||
/* PIPEn Transaction Counter Registers */
|
||||
word_union(PIPE1TRE,
|
||||
uint16_t :6;
|
||||
uint16_t TRENB :1; /* Transaction Counter Enable */
|
||||
uint16_t TRCLR :1; /* Transaction Counter Clear */
|
||||
uint16_t :8;
|
||||
);
|
||||
word_union(PIPE1TRN,
|
||||
uint16_t TRCNT :16; /* Transaction Counter */
|
||||
);
|
||||
word_union(PIPE2TRE,
|
||||
uint16_t :6;
|
||||
uint16_t TRENB :1; /* Transaction Counter Enable */
|
||||
uint16_t TRCLR :1; /* Transaction Counter Clear */
|
||||
uint16_t :8;
|
||||
);
|
||||
word_union(PIPE2TRN,
|
||||
uint16_t TRCNT :16; /* Transaction Counter */
|
||||
);
|
||||
word_union(PIPE3TRE,
|
||||
uint16_t :6;
|
||||
uint16_t TRENB :1; /* Transaction Counter Enable */
|
||||
uint16_t TRCLR :1; /* Transaction Counter Clear */
|
||||
uint16_t :8;
|
||||
);
|
||||
word_union(PIPE3TRN,
|
||||
uint16_t TRCNT :16; /* Transaction Counter */
|
||||
);
|
||||
word_union(PIPE4TRE,
|
||||
uint16_t :6;
|
||||
uint16_t TRENB :1; /* Transaction Counter Enable */
|
||||
uint16_t TRCLR :1; /* Transaction Counter Clear */
|
||||
uint16_t :8;
|
||||
);
|
||||
word_union(PIPE4TRN,
|
||||
uint16_t TRCNT :16; /* Transaction Counter */
|
||||
);
|
||||
word_union(PIPE5TRE,
|
||||
uint16_t :6;
|
||||
uint16_t TRENB :1; /* Transaction Counter Enable */
|
||||
uint16_t TRCLR :1; /* Transaction Counter Clear */
|
||||
uint16_t :8;
|
||||
);
|
||||
word_union(PIPE5TRN,
|
||||
uint16_t TRCNT :16; /* Transaction Counter */
|
||||
);
|
||||
/* Transaction Counter Registers (PIPE1..PIPE5 only) */
|
||||
sh7305_usb_pipetr PIPETR[5];
|
||||
pad(0x1e);
|
||||
|
||||
uint16_t REG_C2;
|
||||
|
|
109
src/usb/pipes.c
109
src/usb/pipes.c
|
@ -18,21 +18,42 @@
|
|||
void usb_pipe_configure(int address, endpoint_t const *ep)
|
||||
{
|
||||
/* Maps USB 2.0 transfer types to SH7305 USB module transfer types */
|
||||
static uint8_t type_map[4] = { 0, 3, 1, 2 };
|
||||
USB.PIPESEL.PIPESEL = ep->pipe;
|
||||
static uint8_t type_map[4] = {
|
||||
0, TYPE_ISOCHRONOUS, TYPE_BULK, TYPE_INTERRUPT };
|
||||
|
||||
USB.PIPECFG.TYPE = type_map[ep->dc->bmAttributes & 0x03];
|
||||
USB.PIPECFG.BFRE = 0;
|
||||
if(ep->pipe > 0) {
|
||||
/* Set PID to NAK so we can modify the pipe's configuration */
|
||||
USB.PIPECTR[ep->pipe-1].PID = PID_NAK;
|
||||
usb_while(USB.PIPECTR[ep->pipe-1].PBUSY);
|
||||
}
|
||||
|
||||
int type = type_map[ep->dc->bmAttributes & 0x03];
|
||||
bool dir_transmitting = (address & 0x80) != 0;
|
||||
bool dir_receiving = !dir_transmitting;
|
||||
|
||||
USB.PIPESEL.PIPESEL = ep->pipe;
|
||||
USB.PIPECFG.TYPE = type;
|
||||
USB.PIPECFG.BFRE = dir_receiving;
|
||||
/* Enable continuous mode on all bulk transfer pipes
|
||||
TODO: Also make it double mode*/
|
||||
USB.PIPECFG.DBLB = 0;
|
||||
USB.PIPECFG.CNTMD = 1;
|
||||
USB.PIPECFG.SHTNAK = 0;
|
||||
USB.PIPECFG.DIR = (address & 0x80) != 0;
|
||||
USB.PIPECFG.CNTMD = (type == TYPE_BULK);
|
||||
USB.PIPECFG.SHTNAK = 1;
|
||||
USB.PIPECFG.DIR = dir_transmitting;
|
||||
USB.PIPECFG.EPNUM = (address & 0x0f);
|
||||
|
||||
USB.PIPEBUF.BUFSIZE = ep->bufsize - 1;
|
||||
USB.PIPEBUF.BUFNMB = ep->bufnmb;
|
||||
|
||||
USB.PIPEMAXP.MXPS = le16toh(ep->dc->wMaxPacketSize);
|
||||
|
||||
USB.PIPEPERI.IFIS = 0;
|
||||
USB.PIPEPERI.IITV = 0;
|
||||
|
||||
if(ep->pipe >= 1 && ep->pipe <= 5) {
|
||||
USB.PIPETR[ep->pipe-1].TRE.TRCLR = 1;
|
||||
USB.PIPETR[ep->pipe-1].TRE.TRENB = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* usb_pipe_clear(): Clear all data in the pipe */
|
||||
|
@ -41,16 +62,14 @@ void usb_pipe_clear(int pipe)
|
|||
if(pipe <= 0 || pipe > 9) return;
|
||||
|
||||
/* Set PID=NAK then use ACLRM to clear the pipe */
|
||||
USB.PIPECTR[pipe-1].PID = 0;
|
||||
USB.PIPECTR[pipe-1].PID = PID_NAK;
|
||||
usb_while(USB.PIPECTR[pipe-1].PBUSY);
|
||||
|
||||
USB.PIPECTR[pipe-1].ACLRM = 1;
|
||||
USB.PIPECTR[pipe-1].ACLRM = 0;
|
||||
usb_while(!USB.PIPECTR[pipe-1].BSTS);
|
||||
|
||||
USB.PIPECTR[pipe-1].PID = 0;
|
||||
usb_while(USB.PIPECTR[pipe-1].CSSTS || USB.PIPECTR[pipe-1].PBUSY);
|
||||
|
||||
/* Clear the sequence bit (important after a world switch since we restore
|
||||
hardware registers but the host connection is starting from scratch!) */
|
||||
USB.PIPECTR[pipe-1].SQCLR = 1;
|
||||
usb_while(USB.PIPECTR[pipe-1].SQMON != 0);
|
||||
}
|
||||
|
@ -65,22 +84,22 @@ typedef enum {
|
|||
CF, /* Used for the Default Control Pipe */
|
||||
D0F, /* FIFO Controller 0 */
|
||||
D1F, /* FIFO Controller 1 */
|
||||
} fifo_t;
|
||||
} GPACKEDENUM fifo_t;
|
||||
|
||||
enum {
|
||||
FIFO_READ = 0, /* Read mode */
|
||||
FIFO_WRITE = 1, /* Write mode */
|
||||
};
|
||||
|
||||
/* fifo_access(): Get a FIFO controller for a pipe */
|
||||
static fifo_t fifo_access(int pipe)
|
||||
/* fifo_find_available_controller(): Get a FIFO controller for a pipe */
|
||||
static fifo_t fifo_find_available_controller(int pipe)
|
||||
{
|
||||
/* TODO: USB: fifo_access(): Possibly use CFIFO for all pipes? */
|
||||
if(pipe == 0) return CF;
|
||||
/* Find a free controller */
|
||||
|
||||
if(USB.D0FIFOSEL.CURPIPE == 0) return D0F;
|
||||
USB_LOG("Wait D0 is unavailable\n");
|
||||
USB_LOG("D0 is unavailable!\n");
|
||||
if(USB.D1FIFOSEL.CURPIPE == 0) return D1F;
|
||||
USB_LOG("D1 is unavailable!\n");
|
||||
|
||||
return NOF;
|
||||
}
|
||||
|
@ -90,38 +109,58 @@ static void fifo_bind(fifo_t ct, int pipe, int mode, int size)
|
|||
{
|
||||
size = (size - (size == 4) - 1) & 3;
|
||||
|
||||
if(pipe == 0)
|
||||
{
|
||||
if(USB.CFIFOSEL.ISEL == 1 && USB.DCPCTR.PID == 1) return;
|
||||
if(pipe == 0) {
|
||||
if(USB.CFIFOSEL.ISEL == 1 && USB.DCPCTR.PID == 1)
|
||||
return;
|
||||
|
||||
if(mode == FIFO_WRITE) USB.DCPCTR.PID = 1;
|
||||
if(mode == FIFO_WRITE)
|
||||
USB.DCPCTR.PID = PID_BUF;
|
||||
/* RCNT=0 REW=0 MBW=size BIGEND=1 ISEL=mode CURPIPE=0 */
|
||||
USB.CFIFOSEL.word = 0x0100 | (mode << 5) | (size << 10);
|
||||
usb_while(!USB.CFIFOCTR.FRDY || USB.CFIFOSEL.ISEL != mode);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set PID to BUF */
|
||||
USB.PIPECTR[pipe-1].PID = 1;
|
||||
__typeof__(USB.D0FIFOSEL) sel;
|
||||
sel.RCNT = 0;
|
||||
sel.REW = 0;
|
||||
sel.DCLRM = (mode == FIFO_READ);
|
||||
sel.DREQE = 0;
|
||||
sel.MBW = size;
|
||||
sel.BIGEND = 1;
|
||||
sel.CURPIPE = pipe;
|
||||
|
||||
/* RCNT=0 REW=0 DCLRM=0 DREQE=0 MBW=size BIGEND=1 */
|
||||
if(ct == D0F) USB.D0FIFOSEL.word = 0x0100 | (size << 10) | pipe;
|
||||
if(ct == D1F) USB.D1FIFOSEL.word = 0x0100 | (size << 10) | pipe;
|
||||
if(ct == D0F) {
|
||||
USB.D0FIFOSEL.word = sel.word;
|
||||
usb_while(!USB.D0FIFOCTR.FRDY || USB.PIPECFG.DIR != mode);
|
||||
}
|
||||
if(ct == D1F) {
|
||||
USB.D1FIFOSEL.word = sel.word;
|
||||
usb_while(!USB.D1FIFOCTR.FRDY || USB.PIPECFG.DIR != mode);
|
||||
}
|
||||
|
||||
if(ct == D0F) usb_while(!USB.D0FIFOCTR.FRDY || USB.PIPECFG.DIR!=mode);
|
||||
if(ct == D1F) usb_while(!USB.D1FIFOCTR.FRDY || USB.PIPECFG.DIR!=mode);
|
||||
/* Enable USB comunication! */
|
||||
USB.PIPECTR[pipe-1].PID = PID_BUF;
|
||||
}
|
||||
|
||||
/* fifo_unbind(): Free a FIFO */
|
||||
/* fifo_unbind(): Unbind a FIFO */
|
||||
static void fifo_unbind(fifo_t ct)
|
||||
{
|
||||
if(ct == D0F)
|
||||
{
|
||||
int pipe = -1;
|
||||
if(ct == D0F) pipe = USB.D0FIFOSEL.CURPIPE;
|
||||
if(ct == D1F) pipe = USB.D1FIFOSEL.CURPIPE;
|
||||
if(pipe <= 0)
|
||||
return;
|
||||
|
||||
/* Disbable communication on the pipe */
|
||||
USB.PIPECTR[pipe-1].PID = PID_NAK;
|
||||
usb_while(USB.PIPECTR[pipe-1].PBUSY);
|
||||
|
||||
if(ct == D0F) {
|
||||
USB.D0FIFOSEL.word = 0x0000;
|
||||
usb_while(USB.D0FIFOSEL.CURPIPE != 0);
|
||||
}
|
||||
if(ct == D1F)
|
||||
{
|
||||
if(ct == D1F) {
|
||||
USB.D1FIFOSEL.word = 0x0000;
|
||||
usb_while(USB.D1FIFOSEL.CURPIPE != 0);
|
||||
}
|
||||
|
@ -327,7 +366,7 @@ int usb_write_async(int pipe, void const *data, int size, int unit_size,
|
|||
otherwise try to get a new free one */
|
||||
/* TODO: usb_write_async(): TOC/TOU race on controller being free */
|
||||
fifo_t ct = t->ct;
|
||||
if(ct == NOF) ct = fifo_access(pipe);
|
||||
if(ct == NOF) ct = fifo_find_available_controller(pipe);
|
||||
if(ct == NOF) return USB_WRITE_NOFIFO;
|
||||
|
||||
t->data = data;
|
||||
|
|
|
@ -30,21 +30,14 @@ uint16_t usb_dc_string(uint16_t const *literal, size_t len)
|
|||
dc->bDescriptorType = USB_DC_STRING;
|
||||
for(size_t i = 0; i < len; i++) dc->data[i] = htole16(literal[i]);
|
||||
|
||||
/* Try to make room in the array; if realloc() fails, try to allocate
|
||||
again in another arena */
|
||||
/* Try to make room in the array */
|
||||
size_t new_size = (array_size + 1) * sizeof(*array);
|
||||
usb_dc_string_t **new_array = realloc(array, new_size);
|
||||
|
||||
if(!new_array)
|
||||
{
|
||||
new_array = malloc(new_size);
|
||||
if(!new_array)
|
||||
{
|
||||
free(dc);
|
||||
return 0;
|
||||
}
|
||||
memcpy(new_array, array, array_size * sizeof(*array));
|
||||
free(array);
|
||||
free(dc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
array = new_array;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include <gint/mpu/usb.h>
|
||||
#include <gint/mpu/power.h>
|
||||
#include <gint/mpu/cpg.h>
|
||||
#include <gint/mpu/pfc.h>
|
||||
#include <gint/drivers.h>
|
||||
#include <gint/drivers/states.h>
|
||||
#include <gint/clock.h>
|
||||
|
@ -76,11 +77,8 @@ static void hpoweron(void)
|
|||
{
|
||||
if(hpowered()) return;
|
||||
|
||||
/* TODO: USB: Proper handling of MSELCRA and MSELCRB */
|
||||
uint16_t volatile *MSELCRA = (void *)0xa4050180;
|
||||
uint16_t volatile *MSELCRB = (void *)0xa4050182;
|
||||
*MSELCRA &= 0xff3f;
|
||||
*MSELCRB &= 0x3fff;
|
||||
SH7305_PFC.MSELCRA.UNKNOWN_USB = 0;
|
||||
SH7305_PFC.MSELCRB.XTAL_USB = 0;
|
||||
|
||||
/* Leave some delay for the clock to settle. The OS leaves
|
||||
100 ms, but it just never seems necessary. */
|
||||
|
@ -106,9 +104,6 @@ static void hpoweron_write(void)
|
|||
|
||||
static void hpoweroff(void)
|
||||
{
|
||||
uint16_t volatile *MSELCRA = (void *)0xa4050180;
|
||||
uint16_t volatile *MSELCRB = (void *)0xa4050182;
|
||||
|
||||
SH7305_USB_UPONCR.word = 0x0000;
|
||||
|
||||
/* This delay is crucial and omitting it has caused constant freezes in
|
||||
|
@ -120,12 +115,15 @@ static void hpoweroff(void)
|
|||
sleep_us_spin(1000);
|
||||
|
||||
/* The values used by the OS (a PFC driver could do better) */
|
||||
*MSELCRB = (*MSELCRB & 0x3fff) | 0xc000;
|
||||
*MSELCRA = (*MSELCRA & 0xff3f) | 0x0040;
|
||||
SH7305_PFC.MSELCRB.XTAL_USB = 3;
|
||||
SH7305_PFC.MSELCRA.UNKNOWN_USB = 1;
|
||||
}
|
||||
|
||||
int usb_open(usb_interface_t const **interfaces, gint_call_t callback)
|
||||
{
|
||||
/* TODO: Check whether the calculator can host devices (probably no) */
|
||||
bool host = false;
|
||||
|
||||
USB_LOG("---- usb_open ----\n");
|
||||
|
||||
int rc = usb_configure_solve(interfaces);
|
||||
|
@ -143,38 +141,37 @@ int usb_open(usb_interface_t const **interfaces, gint_call_t callback)
|
|||
|
||||
USB.REG_C2 = 0x0020;
|
||||
|
||||
// TODO: Configuration sequence
|
||||
// - DPRPU = 0 (disconnect if previously a function)
|
||||
// - DPRD = 0 (required for setting DCFM)
|
||||
// - DCFM = 0/1 (select host/function)
|
||||
// - USBE = 0 (clears registers based on DCFM)
|
||||
// Then for function:
|
||||
// - HSE = 1 (use high-speed)
|
||||
// - USBE = 1
|
||||
// - ...
|
||||
// - DPRPU = 1 (notify host of connection)
|
||||
// - Read LNST
|
||||
// And for host:
|
||||
// - HSE = 0 (allow slow devices)
|
||||
// - USBE = 1
|
||||
// - DRPD = 1 (host setting)
|
||||
// - Read LNST
|
||||
|
||||
/* Turn on the module now that SCKE=1 */
|
||||
// TODO: Set to 0 now, set to 1 after enabling DPRPU/DPRD
|
||||
USB.SYSCFG.USBE = 1;
|
||||
USB.SYSCFG.HSE = 1;
|
||||
|
||||
/* Disable pin pull-down and pull-up in order to change DCFM */
|
||||
USB.SYSCFG.DRPD = 0;
|
||||
/* Disconnect (DPRPU=0) if we were previously connected as a function. Also
|
||||
drive down DRPR, since both are required for setting DCFM. */
|
||||
USB.SYSCFG.DPRPU = 0;
|
||||
/* Select function controller */
|
||||
USB.SYSCFG.DCFM = 0;
|
||||
USB.SYSCFG.DRPD = 0;
|
||||
|
||||
/* Pull D+ up to 3.3V, notifying connection when possible. Read
|
||||
SYSSTS.LNST as required after modifying DPRPU */
|
||||
USB.SYSCFG.DPRPU = 1;
|
||||
GUNUSED volatile int LNST = USB.SYSSTS.LNST;
|
||||
if(host) {
|
||||
/* Select the host controller */
|
||||
USB.SYSCFG.DCFM = 1;
|
||||
/* Clear registers to prepare for host operation */
|
||||
USB.SYSCFG.USBE = 0;
|
||||
/* Do not require high-speed operation; also accept full-speed */
|
||||
USB.SYSCFG.HSE = 0;
|
||||
|
||||
/* Pull DPRD and eliminate chattering */
|
||||
USB.SYSCFG.DRPD = 1;
|
||||
GUNUSED volatile int LNST = USB.SYSSTS.LNST;
|
||||
|
||||
/* Enable the module */
|
||||
USB.SYSCFG.USBE = 1;
|
||||
}
|
||||
else {
|
||||
/* Select the function controller */
|
||||
USB.SYSCFG.DCFM = 0;
|
||||
/* Clear registers to prepare for function operation */
|
||||
USB.SYSCFG.USBE = 0;
|
||||
/* Use high-speed only */
|
||||
USB.SYSCFG.HSE = 1;
|
||||
|
||||
/* Enable the module */
|
||||
USB.SYSCFG.USBE = 1;
|
||||
}
|
||||
|
||||
/* Prepare the default control pipe. */
|
||||
USB.DCPCFG.DIR = 0;
|
||||
|
@ -206,6 +203,11 @@ int usb_open(usb_interface_t const **interfaces, gint_call_t callback)
|
|||
intc_handler_function(0xa20, GINT_CALL(usb_interrupt_handler));
|
||||
intc_priority(INTC_USB, 8);
|
||||
|
||||
/* Pull D+ up to 3.3V, notifying connection when possible. Read
|
||||
SYSSTS.LNST as required after modifying DPRPU */
|
||||
USB.SYSCFG.DPRPU = 1;
|
||||
GUNUSED volatile int LNST = USB.SYSSTS.LNST;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -356,7 +358,7 @@ static void hrestore(usb_state_t const *s)
|
|||
|
||||
gint_driver_t drv_usb = {
|
||||
.name = "USB",
|
||||
/* TODO: Wait for remaining transfers in unbind() */
|
||||
/* TODO: usb: Wait for remaining transfers in unbind() */
|
||||
.hpowered = hpowered,
|
||||
.hpoweron = hpoweron,
|
||||
.hpoweroff = hpoweroff,
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#define GINT_USB_USB_PRIVATE
|
||||
|
||||
#include <gint/defs/attributes.h>
|
||||
#include <gint/timer.h>
|
||||
#include <gint/defs/timeout.h>
|
||||
#include <gint/gint.h>
|
||||
#include <gint/usb.h>
|
||||
|
||||
|
@ -133,20 +133,15 @@ void usb_pipe_write_bemp(int pipe);
|
|||
void usb_pipe_init_transfers(void);
|
||||
|
||||
//---
|
||||
// Timout waits
|
||||
// Timeout waits
|
||||
//---
|
||||
|
||||
/* usb_while(): A while loop with a timeout */
|
||||
#define usb_while(condition) ({ \
|
||||
volatile int __f = 0; \
|
||||
int __t = timer_configure(TIMER_ANY, 100000 /*µs*/, \
|
||||
GINT_CALL_SET_STOP(&__f)); \
|
||||
if(__t >= 0) timer_start(__t); \
|
||||
while((condition) && __f == 0) {} \
|
||||
if(__f) USB_LOG("%s: %d: (" #condition ") holds\n", \
|
||||
__FUNCTION__, __LINE__); \
|
||||
if(__t >= 0) timer_stop(__t); \
|
||||
__f != 0; \
|
||||
#define usb_while(COND) ({ \
|
||||
timeout_t __t = timeout_make_ms(100); \
|
||||
bool __b = false; \
|
||||
while((COND) && !(__b = timeout_elapsed(&__t))) {} \
|
||||
if(__b) USB_LOG("%s:%d: inf. while(" #COND ")\n", __FUNCTION__, __LINE__); \
|
||||
})
|
||||
|
||||
//---
|
||||
|
@ -175,4 +170,20 @@ enum {
|
|||
USBLENG registers, along with the DCP FIFO. */
|
||||
void usb_req_setup(void);
|
||||
|
||||
//---
|
||||
// Enumerations and stuff
|
||||
//---
|
||||
|
||||
enum {
|
||||
PID_NAK = 0,
|
||||
PID_BUF = 1,
|
||||
PID_STALL2 = 2,
|
||||
PID_STALL3 = 3,
|
||||
};
|
||||
enum {
|
||||
TYPE_BULK = 1,
|
||||
TYPE_INTERRUPT = 2,
|
||||
TYPE_ISOCHRONOUS = 3,
|
||||
};
|
||||
|
||||
#endif /* GINT_USB_USB_PRIVATE */
|
||||
|
|
Loading…
Reference in a new issue