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 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, 0); 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, 0); 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 #if defined(TARGET_RZ_A1H) 00226 Thread::wait(50); // Reset release waiting for Hi-Speed check. 00227 #endif 00228 while(1) { 00229 status = getPortStatus(port); 00230 if (status & (PORT_ENABLE | PORT_RESET)) 00231 break; 00232 if (status & PORT_OVER_CURRENT) { 00233 USB_ERR("OVER CURRENT DETECTED\r\n"); 00234 clearPortFeature(PORT_OVER_CURRENT, port); 00235 host->deviceDisconnected(dev->getHub() + 1, port, this, 0); 00236 break; 00237 } 00238 Thread::wait(10); 00239 } 00240 } 00241 00242 void USBHostHub::setPortFeature(uint32_t feature, uint8_t port) { 00243 host->controlWrite( dev, 00244 USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE | USB_RECIPIENT_ENDPOINT, 00245 SET_FEATURE, 00246 feature, 00247 port, 00248 NULL, 00249 0); 00250 } 00251 00252 void USBHostHub::clearPortFeature(uint32_t feature, uint8_t port) { 00253 host->controlWrite( dev, 00254 USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE | USB_RECIPIENT_ENDPOINT, 00255 CLEAR_FEATURE, 00256 feature, 00257 port, 00258 NULL, 00259 0); 00260 } 00261 00262 uint32_t USBHostHub::getPortStatus(uint8_t port) { 00263 uint32_t st; 00264 host->controlRead( dev, 00265 USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE | USB_RECIPIENT_ENDPOINT, 00266 GET_STATUS, 00267 0, 00268 port, 00269 (uint8_t *)&st, 00270 4); 00271 return st; 00272 } 00273 00274 #endif
Generated on Tue Jul 12 2022 17:34:59 by
