USB Host Driver with Socket Modem support. Works with revision 323 of mbed-src but broken with any later version.
Dependencies: FATFileSystem
Fork of F401RE-USBHost by
Diff: USBHost/USBHost.cpp
- Revision:
- 18:61554f238584
- Parent:
- 16:981c3104f6c0
--- 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); +} +