1 /* hidapi_parser $
2 *
3 * Copyright (C) 2013, Marije Baalman <nescivi _at_ gmail.com>
4 * This work was funded by a crowd-funding initiative for SuperCollider's [1] HID implementation
5 * including a substantial donation from BEK, Bergen Center for Electronic Arts, Norway
6 *
7 * [1] http://supercollider.sourceforge.net
8 * [2] http://www.bek.no
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <math.h>
29
30 #ifdef _WIN32
31 #include <windows.h>
32 // for MinGW < 5.3 include locally provided "../windows hidsdi.h" rather
33 // than #include <hidsdi.h>:
34 // #include "../windows/hidsdi.h"
35 #include <hidsdi.h>
36 #endif
37
38 #include "hidapi_parser.h"
39
40
41
42 // SET IN CMAKE
43 // #define DEBUG_PARSER
44
45 //// ---------- HID descriptor parser
46
47 // main items
48 #define HID_INPUT 0x80
49 #define HID_OUTPUT 0x90
50 #define HID_COLLECTION 0xA0
51 #define HID_FEATURE 0xB0
52 #define HID_END_COLLECTION 0xC0
53
54 // HID Report Items from HID 1.11 Section 6.2.2
55 #define HID_USAGE_PAGE 0x04
56 #define HID_USAGE 0x08
57 #define HID_USAGE_MIN 0x18
58 #define HID_USAGE_MAX 0x28
59
60 #define HID_DESIGNATOR_INDEX 0x38
61 #define HID_DESIGNATOR_MIN 0x48
62 #define HID_DESIGNATOR_MAX 0x58
63
64 #define HID_STRING_INDEX 0x78
65 #define HID_STRING_MIN 0x88
66 #define HID_STRING_MAX 0x98
67
68 #define HID_DELIMITER 0xA8
69
70 #define HID_LOGICAL_MIN 0x14
71 #define HID_LOGICAL_MAX 0x24
72
73 #define HID_PHYSICAL_MIN 0x34
74 #define HID_PHYSICAL_MAX 0x44
75
76 #define HID_UNIT_EXPONENT 0x54
77 #define HID_UNIT 0x64
78
79 #define HID_REPORT_SIZE 0x74
80 #define HID_REPORT_ID 0x84
81
82 #define HID_REPORT_COUNT 0x94
83
84 #define HID_PUSH 0xA4
85 #define HID_POP 0xB4
86
87 #define HID_RESERVED 0xC4 // above this it is all reserved
88
89
90 // HID Report Usage Pages from HID Usage Tables 1.12 Section 3, Table 1
91 // #define HID_USAGE_PAGE_GENERICDESKTOP 0x01
92 // #define HID_USAGE_PAGE_KEY_CODES 0x07
93 // #define HID_USAGE_PAGE_LEDS 0x08
94 // #define HID_USAGE_PAGE_BUTTONS 0x09
95
96 // HID Report Usages from HID Usage Tables 1.12 Section 4, Table 6
97 // #define HID_USAGE_POINTER 0x01
98 // #define HID_USAGE_MOUSE 0x02
99 // #define HID_USAGE_JOYSTICK 0x04
100 // #define HID_USAGE_KEYBOARD 0x06
101 // #define HID_USAGE_X 0x30
102 // #define HID_USAGE_Y 0x31
103 // #define HID_USAGE_Z 0x32
104 // #define HID_USAGE_RX 0x33
105 // #define HID_USAGE_RY 0x34
106 // #define HID_USAGE_RZ 0x35
107 // #define HID_USAGE_SLIDER 0x36
108 // #define HID_USAGE_DIAL 0x37
109 // #define HID_USAGE_WHEEL 0x38
110
111
112 // HID Report Collection Types from HID 1.12 6.2.2.6
113 #define HID_COLLECTION_PHYSICAL 0x00
114 #define HID_COLLECTION_APPLICATION 0x01
115 #define HID_COLLECTION_LOGICAL 0x02
116 #define HID_COLLECTION_REPORT 0x03
117 #define HID_COLLECTION_NAMED_ARRAY 0x04
118 #define HID_COLLECTION_USAGE_SWITCH 0x05
119 #define HID_COLLECTION_USAGE_MODIFIER 0x06
120 #define HID_COLLECTION_RESERVED 0x07
121 #define HID_COLLECTION_VENDOR 0x80
122
123 // HID Input/Output/Feature Item Data (attributes) from HID 1.11 6.2.2.5
124 /// more like flags - for input, output, and feature
125 #define HID_ITEM_CONSTANT 0x1 // data(0), constant(1)
126 #define HID_ITEM_VARIABLE 0x2 // array(0), variable(1)
127 #define HID_ITEM_RELATIVE 0x4 // absolute(0), relative(1)
128 #define HID_ITEM_WRAP 0x8 // no wrap(0), wrap(1)
129 #define HID_ITEM_LINEAR 0x10 // linear(0), non linear(1)
130 #define HID_ITEM_PREFERRED 0x20 // no preferred(0), preferred(1)
131 #define HID_ITEM_NULL 0x40 // no null(0), null(1)
132 #define HID_ITEM_VOLATILE 0x60 // non volatile(0), volatile(1)
133 #define HID_ITEM_BITFIELD 0x80 // bit field(0), buffered bytes(1)
134
135 // Report Types from HID 1.11 Section 7.2.1
136 #define HID_REPORT_TYPE_INPUT 1
137 #define HID_REPORT_TYPE_OUTPUT 2
138 #define HID_REPORT_TYPE_FEATURE 3
139
140
141 #define BITMASK1(n) ((1ULL << (n)) - 1ULL)
142 #define INVERTBITMASK1(n) ( 255 -(n))
143 #define BITTESTMASK1(n) (1ULL << (n))
144
145 // struct hid_device_descriptor * hid_new_descriptor(){
146 // struct hid_device_descriptor * descriptor;
147 // descriptor = (struct hid_device_descriptor *) malloc( sizeof( struct hid_device_descriptor) );
148 // // hid_descriptor_init( descriptor );
149 //
150 // descriptor->first = NULL;
151 // hid_set_descriptor_callback(descriptor, NULL, NULL);
152 // hid_set_element_callback(descriptor, NULL, NULL);
153 // return descriptor;
154 // }
155
hid_new_element()156 struct hid_device_element * hid_new_element(){
157 struct hid_device_element * element = (struct hid_device_element *) malloc( sizeof( struct hid_device_element ) );
158 element->next = NULL;
159 element->parent_collection = NULL;
160 element->index = -1;
161 element->repeat = 0;
162
163 element->usage_min = 0;
164 element->usage_max = 0;
165 element->logical_min = 0;
166 element->logical_max = 0;
167 element->phys_min = 0;
168 element->phys_max = 0;
169 element->report_id = 0;
170 element->unit = 0;
171 element->unit_exponent = 0;
172
173 element->rawvalue = 0;
174
175 return element;
176 }
177
hid_free_element(struct hid_device_element * ele)178 void hid_free_element( struct hid_device_element * ele ){
179 free( ele );
180 }
181
hid_new_collection()182 struct hid_device_collection * hid_new_collection(){
183 struct hid_device_collection * collection = (struct hid_device_collection *) malloc( sizeof( struct hid_device_collection ) );
184 collection->first_collection = NULL;
185 collection->next_collection = NULL;
186 collection->parent_collection = NULL;
187 collection->first_element = NULL;
188 collection->num_collections = 0;
189 collection->num_elements = 0;
190 collection->index = -1;
191 collection->usage_page = 0;
192 collection->usage_index = 0;
193 return collection;
194 }
195
hid_free_collection(struct hid_device_collection * coll)196 void hid_free_collection( struct hid_device_collection * coll ){
197 struct hid_device_element * cur_element = coll->first_element;
198 struct hid_device_element * next_element;
199 while (cur_element != NULL ) {
200 next_element = cur_element->next;
201 free( cur_element );
202 cur_element = next_element;
203 }
204 struct hid_device_collection * cur_collection = coll->first_collection;
205 struct hid_device_collection * next_collection;
206 while (cur_collection != NULL ) {
207 next_collection = cur_collection->next_collection;
208 free( cur_collection );
209 cur_collection = next_collection;
210 }
211 free( coll );
212 }
213
hid_set_descriptor_callback(struct hid_dev_desc * devd,hid_descriptor_callback cb,void * user_data)214 void hid_set_descriptor_callback( struct hid_dev_desc * devd, hid_descriptor_callback cb, void *user_data ){
215 devd->_descriptor_callback = cb;
216 devd->_descriptor_data = user_data;
217 }
218
hid_set_readerror_callback(struct hid_dev_desc * devd,hid_descriptor_callback cb,void * user_data)219 void hid_set_readerror_callback( struct hid_dev_desc * devd, hid_descriptor_callback cb, void *user_data ){
220 devd->_readerror_callback = cb;
221 devd->_readerror_data = user_data;
222 }
223
hid_set_element_callback(struct hid_dev_desc * devd,hid_element_callback cb,void * user_data)224 void hid_set_element_callback( struct hid_dev_desc * devd, hid_element_callback cb, void *user_data ){
225 devd->_element_callback = cb;
226 devd->_element_data = user_data;
227 }
228
hid_set_from_making_element(struct hid_device_element * making,struct hid_device_element * new_element)229 void hid_set_from_making_element( struct hid_device_element * making, struct hid_device_element * new_element ){
230
231 new_element->type = making->type;
232 new_element->isrelative = (making->type & HID_ITEM_RELATIVE ) > 0;
233 new_element->isarray = ( (making->type & HID_ITEM_VARIABLE ) == 0 );
234 new_element->isvariable = (making->type & HID_ITEM_CONSTANT ) == 0;
235
236 new_element->usage_page = making->usage_page;
237 new_element->logical_min = making->logical_min;
238 new_element->logical_max = making->logical_max;
239 new_element->usage_min = making->usage_min;
240 new_element->usage_max = making->usage_max;
241 if ( (making->phys_min == 0) && (making->phys_max == 0) ){
242 new_element->phys_min = making->logical_min;
243 new_element->phys_max = making->logical_max;
244
245 } else {
246 new_element->phys_min = making->phys_min;
247 new_element->phys_max = making->phys_max;
248 }
249 new_element->unit = making->unit;
250 new_element->unit_exponent = making->unit_exponent;
251
252 new_element->report_size = making->report_size;
253 new_element->report_id = making->report_id;
254 }
255
hid_element_get_signed_value(int inputvalue,int bytesize)256 int hid_element_get_signed_value( int inputvalue, int bytesize ){
257 int outputvalue;
258 int bitSignIndex = bytesize*8 - 1;
259 int signBit = 0x1 << bitSignIndex;
260 if ( signBit & inputvalue ){
261 unsigned int bitMask = BITMASK1( bytesize*8 );
262 unsigned int uvalue = (unsigned int) inputvalue;
263 unsigned int negvalue = ~(uvalue);
264 negvalue = ~(uvalue) & bitMask;
265 negvalue = negvalue + 1;
266 outputvalue = -1 * negvalue;
267 } else {
268 outputvalue = inputvalue;
269 }
270 return outputvalue;
271 }
272
273 // int hid_parse_report_descriptor( char* descr_buf, int size, struct hid_device_descriptor * descriptor ){
hid_parse_report_descriptor(unsigned char * descr_buf,int size,struct hid_dev_desc * device_desc)274 int hid_parse_report_descriptor( unsigned char* descr_buf, int size, struct hid_dev_desc * device_desc ){
275 struct hid_device_collection * device_collection = hid_new_collection();
276 device_desc->device_collection = device_collection;
277
278 struct hid_device_collection * parent_collection = device_desc->device_collection;
279 struct hid_device_collection * prev_collection = 0;
280 struct hid_device_element * prev_element = 0;
281
282 struct hid_device_element * making_element = hid_new_element();
283
284 int current_usages[256];
285 int current_usage_index = 0;
286 int current_report_size;
287
288 int current_usage_min = -1;
289 int current_usage_max = -1;
290
291 int current_report_count = 0;
292
293 // unsigned char current_input;
294 // unsigned char current_output;
295 int collection_nesting = 0;
296
297 int next_byte_tag = -1;
298 int next_byte_size = 0;
299 int next_byte_type = 0;
300 int next_val = 0;
301
302 unsigned char toadd = 0;
303 int byte_count = 0;
304
305 int i,j;
306
307 int numreports = 1;
308 int report_lengths[256];
309 int report_ids[256];
310 report_ids[0] = 0;
311 report_lengths[0] = 0;
312
313 int k;
314 int index;
315
316 device_collection->num_collections = 0;
317 device_collection->num_elements = 0;
318 #ifdef DEBUG_PARSER
319 printf("----------- parsing report descriptor --------------\n " );
320 #endif
321 for ( i = 0; i < size; i++){
322 #ifdef DEBUG_PARSER
323 printf("\nbuffer value: %02hhx ", descr_buf[i]);
324 printf("\tbyte_type %i, %i, %i \t", next_byte_tag, next_byte_size, next_val);
325 #endif
326 if ( next_byte_tag != -1 ){
327 // unsigned char ubyte = (unsigned char) descr_buf[i];
328 // char sbyte = descr_buf[i]; // descr_buf is signed already
329 int shift = byte_count*8;
330 int bufval = (int) descr_buf[i];
331 next_val |= (bufval << shift);
332 #ifdef DEBUG_PARSER
333 printf("\t nextval shift: %i", next_val);
334 #endif
335 byte_count++;
336 if ( byte_count == next_byte_size ){
337 switch( next_byte_tag ){
338 case HID_USAGE_PAGE:
339 making_element->usage_page = next_val;
340 #ifdef DEBUG_PARSER
341 printf("\n\tusage page: 0x%02hhx", making_element->usage_page);
342 #endif
343 break;
344 case HID_USAGE:
345 making_element->usage = next_val;
346 current_usage_min = -1;
347 current_usage_max = -1;
348 current_usages[ current_usage_index ] = next_val;
349 #ifdef DEBUG_PARSER
350 printf("\n\tusage: 0x%02hhx, %i", current_usages[ current_usage_index ], current_usage_index );
351 #endif
352 current_usage_index++;
353 break;
354 case HID_COLLECTION:
355 {
356 //TODO: COULD ALSO READ WHICH KIND OF COLLECTION
357 struct hid_device_collection * new_collection = hid_new_collection();
358 if ( parent_collection->num_collections == 0 ){
359 parent_collection->first_collection = new_collection;
360 }
361 if ( device_collection->num_collections == 0 ){
362 device_collection->first_collection = new_collection;
363 } else {
364 prev_collection->next_collection = new_collection;
365 }
366 new_collection->parent_collection = parent_collection;
367 new_collection->type = next_val;
368 new_collection->usage_page = making_element->usage_page;
369 new_collection->usage_index = making_element->usage;
370 new_collection->usage_min = making_element->usage_min;
371 new_collection->usage_max = making_element->usage_max;
372 new_collection->index = device_collection->num_collections;
373 device_collection->num_collections++;
374 if ( device_collection != parent_collection ){
375 parent_collection->num_collections++;
376 }
377 parent_collection = new_collection;
378 prev_collection = new_collection;
379 collection_nesting++;
380 #ifdef DEBUG_PARSER
381 printf("\n\tcollection: %i, %i", collection_nesting, next_val );
382 #endif
383 break;
384 }
385 case HID_USAGE_MIN:
386 current_usage_min = next_val;
387 making_element->usage_min = next_val;
388 #ifdef DEBUG_PARSER
389 printf("\n\tusage min: %i", current_usage_min);
390 #endif
391 break;
392 case HID_USAGE_MAX:
393 current_usage_max = next_val;
394 making_element->usage_max = next_val;
395 #ifdef DEBUG_PARSER
396 printf("\n\tusage max: %i", current_usage_max);
397 #endif
398 break;
399 case HID_LOGICAL_MIN:
400 making_element->logical_min = hid_element_get_signed_value( next_val, byte_count );
401 #ifdef DEBUG_PARSER
402 printf("\n\tlogical min: %i", making_element->logical_min);
403 #endif
404 break;
405 case HID_LOGICAL_MAX:
406 if ( making_element->logical_min >= 0 ){
407 making_element->logical_max = next_val;
408 } else {
409 making_element->logical_max = hid_element_get_signed_value( next_val, byte_count );
410 }
411 #ifdef DEBUG_PARSER
412 printf("\n\tlogical max: %i", making_element->logical_max);
413 #endif
414 break;
415 case HID_PHYSICAL_MIN:
416 making_element->phys_min = hid_element_get_signed_value( next_val, byte_count );
417 #ifdef DEBUG_PARSER
418 printf("\n\tphysical min: %i", making_element->phys_min);
419 #endif
420 break;
421 case HID_PHYSICAL_MAX:
422 if ( making_element->phys_min >= 0 ){
423 making_element->phys_max = next_val;
424 } else {
425 making_element->phys_max = hid_element_get_signed_value( next_val, byte_count );
426 }
427 #ifdef DEBUG_PARSER
428 printf("\n\tphysical max: %i", making_element->phys_min);
429 #endif
430 break;
431 case HID_REPORT_COUNT:
432 current_report_count = next_val;
433 #ifdef DEBUG_PARSER
434 printf("\n\treport count: %i", current_report_count);
435 #endif
436 break;
437 case HID_REPORT_SIZE:
438 making_element->report_size = next_val;
439 #ifdef DEBUG_PARSER
440 printf("\n\treport size: %i", making_element->report_size);
441 #endif
442 break;
443 case HID_REPORT_ID:
444 making_element->report_id = next_val;
445 // check if report id already exists
446 int reportexists = 0;
447 for ( j = 0; j < numreports; j++ ){
448 reportexists = (report_ids[j] == making_element->report_id);
449 }
450 if ( !reportexists ){
451 report_ids[ numreports ] = making_element->report_id;
452 report_lengths[ numreports ] = 0;
453 numreports++;
454 }
455 #ifdef DEBUG_PARSER
456 printf("\n\treport id: %i", making_element->report_id);
457 #endif
458 break;
459 case HID_POP:
460 // TODO: something useful with pop
461 #ifdef DEBUG_PARSER
462 printf("\n\tpop: %i", next_val );
463 #endif
464 break;
465 case HID_PUSH:
466 // TODO: something useful with push
467 #ifdef DEBUG_PARSER
468 printf("\n\tpop: %i", next_val );
469 #endif
470 break;
471 case HID_UNIT:
472 making_element->unit = next_val;
473 #ifdef DEBUG_PARSER
474 printf("\n\tunit: %i", next_val );
475 #endif
476 break;
477 case HID_UNIT_EXPONENT:
478 making_element->unit_exponent = hid_element_get_signed_value( next_val, byte_count );
479 #ifdef DEBUG_PARSER
480 printf("\n\tunit exponent: %i", next_val );
481 #endif
482 break;
483 case HID_INPUT:
484 #ifdef DEBUG_PARSER
485 printf("\n\tinput: %i", next_val);
486 printf("\tmaking_element->usage: %i", making_element->usage);
487 #endif
488 making_element->type = next_val;
489 // add the elements for this report
490 for ( j=0; j<current_report_count; j++ ){
491 struct hid_device_element * new_element = hid_new_element();
492 // = (struct hid_device_element *) malloc( sizeof( struct hid_device_element ) );
493 new_element->io_type = 1;
494 new_element->index = device_collection->num_elements;
495 new_element->parent_collection = parent_collection;
496 hid_set_from_making_element( making_element, new_element );
497 if ( current_usage_min == -1 ){
498 new_element->usage = current_usages[j]; /// FIXME
499 } else {
500 new_element->usage = current_usage_min + j;
501 }
502 new_element->report_index = j;
503
504 new_element->value = 0;
505 new_element->array_value = 0;
506 if ( parent_collection->num_elements == 0 ){
507 parent_collection->first_element = new_element;
508 }
509 if ( device_collection->num_elements == 0 ){
510 device_collection->first_element = new_element;
511 }
512 device_collection->num_elements++;
513 if ( parent_collection != device_collection ) {
514 parent_collection->num_elements++;
515 }
516 if ( prev_element != NULL ){
517 prev_element->next = new_element;
518 }
519 prev_element = new_element;
520 }
521 for ( j=0; j < current_usage_index; j++ ){
522 current_usages[j] = 0;
523 }
524 current_usage_index = 0;
525 current_usage_min = -1;
526 current_usage_max = -1;
527 making_element->usage_min = -1;
528 making_element->usage_max = -1;
529 making_element->usage = 0;
530 break;
531 case HID_OUTPUT:
532 #ifdef DEBUG_PARSER
533 printf("\n\toutput: %i", next_val);
534 printf("\tmaking_element->usage: %i", making_element->usage);
535 #endif
536 making_element->type = next_val;
537 // add the elements for this report
538 for ( j=0; j<current_report_count; j++ ){
539 struct hid_device_element * new_element = hid_new_element();
540 // struct hid_device_element * new_element = (struct hid_device_element *) malloc( sizeof( struct hid_device_element ) );
541 new_element->io_type = 2;
542 new_element->index = device_collection->num_elements;
543 new_element->parent_collection = parent_collection;
544 hid_set_from_making_element( making_element, new_element );
545 if ( current_usage_min == -1 ){
546 new_element->usage = current_usages[j]; /// FIXME
547 } else {
548 new_element->usage = current_usage_min + j;
549 }
550 new_element->report_index = j;
551
552 index = 0;
553 for ( k=0; k<numreports; k++ ){
554 if ( making_element->report_id == report_ids[k] ){
555 index = k;
556 break;
557 }
558 }
559 report_lengths[index] += making_element->report_size;
560
561 new_element->value = 0;
562 new_element->array_value = 0;
563 if ( parent_collection->num_elements == 0 ){
564 parent_collection->first_element = new_element;
565 }
566 if ( device_collection->num_elements == 0 ){
567 device_collection->first_element = new_element;
568 }
569 device_collection->num_elements++;
570 if ( parent_collection != device_collection ) {
571 parent_collection->num_elements++;
572 }
573 if ( prev_element != NULL ){
574 prev_element->next = new_element;
575 }
576 prev_element = new_element;
577 }
578 for ( j=0; j < current_usage_index; j++ ){
579 current_usages[j] = 0;
580 }
581 current_usage_index = 0;
582 current_usage_min = -1;
583 current_usage_max = -1;
584 making_element->usage_min = -1;
585 making_element->usage_max = -1;
586 making_element->usage = 0;
587 break;
588 case HID_FEATURE:
589 #ifdef DEBUG_PARSER
590 printf("\n\tfeature: %i", next_val);
591 printf("\tcurrent_usage: %i", making_element->usage);
592 #endif
593 making_element->type = next_val;
594 // add the elements for this report
595 for ( j=0; j<current_report_count; j++ ){
596 struct hid_device_element * new_element = hid_new_element();
597 new_element->io_type = 3;
598 new_element->index = device_collection->num_elements;
599 new_element->parent_collection = parent_collection;
600 hid_set_from_making_element( making_element, new_element );
601 if ( current_usage_min == -1 ){
602 new_element->usage = current_usages[j]; /// FIXME
603 } else {
604 new_element->usage = current_usage_min + j;
605 }
606 new_element->report_index = j;
607
608 new_element->value = 0;
609 new_element->array_value = 0;
610 if ( parent_collection->num_elements == 0 ){
611 parent_collection->first_element = new_element;
612 }
613 if ( device_collection->num_elements == 0 ){
614 device_collection->first_element = new_element;
615 }
616 device_collection->num_elements++;
617 if ( parent_collection != device_collection ) {
618 parent_collection->num_elements++;
619 }
620 if ( prev_element != NULL ){
621 prev_element->next = new_element;
622 }
623 prev_element = new_element;
624 }
625 for ( j=0; j < current_usage_index; j++ ){
626 current_usages[j] = 0;
627 }
628 current_usage_index = 0;
629 current_usage_min = -1;
630 current_usage_max = -1;
631 making_element->usage_min = -1;
632 making_element->usage_max = -1;
633 making_element->usage = 0;
634 break;
635 #ifdef DEBUG_PARSER
636 default:
637 if ( next_byte_tag >= HID_RESERVED ){
638 printf("\n\treserved bytes 0x%02hhx, %i", next_byte_tag, next_val );
639 } else {
640 printf("\n\tundefined byte type 0x%02hhx, %i", next_byte_tag, next_val );
641 }
642 #endif
643 }
644 next_byte_tag = -1;
645 }
646 } else {
647 #ifdef DEBUG_PARSER
648 printf("\tsetting next byte type: %i, 0x%02hhx ", descr_buf[i], descr_buf[i] );
649 #endif
650 if ( descr_buf[i] == HID_END_COLLECTION ){ // JUST one byte
651 // prev_collection = parent_collection;
652 making_element->usage_page = parent_collection->usage_page;
653 making_element->usage = parent_collection->usage_index;
654 parent_collection = parent_collection->parent_collection;
655 for ( j=0; j < current_usage_index; j++ ){
656 current_usages[j] = 0;
657 }
658 making_element->usage_min = -1;
659 making_element->usage_max = -1;
660 current_usage_index = 0;
661 current_usage_min = -1;
662 current_usage_max = -1;
663 collection_nesting--;
664 #ifdef DEBUG_PARSER
665 printf("\n\tend collection: %i, %i\n", collection_nesting, descr_buf[i] );
666 #endif
667 } else {
668 byte_count = 0;
669 next_val = 0;
670 // u_next_val = 0;
671 next_byte_tag = descr_buf[i] & 0xFC;
672 next_byte_type = descr_buf[i] & 0x0C;
673 next_byte_size = descr_buf[i] & 0x03;
674 if ( next_byte_size == 3 ){
675 next_byte_size = 4;
676 }
677 #ifdef DEBUG_PARSER
678 printf("\t next byte type: 0x%02hhx, %i, %i ", next_byte_tag, next_byte_type, next_byte_size );
679 #endif
680 }
681 }
682 }
683 #ifdef DEBUG_PARSER
684 printf("----------- end parsing report descriptor --------------\n " );
685 #endif
686
687 device_desc->number_of_reports = numreports;
688 device_desc->report_lengths = (int*) malloc( sizeof( int ) * numreports );
689 device_desc->report_ids = (int*) malloc( sizeof( int ) * numreports );
690 for ( j = 0; j<numreports; j++ ){
691 device_desc->report_lengths[j] = report_lengths[j];
692 device_desc->report_ids[j] = report_ids[j];
693 }
694
695 #ifdef DEBUG_PARSER
696 printf("----------- end setting report ids --------------\n " );
697 #endif
698
699 return 0;
700 }
701
hid_element_set_value_from_input(struct hid_device_element * element,int value)702 void hid_element_set_value_from_input( struct hid_device_element * element, int value ){
703 element->rawvalue = value;
704 if (element->logical_min < 0){
705 // value should be interpreted as signed value
706 // so: check report size, test the highest bit, if one, invert and add one, otherwise keep value
707 int bitSignIndex = element->report_size - 1;
708 int signBit = 0x1 << bitSignIndex;
709 if (signBit & value){
710 unsigned int bitMask = BITMASK1(element->report_size);
711 unsigned int uvalue = (unsigned int)value;
712 unsigned int negvalue = ~(uvalue);
713 negvalue = ~(uvalue)& bitMask;
714 negvalue = negvalue + 1;
715 element->value = -1 * negvalue;
716 }
717 else {
718 element->value = value;
719 }
720 }
721 else {
722 // value should be interpreted as unsigned value
723 // so: keep value as is
724 if (element->isarray){ // array elements should be parsed differently
725 if (value == 0){ // previous key was pressed, so keep previous usage
726 element->value = 0;
727 element->array_value = 0;
728 }
729 else { // new key, so value + usage min is the current usage
730 element->usage = element->usage_min + value;
731 element->value = 1;
732 element->array_value = value;
733 }
734 }
735 else {
736 element->value = value;
737 }
738 }
739 }
740
hid_element_map_logical(struct hid_device_element * element)741 float hid_element_map_logical( struct hid_device_element * element ){
742 float result;
743 if ( element->isarray ){
744 result = (float) element->value;
745 } else {
746 result = ( (float) element->value - (float) element->logical_min)/( (float) element->logical_max - (float) element->logical_min );
747 }
748 return result;
749 }
750
751 /** TODO: this needs a linking with the math library */
hid_element_resolution(struct hid_device_element * element)752 float hid_element_resolution( struct hid_device_element * element ){
753 float result = 0;
754 // result = ( element->logical_max - element->logical_min) / ( ( element->phys_max - element->phys_min) * pow(10, element->unit_exponent) );
755 return result;
756 }
757
hid_element_map_physical(struct hid_device_element * element)758 float hid_element_map_physical( struct hid_device_element * element ){
759 float result;
760 float logicalvalue = hid_element_map_logical(element);
761 result = logicalvalue * ( element->phys_max - element->phys_min ) + element->phys_min;
762 return result;
763 }
764
765 /** is this used anywhere? */
hid_element_set_rawvalue(struct hid_device_element * element,int value)766 void hid_element_set_rawvalue( struct hid_device_element * element, int value ){
767 element->value = value;
768 }
769
770 /** is this used anywhere? */
hid_element_set_logicalvalue(struct hid_device_element * element,float value)771 void hid_element_set_logicalvalue( struct hid_device_element * element, float value ){
772 int mapvalue;
773 mapvalue = (int) ( value * ( (float) element->logical_max - (float) element->logical_min ) ) - element->logical_min;
774 element->value = mapvalue;
775 }
776
hid_get_next_input_element(struct hid_device_element * curel)777 struct hid_device_element * hid_get_next_input_element( struct hid_device_element * curel ){
778
779 struct hid_device_element * nextel = curel->next;
780 while ( nextel != NULL ){
781 if ( nextel->io_type == 1 ){
782 return nextel;
783 } else {
784 nextel = nextel->next;
785 }
786 }
787 return nextel; // is NULL
788 // return curel; // return the previous element
789 // is NULL
790 }
791
hid_get_next_input_element_with_reportid(struct hid_device_element * curel,int reportid)792 struct hid_device_element * hid_get_next_input_element_with_reportid( struct hid_device_element * curel, int reportid ){
793
794 struct hid_device_element * nextel = curel->next;
795 while ( nextel != NULL ){
796 if ( nextel->io_type == 1 && ( nextel->report_id == reportid ) ){
797 return nextel;
798 } else {
799 nextel = nextel->next;
800 }
801 }
802 return nextel;
803 // return curel; // return the previous element
804 // is NULL
805 }
806
hid_get_next_output_element(struct hid_device_element * curel)807 struct hid_device_element * hid_get_next_output_element( struct hid_device_element * curel ){
808
809 struct hid_device_element * nextel = curel->next;
810 while ( nextel != NULL ){
811 if ( nextel->io_type == 2 ){
812 return nextel;
813 } else {
814 nextel = nextel->next;
815 }
816 }
817 return nextel;
818 // return curel; // return the previous element
819 // is NULL
820 }
821
hid_get_next_output_element_with_reportid(struct hid_device_element * curel,int reportid)822 struct hid_device_element * hid_get_next_output_element_with_reportid( struct hid_device_element * curel, int reportid ){
823
824 struct hid_device_element * nextel = curel->next;
825 while ( nextel != NULL ){
826 if ( nextel->io_type == 2 && ( nextel->report_id == reportid ) ){
827 return nextel;
828 } else {
829 nextel = nextel->next;
830 }
831 }
832 return NULL;
833 // return curel; // return the previous element
834 // is NULL
835 }
836
hid_get_next_feature_element(struct hid_device_element * curel)837 struct hid_device_element * hid_get_next_feature_element( struct hid_device_element * curel ){
838
839 struct hid_device_element * nextel = curel->next;
840 while ( nextel != NULL ){
841 if ( nextel->io_type == 3 ){
842 return nextel;
843 } else {
844 nextel = nextel->next;
845 }
846 }
847 return nextel;
848 //return curel; // return the previous element
849 // is NULL
850 }
851
852 struct hid_parsing_byte {
853 int nextVal;
854 int currentSize;
855 int bitIndex;
856 int remainingBits;
857 int shiftedByte;
858 };
859
hid_parse_single_byte(unsigned char current_byte,struct hid_parsing_byte * pbyte)860 int hid_parse_single_byte( unsigned char current_byte, struct hid_parsing_byte * pbyte ){
861 int nextVal;
862 unsigned char bitMask;
863 unsigned char invBitMask;
864 unsigned char maskedByte;
865 int currentBitsize = pbyte->currentSize - pbyte->bitIndex;
866 if ( currentBitsize >= pbyte->remainingBits ){
867 // using the full byte
868 nextVal = ( current_byte << pbyte->bitIndex );
869 pbyte->bitIndex += pbyte->remainingBits;
870 pbyte->remainingBits = 0;
871 } else {
872 // use a partial byte:
873 bitMask = BITMASK1( currentBitsize );
874 nextVal = bitMask & current_byte;
875 nextVal = nextVal << pbyte->bitIndex;
876 pbyte->remainingBits -= currentBitsize;
877 // shift the remaining value
878 invBitMask = INVERTBITMASK1( bitMask );
879 maskedByte = current_byte & invBitMask;
880 pbyte->shiftedByte = maskedByte >> currentBitsize;
881 pbyte->bitIndex = pbyte->currentSize; // is this always true?
882 };
883 pbyte->nextVal += nextVal;
884 if ( (pbyte->currentSize - pbyte->bitIndex) == 0 ){
885 pbyte->bitIndex = 0;
886 nextVal = pbyte->nextVal;
887 pbyte->nextVal = 0;
888 return nextVal;
889 }
890 return -1;
891 }
892
hid_parse_input_report(unsigned char * buf,int size,struct hid_dev_desc * devdesc)893 int hid_parse_input_report( unsigned char* buf, int size, struct hid_dev_desc * devdesc ){
894
895 #ifdef APPLE
896 return hid_parse_input_elements_values( buf, devdesc );
897 #endif
898 #ifdef WIN32
899 return hid_parse_input_elements_values( buf, size, devdesc );
900 #endif
901 #ifdef LINUX_FREEBSD
902 struct hid_parsing_byte pbyte;
903 pbyte.nextVal = 0;
904 pbyte.currentSize = 10;
905 pbyte.bitIndex = 0;
906 pbyte.remainingBits = 0;
907 pbyte.shiftedByte = 0;
908
909 struct hid_device_collection * device_collection = devdesc->device_collection;
910 struct hid_device_element * cur_element = device_collection->first_element;
911 int newvalue;
912 int i = 0;
913 int starti = 0;
914 int reportid = 0;
915
916 if ( devdesc->number_of_reports > 1 ){
917 reportid = (int) buf[i];
918 starti = 1;
919 }
920
921 if ( cur_element->io_type != 1 || ( cur_element->report_id != reportid ) ){
922 cur_element = hid_get_next_input_element_with_reportid(cur_element, reportid );
923 }
924
925 for ( i = starti; i < size; i++){
926 unsigned char curbyte = buf[i];
927 pbyte.remainingBits = 8;
928 pbyte.shiftedByte = curbyte;
929 while( pbyte.remainingBits > 0 ) {
930 // get next element
931 pbyte.currentSize = cur_element->report_size;
932 newvalue = hid_parse_single_byte( pbyte.shiftedByte, &pbyte );
933 if ( newvalue != -1 ){
934 if ( devdesc->_element_callback != NULL ){
935 if ( newvalue != cur_element->rawvalue || cur_element->repeat ){
936 hid_element_set_value_from_input( cur_element, newvalue );
937 devdesc->_element_callback( cur_element, devdesc->_element_data );
938 }
939 }
940 cur_element = hid_get_next_input_element_with_reportid( cur_element, reportid );
941 }
942 }
943 }
944 return 0;
945 #endif
946 }
947
hid_throw_readerror(struct hid_dev_desc * devd)948 void hid_throw_readerror( struct hid_dev_desc * devd ){
949 devd->_readerror_callback( devd, devd->_readerror_data );
950 }
951
hid_send_output_report(struct hid_dev_desc * devd,int reportid)952 int hid_send_output_report( struct hid_dev_desc * devd, int reportid ){
953 char * buf;
954 // find the right report id
955 int index = 0;
956 int i;
957 for ( i=0; i<devd->number_of_reports; i++ ){
958 if ( reportid == devd->report_ids[i] ){
959 index = i;
960 break;
961 }
962 }
963
964 size_t buflength = devd->report_lengths[ index ] / 8;
965 #ifdef DEBUG_PARSER
966 printf("report id %i, buflength %i\t", reportid, buflength );
967 #endif
968
969 // if ( reportid != 0 ){
970 buflength++; // one more byte if report id is not 0
971 // }
972 buf = (char *) malloc( sizeof( char ) * buflength );
973 memset(buf, 0x0, sizeof(char) * buflength);
974
975
976 // iterate over elements, find which ones are output elements with the right report id,
977 // and set their output values to the buffer
978
979
980 struct hid_device_collection * device_collection = devd->device_collection;
981 struct hid_device_element * cur_element = device_collection->first_element;
982 if ( cur_element->io_type != 2 || ( cur_element->report_id != reportid ) ){
983 cur_element = hid_get_next_output_element_with_reportid(cur_element, reportid);
984 }
985
986 #ifdef DEBUG_PARSER
987 printf("-----------------------\n");
988 #endif
989
990 buf[0] = reportid;
991 int byte_index = 1;
992 int bit_offset = 0;
993 int next_val = 0;
994
995
996 while ( cur_element != NULL && (byte_index < buflength) ){
997 int current_output = 0;
998 unsigned char current_byte = 0;
999 int current_bit_size = cur_element->report_size;
1000 int current_byte_size = (int) ceil( (float) current_bit_size / 8);
1001 #ifdef DEBUG_PARSER
1002 printf("report_size %i, bytesize %i, bitsize %i, bitoffset %i, byte_index %i \n", cur_element->report_size, current_byte_size, current_bit_size, bit_offset, byte_index );
1003 printf("current_output %i \t", current_output );
1004 #endif
1005 current_output = cur_element->value << bit_offset;
1006 #ifdef DEBUG_PARSER
1007 printf("current_output shift %i \t", current_output );
1008 #endif
1009 int i;
1010 for ( i=0; i<current_byte_size; i++ ){
1011 current_byte = current_output % 256;
1012 current_output = current_output >> 8;
1013 buf[ byte_index + i ] += current_byte;
1014 #ifdef DEBUG_PARSER
1015 printf("current_output %i, current_byte %i, buf %i\t", current_output, current_byte, buf[ byte_index + i ] );
1016 #endif
1017 }
1018 bit_offset += current_bit_size;
1019 byte_index += (int) floor( (float) current_bit_size / 8 );
1020 bit_offset = bit_offset%8;
1021 #ifdef DEBUG_PARSER
1022 printf("bit_offset %i, byte_index %i\n", bit_offset, byte_index );
1023 #endif
1024 cur_element = hid_get_next_output_element_with_reportid(cur_element, reportid);
1025 }
1026 #ifdef DEBUG_PARSER
1027 printf("-----------------------\n");
1028 #endif
1029
1030
1031 int res = hid_write(devd->device, (const unsigned char*)buf, buflength);
1032
1033 free( buf );
1034 return res;
1035 }
1036
hid_send_output_report_old(struct hid_dev_desc * devd,int reportid)1037 int hid_send_output_report_old( struct hid_dev_desc * devd, int reportid ){
1038 char * buf;
1039 // find the right report id
1040 int index = 0;
1041 int i;
1042 for ( i=0; i<devd->number_of_reports; i++ ){
1043 if ( reportid == devd->report_ids[i] ){
1044 index = i;
1045 break;
1046 }
1047 }
1048
1049 size_t buflength = devd->report_lengths[ index ] / 8;
1050 #ifdef DEBUG_PARSER
1051 printf("report id %i, buflength %i\t", reportid, buflength );
1052 #endif
1053
1054 if ( reportid != 0 ){
1055 buflength++; // one more byte if report id is not 0
1056 }
1057 buf = (char *) malloc( sizeof( char ) * buflength );
1058 memset(buf, 0x0, sizeof(char) * buflength);
1059
1060 // iterate over elements, find which ones are output elements with the right report id,
1061 // and set their output values to the buffer
1062
1063 int next_byte_size;
1064 int next_mod_bit_size;
1065 int byte_count = 0;
1066 int next_val = 0;
1067
1068 struct hid_device_collection * device_collection = devd->device_collection;
1069 struct hid_device_element * cur_element = device_collection->first_element;
1070 if ( cur_element->io_type != 2 || ( cur_element->report_id != reportid ) ){
1071 cur_element = hid_get_next_output_element_with_reportid(cur_element, reportid);
1072 }
1073 next_byte_size = cur_element->report_size/8;
1074
1075 #ifdef DEBUG_PARSER
1076 printf("report_size %i, bytesize %i, bitsize %i \t", cur_element->report_size, next_byte_size, next_mod_bit_size );
1077 #endif
1078
1079 #ifdef DEBUG_PARSER
1080 printf("-----------------------\n");
1081 #endif
1082
1083 for ( i = 0; i < buflength; i++){
1084 unsigned char curbyte = 0;
1085 if ( cur_element->report_size == 8 ){
1086 curbyte = (unsigned char) cur_element->value;
1087 #ifdef DEBUG_PARSER
1088 printf("element page %i, usage %i, index %i, value %i, report_size %i, curbyte %i\n", cur_element->usage_page, cur_element->usage, cur_element->index, cur_element->value, cur_element->report_size, curbyte );
1089 #endif
1090 cur_element = hid_get_next_output_element_with_reportid( cur_element, reportid );
1091 next_byte_size = cur_element->report_size/8;
1092 } else if ( cur_element->report_size == 16 ){
1093 int shift = byte_count*8;
1094 curbyte = (unsigned char) (cur_element->value >> shift);
1095 byte_count++;
1096 #ifdef DEBUG_PARSER
1097 printf("element page %i, usage %i, index %i, value %i, report_size %i, curbyte %i\n", cur_element->usage_page, cur_element->usage, cur_element->index, cur_element->value, cur_element->report_size, curbyte );
1098 #endif
1099 if ( byte_count == next_byte_size ){
1100 cur_element = hid_get_next_output_element_with_reportid( cur_element, reportid );
1101 next_byte_size = cur_element->report_size/8;
1102 }
1103 } else if ( cur_element->report_size < 8 ){
1104 int bitindex = 0;
1105 char curbits = 0;
1106 // fill up the byte
1107 while( bitindex < 8 ){
1108 curbits = cur_element->value & BITMASK1( cur_element->report_size );
1109 curbits = curbits << bitindex;
1110 curbyte += curbits;
1111 bitindex += cur_element->report_size;
1112 #ifdef DEBUG_PARSER
1113 printf("element page %i, usage %i, index %i, value %i, report_size %i, curbyte %i\n", cur_element->usage_page, cur_element->usage, cur_element->index, cur_element->value, cur_element->report_size, curbyte );
1114 #endif
1115 cur_element = hid_get_next_output_element_with_reportid( cur_element, reportid );
1116 next_byte_size = cur_element->report_size/8;
1117 }
1118 }
1119 buf[ i ] = curbyte;
1120 }
1121 #ifdef DEBUG_PARSER
1122 printf("-----------------------\n");
1123 #endif
1124
1125
1126 int res = hid_write(devd->device, (const unsigned char*)buf, buflength);
1127
1128 free( buf );
1129 return res;
1130 }
1131
1132
hid_read_descriptor(hid_device * devd)1133 struct hid_dev_desc * hid_read_descriptor( hid_device * devd ){
1134 struct hid_dev_desc * desc;
1135
1136 #ifdef APPLE
1137 desc = (struct hid_dev_desc *) malloc( sizeof( struct hid_dev_desc ) );
1138 desc->device = devd;
1139 hid_parse_element_info( desc );
1140 return desc;
1141 #endif
1142 #ifdef WIN32
1143 desc = (struct hid_dev_desc *) malloc( sizeof( struct hid_dev_desc ) );
1144 desc->device = devd;
1145 hid_parse_element_info( desc );
1146 return desc;
1147 #endif
1148 #ifdef LINUX_FREEBSD
1149 unsigned char descr_buf[HIDAPI_MAX_DESCRIPTOR_SIZE];
1150 int res;
1151 res = hid_get_report_descriptor( devd, descr_buf, HIDAPI_MAX_DESCRIPTOR_SIZE );
1152 if (res < 0){
1153 printf("Unable to read report descriptor\n");
1154 return NULL;
1155 } else {
1156 desc = (struct hid_dev_desc *) malloc( sizeof( struct hid_dev_desc ) );
1157 desc->device = devd;
1158 hid_parse_report_descriptor( descr_buf, res, desc );
1159 return desc;
1160 }
1161 #endif
1162 }
1163
hid_open_device_path(const char * path,unsigned short vendor,unsigned short product)1164 struct hid_dev_desc * hid_open_device_path( const char *path, unsigned short vendor, unsigned short product ){
1165 hid_device * handle = hid_open_path( path );
1166 if (!handle){
1167 return NULL;
1168 }
1169 struct hid_dev_desc * newdesc = hid_read_descriptor( handle );
1170 if ( newdesc == NULL ){
1171 hid_close( handle );
1172 return NULL;
1173 }
1174 struct hid_device_info * newinfo = hid_enumerate(vendor,product);
1175 //newdesc->device = handle;
1176 int havenotfound = strcmp(path, newinfo->path) != 0;
1177 while (havenotfound && (newinfo != NULL) ){
1178 newinfo = newinfo->next;
1179 havenotfound = strcmp(path, newinfo->path) != 0;
1180 }
1181 if ( newinfo == NULL ){
1182 hid_close( handle );
1183 return NULL;
1184 }
1185
1186 newdesc->info = newinfo;
1187
1188 // Set the hid_read() function to be non-blocking.
1189 hid_set_nonblocking( handle, 1);
1190
1191 return newdesc;
1192 }
1193
1194 // this one is actually not secure when vendor and product have double entries, so you do not actually know which one you are opening
hid_open_device(unsigned short vendor,unsigned short product,const wchar_t * serial_number)1195 struct hid_dev_desc * hid_open_device( unsigned short vendor, unsigned short product, const wchar_t *serial_number ){
1196 hid_device * handle = hid_open( vendor, product, serial_number );
1197 if (!handle){
1198 return NULL;
1199 }
1200 struct hid_dev_desc * newdesc = hid_read_descriptor( handle );
1201 if ( newdesc == NULL ){
1202 hid_close( handle );
1203 return NULL;
1204 }
1205 struct hid_device_info * newinfo = hid_enumerate(vendor,product);
1206 //newdesc->device = handle;
1207 //TODO: if serial_number is given, the info descriptor should also point to that one!
1208 // int havenotfound = wcscmp(serial_number, newinfo->serial_number) == 0;
1209 // while (havenotfound && (newinfo != NULL) ){
1210 // newinfo = newinfo->next;
1211 // havenotfound = wcscmp(serial_number, newinfo->serial_number) == 0;
1212 // }
1213 if ( newinfo == NULL ){
1214 hid_close( handle );
1215 return NULL;
1216 }
1217
1218 newdesc->info = newinfo;
1219
1220 // Set the hid_read() function to be non-blocking.
1221 hid_set_nonblocking( handle, 1);
1222
1223 return newdesc;
1224 }
1225
hid_close_device(struct hid_dev_desc * devdesc)1226 void hid_close_device( struct hid_dev_desc * devdesc ){
1227 hid_close( devdesc->device );
1228 hid_free_enumeration( devdesc->info );
1229 hid_free_collection( devdesc->device_collection );
1230 free( devdesc->report_ids );
1231 free( devdesc->report_lengths );
1232 // hid_free_descriptor( devdesc->descriptor );
1233 //TODO: more memory freeing?
1234 }
1235
hid_element_set_output_value(struct hid_dev_desc * devdesc,struct hid_device_element * element,int value)1236 void hid_element_set_output_value( struct hid_dev_desc * devdesc, struct hid_device_element * element, int value ){
1237 element->value = value;
1238 #ifdef APPLE
1239 hid_send_element_output( devdesc, element );
1240 #endif
1241 #ifdef WIN32
1242 hid_send_element_output( devdesc, element );
1243 #endif
1244 #ifdef LINUX_FREEBSD
1245 hid_send_output_report( devdesc, element->report_id );
1246 #endif
1247 }
1248
1249
1250 #ifdef WIN32
1251
debug_element(struct hid_device_element * element)1252 void debug_element(struct hid_device_element *element)
1253 {
1254 printf("index: %d\n", element->index);
1255 printf("parent_collection: %p\n", element->parent_collection);
1256 printf("io_type: %d\n", element->io_type);
1257 printf("usage_page: %d\n", element->usage_page);
1258 printf("usage_min: %d\n", element->usage_min);
1259 printf("usage_max: %d\n", element->usage_max);
1260 printf("usage: %d\n", element->usage);
1261 printf("type: %d\n", element->type);
1262 printf("isarray: %d\n", element->isarray);
1263 printf("isrelative: %d\n", element->isrelative);
1264 printf("isvariable: %d\n", element->isvariable);
1265 printf("logical_min: %d\n", element->logical_min);
1266 printf("logical_max: %d\n", element->logical_max);
1267 printf("phys_min: %d\n", element->phys_min);
1268 printf("phys_max: %d\n", element->phys_max);
1269 printf("unit: %d\n", element->unit);
1270 printf("unit_exponent: %d\n", element->unit_exponent);
1271 printf("report_id: %d\n", element->report_id);
1272 printf("report_size: %d\n", element->report_size);
1273 printf("report_index: %d\n", element->report_index);
1274 printf("\n\n");
1275 fflush(stdout);
1276 }
1277
debug_collection(struct hid_device_collection * collection,int col_index)1278 void debug_collection(struct hid_device_collection *collection, int col_index)
1279 {
1280 printf("COLLECTION[%d] @%p:\n", col_index, collection);
1281 printf("index: %d\n", collection->index);
1282 printf("type: %d\n", collection->type);
1283 printf("usage_page: %d\n", collection->usage_page);
1284 printf("usage_index: %d\n", collection->usage_index);
1285 printf("parent: %p\n", collection->parent_collection);
1286 printf("children collections: %d\n", collection->num_collections);
1287 if (collection->first_collection)
1288 printf("first_collection: %p\n", collection->first_collection);
1289 if (collection->next_collection)
1290 printf("next_collection: %p\n", collection->next_collection);
1291 printf("children elements: %d\n", collection->num_elements);
1292 if (collection->first_element)
1293 printf("first_element: %p\n", collection->first_element);
1294 printf("\n\n");
1295 fflush(stdout);
1296 }
1297
add_element_to_collection(struct hid_device_collection * collection,struct hid_device_element * element)1298 static void add_element_to_collection(struct hid_device_collection *collection, struct hid_device_element *element)
1299 {
1300 if (!collection->first_element){
1301 collection->first_element = element;
1302 }
1303 collection->num_elements++;
1304 element->parent_collection = collection;
1305 }
1306
1307
duplicate_element_with_new_usage(struct hid_device_element * source_element,int new_usage,struct hid_device_collection * device_collection,int * index)1308 static struct hid_device_element *duplicate_element_with_new_usage(struct hid_device_element *source_element, int new_usage, struct hid_device_collection *device_collection, int *index)
1309 {
1310 struct hid_device_element *new_element = hid_new_element();
1311 memcpy(new_element, source_element, sizeof(struct hid_device_element));
1312 new_element->index = (*index)++;
1313 device_collection->num_elements++;
1314 // Update the collection
1315 add_element_to_collection(source_element->parent_collection, new_element);
1316 new_element->usage = new_usage;
1317 return new_element;
1318 }
1319
1320
fill_element_from_button_caps(PHIDP_BUTTON_CAPS pCaps,struct hid_device_element * element)1321 static void fill_element_from_button_caps(PHIDP_BUTTON_CAPS pCaps, struct hid_device_element *element)
1322 {
1323 USHORT bitField = pCaps->BitField;
1324 element->usage_page = pCaps->UsagePage;
1325 element->type = bitField & 0xf;
1326 element->logical_min = 0;
1327 element->logical_max = 1;
1328 element->isarray = ((bitField & HID_ITEM_VARIABLE) == 0);
1329 element->isrelative = pCaps->IsAbsolute ? 0 : 1;
1330 element->isvariable = ((bitField & HID_ITEM_CONSTANT) == 0);
1331 element->report_id = pCaps->ReportID;
1332 element->report_size = pCaps->Range.UsageMax - pCaps->Range.UsageMin + 1;
1333 element->report_index = 1; // TODO: not sure about this one. The API does not seem to provide this. Perhaps set to 1?
1334
1335 }
1336
1337
fill_element_from_value_caps(PHIDP_VALUE_CAPS pCaps,struct hid_device_element * element)1338 static void fill_element_from_value_caps(PHIDP_VALUE_CAPS pCaps, struct hid_device_element *element)
1339 {
1340 USHORT bitField = pCaps->BitField;
1341 element->usage_page = pCaps->UsagePage;
1342 element->type = bitField & 0xf;
1343 element->isarray = ((bitField & HID_ITEM_VARIABLE) == 0);
1344 element->isrelative = pCaps->IsAbsolute ? 0 : 1;
1345 element->isvariable = ((bitField & HID_ITEM_CONSTANT) == 0);
1346 element->logical_min = pCaps->LogicalMin;
1347 element->logical_max = pCaps->LogicalMax;
1348 element->phys_min = pCaps->PhysicalMin;
1349 element->phys_max = pCaps->PhysicalMax;
1350 element->unit = pCaps->Units;
1351 element->unit_exponent = pCaps->UnitsExp;
1352 element->report_id = pCaps->ReportID;
1353 element->report_size = pCaps->BitSize;
1354 element->report_index = pCaps->ReportCount;
1355 }
1356
hid_parse_caps(struct hid_device_element ** pplast_element,struct hid_device_collection ** ppcollections,struct hid_device_collection * pdevice_collection,const PHIDP_PREPARSED_DATA pp_data,const PHIDP_CAPS caps,int report_type,BOOL is_button,int * index)1357 static int hid_parse_caps(struct hid_device_element **pplast_element, struct hid_device_collection **ppcollections, struct hid_device_collection *pdevice_collection,
1358 const PHIDP_PREPARSED_DATA pp_data, const PHIDP_CAPS caps, int report_type, BOOL is_button, int *index)
1359 {
1360 int i, j;
1361 USHORT numCaps;
1362 enum _HIDP_REPORT_TYPE api_report_type;
1363 struct hid_device_element *plast_element = *pplast_element;
1364
1365 if (is_button){
1366 switch (report_type){
1367 case HID_REPORT_TYPE_INPUT: numCaps = caps->NumberInputButtonCaps; api_report_type = HidP_Input; break;
1368 case HID_REPORT_TYPE_OUTPUT: numCaps = caps->NumberOutputButtonCaps; api_report_type = HidP_Output; break;
1369 case HID_REPORT_TYPE_FEATURE: numCaps = caps->NumberFeatureButtonCaps; api_report_type = HidP_Feature; break;
1370 }
1371 PHIDP_BUTTON_CAPS pButtonCaps;
1372 pButtonCaps = malloc(numCaps * sizeof(HIDP_BUTTON_CAPS));
1373 if (HidP_GetButtonCaps(api_report_type, pButtonCaps, &numCaps, pp_data) != HIDP_STATUS_SUCCESS){
1374 free(pButtonCaps);
1375 return -1;
1376 }
1377 for (i = 0; i < numCaps; i++){
1378 // Create a new element
1379 struct hid_device_element *new_element = hid_new_element();
1380 if (plast_element){
1381 plast_element->next = new_element;
1382 }
1383 // Connect to previous element
1384 plast_element = new_element;
1385 // Add element to collections, and fill element values
1386 PHIDP_BUTTON_CAPS pCaps = &pButtonCaps[i];
1387 add_element_to_collection(pdevice_collection, new_element);
1388 add_element_to_collection(ppcollections[pCaps->LinkCollection], new_element);
1389 new_element->io_type = report_type;
1390 new_element->index = (*index)++;
1391 fill_element_from_button_caps(pCaps, new_element);
1392 if (pCaps->IsRange){
1393 // If it is a range, we copy the element, and update the usage. We want to have an element per usage.
1394 new_element->usage = pCaps->Range.UsageMin;
1395 #ifdef DEBUG_PARSER
1396 debug_element(new_element);
1397 #endif
1398 for (j = pCaps->Range.UsageMin + 1; j <= pCaps->Range.UsageMax; j++){
1399 new_element = duplicate_element_with_new_usage(plast_element, j, pdevice_collection, index);
1400 plast_element->next = new_element;
1401 plast_element = new_element;
1402 #ifdef DEBUG_PARSER
1403 debug_element(new_element);
1404 #endif
1405 }
1406 }
1407 else{
1408 new_element->usage = pCaps->NotRange.Usage;
1409 #ifdef DEBUG_PARSER
1410 debug_element(new_element);
1411 #endif
1412 }
1413 }
1414 free(pButtonCaps);
1415 }
1416 else {
1417 switch (report_type){
1418 case HID_REPORT_TYPE_INPUT: numCaps = caps->NumberInputValueCaps; api_report_type = HidP_Input; break;
1419 case HID_REPORT_TYPE_OUTPUT: numCaps = caps->NumberOutputValueCaps; api_report_type = HidP_Output; break;
1420 case HID_REPORT_TYPE_FEATURE: numCaps = caps->NumberFeatureValueCaps; api_report_type = HidP_Feature; break;
1421 }
1422 PHIDP_VALUE_CAPS pValueCaps;
1423 pValueCaps = malloc(numCaps * sizeof(HIDP_VALUE_CAPS));
1424 if (HidP_GetValueCaps(api_report_type, pValueCaps, &numCaps, pp_data) != HIDP_STATUS_SUCCESS){
1425 free(pValueCaps);
1426 return -1;
1427 }
1428 for (i = 0; i < numCaps; i++){
1429 // Create a new element
1430 struct hid_device_element *new_element = hid_new_element();
1431 if (plast_element){
1432 plast_element->next = new_element;
1433 }
1434 // Connect to previous element
1435 plast_element = new_element;
1436 // Add element to collections, and fill element values
1437 PHIDP_VALUE_CAPS pCaps = &pValueCaps[i];
1438 add_element_to_collection(pdevice_collection, new_element);
1439 add_element_to_collection(ppcollections[pCaps->LinkCollection], new_element);
1440 new_element->io_type = report_type;
1441 new_element->index = (*index)++;
1442 fill_element_from_value_caps(pCaps, new_element);
1443
1444 if (pCaps->IsRange){
1445 // If it is a range, we copy the element, and update the usage. We want to have an element per usage.
1446 new_element->usage = pCaps->Range.UsageMin;
1447 debug_element(new_element);
1448 for (j = pCaps->Range.UsageMin + 1; j <= pCaps->Range.UsageMax; j++){
1449 new_element = duplicate_element_with_new_usage(plast_element, j, pdevice_collection, index);
1450 plast_element->next = new_element;
1451 plast_element = new_element;
1452 #ifdef DEBUG_PARSER
1453 debug_element(new_element);
1454 #endif
1455 }
1456 }
1457 else{
1458 new_element->usage = pCaps->NotRange.Usage;
1459 #ifdef DEBUG_PARSER
1460 debug_element(new_element);
1461 #endif
1462 }
1463 }
1464 free(pValueCaps);
1465 }
1466
1467 // make sure the last element index is visible outside
1468 *pplast_element = plast_element;
1469 return 0;
1470 }
1471
1472
1473
hid_send_element_output(struct hid_dev_desc * devdesc,struct hid_device_element * element)1474 int hid_send_element_output( struct hid_dev_desc * devdesc, struct hid_device_element * element ){
1475 return 0;
1476 }
hid_parse_input_elements_values(unsigned char * buf,int size,struct hid_dev_desc * devdesc)1477 int hid_parse_input_elements_values( unsigned char* buf, int size, struct hid_dev_desc * devdesc ){
1478 // If there is only one report, there will be no report ID in the report. Otherwise, it is the first byte
1479 int i;
1480 int report_id = 0;
1481 int report_length = 0;
1482 struct hid_device_collection * device_collection = devdesc->device_collection;
1483 struct hid_device_element * cur_element = device_collection->first_element;
1484 NTSTATUS res;
1485
1486 if (devdesc->number_of_reports != 1){
1487 report_id = buf[0];
1488 }
1489
1490 // I thtink on Windows we do not need to calculate the report size here, and we can just get it from the size parameter that we got from above
1491 for (i = 0; i < devdesc->number_of_reports; i++){
1492 if (devdesc->report_ids[i] == report_id){
1493 report_length = size;
1494 }
1495 }
1496 if (report_length == 0){
1497 // This should not happen, the report was not found
1498 return -1;
1499 }
1500
1501 if (cur_element->io_type != HID_REPORT_TYPE_INPUT){
1502 cur_element = hid_get_next_input_element(cur_element);
1503 }
1504
1505 // The Windows API has a function to get the data of all the buttons that are on, and another to get the value data by component page and usage
1506 // We get all the buttons that are on
1507 HANDLE dev_handle = get_device_handle(devdesc->device);
1508 PHIDP_PREPARSED_DATA pp_data;
1509 if (!HidD_GetPreparsedData(dev_handle, &pp_data)){
1510 return -1;
1511 }
1512 long usage_and_page_length = HidP_MaxUsageListLength(HidP_Input, 0, pp_data);
1513 PUSAGE_AND_PAGE usage_and_page_list = malloc(usage_and_page_length * sizeof(USAGE_AND_PAGE));
1514 memset(usage_and_page_list, 0, usage_and_page_length * sizeof(USAGE_AND_PAGE));
1515
1516 NTSTATUS ntres = HidP_GetButtonsEx(HidP_Input, 0, usage_and_page_list, &usage_and_page_length, pp_data, buf, report_length);
1517 if ( ntres != HIDP_STATUS_SUCCESS){
1518 free(usage_and_page_list);
1519 return -1;
1520 }
1521
1522 while (cur_element != NULL){
1523 // Check that the element is part of this report
1524 if (cur_element->report_id != report_id){
1525 cur_element = hid_get_next_input_element(cur_element);
1526 continue;
1527 }
1528
1529 if (devdesc->_element_callback != NULL){
1530 // TODO may need to use HidP_GetUsageValueArray, if element->report_index > 1
1531 unsigned long new_value;
1532 res = HidP_GetUsageValue(HidP_Input, cur_element->usage_page, 0, cur_element->usage, &new_value, pp_data, buf, report_length);
1533 if (res == HIDP_STATUS_SUCCESS){
1534 if (new_value != cur_element->rawvalue || cur_element->repeat){
1535 #ifdef DEBUG_PARSER
1536 printf("element page %i, usage %i, index %i, value %i, rawvalue %i, newvalue %i\n", cur_element->usage_page, cur_element->usage, cur_element->index, cur_element->value, cur_element->rawvalue, new_value);
1537 #endif
1538 hid_element_set_value_from_input(cur_element, new_value);
1539 devdesc->_element_callback(cur_element, devdesc->_element_data);
1540 }
1541 }
1542 else if (res == HIDP_STATUS_USAGE_NOT_FOUND){
1543 // Then see if we can find the element's page and usage in the buttons that are set to on, if not, it is implicitly 0
1544 new_value = 0;
1545 for (i = 0; i < usage_and_page_length; i++){
1546 USAGE usage = usage_and_page_list[i].Usage;
1547 if (usage_and_page_list[i].UsagePage = cur_element->usage_page && usage == cur_element->usage){
1548 new_value = 1;
1549 break;
1550 }
1551 }
1552 if (new_value != cur_element->rawvalue || cur_element->repeat){
1553 hid_element_set_value_from_input(cur_element, new_value);
1554 #ifdef DEBUG_PARSER
1555 printf("element page %i, usage %i, index %i, value %i, rawvalue %i, newvalue %i\n", cur_element->usage_page, cur_element->usage, cur_element->index, cur_element->value, cur_element->rawvalue, new_value);
1556 #endif
1557 devdesc->_element_callback(cur_element, devdesc->_element_data);
1558 }
1559 }
1560 }
1561 cur_element = hid_get_next_input_element(cur_element);
1562 }
1563 free(usage_and_page_list);
1564
1565 return 0;
1566 }
hid_parse_element_info(struct hid_dev_desc * devdesc)1567 void hid_parse_element_info( struct hid_dev_desc * devdesc ){
1568
1569 int i, j;
1570 hid_device * dev = devdesc->device;
1571
1572 struct hid_device_collection * device_collection = hid_new_collection();
1573 devdesc->device_collection = device_collection;
1574
1575 struct hid_device_collection * parent_collection = devdesc->device_collection;
1576
1577 device_collection->num_collections = 0;
1578 device_collection->num_elements = 0;
1579
1580 int numreports = 1;
1581 int report_lengths[256];
1582 int report_ids[256];
1583 report_ids[0] = 0;
1584 report_lengths[0] = 0;
1585
1586 // To keep track of indices
1587 int new_index = 0;
1588
1589 int numColls = 0;
1590
1591 NTSTATUS nt_res;
1592 PHIDP_PREPARSED_DATA pp_data = NULL;
1593 HIDP_CAPS caps;
1594
1595 /* Open a handle to the device */
1596 HANDLE dev_handle = get_device_handle(dev);
1597
1598 /* Check validity of write_handle. */
1599 if (dev_handle == INVALID_HANDLE_VALUE) {
1600 /* Unable to open the device. */
1601 //register_error(dev, "CreateFile");
1602 // TODO: not sure what to do here
1603 return;
1604 }
1605
1606 /* Get the Usage Page and Usage for this device. */
1607 BOOLEAN res = HidD_GetPreparsedData(dev_handle, &pp_data);
1608 if (!res){
1609 // TODO: what should we do here?
1610 return;
1611 }
1612
1613 nt_res = HidP_GetCaps(pp_data, &caps);
1614 if (nt_res != HIDP_STATUS_SUCCESS) {
1615 // TODO: what should we do here
1616 return;
1617 }
1618 numColls = caps.NumberLinkCollectionNodes;
1619
1620 device_collection->num_collections = numColls;
1621 device_collection->usage_page = caps.UsagePage;
1622 device_collection->usage_index = caps.Usage;
1623
1624 device_collection->index = new_index++;
1625 device_collection->num_elements = 0;
1626
1627 PHIDP_LINK_COLLECTION_NODE linkCollectionNodes;
1628 linkCollectionNodes = malloc(numColls * sizeof(HIDP_LINK_COLLECTION_NODE));
1629 struct hid_device_collection **collections = malloc(numColls * sizeof(struct hid_device_collection *));
1630 nt_res = HidP_GetLinkCollectionNodes( linkCollectionNodes, &numColls, pp_data );
1631 if (nt_res != HIDP_STATUS_SUCCESS){
1632 // TODO: what to do here?
1633 return;
1634 }
1635
1636 // Create the N collections, and put them in an array, so that we can efficiently construct the pointers to each other using the Windows API
1637 for (i = 0; i < numColls; i++){
1638 collections[i] = hid_new_collection();
1639 }
1640
1641 // And now fill the data and create the collection links
1642 for (i = 0; i < numColls; i++){
1643 PHIDP_LINK_COLLECTION_NODE p_collection = &linkCollectionNodes[i];
1644 // Documentation says that if parent is 0, then there is no parent, but then how do you indicate that the parent is at index 0???
1645 // I think that is wrong, and 0 indicates that the parent is the collection at index
1646 // I will assume that the collection at index 0 is always the outermost one
1647 if (i == 0){
1648 device_collection->first_collection = collections[i];
1649 collections[i]->parent_collection = device_collection;
1650 }
1651 else{
1652 collections[i]->parent_collection = collections[p_collection->Parent];
1653 }
1654 if (p_collection->NextSibling)
1655 collections[i]->next_collection = collections[p_collection->NextSibling];
1656
1657 if (p_collection->FirstChild)
1658 collections[i]->first_collection = collections[p_collection->FirstChild];
1659
1660 collections[i]->num_collections = p_collection->NumberOfChildren;
1661 collections[i]->type = p_collection->CollectionType;
1662 collections[i]->usage_page = p_collection->LinkUsagePage;
1663 collections[i]->usage_index = p_collection->LinkUsage;
1664 collections[i]->index = new_index++; // TODO not sure about this one
1665 #ifdef DEBUG_PARSER
1666 debug_collection(collections[i], i);
1667 #endif
1668 }
1669 #ifdef DEBUG_PARSER
1670 debug_collection(device_collection, 100);
1671 #endif
1672
1673 /* Now, create the elements, parsing the (input, output, feature) x (button, values) capabilities */
1674 int index_element = 0;
1675 new_index = 0;
1676 struct hid_device_element *last_element = NULL;
1677 hid_parse_caps(&last_element, collections, device_collection, pp_data, &caps, HID_REPORT_TYPE_INPUT, FALSE, &new_index);
1678 hid_parse_caps(&last_element, collections, device_collection, pp_data, &caps, HID_REPORT_TYPE_INPUT, TRUE, &new_index);
1679 hid_parse_caps(&last_element, collections, device_collection, pp_data, &caps, HID_REPORT_TYPE_OUTPUT, FALSE, &new_index);
1680 hid_parse_caps(&last_element, collections, device_collection, pp_data, &caps, HID_REPORT_TYPE_OUTPUT, TRUE, &new_index);
1681 hid_parse_caps(&last_element, collections, device_collection, pp_data, &caps, HID_REPORT_TYPE_FEATURE, FALSE, &new_index);
1682 hid_parse_caps(&last_element, collections, device_collection, pp_data, &caps, HID_REPORT_TYPE_FEATURE, TRUE, &new_index);
1683
1684 /* Reports */
1685 // Perhaps look at this (from MSDN): The XxxReportByteLength members of a HID collection's HIDP_CAPS structure specify the required size of input, output, and feature reports
1686 // On Windows it is not clear that knowing the report size is important at this point, since we get it implicitly on the read size. It's quite likely that the calculation done here
1687 // is not right, but it does not affect (should revisit later)
1688 struct hid_device_element *element = device_collection->first_element;
1689 while (element != NULL){
1690 int report_id = element->report_id;
1691 int report_size = element->report_size;
1692 int report_count = element->report_index; // TODO: report_count is not used????
1693
1694 int reportexists = 0;
1695 for (j = 0; j < numreports; j++){
1696 reportexists = (report_ids[j] == report_id);
1697 }
1698 if (!reportexists){
1699 report_ids[numreports] = report_id;
1700 report_lengths[numreports] = 0;
1701 numreports++;
1702 }
1703 int k = 0;
1704 int index = 0;
1705 for (k = 0; k<numreports; k++){
1706 if (report_id == report_ids[k]){
1707 index = k;
1708 break;
1709 }
1710 }
1711 report_lengths[index] += report_size;
1712 element = element->next;
1713 }
1714
1715 devdesc->number_of_reports = numreports;
1716 devdesc->report_lengths = (int*)malloc(sizeof(int) * numreports);
1717 devdesc->report_ids = (int*)malloc(sizeof(int) * numreports);
1718 for (j = 0; j<numreports; j++){
1719 devdesc->report_lengths[j] = report_lengths[j];
1720 devdesc->report_ids[j] = report_ids[j];
1721 }
1722
1723 /* And clean up the temp structures */
1724 free(collections);
1725 free(linkCollectionNodes);
1726 HidD_FreePreparsedData(pp_data);
1727 }
1728 #endif
1729
1730
1731 #ifdef APPLE
1732
1733 #include <IOKit/hid/IOHIDManager.h>
1734 #include <IOKit/hid/IOHIDKeys.h>
1735 #include <CoreFoundation/CoreFoundation.h>
1736
1737 // from: https://developer.apple.com/library/mac/documentation/devicedrivers/conceptual/HID/new_api_10_5/tn2187.html#//apple_ref/doc/uid/TP40000970-CH214-SW2
1738
hid_send_element_output(struct hid_dev_desc * devdesc,struct hid_device_element * element)1739 int hid_send_element_output( struct hid_dev_desc * devdesc, struct hid_device_element * element ){
1740 IOReturn tIOReturn;
1741 IOHIDDeviceRef device_handle = get_device_handle( devdesc->device );
1742 IOHIDElementRef tIOHIDElementRef = element->appleIOHIDElementRef;
1743
1744 // get the logical mix/max for this LED element
1745 CFIndex minCFIndex = IOHIDElementGetLogicalMin( tIOHIDElementRef );
1746 CFIndex maxCFIndex = IOHIDElementGetLogicalMax( tIOHIDElementRef );
1747 // calculate the range
1748 CFIndex modCFIndex = maxCFIndex - minCFIndex + 1;
1749 // compute the value for this LED element
1750 CFIndex tCFIndex = minCFIndex + ( element->value % modCFIndex );
1751
1752 uint64_t timestamp = 0; // create the IO HID Value to be sent
1753
1754 IOHIDValueRef tIOHIDValueRef = IOHIDValueCreateWithIntegerValue( kCFAllocatorDefault, tIOHIDElementRef, timestamp, tCFIndex );
1755
1756 if ( tIOHIDValueRef ) {
1757 tIOReturn = IOHIDDeviceSetValue( device_handle, tIOHIDElementRef, tIOHIDValueRef );
1758 CFRelease( tIOHIDValueRef );
1759 if ( tIOReturn == kIOReturnSuccess ){
1760 return 0;
1761 }
1762 }
1763 return -1;
1764 }
1765
1766 // int hid_parse_input_report( unsigned char* buf, int size, struct hid_dev_desc * devdesc ){
hid_parse_input_elements_values(unsigned char * buf,struct hid_dev_desc * devdesc)1767 int hid_parse_input_elements_values( unsigned char* buf, struct hid_dev_desc * devdesc ){
1768 struct hid_device_collection * device_collection = devdesc->device_collection;
1769 struct hid_device_element * cur_element = device_collection->first_element;
1770 int i=0;
1771 int newvalue;
1772 int reportid = 0;
1773
1774 IOHIDDeviceRef device_handle = get_device_handle( devdesc->device );
1775 IOHIDValueRef newValueRef;
1776 IOReturn tIOReturn;
1777
1778 /*
1779 if ( devdesc->number_of_reports > 1 ){
1780 reportid = (int) buf[i];
1781 }
1782
1783 if ( cur_element->io_type != 1 || ( cur_element->report_id != reportid ) ){
1784 cur_element = hid_get_next_input_element_with_reportid(cur_element, reportid );
1785 }
1786 */
1787 // printf( "======== start of report: cur_element %i\n", cur_element );
1788 if ( cur_element->io_type != 1 ){
1789 cur_element = hid_get_next_input_element(cur_element);
1790 }
1791 //printf( "cur_element %i", cur_element );
1792
1793 while( cur_element != NULL ){
1794 if ( devdesc->_element_callback != NULL ){
1795 tIOReturn = IOHIDDeviceGetValue( device_handle, cur_element->appleIOHIDElementRef, &newValueRef );
1796 // printf("element page %i, usage %i, index %i, value %i, rawvalue %i, newvalueref %i\n", cur_element->usage_page, cur_element->usage, cur_element->index, cur_element->value, cur_element->rawvalue, newValueRef );
1797 if ( tIOReturn == kIOReturnSuccess ){
1798 newvalue = IOHIDValueGetIntegerValue( newValueRef );
1799 if ( newvalue != cur_element->rawvalue || cur_element->repeat ){
1800 #ifdef DEBUG_PARSER
1801 printf("element page %i, usage %i, index %i, value %i, rawvalue %i, newvalue %i\n", cur_element->usage_page, cur_element->usage, cur_element->index, cur_element->value, cur_element->rawvalue, newvalue );
1802 #endif
1803 hid_element_set_value_from_input( cur_element, newvalue );
1804 devdesc->_element_callback( cur_element, devdesc->_element_data );
1805 }
1806 }
1807 }
1808 // cur_element = hid_get_next_input_element_with_reportid( cur_element, reportid );
1809 cur_element = hid_get_next_input_element( cur_element );
1810 // printf( "cur_element %i\n", cur_element );
1811 }
1812 // printf( "======== end of report\n");
1813 return 0;
1814 }
1815
1816 /*
1817 IOReturn tIOReturn = IOHIDDeviceGetValue(
1818 deviceRef, // IOHIDDeviceRef for the HID device
1819 elementRef, // IOHIDElementRef for the HID element
1820 valueRef); // IOHIDValueRef for the HID element's new value
1821 */
1822
hid_parse_element_info(struct hid_dev_desc * devdesc)1823 void hid_parse_element_info( struct hid_dev_desc * devdesc )
1824 {
1825 hid_device * dev = devdesc->device;
1826
1827 struct hid_device_collection * device_collection = hid_new_collection();
1828 devdesc->device_collection = device_collection;
1829
1830 struct hid_device_collection * parent_collection = devdesc->device_collection;
1831 struct hid_device_collection * prev_collection;
1832 struct hid_device_element * prev_element;
1833
1834 device_collection->num_collections = 0;
1835 device_collection->num_elements = 0;
1836
1837 int numreports = 1;
1838 int report_lengths[256];
1839 int report_ids[256];
1840 report_ids[0] = 0;
1841 report_lengths[0] = 0;
1842
1843 IOHIDDeviceRef device_handle = get_device_handle( dev );
1844 CFArrayRef elementCFArrayRef = IOHIDDeviceCopyMatchingElements(device_handle,
1845 NULL /* matchingCFDictRef */
1846 , kIOHIDOptionsTypeNone);
1847 if (elementCFArrayRef) {
1848 // iterate over all the elements
1849 CFIndex elementIndex, elementCount = CFArrayGetCount(elementCFArrayRef);
1850 for (elementIndex = 0; elementIndex < elementCount; elementIndex++) {
1851 IOHIDElementRef tIOHIDElementRef = (IOHIDElementRef)CFArrayGetValueAtIndex(elementCFArrayRef,elementIndex);
1852 if (tIOHIDElementRef) {
1853 IOHIDElementType tIOHIDElementType = IOHIDElementGetType(tIOHIDElementRef);
1854 uint32_t usagePage = IOHIDElementGetUsagePage(tIOHIDElementRef);
1855 uint32_t usage = IOHIDElementGetUsage(tIOHIDElementRef);
1856
1857 if ( tIOHIDElementType == kIOHIDElementTypeCollection ){
1858 //TODO: COULD ALSO READ WHICH KIND OF COLLECTION
1859 struct hid_device_collection * new_collection = hid_new_collection();
1860 if ( parent_collection->num_collections == 0 ){
1861 parent_collection->first_collection = new_collection;
1862 }
1863 if ( device_collection->num_collections == 0 ){
1864 device_collection->first_collection = new_collection;
1865 } else {
1866 prev_collection->next_collection = new_collection;
1867 }
1868 new_collection->parent_collection = parent_collection;
1869 IOHIDElementCollectionType tIOHIDElementCollectionType = IOHIDElementGetCollectionType(tIOHIDElementRef);
1870 new_collection->type = (int) tIOHIDElementCollectionType;
1871 new_collection->usage_page = usagePage;
1872 new_collection->usage_index = usage;
1873 new_collection->index = device_collection->num_collections;
1874 device_collection->num_collections++;
1875 if ( device_collection != parent_collection ){
1876 parent_collection->num_collections++;
1877 }
1878 parent_collection = new_collection;
1879 prev_collection = new_collection;
1880 // collection_nesting++;
1881 } else {
1882 struct hid_device_element * new_element = hid_new_element();
1883 new_element->appleIOHIDElementRef = tIOHIDElementRef; // set the element ref
1884 new_element->index = device_collection->num_elements;
1885 // check input (1), output (2), or feature (3)
1886 // type - this we parse later on again, so perhaps would be good to bittest this rightaway in general
1887 // ["Data","Constant"],
1888 Boolean isVirtual = IOHIDElementIsVirtual(tIOHIDElementRef);
1889 // ["Array","Variable"]
1890 Boolean isArray = IOHIDElementIsArray(tIOHIDElementRef);
1891 // ["Absolute","Relative"]
1892 Boolean isRelative = IOHIDElementIsRelative(tIOHIDElementRef);
1893 // ["NoWrap","Wrap"],
1894 Boolean isWrapping = IOHIDElementIsWrapping(tIOHIDElementRef);
1895 // ["Linear","NonLinear"],
1896 Boolean isNonLinear = IOHIDElementIsNonLinear(tIOHIDElementRef);
1897 // ["PreferredState","NoPreferred"],
1898 Boolean hasPreferredState = IOHIDElementHasPreferredState(tIOHIDElementRef);
1899 // ["NoNullPosition", "NullState"],
1900 Boolean hasNullState = IOHIDElementHasNullState(tIOHIDElementRef);
1901 int type = 0;
1902 new_element->type = 0;
1903 type = (int) isVirtual;
1904 new_element->isvariable = (int) !isVirtual;
1905 new_element->type += type;
1906 new_element->isarray = (int) isArray;
1907 type = ((int) !isArray) << 1;
1908 new_element->type += type;
1909 new_element->isrelative = (int) isRelative;
1910 type = ((int) isRelative) << 2;
1911 new_element->type += type;
1912 type = ((int) isWrapping) << 3;
1913 new_element->type += type;
1914 type = ((int) isNonLinear) << 4;
1915 new_element->type += type;
1916 type = ((int) !hasPreferredState) << 5;
1917 new_element->type += type;
1918 type = ((int) hasNullState) << 6;
1919 new_element->type += type;
1920 switch (tIOHIDElementType) {
1921 case kIOHIDElementTypeInput_Misc:
1922 {
1923 new_element->io_type = 1;
1924 // printf("type: Misc, ");
1925 break;
1926 }
1927 case kIOHIDElementTypeInput_Button:
1928 {
1929 new_element->io_type = 1;
1930 // printf("type: Button, ");
1931 break;
1932 }
1933 case kIOHIDElementTypeInput_Axis:
1934 {
1935 new_element->io_type = 1;
1936 // printf("type: Axis, ");
1937 break;
1938 }
1939 case kIOHIDElementTypeInput_ScanCodes:
1940 {
1941 new_element->io_type = 1;
1942 // printf("type: ScanCodes, ");
1943 break;
1944 }
1945 case kIOHIDElementTypeOutput:
1946 {
1947 new_element->io_type = 2;
1948 // printf("type: Output, ");
1949 break;
1950 }
1951 case kIOHIDElementTypeFeature:
1952 {
1953 new_element->io_type = 3;
1954 // printf("type: Feature, ");
1955 break;
1956 }
1957 }
1958 new_element->parent_collection = parent_collection;
1959 new_element->usage_page = usagePage;
1960 new_element->usage = usage;
1961 CFIndex logicalMin = IOHIDElementGetLogicalMin(tIOHIDElementRef);
1962 CFIndex logicalMax = IOHIDElementGetLogicalMax(tIOHIDElementRef);
1963 new_element->logical_min = logicalMin;
1964 new_element->logical_max = logicalMax;
1965 CFIndex physicalMin = IOHIDElementGetPhysicalMin(tIOHIDElementRef);
1966 CFIndex physicalMax = IOHIDElementGetPhysicalMax(tIOHIDElementRef);
1967 new_element->phys_min = physicalMin;
1968 new_element->phys_max = physicalMax;
1969 uint32_t unit = IOHIDElementGetUnit(tIOHIDElementRef);
1970 uint32_t unitExp = IOHIDElementGetUnitExponent(tIOHIDElementRef);
1971 new_element->unit = unit;
1972 new_element->unit_exponent = unitExp;
1973 uint32_t reportID = IOHIDElementGetReportID(tIOHIDElementRef);
1974 uint32_t reportSize = IOHIDElementGetReportSize(tIOHIDElementRef);
1975 uint32_t reportCount = IOHIDElementGetReportCount(tIOHIDElementRef);
1976 new_element->report_size = reportSize;
1977 new_element->report_id = reportID;
1978 new_element->report_index = reportCount; // ?? - was j... index
1979 new_element->value = 0;
1980 new_element->array_value = 0;
1981
1982 int reportexists = 0;
1983 for ( int j = 0; j < numreports; j++ ){
1984 reportexists = (report_ids[j] == reportID);
1985 }
1986 if ( !reportexists ){
1987 report_ids[ numreports ] = reportID;
1988 report_lengths[ numreports ] = 0;
1989 numreports++;
1990 }
1991 int k = 0;
1992 int index = 0;
1993 for ( k=0; k<numreports; k++ ){
1994 if ( reportID == report_ids[k] ){
1995 index = k;
1996 break;
1997 }
1998 }
1999 report_lengths[index] += reportSize;
2000
2001 if ( parent_collection->num_elements == 0 ){
2002 parent_collection->first_element = new_element;
2003 }
2004 if ( device_collection->num_elements == 0 ){
2005 device_collection->first_element = new_element;
2006 } else {
2007 prev_element->next = new_element;
2008 }
2009 device_collection->num_elements++;
2010 if ( parent_collection != device_collection ) {
2011 parent_collection->num_elements++;
2012 }
2013 prev_element = new_element;
2014 }
2015 }
2016 }
2017 CFRelease(elementCFArrayRef);
2018 }
2019 devdesc->number_of_reports = numreports;
2020 devdesc->report_lengths = (int*) malloc( sizeof( int ) * numreports );
2021 devdesc->report_ids = (int*) malloc( sizeof( int ) * numreports );
2022 for ( int j = 0; j<numreports; j++ ){
2023 devdesc->report_lengths[j] = report_lengths[j];
2024 devdesc->report_ids[j] = report_ids[j];
2025 }
2026 //return 0;
2027 }
2028
2029 #endif
2030