00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00035 #include <usb/hid/hidparser.h>
00036 #include <errno.h>
00037 #include <stdio.h>
00038 #include <malloc.h>
00039 #include <mem.h>
00040 #include <usb/debug.h>
00041 #include <assert.h>
00042
00043
00052 #define USB_HID_SAME_USAGE(usage1, usage2) \
00053 ((usage1 == usage2) || (usage1 == 0) || (usage2 == 0))
00054
00062 #define USB_HID_SAME_USAGE_PAGE(page1, page2) \
00063 ((page1 == page2) || (page1 == 0) || (page2 == 0))
00064
00065
00075 int usb_hid_report_path_append_item(usb_hid_report_path_t *usage_path,
00076 int32_t usage_page, int32_t usage)
00077 {
00078 usb_hid_report_usage_path_t *item;
00079
00080 if(!(item=malloc(sizeof(usb_hid_report_usage_path_t)))) {
00081 return ENOMEM;
00082 }
00083 list_initialize(&item->link);
00084
00085 item->usage = usage;
00086 item->usage_page = usage_page;
00087 item->flags = 0;
00088
00089 list_append (&item->link, &usage_path->head);
00090 usage_path->depth++;
00091 return EOK;
00092 }
00093
00094
00100 void usb_hid_report_remove_last_item(usb_hid_report_path_t *usage_path)
00101 {
00102 usb_hid_report_usage_path_t *item;
00103
00104 if(!list_empty(&usage_path->head)){
00105 item = list_get_instance(usage_path->head.prev,
00106 usb_hid_report_usage_path_t, link);
00107 list_remove(usage_path->head.prev);
00108 usage_path->depth--;
00109 free(item);
00110 }
00111 }
00112
00113
00120 void usb_hid_report_null_last_item(usb_hid_report_path_t *usage_path)
00121 {
00122 usb_hid_report_usage_path_t *item;
00123
00124 if(!list_empty(&usage_path->head)){
00125 item = list_get_instance(usage_path->head.prev,
00126 usb_hid_report_usage_path_t, link);
00127
00128 memset(item, 0, sizeof(usb_hid_report_usage_path_t));
00129 }
00130 }
00131
00132
00142 void usb_hid_report_set_last_item(usb_hid_report_path_t *usage_path,
00143 int32_t tag, int32_t data)
00144 {
00145 usb_hid_report_usage_path_t *item;
00146
00147 if(!list_empty(&usage_path->head)){
00148 item = list_get_instance(usage_path->head.prev,
00149 usb_hid_report_usage_path_t, link);
00150
00151 switch(tag) {
00152 case USB_HID_TAG_CLASS_GLOBAL:
00153 item->usage_page = data;
00154 break;
00155 case USB_HID_TAG_CLASS_LOCAL:
00156 item->usage = data;
00157 break;
00158 }
00159 }
00160
00161 }
00162
00163
00170 void usb_hid_print_usage_path(usb_hid_report_path_t *path)
00171 {
00172 usb_log_debug("USAGE_PATH FOR RId(%d):\n", path->report_id);
00173 usb_log_debug("\tLENGTH: %d\n", path->depth);
00174
00175 link_t *item = path->head.next;
00176 usb_hid_report_usage_path_t *path_item;
00177 while(item != &path->head) {
00178
00179 path_item = list_get_instance(item, usb_hid_report_usage_path_t,
00180 link);
00181
00182 usb_log_debug("\tUSAGE_PAGE: %X\n", path_item->usage_page);
00183 usb_log_debug("\tUSAGE: %X\n", path_item->usage);
00184 usb_log_debug("\tFLAGS: %d\n", path_item->flags);
00185
00186 item = item->next;
00187 }
00188 }
00189
00190
00200 int usb_hid_report_compare_usage_path(usb_hid_report_path_t *report_path,
00201 usb_hid_report_path_t *path,
00202 int flags)
00203 {
00204 usb_hid_report_usage_path_t *report_item;
00205 usb_hid_report_usage_path_t *path_item;
00206
00207 link_t *report_link;
00208 link_t *path_link;
00209
00210 int only_page;
00211
00212 if(report_path->report_id != path->report_id) {
00213 if(path->report_id != 0) {
00214 return 1;
00215 }
00216 }
00217
00218
00219 if(path->depth == 0){
00220 return EOK;
00221 }
00222
00223
00224 if((only_page = flags & USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY) != 0){
00225 flags -= USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY;
00226 }
00227
00228 switch(flags){
00229
00230 case USB_HID_PATH_COMPARE_ANYWHERE:
00231 if(path->depth != 1){
00232 return 1;
00233 }
00234
00235 report_link = report_path->head.next;
00236 path_link = path->head.next;
00237 path_item = list_get_instance(path_link,
00238 usb_hid_report_usage_path_t, link);
00239
00240 while(report_link != &report_path->head) {
00241 report_item = list_get_instance(report_link,
00242 usb_hid_report_usage_path_t, link);
00243
00244 if(USB_HID_SAME_USAGE_PAGE(report_item->usage_page,
00245 path_item->usage_page)){
00246
00247 if(only_page == 0){
00248 if(USB_HID_SAME_USAGE(
00249 report_item->usage,
00250 path_item->usage)) {
00251
00252 return EOK;
00253 }
00254 }
00255 else {
00256 return EOK;
00257 }
00258 }
00259
00260 report_link = report_link->next;
00261 }
00262
00263 return 1;
00264 break;
00265
00266
00267 case USB_HID_PATH_COMPARE_STRICT:
00268 if(report_path->depth != path->depth){
00269 return 1;
00270 }
00271
00272
00273 case USB_HID_PATH_COMPARE_BEGIN:
00274
00275 report_link = report_path->head.next;
00276 path_link = path->head.next;
00277
00278 while((report_link != &report_path->head) &&
00279 (path_link != &path->head)) {
00280
00281 report_item = list_get_instance(report_link,
00282 usb_hid_report_usage_path_t, link);
00283
00284 path_item = list_get_instance(path_link,
00285 usb_hid_report_usage_path_t, link);
00286
00287 if(!USB_HID_SAME_USAGE_PAGE(report_item->usage_page,
00288 path_item->usage_page) || ((only_page == 0) &&
00289 !USB_HID_SAME_USAGE(report_item->usage,
00290 path_item->usage))) {
00291
00292 return 1;
00293 }
00294 else {
00295 report_link = report_link->next;
00296 path_link = path_link->next;
00297 }
00298
00299 }
00300
00301 if((((flags & USB_HID_PATH_COMPARE_BEGIN) != 0) &&
00302 (path_link == &path->head)) ||
00303 ((report_link == &report_path->head) &&
00304 (path_link == &path->head))) {
00305
00306 return EOK;
00307 }
00308 else {
00309 return 1;
00310 }
00311 break;
00312
00313
00314 case USB_HID_PATH_COMPARE_END:
00315
00316 report_link = report_path->head.prev;
00317 path_link = path->head.prev;
00318
00319 if(list_empty(&path->head)){
00320 return EOK;
00321 }
00322
00323 while((report_link != &report_path->head) &&
00324 (path_link != &path->head)) {
00325
00326 report_item = list_get_instance(report_link,
00327 usb_hid_report_usage_path_t, link);
00328
00329 path_item = list_get_instance(path_link,
00330 usb_hid_report_usage_path_t, link);
00331
00332 if(!USB_HID_SAME_USAGE_PAGE(report_item->usage_page,
00333 path_item->usage_page) || ((only_page == 0) &&
00334 !USB_HID_SAME_USAGE(report_item->usage,
00335 path_item->usage))) {
00336
00337 return 1;
00338 } else {
00339 report_link = report_link->prev;
00340 path_link = path_link->prev;
00341 }
00342
00343 }
00344
00345 if(path_link == &path->head) {
00346 return EOK;
00347 }
00348 else {
00349 return 1;
00350 }
00351
00352 break;
00353
00354 default:
00355 return EINVAL;
00356 }
00357 }
00358
00359
00365 usb_hid_report_path_t *usb_hid_report_path(void)
00366 {
00367 usb_hid_report_path_t *path;
00368 path = malloc(sizeof(usb_hid_report_path_t));
00369 if(path == NULL){
00370 return NULL;
00371 }
00372 else {
00373 path->depth = 0;
00374 path->report_id = 0;
00375 list_initialize(&path->link);
00376 list_initialize(&path->head);
00377 return path;
00378 }
00379 }
00380
00381
00388 void usb_hid_report_path_free(usb_hid_report_path_t *path)
00389 {
00390 while(!list_empty(&path->head)){
00391 usb_hid_report_remove_last_item(path);
00392 }
00393
00394 list_remove(&path->link);
00395 free(path);
00396 }
00397
00398
00405 usb_hid_report_path_t *usb_hid_report_path_clone(
00406 usb_hid_report_path_t *usage_path)
00407 {
00408 link_t *path_link;
00409 usb_hid_report_usage_path_t *path_item;
00410 usb_hid_report_usage_path_t *new_path_item;
00411 usb_hid_report_path_t *new_usage_path = usb_hid_report_path ();
00412
00413 if(new_usage_path == NULL){
00414 return NULL;
00415 }
00416
00417 new_usage_path->report_id = usage_path->report_id;
00418
00419 if(list_empty(&usage_path->head)){
00420 return new_usage_path;
00421 }
00422
00423 path_link = usage_path->head.next;
00424 while(path_link != &usage_path->head) {
00425 path_item = list_get_instance(path_link,
00426 usb_hid_report_usage_path_t, link);
00427
00428 new_path_item = malloc(sizeof(usb_hid_report_usage_path_t));
00429 if(new_path_item == NULL) {
00430 return NULL;
00431 }
00432
00433 list_initialize (&new_path_item->link);
00434 new_path_item->usage_page = path_item->usage_page;
00435 new_path_item->usage = path_item->usage;
00436 new_path_item->flags = path_item->flags;
00437
00438 list_append(&new_path_item->link, &new_usage_path->head);
00439 new_usage_path->depth++;
00440
00441 path_link = path_link->next;
00442 }
00443
00444 return new_usage_path;
00445 }
00446
00447
00455 int usb_hid_report_path_set_report_id(usb_hid_report_path_t *path,
00456 uint8_t report_id)
00457 {
00458 if(path == NULL){
00459 return EINVAL;
00460 }
00461
00462 path->report_id = report_id;
00463 return EOK;
00464 }
00465