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
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 }
Generated on Tue Jul 12 2022 18:12:04 by
1.7.2