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.
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 { 00055 host = NULL; 00056 init(); 00057 } 00058 00059 void USBHostHub::init() 00060 { 00061 dev_connected = false; 00062 dev = NULL; 00063 int_in = NULL; 00064 dev_connected = false; 00065 hub_intf = -1; 00066 hub_device_found = false; 00067 nb_port = 0; 00068 hub_characteristics = 0; 00069 00070 for (int i = 0; i < MAX_HUB_PORT; i++) { 00071 device_children[i] = NULL; 00072 } 00073 } 00074 00075 void USBHostHub::setHost(USBHost * host_) 00076 { 00077 host = host_; 00078 } 00079 00080 bool USBHostHub::connected() 00081 { 00082 return dev_connected; 00083 } 00084 00085 bool USBHostHub::connect(USBDeviceConnected * dev) 00086 { 00087 if (dev_connected) { 00088 return true; 00089 } 00090 00091 if(host->enumerate(dev, this)) { 00092 init(); 00093 return false; 00094 } 00095 00096 if (hub_device_found) { 00097 this->dev = dev; 00098 00099 int_in = dev->getEndpoint(hub_intf, INTERRUPT_ENDPOINT, IN); 00100 00101 if (!int_in) { 00102 init(); 00103 return false; 00104 } 00105 00106 USB_INFO("New HUB: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, hub_intf); 00107 dev->setName("Hub", hub_intf); 00108 host->registerDriver(dev, hub_intf, this, &USBHostHub::disconnect); 00109 00110 int_in->attach(this, &USBHostHub::rxHandler); 00111 00112 // get HUB descriptor 00113 host->controlRead( dev, 00114 USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS, 00115 GET_DESCRIPTOR, 00116 0x29 << 8, 0, buf, sizeof(HubDescriptor)); 00117 nb_port = buf[2]; 00118 hub_characteristics = buf[3]; 00119 00120 USB_DBG("Hub has %d port", nb_port); 00121 00122 for (uint8_t j = 1; j <= nb_port; j++) { 00123 setPortFeature(PORT_POWER_FEATURE, j); 00124 } 00125 wait_ms(buf[5]*2); 00126 00127 host->interruptRead(dev, int_in, buf, 1, false); 00128 dev_connected = true; 00129 return true; 00130 } 00131 00132 return false; 00133 } 00134 00135 void USBHostHub::disconnect() 00136 { 00137 init(); 00138 } 00139 00140 /*virtual*/ void USBHostHub::setVidPid(uint16_t vid, uint16_t pid) 00141 { 00142 // we don't check VID/PID for MSD driver 00143 } 00144 00145 /*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 00146 { 00147 if ((hub_intf == -1) && 00148 (intf_class == HUB_CLASS) && 00149 (intf_subclass == 0) && 00150 (intf_protocol == 0)) { 00151 hub_intf = intf_nb; 00152 return true; 00153 } 00154 return false; 00155 } 00156 00157 /*virtual*/ bool USBHostHub::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used 00158 { 00159 if (intf_nb == hub_intf) { 00160 if ((type == INTERRUPT_ENDPOINT) && (dir == IN)) { 00161 hub_device_found = true; 00162 return true; 00163 } 00164 } 00165 return false; 00166 } 00167 00168 void USBHostHub::deviceConnected(USBDeviceConnected * dev) 00169 { 00170 device_children[dev->getPort() - 1] = dev; 00171 } 00172 00173 void USBHostHub::deviceDisconnected(USBDeviceConnected * dev) 00174 { 00175 device_children[dev->getPort() - 1] = NULL; 00176 } 00177 00178 void USBHostHub::hubDisconnected() 00179 { 00180 for (uint8_t i = 0; i < MAX_HUB_PORT; i++) { 00181 if (device_children[i] != NULL) { 00182 host->freeDevice(device_children[i]); 00183 } 00184 } 00185 } 00186 00187 void USBHostHub::rxHandler() 00188 { 00189 uint32_t status; 00190 if (int_in) { 00191 if ((int_in->getLengthTransferred())&&(int_in->getState() == USB_TYPE_IDLE)) { 00192 for (int port = 1; port <= nb_port; port++) { 00193 status = getPortStatus(port); 00194 USB_DBG("[hub handler hub: %d] status port %d [hub: %p]: 0x%X", dev->getHub(), port, dev, status); 00195 00196 // if connection status has changed 00197 if (status & C_PORT_CONNECTION) { 00198 if (status & PORT_CONNECTION) { 00199 USB_DBG("[hub handler hub: %d - port: %d] new device connected", dev->getHub(), port); 00200 host->deviceConnected(dev->getHub() + 1, port, status & PORT_LOW_SPEED, this); 00201 } else { 00202 USB_DBG("[hub handler hub: %d - port: %d] device disconnected", dev->getHub(), port); 00203 host->deviceDisconnected(dev->getHub() + 1, port, this, 0); 00204 } 00205 00206 clearPortFeature(C_PORT_CONNECTION_FEATURE, port); 00207 } 00208 00209 if (status & C_PORT_RESET) { 00210 clearPortFeature(C_PORT_RESET_FEATURE, port); 00211 } 00212 00213 if (status & C_PORT_ENABLE) { 00214 clearPortFeature(C_PORT_ENABLE_FEATURE, port); 00215 } 00216 00217 if ((status & PORT_OVER_CURRENT)) { 00218 USB_ERR("OVER CURRENT DETECTED\r\n"); 00219 clearPortFeature(PORT_OVER_CURRENT, port); 00220 host->deviceDisconnected(dev->getHub() + 1, port, this, 0); 00221 } 00222 } 00223 } 00224 host->interruptRead(dev, int_in, buf, 1, false); 00225 } 00226 } 00227 00228 void USBHostHub::portReset(uint8_t port) 00229 { 00230 // reset port 00231 uint32_t status; 00232 USB_DBG("reset port %d on hub: %p [this: %p]", port, dev, this) 00233 setPortFeature(PORT_RESET_FEATURE, port); 00234 #if defined(TARGET_RZ_A1H) 00235 Thread::wait(50); // Reset release waiting for Hi-Speed check. 00236 #endif 00237 while(1) { 00238 status = getPortStatus(port); 00239 /* disconnection since reset request */ 00240 if (!(status & PORT_CONNECTION)) { 00241 break; 00242 } 00243 if (status & (PORT_ENABLE | PORT_RESET)) { 00244 break; 00245 } 00246 if (status & PORT_OVER_CURRENT) { 00247 USB_ERR("OVER CURRENT DETECTED\r\n"); 00248 clearPortFeature(PORT_OVER_CURRENT, port); 00249 host->deviceDisconnected(dev->getHub() + 1, port, this, 0); 00250 break; 00251 } 00252 Thread::wait(10); 00253 } 00254 } 00255 00256 void USBHostHub::setPortFeature(uint32_t feature, uint8_t port) 00257 { 00258 host->controlWrite( dev, 00259 USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE | USB_RECIPIENT_ENDPOINT, 00260 SET_FEATURE, 00261 feature, 00262 port, 00263 NULL, 00264 0); 00265 } 00266 00267 void USBHostHub::clearPortFeature(uint32_t feature, uint8_t port) 00268 { 00269 host->controlWrite( dev, 00270 USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE | USB_RECIPIENT_ENDPOINT, 00271 CLEAR_FEATURE, 00272 feature, 00273 port, 00274 NULL, 00275 0); 00276 } 00277 00278 uint32_t USBHostHub::getPortStatus(uint8_t port) 00279 { 00280 uint32_t st; 00281 host->controlRead( dev, 00282 USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE | USB_RECIPIENT_ENDPOINT, 00283 GET_STATUS, 00284 0, 00285 port, 00286 (uint8_t *)&st, 00287 4); 00288 return st; 00289 } 00290 00291 #endif
Generated on Tue Jul 12 2022 14:25:17 by
