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.
hidcomposite.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 "hidcomposite.h" 00019 00020 HIDComposite::HIDComposite(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 HIDComposite::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 HIDComposite::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 00072 bool HIDComposite::SetReportParser(uint8_t id, HIDReportParser *prs) { 00073 for(uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) { 00074 if(rptParsers[i].rptId == 0 && rptParsers[i].rptParser == NULL) { 00075 rptParsers[i].rptId = id; 00076 rptParsers[i].rptParser = prs; 00077 return true; 00078 } 00079 } 00080 return false; 00081 } 00082 00083 HIDReportParser* HIDComposite::GetReportParser(uint8_t id) { 00084 if(!bHasReportId) 00085 return ((rptParsers[0].rptParser) ? rptParsers[0].rptParser : NULL); 00086 00087 for(uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) { 00088 if(rptParsers[i].rptId == id) 00089 return rptParsers[i].rptParser; 00090 } 00091 return NULL; 00092 } 00093 00094 uint8_t HIDComposite::Init(uint8_t parent, uint8_t port, bool lowspeed) { 00095 const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR); 00096 00097 uint8_t buf[constBufSize]; 00098 USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf); 00099 uint8_t rcode; 00100 UsbDevice *p = NULL; 00101 EpInfo *oldep_ptr = NULL; 00102 uint8_t len = 0; 00103 00104 uint8_t num_of_conf; // number of configurations 00105 //uint8_t num_of_intf; // number of interfaces 00106 00107 AddressPool &addrPool = pUsb->GetAddressPool(); 00108 00109 USBTRACE("HU Init\r\n"); 00110 00111 if(bAddress) 00112 return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; 00113 00114 // Get pointer to pseudo device with address 0 assigned 00115 p = addrPool.GetUsbDevicePtr(0); 00116 00117 if(!p) 00118 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; 00119 00120 if(!p->epinfo) { 00121 USBTRACE("epinfo\r\n"); 00122 return USB_ERROR_EPINFO_IS_NULL; 00123 } 00124 00125 // Save old pointer to EP_RECORD of address 0 00126 oldep_ptr = p->epinfo; 00127 00128 // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence 00129 p->epinfo = epInfo; 00130 00131 p->lowspeed = lowspeed; 00132 00133 // Get device descriptor 00134 rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*)buf); 00135 00136 if(!rcode) 00137 len = (buf[0] > constBufSize) ? constBufSize : buf[0]; 00138 00139 if(rcode) { 00140 // Restore p->epinfo 00141 p->epinfo = oldep_ptr; 00142 00143 goto FailGetDevDescr; 00144 } 00145 00146 // Restore p->epinfo 00147 p->epinfo = oldep_ptr; 00148 00149 // Allocate new address according to device class 00150 bAddress = addrPool.AllocAddress(parent, false, port); 00151 00152 if(!bAddress) 00153 return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; 00154 00155 // Extract Max Packet Size from the device descriptor 00156 epInfo[0].maxPktSize = udd->bMaxPacketSize0; 00157 00158 // Assign new address to the device 00159 rcode = pUsb->setAddr(0, 0, bAddress); 00160 00161 if(rcode) { 00162 p->lowspeed = false; 00163 addrPool.FreeAddress(bAddress); 00164 bAddress = 0; 00165 USBTRACE2("setAddr:", rcode); 00166 return rcode; 00167 } 00168 00169 //delay(2); //per USB 2.0 sect.9.2.6.3 00170 00171 USBTRACE2("Addr:", bAddress); 00172 00173 p->lowspeed = false; 00174 00175 p = addrPool.GetUsbDevicePtr(bAddress); 00176 00177 if(!p) 00178 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; 00179 00180 p->lowspeed = lowspeed; 00181 00182 if(len) 00183 rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*)buf); 00184 00185 if(rcode) 00186 goto FailGetDevDescr; 00187 00188 VID = udd->idVendor; // Can be used by classes that inherits this class to check the VID and PID of the connected device 00189 PID = udd->idProduct; 00190 00191 num_of_conf = udd->bNumConfigurations; 00192 00193 // Assign epInfo to epinfo pointer 00194 rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); 00195 00196 if(rcode) 00197 goto FailSetDevTblEntry; 00198 00199 USBTRACE2("NC:", num_of_conf); 00200 00201 for(uint8_t i = 0; i < num_of_conf; i++) { 00202 //HexDumper<USBReadParser, uint16_t, uint16_t> HexDump; 00203 ConfigDescParser<USB_CLASS_HID, 0, 0, 00204 CP_MASK_COMPARE_CLASS> confDescrParser(this); 00205 00206 //rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump); 00207 rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); 00208 00209 if(rcode) 00210 goto FailGetConfDescr; 00211 00212 if(bNumEP > 1) 00213 break; 00214 } // for 00215 00216 if(bNumEP < 2) 00217 return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; 00218 00219 // Assign epInfo to epinfo pointer 00220 rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); 00221 00222 USBTRACE2("Cnf:", bConfNum); 00223 00224 // Set Configuration Value 00225 rcode = pUsb->setConf(bAddress, 0, bConfNum); 00226 00227 if(rcode) 00228 goto FailSetConfDescr; 00229 00230 USBTRACE2("NumIface:", bNumIface); 00231 00232 for(uint8_t i = 0; i < bNumIface; i++) { 00233 if(hidInterfaces[i].epIndex[epInterruptInIndex] == 0) 00234 continue; 00235 00236 USBTRACE2("SetIdle:", hidInterfaces[i].bmInterface); 00237 00238 rcode = SetIdle(hidInterfaces[i].bmInterface, 0, 0); 00239 00240 if(rcode && rcode != hrSTALL) 00241 goto FailSetIdle; 00242 } 00243 00244 USBTRACE("HU configured\r\n"); 00245 00246 OnInitSuccessful(); 00247 00248 bPollEnable = true; 00249 return 0; 00250 00251 FailGetDevDescr: 00252 #ifdef DEBUG_USB_HOST 00253 NotifyFailGetDevDescr(); 00254 goto Fail; 00255 #endif 00256 00257 FailSetDevTblEntry: 00258 #ifdef DEBUG_USB_HOST 00259 NotifyFailSetDevTblEntry(); 00260 goto Fail; 00261 #endif 00262 00263 FailGetConfDescr: 00264 #ifdef DEBUG_USB_HOST 00265 NotifyFailGetConfDescr(); 00266 goto Fail; 00267 #endif 00268 00269 FailSetConfDescr: 00270 #ifdef DEBUG_USB_HOST 00271 NotifyFailSetConfDescr(); 00272 goto Fail; 00273 #endif 00274 00275 00276 FailSetIdle: 00277 #ifdef DEBUG_USB_HOST 00278 USBTRACE("SetIdle:"); 00279 #endif 00280 00281 #ifdef DEBUG_USB_HOST 00282 Fail: 00283 NotifyFail(rcode); 00284 #endif 00285 Release(); 00286 return rcode; 00287 } 00288 00289 HIDComposite::HIDInterface* HIDComposite::FindInterface(uint8_t iface, uint8_t alt, uint8_t proto) { 00290 for(uint8_t i = 0; i < bNumIface && i < maxHidInterfaces; i++) 00291 if(hidInterfaces[i].bmInterface == iface && hidInterfaces[i].bmAltSet == alt 00292 && hidInterfaces[i].bmProtocol == proto) 00293 return hidInterfaces + i; 00294 return NULL; 00295 } 00296 00297 void HIDComposite::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) { 00298 //ErrorMessage<uint8_t>(PSTR("\r\nConf.Val"), conf); 00299 //ErrorMessage<uint8_t>(PSTR("Iface Num"), iface); 00300 //ErrorMessage<uint8_t>(PSTR("Alt.Set"), alt); 00301 00302 bConfNum = conf; 00303 00304 uint8_t index = 0; 00305 HIDInterface *piface = FindInterface(iface, alt, proto); 00306 00307 // Fill in interface structure in case of new interface 00308 if(!piface) { 00309 piface = hidInterfaces + bNumIface; 00310 piface->bmInterface = iface; 00311 piface->bmAltSet = alt; 00312 piface->bmProtocol = proto; 00313 bNumIface++; 00314 } 00315 00316 if((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_INTERRUPT) 00317 index = (pep->bEndpointAddress & 0x80) == 0x80 ? epInterruptInIndex : epInterruptOutIndex; 00318 00319 if(!SelectInterface(iface, proto)) 00320 index = 0; 00321 00322 if(index) { 00323 // Fill in the endpoint info structure 00324 epInfo[bNumEP].epAddr = (pep->bEndpointAddress & 0x0F); 00325 epInfo[bNumEP].maxPktSize = (uint8_t)pep->wMaxPacketSize; 00326 epInfo[bNumEP].bmSndToggle = 0; 00327 epInfo[bNumEP].bmRcvToggle = 0; 00328 epInfo[bNumEP].bmNakPower = USB_NAK_NOWAIT; 00329 00330 // Fill in the endpoint index list 00331 piface->epIndex[index] = bNumEP; //(pep->bEndpointAddress & 0x0F); 00332 00333 if(pollInterval < pep->bInterval) // Set the polling interval as the largest polling interval obtained from endpoints 00334 pollInterval = pep->bInterval; 00335 00336 bNumEP++; 00337 } 00338 } 00339 00340 uint8_t HIDComposite::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 void HIDComposite::ZeroMemory(uint8_t len, uint8_t *buf) { 00351 for(uint8_t i = 0; i < len; i++) 00352 buf[i] = 0; 00353 } 00354 00355 uint8_t HIDComposite::Poll() { 00356 uint8_t rcode = 0; 00357 00358 if(!bPollEnable) 00359 return 0; 00360 00361 if((int32_t)((uint32_t)millis() - qNextPollTime) >= 0L) { 00362 qNextPollTime = (uint32_t)millis() + pollInterval; 00363 00364 uint8_t buf[constBuffLen]; 00365 00366 for(uint8_t i = 0; i < bNumIface; i++) { 00367 uint8_t index = hidInterfaces[i].epIndex[epInterruptInIndex]; 00368 00369 if (index == 0) 00370 continue; 00371 00372 uint16_t read = (uint16_t)epInfo[index].maxPktSize; 00373 00374 ZeroMemory(constBuffLen, buf); 00375 00376 uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[index].epAddr, &read, buf); 00377 00378 if(rcode) { 00379 if(rcode != hrNAK) 00380 USBTRACE3("(hidcomposite.h) Poll:", rcode, 0x81); 00381 continue; 00382 } 00383 00384 if(read == 0) 00385 continue; 00386 00387 if(read > constBuffLen) 00388 read = constBuffLen; 00389 00390 #if 0 00391 Notify(PSTR("\r\nBuf: "), 0x80); 00392 00393 for(uint8_t i = 0; i < read; i++) { 00394 D_PrintHex<uint8_t > (buf[i], 0x80); 00395 Notify(PSTR(" "), 0x80); 00396 } 00397 00398 Notify(PSTR("\r\n"), 0x80); 00399 #endif 00400 ParseHIDData(this, epInfo[index].epAddr, bHasReportId, (uint8_t)read, buf); 00401 00402 HIDReportParser *prs = GetReportParser(((bHasReportId) ? *buf : 0)); 00403 00404 if(prs) 00405 prs->Parse(this, bHasReportId, (uint8_t)read, buf); 00406 } 00407 00408 } 00409 return rcode; 00410 } 00411 00412 // Send a report to interrupt out endpoint. This is NOT SetReport() request! 00413 uint8_t HIDComposite::SndRpt(uint16_t nbytes, uint8_t *dataptr) { 00414 return pUsb->outTransfer(bAddress, epInfo[epInterruptOutIndex].epAddr, nbytes, dataptr); 00415 } 00416
Generated on Thu Jul 14 2022 08:33:41 by
1.7.2