logo

qmk_firmware

custom branch of QMK firmware git clone https://anongit.hacktivis.me/git/qmk_firmware.git

hiduniversal.cpp (13181B)


  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 : support@circuitsathome.com
  13. */
  14. #include "hiduniversal.h"
  15. HIDUniversal::HIDUniversal(USB *p) :
  16. HID(p),
  17. qNextPollTime(0),
  18. pollInterval(0),
  19. bPollEnable(false),
  20. bHasReportId(false) {
  21. Initialize();
  22. if(pUsb)
  23. pUsb->RegisterDeviceClass(this);
  24. }
  25. uint16_t HIDUniversal::GetHidClassDescrLen(uint8_t type, uint8_t num) {
  26. for(uint8_t i = 0, n = 0; i < HID_MAX_HID_CLASS_DESCRIPTORS; i++) {
  27. if(descrInfo[i].bDescrType == type) {
  28. if(n == num)
  29. return descrInfo[i].wDescriptorLength;
  30. n++;
  31. }
  32. }
  33. return 0;
  34. }
  35. void HIDUniversal::Initialize() {
  36. for(uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) {
  37. rptParsers[i].rptId = 0;
  38. rptParsers[i].rptParser = NULL;
  39. }
  40. for(uint8_t i = 0; i < HID_MAX_HID_CLASS_DESCRIPTORS; i++) {
  41. descrInfo[i].bDescrType = 0;
  42. descrInfo[i].wDescriptorLength = 0;
  43. }
  44. for(uint8_t i = 0; i < maxHidInterfaces; i++) {
  45. hidInterfaces[i].bmInterface = 0;
  46. hidInterfaces[i].bmProtocol = 0;
  47. for(uint8_t j = 0; j < maxEpPerInterface; j++)
  48. hidInterfaces[i].epIndex[j] = 0;
  49. }
  50. for(uint8_t i = 0; i < totalEndpoints; i++) {
  51. epInfo[i].epAddr = 0;
  52. epInfo[i].maxPktSize = (i) ? 0 : 8;
  53. epInfo[i].epAttribs = 0;
  54. epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
  55. }
  56. bNumEP = 1;
  57. bNumIface = 0;
  58. bConfNum = 0;
  59. pollInterval = 0;
  60. ZeroMemory(constBuffLen, prevBuf);
  61. }
  62. bool HIDUniversal::SetReportParser(uint8_t id, HIDReportParser *prs) {
  63. for(uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) {
  64. if(rptParsers[i].rptId == 0 && rptParsers[i].rptParser == NULL) {
  65. rptParsers[i].rptId = id;
  66. rptParsers[i].rptParser = prs;
  67. return true;
  68. }
  69. }
  70. return false;
  71. }
  72. HIDReportParser* HIDUniversal::GetReportParser(uint8_t id) {
  73. if(!bHasReportId)
  74. return ((rptParsers[0].rptParser) ? rptParsers[0].rptParser : NULL);
  75. for(uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) {
  76. if(rptParsers[i].rptId == id)
  77. return rptParsers[i].rptParser;
  78. }
  79. return NULL;
  80. }
  81. uint8_t HIDUniversal::Init(uint8_t parent, uint8_t port, bool lowspeed) {
  82. const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);
  83. uint8_t buf[constBufSize];
  84. USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
  85. uint8_t rcode;
  86. UsbDevice *p = NULL;
  87. EpInfo *oldep_ptr = NULL;
  88. uint8_t len = 0;
  89. uint8_t num_of_conf; // number of configurations
  90. //uint8_t num_of_intf; // number of interfaces
  91. AddressPool &addrPool = pUsb->GetAddressPool();
  92. USBTRACE("HU Init\r\n");
  93. if(bAddress)
  94. return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
  95. // Get pointer to pseudo device with address 0 assigned
  96. p = addrPool.GetUsbDevicePtr(0);
  97. if(!p)
  98. return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
  99. if(!p->epinfo) {
  100. USBTRACE("epinfo\r\n");
  101. return USB_ERROR_EPINFO_IS_NULL;
  102. }
  103. // Save old pointer to EP_RECORD of address 0
  104. oldep_ptr = p->epinfo;
  105. // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
  106. p->epinfo = epInfo;
  107. p->lowspeed = lowspeed;
  108. // Get device descriptor
  109. rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*)buf);
  110. if(!rcode)
  111. len = (buf[0] > constBufSize) ? constBufSize : buf[0];
  112. if(rcode) {
  113. // Restore p->epinfo
  114. p->epinfo = oldep_ptr;
  115. goto FailGetDevDescr;
  116. }
  117. // Restore p->epinfo
  118. p->epinfo = oldep_ptr;
  119. // Allocate new address according to device class
  120. bAddress = addrPool.AllocAddress(parent, false, port);
  121. if(!bAddress)
  122. return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
  123. // Extract Max Packet Size from the device descriptor
  124. epInfo[0].maxPktSize = udd->bMaxPacketSize0;
  125. // Assign new address to the device
  126. rcode = pUsb->setAddr(0, 0, bAddress);
  127. if(rcode) {
  128. p->lowspeed = false;
  129. addrPool.FreeAddress(bAddress);
  130. bAddress = 0;
  131. USBTRACE2("setAddr:", rcode);
  132. return rcode;
  133. }
  134. //delay(2); //per USB 2.0 sect.9.2.6.3
  135. USBTRACE2("Addr:", bAddress);
  136. p->lowspeed = false;
  137. p = addrPool.GetUsbDevicePtr(bAddress);
  138. if(!p)
  139. return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
  140. p->lowspeed = lowspeed;
  141. if(len)
  142. rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*)buf);
  143. if(rcode)
  144. goto FailGetDevDescr;
  145. VID = udd->idVendor; // Can be used by classes that inherits this class to check the VID and PID of the connected device
  146. PID = udd->idProduct;
  147. num_of_conf = udd->bNumConfigurations;
  148. // Assign epInfo to epinfo pointer
  149. rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
  150. if(rcode)
  151. goto FailSetDevTblEntry;
  152. USBTRACE2("NC:", num_of_conf);
  153. for(uint8_t i = 0; i < num_of_conf; i++) {
  154. //HexDumper<USBReadParser, uint16_t, uint16_t> HexDump;
  155. ConfigDescParser<USB_CLASS_HID, 0, 0,
  156. CP_MASK_COMPARE_CLASS> confDescrParser(this);
  157. //rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump);
  158. rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
  159. if(rcode)
  160. goto FailGetConfDescr;
  161. if(bNumEP > 1)
  162. break;
  163. } // for
  164. if(bNumEP < 2)
  165. return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
  166. // Assign epInfo to epinfo pointer
  167. rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);
  168. USBTRACE2("Cnf:", bConfNum);
  169. // Set Configuration Value
  170. rcode = pUsb->setConf(bAddress, 0, bConfNum);
  171. if(rcode)
  172. goto FailSetConfDescr;
  173. for(uint8_t i = 0; i < bNumIface; i++) {
  174. if(hidInterfaces[i].epIndex[epInterruptInIndex] == 0)
  175. continue;
  176. rcode = SetIdle(hidInterfaces[i].bmInterface, 0, 0);
  177. if(rcode && rcode != hrSTALL)
  178. goto FailSetIdle;
  179. }
  180. USBTRACE("HU configured\r\n");
  181. OnInitSuccessful();
  182. bPollEnable = true;
  183. return 0;
  184. FailGetDevDescr:
  185. #ifdef DEBUG_USB_HOST
  186. NotifyFailGetDevDescr();
  187. goto Fail;
  188. #endif
  189. FailSetDevTblEntry:
  190. #ifdef DEBUG_USB_HOST
  191. NotifyFailSetDevTblEntry();
  192. goto Fail;
  193. #endif
  194. FailGetConfDescr:
  195. #ifdef DEBUG_USB_HOST
  196. NotifyFailGetConfDescr();
  197. goto Fail;
  198. #endif
  199. FailSetConfDescr:
  200. #ifdef DEBUG_USB_HOST
  201. NotifyFailSetConfDescr();
  202. goto Fail;
  203. #endif
  204. FailSetIdle:
  205. #ifdef DEBUG_USB_HOST
  206. USBTRACE("SetIdle:");
  207. #endif
  208. #ifdef DEBUG_USB_HOST
  209. Fail:
  210. NotifyFail(rcode);
  211. #endif
  212. Release();
  213. return rcode;
  214. }
  215. HIDUniversal::HIDInterface* HIDUniversal::FindInterface(uint8_t iface, uint8_t alt, uint8_t proto) {
  216. for(uint8_t i = 0; i < bNumIface && i < maxHidInterfaces; i++)
  217. if(hidInterfaces[i].bmInterface == iface && hidInterfaces[i].bmAltSet == alt
  218. && hidInterfaces[i].bmProtocol == proto)
  219. return hidInterfaces + i;
  220. return NULL;
  221. }
  222. void HIDUniversal::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) {
  223. // If the first configuration satisfies, the others are not concidered.
  224. if(bNumEP > 1 && conf != bConfNum)
  225. return;
  226. //ErrorMessage<uint8_t>(PSTR("\r\nConf.Val"), conf);
  227. //ErrorMessage<uint8_t>(PSTR("Iface Num"), iface);
  228. //ErrorMessage<uint8_t>(PSTR("Alt.Set"), alt);
  229. bConfNum = conf;
  230. uint8_t index = 0;
  231. HIDInterface *piface = FindInterface(iface, alt, proto);
  232. // Fill in interface structure in case of new interface
  233. if(!piface) {
  234. piface = hidInterfaces + bNumIface;
  235. piface->bmInterface = iface;
  236. piface->bmAltSet = alt;
  237. piface->bmProtocol = proto;
  238. bNumIface++;
  239. }
  240. if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80)
  241. index = epInterruptInIndex;
  242. else
  243. index = epInterruptOutIndex;
  244. if(index) {
  245. // Fill in the endpoint info structure
  246. epInfo[bNumEP].epAddr = (pep->bEndpointAddress & 0x0F);
  247. epInfo[bNumEP].maxPktSize = (uint8_t)pep->wMaxPacketSize;
  248. epInfo[bNumEP].epAttribs = 0;
  249. epInfo[bNumEP].bmNakPower = USB_NAK_NOWAIT;
  250. // Fill in the endpoint index list
  251. piface->epIndex[index] = bNumEP; //(pep->bEndpointAddress & 0x0F);
  252. if(pollInterval < pep->bInterval) // Set the polling interval as the largest polling interval obtained from endpoints
  253. pollInterval = pep->bInterval;
  254. bNumEP++;
  255. }
  256. //PrintEndpointDescriptor(pep);
  257. }
  258. uint8_t HIDUniversal::Release() {
  259. pUsb->GetAddressPool().FreeAddress(bAddress);
  260. bNumEP = 1;
  261. bAddress = 0;
  262. qNextPollTime = 0;
  263. bPollEnable = false;
  264. return 0;
  265. }
  266. bool HIDUniversal::BuffersIdentical(uint8_t len, uint8_t *buf1, uint8_t *buf2) {
  267. for(uint8_t i = 0; i < len; i++)
  268. if(buf1[i] != buf2[i])
  269. return false;
  270. return true;
  271. }
  272. void HIDUniversal::ZeroMemory(uint8_t len, uint8_t *buf) {
  273. for(uint8_t i = 0; i < len; i++)
  274. buf[i] = 0;
  275. }
  276. void HIDUniversal::SaveBuffer(uint8_t len, uint8_t *src, uint8_t *dest) {
  277. for(uint8_t i = 0; i < len; i++)
  278. dest[i] = src[i];
  279. }
  280. uint8_t HIDUniversal::Poll() {
  281. uint8_t rcode = 0;
  282. if(!bPollEnable)
  283. return 0;
  284. if((long)(millis() - qNextPollTime) >= 0L) {
  285. qNextPollTime = millis() + pollInterval;
  286. uint8_t buf[constBuffLen];
  287. for(uint8_t i = 0; i < bNumIface; i++) {
  288. uint8_t index = hidInterfaces[i].epIndex[epInterruptInIndex];
  289. uint16_t read = (uint16_t)epInfo[index].maxPktSize;
  290. ZeroMemory(constBuffLen, buf);
  291. uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[index].epAddr, &read, buf);
  292. if(rcode) {
  293. if(rcode != hrNAK)
  294. USBTRACE3("(hiduniversal.h) Poll:", rcode, 0x81);
  295. return rcode;
  296. }
  297. if(read > constBuffLen)
  298. read = constBuffLen;
  299. bool identical = BuffersIdentical(read, buf, prevBuf);
  300. SaveBuffer(read, buf, prevBuf);
  301. if(identical)
  302. return 0;
  303. #if 0
  304. Notify(PSTR("\r\nBuf: "), 0x80);
  305. for(uint8_t i = 0; i < read; i++) {
  306. D_PrintHex<uint8_t > (buf[i], 0x80);
  307. Notify(PSTR(" "), 0x80);
  308. }
  309. Notify(PSTR("\r\n"), 0x80);
  310. #endif
  311. ParseHIDData(this, bHasReportId, (uint8_t)read, buf);
  312. HIDReportParser *prs = GetReportParser(((bHasReportId) ? *buf : 0));
  313. if(prs)
  314. prs->Parse(this, bHasReportId, (uint8_t)read, buf);
  315. }
  316. }
  317. return rcode;
  318. }
  319. // Send a report to interrupt out endpoint. This is NOT SetReport() request!
  320. uint8_t HIDUniversal::SndRpt(uint16_t nbytes, uint8_t *dataptr) {
  321. return pUsb->outTransfer(bAddress, epInfo[epInterruptOutIndex].epAddr, nbytes, dataptr);
  322. }