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.
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 00025 #if !defined(_usb_h_) || defined(__ADDRESS_H__) 00026 #error "Never include address.h directly; include Usb.h instead" 00027 #else 00028 #define __ADDRESS_H__ 00029 00030 00031 00032 /* NAK powers. To save space in endpoint data structure, amount of retries before giving up and returning 0x4 is stored in */ 00033 /* bmNakPower as a power of 2. The actual nak_limit is then calculated as nak_limit = ( 2^bmNakPower - 1) */ 00034 #define USB_NAK_MAX_POWER 15 //NAK binary order maximum value 00035 #define USB_NAK_DEFAULT 14 //default 32K-1 NAKs before giving up 00036 #define USB_NAK_NOWAIT 1 //Single NAK stops transfer 00037 #define USB_NAK_NONAK 0 //Do not count NAKs, stop retrying after USB Timeout 00038 00039 struct EpInfo { 00040 uint8_t epAddr; // Endpoint address 00041 uint8_t maxPktSize; // Maximum packet size 00042 00043 union { 00044 uint8_t epAttribs; 00045 00046 struct { 00047 uint8_t bmSndToggle : 1; // Send toggle, when zero bmSNDTOG0, bmSNDTOG1 otherwise 00048 uint8_t bmRcvToggle : 1; // Send toggle, when zero bmRCVTOG0, bmRCVTOG1 otherwise 00049 uint8_t bmNakPower : 6; // Binary order for NAK_LIMIT value 00050 } __attribute__((packed)); 00051 }; 00052 } __attribute__((packed)); 00053 00054 // 7 6 5 4 3 2 1 0 00055 // --------------------------------- 00056 // | | H | P | P | P | A | A | A | 00057 // --------------------------------- 00058 // 00059 // H - if 1 the address is a hub address 00060 // P - parent hub address 00061 // A - device address / port number in case of hub 00062 // 00063 00064 struct UsbDeviceAddress { 00065 00066 union { 00067 00068 struct { 00069 uint8_t bmAddress : 3; // device address/port number 00070 uint8_t bmParent : 3; // parent hub address 00071 uint8_t bmHub : 1; // hub flag 00072 uint8_t bmReserved : 1; // reserved, must be zero 00073 } __attribute__((packed)); 00074 uint8_t devAddress; 00075 }; 00076 } __attribute__((packed)); 00077 00078 #define bmUSB_DEV_ADDR_ADDRESS 0x07 00079 #define bmUSB_DEV_ADDR_PARENT 0x38 00080 #define bmUSB_DEV_ADDR_HUB 0x40 00081 00082 struct UsbDevice { 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 // uint8_t devclass; // device class 00088 } __attribute__((packed)); 00089 00090 class AddressPool { 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 EpInfo dev0ep; //Endpoint data structure used during enumeration for uninitialized device 00105 00106 uint8_t hubCounter; // hub counter is kept 00107 // in order to avoid hub address duplication 00108 00109 UsbDevice thePool[MAX_DEVICES_ALLOWED]; 00110 00111 // Initializes address pool entry 00112 00113 void InitEntry(uint8_t index) { 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 00122 uint8_t FindAddressIndex(uint8_t address = 0) { 00123 for(uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++) { 00124 if(thePool[i].address.devAddress == address) 00125 return i; 00126 } 00127 return 0; 00128 }; 00129 00130 // Returns thePool child index for a given parent 00131 00132 uint8_t FindChildIndex(UsbDeviceAddress addr, uint8_t start = 1) { 00133 for(uint8_t i = (start < 1 || start >= MAX_DEVICES_ALLOWED) ? 1 : start; i < MAX_DEVICES_ALLOWED; i++) { 00134 if(thePool[i].address.bmParent == addr.bmAddress) 00135 return i; 00136 } 00137 return 0; 00138 }; 00139 00140 // Frees address entry specified by index parameter 00141 00142 void FreeAddressByIndex(uint8_t index) { 00143 // Zero field is reserved and should not be affected 00144 if(index == 0) 00145 return; 00146 00147 UsbDeviceAddress uda = thePool[index].address; 00148 // If a hub was switched off all port addresses should be freed 00149 if(uda.bmHub == 1) { 00150 for(uint8_t i = 1; (i = FindChildIndex(uda, i));) 00151 FreeAddressByIndex(i); 00152 00153 // If the hub had the last allocated address, hubCounter should be decremented 00154 if(hubCounter == uda.bmAddress) 00155 hubCounter--; 00156 } 00157 InitEntry(index); 00158 } 00159 00160 // Initializes the whole address pool at once 00161 00162 void InitAllAddresses() { 00163 for(uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++) 00164 InitEntry(i); 00165 00166 hubCounter = 0; 00167 }; 00168 00169 public: 00170 00171 AddressPoolImpl() : hubCounter(0) { 00172 // Zero address is reserved 00173 InitEntry(0); 00174 00175 thePool[0].address.devAddress = 0; 00176 thePool[0].epinfo = &dev0ep; 00177 dev0ep.epAddr = 0; 00178 dev0ep.maxPktSize = 8; 00179 dev0ep.bmSndToggle = 0; // Set DATA0/1 toggles to 0 00180 dev0ep.bmRcvToggle = 0; 00181 dev0ep.bmNakPower = USB_NAK_MAX_POWER; 00182 00183 InitAllAddresses(); 00184 }; 00185 00186 // Returns a pointer to a specified address entry 00187 00188 virtual UsbDevice* GetUsbDevicePtr(uint8_t addr) { 00189 if(!addr) 00190 return thePool; 00191 00192 uint8_t index = FindAddressIndex(addr); 00193 00194 return (!index) ? NULL : thePool + index; 00195 }; 00196 00197 // Performs an operation specified by pfunc for each addressed device 00198 00199 void ForEachUsbDevice(UsbDeviceHandleFunc pfunc) { 00200 if(!pfunc) 00201 return; 00202 00203 for(uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++) 00204 if(thePool[i].address.devAddress) 00205 pfunc(thePool + i); 00206 }; 00207 00208 // Allocates new address 00209 00210 virtual uint8_t AllocAddress(uint8_t parent, bool is_hub = false, uint8_t port = 0) { 00211 /* if (parent != 0 && port == 0) 00212 USB_HOST_SERIAL.println("PRT:0"); */ 00213 UsbDeviceAddress _parent; 00214 _parent.devAddress = parent; 00215 if(_parent.bmReserved || port > 7) 00216 //if(parent > 127 || port > 7) 00217 return 0; 00218 00219 if(is_hub && hubCounter == 7) 00220 return 0; 00221 00222 // finds first empty address entry starting from one 00223 uint8_t index = FindAddressIndex(0); 00224 00225 if(!index) // if empty entry is not found 00226 return 0; 00227 00228 if(_parent.devAddress == 0) { 00229 if(is_hub) { 00230 thePool[index].address.devAddress = 0x41; 00231 hubCounter++; 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 } else { 00245 addr.bmHub = 0; 00246 addr.bmAddress = port; 00247 } 00248 thePool[index].address = addr; 00249 /* 00250 USB_HOST_SERIAL.print("Addr:"); 00251 USB_HOST_SERIAL.print(addr.bmHub, HEX); 00252 USB_HOST_SERIAL.print("."); 00253 USB_HOST_SERIAL.print(addr.bmParent, HEX); 00254 USB_HOST_SERIAL.print("."); 00255 USB_HOST_SERIAL.println(addr.bmAddress, HEX); 00256 */ 00257 return thePool[index].address.devAddress; 00258 }; 00259 00260 // Empties pool entry 00261 00262 virtual void FreeAddress(uint8_t addr) { 00263 // if the root hub is disconnected all the addresses should be initialized 00264 if(addr == 0x41) { 00265 InitAllAddresses(); 00266 return; 00267 } 00268 uint8_t index = FindAddressIndex(addr); 00269 FreeAddressByIndex(index); 00270 }; 00271 00272 // Returns number of hubs attached 00273 // It can be rather helpfull to find out if there are hubs attached than getting the exact number of hubs. 00274 //uint8_t GetNumHubs() 00275 //{ 00276 // return hubCounter; 00277 //}; 00278 //uint8_t GetNumDevices() 00279 //{ 00280 // uint8_t counter = 0; 00281 00282 // for (uint8_t i=1; i<MAX_DEVICES_ALLOWED; i++) 00283 // if (thePool[i].address != 0); 00284 // counter ++; 00285 00286 // return counter; 00287 //}; 00288 }; 00289 00290 #endif // __ADDRESS_H__ 00291
Generated on Thu Jul 14 2022 08:33:40 by
1.7.2