This example demonstrates the reading of the USB Gamepad in the Nucleo.
Intro
This example demonstrates the reading of the USB Gamepad in the Nucleo.
Parts
STM32 Nucleo F446RE |
USB Connector |
LED 2pcs |
Register 470 ohm 2pcs |
Breadboard |
Wires |
Wiring diagram
This circuit diagram was created by fritzing.
USB con. | Nucleo |
---|---|
GND | GND |
+ | PA_12 |
- | PA_11 |
5V | 5V |
Original Library
- F401RE-USBHost by Norimasa Okamoto
- USBHostGamepad by Yuuichi Akagawa
Revision 0:b5f79b4f741d, committed 2016-03-15
- Comitter:
- beaglescout007
- Date:
- Tue Mar 15 11:39:04 2016 +0000
- Commit message:
- Release
Changed in this revision
diff -r 000000000000 -r b5f79b4f741d USBHost/IUSBEnumerator.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/IUSBEnumerator.h Tue Mar 15 11:39:04 2016 +0000 @@ -0,0 +1,37 @@ +/* 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_*/ + +
diff -r 000000000000 -r b5f79b4f741d USBHost/USBDeviceConnected.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/USBDeviceConnected.cpp Tue Mar 15 11:39:04 2016 +0000 @@ -0,0 +1,90 @@ +/* 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]; +} +
diff -r 000000000000 -r b5f79b4f741d USBHost/USBDeviceConnected.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/USBDeviceConnected.h Tue Mar 15 11:39:04 2016 +0000 @@ -0,0 +1,134 @@ +/* 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(); +}; +
diff -r 000000000000 -r b5f79b4f741d USBHost/USBEndpoint.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/USBEndpoint.h Tue Mar 15 11:39:04 2016 +0000 @@ -0,0 +1,168 @@ +/* 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; + pData = NULL; + } + + /** + * 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) { + setState(USB_TYPE_FREE); + setType(_type); + dir = _dir; + MaxPacketSize = size; + address = ep_number; + data01_toggle = DATA0; + } + + void ohci_init(uint8_t frameCount, uint8_t queueLimit) { + ohci.frameCount = frameCount; + ohci.queueLimit = queueLimit; + } + + /** + * Attach a member function to call when a transfer is finished + * + * @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 setType(ENDPOINT_TYPE _type) { type = _type; } + void setState(USB_TYPE st) { state = st; } + void setDevice(USBDeviceConnected* _dev) { dev = _dev; } + void setBuffer(uint8_t* buf, int size) { buf_start = buf, buf_size = size; } + void setLengthTransferred(int len) { transferred = len; }; + void setAddress(int addr) { address = addr; } + void setSize(int size) { MaxPacketSize = size; } + void setData01(uint8_t data01) { data01_toggle = data01; } + void setNextEndpoint(USBEndpoint* ep) { nextEp = ep; }; + template<class T> + void setHALData(T data) { pData = data; } + + USBDeviceConnected* getDevice() { return dev; } + ENDPOINT_TYPE getType() { return type; }; + USB_TYPE getState() { return state; } + 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; }; + template<class T> + T getHALData() { return reinterpret_cast<T>(pData); } + + struct { + uint8_t queueLimit; + uint8_t frameCount; // 1-8 + } ohci; +private: + USBEndpoint(){} + ENDPOINT_TYPE type; + USB_TYPE state; + 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; + void* pData; +}; + +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; +}; + + +
diff -r 000000000000 -r b5f79b4f741d USBHost/USBHALHost.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/USBHALHost.h Tue Mar 15 11:39:04 2016 +0000 @@ -0,0 +1,35 @@ +#include "mbed.h" + +struct SETUP_PACKET { + uint8_t bmRequestType; + uint8_t bRequest; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; + SETUP_PACKET(uint8_t RequestType, uint8_t Request, uint16_t Value, uint16_t Index, uint16_t Length) { + bmRequestType = RequestType; + bRequest = Request; + wValue = Value; + wIndex = Index; + wLength = Length; + } +}; + +#if defined(TARGET_NUCLEO_F401RE)||defined(TARGET_NUCLEO_F411RE)||defined(TARGET_NUCLEO_F446RE) +#include "USBHALHost_F401RE.h" +#elif defined(TARGET_KL46Z)||defined(TARGET_KL25Z)||defined(TARGET_K64F) +#include "USBHALHost_KL46Z.h" +#elif defined(TARGET_LPC4088)||defined(TARGET_LPC1768) +#include "USBHALHost_LPC4088.h" +#else +#error "target error" +#endif + +#ifndef CTASSERT +template <bool>struct CtAssert; +template <>struct CtAssert<true> {}; +#define CTASSERT(A) CtAssert<A>(); +#endif // CTASSERT + + +
diff -r 000000000000 -r b5f79b4f741d USBHost/USBHALHost2_F401RE.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/USBHALHost2_F401RE.cpp Tue Mar 15 11:39:04 2016 +0000 @@ -0,0 +1,540 @@ +#if defined(TARGET_NUCLEO_F401RE)||defined(TARGET_NUCLEO_F411RE)||defined(TARGET_NUCLEO_F446RE) +#include "USBHALHost.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); + } + else if(hhcd->hc[chnum].ep_type == EP_TYPE_ISOC) + { + USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_ODDFRM; + hhcd->hc[chnum].urb_state = URB_DONE; + HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state); + } + 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 + +
diff -r 000000000000 -r b5f79b4f741d USBHost/USBHALHost_F401RE.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/USBHALHost_F401RE.cpp Tue Mar 15 11:39:04 2016 +0000 @@ -0,0 +1,534 @@ +#if defined(TARGET_NUCLEO_F401RE)||defined(TARGET_NUCLEO_F411RE)||defined(TARGET_NUCLEO_F446RE) +#include "USBHALHost.h" +#include <algorithm> + +#ifdef _USB_DBG +extern RawSerial pc; +//RawSerial pc(USBTX,USBRX); +#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 + +#undef USB_TEST_ASSERT +void usb_test_assert_internal(const char *expr, const char *file, int line); +#define USB_TEST_ASSERT(EXPR) while(!(EXPR)){usb_test_assert_internal(#EXPR,__FILE__,__LINE__);} + +#define USB_TRACE1(A) while(0) + +#define USB_INFO(...) do{fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");}while(0); + +__IO bool attach_done = false; + +void delay_ms(uint32_t t) +{ + HAL_Delay(t); +} + +// 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); + } +} + +// stm32f4xx_it.c +extern "C" { +void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd) +{ + USB_TRACE1(hhcd); + attach_done = true; +} + +} // extern "C" + +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) { + const uint8_t ep_addr = 0x00; + HC hc; + USBDeviceConnected* dev = ep->getDevice(); + hc.Init(ep_addr, + dev->getAddress(), + dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL, + EP_TYPE_CTRL, ep->getSize()); + + setup->wLength = wLength; + hc.SubmitRequest((uint8_t*)setup, 8, true); // PID_SETUP + while(hc.GetURBState() == URB_IDLE); + + switch(hc.GetURBState()) { + case URB_DONE: + LastStatus = ACK; + break; + default: + LastStatus = 0xff; + break; + } + ep->setData01(DATA1); + return 8; +} + +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) { + const uint8_t ep_addr = 0x80; + HC hc; + USBDeviceConnected* dev = ep->getDevice(); + hc.Init(ep_addr, + dev->getAddress(), + dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL, + EP_TYPE_CTRL, ep->getSize()); + + hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1); + + hc.SubmitRequest(data, size); + while(hc.GetURBState() == URB_IDLE); + + switch(hc.GetURBState()) { + case URB_DONE: + LastStatus = ACK; + break; + default: + LastStatus = 0xff; + return -1; + } + ep->toggleData01(); + return hc.GetXferCount(); +} + +int USBHALHost::token_int_in(USBEndpoint* ep, uint8_t* data, int size) { + HC hc; + USBDeviceConnected* dev = ep->getDevice(); + hc.Init( + ep->getAddress(), + dev->getAddress(), + dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL, + EP_TYPE_INTR, ep->getSize()); + + hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1); + + hc.SubmitRequest(data, size); + while(hc.GetURBState() == URB_IDLE); + switch(hc.GetURBState()) { + case URB_DONE: + switch(hc.GetState()) { + case HC_XFRC: + LastStatus = ep->getData01(); + ep->toggleData01(); + return hc.GetXferCount(); + 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) { + HC hc; + USBDeviceConnected* dev = ep->getDevice(); + hc.Init( + ep->getAddress(), + dev->getAddress(), + HCD_SPEED_FULL, + EP_TYPE_BULK, ep->getSize()); + + hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1); + + int retry = 0; + do { + hc.SubmitRequest(data, size); + while(hc.GetURBState() == URB_IDLE); + + switch(hc.GetURBState()) { + case URB_DONE: + switch(hc.GetState()) { + case HC_XFRC: + LastStatus = ep->getData01(); + ep->toggleData01(); + return hc.GetXferCount(); + 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) { + const uint8_t ep_addr = 0x00; + HC hc; + USBDeviceConnected* dev = ep->getDevice(); + hc.Init(ep_addr, + dev->getAddress(), + dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL, + EP_TYPE_CTRL, ep->getSize()); + + hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1); + + do { + hc.SubmitRequest((uint8_t*)data, size); + while(hc.GetURBState() == URB_IDLE); + + switch(hc.GetURBState()) { + case URB_DONE: + LastStatus = ACK; + ep->toggleData01(); + return size; + + default: + break; + } + delay_ms(1); + }while(retryLimit-- > 0); + return -1; +} + +int USBHALHost::token_int_out(USBEndpoint* ep, const uint8_t* data, int size) { + HC hc; + USBDeviceConnected* dev = ep->getDevice(); + hc.Init( + ep->getAddress(), + dev->getAddress(), + dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL, + EP_TYPE_INTR, ep->getSize()); + + hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1); + + hc.SubmitRequest((uint8_t*)data, size); + while(hc.GetURBState() == URB_IDLE); + if (hc.GetURBState() != URB_DONE) { + return -1; + } + ep->toggleData01(); + return size; +} + +int USBHALHost::token_blk_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit) { + HC hc; + USBDeviceConnected* dev = ep->getDevice(); + hc.Init( + ep->getAddress(), dev->getAddress(), + HCD_SPEED_FULL, EP_TYPE_BULK, ep->getSize()); + + hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1); + + int retry = 0; + do { + hc.SubmitRequest((uint8_t*)data, size); + while(hc.GetURBState() == URB_IDLE); + + switch(hc.GetURBState()) { + case URB_DONE: + switch(hc.GetState()) { + case HC_XFRC: // ACK + LastStatus = ep->getData01(); + ep->toggleData01(); + return size; + 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) { + HC* hc = ep->getHALData<HC*>(); + if (hc == NULL) { + hc = new HC; + ep->setHALData<HC*>(hc); + USBDeviceConnected* dev = ep->getDevice(); + hc->Init( + ep->getAddress(), dev->getAddress(), + HCD_SPEED_FULL, EP_TYPE_ISOC, ep->getSize()); + } + hc->SubmitRequest(data, size); + while(hc->GetURBState() == URB_IDLE); + return hc->GetXferCount(); +} + +int USBHALHost::multi_token_in(USBEndpoint* ep, uint8_t* data, size_t total, bool block) { + if (total == 0) { + return token_in(ep); + } + int retryLimit = block ? 10 : 0; + int read_len = 0; + for(int n = 0; read_len < total; n++) { + int size = std::min((int)total-read_len, ep->getSize()); + int result = token_in(ep, data+read_len, size, retryLimit); + if (result < 0) { + if (block) { + return -1; + } + if (LastStatus == NAK) { + if (n == 0) { + return -1; + } + break; + } + return result; + } + read_len += result; + if (result < ep->getSize()) { + break; + } + } + return read_len; +} + +int USBHALHost::multi_token_out(USBEndpoint* ep, const uint8_t* data, size_t total) { + if (total == 0) { + return token_out(ep); + } + int write_len = 0; + for(int n = 0; write_len < total; n++) { + int size = std::min((int)total-write_len, ep->getSize()); + int result = token_out(ep, data+write_len, size); + 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; + } + } + return write_len; +} +void USBHALHost::multi_token_inNB(USBEndpoint* ep, uint8_t* data, int size) { + USB_TRACE1(size); + USB_TEST_ASSERT(ep->getState() != USB_TYPE_PROCESSING); + ep->setBuffer(data, size); + ep->setState(USB_TYPE_PROCESSING); +} + +USB_TYPE USBHALHost::multi_token_inNB_result(USBEndpoint* ep) { + USB_TEST_ASSERT(ep->getState() == USB_TYPE_PROCESSING); + uint8_t* buf = ep->getBufStart(); + int size = ep->getBufSize(); + int result = multi_token_in(ep, buf, size, false); + USB_TRACE1(result); + if (result < 0) { + return USB_TYPE_PROCESSING; + } + ep->setLengthTransferred(result); + ep->setState(USB_TYPE_IDLE); + return USB_TYPE_OK; + +} + +void USBHALHost::setToggle(USBEndpoint* ep, uint8_t toggle) { + USB_TEST_ASSERT(toggle == 1); + ep->setData01(toggle == 0 ? DATA0 : DATA1); +} + +uint8_t HC::slot = 0x00; + +HC::HC() { + static const int start = 1; + uint8_t mask = (1<<start); + for(int i = start; i < 8; i++, mask <<= 1) { + if (!(slot & mask)) { + slot |= mask; + _ch = i; + return; + } + } + _ch = 0; // ERROR!!! +} + +HC::HC(int ch) { + _ch = ch; + slot |= (1<<_ch); +} + +HC::~HC() { + slot &= ~(1<<_ch); +} + +HAL_StatusTypeDef HC::Init(uint8_t epnum, uint8_t dev_address, uint8_t speed, uint8_t ep_type, uint16_t mps) { + _ep_addr = epnum; + _ep_type = ep_type; + return HAL_HCD_HC_Init(&hhcd_USB_OTG_FS, _ch, + epnum, dev_address, speed, ep_type, mps); +} + +HAL_StatusTypeDef HC::SubmitRequest(uint8_t* pbuff, uint16_t length, bool setup) { + uint8_t direction = (_ep_addr & 0x80) ? DIR_IN : DIR_OUT; + if (_ep_type == EP_TYPE_CTRL) { + HCD_HCTypeDef* hc = &hhcd_USB_OTG_FS.hc[_ch]; + if (setup) { + hc->data_pid = HC_PID_SETUP; + hc->toggle_out = 0; + } else { + if (direction == DIR_IN) { + if (hc->toggle_in == 0) { + hc->data_pid = HC_PID_DATA0; + } else { + hc->data_pid = HC_PID_DATA1; + } + } else { // OUT + if (hc->toggle_out == 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; + hc->state = HC_IDLE; + + return USB_HC_StartXfer(hhcd_USB_OTG_FS.Instance, hc, 0); + } + return HAL_HCD_HC_SubmitRequest(&hhcd_USB_OTG_FS, _ch, + direction, _ep_type, 0, pbuff, length, 0); +} + +HCD_URBStateTypeDef HC::GetURBState() { + return HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, _ch); +} + +HCD_HCStateTypeDef HC::GetState() { + return HAL_HCD_HC_GetState(&hhcd_USB_OTG_FS, _ch); +} + +uint32_t HC::GetXferCount() { + return HAL_HCD_HC_GetXferCount(&hhcd_USB_OTG_FS, _ch); +} + +void HC::SetToggle(uint8_t toggle) { + if (_ep_addr & 0x80) { // IN + hhcd_USB_OTG_FS.hc[_ch].toggle_in = toggle; + } else { // OUT + hhcd_USB_OTG_FS.hc[_ch].toggle_out = toggle; + } +} + +#endif + + +
diff -r 000000000000 -r b5f79b4f741d USBHost/USBHALHost_F401RE.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/USBHALHost_F401RE.h Tue Mar 15 11:39:04 2016 +0000 @@ -0,0 +1,59 @@ +#pragma once +#include "mbed.h" +#include "USBHostTypes.h" +#include "USBEndpoint.h" + +class HC { + static const uint8_t DIR_IN = 1; + static const uint8_t DIR_OUT = 0; + +public: + HC(); + HC(int ch); + ~HC(); + HAL_StatusTypeDef Init(uint8_t epnum, uint8_t dev_address, uint8_t speed, uint8_t ep_type, uint16_t mps); + HAL_StatusTypeDef SubmitRequest(uint8_t* pbuff, uint16_t length, bool setup = false); + HCD_URBStateTypeDef GetURBState(); + HCD_HCStateTypeDef GetState(); + uint32_t GetXferCount(); + void SetToggle(uint8_t toggle); + + static uint8_t slot; + +private: + int _ch; + uint8_t _ep_addr; + uint8_t _ep_type; +}; + +class USBHALHost { +public: + uint8_t LastStatus; + uint8_t prev_LastStatus; + +protected: + USBHALHost(); + void init(); + virtual bool addDevice(USBDeviceConnected* parent, int port, bool lowSpeed) = 0; + int token_setup(USBEndpoint* ep, SETUP_PACKET* setup, uint16_t wLength = 0); + int token_iso_in(USBEndpoint* ep, uint8_t* data, int size); + int multi_token_in(USBEndpoint* ep, uint8_t* data = NULL, size_t total = 0, bool block = true); + int multi_token_out(USBEndpoint* ep, const uint8_t* data = NULL, size_t total = 0); + void multi_token_inNB(USBEndpoint* ep, uint8_t* data, int size); + USB_TYPE multi_token_inNB_result(USBEndpoint* ep); + void setToggle(USBEndpoint* ep, uint8_t toggle); + +private: + int token_in(USBEndpoint* ep, uint8_t* data = NULL, int size = 0, int retryLimit = 10); + int token_out(USBEndpoint* ep, const uint8_t* data = NULL, int size = 0, int retryLimit = 10); + 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; +}; + +
diff -r 000000000000 -r b5f79b4f741d USBHost/USBHost.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/USBHost.cpp Tue Mar 15 11:39:04 2016 +0000 @@ -0,0 +1,352 @@ +/* mbed USBHost Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "USBHost.h" + +#define USB_TRACE1(A) while(0) +#undef USB_TEST_ASSERT +void usb_test_assert_internal(const char *expr, const char *file, int line); +#define USB_TEST_ASSERT(EXPR) while(!(EXPR)){usb_test_assert_internal(#EXPR,__FILE__,__LINE__);} + +USBHost* USBHost::inst = NULL; + +USBHost* USBHost::getHostInst() { + 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) { + USBEndpoint* ep = dev->getEpCtl(); + SETUP_PACKET setup(requestType, request, value, index, len); + + int result = token_setup(ep, &setup, len); // setup stage + USB_TRACE1(result); + if (result < 0) { + return USB_TYPE_ERROR; + } + + int read_len = multi_token_in(ep, buf, len); // data stage + USB_TRACE1(read_len); + if (read_len < 0) { + return USB_TYPE_ERROR; + } + + setToggle(ep, 1); // DATA1 + result = multi_token_out(ep); // status stage + USB_TRACE1(result); + if (result < 0) { + return USB_TYPE_ERROR; + } + ep->setLengthTransferred(read_len); + return USB_TYPE_OK; +} + +USB_TYPE USBHost::controlWrite(USBDeviceConnected* dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) { + USBEndpoint* ep = dev->getEpCtl(); + SETUP_PACKET setup(requestType, request, value, index, len); + + int result = token_setup(ep, &setup, len); // setup stage + USB_TRACE1(result); + if (result < 0) { + return USB_TYPE_ERROR; + } + int write_len = 0; + if (buf != NULL) { + write_len = multi_token_out(ep, buf, len); // data stage + USB_TRACE1(write_len); + if (write_len < 0) { + return USB_TYPE_ERROR; + } + } + + setToggle(ep, 1); // DATA1 + result = multi_token_in(ep); // status stage + USB_TRACE1(result); + if (result < 0) { + return USB_TYPE_ERROR; + } + ep->setLengthTransferred(write_len); + return USB_TYPE_OK; +} + +USB_TYPE USBHost::bulkRead(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { + if (blocking == false) { + ep->setBuffer(buf, len); + ep_queue.push(ep); + multi_token_inNB(ep, buf, len); + return USB_TYPE_PROCESSING; + } + int result = multi_token_in(ep, buf, len); + USB_TRACE1(result); + if (result < 0) { + return USB_TYPE_ERROR; + } + ep->setLengthTransferred(result); + return USB_TYPE_OK; +} + +USB_TYPE USBHost::bulkWrite(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { + USB_TEST_ASSERT(blocking); + int result = multi_token_out(ep, buf, len); + USB_TRACE1(result); + if (result < 0) { + return USB_TYPE_ERROR; + } + ep->setLengthTransferred(result); + return USB_TYPE_OK; +} + +USB_TYPE USBHost::interruptRead(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { + if (blocking == false) { + ep->setBuffer(buf, len); + ep_queue.push(ep); + multi_token_inNB(ep, buf, len); + return USB_TYPE_PROCESSING; + } + int result = multi_token_in(ep, buf, len); + USB_TRACE1(result); + if (result < 0) { + return USB_TYPE_ERROR; + } + ep->setLengthTransferred(result); + return USB_TYPE_OK; +} + +USB_TYPE USBHost::interruptWrite(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { + USB_TEST_ASSERT(blocking); + int result = multi_token_out(ep, buf, len); + USB_TRACE1(result); + if (result < 0) { + return USB_TYPE_ERROR; + } + ep->setLengthTransferred(result); + return USB_TYPE_OK; +} + +USB_TYPE USBHost::isochronousRead(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { + USB_TEST_ASSERT(blocking); + isochronousReadNB(ep, buf, len); + return USB_TYPE_OK; +} + +int USBHost::interruptReadNB(USBEndpoint* ep, uint8_t* data, int size) { + USB_TRACE1(size); + if (ep->getState() != USB_TYPE_PROCESSING) { + ep->setState(USB_TYPE_PROCESSING); + ep->setBuffer(data, size); + multi_token_inNB(ep, data, size); + } + if (multi_token_inNB_result(ep) != USB_TYPE_PROCESSING) { + return ep->getLengthTransferred(); + } + return -1; +} + +int USBHost::bulkReadNB(USBEndpoint* ep, uint8_t* data, int size) { + USB_TRACE1(size); + return interruptReadNB(ep, data, size); +} + +int USBHost::isochronousReadNB(USBEndpoint* ep, uint8_t* data, int size) { + USB_TRACE1(size); + int result = token_iso_in(ep, data, size); + if (result >= 0) { + ep->setLengthTransferred(result); + } + return result; +} + +void USBHost::task() { + USBEndpoint* ep = ep_queue.pop(); + if (ep) { + USB_TEST_ASSERT(ep->getDir() == IN); + if (multi_token_inNB_result(ep) != USB_TYPE_PROCESSING) { + ep->call(); + } else { + ep_queue.push(ep); + } + } +} + +void usb_test_assert_internal(const char *expr, const char *file, int line){ + error("\n\n%s@%d %s ASSERT!\n\n", file, line, expr); +} + +
diff -r 000000000000 -r b5f79b4f741d USBHost/USBHost.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/USBHost.h Tue Mar 15 11:39:04 2016 +0000 @@ -0,0 +1,195 @@ +/* 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 bulkReadNB(USBEndpoint*ep, uint8_t* data, int size); + int isochronousReadNB(USBEndpoint*ep, uint8_t* data, int size); + + /** + * non-blocking processing + */ + 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; + 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); +}; + +
diff -r 000000000000 -r b5f79b4f741d USBHost/USBHostConf.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/USBHostConf.h Tue Mar 15 11:39:04 2016 +0000 @@ -0,0 +1,72 @@ +/* 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 1 + +/* +* Maximum number of ports on a USB hub +*/ +#define MAX_HUB_PORT 4 + +/* +* Enable USBHostMSD +*/ +#define USBHOST_MSD 0 + +/* +* Enable USBHostKeyboard +*/ +#define USBHOST_KEYBOARD 0 + +/* +* Enable USBHostMouse +*/ +#define USBHOST_MOUSE 0 + +/* +* Enable USBHostSerial or USBHostMultiSerial (if set > 1) +*/ +#define USBHOST_SERIAL 0 + +/* +* Enable USB3Gmodule +*/ +#define USBHOST_3GMODULE 0 + +/* +* 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 +
diff -r 000000000000 -r b5f79b4f741d USBHost/USBHostGamepad.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/USBHostGamepad.cpp Tue Mar 15 11:39:04 2016 +0000 @@ -0,0 +1,119 @@ +/* + * mbed USBHost Gamepad driver sample + * Copyright (c) 2014 Yuuichi Akagawa + * + * modified from mbed USBHostMouse + * + * 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 "USBHostGamepad.h" +//#if USBHOST_GAMEPAD + +USBHostGamepad::USBHostGamepad() { + host = USBHost::getHostInst(); + init(); +} + +void USBHostGamepad::init() { + dev = NULL; + int_in = NULL; + dev_connected = false; + gamepad_device_found = false; + gamepad_intf = -1; +} + +bool USBHostGamepad::connected() { + return dev_connected; +} + +bool USBHostGamepad::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 (gamepad_device_found) { + + int_in = dev->getEndpoint(gamepad_intf, INTERRUPT_ENDPOINT, IN); + if (!int_in) + break; + + USB_INFO("New Gamepad/Joystick device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, gamepad_intf); +#if DEBUG > 3 + //Parse HID Report Descriptor + parseHidDescr(); +#endif + dev->setName("Gamepad", gamepad_intf); + host->registerDriver(dev, gamepad_intf, this, &USBHostGamepad::init); + + int_in->attach(this, &USBHostGamepad::rxHandler); + rxSize = int_in->getSize(); + if (rxSize > sizeof(report)) + rxSize = sizeof(report); + host->interruptRead(dev, int_in, report, rxSize, false); + + dev_connected = true; + return true; + } + } + } + init(); + return false; +} + +void USBHostGamepad::rxHandler() { + if (dev) + host->interruptRead(dev, int_in, report, rxSize, false); + + /* modified 2016 Racoon */ + +} + +/*virtual*/ void USBHostGamepad::setVidPid(uint16_t vid, uint16_t pid) +{ + // we don't check VID/PID for gamepad driver +} + +/*virtual*/ bool USBHostGamepad::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 ((gamepad_intf == -1) && + (intf_class == HID_CLASS) && + (intf_subclass == 0x00) && + (intf_protocol == 0x00)) { + gamepad_intf = intf_nb; + return true; + } + return false; +} + +/*virtual*/ bool USBHostGamepad::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used +{ + if (intf_nb == gamepad_intf) { + if (type == INTERRUPT_ENDPOINT && dir == IN) { + gamepad_device_found = true; + return true; + } + } + return false; +} + +
diff -r 000000000000 -r b5f79b4f741d USBHost/USBHostGamepad.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/USBHostGamepad.h Tue Mar 15 11:39:04 2016 +0000 @@ -0,0 +1,90 @@ +/* + * modified from + * mbed USBHost Gamepad driver sample + * Copyright (c) 2014 Yuuichi Akagawa + * + * modified from mbed USBHostMouse + * + * Copyright (c) 2014 mbed.org, MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef USBHOSTGAMEPAD_H +#define USBHOSTGAMEPAD_H + +#include "USBHostConf.h" + +//#if USBHOST_GAMEPAD + +#include "USBHost.h" +//HID Class Request +#define HID_GET_REPORT 0x01 +#define HID_GET_IDLE 0x02 +#define HID_GET_PROTOCOL 0x03 +#define HID_GET_DESCRIPTOR 0x06 +#define HID_SET_REPORT 0x09 +#define HID_SET_IDLE 0x0a +#define HID_SET_PROTOCOL 0x0b + +/** + * A class to communicate a USB MIDI device + */ +class USBHostGamepad : public IUSBEnumerator { +public: + /** + * Constructor + */ + USBHostGamepad(); + + /** + * Try to connect a gamepad device + * + * @return true if connection was successful + */ + bool connect(); + + /** + * Check if a gamepad is connected + * + * @returns true if a gamepad is connected + */ + bool connected(); + + uint8_t report[8]; /* modified 2016 Racoon */ + int rxSize; + +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; + + bool dev_connected; + bool gamepad_device_found; + int gamepad_intf; + + void rxHandler(); + void init(); +}; + +#endif +
diff -r 000000000000 -r b5f79b4f741d USBHost/USBHostHub.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/USBHostHub.cpp Tue Mar 15 11:39:04 2016 +0000 @@ -0,0 +1,113 @@ +#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; +} +
diff -r 000000000000 -r b5f79b4f741d USBHost/USBHostTypes.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/USBHostTypes.h Tue Mar 15 11:39:04 2016 +0000 @@ -0,0 +1,168 @@ +/* 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 +
diff -r 000000000000 -r b5f79b4f741d USBHost/dbg.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/dbg.h Tue Mar 15 11:39:04 2016 +0000 @@ -0,0 +1,91 @@ +/* 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*/ +#define DEBUG 0 +#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 + +#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 + +
diff -r 000000000000 -r b5f79b4f741d USBHost/mydebug.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/mydebug.h Tue Mar 15 11:39:04 2016 +0000 @@ -0,0 +1,14 @@ +#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"); +} + +
diff -r 000000000000 -r b5f79b4f741d USBHost/mymap.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/mymap.h Tue Mar 15 11:39:04 2016 +0000 @@ -0,0 +1,66 @@ +#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; +}; +
diff -r 000000000000 -r b5f79b4f741d USBHost/myvector.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/myvector.h Tue Mar 15 11:39:04 2016 +0000 @@ -0,0 +1,35 @@ +#pragma once + +template<class T> +class myvector { +public: + myvector() { + m_size = 0; + m_buf = NULL; + } + ~myvector() { + if (m_buf) { + delete[] m_buf; + } + } + 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; +}; +
diff -r 000000000000 -r b5f79b4f741d main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Tue Mar 15 11:39:04 2016 +0000 @@ -0,0 +1,29 @@ +#include "mbed.h" +#include "USBHostGamepad.h" + +USBHostGamepad *pad; + +// LED +DigitalOut red(PB_5); +DigitalOut yellow(PA_10); + +int main() +{ + // USB Gmaepad Initialize + pad = new USBHostGamepad(); + if (!pad->connect()) { + printf("USB Gamepad not found.\r\n"); + while(1); + } + + while(1) + { + USBHost::poll(); + + red = pad->report[4] & 0x20; + yellow = pad->report[4] & 0x40; + + printf("%02x %02x %02x %02x %02x %02x %02x %02x\r\n", pad->report[0],pad->report[1],pad->report[2],pad->report[3],pad->report[4],pad->report[5],pad->report[6],pad->report[7]); + wait_ms(16); + } +}
diff -r 000000000000 -r b5f79b4f741d mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Tue Mar 15 11:39:04 2016 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/87f2f5183dfb \ No newline at end of file