Changeset 20a3465 in mainline for uspace/lib
- Timestamp:
- 2011-10-30T19:50:54Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 3ce78580, 48902fa
- Parents:
- 4c3ad56 (diff), 45bf63c (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - Location:
- uspace/lib
- Files:
-
- 24 edited
-
c/generic/str.c (modified) (1 diff)
-
c/include/str.h (modified) (1 diff)
-
usbdev/include/usb/dev/dp.h (modified) (3 diffs)
-
usbdev/include/usb/dev/driver.h (modified) (3 diffs)
-
usbdev/include/usb/dev/pipes.h (modified) (1 diff)
-
usbdev/src/altiface.c (modified) (10 diffs)
-
usbdev/src/devdrv.c (modified) (15 diffs)
-
usbdev/src/dp.c (modified) (15 diffs)
-
usbdev/src/pipesinit.c (modified) (11 diffs)
-
usbdev/src/request.c (modified) (2 diffs)
-
usbhid/include/usb/hid/hiddescriptor.h (modified) (2 diffs)
-
usbhid/src/hiddescriptor.c (modified) (2 diffs)
-
usbhid/src/hidparser.c (modified) (23 diffs)
-
usbhid/src/hidreport.c (modified) (2 diffs)
-
usbhost/include/usb/host/endpoint.h (modified) (1 diff)
-
usbhost/include/usb/host/hcd.h (modified) (1 diff)
-
usbhost/include/usb/host/usb_device_manager.h (modified) (2 diffs)
-
usbhost/include/usb/host/usb_endpoint_manager.h (modified) (2 diffs)
-
usbhost/include/usb/host/usb_transfer_batch.h (modified) (5 diffs)
-
usbhost/src/endpoint.c (modified) (5 diffs)
-
usbhost/src/iface.c (modified) (10 diffs)
-
usbhost/src/usb_device_manager.c (modified) (9 diffs)
-
usbhost/src/usb_endpoint_manager.c (modified) (7 diffs)
-
usbhost/src/usb_transfer_batch.c (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/str.c
r4c3ad56 r20a3465 839 839 840 840 return NULL; 841 } 842 843 /** Removes specified trailing characters from a string. 844 * 845 * @param str String to remove from. 846 * @param ch Character to remove. 847 */ 848 void str_rtrim(char *str, wchar_t ch) 849 { 850 size_t off = 0; 851 size_t pos = 0; 852 wchar_t c; 853 bool update_last_chunk = true; 854 char *last_chunk = NULL; 855 856 while ((c = str_decode(str, &off, STR_NO_LIMIT))) { 857 if (c != ch) { 858 update_last_chunk = true; 859 last_chunk = NULL; 860 } else if (update_last_chunk) { 861 update_last_chunk = false; 862 last_chunk = (str + pos); 863 } 864 pos = off; 865 } 866 867 if (last_chunk) 868 *last_chunk = '\0'; 869 } 870 871 /** Removes specified leading characters from a string. 872 * 873 * @param str String to remove from. 874 * @param ch Character to remove. 875 */ 876 void str_ltrim(char *str, wchar_t ch) 877 { 878 wchar_t acc; 879 size_t off = 0; 880 size_t pos = 0; 881 size_t str_sz = str_size(str); 882 883 while ((acc = str_decode(str, &off, STR_NO_LIMIT)) != 0) { 884 if (acc != ch) 885 break; 886 else 887 pos = off; 888 } 889 890 if (pos > 0) { 891 memmove(str, &str[pos], str_sz - pos); 892 pos = str_sz - pos; 893 str[str_sz - pos] = '\0'; 894 } 841 895 } 842 896 -
uspace/lib/c/include/str.h
r4c3ad56 r20a3465 91 91 extern char *str_rchr(const char *str, wchar_t ch); 92 92 93 extern void str_rtrim(char *str, wchar_t ch); 94 extern void str_ltrim(char *str, wchar_t ch); 95 93 96 extern bool wstr_linsert(wchar_t *str, wchar_t ch, size_t pos, size_t max_pos); 94 97 extern bool wstr_remove(wchar_t *str, size_t pos); -
uspace/lib/usbdev/include/usb/dev/dp.h
r4c3ad56 r20a3465 59 59 typedef struct { 60 60 /** Used descriptor nesting. */ 61 usb_dp_descriptor_nesting_t *nesting;61 const usb_dp_descriptor_nesting_t *nesting; 62 62 } usb_dp_parser_t; 63 63 … … 65 65 typedef struct { 66 66 /** Data to be parsed. */ 67 uint8_t *data;67 const uint8_t *data; 68 68 /** Size of input data in bytes. */ 69 69 size_t size; … … 72 72 } usb_dp_parser_data_t; 73 73 74 uint8_t *usb_dp_get_nested_descriptor(usb_dp_parser_t *, 75 usb_dp_parser_data_t *, uint8_t *); 76 uint8_t *usb_dp_get_sibling_descriptor(usb_dp_parser_t *, 77 usb_dp_parser_data_t *, uint8_t *, uint8_t *); 74 typedef void (*walk_callback_t)(const uint8_t *, size_t, void *); 78 75 79 void usb_dp_walk_simple(uint8_t *, size_t, usb_dp_descriptor_nesting_t *, 80 void (*)(uint8_t *, size_t, void *), void *); 76 const uint8_t *usb_dp_get_nested_descriptor(const usb_dp_parser_t *, 77 const usb_dp_parser_data_t *, const uint8_t *); 78 const uint8_t *usb_dp_get_sibling_descriptor(const usb_dp_parser_t *, 79 const usb_dp_parser_data_t *, const uint8_t *, const uint8_t *); 80 81 void usb_dp_walk_simple(uint8_t *, size_t, const usb_dp_descriptor_nesting_t *, 82 walk_callback_t, void *); 81 83 82 84 #endif -
uspace/lib/usbdev/include/usb/dev/driver.h
r4c3ad56 r20a3465 43 43 usb_standard_device_descriptor_t device; 44 44 /** Full configuration descriptor of current configuration. */ 45 uint8_t *configuration;45 const uint8_t *configuration; 46 46 size_t configuration_size; 47 47 } usb_device_descriptors_t; … … 53 53 typedef struct { 54 54 /** Interface descriptor. */ 55 usb_standard_interface_descriptor_t *interface;55 const usb_standard_interface_descriptor_t *interface; 56 56 /** Pointer to start of descriptor tree bound with this interface. */ 57 uint8_t *nested_descriptors;57 const uint8_t *nested_descriptors; 58 58 /** Size of data pointed by nested_descriptors in bytes. */ 59 59 size_t nested_descriptors_size; … … 156 156 \endcode 157 157 */ 158 usb_endpoint_description_t **endpoints;158 const usb_endpoint_description_t **endpoints; 159 159 /** Driver ops. */ 160 usb_driver_ops_t *ops;160 const usb_driver_ops_t *ops; 161 161 } usb_driver_t; 162 162 163 int usb_driver_main( usb_driver_t *);163 int usb_driver_main(const usb_driver_t *); 164 164 165 165 int usb_device_select_interface(usb_device_t *, uint8_t, 166 usb_endpoint_description_t **);166 const usb_endpoint_description_t **); 167 167 168 168 int usb_device_retrieve_descriptors(usb_pipe_t *, usb_device_descriptors_t *); 169 169 int usb_device_create_pipes(const ddf_dev_t *, usb_device_connection_t *, 170 usb_endpoint_description_t **,uint8_t *, size_t, int, int,170 const usb_endpoint_description_t **, const uint8_t *, size_t, int, int, 171 171 usb_endpoint_mapping_t **, size_t *); 172 172 int usb_device_destroy_pipes(const ddf_dev_t *, usb_endpoint_mapping_t *, size_t); 173 int usb_device_create(ddf_dev_t *, usb_endpoint_description_t **, usb_device_t **, const char **); 174 void usb_device_destroy(usb_device_t *); 173 int usb_device_init(usb_device_t *, ddf_dev_t *, 174 const usb_endpoint_description_t **, const char **); 175 void usb_device_deinit(usb_device_t *); 175 176 176 size_t usb_interface_count_alternates(uint8_t *, size_t, uint8_t); 177 int usb_alternate_interfaces_create(uint8_t *, size_t, int, 177 void * usb_device_data_alloc(usb_device_t *, size_t); 178 179 size_t usb_interface_count_alternates(const uint8_t *, size_t, uint8_t); 180 int usb_alternate_interfaces_create(const uint8_t *, size_t, int, 178 181 usb_alternate_interfaces_t **); 179 182 void usb_alternate_interfaces_destroy(usb_alternate_interfaces_t *); 180 183 #endif 181 184 /** -
uspace/lib/usbdev/include/usb/dev/pipes.h
r4c3ad56 r20a3465 171 171 int usb_pipe_probe_default_control(usb_pipe_t *); 172 172 int usb_pipe_initialize_from_configuration(usb_endpoint_mapping_t *, 173 size_t, uint8_t *, size_t, usb_device_connection_t *);173 size_t, const uint8_t *, size_t, usb_device_connection_t *); 174 174 int usb_pipe_register_with_speed(usb_pipe_t *, usb_speed_t, 175 175 unsigned int, usb_hc_connection_t *); -
uspace/lib/usbdev/src/altiface.c
r4c3ad56 r20a3465 48 48 * @return Number of alternate interfaces for @p interface_no interface. 49 49 */ 50 size_t usb_interface_count_alternates( uint8_t *config_descr,50 size_t usb_interface_count_alternates(const uint8_t *config_descr, 51 51 size_t config_descr_size, uint8_t interface_no) 52 52 { … … 54 54 assert(config_descr_size > 0); 55 55 56 usb_dp_parser_t dp_parser = {56 const usb_dp_parser_t dp_parser = { 57 57 .nesting = usb_dp_standard_descriptor_nesting 58 58 }; 59 usb_dp_parser_data_t dp_data = {59 const usb_dp_parser_data_t dp_data = { 60 60 .data = config_descr, 61 61 .size = config_descr_size, … … 65 65 size_t alternate_count = 0; 66 66 67 uint8_t *iface_ptr = usb_dp_get_nested_descriptor(&dp_parser,67 const uint8_t *iface_ptr = usb_dp_get_nested_descriptor(&dp_parser, 68 68 &dp_data, config_descr); 69 69 while (iface_ptr != NULL) { … … 90 90 * @return Error code. 91 91 */ 92 int usb_alternate_interfaces_create( uint8_t *config_descr,92 int usb_alternate_interfaces_create(const uint8_t *config_descr, 93 93 size_t config_descr_size, int interface_number, 94 94 usb_alternate_interfaces_t **alternates_ptr) … … 98 98 assert(config_descr_size > 0); 99 99 100 *alternates_ptr = NULL; 100 101 if (interface_number < 0) { 101 alternates_ptr = NULL;102 102 return EOK; 103 103 } … … 105 105 usb_alternate_interfaces_t *alternates 106 106 = malloc(sizeof(usb_alternate_interfaces_t)); 107 108 107 if (alternates == NULL) { 109 108 return ENOMEM; … … 119 118 } 120 119 121 alternates->alternatives = malloc(alternates->alternative_count122 *sizeof(usb_alternate_interface_descriptors_t));120 alternates->alternatives = calloc(alternates->alternative_count, 121 sizeof(usb_alternate_interface_descriptors_t)); 123 122 if (alternates->alternatives == NULL) { 124 123 free(alternates); … … 140 139 = &alternates->alternatives[0]; 141 140 142 uint8_t *iface_ptr = usb_dp_get_nested_descriptor(&dp_parser,141 const uint8_t *iface_ptr = usb_dp_get_nested_descriptor(&dp_parser, 143 142 &dp_data, dp_data.data); 144 143 while (iface_ptr != NULL) { … … 160 159 dp_data.data, iface_ptr); 161 160 if (iface_ptr == NULL) { 162 uint8_t *next = dp_data.data + dp_data.size;161 const uint8_t *next = dp_data.data + dp_data.size; 163 162 cur_alt_iface->nested_descriptors_size 164 163 = next - cur_alt_iface->nested_descriptors; … … 176 175 } 177 176 178 177 void usb_alternate_interfaces_destroy(usb_alternate_interfaces_t *alternate) 178 { 179 if (!alternate) 180 return; 181 free(alternate->alternatives); 182 free(alternate); 183 } 179 184 /** 180 185 * @} -
uspace/lib/usbdev/src/devdrv.c
r4c3ad56 r20a3465 54 54 }; 55 55 56 static usb_driver_t *driver = NULL;56 static const usb_driver_t *driver = NULL; 57 57 58 58 … … 64 64 * @return Task exit status. 65 65 */ 66 int usb_driver_main( usb_driver_t *drv)66 int usb_driver_main(const usb_driver_t *drv) 67 67 { 68 68 assert(drv != NULL); … … 81 81 * @return Number of pipes (excluding default control pipe). 82 82 */ 83 static size_t count_other_pipes( usb_endpoint_description_t **endpoints)83 static size_t count_other_pipes(const usb_endpoint_description_t **endpoints) 84 84 { 85 85 size_t count = 0; … … 101 101 * @return Error code. 102 102 */ 103 static int initialize_other_pipes( usb_endpoint_description_t **endpoints,103 static int initialize_other_pipes(const usb_endpoint_description_t **endpoints, 104 104 usb_device_t *dev, int alternate_setting) 105 105 { … … 115 115 int rc = usb_device_create_pipes(dev->ddf_dev, &dev->wire, endpoints, 116 116 dev->descriptors.configuration, dev->descriptors.configuration_size, 117 dev->interface_no, alternate_setting, 118 &pipes, &pipes_count); 117 dev->interface_no, alternate_setting, &pipes, &pipes_count); 119 118 120 119 if (rc != EOK) { … … 141 140 assert(driver->ops->device_add); 142 141 143 int rc; 144 145 usb_device_t *dev = NULL; 142 usb_device_t *dev = ddf_dev_data_alloc(gen_dev, sizeof(usb_device_t)); 143 if (dev == NULL) { 144 usb_log_error("USB device `%s' structure allocation failed.\n", 145 gen_dev->name); 146 return ENOMEM; 147 } 146 148 const char *err_msg = NULL; 147 rc = usb_device_create(gen_dev, driver->endpoints, &dev, &err_msg);148 if (rc != EOK) { 149 usb_log_error("USB device `%s' creationfailed (%s): %s.\n",149 int rc = usb_device_init(dev, gen_dev, driver->endpoints, &err_msg); 150 if (rc != EOK) { 151 usb_log_error("USB device `%s' init failed (%s): %s.\n", 150 152 gen_dev->name, err_msg, str_error(rc)); 151 153 return rc; 152 154 } 153 gen_dev->driver_data = dev; 154 155 return driver->ops->device_add(dev); 155 156 rc = driver->ops->device_add(dev); 157 if (rc != EOK) 158 usb_device_deinit(dev); 159 return rc; 156 160 } 157 161 /*----------------------------------------------------------------------------*/ … … 186 190 if (driver->ops->device_gone == NULL) 187 191 return ENOTSUP; 188 const int ret = driver->ops->device_gone(gen_dev->driver_data); 192 usb_device_t *usb_dev = gen_dev->driver_data; 193 const int ret = driver->ops->device_gone(usb_dev); 189 194 if (ret == EOK) 190 usb_device_de stroy(gen_dev->driver_data);195 usb_device_deinit(usb_dev); 191 196 192 197 return ret; … … 235 240 */ 236 241 int usb_device_select_interface(usb_device_t *dev, uint8_t alternate_setting, 237 usb_endpoint_description_t **endpoints)242 const usb_endpoint_description_t **endpoints) 238 243 { 239 244 if (dev->interface_no < 0) { … … 318 323 */ 319 324 int usb_device_create_pipes(const ddf_dev_t *dev, usb_device_connection_t *wire, 320 usb_endpoint_description_t **endpoints,321 uint8_t *config_descr, size_t config_descr_size,325 const usb_endpoint_description_t **endpoints, 326 const uint8_t *config_descr, size_t config_descr_size, 322 327 int interface_no, int interface_setting, 323 328 usb_endpoint_mapping_t **pipes_ptr, size_t *pipes_count_ptr) … … 333 338 int rc; 334 339 335 size_t pipe_count = count_other_pipes(endpoints);340 const size_t pipe_count = count_other_pipes(endpoints); 336 341 if (pipe_count == 0) { 342 *pipes_count_ptr = pipe_count; 337 343 *pipes_ptr = NULL; 338 344 return EOK; … … 445 451 { 446 452 assert(dev != NULL); 447 assert(((pipes != NULL) && (pipes_count > 0))448 || ((pipes == NULL) && (pipes_count == 0)));449 453 450 454 if (pipes_count == 0) { 455 assert(pipes == NULL); 451 456 return EOK; 452 457 } 458 assert(pipes != NULL); 453 459 454 460 int rc; … … 468 474 size_t i; 469 475 for (i = 0; i < pipes_count; i++) { 470 usb_pipe_unregister(pipes[i].pipe, &hc_conn); 476 usb_log_debug2("Unregistering pipe %zu (%spresent).\n", 477 i, pipes[i].present ? "" : "not "); 478 if (pipes[i].present) 479 usb_pipe_unregister(pipes[i].pipe, &hc_conn); 471 480 free(pipes[i].pipe); 472 481 } … … 509 518 510 519 511 /** Create new instance of USB device. 512 * 520 /** Initialize new instance of USB device. 521 * 522 * @param[in] usb_dev Pointer to the new device. 513 523 * @param[in] ddf_dev Generic DDF device backing the USB one. 514 524 * @param[in] endpoints NULL terminated array of endpoints (NULL for none). 515 * @param[out] dev_ptr Where to store pointer to the new device.516 525 * @param[out] errstr_ptr Where to store description of context 517 526 * (in case error occurs). 518 527 * @return Error code. 519 528 */ 520 int usb_device_create(ddf_dev_t *ddf_dev, 521 usb_endpoint_description_t **endpoints, 522 usb_device_t **dev_ptr, const char **errstr_ptr) 523 { 524 assert(dev_ptr != NULL); 529 int usb_device_init(usb_device_t *usb_dev, ddf_dev_t *ddf_dev, 530 const usb_endpoint_description_t **endpoints, const char **errstr_ptr) 531 { 532 assert(usb_dev != NULL); 525 533 assert(ddf_dev != NULL); 526 534 527 int rc; 528 529 usb_device_t *dev = malloc(sizeof(usb_device_t)); 530 if (dev == NULL) { 531 *errstr_ptr = "structure allocation"; 532 return ENOMEM; 533 } 534 535 // FIXME: proper deallocation in case of errors 536 537 dev->ddf_dev = ddf_dev; 538 dev->driver_data = NULL; 539 dev->descriptors.configuration = NULL; 540 dev->alternate_interfaces = NULL; 541 542 dev->pipes_count = 0; 543 dev->pipes = NULL; 535 usb_dev->ddf_dev = ddf_dev; 536 usb_dev->driver_data = NULL; 537 usb_dev->descriptors.configuration = NULL; 538 usb_dev->alternate_interfaces = NULL; 539 usb_dev->pipes_count = 0; 540 usb_dev->pipes = NULL; 544 541 545 542 /* Initialize backing wire and control pipe. */ 546 rc = init_wire_and_ctrl_pipe(dev, errstr_ptr);543 int rc = init_wire_and_ctrl_pipe(usb_dev, errstr_ptr); 547 544 if (rc != EOK) { 548 545 return rc; … … 550 547 551 548 /* Get our interface. */ 552 dev->interface_no = usb_device_get_assigned_interface(dev->ddf_dev);549 usb_dev->interface_no = usb_device_get_assigned_interface(ddf_dev); 553 550 554 551 /* Retrieve standard descriptors. */ 555 rc = usb_device_retrieve_descriptors(&dev->ctrl_pipe, 556 &dev->descriptors); 557 if (rc != EOK) { 552 rc = usb_device_retrieve_descriptors(&usb_dev->ctrl_pipe, 553 &usb_dev->descriptors); 554 if (rc != EOK) { 555 /* Nothing allocated, nothing to free. */ 558 556 *errstr_ptr = "descriptor retrieval"; 559 557 return rc; 560 558 } 561 559 562 /* Create alternate interfaces. */ 563 rc = usb_alternate_interfaces_create(dev->descriptors.configuration, 564 dev->descriptors.configuration_size, dev->interface_no, 565 &dev->alternate_interfaces); 566 if (rc != EOK) { 567 /* We will try to silently ignore this. */ 568 dev->alternate_interfaces = NULL; 569 } 570 571 rc = initialize_other_pipes(endpoints, dev, 0); 572 if (rc != EOK) { 560 /* Create alternate interfaces. We will silently ignore failure. */ 561 //TODO Why ignore? 562 usb_alternate_interfaces_create(usb_dev->descriptors.configuration, 563 usb_dev->descriptors.configuration_size, usb_dev->interface_no, 564 &usb_dev->alternate_interfaces); 565 566 rc = initialize_other_pipes(endpoints, usb_dev, 0); 567 if (rc != EOK) { 568 /* Full configuration descriptor is allocated. */ 569 free(usb_dev->descriptors.configuration); 570 /* Alternate interfaces may be allocated */ 571 usb_alternate_interfaces_destroy(usb_dev->alternate_interfaces); 573 572 *errstr_ptr = "pipes initialization"; 574 573 return rc; … … 576 575 577 576 *errstr_ptr = NULL; 578 *dev_ptr = dev;579 577 580 578 return EOK; 581 579 } 582 580 583 /** Destroy instance of a USB device. 584 * 585 * @param dev Device to be destroyed. 586 */ 587 void usb_device_destroy(usb_device_t *dev) 588 { 589 if (dev == NULL) { 590 return; 591 } 592 593 /* Ignore errors and hope for the best. */ 594 usb_device_destroy_pipes(dev->ddf_dev, dev->pipes, dev->pipes_count); 595 free(dev->descriptors.configuration); 596 597 if (dev->alternate_interfaces != NULL) { 598 free(dev->alternate_interfaces->alternatives); 599 } 600 free(dev->alternate_interfaces); 601 602 free(dev); 581 /** Clean instance of a USB device. 582 * 583 * @param dev Device to be de-initialized. 584 * 585 * Does not free/destroy supplied pointer. 586 */ 587 void usb_device_deinit(usb_device_t *dev) 588 { 589 if (dev) { 590 /* Ignore errors and hope for the best. */ 591 destroy_current_pipes(dev); 592 593 usb_alternate_interfaces_destroy(dev->alternate_interfaces); 594 free(dev->descriptors.configuration); 595 free(dev->driver_data); 596 } 597 } 598 599 void * usb_device_data_alloc(usb_device_t *usb_dev, size_t size) 600 { 601 assert(usb_dev); 602 assert(usb_dev->driver_data == NULL); 603 return usb_dev->driver_data = calloc(1, size); 604 603 605 } 604 606 -
uspace/lib/usbdev/src/dp.c
r4c3ad56 r20a3465 75 75 * @return Whether @p ptr points inside <code>data->data</code> field. 76 76 */ 77 static bool is_valid_descriptor_pointer( usb_dp_parser_data_t *data,78 uint8_t *ptr)77 static bool is_valid_descriptor_pointer(const usb_dp_parser_data_t *data, 78 const uint8_t *ptr) 79 79 { 80 80 if (ptr == NULL) { … … 100 100 * @retval NULL Invalid input or no next descriptor. 101 101 */ 102 static uint8_t *get_next_descriptor(usb_dp_parser_data_t *data,103 uint8_t *current)102 static const uint8_t *get_next_descriptor(const usb_dp_parser_data_t *data, 103 const uint8_t *current) 104 104 { 105 105 assert(is_valid_descriptor_pointer(data, current)); 106 106 107 uint8_t current_length = *current;108 uint8_t *next = current + current_length;107 const uint8_t current_length = *current; 108 const uint8_t *next = current + current_length; 109 109 110 110 if (!is_valid_descriptor_pointer(data, next)) { … … 124 124 * @retval -1 Invalid input. 125 125 */ 126 static int get_descriptor_type( usb_dp_parser_data_t *data,uint8_t *start)126 static int get_descriptor_type(const usb_dp_parser_data_t *data, const uint8_t *start) 127 127 { 128 128 if (start == NULL) { … … 145 145 * @return Whether @p child could be child of @p parent. 146 146 */ 147 static bool is_nested_descriptor_type( usb_dp_parser_t *parser,147 static bool is_nested_descriptor_type(const usb_dp_parser_t *parser, 148 148 int child, int parent) 149 149 { 150 usb_dp_descriptor_nesting_t *nesting = parser->nesting;150 const usb_dp_descriptor_nesting_t *nesting = parser->nesting; 151 151 while ((nesting->child > 0) && (nesting->parent > 0)) { 152 152 if ((nesting->child == child) && (nesting->parent == parent)) { … … 166 166 * @return Whether @p child could be child of @p parent. 167 167 */ 168 static bool is_nested_descriptor( usb_dp_parser_t *parser,169 usb_dp_parser_data_t *data, uint8_t *child,uint8_t *parent)168 static bool is_nested_descriptor(const usb_dp_parser_t *parser, 169 const usb_dp_parser_data_t *data, const uint8_t *child, const uint8_t *parent) 170 170 { 171 171 return is_nested_descriptor_type(parser, … … 183 183 * @retval NULL Invalid input. 184 184 */ 185 uint8_t *usb_dp_get_nested_descriptor(usb_dp_parser_t *parser,186 usb_dp_parser_data_t *data,uint8_t *parent)185 const uint8_t *usb_dp_get_nested_descriptor(const usb_dp_parser_t *parser, 186 const usb_dp_parser_data_t *data, const uint8_t *parent) 187 187 { 188 188 if (!is_valid_descriptor_pointer(data, parent)) { … … 190 190 } 191 191 192 uint8_t *next = get_next_descriptor(data, parent);192 const uint8_t *next = get_next_descriptor(data, parent); 193 193 if (next == NULL) { 194 194 return NULL; … … 211 211 * @retval NULL Invalid input. 212 212 */ 213 static uint8_t *skip_nested_descriptors(usb_dp_parser_t *parser, 214 usb_dp_parser_data_t *data, uint8_t *parent) 215 { 216 uint8_t *child = usb_dp_get_nested_descriptor(parser, data, parent); 213 static const uint8_t *skip_nested_descriptors(const usb_dp_parser_t *parser, 214 const usb_dp_parser_data_t *data, const uint8_t *parent) 215 { 216 const uint8_t *child = 217 usb_dp_get_nested_descriptor(parser, data, parent); 217 218 if (child == NULL) { 218 219 return get_next_descriptor(data, parent); 219 220 } 220 uint8_t *next_child = skip_nested_descriptors(parser, data, child); 221 const uint8_t *next_child = 222 skip_nested_descriptors(parser, data, child); 221 223 while (is_nested_descriptor(parser, data, next_child, parent)) { 222 224 next_child = skip_nested_descriptors(parser, data, next_child); … … 236 238 * @retval NULL Invalid input. 237 239 */ 238 uint8_t *usb_dp_get_sibling_descriptor(usb_dp_parser_t *parser, 239 usb_dp_parser_data_t *data, uint8_t *parent, uint8_t *sibling) 240 const uint8_t *usb_dp_get_sibling_descriptor( 241 const usb_dp_parser_t *parser, const usb_dp_parser_data_t *data, 242 const uint8_t *parent, const uint8_t *sibling) 240 243 { 241 244 if (!is_valid_descriptor_pointer(data, parent) … … 244 247 } 245 248 246 uint8_t *possible_sibling = skip_nested_descriptors(parser, data, sibling); 249 const uint8_t *possible_sibling = 250 skip_nested_descriptors(parser, data, sibling); 247 251 if (possible_sibling == NULL) { 248 252 return NULL; … … 269 273 * @param arg Custom (user) argument. 270 274 */ 271 static void usb_dp_browse_simple_internal( usb_dp_parser_t *parser,272 usb_dp_parser_data_t *data,uint8_t *root, size_t depth,273 void (*callback)( uint8_t *, size_t, void *), void *arg)275 static void usb_dp_browse_simple_internal(const usb_dp_parser_t *parser, 276 const usb_dp_parser_data_t *data, const uint8_t *root, size_t depth, 277 void (*callback)(const uint8_t *, size_t, void *), void *arg) 274 278 { 275 279 if (root == NULL) { … … 277 281 } 278 282 callback(root, depth, arg); 279 uint8_t *child = usb_dp_get_nested_descriptor(parser, data, root);283 const uint8_t *child = usb_dp_get_nested_descriptor(parser, data, root); 280 284 do { 281 285 usb_dp_browse_simple_internal(parser, data, child, depth + 1, … … 301 305 */ 302 306 void usb_dp_walk_simple(uint8_t *descriptors, size_t descriptors_size, 303 usb_dp_descriptor_nesting_t *descriptor_nesting,304 void (*callback)(uint8_t *, size_t, void *), void *arg)307 const usb_dp_descriptor_nesting_t *descriptor_nesting, 308 walk_callback_t callback, void *arg) 305 309 { 306 310 if ((descriptors == NULL) || (descriptors_size == 0) … … 309 313 } 310 314 311 usb_dp_parser_data_t data = {315 const usb_dp_parser_data_t data = { 312 316 .data = descriptors, 313 317 .size = descriptors_size, … … 315 319 }; 316 320 317 usb_dp_parser_t parser = {321 const usb_dp_parser_t parser = { 318 322 .nesting = descriptor_nesting 319 323 }; -
uspace/lib/usbdev/src/pipesinit.c
r4c3ad56 r20a3465 68 68 * @return Whether the given descriptor is endpoint descriptor. 69 69 */ 70 static inline bool is_endpoint_descriptor( uint8_t *descriptor)70 static inline bool is_endpoint_descriptor(const uint8_t *descriptor) 71 71 { 72 72 return descriptor[1] == USB_DESCTYPE_ENDPOINT; … … 80 80 */ 81 81 static bool endpoint_fits_description(const usb_endpoint_description_t *wanted, 82 usb_endpoint_description_t *found)82 const usb_endpoint_description_t *found) 83 83 { 84 84 #define _SAME(fieldname) ((wanted->fieldname) == (found->fieldname)) … … 120 120 static usb_endpoint_mapping_t *find_endpoint_mapping( 121 121 usb_endpoint_mapping_t *mapping, size_t mapping_count, 122 usb_endpoint_description_t *found_endpoint,122 const usb_endpoint_description_t *found_endpoint, 123 123 int interface_number, int interface_setting) 124 124 { … … 160 160 usb_device_connection_t *wire) 161 161 { 162 usb_endpoint_description_t description;163 162 164 163 /* … … 167 166 168 167 /* Actual endpoint number is in bits 0..3 */ 169 usb_endpoint_t ep_no = endpoint->endpoint_address & 0x0F; 170 171 /* Endpoint direction is set by bit 7 */ 172 description.direction = (endpoint->endpoint_address & 128) 173 ? USB_DIRECTION_IN : USB_DIRECTION_OUT; 174 /* Transfer type is in bits 0..2 and the enum values corresponds 1:1 */ 175 description.transfer_type = endpoint->attributes & 3; 176 177 /* 178 * Get interface characteristics. 179 */ 180 description.interface_class = interface->interface_class; 181 description.interface_subclass = interface->interface_subclass; 182 description.interface_protocol = interface->interface_protocol; 168 const usb_endpoint_t ep_no = endpoint->endpoint_address & 0x0F; 169 170 const usb_endpoint_description_t description = { 171 /* Endpoint direction is set by bit 7 */ 172 .direction = (endpoint->endpoint_address & 128) 173 ? USB_DIRECTION_IN : USB_DIRECTION_OUT, 174 /* Transfer type is in bits 0..2 and 175 * the enum values corresponds 1:1 */ 176 .transfer_type = endpoint->attributes & 3, 177 178 /* Get interface characteristics. */ 179 .interface_class = interface->interface_class, 180 .interface_subclass = interface->interface_subclass, 181 .interface_protocol = interface->interface_protocol, 182 }; 183 183 184 184 /* … … 224 224 static int process_interface( 225 225 usb_endpoint_mapping_t *mapping, size_t mapping_count, 226 usb_dp_parser_t *parser,usb_dp_parser_data_t *parser_data,227 uint8_t *interface_descriptor)228 { 229 uint8_t *descriptor = usb_dp_get_nested_descriptor(parser,226 const usb_dp_parser_t *parser, const usb_dp_parser_data_t *parser_data, 227 const uint8_t *interface_descriptor) 228 { 229 const uint8_t *descriptor = usb_dp_get_nested_descriptor(parser, 230 230 parser_data, interface_descriptor); 231 231 … … 284 284 int usb_pipe_initialize_from_configuration( 285 285 usb_endpoint_mapping_t *mapping, size_t mapping_count, 286 uint8_t *configuration_descriptor, size_t configuration_descriptor_size,286 const uint8_t *config_descriptor, size_t config_descriptor_size, 287 287 usb_device_connection_t *connection) 288 288 { 289 289 assert(connection); 290 290 291 if (config uration_descriptor == NULL) {291 if (config_descriptor == NULL) { 292 292 return EBADMEM; 293 293 } 294 if (config uration_descriptor_size294 if (config_descriptor_size 295 295 < sizeof(usb_standard_configuration_descriptor_t)) { 296 296 return ERANGE; … … 310 310 * Prepare the descriptor parser. 311 311 */ 312 usb_dp_parser_t dp_parser = {312 const usb_dp_parser_t dp_parser = { 313 313 .nesting = descriptor_nesting 314 314 }; 315 usb_dp_parser_data_t dp_data = {316 .data = config uration_descriptor,317 .size = config uration_descriptor_size,315 const usb_dp_parser_data_t dp_data = { 316 .data = config_descriptor, 317 .size = config_descriptor_size, 318 318 .arg = connection 319 319 }; … … 322 322 * Iterate through all interfaces. 323 323 */ 324 uint8_t *interface = usb_dp_get_nested_descriptor(&dp_parser,325 &dp_data, config uration_descriptor);324 const uint8_t *interface = usb_dp_get_nested_descriptor(&dp_parser, 325 &dp_data, config_descriptor); 326 326 if (interface == NULL) { 327 327 return ENOENT; … … 329 329 do { 330 330 (void) process_interface(mapping, mapping_count, 331 &dp_parser, &dp_data, 332 interface); 331 &dp_parser, &dp_data, interface); 333 332 interface = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data, 334 config uration_descriptor, interface);333 config_descriptor, interface); 335 334 } while (interface != NULL); 336 335 … … 514 513 { 515 514 assert(pipe); 515 assert(pipe->wire); 516 516 assert(hc_connection); 517 517 -
uspace/lib/usbdev/src/request.c
r4c3ad56 r20a3465 425 425 426 426 /* Everything is okay, copy the descriptor. */ 427 memcpy(descriptor, &descriptor_tmp, 428 sizeof(descriptor_tmp)); 427 memcpy(descriptor, &descriptor_tmp, sizeof(descriptor_tmp)); 429 428 430 429 return EOK; … … 470 469 471 470 /* Everything is okay, copy the descriptor. */ 472 memcpy(descriptor, &descriptor_tmp, 473 sizeof(descriptor_tmp)); 471 memcpy(descriptor, &descriptor_tmp, sizeof(descriptor_tmp)); 474 472 475 473 return EOK; -
uspace/lib/usbhid/include/usb/hid/hiddescriptor.h
r4c3ad56 r20a3465 42 42 #include <usb/hid/hidtypes.h> 43 43 44 int usb_hid_parse_report_descriptor(usb_hid_report_t *report, 44 int usb_hid_parse_report_descriptor(usb_hid_report_t *report, 45 45 const uint8_t *data, size_t size); 46 47 void usb_hid_free_report(usb_hid_report_t *report);48 46 49 47 void usb_hid_descriptor_print(usb_hid_report_t *report); 50 48 51 49 int usb_hid_report_init(usb_hid_report_t *report); 50 51 void usb_hid_report_deinit(usb_hid_report_t *report); 52 52 53 53 int usb_hid_report_append_fields(usb_hid_report_t *report, … … 78 78 void usb_hid_report_reset_local_items(usb_hid_report_item_t *report_item); 79 79 80 void usb_hid_free_report_list(list_t *list);81 82 80 usb_hid_report_item_t *usb_hid_report_item_clone( 83 81 const usb_hid_report_item_t *item); -
uspace/lib/usbhid/src/hiddescriptor.c
r4c3ad56 r20a3465 974 974 /*---------------------------------------------------------------------------*/ 975 975 976 /**977 * Releases whole linked list of report items978 *979 * @param list List of report descriptor items (usb_hid_report_item_t)980 * @return void981 */982 void usb_hid_free_report_list(list_t *list)983 {984 return; /* XXX What's this? */985 986 /* usb_hid_report_item_t *report_item;987 link_t *next;988 989 if(list == NULL || list_empty(list)) {990 return;991 }992 993 next = list->head.next;994 while (next != &list->head) {995 report_item = list_get_instance(next, usb_hid_report_item_t,996 rpath_items_link);997 998 while(!list_empty(&report_item->usage_path->link)) {999 usb_hid_report_remove_last_item(report_item->usage_path);1000 }1001 1002 1003 next = next->next;1004 1005 free(report_item);1006 }1007 1008 return;1009 */1010 }1011 /*---------------------------------------------------------------------------*/1012 976 1013 977 /** Frees the HID report descriptor parser structure … … 1016 980 * @return void 1017 981 */ 1018 void usb_hid_ free_report(usb_hid_report_t *report)982 void usb_hid_report_deinit(usb_hid_report_t *report) 1019 983 { 1020 984 if(report == NULL){ -
uspace/lib/usbhid/src/hidparser.c
r4c3ad56 r20a3465 52 52 int32_t value); 53 53 54 int usb_pow(int a, int b); 55 56 /*---------------------------------------------------------------------------*/ 57 58 // TODO: tohle ma bejt asi jinde 59 int usb_pow(int a, int b) 60 { 61 switch(b) { 54 /*---------------------------------------------------------------------------*/ 55 56 static int usb_pow(int a, int b) 57 { 58 switch (b) { 62 59 case 0: 63 60 return 1; … … 67 64 break; 68 65 default: 69 return a * usb_pow(a, b -1);66 return a * usb_pow(a, b - 1); 70 67 break; 71 68 } … … 81 78 */ 82 79 size_t usb_hid_report_size(usb_hid_report_t *report, uint8_t report_id, 83 usb_hid_report_type_t type)80 usb_hid_report_type_t type) 84 81 { 85 82 usb_hid_report_description_t *report_des; 86 83 87 if (report == NULL) {84 if (report == NULL) { 88 85 return 0; 89 86 } 90 87 91 report_des = usb_hid_report_find_description (report, report_id, type);92 if (report_des == NULL){88 report_des = usb_hid_report_find_description(report, report_id, type); 89 if (report_des == NULL) { 93 90 return 0; 94 } 95 else { 91 } else { 96 92 return report_des->item_length; 97 93 } … … 106 102 */ 107 103 size_t usb_hid_report_byte_size(usb_hid_report_t *report, uint8_t report_id, 108 usb_hid_report_type_t type)104 usb_hid_report_type_t type) 109 105 { 110 106 usb_hid_report_description_t *report_des; 111 107 112 if (report == NULL) {108 if (report == NULL) { 113 109 return 0; 114 110 } 115 111 116 report_des = usb_hid_report_find_description (report, report_id, type);117 if (report_des == NULL){112 report_des = usb_hid_report_find_description(report, report_id, type); 113 if (report_des == NULL) { 118 114 return 0; 119 } 120 else { 115 } else { 121 116 return ((report_des->bit_length + 7) / 8) ; 122 117 } … … 133 128 */ 134 129 int usb_hid_parse_report(const usb_hid_report_t *report, const uint8_t *data, 135 size_t size, uint8_t *report_id)130 size_t size, uint8_t *report_id) 136 131 { 137 132 usb_hid_report_field_t *item; … … 140 135 usb_hid_report_type_t type = USB_HID_REPORT_TYPE_INPUT; 141 136 142 if (report == NULL) {137 if (report == NULL) { 143 138 return EINVAL; 144 139 } 145 140 146 if (report->use_report_ids != 0) {141 if (report->use_report_ids != 0) { 147 142 *report_id = data[0]; 148 } 149 else { 143 } else { 150 144 *report_id = 0; 151 145 } 152 146 153 154 147 report_des = usb_hid_report_find_description(report, *report_id, 155 type);156 157 if (report_des == NULL) {148 type); 149 150 if (report_des == NULL) { 158 151 return EINVAL; 159 152 } … … 162 155 list_foreach(report_des->report_items, list_item) { 163 156 item = list_get_instance(list_item, usb_hid_report_field_t, 164 ritems_link);165 166 if (USB_HID_ITEM_FLAG_CONSTANT(item->item_flags) == 0) {157 ritems_link); 158 159 if (USB_HID_ITEM_FLAG_CONSTANT(item->item_flags) == 0) { 167 160 168 if(USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0){ 169 170 // array 161 if (USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0) { 162 /* array */ 171 163 item->value = 172 164 usb_hid_translate_data(item, data); 173 165 174 166 item->usage = USB_HID_EXTENDED_USAGE( 175 item->usages[ 176 item-> value - item->physical_minimum]);167 item->usages[item->value - 168 item->physical_minimum]); 177 169 178 170 item->usage_page = 179 171 USB_HID_EXTENDED_USAGE_PAGE( 180 item->usages[ 181 item-> value - item->physical_minimum]);182 183 usb_hid_report_set_last_item (172 item->usages[item->value - 173 item->physical_minimum]); 174 175 usb_hid_report_set_last_item( 184 176 item->collection_path, 185 177 USB_HID_TAG_CLASS_GLOBAL, 186 178 item->usage_page); 187 179 188 usb_hid_report_set_last_item (180 usb_hid_report_set_last_item( 189 181 item->collection_path, 190 182 USB_HID_TAG_CLASS_LOCAL, item->usage); 191 192 } 193 else { 194 // variable item 183 } else { 184 /* variable item */ 195 185 item->value = usb_hid_translate_data(item, 196 186 data); … … 200 190 201 191 return EOK; 202 203 192 } 204 193 … … 217 206 int part_size; 218 207 219 int32_t value =0;220 int32_t mask =0;221 const uint8_t *foo =0;222 223 / / now only shot tags are allowed224 if (item->size > 32) {208 int32_t value = 0; 209 int32_t mask = 0; 210 const uint8_t *foo = 0; 211 212 /* now only short tags are allowed */ 213 if (item->size > 32) { 225 214 return 0; 226 215 } 227 216 228 if ((item->physical_minimum == 0) && (item->physical_maximum == 0)){217 if ((item->physical_minimum == 0) && (item->physical_maximum == 0)) { 229 218 item->physical_minimum = item->logical_minimum; 230 219 item->physical_maximum = item->logical_maximum; … … 232 221 233 222 234 if (item->physical_maximum == item->physical_minimum){223 if (item->physical_maximum == item->physical_minimum) { 235 224 resolution = 1; 236 } 237 else { 225 } else { 238 226 resolution = (item->logical_maximum - item->logical_minimum) / 239 227 ((item->physical_maximum - item->physical_minimum) * 240 (usb_pow(10, (item->unit_exponent))));228 (usb_pow(10, (item->unit_exponent)))); 241 229 } 242 230 243 231 offset = item->offset; 244 232 // FIXME 245 if ((size_t)(offset/8) != (size_t)((offset+item->size-1)/8)) {233 if ((size_t) (offset / 8) != (size_t) ((offset+item->size - 1) / 8)) { 246 234 247 235 part_size = 0; 248 236 249 size_t i=0; 250 for(i=(size_t)(offset/8); i<=(size_t)(offset+item->size-1)/8; i++){ 251 if(i == (size_t)(offset/8)) { 252 // the higher one 237 size_t i = 0; 238 for (i = (size_t) (offset / 8); 239 i <= (size_t) (offset + item->size - 1) / 8; i++) { 240 if (i == (size_t) (offset / 8)) { 241 /* the higher one */ 253 242 part_size = 8 - (offset % 8); 254 243 foo = data + i; 255 mask = ((1 << (item->size -part_size))-1);244 mask = ((1 << (item->size - part_size)) - 1); 256 245 value = (*foo & mask); 257 } 258 else if(i == ((offset+item->size-1)/8)){ 259 // the lower one 246 } else if (i == ((offset + item->size - 1) / 8)) { 247 /* the lower one */ 260 248 foo = data + i; 261 mask = ((1 << (item->size - part_size)) - 1) 262 <<(8 - (item->size - part_size));249 mask = ((1 << (item->size - part_size)) - 1) << 250 (8 - (item->size - part_size)); 263 251 264 252 value = (((*foo & mask) >> (8 - 265 (item->size - part_size))) << part_size )266 +value;267 } 268 else {269 value = (*(data + 1) << (part_size + 8)) +value;253 (item->size - part_size))) << part_size) + 254 value; 255 } else { 256 value = (*(data + 1) << (part_size + 8)) + 257 value; 270 258 part_size += 8; 271 259 } 272 260 } 273 } 274 else {275 foo = data+(offset/8);276 mask = ((1 << item->size)-1) << (8-((offset%8)+item->size));277 value = (*foo & mask) >> (8 -((offset%8)+item->size));278 } 279 280 if ((item->logical_minimum < 0) || (item->logical_maximum < 0)){261 } else { 262 foo = data + (offset / 8); 263 mask = ((1 << item->size) - 1) << 264 (8 - ((offset % 8) + item->size)); 265 value = (*foo & mask) >> (8 - ((offset % 8) + item->size)); 266 } 267 268 if ((item->logical_minimum < 0) || (item->logical_maximum < 0)) { 281 269 value = USB_HID_UINT32_TO_INT32(value, item->size); 282 270 } 283 271 284 return (int)(((value - item->logical_minimum) / resolution) + 285 item->physical_minimum); 286 272 return (int) (((value - item->logical_minimum) / resolution) + 273 item->physical_minimum); 287 274 } 288 275 … … 299 286 */ 300 287 uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size, 301 uint8_t report_id)302 { 303 if (report == NULL) {288 uint8_t report_id) 289 { 290 if (report == NULL) { 304 291 *size = 0; 305 292 return NULL; … … 310 297 list_foreach(report->reports, report_it) { 311 298 report_des = list_get_instance(report_it, 312 usb_hid_report_description_t, reports_link);299 usb_hid_report_description_t, reports_link); 313 300 314 if ((report_des->report_id == report_id) &&315 (report_des->type == USB_HID_REPORT_TYPE_OUTPUT)){301 if ((report_des->report_id == report_id) && 302 (report_des->type == USB_HID_REPORT_TYPE_OUTPUT)) { 316 303 break; 317 304 } 318 305 } 319 306 320 if (report_des == NULL){307 if (report_des == NULL) { 321 308 *size = 0; 322 309 return NULL; 323 } 324 else { 325 *size = (report_des->bit_length + (8 - 1))/8; 310 } else { 311 *size = (report_des->bit_length + (8 - 1)) / 8; 326 312 uint8_t *ret = malloc((*size) * sizeof(uint8_t)); 327 313 memset(ret, 0, (*size) * sizeof(uint8_t)); … … 337 323 */ 338 324 void usb_hid_report_output_free(uint8_t *output) 339 340 { 341 if(output != NULL) { 342 free (output); 325 { 326 if (output != NULL) { 327 free(output); 343 328 } 344 329 } … … 354 339 */ 355 340 int usb_hid_report_output_translate(usb_hid_report_t *report, 356 uint8_t report_id, uint8_t *buffer, size_t size)357 { 358 int32_t value =0;341 uint8_t report_id, uint8_t *buffer, size_t size) 342 { 343 int32_t value = 0; 359 344 int offset; 360 345 int length; 361 346 int32_t tmp_value; 362 347 363 if (report == NULL) {348 if (report == NULL) { 364 349 return EINVAL; 365 350 } 366 351 367 if (report->use_report_ids != 0) {352 if (report->use_report_ids != 0) { 368 353 buffer[0] = report_id; 369 354 } 370 355 371 356 usb_hid_report_description_t *report_des; 372 report_des = usb_hid_report_find_description (report, report_id,373 USB_HID_REPORT_TYPE_OUTPUT);374 375 if (report_des == NULL){357 report_des = usb_hid_report_find_description(report, report_id, 358 USB_HID_REPORT_TYPE_OUTPUT); 359 360 if (report_des == NULL) { 376 361 return EINVAL; 377 362 } … … 384 369 385 370 value = usb_hid_translate_data_reverse(report_item, 386 report_item->value);371 report_item->value); 387 372 388 373 offset = report_des->bit_length - report_item->offset - 1; … … 391 376 usb_log_debug("\ttranslated value: %x\n", value); 392 377 393 if((offset/8) == ((offset+length-1)/8)) { 394 // je to v jednom bytu 395 if(((size_t)(offset/8) >= size) || 396 ((size_t)(offset+length-1)/8) >= size) { 378 if ((offset / 8) == ((offset + length - 1) / 8)) { 379 if (((size_t) (offset / 8) >= size) || 380 ((size_t) (offset + length - 1) / 8) >= size) { 397 381 break; // TODO ErrorCode 398 382 } 399 size_t shift = 8 - offset %8 - length;383 size_t shift = 8 - offset % 8 - length; 400 384 value = value << shift; 401 value = value & (((1 << length) -1) << shift);385 value = value & (((1 << length) - 1) << shift); 402 386 403 387 uint8_t mask = 0; 404 388 mask = 0xff - (((1 << length) - 1) << shift); 405 buffer[offset /8] = (buffer[offset/8] & mask) | value;406 }407 else {389 buffer[offset / 8] = (buffer[offset / 8] & mask) | 390 value; 391 } else { 408 392 int i = 0; 409 393 uint8_t mask = 0; 410 for(i = (offset/8); i <= ((offset+length-1)/8); i++) { 411 if(i == (offset/8)) { 394 for (i = (offset / 8); 395 i <= ((offset + length - 1) / 8); i++) { 396 if (i == (offset / 8)) { 412 397 tmp_value = value; 413 398 tmp_value = tmp_value & 414 ((1 << (8-(offset%8)))-1);415 416 tmp_value = tmp_value << (offset %8);417 418 mask = ~(((1 << (8 -(offset%8)))-1) <<419 (offset%8));399 ((1 << (8 - (offset % 8))) - 1); 400 401 tmp_value = tmp_value << (offset % 8); 402 403 mask = ~(((1 << (8 - (offset % 8))) - 1) 404 << (offset % 8)); 420 405 421 406 buffer[i] = (buffer[i] & mask) | 422 tmp_value; 423 } 424 else if (i == ((offset + length -1)/8)) { 407 tmp_value; 408 } else if (i == ((offset + length - 1) / 8)) { 425 409 426 410 value = value >> (length - 427 ((offset + length) % 8));411 ((offset + length) % 8)); 428 412 429 413 value = value & ((1 << (length - 430 ((offset + length) % 8))) - 1);414 ((offset + length) % 8))) - 1); 431 415 432 416 mask = (1 << (length - 433 ((offset + length) % 8))) - 1;417 ((offset + length) % 8))) - 1; 434 418 435 419 buffer[i] = (buffer[i] & mask) | value; 436 } 437 else { 438 buffer[i] = value & (0xFF << i); 420 } else { 421 buffer[i] = value & (0xff << i); 439 422 } 440 423 } 441 424 } 442 425 443 / / reset value426 /* reset value */ 444 427 report_item->value = 0; 445 428 } … … 456 439 */ 457 440 uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, 458 int value)459 { 460 int ret =0;441 int value) 442 { 443 int ret = 0; 461 444 int resolution; 462 445 463 if (USB_HID_ITEM_FLAG_CONSTANT(item->item_flags)) {446 if (USB_HID_ITEM_FLAG_CONSTANT(item->item_flags)) { 464 447 ret = item->logical_minimum; 465 448 } 466 449 467 if ((item->physical_minimum == 0) && (item->physical_maximum == 0)){450 if ((item->physical_minimum == 0) && (item->physical_maximum == 0)) { 468 451 item->physical_minimum = item->logical_minimum; 469 452 item->physical_maximum = item->logical_maximum; 470 453 } 471 454 472 / / variable item473 if (item->physical_maximum == item->physical_minimum){455 /* variable item */ 456 if (item->physical_maximum == item->physical_minimum) { 474 457 resolution = 1; 475 } 476 else { 458 } else { 477 459 resolution = (item->logical_maximum - item->logical_minimum) / 478 460 ((item->physical_maximum - item->physical_minimum) * 479 (usb_pow(10, (item->unit_exponent))));461 (usb_pow(10, (item->unit_exponent)))); 480 462 } 481 463 482 464 ret = ((value - item->physical_minimum) * resolution) + 483 item->logical_minimum;484 485 usb_log_debug("\tvalue(%x), resolution(%x), phymin(%x) logmin(%x), \486 ret(%x)\n", value, resolution, item->physical_minimum,487 item->logical_minimum, ret);488 489 if ((item->logical_minimum < 0) || (item->logical_maximum < 0)){465 item->logical_minimum; 466 467 usb_log_debug("\tvalue(%x), resolution(%x), phymin(%x) logmin(%x), " 468 "ret(%x)\n", value, resolution, item->physical_minimum, 469 item->logical_minimum, ret); 470 471 if ((item->logical_minimum < 0) || (item->logical_maximum < 0)) { 490 472 return USB_HID_INT32_TO_UINT32(ret, item->size); 491 473 } 492 return (int32_t)0 + ret; 474 475 return (int32_t) 0 + ret; 493 476 } 494 477 … … 501 484 */ 502 485 usb_hid_report_item_t *usb_hid_report_item_clone( 503 const usb_hid_report_item_t *item)486 const usb_hid_report_item_t *item) 504 487 { 505 488 usb_hid_report_item_t *new_report_item; 506 489 507 if (!(new_report_item = malloc(sizeof(usb_hid_report_item_t)))) {490 if (!(new_report_item = malloc(sizeof(usb_hid_report_item_t)))) { 508 491 return NULL; 509 492 } … … 529 512 */ 530 513 usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report, 531 usb_hid_report_field_t *field, usb_hid_report_path_t *path, int flags,532 usb_hid_report_type_t type)514 usb_hid_report_field_t *field, usb_hid_report_path_t *path, int flags, 515 usb_hid_report_type_t type) 533 516 { 534 517 usb_hid_report_description_t *report_des = 535 usb_hid_report_find_description(report, path->report_id, type);518 usb_hid_report_find_description(report, path->report_id, type); 536 519 537 520 link_t *field_it; 538 521 539 if (report_des == NULL){522 if (report_des == NULL) { 540 523 return NULL; 541 524 } 542 525 543 if (field == NULL){526 if (field == NULL) { 544 527 field_it = report_des->report_items.head.next; 545 } 546 else { 528 } else { 547 529 field_it = field->ritems_link.next; 548 530 } 549 531 550 while (field_it != &report_des->report_items.head) {532 while (field_it != &report_des->report_items.head) { 551 533 field = list_get_instance(field_it, usb_hid_report_field_t, 552 ritems_link); 553 554 if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0) { 555 usb_hid_report_path_append_item ( 556 field->collection_path, field->usage_page, 557 field->usage); 558 559 if(usb_hid_report_compare_usage_path( 560 field->collection_path, path, flags) == EOK){ 561 534 ritems_link); 535 536 if (USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0) { 537 usb_hid_report_path_append_item(field->collection_path, 538 field->usage_page, field->usage); 539 540 if (usb_hid_report_compare_usage_path( 541 field->collection_path, path, flags) == EOK) { 562 542 usb_hid_report_remove_last_item( 563 field->collection_path); 564 543 field->collection_path); 565 544 return field; 566 545 } 567 usb_hid_report_remove_last_item ( 568 field->collection_path); 546 usb_hid_report_remove_last_item(field->collection_path); 569 547 } 570 548 field_it = field_it->next; … … 586 564 * @retval report_id otherwise 587 565 */ 588 uint8_t usb_hid_get_next_report_id(usb_hid_report_t *report, 589 uint8_t report_id,usb_hid_report_type_t type)590 { 591 if (report == NULL){566 uint8_t usb_hid_get_next_report_id(usb_hid_report_t *report, uint8_t report_id, 567 usb_hid_report_type_t type) 568 { 569 if (report == NULL) { 592 570 return 0; 593 571 } … … 596 574 link_t *report_it; 597 575 598 if (report_id > 0) {576 if (report_id > 0) { 599 577 report_des = usb_hid_report_find_description(report, report_id, 600 type);601 if (report_des == NULL) {578 type); 579 if (report_des == NULL) { 602 580 return 0; 603 } 604 else { 581 } else { 605 582 report_it = report_des->reports_link.next; 606 583 } 607 } 608 else { 584 } else { 609 585 report_it = report->reports.head.next; 610 586 } 611 587 612 while (report_it != &report->reports.head) {588 while (report_it != &report->reports.head) { 613 589 report_des = list_get_instance(report_it, 614 usb_hid_report_description_t, reports_link);615 616 if (report_des->type == type){590 usb_hid_report_description_t, reports_link); 591 592 if (report_des->type == type) { 617 593 return report_des->report_id; 618 594 } … … 635 611 void usb_hid_report_reset_local_items(usb_hid_report_item_t *report_item) 636 612 { 637 if (report_item == NULL){613 if (report_item == NULL) { 638 614 return; 639 615 } … … 651 627 report_item->string_minimum = 0; 652 628 report_item->string_maximum = 0; 653 654 return; 655 } 629 } 630 656 631 /** 657 632 * @} -
uspace/lib/usbhid/src/hidreport.c
r4c3ad56 r20a3465 69 69 * First nested descriptor of the configuration descriptor. 70 70 */ 71 uint8_t *d =71 const uint8_t *d = 72 72 usb_dp_get_nested_descriptor(&parser, &parser_data, 73 73 dev->descriptors.configuration); … … 92 92 * First nested descriptor of the interface descriptor. 93 93 */ 94 uint8_t *iface_desc = d;94 const uint8_t *iface_desc = d; 95 95 d = usb_dp_get_nested_descriptor(&parser, &parser_data, iface_desc); 96 96 -
uspace/lib/usbhost/include/usb/host/endpoint.h
r4c3ad56 r20a3465 36 36 #define LIBUSBHOST_HOST_ENDPOINT_H 37 37 38 #include <assert.h>39 38 #include <bool.h> 40 39 #include <adt/list.h> 41 40 #include <fibril_synch.h> 42 43 41 #include <usb/usb.h> 44 42 43 /** Host controller side endpoint structure. */ 45 44 typedef struct endpoint { 45 /** Part of linked list. */ 46 link_t link; 47 /** USB address. */ 46 48 usb_address_t address; 49 /** USB endpoint number. */ 47 50 usb_endpoint_t endpoint; 51 /** Communication direction. */ 48 52 usb_direction_t direction; 53 /** USB transfer type. */ 49 54 usb_transfer_type_t transfer_type; 55 /** Communication speed. */ 50 56 usb_speed_t speed; 57 /** Maximum size of data packets. */ 51 58 size_t max_packet_size; 59 /** Necessary bandwidth. */ 60 size_t bandwidth; 61 /** Value of the toggle bit. */ 52 62 unsigned toggle:1; 63 /** True if there is a batch using this scheduled for this endpoint. */ 64 volatile bool active; 65 /** Protects resources and active status changes. */ 53 66 fibril_mutex_t guard; 67 /** Signals change of active status. */ 54 68 fibril_condvar_t avail; 55 volatile bool active; 56 void (*destroy_hook)(struct endpoint *); 69 /** Optional device specific data. */ 57 70 struct { 71 /** Device specific data. */ 58 72 void *data; 73 /** Callback to get the value of toggle bit. */ 59 74 int (*toggle_get)(void *); 75 /** Callback to set the value of toggle bit. */ 60 76 void (*toggle_set)(void *, int); 61 77 } hc_data; 62 78 } endpoint_t; 63 79 64 endpoint_t * endpoint_ get(usb_address_t address, usb_endpoint_t endpoint,80 endpoint_t * endpoint_create(usb_address_t address, usb_endpoint_t endpoint, 65 81 usb_direction_t direction, usb_transfer_type_t type, usb_speed_t speed, 66 size_t max_packet_size); 67 82 size_t max_packet_size, size_t bw); 68 83 void endpoint_destroy(endpoint_t *instance); 69 84 70 85 void endpoint_set_hc_data(endpoint_t *instance, 71 void *data, void (*destroy_hook)(endpoint_t *), 72 int (*toggle_get)(void *), void (*toggle_set)(void *, int)); 73 86 void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int)); 74 87 void endpoint_clear_hc_data(endpoint_t *instance); 75 88 76 89 void endpoint_use(endpoint_t *instance); 77 78 90 void endpoint_release(endpoint_t *instance); 79 91 80 92 int endpoint_toggle_get(endpoint_t *instance); 81 82 93 void endpoint_toggle_set(endpoint_t *instance, int toggle); 83 94 84 void endpoint_toggle_reset_filtered(endpoint_t *instance, usb_target_t target); 95 /** list_get_instance wrapper. 96 * @param item Pointer to link member. 97 * @return Pointer to enpoint_t structure. 98 */ 99 static inline endpoint_t * endpoint_get_instance(link_t *item) 100 { 101 return list_get_instance(item, endpoint_t, link); 102 } 85 103 #endif 86 104 /** -
uspace/lib/usbhost/include/usb/host/hcd.h
r4c3ad56 r20a3465 37 37 38 38 #include <assert.h> 39 #include <usbhc_iface.h> 40 39 41 #include <usb/host/usb_device_manager.h> 40 42 #include <usb/host/usb_endpoint_manager.h> 41 43 #include <usb/host/usb_transfer_batch.h> 42 #include <usbhc_iface.h>43 44 44 45 typedef struct hcd hcd_t; 45 46 47 /** Generic host controller driver structure. */ 46 48 struct hcd { 49 /** Device manager storing handles and addresses. */ 47 50 usb_device_manager_t dev_manager; 51 /** Endpoint manager. */ 48 52 usb_endpoint_manager_t ep_manager; 53 54 /** Device specific driver data. */ 49 55 void *private_data; 50 56 /** Transfer scheduling, implement in device driver. */ 51 57 int (*schedule)(hcd_t *, usb_transfer_batch_t *); 58 /** Hook called upon registering new endpoint. */ 52 59 int (*ep_add_hook)(hcd_t *, endpoint_t *); 60 /** Hook called upon removing of an endpoint. */ 61 void (*ep_remove_hook)(hcd_t *, endpoint_t *); 53 62 }; 54 63 /*----------------------------------------------------------------------------*/ 55 static inline int hcd_init(hcd_t *hcd, size_t bandwidth, 64 /** Initialize hcd_t structure. 65 * Initializes device and endpoint managers. Sets data nd hook pointer to NULL. 66 * @param hcd hcd_t structure to initialize, non-null. 67 * @param bandwidth Available bandwidth, passed to endpoint manager. 68 * @param bw_count Bandwidth compute function, passed to endpoint manager. 69 */ 70 static inline void hcd_init(hcd_t *hcd, size_t bandwidth, 56 71 size_t (*bw_count)(usb_speed_t, usb_transfer_type_t, size_t, size_t)) 57 72 { 58 73 assert(hcd); 59 74 usb_device_manager_init(&hcd->dev_manager); 60 return usb_endpoint_manager_init(&hcd->ep_manager, bandwidth, bw_count); 75 usb_endpoint_manager_init(&hcd->ep_manager, bandwidth, bw_count); 76 hcd->private_data = NULL; 77 hcd->schedule = NULL; 78 hcd->ep_add_hook = NULL; 79 hcd->ep_remove_hook = NULL; 61 80 } 62 81 /*----------------------------------------------------------------------------*/ 63 static inline void hcd_destroy(hcd_t *hcd) 64 { 65 usb_endpoint_manager_destroy(&hcd->ep_manager); 66 } 67 /*----------------------------------------------------------------------------*/68 static inline void reset_ep_if_need( 69 hcd_t *hcd, usb_target_t target, const char* setup_data)82 /** Check registered endpoints and reset toggle bit if necessary. 83 * @param hcd hcd_t structure, non-null. 84 * @param target Control communication target. 85 * @param setup_data Setup packet of the control communication. 86 */ 87 static inline void reset_ep_if_need(hcd_t *hcd, usb_target_t target, 88 const char setup_data[8]) 70 89 { 71 90 assert(hcd); 72 usb_endpoint_manager_reset_ if_need(91 usb_endpoint_manager_reset_eps_if_need( 73 92 &hcd->ep_manager, target, (const uint8_t *)setup_data); 74 93 } 75 94 /*----------------------------------------------------------------------------*/ 76 static inline hcd_t * fun_to_hcd(ddf_fun_t *fun) 95 /** Data retrieve wrapper. 96 * @param fun ddf function, non-null. 97 * @return pointer cast to hcd_t*. 98 */ 99 static inline hcd_t * fun_to_hcd(const ddf_fun_t *fun) 77 100 { 78 101 assert(fun); -
uspace/lib/usbhost/include/usb/host/usb_device_manager.h
r4c3ad56 r20a3465 49 49 #define USB_ADDRESS_COUNT (USB11_ADDRESS_MAX + 1) 50 50 51 /** Information about attached USB device. */52 struct usb_device_info {53 usb_speed_t speed;54 bool occupied;55 devman_handle_t handle;56 };57 58 51 /** Host controller device manager. 59 * You shall not access members directly but only using functions below.52 * You shall not access members directly. 60 53 */ 61 54 typedef struct { 62 struct usb_device_info devices[USB_ADDRESS_COUNT]; 55 /** Information about attached USB devices. */ 56 struct { 57 usb_speed_t speed; /**< Device speed */ 58 bool occupied; /**< The address is in use. */ 59 devman_handle_t handle; /**< Devman handle of the device. */ 60 } devices[USB_ADDRESS_COUNT]; 63 61 fibril_mutex_t guard; 62 /** The last reserved address */ 64 63 usb_address_t last_address; 65 64 } usb_device_manager_t; … … 70 69 usb_device_manager_t *instance, usb_speed_t speed); 71 70 72 voidusb_device_manager_bind(usb_device_manager_t *instance,71 int usb_device_manager_bind(usb_device_manager_t *instance, 73 72 usb_address_t address, devman_handle_t handle); 74 73 75 voidusb_device_manager_release(usb_device_manager_t *instance,74 int usb_device_manager_release(usb_device_manager_t *instance, 76 75 usb_address_t address); 77 76 78 usb_address_t usb_device_manager_find (usb_device_manager_t *instance,77 usb_address_t usb_device_manager_find_address(usb_device_manager_t *instance, 79 78 devman_handle_t handle); 80 79 81 bool usb_device_manager_find_by_address(usb_device_manager_t *instance, 82 usb_address_t address, devman_handle_t *handle); 83 84 usb_speed_t usb_device_manager_get_speed(usb_device_manager_t *instance, 85 usb_address_t address); 80 int usb_device_manager_get_info_by_address(usb_device_manager_t *instance, 81 usb_address_t address, devman_handle_t *handle, usb_speed_t *speed); 86 82 #endif 87 83 /** -
uspace/lib/usbhost/include/usb/host/usb_endpoint_manager.h
r4c3ad56 r20a3465 40 40 #define LIBUSBHOST_HOST_USB_ENDPOINT_MANAGER_H 41 41 42 #include <stdlib.h> 43 #include <adt/hash_table.h> 42 #include <adt/list.h> 44 43 #include <fibril_synch.h> 45 44 #include <usb/usb.h> 45 46 46 #include <usb/host/endpoint.h> 47 47 48 #define BANDWIDTH_TOTAL_USB11 12000000 48 /** Bytes per second in FULL SPEED */ 49 #define BANDWIDTH_TOTAL_USB11 (12000000 / 8) 50 /** 90% of total bandwidth is available for periodic transfers */ 49 51 #define BANDWIDTH_AVAILABLE_USB11 ((BANDWIDTH_TOTAL_USB11 / 10) * 9) 52 /** 16 addresses per list */ 53 #define ENDPOINT_LIST_COUNT 8 50 54 55 /** Endpoint management structure */ 51 56 typedef struct usb_endpoint_manager { 52 hash_table_t ep_table; 57 /** Store endpoint_t instances */ 58 list_t endpoint_lists[ENDPOINT_LIST_COUNT]; 59 /** Prevents races accessing lists */ 53 60 fibril_mutex_t guard; 61 /** Size of the bandwidth pool */ 54 62 size_t free_bw; 63 /** Use this function to count bw required by EP */ 55 64 size_t (*bw_count)(usb_speed_t, usb_transfer_type_t, size_t, size_t); 56 65 } usb_endpoint_manager_t; … … 63 72 size_t (*bw_count)(usb_speed_t, usb_transfer_type_t, size_t, size_t)); 64 73 65 void usb_endpoint_manager_destroy(usb_endpoint_manager_t *instance); 74 void usb_endpoint_manager_reset_eps_if_need(usb_endpoint_manager_t *instance, 75 usb_target_t target, const uint8_t data[8]); 66 76 67 int usb_endpoint_manager_register_ep(usb_endpoint_manager_t *instance, 68 endpoint_t *ep, size_t data_size); 69 70 int usb_endpoint_manager_unregister_ep(usb_endpoint_manager_t *instance, 77 int usb_endpoint_manager_register_ep( 78 usb_endpoint_manager_t *instance, endpoint_t *ep, size_t data_size); 79 int usb_endpoint_manager_unregister_ep( 80 usb_endpoint_manager_t *instance, endpoint_t *ep); 81 endpoint_t * usb_endpoint_manager_find_ep(usb_endpoint_manager_t *instance, 71 82 usb_address_t address, usb_endpoint_t ep, usb_direction_t direction); 72 83 73 endpoint_t * usb_endpoint_manager_get_ep(usb_endpoint_manager_t *instance, 74 usb_address_t address, usb_endpoint_t ep, usb_direction_t direction, 75 size_t *bw); 76 77 void usb_endpoint_manager_reset_if_need( 78 usb_endpoint_manager_t *instance, usb_target_t target, const uint8_t *data); 79 80 /** Wrapper combining allocation and insertion */ 81 static inline int usb_endpoint_manager_add_ep(usb_endpoint_manager_t *instance, 84 int usb_endpoint_manager_add_ep(usb_endpoint_manager_t *instance, 82 85 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction, 83 86 usb_transfer_type_t type, usb_speed_t speed, size_t max_packet_size, 84 size_t data_size) 85 { 86 endpoint_t *ep = endpoint_get( 87 address, endpoint, direction, type, speed, max_packet_size); 88 if (!ep) 89 return ENOMEM; 87 size_t data_size, int (*callback)(endpoint_t *, void *), void *arg); 90 88 91 const int ret = 92 usb_endpoint_manager_register_ep(instance, ep, data_size); 93 if (ret != EOK) { 94 endpoint_destroy(ep); 95 } 96 return ret; 97 } 89 int usb_endpoint_manager_remove_ep(usb_endpoint_manager_t *instance, 90 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction, 91 void (*callback)(endpoint_t *, void *), void *arg); 98 92 #endif 99 93 /** 100 94 * @} 101 95 */ 102 -
uspace/lib/usbhost/include/usb/host/usb_transfer_batch.h
r4c3ad56 r20a3465 43 43 #define USB_SETUP_PACKET_SIZE 8 44 44 45 typedef struct usb_transfer_batch usb_transfer_batch_t;46 45 /** Structure stores additional data needed for communication with EP */ 47 struct usb_transfer_batch {46 typedef struct usb_transfer_batch { 48 47 /** Endpoint used for communication */ 49 48 endpoint_t *ep; … … 77 76 /** Callback to properly remove driver data during destruction */ 78 77 void (*private_data_dtor)(void *p_data); 79 } ;78 } usb_transfer_batch_t; 80 79 81 80 /** Printf formatting string for dumping usb_transfer_batch_t. */ … … 93 92 94 93 95 usb_transfer_batch_t * usb_transfer_batch_ get(94 usb_transfer_batch_t * usb_transfer_batch_create( 96 95 endpoint_t *ep, 97 96 char *buffer, … … 105 104 void (*private_data_dtor)(void *p_data) 106 105 ); 106 void usb_transfer_batch_destroy(const usb_transfer_batch_t *instance); 107 107 108 void usb_transfer_batch_finish( usb_transfer_batch_t *instance,108 void usb_transfer_batch_finish(const usb_transfer_batch_t *instance, 109 109 const void* data, size_t size); 110 void usb_transfer_batch_call_in(usb_transfer_batch_t *instance);111 void usb_transfer_batch_call_out(usb_transfer_batch_t *instance);112 void usb_transfer_batch_dispose(usb_transfer_batch_t *instance);113 114 /** Helper function, calls callback and correctly destroys batch structure.115 *116 * @param[in] instance Batch structure to use.117 */118 static inline void usb_transfer_batch_call_in_and_dispose(119 usb_transfer_batch_t *instance)120 {121 assert(instance);122 usb_transfer_batch_call_in(instance);123 usb_transfer_batch_dispose(instance);124 }125 110 /*----------------------------------------------------------------------------*/ 126 /** Helper function calls callback and correctly destroys batch structure. 127 * 128 * @param[in] instance Batch structure to use. 129 */ 130 static inline void usb_transfer_batch_call_out_and_dispose( 131 usb_transfer_batch_t *instance) 132 { 133 assert(instance); 134 usb_transfer_batch_call_out(instance); 135 usb_transfer_batch_dispose(instance); 136 } 137 /*----------------------------------------------------------------------------*/ 138 /** Helper function, sets error value and finishes transfer. 111 /** Override error value and finishes transfer. 139 112 * 140 113 * @param[in] instance Batch structure to use. … … 151 124 } 152 125 /*----------------------------------------------------------------------------*/ 153 /** Helper function, determines batch direction absed on the present callbacks154 * @param[in] instance Batch structure to use .126 /** Determine batch direction based on the callbacks present 127 * @param[in] instance Batch structure to use, non-null. 155 128 * @return USB_DIRECTION_IN, or USB_DIRECTION_OUT. 156 129 */ -
uspace/lib/usbhost/src/endpoint.c
r4c3ad56 r20a3465 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 29 /** @addtogroup drvusbuhcihc 28 /** @addtogroup libusbhost 30 29 * @{ 31 30 */ … … 39 38 #include <usb/host/endpoint.h> 40 39 41 endpoint_t * endpoint_get(usb_address_t address, usb_endpoint_t endpoint, 40 /** Allocate ad initialize endpoint_t structure. 41 * @param address USB address. 42 * @param endpoint USB endpoint number. 43 * @param direction Communication direction. 44 * @param type USB transfer type. 45 * @param speed Communication speed. 46 * @param max_packet_size Maximum size of data packets. 47 * @param bw Required bandwidth. 48 * @return Pointer to initialized endpoint_t structure, NULL on failure. 49 */ 50 endpoint_t * endpoint_create(usb_address_t address, usb_endpoint_t endpoint, 42 51 usb_direction_t direction, usb_transfer_type_t type, usb_speed_t speed, 43 size_t max_packet_size )52 size_t max_packet_size, size_t bw) 44 53 { 45 54 endpoint_t *instance = malloc(sizeof(endpoint_t)); … … 51 60 instance->speed = speed; 52 61 instance->max_packet_size = max_packet_size; 62 instance->bandwidth = bw; 53 63 instance->toggle = 0; 54 64 instance->active = false; 55 instance->destroy_hook = NULL;56 65 instance->hc_data.data = NULL; 57 66 instance->hc_data.toggle_get = NULL; 58 67 instance->hc_data.toggle_set = NULL; 68 link_initialize(&instance->link); 59 69 fibril_mutex_initialize(&instance->guard); 60 70 fibril_condvar_initialize(&instance->avail); 61 endpoint_clear_hc_data(instance);62 71 } 63 72 return instance; 64 73 } 65 74 /*----------------------------------------------------------------------------*/ 75 /** Properly dispose of endpoint_t structure. 76 * @param instance endpoint_t structure. 77 */ 66 78 void endpoint_destroy(endpoint_t *instance) 67 79 { 68 80 assert(instance); 81 //TODO: Do something about waiting fibrils. 69 82 assert(!instance->active); 70 if (instance->hc_data.data) { 71 assert(instance->destroy_hook); 72 instance->destroy_hook(instance); 73 } 83 assert(instance->hc_data.data == NULL); 74 84 free(instance); 75 85 } 76 86 /*----------------------------------------------------------------------------*/ 87 /** Set device specific data and hooks. 88 * @param instance endpoint_t structure. 89 * @param data device specific data. 90 * @param toggle_get Hook to call when retrieving value of toggle bit. 91 * @param toggle_set Hook to call when setting the value of toggle bit. 92 */ 77 93 void endpoint_set_hc_data(endpoint_t *instance, 78 void *data, void (*destroy_hook)(endpoint_t *), 79 int (*toggle_get)(void *), void (*toggle_set)(void *, int)) 94 void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int)) 80 95 { 81 96 assert(instance); 82 instance->destroy_hook = destroy_hook;97 fibril_mutex_lock(&instance->guard); 83 98 instance->hc_data.data = data; 84 99 instance->hc_data.toggle_get = toggle_get; 85 100 instance->hc_data.toggle_set = toggle_set; 101 fibril_mutex_unlock(&instance->guard); 86 102 } 87 103 /*----------------------------------------------------------------------------*/ 104 /** Clear device specific data and hooks. 105 * @param instance endpoint_t structure. 106 * @note This function does not free memory pointed to by data pointer. 107 */ 88 108 void endpoint_clear_hc_data(endpoint_t *instance) 89 109 { 90 110 assert(instance); 91 instance->destroy_hook = NULL;111 fibril_mutex_lock(&instance->guard); 92 112 instance->hc_data.data = NULL; 93 113 instance->hc_data.toggle_get = NULL; 94 114 instance->hc_data.toggle_set = NULL; 115 fibril_mutex_unlock(&instance->guard); 95 116 } 96 117 /*----------------------------------------------------------------------------*/ 118 /** Mark the endpoint as active and block access for further fibrils. 119 * @param instance endpoint_t structure. 120 */ 97 121 void endpoint_use(endpoint_t *instance) 98 122 { … … 105 129 } 106 130 /*----------------------------------------------------------------------------*/ 131 /** Mark the endpoint as inactive and allow access for further fibrils. 132 * @param instance endpoint_t structure. 133 */ 107 134 void endpoint_release(endpoint_t *instance) 108 135 { … … 114 141 } 115 142 /*----------------------------------------------------------------------------*/ 143 /** Get the value of toggle bit. 144 * @param instance endpoint_t structure. 145 * @note Will use provided hook. 146 */ 116 147 int endpoint_toggle_get(endpoint_t *instance) 117 148 { 118 149 assert(instance); 150 fibril_mutex_lock(&instance->guard); 119 151 if (instance->hc_data.toggle_get) 120 152 instance->toggle = 121 153 instance->hc_data.toggle_get(instance->hc_data.data); 122 return (int)instance->toggle; 154 const int ret = instance->toggle; 155 fibril_mutex_unlock(&instance->guard); 156 return ret; 123 157 } 124 158 /*----------------------------------------------------------------------------*/ 159 /** Set the value of toggle bit. 160 * @param instance endpoint_t structure. 161 * @note Will use provided hook. 162 */ 125 163 void endpoint_toggle_set(endpoint_t *instance, int toggle) 126 164 { 127 165 assert(instance); 128 166 assert(toggle == 0 || toggle == 1); 167 fibril_mutex_lock(&instance->guard); 168 instance->toggle = toggle; 129 169 if (instance->hc_data.toggle_set) 130 170 instance->hc_data.toggle_set(instance->hc_data.data, toggle); 131 instance->toggle = toggle; 132 } 133 /*----------------------------------------------------------------------------*/ 134 void endpoint_toggle_reset_filtered(endpoint_t *instance, usb_target_t target) 135 { 136 assert(instance); 137 if (instance->address == target.address && 138 (instance->endpoint == target.endpoint || target.endpoint == 0)) 139 endpoint_toggle_set(instance, 0); 171 fibril_mutex_unlock(&instance->guard); 140 172 } 141 173 /** -
uspace/lib/usbhost/src/iface.c
r4c3ad56 r20a3465 49 49 assert(hcd); 50 50 51 int ret; 52 53 size_t res_bw; 54 endpoint_t *ep = usb_endpoint_manager_get_ep(&hcd->ep_manager, 55 target.address, target.endpoint, direction, &res_bw); 51 endpoint_t *ep = usb_endpoint_manager_find_ep(&hcd->ep_manager, 52 target.address, target.endpoint, direction); 56 53 if (ep == NULL) { 57 54 usb_log_error("Endpoint(%d:%d) not registered for %s.\n", … … 65 62 const size_t bw = bandwidth_count_usb11( 66 63 ep->speed, ep->transfer_type, size, ep->max_packet_size); 67 if (res_bw < bw) { 64 /* Check if we have enough bandwidth reserved */ 65 if (ep->bandwidth < bw) { 68 66 usb_log_error("Endpoint(%d:%d) %s needs %zu bw " 69 67 "but only %zu is reserved.\n", 70 target.address, target.endpoint, name, bw, res_bw);68 ep->address, ep->endpoint, name, bw, ep->bandwidth); 71 69 return ENOSPC; 72 70 } … … 78 76 /* No private data and no private data dtor */ 79 77 usb_transfer_batch_t *batch = 80 usb_transfer_batch_ get(ep, data, size, setup_data,78 usb_transfer_batch_create(ep, data, size, setup_data, 81 79 in, out, arg, fun, NULL, NULL); 82 80 if (!batch) { … … 84 82 } 85 83 86 ret = hcd->schedule(hcd, batch);84 const int ret = hcd->schedule(hcd, batch); 87 85 if (ret != EOK) 88 usb_transfer_batch_d ispose(batch);86 usb_transfer_batch_destroy(batch); 89 87 90 88 return ret; … … 130 128 131 129 usb_log_debug("Address bind %d-%" PRIun ".\n", address, handle); 132 usb_device_manager_bind(&hcd->dev_manager, address, handle); 133 return EOK; 130 return usb_device_manager_bind(&hcd->dev_manager, address, handle); 134 131 } 135 132 /*----------------------------------------------------------------------------*/ … … 147 144 hcd_t *hcd = fun_to_hcd(fun); 148 145 assert(hcd); 149 const bool found = 150 usb_device_manager_find_by_address(&hcd->dev_manager, address, handle); 151 return found ? EOK : ENOENT; 146 return usb_device_manager_get_info_by_address( 147 &hcd->dev_manager, address, handle, NULL); 152 148 } 153 149 /*----------------------------------------------------------------------------*/ … … 166 162 usb_device_manager_release(&hcd->dev_manager, address); 167 163 return EOK; 164 } 165 /*----------------------------------------------------------------------------*/ 166 static int register_helper(endpoint_t *ep, void *arg) 167 { 168 hcd_t *hcd = arg; 169 assert(ep); 170 assert(hcd); 171 if (hcd->ep_add_hook) 172 return hcd->ep_add_hook(hcd, ep); 173 return EOK; 174 } 175 /*----------------------------------------------------------------------------*/ 176 static void unregister_helper(endpoint_t *ep, void *arg) 177 { 178 hcd_t *hcd = arg; 179 assert(ep); 180 assert(hcd); 181 if (hcd->ep_remove_hook) 182 hcd->ep_remove_hook(hcd, ep); 168 183 } 169 184 /*----------------------------------------------------------------------------*/ … … 180 195 /* Default address is not bound or registered, 181 196 * thus it does not provide speed info. */ 182 const usb_speed_t speed = (address == 0) ? ep_speed : 183 usb_device_manager_get_speed(&hcd->dev_manager, address); 197 usb_speed_t speed = ep_speed; 198 /* NOTE The function will return EINVAL and won't 199 * touch speed variable for default address */ 200 usb_device_manager_get_info_by_address( 201 &hcd->dev_manager, address, NULL, &speed); 184 202 185 203 usb_log_debug("Register endpoint %d:%d %s-%s %s %zuB %ums.\n", … … 188 206 max_packet_size, interval); 189 207 190 endpoint_t *ep = endpoint_get( 191 address, endpoint, direction, transfer_type, speed, max_packet_size); 192 if (!ep) 193 return ENOMEM; 194 int ret = EOK; 195 196 if (hcd->ep_add_hook) { 197 ret = hcd->ep_add_hook(hcd, ep); 198 } 199 if (ret != EOK) { 200 endpoint_destroy(ep); 201 return ret; 202 } 203 204 ret = usb_endpoint_manager_register_ep(&hcd->ep_manager, ep, size); 205 if (ret != EOK) { 206 endpoint_destroy(ep); 207 } 208 return ret; 208 return usb_endpoint_manager_add_ep(&hcd->ep_manager, address, endpoint, 209 direction, transfer_type, speed, max_packet_size, size, 210 register_helper, hcd); 209 211 } 210 212 /*----------------------------------------------------------------------------*/ … … 218 220 usb_log_debug("Unregister endpoint %d:%d %s.\n", 219 221 address, endpoint, usb_str_direction(direction)); 220 return usb_endpoint_manager_ unregister_ep(&hcd->ep_manager, address,221 endpoint, direction );222 return usb_endpoint_manager_remove_ep(&hcd->ep_manager, address, 223 endpoint, direction, unregister_helper, hcd); 222 224 } 223 225 /*----------------------------------------------------------------------------*/ -
uspace/lib/usbhost/src/usb_device_manager.c
r4c3ad56 r20a3465 38 38 #include <usb/host/usb_device_manager.h> 39 39 40 /*----------------------------------------------------------------------------*/41 40 /** Initialize device manager structure. 42 41 * … … 48 47 { 49 48 assert(instance); 50 unsigned i = 0; 51 for (; i < USB_ADDRESS_COUNT; ++i) { 49 for (unsigned i = 0; i < USB_ADDRESS_COUNT; ++i) { 52 50 instance->devices[i].occupied = false; 53 51 instance->devices[i].handle = 0; … … 77 75 ++new_address; 78 76 if (new_address > USB11_ADDRESS_MAX) 79 new_address = 1; 77 new_address = 1; // NOTE it should be safe to put 0 here 78 // TODO Use mod 80 79 if (new_address == instance->last_address) { 81 80 fibril_mutex_unlock(&instance->guard); … … 86 85 assert(new_address != USB_ADDRESS_DEFAULT); 87 86 assert(instance->devices[new_address].occupied == false); 87 assert(instance->devices[new_address].handle == 0); 88 88 89 89 instance->devices[new_address].occupied = true; … … 100 100 * @param[in] address Device address 101 101 * @param[in] handle Devman handle of the device. 102 */ 103 void usb_device_manager_bind(usb_device_manager_t *instance, 102 * @return Error code. 103 */ 104 int usb_device_manager_bind(usb_device_manager_t *instance, 104 105 usb_address_t address, devman_handle_t handle) 105 106 { 106 assert(instance); 107 fibril_mutex_lock(&instance->guard); 108 109 assert(address > 0); 110 assert(address <= USB11_ADDRESS_MAX); 111 assert(instance->devices[address].occupied); 112 107 if ((address <= 0) || (address >= USB_ADDRESS_COUNT)) { 108 return EINVAL; 109 } 110 assert(instance); 111 112 fibril_mutex_lock(&instance->guard); 113 /* Not reserved */ 114 if (!instance->devices[address].occupied) { 115 fibril_mutex_unlock(&instance->guard); 116 return ENOENT; 117 } 118 /* Already bound */ 119 if (instance->devices[address].handle != 0) { 120 fibril_mutex_unlock(&instance->guard); 121 return EEXISTS; 122 } 113 123 instance->devices[address].handle = handle; 114 124 fibril_mutex_unlock(&instance->guard); 125 return EOK; 115 126 } 116 127 /*----------------------------------------------------------------------------*/ … … 119 130 * @param[in] instance Device manager structure to use. 120 131 * @param[in] address Device address 121 */ 122 void usb_device_manager_release( 132 * @return Error code. 133 */ 134 int usb_device_manager_release( 123 135 usb_device_manager_t *instance, usb_address_t address) 124 136 { 125 assert(instance); 126 assert(address > 0); 127 assert(address <= USB11_ADDRESS_MAX); 128 129 fibril_mutex_lock(&instance->guard); 130 assert(instance->devices[address].occupied); 137 if ((address <= 0) || (address >= USB_ADDRESS_COUNT)) { 138 return EINVAL; 139 } 140 assert(instance); 141 142 fibril_mutex_lock(&instance->guard); 143 if (!instance->devices[address].occupied) { 144 fibril_mutex_unlock(&instance->guard); 145 return ENOENT; 146 } 131 147 132 148 instance->devices[address].occupied = false; 133 fibril_mutex_unlock(&instance->guard); 149 instance->devices[address].handle = 0; 150 fibril_mutex_unlock(&instance->guard); 151 return EOK; 134 152 } 135 153 /*----------------------------------------------------------------------------*/ … … 140 158 * @return USB Address, or error code. 141 159 */ 142 usb_address_t usb_device_manager_find (160 usb_address_t usb_device_manager_find_address( 143 161 usb_device_manager_t *instance, devman_handle_t handle) 144 162 { 145 163 assert(instance); 146 164 fibril_mutex_lock(&instance->guard); 147 usb_address_t address = 1;148 while (address <= USB11_ADDRESS_MAX){165 for (usb_address_t address = 1; address <= USB11_ADDRESS_MAX; ++address) 166 { 149 167 if (instance->devices[address].handle == handle) { 150 168 assert(instance->devices[address].occupied); … … 152 170 return address; 153 171 } 154 ++address;155 172 } 156 173 fibril_mutex_unlock(&instance->guard); 157 174 return ENOENT; 158 175 } 159 160 /** Find devman handle a ssigned to USB address.161 * Intentionally refuse to find handle ofdefault address.176 /*----------------------------------------------------------------------------*/ 177 /** Find devman handle and speed assigned to USB address. 178 * Intentionally refuse to work on default address. 162 179 * 163 180 * @param[in] instance Device manager structure to use. 164 181 * @param[in] address Address the caller wants to find. 165 182 * @param[out] handle Where to store found handle. 166 * @ return Whether such address is currently occupied.167 * /168 bool usb_device_manager_find_by_address(usb_device_manager_t *instance, 169 usb_address_t address, devman_handle_t *handle) 170 { 171 assert(instance); 172 fibril_mutex_lock(&instance->guard);183 * @param[out] speed Assigned speed. 184 * @return Error code. 185 */ 186 int usb_device_manager_get_info_by_address(usb_device_manager_t *instance, 187 usb_address_t address, devman_handle_t *handle, usb_speed_t *speed) 188 { 189 assert(instance); 173 190 if ((address <= 0) || (address >= USB_ADDRESS_COUNT)) { 174 fibril_mutex_unlock(&instance->guard); 175 return false; 176 } 191 return EINVAL; 192 } 193 194 fibril_mutex_lock(&instance->guard); 177 195 if (!instance->devices[address].occupied) { 178 196 fibril_mutex_unlock(&instance->guard); 179 return false;197 return ENOENT; 180 198 } 181 199 … … 183 201 *handle = instance->devices[address].handle; 184 202 } 185 186 fibril_mutex_unlock(&instance->guard); 187 return true; 188 } 189 190 /*----------------------------------------------------------------------------*/ 191 /** Get speed associated with the address 192 * 193 * @param[in] instance Device manager structure to use. 194 * @param[in] address Address of the device. 195 * @return USB speed. 196 */ 197 usb_speed_t usb_device_manager_get_speed( 198 usb_device_manager_t *instance, usb_address_t address) 199 { 200 assert(instance); 201 assert(address >= 0); 202 assert(address <= USB11_ADDRESS_MAX); 203 204 return instance->devices[address].speed; 203 if (speed != NULL) { 204 *speed = instance->devices[address].speed; 205 } 206 207 fibril_mutex_unlock(&instance->guard); 208 return EOK; 205 209 } 206 210 /** -
uspace/lib/usbhost/src/usb_endpoint_manager.c
r4c3ad56 r20a3465 34 34 #include <usb/host/usb_endpoint_manager.h> 35 35 36 #define BUCKET_COUNT 7 37 38 #define MAX_KEYS (3) 39 typedef struct { 40 link_t link; 41 size_t bw; 42 endpoint_t *ep; 43 } node_t; 44 /*----------------------------------------------------------------------------*/ 45 static hash_index_t node_hash(unsigned long key[]) 46 { 47 /* USB endpoints use 4 bits, thus ((key[0] << 4) | key[1]) 48 * produces unique value for every address.endpoint pair */ 49 return ((key[0] << 4) | key[1]) % BUCKET_COUNT; 50 } 51 /*----------------------------------------------------------------------------*/ 52 static int node_compare(unsigned long key[], hash_count_t keys, link_t *item) 53 { 54 assert(item); 55 node_t *node = hash_table_get_instance(item, node_t, link); 56 assert(node); 57 assert(node->ep); 58 bool match = true; 59 switch (keys) { 60 case 3: 61 match = match && 62 ((key[2] == node->ep->direction) 63 || (node->ep->direction == USB_DIRECTION_BOTH)); 64 case 2: 65 match = match && (key[1] == (unsigned long)node->ep->endpoint); 66 case 1: 67 match = match && (key[0] == (unsigned long)node->ep->address); 68 break; 69 default: 70 match = false; 71 } 72 return match; 73 } 74 /*----------------------------------------------------------------------------*/ 75 static void node_remove(link_t *item) 76 { 77 assert(item); 78 node_t *node = hash_table_get_instance(item, node_t, link); 79 endpoint_destroy(node->ep); 80 free(node); 81 } 82 /*----------------------------------------------------------------------------*/ 83 static void node_toggle_reset_filtered(link_t *item, void *arg) 84 { 85 assert(item); 86 node_t *node = hash_table_get_instance(item, node_t, link); 87 usb_target_t *target = arg; 88 endpoint_toggle_reset_filtered(node->ep, *target); 89 } 90 /*----------------------------------------------------------------------------*/ 91 static hash_table_operations_t op = { 92 .hash = node_hash, 93 .compare = node_compare, 94 .remove_callback = node_remove, 95 }; 96 /*----------------------------------------------------------------------------*/ 36 /** Endpoint compare helper function. 37 * 38 * USB_DIRECTION_BOTH matches both IN and OUT. 39 * @param ep Endpoint to compare, non-null. 40 * @param address Tested address. 41 * @param endpoint Tested endpoint number. 42 * @param direction Tested direction. 43 * @return True if ep can be used to communicate with given device, 44 * false otherwise. 45 */ 46 static inline bool ep_match(const endpoint_t *ep, 47 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction) 48 { 49 assert(ep); 50 return 51 ((direction == ep->direction) 52 || (ep->direction == USB_DIRECTION_BOTH) 53 || (direction == USB_DIRECTION_BOTH)) 54 && (endpoint == ep->endpoint) 55 && (address == ep->address); 56 } 57 /*----------------------------------------------------------------------------*/ 58 /** Get list that holds endpints for given address. 59 * @param instance usb_endpoint_manager structure, non-null. 60 * @param addr USB address, must be >= 0. 61 * @return Pointer to the appropriate list. 62 */ 63 static list_t * get_list(usb_endpoint_manager_t *instance, usb_address_t addr) 64 { 65 assert(instance); 66 assert(addr >= 0); 67 return &instance->endpoint_lists[addr % ENDPOINT_LIST_COUNT]; 68 } 69 /*----------------------------------------------------------------------------*/ 70 /** Internal search function, works on locked structure. 71 * @param instance usb_endpoint_manager structure, non-null. 72 * @param address USB address, must be valid. 73 * @param endpoint USB endpoint number. 74 * @param direction Communication direction. 75 * @return Pointer to endpoint_t structure representing given communication 76 * target, NULL if there is no such endpoint registered. 77 */ 78 static endpoint_t * find_locked(usb_endpoint_manager_t *instance, 79 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction) 80 { 81 assert(instance); 82 assert(fibril_mutex_is_locked(&instance->guard)); 83 if (address < 0) 84 return NULL; 85 list_foreach(*get_list(instance, address), iterator) { 86 endpoint_t *ep = endpoint_get_instance(iterator); 87 if (ep_match(ep, address, endpoint, direction)) 88 return ep; 89 } 90 return NULL; 91 } 92 /*----------------------------------------------------------------------------*/ 93 /** Calculate bandwidth that needs to be reserved for communication with EP. 94 * Calculation follows USB 1.1 specification. 95 * @param speed Device's speed. 96 * @param type Type of the transfer. 97 * @param size Number of byte to transfer. 98 * @param max_packet_size Maximum bytes in one packet. 99 */ 97 100 size_t bandwidth_count_usb11(usb_speed_t speed, usb_transfer_type_t type, 98 101 size_t size, size_t max_packet_size) … … 106 109 const unsigned packet_count = 107 110 (size + max_packet_size - 1) / max_packet_size; 108 /* TODO: It may be that ISO and INT transfers use only one data packet 109 * per transaction, but I did not find text in UB spec that confirms 110 * this */ 111 /* TODO: It may be that ISO and INT transfers use only one packet per 112 * transaction, but I did not find text in USB spec to confirm this */ 111 113 /* NOTE: All data packets will be considered to be max_packet_size */ 112 114 switch (speed) … … 137 139 } 138 140 /*----------------------------------------------------------------------------*/ 141 /** Initialize to default state. 142 * You need to provide valid bw_count function if you plan to use 143 * add_endpoint/remove_endpoint pair. 144 * 145 * @param instance usb_endpoint_manager structure, non-null. 146 * @param available_bandwidth Size of the bandwidth pool. 147 * @param bw_count function to use to calculate endpoint bw requirements. 148 * @return Error code. 149 */ 139 150 int usb_endpoint_manager_init(usb_endpoint_manager_t *instance, 140 151 size_t available_bandwidth, … … 145 156 instance->free_bw = available_bandwidth; 146 157 instance->bw_count = bw_count; 147 const bool ht = 148 hash_table_create(&instance->ep_table, BUCKET_COUNT, MAX_KEYS, &op); 149 return ht ? EOK : ENOMEM; 150 } 151 /*----------------------------------------------------------------------------*/ 152 void usb_endpoint_manager_destroy(usb_endpoint_manager_t *instance) 153 { 154 hash_table_destroy(&instance->ep_table); 155 } 156 /*----------------------------------------------------------------------------*/ 157 int usb_endpoint_manager_register_ep(usb_endpoint_manager_t *instance, 158 endpoint_t *ep, size_t data_size) 159 { 160 assert(instance); 161 assert(instance->bw_count); 162 assert(ep); 163 const size_t bw = instance->bw_count(ep->speed, ep->transfer_type, 164 data_size, ep->max_packet_size); 165 166 fibril_mutex_lock(&instance->guard); 167 168 if (bw > instance->free_bw) { 169 fibril_mutex_unlock(&instance->guard); 170 return ENOSPC; 171 } 172 173 unsigned long key[MAX_KEYS] = 174 {ep->address, ep->endpoint, ep->direction}; 175 176 const link_t *item = 177 hash_table_find(&instance->ep_table, key); 178 if (item != NULL) { 179 fibril_mutex_unlock(&instance->guard); 180 return EEXISTS; 181 } 182 183 node_t *node = malloc(sizeof(node_t)); 184 if (node == NULL) { 185 fibril_mutex_unlock(&instance->guard); 186 return ENOMEM; 187 } 188 189 node->bw = bw; 190 node->ep = ep; 191 link_initialize(&node->link); 192 193 hash_table_insert(&instance->ep_table, key, &node->link); 194 instance->free_bw -= bw; 195 fibril_mutex_unlock(&instance->guard); 196 return EOK; 197 } 198 /*----------------------------------------------------------------------------*/ 199 int usb_endpoint_manager_unregister_ep(usb_endpoint_manager_t *instance, 200 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction) 201 { 202 assert(instance); 203 unsigned long key[MAX_KEYS] = {address, endpoint, direction}; 204 205 fibril_mutex_lock(&instance->guard); 206 link_t *item = hash_table_find(&instance->ep_table, key); 207 if (item == NULL) { 208 fibril_mutex_unlock(&instance->guard); 209 return EINVAL; 210 } 211 212 node_t *node = hash_table_get_instance(item, node_t, link); 213 if (node->ep->active) { 214 fibril_mutex_unlock(&instance->guard); 215 return EBUSY; 216 } 217 218 instance->free_bw += node->bw; 219 hash_table_remove(&instance->ep_table, key, MAX_KEYS); 220 221 fibril_mutex_unlock(&instance->guard); 222 return EOK; 223 } 224 /*----------------------------------------------------------------------------*/ 225 endpoint_t * usb_endpoint_manager_get_ep(usb_endpoint_manager_t *instance, 226 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction, 227 size_t *bw) 228 { 229 assert(instance); 230 unsigned long key[MAX_KEYS] = {address, endpoint, direction}; 231 232 fibril_mutex_lock(&instance->guard); 233 const link_t *item = hash_table_find(&instance->ep_table, key); 234 if (item == NULL) { 235 fibril_mutex_unlock(&instance->guard); 236 return NULL; 237 } 238 const node_t *node = hash_table_get_instance(item, node_t, link); 239 if (bw) 240 *bw = node->bw; 241 242 fibril_mutex_unlock(&instance->guard); 243 return node->ep; 158 for (unsigned i = 0; i < ENDPOINT_LIST_COUNT; ++i) { 159 list_initialize(&instance->endpoint_lists[i]); 160 } 161 return EOK; 244 162 } 245 163 /*----------------------------------------------------------------------------*/ 246 164 /** Check setup packet data for signs of toggle reset. 247 165 * 248 * @param[in] instance Device keeper structure to use.166 * @param[in] instance usb_endpoint_manager structure, non-null. 249 167 * @param[in] target Device to receive setup packet. 250 168 * @param[in] data Setup packet data. 251 169 * 252 * Really ugly one. 253 */ 254 void usb_endpoint_manager_reset_ if_need(255 usb_ endpoint_manager_t *instance, usb_target_t target, const uint8_t *data)170 * Really ugly one. Resets toggle bit on all endpoints that need it. 171 */ 172 void usb_endpoint_manager_reset_eps_if_need(usb_endpoint_manager_t *instance, 173 usb_target_t target, const uint8_t data[8]) 256 174 { 257 175 assert(instance); … … 267 185 /* Recipient is endpoint, value is zero (ENDPOINT_STALL) */ 268 186 if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) { 187 fibril_mutex_lock(&instance->guard); 269 188 /* endpoint number is < 16, thus first byte is enough */ 270 usb_target_t reset_target = 271 { .address = target.address, data[4] }; 272 fibril_mutex_lock(&instance->guard); 273 hash_table_apply(&instance->ep_table, 274 node_toggle_reset_filtered, &reset_target); 189 list_foreach(*get_list(instance, target.address), it) { 190 endpoint_t *ep = endpoint_get_instance(it); 191 if ((ep->address == target.address) 192 && (ep->endpoint = data[4])) { 193 endpoint_toggle_set(ep,0); 194 } 195 } 275 196 fibril_mutex_unlock(&instance->guard); 276 197 } … … 279 200 case 0x9: /* Set Configuration */ 280 201 case 0x11: /* Set Interface */ 281 /* Recipient must be device */ 202 /* Recipient must be device, this resets all endpoints, 203 * In fact there should be no endpoints but EP 0 registered 204 * as different interfaces use different endpoints. */ 282 205 if ((data[0] & 0xf) == 0) { 283 usb_target_t reset_target =284 { .address = target.address, 0 };285 206 fibril_mutex_lock(&instance->guard); 286 hash_table_apply(&instance->ep_table, 287 node_toggle_reset_filtered, &reset_target); 207 list_foreach(*get_list(instance, target.address), it) { 208 endpoint_t *ep = endpoint_get_instance(it); 209 if (ep->address == target.address) { 210 endpoint_toggle_set(ep,0); 211 } 212 } 288 213 fibril_mutex_unlock(&instance->guard); 289 214 } … … 291 216 } 292 217 } 218 /*----------------------------------------------------------------------------*/ 219 /** Register endpoint structure. 220 * Checks for duplicates. 221 * @param instance usb_endpoint_manager, non-null. 222 * @param ep endpoint_t to register. 223 * @param data_size Size of data to transfer. 224 * @return Error code. 225 */ 226 int usb_endpoint_manager_register_ep(usb_endpoint_manager_t *instance, 227 endpoint_t *ep, size_t data_size) 228 { 229 assert(instance); 230 if (ep == NULL || ep->address < 0) 231 return EINVAL; 232 233 fibril_mutex_lock(&instance->guard); 234 /* Check for available bandwidth */ 235 if (ep->bandwidth > instance->free_bw) { 236 fibril_mutex_unlock(&instance->guard); 237 return ENOSPC; 238 } 239 240 /* Check for existence */ 241 const endpoint_t *endpoint = 242 find_locked(instance, ep->address, ep->endpoint, ep->direction); 243 if (endpoint != NULL) { 244 fibril_mutex_unlock(&instance->guard); 245 return EEXISTS; 246 } 247 list_append(&ep->link, get_list(instance, ep->address)); 248 249 instance->free_bw -= ep->bandwidth; 250 fibril_mutex_unlock(&instance->guard); 251 return EOK; 252 } 253 /*----------------------------------------------------------------------------*/ 254 /** Unregister endpoint structure. 255 * Checks for duplicates. 256 * @param instance usb_endpoint_manager, non-null. 257 * @param ep endpoint_t to unregister. 258 * @return Error code. 259 */ 260 int usb_endpoint_manager_unregister_ep( 261 usb_endpoint_manager_t *instance, endpoint_t *ep) 262 { 263 assert(instance); 264 if (ep == NULL || ep->address < 0) 265 return EINVAL; 266 267 fibril_mutex_lock(&instance->guard); 268 if (!list_member(&ep->link, get_list(instance, ep->address))) { 269 fibril_mutex_unlock(&instance->guard); 270 return ENOENT; 271 } 272 list_remove(&ep->link); 273 instance->free_bw += ep->bandwidth; 274 fibril_mutex_unlock(&instance->guard); 275 return EOK; 276 } 277 /*----------------------------------------------------------------------------*/ 278 /** Find endpoint_t representing the given communication route. 279 * @param instance usb_endpoint_manager, non-null. 280 * @param address 281 */ 282 endpoint_t * usb_endpoint_manager_find_ep(usb_endpoint_manager_t *instance, 283 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction) 284 { 285 assert(instance); 286 287 fibril_mutex_lock(&instance->guard); 288 endpoint_t *ep = find_locked(instance, address, endpoint, direction); 289 fibril_mutex_unlock(&instance->guard); 290 return ep; 291 } 292 /*----------------------------------------------------------------------------*/ 293 /** Create and register new endpoint_t structure. 294 * @param instance usb_endpoint_manager structure, non-null. 295 * @param address USB address. 296 * @param endpoint USB endpoint number. 297 * @param direction Communication direction. 298 * @param type USB transfer type. 299 * @param speed USB Communication speed. 300 * @param max_packet_size Maximum size of data packets. 301 * @param data_size Expected communication size. 302 * @param callback function to call just after registering. 303 * @param arg Argument to pass to the callback function. 304 * @return Error code. 305 */ 306 int usb_endpoint_manager_add_ep(usb_endpoint_manager_t *instance, 307 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction, 308 usb_transfer_type_t type, usb_speed_t speed, size_t max_packet_size, 309 size_t data_size, int (*callback)(endpoint_t *, void *), void *arg) 310 { 311 assert(instance); 312 if (instance->bw_count == NULL) 313 return ENOTSUP; 314 if (address < 0) 315 return EINVAL; 316 317 const size_t bw = 318 instance->bw_count(speed, type, data_size, max_packet_size); 319 320 fibril_mutex_lock(&instance->guard); 321 /* Check for available bandwidth */ 322 if (bw > instance->free_bw) { 323 fibril_mutex_unlock(&instance->guard); 324 return ENOSPC; 325 } 326 327 /* Check for existence */ 328 endpoint_t *ep = find_locked(instance, address, endpoint, direction); 329 if (ep != NULL) { 330 fibril_mutex_unlock(&instance->guard); 331 return EEXISTS; 332 } 333 334 ep = endpoint_create( 335 address, endpoint, direction, type, speed, max_packet_size, bw); 336 if (!ep) { 337 fibril_mutex_unlock(&instance->guard); 338 return ENOMEM; 339 } 340 341 if (callback) { 342 const int ret = callback(ep, arg); 343 if (ret != EOK) { 344 fibril_mutex_unlock(&instance->guard); 345 endpoint_destroy(ep); 346 return ret; 347 } 348 } 349 list_append(&ep->link, get_list(instance, ep->address)); 350 351 instance->free_bw -= ep->bandwidth; 352 fibril_mutex_unlock(&instance->guard); 353 return EOK; 354 } 355 /*----------------------------------------------------------------------------*/ 356 /** Unregister and destroy endpoint_t structure representing given route. 357 * @param instance usb_endpoint_manager structure, non-null. 358 * @param address USB address. 359 * @param endpoint USB endpoint number. 360 * @param direction Communication direction. 361 * @param callback Function to call after unregister, before destruction. 362 * @arg Argument to pass to the callback function. 363 * @return Error code. 364 */ 365 int usb_endpoint_manager_remove_ep(usb_endpoint_manager_t *instance, 366 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction, 367 void (*callback)(endpoint_t *, void *), void *arg) 368 { 369 assert(instance); 370 fibril_mutex_lock(&instance->guard); 371 endpoint_t *ep = find_locked(instance, address, endpoint, direction); 372 if (ep != NULL) { 373 list_remove(&ep->link); 374 instance->free_bw += ep->bandwidth; 375 } 376 fibril_mutex_unlock(&instance->guard); 377 if (ep == NULL) 378 return ENOENT; 379 380 if (callback) { 381 callback(ep, arg); 382 } 383 endpoint_destroy(ep); 384 return EOK; 385 } -
uspace/lib/usbhost/src/usb_transfer_batch.c
r4c3ad56 r20a3465 37 37 #include <usb/usb.h> 38 38 #include <usb/debug.h> 39 39 40 #include <usb/host/usb_transfer_batch.h> 40 41 #include <usb/host/hcd.h> 41 42 42 usb_transfer_batch_t * usb_transfer_batch_get( 43 /** Allocate and initialize usb_transfer_batch structure. 44 * @param ep endpoint used by the transfer batch. 45 * @param buffer data to send/recieve. 46 * @param buffer_size Size of data buffer. 47 * @param setup_buffer Data to send in SETUP stage of control transfer. 48 * @param func_in callback on IN transfer completion. 49 * @param func_out callback on OUT transfer completion. 50 * @param arg Argument to pass to the callback function. 51 * @param private_data driver specific per batch data. 52 * @param private_data_dtor Function to properly destroy private_data. 53 * @return Pointer to valid usb_transfer_batch_t structure, NULL on failure. 54 */ 55 usb_transfer_batch_t * usb_transfer_batch_create( 43 56 endpoint_t *ep, 44 57 char *buffer, … … 53 66 ) 54 67 { 68 if (func_in == NULL && func_out == NULL) 69 return NULL; 70 if (func_in != NULL && func_out != NULL) 71 return NULL; 72 55 73 usb_transfer_batch_t *instance = malloc(sizeof(usb_transfer_batch_t)); 56 74 if (instance) { … … 78 96 } 79 97 /*----------------------------------------------------------------------------*/ 80 /** Mark batch as finished and run callback.81 *82 * @param[in] instance Batch structure to use.83 * @param[in] data Data to copy to the output buffer.84 * @param[in] size Size of @p data.85 */86 void usb_transfer_batch_finish(87 usb_transfer_batch_t *instance, const void *data, size_t size)88 {89 assert(instance);90 assert(instance->ep);91 /* we care about the data and there are some to copy */92 if (instance->ep->direction != USB_DIRECTION_OUT93 && data) {94 const size_t min_size =95 size < instance->buffer_size ? size : instance->buffer_size;96 memcpy(instance->buffer, data, min_size);97 }98 if (instance->callback_out)99 usb_transfer_batch_call_out(instance);100 if (instance->callback_in)101 usb_transfer_batch_call_in(instance);102 103 }104 /*----------------------------------------------------------------------------*/105 /** Prepare data, get error status and call callback in.106 *107 * @param[in] instance Batch structure to use.108 * Copies data from transport buffer, and calls callback with appropriate109 * parameters.110 */111 void usb_transfer_batch_call_in(usb_transfer_batch_t *instance)112 {113 assert(instance);114 assert(instance->callback_in);115 116 usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " completed (%zuB): %s.\n",117 instance, USB_TRANSFER_BATCH_ARGS(*instance),118 instance->transfered_size, str_error(instance->error));119 120 instance->callback_in(instance->fun, instance->error,121 instance->transfered_size, instance->arg);122 }123 /*----------------------------------------------------------------------------*/124 /** Get error status and call callback out.125 *126 * @param[in] instance Batch structure to use.127 */128 void usb_transfer_batch_call_out(usb_transfer_batch_t *instance)129 {130 assert(instance);131 assert(instance->callback_out);132 133 usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " completed: %s.\n",134 instance, USB_TRANSFER_BATCH_ARGS(*instance),135 str_error(instance->error));136 137 if (instance->ep->transfer_type == USB_TRANSFER_CONTROL138 && instance->error == EOK) {139 const usb_target_t target =140 {{ instance->ep->address, instance->ep->endpoint }};141 reset_ep_if_need(142 fun_to_hcd(instance->fun), target, instance->setup_buffer);143 }144 145 instance->callback_out(instance->fun,146 instance->error, instance->arg);147 }148 /*----------------------------------------------------------------------------*/149 98 /** Correctly dispose all used data structures. 150 99 * 151 100 * @param[in] instance Batch structure to use. 152 101 */ 153 void usb_transfer_batch_d ispose(usb_transfer_batch_t *instance)102 void usb_transfer_batch_destroy(const usb_transfer_batch_t *instance) 154 103 { 155 104 if (!instance) … … 166 115 free(instance); 167 116 } 117 /*----------------------------------------------------------------------------*/ 118 /** Prepare data and call the right callback. 119 * 120 * @param[in] instance Batch structure to use. 121 * @param[in] data Data to copy to the output buffer. 122 * @param[in] size Size of @p data. 123 */ 124 void usb_transfer_batch_finish( 125 const usb_transfer_batch_t *instance, const void *data, size_t size) 126 { 127 assert(instance); 128 usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " finishing.\n", 129 instance, USB_TRANSFER_BATCH_ARGS(*instance)); 130 131 /* NOTE: Only one of these pointers should be set. */ 132 if (instance->callback_out) { 133 /* Check for commands that reset toggle bit */ 134 if (instance->ep->transfer_type == USB_TRANSFER_CONTROL 135 && instance->error == EOK) { 136 const usb_target_t target = 137 {{ instance->ep->address, instance->ep->endpoint }}; 138 reset_ep_if_need(fun_to_hcd(instance->fun), target, 139 instance->setup_buffer); 140 } 141 instance->callback_out(instance->fun, 142 instance->error, instance->arg); 143 } 144 145 if (instance->callback_in) { 146 /* We care about the data and there are some to copy */ 147 if (data) { 148 const size_t min_size = size < instance->buffer_size 149 ? size : instance->buffer_size; 150 memcpy(instance->buffer, data, min_size); 151 } 152 instance->callback_in(instance->fun, instance->error, 153 instance->transfered_size, instance->arg); 154 } 155 } 168 156 /** 169 157 * @}
Note:
See TracChangeset
for help on using the changeset viewer.
