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 bPollEnable(false),
7 bHasReportId(false) {
8  Initialize();
9 
10  if (pUsb)
12 }
13 
14 uint16_t HIDUniversal::GetHidClassDescrLen(uint8_t type, uint8_t num) {
15  for (uint8_t i = 0, n = 0; i < HID_MAX_HID_CLASS_DESCRIPTORS; i++) {
16  if (descrInfo[i].bDescrType == type) {
17  if (n == num)
18  return descrInfo[i].wDescriptorLength;
19  n++;
20  }
21  }
22  return 0;
23 }
24 
25 void HIDUniversal::Initialize() {
26  for (uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) {
27  rptParsers[i].rptId = 0;
28  rptParsers[i].rptParser = NULL;
29  }
30  for (uint8_t i = 0; i < HID_MAX_HID_CLASS_DESCRIPTORS; i++) {
31  descrInfo[i].bDescrType = 0;
32  descrInfo[i].wDescriptorLength = 0;
33  }
34  for (uint8_t i = 0; i < maxHidInterfaces; i++) {
35  hidInterfaces[i].bmInterface = 0;
36  hidInterfaces[i].bmProtocol = 0;
37 
38  for (uint8_t j = 0; j < maxEpPerInterface; j++)
39  hidInterfaces[i].epIndex[j] = 0;
40  }
41  for (uint8_t i = 0; i < totalEndpoints; i++) {
42  epInfo[i].epAddr = 0;
43  epInfo[i].maxPktSize = (i) ? 0 : 8;
44  epInfo[i].epAttribs = 0;
45  epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
46  }
47  bNumEP = 1;
48  bNumIface = 0;
49  bConfNum = 0;
50 
51  ZeroMemory(constBuffLen, prevBuf);
52 }
53 
55  for (uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) {
56  if (rptParsers[i].rptId == 0 && rptParsers[i].rptParser == NULL) {
57  rptParsers[i].rptId = id;
58  rptParsers[i].rptParser = prs;
59  return true;
60  }
61  }
62  return false;
63 }
64 
66  if (!bHasReportId)
67  return ((rptParsers[0].rptParser) ? rptParsers[0].rptParser : NULL);
68 
69  for (uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) {
70  if (rptParsers[i].rptId == id)
71  return rptParsers[i].rptParser;
72  }
73  return NULL;
74 }
75 
76 uint8_t HIDUniversal::Init(uint8_t parent, uint8_t port, bool lowspeed) {
77  const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);
78 
79  uint8_t buf[constBufSize];
80  uint8_t rcode;
81  UsbDevice *p = NULL;
82  EpInfo *oldep_ptr = NULL;
83  uint8_t len = 0;
84 
85  uint8_t num_of_conf; // number of configurations
86  //uint8_t num_of_intf; // number of interfaces
87 
88  AddressPool &addrPool = pUsb->GetAddressPool();
89 
90  USBTRACE("HU Init\r\n");
91 
92  if (bAddress)
94 
95  // Get pointer to pseudo device with address 0 assigned
96  p = addrPool.GetUsbDevicePtr(0);
97 
98  if (!p)
100 
101  if (!p->epinfo) {
102  USBTRACE("epinfo\r\n");
104  }
105 
106  // Save old pointer to EP_RECORD of address 0
107  oldep_ptr = p->epinfo;
108 
109  // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
110  p->epinfo = epInfo;
111 
112  p->lowspeed = lowspeed;
113 
114  // Get device descriptor
115  rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*)buf);
116 
117  if (!rcode)
118  len = (buf[0] > constBufSize) ? constBufSize : buf[0];
119 
120  if (rcode) {
121  // Restore p->epinfo
122  p->epinfo = oldep_ptr;
123 
124  goto FailGetDevDescr;
125  }
126 
127  // Restore p->epinfo
128  p->epinfo = oldep_ptr;
129 
130  // Allocate new address according to device class
131  bAddress = addrPool.AllocAddress(parent, false, port);
132 
133  if (!bAddress)
135 
136  // Extract Max Packet Size from the device descriptor
137  epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0;
138 
139  // Assign new address to the device
140  rcode = pUsb->setAddr(0, 0, bAddress);
141 
142  if (rcode) {
143  p->lowspeed = false;
144  addrPool.FreeAddress(bAddress);
145  bAddress = 0;
146  USBTRACE2("setAddr:", rcode);
147  return rcode;
148  }
149 
150  USBTRACE2("Addr:", bAddress);
151 
152  p->lowspeed = false;
153 
154  p = addrPool.GetUsbDevicePtr(bAddress);
155 
156  if (!p)
158 
159  p->lowspeed = lowspeed;
160 
161  if (len)
162  rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*)buf);
163 
164  if (rcode)
165  goto FailGetDevDescr;
166 
167  num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations;
168 
169  // Assign epInfo to epinfo pointer
170  rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
171 
172  if (rcode)
173  goto FailSetDevTblEntry;
174 
175  USBTRACE2("NC:", num_of_conf);
176 
177  for (uint8_t i = 0; i < num_of_conf; i++) {
178  //HexDumper<USBReadParser, uint16_t, uint16_t> HexDump;
180  CP_MASK_COMPARE_CLASS> confDescrParser(this);
181 
182  //rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump);
183  rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
184 
185  if (rcode)
186  goto FailGetConfDescr;
187 
188  if (bNumEP > 1)
189  break;
190  } // for
191 
192  if (bNumEP < 2)
194 
195  // Assign epInfo to epinfo pointer
196  rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);
197 
198  USBTRACE2("\r\nCnf:", bConfNum);
199 
200  // Set Configuration Value
201  rcode = pUsb->setConf(bAddress, 0, bConfNum);
202 
203  if (rcode)
204  goto FailSetConfDescr;
205 
206  for (uint8_t i = 0; i < bNumIface; i++) {
207  if (hidInterfaces[i].epIndex[epInterruptInIndex] == 0)
208  continue;
209 
210  rcode = SetIdle(hidInterfaces[i].bmInterface, 0, 0);
211 
212  if (rcode && rcode != hrSTALL)
213  goto FailSetIdle;
214  }
215 
216  USBTRACE("HU configured\r\n");
217 
219 
220  bPollEnable = true;
221  return 0;
222 
223 FailGetDevDescr:
224 #ifdef DEBUG_USB_HOST
226  goto Fail;
227 #endif
228 
229 FailSetDevTblEntry:
230 #ifdef DEBUG_USB_HOST
232  goto Fail;
233 #endif
234 
235 FailGetConfDescr:
236 #ifdef DEBUG_USB_HOST
238  goto Fail;
239 #endif
240 
241 FailSetConfDescr:
242 #ifdef DEBUG_USB_HOST
244  goto Fail;
245 #endif
246 
247 
248 FailSetIdle:
249 #ifdef DEBUG_USB_HOST
250  USBTRACE("SetIdle:");
251 #endif
252 
253 Fail:
254 #ifdef DEBUG_USB_HOST
255  NotifyFail(rcode);
256 #endif
257  Release();
258  return rcode;
259 }
260 
261 HIDUniversal::HIDInterface* HIDUniversal::FindInterface(uint8_t iface, uint8_t alt, uint8_t proto) {
262  for (uint8_t i = 0; i < bNumIface && i < maxHidInterfaces; i++)
263  if (hidInterfaces[i].bmInterface == iface && hidInterfaces[i].bmAltSet == alt
264  && hidInterfaces[i].bmProtocol == proto)
265  return hidInterfaces + i;
266  return NULL;
267 }
268 
269 void HIDUniversal::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) {
270  // If the first configuration satisfies, the others are not concidered.
271  if (bNumEP > 1 && conf != bConfNum)
272  return;
273 
274  //ErrorMessage<uint8_t>(PSTR("\r\nConf.Val"), conf);
275  //ErrorMessage<uint8_t>(PSTR("Iface Num"), iface);
276  //ErrorMessage<uint8_t>(PSTR("Alt.Set"), alt);
277 
278  bConfNum = conf;
279 
280  uint8_t index = 0;
281  HIDInterface *piface = FindInterface(iface, alt, proto);
282 
283  // Fill in interface structure in case of new interface
284  if (!piface) {
285  piface = hidInterfaces + bNumIface;
286  piface->bmInterface = iface;
287  piface->bmAltSet = alt;
288  piface->bmProtocol = proto;
289  bNumIface++;
290  }
291 
292  if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80)
293  index = epInterruptInIndex;
294  else
295  index = epInterruptOutIndex;
296 
297  if (index) {
298  // Fill in the endpoint info structure
299  epInfo[bNumEP].epAddr = (pep->bEndpointAddress & 0x0F);
300  epInfo[bNumEP].maxPktSize = (uint8_t)pep->wMaxPacketSize;
301  epInfo[bNumEP].epAttribs = 0;
302  epInfo[bNumEP].bmNakPower = USB_NAK_NOWAIT;
303 
304  // Fill in the endpoint index list
305  piface->epIndex[index] = bNumEP; //(pep->bEndpointAddress & 0x0F);
306 
307  bNumEP++;
308  }
309  //PrintEndpointDescriptor(pep);
310 }
311 
314 
315  bNumEP = 1;
316  bAddress = 0;
317  qNextPollTime = 0;
318  bPollEnable = false;
319  return 0;
320 }
321 
322 bool HIDUniversal::BuffersIdentical(uint8_t len, uint8_t *buf1, uint8_t *buf2) {
323  for (uint8_t i = 0; i < len; i++)
324  if (buf1[i] != buf2[i])
325  return false;
326  return true;
327 }
328 
329 void HIDUniversal::ZeroMemory(uint8_t len, uint8_t *buf) {
330  for (uint8_t i = 0; i < len; i++)
331  buf[i] = 0;
332 }
333 
334 void HIDUniversal::SaveBuffer(uint8_t len, uint8_t *src, uint8_t *dest) {
335  for (uint8_t i = 0; i < len; i++)
336  dest[i] = src[i];
337 }
338 
340  uint8_t rcode = 0;
341 
342  if (!bPollEnable)
343  return 0;
344 
345  if (qNextPollTime <= millis()) {
346  qNextPollTime = millis() + 50;
347 
348  uint8_t buf[constBuffLen];
349 
350  for (uint8_t i = 0; i < bNumIface; i++) {
351  uint8_t index = hidInterfaces[i].epIndex[epInterruptInIndex];
352  uint16_t read = (uint16_t)epInfo[index].maxPktSize;
353 
354  ZeroMemory(constBuffLen, buf);
355 
356  uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[index].epAddr, &read, buf);
357 
358  if (rcode) {
359  if (rcode != hrNAK)
360  USBTRACE2("Poll:", rcode);
361  return rcode;
362  }
363 
364  if (read > constBuffLen)
365  read = constBuffLen;
366 
367  bool identical = BuffersIdentical(read, buf, prevBuf);
368 
369  SaveBuffer(read, buf, prevBuf);
370 
371  if (identical)
372  return 0;
373 
374  Notify(PSTR("\r\nBuf: "), 0x80);
375 
376  for (uint8_t i = 0; i < read; i++)
377  PrintHex<uint8_t > (buf[i], 0x80);
378 
379  Notify(PSTR("\r\n"), 0x80);
380 
381  HIDReportParser *prs = GetReportParser(((bHasReportId) ? *buf : 0));
382 
383  if (prs)
384  prs->Parse(this, bHasReportId, (uint8_t)read, buf);
385  }
386  }
387  return rcode;
388 }