USB Host Shield 2.0
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
hiduniversal.cpp
Go to the documentation of this file.
1 #include "hiduniversal.h"
2 
4 HID(p),
5 qNextPollTime(0),
6 pollInterval(0),
7 bPollEnable(false),
8 bHasReportId(false) {
9  Initialize();
10 
11  if(pUsb)
13 }
14 
15 uint16_t HIDUniversal::GetHidClassDescrLen(uint8_t type, uint8_t num) {
16  for(uint8_t i = 0, n = 0; i < HID_MAX_HID_CLASS_DESCRIPTORS; i++) {
17  if(descrInfo[i].bDescrType == type) {
18  if(n == num)
19  return descrInfo[i].wDescriptorLength;
20  n++;
21  }
22  }
23  return 0;
24 }
25 
26 void HIDUniversal::Initialize() {
27  for(uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) {
28  rptParsers[i].rptId = 0;
29  rptParsers[i].rptParser = NULL;
30  }
31  for(uint8_t i = 0; i < HID_MAX_HID_CLASS_DESCRIPTORS; i++) {
32  descrInfo[i].bDescrType = 0;
33  descrInfo[i].wDescriptorLength = 0;
34  }
35  for(uint8_t i = 0; i < maxHidInterfaces; i++) {
36  hidInterfaces[i].bmInterface = 0;
37  hidInterfaces[i].bmProtocol = 0;
38 
39  for(uint8_t j = 0; j < maxEpPerInterface; j++)
40  hidInterfaces[i].epIndex[j] = 0;
41  }
42  for(uint8_t i = 0; i < totalEndpoints; i++) {
43  epInfo[i].epAddr = 0;
44  epInfo[i].maxPktSize = (i) ? 0 : 8;
45  epInfo[i].epAttribs = 0;
46  epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
47  }
48  bNumEP = 1;
49  bNumIface = 0;
50  bConfNum = 0;
51  pollInterval = 0;
52 
53  ZeroMemory(constBuffLen, prevBuf);
54 }
55 
57  for(uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) {
58  if(rptParsers[i].rptId == 0 && rptParsers[i].rptParser == NULL) {
59  rptParsers[i].rptId = id;
60  rptParsers[i].rptParser = prs;
61  return true;
62  }
63  }
64  return false;
65 }
66 
68  if(!bHasReportId)
69  return ((rptParsers[0].rptParser) ? rptParsers[0].rptParser : NULL);
70 
71  for(uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) {
72  if(rptParsers[i].rptId == id)
73  return rptParsers[i].rptParser;
74  }
75  return NULL;
76 }
77 
78 uint8_t HIDUniversal::Init(uint8_t parent, uint8_t port, bool lowspeed) {
79  const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);
80 
81  uint8_t buf[constBufSize];
82  USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
83  uint8_t rcode;
84  UsbDevice *p = NULL;
85  EpInfo *oldep_ptr = NULL;
86  uint8_t len = 0;
87 
88  uint8_t num_of_conf; // number of configurations
89  //uint8_t num_of_intf; // number of interfaces
90 
91  AddressPool &addrPool = pUsb->GetAddressPool();
92 
93  USBTRACE("HU Init\r\n");
94 
95  if(bAddress)
97 
98  // Get pointer to pseudo device with address 0 assigned
99  p = addrPool.GetUsbDevicePtr(0);
100 
101  if(!p)
103 
104  if(!p->epinfo) {
105  USBTRACE("epinfo\r\n");
107  }
108 
109  // Save old pointer to EP_RECORD of address 0
110  oldep_ptr = p->epinfo;
111 
112  // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
113  p->epinfo = epInfo;
114 
115  p->lowspeed = lowspeed;
116 
117  // Get device descriptor
118  rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*)buf);
119 
120  if(!rcode)
121  len = (buf[0] > constBufSize) ? constBufSize : buf[0];
122 
123  if(rcode) {
124  // Restore p->epinfo
125  p->epinfo = oldep_ptr;
126 
127  goto FailGetDevDescr;
128  }
129 
130  // Restore p->epinfo
131  p->epinfo = oldep_ptr;
132 
133  // Allocate new address according to device class
134  bAddress = addrPool.AllocAddress(parent, false, port);
135 
136  if(!bAddress)
138 
139  // Extract Max Packet Size from the device descriptor
140  epInfo[0].maxPktSize = udd->bMaxPacketSize0;
141 
142  // Assign new address to the device
143  rcode = pUsb->setAddr(0, 0, bAddress);
144 
145  if(rcode) {
146  p->lowspeed = false;
147  addrPool.FreeAddress(bAddress);
148  bAddress = 0;
149  USBTRACE2("setAddr:", rcode);
150  return rcode;
151  }
152 
153  //delay(2); //per USB 2.0 sect.9.2.6.3
154 
155  USBTRACE2("Addr:", bAddress);
156 
157  p->lowspeed = false;
158 
159  p = addrPool.GetUsbDevicePtr(bAddress);
160 
161  if(!p)
163 
164  p->lowspeed = lowspeed;
165 
166  if(len)
167  rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*)buf);
168 
169  if(rcode)
170  goto FailGetDevDescr;
171 
172  VID = udd->idVendor; // Can be used by classes that inherits this class to check the VID and PID of the connected device
173  PID = udd->idProduct;
174 
175  num_of_conf = udd->bNumConfigurations;
176 
177  // Assign epInfo to epinfo pointer
178  rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
179 
180  if(rcode)
181  goto FailSetDevTblEntry;
182 
183  USBTRACE2("NC:", num_of_conf);
184 
185  for(uint8_t i = 0; i < num_of_conf; i++) {
186  //HexDumper<USBReadParser, uint16_t, uint16_t> HexDump;
188  CP_MASK_COMPARE_CLASS> confDescrParser(this);
189 
190  //rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump);
191  rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
192 
193  if(rcode)
194  goto FailGetConfDescr;
195 
196  if(bNumEP > 1)
197  break;
198  } // for
199 
200  if(bNumEP < 2)
202 
203  // Assign epInfo to epinfo pointer
204  rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);
205 
206  USBTRACE2("Cnf:", bConfNum);
207 
208  // Set Configuration Value
209  rcode = pUsb->setConf(bAddress, 0, bConfNum);
210 
211  if(rcode)
212  goto FailSetConfDescr;
213 
214  for(uint8_t i = 0; i < bNumIface; i++) {
215  if(hidInterfaces[i].epIndex[epInterruptInIndex] == 0)
216  continue;
217 
218  rcode = SetIdle(hidInterfaces[i].bmInterface, 0, 0);
219 
220  if(rcode && rcode != hrSTALL)
221  goto FailSetIdle;
222  }
223 
224  USBTRACE("HU configured\r\n");
225 
227 
228  bPollEnable = true;
229  return 0;
230 
231 FailGetDevDescr:
232 #ifdef DEBUG_USB_HOST
234  goto Fail;
235 #endif
236 
237 FailSetDevTblEntry:
238 #ifdef DEBUG_USB_HOST
240  goto Fail;
241 #endif
242 
243 FailGetConfDescr:
244 #ifdef DEBUG_USB_HOST
246  goto Fail;
247 #endif
248 
249 FailSetConfDescr:
250 #ifdef DEBUG_USB_HOST
252  goto Fail;
253 #endif
254 
255 
256 FailSetIdle:
257 #ifdef DEBUG_USB_HOST
258  USBTRACE("SetIdle:");
259 #endif
260 
261 #ifdef DEBUG_USB_HOST
262 Fail:
263  NotifyFail(rcode);
264 #endif
265  Release();
266  return rcode;
267 }
268 
269 HIDUniversal::HIDInterface* HIDUniversal::FindInterface(uint8_t iface, uint8_t alt, uint8_t proto) {
270  for(uint8_t i = 0; i < bNumIface && i < maxHidInterfaces; i++)
271  if(hidInterfaces[i].bmInterface == iface && hidInterfaces[i].bmAltSet == alt
272  && hidInterfaces[i].bmProtocol == proto)
273  return hidInterfaces + i;
274  return NULL;
275 }
276 
277 void HIDUniversal::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) {
278  // If the first configuration satisfies, the others are not concidered.
279  if(bNumEP > 1 && conf != bConfNum)
280  return;
281 
282  //ErrorMessage<uint8_t>(PSTR("\r\nConf.Val"), conf);
283  //ErrorMessage<uint8_t>(PSTR("Iface Num"), iface);
284  //ErrorMessage<uint8_t>(PSTR("Alt.Set"), alt);
285 
286  bConfNum = conf;
287 
288  uint8_t index = 0;
289  HIDInterface *piface = FindInterface(iface, alt, proto);
290 
291  // Fill in interface structure in case of new interface
292  if(!piface) {
293  piface = hidInterfaces + bNumIface;
294  piface->bmInterface = iface;
295  piface->bmAltSet = alt;
296  piface->bmProtocol = proto;
297  bNumIface++;
298  }
299 
300  if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80)
301  index = epInterruptInIndex;
302  else
303  index = epInterruptOutIndex;
304 
305  if(index) {
306  // Fill in the endpoint info structure
307  epInfo[bNumEP].epAddr = (pep->bEndpointAddress & 0x0F);
308  epInfo[bNumEP].maxPktSize = (uint8_t)pep->wMaxPacketSize;
309  epInfo[bNumEP].epAttribs = 0;
310  epInfo[bNumEP].bmNakPower = USB_NAK_NOWAIT;
311 
312  // Fill in the endpoint index list
313  piface->epIndex[index] = bNumEP; //(pep->bEndpointAddress & 0x0F);
314 
315  if(pollInterval < pep->bInterval) // Set the polling interval as the largest polling interval obtained from endpoints
316  pollInterval = pep->bInterval;
317 
318  bNumEP++;
319  }
320  //PrintEndpointDescriptor(pep);
321 }
322 
325 
326  bNumEP = 1;
327  bAddress = 0;
328  qNextPollTime = 0;
329  bPollEnable = false;
330  return 0;
331 }
332 
333 bool HIDUniversal::BuffersIdentical(uint8_t len, uint8_t *buf1, uint8_t *buf2) {
334  for(uint8_t i = 0; i < len; i++)
335  if(buf1[i] != buf2[i])
336  return false;
337  return true;
338 }
339 
340 void HIDUniversal::ZeroMemory(uint8_t len, uint8_t *buf) {
341  for(uint8_t i = 0; i < len; i++)
342  buf[i] = 0;
343 }
344 
345 void HIDUniversal::SaveBuffer(uint8_t len, uint8_t *src, uint8_t *dest) {
346  for(uint8_t i = 0; i < len; i++)
347  dest[i] = src[i];
348 }
349 
351  uint8_t rcode = 0;
352 
353  if(!bPollEnable)
354  return 0;
355 
356  if(qNextPollTime <= millis()) {
357  qNextPollTime = millis() + pollInterval;
358 
359  uint8_t buf[constBuffLen];
360 
361  for(uint8_t i = 0; i < bNumIface; i++) {
362  uint8_t index = hidInterfaces[i].epIndex[epInterruptInIndex];
363  uint16_t read = (uint16_t)epInfo[index].maxPktSize;
364 
365  ZeroMemory(constBuffLen, buf);
366 
367  uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[index].epAddr, &read, buf);
368 
369  if(rcode) {
370  if(rcode != hrNAK)
371  USBTRACE3("(hiduniversal.h) Poll:", rcode, 0x81);
372  return rcode;
373  }
374 
375  if(read > constBuffLen)
376  read = constBuffLen;
377 
378  bool identical = BuffersIdentical(read, buf, prevBuf);
379 
380  SaveBuffer(read, buf, prevBuf);
381 
382  if(identical)
383  return 0;
384 
385  Notify(PSTR("\r\nBuf: "), 0x80);
386 
387  for(uint8_t i = 0; i < read; i++)
388  D_PrintHex<uint8_t > (buf[i], 0x80);
389 
390  Notify(PSTR("\r\n"), 0x80);
391 
392  ParseHIDData(this, bHasReportId, (uint8_t)read, buf);
393 
394  HIDReportParser *prs = GetReportParser(((bHasReportId) ? *buf : 0));
395 
396  if(prs)
397  prs->Parse(this, bHasReportId, (uint8_t)read, buf);
398  }
399  }
400  return rcode;
401 }
uint16_t PID
Definition: hiduniversal.h:54
uint8_t getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t *dataptr)
Definition: Usb.cpp:766
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed)
bool bHasReportId
Definition: hiduniversal.h:52
EpInfo * epinfo
Definition: address.h:76
bool lowspeed
Definition: address.h:79
#define USB_ERROR_EPINFO_IS_NULL
Definition: UsbCore.h:67
#define hrSTALL
Definition: max3421e.h:217
uint8_t bmNakPower
Definition: address.h:42
uint8_t bMaxPacketSize0
Definition: usb_ch9.h:105
#define NotifyFail(...)
Definition: message.h:55
static const uint8_t epInterruptOutIndex
Definition: hid.h:150
uint8_t setConf(uint8_t addr, uint8_t ep, uint8_t conf_value)
Definition: Usb.cpp:805
#define NotifyFailGetDevDescr(...)
Definition: message.h:50
uint8_t bAddress
Definition: hid.h:146
uint8_t setEpInfoEntry(uint8_t addr, uint8_t epcount, EpInfo *eprecord_ptr)
Definition: Usb.cpp:64
virtual uint8_t Release()
#define CP_MASK_COMPARE_CLASS
uint16_t VID
Definition: hiduniversal.h:54
virtual uint8_t OnInitSuccessful()
Definition: hiduniversal.h:59
#define USB_CLASS_HID
Definition: UsbCore.h:43
virtual void FreeAddress(uint8_t addr)=0
virtual uint8_t Poll()
uint8_t epAttribs
Definition: address.h:37
virtual UsbDevice * GetUsbDevicePtr(uint8_t addr)=0
#define Notify(...)
Definition: message.h:44
#define USBTRACE2(s, r)
Definition: macros.h:67
uint8_t setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr)
Definition: Usb.cpp:796
#define NotifyFailGetConfDescr(...)
Definition: message.h:52
virtual void ParseHIDData(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf)
Definition: hiduniversal.h:63
uint8_t epAddr
Definition: address.h:33
#define USB_NAK_MAX_POWER
Definition: address.h:27
virtual HIDReportParser * GetReportParser(uint8_t id)
Definition: address.h:32
virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep)
#define hrNAK
Definition: max3421e.h:216
HIDUniversal(USB *p)
Definition: hiduniversal.cpp:3
uint16_t wMaxPacketSize
Definition: usb_ch9.h:146
Definition: hid.h:143
virtual uint8_t AllocAddress(uint8_t parent, bool is_hub=false, uint8_t port=0)=0
uint8_t bEndpointAddress
Definition: usb_ch9.h:144
#define USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE
Definition: UsbCore.h:69
#define USB_NAK_NOWAIT
Definition: address.h:29
#define USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL
Definition: UsbCore.h:66
virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf)=0
uint8_t inTransfer(uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t *data)
Definition: Usb.cpp:206
#define MAX_REPORT_PARSERS
Definition: hid.h:23
#define USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED
Definition: UsbCore.h:61
USB * pUsb
Definition: hid.h:145
uint8_t SetIdle(uint8_t iface, uint8_t reportID, uint8_t duration)
Definition: hid.cpp:45
uint16_t idProduct
Definition: usb_ch9.h:107
static const uint8_t epInterruptInIndex
Definition: hid.h:149
uint8_t bNumConfigurations
Definition: usb_ch9.h:112
#define USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL
Definition: UsbCore.h:64
uint8_t maxPktSize
Definition: address.h:34
AddressPool & GetAddressPool()
Definition: UsbCore.h:192
Definition: UsbCore.h:176
#define USBTRACE3(s, r, l)
Definition: macros.h:68
uint8_t RegisterDeviceClass(USBDeviceConfig *pdev)
Definition: UsbCore.h:196
static const uint8_t totalEndpoints
Definition: hid.h:154
#define NotifyFailSetConfDescr(...)
Definition: message.h:53
#define HID_MAX_HID_CLASS_DESCRIPTORS
Definition: hid.h:24
static const uint8_t maxEpPerInterface
Definition: hid.h:153
virtual bool SetReportParser(uint8_t id, HIDReportParser *prs)
#define USBTRACE(s)
Definition: macros.h:65
uint8_t getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t *dataptr)
defined(USB_METHODS_INLINE)
Definition: Usb.cpp:761
#define NotifyFailSetDevTblEntry(...)
Definition: message.h:51
static const uint8_t maxHidInterfaces
Definition: hid.h:152