This example demonstrates the reading of the USB Gamepad in the Nucleo.

Dependencies:   mbed

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

/media/uploads/beaglescout007/nucleo_ex04_usbpad.png This circuit diagram was created by fritzing.

/media/uploads/beaglescout007/usbcon.jpg

USB con.Nucleo
GNDGND
+PA_12
-PA_11
5V5V

https://youtu.be/EYIukjwJSew

Original Library

Committer:
beaglescout007
Date:
Tue Mar 15 11:39:04 2016 +0000
Revision:
0:b5f79b4f741d
Release

Who changed what in which revision?

UserRevisionLine numberNew contents of line
beaglescout007 0:b5f79b4f741d 1 #if defined(TARGET_NUCLEO_F401RE)||defined(TARGET_NUCLEO_F411RE)||defined(TARGET_NUCLEO_F446RE)
beaglescout007 0:b5f79b4f741d 2 #include "USBHALHost.h"
beaglescout007 0:b5f79b4f741d 3 #include <algorithm>
beaglescout007 0:b5f79b4f741d 4
beaglescout007 0:b5f79b4f741d 5 #ifdef _USB_DBG
beaglescout007 0:b5f79b4f741d 6 extern RawSerial pc;
beaglescout007 0:b5f79b4f741d 7 //RawSerial pc(USBTX,USBRX);
beaglescout007 0:b5f79b4f741d 8 #include "mydebug.h"
beaglescout007 0:b5f79b4f741d 9 #define USB_DBG(...) do{pc.printf("[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);pc.printf(__VA_ARGS__);pc.puts("\n");} while(0);
beaglescout007 0:b5f79b4f741d 10 #define USB_DBG_HEX(A,B) debug_hex<RawSerial>(pc,A,B)
beaglescout007 0:b5f79b4f741d 11
beaglescout007 0:b5f79b4f741d 12 #else
beaglescout007 0:b5f79b4f741d 13 #define USB_DBG(...) while(0)
beaglescout007 0:b5f79b4f741d 14 #define USB_DBG_HEX(A,B) while(0)
beaglescout007 0:b5f79b4f741d 15 #endif
beaglescout007 0:b5f79b4f741d 16
beaglescout007 0:b5f79b4f741d 17 #undef USB_TEST_ASSERT
beaglescout007 0:b5f79b4f741d 18 void usb_test_assert_internal(const char *expr, const char *file, int line);
beaglescout007 0:b5f79b4f741d 19 #define USB_TEST_ASSERT(EXPR) while(!(EXPR)){usb_test_assert_internal(#EXPR,__FILE__,__LINE__);}
beaglescout007 0:b5f79b4f741d 20
beaglescout007 0:b5f79b4f741d 21 #define USB_TRACE1(A) while(0)
beaglescout007 0:b5f79b4f741d 22
beaglescout007 0:b5f79b4f741d 23 #define USB_INFO(...) do{fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");}while(0);
beaglescout007 0:b5f79b4f741d 24
beaglescout007 0:b5f79b4f741d 25 __IO bool attach_done = false;
beaglescout007 0:b5f79b4f741d 26
beaglescout007 0:b5f79b4f741d 27 void delay_ms(uint32_t t)
beaglescout007 0:b5f79b4f741d 28 {
beaglescout007 0:b5f79b4f741d 29 HAL_Delay(t);
beaglescout007 0:b5f79b4f741d 30 }
beaglescout007 0:b5f79b4f741d 31
beaglescout007 0:b5f79b4f741d 32 // usbh_conf.c
beaglescout007 0:b5f79b4f741d 33 extern HCD_HandleTypeDef hhcd_USB_OTG_FS;
beaglescout007 0:b5f79b4f741d 34
beaglescout007 0:b5f79b4f741d 35 void HAL_HCD_MspInit(HCD_HandleTypeDef* hhcd)
beaglescout007 0:b5f79b4f741d 36 {
beaglescout007 0:b5f79b4f741d 37 GPIO_InitTypeDef GPIO_InitStruct;
beaglescout007 0:b5f79b4f741d 38 if(hhcd->Instance==USB_OTG_FS)
beaglescout007 0:b5f79b4f741d 39 {
beaglescout007 0:b5f79b4f741d 40 /* Peripheral clock enable */
beaglescout007 0:b5f79b4f741d 41 __USB_OTG_FS_CLK_ENABLE();
beaglescout007 0:b5f79b4f741d 42
beaglescout007 0:b5f79b4f741d 43 /**USB_OTG_FS GPIO Configuration
beaglescout007 0:b5f79b4f741d 44 PA11 ------> USB_OTG_FS_DM
beaglescout007 0:b5f79b4f741d 45 PA12 ------> USB_OTG_FS_DP
beaglescout007 0:b5f79b4f741d 46 */
beaglescout007 0:b5f79b4f741d 47 GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12;
beaglescout007 0:b5f79b4f741d 48 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
beaglescout007 0:b5f79b4f741d 49 GPIO_InitStruct.Pull = GPIO_NOPULL;
beaglescout007 0:b5f79b4f741d 50 GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
beaglescout007 0:b5f79b4f741d 51 GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS;
beaglescout007 0:b5f79b4f741d 52 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
beaglescout007 0:b5f79b4f741d 53
beaglescout007 0:b5f79b4f741d 54 /* Peripheral interrupt init*/
beaglescout007 0:b5f79b4f741d 55 /* Sets the priority grouping field */
beaglescout007 0:b5f79b4f741d 56 HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_0);
beaglescout007 0:b5f79b4f741d 57 HAL_NVIC_SetPriority(OTG_FS_IRQn, 0, 0);
beaglescout007 0:b5f79b4f741d 58 HAL_NVIC_EnableIRQ(OTG_FS_IRQn);
beaglescout007 0:b5f79b4f741d 59 }
beaglescout007 0:b5f79b4f741d 60 }
beaglescout007 0:b5f79b4f741d 61
beaglescout007 0:b5f79b4f741d 62 // stm32f4xx_it.c
beaglescout007 0:b5f79b4f741d 63 extern "C" {
beaglescout007 0:b5f79b4f741d 64 void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd)
beaglescout007 0:b5f79b4f741d 65 {
beaglescout007 0:b5f79b4f741d 66 USB_TRACE1(hhcd);
beaglescout007 0:b5f79b4f741d 67 attach_done = true;
beaglescout007 0:b5f79b4f741d 68 }
beaglescout007 0:b5f79b4f741d 69
beaglescout007 0:b5f79b4f741d 70 } // extern "C"
beaglescout007 0:b5f79b4f741d 71
beaglescout007 0:b5f79b4f741d 72 USBHALHost* USBHALHost::instHost;
beaglescout007 0:b5f79b4f741d 73
beaglescout007 0:b5f79b4f741d 74 USBHALHost::USBHALHost() {
beaglescout007 0:b5f79b4f741d 75 instHost = this;
beaglescout007 0:b5f79b4f741d 76 }
beaglescout007 0:b5f79b4f741d 77
beaglescout007 0:b5f79b4f741d 78 void USBHALHost::init() {
beaglescout007 0:b5f79b4f741d 79 hhcd_USB_OTG_FS.Instance = USB_OTG_FS;
beaglescout007 0:b5f79b4f741d 80 hhcd_USB_OTG_FS.Init.Host_channels = 8;
beaglescout007 0:b5f79b4f741d 81 hhcd_USB_OTG_FS.Init.speed = HCD_SPEED_FULL;
beaglescout007 0:b5f79b4f741d 82 hhcd_USB_OTG_FS.Init.dma_enable = DISABLE;
beaglescout007 0:b5f79b4f741d 83 hhcd_USB_OTG_FS.Init.phy_itface = HCD_PHY_EMBEDDED;
beaglescout007 0:b5f79b4f741d 84 hhcd_USB_OTG_FS.Init.Sof_enable = DISABLE;
beaglescout007 0:b5f79b4f741d 85 hhcd_USB_OTG_FS.Init.low_power_enable = ENABLE;
beaglescout007 0:b5f79b4f741d 86 hhcd_USB_OTG_FS.Init.vbus_sensing_enable = DISABLE;
beaglescout007 0:b5f79b4f741d 87 hhcd_USB_OTG_FS.Init.use_external_vbus = DISABLE;
beaglescout007 0:b5f79b4f741d 88
beaglescout007 0:b5f79b4f741d 89 HAL_HCD_Init(&hhcd_USB_OTG_FS);
beaglescout007 0:b5f79b4f741d 90 HAL_HCD_Start(&hhcd_USB_OTG_FS);
beaglescout007 0:b5f79b4f741d 91
beaglescout007 0:b5f79b4f741d 92 bool lowSpeed = wait_attach();
beaglescout007 0:b5f79b4f741d 93 delay_ms(200);
beaglescout007 0:b5f79b4f741d 94 HAL_HCD_ResetPort(&hhcd_USB_OTG_FS);
beaglescout007 0:b5f79b4f741d 95 delay_ms(100); // Wait for 100 ms after Reset
beaglescout007 0:b5f79b4f741d 96 addDevice(NULL, 0, lowSpeed);
beaglescout007 0:b5f79b4f741d 97 }
beaglescout007 0:b5f79b4f741d 98
beaglescout007 0:b5f79b4f741d 99 bool USBHALHost::wait_attach() {
beaglescout007 0:b5f79b4f741d 100 Timer t;
beaglescout007 0:b5f79b4f741d 101 t.reset();
beaglescout007 0:b5f79b4f741d 102 t.start();
beaglescout007 0:b5f79b4f741d 103 while(!attach_done) {
beaglescout007 0:b5f79b4f741d 104 if (t.read_ms() > 5*1000) {
beaglescout007 0:b5f79b4f741d 105 t.reset();
beaglescout007 0:b5f79b4f741d 106 USB_INFO("Please attach USB device.");
beaglescout007 0:b5f79b4f741d 107 }
beaglescout007 0:b5f79b4f741d 108 }
beaglescout007 0:b5f79b4f741d 109 wait_ms(100);
beaglescout007 0:b5f79b4f741d 110 return HAL_HCD_GetCurrentSpeed(&hhcd_USB_OTG_FS) == USB_OTG_SPEED_LOW;
beaglescout007 0:b5f79b4f741d 111 }
beaglescout007 0:b5f79b4f741d 112
beaglescout007 0:b5f79b4f741d 113 int USBHALHost::token_setup(USBEndpoint* ep, SETUP_PACKET* setup, uint16_t wLength) {
beaglescout007 0:b5f79b4f741d 114 const uint8_t ep_addr = 0x00;
beaglescout007 0:b5f79b4f741d 115 HC hc;
beaglescout007 0:b5f79b4f741d 116 USBDeviceConnected* dev = ep->getDevice();
beaglescout007 0:b5f79b4f741d 117 hc.Init(ep_addr,
beaglescout007 0:b5f79b4f741d 118 dev->getAddress(),
beaglescout007 0:b5f79b4f741d 119 dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL,
beaglescout007 0:b5f79b4f741d 120 EP_TYPE_CTRL, ep->getSize());
beaglescout007 0:b5f79b4f741d 121
beaglescout007 0:b5f79b4f741d 122 setup->wLength = wLength;
beaglescout007 0:b5f79b4f741d 123 hc.SubmitRequest((uint8_t*)setup, 8, true); // PID_SETUP
beaglescout007 0:b5f79b4f741d 124 while(hc.GetURBState() == URB_IDLE);
beaglescout007 0:b5f79b4f741d 125
beaglescout007 0:b5f79b4f741d 126 switch(hc.GetURBState()) {
beaglescout007 0:b5f79b4f741d 127 case URB_DONE:
beaglescout007 0:b5f79b4f741d 128 LastStatus = ACK;
beaglescout007 0:b5f79b4f741d 129 break;
beaglescout007 0:b5f79b4f741d 130 default:
beaglescout007 0:b5f79b4f741d 131 LastStatus = 0xff;
beaglescout007 0:b5f79b4f741d 132 break;
beaglescout007 0:b5f79b4f741d 133 }
beaglescout007 0:b5f79b4f741d 134 ep->setData01(DATA1);
beaglescout007 0:b5f79b4f741d 135 return 8;
beaglescout007 0:b5f79b4f741d 136 }
beaglescout007 0:b5f79b4f741d 137
beaglescout007 0:b5f79b4f741d 138 int USBHALHost::token_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit) {
beaglescout007 0:b5f79b4f741d 139 switch(ep->getType()) {
beaglescout007 0:b5f79b4f741d 140 case CONTROL_ENDPOINT:
beaglescout007 0:b5f79b4f741d 141 return token_ctl_in(ep, data, size, retryLimit);
beaglescout007 0:b5f79b4f741d 142 case INTERRUPT_ENDPOINT:
beaglescout007 0:b5f79b4f741d 143 return token_int_in(ep, data, size);
beaglescout007 0:b5f79b4f741d 144 case BULK_ENDPOINT:
beaglescout007 0:b5f79b4f741d 145 return token_blk_in(ep, data, size, retryLimit);
beaglescout007 0:b5f79b4f741d 146 }
beaglescout007 0:b5f79b4f741d 147 return -1;
beaglescout007 0:b5f79b4f741d 148 }
beaglescout007 0:b5f79b4f741d 149
beaglescout007 0:b5f79b4f741d 150 int USBHALHost::token_ctl_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit) {
beaglescout007 0:b5f79b4f741d 151 const uint8_t ep_addr = 0x80;
beaglescout007 0:b5f79b4f741d 152 HC hc;
beaglescout007 0:b5f79b4f741d 153 USBDeviceConnected* dev = ep->getDevice();
beaglescout007 0:b5f79b4f741d 154 hc.Init(ep_addr,
beaglescout007 0:b5f79b4f741d 155 dev->getAddress(),
beaglescout007 0:b5f79b4f741d 156 dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL,
beaglescout007 0:b5f79b4f741d 157 EP_TYPE_CTRL, ep->getSize());
beaglescout007 0:b5f79b4f741d 158
beaglescout007 0:b5f79b4f741d 159 hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1);
beaglescout007 0:b5f79b4f741d 160
beaglescout007 0:b5f79b4f741d 161 hc.SubmitRequest(data, size);
beaglescout007 0:b5f79b4f741d 162 while(hc.GetURBState() == URB_IDLE);
beaglescout007 0:b5f79b4f741d 163
beaglescout007 0:b5f79b4f741d 164 switch(hc.GetURBState()) {
beaglescout007 0:b5f79b4f741d 165 case URB_DONE:
beaglescout007 0:b5f79b4f741d 166 LastStatus = ACK;
beaglescout007 0:b5f79b4f741d 167 break;
beaglescout007 0:b5f79b4f741d 168 default:
beaglescout007 0:b5f79b4f741d 169 LastStatus = 0xff;
beaglescout007 0:b5f79b4f741d 170 return -1;
beaglescout007 0:b5f79b4f741d 171 }
beaglescout007 0:b5f79b4f741d 172 ep->toggleData01();
beaglescout007 0:b5f79b4f741d 173 return hc.GetXferCount();
beaglescout007 0:b5f79b4f741d 174 }
beaglescout007 0:b5f79b4f741d 175
beaglescout007 0:b5f79b4f741d 176 int USBHALHost::token_int_in(USBEndpoint* ep, uint8_t* data, int size) {
beaglescout007 0:b5f79b4f741d 177 HC hc;
beaglescout007 0:b5f79b4f741d 178 USBDeviceConnected* dev = ep->getDevice();
beaglescout007 0:b5f79b4f741d 179 hc.Init(
beaglescout007 0:b5f79b4f741d 180 ep->getAddress(),
beaglescout007 0:b5f79b4f741d 181 dev->getAddress(),
beaglescout007 0:b5f79b4f741d 182 dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL,
beaglescout007 0:b5f79b4f741d 183 EP_TYPE_INTR, ep->getSize());
beaglescout007 0:b5f79b4f741d 184
beaglescout007 0:b5f79b4f741d 185 hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1);
beaglescout007 0:b5f79b4f741d 186
beaglescout007 0:b5f79b4f741d 187 hc.SubmitRequest(data, size);
beaglescout007 0:b5f79b4f741d 188 while(hc.GetURBState() == URB_IDLE);
beaglescout007 0:b5f79b4f741d 189 switch(hc.GetURBState()) {
beaglescout007 0:b5f79b4f741d 190 case URB_DONE:
beaglescout007 0:b5f79b4f741d 191 switch(hc.GetState()) {
beaglescout007 0:b5f79b4f741d 192 case HC_XFRC:
beaglescout007 0:b5f79b4f741d 193 LastStatus = ep->getData01();
beaglescout007 0:b5f79b4f741d 194 ep->toggleData01();
beaglescout007 0:b5f79b4f741d 195 return hc.GetXferCount();
beaglescout007 0:b5f79b4f741d 196 case HC_NAK:
beaglescout007 0:b5f79b4f741d 197 LastStatus = NAK;
beaglescout007 0:b5f79b4f741d 198 return -1;
beaglescout007 0:b5f79b4f741d 199 }
beaglescout007 0:b5f79b4f741d 200 break;
beaglescout007 0:b5f79b4f741d 201 }
beaglescout007 0:b5f79b4f741d 202 LastStatus = STALL;
beaglescout007 0:b5f79b4f741d 203 return -1;
beaglescout007 0:b5f79b4f741d 204 }
beaglescout007 0:b5f79b4f741d 205
beaglescout007 0:b5f79b4f741d 206 int USBHALHost::token_blk_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit) {
beaglescout007 0:b5f79b4f741d 207 HC hc;
beaglescout007 0:b5f79b4f741d 208 USBDeviceConnected* dev = ep->getDevice();
beaglescout007 0:b5f79b4f741d 209 hc.Init(
beaglescout007 0:b5f79b4f741d 210 ep->getAddress(),
beaglescout007 0:b5f79b4f741d 211 dev->getAddress(),
beaglescout007 0:b5f79b4f741d 212 HCD_SPEED_FULL,
beaglescout007 0:b5f79b4f741d 213 EP_TYPE_BULK, ep->getSize());
beaglescout007 0:b5f79b4f741d 214
beaglescout007 0:b5f79b4f741d 215 hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1);
beaglescout007 0:b5f79b4f741d 216
beaglescout007 0:b5f79b4f741d 217 int retry = 0;
beaglescout007 0:b5f79b4f741d 218 do {
beaglescout007 0:b5f79b4f741d 219 hc.SubmitRequest(data, size);
beaglescout007 0:b5f79b4f741d 220 while(hc.GetURBState() == URB_IDLE);
beaglescout007 0:b5f79b4f741d 221
beaglescout007 0:b5f79b4f741d 222 switch(hc.GetURBState()) {
beaglescout007 0:b5f79b4f741d 223 case URB_DONE:
beaglescout007 0:b5f79b4f741d 224 switch(hc.GetState()) {
beaglescout007 0:b5f79b4f741d 225 case HC_XFRC:
beaglescout007 0:b5f79b4f741d 226 LastStatus = ep->getData01();
beaglescout007 0:b5f79b4f741d 227 ep->toggleData01();
beaglescout007 0:b5f79b4f741d 228 return hc.GetXferCount();
beaglescout007 0:b5f79b4f741d 229 case HC_NAK:
beaglescout007 0:b5f79b4f741d 230 LastStatus = NAK;
beaglescout007 0:b5f79b4f741d 231 if (retryLimit > 0) {
beaglescout007 0:b5f79b4f741d 232 delay_ms(1 + 10 * retry);
beaglescout007 0:b5f79b4f741d 233 }
beaglescout007 0:b5f79b4f741d 234 break;
beaglescout007 0:b5f79b4f741d 235 default:
beaglescout007 0:b5f79b4f741d 236 break;
beaglescout007 0:b5f79b4f741d 237 }
beaglescout007 0:b5f79b4f741d 238 break;
beaglescout007 0:b5f79b4f741d 239 case URB_STALL:
beaglescout007 0:b5f79b4f741d 240 LastStatus = STALL;
beaglescout007 0:b5f79b4f741d 241 return -1;
beaglescout007 0:b5f79b4f741d 242 default:
beaglescout007 0:b5f79b4f741d 243 LastStatus = STALL;
beaglescout007 0:b5f79b4f741d 244 delay_ms(500 + 100 * retry);
beaglescout007 0:b5f79b4f741d 245 break;
beaglescout007 0:b5f79b4f741d 246 }
beaglescout007 0:b5f79b4f741d 247 }while(retry++ < retryLimit);
beaglescout007 0:b5f79b4f741d 248 return -1;
beaglescout007 0:b5f79b4f741d 249 }
beaglescout007 0:b5f79b4f741d 250
beaglescout007 0:b5f79b4f741d 251 int USBHALHost::token_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit) {
beaglescout007 0:b5f79b4f741d 252 switch(ep->getType()) {
beaglescout007 0:b5f79b4f741d 253 case CONTROL_ENDPOINT:
beaglescout007 0:b5f79b4f741d 254 return token_ctl_out(ep, data, size, retryLimit);
beaglescout007 0:b5f79b4f741d 255 case INTERRUPT_ENDPOINT:
beaglescout007 0:b5f79b4f741d 256 return token_int_out(ep, data, size);
beaglescout007 0:b5f79b4f741d 257 case BULK_ENDPOINT:
beaglescout007 0:b5f79b4f741d 258 return token_blk_out(ep, data, size, retryLimit);
beaglescout007 0:b5f79b4f741d 259 }
beaglescout007 0:b5f79b4f741d 260 return -1;
beaglescout007 0:b5f79b4f741d 261 }
beaglescout007 0:b5f79b4f741d 262
beaglescout007 0:b5f79b4f741d 263 int USBHALHost::token_ctl_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit) {
beaglescout007 0:b5f79b4f741d 264 const uint8_t ep_addr = 0x00;
beaglescout007 0:b5f79b4f741d 265 HC hc;
beaglescout007 0:b5f79b4f741d 266 USBDeviceConnected* dev = ep->getDevice();
beaglescout007 0:b5f79b4f741d 267 hc.Init(ep_addr,
beaglescout007 0:b5f79b4f741d 268 dev->getAddress(),
beaglescout007 0:b5f79b4f741d 269 dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL,
beaglescout007 0:b5f79b4f741d 270 EP_TYPE_CTRL, ep->getSize());
beaglescout007 0:b5f79b4f741d 271
beaglescout007 0:b5f79b4f741d 272 hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1);
beaglescout007 0:b5f79b4f741d 273
beaglescout007 0:b5f79b4f741d 274 do {
beaglescout007 0:b5f79b4f741d 275 hc.SubmitRequest((uint8_t*)data, size);
beaglescout007 0:b5f79b4f741d 276 while(hc.GetURBState() == URB_IDLE);
beaglescout007 0:b5f79b4f741d 277
beaglescout007 0:b5f79b4f741d 278 switch(hc.GetURBState()) {
beaglescout007 0:b5f79b4f741d 279 case URB_DONE:
beaglescout007 0:b5f79b4f741d 280 LastStatus = ACK;
beaglescout007 0:b5f79b4f741d 281 ep->toggleData01();
beaglescout007 0:b5f79b4f741d 282 return size;
beaglescout007 0:b5f79b4f741d 283
beaglescout007 0:b5f79b4f741d 284 default:
beaglescout007 0:b5f79b4f741d 285 break;
beaglescout007 0:b5f79b4f741d 286 }
beaglescout007 0:b5f79b4f741d 287 delay_ms(1);
beaglescout007 0:b5f79b4f741d 288 }while(retryLimit-- > 0);
beaglescout007 0:b5f79b4f741d 289 return -1;
beaglescout007 0:b5f79b4f741d 290 }
beaglescout007 0:b5f79b4f741d 291
beaglescout007 0:b5f79b4f741d 292 int USBHALHost::token_int_out(USBEndpoint* ep, const uint8_t* data, int size) {
beaglescout007 0:b5f79b4f741d 293 HC hc;
beaglescout007 0:b5f79b4f741d 294 USBDeviceConnected* dev = ep->getDevice();
beaglescout007 0:b5f79b4f741d 295 hc.Init(
beaglescout007 0:b5f79b4f741d 296 ep->getAddress(),
beaglescout007 0:b5f79b4f741d 297 dev->getAddress(),
beaglescout007 0:b5f79b4f741d 298 dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL,
beaglescout007 0:b5f79b4f741d 299 EP_TYPE_INTR, ep->getSize());
beaglescout007 0:b5f79b4f741d 300
beaglescout007 0:b5f79b4f741d 301 hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1);
beaglescout007 0:b5f79b4f741d 302
beaglescout007 0:b5f79b4f741d 303 hc.SubmitRequest((uint8_t*)data, size);
beaglescout007 0:b5f79b4f741d 304 while(hc.GetURBState() == URB_IDLE);
beaglescout007 0:b5f79b4f741d 305 if (hc.GetURBState() != URB_DONE) {
beaglescout007 0:b5f79b4f741d 306 return -1;
beaglescout007 0:b5f79b4f741d 307 }
beaglescout007 0:b5f79b4f741d 308 ep->toggleData01();
beaglescout007 0:b5f79b4f741d 309 return size;
beaglescout007 0:b5f79b4f741d 310 }
beaglescout007 0:b5f79b4f741d 311
beaglescout007 0:b5f79b4f741d 312 int USBHALHost::token_blk_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit) {
beaglescout007 0:b5f79b4f741d 313 HC hc;
beaglescout007 0:b5f79b4f741d 314 USBDeviceConnected* dev = ep->getDevice();
beaglescout007 0:b5f79b4f741d 315 hc.Init(
beaglescout007 0:b5f79b4f741d 316 ep->getAddress(), dev->getAddress(),
beaglescout007 0:b5f79b4f741d 317 HCD_SPEED_FULL, EP_TYPE_BULK, ep->getSize());
beaglescout007 0:b5f79b4f741d 318
beaglescout007 0:b5f79b4f741d 319 hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1);
beaglescout007 0:b5f79b4f741d 320
beaglescout007 0:b5f79b4f741d 321 int retry = 0;
beaglescout007 0:b5f79b4f741d 322 do {
beaglescout007 0:b5f79b4f741d 323 hc.SubmitRequest((uint8_t*)data, size);
beaglescout007 0:b5f79b4f741d 324 while(hc.GetURBState() == URB_IDLE);
beaglescout007 0:b5f79b4f741d 325
beaglescout007 0:b5f79b4f741d 326 switch(hc.GetURBState()) {
beaglescout007 0:b5f79b4f741d 327 case URB_DONE:
beaglescout007 0:b5f79b4f741d 328 switch(hc.GetState()) {
beaglescout007 0:b5f79b4f741d 329 case HC_XFRC: // ACK
beaglescout007 0:b5f79b4f741d 330 LastStatus = ep->getData01();
beaglescout007 0:b5f79b4f741d 331 ep->toggleData01();
beaglescout007 0:b5f79b4f741d 332 return size;
beaglescout007 0:b5f79b4f741d 333 default:
beaglescout007 0:b5f79b4f741d 334 break;
beaglescout007 0:b5f79b4f741d 335 }
beaglescout007 0:b5f79b4f741d 336 break;
beaglescout007 0:b5f79b4f741d 337 case URB_NOTREADY: // HC_NAK
beaglescout007 0:b5f79b4f741d 338 LastStatus = NAK;
beaglescout007 0:b5f79b4f741d 339 delay_ms(100 * retry);
beaglescout007 0:b5f79b4f741d 340 break;
beaglescout007 0:b5f79b4f741d 341 default:
beaglescout007 0:b5f79b4f741d 342 LastStatus = STALL;
beaglescout007 0:b5f79b4f741d 343 return -1;
beaglescout007 0:b5f79b4f741d 344 }
beaglescout007 0:b5f79b4f741d 345 } while(retry++ < retryLimit);
beaglescout007 0:b5f79b4f741d 346 return -1;
beaglescout007 0:b5f79b4f741d 347 }
beaglescout007 0:b5f79b4f741d 348
beaglescout007 0:b5f79b4f741d 349 int USBHALHost::token_iso_in(USBEndpoint* ep, uint8_t* data, int size) {
beaglescout007 0:b5f79b4f741d 350 HC* hc = ep->getHALData<HC*>();
beaglescout007 0:b5f79b4f741d 351 if (hc == NULL) {
beaglescout007 0:b5f79b4f741d 352 hc = new HC;
beaglescout007 0:b5f79b4f741d 353 ep->setHALData<HC*>(hc);
beaglescout007 0:b5f79b4f741d 354 USBDeviceConnected* dev = ep->getDevice();
beaglescout007 0:b5f79b4f741d 355 hc->Init(
beaglescout007 0:b5f79b4f741d 356 ep->getAddress(), dev->getAddress(),
beaglescout007 0:b5f79b4f741d 357 HCD_SPEED_FULL, EP_TYPE_ISOC, ep->getSize());
beaglescout007 0:b5f79b4f741d 358 }
beaglescout007 0:b5f79b4f741d 359 hc->SubmitRequest(data, size);
beaglescout007 0:b5f79b4f741d 360 while(hc->GetURBState() == URB_IDLE);
beaglescout007 0:b5f79b4f741d 361 return hc->GetXferCount();
beaglescout007 0:b5f79b4f741d 362 }
beaglescout007 0:b5f79b4f741d 363
beaglescout007 0:b5f79b4f741d 364 int USBHALHost::multi_token_in(USBEndpoint* ep, uint8_t* data, size_t total, bool block) {
beaglescout007 0:b5f79b4f741d 365 if (total == 0) {
beaglescout007 0:b5f79b4f741d 366 return token_in(ep);
beaglescout007 0:b5f79b4f741d 367 }
beaglescout007 0:b5f79b4f741d 368 int retryLimit = block ? 10 : 0;
beaglescout007 0:b5f79b4f741d 369 int read_len = 0;
beaglescout007 0:b5f79b4f741d 370 for(int n = 0; read_len < total; n++) {
beaglescout007 0:b5f79b4f741d 371 int size = std::min((int)total-read_len, ep->getSize());
beaglescout007 0:b5f79b4f741d 372 int result = token_in(ep, data+read_len, size, retryLimit);
beaglescout007 0:b5f79b4f741d 373 if (result < 0) {
beaglescout007 0:b5f79b4f741d 374 if (block) {
beaglescout007 0:b5f79b4f741d 375 return -1;
beaglescout007 0:b5f79b4f741d 376 }
beaglescout007 0:b5f79b4f741d 377 if (LastStatus == NAK) {
beaglescout007 0:b5f79b4f741d 378 if (n == 0) {
beaglescout007 0:b5f79b4f741d 379 return -1;
beaglescout007 0:b5f79b4f741d 380 }
beaglescout007 0:b5f79b4f741d 381 break;
beaglescout007 0:b5f79b4f741d 382 }
beaglescout007 0:b5f79b4f741d 383 return result;
beaglescout007 0:b5f79b4f741d 384 }
beaglescout007 0:b5f79b4f741d 385 read_len += result;
beaglescout007 0:b5f79b4f741d 386 if (result < ep->getSize()) {
beaglescout007 0:b5f79b4f741d 387 break;
beaglescout007 0:b5f79b4f741d 388 }
beaglescout007 0:b5f79b4f741d 389 }
beaglescout007 0:b5f79b4f741d 390 return read_len;
beaglescout007 0:b5f79b4f741d 391 }
beaglescout007 0:b5f79b4f741d 392
beaglescout007 0:b5f79b4f741d 393 int USBHALHost::multi_token_out(USBEndpoint* ep, const uint8_t* data, size_t total) {
beaglescout007 0:b5f79b4f741d 394 if (total == 0) {
beaglescout007 0:b5f79b4f741d 395 return token_out(ep);
beaglescout007 0:b5f79b4f741d 396 }
beaglescout007 0:b5f79b4f741d 397 int write_len = 0;
beaglescout007 0:b5f79b4f741d 398 for(int n = 0; write_len < total; n++) {
beaglescout007 0:b5f79b4f741d 399 int size = std::min((int)total-write_len, ep->getSize());
beaglescout007 0:b5f79b4f741d 400 int result = token_out(ep, data+write_len, size);
beaglescout007 0:b5f79b4f741d 401 if (result < 0) {
beaglescout007 0:b5f79b4f741d 402 if (LastStatus == NAK) {
beaglescout007 0:b5f79b4f741d 403 if (n == 0) {
beaglescout007 0:b5f79b4f741d 404 return -1;
beaglescout007 0:b5f79b4f741d 405 }
beaglescout007 0:b5f79b4f741d 406 break;
beaglescout007 0:b5f79b4f741d 407 }
beaglescout007 0:b5f79b4f741d 408 USB_DBG("token_out result=%d %02x", result, LastStatus);
beaglescout007 0:b5f79b4f741d 409 return result;
beaglescout007 0:b5f79b4f741d 410 }
beaglescout007 0:b5f79b4f741d 411 write_len += result;
beaglescout007 0:b5f79b4f741d 412 if (result < ep->getSize()) {
beaglescout007 0:b5f79b4f741d 413 break;
beaglescout007 0:b5f79b4f741d 414 }
beaglescout007 0:b5f79b4f741d 415 }
beaglescout007 0:b5f79b4f741d 416 return write_len;
beaglescout007 0:b5f79b4f741d 417 }
beaglescout007 0:b5f79b4f741d 418 void USBHALHost::multi_token_inNB(USBEndpoint* ep, uint8_t* data, int size) {
beaglescout007 0:b5f79b4f741d 419 USB_TRACE1(size);
beaglescout007 0:b5f79b4f741d 420 USB_TEST_ASSERT(ep->getState() != USB_TYPE_PROCESSING);
beaglescout007 0:b5f79b4f741d 421 ep->setBuffer(data, size);
beaglescout007 0:b5f79b4f741d 422 ep->setState(USB_TYPE_PROCESSING);
beaglescout007 0:b5f79b4f741d 423 }
beaglescout007 0:b5f79b4f741d 424
beaglescout007 0:b5f79b4f741d 425 USB_TYPE USBHALHost::multi_token_inNB_result(USBEndpoint* ep) {
beaglescout007 0:b5f79b4f741d 426 USB_TEST_ASSERT(ep->getState() == USB_TYPE_PROCESSING);
beaglescout007 0:b5f79b4f741d 427 uint8_t* buf = ep->getBufStart();
beaglescout007 0:b5f79b4f741d 428 int size = ep->getBufSize();
beaglescout007 0:b5f79b4f741d 429 int result = multi_token_in(ep, buf, size, false);
beaglescout007 0:b5f79b4f741d 430 USB_TRACE1(result);
beaglescout007 0:b5f79b4f741d 431 if (result < 0) {
beaglescout007 0:b5f79b4f741d 432 return USB_TYPE_PROCESSING;
beaglescout007 0:b5f79b4f741d 433 }
beaglescout007 0:b5f79b4f741d 434 ep->setLengthTransferred(result);
beaglescout007 0:b5f79b4f741d 435 ep->setState(USB_TYPE_IDLE);
beaglescout007 0:b5f79b4f741d 436 return USB_TYPE_OK;
beaglescout007 0:b5f79b4f741d 437
beaglescout007 0:b5f79b4f741d 438 }
beaglescout007 0:b5f79b4f741d 439
beaglescout007 0:b5f79b4f741d 440 void USBHALHost::setToggle(USBEndpoint* ep, uint8_t toggle) {
beaglescout007 0:b5f79b4f741d 441 USB_TEST_ASSERT(toggle == 1);
beaglescout007 0:b5f79b4f741d 442 ep->setData01(toggle == 0 ? DATA0 : DATA1);
beaglescout007 0:b5f79b4f741d 443 }
beaglescout007 0:b5f79b4f741d 444
beaglescout007 0:b5f79b4f741d 445 uint8_t HC::slot = 0x00;
beaglescout007 0:b5f79b4f741d 446
beaglescout007 0:b5f79b4f741d 447 HC::HC() {
beaglescout007 0:b5f79b4f741d 448 static const int start = 1;
beaglescout007 0:b5f79b4f741d 449 uint8_t mask = (1<<start);
beaglescout007 0:b5f79b4f741d 450 for(int i = start; i < 8; i++, mask <<= 1) {
beaglescout007 0:b5f79b4f741d 451 if (!(slot & mask)) {
beaglescout007 0:b5f79b4f741d 452 slot |= mask;
beaglescout007 0:b5f79b4f741d 453 _ch = i;
beaglescout007 0:b5f79b4f741d 454 return;
beaglescout007 0:b5f79b4f741d 455 }
beaglescout007 0:b5f79b4f741d 456 }
beaglescout007 0:b5f79b4f741d 457 _ch = 0; // ERROR!!!
beaglescout007 0:b5f79b4f741d 458 }
beaglescout007 0:b5f79b4f741d 459
beaglescout007 0:b5f79b4f741d 460 HC::HC(int ch) {
beaglescout007 0:b5f79b4f741d 461 _ch = ch;
beaglescout007 0:b5f79b4f741d 462 slot |= (1<<_ch);
beaglescout007 0:b5f79b4f741d 463 }
beaglescout007 0:b5f79b4f741d 464
beaglescout007 0:b5f79b4f741d 465 HC::~HC() {
beaglescout007 0:b5f79b4f741d 466 slot &= ~(1<<_ch);
beaglescout007 0:b5f79b4f741d 467 }
beaglescout007 0:b5f79b4f741d 468
beaglescout007 0:b5f79b4f741d 469 HAL_StatusTypeDef HC::Init(uint8_t epnum, uint8_t dev_address, uint8_t speed, uint8_t ep_type, uint16_t mps) {
beaglescout007 0:b5f79b4f741d 470 _ep_addr = epnum;
beaglescout007 0:b5f79b4f741d 471 _ep_type = ep_type;
beaglescout007 0:b5f79b4f741d 472 return HAL_HCD_HC_Init(&hhcd_USB_OTG_FS, _ch,
beaglescout007 0:b5f79b4f741d 473 epnum, dev_address, speed, ep_type, mps);
beaglescout007 0:b5f79b4f741d 474 }
beaglescout007 0:b5f79b4f741d 475
beaglescout007 0:b5f79b4f741d 476 HAL_StatusTypeDef HC::SubmitRequest(uint8_t* pbuff, uint16_t length, bool setup) {
beaglescout007 0:b5f79b4f741d 477 uint8_t direction = (_ep_addr & 0x80) ? DIR_IN : DIR_OUT;
beaglescout007 0:b5f79b4f741d 478 if (_ep_type == EP_TYPE_CTRL) {
beaglescout007 0:b5f79b4f741d 479 HCD_HCTypeDef* hc = &hhcd_USB_OTG_FS.hc[_ch];
beaglescout007 0:b5f79b4f741d 480 if (setup) {
beaglescout007 0:b5f79b4f741d 481 hc->data_pid = HC_PID_SETUP;
beaglescout007 0:b5f79b4f741d 482 hc->toggle_out = 0;
beaglescout007 0:b5f79b4f741d 483 } else {
beaglescout007 0:b5f79b4f741d 484 if (direction == DIR_IN) {
beaglescout007 0:b5f79b4f741d 485 if (hc->toggle_in == 0) {
beaglescout007 0:b5f79b4f741d 486 hc->data_pid = HC_PID_DATA0;
beaglescout007 0:b5f79b4f741d 487 } else {
beaglescout007 0:b5f79b4f741d 488 hc->data_pid = HC_PID_DATA1;
beaglescout007 0:b5f79b4f741d 489 }
beaglescout007 0:b5f79b4f741d 490 } else { // OUT
beaglescout007 0:b5f79b4f741d 491 if (hc->toggle_out == 0) {
beaglescout007 0:b5f79b4f741d 492 hc->data_pid = HC_PID_DATA0;
beaglescout007 0:b5f79b4f741d 493 } else {
beaglescout007 0:b5f79b4f741d 494 hc->data_pid = HC_PID_DATA1;
beaglescout007 0:b5f79b4f741d 495 }
beaglescout007 0:b5f79b4f741d 496 }
beaglescout007 0:b5f79b4f741d 497 }
beaglescout007 0:b5f79b4f741d 498 hc->xfer_buff = pbuff;
beaglescout007 0:b5f79b4f741d 499 hc->xfer_len = length;
beaglescout007 0:b5f79b4f741d 500 hc->urb_state = URB_IDLE;
beaglescout007 0:b5f79b4f741d 501 hc->xfer_count = 0;
beaglescout007 0:b5f79b4f741d 502 hc->ch_num = _ch;
beaglescout007 0:b5f79b4f741d 503 hc->state = HC_IDLE;
beaglescout007 0:b5f79b4f741d 504
beaglescout007 0:b5f79b4f741d 505 return USB_HC_StartXfer(hhcd_USB_OTG_FS.Instance, hc, 0);
beaglescout007 0:b5f79b4f741d 506 }
beaglescout007 0:b5f79b4f741d 507 return HAL_HCD_HC_SubmitRequest(&hhcd_USB_OTG_FS, _ch,
beaglescout007 0:b5f79b4f741d 508 direction, _ep_type, 0, pbuff, length, 0);
beaglescout007 0:b5f79b4f741d 509 }
beaglescout007 0:b5f79b4f741d 510
beaglescout007 0:b5f79b4f741d 511 HCD_URBStateTypeDef HC::GetURBState() {
beaglescout007 0:b5f79b4f741d 512 return HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, _ch);
beaglescout007 0:b5f79b4f741d 513 }
beaglescout007 0:b5f79b4f741d 514
beaglescout007 0:b5f79b4f741d 515 HCD_HCStateTypeDef HC::GetState() {
beaglescout007 0:b5f79b4f741d 516 return HAL_HCD_HC_GetState(&hhcd_USB_OTG_FS, _ch);
beaglescout007 0:b5f79b4f741d 517 }
beaglescout007 0:b5f79b4f741d 518
beaglescout007 0:b5f79b4f741d 519 uint32_t HC::GetXferCount() {
beaglescout007 0:b5f79b4f741d 520 return HAL_HCD_HC_GetXferCount(&hhcd_USB_OTG_FS, _ch);
beaglescout007 0:b5f79b4f741d 521 }
beaglescout007 0:b5f79b4f741d 522
beaglescout007 0:b5f79b4f741d 523 void HC::SetToggle(uint8_t toggle) {
beaglescout007 0:b5f79b4f741d 524 if (_ep_addr & 0x80) { // IN
beaglescout007 0:b5f79b4f741d 525 hhcd_USB_OTG_FS.hc[_ch].toggle_in = toggle;
beaglescout007 0:b5f79b4f741d 526 } else { // OUT
beaglescout007 0:b5f79b4f741d 527 hhcd_USB_OTG_FS.hc[_ch].toggle_out = toggle;
beaglescout007 0:b5f79b4f741d 528 }
beaglescout007 0:b5f79b4f741d 529 }
beaglescout007 0:b5f79b4f741d 530
beaglescout007 0:b5f79b4f741d 531 #endif
beaglescout007 0:b5f79b4f741d 532
beaglescout007 0:b5f79b4f741d 533
beaglescout007 0:b5f79b4f741d 534