Changeset e50cd7f in mainline for uspace/lib/usb
- Timestamp:
- 2011-04-17T19:17:55Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 63517c2, cfbbe1d3
- Parents:
- ef354b6 (diff), 8595577b (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/usb
- Files:
-
- 7 added
- 27 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usb/Makefile
ref354b6 re50cd7f 34 34 SOURCES = \ 35 35 src/addrkeep.c \ 36 src/altiface.c \ 36 37 src/class.c \ 37 38 src/ddfiface.c \ … … 41 42 src/dp.c \ 42 43 src/dump.c \ 44 src/hidiface.c \ 43 45 src/hidparser.c \ 44 46 src/hub.c \ 47 src/pipepriv.c \ 45 48 src/pipes.c \ 46 49 src/pipesinit.c \ -
uspace/lib/usb/include/usb/classes/hidparser.h
ref354b6 re50cd7f 317 317 usb_hid_report_path_t *usb_hid_report_path_clone(usb_hid_report_path_t *usage_path); 318 318 319 usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report, usb_hid_report_field_t *field, usb_hid_report_path_t *path, int flags, usb_hid_report_type_t type); 319 320 320 321 /* -
uspace/lib/usb/include/usb/classes/hub.h
ref354b6 re50cd7f 43 43 */ 44 44 typedef enum { 45 USB_HUB_FEATURE_HUB_LOCAL_POWER = 0, 46 USB_HUB_FEATURE_HUB_OVER_CURRENT = 1, 45 47 USB_HUB_FEATURE_C_HUB_LOCAL_POWER = 0, 46 48 USB_HUB_FEATURE_C_HUB_OVER_CURRENT = 1, … … 59 61 /* USB_HUB_FEATURE_ = , */ 60 62 } usb_hub_class_feature_t; 63 61 64 62 65 /** Header of standard hub descriptor without the "variadic" part. */ … … 149 152 maximum of 255 ports). 150 153 */ 151 uint8_t * devices_removable;154 uint8_t devices_removable[32]; 152 155 153 156 /** -
uspace/lib/usb/include/usb/devdrv.h
ref354b6 re50cd7f 162 162 usb_endpoint_description_t **); 163 163 164 typedef bool (*usb_polling_callback_t)(usb_device_t *, 165 uint8_t *, size_t, void *); 166 typedef void (*usb_polling_terminted_callback_t)(usb_device_t *, bool, void *); 164 int usb_device_retrieve_descriptors(usb_pipe_t *, usb_device_descriptors_t *); 165 int usb_device_create_pipes(ddf_dev_t *, usb_device_connection_t *, 166 usb_endpoint_description_t **, uint8_t *, size_t, int, int, 167 usb_endpoint_mapping_t **, size_t *); 168 int usb_device_destroy_pipes(ddf_dev_t *, usb_endpoint_mapping_t *, size_t); 169 int usb_device_create(ddf_dev_t *, usb_endpoint_description_t **, usb_device_t **, const char **); 167 170 168 int usb_device_auto_poll(usb_device_t *, size_t, 169 usb_polling_callback_t, size_t, usb_polling_terminted_callback_t, void *); 171 size_t usb_interface_count_alternates(uint8_t *, size_t, uint8_t); 172 int usb_alternate_interfaces_create(uint8_t *, size_t, int, 173 usb_alternate_interfaces_t **); 170 174 171 175 #endif -
uspace/lib/usb/include/usb/host/batch.h
ref354b6 re50cd7f 43 43 typedef struct usb_transfer_batch usb_transfer_batch_t; 44 44 struct usb_transfer_batch { 45 endpoint_t *ep; 45 46 link_t link; 46 usb_target_t target;47 usb_transfer_type_t transfer_type;48 usb_speed_t speed;49 usb_direction_t direction;50 47 usbhc_iface_transfer_in_callback_t callback_in; 51 48 usbhc_iface_transfer_out_callback_t callback_out; 49 void *arg; 52 50 char *buffer; 53 char * transport_buffer;51 char *data_buffer; 54 52 size_t buffer_size; 55 53 char *setup_buffer; 56 54 size_t setup_size; 57 size_t max_packet_size;58 55 size_t transfered_size; 59 56 void (*next_step)(usb_transfer_batch_t *); 60 57 int error; 61 58 ddf_fun_t *fun; 62 void *arg;63 endpoint_t *ep;64 59 void *private_data; 60 void (*private_data_dtor)(void *p_data); 65 61 }; 66 62 67 63 void usb_transfer_batch_init( 68 64 usb_transfer_batch_t *instance, 69 usb_target_t target, 70 usb_transfer_type_t transfer_type, 71 usb_speed_t speed, 72 size_t max_packet_size, 65 endpoint_t *ep, 73 66 char *buffer, 74 char * transport_buffer,67 char *data_buffer, 75 68 size_t buffer_size, 76 69 char *setup_buffer, … … 80 73 void *arg, 81 74 ddf_fun_t *fun, 82 endpoint_t *ep,83 void *private_data75 void *private_data, 76 void (*private_data_dtor)(void *p_data) 84 77 ); 78 79 void usb_transfer_batch_call_in_and_dispose(usb_transfer_batch_t *instance); 80 void usb_transfer_batch_call_out_and_dispose(usb_transfer_batch_t *instance); 81 void usb_transfer_batch_finish(usb_transfer_batch_t *instance); 82 void usb_transfer_batch_dispose(usb_transfer_batch_t *instance); 83 84 static inline void usb_transfer_batch_finish_error( 85 usb_transfer_batch_t *instance, int error) 86 { 87 assert(instance); 88 instance->error = error; 89 usb_transfer_batch_finish(instance); 90 } 85 91 86 92 static inline usb_transfer_batch_t *usb_transfer_batch_from_link(link_t *l) … … 90 96 } 91 97 92 void usb_transfer_batch_call_in(usb_transfer_batch_t *instance);93 void usb_transfer_batch_call_out(usb_transfer_batch_t *instance);94 void usb_transfer_batch_finish(usb_transfer_batch_t *instance, int error);95 96 98 #endif 97 99 /** -
uspace/lib/usb/include/usb/host/device_keeper.h
ref354b6 re50cd7f 54 54 usb_speed_t speed; 55 55 bool occupied; 56 link_t endpoints;57 uint16_t control_used;58 56 devman_handle_t handle; 59 57 }; … … 65 63 struct usb_device_info devices[USB_ADDRESS_COUNT]; 66 64 fibril_mutex_t guard; 67 fibril_condvar_t change;68 65 usb_address_t last_address; 69 66 } usb_device_keeper_t; 70 67 71 68 void usb_device_keeper_init(usb_device_keeper_t *instance); 72 73 void usb_device_keeper_add_ep(74 usb_device_keeper_t *instance, usb_address_t address, endpoint_t *ep);75 76 void usb_device_keeper_reserve_default_address(77 usb_device_keeper_t *instance, usb_speed_t speed);78 79 void usb_device_keeper_release_default_address(usb_device_keeper_t *instance);80 81 void usb_device_keeper_reset_if_need(usb_device_keeper_t *instance,82 usb_target_t target, const uint8_t *setup_data);83 69 84 70 usb_address_t device_keeper_get_free_address(usb_device_keeper_t *instance, … … 96 82 usb_speed_t usb_device_keeper_get_speed(usb_device_keeper_t *instance, 97 83 usb_address_t address); 98 99 void usb_device_keeper_use_control(usb_device_keeper_t *instance,100 usb_target_t target);101 102 void usb_device_keeper_release_control(usb_device_keeper_t *instance,103 usb_target_t target);104 105 84 #endif 106 85 /** -
uspace/lib/usb/include/usb/host/endpoint.h
ref354b6 re50cd7f 39 39 #include <bool.h> 40 40 #include <adt/list.h> 41 #include <fibril_synch.h> 42 41 43 #include <usb/usb.h> 42 44 … … 48 50 usb_speed_t speed; 49 51 size_t max_packet_size; 50 bool active;51 52 unsigned toggle:1; 52 link_t same_device_eps; 53 fibril_mutex_t guard; 54 fibril_condvar_t avail; 55 volatile bool active; 56 struct { 57 void *data; 58 int (*toggle_get)(void *); 59 void (*toggle_set)(void *, int); 60 } hc_data; 53 61 } endpoint_t; 54 62 … … 59 67 void endpoint_destroy(endpoint_t *instance); 60 68 69 void endpoint_set_hc_data(endpoint_t *instance, 70 void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int)); 71 72 void endpoint_clear_hc_data(endpoint_t *instance); 73 74 void endpoint_use(endpoint_t *instance); 75 76 void endpoint_release(endpoint_t *instance); 77 61 78 int endpoint_toggle_get(endpoint_t *instance); 62 79 63 80 void endpoint_toggle_set(endpoint_t *instance, int toggle); 64 81 65 void endpoint_toggle_reset(link_t *ep); 66 67 void endpoint_toggle_reset_filtered(link_t *ep, usb_endpoint_t epn); 68 82 void endpoint_toggle_reset_filtered(endpoint_t *instance, usb_target_t target); 69 83 #endif 70 84 /** -
uspace/lib/usb/include/usb/host/usb_endpoint_manager.h
ref354b6 re50cd7f 66 66 endpoint_t *ep, size_t data_size); 67 67 68 int usb_endpoint_manager_register_ep_wait(usb_endpoint_manager_t *instance,69 usb_address_t address, usb_endpoint_t ep, usb_direction_t direction,70 void *data, void (*data_remove_callback)(void* data, void* arg), void *arg,71 size_t bw);72 73 68 int usb_endpoint_manager_unregister_ep(usb_endpoint_manager_t *instance, 74 69 usb_address_t address, usb_endpoint_t ep, usb_direction_t direction); … … 78 73 size_t *bw); 79 74 75 void usb_endpoint_manager_reset_if_need( 76 usb_endpoint_manager_t *instance, usb_target_t target, const uint8_t *data); 77 78 static inline int usb_endpoint_manager_add_ep(usb_endpoint_manager_t *instance, 79 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction, 80 usb_transfer_type_t type, usb_speed_t speed, size_t max_packet_size, 81 size_t data_size) 82 { 83 endpoint_t *ep = malloc(sizeof(endpoint_t)); 84 if (ep == NULL) 85 return ENOMEM; 86 87 int ret = endpoint_init(ep, address, endpoint, direction, type, speed, 88 max_packet_size); 89 if (ret != EOK) { 90 free(ep); 91 return ret; 92 } 93 94 ret = usb_endpoint_manager_register_ep(instance, ep, data_size); 95 if (ret != EOK) { 96 endpoint_destroy(ep); 97 return ret; 98 } 99 return EOK; 100 } 80 101 #endif 81 102 /** -
uspace/lib/usb/include/usb/hub.h
ref354b6 re50cd7f 59 59 } usb_hc_attached_device_t; 60 60 61 int usb_hc_reserve_default_address(usb_hc_connection_t *, usb_speed_t);62 int usb_hc_release_default_address(usb_hc_connection_t *);63 64 61 usb_address_t usb_hc_request_address(usb_hc_connection_t *, usb_speed_t); 65 62 int usb_hc_register_device(usb_hc_connection_t *, -
uspace/lib/usb/include/usb/pipes.h
ref354b6 re50cd7f 42 42 #include <ipc/devman.h> 43 43 #include <ddf/driver.h> 44 #include <fibril_synch.h> 44 45 45 46 /** Abstraction of a physical connection to the device. … … 59 60 * This endpoint must be bound with existing usb_device_connection_t 60 61 * (i.e. the wire to send data over). 62 * 63 * Locking order: if you want to lock both mutexes 64 * (@c guard and @c hc_phone_mutex), lock @c guard first. 65 * It is not necessary to lock @c guard if you want to lock @c hc_phone_mutex 66 * only. 61 67 */ 62 68 typedef struct { 69 /** Guard of the whole pipe. */ 70 fibril_mutex_t guard; 71 63 72 /** The connection used for sending the data. */ 64 73 usb_device_connection_t *wire; … … 78 87 /** Phone to the host controller. 79 88 * Negative when no session is active. 89 * It is an error to access this member without @c hc_phone_mutex 90 * being locked. 91 * If call over the phone is to be made, it must be preceeded by 92 * call to pipe_add_ref() [internal libusb function]. 80 93 */ 81 94 int hc_phone; 95 96 /** Guard for serialization of requests over the phone. */ 97 fibril_mutex_t hc_phone_mutex; 98 99 /** Number of active transfers over the pipe. */ 100 int refcount; 101 102 /** Whether to automatically reset halt on the endpoint. 103 * Valid only for control endpoint zero. 104 */ 105 bool auto_reset_halt; 82 106 } usb_pipe_t; 83 107 … … 134 158 int usb_pipe_initialize_from_configuration(usb_endpoint_mapping_t *, 135 159 size_t, uint8_t *, size_t, usb_device_connection_t *); 160 int usb_pipe_register_with_speed(usb_pipe_t *, usb_speed_t, 161 unsigned int, usb_hc_connection_t *); 136 162 int usb_pipe_register(usb_pipe_t *, unsigned int, usb_hc_connection_t *); 137 163 int usb_pipe_unregister(usb_pipe_t *, usb_hc_connection_t *); … … 140 166 int usb_pipe_end_session(usb_pipe_t *); 141 167 bool usb_pipe_is_session_started(usb_pipe_t *); 168 169 int usb_pipe_start_long_transfer(usb_pipe_t *); 170 void usb_pipe_end_long_transfer(usb_pipe_t *); 142 171 143 172 int usb_pipe_read(usb_pipe_t *, void *, size_t, size_t *); -
uspace/lib/usb/include/usb/request.h
ref354b6 re50cd7f 50 50 /** USB endpoint status - endpoint is halted (stalled). */ 51 51 #define USB_ENDPOINT_STATUS_HALTED ((uint16_t)(1 << 0)) 52 53 /** USB feature selector - endpoint halt (stall). */ 54 #define USB_FEATURE_SELECTOR_ENDPOINT_HALT (0) 55 56 /** USB feature selector - device remote wake-up. */ 57 #define USB_FEATURE_SELECTOR_REMOTE_WAKEUP (1) 52 58 53 59 /** Standard device request. */ … … 135 141 char **); 136 142 143 int usb_request_clear_endpoint_halt(usb_pipe_t *, uint16_t); 144 137 145 #endif 138 146 /** -
uspace/lib/usb/include/usb/usb.h
ref354b6 re50cd7f 77 77 USB_SPEED_FULL, 78 78 /** USB 2.0 high speed (480Mbits/s). */ 79 USB_SPEED_HIGH 79 USB_SPEED_HIGH, 80 /** Psuedo-speed serving as a boundary. */ 81 USB_SPEED_MAX 80 82 } usb_speed_t; 81 83 -
uspace/lib/usb/src/devdrv.c
ref354b6 re50cd7f 72 72 } 73 73 74 /** Log out of memory error on given device.75 *76 * @param dev Device causing the trouble.77 */78 static void usb_log_oom(ddf_dev_t *dev)79 {80 usb_log_error("Out of memory when adding device `%s'.\n",81 dev->name);82 }83 84 74 /** Count number of pipes the driver expects. 85 75 * … … 108 98 */ 109 99 static int initialize_other_pipes(usb_endpoint_description_t **endpoints, 110 usb_device_t *dev) 111 { 112 int rc; 113 114 size_t pipe_count = count_other_pipes(endpoints); 115 if (pipe_count == 0) { 100 usb_device_t *dev, int alternate_setting) 101 { 102 if (endpoints == NULL) { 103 dev->pipes = NULL; 104 dev->pipes_count = 0; 116 105 return EOK; 117 106 } 118 107 119 dev->pipes = malloc(sizeof(usb_endpoint_mapping_t) * pipe_count); 120 if (dev->pipes == NULL) { 121 usb_log_oom(dev->ddf_dev); 122 return ENOMEM; 123 } 124 125 size_t i; 126 127 /* Initialize to NULL first for rollback purposes. */ 128 for (i = 0; i < pipe_count; i++) { 129 dev->pipes[i].pipe = NULL; 130 } 131 132 for (i = 0; i < pipe_count; i++) { 133 dev->pipes[i].pipe = malloc(sizeof(usb_pipe_t)); 134 if (dev->pipes[i].pipe == NULL) { 135 usb_log_oom(dev->ddf_dev); 136 rc = ENOMEM; 137 goto rollback; 138 } 139 140 dev->pipes[i].description = endpoints[i]; 141 dev->pipes[i].interface_no = dev->interface_no; 142 dev->pipes[i].interface_setting = 0; 143 } 144 145 rc = usb_pipe_initialize_from_configuration(dev->pipes, pipe_count, 108 usb_endpoint_mapping_t *pipes; 109 size_t pipes_count; 110 111 int rc = usb_device_create_pipes(dev->ddf_dev, &dev->wire, endpoints, 146 112 dev->descriptors.configuration, dev->descriptors.configuration_size, 147 &dev->wire); 148 if (rc != EOK) { 149 usb_log_error("Failed initializing USB endpoints: %s.\n", 150 str_error(rc)); 151 goto rollback; 152 } 153 154 /* Register the endpoints. */ 155 usb_hc_connection_t hc_conn; 156 rc = usb_hc_connection_initialize_from_device(&hc_conn, dev->ddf_dev); 157 if (rc != EOK) { 158 usb_log_error( 159 "Failed initializing connection to host controller: %s.\n", 160 str_error(rc)); 161 goto rollback; 162 } 163 rc = usb_hc_connection_open(&hc_conn); 164 if (rc != EOK) { 165 usb_log_error("Failed to connect to host controller: %s.\n", 166 str_error(rc)); 167 goto rollback; 168 } 169 for (i = 0; i < pipe_count; i++) { 170 if (dev->pipes[i].present) { 171 rc = usb_pipe_register(dev->pipes[i].pipe, 172 dev->pipes[i].descriptor->poll_interval, 173 &hc_conn); 174 /* Ignore error when operation not supported by HC. */ 175 if ((rc != EOK) && (rc != ENOTSUP)) { 176 /* FIXME: what shall we do? */ 177 dev->pipes[i].present = false; 178 free(dev->pipes[i].pipe); 179 dev->pipes[i].pipe = NULL; 180 } 181 } 182 } 183 /* Ignoring errors here. */ 184 usb_hc_connection_close(&hc_conn); 185 186 dev->pipes_count = pipe_count; 187 188 return EOK; 189 190 rollback: 191 for (i = 0; i < pipe_count; i++) { 192 if (dev->pipes[i].pipe != NULL) { 193 free(dev->pipes[i].pipe); 194 } 195 } 196 free(dev->pipes); 197 198 return rc; 199 } 200 201 /** Initialize all endpoint pipes. 202 * 203 * @param drv The driver. 204 * @param dev The device to be initialized. 205 * @return Error code. 206 */ 207 static int initialize_pipes(usb_device_t *dev) 208 { 209 int rc; 210 211 rc = usb_device_connection_initialize_from_device(&dev->wire, 212 dev->ddf_dev); 213 if (rc != EOK) { 214 usb_log_error( 215 "Failed initializing connection on device `%s'. %s.\n", 216 dev->ddf_dev->name, str_error(rc)); 217 return rc; 218 } 219 220 rc = usb_pipe_initialize_default_control(&dev->ctrl_pipe, 221 &dev->wire); 222 if (rc != EOK) { 223 usb_log_error("Failed to initialize default control pipe " \ 224 "on device `%s': %s.\n", 225 dev->ddf_dev->name, str_error(rc)); 226 return rc; 227 } 228 229 rc = usb_pipe_probe_default_control(&dev->ctrl_pipe); 230 if (rc != EOK) { 231 usb_log_error( 232 "Probing default control pipe on device `%s' failed: %s.\n", 233 dev->ddf_dev->name, str_error(rc)); 234 return rc; 235 } 236 237 /* Get our interface. */ 238 dev->interface_no = usb_device_get_assigned_interface(dev->ddf_dev); 239 240 /* 241 * For further actions, we need open session on default control pipe. 242 */ 243 rc = usb_pipe_start_session(&dev->ctrl_pipe); 244 if (rc != EOK) { 245 usb_log_error("Failed to start an IPC session: %s.\n", 246 str_error(rc)); 247 return rc; 248 } 249 250 /* Get the device descriptor. */ 251 rc = usb_request_get_device_descriptor(&dev->ctrl_pipe, 252 &dev->descriptors.device); 253 if (rc != EOK) { 254 usb_log_error("Failed to retrieve device descriptor: %s.\n", 255 str_error(rc)); 256 return rc; 257 } 258 259 /* Get the full configuration descriptor. */ 260 rc = usb_request_get_full_configuration_descriptor_alloc( 261 &dev->ctrl_pipe, 0, (void **) &dev->descriptors.configuration, 262 &dev->descriptors.configuration_size); 263 if (rc != EOK) { 264 usb_log_error("Failed retrieving configuration descriptor: %s. %s\n", 265 dev->ddf_dev->name, str_error(rc)); 266 return rc; 267 } 268 269 if (driver->endpoints != NULL) { 270 rc = initialize_other_pipes(driver->endpoints, dev); 271 } 272 273 /* No checking here. */ 274 usb_pipe_end_session(&dev->ctrl_pipe); 275 276 /* Rollback actions. */ 277 if (rc != EOK) { 278 if (dev->descriptors.configuration != NULL) { 279 free(dev->descriptors.configuration); 280 } 281 } 282 283 return rc; 284 } 285 286 /** Count number of alternate settings of a interface. 287 * 288 * @param config_descr Full configuration descriptor. 289 * @param config_descr_size Size of @p config_descr in bytes. 290 * @param interface_no Interface number. 291 * @return Number of alternate interfaces for @p interface_no interface. 292 */ 293 static size_t count_alternate_interfaces(uint8_t *config_descr, 294 size_t config_descr_size, int interface_no) 295 { 296 assert(config_descr != NULL); 297 usb_dp_parser_t dp_parser = { 298 .nesting = usb_dp_standard_descriptor_nesting 299 }; 300 usb_dp_parser_data_t dp_data = { 301 .data = config_descr, 302 .size = config_descr_size, 303 .arg = NULL 304 }; 305 306 size_t alternate_count = 0; 307 308 uint8_t *iface_ptr = usb_dp_get_nested_descriptor(&dp_parser, 309 &dp_data, config_descr); 310 while (iface_ptr != NULL) { 311 usb_standard_interface_descriptor_t *iface 312 = (usb_standard_interface_descriptor_t *) iface_ptr; 313 if (iface->descriptor_type == USB_DESCTYPE_INTERFACE) { 314 if (iface->interface_number == interface_no) { 315 alternate_count++; 316 } 317 } 318 iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data, 319 config_descr, iface_ptr); 320 } 321 322 return alternate_count; 323 } 324 325 /** Initialize structures related to alternate interfaces. 326 * 327 * @param dev Device where alternate settings shall be initialized. 328 * @return Error code. 329 */ 330 static int initialize_alternate_interfaces(usb_device_t *dev) 331 { 332 if (dev->interface_no < 0) { 333 dev->alternate_interfaces = NULL; 334 return EOK; 335 } 336 337 usb_alternate_interfaces_t *alternates 338 = malloc(sizeof(usb_alternate_interfaces_t)); 339 340 if (alternates == NULL) { 341 return ENOMEM; 342 } 343 344 alternates->alternative_count 345 = count_alternate_interfaces(dev->descriptors.configuration, 346 dev->descriptors.configuration_size, dev->interface_no); 347 348 if (alternates->alternative_count == 0) { 349 free(alternates); 350 return ENOENT; 351 } 352 353 alternates->alternatives = malloc(alternates->alternative_count 354 * sizeof(usb_alternate_interface_descriptors_t)); 355 if (alternates->alternatives == NULL) { 356 free(alternates); 357 return ENOMEM; 358 } 359 360 alternates->current = 0; 361 362 usb_dp_parser_t dp_parser = { 363 .nesting = usb_dp_standard_descriptor_nesting 364 }; 365 usb_dp_parser_data_t dp_data = { 366 .data = dev->descriptors.configuration, 367 .size = dev->descriptors.configuration_size, 368 .arg = NULL 369 }; 370 371 usb_alternate_interface_descriptors_t *cur_alt_iface 372 = &alternates->alternatives[0]; 373 374 uint8_t *iface_ptr = usb_dp_get_nested_descriptor(&dp_parser, 375 &dp_data, dp_data.data); 376 while (iface_ptr != NULL) { 377 usb_standard_interface_descriptor_t *iface 378 = (usb_standard_interface_descriptor_t *) iface_ptr; 379 if ((iface->descriptor_type != USB_DESCTYPE_INTERFACE) 380 || (iface->interface_number != dev->interface_no)) { 381 iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, 382 &dp_data, 383 dp_data.data, iface_ptr); 384 continue; 385 } 386 387 cur_alt_iface->interface = iface; 388 cur_alt_iface->nested_descriptors = iface_ptr + sizeof(*iface); 389 390 /* Find next interface to count size of nested descriptors. */ 391 iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data, 392 dp_data.data, iface_ptr); 393 if (iface_ptr == NULL) { 394 uint8_t *next = dp_data.data + dp_data.size; 395 cur_alt_iface->nested_descriptors_size 396 = next - cur_alt_iface->nested_descriptors; 397 } else { 398 cur_alt_iface->nested_descriptors_size 399 = iface_ptr - cur_alt_iface->nested_descriptors; 400 } 401 402 cur_alt_iface++; 403 } 404 405 dev->alternate_interfaces = alternates; 113 dev->interface_no, alternate_setting, 114 &pipes, &pipes_count); 115 116 if (rc != EOK) { 117 return rc; 118 } 119 120 dev->pipes = pipes; 121 dev->pipes_count = pipes_count; 406 122 407 123 return EOK; … … 423 139 int rc; 424 140 425 usb_device_t *dev = malloc(sizeof(usb_device_t)); 426 if (dev == NULL) { 427 usb_log_error("Out of memory when adding device `%s'.\n", 428 gen_dev->name); 429 return ENOMEM; 430 } 431 432 433 dev->ddf_dev = gen_dev; 434 dev->ddf_dev->driver_data = dev; 435 dev->driver_data = NULL; 436 dev->descriptors.configuration = NULL; 437 438 dev->pipes_count = 0; 439 dev->pipes = NULL; 440 441 rc = initialize_pipes(dev); 442 if (rc != EOK) { 443 free(dev); 444 return rc; 445 } 446 447 (void) initialize_alternate_interfaces(dev); 141 usb_device_t *dev = NULL; 142 const char *err_msg = NULL; 143 rc = usb_device_create(gen_dev, driver->endpoints, &dev, &err_msg); 144 if (rc != EOK) { 145 usb_log_error("USB device `%s' creation failed (%s): %s.\n", 146 gen_dev->name, err_msg, str_error(rc)); 147 return rc; 148 } 448 149 449 150 return driver->ops->add_device(dev); … … 457 158 static int destroy_current_pipes(usb_device_t *dev) 458 159 { 459 size_t i; 460 int rc; 461 462 /* TODO: this shall be done under some device mutex. */ 463 464 /* First check that no session is opened. */ 465 for (i = 0; i < dev->pipes_count; i++) { 466 if (usb_pipe_is_session_started(dev->pipes[i].pipe)) { 467 return EBUSY; 468 } 469 } 470 471 /* Prepare connection to HC. */ 472 usb_hc_connection_t hc_conn; 473 rc = usb_hc_connection_initialize_from_device(&hc_conn, dev->ddf_dev); 474 if (rc != EOK) { 475 return rc; 476 } 477 rc = usb_hc_connection_open(&hc_conn); 478 if (rc != EOK) { 479 return rc; 480 } 481 482 /* Destroy the pipes. */ 483 for (i = 0; i < dev->pipes_count; i++) { 484 usb_pipe_unregister(dev->pipes[i].pipe, &hc_conn); 485 free(dev->pipes[i].pipe); 486 } 487 488 usb_hc_connection_close(&hc_conn); 489 490 free(dev->pipes); 160 int rc = usb_device_destroy_pipes(dev->ddf_dev, 161 dev->pipes, dev->pipes_count); 162 if (rc != EOK) { 163 return rc; 164 } 165 491 166 dev->pipes = NULL; 492 167 dev->pipes_count = 0; … … 505 180 * with usb_pipe_initialize_from_configuration(). 506 181 * 182 * @warning This is a wrapper function that does several operations that 183 * can fail and that cannot be rollbacked easily. That means that a failure 184 * during the SET_INTERFACE request would result in having a device with 185 * no pipes at all (except the default control one). That is because the old 186 * pipes needs to be unregistered at HC first and the new ones could not 187 * be created. 188 * 507 189 * @param dev USB device. 508 190 * @param alternate_setting Alternate setting to choose. … … 519 201 int rc; 520 202 521 /* TODO: more transactional behavior. */522 523 203 /* Destroy existing pipes. */ 524 204 rc = destroy_current_pipes(dev); … … 535 215 536 216 /* Create new pipes. */ 537 rc = initialize_other_pipes(endpoints, dev );217 rc = initialize_other_pipes(endpoints, dev, (int) alternate_setting); 538 218 539 219 return rc; 220 } 221 222 /** Retrieve basic descriptors from the device. 223 * 224 * @param[in] ctrl_pipe Control endpoint pipe. 225 * @param[out] descriptors Where to store the descriptors. 226 * @return Error code. 227 */ 228 int usb_device_retrieve_descriptors(usb_pipe_t *ctrl_pipe, 229 usb_device_descriptors_t *descriptors) 230 { 231 assert(descriptors != NULL); 232 233 descriptors->configuration = NULL; 234 235 int rc; 236 237 /* It is worth to start a long transfer. */ 238 rc = usb_pipe_start_long_transfer(ctrl_pipe); 239 if (rc != EOK) { 240 return rc; 241 } 242 243 /* Get the device descriptor. */ 244 rc = usb_request_get_device_descriptor(ctrl_pipe, &descriptors->device); 245 if (rc != EOK) { 246 goto leave; 247 } 248 249 /* Get the full configuration descriptor. */ 250 rc = usb_request_get_full_configuration_descriptor_alloc( 251 ctrl_pipe, 0, (void **) &descriptors->configuration, 252 &descriptors->configuration_size); 253 254 leave: 255 usb_pipe_end_long_transfer(ctrl_pipe); 256 257 return rc; 258 } 259 260 /** Create pipes for a device. 261 * 262 * This is more or less a wrapper that does following actions: 263 * - allocate and initialize pipes 264 * - map endpoints to the pipes based on the descriptions 265 * - registers endpoints with the host controller 266 * 267 * @param[in] dev Generic DDF device backing the USB one. 268 * @param[in] wire Initialized backing connection to the host controller. 269 * @param[in] endpoints Endpoints description, NULL terminated. 270 * @param[in] config_descr Configuration descriptor of active configuration. 271 * @param[in] config_descr_size Size of @p config_descr in bytes. 272 * @param[in] interface_no Interface to map from. 273 * @param[in] interface_setting Interface setting (default is usually 0). 274 * @param[out] pipes_ptr Where to store array of created pipes 275 * (not NULL terminated). 276 * @param[out] pipes_count_ptr Where to store number of pipes 277 * (set to if you wish to ignore the count). 278 * @return Error code. 279 */ 280 int usb_device_create_pipes(ddf_dev_t *dev, usb_device_connection_t *wire, 281 usb_endpoint_description_t **endpoints, 282 uint8_t *config_descr, size_t config_descr_size, 283 int interface_no, int interface_setting, 284 usb_endpoint_mapping_t **pipes_ptr, size_t *pipes_count_ptr) 285 { 286 assert(dev != NULL); 287 assert(wire != NULL); 288 assert(endpoints != NULL); 289 assert(config_descr != NULL); 290 assert(config_descr_size > 0); 291 assert(pipes_ptr != NULL); 292 293 size_t i; 294 int rc; 295 296 size_t pipe_count = count_other_pipes(endpoints); 297 if (pipe_count == 0) { 298 *pipes_ptr = NULL; 299 return EOK; 300 } 301 302 usb_endpoint_mapping_t *pipes 303 = malloc(sizeof(usb_endpoint_mapping_t) * pipe_count); 304 if (pipes == NULL) { 305 return ENOMEM; 306 } 307 308 /* Initialize to NULL to allow smooth rollback. */ 309 for (i = 0; i < pipe_count; i++) { 310 pipes[i].pipe = NULL; 311 } 312 313 /* Now allocate and fully initialize. */ 314 for (i = 0; i < pipe_count; i++) { 315 pipes[i].pipe = malloc(sizeof(usb_pipe_t)); 316 if (pipes[i].pipe == NULL) { 317 rc = ENOMEM; 318 goto rollback_free_only; 319 } 320 pipes[i].description = endpoints[i]; 321 pipes[i].interface_no = interface_no; 322 pipes[i].interface_setting = interface_setting; 323 } 324 325 /* Find the mapping from configuration descriptor. */ 326 rc = usb_pipe_initialize_from_configuration(pipes, pipe_count, 327 config_descr, config_descr_size, wire); 328 if (rc != EOK) { 329 goto rollback_free_only; 330 } 331 332 /* Register the endpoints with HC. */ 333 usb_hc_connection_t hc_conn; 334 rc = usb_hc_connection_initialize_from_device(&hc_conn, dev); 335 if (rc != EOK) { 336 goto rollback_free_only; 337 } 338 339 rc = usb_hc_connection_open(&hc_conn); 340 if (rc != EOK) { 341 goto rollback_free_only; 342 } 343 344 for (i = 0; i < pipe_count; i++) { 345 if (pipes[i].present) { 346 rc = usb_pipe_register(pipes[i].pipe, 347 pipes[i].descriptor->poll_interval, &hc_conn); 348 if (rc != EOK) { 349 goto rollback_unregister_endpoints; 350 } 351 } 352 } 353 354 usb_hc_connection_close(&hc_conn); 355 356 *pipes_ptr = pipes; 357 if (pipes_count_ptr != NULL) { 358 *pipes_count_ptr = pipe_count; 359 } 360 361 return EOK; 362 363 /* 364 * Jump here if something went wrong after endpoints have 365 * been registered. 366 * This is also the target when the registration of 367 * endpoints fails. 368 */ 369 rollback_unregister_endpoints: 370 for (i = 0; i < pipe_count; i++) { 371 if (pipes[i].present) { 372 usb_pipe_unregister(pipes[i].pipe, &hc_conn); 373 } 374 } 375 376 usb_hc_connection_close(&hc_conn); 377 378 /* 379 * Jump here if something went wrong before some actual communication 380 * with HC. Then the only thing that needs to be done is to free 381 * allocated memory. 382 */ 383 rollback_free_only: 384 for (i = 0; i < pipe_count; i++) { 385 if (pipes[i].pipe != NULL) { 386 free(pipes[i].pipe); 387 } 388 } 389 free(pipes); 390 391 return rc; 392 } 393 394 /** Destroy pipes previously created by usb_device_create_pipes. 395 * 396 * @param[in] dev Generic DDF device backing the USB one. 397 * @param[in] pipes Endpoint mapping to be destroyed. 398 * @param[in] pipes_count Number of endpoints. 399 */ 400 int usb_device_destroy_pipes(ddf_dev_t *dev, 401 usb_endpoint_mapping_t *pipes, size_t pipes_count) 402 { 403 assert(dev != NULL); 404 assert(((pipes != NULL) && (pipes_count > 0)) 405 || ((pipes == NULL) && (pipes_count == 0))); 406 407 if (pipes_count == 0) { 408 return EOK; 409 } 410 411 int rc; 412 413 /* Prepare connection to HC to allow endpoint unregistering. */ 414 usb_hc_connection_t hc_conn; 415 rc = usb_hc_connection_initialize_from_device(&hc_conn, dev); 416 if (rc != EOK) { 417 return rc; 418 } 419 rc = usb_hc_connection_open(&hc_conn); 420 if (rc != EOK) { 421 return rc; 422 } 423 424 /* Destroy the pipes. */ 425 size_t i; 426 for (i = 0; i < pipes_count; i++) { 427 usb_pipe_unregister(pipes[i].pipe, &hc_conn); 428 free(pipes[i].pipe); 429 } 430 431 usb_hc_connection_close(&hc_conn); 432 433 free(pipes); 434 435 return EOK; 436 } 437 438 /** Initialize control pipe in a device. 439 * 440 * @param dev USB device in question. 441 * @param errmsg Where to store error context. 442 * @return 443 */ 444 static int init_wire_and_ctrl_pipe(usb_device_t *dev, const char **errmsg) 445 { 446 int rc; 447 448 rc = usb_device_connection_initialize_from_device(&dev->wire, 449 dev->ddf_dev); 450 if (rc != EOK) { 451 *errmsg = "device connection initialization"; 452 return rc; 453 } 454 455 rc = usb_pipe_initialize_default_control(&dev->ctrl_pipe, 456 &dev->wire); 457 if (rc != EOK) { 458 *errmsg = "default control pipe initialization"; 459 return rc; 460 } 461 462 return EOK; 463 } 464 465 466 /** Create new instance of USB device. 467 * 468 * @param[in] ddf_dev Generic DDF device backing the USB one. 469 * @param[in] endpoints NULL terminated array of endpoints (NULL for none). 470 * @param[out] dev_ptr Where to store pointer to the new device. 471 * @param[out] errstr_ptr Where to store description of context 472 * (in case error occurs). 473 * @return Error code. 474 */ 475 int usb_device_create(ddf_dev_t *ddf_dev, 476 usb_endpoint_description_t **endpoints, 477 usb_device_t **dev_ptr, const char **errstr_ptr) 478 { 479 assert(dev_ptr != NULL); 480 assert(ddf_dev != NULL); 481 482 int rc; 483 484 usb_device_t *dev = malloc(sizeof(usb_device_t)); 485 if (dev == NULL) { 486 *errstr_ptr = "structure allocation"; 487 return ENOMEM; 488 } 489 490 // FIXME: proper deallocation in case of errors 491 492 dev->ddf_dev = ddf_dev; 493 dev->driver_data = NULL; 494 dev->descriptors.configuration = NULL; 495 dev->alternate_interfaces = NULL; 496 497 dev->pipes_count = 0; 498 dev->pipes = NULL; 499 500 /* Initialize backing wire and control pipe. */ 501 rc = init_wire_and_ctrl_pipe(dev, errstr_ptr); 502 if (rc != EOK) { 503 return rc; 504 } 505 506 /* Get our interface. */ 507 dev->interface_no = usb_device_get_assigned_interface(dev->ddf_dev); 508 509 /* Retrieve standard descriptors. */ 510 rc = usb_device_retrieve_descriptors(&dev->ctrl_pipe, 511 &dev->descriptors); 512 if (rc != EOK) { 513 *errstr_ptr = "descriptor retrieval"; 514 return rc; 515 } 516 517 /* Create alternate interfaces. */ 518 rc = usb_alternate_interfaces_create(dev->descriptors.configuration, 519 dev->descriptors.configuration_size, dev->interface_no, 520 &dev->alternate_interfaces); 521 if (rc != EOK) { 522 /* We will try to silently ignore this. */ 523 dev->alternate_interfaces = NULL; 524 } 525 526 rc = initialize_other_pipes(endpoints, dev, 0); 527 if (rc != EOK) { 528 *errstr_ptr = "pipes initialization"; 529 return rc; 530 } 531 532 *errstr_ptr = NULL; 533 *dev_ptr = dev; 534 535 return EOK; 540 536 } 541 537 -
uspace/lib/usb/src/devpoll.c
ref354b6 re50cd7f 33 33 * USB device driver framework - automatic interrupt polling. 34 34 */ 35 #include <usb/dev drv.h>35 #include <usb/devpoll.h> 36 36 #include <usb/request.h> 37 37 #include <usb/debug.h> 38 #include <usb/classes/classes.h> 38 39 #include <errno.h> 39 40 #include <str_error.h> … … 45 46 /** Data needed for polling. */ 46 47 typedef struct { 48 int debug; 49 size_t max_failures; 50 useconds_t delay; 51 bool auto_clear_halt; 52 bool (*on_data)(usb_device_t *, uint8_t *, size_t, void *); 53 void (*on_polling_end)(usb_device_t *, bool, void *); 54 bool (*on_error)(usb_device_t *, int, void *); 55 47 56 usb_device_t *dev; 48 57 size_t pipe_index; 49 usb_polling_callback_t callback;50 usb_polling_terminted_callback_t terminated_callback;51 58 size_t request_size; 52 59 uint8_t *buffer; … … 54 61 } polling_data_t; 55 62 63 56 64 /** Polling fibril. 57 65 * … … 66 74 usb_pipe_t *pipe 67 75 = polling_data->dev->pipes[polling_data->pipe_index].pipe; 76 77 if (polling_data->debug > 0) { 78 usb_endpoint_mapping_t *mapping 79 = &polling_data->dev->pipes[polling_data->pipe_index]; 80 usb_log_debug("Poll0x%x: started polling of `%s' - " \ 81 "interface %d (%s,%d,%d), %zuB/%zu.\n", 82 polling_data, 83 polling_data->dev->ddf_dev->name, 84 (int) mapping->interface->interface_number, 85 usb_str_class(mapping->interface->interface_class), 86 (int) mapping->interface->interface_subclass, 87 (int) mapping->interface->interface_protocol, 88 polling_data->request_size, pipe->max_packet_size); 89 } 68 90 69 91 size_t failed_attempts = 0; 70 while (failed_attempts < MAX_FAILED_ATTEMPTS) {92 while (failed_attempts <= polling_data->max_failures) { 71 93 int rc; 72 73 rc = usb_pipe_start_session(pipe);74 if (rc != EOK) {75 failed_attempts++;76 continue;77 }78 94 79 95 size_t actual_size; … … 81 97 polling_data->request_size, &actual_size); 82 98 83 /* Quit the session regardless of errors. */ 84 usb_pipe_end_session(pipe); 99 if (polling_data->debug > 1) { 100 if (rc == EOK) { 101 usb_log_debug( 102 "Poll0x%x: received: '%s' (%zuB).\n", 103 polling_data, 104 usb_debug_str_buffer(polling_data->buffer, 105 actual_size, 16), 106 actual_size); 107 } else { 108 usb_log_debug( 109 "Poll0x%x: polling failed: %s.\n", 110 polling_data, str_error(rc)); 111 } 112 } 113 114 /* If the pipe stalled, we can try to reset the stall. */ 115 if ((rc == ESTALL) && (polling_data->auto_clear_halt)) { 116 /* 117 * We ignore error here as this is usually a futile 118 * attempt anyway. 119 */ 120 usb_request_clear_endpoint_halt( 121 &polling_data->dev->ctrl_pipe, 122 pipe->endpoint_no); 123 } 85 124 86 125 if (rc != EOK) { 126 if (polling_data->on_error != NULL) { 127 bool cont = polling_data->on_error( 128 polling_data->dev, rc, 129 polling_data->custom_arg); 130 if (!cont) { 131 failed_attempts 132 = polling_data->max_failures; 133 } 134 } 87 135 failed_attempts++; 88 136 continue; … … 90 138 91 139 /* We have the data, execute the callback now. */ 92 bool carry_on = polling_data-> callback(polling_data->dev,140 bool carry_on = polling_data->on_data(polling_data->dev, 93 141 polling_data->buffer, actual_size, 94 142 polling_data->custom_arg); … … 101 149 /* Reset as something might be only a temporary problem. */ 102 150 failed_attempts = 0; 103 } 104 105 if (failed_attempts > 0) { 106 usb_log_error( 107 "Polling of device `%s' terminated: recurring failures.\n", 108 polling_data->dev->ddf_dev->name); 109 } 110 111 if (polling_data->terminated_callback != NULL) { 112 polling_data->terminated_callback(polling_data->dev, 151 152 /* Take a rest before next request. */ 153 async_usleep(polling_data->delay); 154 } 155 156 if (polling_data->on_polling_end != NULL) { 157 polling_data->on_polling_end(polling_data->dev, 113 158 failed_attempts > 0, polling_data->custom_arg); 159 } 160 161 if (polling_data->debug > 0) { 162 if (failed_attempts > 0) { 163 usb_log_error( 164 "Polling of device `%s' terminated: %s.\n", 165 polling_data->dev->ddf_dev->name, 166 "recurring failures"); 167 } else { 168 usb_log_debug( 169 "Polling of device `%s' terminated by user.\n", 170 polling_data->dev->ddf_dev->name 171 ); 172 } 114 173 } 115 174 … … 154 213 } 155 214 215 usb_device_auto_polling_t *auto_polling 216 = malloc(sizeof(usb_device_auto_polling_t)); 217 if (auto_polling == NULL) { 218 return ENOMEM; 219 } 220 221 auto_polling->debug = 1; 222 auto_polling->auto_clear_halt = true; 223 auto_polling->delay = 0; 224 auto_polling->max_failures = MAX_FAILED_ATTEMPTS; 225 auto_polling->on_data = callback; 226 auto_polling->on_polling_end = terminated_callback; 227 auto_polling->on_error = NULL; 228 229 int rc = usb_device_auto_polling(dev, pipe_index, auto_polling, 230 request_size, arg); 231 232 free(auto_polling); 233 234 return rc; 235 } 236 237 /** Start automatic device polling over interrupt in pipe. 238 * 239 * The polling settings is copied thus it is okay to destroy the structure 240 * after this function returns. 241 * 242 * @warning There is no guarantee when the request to the device 243 * will be sent for the first time (it is possible that this 244 * first request would be executed prior to return from this function). 245 * 246 * @param dev Device to be periodically polled. 247 * @param pipe_index Index of the endpoint pipe used for polling. 248 * @param polling Polling settings. 249 * @param request_size How many bytes to ask for in each request. 250 * @param arg Custom argument (passed as is to the callbacks). 251 * @return Error code. 252 * @retval EOK New fibril polling the device was already started. 253 */ 254 int usb_device_auto_polling(usb_device_t *dev, size_t pipe_index, 255 usb_device_auto_polling_t *polling, 256 size_t request_size, void *arg) 257 { 258 if (dev == NULL) { 259 return EBADMEM; 260 } 261 if (pipe_index >= dev->pipes_count) { 262 return EINVAL; 263 } 264 if ((dev->pipes[pipe_index].pipe->transfer_type != USB_TRANSFER_INTERRUPT) 265 || (dev->pipes[pipe_index].pipe->direction != USB_DIRECTION_IN)) { 266 return EINVAL; 267 } 268 if ((polling == NULL) || (polling->on_data == NULL)) { 269 return EBADMEM; 270 } 271 156 272 polling_data_t *polling_data = malloc(sizeof(polling_data_t)); 157 273 if (polling_data == NULL) { … … 159 275 } 160 276 161 /* Allocate now to prevent immediate failure in the polling fibril. */162 polling_data->buffer = malloc( request_size);277 /* Fill-in the data. */ 278 polling_data->buffer = malloc(sizeof(request_size)); 163 279 if (polling_data->buffer == NULL) { 164 280 free(polling_data); 165 281 return ENOMEM; 166 282 } 283 polling_data->request_size = request_size; 167 284 polling_data->dev = dev; 168 285 polling_data->pipe_index = pipe_index; 169 polling_data->callback = callback;170 polling_data->terminated_callback = terminated_callback;171 polling_data->request_size = request_size;172 286 polling_data->custom_arg = arg; 287 288 polling_data->debug = polling->debug; 289 polling_data->max_failures = polling->max_failures; 290 if (polling->delay >= 0) { 291 polling_data->delay = (useconds_t) polling->delay; 292 } else { 293 polling_data->delay = (useconds_t) dev->pipes[pipe_index] 294 .descriptor->poll_interval; 295 } 296 polling_data->auto_clear_halt = polling->auto_clear_halt; 297 298 polling_data->on_data = polling->on_data; 299 polling_data->on_polling_end = polling->on_polling_end; 300 polling_data->on_error = polling->on_error; 173 301 174 302 fid_t fibril = fibril_create(polling_fibril, polling_data); … … 176 304 free(polling_data->buffer); 177 305 free(polling_data); 178 /* FIXME: better error code. */179 306 return ENOMEM; 180 307 } 181 308 fibril_add_ready(fibril); 182 309 183 /* The allocated buffer etc. will be freed by the fibril. */310 /* Fibril launched. That fibril will free the allocated data. */ 184 311 185 312 return EOK; -
uspace/lib/usb/src/hidparser.c
ref354b6 re50cd7f 877 877 878 878 offset = item->offset + (j * item->size); 879 880 879 // FIXME 881 880 if((size_t)(offset/8) != (size_t)((offset+item->size-1)/8)) { … … 1352 1351 1353 1352 field = list_get_instance(field_it, usb_hid_report_field_t, link); 1354 usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage); 1355 if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK) { 1356 ret++; 1357 } 1358 usb_hid_report_remove_last_item (field->collection_path); 1353 if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0){ 1354 usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage); 1355 if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK) { 1356 ret++; 1357 } 1358 usb_hid_report_remove_last_item (field->collection_path); 1359 } 1359 1360 1360 1361 field_it = field_it->next; … … 1536 1537 1537 1538 /** 1538 * Clones given report item structure and returns the new one1539 *1540 * @param item Report item structure to clone1541 * @return Clonned item1542 */1543 usb_hid_report_item_t *usb_hid_report_item_clone(const usb_hid_report_item_t *item)1544 {1545 usb_hid_report_item_t *new_report_item;1546 1547 if(!(new_report_item = malloc(sizeof(usb_hid_report_item_t)))) {1548 return NULL;1549 }1550 memcpy(new_report_item,item, sizeof(usb_hid_report_item_t));1551 link_initialize(&(new_report_item->link));1552 1553 return new_report_item;1554 }1555 1556 1557 /**1558 1539 * 1559 1540 * … … 1604 1585 } 1605 1586 1587 1588 usb_hid_report_item_t *usb_hid_report_item_clone(const usb_hid_report_item_t *item) 1589 { 1590 usb_hid_report_item_t *new_report_item; 1591 1592 if(!(new_report_item = malloc(sizeof(usb_hid_report_item_t)))) { 1593 return NULL; 1594 } 1595 memcpy(new_report_item,item, sizeof(usb_hid_report_item_t)); 1596 link_initialize(&(new_report_item->link)); 1597 1598 return new_report_item; 1599 } 1600 1601 1602 usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report, 1603 usb_hid_report_field_t *field, 1604 usb_hid_report_path_t *path, int flags, 1605 usb_hid_report_type_t type) 1606 { 1607 usb_hid_report_description_t *report_des = usb_hid_report_find_description (report, path->report_id, type); 1608 link_t *field_it; 1609 1610 if(report_des == NULL){ 1611 return NULL; 1612 } 1613 1614 if(field == NULL){ 1615 // vezmu prvni co mathuje podle path!! 1616 field_it = report_des->report_items.next; 1617 } 1618 else { 1619 field_it = field->link.next; 1620 } 1621 1622 while(field_it != &report_des->report_items) { 1623 field = list_get_instance(field_it, usb_hid_report_field_t, link); 1624 1625 usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage); 1626 if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK){ 1627 usb_hid_report_remove_last_item (field->collection_path); 1628 usb_log_debug("....OK\n"); 1629 return field; 1630 } 1631 usb_hid_report_remove_last_item (field->collection_path); 1632 1633 field_it = field_it->next; 1634 } 1635 1636 return NULL; 1637 } 1606 1638 /** 1607 1639 * @} -
uspace/lib/usb/src/hidreport.c
ref354b6 re50cd7f 80 80 d = usb_dp_get_sibling_descriptor(&parser, &parser_data, 81 81 dev->descriptors.configuration, d); 82 ++i; 82 83 } 83 84 … … 118 119 uint16_t length = hid_desc->report_desc_info.length; 119 120 size_t actual_size = 0; 120 121 /*122 * Start session for the control transfer.123 */124 int sess_rc = usb_pipe_start_session(&dev->ctrl_pipe);125 if (sess_rc != EOK) {126 usb_log_warning("Failed to start a session: %s.\n",127 str_error(sess_rc));128 return sess_rc;129 }130 121 131 122 /* … … 161 152 "%u)\n", actual_size, length); 162 153 return EINVAL; 163 }164 165 /*166 * End session for the control transfer.167 */168 sess_rc = usb_pipe_end_session(&dev->ctrl_pipe);169 if (sess_rc != EOK) {170 usb_log_warning("Failed to end a session: %s.\n",171 str_error(sess_rc));172 free(*report_desc);173 *report_desc = NULL;174 return sess_rc;175 154 } 176 155 -
uspace/lib/usb/src/hidreq.c
ref354b6 re50cd7f 56 56 * @retval EOK if successful. 57 57 * @retval EINVAL if no HID device is given. 58 * @return Other value inherited from one of functions 59 * usb_pipe_start_session(), usb_pipe_end_session(), 60 * usb_control_request_set(). 58 * @return Other value inherited from function usb_control_request_set(). 61 59 */ 62 60 int usbhid_req_set_report(usb_pipe_t *ctrl_pipe, int iface_no, … … 79 77 */ 80 78 81 int rc, sess_rc; 82 83 sess_rc = usb_pipe_start_session(ctrl_pipe); 84 if (sess_rc != EOK) { 85 usb_log_warning("Failed to start a session: %s.\n", 86 str_error(sess_rc)); 87 return sess_rc; 88 } 79 int rc; 89 80 90 81 uint16_t value = 0; … … 97 88 USB_HIDREQ_SET_REPORT, value, iface_no, buffer, buf_size); 98 89 99 sess_rc = usb_pipe_end_session(ctrl_pipe); 100 101 if (rc != EOK) { 102 usb_log_warning("Error sending output report to the keyboard: " 103 "%s.\n", str_error(rc)); 104 return rc; 105 } 106 107 if (sess_rc != EOK) { 108 usb_log_warning("Error closing session: %s.\n", 109 str_error(sess_rc)); 110 return sess_rc; 90 if (rc != EOK) { 91 usb_log_warning("Error sending output report to the keyboard: " 92 "%s.\n", str_error(rc)); 93 return rc; 111 94 } 112 95 … … 123 106 * @retval EOK if successful. 124 107 * @retval EINVAL if no HID device is given. 125 * @return Other value inherited from one of functions 126 * usb_pipe_start_session(), usb_pipe_end_session(), 127 * usb_control_request_set(). 108 * @return Other value inherited from function usb_control_request_set(). 128 109 */ 129 110 int usbhid_req_set_protocol(usb_pipe_t *ctrl_pipe, int iface_no, … … 146 127 */ 147 128 148 int rc, sess_rc; 149 150 sess_rc = usb_pipe_start_session(ctrl_pipe); 151 if (sess_rc != EOK) { 152 usb_log_warning("Failed to start a session: %s.\n", 153 str_error(sess_rc)); 154 return sess_rc; 155 } 129 int rc; 156 130 157 131 usb_log_debug("Sending Set_Protocol request to the device (" … … 162 136 USB_HIDREQ_SET_PROTOCOL, protocol, iface_no, NULL, 0); 163 137 164 sess_rc = usb_pipe_end_session(ctrl_pipe); 165 166 if (rc != EOK) { 167 usb_log_warning("Error sending output report to the keyboard: " 168 "%s.\n", str_error(rc)); 169 return rc; 170 } 171 172 if (sess_rc != EOK) { 173 usb_log_warning("Error closing session: %s.\n", 174 str_error(sess_rc)); 175 return sess_rc; 138 if (rc != EOK) { 139 usb_log_warning("Error sending output report to the keyboard: " 140 "%s.\n", str_error(rc)); 141 return rc; 176 142 } 177 143 … … 189 155 * @retval EOK if successful. 190 156 * @retval EINVAL if no HID device is given. 191 * @return Other value inherited from one of functions 192 * usb_pipe_start_session(), usb_pipe_end_session(), 193 * usb_control_request_set(). 157 * @return Other value inherited from function usb_control_request_set(). 194 158 */ 195 159 int usbhid_req_set_idle(usb_pipe_t *ctrl_pipe, int iface_no, uint8_t duration) … … 211 175 */ 212 176 213 int rc, sess_rc; 214 215 sess_rc = usb_pipe_start_session(ctrl_pipe); 216 if (sess_rc != EOK) { 217 usb_log_warning("Failed to start a session: %s.\n", 218 str_error(sess_rc)); 219 return sess_rc; 220 } 177 int rc; 221 178 222 179 usb_log_debug("Sending Set_Idle request to the device (" … … 229 186 USB_HIDREQ_SET_IDLE, value, iface_no, NULL, 0); 230 187 231 sess_rc = usb_pipe_end_session(ctrl_pipe); 232 233 if (rc != EOK) { 234 usb_log_warning("Error sending output report to the keyboard: " 235 "%s.\n", str_error(rc)); 236 return rc; 237 } 238 239 if (sess_rc != EOK) { 240 usb_log_warning("Error closing session: %s.\n", 241 str_error(sess_rc)); 242 return sess_rc; 188 if (rc != EOK) { 189 usb_log_warning("Error sending output report to the keyboard: " 190 "%s.\n", str_error(rc)); 191 return rc; 243 192 } 244 193 … … 259 208 * @retval EOK if successful. 260 209 * @retval EINVAL if no HID device is given. 261 * @return Other value inherited from one of functions 262 * usb_pipe_start_session(), usb_pipe_end_session(), 263 * usb_control_request_set(). 210 * @return Other value inherited from function usb_control_request_set(). 264 211 */ 265 212 int usbhid_req_get_report(usb_pipe_t *ctrl_pipe, int iface_no, … … 283 230 */ 284 231 285 int rc, sess_rc; 286 287 sess_rc = usb_pipe_start_session(ctrl_pipe); 288 if (sess_rc != EOK) { 289 usb_log_warning("Failed to start a session: %s.\n", 290 str_error(sess_rc)); 291 return sess_rc; 292 } 232 int rc; 293 233 294 234 uint16_t value = 0; … … 302 242 actual_size); 303 243 304 sess_rc = usb_pipe_end_session(ctrl_pipe); 305 306 if (rc != EOK) { 307 usb_log_warning("Error sending output report to the keyboard: " 308 "%s.\n", str_error(rc)); 309 return rc; 310 } 311 312 if (sess_rc != EOK) { 313 usb_log_warning("Error closing session: %s.\n", 314 str_error(sess_rc)); 315 return sess_rc; 244 if (rc != EOK) { 245 usb_log_warning("Error sending output report to the keyboard: " 246 "%s.\n", str_error(rc)); 247 return rc; 316 248 } 317 249 … … 328 260 * @retval EOK if successful. 329 261 * @retval EINVAL if no HID device is given. 330 * @return Other value inherited from one of functions 331 * usb_pipe_start_session(), usb_pipe_end_session(), 332 * usb_control_request_set(). 262 * @return Other value inherited from function usb_control_request_set(). 333 263 */ 334 264 int usbhid_req_get_protocol(usb_pipe_t *ctrl_pipe, int iface_no, … … 351 281 */ 352 282 353 int rc, sess_rc; 354 355 sess_rc = usb_pipe_start_session(ctrl_pipe); 356 if (sess_rc != EOK) { 357 usb_log_warning("Failed to start a session: %s.\n", 358 str_error(sess_rc)); 359 return sess_rc; 360 } 283 int rc; 361 284 362 285 usb_log_debug("Sending Get_Protocol request to the device (" … … 370 293 USB_HIDREQ_GET_PROTOCOL, 0, iface_no, buffer, 1, &actual_size); 371 294 372 sess_rc = usb_pipe_end_session(ctrl_pipe); 373 374 if (rc != EOK) { 375 usb_log_warning("Error sending output report to the keyboard: " 376 "%s.\n", str_error(rc)); 377 return rc; 378 } 379 380 if (sess_rc != EOK) { 381 usb_log_warning("Error closing session: %s.\n", 382 str_error(sess_rc)); 383 return sess_rc; 295 if (rc != EOK) { 296 usb_log_warning("Error sending output report to the keyboard: " 297 "%s.\n", str_error(rc)); 298 return rc; 384 299 } 385 300 … … 427 342 */ 428 343 429 int rc, sess_rc; 430 431 sess_rc = usb_pipe_start_session(ctrl_pipe); 432 if (sess_rc != EOK) { 433 usb_log_warning("Failed to start a session: %s.\n", 434 str_error(sess_rc)); 435 return sess_rc; 436 } 344 int rc; 437 345 438 346 usb_log_debug("Sending Get_Idle request to the device (" … … 448 356 &actual_size); 449 357 450 sess_rc = usb_pipe_end_session(ctrl_pipe); 451 452 if (rc != EOK) { 453 usb_log_warning("Error sending output report to the keyboard: " 454 "%s.\n", str_error(rc)); 455 return rc; 456 } 457 458 if (sess_rc != EOK) { 459 usb_log_warning("Error closing session: %s.\n", 460 str_error(sess_rc)); 461 return sess_rc; 358 if (rc != EOK) { 359 usb_log_warning("Error sending output report to the keyboard: " 360 "%s.\n", str_error(rc)); 361 return rc; 462 362 } 463 363 -
uspace/lib/usb/src/host/batch.c
ref354b6 re50cd7f 39 39 #include <usb/host/batch.h> 40 40 41 void usb_transfer_batch_call_in(usb_transfer_batch_t *instance); 42 void usb_transfer_batch_call_out(usb_transfer_batch_t *instance); 43 41 44 void usb_transfer_batch_init( 42 45 usb_transfer_batch_t *instance, 43 usb_target_t target, 44 usb_transfer_type_t transfer_type, 45 usb_speed_t speed, 46 size_t max_packet_size, 46 endpoint_t *ep, 47 47 char *buffer, 48 char * transport_buffer,48 char *data_buffer, 49 49 size_t buffer_size, 50 50 char *setup_buffer, … … 54 54 void *arg, 55 55 ddf_fun_t *fun, 56 endpoint_t *ep,57 void *private_data56 void *private_data, 57 void (*private_data_dtor)(void *p_data) 58 58 ) 59 59 { 60 60 assert(instance); 61 61 link_initialize(&instance->link); 62 instance->target = target; 63 instance->transfer_type = transfer_type; 64 instance->speed = speed; 65 instance->direction = USB_DIRECTION_BOTH; 62 instance->ep = ep; 66 63 instance->callback_in = func_in; 67 64 instance->callback_out = func_out; 68 65 instance->arg = arg; 69 66 instance->buffer = buffer; 70 instance-> transport_buffer = transport_buffer;67 instance->data_buffer = data_buffer; 71 68 instance->buffer_size = buffer_size; 72 69 instance->setup_buffer = setup_buffer; 73 70 instance->setup_size = setup_size; 74 instance->max_packet_size = max_packet_size;75 71 instance->fun = fun; 76 72 instance->private_data = private_data; 73 instance->private_data_dtor = private_data_dtor; 77 74 instance->transfered_size = 0; 78 75 instance->next_step = NULL; 79 76 instance->error = EOK; 80 instance->ep = ep; 77 endpoint_use(instance->ep); 78 } 79 /*----------------------------------------------------------------------------*/ 80 /** Helper function, calls callback and correctly destroys batch structure. 81 * 82 * @param[in] instance Batch structure to use. 83 */ 84 void usb_transfer_batch_call_in_and_dispose(usb_transfer_batch_t *instance) 85 { 86 assert(instance); 87 usb_transfer_batch_call_in(instance); 88 usb_transfer_batch_dispose(instance); 89 } 90 /*----------------------------------------------------------------------------*/ 91 /** Helper function calls callback and correctly destroys batch structure. 92 * 93 * @param[in] instance Batch structure to use. 94 */ 95 void usb_transfer_batch_call_out_and_dispose(usb_transfer_batch_t *instance) 96 { 97 assert(instance); 98 usb_transfer_batch_call_out(instance); 99 usb_transfer_batch_dispose(instance); 81 100 } 82 101 /*----------------------------------------------------------------------------*/ … … 86 105 * 87 106 */ 88 void usb_transfer_batch_finish(usb_transfer_batch_t *instance , int error)107 void usb_transfer_batch_finish(usb_transfer_batch_t *instance) 89 108 { 90 109 assert(instance); 91 instance->error = error; 110 assert(instance->ep); 111 endpoint_release(instance->ep); 92 112 instance->next_step(instance); 93 113 } … … 103 123 assert(instance); 104 124 assert(instance->callback_in); 125 assert(instance->ep); 105 126 106 127 /* We are data in, we need data */ 107 memcpy(instance->buffer, instance->transport_buffer, 108 instance->buffer_size); 128 memcpy(instance->buffer, instance->data_buffer, instance->buffer_size); 109 129 110 130 usb_log_debug("Batch %p done (T%d.%d, %s %s in, %zuB): %s (%d).\n", 111 instance, 112 instance->target.address, instance->target.endpoint, 113 usb_str_speed(instance->speed), 114 usb_str_transfer_type_short(instance->transfer_type), 115 instance->transfered_size, 116 str_error(instance->error), instance->error); 131 instance, instance->ep->address, instance->ep->endpoint, 132 usb_str_speed(instance->ep->speed), 133 usb_str_transfer_type_short(instance->ep->transfer_type), 134 instance->transfered_size, str_error(instance->error), instance->error); 117 135 118 136 instance->callback_in(instance->fun, instance->error, … … 130 148 131 149 usb_log_debug("Batch %p done (T%d.%d, %s %s out): %s (%d).\n", 132 instance, 133 instance->target.address, instance->target.endpoint, 134 usb_str_speed(instance->speed), 135 usb_str_transfer_type_short(instance->transfer_type), 150 instance, instance->ep->address, instance->ep->endpoint, 151 usb_str_speed(instance->ep->speed), 152 usb_str_transfer_type_short(instance->ep->transfer_type), 136 153 str_error(instance->error), instance->error); 137 154 … … 139 156 instance->error, instance->arg); 140 157 } 158 /*----------------------------------------------------------------------------*/ 159 /** Correctly dispose all used data structures. 160 * 161 * @param[in] instance Batch structure to use. 162 */ 163 void usb_transfer_batch_dispose(usb_transfer_batch_t *instance) 164 { 165 assert(instance); 166 usb_log_debug("Batch(%p) disposing.\n", instance); 167 if (instance->private_data) { 168 assert(instance->private_data_dtor); 169 instance->private_data_dtor(instance->private_data); 170 } 171 free(instance); 172 } 141 173 /** 142 174 * @} -
uspace/lib/usb/src/host/device_keeper.c
ref354b6 re50cd7f 48 48 { 49 49 assert(instance); 50 fibril_mutex_initialize(&instance->guard);51 fibril_condvar_initialize(&instance->change);52 instance->last_address = 0;53 50 unsigned i = 0; 54 51 for (; i < USB_ADDRESS_COUNT; ++i) { 55 52 instance->devices[i].occupied = false; 56 instance->devices[i].control_used = 0;57 53 instance->devices[i].handle = 0; 58 list_initialize(&instance->devices[i].endpoints);54 instance->devices[i].speed = USB_SPEED_MAX; 59 55 } 60 } 61 /*----------------------------------------------------------------------------*/ 62 void usb_device_keeper_add_ep( 63 usb_device_keeper_t *instance, usb_address_t address, endpoint_t *ep) 64 { 65 assert(instance); 66 fibril_mutex_lock(&instance->guard); 67 assert(instance->devices[address].occupied); 68 list_append(&ep->same_device_eps, &instance->devices[address].endpoints); 69 fibril_mutex_unlock(&instance->guard); 70 } 71 /*----------------------------------------------------------------------------*/ 72 /** Attempt to obtain address 0, blocks. 73 * 74 * @param[in] instance Device keeper structure to use. 75 * @param[in] speed Speed of the device requesting default address. 76 */ 77 void usb_device_keeper_reserve_default_address( 78 usb_device_keeper_t *instance, usb_speed_t speed) 79 { 80 assert(instance); 81 fibril_mutex_lock(&instance->guard); 82 while (instance->devices[USB_ADDRESS_DEFAULT].occupied) { 83 fibril_condvar_wait(&instance->change, &instance->guard); 84 } 85 instance->devices[USB_ADDRESS_DEFAULT].occupied = true; 86 instance->devices[USB_ADDRESS_DEFAULT].speed = speed; 87 fibril_mutex_unlock(&instance->guard); 88 } 89 /*----------------------------------------------------------------------------*/ 90 /** Attempt to obtain address 0, blocks. 91 * 92 * @param[in] instance Device keeper structure to use. 93 * @param[in] speed Speed of the device requesting default address. 94 */ 95 void usb_device_keeper_release_default_address(usb_device_keeper_t *instance) 96 { 97 assert(instance); 98 fibril_mutex_lock(&instance->guard); 99 instance->devices[USB_ADDRESS_DEFAULT].occupied = false; 100 fibril_mutex_unlock(&instance->guard); 101 fibril_condvar_signal(&instance->change); 102 } 103 /*----------------------------------------------------------------------------*/ 104 /** Check setup packet data for signs of toggle reset. 105 * 106 * @param[in] instance Device keeper structure to use. 107 * @param[in] target Device to receive setup packet. 108 * @param[in] data Setup packet data. 109 * 110 * Really ugly one. 111 */ 112 void usb_device_keeper_reset_if_need( 113 usb_device_keeper_t *instance, usb_target_t target, const uint8_t *data) 114 { 115 assert(instance); 116 fibril_mutex_lock(&instance->guard); 117 if (target.endpoint > 15 || target.endpoint < 0 118 || target.address >= USB_ADDRESS_COUNT || target.address < 0 119 || !instance->devices[target.address].occupied) { 120 fibril_mutex_unlock(&instance->guard); 121 usb_log_error("Invalid data when checking for toggle reset.\n"); 122 return; 123 } 124 125 switch (data[1]) 126 { 127 case 0x01: /*clear feature*/ 128 /* recipient is endpoint, value is zero (ENDPOINT_STALL) */ 129 if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) { 130 link_t *current = 131 instance->devices[target.address].endpoints.next; 132 while (current != 133 &instance->devices[target.address].endpoints) 134 { 135 /* endpoint number is < 16, thus first byte is enough */ 136 endpoint_toggle_reset_filtered( 137 current, data[4]); 138 current = current->next; 139 } 140 } 141 break; 142 143 case 0x9: /* set configuration */ 144 case 0x11: /* set interface */ 145 /* target must be device */ 146 if ((data[0] & 0xf) == 0) { 147 link_t *current = 148 instance->devices[target.address].endpoints.next; 149 while (current != 150 &instance->devices[target.address].endpoints) 151 { 152 endpoint_toggle_reset(current); 153 current = current->next; 154 } 155 } 156 break; 157 } 158 fibril_mutex_unlock(&instance->guard); 56 // TODO: is this hack enough? 57 // (it is needed to allow smooth registration at default address) 58 instance->devices[0].occupied = true; 59 instance->last_address = 0; 60 fibril_mutex_initialize(&instance->guard); 159 61 } 160 62 /*----------------------------------------------------------------------------*/ … … 184 86 assert(new_address != USB_ADDRESS_DEFAULT); 185 87 assert(instance->devices[new_address].occupied == false); 88 186 89 instance->devices[new_address].occupied = true; 187 90 instance->devices[new_address].speed = speed; 188 91 instance->last_address = new_address; 92 189 93 fibril_mutex_unlock(&instance->guard); 190 94 return new_address; … … 202 106 assert(instance); 203 107 fibril_mutex_lock(&instance->guard); 108 204 109 assert(address > 0); 205 110 assert(address <= USB11_ADDRESS_MAX); 206 111 assert(instance->devices[address].occupied); 112 207 113 instance->devices[address].handle = handle; 208 114 fibril_mutex_unlock(&instance->guard); … … 223 129 fibril_mutex_lock(&instance->guard); 224 130 assert(instance->devices[address].occupied); 131 225 132 instance->devices[address].occupied = false; 226 133 fibril_mutex_unlock(&instance->guard); … … 241 148 while (address <= USB11_ADDRESS_MAX) { 242 149 if (instance->devices[address].handle == handle) { 150 assert(instance->devices[address].occupied); 243 151 fibril_mutex_unlock(&instance->guard); 244 152 return address; … … 262 170 assert(address >= 0); 263 171 assert(address <= USB11_ADDRESS_MAX); 172 264 173 return instance->devices[address].speed; 265 }266 /*----------------------------------------------------------------------------*/267 void usb_device_keeper_use_control(268 usb_device_keeper_t *instance, usb_target_t target)269 {270 assert(instance);271 const uint16_t ep = 1 << target.endpoint;272 fibril_mutex_lock(&instance->guard);273 while (instance->devices[target.address].control_used & ep) {274 fibril_condvar_wait(&instance->change, &instance->guard);275 }276 instance->devices[target.address].control_used |= ep;277 fibril_mutex_unlock(&instance->guard);278 }279 /*----------------------------------------------------------------------------*/280 void usb_device_keeper_release_control(281 usb_device_keeper_t *instance, usb_target_t target)282 {283 assert(instance);284 const uint16_t ep = 1 << target.endpoint;285 fibril_mutex_lock(&instance->guard);286 assert((instance->devices[target.address].control_used & ep) != 0);287 instance->devices[target.address].control_used &= ~ep;288 fibril_mutex_unlock(&instance->guard);289 fibril_condvar_signal(&instance->change);290 174 } 291 175 /** -
uspace/lib/usb/src/host/endpoint.c
ref354b6 re50cd7f 34 34 */ 35 35 36 #include <assert.h> 36 37 #include <errno.h> 37 38 #include <usb/host/endpoint.h> … … 49 50 instance->max_packet_size = max_packet_size; 50 51 instance->toggle = 0; 51 link_initialize(&instance->same_device_eps); 52 instance->active = false; 53 fibril_mutex_initialize(&instance->guard); 54 fibril_condvar_initialize(&instance->avail); 55 endpoint_clear_hc_data(instance); 52 56 return EOK; 53 57 } … … 56 60 { 57 61 assert(instance); 58 list_remove(&instance->same_device_eps);62 assert(!instance->active); 59 63 free(instance); 64 } 65 /*----------------------------------------------------------------------------*/ 66 void endpoint_set_hc_data(endpoint_t *instance, 67 void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int)) 68 { 69 assert(instance); 70 instance->hc_data.data = data; 71 instance->hc_data.toggle_get = toggle_get; 72 instance->hc_data.toggle_set = toggle_set; 73 } 74 /*----------------------------------------------------------------------------*/ 75 void endpoint_clear_hc_data(endpoint_t *instance) 76 { 77 assert(instance); 78 instance->hc_data.data = NULL; 79 instance->hc_data.toggle_get = NULL; 80 instance->hc_data.toggle_set = NULL; 81 } 82 /*----------------------------------------------------------------------------*/ 83 void endpoint_use(endpoint_t *instance) 84 { 85 assert(instance); 86 fibril_mutex_lock(&instance->guard); 87 while (instance->active) 88 fibril_condvar_wait(&instance->avail, &instance->guard); 89 instance->active = true; 90 fibril_mutex_unlock(&instance->guard); 91 } 92 /*----------------------------------------------------------------------------*/ 93 void endpoint_release(endpoint_t *instance) 94 { 95 assert(instance); 96 fibril_mutex_lock(&instance->guard); 97 instance->active = false; 98 fibril_mutex_unlock(&instance->guard); 99 fibril_condvar_signal(&instance->avail); 60 100 } 61 101 /*----------------------------------------------------------------------------*/ … … 63 103 { 64 104 assert(instance); 105 if (instance->hc_data.toggle_get) 106 instance->toggle = 107 instance->hc_data.toggle_get(instance->hc_data.data); 65 108 return (int)instance->toggle; 66 109 } … … 70 113 assert(instance); 71 114 assert(toggle == 0 || toggle == 1); 115 if (instance->hc_data.toggle_set) 116 instance->hc_data.toggle_set(instance->hc_data.data, toggle); 72 117 instance->toggle = toggle; 73 118 } 74 119 /*----------------------------------------------------------------------------*/ 75 void endpoint_toggle_reset (link_t *ep)120 void endpoint_toggle_reset_filtered(endpoint_t *instance, usb_target_t target) 76 121 { 77 endpoint_t *instance =78 list_get_instance(ep, endpoint_t, same_device_eps);79 122 assert(instance); 80 instance->toggle = 0; 81 } 82 /*----------------------------------------------------------------------------*/ 83 void endpoint_toggle_reset_filtered(link_t *ep, usb_endpoint_t epn) 84 { 85 endpoint_t *instance = 86 list_get_instance(ep, endpoint_t, same_device_eps); 87 assert(instance); 88 if (instance->endpoint == epn) 89 instance->toggle = 0; 123 if (instance->address == target.address && 124 (instance->endpoint == target.endpoint || target.endpoint == 0)) 125 endpoint_toggle_set(instance, 0); 90 126 } 91 127 /** -
uspace/lib/usb/src/host/usb_endpoint_manager.c
ref354b6 re50cd7f 31 31 #include <errno.h> 32 32 33 #include <usb/debug.h> 33 34 #include <usb/host/usb_endpoint_manager.h> 34 35 … … 80 81 endpoint_destroy(node->ep); 81 82 free(node); 83 } 84 /*----------------------------------------------------------------------------*/ 85 static void node_toggle_reset_filtered(link_t *item, void *arg) 86 { 87 assert(item); 88 node_t *node = hash_table_get_instance(item, node_t, link); 89 usb_target_t *target = arg; 90 endpoint_toggle_reset_filtered(node->ep, *target); 82 91 } 83 92 /*----------------------------------------------------------------------------*/ … … 202 211 203 212 node_t *node = hash_table_get_instance(item, node_t, link); 213 if (node->ep->active) 214 return EBUSY; 215 204 216 instance->free_bw += node->bw; 205 217 hash_table_remove(&instance->ep_table, key, MAX_KEYS); … … 230 242 return node->ep; 231 243 } 244 /*----------------------------------------------------------------------------*/ 245 /** Check setup packet data for signs of toggle reset. 246 * 247 * @param[in] instance Device keeper structure to use. 248 * @param[in] target Device to receive setup packet. 249 * @param[in] data Setup packet data. 250 * 251 * Really ugly one. 252 */ 253 void usb_endpoint_manager_reset_if_need( 254 usb_endpoint_manager_t *instance, usb_target_t target, const uint8_t *data) 255 { 256 assert(instance); 257 if (target.endpoint > 15 || target.endpoint < 0 258 || target.address >= USB11_ADDRESS_MAX || target.address < 0) { 259 usb_log_error("Invalid data when checking for toggle reset.\n"); 260 return; 261 } 262 263 switch (data[1]) 264 { 265 case 0x01: /*clear feature*/ 266 /* recipient is endpoint, value is zero (ENDPOINT_STALL) */ 267 if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) { 268 /* endpoint number is < 16, thus first byte is enough */ 269 usb_target_t reset_target = 270 { .address = target.address, data[4] }; 271 fibril_mutex_lock(&instance->guard); 272 hash_table_apply(&instance->ep_table, 273 node_toggle_reset_filtered, &reset_target); 274 fibril_mutex_unlock(&instance->guard); 275 } 276 break; 277 278 case 0x9: /* set configuration */ 279 case 0x11: /* set interface */ 280 /* target must be device */ 281 if ((data[0] & 0xf) == 0) { 282 usb_target_t reset_target = 283 { .address = target.address, 0 }; 284 fibril_mutex_lock(&instance->guard); 285 hash_table_apply(&instance->ep_table, 286 node_toggle_reset_filtered, &reset_target); 287 fibril_mutex_unlock(&instance->guard); 288 } 289 break; 290 } 291 } -
uspace/lib/usb/src/hub.c
ref354b6 re50cd7f 40 40 #include <errno.h> 41 41 #include <assert.h> 42 #include <usb/debug.h> 43 44 /** How much time to wait between attempts to register endpoint 0:0. 45 * The value is based on typical value for port reset + some overhead. 46 */ 47 #define ENDPOINT_0_0_REGISTER_ATTEMPT_DELAY_USEC (1000 * (10 + 2)) 42 48 43 49 /** Check that HC connection is alright. … … 53 59 } while (false) 54 60 55 56 /** Tell host controller to reserve default address.57 *58 * @param connection Opened connection to host controller.59 * @param speed Speed of the device that will respond on the default address.60 * @return Error code.61 */62 int usb_hc_reserve_default_address(usb_hc_connection_t *connection,63 usb_speed_t speed)64 {65 CHECK_CONNECTION(connection);66 67 return async_req_2_0(connection->hc_phone,68 DEV_IFACE_ID(USBHC_DEV_IFACE),69 IPC_M_USBHC_RESERVE_DEFAULT_ADDRESS, speed);70 }71 72 /** Tell host controller to release default address.73 *74 * @param connection Opened connection to host controller.75 * @return Error code.76 */77 int usb_hc_release_default_address(usb_hc_connection_t *connection)78 {79 CHECK_CONNECTION(connection);80 81 return async_req_1_0(connection->hc_phone,82 DEV_IFACE_ID(USBHC_DEV_IFACE),83 IPC_M_USBHC_RELEASE_DEFAULT_ADDRESS);84 }85 86 61 /** Ask host controller for free address assignment. 87 62 * … … 178 153 * error codes than those listed as return codes by this function itself). 179 154 * 155 * The @p connection representing connection with host controller does not 156 * need to be started. 157 * This function duplicates the connection to allow simultaneous calls of 158 * this function (i.e. from different fibrils). 159 * 180 160 * @param[in] parent Parent device (i.e. the hub device). 181 * @param[in] connection Opened connection to host controller.161 * @param[in] connection Connection to host controller. 182 162 * @param[in] dev_speed New device speed. 183 163 * @param[in] enable_port Function for enabling signaling through the port the … … 206 186 ddf_dev_ops_t *dev_ops, void *new_dev_data, ddf_fun_t **new_fun) 207 187 { 208 CHECK_CONNECTION(connection); 188 assert(connection != NULL); 189 // FIXME: this is awful, we are accessing directly the structure. 190 usb_hc_connection_t hc_conn = { 191 .hc_handle = connection->hc_handle, 192 .hc_phone = -1 193 }; 194 195 int rc; 196 197 rc = usb_hc_connection_open(&hc_conn); 198 if (rc != EOK) { 199 return rc; 200 } 201 209 202 210 203 /* 211 204 * Request new address. 212 205 */ 213 usb_address_t dev_addr = usb_hc_request_address( connection, dev_speed);206 usb_address_t dev_addr = usb_hc_request_address(&hc_conn, dev_speed); 214 207 if (dev_addr < 0) { 208 usb_hc_connection_close(&hc_conn); 215 209 return EADDRNOTAVAIL; 216 210 } 217 211 218 int rc; 219 220 /* 221 * Reserve the default address. 222 */ 223 rc = usb_hc_reserve_default_address(connection, dev_speed); 224 if (rc != EOK) { 225 rc = EBUSY; 226 goto leave_release_free_address; 227 } 228 229 /* 230 * Enable the port (i.e. allow signaling through this port). 231 */ 232 rc = enable_port(port_no, arg); 233 if (rc != EOK) { 234 goto leave_release_default_address; 235 } 236 237 /* 238 * Change the address from default to the free one. 239 * We need to create a new control pipe for that. 212 /* 213 * We will not register control pipe on default address. 214 * The registration might fail. That means that someone else already 215 * registered that endpoint. We will simply wait and try again. 216 * (Someone else already wants to add a new device.) 240 217 */ 241 218 usb_device_connection_t dev_conn; 242 219 rc = usb_device_connection_initialize_on_default_address(&dev_conn, 243 connection);220 &hc_conn); 244 221 if (rc != EOK) { 245 222 rc = ENOTCONN; 246 goto leave_release_ default_address;223 goto leave_release_free_address; 247 224 } 248 225 … … 252 229 if (rc != EOK) { 253 230 rc = ENOTCONN; 231 goto leave_release_free_address; 232 } 233 234 do { 235 rc = usb_pipe_register_with_speed(&ctrl_pipe, dev_speed, 0, 236 &hc_conn); 237 if (rc != EOK) { 238 /* Do not overheat the CPU ;-). */ 239 async_usleep(ENDPOINT_0_0_REGISTER_ATTEMPT_DELAY_USEC); 240 } 241 } while (rc != EOK); 242 243 /* 244 * Endpoint is registered. We can enable the port and change 245 * device address. 246 */ 247 rc = enable_port(port_no, arg); 248 if (rc != EOK) { 254 249 goto leave_release_default_address; 255 250 } 256 251 257 /* Before sending any traffic, we need to register this 258 * endpoint. 259 */ 260 rc = usb_pipe_register(&ctrl_pipe, 0, connection); 261 if (rc != EOK) { 262 rc = EREFUSED; 252 rc = usb_pipe_probe_default_control(&ctrl_pipe); 253 if (rc != EOK) { 254 rc = ESTALL; 263 255 goto leave_release_default_address; 264 256 } 265 rc = usb_pipe_probe_default_control(&ctrl_pipe); 266 if (rc != EOK) { 267 rc = ENOTCONN; 257 258 rc = usb_request_set_address(&ctrl_pipe, dev_addr); 259 if (rc != EOK) { 260 rc = ESTALL; 268 261 goto leave_release_default_address; 269 262 } 270 263 271 rc = usb_pipe_start_session(&ctrl_pipe); 272 if (rc != EOK) { 273 rc = ENOTCONN; 274 goto leave_unregister_endpoint; 275 } 276 277 rc = usb_request_set_address(&ctrl_pipe, dev_addr); 278 if (rc != EOK) { 279 rc = ESTALL; 280 goto leave_stop_session; 281 } 282 283 usb_pipe_end_session(&ctrl_pipe); 284 285 /* 286 * Register the control endpoint for the new device. 287 */ 288 rc = usb_pipe_register(&ctrl_pipe, 0, connection); 289 if (rc != EOK) { 290 rc = EREFUSED; 291 goto leave_unregister_endpoint; 292 } 293 294 /* 295 * Release the original endpoint. 296 */ 297 unregister_control_endpoint_on_default_address(connection); 298 299 /* 300 * Once the address is changed, we can return the default address. 301 */ 302 usb_hc_release_default_address(connection); 303 264 /* 265 * Address changed. We can release the original endpoint, thus 266 * allowing other to access the default address. 267 */ 268 unregister_control_endpoint_on_default_address(&hc_conn); 269 270 /* 271 * Time to register the new endpoint. 272 */ 273 rc = usb_pipe_register(&ctrl_pipe, 0, &hc_conn); 274 if (rc != EOK) { 275 goto leave_release_free_address; 276 } 304 277 305 278 /* … … 316 289 } 317 290 318 319 320 291 /* 321 292 * And now inform the host controller about the handle. … … 325 296 .handle = child_handle 326 297 }; 327 rc = usb_hc_register_device( connection, &new_device);298 rc = usb_hc_register_device(&hc_conn, &new_device); 328 299 if (rc != EOK) { 329 300 rc = EDESTADDRREQ; … … 349 320 * Completely ignoring errors here. 350 321 */ 351 352 leave_stop_session:353 usb_pipe_end_session(&ctrl_pipe);354 355 leave_unregister_endpoint:356 usb_pipe_unregister(&ctrl_pipe, connection);357 358 322 leave_release_default_address: 359 usb_ hc_release_default_address(connection);323 usb_pipe_unregister(&ctrl_pipe, &hc_conn); 360 324 361 325 leave_release_free_address: 362 usb_hc_unregister_device(connection, dev_addr); 326 usb_hc_unregister_device(&hc_conn, dev_addr); 327 328 usb_hc_connection_close(&hc_conn); 363 329 364 330 return rc; -
uspace/lib/usb/src/pipes.c
ref354b6 re50cd7f 41 41 #include <errno.h> 42 42 #include <assert.h> 43 #include "pipepriv.h" 43 44 44 45 #define IPC_AGAIN_DELAY (1000 * 2) /* 2ms */ … … 241 242 * necessary. 242 243 * 244 * @deprecated 245 * Obsoleted with introduction of usb_pipe_start_long_transfer 246 * 243 247 * @param pipe Endpoint pipe to start the session on. 244 248 * @return Error code. … … 246 250 int usb_pipe_start_session(usb_pipe_t *pipe) 247 251 { 248 assert(pipe); 249 250 if (usb_pipe_is_session_started(pipe)) { 251 return EBUSY; 252 } 253 254 int phone = devman_device_connect(pipe->wire->hc_handle, 0); 255 if (phone < 0) { 256 return phone; 257 } 258 259 pipe->hc_phone = phone; 260 252 usb_log_warning("usb_pipe_start_session() was deprecated.\n"); 261 253 return EOK; 262 254 } … … 265 257 /** Ends a session on the endpoint pipe. 266 258 * 259 * @deprecated 260 * Obsoleted with introduction of usb_pipe_end_long_transfer 261 * 267 262 * @see usb_pipe_start_session 268 263 * … … 272 267 int usb_pipe_end_session(usb_pipe_t *pipe) 273 268 { 274 assert(pipe); 275 276 if (!usb_pipe_is_session_started(pipe)) { 277 return ENOENT; 278 } 279 280 int rc = async_hangup(pipe->hc_phone); 281 if (rc != EOK) { 282 return rc; 283 } 284 285 pipe->hc_phone = -1; 286 269 usb_log_warning("usb_pipe_end_session() was deprecated.\n"); 287 270 return EOK; 288 271 } … … 298 281 bool usb_pipe_is_session_started(usb_pipe_t *pipe) 299 282 { 300 return (pipe->hc_phone >= 0); 283 pipe_acquire(pipe); 284 bool started = pipe->refcount > 0; 285 pipe_release(pipe); 286 return started; 287 } 288 289 /** Prepare pipe for a long transfer. 290 * 291 * By a long transfer is mean transfer consisting of several 292 * requests to the HC. 293 * Calling such function is optional and it has positive effect of 294 * improved performance because IPC session is initiated only once. 295 * 296 * @param pipe Pipe over which the transfer will happen. 297 * @return Error code. 298 */ 299 int usb_pipe_start_long_transfer(usb_pipe_t *pipe) 300 { 301 return pipe_add_ref(pipe); 302 } 303 304 /** Terminate a long transfer on a pipe. 305 * 306 * @see usb_pipe_start_long_transfer 307 * 308 * @param pipe Pipe where to end the long transfer. 309 */ 310 void usb_pipe_end_long_transfer(usb_pipe_t *pipe) 311 { 312 pipe_drop_ref(pipe); 301 313 } 302 314 -
uspace/lib/usb/src/pipesinit.c
ref354b6 re50cd7f 356 356 assert(connection); 357 357 358 fibril_mutex_initialize(&pipe->guard); 358 359 pipe->wire = connection; 359 360 pipe->hc_phone = -1; 361 fibril_mutex_initialize(&pipe->hc_phone_mutex); 360 362 pipe->endpoint_no = endpoint_no; 361 363 pipe->transfer_type = transfer_type; 362 364 pipe->max_packet_size = max_packet_size; 363 365 pipe->direction = direction; 366 pipe->refcount = 0; 367 pipe->auto_reset_halt = false; 364 368 365 369 return EOK; … … 382 386 0, USB_TRANSFER_CONTROL, CTRL_PIPE_MIN_PACKET_SIZE, 383 387 USB_DIRECTION_BOTH); 388 389 pipe->auto_reset_halt = true; 384 390 385 391 return rc; … … 413 419 int rc; 414 420 415 TRY_LOOP(failed_attempts) { 416 rc = usb_pipe_start_session(pipe); 417 if (rc == EOK) { 418 break; 419 } 420 } 421 rc = usb_pipe_start_long_transfer(pipe); 421 422 if (rc != EOK) { 422 423 return rc; … … 439 440 } 440 441 } 441 usb_pipe_end_ session(pipe);442 usb_pipe_end_long_transfer(pipe); 442 443 if (rc != EOK) { 443 444 return rc; … … 461 462 usb_hc_connection_t *hc_connection) 462 463 { 464 return usb_pipe_register_with_speed(pipe, USB_SPEED_MAX + 1, 465 interval, hc_connection); 466 } 467 468 /** Register endpoint with a speed at the host controller. 469 * 470 * You will rarely need to use this function because it is needed only 471 * if the registered endpoint is of address 0 and there is no other way 472 * to tell speed of the device at address 0. 473 * 474 * @param pipe Pipe to be registered. 475 * @param speed Speed of the device 476 * (invalid speed means use previously specified one). 477 * @param interval Polling interval. 478 * @param hc_connection Connection to the host controller (must be opened). 479 * @return Error code. 480 */ 481 int usb_pipe_register_with_speed(usb_pipe_t *pipe, usb_speed_t speed, 482 unsigned int interval, 483 usb_hc_connection_t *hc_connection) 484 { 463 485 assert(pipe); 464 486 assert(hc_connection); … … 468 490 } 469 491 470 #define _PACK(high, low) ((high) * 256 + (low)) 471 472 return async_req_5_0(hc_connection->hc_phone, 492 #define _PACK2(high, low) (((high) << 16) + (low)) 493 #define _PACK3(high, middle, low) (((((high) << 8) + (middle)) << 8) + (low)) 494 495 return async_req_4_0(hc_connection->hc_phone, 473 496 DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_REGISTER_ENDPOINT, 474 _PACK(pipe->wire->address, pipe->endpoint_no), 475 _PACK(pipe->transfer_type, pipe->direction), 476 pipe->max_packet_size, interval); 477 478 #undef _PACK 497 _PACK2(pipe->wire->address, pipe->endpoint_no), 498 _PACK3(speed, pipe->transfer_type, pipe->direction), 499 _PACK2(pipe->max_packet_size, interval)); 500 501 #undef _PACK2 502 #undef _PACK3 479 503 } 480 504 -
uspace/lib/usb/src/pipesio.c
ref354b6 re50cd7f 49 49 #include <assert.h> 50 50 #include <usbhc_iface.h> 51 #include <usb/request.h> 52 #include "pipepriv.h" 51 53 52 54 /** Request an in transfer, no checking of input parameters. … … 78 80 } 79 81 82 /* Ensure serialization over the phone. */ 83 pipe_start_transaction(pipe); 84 80 85 /* 81 86 * Make call identifying target USB device and type of transfer. 82 87 */ 83 aid_t opening_request = async_send_ 4(pipe->hc_phone,88 aid_t opening_request = async_send_3(pipe->hc_phone, 84 89 DEV_IFACE_ID(USBHC_DEV_IFACE), ipc_method, 85 90 pipe->wire->address, pipe->endpoint_no, 86 pipe->max_packet_size,87 91 NULL); 88 92 if (opening_request == 0) { 93 pipe_end_transaction(pipe); 89 94 return ENOMEM; 90 95 } … … 96 101 aid_t data_request = async_data_read(pipe->hc_phone, buffer, size, 97 102 &data_request_call); 103 104 /* 105 * Since now on, someone else might access the backing phone 106 * without breaking the transfer IPC protocol. 107 */ 108 pipe_end_transaction(pipe); 98 109 99 110 if (data_request == 0) { … … 146 157 147 158 if (buffer == NULL) { 148 159 return EINVAL; 149 160 } 150 161 151 162 if (size == 0) { 152 163 return EINVAL; 153 }154 155 if (!usb_pipe_is_session_started(pipe)) {156 return EBADF;157 164 } 158 165 … … 165 172 } 166 173 174 int rc; 175 rc = pipe_add_ref(pipe); 176 if (rc != EOK) { 177 return rc; 178 } 179 180 167 181 size_t act_size = 0; 168 int rc;169 182 170 183 rc = usb_pipe_read_no_checks(pipe, buffer, size, &act_size); 184 185 pipe_drop_ref(pipe); 186 171 187 if (rc != EOK) { 172 188 return rc; … … 210 226 } 211 227 228 /* Ensure serialization over the phone. */ 229 pipe_start_transaction(pipe); 230 212 231 /* 213 232 * Make call identifying target USB device and type of transfer. 214 233 */ 215 aid_t opening_request = async_send_ 4(pipe->hc_phone,234 aid_t opening_request = async_send_3(pipe->hc_phone, 216 235 DEV_IFACE_ID(USBHC_DEV_IFACE), ipc_method, 217 236 pipe->wire->address, pipe->endpoint_no, 218 pipe->max_packet_size,219 237 NULL); 220 238 if (opening_request == 0) { 239 pipe_end_transaction(pipe); 221 240 return ENOMEM; 222 241 } … … 226 245 */ 227 246 int rc = async_data_write_start(pipe->hc_phone, buffer, size); 247 248 /* 249 * Since now on, someone else might access the backing phone 250 * without breaking the transfer IPC protocol. 251 */ 252 pipe_end_transaction(pipe); 253 228 254 if (rc != EOK) { 229 255 async_wait_for(opening_request, NULL); … … 260 286 } 261 287 262 if (!usb_pipe_is_session_started(pipe)) {263 return EBADF;264 }265 266 288 if (pipe->direction != USB_DIRECTION_OUT) { 267 289 return EBADF; … … 272 294 } 273 295 274 int rc = usb_pipe_write_no_check(pipe, buffer, size); 296 int rc; 297 298 rc = pipe_add_ref(pipe); 299 if (rc != EOK) { 300 return rc; 301 } 302 303 rc = usb_pipe_write_no_check(pipe, buffer, size); 304 305 pipe_drop_ref(pipe); 275 306 276 307 return rc; 308 } 309 310 /** Try to clear endpoint halt of default control pipe. 311 * 312 * @param pipe Pipe for control endpoint zero. 313 */ 314 static void clear_self_endpoint_halt(usb_pipe_t *pipe) 315 { 316 assert(pipe != NULL); 317 318 if (!pipe->auto_reset_halt || (pipe->endpoint_no != 0)) { 319 return; 320 } 321 322 323 /* Prevent indefinite recursion. */ 324 pipe->auto_reset_halt = false; 325 usb_request_clear_endpoint_halt(pipe, 0); 326 pipe->auto_reset_halt = true; 277 327 } 278 328 … … 293 343 void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size) 294 344 { 345 /* Ensure serialization over the phone. */ 346 pipe_start_transaction(pipe); 347 295 348 /* 296 349 * Make call identifying target USB device and control transfer type. 297 350 */ 298 aid_t opening_request = async_send_ 4(pipe->hc_phone,351 aid_t opening_request = async_send_3(pipe->hc_phone, 299 352 DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_CONTROL_READ, 300 353 pipe->wire->address, pipe->endpoint_no, 301 pipe->max_packet_size,302 354 NULL); 303 355 if (opening_request == 0) { … … 311 363 setup_buffer, setup_buffer_size); 312 364 if (rc != EOK) { 365 pipe_end_transaction(pipe); 313 366 async_wait_for(opening_request, NULL); 314 367 return rc; … … 322 375 data_buffer, data_buffer_size, 323 376 &data_request_call); 377 378 /* 379 * Since now on, someone else might access the backing phone 380 * without breaking the transfer IPC protocol. 381 */ 382 pipe_end_transaction(pipe); 383 384 324 385 if (data_request == 0) { 325 386 async_wait_for(opening_request, NULL); … … 379 440 } 380 441 381 if (!usb_pipe_is_session_started(pipe)) {382 return EBADF;383 }384 385 442 if ((pipe->direction != USB_DIRECTION_BOTH) 386 443 || (pipe->transfer_type != USB_TRANSFER_CONTROL)) { … … 388 445 } 389 446 447 int rc; 448 449 rc = pipe_add_ref(pipe); 450 if (rc != EOK) { 451 return rc; 452 } 453 390 454 size_t act_size = 0; 391 intrc = usb_pipe_control_read_no_check(pipe,455 rc = usb_pipe_control_read_no_check(pipe, 392 456 setup_buffer, setup_buffer_size, 393 457 data_buffer, data_buffer_size, &act_size); 458 459 if (rc == ESTALL) { 460 clear_self_endpoint_halt(pipe); 461 } 462 463 pipe_drop_ref(pipe); 394 464 395 465 if (rc != EOK) { … … 418 488 void *data_buffer, size_t data_buffer_size) 419 489 { 490 /* Ensure serialization over the phone. */ 491 pipe_start_transaction(pipe); 492 420 493 /* 421 494 * Make call identifying target USB device and control transfer type. 422 495 */ 423 aid_t opening_request = async_send_ 5(pipe->hc_phone,496 aid_t opening_request = async_send_4(pipe->hc_phone, 424 497 DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_CONTROL_WRITE, 425 498 pipe->wire->address, pipe->endpoint_no, 426 499 data_buffer_size, 427 pipe->max_packet_size,428 500 NULL); 429 501 if (opening_request == 0) { 502 pipe_end_transaction(pipe); 430 503 return ENOMEM; 431 504 } … … 437 510 setup_buffer, setup_buffer_size); 438 511 if (rc != EOK) { 512 pipe_end_transaction(pipe); 439 513 async_wait_for(opening_request, NULL); 440 514 return rc; … … 447 521 rc = async_data_write_start(pipe->hc_phone, 448 522 data_buffer, data_buffer_size); 523 524 /* All data sent, pipe can be released. */ 525 pipe_end_transaction(pipe); 526 449 527 if (rc != EOK) { 450 528 async_wait_for(opening_request, NULL); 451 529 return rc; 452 530 } 531 } else { 532 /* No data to send, we can release the pipe for others. */ 533 pipe_end_transaction(pipe); 453 534 } 454 535 … … 491 572 } 492 573 493 if (!usb_pipe_is_session_started(pipe)) {494 return EBADF;495 }496 497 574 if ((pipe->direction != USB_DIRECTION_BOTH) 498 575 || (pipe->transfer_type != USB_TRANSFER_CONTROL)) { … … 500 577 } 501 578 502 int rc = usb_pipe_control_write_no_check(pipe, 579 int rc; 580 581 rc = pipe_add_ref(pipe); 582 if (rc != EOK) { 583 return rc; 584 } 585 586 rc = usb_pipe_control_write_no_check(pipe, 503 587 setup_buffer, setup_buffer_size, data_buffer, data_buffer_size); 588 589 if (rc == ESTALL) { 590 clear_self_endpoint_halt(pipe); 591 } 592 593 pipe_drop_ref(pipe); 504 594 505 595 return rc; -
uspace/lib/usb/src/recognise.c
ref354b6 re50cd7f 404 404 child->driver_data = dev_data; 405 405 406 rc = usb_pipe_start_session(&ctrl_pipe);407 if (rc != EOK) {408 goto failure;409 }410 411 406 rc = usb_device_create_match_ids(&ctrl_pipe, &child->match_ids); 412 if (rc != EOK) {413 goto failure;414 }415 416 rc = usb_pipe_end_session(&ctrl_pipe);417 407 if (rc != EOK) { 418 408 goto failure; -
uspace/lib/usb/src/request.c
ref354b6 re50cd7f 871 871 } 872 872 873 /** Clear halt bit of an endpoint pipe (after pipe stall). 874 * 875 * @param pipe Control pipe. 876 * @param ep_index Endpoint index (in native endianness). 877 * @return Error code. 878 */ 879 int usb_request_clear_endpoint_halt(usb_pipe_t *pipe, uint16_t ep_index) 880 { 881 return usb_request_clear_feature(pipe, 882 USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_ENDPOINT, 883 uint16_host2usb(USB_FEATURE_SELECTOR_ENDPOINT_HALT), 884 uint16_host2usb(ep_index)); 885 } 886 873 887 /** 874 888 * @}
Note:
See TracChangeset
for help on using the changeset viewer.