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  USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
81  uint8_t rcode;
82  UsbDevice *p = NULL;
83  EpInfo *oldep_ptr = NULL;
84  uint8_t len = 0;
85 
86  uint8_t num_of_conf; // number of configurations
87  //uint8_t num_of_intf; // number of interfaces
88 
89  AddressPool &addrPool = pUsb->GetAddressPool();
90 
91  USBTRACE("HU Init\r\n");
92 
93  if(bAddress)
95 
96  // Get pointer to pseudo device with address 0 assigned
97  p = addrPool.GetUsbDevicePtr(0);
98 
99  if(!p)
101 
102  if(!p->epinfo) {
103  USBTRACE("epinfo\r\n");
105  }
106 
107  // Save old pointer to EP_RECORD of address 0
108  oldep_ptr = p->epinfo;
109 
110  // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
111  p->epinfo = epInfo;
112 
113  p->lowspeed = lowspeed;
114 
115  // Get device descriptor
116  rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*)buf);
117 
118  if(!rcode)
119  len = (buf[0] > constBufSize) ? constBufSize : buf[0];
120 
121  if(rcode) {
122  // Restore p->epinfo
123  p->epinfo = oldep_ptr;
124 
125  goto FailGetDevDescr;
126  }
127 
128  // Restore p->epinfo
129  p->epinfo = oldep_ptr;
130 
131  // Allocate new address according to device class
132  bAddress = addrPool.AllocAddress(parent, false, port);
133 
134  if(!bAddress)
136 
137  // Extract Max Packet Size from the device descriptor
138  epInfo[0].maxPktSize = udd->bMaxPacketSize0;
139 
140  // Assign new address to the device
141  rcode = pUsb->setAddr(0, 0, bAddress);
142 
143  if(rcode) {
144  p->lowspeed = false;
145  addrPool.FreeAddress(bAddress);
146  bAddress = 0;
147  USBTRACE2("setAddr:", rcode);
148  return rcode;
149  }
150 
151  //delay(2); //per USB 2.0 sect.9.2.6.3
152 
153  USBTRACE2("Addr:", bAddress);
154 
155  p->lowspeed = false;
156 
157  p = addrPool.GetUsbDevicePtr(bAddress);
158 
159  if(!p)
161 
162  p->lowspeed = lowspeed;
163 
164  if(len)
165  rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*)buf);
166 
167  if(rcode)
168  goto FailGetDevDescr;
169 
170  num_of_conf = udd->bNumConfigurations;
171 
172  // Assign epInfo to epinfo pointer
173  rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
174 
175  if(rcode)
176  goto FailSetDevTblEntry;
177 
178  USBTRACE2("NC:", num_of_conf);
179 
180  for(uint8_t i = 0; i < num_of_conf; i++) {
181  //HexDumper<USBReadParser, uint16_t, uint16_t> HexDump;
183  CP_MASK_COMPARE_CLASS> confDescrParser(this);
184 
185  //rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump);
186  rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
187 
188  if(rcode)
189  goto FailGetConfDescr;
190 
191  if(bNumEP > 1)
192  break;
193  } // for
194 
195  if(bNumEP < 2)
197 
198  // Assign epInfo to epinfo pointer
199  rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);
200 
201  USBTRACE2("\r\nCnf:", bConfNum);
202 
203  // Set Configuration Value
204  rcode = pUsb->setConf(bAddress, 0, bConfNum);
205 
206  if(rcode)
207  goto FailSetConfDescr;
208 
209  for(uint8_t i = 0; i < bNumIface; i++) {
210  if(hidInterfaces[i].epIndex[epInterruptInIndex] == 0)
211  continue;
212 
213  rcode = SetIdle(hidInterfaces[i].bmInterface, 0, 0);
214 
215  if(rcode && rcode != hrSTALL)
216  goto FailSetIdle;
217  }
218 
219  USBTRACE("HU configured\r\n");
220 
222 
223  bPollEnable = true;
224  return 0;
225 
226 FailGetDevDescr:
227 #ifdef DEBUG_USB_HOST
229  goto Fail;
230 #endif
231 
232 FailSetDevTblEntry:
233 #ifdef DEBUG_USB_HOST
235  goto Fail;
236 #endif
237 
238 FailGetConfDescr:
239 #ifdef DEBUG_USB_HOST
241  goto Fail;
242 #endif
243 
244 FailSetConfDescr:
245 #ifdef DEBUG_USB_HOST
247  goto Fail;
248 #endif
249 
250 
251 FailSetIdle:
252 #ifdef DEBUG_USB_HOST
253  USBTRACE("SetIdle:");
254 #endif
255 
256 #ifdef DEBUG_USB_HOST
257 Fail:
258  NotifyFail(rcode);
259 #endif
260  Release();
261  return rcode;
262 }
263 
264 HIDUniversal::HIDInterface* HIDUniversal::FindInterface(uint8_t iface, uint8_t alt, uint8_t proto) {
265  for(uint8_t i = 0; i < bNumIface && i < maxHidInterfaces; i++)
266  if(hidInterfaces[i].bmInterface == iface && hidInterfaces[i].bmAltSet == alt
267  && hidInterfaces[i].bmProtocol == proto)
268  return hidInterfaces + i;
269  return NULL;
270 }
271 
272 void HIDUniversal::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) {
273  // If the first configuration satisfies, the others are not concidered.
274  if(bNumEP > 1 && conf != bConfNum)
275  return;
276 
277  //ErrorMessage<uint8_t>(PSTR("\r\nConf.Val"), conf);
278  //ErrorMessage<uint8_t>(PSTR("Iface Num"), iface);
279  //ErrorMessage<uint8_t>(PSTR("Alt.Set"), alt);
280 
281  bConfNum = conf;
282 
283  uint8_t index = 0;
284  HIDInterface *piface = FindInterface(iface, alt, proto);
285 
286  // Fill in interface structure in case of new interface
287  if(!piface) {
288  piface = hidInterfaces + bNumIface;
289  piface->bmInterface = iface;
290  piface->bmAltSet = alt;
291  piface->bmProtocol = proto;
292  bNumIface++;
293  }
294 
295  if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80)
296  index = epInterruptInIndex;
297  else
298  index = epInterruptOutIndex;
299 
300  if(index) {
301  // Fill in the endpoint info structure
302  epInfo[bNumEP].epAddr = (pep->bEndpointAddress & 0x0F);
303  epInfo[bNumEP].maxPktSize = (uint8_t)pep->wMaxPacketSize;
304  epInfo[bNumEP].epAttribs = 0;
305  epInfo[bNumEP].bmNakPower = USB_NAK_NOWAIT;
306 
307  // Fill in the endpoint index list
308  piface->epIndex[index] = bNumEP; //(pep->bEndpointAddress & 0x0F);
309 
310  bNumEP++;
311  }
312  //PrintEndpointDescriptor(pep);
313 }
314 
317 
318  bNumEP = 1;
319  bAddress = 0;
320  qNextPollTime = 0;
321  bPollEnable = false;
322  return 0;
323 }
324 
325 bool HIDUniversal::BuffersIdentical(uint8_t len, uint8_t *buf1, uint8_t *buf2) {
326  for(uint8_t i = 0; i < len; i++)
327  if(buf1[i] != buf2[i])
328  return false;
329  return true;
330 }
331 
332 void HIDUniversal::ZeroMemory(uint8_t len, uint8_t *buf) {
333  for(uint8_t i = 0; i < len; i++)
334  buf[i] = 0;
335 }
336 
337 void HIDUniversal::SaveBuffer(uint8_t len, uint8_t *src, uint8_t *dest) {
338  for(uint8_t i = 0; i < len; i++)
339  dest[i] = src[i];
340 }
341 
343  uint8_t rcode = 0;
344 
345  if(!bPollEnable)
346  return 0;
347 
348  if(qNextPollTime <= millis()) {
349  qNextPollTime = millis() + 50;
350 
351  uint8_t buf[constBuffLen];
352 
353  for(uint8_t i = 0; i < bNumIface; i++) {
354  uint8_t index = hidInterfaces[i].epIndex[epInterruptInIndex];
355  uint16_t read = (uint16_t)epInfo[index].maxPktSize;
356 
357  ZeroMemory(constBuffLen, buf);
358 
359  uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[index].epAddr, &read, buf);
360 
361  if(rcode) {
362  if(rcode != hrNAK)
363  USBTRACE3("(hiduniversal.h) Poll:", rcode, 0x81);
364  return rcode;
365  }
366 
367  if(read > constBuffLen)
368  read = constBuffLen;
369 
370  bool identical = BuffersIdentical(read, buf, prevBuf);
371 
372  SaveBuffer(read, buf, prevBuf);
373 
374  if(identical)
375  return 0;
376 
377  Notify(PSTR("\r\nBuf: "), 0x80);
378 
379  for(uint8_t i = 0; i < read; i++)
380  D_PrintHex<uint8_t > (buf[i], 0x80);
381 
382  Notify(PSTR("\r\n"), 0x80);
383 
384  HIDReportParser *prs = GetReportParser(((bHasReportId) ? *buf : 0));
385 
386  if(prs)
387  prs->Parse(this, bHasReportId, (uint8_t)read, buf);
388  }
389  }
390  return rcode;
391 }
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:51
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
virtual uint8_t OnInitSuccessful()
Definition: hiduniversal.h:56
#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
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
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