Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of USBHost by
USBHostHub.cpp
00001 /* mbed USBHost Library 00002 * Copyright (c) 2006-2013 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include "USBHostHub.h" 00018 00019 #if MAX_HUB_NB 00020 00021 #include "USBHost.h" 00022 #include "dbg.h" 00023 00024 #define GET_STATUS 0x00 00025 #define CLEAR_FEATURE 0x01 00026 #define GET_STATE 0x02 00027 #define SET_FEATURE 0x03 00028 #define GET_DESCRIPTOR 0x06 00029 00030 #define PORT_CONNECTION_FEATURE (0x00) 00031 #define PORT_ENABLE_FEATURE (0x01) 00032 #define PORT_RESET_FEATURE (0x04) 00033 #define PORT_POWER_FEATURE (0x08) 00034 00035 #define C_PORT_CONNECTION_FEATURE (16) 00036 #define C_PORT_ENABLE_FEATURE (17) 00037 #define C_PORT_RESET_FEATURE (20) 00038 00039 #define PORT_CONNECTION (1 << 0) 00040 #define PORT_ENABLE (1 << 1) 00041 #define PORT_SUSPEND (1 << 2) 00042 #define PORT_OVER_CURRENT (1 << 3) 00043 #define PORT_RESET (1 << 4) 00044 #define PORT_POWER (1 << 8) 00045 #define PORT_LOW_SPEED (1 << 9) 00046 00047 #define C_PORT_CONNECTION (1 << 16) 00048 #define C_PORT_ENABLE (1 << 17) 00049 #define C_PORT_SUSPEND (1 << 18) 00050 #define C_PORT_OVER_CURRENT (1 << 19) 00051 #define C_PORT_RESET (1 << 20) 00052 00053 USBHostHub::USBHostHub() { 00054 host = NULL; 00055 init(); 00056 } 00057 00058 void USBHostHub::init() { 00059 dev_connected = false; 00060 dev = NULL; 00061 int_in = NULL; 00062 dev_connected = false; 00063 hub_intf = -1; 00064 hub_device_found = false; 00065 nb_port = 0; 00066 hub_characteristics = 0; 00067 00068 for (int i = 0; i < MAX_HUB_PORT; i++) { 00069 device_children[i] = NULL; 00070 } 00071 } 00072 00073 void USBHostHub::setHost(USBHost * host_) { 00074 host = host_; 00075 } 00076 00077 bool USBHostHub::connected() 00078 { 00079 return dev_connected; 00080 } 00081 00082 bool USBHostHub::connect(USBDeviceConnected * dev) 00083 { 00084 if (dev_connected) { 00085 return true; 00086 } 00087 00088 if(host->enumerate(dev, this)) { 00089 init(); 00090 return false; 00091 } 00092 00093 if (hub_device_found) { 00094 this->dev = dev; 00095 00096 int_in = dev->getEndpoint(hub_intf, INTERRUPT_ENDPOINT, IN); 00097 00098 if (!int_in) { 00099 init(); 00100 return false; 00101 } 00102 00103 USB_INFO("New HUB: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, hub_intf); 00104 dev->setName("Hub", hub_intf); 00105 host->registerDriver(dev, hub_intf, this, &USBHostHub::disconnect); 00106 00107 int_in->attach(this, &USBHostHub::rxHandler); 00108 00109 // get HUB descriptor 00110 host->controlRead( dev, 00111 USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS, 00112 GET_DESCRIPTOR, 00113 0x29 << 8, 0, buf, sizeof(HubDescriptor)); 00114 nb_port = buf[2]; 00115 hub_characteristics = buf[3]; 00116 00117 USB_DBG("Hub has %d port", nb_port); 00118 00119 for (uint8_t j = 1; j <= nb_port; j++) { 00120 setPortFeature(PORT_POWER_FEATURE, j); 00121 } 00122 wait_ms(buf[5]*2); 00123 00124 host->interruptRead(dev, int_in, buf, 1, false); 00125 dev_connected = true; 00126 return true; 00127 } 00128 00129 return false; 00130 } 00131 00132 void USBHostHub::disconnect() { 00133 init(); 00134 } 00135 00136 /*virtual*/ void USBHostHub::setVidPid(uint16_t vid, uint16_t pid) 00137 { 00138 // we don't check VID/PID for MSD driver 00139 } 00140 00141 /*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 00142 { 00143 if ((hub_intf == -1) && 00144 (intf_class == HUB_CLASS) && 00145 (intf_subclass == 0) && 00146 (intf_protocol == 0)) { 00147 hub_intf = intf_nb; 00148 return true; 00149 } 00150 return false; 00151 } 00152 00153 /*virtual*/ bool USBHostHub::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used 00154 { 00155 if (intf_nb == hub_intf) { 00156 if ((type == INTERRUPT_ENDPOINT) && (dir == IN)) { 00157 hub_device_found = true; 00158 return true; 00159 } 00160 } 00161 return false; 00162 } 00163 00164 void USBHostHub::deviceConnected(USBDeviceConnected * dev) { 00165 device_children[dev->getPort() - 1] = dev; 00166 } 00167 00168 void USBHostHub::deviceDisconnected(USBDeviceConnected * dev) { 00169 device_children[dev->getPort() - 1] = NULL; 00170 } 00171 00172 void USBHostHub::hubDisconnected() { 00173 for (uint8_t i = 0; i < MAX_HUB_PORT; i++) { 00174 if (device_children[i] != NULL) { 00175 host->freeDevice(device_children[i]); 00176 } 00177 } 00178 } 00179 00180 void USBHostHub::rxHandler() { 00181 uint32_t status; 00182 if (int_in) { 00183 if (int_in->getState() == USB_TYPE_IDLE) { 00184 for (int port = 1; port <= nb_port; port++) { 00185 status = getPortStatus(port); 00186 USB_DBG("[hub handler hub: %d] status port %d [hub: %p]: 0x%X", dev->getHub(), port, dev, status); 00187 00188 // if connection status has changed 00189 if (status & C_PORT_CONNECTION) { 00190 if (status & PORT_CONNECTION) { 00191 USB_DBG("[hub handler hub: %d - port: %d] new device connected", dev->getHub(), port); 00192 host->deviceConnected(dev->getHub() + 1, port, status & PORT_LOW_SPEED, this); 00193 } else { 00194 USB_DBG("[hub handler hub: %d - port: %d] device disconnected", dev->getHub(), port); 00195 host->deviceDisconnected(dev->getHub() + 1, port, this, NULL); 00196 } 00197 00198 clearPortFeature(C_PORT_CONNECTION_FEATURE, port); 00199 } 00200 00201 if (status & C_PORT_RESET) { 00202 clearPortFeature(C_PORT_RESET_FEATURE, port); 00203 } 00204 00205 if (status & C_PORT_ENABLE) { 00206 clearPortFeature(C_PORT_ENABLE_FEATURE, port); 00207 } 00208 00209 if ((status & PORT_OVER_CURRENT)) { 00210 USB_ERR("OVER CURRENT DETECTED\r\n"); 00211 clearPortFeature(PORT_OVER_CURRENT, port); 00212 host->deviceDisconnected(dev->getHub() + 1, port, this, NULL); 00213 } 00214 } 00215 } 00216 host->interruptRead(dev, int_in, buf, 1, false); 00217 } 00218 } 00219 00220 void USBHostHub::portReset(uint8_t port) { 00221 // reset port 00222 uint32_t status; 00223 USB_DBG("reset port %d on hub: %p [this: %p]", port, dev, this) 00224 setPortFeature(PORT_RESET_FEATURE, port); 00225 while(1) { 00226 status = getPortStatus(port); 00227 if (status & (PORT_ENABLE | PORT_RESET)) 00228 break; 00229 if (status & PORT_OVER_CURRENT) { 00230 USB_ERR("OVER CURRENT DETECTED\r\n"); 00231 clearPortFeature(PORT_OVER_CURRENT, port); 00232 host->deviceDisconnected(dev->getHub() + 1, port, this, NULL); 00233 break; 00234 } 00235 Thread::wait(10); 00236 } 00237 } 00238 00239 void USBHostHub::setPortFeature(uint32_t feature, uint8_t port) { 00240 host->controlWrite( dev, 00241 USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE | USB_RECIPIENT_ENDPOINT, 00242 SET_FEATURE, 00243 feature, 00244 port, 00245 NULL, 00246 0); 00247 } 00248 00249 void USBHostHub::clearPortFeature(uint32_t feature, uint8_t port) { 00250 host->controlWrite( dev, 00251 USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE | USB_RECIPIENT_ENDPOINT, 00252 CLEAR_FEATURE, 00253 feature, 00254 port, 00255 NULL, 00256 0); 00257 } 00258 00259 uint32_t USBHostHub::getPortStatus(uint8_t port) { 00260 uint32_t st; 00261 host->controlRead( dev, 00262 USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE | USB_RECIPIENT_ENDPOINT, 00263 GET_STATUS, 00264 0, 00265 port, 00266 (uint8_t *)&st, 00267 4); 00268 return st; 00269 } 00270 00271 #endif
Generated on Sat Jul 16 2022 04:39:31 by
