Pierre Provent / USBHost

Dependents:   TEST_USB_Nucleo_F429ZI Essais_USB_Nucleo_F429ZI SID_V3_Nucleo_F429ZI SID_V4_Nucleo_F429ZI_copy

Committer:
pierreprovent
Date:
Fri Sep 25 10:17:49 2020 +0000
Revision:
0:77ca32e8e04e
Programme acquisition en enregistrement sur clef USB carte Nucleo F429ZI cours ELE118 Cnam

Who changed what in which revision?

UserRevisionLine numberNew contents of line
pierreprovent 0:77ca32e8e04e 1 /* mbed USBHost Library
pierreprovent 0:77ca32e8e04e 2 * Copyright (c) 2006-2013 ARM Limited
pierreprovent 0:77ca32e8e04e 3 *
pierreprovent 0:77ca32e8e04e 4 * Licensed under the Apache License, Version 2.0 (the "License");
pierreprovent 0:77ca32e8e04e 5 * you may not use this file except in compliance with the License.
pierreprovent 0:77ca32e8e04e 6 * You may obtain a copy of the License at
pierreprovent 0:77ca32e8e04e 7 *
pierreprovent 0:77ca32e8e04e 8 * http://www.apache.org/licenses/LICENSE-2.0
pierreprovent 0:77ca32e8e04e 9 *
pierreprovent 0:77ca32e8e04e 10 * Unless required by applicable law or agreed to in writing, software
pierreprovent 0:77ca32e8e04e 11 * distributed under the License is distributed on an "AS IS" BASIS,
pierreprovent 0:77ca32e8e04e 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
pierreprovent 0:77ca32e8e04e 13 * See the License for the specific language governing permissions and
pierreprovent 0:77ca32e8e04e 14 * limitations under the License.
pierreprovent 0:77ca32e8e04e 15 */
pierreprovent 0:77ca32e8e04e 16
pierreprovent 0:77ca32e8e04e 17 #include "USBHostHub.h"
pierreprovent 0:77ca32e8e04e 18
pierreprovent 0:77ca32e8e04e 19 #if MAX_HUB_NB
pierreprovent 0:77ca32e8e04e 20
pierreprovent 0:77ca32e8e04e 21 #include "USBHost.h"
pierreprovent 0:77ca32e8e04e 22 #include "dbg.h"
pierreprovent 0:77ca32e8e04e 23
pierreprovent 0:77ca32e8e04e 24 #define GET_STATUS 0x00
pierreprovent 0:77ca32e8e04e 25 #define CLEAR_FEATURE 0x01
pierreprovent 0:77ca32e8e04e 26 #define GET_STATE 0x02
pierreprovent 0:77ca32e8e04e 27 #define SET_FEATURE 0x03
pierreprovent 0:77ca32e8e04e 28 #define GET_DESCRIPTOR 0x06
pierreprovent 0:77ca32e8e04e 29
pierreprovent 0:77ca32e8e04e 30 #define PORT_CONNECTION_FEATURE (0x00)
pierreprovent 0:77ca32e8e04e 31 #define PORT_ENABLE_FEATURE (0x01)
pierreprovent 0:77ca32e8e04e 32 #define PORT_RESET_FEATURE (0x04)
pierreprovent 0:77ca32e8e04e 33 #define PORT_POWER_FEATURE (0x08)
pierreprovent 0:77ca32e8e04e 34
pierreprovent 0:77ca32e8e04e 35 #define C_PORT_CONNECTION_FEATURE (16)
pierreprovent 0:77ca32e8e04e 36 #define C_PORT_ENABLE_FEATURE (17)
pierreprovent 0:77ca32e8e04e 37 #define C_PORT_RESET_FEATURE (20)
pierreprovent 0:77ca32e8e04e 38
pierreprovent 0:77ca32e8e04e 39 #define PORT_CONNECTION (1 << 0)
pierreprovent 0:77ca32e8e04e 40 #define PORT_ENABLE (1 << 1)
pierreprovent 0:77ca32e8e04e 41 #define PORT_SUSPEND (1 << 2)
pierreprovent 0:77ca32e8e04e 42 #define PORT_OVER_CURRENT (1 << 3)
pierreprovent 0:77ca32e8e04e 43 #define PORT_RESET (1 << 4)
pierreprovent 0:77ca32e8e04e 44 #define PORT_POWER (1 << 8)
pierreprovent 0:77ca32e8e04e 45 #define PORT_LOW_SPEED (1 << 9)
pierreprovent 0:77ca32e8e04e 46
pierreprovent 0:77ca32e8e04e 47 #define C_PORT_CONNECTION (1 << 16)
pierreprovent 0:77ca32e8e04e 48 #define C_PORT_ENABLE (1 << 17)
pierreprovent 0:77ca32e8e04e 49 #define C_PORT_SUSPEND (1 << 18)
pierreprovent 0:77ca32e8e04e 50 #define C_PORT_OVER_CURRENT (1 << 19)
pierreprovent 0:77ca32e8e04e 51 #define C_PORT_RESET (1 << 20)
pierreprovent 0:77ca32e8e04e 52
pierreprovent 0:77ca32e8e04e 53 USBHostHub::USBHostHub()
pierreprovent 0:77ca32e8e04e 54 {
pierreprovent 0:77ca32e8e04e 55 host = NULL;
pierreprovent 0:77ca32e8e04e 56 init();
pierreprovent 0:77ca32e8e04e 57 }
pierreprovent 0:77ca32e8e04e 58
pierreprovent 0:77ca32e8e04e 59 void USBHostHub::init()
pierreprovent 0:77ca32e8e04e 60 {
pierreprovent 0:77ca32e8e04e 61 dev_connected = false;
pierreprovent 0:77ca32e8e04e 62 dev = NULL;
pierreprovent 0:77ca32e8e04e 63 int_in = NULL;
pierreprovent 0:77ca32e8e04e 64 dev_connected = false;
pierreprovent 0:77ca32e8e04e 65 hub_intf = -1;
pierreprovent 0:77ca32e8e04e 66 hub_device_found = false;
pierreprovent 0:77ca32e8e04e 67 nb_port = 0;
pierreprovent 0:77ca32e8e04e 68 hub_characteristics = 0;
pierreprovent 0:77ca32e8e04e 69
pierreprovent 0:77ca32e8e04e 70 for (int i = 0; i < MAX_HUB_PORT; i++) {
pierreprovent 0:77ca32e8e04e 71 device_children[i] = NULL;
pierreprovent 0:77ca32e8e04e 72 }
pierreprovent 0:77ca32e8e04e 73 }
pierreprovent 0:77ca32e8e04e 74
pierreprovent 0:77ca32e8e04e 75 void USBHostHub::setHost(USBHost * host_)
pierreprovent 0:77ca32e8e04e 76 {
pierreprovent 0:77ca32e8e04e 77 host = host_;
pierreprovent 0:77ca32e8e04e 78 }
pierreprovent 0:77ca32e8e04e 79
pierreprovent 0:77ca32e8e04e 80 bool USBHostHub::connected()
pierreprovent 0:77ca32e8e04e 81 {
pierreprovent 0:77ca32e8e04e 82 return dev_connected;
pierreprovent 0:77ca32e8e04e 83 }
pierreprovent 0:77ca32e8e04e 84
pierreprovent 0:77ca32e8e04e 85 bool USBHostHub::connect(USBDeviceConnected * dev)
pierreprovent 0:77ca32e8e04e 86 {
pierreprovent 0:77ca32e8e04e 87 if (dev_connected) {
pierreprovent 0:77ca32e8e04e 88 return true;
pierreprovent 0:77ca32e8e04e 89 }
pierreprovent 0:77ca32e8e04e 90
pierreprovent 0:77ca32e8e04e 91 if(host->enumerate(dev, this)) {
pierreprovent 0:77ca32e8e04e 92 init();
pierreprovent 0:77ca32e8e04e 93 return false;
pierreprovent 0:77ca32e8e04e 94 }
pierreprovent 0:77ca32e8e04e 95
pierreprovent 0:77ca32e8e04e 96 if (hub_device_found) {
pierreprovent 0:77ca32e8e04e 97 this->dev = dev;
pierreprovent 0:77ca32e8e04e 98
pierreprovent 0:77ca32e8e04e 99 int_in = dev->getEndpoint(hub_intf, INTERRUPT_ENDPOINT, IN);
pierreprovent 0:77ca32e8e04e 100
pierreprovent 0:77ca32e8e04e 101 if (!int_in) {
pierreprovent 0:77ca32e8e04e 102 init();
pierreprovent 0:77ca32e8e04e 103 return false;
pierreprovent 0:77ca32e8e04e 104 }
pierreprovent 0:77ca32e8e04e 105
pierreprovent 0:77ca32e8e04e 106 USB_INFO("New HUB: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, hub_intf);
pierreprovent 0:77ca32e8e04e 107 dev->setName("Hub", hub_intf);
pierreprovent 0:77ca32e8e04e 108 host->registerDriver(dev, hub_intf, this, &USBHostHub::disconnect);
pierreprovent 0:77ca32e8e04e 109
pierreprovent 0:77ca32e8e04e 110 int_in->attach(this, &USBHostHub::rxHandler);
pierreprovent 0:77ca32e8e04e 111
pierreprovent 0:77ca32e8e04e 112 // get HUB descriptor
pierreprovent 0:77ca32e8e04e 113 host->controlRead( dev,
pierreprovent 0:77ca32e8e04e 114 USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS,
pierreprovent 0:77ca32e8e04e 115 GET_DESCRIPTOR,
pierreprovent 0:77ca32e8e04e 116 0x29 << 8, 0, buf, sizeof(HubDescriptor));
pierreprovent 0:77ca32e8e04e 117 nb_port = buf[2];
pierreprovent 0:77ca32e8e04e 118 hub_characteristics = buf[3];
pierreprovent 0:77ca32e8e04e 119
pierreprovent 0:77ca32e8e04e 120 USB_DBG("Hub has %d port", nb_port);
pierreprovent 0:77ca32e8e04e 121
pierreprovent 0:77ca32e8e04e 122 for (uint8_t j = 1; j <= nb_port; j++) {
pierreprovent 0:77ca32e8e04e 123 setPortFeature(PORT_POWER_FEATURE, j);
pierreprovent 0:77ca32e8e04e 124 }
pierreprovent 0:77ca32e8e04e 125 wait_ms(buf[5]*2);
pierreprovent 0:77ca32e8e04e 126
pierreprovent 0:77ca32e8e04e 127 host->interruptRead(dev, int_in, buf, 1, false);
pierreprovent 0:77ca32e8e04e 128 dev_connected = true;
pierreprovent 0:77ca32e8e04e 129 return true;
pierreprovent 0:77ca32e8e04e 130 }
pierreprovent 0:77ca32e8e04e 131
pierreprovent 0:77ca32e8e04e 132 return false;
pierreprovent 0:77ca32e8e04e 133 }
pierreprovent 0:77ca32e8e04e 134
pierreprovent 0:77ca32e8e04e 135 void USBHostHub::disconnect()
pierreprovent 0:77ca32e8e04e 136 {
pierreprovent 0:77ca32e8e04e 137 init();
pierreprovent 0:77ca32e8e04e 138 }
pierreprovent 0:77ca32e8e04e 139
pierreprovent 0:77ca32e8e04e 140 /*virtual*/ void USBHostHub::setVidPid(uint16_t vid, uint16_t pid)
pierreprovent 0:77ca32e8e04e 141 {
pierreprovent 0:77ca32e8e04e 142 // we don't check VID/PID for MSD driver
pierreprovent 0:77ca32e8e04e 143 }
pierreprovent 0:77ca32e8e04e 144
pierreprovent 0:77ca32e8e04e 145 /*virtual*/ bool USBHostHub::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
pierreprovent 0:77ca32e8e04e 146 {
pierreprovent 0:77ca32e8e04e 147 if ((hub_intf == -1) &&
pierreprovent 0:77ca32e8e04e 148 (intf_class == HUB_CLASS) &&
pierreprovent 0:77ca32e8e04e 149 (intf_subclass == 0) &&
pierreprovent 0:77ca32e8e04e 150 (intf_protocol == 0)) {
pierreprovent 0:77ca32e8e04e 151 hub_intf = intf_nb;
pierreprovent 0:77ca32e8e04e 152 return true;
pierreprovent 0:77ca32e8e04e 153 }
pierreprovent 0:77ca32e8e04e 154 return false;
pierreprovent 0:77ca32e8e04e 155 }
pierreprovent 0:77ca32e8e04e 156
pierreprovent 0:77ca32e8e04e 157 /*virtual*/ bool USBHostHub::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
pierreprovent 0:77ca32e8e04e 158 {
pierreprovent 0:77ca32e8e04e 159 if (intf_nb == hub_intf) {
pierreprovent 0:77ca32e8e04e 160 if ((type == INTERRUPT_ENDPOINT) && (dir == IN)) {
pierreprovent 0:77ca32e8e04e 161 hub_device_found = true;
pierreprovent 0:77ca32e8e04e 162 return true;
pierreprovent 0:77ca32e8e04e 163 }
pierreprovent 0:77ca32e8e04e 164 }
pierreprovent 0:77ca32e8e04e 165 return false;
pierreprovent 0:77ca32e8e04e 166 }
pierreprovent 0:77ca32e8e04e 167
pierreprovent 0:77ca32e8e04e 168 void USBHostHub::deviceConnected(USBDeviceConnected * dev)
pierreprovent 0:77ca32e8e04e 169 {
pierreprovent 0:77ca32e8e04e 170 device_children[dev->getPort() - 1] = dev;
pierreprovent 0:77ca32e8e04e 171 }
pierreprovent 0:77ca32e8e04e 172
pierreprovent 0:77ca32e8e04e 173 void USBHostHub::deviceDisconnected(USBDeviceConnected * dev)
pierreprovent 0:77ca32e8e04e 174 {
pierreprovent 0:77ca32e8e04e 175 device_children[dev->getPort() - 1] = NULL;
pierreprovent 0:77ca32e8e04e 176 }
pierreprovent 0:77ca32e8e04e 177
pierreprovent 0:77ca32e8e04e 178 void USBHostHub::hubDisconnected()
pierreprovent 0:77ca32e8e04e 179 {
pierreprovent 0:77ca32e8e04e 180 for (uint8_t i = 0; i < MAX_HUB_PORT; i++) {
pierreprovent 0:77ca32e8e04e 181 if (device_children[i] != NULL) {
pierreprovent 0:77ca32e8e04e 182 host->freeDevice(device_children[i]);
pierreprovent 0:77ca32e8e04e 183 }
pierreprovent 0:77ca32e8e04e 184 }
pierreprovent 0:77ca32e8e04e 185 }
pierreprovent 0:77ca32e8e04e 186
pierreprovent 0:77ca32e8e04e 187 void USBHostHub::rxHandler()
pierreprovent 0:77ca32e8e04e 188 {
pierreprovent 0:77ca32e8e04e 189 uint32_t status;
pierreprovent 0:77ca32e8e04e 190 if (int_in) {
pierreprovent 0:77ca32e8e04e 191 if ((int_in->getLengthTransferred())&&(int_in->getState() == USB_TYPE_IDLE)) {
pierreprovent 0:77ca32e8e04e 192 for (int port = 1; port <= nb_port; port++) {
pierreprovent 0:77ca32e8e04e 193 status = getPortStatus(port);
pierreprovent 0:77ca32e8e04e 194 USB_DBG("[hub handler hub: %d] status port %d [hub: %p]: 0x%X", dev->getHub(), port, dev, status);
pierreprovent 0:77ca32e8e04e 195
pierreprovent 0:77ca32e8e04e 196 // if connection status has changed
pierreprovent 0:77ca32e8e04e 197 if (status & C_PORT_CONNECTION) {
pierreprovent 0:77ca32e8e04e 198 if (status & PORT_CONNECTION) {
pierreprovent 0:77ca32e8e04e 199 USB_DBG("[hub handler hub: %d - port: %d] new device connected", dev->getHub(), port);
pierreprovent 0:77ca32e8e04e 200 host->deviceConnected(dev->getHub() + 1, port, status & PORT_LOW_SPEED, this);
pierreprovent 0:77ca32e8e04e 201 } else {
pierreprovent 0:77ca32e8e04e 202 USB_DBG("[hub handler hub: %d - port: %d] device disconnected", dev->getHub(), port);
pierreprovent 0:77ca32e8e04e 203 host->deviceDisconnected(dev->getHub() + 1, port, this, 0);
pierreprovent 0:77ca32e8e04e 204 }
pierreprovent 0:77ca32e8e04e 205
pierreprovent 0:77ca32e8e04e 206 clearPortFeature(C_PORT_CONNECTION_FEATURE, port);
pierreprovent 0:77ca32e8e04e 207 }
pierreprovent 0:77ca32e8e04e 208
pierreprovent 0:77ca32e8e04e 209 if (status & C_PORT_RESET) {
pierreprovent 0:77ca32e8e04e 210 clearPortFeature(C_PORT_RESET_FEATURE, port);
pierreprovent 0:77ca32e8e04e 211 }
pierreprovent 0:77ca32e8e04e 212
pierreprovent 0:77ca32e8e04e 213 if (status & C_PORT_ENABLE) {
pierreprovent 0:77ca32e8e04e 214 clearPortFeature(C_PORT_ENABLE_FEATURE, port);
pierreprovent 0:77ca32e8e04e 215 }
pierreprovent 0:77ca32e8e04e 216
pierreprovent 0:77ca32e8e04e 217 if ((status & PORT_OVER_CURRENT)) {
pierreprovent 0:77ca32e8e04e 218 USB_ERR("OVER CURRENT DETECTED\r\n");
pierreprovent 0:77ca32e8e04e 219 clearPortFeature(PORT_OVER_CURRENT, port);
pierreprovent 0:77ca32e8e04e 220 host->deviceDisconnected(dev->getHub() + 1, port, this, 0);
pierreprovent 0:77ca32e8e04e 221 }
pierreprovent 0:77ca32e8e04e 222 }
pierreprovent 0:77ca32e8e04e 223 }
pierreprovent 0:77ca32e8e04e 224 host->interruptRead(dev, int_in, buf, 1, false);
pierreprovent 0:77ca32e8e04e 225 }
pierreprovent 0:77ca32e8e04e 226 }
pierreprovent 0:77ca32e8e04e 227
pierreprovent 0:77ca32e8e04e 228 void USBHostHub::portReset(uint8_t port)
pierreprovent 0:77ca32e8e04e 229 {
pierreprovent 0:77ca32e8e04e 230 // reset port
pierreprovent 0:77ca32e8e04e 231 uint32_t status;
pierreprovent 0:77ca32e8e04e 232 USB_DBG("reset port %d on hub: %p [this: %p]", port, dev, this)
pierreprovent 0:77ca32e8e04e 233 setPortFeature(PORT_RESET_FEATURE, port);
pierreprovent 0:77ca32e8e04e 234 #if defined(TARGET_RZ_A1H)
pierreprovent 0:77ca32e8e04e 235 Thread::wait(50); // Reset release waiting for Hi-Speed check.
pierreprovent 0:77ca32e8e04e 236 #endif
pierreprovent 0:77ca32e8e04e 237 while(1) {
pierreprovent 0:77ca32e8e04e 238 status = getPortStatus(port);
pierreprovent 0:77ca32e8e04e 239 /* disconnection since reset request */
pierreprovent 0:77ca32e8e04e 240 if (!(status & PORT_CONNECTION)) {
pierreprovent 0:77ca32e8e04e 241 break;
pierreprovent 0:77ca32e8e04e 242 }
pierreprovent 0:77ca32e8e04e 243 if (status & (PORT_ENABLE | PORT_RESET)) {
pierreprovent 0:77ca32e8e04e 244 break;
pierreprovent 0:77ca32e8e04e 245 }
pierreprovent 0:77ca32e8e04e 246 if (status & PORT_OVER_CURRENT) {
pierreprovent 0:77ca32e8e04e 247 USB_ERR("OVER CURRENT DETECTED\r\n");
pierreprovent 0:77ca32e8e04e 248 clearPortFeature(PORT_OVER_CURRENT, port);
pierreprovent 0:77ca32e8e04e 249 host->deviceDisconnected(dev->getHub() + 1, port, this, 0);
pierreprovent 0:77ca32e8e04e 250 break;
pierreprovent 0:77ca32e8e04e 251 }
pierreprovent 0:77ca32e8e04e 252 Thread::wait(10);
pierreprovent 0:77ca32e8e04e 253 }
pierreprovent 0:77ca32e8e04e 254 }
pierreprovent 0:77ca32e8e04e 255
pierreprovent 0:77ca32e8e04e 256 void USBHostHub::setPortFeature(uint32_t feature, uint8_t port)
pierreprovent 0:77ca32e8e04e 257 {
pierreprovent 0:77ca32e8e04e 258 host->controlWrite( dev,
pierreprovent 0:77ca32e8e04e 259 USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE | USB_RECIPIENT_ENDPOINT,
pierreprovent 0:77ca32e8e04e 260 SET_FEATURE,
pierreprovent 0:77ca32e8e04e 261 feature,
pierreprovent 0:77ca32e8e04e 262 port,
pierreprovent 0:77ca32e8e04e 263 NULL,
pierreprovent 0:77ca32e8e04e 264 0);
pierreprovent 0:77ca32e8e04e 265 }
pierreprovent 0:77ca32e8e04e 266
pierreprovent 0:77ca32e8e04e 267 void USBHostHub::clearPortFeature(uint32_t feature, uint8_t port)
pierreprovent 0:77ca32e8e04e 268 {
pierreprovent 0:77ca32e8e04e 269 host->controlWrite( dev,
pierreprovent 0:77ca32e8e04e 270 USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE | USB_RECIPIENT_ENDPOINT,
pierreprovent 0:77ca32e8e04e 271 CLEAR_FEATURE,
pierreprovent 0:77ca32e8e04e 272 feature,
pierreprovent 0:77ca32e8e04e 273 port,
pierreprovent 0:77ca32e8e04e 274 NULL,
pierreprovent 0:77ca32e8e04e 275 0);
pierreprovent 0:77ca32e8e04e 276 }
pierreprovent 0:77ca32e8e04e 277
pierreprovent 0:77ca32e8e04e 278 uint32_t USBHostHub::getPortStatus(uint8_t port)
pierreprovent 0:77ca32e8e04e 279 {
pierreprovent 0:77ca32e8e04e 280 uint32_t st;
pierreprovent 0:77ca32e8e04e 281 host->controlRead( dev,
pierreprovent 0:77ca32e8e04e 282 USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE | USB_RECIPIENT_ENDPOINT,
pierreprovent 0:77ca32e8e04e 283 GET_STATUS,
pierreprovent 0:77ca32e8e04e 284 0,
pierreprovent 0:77ca32e8e04e 285 port,
pierreprovent 0:77ca32e8e04e 286 (uint8_t *)&st,
pierreprovent 0:77ca32e8e04e 287 4);
pierreprovent 0:77ca32e8e04e 288 return st;
pierreprovent 0:77ca32e8e04e 289 }
pierreprovent 0:77ca32e8e04e 290
pierreprovent 0:77ca32e8e04e 291 #endif