Changes in / [26f6094:9e929a0] in mainline
- Location:
- uspace
- Files:
-
- 5 deleted
- 18 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/usbhid/generic/hiddev.c
r26f6094 r9e929a0 37 37 #include <usb/debug.h> 38 38 #include <usb/classes/classes.h> 39 #include <errno.h>40 #include <str_error.h>41 42 #include <usbhid_iface.h>43 39 44 40 #include "hiddev.h" … … 59 55 /*----------------------------------------------------------------------------*/ 60 56 61 static size_t usb_generic_hid_get_event_length(ddf_fun_t *fun);62 63 static int usb_generic_hid_get_event(ddf_fun_t *fun, int32_t *buffer,64 size_t size, size_t *act_size, unsigned int flags);65 66 /*----------------------------------------------------------------------------*/67 68 static usbhid_iface_t usb_generic_iface = {69 .get_event = usb_generic_hid_get_event,70 .get_event_length = usb_generic_hid_get_event_length71 };72 73 static ddf_dev_ops_t usb_generic_hid_ops = {74 .interfaces[USBHID_DEV_IFACE] = &usb_generic_iface75 };76 77 /*----------------------------------------------------------------------------*/78 79 static size_t usb_generic_hid_get_event_length(ddf_fun_t *fun)80 {81 if (fun == NULL || fun->driver_data) {82 return 0;83 }84 85 usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;86 87 return hid_dev->input_report_size;88 }89 90 /*----------------------------------------------------------------------------*/91 92 static int usb_generic_hid_get_event(ddf_fun_t *fun, int32_t *buffer,93 size_t size, size_t *act_size, unsigned int flags)94 {95 if (fun == NULL || fun->driver_data) {96 return EINVAL;97 }98 99 usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;100 101 if (hid_dev->input_report_size > size) {102 return EINVAL; // TODO: other error code103 }104 105 /*! @todo This should probably be atomic. */106 memcpy(buffer, hid_dev->input_report, hid_dev->input_report_size);107 *act_size = hid_dev->input_report_size;108 109 // clear the buffer so that it will not be received twice110 memset(hid_dev->input_report, 0, hid_dev->input_report_size);111 112 return EOK;113 }114 115 /*----------------------------------------------------------------------------*/116 117 static int usb_generic_hid_create_function(usb_hid_dev_t *hid_dev)118 {119 /* Create the function exposed under /dev/devices. */120 /** @todo Generate numbers for the devices? */121 usb_log_debug("Creating DDF function %s...\n", HID_GENERIC_FUN_NAME);122 ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed,123 HID_GENERIC_FUN_NAME);124 if (fun == NULL) {125 usb_log_error("Could not create DDF function node.\n");126 return ENOMEM;127 }128 129 int rc = ddf_fun_bind(fun);130 if (rc != EOK) {131 usb_log_error("Could not bind DDF function: %s.\n",132 str_error(rc));133 ddf_fun_destroy(fun);134 return rc;135 }136 137 fun->ops = &usb_generic_hid_ops;138 fun->driver_data = hid_dev;139 140 return EOK;141 }142 143 /*----------------------------------------------------------------------------*/144 145 int usb_generic_hid_init(usb_hid_dev_t *hid_dev)146 {147 if (hid_dev == NULL) {148 return EINVAL;149 }150 151 return usb_generic_hid_create_function(hid_dev);152 }153 154 /*----------------------------------------------------------------------------*/155 156 57 bool usb_generic_hid_polling_callback(usb_hid_dev_t *hid_dev, 157 58 uint8_t *buffer, size_t buffer_size) -
uspace/drv/usbhid/generic/hiddev.h
r26f6094 r9e929a0 46 46 const char *HID_GENERIC_CLASS_NAME; 47 47 48 /*----------------------------------------------------------------------------*/49 50 int usb_generic_hid_init(struct usb_hid_dev *hid_dev);51 52 48 bool usb_generic_hid_polling_callback(struct usb_hid_dev *hid_dev, 53 49 uint8_t *buffer, size_t buffer_size); -
uspace/drv/usbhid/kbd/kbddev.c
r26f6094 r9e929a0 766 766 767 767 /*----------------------------------------------------------------------------*/ 768 769 static int usb_kbd_create_function(usb_hid_dev_t *hid_dev)770 {771 assert(hid_dev != NULL);772 assert(hid_dev->usb_dev != NULL);773 774 /* Create the function exposed under /dev/devices. */775 usb_log_debug("Creating DDF function %s...\n", HID_KBD_FUN_NAME);776 ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed,777 HID_KBD_FUN_NAME);778 if (fun == NULL) {779 usb_log_error("Could not create DDF function node.\n");780 return ENOMEM;781 }782 783 /*784 * Store the initialized HID device and HID ops785 * to the DDF function.786 */787 fun->ops = &hid_dev->ops;788 fun->driver_data = hid_dev; // TODO: maybe change to hid_dev->data789 790 int rc = ddf_fun_bind(fun);791 if (rc != EOK) {792 usb_log_error("Could not bind DDF function: %s.\n",793 str_error(rc));794 ddf_fun_destroy(fun);795 return rc;796 }797 798 usb_log_debug("Adding DDF function to class %s...\n",799 HID_KBD_CLASS_NAME);800 rc = ddf_fun_add_to_class(fun, HID_KBD_CLASS_NAME);801 if (rc != EOK) {802 usb_log_error(803 "Could not add DDF function to class %s: %s.\n",804 HID_KBD_CLASS_NAME, str_error(rc));805 ddf_fun_destroy(fun);806 return rc;807 }808 809 return EOK;810 }811 812 /*----------------------------------------------------------------------------*/813 768 /* API functions */ 814 769 /*----------------------------------------------------------------------------*/ … … 975 930 usb_log_debug("HID/KBD device structure initialized.\n"); 976 931 977 usb_log_debug("Creating KBD function...\n");978 int rc = usb_kbd_create_function(hid_dev);979 if (rc != EOK) {980 usb_kbd_free(&kbd_dev);981 return rc;982 }983 984 932 return EOK; 985 933 } … … 1045 993 if ((*kbd_dev)->led_data != NULL) { 1046 994 free((*kbd_dev)->led_data); 995 } 996 if ((*kbd_dev)->output_buffer != NULL) { 997 free((*kbd_dev)->output_buffer); 1047 998 } 1048 999 if ((*kbd_dev)->led_path != NULL) { -
uspace/drv/usbhid/lgtch-ultrax/keymap.c
r26f6094 r9e929a0 55 55 [0xc] = KC_F6, /* Just for testing purposes */ 56 56 57 [0xb5] = 0, 58 [0xb6] = 0, 59 [0xb7] = 0, 60 [0xb8] = 0, 61 [0xcd] = KC_F2, 62 [0xe2] = KC_F3, 63 [0xe9] = KC_F5, 64 [0xea] = KC_F4, 65 [0x183] = 0, 66 [0x18a] = 0, 67 [0x192] = 0, 68 [0x221] = 0, 69 [0x223] = 0, 70 [0x224] = 0, 71 [0x225] = 0, 72 [0x226] = 0, 73 [0x227] = KC_F1, 74 [0x22a] = KC_F6 57 [0xb5] = 0, /* Scan Next Track */ 58 [0xb6] = 0, /* Scan Previous Track */ 59 [0xb7] = 0, /* Stop */ 60 [0xb8] = 0, /* Eject */ 61 [0xcd] = KC_F2, /* Play/Pause */ 62 [0xe2] = KC_F3, /* Mute */ 63 [0xe9] = KC_F5, /* Volume Increment */ 64 [0xea] = KC_F4, /* Volume Decrement */ 65 [0x183] = 0, /* AL Consumer Control Configuration */ 66 [0x18a] = 0, /* AL Email Reader */ 67 [0x192] = 0, /* AL Calculator */ 68 [0x221] = 0, /* AC Search */ 69 [0x223] = 0, /* AC Home */ 70 [0x224] = 0, /* AC Back */ 71 [0x225] = 0, /* AC Forward */ 72 [0x226] = 0, /* AC Stop */ 73 [0x227] = KC_F1, /* AC Refresh */ 74 [0x22a] = KC_F6 /* AC Bookmarks */ 75 75 }; 76 76 -
uspace/drv/usbhid/lgtch-ultrax/lgtch-ultrax.c
r26f6094 r9e929a0 58 58 } usb_lgtch_flags; 59 59 60 /*----------------------------------------------------------------------------*/61 /**62 * Logitech UltraX device type.63 */64 typedef struct usb_lgtch_ultrax_t {65 /** Previously pressed keys (not translated to key codes). */66 int32_t *keys_old;67 /** Currently pressed keys (not translated to key codes). */68 int32_t *keys;69 /** Count of stored keys (i.e. number of keys in the report). */70 size_t key_count;71 72 /** IPC phone to the console device (for sending key events). */73 int console_phone;74 75 /** Information for auto-repeat of keys. */76 // usb_kbd_repeat_t repeat;77 78 /** Mutex for accessing the information about auto-repeat. */79 // fibril_mutex_t *repeat_mtx;80 81 /** State of the structure (for checking before use).82 *83 * 0 - not initialized84 * 1 - initialized85 * -1 - ready for destroying86 */87 int initialized;88 } usb_lgtch_ultrax_t;89 90 60 91 61 /*----------------------------------------------------------------------------*/ … … 238 208 /*----------------------------------------------------------------------------*/ 239 209 240 static int usb_lgtch_create_function(usb_hid_dev_t *hid_dev) 241 { 210 int usb_lgtch_init(struct usb_hid_dev *hid_dev) 211 { 212 if (hid_dev == NULL || hid_dev->usb_dev == NULL) { 213 return EINVAL; /*! @todo Other return code? */ 214 } 215 216 usb_log_debug(NAME " Initializing HID/lgtch_ultrax structure...\n"); 217 218 usb_lgtch_ultrax_t *lgtch_dev = (usb_lgtch_ultrax_t *)malloc( 219 sizeof(usb_lgtch_ultrax_t)); 220 if (lgtch_dev == NULL) { 221 return ENOMEM; 222 } 223 224 lgtch_dev->console_phone = -1; 225 226 usb_hid_report_path_t *path = usb_hid_report_path(); 227 usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_CONSUMER, 0); 228 229 usb_hid_report_path_set_report_id(path, 1); 230 231 lgtch_dev->key_count = usb_hid_report_input_length( 232 hid_dev->report, path, 233 USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY); 234 usb_hid_report_path_free(path); 235 236 usb_log_debug(NAME " Size of the input report: %zu\n", 237 lgtch_dev->key_count); 238 239 lgtch_dev->keys = (int32_t *)calloc(lgtch_dev->key_count, 240 sizeof(int32_t)); 241 242 if (lgtch_dev->keys == NULL) { 243 usb_log_fatal("No memory!\n"); 244 free(lgtch_dev); 245 return ENOMEM; 246 } 247 248 lgtch_dev->keys_old = 249 (int32_t *)calloc(lgtch_dev->key_count, sizeof(int32_t)); 250 251 if (lgtch_dev->keys_old == NULL) { 252 usb_log_fatal("No memory!\n"); 253 free(lgtch_dev->keys); 254 free(lgtch_dev); 255 return ENOMEM; 256 } 257 258 /*! @todo Autorepeat */ 259 260 // save the KBD device structure into the HID device structure 261 hid_dev->data = lgtch_dev; 262 242 263 /* Create the function exposed under /dev/devices. */ 243 264 ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, … … 248 269 } 249 270 271 lgtch_dev->initialized = USB_LGTCH_STATUS_INITIALIZED; 272 usb_log_debug(NAME " HID/lgtch_ultrax device structure initialized.\n"); 273 250 274 /* 251 275 * Store the initialized HID device and HID ops … … 255 279 fun->driver_data = hid_dev; // TODO: maybe change to hid_dev->data 256 280 281 /* 282 * 1) subdriver vytvori vlastnu ddf_fun, vlastne ddf_dev_ops, ktore da 283 * do nej. 284 * 2) do tych ops do .interfaces[DEV_IFACE_USBHID (asi)] priradi 285 * vyplnenu strukturu usbhid_iface_t. 286 * 3) klientska aplikacia - musi si rucne vytvorit telefon 287 * (devman_device_connect() - cesta k zariadeniu (/hw/pci0/...) az 288 * k tej fcii. 289 * pouzit usb/classes/hid/iface.h - prvy int je telefon 290 */ 291 257 292 int rc = ddf_fun_bind(fun); 258 293 if (rc != EOK) { … … 261 296 // TODO: Can / should I destroy the DDF function? 262 297 ddf_fun_destroy(fun); 298 usb_lgtch_free(&lgtch_dev); 263 299 return rc; 264 300 } … … 271 307 // TODO: Can / should I destroy the DDF function? 272 308 ddf_fun_destroy(fun); 273 return rc;274 }275 276 return EOK;277 }278 279 /*----------------------------------------------------------------------------*/280 281 int usb_lgtch_init(struct usb_hid_dev *hid_dev)282 {283 if (hid_dev == NULL || hid_dev->usb_dev == NULL) {284 return EINVAL; /*! @todo Other return code? */285 }286 287 usb_log_debug(NAME " Initializing HID/lgtch_ultrax structure...\n");288 289 usb_lgtch_ultrax_t *lgtch_dev = (usb_lgtch_ultrax_t *)malloc(290 sizeof(usb_lgtch_ultrax_t));291 if (lgtch_dev == NULL) {292 return ENOMEM;293 }294 295 lgtch_dev->console_phone = -1;296 297 usb_hid_report_path_t *path = usb_hid_report_path();298 usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_CONSUMER, 0);299 300 usb_hid_report_path_set_report_id(path, 1);301 302 lgtch_dev->key_count = usb_hid_report_input_length(303 hid_dev->report, path,304 USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY);305 usb_hid_report_path_free(path);306 307 usb_log_debug(NAME " Size of the input report: %zu\n",308 lgtch_dev->key_count);309 310 lgtch_dev->keys = (int32_t *)calloc(lgtch_dev->key_count,311 sizeof(int32_t));312 313 if (lgtch_dev->keys == NULL) {314 usb_log_fatal("No memory!\n");315 free(lgtch_dev);316 return ENOMEM;317 }318 319 lgtch_dev->keys_old =320 (int32_t *)calloc(lgtch_dev->key_count, sizeof(int32_t));321 322 if (lgtch_dev->keys_old == NULL) {323 usb_log_fatal("No memory!\n");324 free(lgtch_dev->keys);325 free(lgtch_dev);326 return ENOMEM;327 }328 329 /*! @todo Autorepeat */330 331 // save the KBD device structure into the HID device structure332 hid_dev->data = lgtch_dev;333 334 lgtch_dev->initialized = USB_LGTCH_STATUS_INITIALIZED;335 usb_log_debug(NAME " HID/lgtch_ultrax device structure initialized.\n");336 337 int rc = usb_lgtch_create_function(hid_dev);338 if (rc != EOK) {339 309 usb_lgtch_free(&lgtch_dev); 340 310 return rc; … … 386 356 int rc = usb_hid_parse_report(hid_dev->report, buffer, buffer_size, 387 357 &report_id); 388 389 if (rc != EOK) {390 usb_log_warning(NAME "Error in usb_hid_parse_report(): %s\n",391 str_error(rc));392 return true;393 }394 395 358 usb_hid_report_path_set_report_id(path, report_id); 396 359 … … 420 383 usb_hid_report_path_free(path); 421 384 385 if (rc != EOK) { 386 usb_log_warning(NAME "Error in usb_hid_boot_keyboard_input_report():" 387 "%s\n", str_error(rc)); 388 } 389 422 390 return true; 423 391 } -
uspace/drv/usbhid/lgtch-ultrax/lgtch-ultrax.h
r26f6094 r9e929a0 42 42 43 43 /*----------------------------------------------------------------------------*/ 44 /** 45 * USB/HID keyboard device type. 46 * 47 * Holds a reference to generic USB/HID device structure and keyboard-specific 48 * data, such as currently pressed keys, modifiers and lock keys. 49 * 50 * Also holds a IPC phone to the console (since there is now no other way to 51 * communicate with it). 52 * 53 * @note Storing active lock keys in this structure results in their setting 54 * being device-specific. 55 */ 56 typedef struct usb_lgtch_ultrax_t { 57 /** Previously pressed keys (not translated to key codes). */ 58 int32_t *keys_old; 59 /** Currently pressed keys (not translated to key codes). */ 60 int32_t *keys; 61 /** Count of stored keys (i.e. number of keys in the report). */ 62 size_t key_count; 63 64 /** IPC phone to the console device (for sending key events). */ 65 int console_phone; 66 67 /** Information for auto-repeat of keys. */ 68 // usb_kbd_repeat_t repeat; 69 70 /** Mutex for accessing the information about auto-repeat. */ 71 // fibril_mutex_t *repeat_mtx; 72 73 /** State of the structure (for checking before use). 74 * 75 * 0 - not initialized 76 * 1 - initialized 77 * -1 - ready for destroying 78 */ 79 int initialized; 80 } usb_lgtch_ultrax_t; 81 82 /*----------------------------------------------------------------------------*/ 44 83 45 84 int usb_lgtch_init(struct usb_hid_dev *hid_dev); -
uspace/drv/usbhid/main.c
r26f6094 r9e929a0 99 99 usb_log_debug("USB/HID device structure initialized.\n"); 100 100 101 /* Create the function exposed under /dev/devices. */ 102 ddf_fun_t *hid_fun = ddf_fun_create(dev->ddf_dev, fun_exposed, 103 usb_hid_get_function_name(hid_dev)); 104 if (hid_fun == NULL) { 105 usb_log_error("Could not create DDF function node.\n"); 106 usb_hid_free(&hid_dev); 107 return ENOMEM; 108 } 109 110 /* 111 * Store the initialized HID device and HID ops 112 * to the DDF function. 113 */ 114 hid_fun->ops = &hid_dev->ops; 115 hid_fun->driver_data = hid_dev; // TODO: maybe change to hid_dev->data 116 101 117 /* 102 118 * 1) subdriver vytvori vlastnu ddf_fun, vlastne ddf_dev_ops, ktore da … … 109 125 * pouzit usb/classes/hid/iface.h - prvy int je telefon 110 126 */ 127 128 rc = ddf_fun_bind(hid_fun); 129 if (rc != EOK) { 130 usb_log_error("Could not bind DDF function: %s.\n", 131 str_error(rc)); 132 // TODO: Can / should I destroy the DDF function? 133 ddf_fun_destroy(hid_fun); 134 usb_hid_free(&hid_dev); 135 return rc; 136 } 137 138 rc = ddf_fun_add_to_class(hid_fun, usb_hid_get_class_name(hid_dev)); 139 if (rc != EOK) { 140 usb_log_error( 141 "Could not add DDF function to class 'hid': %s.\n", 142 str_error(rc)); 143 // TODO: Can / should I destroy the DDF function? 144 ddf_fun_destroy(hid_fun); 145 usb_hid_free(&hid_dev); 146 return rc; 147 } 111 148 112 149 /* Start automated polling function. … … 202 239 printf(NAME ": HelenOS USB HID driver.\n"); 203 240 204 //usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);241 usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME); 205 242 206 243 return usb_driver_main(&usb_hid_driver); -
uspace/drv/usbhid/mouse/mousedev.c
r26f6094 r9e929a0 39 39 #include <usb/classes/hid.h> 40 40 #include <usb/classes/hidreq.h> 41 #include <usb/classes/hidut.h>42 41 #include <errno.h> 43 42 #include <str_error.h> … … 46 45 #include "mousedev.h" 47 46 #include "../usbhid.h" 48 49 #define NAME "mouse"50 47 51 48 /*----------------------------------------------------------------------------*/ … … 65 62 /** Default idle rate for mouses. */ 66 63 static const uint8_t IDLE_RATE = 0; 67 static const size_t USB_MOUSE_BUTTON_COUNT = 3;68 64 69 65 /*----------------------------------------------------------------------------*/ … … 174 170 /*----------------------------------------------------------------------------*/ 175 171 176 static bool usb_mouse_process_boot_report(usb_ hid_dev_t *hid_dev,172 static bool usb_mouse_process_boot_report(usb_mouse_t *mouse_dev, 177 173 uint8_t *buffer, size_t buffer_size) 178 174 { 179 usb_mouse_t *mouse_dev = (usb_mouse_t *)hid_dev->data;180 181 175 usb_log_debug2("got buffer: %s.\n", 182 176 usb_debug_str_buffer(buffer, buffer_size, 0)); 183 184 if (mouse_dev->console_phone < 0) { 185 usb_log_error(NAME " No console phone.\n"); 186 return false; // ?? 187 } 188 189 /* 190 * parse the input report 191 */ 192 193 usb_log_debug(NAME " Calling usb_hid_parse_report() with " 194 "buffer %s\n", usb_debug_str_buffer(buffer, buffer_size, 0)); 195 196 uint8_t report_id; 197 198 int rc = usb_hid_parse_report(hid_dev->report, buffer, buffer_size, 199 &report_id); 200 201 if (rc != EOK) { 202 usb_log_warning(NAME "Error in usb_hid_parse_report(): %s\n", 203 str_error(rc)); 204 return true; 205 } 206 207 /* 208 * X 209 */ 210 int shift_x = 0; 211 212 usb_hid_report_path_t *path = usb_hid_report_path(); 213 usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_GENERIC_DESKTOP, 214 USB_HIDUT_USAGE_GENERIC_DESKTOP_X); 215 216 usb_hid_report_path_set_report_id(path, report_id); 217 218 usb_hid_report_field_t *field = usb_hid_report_get_sibling( 219 hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END, 220 USB_HID_REPORT_TYPE_INPUT); 221 222 if (field != NULL) { 223 usb_log_debug(NAME " VALUE(%X) USAGE(%X)\n", field->value, 224 field->usage); 225 shift_x = field->value; 226 } 227 228 usb_hid_report_path_free(path); 229 230 /* 231 * Y 232 */ 233 int shift_y = 0; 234 235 path = usb_hid_report_path(); 236 usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_GENERIC_DESKTOP, 237 USB_HIDUT_USAGE_GENERIC_DESKTOP_Y); 238 239 usb_hid_report_path_set_report_id(path, report_id); 240 241 field = usb_hid_report_get_sibling( 242 hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END, 243 USB_HID_REPORT_TYPE_INPUT); 244 245 if (field != NULL) { 246 usb_log_debug(NAME " VALUE(%X) USAGE(%X)\n", field->value, 247 field->usage); 248 shift_y = field->value; 249 } 250 251 usb_hid_report_path_free(path); 252 253 if ((shift_x != 0) || (shift_y != 0)) { 254 async_req_2_0(mouse_dev->console_phone, 255 MEVENT_MOVE, shift_x, shift_y); 256 } 257 258 /* 259 * Buttons 260 */ 261 path = usb_hid_report_path(); 262 usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_BUTTON, 0); 263 usb_hid_report_path_set_report_id(path, report_id); 264 265 field = usb_hid_report_get_sibling( 266 hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END 267 | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 268 USB_HID_REPORT_TYPE_INPUT); 269 270 while (field != NULL) { 271 usb_log_debug(NAME " VALUE(%X) USAGE(%X)\n", field->value, 272 field->usage); 273 274 if (mouse_dev->buttons[field->usage - field->usage_minimum] == 0 275 && field->value != 0) { 177 178 uint8_t butt = buffer[0]; 179 char str_buttons[4] = { 180 butt & 1 ? '#' : '.', 181 butt & 2 ? '#' : '.', 182 butt & 4 ? '#' : '.', 183 0 184 }; 185 186 int shift_x = ((int) buffer[1]) - 127; 187 int shift_y = ((int) buffer[2]) - 127; 188 int wheel = ((int) buffer[3]) - 127; 189 190 if (buffer[1] == 0) { 191 shift_x = 0; 192 } 193 if (buffer[2] == 0) { 194 shift_y = 0; 195 } 196 if (buffer[3] == 0) { 197 wheel = 0; 198 } 199 200 if (mouse_dev->console_phone >= 0) { 201 usb_log_debug("Console phone: %d\n", mouse_dev->console_phone); 202 if ((shift_x != 0) || (shift_y != 0)) { 203 /* FIXME: guessed for QEMU */ 276 204 async_req_2_0(mouse_dev->console_phone, 277 MEVENT_BUTTON, field->usage, 1); 278 mouse_dev->buttons[field->usage - field->usage_minimum] 279 = field->value; 280 } else if ( 281 mouse_dev->buttons[field->usage - field->usage_minimum] != 0 282 && field->value == 0) { 283 async_req_2_0(mouse_dev->console_phone, 284 MEVENT_BUTTON, field->usage, 0); 285 mouse_dev->buttons[field->usage - field->usage_minimum] 286 = field->value; 287 } 288 289 field = usb_hid_report_get_sibling( 290 hid_dev->report, field, path, USB_HID_PATH_COMPARE_END 291 | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 292 USB_HID_REPORT_TYPE_INPUT); 293 } 294 295 usb_hid_report_path_free(path); 205 MEVENT_MOVE, 206 - shift_x / 10, - shift_y / 10); 207 } else { 208 usb_log_error("No move reported\n"); 209 } 210 if (butt) { 211 /* FIXME: proper button clicking. */ 212 async_req_2_0(mouse_dev->console_phone, 213 MEVENT_BUTTON, 1, 1); 214 async_req_2_0(mouse_dev->console_phone, 215 MEVENT_BUTTON, 1, 0); 216 } 217 } else { 218 usb_log_error("No console phone in mouse!!\n"); 219 } 220 221 usb_log_debug("buttons=%s dX=%+3d dY=%+3d wheel=%+3d\n", 222 str_buttons, shift_x, shift_y, wheel); 223 224 /* Guess. */ 225 //async_usleep(1000); 226 // no sleep right now 296 227 297 228 return true; 298 }299 300 /*----------------------------------------------------------------------------*/301 302 static int usb_mouse_create_function(usb_hid_dev_t *hid_dev)303 {304 /* Create the function exposed under /dev/devices. */305 usb_log_debug("Creating DDF function %s...\n", HID_MOUSE_FUN_NAME);306 ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed,307 HID_MOUSE_FUN_NAME);308 if (fun == NULL) {309 usb_log_error("Could not create DDF function node.\n");310 return ENOMEM;311 }312 313 /*314 * Store the initialized HID device and HID ops315 * to the DDF function.316 */317 fun->ops = &hid_dev->ops;318 fun->driver_data = hid_dev; // TODO: maybe change to hid_dev->data319 320 int rc = ddf_fun_bind(fun);321 if (rc != EOK) {322 usb_log_error("Could not bind DDF function: %s.\n",323 str_error(rc));324 ddf_fun_destroy(fun);325 return rc;326 }327 328 usb_log_debug("Adding DDF function to class %s...\n",329 HID_MOUSE_CLASS_NAME);330 rc = ddf_fun_add_to_class(fun, HID_MOUSE_CLASS_NAME);331 if (rc != EOK) {332 usb_log_error(333 "Could not add DDF function to class %s: %s.\n",334 HID_MOUSE_CLASS_NAME, str_error(rc));335 ddf_fun_destroy(fun);336 return rc;337 }338 339 return EOK;340 229 } 341 230 … … 359 248 } 360 249 361 mouse_dev->buttons = (int32_t *)calloc(USB_MOUSE_BUTTON_COUNT,362 sizeof(int32_t));363 364 if (mouse_dev->buttons == NULL) {365 usb_log_fatal("No memory!\n");366 free(mouse_dev);367 return ENOMEM;368 }369 370 250 // save the Mouse device structure into the HID device structure 371 251 hid_dev->data = mouse_dev; … … 375 255 376 256 // TODO: how to know if the device supports the request??? 377 // usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe, 378 // hid_dev->usb_dev->interface_no, IDLE_RATE); 379 380 int rc = usb_mouse_create_function(hid_dev); 381 if (rc != EOK) { 382 usb_mouse_free(&mouse_dev); 383 return rc; 384 } 257 usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe, 258 hid_dev->usb_dev->interface_no, IDLE_RATE); 385 259 386 260 return EOK; … … 406 280 return false; 407 281 } 408 409 return usb_mouse_process_boot_report(hid_dev, buffer, buffer_size); 282 usb_mouse_t *mouse_dev = (usb_mouse_t *)hid_dev->data; 283 284 return usb_mouse_process_boot_report(mouse_dev, buffer, buffer_size); 410 285 } 411 286 -
uspace/drv/usbhid/mouse/mousedev.h
r26f6094 r9e929a0 49 49 /** IPC phone to console (consumer). */ 50 50 int console_phone; 51 52 int32_t *buttons;53 51 } usb_mouse_t; 54 52 -
uspace/drv/usbhid/usbhid.c
r26f6094 r9e929a0 136 136 137 137 // set the init callback 138 hid_dev->subdrivers[0].init = usb_generic_hid_init;138 hid_dev->subdrivers[0].init = NULL; 139 139 140 140 // set the polling callback … … 490 490 usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg; 491 491 492 int allocated = (hid_dev->input_report != NULL);493 494 if (!allocated495 || hid_dev->input_report_size < buffer_size) {496 uint8_t *input_old = hid_dev->input_report;497 uint8_t *input_new = (uint8_t *)malloc(buffer_size);498 499 if (input_new == NULL) {500 usb_log_error("Failed to allocate space for input "501 "buffer. This event may not be reported\n");502 memset(hid_dev->input_report, 0,503 hid_dev->input_report_size);504 } else {505 memcpy(input_new, input_old,506 hid_dev->input_report_size);507 hid_dev->input_report = input_new;508 if (allocated) {509 free(input_old);510 }511 }512 }513 514 /*! @todo This should probably be atomic. */515 memcpy(hid_dev->input_report, buffer, buffer_size);516 hid_dev->input_report_size = buffer_size;517 518 492 bool cont = false; 519 493 … … 554 528 /*----------------------------------------------------------------------------*/ 555 529 556 //const char *usb_hid_get_function_name(const usb_hid_dev_t *hid_dev)557 //{558 //switch (hid_dev->poll_pipe_index) {559 //case USB_HID_KBD_POLL_EP_NO:560 //return HID_KBD_FUN_NAME;561 //break;562 //case USB_HID_MOUSE_POLL_EP_NO:563 //return HID_MOUSE_FUN_NAME;564 //break;565 //default:566 //return HID_GENERIC_FUN_NAME;567 //}568 //}569 570 /*----------------------------------------------------------------------------*/ 571 572 //const char *usb_hid_get_class_name(const usb_hid_dev_t *hid_dev)573 //{574 //// this means that only boot protocol keyboards will be connected575 //// to the console; there is probably no better way to do this576 577 //switch (hid_dev->poll_pipe_index) {578 //case USB_HID_KBD_POLL_EP_NO:579 //return HID_KBD_CLASS_NAME;580 //break;581 //case USB_HID_MOUSE_POLL_EP_NO:582 //return HID_MOUSE_CLASS_NAME;583 //break;584 //default:585 //return HID_GENERIC_CLASS_NAME;586 //}587 //}530 const char *usb_hid_get_function_name(const usb_hid_dev_t *hid_dev) 531 { 532 switch (hid_dev->poll_pipe_index) { 533 case USB_HID_KBD_POLL_EP_NO: 534 return HID_KBD_FUN_NAME; 535 break; 536 case USB_HID_MOUSE_POLL_EP_NO: 537 return HID_MOUSE_FUN_NAME; 538 break; 539 default: 540 return HID_GENERIC_FUN_NAME; 541 } 542 } 543 544 /*----------------------------------------------------------------------------*/ 545 546 const char *usb_hid_get_class_name(const usb_hid_dev_t *hid_dev) 547 { 548 // this means that only boot protocol keyboards will be connected 549 // to the console; there is probably no better way to do this 550 551 switch (hid_dev->poll_pipe_index) { 552 case USB_HID_KBD_POLL_EP_NO: 553 return HID_KBD_CLASS_NAME; 554 break; 555 case USB_HID_MOUSE_POLL_EP_NO: 556 return HID_MOUSE_CLASS_NAME; 557 break; 558 default: 559 return HID_GENERIC_CLASS_NAME; 560 } 561 } 588 562 589 563 /*----------------------------------------------------------------------------*/ -
uspace/drv/usbhid/usbhid.h
r26f6094 r9e929a0 93 93 usb_hid_report_t *report; 94 94 95 uint8_t *input_report;96 97 size_t input_report_size;98 99 95 /** Arbitrary data (e.g. a special structure for handling keyboard). */ 100 96 void *data; … … 124 120 void *arg); 125 121 126 //const char *usb_hid_get_function_name(const usb_hid_dev_t *hid_dev);122 const char *usb_hid_get_function_name(const usb_hid_dev_t *hid_dev); 127 123 128 //const char *usb_hid_get_class_name(const usb_hid_dev_t *hid_dev);124 const char *usb_hid_get_class_name(const usb_hid_dev_t *hid_dev); 129 125 130 126 void usb_hid_free(usb_hid_dev_t **hid_dev); -
uspace/drv/usbkbd/kbddev.c
r26f6094 r9e929a0 294 294 usb_log_debug("Creating output report.\n"); 295 295 296 //usb_hid_report_output_set_data(kbd_dev->parser, kbd_dev->led_path,297 //USB_HID_PATH_COMPARE_END , kbd_dev->led_data,298 //kbd_dev->led_output_size);296 usb_hid_report_output_set_data(kbd_dev->parser, kbd_dev->led_path, 297 USB_HID_PATH_COMPARE_END , kbd_dev->led_data, 298 kbd_dev->led_output_size); 299 299 int rc = usb_hid_report_output_translate(kbd_dev->parser, 0, 300 300 kbd_dev->output_buffer, kbd_dev->output_size); -
uspace/lib/drv/include/usbhid_iface.h
r26f6094 r9e929a0 72 72 /** USB HID device communication interface. */ 73 73 typedef struct { 74 /** Get size of the event in bytes.74 /** Get number of items in the event. 75 75 * 76 76 * @param[in] fun DDF function answering the request. 77 77 * @return Number of events or error code. 78 78 */ 79 size_t (*get_event_length)(ddf_fun_t *fun);79 int (*get_event_length)(ddf_fun_t *fun); 80 80 81 81 /** Get single event from the HID device. 82 82 * 83 83 * @param[in] fun DDF function answering the request. 84 * @param[out] buffer Buffer with raw data from the device. 84 * @param[out] usage_page Array of usage pages and usages. 85 * @param[out] usage Array of data (1:1 with @p usage). 86 * @param[in] size Size of @p usage and @p data arrays. 85 87 * @param[out] act_size Actual number of returned events. 86 88 * @param[in] flags Flags (see USBHID_IFACE_FLAG_*). 87 89 * @return Error code. 88 90 */ 89 int (*get_event)(ddf_fun_t *fun, int32_t *buffer, size_t size, 90 size_t *act_size, unsigned int flags); 91 int (*get_event)(ddf_fun_t *fun, 92 uint16_t *usage_page, uint16_t *usage, size_t size, size_t *act_size, 93 unsigned int flags); 91 94 } usbhid_iface_t; 92 95 -
uspace/lib/usb/Makefile
r26f6094 r9e929a0 43 43 src/dump.c \ 44 44 src/hidiface.c \ 45 src/hidpath.c \46 45 src/hidparser.c \ 47 src/hiddescriptor.c \48 46 src/hub.c \ 49 47 src/pipepriv.c \ -
uspace/lib/usb/include/usb/classes/hid_report_items.h
r26f6094 r9e929a0 1 1 /* 2 * Copyright (c) 201 1 Matej Klonfar2 * Copyright (c) 2010 Vojtech Horky 3 3 * All rights reserved. 4 4 * … … 37 37 38 38 #include <stdint.h> 39 40 /**41 * Item prefix42 */43 #define USB_HID_ITEM_SIZE(data) ((uint8_t)(data & 0x3))44 #define USB_HID_ITEM_TAG(data) ((uint8_t)((data & 0xF0) >> 4))45 #define USB_HID_ITEM_TAG_CLASS(data) ((uint8_t)((data & 0xC) >> 2))46 #define USB_HID_ITEM_IS_LONG(data) (data == 0xFE)47 48 49 /**50 * Input/Output/Feature Item flags51 */52 /** Constant (1) / Variable (0) */53 #define USB_HID_ITEM_FLAG_CONSTANT(flags) ((flags & 0x1) == 0x1)54 /** Variable (1) / Array (0) */55 #define USB_HID_ITEM_FLAG_VARIABLE(flags) ((flags & 0x2) == 0x2)56 /** Absolute / Relative*/57 #define USB_HID_ITEM_FLAG_RELATIVE(flags) ((flags & 0x4) == 0x4)58 /** Wrap / No Wrap */59 #define USB_HID_ITEM_FLAG_WRAP(flags) ((flags & 0x8) == 0x8)60 #define USB_HID_ITEM_FLAG_LINEAR(flags) ((flags & 0x10) == 0x10)61 #define USB_HID_ITEM_FLAG_PREFERRED(flags) ((flags & 0x20) == 0x20)62 #define USB_HID_ITEM_FLAG_POSITION(flags) ((flags & 0x40) == 0x40)63 #define USB_HID_ITEM_FLAG_VOLATILE(flags) ((flags & 0x80) == 0x80)64 #define USB_HID_ITEM_FLAG_BUFFERED(flags) ((flags & 0x100) == 0x100)65 39 66 40 /* MAIN ITEMS */ -
uspace/lib/usb/include/usb/classes/hidparser.h
r26f6094 r9e929a0 1 1 /* 2 * Copyright (c) 201 1 Matej Klonfar2 * Copyright (c) 2010 Vojtech Horky 3 3 * All rights reserved. 4 4 * … … 39 39 #include <adt/list.h> 40 40 #include <usb/classes/hid_report_items.h> 41 #include <usb/classes/hidpath.h> 42 #include <usb/classes/hidtypes.h> 43 #include <usb/classes/hiddescriptor.h> 41 42 /** 43 * Item prefix 44 */ 45 #define USB_HID_ITEM_SIZE(data) ((uint8_t)(data & 0x3)) 46 #define USB_HID_ITEM_TAG(data) ((uint8_t)((data & 0xF0) >> 4)) 47 #define USB_HID_ITEM_TAG_CLASS(data) ((uint8_t)((data & 0xC) >> 2)) 48 #define USB_HID_ITEM_IS_LONG(data) (data == 0xFE) 49 50 51 /** 52 * Input/Output/Feature Item flags 53 */ 54 /** Constant (1) / Variable (0) */ 55 #define USB_HID_ITEM_FLAG_CONSTANT(flags) ((flags & 0x1) == 0x1) 56 /** Variable (1) / Array (0) */ 57 #define USB_HID_ITEM_FLAG_VARIABLE(flags) ((flags & 0x2) == 0x2) 58 /** Absolute / Relative*/ 59 #define USB_HID_ITEM_FLAG_RELATIVE(flags) ((flags & 0x4) == 0x4) 60 /** Wrap / No Wrap */ 61 #define USB_HID_ITEM_FLAG_WRAP(flags) ((flags & 0x8) == 0x8) 62 #define USB_HID_ITEM_FLAG_LINEAR(flags) ((flags & 0x10) == 0x10) 63 #define USB_HID_ITEM_FLAG_PREFERRED(flags) ((flags & 0x20) == 0x20) 64 #define USB_HID_ITEM_FLAG_POSITION(flags) ((flags & 0x40) == 0x40) 65 #define USB_HID_ITEM_FLAG_VOLATILE(flags) ((flags & 0x80) == 0x80) 66 #define USB_HID_ITEM_FLAG_BUFFERED(flags) ((flags & 0x100) == 0x100) 67 68 69 /** 70 * Description of path of usage pages and usages in report descriptor 71 */ 72 #define USB_HID_PATH_COMPARE_STRICT 0 73 #define USB_HID_PATH_COMPARE_END 1 74 #define USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY 4 75 #define USB_HID_PATH_COMPARE_COLLECTION_ONLY 2 /* porovnava jenom cestu z Kolekci */ 76 77 78 #define USB_HID_MAX_USAGES 20 79 80 typedef enum { 81 USB_HID_REPORT_TYPE_INPUT = 1, 82 USB_HID_REPORT_TYPE_OUTPUT = 2, 83 USB_HID_REPORT_TYPE_FEATURE = 3 84 } usb_hid_report_type_t; 85 86 /** Collection usage path structure */ 87 typedef struct { 88 /** */ 89 uint32_t usage_page; 90 /** */ 91 uint32_t usage; 92 93 uint8_t flags; 94 /** */ 95 link_t link; 96 } usb_hid_report_usage_path_t; 97 98 /** */ 99 typedef struct { 100 /** */ 101 int depth; 102 uint8_t report_id; 103 104 /** */ 105 link_t link; /* list */ 106 107 link_t head; /* head of list of usage paths */ 108 109 } usb_hid_report_path_t; 110 111 112 typedef struct { 113 /** */ 114 int report_count; 115 link_t reports; /** list of usb_hid_report_description_t */ 116 117 link_t collection_paths; 118 int collection_paths_count; 119 120 int use_report_ids; 121 uint8_t last_report_id; 122 123 } usb_hid_report_t; 124 125 typedef struct { 126 uint8_t report_id; 127 usb_hid_report_type_t type; 128 129 size_t bit_length; 130 size_t item_length; 131 132 link_t report_items; /** list of report items (fields) */ 133 134 link_t link; 135 } usb_hid_report_description_t; 136 137 typedef struct { 138 139 int offset; 140 size_t size; 141 142 uint16_t usage_page; 143 uint16_t usage; 144 145 uint8_t item_flags; 146 usb_hid_report_path_t *collection_path; 147 148 int32_t logical_minimum; 149 int32_t logical_maximum; 150 int32_t physical_minimum; 151 int32_t physical_maximum; 152 uint32_t usage_minimum; 153 uint32_t usage_maximum; 154 uint32_t unit; 155 uint32_t unit_exponent; 156 157 158 int32_t value; 159 160 link_t link; 161 } usb_hid_report_field_t; 162 163 164 165 /** 166 * state table 167 */ 168 typedef struct { 169 /** report id */ 170 int32_t id; 171 172 /** */ 173 uint16_t extended_usage_page; 174 uint32_t usages[USB_HID_MAX_USAGES]; 175 int usages_count; 176 177 /** */ 178 uint32_t usage_page; 179 180 /** */ 181 uint32_t usage_minimum; 182 /** */ 183 uint32_t usage_maximum; 184 /** */ 185 int32_t logical_minimum; 186 /** */ 187 int32_t logical_maximum; 188 /** */ 189 int32_t size; 190 /** */ 191 int32_t count; 192 /** */ 193 size_t offset; 194 /** */ 195 int32_t unit_exponent; 196 /** */ 197 int32_t unit; 198 199 /** */ 200 uint32_t string_index; 201 /** */ 202 uint32_t string_minimum; 203 /** */ 204 uint32_t string_maximum; 205 /** */ 206 uint32_t designator_index; 207 /** */ 208 uint32_t designator_minimum; 209 /** */ 210 uint32_t designator_maximum; 211 /** */ 212 int32_t physical_minimum; 213 /** */ 214 int32_t physical_maximum; 215 216 /** */ 217 uint8_t item_flags; 218 219 usb_hid_report_type_t type; 220 221 /** current collection path*/ 222 usb_hid_report_path_t *usage_path; 223 /** */ 224 link_t link; 225 } usb_hid_report_item_t; 226 227 /** HID parser callbacks for IN items. */ 228 typedef struct { 229 /** Callback for keyboard. 230 * 231 * @param key_codes Array of pressed key (including modifiers). 232 * @param count Length of @p key_codes. 233 * @param arg Custom argument. 234 */ 235 void (*keyboard)(const uint8_t *key_codes, size_t count, const uint8_t report_id, void *arg); 236 } usb_hid_report_in_callbacks_t; 237 238 239 typedef enum { 240 USB_HID_MOD_LCTRL = 0x01, 241 USB_HID_MOD_LSHIFT = 0x02, 242 USB_HID_MOD_LALT = 0x04, 243 USB_HID_MOD_LGUI = 0x08, 244 USB_HID_MOD_RCTRL = 0x10, 245 USB_HID_MOD_RSHIFT = 0x20, 246 USB_HID_MOD_RALT = 0x40, 247 USB_HID_MOD_RGUI = 0x80, 248 USB_HID_MOD_COUNT = 8 249 } usb_hid_modifiers_t; 250 251 static const usb_hid_modifiers_t 252 usb_hid_modifiers_consts[USB_HID_MOD_COUNT] = { 253 USB_HID_MOD_LCTRL, 254 USB_HID_MOD_LSHIFT, 255 USB_HID_MOD_LALT, 256 USB_HID_MOD_LGUI, 257 USB_HID_MOD_RCTRL, 258 USB_HID_MOD_RSHIFT, 259 USB_HID_MOD_RALT, 260 USB_HID_MOD_RGUI 261 }; 262 263 /* 264 * Descriptor parser functions 265 */ 266 267 /** */ 268 int usb_hid_parse_report_descriptor(usb_hid_report_t *report, 269 const uint8_t *data, size_t size); 270 271 /** */ 272 void usb_hid_free_report(usb_hid_report_t *report); 273 274 /** */ 275 void usb_hid_descriptor_print(usb_hid_report_t *report); 44 276 45 277 … … 48 280 */ 49 281 /** */ 50 int usb_hid_parse_report(const usb_hid_report_t *report, const uint8_t *data, 51 size_t size, uint8_t *report_id); 282 int usb_hid_parse_report(const usb_hid_report_t *report, const uint8_t *data, size_t size, uint8_t *report_id); 52 283 53 284 /** */ … … 55 286 usb_hid_report_path_t *path, int flags); 56 287 288 289 290 /* 291 * usage path functions 292 */ 293 /** */ 294 usb_hid_report_path_t *usb_hid_report_path(void); 295 296 /** */ 297 void usb_hid_report_path_free(usb_hid_report_path_t *path); 298 299 /** */ 300 int usb_hid_report_path_set_report_id(usb_hid_report_path_t *usage_path, uint8_t report_id); 301 302 /** */ 303 int usb_hid_report_path_append_item(usb_hid_report_path_t *usage_path, int32_t usage_page, int32_t usage); 304 305 /** */ 306 void usb_hid_report_remove_last_item(usb_hid_report_path_t *usage_path); 307 308 /** */ 309 void usb_hid_report_null_last_item(usb_hid_report_path_t *usage_path); 310 311 /** */ 312 void usb_hid_report_set_last_item(usb_hid_report_path_t *usage_path, int32_t tag, int32_t data); 313 314 /** */ 315 int usb_hid_report_compare_usage_path(usb_hid_report_path_t *report_path, usb_hid_report_path_t *path, int flags); 316 317 /** */ 318 usb_hid_report_path_t *usb_hid_report_path_clone(usb_hid_report_path_t *usage_path); 319 320 usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report, usb_hid_report_field_t *field, usb_hid_report_path_t *path, int flags, usb_hid_report_type_t type); 321 322 uint8_t usb_hid_report_get_report_id(usb_hid_report_t *report, uint8_t report_id, usb_hid_report_type_t type); 323 324 57 325 /* 58 326 * Output report parser functions 59 327 */ 60 328 /** Allocates output report buffer*/ 61 uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size, 62 uint8_t report_id); 329 uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size, uint8_t report_id); 63 330 64 331 /** Frees output report buffer*/ … … 69 336 usb_hid_report_path_t *path, int flags); 70 337 338 /** Sets data in report structure */ 339 int usb_hid_report_output_set_data(usb_hid_report_t *report, 340 usb_hid_report_path_t *path, int flags, 341 int *data, size_t data_size); 342 71 343 /** Makes the output report buffer by translated given data */ 72 int usb_hid_report_output_translate(usb_hid_report_t *report, uint8_t report_id, 73 uint8_t *buffer, size_t size); 74 75 /** */ 76 usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report, 77 usb_hid_report_field_t *field, 78 usb_hid_report_path_t *path, 79 int flags, 80 usb_hid_report_type_t type); 81 82 /** */ 83 uint8_t usb_hid_report_get_report_id(usb_hid_report_t *report, 84 uint8_t report_id, 85 usb_hid_report_type_t type); 86 344 int usb_hid_report_output_translate(usb_hid_report_t *report, uint8_t report_id, uint8_t *buffer, size_t size); 87 345 #endif 88 346 /** -
uspace/lib/usb/include/usb/classes/hidut.h
r26f6094 r9e929a0 59 59 USB_HIDUT_USAGE_GENERIC_DESKTOP_GAMEPAD = 5, 60 60 USB_HIDUT_USAGE_GENERIC_DESKTOP_KEYBOARD = 6, 61 USB_HIDUT_USAGE_GENERIC_DESKTOP_KEYPAD = 7, 62 USB_HIDUT_USAGE_GENERIC_DESKTOP_X = 0x30, 63 USB_HIDUT_USAGE_GENERIC_DESKTOP_Y = 0x31, 64 USB_HIDUT_USAGE_GENERIC_DESKTOP_WHEEL = 0x38 61 USB_HIDUT_USAGE_GENERIC_DESKTOP_KEYPAD = 7 65 62 /* USB_HIDUT_USAGE_GENERIC_DESKTOP_ = , */ 66 63 -
uspace/lib/usb/src/hidparser.c
r26f6094 r9e929a0 1 1 /* 2 * Copyright (c) 201 1 Matej Klonfar2 * Copyright (c) 2010 Vojtech Horky 3 3 * All rights reserved. 4 4 * … … 41 41 #include <assert.h> 42 42 43 43 /** The new report item flag. Used to determine when the item is completly 44 * configured and should be added to the report structure 45 */ 46 #define USB_HID_NEW_REPORT_ITEM 1 47 48 /** No special action after the report descriptor tag is processed should be 49 * done 50 */ 51 #define USB_HID_NO_ACTION 2 52 53 #define USB_HID_RESET_OFFSET 3 54 55 /** Unknown tag was founded in report descriptor data*/ 56 #define USB_HID_UNKNOWN_TAG -99 57 58 /* 59 * Private descriptor parser functions 60 */ 61 int usb_hid_report_init(usb_hid_report_t *report); 62 int usb_hid_report_append_fields(usb_hid_report_t *report, usb_hid_report_item_t *report_item); 63 usb_hid_report_description_t * usb_hid_report_find_description(const usb_hid_report_t *report, uint8_t report_id, usb_hid_report_type_t type); 64 int usb_hid_report_parse_tag(uint8_t tag, uint8_t class, const uint8_t *data, size_t item_size, 65 usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path); 66 int usb_hid_report_parse_main_tag(uint8_t tag, const uint8_t *data, size_t item_size, 67 usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path); 68 int usb_hid_report_parse_global_tag(uint8_t tag, const uint8_t *data, size_t item_size, 69 usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path); 70 int usb_hid_report_parse_local_tag(uint8_t tag, const uint8_t *data, size_t item_size, 71 usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path); 72 73 void usb_hid_print_usage_path(usb_hid_report_path_t *path); 74 void usb_hid_descriptor_print_list(link_t *head); 75 void usb_hid_report_reset_local_items(usb_hid_report_item_t *report_item); 76 void usb_hid_free_report_list(link_t *head); 77 usb_hid_report_item_t *usb_hid_report_item_clone(const usb_hid_report_item_t *item); 44 78 /* 45 79 * Data translation private functions … … 51 85 int usb_pow(int a, int b); 52 86 53 87 #define USB_HID_UINT32_TO_INT32(x, size) ((((x) & (1 << ((size) - 1))) != 0) ? -(~(x - 1) & ((1 << size) - 1)) : (x)) //(-(~((x) - 1))) 88 #define USB_HID_INT32_TO_UINT32(x, size) (((x) < 0 ) ? ((1 << (size)) + (x)) : (x)) 54 89 // TODO: tohle ma bejt asi jinde 55 90 int usb_pow(int a, int b) … … 68 103 } 69 104 70 71 105 /** 106 * Initialize the report descriptor parser structure 107 * 108 * @param parser Report descriptor parser structure 109 * @return Error code 110 */ 111 int usb_hid_report_init(usb_hid_report_t *report) 112 { 113 if(report == NULL) { 114 return EINVAL; 115 } 116 117 memset(report, 0, sizeof(usb_hid_report_t)); 118 list_initialize(&report->reports); 119 list_initialize(&report->collection_paths); 120 121 report->use_report_ids = 0; 122 return EOK; 123 } 124 125 int usb_hid_report_append_fields(usb_hid_report_t *report, usb_hid_report_item_t *report_item) 126 { 127 usb_hid_report_field_t *field; 128 int i; 129 130 131 /* find or append current collection path to the list */ 132 link_t *path_it = report->collection_paths.next; 133 usb_hid_report_path_t *path = NULL; 134 while(path_it != &report->collection_paths) { 135 path = list_get_instance(path_it, usb_hid_report_path_t, link); 136 137 if(usb_hid_report_compare_usage_path(path, report_item->usage_path, USB_HID_PATH_COMPARE_STRICT) == EOK){ 138 break; 139 } 140 path_it = path_it->next; 141 } 142 if(path_it == &report->collection_paths) { 143 path = usb_hid_report_path_clone(report_item->usage_path); 144 list_append(&path->link, &report->collection_paths); 145 report->collection_paths_count++; 146 } 147 148 for(i=0; i<report_item->usages_count; i++){ 149 usb_log_debug("usages (%d) - %x\n", i, report_item->usages[i]); 150 } 151 152 153 for(i=0; i<report_item->count; i++){ 154 155 field = malloc(sizeof(usb_hid_report_field_t)); 156 memset(field, 0, sizeof(usb_hid_report_field_t)); 157 list_initialize(&field->link); 158 159 /* fill the attributes */ 160 field->collection_path = path; 161 field->logical_minimum = report_item->logical_minimum; 162 field->logical_maximum = report_item->logical_maximum; 163 field->physical_minimum = report_item->physical_minimum; 164 field->physical_maximum = report_item->physical_maximum; 165 166 field->usage_minimum = report_item->usage_minimum; 167 field->usage_maximum = report_item->usage_maximum; 168 if(report_item->extended_usage_page != 0){ 169 field->usage_page = report_item->extended_usage_page; 170 } 171 else { 172 field->usage_page = report_item->usage_page; 173 } 174 175 if(report_item->usages_count > 0 && ((report_item->usage_minimum == 0) && (report_item->usage_maximum == 0))) { 176 uint32_t usage; 177 if(report_item->type != USB_HID_REPORT_TYPE_INPUT) { 178 if(i < report_item->usages_count){ 179 usage = report_item->usages[i]; 180 } 181 else { 182 usage = report_item->usages[report_item->usages_count - 1]; 183 } 184 } 185 else { 186 if((report_item->count - i - 1) < report_item->usages_count){ 187 usage = report_item->usages[(report_item->count - i - 1)]; 188 } 189 else { 190 usage = report_item->usages[report_item->usages_count - 1]; 191 } 192 } 193 194 195 if((usage & 0xFFFF0000) != 0){ 196 field->usage_page = (usage >> 16); 197 field->usage = (usage & 0xFFFF); 198 } 199 else { 200 field->usage = usage; 201 } 202 203 204 } 205 206 if((USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) != 0) && (!((report_item->usage_minimum == 0) && (report_item->usage_maximum == 0)))) { 207 if(report_item->type == USB_HID_REPORT_TYPE_INPUT) { 208 field->usage = report_item->usage_maximum - i; 209 } 210 else { 211 field->usage = report_item->usage_minimum + i; 212 } 213 214 } 215 216 field->size = report_item->size; 217 field->offset = report_item->offset + (i * report_item->size); 218 if(report_item->id != 0) { 219 field->offset += 8; 220 report->use_report_ids = 1; 221 } 222 field->item_flags = report_item->item_flags; 223 224 /* find the right report list*/ 225 usb_hid_report_description_t *report_des; 226 report_des = usb_hid_report_find_description(report, report_item->id, report_item->type); 227 if(report_des == NULL){ 228 report_des = malloc(sizeof(usb_hid_report_description_t)); 229 memset(report_des, 0, sizeof(usb_hid_report_description_t)); 230 231 report_des->type = report_item->type; 232 report_des->report_id = report_item->id; 233 list_initialize (&report_des->link); 234 list_initialize (&report_des->report_items); 235 236 list_append(&report_des->link, &report->reports); 237 report->report_count++; 238 } 239 240 /* append this field to the end of founded report list */ 241 list_append (&field->link, &report_des->report_items); 242 243 /* update the sizes */ 244 report_des->bit_length += field->size; 245 report_des->item_length++; 246 247 } 248 249 250 return EOK; 251 } 252 253 usb_hid_report_description_t * usb_hid_report_find_description(const usb_hid_report_t *report, uint8_t report_id, usb_hid_report_type_t type) 254 { 255 link_t *report_it = report->reports.next; 256 usb_hid_report_description_t *report_des = NULL; 257 258 while(report_it != &report->reports) { 259 report_des = list_get_instance(report_it, usb_hid_report_description_t, link); 260 261 if((report_des->report_id == report_id) && (report_des->type == type)){ 262 return report_des; 263 } 264 265 report_it = report_it->next; 266 } 267 268 return NULL; 269 } 270 271 /** Parse HID report descriptor. 272 * 273 * @param parser Opaque HID report parser structure. 274 * @param data Data describing the report. 275 * @return Error code. 276 */ 277 int usb_hid_parse_report_descriptor(usb_hid_report_t *report, 278 const uint8_t *data, size_t size) 279 { 280 size_t i=0; 281 uint8_t tag=0; 282 uint8_t item_size=0; 283 int class=0; 284 int ret; 285 usb_hid_report_item_t *report_item=0; 286 usb_hid_report_item_t *new_report_item; 287 usb_hid_report_path_t *usage_path; 288 289 size_t offset_input=0; 290 size_t offset_output=0; 291 size_t offset_feature=0; 292 293 link_t stack; 294 list_initialize(&stack); 295 296 /* parser structure initialization*/ 297 if(usb_hid_report_init(report) != EOK) { 298 return EINVAL; 299 } 300 301 /*report item initialization*/ 302 if(!(report_item=malloc(sizeof(usb_hid_report_item_t)))){ 303 return ENOMEM; 304 } 305 memset(report_item, 0, sizeof(usb_hid_report_item_t)); 306 list_initialize(&(report_item->link)); 307 308 /* usage path context initialization */ 309 if(!(usage_path=usb_hid_report_path())){ 310 return ENOMEM; 311 } 312 313 while(i<size){ 314 if(!USB_HID_ITEM_IS_LONG(data[i])){ 315 316 if((i+USB_HID_ITEM_SIZE(data[i]))>= size){ 317 return EINVAL; 318 } 319 320 tag = USB_HID_ITEM_TAG(data[i]); 321 item_size = USB_HID_ITEM_SIZE(data[i]); 322 class = USB_HID_ITEM_TAG_CLASS(data[i]); 323 324 ret = usb_hid_report_parse_tag(tag,class,data+i+1, 325 item_size,report_item, usage_path); 326 switch(ret){ 327 case USB_HID_NEW_REPORT_ITEM: 328 // store report item to report and create the new one 329 // store current collection path 330 report_item->usage_path = usage_path; 331 332 usb_hid_report_path_set_report_id(report_item->usage_path, report_item->id); 333 if(report_item->id != 0){ 334 report->use_report_ids = 1; 335 } 336 337 switch(tag) { 338 case USB_HID_REPORT_TAG_INPUT: 339 report_item->type = USB_HID_REPORT_TYPE_INPUT; 340 report_item->offset = offset_input; 341 offset_input += report_item->count * report_item->size; 342 break; 343 case USB_HID_REPORT_TAG_OUTPUT: 344 report_item->type = USB_HID_REPORT_TYPE_OUTPUT; 345 report_item->offset = offset_output; 346 offset_output += report_item->count * report_item->size; 347 348 break; 349 case USB_HID_REPORT_TAG_FEATURE: 350 report_item->type = USB_HID_REPORT_TYPE_FEATURE; 351 report_item->offset = offset_feature; 352 offset_feature += report_item->count * report_item->size; 353 break; 354 default: 355 usb_log_debug("\tjump over - tag %X\n", tag); 356 break; 357 } 358 359 /* 360 * append new fields to the report 361 * structure 362 */ 363 usb_hid_report_append_fields(report, report_item); 364 365 /* reset local items */ 366 usb_hid_report_reset_local_items (report_item); 367 368 break; 369 370 case USB_HID_RESET_OFFSET: 371 offset_input = 0; 372 offset_output = 0; 373 offset_feature = 0; 374 usb_hid_report_path_set_report_id (usage_path, report_item->id); 375 break; 376 377 case USB_HID_REPORT_TAG_PUSH: 378 // push current state to stack 379 new_report_item = usb_hid_report_item_clone(report_item); 380 usb_hid_report_path_t *tmp_path = usb_hid_report_path_clone(usage_path); 381 new_report_item->usage_path = tmp_path; 382 383 list_prepend (&new_report_item->link, &stack); 384 break; 385 case USB_HID_REPORT_TAG_POP: 386 // restore current state from stack 387 if(list_empty (&stack)) { 388 return EINVAL; 389 } 390 free(report_item); 391 392 report_item = list_get_instance(stack.next, usb_hid_report_item_t, link); 393 394 usb_hid_report_usage_path_t *tmp_usage_path; 395 tmp_usage_path = list_get_instance(report_item->usage_path->link.prev, usb_hid_report_usage_path_t, link); 396 397 usb_hid_report_set_last_item(usage_path, tmp_usage_path->usage_page, tmp_usage_path->usage); 398 399 usb_hid_report_path_free(report_item->usage_path); 400 list_initialize(&report_item->usage_path->link); 401 list_remove (stack.next); 402 403 break; 404 405 default: 406 // nothing special to do 407 break; 408 } 409 410 /* jump over the processed block */ 411 i += 1 + USB_HID_ITEM_SIZE(data[i]); 412 } 413 else{ 414 // TBD 415 i += 3 + USB_HID_ITEM_SIZE(data[i+1]); 416 } 417 418 419 } 420 421 return EOK; 422 } 423 424 425 /** 426 * Parse one tag of the report descriptor 427 * 428 * @param Tag to parse 429 * @param Report descriptor buffer 430 * @param Size of data belongs to this tag 431 * @param Current report item structe 432 * @return Code of action to be done next 433 */ 434 int usb_hid_report_parse_tag(uint8_t tag, uint8_t class, const uint8_t *data, size_t item_size, 435 usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path) 436 { 437 int ret; 438 439 switch(class){ 440 case USB_HID_TAG_CLASS_MAIN: 441 442 if((ret=usb_hid_report_parse_main_tag(tag,data,item_size,report_item, usage_path)) == EOK) { 443 return USB_HID_NEW_REPORT_ITEM; 444 } 445 else { 446 /*TODO process the error */ 447 return ret; 448 } 449 break; 450 451 case USB_HID_TAG_CLASS_GLOBAL: 452 return usb_hid_report_parse_global_tag(tag,data,item_size,report_item, usage_path); 453 break; 454 455 case USB_HID_TAG_CLASS_LOCAL: 456 return usb_hid_report_parse_local_tag(tag,data,item_size,report_item, usage_path); 457 break; 458 default: 459 return USB_HID_NO_ACTION; 460 } 461 } 462 463 /** 464 * Parse main tags of report descriptor 465 * 466 * @param Tag identifier 467 * @param Data buffer 468 * @param Length of data buffer 469 * @param Current state table 470 * @return Error code 471 */ 472 473 int usb_hid_report_parse_main_tag(uint8_t tag, const uint8_t *data, size_t item_size, 474 usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path) 475 { 476 switch(tag) 477 { 478 case USB_HID_REPORT_TAG_INPUT: 479 case USB_HID_REPORT_TAG_OUTPUT: 480 case USB_HID_REPORT_TAG_FEATURE: 481 report_item->item_flags = *data; 482 return EOK; 483 break; 484 485 case USB_HID_REPORT_TAG_COLLECTION: 486 // TODO usage_path->flags = *data; 487 usb_hid_report_path_append_item(usage_path, report_item->usage_page, report_item->usages[report_item->usages_count-1]); 488 usb_hid_report_reset_local_items (report_item); 489 return USB_HID_NO_ACTION; 490 break; 491 492 case USB_HID_REPORT_TAG_END_COLLECTION: 493 usb_hid_report_remove_last_item(usage_path); 494 return USB_HID_NO_ACTION; 495 break; 496 default: 497 return USB_HID_NO_ACTION; 498 } 499 500 return EOK; 501 } 502 503 /** 504 * Parse global tags of report descriptor 505 * 506 * @param Tag identifier 507 * @param Data buffer 508 * @param Length of data buffer 509 * @param Current state table 510 * @return Error code 511 */ 512 int usb_hid_report_parse_global_tag(uint8_t tag, const uint8_t *data, size_t item_size, 513 usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path) 514 { 515 // TODO take care about the bit length of data 516 switch(tag) 517 { 518 case USB_HID_REPORT_TAG_USAGE_PAGE: 519 report_item->usage_page = usb_hid_report_tag_data_uint32(data, item_size); 520 break; 521 case USB_HID_REPORT_TAG_LOGICAL_MINIMUM: 522 report_item->logical_minimum = USB_HID_UINT32_TO_INT32(usb_hid_report_tag_data_uint32(data,item_size), item_size * 8); 523 break; 524 case USB_HID_REPORT_TAG_LOGICAL_MAXIMUM: 525 report_item->logical_maximum = USB_HID_UINT32_TO_INT32(usb_hid_report_tag_data_uint32(data,item_size), item_size * 8); 526 break; 527 case USB_HID_REPORT_TAG_PHYSICAL_MINIMUM: 528 report_item->physical_minimum = USB_HID_UINT32_TO_INT32(usb_hid_report_tag_data_uint32(data,item_size), item_size * 8); 529 break; 530 case USB_HID_REPORT_TAG_PHYSICAL_MAXIMUM: 531 report_item->physical_maximum = USB_HID_UINT32_TO_INT32(usb_hid_report_tag_data_uint32(data,item_size), item_size * 8); 532 533 break; 534 case USB_HID_REPORT_TAG_UNIT_EXPONENT: 535 report_item->unit_exponent = usb_hid_report_tag_data_uint32(data,item_size); 536 break; 537 case USB_HID_REPORT_TAG_UNIT: 538 report_item->unit = usb_hid_report_tag_data_uint32(data,item_size); 539 break; 540 case USB_HID_REPORT_TAG_REPORT_SIZE: 541 report_item->size = usb_hid_report_tag_data_uint32(data,item_size); 542 break; 543 case USB_HID_REPORT_TAG_REPORT_COUNT: 544 report_item->count = usb_hid_report_tag_data_uint32(data,item_size); 545 break; 546 case USB_HID_REPORT_TAG_REPORT_ID: 547 report_item->id = usb_hid_report_tag_data_uint32(data,item_size); 548 return USB_HID_RESET_OFFSET; 549 break; 550 case USB_HID_REPORT_TAG_PUSH: 551 case USB_HID_REPORT_TAG_POP: 552 /* 553 * stack operations are done in top level parsing 554 * function 555 */ 556 return tag; 557 break; 558 559 default: 560 return USB_HID_NO_ACTION; 561 } 562 563 return EOK; 564 } 565 566 /** 567 * Parse local tags of report descriptor 568 * 569 * @param Tag identifier 570 * @param Data buffer 571 * @param Length of data buffer 572 * @param Current state table 573 * @return Error code 574 */ 575 int usb_hid_report_parse_local_tag(uint8_t tag, const uint8_t *data, size_t item_size, 576 usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path) 577 { 578 switch(tag) 579 { 580 case USB_HID_REPORT_TAG_USAGE: 581 report_item->usages[report_item->usages_count] = usb_hid_report_tag_data_uint32(data,item_size); 582 report_item->usages_count++; 583 break; 584 case USB_HID_REPORT_TAG_USAGE_MINIMUM: 585 if (item_size == 3) { 586 // usage extended usages 587 report_item->extended_usage_page = (usb_hid_report_tag_data_uint32(data,item_size) & 0xFF00) >> 16; 588 report_item->usage_minimum = usb_hid_report_tag_data_uint32(data,item_size) & 0xFF; 589 } 590 else { 591 report_item->usage_minimum = usb_hid_report_tag_data_uint32(data,item_size); 592 } 593 break; 594 case USB_HID_REPORT_TAG_USAGE_MAXIMUM: 595 if (item_size == 3) { 596 // usage extended usages 597 report_item->extended_usage_page = (usb_hid_report_tag_data_uint32(data,item_size) & 0xFF00) >> 16; 598 report_item->usage_maximum = usb_hid_report_tag_data_uint32(data,item_size) & 0xFF; 599 } 600 else { 601 report_item->usage_maximum = usb_hid_report_tag_data_uint32(data,item_size); 602 } 603 break; 604 case USB_HID_REPORT_TAG_DESIGNATOR_INDEX: 605 report_item->designator_index = usb_hid_report_tag_data_uint32(data,item_size); 606 break; 607 case USB_HID_REPORT_TAG_DESIGNATOR_MINIMUM: 608 report_item->designator_minimum = usb_hid_report_tag_data_uint32(data,item_size); 609 break; 610 case USB_HID_REPORT_TAG_DESIGNATOR_MAXIMUM: 611 report_item->designator_maximum = usb_hid_report_tag_data_uint32(data,item_size); 612 break; 613 case USB_HID_REPORT_TAG_STRING_INDEX: 614 report_item->string_index = usb_hid_report_tag_data_uint32(data,item_size); 615 break; 616 case USB_HID_REPORT_TAG_STRING_MINIMUM: 617 report_item->string_minimum = usb_hid_report_tag_data_uint32(data,item_size); 618 break; 619 case USB_HID_REPORT_TAG_STRING_MAXIMUM: 620 report_item->string_maximum = usb_hid_report_tag_data_uint32(data,item_size); 621 break; 622 case USB_HID_REPORT_TAG_DELIMITER: 623 //report_item->delimiter = usb_hid_report_tag_data_uint32(data,item_size); 624 //TODO: 625 // DELIMITER STUFF 626 break; 627 628 default: 629 return USB_HID_NO_ACTION; 630 } 631 632 return EOK; 633 } 634 635 /** 636 * Converts raw data to uint32 (thats the maximum length of short item data) 637 * 638 * @param Data buffer 639 * @param Size of buffer 640 * @return Converted int32 number 641 */ 642 uint32_t usb_hid_report_tag_data_uint32(const uint8_t *data, size_t size) 643 { 644 unsigned int i; 645 uint32_t result; 646 647 result = 0; 648 for(i=0; i<size; i++) { 649 result = (result | (data[i]) << (i*8)); 650 } 651 652 return result; 653 } 654 655 /** 656 * Prints content of given list of report items. 657 * 658 * @param List of report items (usb_hid_report_item_t) 659 * @return void 660 */ 661 void usb_hid_descriptor_print_list(link_t *head) 662 { 663 usb_hid_report_field_t *report_item; 664 link_t *item; 665 666 667 if(head == NULL || list_empty(head)) { 668 usb_log_debug("\tempty\n"); 669 return; 670 } 671 672 for(item = head->next; item != head; item = item->next) { 673 674 report_item = list_get_instance(item, usb_hid_report_field_t, link); 675 676 usb_log_debug("\t\tOFFSET: %X\n", report_item->offset); 677 usb_log_debug("\t\tSIZE: %X\n", report_item->size); 678 usb_log_debug("\t\tLOGMIN: %d\n", report_item->logical_minimum); 679 usb_log_debug("\t\tLOGMAX: %d\n", report_item->logical_maximum); 680 usb_log_debug("\t\tPHYMIN: %d\n", report_item->physical_minimum); 681 usb_log_debug("\t\tPHYMAX: %d\n", report_item->physical_maximum); 682 usb_log_debug("\t\ttUSAGEMIN: %X\n", report_item->usage_minimum); 683 usb_log_debug("\t\tUSAGEMAX: %X\n", report_item->usage_maximum); 684 685 usb_log_debug("\t\tVALUE: %X\n", report_item->value); 686 usb_log_debug("\t\ttUSAGE: %X\n", report_item->usage); 687 usb_log_debug("\t\tUSAGE PAGE: %X\n", report_item->usage_page); 688 689 // usb_log_debug("\n"); 690 691 } 692 693 694 } 695 /** 696 * Prints content of given report descriptor in human readable format. 697 * 698 * @param parser Parsed descriptor to print 699 * @return void 700 */ 701 void usb_hid_descriptor_print(usb_hid_report_t *report) 702 { 703 if(report == NULL) { 704 return; 705 } 706 707 link_t *report_it = report->reports.next; 708 usb_hid_report_description_t *report_des; 709 710 while(report_it != &report->reports) { 711 report_des = list_get_instance(report_it, usb_hid_report_description_t, link); 712 usb_log_debug("Report ID: %d\n", report_des->report_id); 713 usb_log_debug("\tType: %d\n", report_des->type); 714 usb_log_debug("\tLength: %d\n", report_des->bit_length); 715 usb_log_debug("\tItems: %d\n", report_des->item_length); 716 717 usb_hid_descriptor_print_list(&report_des->report_items); 718 719 720 link_t *path_it = report->collection_paths.next; 721 while(path_it != &report->collection_paths) { 722 usb_hid_print_usage_path (list_get_instance(path_it, usb_hid_report_path_t, link)); 723 path_it = path_it->next; 724 } 725 726 report_it = report_it->next; 727 } 728 } 729 730 /** 731 * Releases whole linked list of report items 732 * 733 * @param head Head of list of report descriptor items (usb_hid_report_item_t) 734 * @return void 735 */ 736 void usb_hid_free_report_list(link_t *head) 737 { 738 return; 739 740 usb_hid_report_item_t *report_item; 741 link_t *next; 742 743 if(head == NULL || list_empty(head)) { 744 return; 745 } 746 747 next = head->next; 748 while(next != head) { 749 750 report_item = list_get_instance(next, usb_hid_report_item_t, link); 751 752 while(!list_empty(&report_item->usage_path->link)) { 753 usb_hid_report_remove_last_item(report_item->usage_path); 754 } 755 756 757 next = next->next; 758 759 free(report_item); 760 } 761 762 return; 763 764 } 765 766 /** Frees the HID report descriptor parser structure 767 * 768 * @param parser Opaque HID report parser structure 769 * @return void 770 */ 771 void usb_hid_free_report(usb_hid_report_t *report) 772 { 773 if(report == NULL){ 774 return; 775 } 776 777 // free collection paths 778 usb_hid_report_path_t *path; 779 while(!list_empty(&report->collection_paths)) { 780 path = list_get_instance(report->collection_paths.next, usb_hid_report_path_t, link); 781 usb_hid_report_path_free(path); 782 } 783 784 // free report items 785 usb_hid_report_description_t *report_des; 786 usb_hid_report_field_t *field; 787 while(!list_empty(&report->reports)) { 788 report_des = list_get_instance(report->reports.next, usb_hid_report_description_t, link); 789 list_remove(&report_des->link); 790 791 while(!list_empty(&report_des->report_items)) { 792 field = list_get_instance(report_des->report_items.next, usb_hid_report_field_t, link); 793 list_remove(&field->link); 794 795 free(field); 796 } 797 798 free(report_des); 799 } 800 801 return; 802 } 72 803 73 804 /** Parse and act upon a HID report. … … 249 980 return ret; 250 981 } 982 983 984 /** 985 * Appends one item (couple of usage_path and usage) into the usage path 986 * structure 987 * 988 * @param usage_path Usage path structure 989 * @param usage_page Usage page constant 990 * @param usage Usage constant 991 * @return Error code 992 */ 993 int usb_hid_report_path_append_item(usb_hid_report_path_t *usage_path, 994 int32_t usage_page, int32_t usage) 995 { 996 usb_hid_report_usage_path_t *item; 997 998 if(!(item=malloc(sizeof(usb_hid_report_usage_path_t)))) { 999 return ENOMEM; 1000 } 1001 list_initialize(&item->link); 1002 1003 item->usage = usage; 1004 item->usage_page = usage_page; 1005 item->flags = 0; 1006 1007 list_append (&item->link, &usage_path->head); 1008 usage_path->depth++; 1009 return EOK; 1010 } 1011 1012 /** 1013 * Removes last item from the usage path structure 1014 * @param usage_path 1015 * @return void 1016 */ 1017 void usb_hid_report_remove_last_item(usb_hid_report_path_t *usage_path) 1018 { 1019 usb_hid_report_usage_path_t *item; 1020 1021 if(!list_empty(&usage_path->head)){ 1022 item = list_get_instance(usage_path->head.prev, usb_hid_report_usage_path_t, link); 1023 list_remove(usage_path->head.prev); 1024 usage_path->depth--; 1025 free(item); 1026 } 1027 } 1028 1029 /** 1030 * Nulls last item of the usage path structure. 1031 * 1032 * @param usage_path 1033 * @return void 1034 */ 1035 void usb_hid_report_null_last_item(usb_hid_report_path_t *usage_path) 1036 { 1037 usb_hid_report_usage_path_t *item; 1038 1039 if(!list_empty(&usage_path->head)){ 1040 item = list_get_instance(usage_path->head.prev, usb_hid_report_usage_path_t, link); 1041 memset(item, 0, sizeof(usb_hid_report_usage_path_t)); 1042 } 1043 } 1044 1045 /** 1046 * Modifies last item of usage path structure by given usage page or usage 1047 * 1048 * @param usage_path Opaque usage path structure 1049 * @param tag Class of currently processed tag (Usage page tag falls into Global 1050 * class but Usage tag into the Local) 1051 * @param data Value of the processed tag 1052 * @return void 1053 */ 1054 void usb_hid_report_set_last_item(usb_hid_report_path_t *usage_path, int32_t tag, int32_t data) 1055 { 1056 usb_hid_report_usage_path_t *item; 1057 1058 if(!list_empty(&usage_path->head)){ 1059 item = list_get_instance(usage_path->head.prev, usb_hid_report_usage_path_t, link); 1060 1061 switch(tag) { 1062 case USB_HID_TAG_CLASS_GLOBAL: 1063 item->usage_page = data; 1064 break; 1065 case USB_HID_TAG_CLASS_LOCAL: 1066 item->usage = data; 1067 break; 1068 } 1069 } 1070 1071 } 1072 1073 1074 void usb_hid_print_usage_path(usb_hid_report_path_t *path) 1075 { 1076 usb_log_debug("USAGE_PATH FOR RId(%d):\n", path->report_id); 1077 usb_log_debug("\tLENGTH: %d\n", path->depth); 1078 1079 link_t *item = path->head.next; 1080 usb_hid_report_usage_path_t *path_item; 1081 while(item != &path->head) { 1082 1083 path_item = list_get_instance(item, usb_hid_report_usage_path_t, link); 1084 usb_log_debug("\tUSAGE_PAGE: %X\n", path_item->usage_page); 1085 usb_log_debug("\tUSAGE: %X\n", path_item->usage); 1086 usb_log_debug("\tFLAGS: %d\n", path_item->flags); 1087 1088 item = item->next; 1089 } 1090 } 1091 1092 /** 1093 * Compares two usage paths structures 1094 * 1095 * If USB_HID_PATH_COMPARE_COLLECTION_ONLY flag is given, the last item in report_path structure is forgotten 1096 * 1097 * @param report_path usage path structure to compare 1098 * @param path usage patrh structure to compare 1099 * @param flags Flags determining the mode of comparison 1100 * @return EOK if both paths are identical, non zero number otherwise 1101 */ 1102 int usb_hid_report_compare_usage_path(usb_hid_report_path_t *report_path, 1103 usb_hid_report_path_t *path, 1104 int flags) 1105 { 1106 usb_hid_report_usage_path_t *report_item; 1107 usb_hid_report_usage_path_t *path_item; 1108 1109 link_t *report_link; 1110 link_t *path_link; 1111 1112 int only_page; 1113 1114 if(report_path->report_id != path->report_id) { 1115 return 1; 1116 } 1117 1118 if(path->depth == 0){ 1119 return EOK; 1120 } 1121 1122 1123 if((only_page = flags & USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY) != 0){ 1124 flags -= USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY; 1125 } 1126 1127 switch(flags){ 1128 /* path must be completly identical */ 1129 case USB_HID_PATH_COMPARE_STRICT: 1130 if(report_path->depth != path->depth){ 1131 return 1; 1132 } 1133 1134 report_link = report_path->head.next; 1135 path_link = path->head.next; 1136 1137 while((report_link != &report_path->head) && (path_link != &path->head)) { 1138 report_item = list_get_instance(report_link, usb_hid_report_usage_path_t, link); 1139 path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link); 1140 1141 if((report_item->usage_page != path_item->usage_page) || 1142 ((only_page == 0) && (report_item->usage != path_item->usage))) { 1143 return 1; 1144 } else { 1145 report_link = report_link->next; 1146 path_link = path_link->next; 1147 } 1148 1149 } 1150 1151 if(((report_link == &report_path->head) && (path_link == &path->head)) || 1152 (((flags & USB_HID_PATH_COMPARE_COLLECTION_ONLY) != 0) && (path_link = &path->head) && (report_link == report_path->head.prev))) { 1153 return EOK; 1154 } 1155 else { 1156 return 1; 1157 } 1158 break; 1159 1160 /* compare with only the end of path*/ 1161 case USB_HID_PATH_COMPARE_END: 1162 1163 if((flags & USB_HID_PATH_COMPARE_COLLECTION_ONLY) != 0) { 1164 report_link = report_path->head.prev->prev; 1165 } 1166 else { 1167 report_link = report_path->head.prev; 1168 } 1169 path_link = path->head.prev; 1170 1171 if(list_empty(&path->head)){ 1172 return EOK; 1173 } 1174 1175 while((report_link != &report_path->head) && (path_link != &path->head)) { 1176 report_item = list_get_instance(report_link, usb_hid_report_usage_path_t, link); 1177 path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link); 1178 1179 if((report_item->usage_page != path_item->usage_page) || 1180 ((only_page == 0) && (report_item->usage != path_item->usage))) { 1181 return 1; 1182 } else { 1183 report_link = report_link->prev; 1184 path_link = path_link->prev; 1185 } 1186 1187 } 1188 1189 if(path_link == &path->head) { 1190 return EOK; 1191 } 1192 else { 1193 return 1; 1194 } 1195 1196 break; 1197 1198 default: 1199 return EINVAL; 1200 } 1201 1202 1203 1204 1205 } 1206 1207 /** 1208 * Allocates and initializes new usage path structure. 1209 * 1210 * @return Initialized usage path structure 1211 */ 1212 usb_hid_report_path_t *usb_hid_report_path(void) 1213 { 1214 usb_hid_report_path_t *path; 1215 path = malloc(sizeof(usb_hid_report_path_t)); 1216 if(path == NULL){ 1217 return NULL; 1218 } 1219 else { 1220 path->depth = 0; 1221 path->report_id = 0; 1222 list_initialize(&path->link); 1223 list_initialize(&path->head); 1224 return path; 1225 } 1226 } 1227 1228 /** 1229 * Releases given usage path structure. 1230 * 1231 * @param path usage path structure to release 1232 * @return void 1233 */ 1234 void usb_hid_report_path_free(usb_hid_report_path_t *path) 1235 { 1236 while(!list_empty(&path->head)){ 1237 usb_hid_report_remove_last_item(path); 1238 } 1239 1240 list_remove(&path->link); 1241 free(path); 1242 } 1243 1244 1245 /** 1246 * Clone content of given usage path to the new one 1247 * 1248 * @param usage_path Usage path structure to clone 1249 * @return New copy of given usage path structure 1250 */ 1251 usb_hid_report_path_t *usb_hid_report_path_clone(usb_hid_report_path_t *usage_path) 1252 { 1253 link_t *path_link; 1254 usb_hid_report_usage_path_t *path_item; 1255 usb_hid_report_usage_path_t *new_path_item; 1256 usb_hid_report_path_t *new_usage_path = usb_hid_report_path (); 1257 1258 if(new_usage_path == NULL){ 1259 return NULL; 1260 } 1261 1262 new_usage_path->report_id = usage_path->report_id; 1263 1264 if(list_empty(&usage_path->head)){ 1265 return new_usage_path; 1266 } 1267 1268 path_link = usage_path->head.next; 1269 while(path_link != &usage_path->head) { 1270 path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link); 1271 new_path_item = malloc(sizeof(usb_hid_report_usage_path_t)); 1272 if(new_path_item == NULL) { 1273 return NULL; 1274 } 1275 1276 list_initialize (&new_path_item->link); 1277 new_path_item->usage_page = path_item->usage_page; 1278 new_path_item->usage = path_item->usage; 1279 new_path_item->flags = path_item->flags; 1280 1281 list_append(&new_path_item->link, &new_usage_path->head); 1282 new_usage_path->depth++; 1283 1284 path_link = path_link->next; 1285 } 1286 1287 return new_usage_path; 1288 } 1289 251 1290 252 1291 /*** OUTPUT API **/ … … 504 1543 } 505 1544 1545 /** 1546 * Sets report id in usage path structure 1547 * 1548 * @param path Usage path structure 1549 * @param report_id Report id to set 1550 * @return Error code 1551 */ 1552 int usb_hid_report_path_set_report_id(usb_hid_report_path_t *path, uint8_t report_id) 1553 { 1554 if(path == NULL){ 1555 return EINVAL; 1556 } 1557 1558 path->report_id = report_id; 1559 return EOK; 1560 } 1561 1562 /** 1563 * 1564 * 1565 * 1566 * 1567 * 1568 */ 1569 int usb_hid_report_output_set_data(usb_hid_report_t *report, 1570 usb_hid_report_path_t *path, int flags, 1571 int *data, size_t data_size) 1572 { 1573 size_t data_idx = 0; 1574 if(report == NULL){ 1575 return EINVAL; 1576 } 1577 1578 usb_hid_report_description_t *report_des; 1579 report_des = usb_hid_report_find_description (report, path->report_id, 1580 USB_HID_REPORT_TYPE_OUTPUT); 1581 if(report_des == NULL){ 1582 return EINVAL; 1583 } 1584 1585 usb_hid_report_field_t *field; 1586 link_t *field_it = report_des->report_items.next; 1587 while(field_it != &report_des->report_items){ 1588 1589 field = list_get_instance(field_it, usb_hid_report_field_t, link); 1590 if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0) { 1591 usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage); 1592 if(usb_hid_report_compare_usage_path (field->collection_path, path, 1593 flags) == EOK) { 1594 if(data_idx < data_size) { 1595 if((data[data_idx] >= field->physical_minimum) && (data[data_idx] >= field->physical_minimum)) { 1596 field->value = data[data_idx]; 1597 } 1598 else { 1599 return ERANGE; 1600 } 1601 1602 data_idx++; 1603 } 1604 else { 1605 field->value = 0; 1606 } 1607 } 1608 usb_hid_report_remove_last_item (field->collection_path); 1609 } 1610 1611 field_it = field_it->next; 1612 } 1613 1614 return EOK; 1615 } 1616 1617 506 1618 usb_hid_report_item_t *usb_hid_report_item_clone(const usb_hid_report_item_t *item) 507 1619 {
Note:
See TracChangeset
for help on using the changeset viewer.