Pinscape Controller version 1 fork. This is a fork to allow for ongoing bug fixes to the original controller version, from before the major changes for the expansion board project.
Dependencies: FastIO FastPWM SimpleDMA mbed
Fork of Pinscape_Controller by
Revision 53:02408ec83097, committed 2016-02-11
- Comitter:
- mjr
- Date:
- Thu Feb 11 18:31:05 2016 +0000
- Parent:
- 52:63f0a9b45f0c
- Child:
- 54:af65c577a563
- Commit message:
- Full reversion to v33 baseline for all USB code - new starting point to find USB compatibility regression
Changed in this revision
--- a/USBDevice/USBDevice/USBDevice.cpp Thu Feb 11 18:12:52 2016 +0000 +++ b/USBDevice/USBDevice/USBDevice.cpp Thu Feb 11 18:31:05 2016 +0000 @@ -23,11 +23,6 @@ #include "USBDescriptor.h" //#define DEBUG -#ifdef DEBUG -#define printd(fmt, ...) printf(fmt, __VA_ARGS__) -#else -#define printd(fmt, ...) -#endif /* Device status */ #define DEVICE_STATUS_SELF_POWERED (1U<<0) @@ -48,7 +43,9 @@ bool USBDevice::requestGetDescriptor(void) { bool success = false; - printd("get descr: type: %d\r\n", DESCRIPTOR_TYPE(transfer.setup.wValue)); +#ifdef DEBUG + printf("get descr: type: %d\r\n", DESCRIPTOR_TYPE(transfer.setup.wValue)); +#endif switch (DESCRIPTOR_TYPE(transfer.setup.wValue)) { case DEVICE_DESCRIPTOR: @@ -57,7 +54,9 @@ if ((deviceDesc()[0] == DEVICE_DESCRIPTOR_LENGTH) \ && (deviceDesc()[1] == DEVICE_DESCRIPTOR)) { - printd("device descr\r\n"); +#ifdef DEBUG + printf("device descr\r\n"); +#endif transfer.remaining = DEVICE_DESCRIPTOR_LENGTH; transfer.ptr = deviceDesc(); transfer.direction = DEVICE_TO_HOST; @@ -71,8 +70,9 @@ if ((configurationDesc()[0] == CONFIGURATION_DESCRIPTOR_LENGTH) \ && (configurationDesc()[1] == CONFIGURATION_DESCRIPTOR)) { - printd("conf descr request\r\n"); - +#ifdef DEBUG + printf("conf descr request\r\n"); +#endif /* Get wTotalLength */ transfer.remaining = configurationDesc()[2] \ | (configurationDesc()[3] << 8); @@ -84,46 +84,60 @@ } break; case STRING_DESCRIPTOR: - printd("str descriptor\r\n"); +#ifdef DEBUG + printf("str descriptor\r\n"); +#endif switch (DESCRIPTOR_INDEX(transfer.setup.wValue)) { case STRING_OFFSET_LANGID: - printd("1\r\n"); +#ifdef DEBUG + printf("1\r\n"); +#endif transfer.remaining = stringLangidDesc()[0]; transfer.ptr = stringLangidDesc(); transfer.direction = DEVICE_TO_HOST; success = true; break; case STRING_OFFSET_IMANUFACTURER: - printd("2\r\n"); +#ifdef DEBUG + printf("2\r\n"); +#endif transfer.remaining = stringImanufacturerDesc()[0]; transfer.ptr = stringImanufacturerDesc(); transfer.direction = DEVICE_TO_HOST; success = true; break; case STRING_OFFSET_IPRODUCT: - printd("3\r\n"); +#ifdef DEBUG + printf("3\r\n"); +#endif transfer.remaining = stringIproductDesc()[0]; transfer.ptr = stringIproductDesc(); transfer.direction = DEVICE_TO_HOST; success = true; break; case STRING_OFFSET_ISERIAL: - printd("4\r\n"); +#ifdef DEBUG + printf("4\r\n"); +#endif transfer.remaining = stringIserialDesc()[0]; transfer.ptr = stringIserialDesc(); transfer.direction = DEVICE_TO_HOST; success = true; break; case STRING_OFFSET_ICONFIGURATION: - printd("5\r\n"); +#ifdef DEBUG + printf("5\r\n"); +#endif transfer.remaining = stringIConfigurationDesc()[0]; transfer.ptr = stringIConfigurationDesc(); transfer.direction = DEVICE_TO_HOST; success = true; break; case STRING_OFFSET_IINTERFACE: - printd("6\r\n"); +#ifdef DEBUG + printf("6\r\n"); +#endif transfer.remaining = stringIinterfaceDesc()[0]; transfer.ptr = stringIinterfaceDesc(); transfer.direction = DEVICE_TO_HOST; @@ -131,18 +145,20 @@ break; } break; - case INTERFACE_DESCRIPTOR: - printd("interface descr\r\n"); - break; - +#ifdef DEBUG + printf("interface descr\r\n"); +#endif case ENDPOINT_DESCRIPTOR: +#ifdef DEBUG + printf("endpoint descr\r\n"); +#endif /* TODO: Support is optional, not implemented here */ - printd("endpoint descr\r\n"); break; - default: - printd("ERROR - unknown descriptor type in GET DESCRIPTOR\r\n"); +#ifdef DEBUG + printf("ERROR\r\n"); +#endif break; } @@ -176,18 +192,18 @@ * We seem to have a pending device-to-host transfer. The host must have * sent a new control request without waiting for us to finish processing * the previous one. This appears to happen when we're connected to certain - * USB 3.0 host chip sets. Do a zero-length send to tell the host we're not + * USB 3.0 host chip set. Do a zeor-length send to tell the host we're not * ready for the new request - that'll make it resend - and then just * pretend we were successful here so that the pending transfer can finish. */ uint8_t buf[1] = { 0 }; EP0write(buf, 0); - /* execute our pending transfer */ + /* execute our pending ttransfer */ controlIn(); - /* indicate failure so that the host retries */ - return false;//$$$ was return true + /* indicate success */ + return false; #else /* for other platforms, count on the HAL to handle this case */ return false; @@ -257,7 +273,6 @@ EP0readStage(); /* Completed */ - //$$$ transfer.direction = HOST_TO_DEVICE; return true; } @@ -280,12 +295,7 @@ /* Update transfer */ transfer.ptr += packetSize; transfer.remaining -= packetSize; - - /* are we done? */ - //$$$ if (transfer.remaining == 0) - //$$$ transfer.direction = HOST_TO_DEVICE; - /* success */ return true; } @@ -511,7 +521,7 @@ success = requestSetFeature(); break; case SET_ADDRESS: - success = requestSetAddress(); + success = requestSetAddress(); break; case GET_DESCRIPTOR: success = requestGetDescriptor(); @@ -553,18 +563,19 @@ decodeSetupPacket(buffer, &transfer.setup); transfer.ptr = NULL; transfer.remaining = 0; - transfer.direction = HOST_TO_DEVICE; + transfer.direction = 0; transfer.zlp = false; transfer.notify = false; - printd("dataTransferDirection: %d\r\nType: %d\r\nRecipient: %d\r\nbRequest: %d\r\nwValue: %d\r\nwIndex: %d\r\nwLength: %d\r\n", - transfer.setup.bmRequestType.dataTransferDirection, - transfer.setup.bmRequestType.Type, - transfer.setup.bmRequestType.Recipient, - transfer.setup.bRequest, - transfer.setup.wValue, - transfer.setup.wIndex, - transfer.setup.wLength); +#ifdef DEBUG + printf("dataTransferDirection: %d\r\nType: %d\r\nRecipient: %d\r\nbRequest: %d\r\nwValue: %d\r\nwIndex: %d\r\nwLength: %d\r\n",transfer.setup.bmRequestType.dataTransferDirection, + transfer.setup.bmRequestType.Type, + transfer.setup.bmRequestType.Recipient, + transfer.setup.bRequest, + transfer.setup.wValue, + transfer.setup.wIndex, + transfer.setup.wLength); +#endif /* Class / vendor specific */ success = USBCallback_request(); @@ -574,13 +585,15 @@ /* Standard requests */ if (!requestSetup()) { - printd("requestSetup() failed: type=%d, req=%d\r\n", (int)transfer.setup.bmRequestType.Type, (int)transfer.setup.bRequest); +#ifdef DEBUG + printf("fail!!!!\r\n"); +#endif return false; } } /* Check transfer size and direction */ - if (transfer.setup.wLength > 0) + if (transfer.setup.wLength>0) { if (transfer.setup.bmRequestType.dataTransferDirection \ == DEVICE_TO_HOST) @@ -588,7 +601,6 @@ /* IN data stage is required */ if (transfer.direction != DEVICE_TO_HOST) { - printd("controlSetup transfer direction wrong 1\r\n"); return false; } @@ -605,15 +617,12 @@ /* OUT data stage is required */ if (transfer.direction != HOST_TO_DEVICE) { - printd("controlSetup transfer direction wrong 2: type=%d, req=%d\r\n", (int)transfer.setup.bmRequestType.Type, (int)transfer.setup.bRequest); return false; } /* Transfer must be equal to the size requested by the host */ if (transfer.remaining != transfer.setup.wLength) { - printd("controlSetup remaining length wrong: return len=%d, type=%d, req=%d, wvalue=%d, windex=%x, wlength=%d\r\n", - transfer.remaining, transfer.setup.bmRequestType.Type, transfer.setup.bRequest, transfer.setup.wValue, transfer.setup.wIndex, transfer.setup.wLength); return false; } } @@ -623,14 +632,12 @@ /* No data stage; transfer size must be zero */ if (transfer.remaining != 0) { - printd("controlSetup remaining length must be zero: return len=%d, type=%d, req=%d, wvalue=%d, windex=%x, wlength=%d\r\n", - (int)transfer.remaining, (int)transfer.setup.bmRequestType.Type, (int)transfer.setup.bRequest, (int)transfer.setup.wValue, (int)transfer.setup.wIndex, (int)transfer.setup.wLength); return false; } } /* Data or status stage if applicable */ - if (transfer.setup.wLength > 0) + if (transfer.setup.wLength>0) { if (transfer.setup.bmRequestType.dataTransferDirection \ == DEVICE_TO_HOST) @@ -683,6 +690,8 @@ /* Protocol stall */ EP0stall(); } + + /* Return true if an OUT data stage is expected */ } void USBDevice::EP0out(void) @@ -697,6 +706,9 @@ void USBDevice::EP0in(void) { +#ifdef DEBUG + printf("EP0IN\r\n"); +#endif /* Endpoint 0 IN data event */ if (!controlIn()) { @@ -717,8 +729,8 @@ USBHAL::connect(); if (blocking) { - /* Block until configured */ - while (!configured()) { } + /* Block if not configured */ + while (!configured()); } } @@ -783,12 +795,12 @@ do { if (ptr[1] /* bDescriptorType */ == descriptorType) { -//$$$ // Found - if the index has reached zero, it's the one we're -//$$$ // looking for; if not, just decrement the index and keep looking. -//$$$ if (idx == 0) + // Found - if the index has reached zero, it's the one we're + // looking for; if not, just decrement the index and keep looking. + if (idx == 0) return ptr; -//$$$ else -//$$$ --idx; + else + --idx; } /* Skip to next descriptor */ @@ -897,10 +909,10 @@ if(!configured()) { return false; } - + /* Send report */ result = endpointWrite(endpoint, buffer, size); - + if (result != EP_PENDING) { return false; @@ -918,6 +930,9 @@ return (result == EP_COMPLETED); } + + + bool USBDevice::readEP(uint8_t endpoint, uint8_t * buffer, uint32_t * size, uint32_t maxSize) { EP_STATUS result;
--- a/USBDevice/USBDevice/USBEndpoints.h Thu Feb 11 18:12:52 2016 +0000 +++ b/USBDevice/USBDevice/USBEndpoints.h Thu Feb 11 18:31:05 2016 +0000 @@ -33,7 +33,7 @@ EP_COMPLETED, /* Transfer completed */ EP_PENDING, /* Transfer in progress */ EP_INVALID, /* Invalid parameter */ - EP_STALLED /* Endpoint stalled */ + EP_STALLED, /* Endpoint stalled */ } EP_STATUS; /* Include configuration for specific target */
--- a/USBDevice/USBDevice/USBHAL.h Thu Feb 11 18:12:52 2016 +0000 +++ b/USBDevice/USBDevice/USBHAL.h Thu Feb 11 18:31:05 2016 +0000 @@ -58,7 +58,7 @@ bool realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t options); bool getEndpointStallState(unsigned char endpoint); uint32_t endpointReadcore(uint8_t endpoint, uint8_t *buffer); - + protected: virtual void busReset(void){}; virtual void EP0setupCallback(void){}; @@ -112,11 +112,6 @@ bool (USBHAL::*epCallback[10 - 2])(void); #elif defined(TARGET_STM32F4XX) bool (USBHAL::*epCallback[8 - 2])(void); -#elif defined(TARGET_KL25Z) - bool (USBHAL::*epCallback[32])(void); - bool EP0_IN_callback(); - bool EP0_OUT_callback(); - void EP0_SETUP_callback(); #else bool (USBHAL::*epCallback[32 - 2])(void); #endif
--- a/USBDevice/USBDevice/USBHAL_KL25Z.cpp Thu Feb 11 18:12:52 2016 +0000 +++ b/USBDevice/USBDevice/USBHAL_KL25Z.cpp Thu Feb 11 18:31:05 2016 +0000 @@ -18,90 +18,42 @@ #if defined(TARGET_KL25Z) | defined(TARGET_KL46Z) | defined(TARGET_K20D5M) | defined(TARGET_K64F) -//#define DEBUG -#ifdef DEBUG -#define printd(fmt, ...) printf(fmt, __VA_ARGS__) -#else -#define printd(fmt, ...) -#endif - - #include "USBHAL.h" -// Critical section controls. This module uses a bunch of static variables, -// and much of the code that accesses the statics can be called from either -// normal application context or IRQ context. Whenever a shared variable is -// accessed from code that can run in an application context, we have to -// protect against interrupts by entering a critical section. These macros -// enable and disable the USB IRQ if we're running in application context. -// (They do nothing if we're already in interrupt context, because the -// hardware interrupt controller won't generated another of the same IRQ -// that we're already handling. We could still be interrupted by a different, -// higher-priority IRQ, but our shared variables are only shared within this -// module, so they won't be affected by other interrupt handlers.) -static int inIRQ; -#define ENTER_CRITICAL_SECTION \ - if (!inIRQ) \ - NVIC_DisableIRQ(USB0_IRQn); -#define EXIT_CRITICAL_SECTION \ - if (!inIRQ) \ - NVIC_EnableIRQ(USB0_IRQn); +USBHAL * USBHAL::instance; -// static singleton instance pointer -USBHAL * USBHAL::instance; +static volatile int epComplete = 0; // Convert physical endpoint number to register bit #define EP(endpoint) (1<<(endpoint)) -// Convert physical endpoint number to logical endpoint number. -// Each logical endpoint has two physical endpoints, one RX and -// one TX. The physical endpoints are numbered in RX,TX pairs, -// so the logical endpoint number is simply the physical endpoint -// number divided by 2 (discarding the remainder). +// Convert physical to logical #define PHY_TO_LOG(endpoint) ((endpoint)>>1) -// Get a physical endpoint's direction. IN and OUT are from -// the host's perspective, so from our perspective on the device, -// IN == TX and OUT == RX. The physical endpoints are in RX,TX -// pairs, so the OUT/RX is the even numbered element of a pair -// and the IN/TX is the odd numbered element. +// Get endpoint direction #define IN_EP(endpoint) ((endpoint) & 1U ? true : false) #define OUT_EP(endpoint) ((endpoint) & 1U ? false : true) -// BDT status flags, defined by the SIE hardware. These are -// bits packed into the 'info' byte of a BDT entry. -#define BD_OWN_MASK (1<<7) // OWN - hardware SIE owns the BDT (TX/RX in progress) -#define BD_DATA01_MASK (1<<6) // DATA01 - DATA0/DATA1 bit for current TX/RX on endpoint -#define BD_KEEP_MASK (1<<5) // KEEP - hardware keeps BDT ownership after token completes -#define BD_NINC_MASK (1<<4) // NO INCREMENT - buffer location is a FIFO, so use same address for all bytes -#define BD_DTS_MASK (1<<3) // DATA TOGGLE SENSING - hardware SIE checks for DATA0/DATA1 match during RX/TX -#define BD_STALL_MASK (1<<2) // STALL - SIE issues STALL handshake in reply to any host access to endpoint +#define BD_OWN_MASK (1<<7) +#define BD_DATA01_MASK (1<<6) +#define BD_KEEP_MASK (1<<5) +#define BD_NINC_MASK (1<<4) +#define BD_DTS_MASK (1<<3) +#define BD_STALL_MASK (1<<2) -// Endpoint direction #define TX 1 #define RX 0 - -// Buffer parity. The hardware has a double-buffering scheme where each -// physical endpoint has two associated BDT entries, labeled EVEN and ODD. -// We disable the double buffering, so only the EVEN buffers are used in -// this implementation. -#define EVEN 0 -#define ODD 1 +#define ODD 0 +#define EVEN 1 +// this macro waits a physical endpoint number +#define EP_BDT_IDX(ep, dir, odd) (((ep * 4) + (2 * dir) + (1 * odd))) -// Get the BDT index for a given logical endpoint, direction, and buffer parity -#define EP_BDT_IDX(logep, dir, odd) (((logep) * 4) + (2 * (dir)) + (1 * (odd))) - -// Get the BDT index for a given physical endpoint and buffer parity -#define PEP_BDT_IDX(phyep, odd) (((phyep) * 2) + (1 * (odd))) - -// Token types reported in the BDT 'info' flags. -#define TOK_PID(idx) ((bdt[idx].info >> 2) & 0x0F) #define SETUP_TOKEN 0x0D #define IN_TOKEN 0x09 #define OUT_TOKEN 0x01 +#define TOK_PID(idx) ((bdt[idx].info >> 2) & 0x0F) -// Buffer Descriptor Table (BDT) entry. This is the hardware-defined -// memory structure for the shared memory block controlling an endpoint. +// for each endpt: 8 bytes typedef struct BDT { uint8_t info; // BD[0:7] uint8_t dummy; // RSVD: BD[8:15] @@ -109,51 +61,24 @@ uint32_t address; // Addr } BDT; -// There are: -// * 16 bidirectional logical endpoints -> 32 physical endpoints -// * 2 BDT entries per endpoint (EVEN/ODD) -> 64 BDT entries -__attribute__((__aligned__(512))) BDT bdt[NUMBER_OF_PHYSICAL_ENDPOINTS * 2]; - -// Transfer buffers. We allocate the transfer buffers and point the -// SIE hardware to them via the BDT. We disable hardware SIE's -// double-buffering (EVEN/ODD) scheme, so we only allocate one buffer -// per physical endpoint. -uint8_t *endpoint_buffer[NUMBER_OF_PHYSICAL_ENDPOINTS]; -// Allocated size of each endpoint buffer -size_t epMaxPacket[NUMBER_OF_PHYSICAL_ENDPOINTS]; +// there are: +// * 16 bidirectionnal endpt -> 32 physical endpt +// * as there are ODD and EVEN buffer -> 32*2 bdt +__attribute__((__aligned__(512))) BDT bdt[NUMBER_OF_PHYSICAL_ENDPOINTS * 2]; +uint8_t * endpoint_buffer[(NUMBER_OF_PHYSICAL_ENDPOINTS - 2) * 2]; +uint8_t * endpoint_buffer_iso[2*2]; -// SET ADDRESS mode tracking. The address assignment has to be done in a -// specific order and with specific timing defined by the USB setup protocol -// standards. To get the sequencing right, we set a flag when we get the -// address message, and then set the address in the SIE when we're at the -// right subsequent packet step in the protocol exchange. These variables -// are just a place to stash the information between the time we receive the -// data and the time we're ready to update the SIE register. static uint8_t set_addr = 0; static uint8_t addr = 0; -// Endpoint DATA0/DATA1 bits, packed as a bit vector. Each endpoint's -// bit is at (1 << endpoint number). These track the current bit value -// on the endpoint. For TX endpoints, this is the bit for the LAST -// packet we sent (so the next packet will be the inverse). For RX -// endpoints, this is the bit value we expect for the NEXT packet. -// (Yes, it's inconsistent.) static uint32_t Data1 = 0x55555555; -// Endpoint read/write completion flags, packed as a bit vector. Each -// endpoint's bit is at (1 << endpoint number). A 1 bit signifies that -// the last read or write has completed (and hasn't had its result -// consumed yet). -static volatile int epComplete = 0; - -static uint32_t frameNumber() -{ +static uint32_t frameNumber() { return((USB0->FRMNUML | (USB0->FRMNUMH << 8)) & 0x07FF); } -uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) -{ +uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) { return 0; } @@ -165,38 +90,37 @@ MPU->CESR=0; #endif // fill in callback array - epCallback[0] = &USBHAL::EP0_OUT_callback; - epCallback[1] = &USBHAL::EP0_IN_callback; - epCallback[2] = &USBHAL::EP1_OUT_callback; - epCallback[3] = &USBHAL::EP1_IN_callback; - epCallback[4] = &USBHAL::EP2_OUT_callback; - epCallback[5] = &USBHAL::EP2_IN_callback; - epCallback[6] = &USBHAL::EP3_OUT_callback; - epCallback[7] = &USBHAL::EP3_IN_callback; - epCallback[8] = &USBHAL::EP4_OUT_callback; - epCallback[9] = &USBHAL::EP4_IN_callback; - epCallback[10] = &USBHAL::EP5_OUT_callback; - epCallback[11] = &USBHAL::EP5_IN_callback; - epCallback[12] = &USBHAL::EP6_OUT_callback; - epCallback[13] = &USBHAL::EP6_IN_callback; - epCallback[14] = &USBHAL::EP7_OUT_callback; - epCallback[15] = &USBHAL::EP7_IN_callback; - epCallback[16] = &USBHAL::EP8_OUT_callback; - epCallback[17] = &USBHAL::EP8_IN_callback; - epCallback[18] = &USBHAL::EP9_OUT_callback; - epCallback[19] = &USBHAL::EP9_IN_callback; - epCallback[20] = &USBHAL::EP10_OUT_callback; - epCallback[21] = &USBHAL::EP10_IN_callback; - epCallback[22] = &USBHAL::EP11_OUT_callback; - epCallback[23] = &USBHAL::EP11_IN_callback; - epCallback[24] = &USBHAL::EP12_OUT_callback; - epCallback[25] = &USBHAL::EP12_IN_callback; - epCallback[26] = &USBHAL::EP13_OUT_callback; - epCallback[27] = &USBHAL::EP13_IN_callback; - epCallback[28] = &USBHAL::EP14_OUT_callback; - epCallback[29] = &USBHAL::EP14_IN_callback; - epCallback[30] = &USBHAL::EP15_OUT_callback; - epCallback[31] = &USBHAL::EP15_IN_callback; + epCallback[0] = &USBHAL::EP1_OUT_callback; + epCallback[1] = &USBHAL::EP1_IN_callback; + epCallback[2] = &USBHAL::EP2_OUT_callback; + epCallback[3] = &USBHAL::EP2_IN_callback; + epCallback[4] = &USBHAL::EP3_OUT_callback; + epCallback[5] = &USBHAL::EP3_IN_callback; + epCallback[6] = &USBHAL::EP4_OUT_callback; + epCallback[7] = &USBHAL::EP4_IN_callback; + epCallback[8] = &USBHAL::EP5_OUT_callback; + epCallback[9] = &USBHAL::EP5_IN_callback; + epCallback[10] = &USBHAL::EP6_OUT_callback; + epCallback[11] = &USBHAL::EP6_IN_callback; + epCallback[12] = &USBHAL::EP7_OUT_callback; + epCallback[13] = &USBHAL::EP7_IN_callback; + epCallback[14] = &USBHAL::EP8_OUT_callback; + epCallback[15] = &USBHAL::EP8_IN_callback; + epCallback[16] = &USBHAL::EP9_OUT_callback; + epCallback[17] = &USBHAL::EP9_IN_callback; + epCallback[18] = &USBHAL::EP10_OUT_callback; + epCallback[19] = &USBHAL::EP10_IN_callback; + epCallback[20] = &USBHAL::EP11_OUT_callback; + epCallback[21] = &USBHAL::EP11_IN_callback; + epCallback[22] = &USBHAL::EP12_OUT_callback; + epCallback[23] = &USBHAL::EP12_IN_callback; + epCallback[24] = &USBHAL::EP13_OUT_callback; + epCallback[25] = &USBHAL::EP13_IN_callback; + epCallback[26] = &USBHAL::EP14_OUT_callback; + epCallback[27] = &USBHAL::EP14_IN_callback; + epCallback[28] = &USBHAL::EP15_OUT_callback; + epCallback[29] = &USBHAL::EP15_IN_callback; + // choose usb src as PLL SIM->SOPT2 |= (SIM_SOPT2_USBSRC_MASK | SIM_SOPT2_PLLFLLSEL_MASK); @@ -236,51 +160,41 @@ USB0->USBTRC0 |= 0x40; } -USBHAL::~USBHAL(void) -{ -} +USBHAL::~USBHAL(void) { } -void USBHAL::connect(void) -{ +void USBHAL::connect(void) { // enable USB USB0->CTL |= USB_CTL_USBENSOFEN_MASK; - // Pull up enable USB0->CONTROL |= USB_CONTROL_DPPULLUPNONOTG_MASK; } -void USBHAL::disconnect(void) -{ +void USBHAL::disconnect(void) { // disable USB USB0->CTL &= ~USB_CTL_USBENSOFEN_MASK; - // Pull up disable USB0->CONTROL &= ~USB_CONTROL_DPPULLUPNONOTG_MASK; //Free buffers if required: - for (int i = 0 ; i < NUMBER_OF_PHYSICAL_ENDPOINTS ; i++) - { - if (endpoint_buffer[i] != NULL) - { - free(endpoint_buffer[i]); - endpoint_buffer[i] = NULL; - epMaxPacket[i] = 0; - } + for (int i = 0; i<(NUMBER_OF_PHYSICAL_ENDPOINTS - 2) * 2; i++) { + free(endpoint_buffer[i]); + endpoint_buffer[i] = NULL; } + free(endpoint_buffer_iso[2]); + endpoint_buffer_iso[2] = NULL; + free(endpoint_buffer_iso[0]); + endpoint_buffer_iso[0] = NULL; } -void USBHAL::configureDevice(void) -{ +void USBHAL::configureDevice(void) { // not needed } -void USBHAL::unconfigureDevice(void) -{ +void USBHAL::unconfigureDevice(void) { // not needed } -void USBHAL::setAddress(uint8_t address) -{ +void USBHAL::setAddress(uint8_t address) { // we don't set the address now otherwise the usb controller does not ack // we set a flag instead // see usbisr when an IN token is received @@ -288,381 +202,250 @@ addr = address; } -bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t flags) -{ - // validate the endpoint number - if (endpoint >= NUMBER_OF_PHYSICAL_ENDPOINTS) +bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t flags) { + uint32_t handshake_flag = 0; + uint8_t * buf; + + if (endpoint > NUMBER_OF_PHYSICAL_ENDPOINTS - 1) { return false; + } - // get the logical endpoint uint32_t log_endpoint = PHY_TO_LOG(endpoint); - - // Constrain the requested packet size to the maximum for the endpoint type. - // Full Speed USB allows up to 1023 bytes for isochronous endpoints and 64 bytes - // for bulk and interrupt endpoints. - uint32_t realMaxPacket = ((flags & ISOCHRONOUS) ? 1023 : 64); - if (maxPacket > realMaxPacket) - maxPacket = realMaxPacket; - - // Use the HANDSHAKE flag for non-isochronous endpoints. Don't use handshaking - // for an iso endpoint, since this type of endpoint is for applications like - // audio and video streaming where it's preferable to ignore lost packets and - // just carry on with the latest data. - uint32_t ctlFlags = 0; - if (!(flags & ISOCHRONOUS)) - ctlFlags |= USB_ENDPT_EPHSHK_MASK; - - // figure the RX/TX based on the endpoint direction - ctlFlags |= (IN_EP(endpoint) ? USB_ENDPT_EPTXEN_MASK : USB_ENDPT_EPRXEN_MASK); - ENTER_CRITICAL_SECTION - { - // if we don't already have a buffer that's big enough, allocate a new one - uint8_t *buf = endpoint_buffer[endpoint]; - if (buf == 0 || maxPacket > epMaxPacket[endpoint]) - { - // free any existing buffer - if (buf != 0) - free(buf); - - // allocate a new one - epMaxPacket[endpoint] = maxPacket; - endpoint_buffer[endpoint] = buf = (uint8_t *)malloc(maxPacket); + if ((flags & ISOCHRONOUS) == 0) { + handshake_flag = USB_ENDPT_EPHSHK_MASK; + if (IN_EP(endpoint)) { + if (endpoint_buffer[EP_BDT_IDX(log_endpoint, TX, ODD)] == NULL) + endpoint_buffer[EP_BDT_IDX(log_endpoint, TX, ODD)] = (uint8_t *) malloc (64*2); + buf = &endpoint_buffer[EP_BDT_IDX(log_endpoint, TX, ODD)][0]; + } else { + if (endpoint_buffer[EP_BDT_IDX(log_endpoint, RX, ODD)] == NULL) + endpoint_buffer[EP_BDT_IDX(log_endpoint, RX, ODD)] = (uint8_t *) malloc (64*2); + buf = &endpoint_buffer[EP_BDT_IDX(log_endpoint, RX, ODD)][0]; + } + } else { + if (IN_EP(endpoint)) { + if (endpoint_buffer_iso[2] == NULL) + endpoint_buffer_iso[2] = (uint8_t *) malloc (1023*2); + buf = &endpoint_buffer_iso[2][0]; + } else { + if (endpoint_buffer_iso[0] == NULL) + endpoint_buffer_iso[0] = (uint8_t *) malloc (1023*2); + buf = &endpoint_buffer_iso[0][0]; } - - // Set up the BDT entry. Note that we disable the hardware double-buffering - // scheme, so we only use the EVEN buffer for the endpoint. - int idx = PEP_BDT_IDX(endpoint, EVEN); - bdt[idx].info = 0; - bdt[idx].address = (uint32_t)buf; - - // Set the endpoint flags. Note that these bits are additive, since the - // endpoint register represents the logical endpoint, which is the combination - // of the physical IN and OUT endpoints. - USB0->ENDPOINT[log_endpoint].ENDPT |= ctlFlags; - - // If this is an OUT endpoint, queue the first read on the endpoint by - // handing ownership of the BDT to the SIE. - if (OUT_EP(endpoint)) - { - bdt[idx].byte_count = maxPacket; - bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK; - } - - // Set DATA1 on the endpoint. For RX endpoints, we just queued up our first - // read, which will always be a DATA0 packet, so the next read will use DATA1. - // For TX endpoints, we always flip the bit *before* sending the packet, so - // (counterintuitively) we need to set the DATA1 bit now to send DATA0 in the - // next packet. So in either case, we want DATA1 initially. - Data1 |= (1 << endpoint); + } + + // IN endpt -> device to host (TX) + if (IN_EP(endpoint)) { + USB0->ENDPOINT[log_endpoint].ENDPT |= handshake_flag | // ep handshaking (not if iso endpoint) + USB_ENDPT_EPTXEN_MASK; // en TX (IN) tran + bdt[EP_BDT_IDX(log_endpoint, TX, ODD )].address = (uint32_t) buf; + bdt[EP_BDT_IDX(log_endpoint, TX, EVEN)].address = 0; } - EXIT_CRITICAL_SECTION - - // success + // OUT endpt -> host to device (RX) + else { + USB0->ENDPOINT[log_endpoint].ENDPT |= handshake_flag | // ep handshaking (not if iso endpoint) + USB_ENDPT_EPRXEN_MASK; // en RX (OUT) tran. + bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].byte_count = maxPacket; + bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].address = (uint32_t) buf; + bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].info = BD_OWN_MASK | BD_DTS_MASK; + bdt[EP_BDT_IDX(log_endpoint, RX, EVEN)].info = 0; + } + + Data1 |= (1 << endpoint); + return true; } // read setup packet -void USBHAL::EP0setup(uint8_t *buffer) -{ +void USBHAL::EP0setup(uint8_t *buffer) { uint32_t sz; endpointReadResult(EP0OUT, buffer, &sz); } -void USBHAL::EP0readStage(void) -{ - // set DATA0 for the next packet - Data1 &= ~1UL; - - // if we haven't already, give the BDT to the SIE to read the packet - if (!(bdt[0].info & BD_OWN_MASK)) - bdt[0].info = (BD_DTS_MASK | BD_OWN_MASK); +void USBHAL::EP0readStage(void) { + Data1 &= ~1UL; // set DATA0 + bdt[0].info = (BD_DTS_MASK | BD_OWN_MASK); } -void USBHAL::EP0read(void) -{ - if (!(bdt[0].info & BD_OWN_MASK)) - bdt[0].byte_count = MAX_PACKET_SIZE_EP0; +void USBHAL::EP0read(void) { + uint32_t idx = EP_BDT_IDX(PHY_TO_LOG(EP0OUT), RX, 0); + bdt[idx].byte_count = MAX_PACKET_SIZE_EP0; } -uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) -{ +uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) { uint32_t sz; endpointReadResult(EP0OUT, buffer, &sz); return sz; } -void USBHAL::EP0write(uint8_t *buffer, uint32_t size) -{ +void USBHAL::EP0write(uint8_t *buffer, uint32_t size) { endpointWrite(EP0IN, buffer, size); } -void USBHAL::EP0getWriteResult(void) -{ +void USBHAL::EP0getWriteResult(void) { } -void USBHAL::EP0stall(void) -{ - printd("EP0 stall!\r\n"); +void USBHAL::EP0stall(void) { stallEndpoint(EP0OUT); } -EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) -{ - // We always start a new read when we fetch the result of the - // previous read, so we don't have to do anything here. Simply - // indicate that the read is pending so that the caller can proceed - // to check the results. +EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) { + endpoint = PHY_TO_LOG(endpoint); + uint32_t idx = EP_BDT_IDX(endpoint, RX, 0); + bdt[idx].byte_count = maximumSize; return EP_PENDING; } -EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t *buffer, uint32_t *bytesRead) -{ - // validate the endpoint number and direction - if (endpoint >= NUMBER_OF_PHYSICAL_ENDPOINTS || !OUT_EP(endpoint)) - return EP_INVALID; +EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_t *bytesRead) { + uint32_t n, sz, idx, setup = 0; + uint8_t not_iso; + uint8_t * ep_buf; - // get the logical endpoint uint32_t log_endpoint = PHY_TO_LOG(endpoint); - - // get the mode - it's isochronous if it doesn't have the handshake flag - bool iso = !(USB0->ENDPOINT[log_endpoint].ENDPT & USB_ENDPT_EPHSHK_MASK); - - // get the BDT index - int idx = EP_BDT_IDX(log_endpoint, RX, 0); - - // If the "complete" flag isn't set, the read is still pending in the SIE. - // This doesn't apply the isochronous endpoints, since we don't get TOKDNE - // interrupts on those (we use the SOF signal instead). It also doesn't - // apply to endpoint 0, since that doesn't use the epComplete mechanism - // at all (necessary because we handle all transactions on this endpoint - // in IRQ context). For EP0, just make sure the hardware doesn't still - // own the BDT - if it does, the last read hasn't completed yet. - if (log_endpoint == 0) - { - // control endpoint - just make sure we own the BDT - //$$$ if (bdt[idx].info & BD_OWN_MASK) - //$$$ return EP_PENDING; + + if (endpoint > NUMBER_OF_PHYSICAL_ENDPOINTS - 1) { + return EP_INVALID; + } + + // if read on a IN endpoint -> error + if (IN_EP(endpoint)) { + return EP_INVALID; } - else if (!iso && !(epComplete & EP(endpoint))) + + idx = EP_BDT_IDX(log_endpoint, RX, 0); + sz = bdt[idx].byte_count; + not_iso = USB0->ENDPOINT[log_endpoint].ENDPT & USB_ENDPT_EPHSHK_MASK; + + //for isochronous endpoint, we don't wait an interrupt + if ((log_endpoint != 0) && not_iso && !(epComplete & EP(endpoint))) { return EP_PENDING; - - // get the buffer - uint8_t *ep_buf = endpoint_buffer[endpoint]; + } + + if ((log_endpoint == 0) && (TOK_PID(idx) == SETUP_TOKEN)) { + setup = 1; + } - ENTER_CRITICAL_SECTION - { - // get the packet size from the BDT - uint32_t sz = bdt[idx].byte_count; - - // note if it's a SETUP token - bool setup = (log_endpoint == 0 && TOK_PID(idx) == SETUP_TOKEN); - - // copy the data - memcpy(buffer, ep_buf, sz); - *bytesRead = sz; + // non iso endpoint + if (not_iso) { + ep_buf = endpoint_buffer[idx]; + } else { + ep_buf = endpoint_buffer_iso[0]; + } + + for (n = 0; n < sz; n++) { + buffer[n] = ep_buf[n]; + } - // Figure the DATA0/DATA1 bit for the next packet received on this - // endpoint. The bit normally toggles on each packet, but it's - // special for SETUP packets on endpoint 0. The next OUT packet - // after a SETUP packet with no data stage is always DATA0, even - // if the SETUP packet was also DATA0. - if (((Data1 >> endpoint) & 1) == ((bdt[idx].info >> 6) & 1)) - { - if (setup && (buffer[6] == 0)) // if no setup data stage, - Data1 &= ~1UL; // set DATA0 - else - Data1 ^= (1 << endpoint); // otherwise just toggle the last bit - } + if (((Data1 >> endpoint) & 1) == ((bdt[idx].info >> 6) & 1)) { + if (setup && (buffer[6] == 0)) // if no setup data stage, + Data1 &= ~1UL; // set DATA0 + else + Data1 ^= (1 << endpoint); + } - // set up the BDT entry to receive the next packet, and hand it to the SIE to fill - bdt[idx].byte_count = epMaxPacket[endpoint]; - bdt[idx].info = BD_DTS_MASK | BD_OWN_MASK | (((Data1 >> endpoint) & 1) << 6); - - // clear the SUSPEND TOKEN BUSY flag to allow the SIE to continue processing tokens - USB0->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK; - - // clear the completion flag - epComplete &= ~EP(endpoint); + if (((Data1 >> endpoint) & 1)) { + bdt[idx].info = BD_DTS_MASK | BD_DATA01_MASK | BD_OWN_MASK; + } + else { + bdt[idx].info = BD_DTS_MASK | BD_OWN_MASK; } - EXIT_CRITICAL_SECTION - - // the read is completed + + USB0->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK; + *bytesRead = sz; + + epComplete &= ~EP(endpoint); return EP_COMPLETED; } -EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) -{ - // validate the endpoint number and direction - if (endpoint >= NUMBER_OF_PHYSICAL_ENDPOINTS || !IN_EP(endpoint)) +EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) { + uint32_t idx, n; + uint8_t * ep_buf; + + if (endpoint > NUMBER_OF_PHYSICAL_ENDPOINTS - 1) { return EP_INVALID; + } - // get the BDT index - int idx = EP_BDT_IDX(PHY_TO_LOG(endpoint), TX, 0); - - // get the buffer pointer - uint8_t *buf = endpoint_buffer[endpoint]; + // if write on a OUT endpoint -> error + if (OUT_EP(endpoint)) { + return EP_INVALID; + } + + idx = EP_BDT_IDX(PHY_TO_LOG(endpoint), TX, 0); + bdt[idx].byte_count = size; + - ENTER_CRITICAL_SECTION - { - // copy the data to the hardware buffer - bdt[idx].byte_count = size; - memcpy(buf, data, size); + // non iso endpoint + if (USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT & USB_ENDPT_EPHSHK_MASK) { + ep_buf = endpoint_buffer[idx]; + } else { + ep_buf = endpoint_buffer_iso[2]; + } - // flip the DATA1 bit before sending - Data1 ^= (1 << endpoint); + for (n = 0; n < size; n++) { + ep_buf[n] = data[n]; + } - // hand the BDT to the SIE hardware, and set the current DATA1 bit - bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK | (((Data1 >> endpoint) & 1) << 6); + if ((Data1 >> endpoint) & 1) { + bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK; + } else { + bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK | BD_DATA01_MASK; } - EXIT_CRITICAL_SECTION - // the operation is now pending + Data1 ^= (1 << endpoint); + return EP_PENDING; } -EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) -{ - EP_STATUS result = EP_PENDING; +EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) { + if (epComplete & EP(endpoint)) { + epComplete &= ~EP(endpoint); + return EP_COMPLETED; + } - ENTER_CRITICAL_SECTION - { - if (epComplete & EP(endpoint)) { - epComplete &= ~EP(endpoint); - result = EP_COMPLETED; - } - } - EXIT_CRITICAL_SECTION - - return result; + return EP_PENDING; } -void USBHAL::stallEndpoint(uint8_t endpoint) -{ +void USBHAL::stallEndpoint(uint8_t endpoint) { USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT |= USB_ENDPT_EPSTALL_MASK; } -void USBHAL::unstallEndpoint(uint8_t endpoint) -{ - printd("unstall endpoint %d %s\r\n", endpoint>>1,endpoint&1?"TX":"RX"); - ENTER_CRITICAL_SECTION - { - USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT &= ~USB_ENDPT_EPSTALL_MASK; - int idx = PEP_BDT_IDX(endpoint, 0); - bdt[idx].info &= ~(BD_OWN_MASK | BD_STALL_MASK | BD_DATA01_MASK); - - if (OUT_EP(endpoint)) - Data1 &= ~(1 << endpoint); - else - Data1 |= (1 << endpoint); - } - EXIT_CRITICAL_SECTION +void USBHAL::unstallEndpoint(uint8_t endpoint) { + USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT &= ~USB_ENDPT_EPSTALL_MASK; } -bool USBHAL::getEndpointStallState(uint8_t endpoint) -{ +bool USBHAL::getEndpointStallState(uint8_t endpoint) { uint8_t stall = (USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT & USB_ENDPT_EPSTALL_MASK); return (stall) ? true : false; } -void USBHAL::remoteWakeup(void) -{ +void USBHAL::remoteWakeup(void) { // [TODO] } -// Handle SETUP packet on EP0 IN or OUT -void USBHAL::EP0_SETUP_callback(void) -{ - // Set DATA1 on Control IN endpoint for next packet (recall that we - // toggle the bit before a send, so clearing the bit sets DATA1 for - // the next send). If there's a data IN stage for the SETUP packet, - // it must always be DATA1, regardless of the prior state of the IN - // endpoint. - Data1 &= ~0x02; - - // make sure we own the IN enpdoint now, in preparation for the reply - bdt[PEP_BDT_IDX(EP0IN, EVEN)].info &= ~BD_OWN_MASK; - - // process the SETUP packet through the portable protocol code - EP0setupCallback(); -} -// Control endpoint OUT/SETUP callback. Called from ISR context only. -bool USBHAL::EP0_OUT_callback(void) -{ - int idx = PEP_BDT_IDX(EP0OUT, EVEN); - if (TOK_PID(idx) == SETUP_TOKEN) - { - // SETUP packet on EP0 - EP0_SETUP_callback(); - } - else - { - // OUT packet on EP0 - process it through the protocol code - EP0out(); - } - - // success - return true; -} - -// Control endpoint IN packet handler. This is only called from ISR context. -bool USBHAL::EP0_IN_callback(void) -{ - int idx = PEP_BDT_IDX(EP0OUT, EVEN); - if (TOK_PID(idx) == SETUP_TOKEN) - { - // SETUP packet on EP0 - EP0_SETUP_callback(); - } - else - { - // process the IN packet through the portable protocol code - EP0in(); - } - - // If we have a SET ADDRESS command outstanding, put it into effect now. - // The USB spec requires an address change to be made immediately (within - // 2ms) after the reply to the SET ADDRESS SETUP packet. If the flag is - // set, it means that the EP0in() call above just sent the response, so - // now is the time to make the address change in the SIE hardware register. - if (set_addr == 1) - { - USB0->ADDR = addr & 0x7F; - set_addr = 0; - } - - // success - return true; +void USBHAL::_usbisr(void) { + instance->usbisr(); } -void USBHAL::_usbisr(void) -{ - inIRQ = true; - instance->usbisr(); - inIRQ = false; -} - - -void USBHAL::usbisr(void) -{ +void USBHAL::usbisr(void) { uint8_t i; uint8_t istat = USB0->ISTAT; // reset interrupt - if (istat & USB_ISTAT_USBRST_MASK) - { + if (istat & USB_ISTAT_USBRST_MASK) { + // disable all endpt - for(i = 0 ; i < 16 ; i++) + for(i = 0; i < 16; i++) { USB0->ENDPOINT[i].ENDPT = 0x00; + } // enable control endpoint realiseEndpoint(EP0OUT, MAX_PACKET_SIZE_EP0, 0); realiseEndpoint(EP0IN, MAX_PACKET_SIZE_EP0, 0); Data1 = 0x55555555; - epComplete = 0; USB0->CTL |= USB_CTL_ODDRST_MASK; USB0->ISTAT = 0xFF; // clear all interrupt status flags @@ -675,83 +458,91 @@ // we're not suspended suspendStateChanged(0); - - // return now - do no more processing on a RESET interrupt + return; } // resume interrupt - if (istat & USB_ISTAT_RESUME_MASK) - { + if (istat & USB_ISTAT_RESUME_MASK) { + USB0->ISTAT = USB_ISTAT_RESUME_MASK; suspendStateChanged(0); - USB0->ISTAT = USB_ISTAT_RESUME_MASK; } // SOF interrupt - if (istat & USB_ISTAT_SOFTOK_MASK) - { - // Read frame number and signal the SOF event to the callback + if (istat & USB_ISTAT_SOFTOK_MASK) { + USB0->ISTAT = USB_ISTAT_SOFTOK_MASK; + // SOF event, read frame number SOF(frameNumber()); - USB0->ISTAT = USB_ISTAT_SOFTOK_MASK; } // stall interrupt - if (istat & USB_ISTAT_STALL_MASK) - { - // if the control endpoint (EP 0) is stalled, unstall it + if (istat & 1<<7) { if (USB0->ENDPOINT[0].ENDPT & USB_ENDPT_EPSTALL_MASK) - { - unstallEndpoint(EP0OUT); - unstallEndpoint(EP0IN); - } - - // clear the SUSPEND flag to allow token processing to continue - USB0->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK; - USB0->ISTAT = USB_ISTAT_STALL_MASK; + USB0->ENDPOINT[0].ENDPT &= ~USB_ENDPT_EPSTALL_MASK; + USB0->ISTAT |= USB_ISTAT_STALL_MASK; } // token interrupt - if (istat & USB_ISTAT_TOKDNE_MASK) - { + if (istat & 1<<3) { uint32_t num = (USB0->STAT >> 4) & 0x0F; uint32_t dir = (USB0->STAT >> 3) & 0x01; - int endpoint = (num << 1) | dir; - // uint32_t ev_odd = (USB0->STAT >> 2) & 0x01; // we only use EVEN buffers, so this is always 0 + uint32_t ev_odd = (USB0->STAT >> 2) & 0x01; + + // setup packet + if ((num == 0) && (TOK_PID((EP_BDT_IDX(num, dir, ev_odd))) == SETUP_TOKEN)) { + Data1 &= ~0x02; + bdt[EP_BDT_IDX(0, TX, EVEN)].info &= ~BD_OWN_MASK; + bdt[EP_BDT_IDX(0, TX, ODD)].info &= ~BD_OWN_MASK; + + // EP0 SETUP event (SETUP data received) + EP0setupCallback(); - // set the Completed bit for the endpoint to indicate that we've - // finished this send/receive request - epComplete |= EP(endpoint); - - // Call the endpoint packet callback. If that returns true, it means - // that the callback handled the packet. That consumes the packet, so - // clear the Completed flag to indicate that we're on to the next - // transaction on the endpoint. - if ((instance->*(epCallback[endpoint]))()) - epComplete &= ~EP(endpoint); + } else { + // OUT packet + if (TOK_PID((EP_BDT_IDX(num, dir, ev_odd))) == OUT_TOKEN) { + if (num == 0) + EP0out(); + else { + epComplete |= (1 << EP(num)); + if ((instance->*(epCallback[EP(num) - 2]))()) { + epComplete &= ~(1 << EP(num)); + } + } + } - // allow token processing to resume - USB0->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK; - - // reset the TOKDNE interrupt status flag + // IN packet + if (TOK_PID((EP_BDT_IDX(num, dir, ev_odd))) == IN_TOKEN) { + if (num == 0) { + EP0in(); + if (set_addr == 1) { + USB0->ADDR = addr & 0x7F; + set_addr = 0; + } + } + else { + epComplete |= (1 << (EP(num) + 1)); + if ((instance->*(epCallback[EP(num) + 1 - 2]))()) { + epComplete &= ~(1 << (EP(num) + 1)); + } + } + } + } + USB0->ISTAT = USB_ISTAT_TOKDNE_MASK; } // sleep interrupt - if (istat & USB_ISTAT_SLEEP_MASK) - { + if (istat & 1<<4) { + USB0->ISTAT |= USB_ISTAT_SLEEP_MASK; suspendStateChanged(1); - USB0->ISTAT = USB_ISTAT_SLEEP_MASK; } // error interrupt - if (istat & USB_ISTAT_ERROR_MASK) - { - // reset all error status bits, and clear the SUSPEND flag to allow - // token processing to continue + if (istat & USB_ISTAT_ERROR_MASK) { USB0->ERRSTAT = 0xFF; - USB0->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK; - USB0->ISTAT = USB_ISTAT_ERROR_MASK; + USB0->ISTAT |= USB_ISTAT_ERROR_MASK; } } + #endif
--- a/USBDevice/USBHID/USBHID.cpp Thu Feb 11 18:12:52 2016 +0000 +++ b/USBDevice/USBHID/USBHID.cpp Thu Feb 11 18:31:05 2016 +0000 @@ -112,19 +112,16 @@ // multiple interfaces, this is used to identify which interface // is being queried. The base mbed implementation ignores this, // which makes it impossible to implement multiple interfaces. - int idx = DESCRIPTOR_INDEX(transfer->setup.wValue); + int idx = transfer->setup.wIndex; transfer->remaining = reportDescLengthN(idx); transfer->ptr = reportDescN(idx); transfer->direction = DEVICE_TO_HOST; success = true; } break; - case HID_DESCRIPTOR: - { // Find the HID descriptor, after the configuration descriptor - int idx = DESCRIPTOR_INDEX(transfer->setup.wValue); - hidDescriptor = findDescriptor(HID_DESCRIPTOR, idx); + hidDescriptor = findDescriptor(HID_DESCRIPTOR, transfer->setup.wIndex); if (hidDescriptor != NULL) { transfer->remaining = HID_DESCRIPTOR_LENGTH; @@ -132,8 +129,7 @@ transfer->direction = DEVICE_TO_HOST; success = true; } - } - break; + break; default: break; @@ -150,26 +146,7 @@ { switch (transfer->setup.bRequest) { - case GET_REPORT: - // not implemented - break; - - case GET_IDLE: -#if 0 // $$$ - // retrieve the idle rate from an interface - idleData = getIdleTime(transfer->setup.wIndex, LSB(transfer->setup.wValue)); - transfer->ptr = &idleData; - transfer->remaining = 1; - transfer->direction = DEVICE_TO_HOST; - success = true; -#endif // $$$ - break; - - case GET_PROTOCOL: - // not implemented - break; - - case SET_REPORT: + case SET_REPORT: // First byte will be used for report ID outputReport.data[0] = transfer->setup.wValue & 0xff; outputReport.length = transfer->setup.wLength + 1; @@ -179,25 +156,6 @@ transfer->direction = HOST_TO_DEVICE; transfer->notify = true; success = true; - - case SET_IDLE: -#if 0 // $$$ - // Set idle time - time between INTERRUPT IN reports from the - // device when there are no changes to report. setup.wIndex - // is the interface index (we're setting the idle time for the - // given interface only). MSB(setup.wValue) gives the interval - // in 4ms units, with the special case that 0 means infinity. - setIdleTime(transfer->setup.wIndex, LSB(transfer->setup.wValue), MSB(transfer->setup.wValue)); - transfer->remaining = 0; - transfer->direction = DEVICE_TO_HOST; - success = true; -#endif // $$$ - break; - - case SET_PROTOCOL: - // not implemented - break; - default: break; }
--- a/USBDevice/USBHID/USBHID.h Thu Feb 11 18:12:52 2016 +0000 +++ b/USBDevice/USBHID/USBHID.h Thu Feb 11 18:31:05 2016 +0000 @@ -115,7 +115,7 @@ * @returns pointer to the report descriptor */ virtual uint8_t * reportDesc(); - virtual uint8_t * reportDescN(int idx) { return reportDesc(); /*$$$idx == 0 ? reportDesc() : 0;*/ } + virtual uint8_t * reportDescN(int idx) { return idx == 0 ? reportDesc() : 0; } /* * Get the length of the report descriptor @@ -149,39 +149,7 @@ * @returns pointer to the configuration descriptor */ virtual uint8_t * configurationDesc(); - - /* - * Set the idle time on the given interface. The idle time is the time between - * INTERRUPT IN reports sent from the device to the host in the absence of any - * updates in values. E.g., for a keyboard, this is the time between reports - * when there's no new key up/down activity to report. An infinite idle time - * means that reports are sent only when new activity occurs. - * - * @param ifc Interface index (this specifies which interface is affected, in - * cases where the device has multiple interfaces) - * - * @param reportID Report ID (specifies which report type is affected, in cases - * where the device has multiple report types) - * - * @param t Idle time in 4ms units, with the special case that 0 means infinity. - * The maximum value is 255 units (1.02s). - */ - virtual void setIdleTime(int ifc, int reportId, int t) { } - - /* - * Get the idle time on the given interface. Returns the idle time information - * previously set with setIdleTime(). - * - * @param ifc Interface index (specifies which interface is being queried, in - * cases where the device has multiple interfaces) - * - * @param reportID Report ID (specifies which report type is being queried, in - * cases where the device has multiple report types) - * - * @return The idle time currently set on the interface, in 4ms units. 0 means - * infinity (so reports will only be sent when there's new data) - */ - virtual uint8_t getIdleTime(int ifc, int reportId) { return 0; } + /* * HID Report received by SET_REPORT request. Warning: Called in ISR context @@ -215,7 +183,6 @@ HID_REPORT outputReport; uint8_t output_length; uint8_t input_length; - uint8_t idleData; }; #endif
--- a/USBDevice/USBHID/USBHID_Types.h Thu Feb 11 18:12:52 2016 +0000 +++ b/USBDevice/USBHID/USBHID_Types.h Thu Feb 11 18:31:05 2016 +0000 @@ -35,12 +35,10 @@ #define REPORT_DESCRIPTOR (34) /* Class requests */ -#define GET_REPORT (0x01) -#define GET_IDLE (0x02) -#define GET_PROTOCOL (0x03) -#define SET_REPORT (0x09) -#define SET_IDLE (0x0a) -#define SET_PROTOCOL (0x0b) +#define GET_REPORT (0x1) +#define GET_IDLE (0x2) +#define SET_REPORT (0x9) +#define SET_IDLE (0xa) /* HID Class Report Descriptor */ /* Short items: size is 0, 1, 2 or 3 specifying 0, 1, 2 or 4 (four) bytes */