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.
Dependents: UsbHostMAX3421E_Hello
address.h
00001 /* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. 00002 00003 This program is free software; you can redistribute it and/or modify 00004 it under the terms of the GNU General Public License as published by 00005 the Free Software Foundation; either version 2 of the License, or 00006 (at your option) any later version. 00007 00008 This program is distributed in the hope that it will be useful, 00009 but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00011 GNU General Public License for more details. 00012 00013 You should have received a copy of the GNU General Public License 00014 along with this program; if not, write to the Free Software 00015 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00016 00017 Contact information 00018 ------------------- 00019 00020 Circuits At Home, LTD 00021 Web : http://www.circuitsathome.com 00022 e-mail : support@circuitsathome.com 00023 */ 00024 #ifndef __ADDRESS_H__ 00025 #define __ADDRESS_H__ 00026 00027 /* NAK powers. To save space in endpoint data structure, amount of retries before giving up and returning 0x4 is stored in */ 00028 00029 /* bmNakPower as a power of 2. The actual nak_limit is then calculated as nak_limit = ( 2^bmNakPower - 1) */ 00030 #define USB_NAK_MAX_POWER 15 //NAK binary order maximum value 00031 #define USB_NAK_DEFAULT 14 //default 32K-1 NAKs before giving up 00032 #define USB_NAK_NOWAIT 1 //Single NAK stops transfer 00033 #define USB_NAK_NONAK 0 //Do not count NAKs, stop retrying after USB Timeout 00034 struct EpInfo 00035 { 00036 uint8_t epAddr; // Endpoint address 00037 uint8_t maxPktSize; // Maximum packet size 00038 00039 union 00040 { 00041 uint8_t epAttribs; 00042 00043 struct 00044 { 00045 uint8_t bmSndToggle : 1; // Send toggle, when zero bmSNDTOG0, bmSNDTOG1 otherwise 00046 uint8_t bmRcvToggle : 1; // Send toggle, when zero bmRCVTOG0, bmRCVTOG1 otherwise 00047 uint8_t bmNakPower : 6; // Binary order for NAK_LIMIT value 00048 } __attribute__((packed)); 00049 }; 00050 } 00051 __attribute__((packed)); 00052 00053 // 7 6 5 4 3 2 1 0 00054 // --------------------------------- 00055 // | | H | P | P | P | A | A | A | 00056 // --------------------------------- 00057 // 00058 // H - if 1 the address is a hub address 00059 // P - parent hub address 00060 // A - device address / port number in case of hub 00061 // 00062 struct UsbDeviceAddress 00063 { 00064 union 00065 { 00066 struct 00067 { 00068 uint8_t bmAddress : 3; // device address/port number 00069 uint8_t bmParent : 3; // parent hub address 00070 uint8_t bmHub : 1; // hub flag 00071 uint8_t bmReserved : 1; // reserved, must be zero 00072 } __attribute__((packed)); 00073 uint8_t devAddress; 00074 }; 00075 } __attribute__((packed)); 00076 00077 #define bmUSB_DEV_ADDR_ADDRESS 0x07 00078 #define bmUSB_DEV_ADDR_PARENT 0x38 00079 #define bmUSB_DEV_ADDR_HUB 0x40 00080 00081 struct UsbDevice 00082 { 00083 EpInfo* epinfo; // endpoint info pointer 00084 UsbDeviceAddress address; 00085 uint8_t epcount; // number of endpoints 00086 bool lowspeed; // indicates if a device is the low speed one 00087 } __attribute__((packed)); 00088 00089 class AddressPool 00090 { 00091 public: 00092 virtual UsbDevice* GetUsbDevicePtr(uint8_t addr) = 0; 00093 virtual uint8_t AllocAddress(uint8_t parent, bool is_hub = false, uint8_t port = 0) = 0; 00094 virtual void FreeAddress(uint8_t addr) = 0; 00095 }; 00096 00097 typedef void (*UsbDeviceHandleFunc) (UsbDevice * pdev); 00098 00099 #define ADDR_ERROR_INVALID_INDEX 0xFF 00100 #define ADDR_ERROR_INVALID_ADDRESS 0xFF 00101 00102 template<const uint8_t MAX_DEVICES_ALLOWED> 00103 class AddressPoolImpl : public AddressPool 00104 { 00105 EpInfo dev0ep; //Endpoint data structure used during enumeration for uninitialized device 00106 uint8_t hubCounter; // hub counter is kept 00107 00108 // in order to avoid hub address duplication 00109 UsbDevice thePool[MAX_DEVICES_ALLOWED]; 00110 00111 // Initializes address pool entry 00112 void InitEntry(uint8_t index) 00113 { 00114 thePool[index].address.devAddress = 0; 00115 thePool[index].epcount = 1; 00116 thePool[index].lowspeed = 0; 00117 thePool[index].epinfo = &dev0ep; 00118 } 00119 00120 // Returns thePool index for a given address 00121 uint8_t FindAddressIndex(uint8_t address = 0) 00122 { 00123 for (uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++) { 00124 if (thePool[i].address.devAddress == address) 00125 return i; 00126 } 00127 00128 return 0; 00129 } 00130 00131 // Returns thePool child index for a given parent 00132 uint8_t FindChildIndex(UsbDeviceAddress addr, uint8_t start = 1) 00133 { 00134 for (uint8_t i = (start < 1 || start >= MAX_DEVICES_ALLOWED) ? 1 : start; i < MAX_DEVICES_ALLOWED; i++) { 00135 if (thePool[i].address.bmParent == addr.bmAddress) 00136 return i; 00137 } 00138 00139 return 0; 00140 } 00141 00142 // Frees address entry specified by index parameter 00143 void FreeAddressByIndex(uint8_t index) 00144 { 00145 // Zero field is reserved and should not be affected 00146 00147 if (index == 0) 00148 return; 00149 00150 UsbDeviceAddress uda = thePool[index].address; 00151 // If a hub was switched off all port addresses should be freed 00152 00153 if (uda.bmHub == 1) { 00154 for (uint8_t i = 1; (i = FindChildIndex(uda, i));) 00155 FreeAddressByIndex(i); 00156 00157 // If the hub had the last allocated address, hubCounter should be decremented 00158 if (hubCounter == uda.bmAddress) 00159 hubCounter--; 00160 } 00161 00162 InitEntry(index); 00163 } 00164 00165 // Initializes the whole address pool at once 00166 void InitAllAddresses() { for (uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++) InitEntry(i); hubCounter = 0; } 00167 public: 00168 AddressPoolImpl() : hubCounter(0) 00169 { 00170 // Zero address is reserved 00171 00172 InitEntry(0); 00173 00174 thePool[0].address.devAddress = 0; 00175 thePool[0].epinfo = &dev0ep; 00176 dev0ep.epAddr = 0; 00177 dev0ep.maxPktSize = 8; 00178 dev0ep.bmSndToggle = 0; // Set DATA0/1 toggles to 0 00179 dev0ep.bmRcvToggle = 0; 00180 dev0ep.bmNakPower = USB_NAK_MAX_POWER; 00181 00182 InitAllAddresses(); 00183 } 00184 00185 // Returns a pointer to a specified address entry 00186 virtual UsbDevice* GetUsbDevicePtr(uint8_t addr) 00187 { 00188 if (!addr) 00189 return thePool; 00190 00191 uint8_t index = FindAddressIndex(addr); 00192 00193 return(!index) ? NULL : thePool + index; 00194 } 00195 00196 // Performs an operation specified by pfunc for each addressed device 00197 void ForEachUsbDevice(UsbDeviceHandleFunc pfunc) 00198 { 00199 if (!pfunc) 00200 return; 00201 00202 for (uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++) 00203 if (thePool[i].address.devAddress) 00204 pfunc(thePool + i); 00205 } 00206 00207 // Allocates new address 00208 virtual uint8_t AllocAddress(uint8_t parent, bool is_hub = false, uint8_t port = 0) 00209 { 00210 /* if (parent != 0 && port == 0) 00211 USB_HOST_SERIAL.println("PRT:0"); */ 00212 UsbDeviceAddress _parent; 00213 _parent.devAddress = parent; 00214 if (_parent.bmReserved || port > 7) 00215 //if(parent > 127 || port > 7) 00216 return 0; 00217 00218 if (is_hub && hubCounter == 7) 00219 return 0; 00220 00221 // finds first empty address entry starting from one 00222 uint8_t index = FindAddressIndex(0); 00223 00224 if (!index) // if empty entry is not found 00225 return 0; 00226 00227 if (_parent.devAddress == 0) { 00228 if (is_hub) { 00229 thePool[index].address.devAddress = 0x41; 00230 hubCounter++; 00231 } 00232 else 00233 thePool[index].address.devAddress = 1; 00234 00235 return thePool[index].address.devAddress; 00236 } 00237 00238 UsbDeviceAddress addr; 00239 addr.devAddress = 0; // Ensure all bits are zero 00240 addr.bmParent = _parent.bmAddress; 00241 if (is_hub) { 00242 addr.bmHub = 1; 00243 addr.bmAddress = ++hubCounter; 00244 } 00245 else { 00246 addr.bmHub = 0; 00247 addr.bmAddress = port; 00248 } 00249 00250 thePool[index].address = addr; 00251 00252 /* 00253 USB_HOST_SERIAL.print("Addr:"); 00254 USB_HOST_SERIAL.print(addr.bmHub, HEX); 00255 USB_HOST_SERIAL.print("."); 00256 USB_HOST_SERIAL.print(addr.bmParent, HEX); 00257 USB_HOST_SERIAL.print("."); 00258 USB_HOST_SERIAL.println(addr.bmAddress, HEX); 00259 */ 00260 return thePool[index].address.devAddress; 00261 } 00262 00263 // Empties pool entry 00264 virtual void FreeAddress(uint8_t addr) 00265 { 00266 // if the root hub is disconnected all the addresses should be initialized 00267 00268 if (addr == 0x41) { 00269 InitAllAddresses(); 00270 return; 00271 } 00272 00273 uint8_t index = FindAddressIndex(addr); 00274 FreeAddressByIndex(index); 00275 } 00276 00277 // Returns number of hubs attached 00278 // It can be rather helpfull to find out if there are hubs attached than getting the exact number of hubs. 00279 //uint8_t GetNumHubs() 00280 //{ 00281 // return hubCounter; 00282 //}; 00283 //uint8_t GetNumDevices() 00284 //{ 00285 // uint8_t counter = 0; 00286 // for (uint8_t i=1; i<MAX_DEVICES_ALLOWED; i++) 00287 // if (thePool[i].address != 0); 00288 // counter ++; 00289 // return counter; 00290 //}; 00291 }; 00292 #endif // __ADDRESS_H__
Generated on Tue Jul 12 2022 18:12:04 by
1.7.2