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
hiduniversal.cpp
00001 /* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. 00002 00003 This software may be distributed and modified under the terms of the GNU 00004 General Public License version 2 (GPL2) as published by the Free Software 00005 Foundation and appearing in the file GPL2.TXT included in the packaging of 00006 this file. Please note that GPL2 Section 2[b] requires that all works based 00007 on this software must also be made publicly available under the terms of 00008 the GPL2 ("Copyleft"). 00009 00010 Contact information 00011 ------------------- 00012 00013 Circuits At Home, LTD 00014 Web : http://www.circuitsathome.com 00015 e-mail : support@circuitsathome.com 00016 */ 00017 00018 #include "hiduniversal.h" 00019 00020 HIDUniversal::HIDUniversal(Usb *p) : 00021 USBHID(p), 00022 qNextPollTime(0), 00023 pollInterval(0), 00024 bPollEnable(false), 00025 bHasReportId(false) { 00026 Initialize(); 00027 00028 if(pUsb) 00029 pUsb->RegisterDeviceClass(this); 00030 } 00031 00032 uint16_t HIDUniversal::GetHidClassDescrLen(uint8_t type, uint8_t num) { 00033 for(uint8_t i = 0, n = 0; i < HID_MAX_HID_CLASS_DESCRIPTORS; i++) { 00034 if(descrInfo[i].bDescrType == type) { 00035 if(n == num) 00036 return descrInfo[i].wDescriptorLength; 00037 n++; 00038 } 00039 } 00040 return 0; 00041 } 00042 00043 void HIDUniversal::Initialize() { 00044 for(uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) { 00045 rptParsers[i].rptId = 0; 00046 rptParsers[i].rptParser = NULL; 00047 } 00048 for(uint8_t i = 0; i < HID_MAX_HID_CLASS_DESCRIPTORS; i++) { 00049 descrInfo[i].bDescrType = 0; 00050 descrInfo[i].wDescriptorLength = 0; 00051 } 00052 for(uint8_t i = 0; i < maxHidInterfaces; i++) { 00053 hidInterfaces[i].bmInterface = 0; 00054 hidInterfaces[i].bmProtocol = 0; 00055 00056 for(uint8_t j = 0; j < maxEpPerInterface; j++) 00057 hidInterfaces[i].epIndex[j] = 0; 00058 } 00059 for(uint8_t i = 0; i < totalEndpoints; i++) { 00060 epInfo[i].epAddr = 0; 00061 epInfo[i].maxPktSize = (i) ? 0 : 8; 00062 epInfo[i].bmSndToggle = 0; 00063 epInfo[i].bmRcvToggle = 0; 00064 epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER; 00065 } 00066 bNumEP = 1; 00067 bNumIface = 0; 00068 bConfNum = 0; 00069 pollInterval = 0; 00070 00071 ZeroMemory(constBuffLen, prevBuf); 00072 } 00073 00074 bool HIDUniversal::SetReportParser(uint8_t id, HIDReportParser *prs) { 00075 for(uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) { 00076 if(rptParsers[i].rptId == 0 && rptParsers[i].rptParser == NULL) { 00077 rptParsers[i].rptId = id; 00078 rptParsers[i].rptParser = prs; 00079 return true; 00080 } 00081 } 00082 return false; 00083 } 00084 00085 HIDReportParser* HIDUniversal::GetReportParser(uint8_t id) { 00086 if(!bHasReportId) 00087 return ((rptParsers[0].rptParser) ? rptParsers[0].rptParser : NULL); 00088 00089 for(uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) { 00090 if(rptParsers[i].rptId == id) 00091 return rptParsers[i].rptParser; 00092 } 00093 return NULL; 00094 } 00095 00096 uint8_t HIDUniversal::Init(uint8_t parent, uint8_t port, bool lowspeed) { 00097 const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR); 00098 00099 uint8_t buf[constBufSize]; 00100 USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf); 00101 uint8_t rcode; 00102 UsbDevice *p = NULL; 00103 EpInfo *oldep_ptr = NULL; 00104 uint8_t len = 0; 00105 00106 uint8_t num_of_conf; // number of configurations 00107 //uint8_t num_of_intf; // number of interfaces 00108 00109 AddressPool &addrPool = pUsb->GetAddressPool(); 00110 00111 USBTRACE("HU Init\r\n"); 00112 00113 if(bAddress) 00114 return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; 00115 00116 // Get pointer to pseudo device with address 0 assigned 00117 p = addrPool.GetUsbDevicePtr(0); 00118 00119 if(!p) 00120 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; 00121 00122 if(!p->epinfo) { 00123 USBTRACE("epinfo\r\n"); 00124 return USB_ERROR_EPINFO_IS_NULL; 00125 } 00126 00127 // Save old pointer to EP_RECORD of address 0 00128 oldep_ptr = p->epinfo; 00129 00130 // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence 00131 p->epinfo = epInfo; 00132 00133 p->lowspeed = lowspeed; 00134 00135 // Get device descriptor 00136 rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*)buf); 00137 00138 if(!rcode) 00139 len = (buf[0] > constBufSize) ? constBufSize : buf[0]; 00140 00141 if(rcode) { 00142 // Restore p->epinfo 00143 p->epinfo = oldep_ptr; 00144 00145 goto FailGetDevDescr; 00146 } 00147 00148 // Restore p->epinfo 00149 p->epinfo = oldep_ptr; 00150 00151 // Allocate new address according to device class 00152 bAddress = addrPool.AllocAddress(parent, false, port); 00153 00154 if(!bAddress) 00155 return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; 00156 00157 // Extract Max Packet Size from the device descriptor 00158 epInfo[0].maxPktSize = udd->bMaxPacketSize0; 00159 00160 // Assign new address to the device 00161 rcode = pUsb->setAddr(0, 0, bAddress); 00162 00163 if(rcode) { 00164 p->lowspeed = false; 00165 addrPool.FreeAddress(bAddress); 00166 bAddress = 0; 00167 USBTRACE2("setAddr:", rcode); 00168 return rcode; 00169 } 00170 00171 //delay(2); //per USB 2.0 sect.9.2.6.3 00172 00173 USBTRACE2("Addr:", bAddress); 00174 00175 p->lowspeed = false; 00176 00177 p = addrPool.GetUsbDevicePtr(bAddress); 00178 00179 if(!p) 00180 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; 00181 00182 p->lowspeed = lowspeed; 00183 00184 if(len) 00185 rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*)buf); 00186 00187 if(rcode) 00188 goto FailGetDevDescr; 00189 00190 VID = udd->idVendor; // Can be used by classes that inherits this class to check the VID and PID of the connected device 00191 PID = udd->idProduct; 00192 00193 num_of_conf = udd->bNumConfigurations; 00194 00195 // Assign epInfo to epinfo pointer 00196 rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); 00197 00198 if(rcode) 00199 goto FailSetDevTblEntry; 00200 00201 USBTRACE2("NC:", num_of_conf); 00202 00203 for(uint8_t i = 0; i < num_of_conf; i++) { 00204 //HexDumper<USBReadParser, uint16_t, uint16_t> HexDump; 00205 ConfigDescParser<USB_CLASS_HID, 0, 0, 00206 CP_MASK_COMPARE_CLASS> confDescrParser(this); 00207 00208 //rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump); 00209 rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); 00210 00211 if(rcode) 00212 goto FailGetConfDescr; 00213 00214 if(bNumEP > 1) 00215 break; 00216 } // for 00217 00218 if(bNumEP < 2) 00219 return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; 00220 00221 // Assign epInfo to epinfo pointer 00222 rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); 00223 00224 USBTRACE2("Cnf:", bConfNum); 00225 00226 // Set Configuration Value 00227 rcode = pUsb->setConf(bAddress, 0, bConfNum); 00228 00229 if(rcode) 00230 goto FailSetConfDescr; 00231 00232 for(uint8_t i = 0; i < bNumIface; i++) { 00233 if(hidInterfaces[i].epIndex[epInterruptInIndex] == 0) 00234 continue; 00235 00236 rcode = SetIdle(hidInterfaces[i].bmInterface, 0, 0); 00237 00238 if(rcode && rcode != hrSTALL) 00239 goto FailSetIdle; 00240 } 00241 00242 USBTRACE("HU configured\r\n"); 00243 00244 OnInitSuccessful(); 00245 00246 bPollEnable = true; 00247 return 0; 00248 00249 FailGetDevDescr: 00250 #ifdef DEBUG_USB_HOST 00251 NotifyFailGetDevDescr(); 00252 goto Fail; 00253 #endif 00254 00255 FailSetDevTblEntry: 00256 #ifdef DEBUG_USB_HOST 00257 NotifyFailSetDevTblEntry(); 00258 goto Fail; 00259 #endif 00260 00261 FailGetConfDescr: 00262 #ifdef DEBUG_USB_HOST 00263 NotifyFailGetConfDescr(); 00264 goto Fail; 00265 #endif 00266 00267 FailSetConfDescr: 00268 #ifdef DEBUG_USB_HOST 00269 NotifyFailSetConfDescr(); 00270 goto Fail; 00271 #endif 00272 00273 00274 FailSetIdle: 00275 #ifdef DEBUG_USB_HOST 00276 USBTRACE("SetIdle:"); 00277 #endif 00278 00279 #ifdef DEBUG_USB_HOST 00280 Fail: 00281 NotifyFail(rcode); 00282 #endif 00283 Release(); 00284 return rcode; 00285 } 00286 00287 HIDUniversal::HIDInterface* HIDUniversal::FindInterface(uint8_t iface, uint8_t alt, uint8_t proto) { 00288 for(uint8_t i = 0; i < bNumIface && i < maxHidInterfaces; i++) 00289 if(hidInterfaces[i].bmInterface == iface && hidInterfaces[i].bmAltSet == alt 00290 && hidInterfaces[i].bmProtocol == proto) 00291 return hidInterfaces + i; 00292 return NULL; 00293 } 00294 00295 void HIDUniversal::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) { 00296 // If the first configuration satisfies, the others are not concidered. 00297 if(bNumEP > 1 && conf != bConfNum) 00298 return; 00299 00300 //ErrorMessage<uint8_t>(PSTR("\r\nConf.Val"), conf); 00301 //ErrorMessage<uint8_t>(PSTR("Iface Num"), iface); 00302 //ErrorMessage<uint8_t>(PSTR("Alt.Set"), alt); 00303 00304 bConfNum = conf; 00305 00306 uint8_t index = 0; 00307 HIDInterface *piface = FindInterface(iface, alt, proto); 00308 00309 // Fill in interface structure in case of new interface 00310 if(!piface) { 00311 piface = hidInterfaces + bNumIface; 00312 piface->bmInterface = iface; 00313 piface->bmAltSet = alt; 00314 piface->bmProtocol = proto; 00315 bNumIface++; 00316 } 00317 00318 if((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_INTERRUPT) 00319 index = (pep->bEndpointAddress & 0x80) == 0x80 ? epInterruptInIndex : epInterruptOutIndex; 00320 00321 if(index) { 00322 // Fill in the endpoint info structure 00323 epInfo[bNumEP].epAddr = (pep->bEndpointAddress & 0x0F); 00324 epInfo[bNumEP].maxPktSize = (uint8_t)pep->wMaxPacketSize; 00325 epInfo[bNumEP].bmSndToggle = 0; 00326 epInfo[bNumEP].bmRcvToggle = 0; 00327 epInfo[bNumEP].bmNakPower = USB_NAK_NOWAIT; 00328 00329 // Fill in the endpoint index list 00330 piface->epIndex[index] = bNumEP; //(pep->bEndpointAddress & 0x0F); 00331 00332 if(pollInterval < pep->bInterval) // Set the polling interval as the largest polling interval obtained from endpoints 00333 pollInterval = pep->bInterval; 00334 00335 bNumEP++; 00336 } 00337 //PrintEndpointDescriptor(pep); 00338 } 00339 00340 uint8_t HIDUniversal::Release() { 00341 pUsb->GetAddressPool().FreeAddress(bAddress); 00342 00343 bNumEP = 1; 00344 bAddress = 0; 00345 qNextPollTime = 0; 00346 bPollEnable = false; 00347 return 0; 00348 } 00349 00350 bool HIDUniversal::BuffersIdentical(uint8_t len, uint8_t *buf1, uint8_t *buf2) { 00351 for(uint8_t i = 0; i < len; i++) 00352 if(buf1[i] != buf2[i]) 00353 return false; 00354 return true; 00355 } 00356 00357 void HIDUniversal::ZeroMemory(uint8_t len, uint8_t *buf) { 00358 for(uint8_t i = 0; i < len; i++) 00359 buf[i] = 0; 00360 } 00361 00362 void HIDUniversal::SaveBuffer(uint8_t len, uint8_t *src, uint8_t *dest) { 00363 for(uint8_t i = 0; i < len; i++) 00364 dest[i] = src[i]; 00365 } 00366 00367 uint8_t HIDUniversal::Poll() { 00368 uint8_t rcode = 0; 00369 00370 if(!bPollEnable) 00371 return 0; 00372 00373 if((int32_t)((uint32_t)millis() - qNextPollTime) >= 0L) { 00374 qNextPollTime = (uint32_t)millis() + pollInterval; 00375 00376 uint8_t buf[constBuffLen]; 00377 00378 for(uint8_t i = 0; i < bNumIface; i++) { 00379 uint8_t index = hidInterfaces[i].epIndex[epInterruptInIndex]; 00380 uint16_t read = (uint16_t)epInfo[index].maxPktSize; 00381 00382 ZeroMemory(constBuffLen, buf); 00383 00384 uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[index].epAddr, &read, buf); 00385 00386 if(rcode) { 00387 if(rcode != hrNAK) 00388 USBTRACE3("(hiduniversal.h) Poll:", rcode, 0x81); 00389 return rcode; 00390 } 00391 00392 if(read > constBuffLen) 00393 read = constBuffLen; 00394 00395 bool identical = BuffersIdentical(read, buf, prevBuf); 00396 00397 SaveBuffer(read, buf, prevBuf); 00398 00399 if(identical) 00400 return 0; 00401 #if 0 00402 Notify(PSTR("\r\nBuf: "), 0x80); 00403 00404 for(uint8_t i = 0; i < read; i++) { 00405 D_PrintHex<uint8_t > (buf[i], 0x80); 00406 Notify(PSTR(" "), 0x80); 00407 } 00408 00409 Notify(PSTR("\r\n"), 0x80); 00410 #endif 00411 ParseHIDData(this, bHasReportId, (uint8_t)read, buf); 00412 00413 HIDReportParser *prs = GetReportParser(((bHasReportId) ? *buf : 0)); 00414 00415 if(prs) 00416 prs->Parse(this, bHasReportId, (uint8_t)read, buf); 00417 } 00418 } 00419 return rcode; 00420 } 00421 00422 // Send a report to interrupt out endpoint. This is NOT SetReport() request! 00423 uint8_t HIDUniversal::SndRpt(uint16_t nbytes, uint8_t *dataptr) { 00424 return pUsb->outTransfer(bAddress, epInfo[epInterruptOutIndex].epAddr, nbytes, dataptr); 00425 }
Generated on Tue Jul 12 2022 18:12:04 by
1.7.2