hidpath.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2011 Matej Klonfar
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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         // Empty path match all others
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         /* path is somewhere in report_path */
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         /* the paths must be identical */
00267         case USB_HID_PATH_COMPARE_STRICT:
00268                 if(report_path->depth != path->depth){
00269                         return 1;
00270                 }
00271                 
00272         /* path is prefix of the report_path */
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         /* path is suffix of report_path */
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 

Generated on Thu Jun 2 07:45:48 2011 for HelenOS/USB by  doxygen 1.4.7