Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
Este repositório está arquivado. Você pode visualizar os arquivos e realizar clone, mas não poderá realizar push nem abrir issues e pull requests.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. /* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
  2. This software may be distributed and modified under the terms of the GNU
  3. General Public License version 2 (GPL2) as published by the Free Software
  4. Foundation and appearing in the file GPL2.TXT included in the packaging of
  5. this file. Please note that GPL2 Section 2[b] requires that all works based
  6. on this software must also be made publicly available under the terms of
  7. the GPL2 ("Copyleft").
  8. Contact information
  9. -------------------
  10. Circuits At Home, LTD
  11. Web : http://www.circuitsathome.com
  12. e-mail : [email protected]
  13. */
  14. #if !defined(_usb_h_) || defined(__ADDRESS_H__)
  15. #error "Never include address.h directly; include Usb.h instead"
  16. #else
  17. #define __ADDRESS_H__
  18. /* NAK powers. To save space in endpoint data structure, amount of retries before giving up and returning 0x4 is stored in */
  19. /* bmNakPower as a power of 2. The actual nak_limit is then calculated as nak_limit = ( 2^bmNakPower - 1) */
  20. #define USB_NAK_MAX_POWER 15 //NAK binary order maximum value
  21. #define USB_NAK_DEFAULT 14 //default 32K-1 NAKs before giving up
  22. #define USB_NAK_NOWAIT 1 //Single NAK stops transfer
  23. #define USB_NAK_NONAK 0 //Do not count NAKs, stop retrying after USB Timeout
  24. struct EpInfo {
  25. uint8_t epAddr; // Endpoint address
  26. uint8_t maxPktSize; // Maximum packet size
  27. union {
  28. uint8_t epAttribs;
  29. struct {
  30. uint8_t bmSndToggle : 1; // Send toggle, when zero bmSNDTOG0, bmSNDTOG1 otherwise
  31. uint8_t bmRcvToggle : 1; // Send toggle, when zero bmRCVTOG0, bmRCVTOG1 otherwise
  32. uint8_t bmNakPower : 6; // Binary order for NAK_LIMIT value
  33. } __attribute__((packed));
  34. };
  35. } __attribute__((packed));
  36. // 7 6 5 4 3 2 1 0
  37. // ---------------------------------
  38. // | | H | P | P | P | A | A | A |
  39. // ---------------------------------
  40. //
  41. // H - if 1 the address is a hub address
  42. // P - parent hub address
  43. // A - device address / port number in case of hub
  44. //
  45. struct UsbDeviceAddress {
  46. union {
  47. struct {
  48. uint8_t bmAddress : 3; // device address/port number
  49. uint8_t bmParent : 3; // parent hub address
  50. uint8_t bmHub : 1; // hub flag
  51. uint8_t bmReserved : 1; // reserved, must be zero
  52. } __attribute__((packed));
  53. uint8_t devAddress;
  54. };
  55. } __attribute__((packed));
  56. #define bmUSB_DEV_ADDR_ADDRESS 0x07
  57. #define bmUSB_DEV_ADDR_PARENT 0x38
  58. #define bmUSB_DEV_ADDR_HUB 0x40
  59. struct UsbDevice {
  60. EpInfo *epinfo; // endpoint info pointer
  61. UsbDeviceAddress address;
  62. uint8_t epcount; // number of endpoints
  63. bool lowspeed; // indicates if a device is the low speed one
  64. // uint8_t devclass; // device class
  65. } __attribute__((packed));
  66. class AddressPool {
  67. public:
  68. virtual UsbDevice* GetUsbDevicePtr(uint8_t addr) = 0;
  69. virtual uint8_t AllocAddress(uint8_t parent, bool is_hub = false, uint8_t port = 0) = 0;
  70. virtual void FreeAddress(uint8_t addr) = 0;
  71. };
  72. typedef void (*UsbDeviceHandleFunc)(UsbDevice *pdev);
  73. #define ADDR_ERROR_INVALID_INDEX 0xFF
  74. #define ADDR_ERROR_INVALID_ADDRESS 0xFF
  75. template <const uint8_t MAX_DEVICES_ALLOWED>
  76. class AddressPoolImpl : public AddressPool {
  77. EpInfo dev0ep; //Endpoint data structure used during enumeration for uninitialized device
  78. uint8_t hubCounter; // hub counter is kept
  79. // in order to avoid hub address duplication
  80. UsbDevice thePool[MAX_DEVICES_ALLOWED];
  81. // Initializes address pool entry
  82. void InitEntry(uint8_t index) {
  83. thePool[index].address.devAddress = 0;
  84. thePool[index].epcount = 1;
  85. thePool[index].lowspeed = 0;
  86. thePool[index].epinfo = &dev0ep;
  87. };
  88. // Returns thePool index for a given address
  89. uint8_t FindAddressIndex(uint8_t address = 0) {
  90. for(uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++) {
  91. if(thePool[i].address.devAddress == address)
  92. return i;
  93. }
  94. return 0;
  95. };
  96. // Returns thePool child index for a given parent
  97. uint8_t FindChildIndex(UsbDeviceAddress addr, uint8_t start = 1) {
  98. for(uint8_t i = (start < 1 || start >= MAX_DEVICES_ALLOWED) ? 1 : start; i < MAX_DEVICES_ALLOWED; i++) {
  99. if(thePool[i].address.bmParent == addr.bmAddress)
  100. return i;
  101. }
  102. return 0;
  103. };
  104. // Frees address entry specified by index parameter
  105. void FreeAddressByIndex(uint8_t index) {
  106. // Zero field is reserved and should not be affected
  107. if(index == 0)
  108. return;
  109. UsbDeviceAddress uda = thePool[index].address;
  110. // If a hub was switched off all port addresses should be freed
  111. if(uda.bmHub == 1) {
  112. for(uint8_t i = 1; (i = FindChildIndex(uda, i));)
  113. FreeAddressByIndex(i);
  114. // If the hub had the last allocated address, hubCounter should be decremented
  115. if(hubCounter == uda.bmAddress)
  116. hubCounter--;
  117. }
  118. InitEntry(index);
  119. }
  120. // Initializes the whole address pool at once
  121. void InitAllAddresses() {
  122. for(uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++)
  123. InitEntry(i);
  124. hubCounter = 0;
  125. };
  126. public:
  127. AddressPoolImpl() : hubCounter(0) {
  128. // Zero address is reserved
  129. InitEntry(0);
  130. thePool[0].address.devAddress = 0;
  131. thePool[0].epinfo = &dev0ep;
  132. dev0ep.epAddr = 0;
  133. dev0ep.maxPktSize = 8;
  134. dev0ep.epAttribs = 0; //set DATA0/1 toggles to 0
  135. dev0ep.bmNakPower = USB_NAK_MAX_POWER;
  136. InitAllAddresses();
  137. };
  138. // Returns a pointer to a specified address entry
  139. virtual UsbDevice* GetUsbDevicePtr(uint8_t addr) {
  140. if(!addr)
  141. return thePool;
  142. uint8_t index = FindAddressIndex(addr);
  143. return (!index) ? NULL : thePool + index;
  144. };
  145. // Performs an operation specified by pfunc for each addressed device
  146. void ForEachUsbDevice(UsbDeviceHandleFunc pfunc) {
  147. if(!pfunc)
  148. return;
  149. for(uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++)
  150. if(thePool[i].address.devAddress)
  151. pfunc(thePool + i);
  152. };
  153. // Allocates new address
  154. virtual uint8_t AllocAddress(uint8_t parent, bool is_hub = false, uint8_t port = 0) {
  155. /* if (parent != 0 && port == 0)
  156. USB_HOST_SERIAL.println("PRT:0"); */
  157. UsbDeviceAddress _parent;
  158. _parent.devAddress = parent;
  159. if(_parent.bmReserved || port > 7)
  160. //if(parent > 127 || port > 7)
  161. return 0;
  162. if(is_hub && hubCounter == 7)
  163. return 0;
  164. // finds first empty address entry starting from one
  165. uint8_t index = FindAddressIndex(0);
  166. if(!index) // if empty entry is not found
  167. return 0;
  168. if(_parent.devAddress == 0) {
  169. if(is_hub) {
  170. thePool[index].address.devAddress = 0x41;
  171. hubCounter++;
  172. } else
  173. thePool[index].address.devAddress = 1;
  174. return thePool[index].address.devAddress;
  175. }
  176. UsbDeviceAddress addr;
  177. addr.devAddress = 0; // Ensure all bits are zero
  178. addr.bmParent = _parent.bmAddress;
  179. if(is_hub) {
  180. addr.bmHub = 1;
  181. addr.bmAddress = ++hubCounter;
  182. } else {
  183. addr.bmHub = 0;
  184. addr.bmAddress = port;
  185. }
  186. thePool[index].address = addr;
  187. /*
  188. USB_HOST_SERIAL.print("Addr:");
  189. USB_HOST_SERIAL.print(addr.bmHub, HEX);
  190. USB_HOST_SERIAL.print(".");
  191. USB_HOST_SERIAL.print(addr.bmParent, HEX);
  192. USB_HOST_SERIAL.print(".");
  193. USB_HOST_SERIAL.println(addr.bmAddress, HEX);
  194. */
  195. return thePool[index].address.devAddress;
  196. };
  197. // Empties pool entry
  198. virtual void FreeAddress(uint8_t addr) {
  199. // if the root hub is disconnected all the addresses should be initialized
  200. if(addr == 0x41) {
  201. InitAllAddresses();
  202. return;
  203. }
  204. uint8_t index = FindAddressIndex(addr);
  205. FreeAddressByIndex(index);
  206. };
  207. // Returns number of hubs attached
  208. // It can be rather helpfull to find out if there are hubs attached than getting the exact number of hubs.
  209. //uint8_t GetNumHubs()
  210. //{
  211. // return hubCounter;
  212. //};
  213. //uint8_t GetNumDevices()
  214. //{
  215. // uint8_t counter = 0;
  216. // for (uint8_t i=1; i<MAX_DEVICES_ALLOWED; i++)
  217. // if (thePool[i].address != 0);
  218. // counter ++;
  219. // return counter;
  220. //};
  221. };
  222. #endif // __ADDRESS_H__