first release for keyboard
Fork of F401RE-USBHost by
Revision 18:61554f238584, committed 2014-07-01
- Comitter:
- va009039
- Date:
- Tue Jul 01 18:33:31 2014 +0900
- Parent:
- 17:4a710e2ba162
- Child:
- 19:47978c25c9b8
- Commit message:
- add lpc4088/lpc1768
Changed in this revision
--- a/USBHost/USBEndpoint.h Mon Jun 23 20:48:53 2014 +0900 +++ b/USBHost/USBEndpoint.h Tue Jul 01 18:33:31 2014 +0900 @@ -52,6 +52,11 @@ data01_toggle = DATA0; } + void ohci_init(uint8_t frameCount, uint8_t queueLimit) { + ohci.frameCount = frameCount; + ohci.queueLimit = queueLimit; + } + /** * Attach a member function to call when a transfer is finished * @@ -112,6 +117,10 @@ template<class T> T getHALData() { return reinterpret_cast<T>(pData); } + struct { + uint8_t queueLimit; + uint8_t frameCount; // 1-8 + } ohci; private: USBEndpoint(){} ENDPOINT_TYPE type;
--- a/USBHost/USBHALHost.h Mon Jun 23 20:48:53 2014 +0900 +++ b/USBHost/USBHALHost.h Tue Jul 01 18:33:31 2014 +0900 @@ -1,9 +1,34 @@ +#include "mbed.h" + +struct SETUP_PACKET { + uint8_t bmRequestType; + uint8_t bRequest; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; + SETUP_PACKET(uint8_t RequestType, uint8_t Request, uint16_t Value, uint16_t Index, uint16_t Length) { + bmRequestType = RequestType; + bRequest = Request; + wValue = Value; + wIndex = Index; + wLength = Length; + } +}; + #if defined(TARGET_NUCLEO_F401RE) #include "USBHALHost_F401RE.h" #elif defined(TARGET_KL46Z)||defined(TARGET_KL25Z)||defined(TARGET_K64F) #include "USBHALHost_KL46Z.h" +#elif defined(TARGET_LPC4088)||defined(TARGET_LPC1768) +#include "USBHALHost_LPC4088.h" #else #error "target error" #endif +#ifndef CTASSERT +template <bool>struct CtAssert; +template <>struct CtAssert<true> {}; +#define CTASSERT(A) CtAssert<A>(); +#endif // CTASSERT +
--- a/USBHost/USBHALHost2_F401RE.cpp Mon Jun 23 20:48:53 2014 +0900 +++ b/USBHost/USBHALHost2_F401RE.cpp Tue Jul 01 18:33:31 2014 +0900 @@ -1,6 +1,5 @@ -// Simple USBHost for Nucleo F401RE #if defined(TARGET_NUCLEO_F401RE) -#include "USBHALHost_F401RE.h" +#include "USBHALHost.h" // usbh_conf.c HCD_HandleTypeDef hhcd_USB_OTG_FS;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/USBHALHost2_LPC4088.cpp Tue Jul 01 18:33:31 2014 +0900 @@ -0,0 +1,205 @@ +#if defined(TARGET_LPC4088)||defined(TARGET_LPC1768) +#include "USBHALHost.h" + +#undef USB_TEST_ASSERT +void usb_test_assert_internal(const char *expr, const char *file, int line); +#define USB_TEST_ASSERT(EXPR) while(!(EXPR)){usb_test_assert_internal(#EXPR,__FILE__,__LINE__);} + +#define USB_INFO(...) do{fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");}while(0); + +//#define DBG_USE_POSIX_MEMALIGN + +#ifdef DBG_USE_POSIX_MEMALIGN +void* usb_ram_malloc(size_t size, int aligment) +{ + TEST_ASSERT(aligment >= 4); + TEST_ASSERT(!(aligment & 3)); + void* p; + if (posix_memalign(&p, aligment, size) == 0) { + return p; + } + return NULL; +} + +void usb_ram_free(void* p) +{ + free(p); +} +#else + +#define CHUNK_SIZE 64 + +#if defined(TARGET_LPC1768) +#define USB_RAM_BASE 0x2007C000 +#define USB_RAM_SIZE 0x4000 +#define BLOCK_COUNT (USB_RAM_SIZE/CHUNK_SIZE) +#elif defined(TARGET_LPC4088) +#define USB_RAM_BASE 0x20000000 +#define USB_RAM_SIZE 0x4000 +#define BLOCK_COUNT (USB_RAM_SIZE/CHUNK_SIZE) +#else +#error "target error" +#endif + +static uint8_t* ram = NULL; +static uint8_t* map; + +static void usb_ram_init() +{ + USB_INFO("USB_RAM: 0x%p(%d)", USB_RAM_BASE, USB_RAM_SIZE); + ram = (uint8_t*)USB_RAM_BASE; + USB_TEST_ASSERT((int)ram%256 == 0); + map = (uint8_t*)malloc(BLOCK_COUNT); + USB_TEST_ASSERT(map); + memset(map, 0, BLOCK_COUNT); +} + +// first fit malloc +void* usb_ram_malloc(size_t size, int aligment) +{ + USB_TEST_ASSERT(aligment >= 4); + USB_TEST_ASSERT(!(aligment & 3)); + if (ram == NULL) { + usb_ram_init(); + } + int needs = (size+CHUNK_SIZE-1)/CHUNK_SIZE; + void* p = NULL; + for(int idx = 0; idx < BLOCK_COUNT;) { + bool found = true; + for(int i = 0; i < needs; i++) { + int block = map[idx + i]; + if (block != 0) { + idx += block; + found = false; + break; + } + } + if (!found) { + continue; + } + p = ram+idx*CHUNK_SIZE; + if ((int)p % aligment) { + idx++; + continue; + } + USB_TEST_ASSERT((idx + needs) <= BLOCK_COUNT); + for(int i = 0; i < needs; i++) { + map[idx + i] = needs - i; + } + break; + } + USB_TEST_ASSERT(p); + return p; +} + +void usb_ram_free(void* p) +{ + USB_TEST_ASSERT(p >= ram); + USB_TEST_ASSERT(p < (ram+CHUNK_SIZE*BLOCK_COUNT)); + int idx = ((int)p-(int)ram)/CHUNK_SIZE; + int block = map[idx]; + USB_TEST_ASSERT(block >= 1); + for(int i =0; i < block; i++) { + map[idx + i] = 0; + } +} + +#endif // DBG_USE_POSIX_MEMALIGN + +void print_td(FILE* stream, HCTD* td) +{ + if (td == NULL) { + fprintf(stream, "TD %p:\n", td); + return; + } + uint32_t* p = reinterpret_cast<uint32_t*>(td); + fprintf(stream, "TD %p: %08X %08X %08X %08X", p, p[0], p[1], p[2], p[3]); + fprintf(stream, " ep=%p\n", td->parent); + uint8_t* bp = reinterpret_cast<uint8_t*>(p[1]); + uint8_t* be = reinterpret_cast<uint8_t*>(p[3]); + if (bp) { + fprintf(stream, "BF %p:", bp); + while(bp <= be) { + fprintf(stream, " %02X", *bp); + bp++; + } + fprintf(stream, "\n"); + } +} + +void print_ed(FILE* stream, HCED* ed) +{ + uint32_t* p = reinterpret_cast<uint32_t*>(ed); + while(p) { + fprintf(stream, "ED %p: %08X %08X %08X %08X\n", p, p[0], p[1], p[2], p[3]); + HCTD* td = reinterpret_cast<HCTD*>(p[2] & ~3); + HCTD* tdtail = reinterpret_cast<HCTD*>(p[1]); + while(td != NULL && td != tdtail) { + print_td(stream, td); + td = td->Next; + } + p = reinterpret_cast<uint32_t*>(p[3]); + } +} + +void print_itd(FILE* stream, HCITD* itd) +{ + if (itd == NULL) { + fprintf(stream, "ITD %p:\n", itd); + return; + } + uint32_t* p = reinterpret_cast<uint32_t*>(itd); + fprintf(stream, "ITD %p: %08X %08X %08X %08X", p, p[0], p[1], p[2], p[3]); + fprintf(stream, " ep=%p\n", itd->parent); + uint16_t* offset = reinterpret_cast<uint16_t*>(p+4); + fprintf(stream, "ITD %p: %04X %04X %04X %04X %04X %04X %04X %04X\n", offset, + offset[0], offset[1], offset[2], offset[3], offset[4], offset[5], offset[6], offset[7]); +} + +void print_ied(FILE* stream, HCED* ed) +{ + uint32_t* p = reinterpret_cast<uint32_t*>(ed); + while(p) { + fprintf(stream, "ED %p: %08X %08X %08X %08X\n", p, p[0], p[1], p[2], p[3]); + HCITD* itd = reinterpret_cast<HCITD*>(p[2] & ~3); + HCITD* itdtail = reinterpret_cast<HCITD*>(p[1]); + while(itd != NULL && itd != itdtail) { + print_itd(stream, itd); + itd = itd->Next; + } + p = reinterpret_cast<uint32_t*>(p[3]); + } +} + +void print_bytes(FILE* stream, char* s, uint8_t* buf, int len) +{ + fprintf(stream, "%s %d:", s, len); + for(int i = 0; i < len; i++) { + fprintf(stream, " %02X", buf[i]); + } + fprintf(stream, "\n"); +} + +void print_hex(FILE* stream, uint8_t* p, int len) +{ + for(int i = 0; i < len; i++) { + if (i%16 == 0) { + fprintf(stream, "%p:", p); + } + fprintf(stream, " %02X", *p); + p++; + if (i%16 == 15) { + fprintf(stream, "\n"); + } + } + fprintf(stream, "\n"); +} + +void assert_print(const char* pf, int line, const char* msg) { + printf("\n\n%s@%d %s ASSERT!\n\n", pf, line, msg); + exit(1); +} + +#endif // defined(TARGET_LPC4088)||defined(TARGET_LPC1768) + +
--- a/USBHost/USBHALHost_F401RE.cpp Mon Jun 23 20:48:53 2014 +0900 +++ b/USBHost/USBHALHost_F401RE.cpp Tue Jul 01 18:33:31 2014 +0900 @@ -1,13 +1,7 @@ -// Simple USBHost for Nucleo F401RE #if defined(TARGET_NUCLEO_F401RE) -#include "USBHALHost_F401RE.h" +#include "USBHALHost.h" #include <algorithm> -template <bool>struct CtAssert; -template <>struct CtAssert<true> {}; -#define CTASSERT(A) CtAssert<A>(); - - #ifdef _USB_DBG extern RawSerial pc; //RawSerial pc(USBTX,USBRX); @@ -20,25 +14,11 @@ #define USB_DBG_HEX(A,B) while(0) #endif -#ifdef _USB_TEST -#define USB_TEST_ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);}; -#define USB_TEST_ASSERT_FALSE(A) USB_TEST_ASSERT(!(A)) -#else -#define USB_TEST_ASSERT(A) while(0) -#define USB_TEST_ASSERT_FALSE(A) while(0) -#endif +#undef USB_TEST_ASSERT +void usb_test_assert_internal(const char *expr, const char *file, int line); +#define USB_TEST_ASSERT(EXPR) while(!(EXPR)){usb_test_assert_internal(#EXPR,__FILE__,__LINE__);} -#ifdef _USB_TRACE -#define USB_TRACE() while(0) #define USB_TRACE1(A) while(0) -#define USB_TRACE_VIEW() while(0) -#define USB_TRACE_CLEAR() while(0) -#else -#define USB_TRACE() while(0) -#define USB_TRACE1(A) while(0) -#define USB_TRACE_VIEW() while(0) -#define USB_TRACE_CLEAR() while(0) -#endif #define USB_INFO(...) do{fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");}while(0); @@ -83,7 +63,7 @@ extern "C" { void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd) { - USB_TRACE(); + USB_TRACE1(hhcd); attach_done = true; } @@ -410,7 +390,7 @@ return read_len; } -int USBHALHost::multi_token_out(USBEndpoint* ep, const uint8_t* data, size_t total, bool block) { +int USBHALHost::multi_token_out(USBEndpoint* ep, const uint8_t* data, size_t total) { if (total == 0) { return token_out(ep); } @@ -435,12 +415,39 @@ } return write_len; } +void USBHALHost::multi_token_inNB(USBEndpoint* ep, uint8_t* data, int size) { + USB_TRACE1(size); + USB_TEST_ASSERT(ep->getState() != USB_TYPE_PROCESSING); + ep->setBuffer(data, size); + ep->setState(USB_TYPE_PROCESSING); +} + +USB_TYPE USBHALHost::multi_token_inNB_result(USBEndpoint* ep) { + USB_TEST_ASSERT(ep->getState() == USB_TYPE_PROCESSING); + uint8_t* buf = ep->getBufStart(); + int size = ep->getBufSize(); + int result = multi_token_in(ep, buf, size, false); + USB_TRACE1(result); + if (result < 0) { + return USB_TYPE_PROCESSING; + } + ep->setLengthTransferred(result); + ep->setState(USB_TYPE_IDLE); + return USB_TYPE_OK; + +} + +void USBHALHost::setToggle(USBEndpoint* ep, uint8_t toggle) { + USB_TEST_ASSERT(toggle == 1); + ep->setData01(toggle == 0 ? DATA0 : DATA1); +} uint8_t HC::slot = 0x00; HC::HC() { - uint8_t mask = 0x01; - for(int i = 1; i < 8; i++, mask <<= 1) { + static const int start = 1; + uint8_t mask = (1<<start); + for(int i = start; i < 8; i++, mask <<= 1) { if (!(slot & mask)) { slot |= mask; _ch = i;
--- a/USBHost/USBHALHost_F401RE.h Mon Jun 23 20:48:53 2014 +0900 +++ b/USBHost/USBHALHost_F401RE.h Tue Jul 01 18:33:31 2014 +0900 @@ -1,17 +1,8 @@ -// Simple USBHost for Nucleo F401RE #pragma once #include "mbed.h" #include "USBHostTypes.h" #include "USBEndpoint.h" -struct SETUP_PACKET { - uint8_t bmRequestType; - uint8_t bRequest; - uint16_t wValue; - uint16_t wIndex; - uint16_t wLength; -}; - class HC { static const uint8_t DIR_IN = 1; static const uint8_t DIR_OUT = 0; @@ -44,14 +35,13 @@ USBHALHost(); void init(); virtual bool addDevice(USBDeviceConnected* parent, int port, bool lowSpeed) = 0; - void setAddr(int addr, bool lowSpeed = false){} - void setEndpoint(){} - void token_transfer_init(){} int token_setup(USBEndpoint* ep, SETUP_PACKET* setup, uint16_t wLength = 0); int token_iso_in(USBEndpoint* ep, uint8_t* data, int size); - void token_ready(){} int multi_token_in(USBEndpoint* ep, uint8_t* data = NULL, size_t total = 0, bool block = true); - int multi_token_out(USBEndpoint* ep, const uint8_t* data = NULL, size_t total = 0, bool block = true); + int multi_token_out(USBEndpoint* ep, const uint8_t* data = NULL, size_t total = 0); + void multi_token_inNB(USBEndpoint* ep, uint8_t* data, int size); + USB_TYPE multi_token_inNB_result(USBEndpoint* ep); + void setToggle(USBEndpoint* ep, uint8_t toggle); private: int token_in(USBEndpoint* ep, uint8_t* data = NULL, int size = 0, int retryLimit = 10);
--- a/USBHost/USBHALHost_KL46Z.cpp Mon Jun 23 20:48:53 2014 +0900 +++ b/USBHost/USBHALHost_KL46Z.cpp Tue Jul 01 18:33:31 2014 +0900 @@ -1,13 +1,8 @@ // Simple USBHost for FRDM-KL46Z #if defined(TARGET_KL46Z)||defined(TARGET_KL25Z)||defined(TARGET_K64F) -#include "USBHALHost_KL46Z.h" +#include "USBHALHost.h" #include <algorithm> -template <bool>struct CtAssert; -template <>struct CtAssert<true> {}; -#define CTASSERT(A) CtAssert<A>(); - - #ifdef _USB_DBG #define USB_DBG(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");} while(0); #define USB_DBG_HEX(A,B) debug_hex(A,B) @@ -17,13 +12,11 @@ #define USB_DBG_HEX(A,B) while(0) #endif -#ifdef _USB_TEST -#define USB_TEST_ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);}; -#define USB_TEST_ASSERT_FALSE(A) USB_TEST_ASSERT(!(A)) -#else -#define USB_TEST_ASSERT(A) while(0) -#define USB_TEST_ASSERT_FALSE(A) while(0) -#endif +#undef USB_TEST_ASSERT +extern void usb_test_assert_internal(const char *expr, const char *file, int line); +#define USB_TEST_ASSERT(EXPR) while(!(EXPR)){usb_test_assert_internal(#EXPR,__FILE__,__LINE__);} + +#define USB_TRACE1(A) while(0) #define USB_INFO(...) do{fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");}while(0); @@ -156,7 +149,7 @@ } } wait_ms(100); - USB_TEST_ASSERT_FALSE(USB0->CTL & USB_CTL_SE0_MASK); + USB_TEST_ASSERT(!(USB0->CTL & USB_CTL_SE0_MASK)); root_lowSpeed = (USB0->CTL & USB_CTL_JSTATE_MASK) ? false : true; return root_lowSpeed; } @@ -181,6 +174,8 @@ int USBHALHost::token_setup(USBEndpoint* ep, SETUP_PACKET* setup, uint16_t wLength) { USBDeviceConnected* dev = ep->getDevice(); + setAddr(dev->getAddress(), dev->getSpeed()); + for(int retry = 0;; retry++) { token_ready(); USB0->ENDPOINT[0].ENDPT = (root_lowSpeed ? USB_ENDPT_HOSTWOHUB_MASK : 0x00) | @@ -220,6 +215,10 @@ } int USBHALHost::token_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit) { + USBDeviceConnected* dev = ep->getDevice(); + setAddr(dev->getAddress(), dev->getSpeed()); + setEndpoint(); + for(int retry = 0;; retry++) { token_ready(); int idx = EP0_BDT_IDX(RX, rx_ptr); @@ -268,6 +267,11 @@ } int USBHALHost::token_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit) { + USBDeviceConnected* dev = ep->getDevice(); + USB_TEST_ASSERT(dev); + setAddr(dev->getAddress(), dev->getSpeed()); + setEndpoint(); + for(int retry = 0;; retry++) { token_ready(); int idx = EP0_BDT_IDX(TX, tx_ptr); @@ -305,7 +309,37 @@ } } +void USBHALHost::multi_token_inNB(USBEndpoint* ep, uint8_t* data, int size) { + USB_TRACE1(size); + USB_TEST_ASSERT(ep->getState() != USB_TYPE_PROCESSING); + ep->setBuffer(data, size); + ep->setState(USB_TYPE_PROCESSING); +} + +USB_TYPE USBHALHost::multi_token_inNB_result(USBEndpoint* ep) { + USB_TEST_ASSERT(ep->getState() == USB_TYPE_PROCESSING); + uint8_t* buf = ep->getBufStart(); + int size = ep->getBufSize(); + int result = multi_token_in(ep, buf, size, false); + USB_TRACE1(result); + if (result < 0) { + return USB_TYPE_PROCESSING; + } + ep->setLengthTransferred(result); + ep->setState(USB_TYPE_IDLE); + return USB_TYPE_OK; +} + +void USBHALHost::setToggle(USBEndpoint* ep, uint8_t toggle) { + USB_TEST_ASSERT(toggle == 1); + ep->setData01(toggle == 0 ? DATA0 : DATA1); +} + int USBHALHost::token_iso_in(USBEndpoint* ep, uint8_t* data, int size) { + USBDeviceConnected* dev = ep->getDevice(); + USB_TEST_ASSERT(dev); + setAddr(dev->getAddress()); + while(USB0->CTL & USB_CTL_TXSUSPENDTOKENBUSY_MASK); // TOKEN_BUSY ? USB0->ISTAT |= USB_ISTAT_SOFTOK_MASK; // Clear SOF while (!(USB0->ISTAT & USB_ISTAT_SOFTOK_MASK)); @@ -371,7 +405,7 @@ return read_len; } -int USBHALHost::multi_token_out(USBEndpoint* ep, const uint8_t* data, size_t total, bool block) { +int USBHALHost::multi_token_out(USBEndpoint* ep, const uint8_t* data, size_t total) { if (total == 0) { return token_out(ep); }
--- a/USBHost/USBHALHost_KL46Z.h Mon Jun 23 20:48:53 2014 +0900 +++ b/USBHost/USBHALHost_KL46Z.h Tue Jul 01 18:33:31 2014 +0900 @@ -1,17 +1,8 @@ -// Simple USBHost for FRDM-KL46Z #pragma once #include "mbed.h" #include "USBHostTypes.h" #include "USBEndpoint.h" -struct SETUP_PACKET { - uint8_t bmRequestType; - uint8_t bRequest; - uint16_t wValue; - uint16_t wIndex; - uint16_t wLength; -}; - #define GET_CONFIGURATION 8 // TOK_PID[5:2] @@ -50,16 +41,19 @@ USBHALHost(); void init(); virtual bool addDevice(USBDeviceConnected* parent, int port, bool lowSpeed) = 0; + int token_setup(USBEndpoint* ep, SETUP_PACKET* setup, uint16_t wLength = 0); + int multi_token_in(USBEndpoint* ep, uint8_t* data = NULL, size_t total = 0, bool block = true); + int multi_token_out(USBEndpoint* ep, const uint8_t* data = NULL, size_t total = 0); + void multi_token_inNB(USBEndpoint* ep, uint8_t* data, int size); + USB_TYPE multi_token_inNB_result(USBEndpoint* ep); + void setToggle(USBEndpoint* ep, uint8_t toggle); + int token_iso_in(USBEndpoint* ep, uint8_t* data, int size); + +private: void setAddr(int addr, bool lowSpeed = false); void setEndpoint(); void token_transfer_init(); - int token_setup(USBEndpoint* ep, SETUP_PACKET* setup, uint16_t wLength = 0); - int multi_token_in(USBEndpoint* ep, uint8_t* data = NULL, size_t total = 0, bool block = true); - int multi_token_out(USBEndpoint* ep, const uint8_t* data = NULL, size_t total = 0, bool block = true); - int token_iso_in(USBEndpoint* ep, uint8_t* data, int size); void token_ready(); - -private: int token_in(USBEndpoint* ep, uint8_t* data = NULL, int size = 0, int retryLimit = 10); int token_out(USBEndpoint* ep, const uint8_t* data = NULL, int size = 0, int retryLimit = 10); static void _usbisr(void);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/USBHALHost_LPC4088.cpp Tue Jul 01 18:33:31 2014 +0900 @@ -0,0 +1,604 @@ +/* mbed USBHost Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined(TARGET_LPC4088)||defined(TARGET_LPC1768) +#include "USBHALHost.h" + +#ifndef CTASSERT +template <bool>struct CtAssert; +template <>struct CtAssert<true> {}; +#define CTASSERT(A) CtAssert<A>(); +#endif + +#ifdef _USB_DBG +#define USB_DBG(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");} while(0); +#define USB_DBG_HEX(A,B) debug_hex(A,B) +#define USB_DBG_ED(A) while(0) +#define USB_DBG_TD(A) while(0) +#define USB_DBG_ED_IF(A,B) while(0) +void debug_hex(uint8_t* buf, int size); +#else +#define USB_DBG(...) while(0) +#define USB_DBG_ED(A) while(0) +#define USB_DBG_TD(A) while(0) +#define USB_DBG_ED_IF(A,B) while(0) +#define USB_DBG_HEX(A,B) while(0) +#endif + +#define USB_TRACE1(A) while(0) + +#ifdef _USB_TEST +#undef USB_TEST_ASSERT +void usb_test_assert_internal(const char *expr, const char *file, int line); +#define USB_TEST_ASSERT(EXPR) while(!(EXPR)){usb_test_assert_internal(#EXPR,__FILE__,__LINE__);} +#else +#define USB_TEST_ASSERT(EXPR) while(0) +#endif + +#define USB_INFO(...) do{fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");}while(0); + +// bits of the USB/OTG clock control register +#define HOST_CLK_EN (1<<0) +#define DEV_CLK_EN (1<<1) +#define PORTSEL_CLK_EN (1<<3) +#define AHB_CLK_EN (1<<4) + +// bits of the USB/OTG clock status register +#define HOST_CLK_ON (1<<0) +#define DEV_CLK_ON (1<<1) +#define PORTSEL_CLK_ON (1<<3) +#define AHB_CLK_ON (1<<4) + +// we need host clock, OTG/portsel clock and AHB clock +#define CLOCK_MASK (HOST_CLK_EN | PORTSEL_CLK_EN | AHB_CLK_EN) +#define FI 0x2EDF /* 12000 bits per frame (-1) */ +#define DEFAULT_FMINTERVAL ((((6 * (FI - 210)) / 7) << 16) | FI) + +USBHALHost* USBHALHost::instHost; + +USBHALHost::USBHALHost() { + instHost = this; +} + +void USBHALHost::init() { + NVIC_DisableIRQ(USB_IRQn); + m_pHcca = new HCCA(); + init_hw_ohci(m_pHcca); + ResetRootHub(); + NVIC_SetVector(USB_IRQn, (uint32_t)_usbisr); + NVIC_SetPriority(USB_IRQn, 0); + NVIC_EnableIRQ(USB_IRQn); + + USB_INFO("Simple USBHost Library for LPC4088/LPC1768"); + bool lowSpeed = wait_attach(); + addDevice(NULL, 0, lowSpeed); +} + +void USBHALHost::init_hw_ohci(HCCA* pHcca) { + LPC_SC->PCONP &= ~(1UL<<31); //Cut power + wait_ms(1000); + LPC_SC->PCONP |= (1UL<<31); // turn on power for USB + LPC_USB->USBClkCtrl |= CLOCK_MASK; // Enable USB host clock, port selection and AHB clock + // Wait for clocks to become available + while ((LPC_USB->USBClkSt & CLOCK_MASK) != CLOCK_MASK) + ; + LPC_USB->OTGStCtrl |= 1; + LPC_USB->USBClkCtrl &= ~PORTSEL_CLK_EN; + +#if defined(TARGET_LPC1768) + LPC_PINCON->PINSEL1 &= ~((3<<26) | (3<<28)); + LPC_PINCON->PINSEL1 |= ((1<<26)|(1<<28)); // 0x14000000 +#elif defined(TARGET_LPC4088) + LPC_IOCON->P0_29 = 0x01; // USB_D+1 + LPC_IOCON->P0_30 = 0x01; // USB_D-1 + // DO NOT CHANGE P1_19. +#else +#error "target error" +#endif + USB_DBG("initialize OHCI\n"); + wait_ms(100); /* Wait 50 ms before apply reset */ + USB_TEST_ASSERT((LPC_USB->HcRevision&0xff) == 0x10); // check revision + LPC_USB->HcControl = 0; /* HARDWARE RESET */ + LPC_USB->HcControlHeadED = 0; /* Initialize Control list head to Zero */ + LPC_USB->HcBulkHeadED = 0; /* Initialize Bulk list head to Zero */ + /* SOFTWARE RESET */ + LPC_USB->HcCommandStatus = OR_CMD_STATUS_HCR; + LPC_USB->HcFmInterval = DEFAULT_FMINTERVAL; /* Write Fm Interval and Largest Data Packet Counter */ + LPC_USB->HcPeriodicStart = FI*90/100; + /* Put HC in operational state */ + LPC_USB->HcControl = (LPC_USB->HcControl & (~OR_CONTROL_HCFS)) | OR_CONTROL_HC_OPER; + LPC_USB->HcRhStatus = OR_RH_STATUS_LPSC; /* Set Global Power */ + USB_TEST_ASSERT(pHcca); + for (int i = 0; i < 32; i++) { + pHcca->InterruptTable[i] = NULL; + } + LPC_USB->HcHCCA = reinterpret_cast<uint32_t>(pHcca); + LPC_USB->HcInterruptStatus |= LPC_USB->HcInterruptStatus; /* Clear Interrrupt Status */ + LPC_USB->HcInterruptEnable = OR_INTR_ENABLE_MIE|OR_INTR_ENABLE_WDH|OR_INTR_ENABLE_FNO; + + LPC_USB->HcRhPortStatus1 = OR_RH_PORT_CSC; + LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC; +} + +void USBHALHost::ResetRootHub() { + wait_ms(100); /* USB 2.0 spec says at least 50ms delay before port reset */ + LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRS; // Initiate port reset + USB_DBG("Before loop\n"); + while (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_PRS) + ; + LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC; // ...and clear port reset signal + USB_DBG("After loop\n"); + wait_ms(200); /* Wait for 100 MS after port reset */ +} + +bool USBHALHost::wait_attach() { + bool lowSpeed = false; + uint32_t status = LPC_USB->HcRhPortStatus1; + if (status & OR_RH_PORT_LSDA) { // lowSpeedDeviceAttached + lowSpeed = true; + } + return lowSpeed; +} + +void enable(ENDPOINT_TYPE type) { + switch(type) { + case CONTROL_ENDPOINT: + LPC_USB->HcCommandStatus |= OR_CMD_STATUS_CLF; + LPC_USB->HcControl |= OR_CONTROL_CLE; + break; + case ISOCHRONOUS_ENDPOINT: + LPC_USB->HcControl |= OR_CONTROL_PLE; + break; + case BULK_ENDPOINT: + LPC_USB->HcCommandStatus |= OR_CMD_STATUS_BLF; + LPC_USB->HcControl |= OR_CONTROL_BLE; + break; + case INTERRUPT_ENDPOINT: + LPC_USB->HcControl |= OR_CONTROL_PLE; + break; + } +} + +void USBHALHost::token_init(USBEndpoint* ep) { + HCED* ed = ep->getHALData<HCED*>(); + if (ed == NULL) { + ed = new HCED(ep); + ep->setHALData<HCED*>(ed); + } + USBDeviceConnected* dev = ep->getDevice(); + USB_TEST_ASSERT(dev); + if (dev) { + uint8_t devAddr = dev->getAddress(); + USB_DBG("devAddr=%02x", devAddr); + ed->setFunctionAddress(devAddr); + } + uint16_t size = ep->getSize(); + USB_DBG("MaxPacketSize=%d", size); + ed->setMaxPacketSize(size); + if (ed->HeadTd == NULL) { + HCTD* td = new HCTD(ed); + ed->TailTd = td; + ed->HeadTd = td; + switch(ep->getType()) { + case CONTROL_ENDPOINT: + ed->Next = reinterpret_cast<HCED*>(LPC_USB->HcControlHeadED); + LPC_USB->HcControlHeadED = reinterpret_cast<uint32_t>(ed); + break; + case BULK_ENDPOINT: + ed->Next = reinterpret_cast<HCED*>(LPC_USB->HcBulkHeadED); + LPC_USB->HcBulkHeadED = reinterpret_cast<uint32_t>(ed); + break; + case INTERRUPT_ENDPOINT: + HCCA* pHcca = reinterpret_cast<HCCA*>(LPC_USB->HcHCCA); + ed->Next = pHcca->InterruptTable[0]; + pHcca->InterruptTable[0] = ed; + break; + } + } +} + +int USBHALHost::token_setup(USBEndpoint* ep, SETUP_PACKET* setup, uint16_t wLength) { + token_init(ep); + HCED* ed = ep->getHALData<HCED*>(); + HCTD* td = ed->TailTd; + setup->wLength = wLength; + TBUF* tbuf = new(sizeof(SETUP_PACKET))TBUF(setup, sizeof(SETUP_PACKET)); + td->transfer(tbuf, sizeof(SETUP_PACKET)); + td->Control |= TD_TOGGLE_0|TD_SETUP; // DATA0 + HCTD* blank = new HCTD(ed); + ed->enqueue(blank); + //DBG_ED(ed); + enable(ep->getType()); + + td = ed->get_queue_HCTD(); + USB_TEST_ASSERT(td); + int result = td->getLengthTransferred(); + USB_DBG_TD(td); + delete tbuf; + delete td; + return result; +} + +static HCED* getHCED_iso(USBEndpoint* ep) { + HCED* ed = ep->getHALData<HCED*>(); + if (ed != NULL) { + return ed; + } + ed = new HCED(ep); + ep->setHALData<HCED*>(ed); + ed->setFormat(); // F Format ITD + ed->iso.FrameCount = ep->ohci.frameCount; + ed->iso.queue_limit = ep->ohci.queueLimit; + ed->iso.queue_count = 0; + ed->iso.Current_FrameCount = 0; + ed->iso.Current_itd = NULL; + ed->iso.FrameNumber = LPC_USB->HcFmNumber + 10; // after 10msec + HCITD* itd = ed->new_HCITD(); + ed->init_queue(reinterpret_cast<HCTD*>(itd)); + HCCA* hcca = reinterpret_cast<HCCA*>(LPC_USB->HcHCCA); + hcca->enqueue(ed); + LPC_USB->HcControl |= OR_CONTROL_PLE; // PeriodicListEnable + LPC_USB->HcControl |= OR_CONTROL_IE; // IsochronousEnable + return ed; +} + +static void enablePeriodic() { + LPC_USB->HcControl |= OR_CONTROL_PLE; +} + +HCITD* isochronousReceive(USBEndpoint* ep) { + HCED* ed = getHCED_iso(ep); + USB_TEST_ASSERT(ed); + while(ed->iso.queue_count < ed->iso.queue_limit) { + HCITD* blank_itd = ed->new_HCITD(); + if (ed->enqueue(reinterpret_cast<HCTD*>(blank_itd))) { + ed->iso.queue_count++; + } + enablePeriodic(); + } + + HCITD* itd = ed->get_queue_HCITD(); + if (itd) { + ed->iso.queue_count--; + } + return itd; +} + +int USBHALHost::token_iso_in(USBEndpoint* ep, uint8_t* data, int size) { + HCED* ed = getHCED_iso(ep); + if (ed->iso.Current_FrameCount == 0) { + HCITD* itd = isochronousReceive(ep); + if (itd == NULL) { + return -1; + } + if (itd->ConditionCode() != 0) { + delete itd; + return -1; + } + ed->iso.Current_itd = itd; + } + + HCITD* itd = ed->iso.Current_itd; + int fc = ed->iso.Current_FrameCount; + int result = -1; + uint8_t cc = itd->ConditionCode(fc); + if (cc == 0 || cc == 9) { + result = itd->Length(fc); + memcpy(data, itd->Buffer(fc), result); + } + + if (++ed->iso.Current_FrameCount >= itd->FrameCount()) { + ed->iso.Current_FrameCount = 0; + delete ed->iso.Current_itd; + } + return result; +} + +int USBHALHost::multi_token_in(USBEndpoint* ep, uint8_t* data, int size) { + token_init(ep); + HCED* ed = ep->getHALData<HCED*>(); + HCTD* td = ed->TailTd; + TBUF* tbuf = NULL; + if (data != NULL) { + tbuf = new(size)TBUF(); + td->transfer(tbuf, size); + } + td->Control |= TD_IN; + HCTD* blank = new HCTD(ed); + ed->enqueue(blank); + USB_DBG_ED_IF(ed->EndpointNumber()==0, ed); // control transfer + enable(ep->getType()); + + td = ed->get_queue_HCTD(); + USB_TEST_ASSERT(td); + if (data != NULL) { + memcpy(data, tbuf->buf, size); + delete tbuf; + } + int result = td->getLengthTransferred(); + delete td; + return result; +} + +int USBHALHost::multi_token_out(USBEndpoint* ep, const uint8_t* data, int size) { + token_init(ep); + HCED* ed = ep->getHALData<HCED*>(); + HCTD* td = ed->TailTd; + TBUF* tbuf = NULL; + if (data != NULL) { + tbuf = new(size)TBUF(data, size); + td->transfer(tbuf, size); + } + td->Control |= TD_OUT; + HCTD* blank = new HCTD(ed); + ed->enqueue(blank); + USB_DBG_ED(ed); + enable(ep->getType()); + + td = ed->get_queue_HCTD(); + USB_TEST_ASSERT(td); + if (data != NULL) { + delete tbuf; + } + int result = td->getLengthTransferred(); + delete td; + return result; +} + +void USBHALHost::multi_token_inNB(USBEndpoint* ep, uint8_t* data, int size) { + token_init(ep); + HCED* ed = ep->getHALData<HCED*>(); + HCTD* td = ed->TailTd; + TBUF* tbuf = new(size)TBUF(); + td->transfer(tbuf, size); + td->Control |= TD_IN; + HCTD* blank = new HCTD(ed); + ed->enqueue(blank); + enable(ep->getType()); +} + +USB_TYPE USBHALHost::multi_token_inNB_result(USBEndpoint* ep) { + HCED* ed = ep->getHALData<HCED*>(); + if (ed == NULL) { + return USB_TYPE_ERROR; + } + HCTD* td = ed->get_queue_HCTD(0); + if (td) { + int len = td->getLengthTransferred(); + TBUF* tbuf = (TBUF*)td->buf_top; + memcpy(ep->getBufStart(), tbuf->buf, len); + ep->setLengthTransferred(len); + ep->setState((USB_TYPE)td->ConditionCode()); + delete td; + delete tbuf; + return USB_TYPE_OK; + } + return USB_TYPE_PROCESSING; +} + +void USBHALHost::setToggle(USBEndpoint* ep, uint8_t toggle) { + USB_TEST_ASSERT(toggle == 1); + HCED* ed = ep->getHALData<HCED*>(); + ed->setToggle(toggle); +} + +void USBHALHost::_usbisr(void) { + if (instHost) { + instHost->UsbIrqhandler(); + } +} + +HCTD* td_reverse(HCTD* td) +{ + HCTD* result = NULL; + HCTD* next; + while(td) { + next = const_cast<HCTD*>(td->Next); + td->Next = result; + result = td; + td = next; + } + return result; +} + +void USBHALHost::UsbIrqhandler() { + if (!(LPC_USB->HcInterruptStatus & LPC_USB->HcInterruptEnable)) { + return; + } + m_report_irq++; + uint32_t status = LPC_USB->HcInterruptStatus; + if (status & OR_INTR_STATUS_FNO) { + m_report_FNO++; + } + if (status & OR_INTR_STATUS_WDH) { + union { + HCTD* done_td; + uint32_t lsb; + }; + done_td = const_cast<HCTD*>(m_pHcca->DoneHead); + USB_TEST_ASSERT(done_td); + m_pHcca->DoneHead = NULL; // reset + if (lsb & 1) { // error ? + lsb &= ~1; + } + HCTD* td = td_reverse(done_td); + while(td) { + HCED* ed = td->parent; + USB_TEST_ASSERT(ed); + if (ed) { + ed->irqWdhHandler(td); + } + td = td->Next; + } + m_report_WDH++; + } + LPC_USB->HcInterruptStatus = status; // Clear Interrrupt Status +} + +TBUF::TBUF(const void* data, int size) { + if (size > 0) { + memcpy(buf, data, size); + } +} + +HCTD::HCTD(HCED* obj) { + CTASSERT(sizeof(HCTD) == 36); + USB_TEST_ASSERT(obj); + Control = TD_CC|TD_ROUNDING; + CurrBufPtr = NULL; + Next = NULL; + BufEnd = NULL; + buf_top = NULL; + buf_size = 0; + parent = obj; +} + +HCITD::HCITD(HCED* obj, uint16_t FrameNumber, int FrameCount, uint16_t PacketSize) { + Control = 0xe0000000 | // CC ConditionCode NOT ACCESSED + ((FrameCount-1) << 24)| // FC FrameCount + TD_DELAY_INT(0) | // DI DelayInterrupt + FrameNumber; // SF StartingFrame + BufferPage0 = const_cast<uint8_t*>(buf); + BufferEnd = const_cast<uint8_t*>(buf) + PacketSize * FrameCount - 1; + Next = NULL; + parent = obj; + uint32_t addr = reinterpret_cast<uint32_t>(buf); + for(int i = 0; i < FrameCount; i++) { + uint16_t offset = addr & 0x0fff; + if ((addr&0xfffff000) == (reinterpret_cast<uint32_t>(BufferEnd)&0xfffff000)) { + offset |= 0x1000; + } + OffsetPSW[i] = 0xe000|offset; + addr += PacketSize; + } +} + +uint8_t* HCITD::Buffer(int fc) { + int offset = fc * parent->getMaxPacketSize(); + return const_cast<uint8_t*>(buf) + offset; +} + +HCED::HCED(USBEndpoint* ep) { + CTASSERT(sizeof(HCED) <= (64*2)); + USBDeviceConnected* dev = ep->getDevice(); + int devAddr = 0; + bool lowSpeed = false; + if (dev) { + devAddr = dev->getAddress(); + lowSpeed = dev->getSpeed(); + } + int ep_number = ep->getAddress(); + int MaxPacketSize = ep->getSize(); + Control = devAddr | /* USB address */ + ((ep_number & 0x7F) << 7) | /* Endpoint address */ + (ep_number!=0?(((ep_number&0x80)?2:1) << 11):0)| /* direction : Out = 1, 2 = In */ + ((lowSpeed?1:0) << 13) | /* speed full=0 low=1 */ + (MaxPacketSize << 16); /* MaxPkt Size */ + TailTd = NULL; + HeadTd = NULL; + Next = NULL; +} + +bool HCED::enqueue(HCTD* td) { + if (td) { + HCTD* tail = reinterpret_cast<HCTD*>(TailTd); + if (tail) { + tail->Next = td; + TailTd = reinterpret_cast<HCTD*>(td); + return true; + } + } + return false; +} + +void HCED::init_queue(HCTD* td) { + TailTd = reinterpret_cast<HCTD*>(td); + HeadTd = reinterpret_cast<HCTD*>(td); +} + +void HCED::setToggle(uint8_t toggle) { + uint32_t c = reinterpret_cast<uint32_t>(HeadTd); + if (toggle == 0) { // DATA0 + c &= ~0x02; + } else { // DATA1 + c |= 0x02; + } + HeadTd = reinterpret_cast<HCTD*>(c); +} + +uint8_t HCED::getToggle() { + uint32_t c = reinterpret_cast<uint32_t>(HeadTd); + return (c&0x02) ? 1 : 0; +} + +HCTD* HCED::get_queue_HCTD(uint32_t millisec) +{ + for(int i = 0; i < 16; i++) { + osEvent evt = done_queue_get(millisec); + if (evt.status == osEventMessage) { + HCTD* td = reinterpret_cast<HCTD*>(evt.value.p); + USB_TEST_ASSERT(td); + uint8_t cc = td->ConditionCode(); + if (cc != 0) { + m_ConditionCode = cc; + USB_DBG_TD(td); + } + return td; + } else if (evt.status == osOK) { + continue; + } else if (evt.status == osEventTimeout) { + return NULL; + } else { + USB_DBG("evt.status: %02x\n", evt.status); + USB_TEST_ASSERT(evt.status == osEventMessage); + } + } + return NULL; +} + +HCITD* HCED::get_queue_HCITD() { + osEvent evt = done_queue_get(0); + if (evt.status == osEventMessage) { + HCITD* itd = reinterpret_cast<HCITD*>(evt.value.p); + USB_TEST_ASSERT(itd); + return itd; + } + return NULL; +} +HCITD* HCED::new_HCITD() { + uint16_t mps = getMaxPacketSize(); + int total_size = mps * iso.FrameCount; + HCITD* itd = new(total_size)HCITD(this, iso.FrameNumber, iso.FrameCount, mps); + iso.FrameNumber += iso.FrameCount; + return itd; +} + +void HCCA::enqueue(HCED* ed) { + for(int i = 0; i < 32; i++) { + if (InterruptTable[i] == NULL) { + InterruptTable[i] = ed; + } else { + HCED* nextEd = InterruptTable[i]; + while(nextEd->Next && nextEd->Next != ed) { + nextEd = nextEd->Next; + } + nextEd->Next = ed; + } + } +} + +#endif // defined(TARGET_LPC4088)||defined(TARGET_LPC1768) +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/USBHALHost_LPC4088.h Tue Jul 01 18:33:31 2014 +0900 @@ -0,0 +1,284 @@ +/* mbed USBHost Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once +#include "mbed.h" +#include "rtos.h" +#include "USBHostTypes.h" +#include "USBEndpoint.h" + +#if defined(TARGET_LPC4088) +#define HcRevision Revision +#define HcControl Control +#define HcCommandStatus CommandStatus +#define HcInterruptStatus InterruptStatus +#define HcInterruptEnable InterruptEnable +#define HcHCCA HCCA +#define HcControlHeadED ControlHeadED +#define HcBulkHeadED BulkHeadED +#define HcFmInterval FmInterval +#define HcFmNumber FmNumber +#define HcPeriodicStart PeriodicStart +#define HcRhStatus RhStatus +#define HcRhPortStatus1 RhPortStatus1 +#define OTGStCtrl StCtrl +#endif +// ------------------ HcControl Register --------------------- +#define OR_CONTROL_PLE 0x00000004 +#define OR_CONTROL_IE 0x00000008 +#define OR_CONTROL_CLE 0x00000010 +#define OR_CONTROL_BLE 0x00000020 +#define OR_CONTROL_HCFS 0x000000C0 +#define OR_CONTROL_HC_OPER 0x00000080 +// ----------------- HcCommandStatus Register ----------------- +#define OR_CMD_STATUS_HCR 0x00000001 +#define OR_CMD_STATUS_CLF 0x00000002 +#define OR_CMD_STATUS_BLF 0x00000004 +// --------------- HcInterruptStatus Register ----------------- +#define OR_INTR_STATUS_WDH 0x00000002 +#define OR_INTR_STATUS_UE 0x00000010 +#define OR_INTR_STATUS_FNO 0x00000020 +#define OR_INTR_STATUS_RHSC 0x00000040 +// --------------- HcInterruptEnable Register ----------------- +#define OR_INTR_ENABLE_WDH 0x00000002 +#define OR_INTR_ENABLE_FNO 0x00000020 +#define OR_INTR_ENABLE_RHSC 0x00000040 +#define OR_INTR_ENABLE_MIE 0x80000000 +// ---------------- HcRhDescriptorA Register ------------------ +#define OR_RH_STATUS_LPSC 0x00010000 +#define OR_RH_STATUS_DRWE 0x00008000 +// -------------- HcRhPortStatus[1:NDP] Register -------------- +#define OR_RH_PORT_CCS 0x00000001 +#define OR_RH_PORT_PRS 0x00000010 +#define OR_RH_PORT_LSDA 0x00000200 +#define OR_RH_PORT_CSC 0x00010000 +#define OR_RH_PORT_PRSC 0x00100000 + +// TRANSFER DESCRIPTOR CONTROL FIELDS +#define TD_ROUNDING (uint32_t)(0x00040000) /* Buffer Rounding */ +#define TD_SETUP (uint32_t)(0x00000000) /* Direction of Setup Packet */ +#define TD_IN (uint32_t)(0x00100000) /* Direction In */ +#define TD_OUT (uint32_t)(0x00080000) /* Direction Out */ +#define TD_DELAY_INT(x) (uint32_t)((x) << 21) /* Delay Interrupt */ +#define TD_DI (uint32_t)(7<<21) /* desable interrupt */ +#define TD_TOGGLE_0 (uint32_t)(0x02000000) /* Toggle 0 */ +#define TD_TOGGLE_1 (uint32_t)(0x03000000) /* Toggle 1 */ +#define TD_CC (uint32_t)(0xF0000000) /* Completion Code */ + +void* usb_ram_malloc(size_t size, int aligment); // USBHALHost2_LPC4088.cpp +void usb_ram_free(void* p); + +struct TBUF { + uint8_t buf[0]; + TBUF(const void* data = NULL, int size = 0); + void* operator new(size_t size, int buf_size) { return usb_ram_malloc(size+buf_size, 4); } + void operator delete(void* p) { usb_ram_free(p); } +}; + +class HCED; + +struct HCTD { // HostController Transfer Descriptor + __IO uint32_t Control; // +0 Transfer descriptor control + __IO uint8_t* CurrBufPtr; // +4 Physical address of current buffer pointer + HCTD* Next; // +8 Physical pointer to next Transfer Descriptor + uint8_t* BufEnd; // +12 Physical address of end of buffer + uint8_t* buf_top; // +16 Buffer start address + uint16_t buf_size; // +20 buffer size size + uint8_t _dummy[10]; // +22 dummy + HCED* parent; // +32 HCED object + // +36 + HCTD(HCED* ed); + void* operator new(size_t size) { return usb_ram_malloc(size, 16); } + void operator delete(void* p) { usb_ram_free(p); } + + void transfer(TBUF* tbuf, int len) { + CurrBufPtr = tbuf->buf; + buf_top = tbuf->buf; + buf_size = len; + BufEnd = const_cast<uint8_t*>(tbuf->buf)+len-1; + } + int getLengthTransferred() { + if (CurrBufPtr) { + return CurrBufPtr - buf_top; + } + return buf_size; + } + int status() { + if (CurrBufPtr) { + return CurrBufPtr - buf_top; + } + return buf_size; + } + + uint8_t ConditionCode() { + return Control>>28; + } +}; + +struct HCITD { // HostController Isochronous Transfer Descriptor + __IO uint32_t Control; // +0 Transfer descriptor control + uint8_t* BufferPage0; // +4 Buffer Page 0 + HCITD* Next; // +8 Physical pointer to next Isochronous Transfer Descriptor + uint8_t* BufferEnd; // +12 buffer End + __IO uint16_t OffsetPSW[8]; // +16 Offset/PSW + HCED* parent; // +32 HCED object + __IO uint8_t buf[0]; // +36 buffer + // +36 + HCITD(HCED* ed, uint16_t FrameNumber, int FrameCount, uint16_t PacketSize); + uint8_t* Buffer(int fc); + void* operator new(size_t size, int buf_size) { return usb_ram_malloc(size+buf_size, 32); } + void operator delete(void* p) { usb_ram_free(p); } + + uint16_t StartingFrame() { + return Control & 0xffff; + } + + uint8_t FrameCount() { + return ((Control>>24)&7)+1; + } + + uint8_t ConditionCode() { + return Control>>28; + } + + uint8_t ConditionCode(int fc) { + uint16_t psw = OffsetPSW[fc]; + return psw>>12; + } + + uint16_t Length(int fc) { + uint16_t psw = OffsetPSW[fc]; + return psw & 0x7ff; + } +}; + +#define HCTD_QUEUE_SIZE 3 + +struct HCED { // HostController EndPoint Descriptor + __IO uint32_t Control; // +0 Endpoint descriptor control + HCTD* TailTd; // +4 Physical address of tail in Transfer descriptor list + __IO HCTD* HeadTd; // +8 Physcial address of head in Transfer descriptor list + HCED* Next; // +12 Physical address of next Endpoint descriptor + // +16 + uint8_t m_ConditionCode; + Queue<HCTD, HCTD_QUEUE_SIZE> _done_queue; // TD done queue + struct { + uint8_t queue_count; + uint8_t queue_limit; + uint16_t FrameNumber; + uint8_t FrameCount; // 1-8 + HCITD* Current_itd; + uint8_t Current_FrameCount; + } iso; + inline osEvent done_queue_get(uint32_t millisec) { return _done_queue.get(millisec); } + inline void irqWdhHandler(HCTD* td) {_done_queue.put(td);} // WDH + HCTD* get_queue_HCTD(uint32_t millisec=osWaitForever); + HCITD* get_queue_HCITD(); + HCITD* new_HCITD(); + HCED(USBEndpoint* ep); + void* operator new(size_t size) { return usb_ram_malloc(size, 16); } + void operator delete(void* p) { usb_ram_free(p); } + + uint8_t FunctionAddress() { + return Control & 0x7f; + } + + uint8_t EndpointNumber() { + return (Control>>7) & 0x7f; + } + + int Speed() { + return (Control>>13)&1; + } + + void setFunctionAddress(int addr) { + Control &= ~0x7f; + Control |= addr; + } + + void setMaxPacketSize(uint16_t size) { + Control &= ~0x07ff0000; + Control |= size<<16; + } + + uint16_t getMaxPacketSize() { + return (Control>>16)&0x7ff; + } + + void setToggle(uint8_t toggle); + uint8_t getToggle(); + + int Skip() { + return (Control>>14) & 1; + } + + void setSkip() { + Control |= (1<<14); + } + + void setFormat() { + Control |= (1<<15); + } + + bool enqueue(HCTD* td); + void init_queue(HCTD* td); +}; + +struct HCCA { // Host Controller Communication Area + HCED* InterruptTable[32]; // +0 Interrupt Table + __IO uint16_t FrameNumber;// +128 Frame Number + __IO uint16_t Pad1; // +130 + __IO HCTD* DoneHead; // +132 Done Head + uint8_t Reserved[116]; // +136 Reserved for future use + uint8_t Unknown[4]; // +252 Unused + // +256 + void* operator new(size_t size) { return usb_ram_malloc(size, 256); } + void operator delete(void* p) { usb_ram_free(p); } + void enqueue(HCED* ed); +}; + +class USBHALHost { +protected: + USBHALHost(); + void init(); + virtual bool addDevice(USBDeviceConnected* parent, int port, bool lowSpeed) = 0; + int token_setup(USBEndpoint* ep, SETUP_PACKET* setup, uint16_t wLength = 0); + int token_iso_in(USBEndpoint* ep, uint8_t* data, int size); + int multi_token_in(USBEndpoint* ep, uint8_t* data = NULL, int size = 0); + int multi_token_out(USBEndpoint* ep, const uint8_t* data = NULL, int size = 0); + void multi_token_inNB(USBEndpoint* ep, uint8_t* data, int size); + USB_TYPE multi_token_inNB_result(USBEndpoint* ep); + void setToggle(USBEndpoint* ep, uint8_t toggle); + + // report + uint32_t m_report_irq; + uint32_t m_report_RHSC; + uint32_t m_report_FNO; + uint32_t m_report_WDH; + uint32_t m_report_sp; + +private: + void init_hw_ohci(HCCA* pHcca); + void ResetRootHub(); + void token_init(USBEndpoint* ep); + static void _usbisr(void); + void UsbIrqhandler(); + HCCA* m_pHcca; + bool wait_attach(); + bool root_lowSpeed; + static USBHALHost * instHost; +}; +
--- a/USBHost/USBHost.cpp Mon Jun 23 20:48:53 2014 +0900 +++ b/USBHost/USBHost.cpp Tue Jul 01 18:33:31 2014 +0900 @@ -1,9 +1,29 @@ +/* mbed USBHost Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #include "USBHost.h" +#define USB_TRACE1(A) while(0) +#undef USB_TEST_ASSERT +void usb_test_assert_internal(const char *expr, const char *file, int line); +#define USB_TEST_ASSERT(EXPR) while(!(EXPR)){usb_test_assert_internal(#EXPR,__FILE__,__LINE__);} + USBHost* USBHost::inst = NULL; -USBHost* USBHost::getHostInst() -{ +USBHost* USBHost::getHostInst() { if (inst == NULL) { inst = new USBHost(); inst->init(); @@ -173,198 +193,139 @@ } USB_TYPE USBHost::controlRead(USBDeviceConnected* dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) { - SETUP_PACKET setup = {requestType, request, value, index}; - int result = ControlRead(dev, &setup, buf, len); - //USB_DBG2("result=%d %02x", result, LastStatus); - return (result >= 0) ? USB_TYPE_OK : USB_TYPE_ERROR; + USBEndpoint* ep = dev->getEpCtl(); + SETUP_PACKET setup(requestType, request, value, index, len); + + int result = token_setup(ep, &setup, len); // setup stage + USB_TRACE1(result); + if (result < 0) { + return USB_TYPE_ERROR; + } + + int read_len = multi_token_in(ep, buf, len); // data stage + USB_TRACE1(read_len); + if (read_len < 0) { + return USB_TYPE_ERROR; + } + + setToggle(ep, 1); // DATA1 + result = multi_token_out(ep); // status stage + USB_TRACE1(result); + if (result < 0) { + return USB_TYPE_ERROR; + } + ep->setLengthTransferred(read_len); + return USB_TYPE_OK; } USB_TYPE USBHost::controlWrite(USBDeviceConnected* dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) { - SETUP_PACKET setup = {requestType, request, value, index}; - int result = ControlWrite(dev, &setup, buf, len); - if (result >= 0) { - return USB_TYPE_OK; + USBEndpoint* ep = dev->getEpCtl(); + SETUP_PACKET setup(requestType, request, value, index, len); + + int result = token_setup(ep, &setup, len); // setup stage + USB_TRACE1(result); + if (result < 0) { + return USB_TYPE_ERROR; } - USB_DBG("result=%d %02x", result, LastStatus); - USB_DBG_HEX(buf, len); - return USB_TYPE_ERROR; + int write_len = 0; + if (buf != NULL) { + write_len = multi_token_out(ep, buf, len); // data stage + USB_TRACE1(write_len); + if (write_len < 0) { + return USB_TYPE_ERROR; + } + } + + setToggle(ep, 1); // DATA1 + result = multi_token_in(ep); // status stage + USB_TRACE1(result); + if (result < 0) { + return USB_TYPE_ERROR; + } + ep->setLengthTransferred(write_len); + return USB_TYPE_OK; } USB_TYPE USBHost::bulkRead(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { if (blocking == false) { ep->setBuffer(buf, len); ep_queue.push(ep); + multi_token_inNB(ep, buf, len); return USB_TYPE_PROCESSING; } - int result = bulkReadBLOCK(ep, buf, len, -1); - if (result >= 0) { - return USB_TYPE_OK; + int result = multi_token_in(ep, buf, len); + USB_TRACE1(result); + if (result < 0) { + return USB_TYPE_ERROR; } - //USB_DBG2("result=%d %02x", result, host->LastStatus); - return USB_TYPE_ERROR; + ep->setLengthTransferred(result); + return USB_TYPE_OK; } USB_TYPE USBHost::bulkWrite(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { USB_TEST_ASSERT(blocking); - int result = bulkWriteNB(ep, buf, len); - if (result >= 0) { - return USB_TYPE_OK; + int result = multi_token_out(ep, buf, len); + USB_TRACE1(result); + if (result < 0) { + return USB_TYPE_ERROR; } - USB_DBG2("result=%d %02x", result, LastStatus); - return USB_TYPE_ERROR; + ep->setLengthTransferred(result); + return USB_TYPE_OK; } USB_TYPE USBHost::interruptRead(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { if (blocking == false) { ep->setBuffer(buf, len); ep_queue.push(ep); + multi_token_inNB(ep, buf, len); return USB_TYPE_PROCESSING; } - interruptReadNB(ep, buf, len); + int result = multi_token_in(ep, buf, len); + USB_TRACE1(result); + if (result < 0) { + return USB_TYPE_ERROR; + } + ep->setLengthTransferred(result); return USB_TYPE_OK; } USB_TYPE USBHost::interruptWrite(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { USB_TEST_ASSERT(blocking); - interruptWriteNB(ep, buf, len); + int result = multi_token_out(ep, buf, len); + USB_TRACE1(result); + if (result < 0) { + return USB_TYPE_ERROR; + } + ep->setLengthTransferred(result); return USB_TYPE_OK; } USB_TYPE USBHost::isochronousRead(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { - if (blocking == false) { - ep->setBuffer(buf, len); - ep_queue.push(ep); - return USB_TYPE_PROCESSING; - } + USB_TEST_ASSERT(blocking); isochronousReadNB(ep, buf, len); return USB_TYPE_OK; } -int USBHost::ControlRead(USBDeviceConnected* dev, SETUP_PACKET* setup, uint8_t* data, int size) { - USB_TEST_ASSERT(dev); - USBEndpoint* ep = dev->getEpCtl(); - USB_TEST_ASSERT(ep); - setAddr(dev->getAddress(), dev->getSpeed()); - token_setup(ep, setup, size); // setup stage - if (LastStatus != ACK) { - USB_DBG("setup %02x", LastStatus); - return -1; - } - int read_len = multi_token_in(ep, data, size); - if (read_len < 0) { - return -1; - } - ep->setData01(DATA1); - int result = multi_token_out(ep); // status stage - if (result < 0) { - USB_DBG("status token_out %02x", LastStatus); - if (LastStatus == STALL) { - ep->setLengthTransferred(read_len); - return read_len; - } - return result; +int USBHost::interruptReadNB(USBEndpoint* ep, uint8_t* data, int size) { + USB_TRACE1(size); + if (ep->getState() != USB_TYPE_PROCESSING) { + ep->setState(USB_TYPE_PROCESSING); + ep->setBuffer(data, size); + multi_token_inNB(ep, data, size); } - ep->setLengthTransferred(read_len); - return read_len; -} - -int USBHost::ControlWrite(USBDeviceConnected* dev, SETUP_PACKET* setup, uint8_t* data, int size) { - USB_TEST_ASSERT(dev); - USBEndpoint* ep = dev->getEpCtl(); - USB_TEST_ASSERT(ep); - setAddr(dev->getAddress(), dev->getSpeed()); - token_setup(ep, setup, size); // setup stage - if (LastStatus != ACK) { - USB_DBG("setup %02x", LastStatus); - return -1; + if (multi_token_inNB_result(ep) != USB_TYPE_PROCESSING) { + return ep->getLengthTransferred(); } - int write_len = 0; - if (data != NULL) { - write_len = multi_token_out(ep, data, size); - if (write_len < 0) { - return -1; - } - } - ep->setData01(DATA1); - int result = multi_token_in(ep); // status stage - if (result < 0) { - USB_DBG("result=%d %02x", result, LastStatus); - //return result; - } - ep->setLengthTransferred(write_len); - return write_len; + return -1; } -int USBHost::interruptReadNB(USBEndpoint* ep, uint8_t* data, int size) -{ - USB_TEST_ASSERT(ep); - USBDeviceConnected* dev = ep->getDevice(); - USB_TEST_ASSERT(dev); - setAddr(dev->getAddress(), dev->getSpeed()); - setEndpoint(); - const bool block = false; - int read_len = multi_token_in(ep, data, size, block); - if (read_len < 0) { - return -1; - } - ep->setLengthTransferred(read_len); - return read_len; -} - -int USBHost::interruptWriteNB(USBEndpoint* ep, const uint8_t* data, int size) -{ - USB_TEST_ASSERT(ep); - USBDeviceConnected* dev = ep->getDevice(); - USB_TEST_ASSERT(dev); - setAddr(dev->getAddress(), dev->getSpeed()); - setEndpoint(); - const bool block = true; - int transferred_len = multi_token_out(ep, data, size, block); - if (transferred_len < 0) { - return -1; - } - ep->setLengthTransferred(transferred_len); - return transferred_len; -} - -int USBHost::bulkReadNB(USBEndpoint* ep, uint8_t* data, int size) -{ - return bulkReadBLOCK(ep, data, size, 0); -} - -int USBHost::bulkReadBLOCK(USBEndpoint* ep, uint8_t* data, int size, int timeout_ms) { - USB_TEST_ASSERT(ep); - USBDeviceConnected* dev = ep->getDevice(); - USB_TEST_ASSERT(dev); - setAddr(dev->getAddress()); - setEndpoint(); - bool block = (timeout_ms != 0); - int read_len = multi_token_in(ep, data, size, block); - if (read_len < 0) { - return -1; - } - ep->setLengthTransferred(read_len); - return read_len; -} - -int USBHost::bulkWriteNB(USBEndpoint* ep, const uint8_t* data, int size) { - USB_TEST_ASSERT(ep); - USBDeviceConnected* dev = ep->getDevice(); - USB_TEST_ASSERT(dev); - setAddr(dev->getAddress()); - setEndpoint(); - int write_len = multi_token_out(ep, data, size); - if (write_len < 0) { - return -1; - } - ep->setLengthTransferred(write_len); - return write_len; +int USBHost::bulkReadNB(USBEndpoint* ep, uint8_t* data, int size) { + USB_TRACE1(size); + return interruptReadNB(ep, data, size); } int USBHost::isochronousReadNB(USBEndpoint* ep, uint8_t* data, int size) { - USBDeviceConnected* dev = ep->getDevice(); - USB_TEST_ASSERT(dev); - setAddr(dev->getAddress()); + USB_TRACE1(size); int result = token_iso_in(ep, data, size); if (result >= 0) { ep->setLengthTransferred(result); @@ -372,30 +333,19 @@ return result; } -void USBHost::task() -{ - if (ep_queue.empty()) { - return; - } +void USBHost::task() { USBEndpoint* ep = ep_queue.pop(); - USB_TEST_ASSERT(ep); - ep->setLengthTransferred(0); - switch(ep->getType()) { - case INTERRUPT_ENDPOINT: - if (ep->getDir() == IN) { - interruptReadNB(ep, ep->getBufStart(), ep->getBufSize()); - } - break; - case BULK_ENDPOINT: - if (ep->getDir() == IN) { - bulkReadNB(ep, ep->getBufStart(), ep->getBufSize()); - } - break; - case ISOCHRONOUS_ENDPOINT: - if (ep->getDir() == IN) { - isochronousReadNB(ep, ep->getBufStart(), ep->getBufSize()); - } - break; + if (ep) { + USB_TEST_ASSERT(ep->getDir() == IN); + if (multi_token_inNB_result(ep) != USB_TYPE_PROCESSING) { + ep->call(); + } else { + ep_queue.push(ep); + } } - ep->call(); } + +void usb_test_assert_internal(const char *expr, const char *file, int line){ + error("\n\n%s@%d %s ASSERT!\n\n", file, line, expr); +} +
--- a/USBHost/USBHost.h Mon Jun 23 20:48:53 2014 +0900 +++ b/USBHost/USBHost.h Tue Jul 01 18:33:31 2014 +0900 @@ -163,10 +163,12 @@ // KL46Z-USBHost extensions int interruptReadNB(USBEndpoint* ep, uint8_t* data, int size); - int interruptWriteNB(USBEndpoint* ep, const uint8_t* data, int size); int bulkReadNB(USBEndpoint*ep, uint8_t* data, int size); - int bulkWriteNB(USBEndpoint*ep, const uint8_t* data, int size); int isochronousReadNB(USBEndpoint*ep, uint8_t* data, int size); + + /** + * non-blocking processing + */ static void poll(); private: @@ -176,10 +178,6 @@ void root_enumeration(USBDeviceConnected* dev); void parseConfDescr(USBDeviceConnected* dev, uint8_t* conf_descr, uint32_t len, IUSBEnumerator* pEnumerator); myvector<USBDeviceConnected*>DeviceLists; - - int ControlRead(USBDeviceConnected* dev, SETUP_PACKET* setup, uint8_t* data, int size); - int ControlWrite(USBDeviceConnected* dev, SETUP_PACKET* setup, uint8_t* data = NULL, int size = 0); - int bulkReadBLOCK(USBEndpoint*ep, uint8_t* data, int size, int timeout_ms); void task(); EndpointQueue ep_queue;
--- a/USBHost/dbg.h Mon Jun 23 20:48:53 2014 +0900 +++ b/USBHost/dbg.h Tue Jul 01 18:33:31 2014 +0900 @@ -1,86 +1,82 @@ -/* mbed USBHost Library - * Copyright (c) 2006-2013 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef USB_DEBUG_H -#define USB_DEBUG_H - +/* mbed USBHost Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef USB_DEBUG_H +#define USB_DEBUG_H + //Debug is disabled by default -#ifndef DEBUG +#ifndef DEBUG #define DEBUG 3 /*INFO,ERR,WARN*/ #endif #ifndef DEBUG2 #define DEBUG2 0 -#endif -#define DEBUG_TRANSFER 0 -#define DEBUG_EP_STATE 0 -#define DEBUG_EVENT 0 - +#endif +#define DEBUG_TRANSFER 0 +#define DEBUG_EP_STATE 0 +#define DEBUG_EVENT 0 + #if (DEBUG > 3) #define USB_DBG(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\r\n");} while(0); -//#define USB_DBG(x, ...) std::printf("[USB_DBG: %s:%d]" x "\r\n", __FILE__, __LINE__, ##__VA_ARGS__); +//#define USB_DBG(x, ...) std::printf("[USB_DBG: %s:%d]" x "\r\n", __FILE__, __LINE__, ##__VA_ARGS__); #define USB_DBG_HEX(A,B) debug_hex(A,B) extern void debug_hex(uint8_t* buf, int size); #define USB_DBG_ERRSTAT() report.print_errstat(); -#else -#define USB_DBG(x, ...) +#else +#define USB_DBG(x, ...) #define USB_DBG_HEX(A,B) while(0) #define USB_DBG_ERRSTAT() while(0) -#endif +#endif #if (DEBUG2 > 3) #define USB_DBG2(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\r\n");} while(0); #else #define USB_DBG2(...) while(0); #endif - + #if (DEBUG > 2) -#define USB_INFO(...) do{fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\r\n");}while(0); -//#define USB_INFO(x, ...) std::printf("[USB_INFO: %s:%d]" x "\r\n", __FILE__, __LINE__, ##__VA_ARGS__); -#else -#define USB_INFO(x, ...) -#endif - -#if (DEBUG > 1) -#define USB_WARN(x, ...) std::printf("[USB_WARNING: %s:%d]" x "\r\n", __FILE__, __LINE__, ##__VA_ARGS__); -#else -#define USB_WARN(x, ...) -#endif - -#if (DEBUG > 0) -#define USB_ERR(x, ...) std::printf("[USB_ERR: %s:%d]" x "\r\n", __FILE__, __LINE__, ##__VA_ARGS__); -#else -#define USB_ERR(x, ...) -#endif - -#if (DEBUG_TRANSFER) -#define USB_DBG_TRANSFER(x, ...) std::printf("[USB_TRANSFER: %s:%d]" x "\r\n", __FILE__, __LINE__, ##__VA_ARGS__); -#else -#define USB_DBG_TRANSFER(x, ...) -#endif - -#if (DEBUG_EVENT) -#define USB_DBG_EVENT(x, ...) std::printf("[USB_EVENT: %s:%d]" x "\r\n", __FILE__, __LINE__, ##__VA_ARGS__); -#else -#define USB_DBG_EVENT(x, ...) -#endif +#define USB_INFO(...) do{fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\r\n");}while(0); +//#define USB_INFO(x, ...) std::printf("[USB_INFO: %s:%d]" x "\r\n", __FILE__, __LINE__, ##__VA_ARGS__); +#else +#define USB_INFO(x, ...) +#endif + +#if (DEBUG > 1) +#define USB_WARN(x, ...) std::printf("[USB_WARNING: %s:%d]" x "\r\n", __FILE__, __LINE__, ##__VA_ARGS__); +#else +#define USB_WARN(x, ...) +#endif -template <bool>struct CtAssert; -template <>struct CtAssert<true> {}; -#define CTASSERT(A) CtAssert<A>(); - +#if (DEBUG > 0) +#define USB_ERR(x, ...) std::printf("[USB_ERR: %s:%d]" x "\r\n", __FILE__, __LINE__, ##__VA_ARGS__); +#else +#define USB_ERR(x, ...) +#endif + +#if (DEBUG_TRANSFER) +#define USB_DBG_TRANSFER(x, ...) std::printf("[USB_TRANSFER: %s:%d]" x "\r\n", __FILE__, __LINE__, ##__VA_ARGS__); +#else +#define USB_DBG_TRANSFER(x, ...) +#endif + +#if (DEBUG_EVENT) +#define USB_DBG_EVENT(x, ...) std::printf("[USB_EVENT: %s:%d]" x "\r\n", __FILE__, __LINE__, ##__VA_ARGS__); +#else +#define USB_DBG_EVENT(x, ...) +#endif + #ifdef _USB_TEST #define USB_TEST_ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);}; #define USB_TEST_ASSERT_FALSE(A) USB_TEST_ASSERT(!(A)) @@ -88,6 +84,6 @@ #define USB_TEST_ASSERT(A) while(0) #define USB_TEST_ASSERT_FALSE(A) while(0) #endif - -#endif - + +#endif +
--- a/USBHostC270/BaseUvc.cpp Mon Jun 23 20:48:53 2014 +0900 +++ b/USBHostC270/BaseUvc.cpp Tue Jul 01 18:33:31 2014 +0900 @@ -3,18 +3,16 @@ #include "USBHost.h" #include "BaseUvc.h" -void BaseUvc::poll() -{ +void BaseUvc::poll() { uint8_t buf[ep_iso_in->getSize()]; int result = host->isochronousReadNB(ep_iso_in, buf, sizeof(buf)); if (result >= 0) { - uint16_t frame = 0; + const uint16_t frame = 0; onResult(frame, buf, ep_iso_in->getLengthTransferred()); } } -USB_TYPE BaseUvc::Control(int req, int cs, int index, uint8_t* buf, int size) -{ +USB_TYPE BaseUvc::Control(int req, int cs, int index, uint8_t* buf, int size) { if (req == SET_CUR) { return host->controlWrite(dev, USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE, @@ -25,8 +23,7 @@ req, cs<<8, index, buf, size); } -USB_TYPE BaseUvc::setInterfaceAlternate(uint8_t intf, uint8_t alt) -{ +USB_TYPE BaseUvc::setInterfaceAlternate(uint8_t intf, uint8_t alt) { return host->controlWrite(dev, USB_HOST_TO_DEVICE | USB_RECIPIENT_INTERFACE, SET_INTERFACE, alt, intf, NULL, 0); }
--- a/USBHostC270/BaseUvc.h Mon Jun 23 20:48:53 2014 +0900 +++ b/USBHostC270/BaseUvc.h Tue Jul 01 18:33:31 2014 +0900 @@ -1,5 +1,4 @@ // BaseUvc.h -//#include "USBIsochronous.h" #pragma once // --- UVC --------------------------------------------------
--- a/USBHostC270/CamInfo.cpp Mon Jun 23 20:48:53 2014 +0900 +++ b/USBHostC270/CamInfo.cpp Tue Jul 01 18:33:31 2014 +0900 @@ -33,7 +33,8 @@ C270_EN, \ 192, \ C270_IF_ALT(192), \ - } + 4, \ + 3} #define C210_PID 0x819 #define C210_INFO(SIZE) {C270_VID, C210_PID, _##SIZE, 0, \ @@ -44,7 +45,8 @@ C270_EN, \ 192, \ C270_IF_ALT(192), \ - } + 4, \ + 3} // Logitech Qcam Orbit AF QCAM-200R #define Q200R_VID 0x046d @@ -76,7 +78,8 @@ Q200R_EN, \ 192, \ Q200R_IF_ALT(192), \ - } + 4, \ + 3} //LifeCam VX700 / VX500 #define VX700_VID 0x045e @@ -102,7 +105,8 @@ VX700_EN, \ 128, \ VX700_IF_ALT(128), \ - } + 4, \ + 3} //Sonix USB 2.0 Camera #define SONIX_160x120 5 @@ -126,7 +130,8 @@ 0x81, \ 128, \ SONIX_IF_ALT(128), \ - } + 4, \ + 3} static const CamInfo CamInfoList[] = { // Logitech C270
--- a/USBHostC270/USBHostCam.cpp Mon Jun 23 20:48:53 2014 +0900 +++ b/USBHostC270/USBHostCam.cpp Tue Jul 01 18:33:31 2014 +0900 @@ -59,6 +59,7 @@ USB_INFO("New Cam: %s device: VID:%04x PID:%04x [dev: %p - intf: %d]", caminfo->name, dev->getVid(), dev->getPid(), dev, cam_intf); ep_iso_in = new USBEndpoint(dev); ep_iso_in->init(ISOCHRONOUS_ENDPOINT, IN, caminfo->mps, caminfo->en); + ep_iso_in->ohci_init(caminfo->frameCount, caminfo->queueLimit); uint8_t buf[26]; memset(buf, 0, sizeof(buf)); buf[2] = caminfo->formatIndex; @@ -81,44 +82,6 @@ return false; } -#if 0 -void USBHostCam::setup() { - caminfo = CamInfoList; - bool found = false; - while(caminfo->vid != 0) { - if (caminfo->vid == host->getDevice(0)->getVid() && - caminfo->pid == host->getDevice(0)->getPid() && - caminfo->size == _caminfo_size && caminfo->option == _caminfo_option) { - found = true; - break; - } - caminfo++; - } - if (!found) { - CAM_INFO("caminfo not found."); - exit(1); - } - CAM_INFO("Found: %s", caminfo->name); - - ep_iso_in.setAddress(caminfo->en); - ep_iso_in.setSize(caminfo->mps); - uint8_t buf[26]; - memset(buf, 0, sizeof(buf)); - buf[2] = caminfo->formatIndex; - buf[3] = caminfo->frameIndex; - *reinterpret_cast<uint32_t*>(buf+4) = caminfo->interval; - USB_TYPE res = Control(SET_CUR, VS_COMMIT_CONTROL, 1, buf, sizeof(buf)); - if (res != USB_TYPE_OK) { - USB_ERR("SET_CUR VS_COMMIT_CONTROL FAILED"); - } - res = setInterfaceAlternate(1, caminfo->if_alt); - if (res != USB_TYPE_OK) { - USB_ERR("SET_INTERFACE FAILED"); - } -} -#endif - - /*virtual*/ void USBHostCam::setVidPid(uint16_t vid, uint16_t pid) { CAM_DBG("vid:%04x,pid:%04x", vid, pid);
--- a/USBHostC270/USBHostCam.h Mon Jun 23 20:48:53 2014 +0900 +++ b/USBHostC270/USBHostCam.h Tue Jul 01 18:33:31 2014 +0900 @@ -33,6 +33,8 @@ uint8_t en; uint8_t mps; uint8_t if_alt; + uint8_t frameCount; // ITD frame count 1-8 + uint8_t queueLimit; // ITD queue limit 1-3 }; /**