Simple USBHost library for Nucleo F446RE/F411RE/F401RE FRDM-KL46Z/KL25Z/F64F LPC4088/LPC1768
Dependents: F401RE-BTstack_example F401RE-USBHostMSD_HelloWorld
Fork of KL46Z-USBHost by
簡易USBホストライブラリです。
official-USBHostの下位互換で対応プログラムを僅かな修正で動かすことが出来ます。
Platforms
- Nucleo F446RE
- Nucleo F411RE
- Nucleo F401RE
- FRDM-K64F
- FRDM-KL46Z
- FRDM-KL25Z
- LPC4088
- LPC1768
Nucleo F446RE/F411RE/F401REのUSB接続方法
ST morpho | USB |
---|---|
U5V (CN10-8) | VBUS (1 RED) |
PA11 (CN10-14) | DM (2 WHITE) |
PA12 (CN10-12) | DP (3 GREEN) |
GND (CN10-20) | GND (4 BLACK) |
Examples
Import programF446RE-USBHostMouse_HelloWorld
USBHostMouse Hello World for ST-Nucleo-F446RE
Import programF401RE-USBHostMSD_HelloWorld
Simple USBHost MSD(USB flash drive) for Nucleo F401RE/FRDM-KL46Z test program
Import programF401RE-USBHostC270_example
Simple USBHost WebCam test program
Import programK64F_USBHostC270_example
Simple USBHost C270 example
Import programF401RE-BTstack_example
BTstack for Nucleo F401RE/FRDM-KL46Z example program
Import programUSBHostRSSI_example
Bluetooth device discovery example program.
Import programKL46Z-USBHostGPS_HelloWorld
Simple USBHost GPS Dongle Receiver for FRDM-KL46Z test program
Revision 11:61843badd06e, committed 2014-06-09
- Comitter:
- va009039
- Date:
- Mon Jun 09 09:00:49 2014 +0000
- Parent:
- 10:40c7f6788902
- Child:
- 12:b91fdea8c0a7
- Commit message:
- Simple USBHost for Nucleo F401RE
Changed in this revision
--- a/FATFileSystem.lib Wed Feb 05 13:34:37 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -http://mbed.org/users/mbed_official/code/FATFileSystem/#b6669c987c8e
--- a/USBHost/IUSBEnumerator.h Wed Feb 05 13:34:37 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -/* 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 IUSBENUMERATOR_H_ -#define IUSBENUMERATOR_H_ - -#include "stdint.h" -#include "USBEndpoint.h" - -/* -Generic interface to implement for "smart" USB enumeration -*/ - -class IUSBEnumerator -{ -public: - virtual void setVidPid(uint16_t vid, uint16_t pid) = 0; - virtual bool parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) = 0; //Must return true if the interface should be parsed - virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) = 0; //Must return true if the endpoint will be used -}; - -#endif /*IUSBENUMERATOR_H_*/ -
--- a/USBHost/USBDeviceConnected.cpp Wed Feb 05 13:34:37 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,89 +0,0 @@ -/* 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 "USBDeviceConnected.h" -#include "dbg.h" - -USBDeviceConnected::USBDeviceConnected() { - init(); -} - -void USBDeviceConnected::init() { - port = 0; - vid = 0; - pid = 0; - nb_interf = 0; - enumerated = false; - device_class = 0; - device_subclass = 0; - proto = 0; - lowSpeed = false; - hub_parent = NULL; -} - -bool USBDeviceConnected::addInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) { - USB_DBG("intf_nb=%d", intf_nb); - if (intf.count(intf_nb) > 0) { - return false; - } - intf[intf_nb] = new INTERFACE(intf_class, intf_subclass, intf_protocol); - return true; -} - -bool USBDeviceConnected::addEndpoint(uint8_t intf_nb, USBEndpoint * ept) { - if (intf.count(intf_nb) > 0) { - intf[intf_nb]->ep.push_back(ept); - return true; - } - return false; -} - -void USBDeviceConnected::init(USBDeviceConnected* parent, uint8_t port_, bool lowSpeed_) { - USB_DBG("init dev: %p", this); - init(); - hub_parent = parent; - port = port_; - lowSpeed = lowSpeed_; -} - -void USBDeviceConnected::disconnect() { - //for(int i = 0; i < MAX_INTF; i++) { - // intf[i].detach.call(); - //} - //init(); -} - - -USBEndpoint * USBDeviceConnected::getEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir, uint8_t index) { - USB_DBG("intf_nb=%d", intf_nb); - USB_TEST_ASSERT(intf.count(intf_nb) > 0); - INTERFACE* inter = intf[intf_nb]; - for (int i = 0; i < inter->ep.size(); i++) { - if ((inter->ep[i]->getType() == type) && (inter->ep[i]->getDir() == dir)) { - if(index) { - index--; - } else { - return inter->ep[i]; - } - } - } - return NULL; -} - -USBEndpoint * USBDeviceConnected::getEndpoint(uint8_t intf_nb, uint8_t index) { - USB_TEST_ASSERT(intf.count(intf_nb) > 0); - return intf[intf_nb]->ep[index]; -}
--- a/USBHost/USBDeviceConnected.h Wed Feb 05 13:34:37 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,133 +0,0 @@ -/* 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 "USBEndpoint.h" -#include "USBHostConf.h" -#include "myvector.h" -#include "mymap.h" - -class USBEndpoint; - -struct INTERFACE { - INTERFACE(uint8_t _class, uint8_t _subclass, uint8_t _protocol) { - intf_class = _class; - intf_subclass = _subclass; - intf_protocol = _protocol; - } - uint8_t intf_class; - uint8_t intf_subclass; - uint8_t intf_protocol; - myvector<USBEndpoint*>ep; -}; - -/** -* USBDeviceConnected class -*/ -class USBDeviceConnected { -public: - - /** - * Constructor - */ - USBDeviceConnected(); - - /** - * Attach an USBEndpoint to this device - * - * @param intf_nb interface number - * @param ep pointeur on the USBEndpoint which will be attached - * @returns true if successful, false otherwise - */ - bool addEndpoint(uint8_t intf_nb, USBEndpoint * ep); - - /** - * Retrieve an USBEndpoint by its TYPE and DIRECTION - * - * @param intf_nb the interface on which to lookup the USBEndpoint - * @param type type of the USBEndpoint looked for - * @param dir direction of the USBEndpoint looked for - * @param index the index of the USBEndpoint whitin the interface - * @returns pointer on the USBEndpoint if found, NULL otherwise - */ - USBEndpoint * getEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir, uint8_t index = 0); - - /** - * Retrieve an USBEndpoint by its index - * - * @param intf_nb interface number - * @param index index of the USBEndpoint - * @returns pointer on the USBEndpoint if found, NULL otherwise - */ - USBEndpoint * getEndpoint(uint8_t intf_nb, uint8_t index); - - /** - * Add a new interface to this device - * - * @param intf_nb interface number - * @param intf_class interface class - * @param intf_subclass interface subclass - * @param intf_protocol interface protocol - * @returns true if successful, false otherwise - */ - bool addInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol); - - /** - * Disconnect the device by calling a callback function registered by a driver - */ - void disconnect(); - - void init(USBDeviceConnected* parent, uint8_t _port, bool _lowSpeed); - void setAddress(uint8_t addr_) { addr = addr_; }; - void setVid(uint16_t vid_) { vid = vid_; }; - void setPid(uint16_t pid_) { pid = pid_; }; - void setClass(uint8_t device_class_) { device_class = device_class_; } - void setSubClass(uint8_t device_subclass_) { device_subclass = device_subclass_; }; - void setProtocol(uint8_t pr) { proto = pr; }; - void setEnumerated() { enumerated = true; }; - void setNbIntf(uint8_t nb_intf) {nb_interf = nb_intf; }; - void setSpeed(bool _lowSpeed) { lowSpeed = _lowSpeed; } - void setName(const char * name_, uint8_t intf_nb) { return; }; - void setEpCtl(USBEndpoint* ep) { ep_ctl = ep; } - - static int getNewAddress() { - static int addr = 1; - return addr++; - } - uint8_t getAddress() { return addr; }; - uint16_t getVid() { return vid; }; - uint16_t getPid() { return pid; }; - uint8_t getClass() { return device_class; }; - bool getSpeed() { return lowSpeed; } - bool isEnumerated() { return enumerated; }; - USBEndpoint* getEpCtl() { return ep_ctl; } - -private: - USBDeviceConnected* hub_parent; - mymap<int,INTERFACE*>intf; - uint8_t port; - uint16_t vid; - uint16_t pid; - uint8_t addr; - uint8_t device_class; - uint8_t device_subclass; - uint8_t proto; - bool lowSpeed; - bool enumerated; - uint8_t nb_interf; - USBEndpoint* ep_ctl; - void init(); -};
--- a/USBHost/USBEndpoint.h Wed Feb 05 13:34:37 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,144 +0,0 @@ -/* 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 "FunctionPointer.h" -#include "USBHostTypes.h" -#include "USBDeviceConnected.h" - -class USBDeviceConnected; - -/** -* USBEndpoint class -*/ -class USBEndpoint { -public: - /** - * Constructor - */ - USBEndpoint(USBDeviceConnected* _dev) { - init(CONTROL_ENDPOINT, IN, 8, 0); - dev = _dev; - } - - /** - * Initialize an endpoint - * - * @param type endpoint type - * @param dir endpoint direction - * @param size endpoint size - * @param ep_number endpoint number - */ - void init(ENDPOINT_TYPE _type, ENDPOINT_DIRECTION _dir, uint32_t size, uint8_t ep_number) { - type = _type; - dir = _dir; - MaxPacketSize = size; - address = ep_number; - data01_toggle = DATA0; - } - - /** - * Attach a member function to call when a transfer is finished - * - * @param tptr pointer to the object to call the member function on - * @param mptr pointer to the member function to be called - */ - template<typename T> - inline void attach(T* tptr, void (T::*mptr)(void)) { - if((mptr != NULL) && (tptr != NULL)) { - rx.attach(tptr, mptr); - } - } - - /** - * Attach a callback called when a transfer is finished - * - * @param fptr function pointer - */ - inline void attach(void (*fptr)(void)) { - if(fptr != NULL) { - rx.attach(fptr); - } - } - - /** - * Call the handler associted to the end of a transfer - */ - inline void call() { - rx.call(); - }; - - void setDevice(USBDeviceConnected* _dev) { dev = _dev; } - void setState(uint8_t st){}; // dummy - void setBuffer(uint8_t* buf, int size) { buf_start = buf, buf_size = size; } - void setLengthTransferred(int len) { transferred = len; }; - void setSize(int size) { MaxPacketSize = size; } - void setData01(uint8_t data01) { data01_toggle = data01; } - void setNextEndpoint(USBEndpoint* ep) { nextEp = ep; }; - - USBDeviceConnected* getDevice() { return dev; } - ENDPOINT_TYPE getType() { return type; }; - int getLengthTransferred() { return transferred; } - uint8_t *getBufStart() { return buf_start; } - int getBufSize() { return buf_size; } - uint8_t getAddress(){ return address; }; - int getSize() { return MaxPacketSize; } - ENDPOINT_DIRECTION getDir() { return dir; } - uint8_t getData01() { return data01_toggle; } - void toggleData01() { - data01_toggle = (data01_toggle == DATA0) ? DATA1 : DATA0; - } - USBEndpoint* nextEndpoint() { return nextEp; }; - -private: - ENDPOINT_TYPE type; - ENDPOINT_DIRECTION dir; - USBDeviceConnected* dev; - uint8_t data01_toggle; // DATA0,DATA1 - uint8_t address; - int transferred; - uint8_t * buf_start; - int buf_size; - FunctionPointer rx; - int MaxPacketSize; - USBEndpoint* nextEp; -}; - -class EndpointQueue { -public: - EndpointQueue():head(NULL),tail(NULL) {} - void push(USBEndpoint* ep) { - if (head) { - tail->setNextEndpoint(ep); - } else { - head = ep; - } - tail = ep; - ep->setNextEndpoint(NULL); - } - USBEndpoint* pop() { - USBEndpoint* ep = head; - if (ep) { - head = ep->nextEndpoint(); - } - return ep; - } - bool empty() { return head == NULL; } - -private: - USBEndpoint* head; - USBEndpoint* tail; -};
--- a/USBHost/USBHALHost.cpp Wed Feb 05 13:34:37 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,422 +0,0 @@ -// Simple USBHost for FRDM-KL46Z -#include "USBHALHost.h" - -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) -void debug_hex(uint8_t* buf, int size); -#else -#define USB_DBG(...) while(0) -#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 - -#define USB_INFO(...) do{fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");}while(0); - -#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) - -#define TX 1 -#define RX 0 - -#define EP0_BDT_IDX(dir, odd) (((2 * dir) + (1 * odd))) - -#define SETUP_TOKEN 0x0D -#define IN_TOKEN 0x09 -#define OUT_TOKEN 0x01 - -// for each endpt: 8 bytes -struct BDT { - uint8_t info; // BD[0:7] - uint8_t dummy; // RSVD: BD[8:15] - uint16_t byte_count; // BD[16:32] - uint32_t address; // Addr - void setBuffer(uint8_t* buf, int size) { - address = (uint32_t)buf; - byte_count = size; - } - uint8_t getStatus() { - return (info>>2)&0x0f; - } -}; - -__attribute__((__aligned__(512))) BDT bdt[64]; - -USBHALHost* USBHALHost::instHost; - -USBHALHost::USBHALHost() { - instHost = this; - report.clear(); -} - -void USBHALHost::init() { - // Disable IRQ - NVIC_DisableIRQ(USB0_IRQn); - - // choose usb src as PLL - SIM->SOPT2 |= (SIM_SOPT2_USBSRC_MASK | SIM_SOPT2_PLLFLLSEL_MASK); - - // enable OTG clock - SIM->SCGC4 |= SIM_SCGC4_USBOTG_MASK; - - // USB Module Configuration - // Reset USB Module - USB0->USBTRC0 |= USB_USBTRC0_USBRESET_MASK; - while(USB0->USBTRC0 & USB_USBTRC0_USBRESET_MASK); - - // Clear interrupt flag - USB0->ISTAT = 0xff; - - // Set BDT Base Register - USB0->BDTPAGE1=(uint8_t)((uint32_t)bdt>>8); - USB0->BDTPAGE2=(uint8_t)((uint32_t)bdt>>16); - USB0->BDTPAGE3=(uint8_t)((uint32_t)bdt>>24); - - // Set SOF threshold - USB0->SOFTHLD = USB_SOFTHLD_CNT(1); - - // pulldown D+ and D- - USB0->USBCTRL = USB_USBCTRL_PDE_MASK; - - USB0->USBTRC0 |= 0x40; - - // Host mode - USB0->CTL |= USB_CTL_HOSTMODEEN_MASK; - // Desable SOF packet generation - USB0->CTL &= ~USB_CTL_USBENSOFEN_MASK; - - NVIC_SetVector(USB0_IRQn, (uint32_t)_usbisr); - NVIC_EnableIRQ(USB0_IRQn); - - bool lowSpeed = wait_attach(); - - for(int retry = 2; retry > 0; retry--) { - // Enable RESET - USB0->CTL |= USB_CTL_RESET_MASK; - wait_ms(500); - USB0->CTL &= ~USB_CTL_RESET_MASK; - - // Enable SOF - USB0->CTL |= USB_CTL_USBENSOFEN_MASK; - wait_ms(100); - - // token transfer initialize - token_transfer_init(); - - USB0->INTEN |= USB_INTEN_TOKDNEEN_MASK| - USB_INTEN_ERROREN_MASK; - USB0->ERREN |= USB_ERREN_PIDERREN_MASK| - USB_ERREN_CRC5EOFEN_MASK| - USB_ERREN_CRC16EN_MASK| - USB_ERREN_DFN8EN_MASK| - USB_ERREN_BTOERREN_MASK| - USB_ERREN_DMAERREN_MASK| - USB_ERREN_BTSERREN_MASK; - - if (addDevice(NULL, 0, lowSpeed)) { - break; - } - USB_DBG("retry=%d", retry); - USB_TEST_ASSERT(retry > 1); - } -} - -bool USBHALHost::wait_attach() { - attach_done = false; - USB0->INTEN = USB_INTEN_ATTACHEN_MASK; - Timer t; - t.reset(); - t.start(); - while(!attach_done) { - if (t.read_ms() > 5*1000) { - t.reset(); - USB_INFO("Please attach USB device."); - } - } - wait_ms(100); - USB_TEST_ASSERT_FALSE(USB0->CTL & USB_CTL_SE0_MASK); - root_lowSpeed = (USB0->CTL & USB_CTL_JSTATE_MASK) ? false : true; - return root_lowSpeed; -} - -void USBHALHost::setAddr(int _addr, bool _lowSpeed) { - USB0->ADDR = (_lowSpeed ? USB_ADDR_LSEN_MASK : 0x00) | USB_ADDR_ADDR(_addr); -} - -void USBHALHost::setEndpoint() { - USB0->ENDPOINT[0].ENDPT = (root_lowSpeed ? USB_ENDPT_HOSTWOHUB_MASK : 0x00)| - USB_ENDPT_RETRYDIS_MASK| - USB_ENDPT_EPCTLDIS_MASK| - USB_ENDPT_EPRXEN_MASK| - USB_ENDPT_EPTXEN_MASK| - USB_ENDPT_EPHSHK_MASK; -} - -void USBHALHost::token_transfer_init() { - tx_ptr = ODD; - rx_ptr = ODD; -} - -int USBHALHost::token_setup(USBEndpoint* ep, SETUP_PACKET* setup, uint16_t wLength) { - USBDeviceConnected* dev = ep->getDevice(); - for(int retry = 0;; retry++) { - token_ready(); - USB0->ENDPOINT[0].ENDPT = (root_lowSpeed ? USB_ENDPT_HOSTWOHUB_MASK : 0x00) | - USB_ENDPT_RETRYDIS_MASK| - USB_ENDPT_EPRXEN_MASK| - USB_ENDPT_EPTXEN_MASK| - USB_ENDPT_EPHSHK_MASK; - CTASSERT(sizeof(SETUP_PACKET) == 8); - setup->wLength = wLength; - int idx = EP0_BDT_IDX(TX, tx_ptr); - bdt[idx].setBuffer((uint8_t*)setup, sizeof(SETUP_PACKET)); - bdt[idx].info = BD_OWN_MASK | - BD_DTS_MASK; // always data0 - token_done = false; - USB0->TOKEN = USB_TOKEN_TOKENPID(SETUP_TOKEN)| - USB_TOKEN_TOKENENDPT(ep->getAddress() & 0x7f); - while(!token_done); - LastStatus = bdt[idx].getStatus(); - if (LastStatus == ACK) { - if (retry > 0) { - USB_DBG("retry=%d %02x", retry, prev_LastStatus); - } - break; - } else if (LastStatus == STALL) { - report.stall++; - return STALL; - } - if (retry > 10) { - USB_DBG("retry=%d", retry); - break; - } - prev_LastStatus = LastStatus; - wait_ms(100 * retry); - } - ep->setData01(DATA1); // next toggle - return LastStatus; -} - -int USBHALHost::token_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit) { - for(int retry = 0;; retry++) { - token_ready(); - int idx = EP0_BDT_IDX(RX, rx_ptr); - bdt[idx].setBuffer(data, size); - bdt[idx].info = BD_OWN_MASK| - BD_DTS_MASK| - (ep->getData01() == DATA1 ? BD_DATA01_MASK : 0); - token_done = false; - USB0->TOKEN = USB_TOKEN_TOKENPID(IN_TOKEN)| - USB_TOKEN_TOKENENDPT(ep->getAddress()&0x7f); - while(!token_done); - LastStatus = bdt[idx].getStatus(); - int len = bdt[idx].byte_count; - if (LastStatus == DATA0 || LastStatus == DATA1) { - USB_TEST_ASSERT(ep->getData01() == LastStatus); - ep->setData01(LastStatus == DATA0 ? DATA1 : DATA0); - if (retry > 0) { - //USB_DBG("len=%d retry=%d %02x", len, retry, prev_LastStatus); - } - return len; - } else if (LastStatus == STALL) { - report.stall++; - return -1; - } else if (LastStatus == NAK) { - report.nak++; - if (retry >= retryLimit) { - if (retryLimit > 0) { - USB_DBG("retry=%d retryLimit=%d", retry, retryLimit); - } - return -1; - } - wait_ms(100 * retry); - } else if (LastStatus == Bus_Timeout) { - if (retry >= retryLimit) { - if (retryLimit > 0) { - USB_DBG("Bus_Timeout retry=%d retryLimit=%d", retry, retryLimit); - } - return -1; - } - wait_ms(500 + 100 * retry); - } else { - return -1; - } - prev_LastStatus = LastStatus; - } -} - -int USBHALHost::token_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit) { - for(int retry = 0;; retry++) { - token_ready(); - int idx = EP0_BDT_IDX(TX, tx_ptr); - bdt[idx].setBuffer((uint8_t*)data, size); - bdt[idx].info = BD_OWN_MASK| - BD_DTS_MASK| - (ep->getData01() == DATA1 ? BD_DATA01_MASK : 0); - token_done = false; - USB0->TOKEN = USB_TOKEN_TOKENPID(OUT_TOKEN)| - USB_TOKEN_TOKENENDPT(ep->getAddress()&0x7f); - while(!token_done); - LastStatus = bdt[idx].getStatus(); - int len = bdt[idx].byte_count; - //USB_DBG("len=%d %02x", len, LastStatus); - if (LastStatus == ACK) { - ep->toggleData01(); - if (retry > 0) { - USB_DBG("len=%d retry=%d %02x", len, retry, prev_LastStatus); - } - return len; - } else if (LastStatus == STALL) { - report.stall++; - return -1; - } else if (LastStatus == NAK) { - report.nak++; - if (retry > retryLimit) { - USB_DBG("retry=%d retryLimit=%d", retry, retryLimit); - return -1; - } - wait_ms(100 * retry); - } else { - return -1; - } - prev_LastStatus = LastStatus; - } -} - -int USBHALHost::token_iso_in(USBEndpoint* ep, uint8_t* data, int size) { - while(USB0->CTL & USB_CTL_TXSUSPENDTOKENBUSY_MASK); // TOKEN_BUSY ? - USB0->ISTAT |= USB_ISTAT_SOFTOK_MASK; // Clear SOF - while (!(USB0->ISTAT & USB_ISTAT_SOFTOK_MASK)); - USB0->SOFTHLD = 0; // this is needed as without this you can get errors - USB0->ISTAT |= USB_ISTAT_SOFTOK_MASK; // clear SOF - - USB0->ENDPOINT[0].ENDPT = USB_ENDPT_EPCTLDIS_MASK| - USB_ENDPT_RETRYDIS_MASK| - USB_ENDPT_EPRXEN_MASK| - USB_ENDPT_EPTXEN_MASK; - int idx = EP0_BDT_IDX(RX, rx_ptr); - bdt[idx].setBuffer(data, size); - bdt[idx].info = BD_OWN_MASK| - BD_DTS_MASK; // always DATA0 - token_done = false; - USB0->TOKEN = USB_TOKEN_TOKENPID(IN_TOKEN)| - USB_TOKEN_TOKENENDPT(ep->getAddress()&0x7f); - while(!token_done); - LastStatus = bdt[idx].getStatus(); - int len = bdt[idx].byte_count; - if (LastStatus == DATA0) { - return len; - } - return -1; -} - -void USBHALHost::token_ready() { - while(USB0->CTL & USB_CTL_TXSUSPENDTOKENBUSY_MASK) { // TOKEN_BUSY ? - wait_ms(1); - } - USB0->ISTAT |= USB_ISTAT_SOFTOK_MASK; // Clear SOF - while (!(USB0->ISTAT & USB_ISTAT_SOFTOK_MASK)); - USB0->SOFTHLD = 0; // this is needed as without this you can get errors - USB0->ISTAT |= USB_ISTAT_SOFTOK_MASK; // clear SOF -} - -void USBHALHost::_usbisr(void) { - if (instHost) { - instHost->UsbIrqhandler(); - } -} - -void USBHALHost::UsbIrqhandler() { - if (USB0->ISTAT & USB_ISTAT_TOKDNE_MASK) { - uint8_t stat = USB0->STAT; - ODD_EVEN next_ptr = (stat & USB_STAT_ODD_MASK) ? ODD : EVEN; - if (stat & USB_STAT_TX_MASK) { - tx_ptr = next_ptr; - } else { - rx_ptr = next_ptr; - } - USB0->ISTAT = USB_ISTAT_TOKDNE_MASK; - token_done = true; - } - if (USB0->ISTAT & USB_ISTAT_ATTACH_MASK) { - USB0->INTEN &= ~USB_INTEN_ATTACHEN_MASK; - USB0->ISTAT = USB_ISTAT_ATTACH_MASK; - attach_done = true; - } - if (USB0->ISTAT & USB_ISTAT_ERROR_MASK) { - uint8_t errstat = USB0->ERRSTAT; - if (errstat & USB_ERRSTAT_PIDERR_MASK) { - report.errstat_piderr++; - } - if (errstat & USB_ERRSTAT_CRC5EOF_MASK) { - report.errstat_crc5eof++; - } - if (errstat & USB_ERRSTAT_CRC16_MASK) { - report.errstat_crc16++; - } - if (errstat & USB_ERRSTAT_DFN8_MASK) { - report.errstat_dfn8++; - } - if (errstat & USB_ERRSTAT_BTOERR_MASK) { - report.errstat_btoerr++; - } - if (errstat & USB_ERRSTAT_DMAERR_MASK) { - report.errstat_dmaerr++; - } - if (errstat & USB_ERRSTAT_BTSERR_MASK) { - report.errstat_btoerr++; - } - USB0->ERRSTAT = errstat; - USB0->ISTAT = USB_ISTAT_ERROR_MASK; - } -} - -void Report::clear() { - errstat_piderr = 0; - errstat_crc5eof = 0; - errstat_crc16 = 0; - errstat_dfn8 = 0; - errstat_btoerr = 0; - errstat_dmaerr = 0; - errstat_bsterr = 0; - // - nak = 0; -} - -void Report::print_errstat() { - printf("ERRSTAT PID: %d, CRC5EOF: %d, CRC16: %d, DFN8: %d, BTO: %d, DMA: %d, BST: %d\n", - errstat_piderr, errstat_crc5eof, - errstat_crc16, errstat_dfn8, - errstat_btoerr, errstat_dmaerr, errstat_bsterr); -} - -void debug_hex(uint8_t* buf, int size) { - int n = 0; - for(int i = 0; i < size; i++) { - fprintf(stderr, "%02x ", buf[i]); - if (++n >= 16) { - fprintf(stderr, "\n"); - n = 0; - } - } - if (n > 0) { - fprintf(stderr, "\n"); - } -} -
--- a/USBHost/USBHALHost.h Wed Feb 05 13:34:37 2014 +0000 +++ b/USBHost/USBHALHost.h Mon Jun 09 09:00:49 2014 +0000 @@ -1,71 +1,9 @@ -// 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] -#define Bus_Timeout 0x00 -#define Data_Error 0x0f - -enum ODD_EVEN { - ODD = 0, - EVEN = 1, -}; +#if defined(TARGET_NUCLEO_F401RE) +#include "USBHALHost_F401RE.h" +#elif defined(TARGET_KL46Z)||defined(TARGET_KL25Z) +#include "USBHALHost_KL46Z.h" +#else +#error "target error" +#endif -class Report { -public: - void clear(); - void print_errstat(); - // error count - uint32_t errstat_piderr; // USBx_ERRSTAT[PIDERR] - uint32_t errstat_crc5eof;// USBx_ERRSTAT[CRC5EOF] - uint32_t errstat_crc16; // USBx_ERRSTAT[CRC16] - uint32_t errstat_dfn8; // USBx_ERRSTAT[DFN8] - uint32_t errstat_btoerr; // USBx_ERRSTAT[BTOERR] - uint32_t errstat_dmaerr; // USBx_ERRSTAT[DMAERR] - uint32_t errstat_bsterr; // USBx_ERRSTAT[BTSERR] - // - uint32_t nak; - uint32_t stall; -}; -class USBHALHost { -public: - uint8_t LastStatus; - uint8_t prev_LastStatus; - Report report; - -protected: - 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_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); - int token_iso_in(USBEndpoint* ep, uint8_t* data, int size); - void token_ready(); -private: - static void _usbisr(void); - void UsbIrqhandler(); - __IO bool attach_done; - __IO bool token_done; - bool wait_attach(); - bool root_lowSpeed; - ODD_EVEN tx_ptr; - ODD_EVEN rx_ptr; - static USBHALHost * instHost; -};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/USBHALHost2_F401RE.cpp Mon Jun 09 09:00:49 2014 +0000 @@ -0,0 +1,534 @@ +// Simple USBHost for Nucleo F401RE +#if defined(TARGET_NUCLEO_F401RE) +#include "USBHALHost_F401RE.h" + +// usbh_conf.c +HCD_HandleTypeDef hhcd_USB_OTG_FS; + +static void HAL_HCD_IRQHandler(HCD_HandleTypeDef *hhcd); + +// stm32f4xx_it.c +extern "C" { +void OTG_FS_IRQHandler(void) +{ + HAL_NVIC_ClearPendingIRQ(OTG_FS_IRQn); + HAL_HCD_IRQHandler(&hhcd_USB_OTG_FS); +} +} + +// stm32f4xx_hal_hcd.c +static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum); +static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum); +static void HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef *hhcd); +static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd); + +/** + * @brief This function handles HCD interrupt request. + * @param hhcd: HCD handle + * @retval none + */ +static void HAL_HCD_IRQHandler(HCD_HandleTypeDef *hhcd) +{ + USB_OTG_GlobalTypeDef *USBx = hhcd->Instance; + uint32_t i = 0 , interrupt = 0; + + /* ensure that we are in device mode */ + if (USB_GetMode(hhcd->Instance) == USB_OTG_MODE_HOST) + { + /* avoid spurious interrupt */ + if(__HAL_HCD_IS_INVALID_INTERRUPT(hhcd)) + { + return; + } + + if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT)) + { + /* incorrect mode, acknowledge the interrupt */ + __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT); + } + + if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_IISOIXFR)) + { + /* incorrect mode, acknowledge the interrupt */ + __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_IISOIXFR); + } + + if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_PTXFE)) + { + /* incorrect mode, acknowledge the interrupt */ + __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_PTXFE); + } + + if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_MMIS)) + { + /* incorrect mode, acknowledge the interrupt */ + __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_MMIS); + } + + /* Handle Host Disconnect Interrupts */ + if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_DISCINT)) + { + + /* Cleanup HPRT */ + USBx_HPRT0 &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |\ + USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG ); + + /* Handle Host Port Interrupts */ + HAL_HCD_Disconnect_Callback(hhcd); + USB_InitFSLSPClkSel(hhcd->Instance ,HCFG_48_MHZ ); + __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_DISCINT); + } + + /* Handle Host Port Interrupts */ + if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HPRTINT)) + { + HCD_Port_IRQHandler (hhcd); + } + + /* Handle Host SOF Interrupts */ + if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_SOF)) + { + HAL_HCD_SOF_Callback(hhcd); + __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_SOF); + } + + /* Handle Host channel Interrupts */ + if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HCINT)) + { + + interrupt = USB_HC_ReadInterrupt(hhcd->Instance); + for (i = 0; i < hhcd->Init.Host_channels ; i++) + { + if (interrupt & (1 << i)) + { + if ((USBx_HC(i)->HCCHAR) & USB_OTG_HCCHAR_EPDIR) + { + HCD_HC_IN_IRQHandler (hhcd, i); + } + else + { + HCD_HC_OUT_IRQHandler (hhcd, i); + } + } + } + __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_HCINT); + } + + /* Handle Rx Queue Level Interrupts */ + if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_RXFLVL)) + { + USB_MASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_RXFLVL); + + HCD_RXQLVL_IRQHandler (hhcd); + + USB_UNMASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_RXFLVL); + } + + } +} +/** + * @brief This function handles Host Channel IN interrupt requests. + * @param hhcd: HCD handle + * @param chnum : Channel number + * This parameter can be a value from 1 to 15 + * @retval none + */ +static void HCD_HC_IN_IRQHandler (HCD_HandleTypeDef *hhcd, uint8_t chnum) +{ + USB_OTG_GlobalTypeDef *USBx = hhcd->Instance; + + if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_AHBERR) + { + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_AHBERR); + __HAL_HCD_UNMASK_HALT_HC_INT(chnum); + } + else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_ACK) + { + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_ACK); + } + + else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_STALL) + { + __HAL_HCD_UNMASK_HALT_HC_INT(chnum); + hhcd->hc[chnum].state = HC_STALL; + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK); + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_STALL); + USB_HC_Halt(hhcd->Instance, chnum); + } + else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_DTERR) + { + __HAL_HCD_UNMASK_HALT_HC_INT(chnum); + USB_HC_Halt(hhcd->Instance, chnum); + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK); + hhcd->hc[chnum].state = HC_DATATGLERR; + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_DTERR); + } + + if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_FRMOR) + { + __HAL_HCD_UNMASK_HALT_HC_INT(chnum); + USB_HC_Halt(hhcd->Instance, chnum); + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_FRMOR); + } + + else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_XFRC) + { + + if (hhcd->Init.dma_enable) + { + hhcd->hc[chnum].xfer_count = hhcd->hc[chnum].xfer_len - \ + (USBx_HC(chnum)->HCTSIZ & USB_OTG_HCTSIZ_XFRSIZ); + } + + hhcd->hc[chnum].state = HC_XFRC; + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_XFRC); + + + if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL)|| + (hhcd->hc[chnum].ep_type == EP_TYPE_BULK)) + { + __HAL_HCD_UNMASK_HALT_HC_INT(chnum); + USB_HC_Halt(hhcd->Instance, chnum); + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK); + + } + else if(hhcd->hc[chnum].ep_type == EP_TYPE_INTR) + { + USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_ODDFRM; + __HAL_HCD_UNMASK_HALT_HC_INT(chnum); + USB_HC_Halt(hhcd->Instance, chnum); + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK); + } + hhcd->hc[chnum].toggle_in ^= 1; + + } + else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_CHH) + { + __HAL_HCD_MASK_HALT_HC_INT(chnum); + + if(hhcd->hc[chnum].state == HC_XFRC) + { + hhcd->hc[chnum].urb_state = URB_DONE; + } + + else if (hhcd->hc[chnum].state == HC_NAK) + { + hhcd->hc[chnum].urb_state = URB_DONE; + } + + else if (hhcd->hc[chnum].state == HC_STALL) + { + hhcd->hc[chnum].urb_state = URB_STALL; + } + + else if (hhcd->hc[chnum].state == HC_XACTERR) + { + hhcd->hc[chnum].urb_state = URB_NOTREADY; + } + + else if (hhcd->hc[chnum].state == HC_DATATGLERR) + { + hhcd->hc[chnum].urb_state = URB_ERROR; + } + + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_CHH); + HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state); + } + + else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_TXERR) + { + __HAL_HCD_UNMASK_HALT_HC_INT(chnum); + hhcd->hc[chnum].state = HC_XACTERR; + USB_HC_Halt(hhcd->Instance, chnum); + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_TXERR); + } + else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_NAK) + { + if(hhcd->hc[chnum].ep_type == EP_TYPE_INTR) + { + __HAL_HCD_UNMASK_HALT_HC_INT(chnum); + USB_HC_Halt(hhcd->Instance, chnum); + } + else if (hhcd->hc[chnum].ep_type == EP_TYPE_CTRL) + { + /* re-activate the channel */ + USBx_HC(chnum)->HCCHAR &= ~USB_OTG_HCCHAR_CHDIS; + USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA; + + } + + else if (hhcd->hc[chnum].ep_type == EP_TYPE_BULK) + { + __HAL_HCD_UNMASK_HALT_HC_INT(chnum); + USB_HC_Halt(hhcd->Instance, chnum); + } + + hhcd->hc[chnum].state = HC_NAK; + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK); + } +} + +/** + * @brief This function handles Host Channel OUT interrupt requests. + * @param hhcd: HCD handle + * @param chnum : Channel number + * This parameter can be a value from 1 to 15 + * @retval none + */ +static void HCD_HC_OUT_IRQHandler (HCD_HandleTypeDef *hhcd, uint8_t chnum) +{ + USB_OTG_GlobalTypeDef *USBx = hhcd->Instance; + + if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_AHBERR) + { + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_AHBERR); + __HAL_HCD_UNMASK_HALT_HC_INT(chnum); + } + else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_ACK) + { + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_ACK); + + if( hhcd->hc[chnum].do_ping == 1) + { + hhcd->hc[chnum].state = HC_NYET; + __HAL_HCD_UNMASK_HALT_HC_INT(chnum); + USB_HC_Halt(hhcd->Instance, chnum); + hhcd->hc[chnum].urb_state = URB_NOTREADY; + } + } + + else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_NYET) + { + hhcd->hc[chnum].state = HC_NYET; + __HAL_HCD_UNMASK_HALT_HC_INT(chnum); + USB_HC_Halt(hhcd->Instance, chnum); + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NYET); + + } + + else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_FRMOR) + { + __HAL_HCD_UNMASK_HALT_HC_INT(chnum); + USB_HC_Halt(hhcd->Instance, chnum); + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_FRMOR); + } + + else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_XFRC) + { + __HAL_HCD_UNMASK_HALT_HC_INT(chnum); + USB_HC_Halt(hhcd->Instance, chnum); + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_XFRC); + hhcd->hc[chnum].state = HC_XFRC; + + } + + else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_STALL) + { + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_STALL); + __HAL_HCD_UNMASK_HALT_HC_INT(chnum); + USB_HC_Halt(hhcd->Instance, chnum); + hhcd->hc[chnum].state = HC_STALL; + } + + else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_NAK) + { + __HAL_HCD_UNMASK_HALT_HC_INT(chnum); + USB_HC_Halt(hhcd->Instance, chnum); + hhcd->hc[chnum].state = HC_NAK; + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK); + } + + else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_TXERR) + { + __HAL_HCD_UNMASK_HALT_HC_INT(chnum); + USB_HC_Halt(hhcd->Instance, chnum); + hhcd->hc[chnum].state = HC_XACTERR; + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_TXERR); + } + + else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_DTERR) + { + __HAL_HCD_UNMASK_HALT_HC_INT(chnum); + USB_HC_Halt(hhcd->Instance, chnum); + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK); + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_DTERR); + hhcd->hc[chnum].state = HC_DATATGLERR; + } + + + else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_CHH) + { + __HAL_HCD_MASK_HALT_HC_INT(chnum); + + if(hhcd->hc[chnum].state == HC_XFRC) + { + hhcd->hc[chnum].urb_state = URB_DONE; + if (hhcd->hc[chnum].ep_type == EP_TYPE_BULK) + { + hhcd->hc[chnum].toggle_out ^= 1; + } + } + else if (hhcd->hc[chnum].state == HC_NAK) + { + hhcd->hc[chnum].urb_state = URB_NOTREADY; + } + + else if (hhcd->hc[chnum].state == HC_NYET) + { + hhcd->hc[chnum].urb_state = URB_NOTREADY; + hhcd->hc[chnum].do_ping = 0; + } + + else if (hhcd->hc[chnum].state == HC_STALL) + { + hhcd->hc[chnum].urb_state = URB_STALL; + } + + else if(hhcd->hc[chnum].state == HC_XACTERR) + { + hhcd->hc[chnum].urb_state = URB_NOTREADY; + } + + else if (hhcd->hc[chnum].state == HC_DATATGLERR) + { + hhcd->hc[chnum].urb_state = URB_ERROR; + } + + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_CHH); + HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state); + } +} + +/** + * @brief This function handles Rx Queue Level interrupt requests. + * @param hhcd: HCD handle + * @retval none + */ +static void HCD_RXQLVL_IRQHandler (HCD_HandleTypeDef *hhcd) +{ + USB_OTG_GlobalTypeDef *USBx = hhcd->Instance; + uint8_t channelnum =0; + uint32_t pktsts; + uint32_t pktcnt; + uint32_t temp = 0; + + temp = hhcd->Instance->GRXSTSP ; + channelnum = temp & USB_OTG_GRXSTSP_EPNUM; + pktsts = (temp & USB_OTG_GRXSTSP_PKTSTS) >> 17; + pktcnt = (temp & USB_OTG_GRXSTSP_BCNT) >> 4; + + switch (pktsts) + { + case GRXSTS_PKTSTS_IN: + /* Read the data into the host buffer. */ + if ((pktcnt > 0) && (hhcd->hc[channelnum].xfer_buff != (void *)0)) + { + + USB_ReadPacket(hhcd->Instance, hhcd->hc[channelnum].xfer_buff, pktcnt); + + /*manage multiple Xfer */ + hhcd->hc[channelnum].xfer_buff += pktcnt; + hhcd->hc[channelnum].xfer_count += pktcnt; + + if((USBx_HC(channelnum)->HCTSIZ & USB_OTG_HCTSIZ_PKTCNT) > 0) + { + /* re-activate the channel when more packets are expected */ + USBx_HC(channelnum)->HCCHAR &= ~USB_OTG_HCCHAR_CHDIS; + USBx_HC(channelnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA; + hhcd->hc[channelnum].toggle_in ^= 1; + } + } + break; + + case GRXSTS_PKTSTS_DATA_TOGGLE_ERR: + break; + case GRXSTS_PKTSTS_IN_XFER_COMP: + case GRXSTS_PKTSTS_CH_HALTED: + default: + break; + } +} + +/** + * @brief This function handles Host Port interrupt requests. + * @param hhcd: HCD handle + * @retval none + */ +static void HCD_Port_IRQHandler (HCD_HandleTypeDef *hhcd) +{ + USB_OTG_GlobalTypeDef *USBx = hhcd->Instance; + __IO uint32_t hprt0, hprt0_dup; + + /* Handle Host Port Interrupts */ + hprt0 = USBx_HPRT0; + hprt0_dup = USBx_HPRT0; + + hprt0_dup &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |\ + USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG ); + + /* Check wether Port Connect Detected */ + if((hprt0 & USB_OTG_HPRT_PCDET) == USB_OTG_HPRT_PCDET) + { + if((hprt0 & USB_OTG_HPRT_PCSTS) == USB_OTG_HPRT_PCSTS) + { + USB_MASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_DISCINT); + HAL_HCD_Connect_Callback(hhcd); + } + hprt0_dup |= USB_OTG_HPRT_PCDET; + + } + + /* Check whether Port Enable Changed */ + if((hprt0 & USB_OTG_HPRT_PENCHNG) == USB_OTG_HPRT_PENCHNG) + { + hprt0_dup |= USB_OTG_HPRT_PENCHNG; + + if((hprt0 & USB_OTG_HPRT_PENA) == USB_OTG_HPRT_PENA) + { + if(hhcd->Init.phy_itface == USB_OTG_EMBEDDED_PHY) + { + if ((hprt0 & USB_OTG_HPRT_PSPD) == (HPRT0_PRTSPD_LOW_SPEED << 17)) + { + USB_InitFSLSPClkSel(hhcd->Instance ,HCFG_6_MHZ ); + } + else + { + USB_InitFSLSPClkSel(hhcd->Instance ,HCFG_48_MHZ ); + } + } + else + { + if(hhcd->Init.speed == HCD_SPEED_FULL) + { + USBx_HOST->HFIR = (uint32_t)60000; + } + } + HAL_HCD_Connect_Callback(hhcd); + + if(hhcd->Init.speed == HCD_SPEED_HIGH) + { + USB_UNMASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_DISCINT); + } + } + else + { + /* Cleanup HPRT */ + USBx_HPRT0 &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |\ + USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG ); + + USB_UNMASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_DISCINT); + } + } + + /* Check For an overcurrent */ + if((hprt0 & USB_OTG_HPRT_POCCHNG) == USB_OTG_HPRT_POCCHNG) + { + hprt0_dup |= USB_OTG_HPRT_POCCHNG; + } + + /* Clear Port Interrupts */ + USBx_HPRT0 = hprt0_dup; +} + +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/USBHALHost_F401RE.cpp Mon Jun 09 09:00:49 2014 +0000 @@ -0,0 +1,434 @@ +// Simple USBHost for Nucleo F401RE +#if defined(TARGET_NUCLEO_F401RE) +#include "USBHALHost_F401RE.h" + +template <bool>struct CtAssert; +template <>struct CtAssert<true> {}; +#define CTASSERT(A) CtAssert<A>(); + + +#ifdef _USB_DBG +extern RawSerial pc; +#include "mydebug.h" +#define USB_DBG(...) do{pc.printf("[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);pc.printf(__VA_ARGS__);pc.puts("\n");} while(0); +#define USB_DBG_HEX(A,B) debug_hex<RawSerial>(pc,A,B) + +#else +#define USB_DBG(...) while(0) +#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 + +#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); + +__IO bool attach_done = false; +__IO bool token_done = false; +__IO HCD_URBStateTypeDef g_urb_state = URB_IDLE; + +void delay_ms(uint32_t t) +{ + HAL_Delay(t); +} + +// from usbh_conf.c +extern HCD_HandleTypeDef hhcd_USB_OTG_FS; + +void HAL_HCD_MspInit(HCD_HandleTypeDef* hhcd) +{ + GPIO_InitTypeDef GPIO_InitStruct; + if(hhcd->Instance==USB_OTG_FS) + { + /* Peripheral clock enable */ + __USB_OTG_FS_CLK_ENABLE(); + + /**USB_OTG_FS GPIO Configuration + PA11 ------> USB_OTG_FS_DM + PA12 ------> USB_OTG_FS_DP + */ + GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_LOW; + GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* Peripheral interrupt init*/ + /* Sets the priority grouping field */ + HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_0); + HAL_NVIC_SetPriority(OTG_FS_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(OTG_FS_IRQn); + } +} + +// from stm32f4xx_it.c +extern "C" { +void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd) +{ + USB_TRACE(); + attach_done = true; +} + +void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef *hhcd) +{ + USB_TRACE(); +} + +void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *hhcd, uint8_t chnum, HCD_URBStateTypeDef urb_state) +{ + USB_TRACE1(chnum); + USB_TRACE1(urb_state); + g_urb_state = urb_state; + token_done = true; +} + +} // extern "C" + +const int CH_CTL_IN = 0; +const int CH_CTL_OUT = 1; +const int CH_INT_IN = 2; +const int CH_INT_OUT = 3; +const int CH_BLK_IN = 4; +const int CH_BLK_OUT = 5; +const int CH_ISO_IN = 6; +const int DIR_IN = 1; +const int DIR_OUT = 0; + + + +USBHALHost* USBHALHost::instHost; + +USBHALHost::USBHALHost() { + instHost = this; +} + +void USBHALHost::init() { + hhcd_USB_OTG_FS.Instance = USB_OTG_FS; + hhcd_USB_OTG_FS.Init.Host_channels = 8; + hhcd_USB_OTG_FS.Init.speed = HCD_SPEED_FULL; + hhcd_USB_OTG_FS.Init.dma_enable = DISABLE; + hhcd_USB_OTG_FS.Init.phy_itface = HCD_PHY_EMBEDDED; + hhcd_USB_OTG_FS.Init.Sof_enable = DISABLE; + hhcd_USB_OTG_FS.Init.low_power_enable = ENABLE; + hhcd_USB_OTG_FS.Init.vbus_sensing_enable = DISABLE; + hhcd_USB_OTG_FS.Init.use_external_vbus = DISABLE; + + HAL_HCD_Init(&hhcd_USB_OTG_FS); + HAL_HCD_Start(&hhcd_USB_OTG_FS); + + bool lowSpeed = wait_attach(); + delay_ms(200); + HAL_HCD_ResetPort(&hhcd_USB_OTG_FS); + delay_ms(100); // Wait for 100 ms after Reset + addDevice(NULL, 0, lowSpeed); +} + +bool USBHALHost::wait_attach() { + Timer t; + t.reset(); + t.start(); + while(!attach_done) { + if (t.read_ms() > 5*1000) { + t.reset(); + USB_INFO("Please attach USB device."); + } + } + wait_ms(100); + return HAL_HCD_GetCurrentSpeed(&hhcd_USB_OTG_FS) == USB_OTG_SPEED_LOW; +} + +int USBHALHost::token_setup(USBEndpoint* ep, SETUP_PACKET* setup, uint16_t wLength) { + USBDeviceConnected* dev = ep->getDevice(); + + HAL_HCD_HC_Init(&hhcd_USB_OTG_FS, CH_CTL_OUT, 0x00, + dev->getAddress(), + dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL, + EP_TYPE_CTRL, ep->getSize()); + + setup->wLength = wLength; + + HAL_HCD_HC_SubmitRequest(&hhcd_USB_OTG_FS, CH_CTL_OUT, DIR_OUT, EP_TYPE_CTRL, 0, (uint8_t*)setup, 8, 0); + while(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_CTL_OUT) == URB_IDLE); + + switch(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_CTL_OUT)) { + case URB_DONE: + LastStatus = ACK; + break; + default: + LastStatus = 0xff; + break; + } + ep->setData01(DATA1); + return HAL_HCD_HC_GetXferCount(&hhcd_USB_OTG_FS, CH_CTL_OUT); +} + +HAL_StatusTypeDef HAL_HCD_HC_SubmitRequest2(HCD_HandleTypeDef *hhcd, + uint8_t ch_num, + uint8_t direction , + uint8_t ep_type, + uint8_t token, + uint8_t* pbuff, + uint16_t length, + uint8_t do_ping) +{ + HCD_HCTypeDef* hc = &(hhcd->hc[ch_num]); + hc->ep_is_in = direction; + hc->ep_type = ep_type; + + if (hc->toggle_in == 0) { + hc->data_pid = HC_PID_DATA0; + } else { + hc->data_pid = HC_PID_DATA1; + } + + hc->xfer_buff = pbuff; + hc->xfer_len = length; + hc->urb_state = URB_IDLE; + hc->xfer_count = 0 ; + hc->ch_num = ch_num; + hc->state = HC_IDLE; + + return USB_HC_StartXfer(hhcd->Instance, hc, hhcd->Init.dma_enable); +} + +int USBHALHost::token_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit) { + switch(ep->getType()) { + case CONTROL_ENDPOINT: + return token_ctl_in(ep, data, size, retryLimit); + case INTERRUPT_ENDPOINT: + return token_int_in(ep, data, size); + case BULK_ENDPOINT: + return token_blk_in(ep, data, size, retryLimit); + } + return -1; +} + +int USBHALHost::token_ctl_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit) { + USBDeviceConnected* dev = ep->getDevice(); + HAL_HCD_HC_Init(&hhcd_USB_OTG_FS, CH_CTL_IN, 0x80, + dev->getAddress(), + dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL, + EP_TYPE_CTRL, ep->getSize()); + hhcd_USB_OTG_FS.hc[CH_CTL_IN].toggle_in = (ep->getData01() == DATA0) ? 0 : 1; + + HAL_HCD_HC_SubmitRequest2(&hhcd_USB_OTG_FS, CH_CTL_IN, DIR_IN, EP_TYPE_CTRL, 1, data, size, 0); + while(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_CTL_IN) == URB_IDLE); + + switch(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_CTL_IN)) { + case URB_DONE: + LastStatus = ACK; + break; + default: + LastStatus = 0xff; + return -1; + } + ep->toggleData01(); + return HAL_HCD_HC_GetXferCount(&hhcd_USB_OTG_FS, CH_CTL_IN); +} + +int USBHALHost::token_int_in(USBEndpoint* ep, uint8_t* data, int size) { + USBDeviceConnected* dev = ep->getDevice(); + HAL_HCD_HC_Init(&hhcd_USB_OTG_FS, CH_INT_IN, + ep->getAddress(), + dev->getAddress(), + dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL, + EP_TYPE_INTR, ep->getSize()); + hhcd_USB_OTG_FS.hc[CH_INT_IN].toggle_in = (ep->getData01() == DATA0) ? 0 : 1; + + HAL_HCD_HC_SubmitRequest(&hhcd_USB_OTG_FS, CH_INT_IN, DIR_IN, EP_TYPE_INTR, 1, data, size, 0); + while(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_INT_IN) == URB_IDLE); + switch(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_INT_IN)) { + case URB_DONE: + switch(HAL_HCD_HC_GetState(&hhcd_USB_OTG_FS, CH_INT_IN)) { + case HC_XFRC: + LastStatus = ep->getData01(); + ep->toggleData01(); + return HAL_HCD_HC_GetXferCount(&hhcd_USB_OTG_FS, CH_INT_IN); + case HC_NAK: + LastStatus = NAK; + return -1; + } + break; + } + LastStatus = STALL; + return -1; +} + +int USBHALHost::token_blk_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit) { + USBDeviceConnected* dev = ep->getDevice(); + int retry = 0; + do { + HAL_HCD_HC_Init(&hhcd_USB_OTG_FS, CH_BLK_IN, + ep->getAddress(), + dev->getAddress(), + HCD_SPEED_FULL, + EP_TYPE_BULK, ep->getSize()); + hhcd_USB_OTG_FS.hc[CH_BLK_IN].toggle_in = (ep->getData01() == DATA0) ? 0 : 1; + + HAL_HCD_HC_SubmitRequest(&hhcd_USB_OTG_FS, CH_BLK_IN, DIR_IN, EP_TYPE_BULK, 1, data, size, 0); + while(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_BLK_IN) == URB_IDLE); + + switch(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_BLK_IN)) { + case URB_DONE: + switch(HAL_HCD_HC_GetState(&hhcd_USB_OTG_FS, CH_BLK_IN)) { + case HC_XFRC: + LastStatus = ep->getData01(); + ep->toggleData01(); + return HAL_HCD_HC_GetXferCount(&hhcd_USB_OTG_FS, CH_BLK_IN); + case HC_NAK: + LastStatus = NAK; + if (retryLimit > 0) { + delay_ms(1 + 10 * retry); + } + break; + default: + break; + } + break; + case URB_STALL: + LastStatus = STALL; + return -1; + default: + LastStatus = STALL; + delay_ms(500 + 100 * retry); + break; + } + }while(retry++ < retryLimit); + return -1; +} + +int USBHALHost::token_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit) { + switch(ep->getType()) { + case CONTROL_ENDPOINT: + return token_ctl_out(ep, data, size, retryLimit); + case INTERRUPT_ENDPOINT: + return token_int_out(ep, data, size); + case BULK_ENDPOINT: + return token_blk_out(ep, data, size, retryLimit); + } + return -1; +} + +int USBHALHost::token_ctl_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit) { + USBDeviceConnected* dev = ep->getDevice(); + HAL_HCD_HC_Init(&hhcd_USB_OTG_FS, CH_CTL_OUT, 0x00, + dev->getAddress(), + dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL, + EP_TYPE_CTRL, ep->getSize()); + hhcd_USB_OTG_FS.hc[CH_CTL_OUT].toggle_out = (ep->getData01() == DATA0) ? 0 : 1; + + do { + HAL_HCD_HC_SubmitRequest(&hhcd_USB_OTG_FS, CH_CTL_OUT, DIR_OUT, EP_TYPE_CTRL, 1, (uint8_t*)data, size, 0); + while(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_CTL_OUT) == URB_IDLE); + + switch(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_CTL_OUT)) { + case URB_DONE: + LastStatus = ACK; + ep->toggleData01(); + return HAL_HCD_HC_GetXferCount(&hhcd_USB_OTG_FS, CH_CTL_OUT); + + default: + break; + } + delay_ms(1); + }while(retryLimit-- > 0); + return -1; +} + +int USBHALHost::token_int_out(USBEndpoint* ep, const uint8_t* data, int size) { + USBDeviceConnected* dev = ep->getDevice(); + HAL_HCD_HC_Init(&hhcd_USB_OTG_FS, CH_INT_OUT, + ep->getAddress(), + dev->getAddress(), + dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL, + EP_TYPE_INTR, ep->getSize()); + hhcd_USB_OTG_FS.hc[CH_INT_OUT].toggle_out = (ep->getData01() == DATA0) ? 0 : 1; + + token_done = false; + HAL_HCD_HC_SubmitRequest(&hhcd_USB_OTG_FS, CH_INT_OUT, DIR_OUT, EP_TYPE_INTR, 1, (uint8_t*)data, size, 0); + while(!token_done); + + if (HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_INT_OUT) != URB_DONE) { + return -1; + } + ep->toggleData01(); + return HAL_HCD_HC_GetXferCount(&hhcd_USB_OTG_FS, CH_INT_OUT); +} + +int USBHALHost::token_blk_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit) { + USBDeviceConnected* dev = ep->getDevice(); + int retry = 0; + do { + HAL_HCD_HC_Init(&hhcd_USB_OTG_FS, CH_BLK_OUT, + ep->getAddress(), dev->getAddress(), + HCD_SPEED_FULL, EP_TYPE_BULK, ep->getSize()); + hhcd_USB_OTG_FS.hc[CH_BLK_OUT].toggle_out = (ep->getData01() == DATA0) ? 0 : 1; + + HAL_HCD_HC_SubmitRequest(&hhcd_USB_OTG_FS, CH_BLK_OUT, DIR_OUT, EP_TYPE_BULK, 1, (uint8_t*)data, size, 0); + while(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_BLK_OUT) == URB_IDLE); + + switch(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_BLK_OUT)) { + case URB_DONE: + switch(HAL_HCD_HC_GetState(&hhcd_USB_OTG_FS, CH_BLK_OUT)) { + case HC_XFRC: // ACK + LastStatus = ep->getData01(); + ep->toggleData01(); + return HAL_HCD_HC_GetXferCount(&hhcd_USB_OTG_FS, CH_BLK_OUT); + default: + break; + } + break; + case URB_NOTREADY: // HC_NAK + LastStatus = NAK; + delay_ms(100 * retry); + break; + default: + LastStatus = STALL; + return -1; + } + } while(retry++ < retryLimit); + return -1; +} + +int USBHALHost::token_iso_in(USBEndpoint* ep, uint8_t* data, int size) { + USBDeviceConnected* dev = ep->getDevice(); + HAL_HCD_HC_Init(&hhcd_USB_OTG_FS, CH_ISO_IN, + ep->getAddress(), + dev->getAddress(), + HCD_SPEED_FULL, + EP_TYPE_ISOC, ep->getSize()); + + token_done = false; + HAL_HCD_HC_SubmitRequest(&hhcd_USB_OTG_FS, CH_ISO_IN, DIR_IN, EP_TYPE_ISOC, 1, data, size, 0); + while(!token_done); + + switch(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_ISO_IN)) { + case URB_DONE: + return HAL_HCD_HC_GetXferCount(&hhcd_USB_OTG_FS, CH_ISO_IN); + + default: + return -1; + } +} + +#endif + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/USBHALHost_F401RE.h Mon Jun 09 09:00:49 2014 +0000 @@ -0,0 +1,43 @@ +// 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 USBHALHost { +public: + uint8_t LastStatus; + uint8_t prev_LastStatus; + +protected: + 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_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); + int token_iso_in(USBEndpoint* ep, uint8_t* data, int size); + void token_ready(){} + +private: + int token_ctl_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit); + int token_int_in(USBEndpoint* ep, uint8_t* data, int size); + int token_blk_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit); + int token_ctl_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit); + int token_int_out(USBEndpoint* ep, const uint8_t* data, int size); + int token_blk_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit); + bool wait_attach(); + static USBHALHost * instHost; +}; +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/USBHALHost_KL46Z.cpp Mon Jun 09 09:00:49 2014 +0000 @@ -0,0 +1,426 @@ +// Simple USBHost for FRDM-KL46Z +#if defined(TARGET_KL46Z)||defined(TARGET_KL25Z) +#include "USBHALHost_KL46Z.h" + +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) +void debug_hex(uint8_t* buf, int size); +#else +#define USB_DBG(...) while(0) +#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 + +#define USB_INFO(...) do{fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");}while(0); + +#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) + +#define TX 1 +#define RX 0 + +#define EP0_BDT_IDX(dir, odd) (((2 * dir) + (1 * odd))) + +#define SETUP_TOKEN 0x0D +#define IN_TOKEN 0x09 +#define OUT_TOKEN 0x01 + +// for each endpt: 8 bytes +struct BDT { + uint8_t info; // BD[0:7] + uint8_t dummy; // RSVD: BD[8:15] + uint16_t byte_count; // BD[16:32] + uint32_t address; // Addr + void setBuffer(uint8_t* buf, int size) { + address = (uint32_t)buf; + byte_count = size; + } + uint8_t getStatus() { + return (info>>2)&0x0f; + } +}; + +__attribute__((__aligned__(512))) BDT bdt[64]; + +USBHALHost* USBHALHost::instHost; + +USBHALHost::USBHALHost() { + instHost = this; + report.clear(); +} + +void USBHALHost::init() { + // Disable IRQ + NVIC_DisableIRQ(USB0_IRQn); + + // choose usb src as PLL + SIM->SOPT2 |= (SIM_SOPT2_USBSRC_MASK | SIM_SOPT2_PLLFLLSEL_MASK); + + // enable OTG clock + SIM->SCGC4 |= SIM_SCGC4_USBOTG_MASK; + + // USB Module Configuration + // Reset USB Module + USB0->USBTRC0 |= USB_USBTRC0_USBRESET_MASK; + while(USB0->USBTRC0 & USB_USBTRC0_USBRESET_MASK); + + // Clear interrupt flag + USB0->ISTAT = 0xff; + + // Set BDT Base Register + USB0->BDTPAGE1=(uint8_t)((uint32_t)bdt>>8); + USB0->BDTPAGE2=(uint8_t)((uint32_t)bdt>>16); + USB0->BDTPAGE3=(uint8_t)((uint32_t)bdt>>24); + + // Set SOF threshold + USB0->SOFTHLD = USB_SOFTHLD_CNT(1); + + // pulldown D+ and D- + USB0->USBCTRL = USB_USBCTRL_PDE_MASK; + + USB0->USBTRC0 |= 0x40; + + // Host mode + USB0->CTL |= USB_CTL_HOSTMODEEN_MASK; + // Desable SOF packet generation + USB0->CTL &= ~USB_CTL_USBENSOFEN_MASK; + + NVIC_SetVector(USB0_IRQn, (uint32_t)_usbisr); + NVIC_EnableIRQ(USB0_IRQn); + + bool lowSpeed = wait_attach(); + + for(int retry = 2; retry > 0; retry--) { + // Enable RESET + USB0->CTL |= USB_CTL_RESET_MASK; + wait_ms(500); + USB0->CTL &= ~USB_CTL_RESET_MASK; + + // Enable SOF + USB0->CTL |= USB_CTL_USBENSOFEN_MASK; + wait_ms(100); + + // token transfer initialize + token_transfer_init(); + + USB0->INTEN |= USB_INTEN_TOKDNEEN_MASK| + USB_INTEN_ERROREN_MASK; + USB0->ERREN |= USB_ERREN_PIDERREN_MASK| + USB_ERREN_CRC5EOFEN_MASK| + USB_ERREN_CRC16EN_MASK| + USB_ERREN_DFN8EN_MASK| + USB_ERREN_BTOERREN_MASK| + USB_ERREN_DMAERREN_MASK| + USB_ERREN_BTSERREN_MASK; + + if (addDevice(NULL, 0, lowSpeed)) { + break; + } + USB_DBG("retry=%d", retry); + USB_TEST_ASSERT(retry > 1); + } +} + +bool USBHALHost::wait_attach() { + attach_done = false; + USB0->INTEN = USB_INTEN_ATTACHEN_MASK; + Timer t; + t.reset(); + t.start(); + while(!attach_done) { + if (t.read_ms() > 5*1000) { + t.reset(); + USB_INFO("Please attach USB device."); + } + } + wait_ms(100); + USB_TEST_ASSERT_FALSE(USB0->CTL & USB_CTL_SE0_MASK); + root_lowSpeed = (USB0->CTL & USB_CTL_JSTATE_MASK) ? false : true; + return root_lowSpeed; +} + +void USBHALHost::setAddr(int _addr, bool _lowSpeed) { + USB0->ADDR = (_lowSpeed ? USB_ADDR_LSEN_MASK : 0x00) | USB_ADDR_ADDR(_addr); +} + +void USBHALHost::setEndpoint() { + USB0->ENDPOINT[0].ENDPT = (root_lowSpeed ? USB_ENDPT_HOSTWOHUB_MASK : 0x00)| + USB_ENDPT_RETRYDIS_MASK| + USB_ENDPT_EPCTLDIS_MASK| + USB_ENDPT_EPRXEN_MASK| + USB_ENDPT_EPTXEN_MASK| + USB_ENDPT_EPHSHK_MASK; +} + +void USBHALHost::token_transfer_init() { + tx_ptr = ODD; + rx_ptr = ODD; +} + +int USBHALHost::token_setup(USBEndpoint* ep, SETUP_PACKET* setup, uint16_t wLength) { + USBDeviceConnected* dev = ep->getDevice(); + for(int retry = 0;; retry++) { + token_ready(); + USB0->ENDPOINT[0].ENDPT = (root_lowSpeed ? USB_ENDPT_HOSTWOHUB_MASK : 0x00) | + USB_ENDPT_RETRYDIS_MASK| + USB_ENDPT_EPRXEN_MASK| + USB_ENDPT_EPTXEN_MASK| + USB_ENDPT_EPHSHK_MASK; + CTASSERT(sizeof(SETUP_PACKET) == 8); + setup->wLength = wLength; + int idx = EP0_BDT_IDX(TX, tx_ptr); + bdt[idx].setBuffer((uint8_t*)setup, sizeof(SETUP_PACKET)); + bdt[idx].info = BD_OWN_MASK | + BD_DTS_MASK; // always data0 + token_done = false; + USB0->TOKEN = USB_TOKEN_TOKENPID(SETUP_TOKEN)| + USB_TOKEN_TOKENENDPT(ep->getAddress() & 0x7f); + while(!token_done); + LastStatus = bdt[idx].getStatus(); + if (LastStatus == ACK) { + if (retry > 0) { + USB_DBG("retry=%d %02x", retry, prev_LastStatus); + } + break; + } else if (LastStatus == STALL) { + report.stall++; + return STALL; + } + if (retry > 10) { + USB_DBG("retry=%d", retry); + break; + } + prev_LastStatus = LastStatus; + wait_ms(100 * retry); + } + ep->setData01(DATA1); // next toggle + return LastStatus; +} + +int USBHALHost::token_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit) { + for(int retry = 0;; retry++) { + token_ready(); + int idx = EP0_BDT_IDX(RX, rx_ptr); + bdt[idx].setBuffer(data, size); + bdt[idx].info = BD_OWN_MASK| + BD_DTS_MASK| + (ep->getData01() == DATA1 ? BD_DATA01_MASK : 0); + token_done = false; + USB0->TOKEN = USB_TOKEN_TOKENPID(IN_TOKEN)| + USB_TOKEN_TOKENENDPT(ep->getAddress()&0x7f); + while(!token_done); + LastStatus = bdt[idx].getStatus(); + int len = bdt[idx].byte_count; + if (LastStatus == DATA0 || LastStatus == DATA1) { + USB_TEST_ASSERT(ep->getData01() == LastStatus); + ep->setData01(LastStatus == DATA0 ? DATA1 : DATA0); + if (retry > 0) { + //USB_DBG("len=%d retry=%d %02x", len, retry, prev_LastStatus); + } + return len; + } else if (LastStatus == STALL) { + report.stall++; + return -1; + } else if (LastStatus == NAK) { + report.nak++; + if (retry >= retryLimit) { + if (retryLimit > 0) { + USB_DBG("retry=%d retryLimit=%d", retry, retryLimit); + } + return -1; + } + wait_ms(100 * retry); + } else if (LastStatus == Bus_Timeout) { + if (retry >= retryLimit) { + if (retryLimit > 0) { + USB_DBG("Bus_Timeout retry=%d retryLimit=%d", retry, retryLimit); + } + return -1; + } + wait_ms(500 + 100 * retry); + } else { + return -1; + } + prev_LastStatus = LastStatus; + } +} + +int USBHALHost::token_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit) { + for(int retry = 0;; retry++) { + token_ready(); + int idx = EP0_BDT_IDX(TX, tx_ptr); + bdt[idx].setBuffer((uint8_t*)data, size); + bdt[idx].info = BD_OWN_MASK| + BD_DTS_MASK| + (ep->getData01() == DATA1 ? BD_DATA01_MASK : 0); + token_done = false; + USB0->TOKEN = USB_TOKEN_TOKENPID(OUT_TOKEN)| + USB_TOKEN_TOKENENDPT(ep->getAddress()&0x7f); + while(!token_done); + LastStatus = bdt[idx].getStatus(); + int len = bdt[idx].byte_count; + //USB_DBG("len=%d %02x", len, LastStatus); + if (LastStatus == ACK) { + ep->toggleData01(); + if (retry > 0) { + USB_DBG("len=%d retry=%d %02x", len, retry, prev_LastStatus); + } + return len; + } else if (LastStatus == STALL) { + report.stall++; + return -1; + } else if (LastStatus == NAK) { + report.nak++; + if (retry > retryLimit) { + USB_DBG("retry=%d retryLimit=%d", retry, retryLimit); + return -1; + } + wait_ms(100 * retry); + } else { + return -1; + } + prev_LastStatus = LastStatus; + } +} + +int USBHALHost::token_iso_in(USBEndpoint* ep, uint8_t* data, int size) { + while(USB0->CTL & USB_CTL_TXSUSPENDTOKENBUSY_MASK); // TOKEN_BUSY ? + USB0->ISTAT |= USB_ISTAT_SOFTOK_MASK; // Clear SOF + while (!(USB0->ISTAT & USB_ISTAT_SOFTOK_MASK)); + USB0->SOFTHLD = 0; // this is needed as without this you can get errors + USB0->ISTAT |= USB_ISTAT_SOFTOK_MASK; // clear SOF + + USB0->ENDPOINT[0].ENDPT = USB_ENDPT_EPCTLDIS_MASK| + USB_ENDPT_RETRYDIS_MASK| + USB_ENDPT_EPRXEN_MASK| + USB_ENDPT_EPTXEN_MASK; + int idx = EP0_BDT_IDX(RX, rx_ptr); + bdt[idx].setBuffer(data, size); + bdt[idx].info = BD_OWN_MASK| + BD_DTS_MASK; // always DATA0 + token_done = false; + USB0->TOKEN = USB_TOKEN_TOKENPID(IN_TOKEN)| + USB_TOKEN_TOKENENDPT(ep->getAddress()&0x7f); + while(!token_done); + LastStatus = bdt[idx].getStatus(); + int len = bdt[idx].byte_count; + if (LastStatus == DATA0) { + return len; + } + return -1; +} + +void USBHALHost::token_ready() { + while(USB0->CTL & USB_CTL_TXSUSPENDTOKENBUSY_MASK) { // TOKEN_BUSY ? + wait_ms(1); + } + USB0->ISTAT |= USB_ISTAT_SOFTOK_MASK; // Clear SOF + while (!(USB0->ISTAT & USB_ISTAT_SOFTOK_MASK)); + USB0->SOFTHLD = 0; // this is needed as without this you can get errors + USB0->ISTAT |= USB_ISTAT_SOFTOK_MASK; // clear SOF +} + +void USBHALHost::_usbisr(void) { + if (instHost) { + instHost->UsbIrqhandler(); + } +} + +void USBHALHost::UsbIrqhandler() { + if (USB0->ISTAT & USB_ISTAT_TOKDNE_MASK) { + uint8_t stat = USB0->STAT; + ODD_EVEN next_ptr = (stat & USB_STAT_ODD_MASK) ? ODD : EVEN; + if (stat & USB_STAT_TX_MASK) { + tx_ptr = next_ptr; + } else { + rx_ptr = next_ptr; + } + USB0->ISTAT = USB_ISTAT_TOKDNE_MASK; + token_done = true; + } + if (USB0->ISTAT & USB_ISTAT_ATTACH_MASK) { + USB0->INTEN &= ~USB_INTEN_ATTACHEN_MASK; + USB0->ISTAT = USB_ISTAT_ATTACH_MASK; + attach_done = true; + } + if (USB0->ISTAT & USB_ISTAT_ERROR_MASK) { + uint8_t errstat = USB0->ERRSTAT; + if (errstat & USB_ERRSTAT_PIDERR_MASK) { + report.errstat_piderr++; + } + if (errstat & USB_ERRSTAT_CRC5EOF_MASK) { + report.errstat_crc5eof++; + } + if (errstat & USB_ERRSTAT_CRC16_MASK) { + report.errstat_crc16++; + } + if (errstat & USB_ERRSTAT_DFN8_MASK) { + report.errstat_dfn8++; + } + if (errstat & USB_ERRSTAT_BTOERR_MASK) { + report.errstat_btoerr++; + } + if (errstat & USB_ERRSTAT_DMAERR_MASK) { + report.errstat_dmaerr++; + } + if (errstat & USB_ERRSTAT_BTSERR_MASK) { + report.errstat_btoerr++; + } + USB0->ERRSTAT = errstat; + USB0->ISTAT = USB_ISTAT_ERROR_MASK; + } +} + +void Report::clear() { + errstat_piderr = 0; + errstat_crc5eof = 0; + errstat_crc16 = 0; + errstat_dfn8 = 0; + errstat_btoerr = 0; + errstat_dmaerr = 0; + errstat_bsterr = 0; + // + nak = 0; +} + +void Report::print_errstat() { + printf("ERRSTAT PID: %d, CRC5EOF: %d, CRC16: %d, DFN8: %d, BTO: %d, DMA: %d, BST: %d\n", + errstat_piderr, errstat_crc5eof, + errstat_crc16, errstat_dfn8, + errstat_btoerr, errstat_dmaerr, errstat_bsterr); +} + +void debug_hex(uint8_t* buf, int size) { + int n = 0; + for(int i = 0; i < size; i++) { + fprintf(stderr, "%02x ", buf[i]); + if (++n >= 16) { + fprintf(stderr, "\n"); + n = 0; + } + } + if (n > 0) { + fprintf(stderr, "\n"); + } +} + +#endif + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/USBHALHost_KL46Z.h Mon Jun 09 09:00:49 2014 +0000 @@ -0,0 +1,71 @@ +// 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] +#define Bus_Timeout 0x00 +#define Data_Error 0x0f + +enum ODD_EVEN { + ODD = 0, + EVEN = 1, +}; + +class Report { +public: + void clear(); + void print_errstat(); + // error count + uint32_t errstat_piderr; // USBx_ERRSTAT[PIDERR] + uint32_t errstat_crc5eof;// USBx_ERRSTAT[CRC5EOF] + uint32_t errstat_crc16; // USBx_ERRSTAT[CRC16] + uint32_t errstat_dfn8; // USBx_ERRSTAT[DFN8] + uint32_t errstat_btoerr; // USBx_ERRSTAT[BTOERR] + uint32_t errstat_dmaerr; // USBx_ERRSTAT[DMAERR] + uint32_t errstat_bsterr; // USBx_ERRSTAT[BTSERR] + // + uint32_t nak; + uint32_t stall; +}; + +class USBHALHost { +public: + uint8_t LastStatus; + uint8_t prev_LastStatus; + Report report; + +protected: + 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_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); + int token_iso_in(USBEndpoint* ep, uint8_t* data, int size); + void token_ready(); +private: + static void _usbisr(void); + void UsbIrqhandler(); + __IO bool attach_done; + __IO bool token_done; + bool wait_attach(); + bool root_lowSpeed; + ODD_EVEN tx_ptr; + ODD_EVEN rx_ptr; + static USBHALHost * instHost; +};
--- a/USBHost/USBHost.cpp Wed Feb 05 13:34:37 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,478 +0,0 @@ -// Simple USBHost for FRDM-KL46Z -#include "USBHost.h" -#include <algorithm> - -USBHost* USBHost::inst = NULL; - -USBHost* USBHost::getHostInst() -{ - if (inst == NULL) { - inst = new USBHost(); - inst->init(); - } - return inst; -} - -void USBHost::poll() -{ - if (inst) { - inst->task(); - } -} - -USBHost::USBHost() { -} - -/* virtual */ bool USBHost::addDevice(USBDeviceConnected* parent, int port, bool lowSpeed) { - USBDeviceConnected* dev = new USBDeviceConnected; - USBEndpoint* ep = new USBEndpoint(dev); - dev->init(0, port, lowSpeed); - dev->setAddress(0); - dev->setEpCtl(ep); - uint8_t desc[18]; - wait_ms(100); - - int rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 1<<8, 0, desc, 8); - USB_TEST_ASSERT(rc == USB_TYPE_OK); - if (rc != USB_TYPE_OK) { - USB_ERR("ADD DEVICE FAILD"); - } - USB_DBG_HEX(desc, 8); - DeviceDescriptor* dev_desc = reinterpret_cast<DeviceDescriptor*>(desc); - ep->setSize(dev_desc->bMaxPacketSize); - - int new_addr = USBDeviceConnected::getNewAddress(); - rc = controlWrite(dev, 0x00, SET_ADDRESS, new_addr, 0, NULL, 0); - USB_TEST_ASSERT(rc == USB_TYPE_OK); - dev->setAddress(new_addr); - wait_ms(100); - - rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 1<<8, 0, desc, sizeof(desc)); - USB_TEST_ASSERT(rc == USB_TYPE_OK); - USB_DBG_HEX(desc, sizeof(desc)); - - dev->setVid(dev_desc->idVendor); - dev->setPid(dev_desc->idProduct); - dev->setClass(dev_desc->bDeviceClass); - USB_INFO("parent:%p port:%d speed:%s VID:%04x PID:%04x class:%02x addr:%d", - parent, port, (lowSpeed ? "low " : "full"), dev->getVid(), dev->getPid(), dev->getClass(), - dev->getAddress()); - - DeviceLists.push_back(dev); - - if (dev->getClass() == HUB_CLASS) { - const int config = 1; - int rc = controlWrite(dev, 0x00, SET_CONFIGURATION, config, 0, NULL, 0); - USB_TEST_ASSERT(rc == USB_TYPE_OK); - wait_ms(100); - Hub(dev); - } - return true; -} - -// enumerate a device with the control USBEndpoint -USB_TYPE USBHost::enumerate(USBDeviceConnected * dev, IUSBEnumerator* pEnumerator) -{ - if (dev->getClass() == HUB_CLASS) { // skip hub class - return USB_TYPE_OK; - } - uint8_t desc[18]; - USB_TYPE rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 1<<8, 0, desc, sizeof(desc)); - USB_TEST_ASSERT(rc == USB_TYPE_OK); - USB_DBG_HEX(desc, sizeof(desc)); - if (rc != USB_TYPE_OK) { - return rc; - } - DeviceDescriptor* dev_desc = reinterpret_cast<DeviceDescriptor*>(desc); - dev->setClass(dev_desc->bDeviceClass); - pEnumerator->setVidPid(dev->getVid(), dev->getPid()); - - rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 2<<8, 0, desc, 4); - USB_TEST_ASSERT(rc == USB_TYPE_OK); - USB_DBG_HEX(desc, 4); - - int TotalLength = desc[2]|desc[3]<<8; - uint8_t* buf = new uint8_t[TotalLength]; - rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 2<<8, 0, buf, TotalLength); - USB_TEST_ASSERT(rc == USB_TYPE_OK); - //USB_DBG_HEX(buf, TotalLength); - - // Parse the configuration descriptor - parseConfDescr(dev, buf, TotalLength, pEnumerator); - delete[] buf; - // only set configuration if not enumerated before - if (!dev->isEnumerated()) { - USB_DBG("Set configuration 1 on dev: %p", dev); - // sixth step: set configuration (only 1 supported) - int config = 1; - USB_TYPE res = controlWrite(dev, 0x00, SET_CONFIGURATION, config, 0, NULL, 0); - if (res != USB_TYPE_OK) { - USB_ERR("SET CONF FAILED"); - return res; - } - // Some devices may require this delay - wait_ms(100); - dev->setEnumerated(); - // Now the device is enumerated! - USB_DBG("dev %p is enumerated", dev); - } - return USB_TYPE_OK; -} - -// this method fills the USBDeviceConnected object: class,.... . It also add endpoints found in the descriptor. -void USBHost::parseConfDescr(USBDeviceConnected * dev, uint8_t * conf_descr, uint32_t len, IUSBEnumerator* pEnumerator) -{ - uint32_t index = 0; - uint32_t len_desc = 0; - uint8_t id = 0; - USBEndpoint * ep = NULL; - uint8_t intf_nb = 0; - bool parsing_intf = false; - uint8_t current_intf = 0; - EndpointDescriptor* ep_desc; - - while (index < len) { - len_desc = conf_descr[index]; - id = conf_descr[index+1]; - USB_DBG_HEX(conf_descr+index, len_desc); - switch (id) { - case CONFIGURATION_DESCRIPTOR: - USB_DBG("dev: %p has %d intf", dev, conf_descr[4]); - dev->setNbIntf(conf_descr[4]); - break; - case INTERFACE_DESCRIPTOR: - if(pEnumerator->parseInterface(conf_descr[index + 2], conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7])) { - intf_nb++; - current_intf = conf_descr[index + 2]; - dev->addInterface(current_intf, conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7]); - USB_DBG("ADD INTF %d on device %p: class: %d, subclass: %d, proto: %d", current_intf, dev, conf_descr[index + 5],conf_descr[index + 6],conf_descr[index + 7]); - parsing_intf = true; - } else { - parsing_intf = false; - } - break; - case ENDPOINT_DESCRIPTOR: - ep_desc = reinterpret_cast<EndpointDescriptor*>(conf_descr+index); - if (parsing_intf && (intf_nb <= MAX_INTF) ) { - ENDPOINT_TYPE type = (ENDPOINT_TYPE)(ep_desc->bmAttributes & 0x03); - ENDPOINT_DIRECTION dir = (ep_desc->bEndpointAddress & 0x80) ? IN : OUT; - if(pEnumerator->useEndpoint(current_intf, type, dir)) { - ep = new USBEndpoint(dev); - ep->init(type, dir, ep_desc->wMaxPacketSize, ep_desc->bEndpointAddress); - USB_DBG("ADD USBEndpoint %p, on interf %d on device %p", ep, current_intf, dev); - dev->addEndpoint(current_intf, ep); - } - } - break; - case HID_DESCRIPTOR: - //lenReportDescr = conf_descr[index + 7] | (conf_descr[index + 8] << 8); - break; - default: - break; - } - index += len_desc; - } -} - -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; -} - -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; - } - USB_DBG("result=%d %02x", result, LastStatus); - USB_DBG_HEX(buf, len); - return USB_TYPE_ERROR; -} - -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); - return USB_TYPE_PROCESSING; - } - int result = bulkReadBLOCK(ep, buf, len, -1); - if (result >= 0) { - return USB_TYPE_OK; - } - //USB_DBG2("result=%d %02x", result, host->LastStatus); - return USB_TYPE_ERROR; -} - -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; - } - USB_DBG2("result=%d %02x", result, LastStatus); - return USB_TYPE_ERROR; -} - -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); - return USB_TYPE_PROCESSING; - } - interruptReadNB(ep, buf, len); - 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); - 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; - } - 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 = 0; - while(read_len < size) { - int size2 = std::min(size-read_len, ep->getSize()); - int result = token_in(ep, data+read_len, size2); - //USB_DBG("token_in result=%d %02x", result, LastStatus); - if (result < 0) { - USB_DBG("token_in %d/%d %02x", read_len, size, LastStatus); - return result; - } - read_len += result; - if (result < ep->getSize()) { - break; - } - } - ep->setData01(DATA1); - int result = 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; - } - 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; - } - int write_len = 0; - if (data != NULL) { - write_len = token_out(ep, data, size); - if (write_len < 0) { - return -1; - } - } - ep->setData01(DATA1); - int result = token_in(ep); // status stage - if (result < 0) { - USB_DBG("result=%d %02x", result, LastStatus); - //return result; - } - ep->setLengthTransferred(write_len); - return write_len; -} - -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 int retryLimit = 0; - int read_len = 0; - for(int n = 0; read_len < size; n++) { - int size2 = std::min(size-read_len, ep->getSize()); - int result = token_in(ep, data+read_len, size2, retryLimit); - if (result < 0) { - if (LastStatus == NAK) { - if (n == 0) { - return -1; - } - break; - } - //USB_DBG("token_in result=%d %02x", result, LastStatus); - return result; - } - read_len += result; - if (result < ep->getSize()) { - break; - } - } - 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 int retryLimit = 0; - int transferred_len = 0; - for(int n = 0; transferred_len < size; n++) { - int size2 = std::min(size-transferred_len, ep->getSize()); - int result = token_out(ep, data+transferred_len, size2, retryLimit); - if (result < 0) { - if (LastStatus == NAK) { - if (n == 0) { - return -1; - } - break; - } - //USB_DBG("token_in result=%d %02x", result, LastStatus); - return result; - } - transferred_len += result; - if (result < ep->getSize()) { - break; - } - } - 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(); - int retryLimit = (timeout_ms == 0) ? 0 : 10; - int read_len = 0; - Timer t; - for(int n = 0; read_len < size; n++) { - int size2 = std::min(size-read_len, ep->getSize()); - int result = token_in(ep, data+read_len, size2, retryLimit); - if (result < 0) { - if (LastStatus == NAK) { - if (n == 0) { - return -1; - } - break; - } - //USB_DBG("token_in result=%d %02x", result, LastStatus); - return result; - } - read_len += result; - if (result < ep->getSize()) { - break; - } - if (timeout_ms > 0 && t.read_ms() > timeout_ms) { - USB_DBG("timeout_ms: %d", timeout_ms); - break; - } - } - 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 = 0; - for(int n = 0; write_len < size; n++) { - int size2 = std::min(size-write_len, ep->getSize()); - int result = token_out(ep, data+write_len, size2); - if (result < 0) { - if (LastStatus == NAK) { - if (n == 0) { - return -1; - } - break; - } - USB_DBG("token_out result=%d %02x", result, LastStatus); - return result; - } - write_len += result; - if (result < ep->getSize()) { - break; - } - } - ep->setLengthTransferred(write_len); - return write_len; -} - -int USBHost::isochronousReadNB(USBEndpoint* ep, uint8_t* data, int size) { - USBDeviceConnected* dev = ep->getDevice(); - USB_TEST_ASSERT(dev); - setAddr(dev->getAddress()); - int result = token_iso_in(ep, data, size); - if (result >= 0) { - ep->setLengthTransferred(result); - } - return result; -} - -void USBHost::task() -{ - if (ep_queue.empty()) { - return; - } - 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; - } - ep->call(); -}
--- a/USBHost/USBHost.h Wed Feb 05 13:34:37 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,196 +0,0 @@ -/* 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 "USBHALHost.h" -#include "USBDeviceConnected.h" -#include "IUSBEnumerator.h" -#include "USBHostConf.h" -#include "dbg.h" -#include "myvector.h" - -/** -* USBHost class -* This class is a singleton. All drivers have a reference on the static USBHost instance -*/ -class USBHost : public USBHALHost { -public: - /** - * Static method to create or retrieve the single USBHost instance - */ - static USBHost* getHostInst(); - - /** - * Control read: setup stage, data stage and status stage - * - * @param dev the control read will be done for this device - * @param requestType request type - * @param request request - * @param value value - * @param index index - * @param buf pointer on a buffer where will be store the data received - * @param len length of the transfer - * - * @returns status of the control read - */ - USB_TYPE controlRead(USBDeviceConnected * dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len); - - /** - * Control write: setup stage, data stage and status stage - * - * @param dev the control write will be done for this device - * @param requestType request type - * @param request request - * @param value value - * @param index index - * @param buf pointer on a buffer which will be written - * @param len length of the transfer - * - * @returns status of the control write - */ - USB_TYPE controlWrite(USBDeviceConnected * dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len); - - /** - * Bulk read - * - * @param dev the bulk transfer will be done for this device - * @param ep USBEndpoint which will be used to read a packet - * @param buf pointer on a buffer where will be store the data received - * @param len length of the transfer - * @param blocking if true, the read is blocking (wait for completion) - * - * @returns status of the bulk read - */ - USB_TYPE bulkRead(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking = true); - - /** - * Bulk write - * - * @param dev the bulk transfer will be done for this device - * @param ep USBEndpoint which will be used to write a packet - * @param buf pointer on a buffer which will be written - * @param len length of the transfer - * @param blocking if true, the write is blocking (wait for completion) - * - * @returns status of the bulk write - */ - USB_TYPE bulkWrite(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking = true); - - /** - * Interrupt read - * - * @param dev the interrupt transfer will be done for this device - * @param ep USBEndpoint which will be used to write a packet - * @param buf pointer on a buffer which will be written - * @param len length of the transfer - * @param blocking if true, the read is blocking (wait for completion) - * - * @returns status of the interrupt read - */ - USB_TYPE interruptRead(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking = true); - - /** - * Interrupt write - * - * @param dev the interrupt transfer will be done for this device - * @param ep USBEndpoint which will be used to write a packet - * @param buf pointer on a buffer which will be written - * @param len length of the transfer - * @param blocking if true, the write is blocking (wait for completion) - * - * @returns status of the interrupt write - */ - USB_TYPE interruptWrite(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking = true); - - /** - * Isochronous read - * - * @param dev the isochronous transfer will be done for this device - * @param ep USBEndpoint which will be used to write a packet - * @param buf pointer on a buffer which will be written - * @param len length of the transfer - * @param blocking if true, the read is blocking (wait for completion) - * - * @returns status of the interrupt read - */ - USB_TYPE isochronousRead(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking = true); - - /** - * Enumerate a device. - * - * @param dev device which will be enumerated - * - * @returns status of the enumeration - */ - USB_TYPE enumerate(USBDeviceConnected * dev, IUSBEnumerator* pEnumerator); - - /** - * Get a device - * - * @param index index of the device which will be returned - * - * @returns pointer on the "index" device - */ - USBDeviceConnected * getDevice(uint8_t index) { - return index < DeviceLists.size() ? DeviceLists[index] : NULL; - } - - /** - * register a driver into the host associated with a callback function called when the device is disconnected - * - * @param dev device - * @param intf interface number - * @param tptr pointer to the object to call the member function on - * @param mptr pointer to the member function to be called - */ - template<typename T> - void registerDriver(USBDeviceConnected * dev, uint8_t intf, T* tptr, void (T::*mptr)(void)) { - } - - // 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); - static void poll(); - -private: - USBHost(); - static USBHost* inst; - virtual bool addDevice(USBDeviceConnected* parent, int port, bool lowSpeed); - 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; - - // USB HUB - bool Hub(USBDeviceConnected* dev); - int SetPortPower(USBDeviceConnected* dev, int port); - int ClearPortPower(USBDeviceConnected* dev, int port); - int PortReset(USBDeviceConnected* dev, int port); - int SetPortFeature(USBDeviceConnected* dev, int feature, int index); - int ClearPortFeature(USBDeviceConnected* dev, int feature, int index); - int SetPortReset(USBDeviceConnected* dev, int port); - int GetPortStatus(USBDeviceConnected* dev, int port, uint32_t* status); -}; -
--- a/USBHost/USBHostConf.h Wed Feb 05 13:34:37 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -/* 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 USBHOST_CONF_H -#define USBHOST_CONF_H - -/* -* Maximum number of devices that can be connected -* to the usb host -*/ -#define MAX_DEVICE_CONNECTED 5 - -/* -* Maximum of Hub connected to the usb host -*/ -#define MAX_HUB_NB 2 - -/* -* Maximum number of ports on a USB hub -*/ -#define MAX_HUB_PORT 4 - -/* -* Enable USBHostMSD -*/ -#define USBHOST_MSD 1 - -/* -* Enable USBHostKeyboard -*/ -#define USBHOST_KEYBOARD 1 - -/* -* Enable USBHostMouse -*/ -#define USBHOST_MOUSE 1 - -/* -* Enable USBHostSerial or USBHostMultiSerial (if set > 1) -*/ -#define USBHOST_SERIAL 1 - -/* -* Enable USB3Gmodule -*/ -#define USBHOST_3GMODULE 1 - -/* -* Maximum number of interfaces of a usb device -*/ -#define MAX_INTF 4 - -/* -* usb_thread stack size -*/ -#define USB_THREAD_STACK (256*4 + MAX_HUB_NB*256*4) - -#endif
--- a/USBHost/USBHostHub.cpp Wed Feb 05 13:34:37 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,112 +0,0 @@ -#include "USBHost.h" - -#define PORT_CONNECTION 0 -#define PORT_ENABLE 1 -#define PORT_SUSPEND 2 -#define PORT_OVER_CURRENT 3 -#define PORT_RESET 4 -#define PORT_POWER 8 -#define PORT_LOW_SPEED 9 - -#define C_PORT_CONNECTION 16 -#define C_PORT_ENABLE 17 -#define C_PORT_SUSPEND 18 -#define C_PORT_OVER_CURRENT 19 -#define C_PORT_RESET 20 - -bool USBHost::Hub(USBDeviceConnected* dev) { - USB_INFO("New HUB: VID:%04x PID:%04x [dev: %p]", dev->getVid(), dev->getPid(), dev); - HubDescriptor hubdesc; - // get HUB descriptor - int rc = controlRead(dev, - USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS, - GET_DESCRIPTOR, - 0x29 << 8, 0, reinterpret_cast<uint8_t*>(&hubdesc), - sizeof(HubDescriptor)); - USB_TEST_ASSERT(rc == USB_TYPE_OK); - if (rc != USB_TYPE_OK) { - return false; - } - USB_DBG_HEX((uint8_t*)&hubdesc, sizeof(hubdesc)); - - uint32_t status; - rc = controlRead( dev, - 0xa0, 0, 0, 0, reinterpret_cast<uint8_t*>(&status), 4); - USB_TEST_ASSERT(rc == USB_TYPE_OK); - if (rc != USB_TYPE_OK) { - return false; - } - USB_DBG("HUB STATUS: %08X\n", status); - - for(int i = 1; i <= hubdesc.bNbrPorts; i++) { - SetPortPower(dev, i); // power on - wait_ms(hubdesc.bPwrOn2PwrGood*2); - uint32_t status; - GetPortStatus(dev, i, &status); - USB_DBG("port: %d status: %08X\n", i, status); - if (status & 0x010000) { // Connect Status Change, has changed - USB_TEST_ASSERT(status & 0x000001); - ClearPortFeature(dev, C_PORT_CONNECTION, i); - int lowSpeed = 0; - if (status & 0x0200) { - lowSpeed = 1; - } - PortReset(dev, i); - if (!addDevice(dev, i, lowSpeed)) { - ClearPortPower(dev, i); // power off - } - } else { - ClearPortPower(dev, i); // power off - } - } - return false; -} - - -int USBHost::SetPortPower(USBDeviceConnected* dev, int port) -{ - return SetPortFeature(dev, PORT_POWER, port); -} - -int USBHost::ClearPortPower(USBDeviceConnected* dev, int port) -{ - return ClearPortFeature(dev, PORT_POWER, port); -} - -int USBHost::SetPortFeature(USBDeviceConnected* dev, int feature, int index) -{ - return controlWrite(dev, 0x23, SET_FEATURE,feature,index,0,0); -} - -int USBHost::ClearPortFeature(USBDeviceConnected* dev, int feature, int index) -{ - return controlWrite(dev, 0x23, CLEAR_FEATURE,feature,index,0,0); -} - -int USBHost::SetPortReset(USBDeviceConnected* dev, int port) -{ - return SetPortFeature(dev, PORT_RESET, port); -} - -int USBHost::GetPortStatus(USBDeviceConnected* dev, int port, uint32_t* status) -{ - return controlRead(dev, 0xa3, GET_STATUS, 0, port, (uint8_t*)status, 4); -} - -int USBHost::PortReset(USBDeviceConnected* dev, int port) -{ - USB_DBG("%p port=%d\n", this, port); - USB_TEST_ASSERT(port >= 1); - SetPortReset(dev, port); - // wait reset - for(int i = 0; i < 100; i++) { - uint32_t status; - GetPortStatus(dev, port, &status); - USB_DBG("RESET port: %d status: %08X\n", port, status); - if (status & 0x100000) { // Reset change , Reset complete - return USB_TYPE_OK; - } - wait_ms(5); - } - return USB_TYPE_ERROR; -}
--- a/USBHost/USBHostTypes.h Wed Feb 05 13:34:37 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,167 +0,0 @@ -/* 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_INC_H -#define USB_INC_H - -#include "mbed.h" -#include "toolchain.h" - -enum USB_TYPE { - USB_TYPE_OK = 0, - - // completion code - USB_TYPE_CRC_ERROR = 1, - USB_TYPE_BIT_STUFFING_ERROR = 2, - USB_TYPE_DATA_TOGGLE_MISMATCH_ERROR = 3, - USB_TYPE_STALL_ERROR = 4, - USB_TYPE_DEVICE_NOT_RESPONDING_ERROR = 5, - USB_TYPE_PID_CHECK_FAILURE_ERROR = 6, - USB_TYPE_UNEXPECTED_PID_ERROR = 7, - USB_TYPE_DATA_OVERRUN_ERROR = 8, - USB_TYPE_DATA_UNDERRUN_ERROR = 9, - USB_TYPE_RESERVED = 9, - USB_TYPE_RESERVED_ = 10, - USB_TYPE_BUFFER_OVERRUN_ERROR = 12, - USB_TYPE_BUFFER_UNDERRUN_ERROR = 13, - - // general usb state - USB_TYPE_DISCONNECTED = 14, - USB_TYPE_FREE = 15, - USB_TYPE_IDLE = 16, - USB_TYPE_PROCESSING = 17, - - USB_TYPE_ERROR = 18, -}; - - -enum ENDPOINT_DIRECTION { - OUT = 1, - IN -}; - -enum ENDPOINT_TYPE { - CONTROL_ENDPOINT = 0, - ISOCHRONOUS_ENDPOINT, - BULK_ENDPOINT, - INTERRUPT_ENDPOINT -}; - -#define AUDIO_CLASS 0x01 -#define CDC_CLASS 0x02 -#define HID_CLASS 0x03 -#define MSD_CLASS 0x08 -#define HUB_CLASS 0x09 -#define SERIAL_CLASS 0x0A - -#define DEVICE_DESCRIPTOR (1) -#define CONFIGURATION_DESCRIPTOR (2) -#define INTERFACE_DESCRIPTOR (4) -#define ENDPOINT_DESCRIPTOR (5) -#define HID_DESCRIPTOR (33) - -// ----------- Control RequestType Fields ----------- -#define USB_DEVICE_TO_HOST 0x80 -#define USB_HOST_TO_DEVICE 0x00 -#define USB_REQUEST_TYPE_CLASS 0x20 -#define USB_REQUEST_TYPE_STANDARD 0x00 -#define USB_RECIPIENT_DEVICE 0x00 -#define USB_RECIPIENT_INTERFACE 0x01 -#define USB_RECIPIENT_ENDPOINT 0x02 - -// -------------- USB Standard Requests -------------- -#define GET_STATUS 0x00 -#define SET_FEATURE 0x03 -#define SET_ADDRESS 0x05 -#define GET_DESCRIPTOR 0x06 -#define SET_CONFIGURATION 0x09 -#define SET_INTERFACE 0x0b -#define CLEAR_FEATURE 0x01 - -// -------------- USB Descriptor Length -------------- -#define DEVICE_DESCRIPTOR_LENGTH 0x12 -#define CONFIGURATION_DESCRIPTOR_LENGTH 0x09 - -// PID -#define DATA0 0x03 -#define DATA1 0x0b -#define ACK 0x02 -#define STALL 0x0e -#define NAK 0x0a - -#pragma pack(push,1) -typedef struct { - uint8_t bLength; - uint8_t bDescriptorType; - uint16_t bcdUSB; - uint8_t bDeviceClass; - uint8_t bDeviceSubClass; - uint8_t bDeviceProtocol; - uint8_t bMaxPacketSize; - uint16_t idVendor; - uint16_t idProduct; - uint16_t bcdDevice; - uint8_t iManufacturer; - uint8_t iProduct; - uint8_t iSerialNumber; - uint8_t bNumConfigurations; -} PACKED DeviceDescriptor; - -typedef struct { - uint8_t bLength; - uint8_t bDescriptorType; - uint16_t wTotalLength; - uint8_t bNumInterfaces; - uint8_t bConfigurationValue; - uint8_t iConfiguration; - uint8_t bmAttributes; - uint8_t bMaxPower; -} PACKED ConfigurationDescriptor; - -typedef struct { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bInterfaceNumber; - uint8_t bAlternateSetting; - uint8_t bNumEndpoints; - uint8_t bInterfaceClass; - uint8_t bInterfaceSubClass; - uint8_t bInterfaceProtocol; - uint8_t iInterface; -} InterfaceDescriptor; - -typedef struct { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bEndpointAddress; - uint8_t bmAttributes; - uint16_t wMaxPacketSize; - uint8_t bInterval; -} EndpointDescriptor; - -typedef struct { - uint8_t bDescLength; - uint8_t bDescriptorType; - uint8_t bNbrPorts; - uint16_t wHubCharacteristics; - uint8_t bPwrOn2PwrGood; - uint8_t bHubContrCurrent; - uint8_t DeviceRemovable; - uint8_t PortPweCtrlMak; -} HubDescriptor; -#pragma pack(pop) - -#endif
--- a/USBHost/dbg.h Wed Feb 05 13:34:37 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -/* 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 -#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 - -#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_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, ...) -#define USB_DBG_HEX(A,B) while(0) -#define USB_DBG_ERRSTAT() while(0) -#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 - -template <bool>struct CtAssert; -template <>struct CtAssert<true> {}; -#define CTASSERT(A) CtAssert<A>(); - -#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 - -#endif -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/mydebug.h Mon Jun 09 09:00:49 2014 +0000 @@ -0,0 +1,13 @@ +#pragma once +template<class SERIAL_T> +void debug_hex(SERIAL_T& pc, const uint8_t* buf, int size) +{ + for(int i = 0; i < size; i++) { + pc.printf("%02x ", buf[i]); + if (i%16 == 15) { + pc.puts("\n"); + } + } + pc.puts("\n"); +} +
--- a/USBHost/mymap.h Wed Feb 05 13:34:37 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -#pragma once - -template<class K,class T> -class mymap { - struct mypair { - K first; - T second; - }; -public: - mymap() { - m_size = 0; - } - T& operator[](const K& key) { - int it; - if (count(key) == 0) { - it = insert(key, 0); - } else { - it = find(key); - } - return m_buf[it].second; - } - bool empty() { return m_size == 0 ? true : false; } - int size() { return m_size; } - void clear() { m_size = 0; } - int count(K key) { - for(int i = 0; i < m_size; i++) { - if (m_buf[i].first == key) { - return 1; - } - } - return 0; - } - -private: - int find(K key) { - for(int i = 0; i < m_size; i++) { - if (m_buf[i].first == key) { - return i; - } - } - return -1; - } - int insert(K key, T value) { - int it = find(key); - if (it != -1) { - m_buf[it].second = value; - return it; - } - mypair* new_buf = new mypair[m_size+1]; - if (m_size > 0) { - for(int i = 0; i < m_size; i++) { - new_buf[i] = m_buf[i]; - } - delete[] m_buf; - } - m_buf = new_buf; - it = m_size++; - m_buf[it].first = key; - m_buf[it].second = value; - return it; - } - - int m_size; - mypair *m_buf; -};
--- a/USBHost/myvector.h Wed Feb 05 13:34:37 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -#pragma once - -template<class T> -class myvector { -public: - myvector() { - m_size = 0; - m_buf = NULL; - } - void push_back(T v) { - T* new_buf = new T[m_size+1]; - if (m_size > 0) { - for(int i = 0; i < m_size; i++) { - new_buf[i] = m_buf[i]; - } - delete[] m_buf; - } - m_buf = new_buf; - m_buf[m_size++] = v; - } - T& operator[](const int index) { - return m_buf[index]; - } - int size() { return m_size; } - -private: - int m_size; - T *m_buf; -};
--- a/USBHostHID/USBHostKeyboard.cpp Wed Feb 05 13:34:37 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,184 +0,0 @@ -/* 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 "USBHostKeyboard.h" - -#if USBHOST_KEYBOARD - -static uint8_t keymap[4][0x39] = { - { 0, 0, 0, 0, 'a', 'b' /*0x05*/, - 'c', 'd', 'e', 'f', 'g' /*0x0a*/, - 'h', 'i', 'j', 'k', 'l'/*0x0f*/, - 'm', 'n', 'o', 'p', 'q'/*0x14*/, - 'r', 's', 't', 'u', 'v'/*0x19*/, - 'w', 'x', 'y', 'z', '1'/*0x1E*/, - '2', '3', '4', '5', '6'/*0x23*/, - '7', '8', '9', '0', 0x0A /*enter*/, /*0x28*/ - 0x1B /*escape*/, 0x08 /*backspace*/, 0x09/*tab*/, 0x20/*space*/, '-', /*0x2d*/ - '=', '[', ']', '\\', '#', /*0x32*/ - ';', '\'', 0, ',', '.', /*0x37*/ - '/'}, - - /* CTRL MODIFIER */ - { 0, 0, 0, 0, 0, 0 /*0x05*/, - 0, 0, 0, 0, 0 /*0x0a*/, - 0, 0, 0, 0, 0/*0x0f*/, - 0, 0, 0, 0, 0/*0x14*/, - 0, 0, 0, 0, 0/*0x19*/, - 0, 0, 0, 0, 0/*0x1E*/, - 0, 0, 0, 0, 0/*0x23*/, - 0, 0, 0, 0, 0 /*enter*/, /*0x28*/ - 0, 0, 0, 0, 0, /*0x2d*/ - 0, 0, 0, 0, 0, /*0x32*/ - 0, 0, 0, 0, 0, /*0x37*/ - 0}, - - /* SHIFT MODIFIER */ - { 0, 0, 0, 0, 'A', 'B' /*0x05*/, - 'C', 'D', 'E', 'F', 'G' /*0x0a*/, - 'H', 'I', 'J', 'K', 'L'/*0x0f*/, - 'M', 'N', 'O', 'P', 'Q'/*0x14*/, - 'R', 'S', 'T', 'U', 'V'/*0x19*/, - 'W', 'X', 'Y', 'Z', '!'/*0x1E*/, - '@', '#', '$', '%', '^'/*0x23*/, - '&', '*', '(', ')', 0, /*0x28*/ - 0, 0, 0, 0, 0, /*0x2d*/ - '+', '{', '}', '|', '~', /*0x32*/ - ':', '"', 0, '<', '>', /*0x37*/ - '?'}, - - /* ALT MODIFIER */ - { 0, 0, 0, 0, 0, 0 /*0x05*/, - 0, 0, 0, 0, 0 /*0x0a*/, - 0, 0, 0, 0, 0/*0x0f*/, - 0, 0, 0, 0, 0/*0x14*/, - 0, 0, 0, 0, 0/*0x19*/, - 0, 0, 0, 0, 0/*0x1E*/, - 0, 0, 0, 0, 0/*0x23*/, - 0, 0, 0, 0, 0 /*enter*/, /*0x28*/ - 0, 0, 0, 0, 0, /*0x2d*/ - 0, 0, 0, 0, 0, /*0x32*/ - 0, 0, 0, 0, 0, /*0x37*/ - 0} - -}; - - -USBHostKeyboard::USBHostKeyboard() { - host = USBHost::getHostInst(); - init(); -} - - -void USBHostKeyboard::init() { - dev = NULL; - int_in = NULL; - report_id = 0; - onKey = NULL; - onKeyCode = NULL; - dev_connected = false; - keyboard_intf = -1; - keyboard_device_found = false; -} - -bool USBHostKeyboard::connected() { - return dev_connected; -} - - -bool USBHostKeyboard::connect() { - - if (dev_connected) { - return true; - } - - for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) { - if ((dev = host->getDevice(i)) != NULL) { - - if (host->enumerate(dev, this)) - break; - - if (keyboard_device_found) { - int_in = dev->getEndpoint(keyboard_intf, INTERRUPT_ENDPOINT, IN); - - if (!int_in) - break; - - USB_INFO("New Keyboard device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, keyboard_intf); - dev->setName("Keyboard", keyboard_intf); - host->registerDriver(dev, keyboard_intf, this, &USBHostKeyboard::init); - - int_in->attach(this, &USBHostKeyboard::rxHandler); - host->interruptRead(dev, int_in, report, int_in->getSize(), false); - - dev_connected = true; - return true; - } - } - } - init(); - return false; -} - -void USBHostKeyboard::rxHandler() { - int len = int_in->getLengthTransferred(); - int index = (len == 9) ? 1 : 0; - int len_listen = int_in->getSize(); - uint8_t key = 0; - if (len == 8 || len == 9) { - uint8_t modifier = (report[index] == 4) ? 3 : report[index]; - len_listen = len; - key = keymap[modifier][report[index + 2]]; - if (key && onKey) { - (*onKey)(key); - } - if ((report[index + 2] || modifier) && onKeyCode) { - (*onKeyCode)(report[index + 2], modifier); - } - } - if (dev && int_in) - host->interruptRead(dev, int_in, report, len_listen, false); -} - -/*virtual*/ void USBHostKeyboard::setVidPid(uint16_t vid, uint16_t pid) -{ - // we don't check VID/PID for keyboard driver -} - -/*virtual*/ bool USBHostKeyboard::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed -{ - if ((keyboard_intf == -1) && - (intf_class == HID_CLASS) && - (intf_subclass == 0x01) && - (intf_protocol == 0x01)) { - keyboard_intf = intf_nb; - return true; - } - return false; -} - -/*virtual*/ bool USBHostKeyboard::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used -{ - if (intf_nb == keyboard_intf) { - if (type == INTERRUPT_ENDPOINT && dir == IN) { - keyboard_device_found = true; - return true; - } - } - return false; -} - -#endif
--- a/USBHostHID/USBHostKeyboard.h Wed Feb 05 13:34:37 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,102 +0,0 @@ -/* 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 USBHOSTKEYBOARD_H -#define USBHOSTKEYBOARD_H - -#include "USBHostConf.h" - -#if USBHOST_KEYBOARD - -#include "USBHost.h" - -/** - * A class to communicate a USB keyboard - */ -class USBHostKeyboard : public IUSBEnumerator { -public: - - /** - * Constructor - */ - USBHostKeyboard(); - - /** - * Try to connect a keyboard device - * - * @return true if connection was successful - */ - bool connect(); - - /** - * Check if a keyboard is connected - * - * @returns true if a keyboard is connected - */ - bool connected(); - - /** - * Attach a callback called when a keyboard event is received - * - * @param ptr function pointer - */ - inline void attach(void (*ptr)(uint8_t key)) { - if (ptr != NULL) { - onKey = ptr; - } - } - - /** - * Attach a callback called when a keyboard event is received - * - * @param ptr function pointer - */ - inline void attach(void (*ptr)(uint8_t keyCode, uint8_t modifier)) { - if (ptr != NULL) { - onKeyCode = ptr; - } - } - -protected: - //From IUSBEnumerator - virtual void setVidPid(uint16_t vid, uint16_t pid); - virtual bool parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol); //Must return true if the interface should be parsed - virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir); //Must return true if the endpoint will be used - -private: - USBHost * host; - USBDeviceConnected * dev; - USBEndpoint * int_in; - uint8_t report[9]; - int keyboard_intf; - bool keyboard_device_found; - - bool dev_connected; - - void rxHandler(); - - void (*onKey)(uint8_t key); - void (*onKeyCode)(uint8_t key, uint8_t modifier); - - int report_id; - - void init(); - -}; - -#endif - -#endif
--- a/USBHostHID/USBHostMouse.cpp Wed Feb 05 13:34:37 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,144 +0,0 @@ -/* 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 "USBHostMouse.h" - -#if USBHOST_MOUSE - -USBHostMouse::USBHostMouse() { - host = USBHost::getHostInst(); - init(); -} - -void USBHostMouse::init() { - dev = NULL; - int_in = NULL; - onUpdate = NULL; - onButtonUpdate = NULL; - onXUpdate = NULL; - onYUpdate = NULL; - onZUpdate = NULL; - report_id = 0; - dev_connected = false; - mouse_device_found = false; - mouse_intf = -1; - - buttons = 0; - x = 0; - y = 0; - z = 0; -} - -bool USBHostMouse::connected() { - return dev_connected; -} - -bool USBHostMouse::connect() { - - if (dev_connected) { - return true; - } - - for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) { - if ((dev = host->getDevice(i)) != NULL) { - - if(host->enumerate(dev, this)) - break; - - if (mouse_device_found) { - - int_in = dev->getEndpoint(mouse_intf, INTERRUPT_ENDPOINT, IN); - if (!int_in) - break; - - USB_INFO("New Mouse device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, mouse_intf); - dev->setName("Mouse", mouse_intf); - host->registerDriver(dev, mouse_intf, this, &USBHostMouse::init); - - int_in->attach(this, &USBHostMouse::rxHandler); - host->interruptRead(dev, int_in, report, int_in->getSize(), false); - - dev_connected = true; - return true; - } - } - } - init(); - return false; -} - -void USBHostMouse::rxHandler() { - int len_listen = int_in->getSize(); - - if (onUpdate) { - (*onUpdate)(report[0] & 0x07, report[1], report[2], report[3]); - } - - if (onButtonUpdate && (buttons != (report[0] & 0x07))) { - (*onButtonUpdate)(report[0] & 0x07); - } - - if (onXUpdate && (x != report[1])) { - (*onXUpdate)(report[1]); - } - - if (onYUpdate && (y != report[2])) { - (*onYUpdate)(report[2]); - } - - if (onZUpdate && (z != report[3])) { - (*onZUpdate)(report[3]); - } - - // update mouse state - buttons = report[0] & 0x07; - x = report[1]; - y = report[2]; - z = report[3]; - - if (dev) - host->interruptRead(dev, int_in, report, len_listen, false); -} - -/*virtual*/ void USBHostMouse::setVidPid(uint16_t vid, uint16_t pid) -{ - // we don't check VID/PID for mouse driver -} - -/*virtual*/ bool USBHostMouse::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed -{ - if ((mouse_intf == -1) && - (intf_class == HID_CLASS) && - (intf_subclass == 0x01) && - (intf_protocol == 0x02)) { - mouse_intf = intf_nb; - return true; - } - return false; -} - -/*virtual*/ bool USBHostMouse::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used -{ - if (intf_nb == mouse_intf) { - if (type == INTERRUPT_ENDPOINT && dir == IN) { - mouse_device_found = true; - return true; - } - } - return false; -} - -#endif
--- a/USBHostHID/USBHostMouse.h Wed Feb 05 13:34:37 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,139 +0,0 @@ -/* 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 USBHOSTMOUSE_H -#define USBHOSTMOUSE_H - -#include "USBHostConf.h" - -#if USBHOST_MOUSE - -#include "USBHost.h" - -/** - * A class to communicate a USB mouse - */ -class USBHostMouse : public IUSBEnumerator { -public: - - /** - * Constructor - */ - USBHostMouse(); - - /** - * Try to connect a mouse device - * - * @return true if connection was successful - */ - bool connect(); - - /** - * Check if a mouse is connected - * - * @returns true if a mouse is connected - */ - bool connected(); - - /** - * Attach a callback called when a mouse event is received - * - * @param ptr function pointer - */ - inline void attachEvent(void (*ptr)(uint8_t buttons, int8_t x, int8_t y, int8_t z)) { - if (ptr != NULL) { - onUpdate = ptr; - } - } - - /** - * Attach a callback called when the button state changes - * - * @param ptr function pointer - */ - inline void attachButtonEvent(void (*ptr)(uint8_t buttons)) { - if (ptr != NULL) { - onButtonUpdate = ptr; - } - } - - /** - * Attach a callback called when the X axis value changes - * - * @param ptr function pointer - */ - inline void attachXEvent(void (*ptr)(int8_t x)) { - if (ptr != NULL) { - onXUpdate = ptr; - } - } - - /** - * Attach a callback called when the Y axis value changes - * - * @param ptr function pointer - */ - inline void attachYEvent(void (*ptr)(int8_t y)) { - if (ptr != NULL) { - onYUpdate = ptr; - } - } - - /** - * Attach a callback called when the Z axis value changes (scrolling) - * - * @param ptr function pointer - */ - inline void attachZEvent(void (*ptr)(int8_t z)) { - if (ptr != NULL) { - onZUpdate = ptr; - } - } - -protected: - //From IUSBEnumerator - virtual void setVidPid(uint16_t vid, uint16_t pid); - virtual bool parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol); //Must return true if the interface should be parsed - virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir); //Must return true if the endpoint will be used - -private: - USBHost * host; - USBDeviceConnected * dev; - USBEndpoint * int_in; - uint8_t report[4]; - - bool dev_connected; - bool mouse_device_found; - int mouse_intf; - - uint8_t buttons; - int8_t x; - int8_t y; - int8_t z; - - void rxHandler(); - void (*onUpdate)(uint8_t buttons, int8_t x, int8_t y, int8_t z); - void (*onButtonUpdate)(uint8_t buttons); - void (*onXUpdate)(int8_t x); - void (*onYUpdate)(int8_t y); - void (*onZUpdate)(int8_t z); - int report_id; - void init(); -}; - -#endif - -#endif
--- a/USBHostMSD/USBHostMSD.cpp Wed Feb 05 13:34:37 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,356 +0,0 @@ -/* 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 "USBHostMSD.h" - -#if USBHOST_MSD - -#include "dbg.h" - -#define CBW_SIGNATURE 0x43425355 -#define CSW_SIGNATURE 0x53425355 - -#define DEVICE_TO_HOST 0x80 -#define HOST_TO_DEVICE 0x00 - -#define GET_MAX_LUN (0xFE) -#define BO_MASS_STORAGE_RESET (0xFF) - -USBHostMSD::USBHostMSD(const char * rootdir) : FATFileSystem(rootdir) -{ - host = USBHost::getHostInst(); - init(); -} - -void USBHostMSD::init() { - dev_connected = false; - dev = NULL; - bulk_in = NULL; - bulk_out = NULL; - dev_connected = false; - blockSize = 0; - blockCount = 0; - msd_intf = -1; - msd_device_found = false; - disk_init = false; - dev_connected = false; - nb_ep = 0; -} - - -bool USBHostMSD::connected() -{ - return dev_connected; -} - -bool USBHostMSD::connect() -{ - - if (dev_connected) { - return true; - } - - for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) { - if ((dev = host->getDevice(i)) != NULL) { - - USB_DBG("Trying to connect MSD device\r\n"); - - if(host->enumerate(dev, this)) - break; - - if (msd_device_found) { - bulk_in = dev->getEndpoint(msd_intf, BULK_ENDPOINT, IN); - bulk_out = dev->getEndpoint(msd_intf, BULK_ENDPOINT, OUT); - - if (!bulk_in || !bulk_out) - continue; - - USB_INFO("New MSD device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, msd_intf); - dev->setName("MSD", msd_intf); - host->registerDriver(dev, msd_intf, this, &USBHostMSD::init); - - dev_connected = true; - return true; - } - } //if() - } //for() - init(); - return false; -} - -/*virtual*/ void USBHostMSD::setVidPid(uint16_t vid, uint16_t pid) -{ - // we don't check VID/PID for MSD driver -} - -/*virtual*/ bool USBHostMSD::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed -{ - if ((msd_intf == -1) && - (intf_class == MSD_CLASS) && - (intf_subclass == 0x06) && - (intf_protocol == 0x50)) { - msd_intf = intf_nb; - return true; - } - return false; -} - -/*virtual*/ bool USBHostMSD::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used -{ - if (intf_nb == msd_intf) { - if (type == BULK_ENDPOINT) { - nb_ep++; - if (nb_ep == 2) - msd_device_found = true; - return true; - } - } - return false; -} - - -int USBHostMSD::testUnitReady() { - USB_DBG("Test unit ready"); - return SCSITransfer(NULL, 6, DEVICE_TO_HOST, 0, 0); -} - - -int USBHostMSD::readCapacity() { - USB_DBG("Read capacity"); - uint8_t cmd[10] = {0x25,0,0,0,0,0,0,0,0,0}; - uint8_t result[8]; - int status = SCSITransfer(cmd, 10, DEVICE_TO_HOST, result, 8); - if (status == 0) { - blockCount = (result[0] << 24) | (result[1] << 16) | (result[2] << 8) | result[3]; - blockSize = (result[4] << 24) | (result[5] << 16) | (result[6] << 8) | result[7]; - USB_INFO("MSD [dev: %p] - blockCount: %lld, blockSize: %d, Capacity: %lld\r\n", dev, blockCount, blockSize, blockCount*blockSize); - } - return status; -} - - -int USBHostMSD::SCSIRequestSense() { - USB_DBG("Request sense"); - uint8_t cmd[6] = {0x03,0,0,0,18,0}; - uint8_t result[18]; - int status = SCSITransfer(cmd, 6, DEVICE_TO_HOST, result, 18); - return status; -} - - -int USBHostMSD::inquiry(uint8_t lun, uint8_t page_code) { - USB_DBG("Inquiry"); - uint8_t evpd = (page_code == 0) ? 0 : 1; - uint8_t cmd[6] = {0x12, uint8_t((lun << 5) | evpd), page_code, 0, 36, 0}; - uint8_t result[36]; - int status = SCSITransfer(cmd, 6, DEVICE_TO_HOST, result, 36); - if (status == 0) { - char vid_pid[17]; - memcpy(vid_pid, &result[8], 8); - vid_pid[8] = 0; - USB_INFO("MSD [dev: %p] - Vendor ID: %s", dev, vid_pid); - - memcpy(vid_pid, &result[16], 16); - vid_pid[16] = 0; - USB_INFO("MSD [dev: %p] - Product ID: %s", dev, vid_pid); - - memcpy(vid_pid, &result[32], 4); - vid_pid[4] = 0; - USB_INFO("MSD [dev: %p] - Product rev: %s", dev, vid_pid); - } - return status; -} - -int USBHostMSD::checkResult(uint8_t res, USBEndpoint * ep) { - // if ep stalled: send clear feature - if (res == USB_TYPE_STALL_ERROR) { - res = host->controlWrite( dev, - USB_RECIPIENT_ENDPOINT | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_STANDARD, - CLEAR_FEATURE, - 0, ep->getAddress(), NULL, 0); - // set state to IDLE if clear feature successful - if (res == USB_TYPE_OK) { - ep->setState(USB_TYPE_IDLE); - } - } - - if (res != USB_TYPE_OK) - return -1; - - return 0; -} - - -int USBHostMSD::SCSITransfer(uint8_t * cmd, uint8_t cmd_len, int flags, uint8_t * data, uint32_t transfer_len) { - - int res = 0; - - cbw.Signature = CBW_SIGNATURE; - cbw.Tag = 0; - cbw.DataLength = transfer_len; - cbw.Flags = flags; - cbw.LUN = 0; - cbw.CBLength = cmd_len; - memset(cbw.CB,0,sizeof(cbw.CB)); - if (cmd) { - memcpy(cbw.CB,cmd,cmd_len); - } - - // send the cbw - USB_DBG("Send CBW"); - res = host->bulkWrite(dev, bulk_out,(uint8_t *)&cbw, 31); - if (checkResult(res, bulk_out)) - return -1; - - // data stage if needed - if (data) { - USB_DBG("data stage"); - if (flags == HOST_TO_DEVICE) { - - res = host->bulkWrite(dev, bulk_out, data, transfer_len); - if (checkResult(res, bulk_out)) - return -1; - - } else if (flags == DEVICE_TO_HOST) { - - res = host->bulkRead(dev, bulk_in, data, transfer_len); - if (checkResult(res, bulk_in)) - return -1; - } - } - - // status stage - csw.Signature = 0; - USB_DBG("Read CSW"); - res = host->bulkRead(dev, bulk_in,(uint8_t *)&csw, 13); - if (checkResult(res, bulk_in)) - return -1; - - if (csw.Signature != CSW_SIGNATURE) { - return -1; - } - - USB_DBG("recv csw: status: %d", csw.Status); - - // ModeSense? - if ((csw.Status == 1) && (cmd[0] != 0x03)) { - USB_DBG("request mode sense"); - return SCSIRequestSense(); - } - - // perform reset recovery - if ((csw.Status == 2) && (cmd[0] != 0x03)) { - - // send Bulk-Only Mass Storage Reset request - res = host->controlWrite( dev, - USB_RECIPIENT_INTERFACE | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS, - BO_MASS_STORAGE_RESET, - 0, msd_intf, NULL, 0); - - // unstall both endpoints - res = host->controlWrite( dev, - USB_RECIPIENT_ENDPOINT | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_STANDARD, - CLEAR_FEATURE, - 0, bulk_in->getAddress(), NULL, 0); - - res = host->controlWrite( dev, - USB_RECIPIENT_ENDPOINT | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_STANDARD, - CLEAR_FEATURE, - 0, bulk_out->getAddress(), NULL, 0); - - } - - return csw.Status; -} - - -int USBHostMSD::dataTransfer(uint8_t * buf, uint32_t block, uint8_t nbBlock, int direction) { - uint8_t cmd[10]; - memset(cmd,0,10); - cmd[0] = (direction == DEVICE_TO_HOST) ? 0x28 : 0x2A; - - cmd[2] = (block >> 24) & 0xff; - cmd[3] = (block >> 16) & 0xff; - cmd[4] = (block >> 8) & 0xff; - cmd[5] = block & 0xff; - - cmd[7] = (nbBlock >> 8) & 0xff; - cmd[8] = nbBlock & 0xff; - - return SCSITransfer(cmd, 10, direction, buf, blockSize*nbBlock); -} - -int USBHostMSD::getMaxLun() { - uint8_t buf[1], res; - res = host->controlRead( dev, USB_RECIPIENT_INTERFACE | USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS, - 0xfe, 0, msd_intf, buf, 1); - USB_DBG("max lun: %d", buf[0]); - return res; -} - -int USBHostMSD::disk_initialize() { - USB_DBG("FILESYSTEM: init"); - /* U16 */int i, timeout = 10; - - getMaxLun(); - - for (i = 0; i < timeout; i++) { - wait_ms(100); //Thread::wait(100); - if (!testUnitReady()) - break; - } - - if (i == timeout) { - disk_init = false; - return -1; - } - - inquiry(0, 0); - disk_init = 1; - return readCapacity(); -} - -int USBHostMSD::disk_write(const uint8_t *buffer, uint64_t block_number) { - USB_DBG("FILESYSTEM: write block: %lld", block_number); - if (!disk_init) { - disk_initialize(); - } - if (!disk_init) - return -1; - return dataTransfer((uint8_t *)buffer, block_number, 1, HOST_TO_DEVICE); -} - -int USBHostMSD::disk_read(uint8_t * buffer, uint64_t block_number) { - USB_DBG("FILESYSTEM: read block %lld", block_number); - if (!disk_init) { - disk_initialize(); - } - if (!disk_init) - return -1; - return dataTransfer((uint8_t *)buffer, block_number, 1, DEVICE_TO_HOST); -} - -uint64_t USBHostMSD::disk_sectors() { - USB_DBG("FILESYSTEM: sectors"); - if (!disk_init) { - disk_initialize(); - } - if (!disk_init) - return 0; - return blockCount; -} - -#endif
--- a/USBHostMSD/USBHostMSD.h Wed Feb 05 13:34:37 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,119 +0,0 @@ -/* 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 USBHOSTMSD_H -#define USBHOSTMSD_H - -#include "USBHostConf.h" - -#if USBHOST_MSD - -#include "USBHost.h" -#include "FATFileSystem.h" - -/** - * A class to communicate a USB flash disk - */ -class USBHostMSD : public IUSBEnumerator, public FATFileSystem { -public: - /** - * Constructor - * - * @param rootdir mount name - */ - USBHostMSD(const char * rootdir); - - /** - * Check if a MSD device is connected - * - * @return true if a MSD device is connected - */ - bool connected(); - - /** - * Try to connect to a MSD device - * - * @return true if connection was successful - */ - bool connect(); - -protected: - //From IUSBEnumerator - virtual void setVidPid(uint16_t vid, uint16_t pid); - virtual bool parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol); //Must return true if the interface should be parsed - virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir); //Must return true if the endpoint will be used - - // From FATFileSystem - virtual int disk_initialize(); - virtual int disk_status() {return 0;}; - virtual int disk_read(uint8_t * buffer, uint64_t sector); - virtual int disk_write(const uint8_t * buffer, uint64_t sector); - virtual int disk_sync() {return 0;}; - virtual uint64_t disk_sectors(); - -private: - USBHost * host; - USBDeviceConnected * dev; - bool dev_connected; - USBEndpoint * bulk_in; - USBEndpoint * bulk_out; - uint8_t nb_ep; - - // Bulk-only CBW - typedef struct { - uint32_t Signature; - uint32_t Tag; - uint32_t DataLength; - uint8_t Flags; - uint8_t LUN; - uint8_t CBLength; - uint8_t CB[16]; - } PACKED CBW; - - // Bulk-only CSW - typedef struct { - uint32_t Signature; - uint32_t Tag; - uint32_t DataResidue; - uint8_t Status; - } PACKED CSW; - - CBW cbw; - CSW csw; - - int SCSITransfer(uint8_t * cmd, uint8_t cmd_len, int flags, uint8_t * data, uint32_t transfer_len); - int testUnitReady(); - int readCapacity(); - int inquiry(uint8_t lun, uint8_t page_code); - int SCSIRequestSense(); - int dataTransfer(uint8_t * buf, uint32_t block, uint8_t nbBlock, int direction); - int checkResult(uint8_t res, USBEndpoint * ep); - int getMaxLun(); - - int blockSize; - uint64_t blockCount; - - int msd_intf; - bool msd_device_found; - bool disk_init; - - void init(); - -}; - -#endif - -#endif