Changeset c7dd69d in mainline for uspace/lib/usb/src
- Timestamp:
- 2011-04-15T13:19:59Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- da1dd48
- Parents:
- e3b5129 (diff), 8fd4ba0 (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/src
- Files:
-
- 1 added
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usb/src/devdrv.c
re3b5129 rc7dd69d 100 100 usb_device_t *dev, int alternate_setting) 101 101 { 102 if (endpoints == NULL) { 103 dev->pipes = NULL; 104 dev->pipes_count = 0; 105 return EOK; 106 } 107 102 108 usb_endpoint_mapping_t *pipes; 103 109 size_t pipes_count; … … 109 115 110 116 if (rc != EOK) { 111 usb_log_error(112 "Failed to create endpoint pipes for `%s': %s.\n",113 dev->ddf_dev->name, str_error(rc));114 117 return rc; 115 118 } … … 117 120 dev->pipes = pipes; 118 121 dev->pipes_count = pipes_count; 119 120 return EOK;121 }122 123 /** Initialize all endpoint pipes.124 *125 * @param drv The driver.126 * @param dev The device to be initialized.127 * @return Error code.128 */129 static int initialize_pipes(usb_device_t *dev)130 {131 int rc;132 133 rc = usb_device_connection_initialize_from_device(&dev->wire,134 dev->ddf_dev);135 if (rc != EOK) {136 usb_log_error(137 "Failed initializing connection on device `%s'. %s.\n",138 dev->ddf_dev->name, str_error(rc));139 return rc;140 }141 142 rc = usb_pipe_initialize_default_control(&dev->ctrl_pipe,143 &dev->wire);144 if (rc != EOK) {145 usb_log_error("Failed to initialize default control pipe " \146 "on device `%s': %s.\n",147 dev->ddf_dev->name, str_error(rc));148 return rc;149 }150 151 rc = usb_pipe_probe_default_control(&dev->ctrl_pipe);152 if (rc != EOK) {153 usb_log_error(154 "Probing default control pipe on device `%s' failed: %s.\n",155 dev->ddf_dev->name, str_error(rc));156 return rc;157 }158 159 /* Get our interface. */160 dev->interface_no = usb_device_get_assigned_interface(dev->ddf_dev);161 162 /*163 * We will do some querying of the device, it is worth to prepare164 * the long transfer.165 */166 rc = usb_pipe_start_long_transfer(&dev->ctrl_pipe);167 if (rc != EOK) {168 usb_log_error("Failed to start transfer: %s.\n",169 str_error(rc));170 return rc;171 }172 173 /* Retrieve the descriptors. */174 rc = usb_device_retrieve_descriptors(&dev->ctrl_pipe,175 &dev->descriptors);176 if (rc != EOK) {177 usb_log_error("Failed to retrieve standard device " \178 "descriptors of %s: %s.\n",179 dev->ddf_dev->name, str_error(rc));180 return rc;181 }182 183 184 if (driver->endpoints != NULL) {185 rc = initialize_other_pipes(driver->endpoints, dev, 0);186 }187 188 usb_pipe_end_long_transfer(&dev->ctrl_pipe);189 190 /* Rollback actions. */191 if (rc != EOK) {192 if (dev->descriptors.configuration != NULL) {193 free(dev->descriptors.configuration);194 }195 }196 197 return rc;198 }199 200 /** Count number of alternate settings of a interface.201 *202 * @param config_descr Full configuration descriptor.203 * @param config_descr_size Size of @p config_descr in bytes.204 * @param interface_no Interface number.205 * @return Number of alternate interfaces for @p interface_no interface.206 */207 size_t usb_interface_count_alternates(uint8_t *config_descr,208 size_t config_descr_size, uint8_t interface_no)209 {210 assert(config_descr != NULL);211 assert(config_descr_size > 0);212 213 usb_dp_parser_t dp_parser = {214 .nesting = usb_dp_standard_descriptor_nesting215 };216 usb_dp_parser_data_t dp_data = {217 .data = config_descr,218 .size = config_descr_size,219 .arg = NULL220 };221 222 size_t alternate_count = 0;223 224 uint8_t *iface_ptr = usb_dp_get_nested_descriptor(&dp_parser,225 &dp_data, config_descr);226 while (iface_ptr != NULL) {227 usb_standard_interface_descriptor_t *iface228 = (usb_standard_interface_descriptor_t *) iface_ptr;229 if (iface->descriptor_type == USB_DESCTYPE_INTERFACE) {230 if (iface->interface_number == interface_no) {231 alternate_count++;232 }233 }234 iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data,235 config_descr, iface_ptr);236 }237 238 return alternate_count;239 }240 241 /** Initialize structures related to alternate interfaces.242 *243 * @param dev Device where alternate settings shall be initialized.244 * @return Error code.245 */246 static int initialize_alternate_interfaces(usb_device_t *dev)247 {248 if (dev->interface_no < 0) {249 dev->alternate_interfaces = NULL;250 return EOK;251 }252 253 usb_alternate_interfaces_t *alternates254 = malloc(sizeof(usb_alternate_interfaces_t));255 256 if (alternates == NULL) {257 return ENOMEM;258 }259 260 alternates->alternative_count261 = usb_interface_count_alternates(dev->descriptors.configuration,262 dev->descriptors.configuration_size, dev->interface_no);263 264 if (alternates->alternative_count == 0) {265 free(alternates);266 return ENOENT;267 }268 269 alternates->alternatives = malloc(alternates->alternative_count270 * sizeof(usb_alternate_interface_descriptors_t));271 if (alternates->alternatives == NULL) {272 free(alternates);273 return ENOMEM;274 }275 276 alternates->current = 0;277 278 usb_dp_parser_t dp_parser = {279 .nesting = usb_dp_standard_descriptor_nesting280 };281 usb_dp_parser_data_t dp_data = {282 .data = dev->descriptors.configuration,283 .size = dev->descriptors.configuration_size,284 .arg = NULL285 };286 287 usb_alternate_interface_descriptors_t *cur_alt_iface288 = &alternates->alternatives[0];289 290 uint8_t *iface_ptr = usb_dp_get_nested_descriptor(&dp_parser,291 &dp_data, dp_data.data);292 while (iface_ptr != NULL) {293 usb_standard_interface_descriptor_t *iface294 = (usb_standard_interface_descriptor_t *) iface_ptr;295 if ((iface->descriptor_type != USB_DESCTYPE_INTERFACE)296 || (iface->interface_number != dev->interface_no)) {297 iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser,298 &dp_data,299 dp_data.data, iface_ptr);300 continue;301 }302 303 cur_alt_iface->interface = iface;304 cur_alt_iface->nested_descriptors = iface_ptr + sizeof(*iface);305 306 /* Find next interface to count size of nested descriptors. */307 iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data,308 dp_data.data, iface_ptr);309 if (iface_ptr == NULL) {310 uint8_t *next = dp_data.data + dp_data.size;311 cur_alt_iface->nested_descriptors_size312 = next - cur_alt_iface->nested_descriptors;313 } else {314 cur_alt_iface->nested_descriptors_size315 = iface_ptr - cur_alt_iface->nested_descriptors;316 }317 318 cur_alt_iface++;319 }320 321 dev->alternate_interfaces = alternates;322 122 323 123 return EOK; … … 339 139 int rc; 340 140 341 usb_device_t *dev = malloc(sizeof(usb_device_t)); 342 if (dev == NULL) { 343 usb_log_error("Out of memory when adding device `%s'.\n", 344 gen_dev->name); 345 return ENOMEM; 346 } 347 348 349 dev->ddf_dev = gen_dev; 350 dev->ddf_dev->driver_data = dev; 351 dev->driver_data = NULL; 352 dev->descriptors.configuration = NULL; 353 354 dev->pipes_count = 0; 355 dev->pipes = NULL; 356 357 rc = initialize_pipes(dev); 358 if (rc != EOK) { 359 free(dev); 360 return rc; 361 } 362 363 (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 } 364 149 365 150 return driver->ops->add_device(dev); … … 395 180 * with usb_pipe_initialize_from_configuration(). 396 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 * 397 189 * @param dev USB device. 398 190 * @param alternate_setting Alternate setting to choose. … … 409 201 int rc; 410 202 411 /* TODO: more transactional behavior. */412 413 203 /* Destroy existing pipes. */ 414 204 rc = destroy_current_pipes(dev); … … 432 222 /** Retrieve basic descriptors from the device. 433 223 * 434 * @param[in] ctrl_pipe Control pipe with opened session.224 * @param[in] ctrl_pipe Control endpoint pipe. 435 225 * @param[out] descriptors Where to store the descriptors. 436 226 * @return Error code. … … 440 230 { 441 231 assert(descriptors != NULL); 442 assert(usb_pipe_is_session_started(ctrl_pipe));443 232 444 233 descriptors->configuration = NULL; 445 234 446 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 } 447 242 448 243 /* Get the device descriptor. */ 449 244 rc = usb_request_get_device_descriptor(ctrl_pipe, &descriptors->device); 450 245 if (rc != EOK) { 451 return rc;246 goto leave; 452 247 } 453 248 … … 456 251 ctrl_pipe, 0, (void **) &descriptors->configuration, 457 252 &descriptors->configuration_size); 458 if (rc != EOK) { 459 return rc; 460 }461 462 return EOK;253 254 leave: 255 usb_pipe_end_long_transfer(ctrl_pipe); 256 257 return rc; 463 258 } 464 259 … … 641 436 } 642 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; 536 } 537 643 538 /** 644 539 * @} -
uspace/lib/usb/src/devpoll.c
re3b5129 rc7dd69d 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 * … … 67 75 = polling_data->dev->pipes[polling_data->pipe_index].pipe; 68 76 69 usb_log_debug("Pipe interface number: %d, protocol: %d, subclass: %d, max packet size: %d\n", 70 polling_data->dev->pipes[polling_data->pipe_index].interface_no, 71 polling_data->dev->pipes[polling_data->pipe_index].description->interface_protocol, 72 polling_data->dev->pipes[polling_data->pipe_index].description->interface_subclass, 73 pipe->max_packet_size); 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 } 74 90 75 91 size_t failed_attempts = 0; 76 while (failed_attempts < MAX_FAILED_ATTEMPTS) {92 while (failed_attempts <= polling_data->max_failures) { 77 93 int rc; 78 94 … … 81 97 polling_data->request_size, &actual_size); 82 98 83 84 // if (rc == ESTALL) { 85 // usb_log_debug("Seding clear feature...\n"); 86 // usb_request_clear_feature(pipe, USB_REQUEST_TYPE_STANDARD, 87 // USB_REQUEST_RECIPIENT_ENDPOINT, 0, pipe->endpoint_no); 88 // continue; 89 // } 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 } 90 124 91 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 } 92 135 failed_attempts++; 93 136 continue; … … 95 138 96 139 /* We have the data, execute the callback now. */ 97 bool carry_on = polling_data-> callback(polling_data->dev,140 bool carry_on = polling_data->on_data(polling_data->dev, 98 141 polling_data->buffer, actual_size, 99 142 polling_data->custom_arg); … … 106 149 /* Reset as something might be only a temporary problem. */ 107 150 failed_attempts = 0; 108 } 109 110 if (failed_attempts > 0) { 111 usb_log_error( 112 "Polling of device `%s' terminated: recurring failures.\n", 113 polling_data->dev->ddf_dev->name); 114 } 115 116 if (polling_data->terminated_callback != NULL) { 117 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, 118 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 } 119 173 } 120 174 … … 159 213 } 160 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 161 272 polling_data_t *polling_data = malloc(sizeof(polling_data_t)); 162 273 if (polling_data == NULL) { … … 164 275 } 165 276 166 /* Allocate now to prevent immediate failure in the polling fibril. */167 polling_data->buffer = malloc( request_size);277 /* Fill-in the data. */ 278 polling_data->buffer = malloc(sizeof(request_size)); 168 279 if (polling_data->buffer == NULL) { 169 280 free(polling_data); 170 281 return ENOMEM; 171 282 } 283 polling_data->request_size = request_size; 172 284 polling_data->dev = dev; 173 285 polling_data->pipe_index = pipe_index; 174 polling_data->callback = callback;175 polling_data->terminated_callback = terminated_callback;176 polling_data->request_size = request_size;177 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; 178 301 179 302 fid_t fibril = fibril_create(polling_fibril, polling_data); … … 181 304 free(polling_data->buffer); 182 305 free(polling_data); 183 /* FIXME: better error code. */184 306 return ENOMEM; 185 307 } 186 308 fibril_add_ready(fibril); 187 309 188 /* The allocated buffer etc. will be freed by the fibril. */310 /* Fibril launched. That fibril will free the allocated data. */ 189 311 190 312 return EOK; -
uspace/lib/usb/src/hidreport.c
re3b5129 rc7dd69d 119 119 uint16_t length = hid_desc->report_desc_info.length; 120 120 size_t actual_size = 0; 121 122 /*123 * Start session for the control transfer.124 */125 int sess_rc = usb_pipe_start_session(&dev->ctrl_pipe);126 if (sess_rc != EOK) {127 usb_log_warning("Failed to start a session: %s.\n",128 str_error(sess_rc));129 return sess_rc;130 }131 121 132 122 /* … … 162 152 "%u)\n", actual_size, length); 163 153 return EINVAL; 164 }165 166 /*167 * End session for the control transfer.168 */169 sess_rc = usb_pipe_end_session(&dev->ctrl_pipe);170 if (sess_rc != EOK) {171 usb_log_warning("Failed to end a session: %s.\n",172 str_error(sess_rc));173 free(*report_desc);174 *report_desc = NULL;175 return sess_rc;176 154 } 177 155 -
uspace/lib/usb/src/hidreq.c
re3b5129 rc7dd69d 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
re3b5129 rc7dd69d 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 = ep->direction; 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;81 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); 82 100 } 83 101 /*----------------------------------------------------------------------------*/ … … 105 123 assert(instance); 106 124 assert(instance->callback_in); 125 assert(instance->ep); 107 126 108 127 /* We are data in, we need data */ 109 memcpy(instance->buffer, instance->transport_buffer, 110 instance->buffer_size); 128 memcpy(instance->buffer, instance->data_buffer, instance->buffer_size); 111 129 112 130 usb_log_debug("Batch %p done (T%d.%d, %s %s in, %zuB): %s (%d).\n", 113 instance, 114 instance->target.address, instance->target.endpoint, 115 usb_str_speed(instance->speed), 116 usb_str_transfer_type_short(instance->transfer_type), 117 instance->transfered_size, 118 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); 119 135 120 136 instance->callback_in(instance->fun, instance->error, … … 132 148 133 149 usb_log_debug("Batch %p done (T%d.%d, %s %s out): %s (%d).\n", 134 instance, 135 instance->target.address, instance->target.endpoint, 136 usb_str_speed(instance->speed), 137 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), 138 153 str_error(instance->error), instance->error); 139 154 … … 141 156 instance->error, instance->arg); 142 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 } 143 173 /** 144 174 * @} -
uspace/lib/usb/src/host/device_keeper.c
re3b5129 rc7dd69d 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) { … … 60 57 // (it is needed to allow smooth registration at default address) 61 58 instance->devices[0].occupied = true; 59 instance->last_address = 0; 60 fibril_mutex_initialize(&instance->guard); 62 61 } 63 /*----------------------------------------------------------------------------*/64 /** Attempt to obtain address 0, blocks.65 *66 * @param[in] instance Device keeper structure to use.67 * @param[in] speed Speed of the device requesting default address.68 */69 void usb_device_keeper_reserve_default_address(70 usb_device_keeper_t *instance, usb_speed_t speed)71 {72 assert(instance);73 fibril_mutex_lock(&instance->guard);74 while (instance->devices[USB_ADDRESS_DEFAULT].occupied) {75 fibril_condvar_wait(&instance->change, &instance->guard);76 }77 instance->devices[USB_ADDRESS_DEFAULT].occupied = true;78 instance->devices[USB_ADDRESS_DEFAULT].speed = speed;79 fibril_mutex_unlock(&instance->guard);80 }81 /*----------------------------------------------------------------------------*/82 /** Attempt to obtain address 0, blocks.83 *84 * @param[in] instance Device keeper structure to use.85 * @param[in] speed Speed of the device requesting default address.86 */87 void usb_device_keeper_release_default_address(usb_device_keeper_t *instance)88 {89 assert(instance);90 fibril_mutex_lock(&instance->guard);91 instance->devices[USB_ADDRESS_DEFAULT].occupied = false;92 fibril_mutex_unlock(&instance->guard);93 fibril_condvar_signal(&instance->change);94 }95 /*----------------------------------------------------------------------------*/96 62 /*----------------------------------------------------------------------------*/ 97 63 /** Get a free USB address … … 120 86 assert(new_address != USB_ADDRESS_DEFAULT); 121 87 assert(instance->devices[new_address].occupied == false); 88 122 89 instance->devices[new_address].occupied = true; 123 90 instance->devices[new_address].speed = speed; 124 91 instance->last_address = new_address; 92 125 93 fibril_mutex_unlock(&instance->guard); 126 94 return new_address; … … 138 106 assert(instance); 139 107 fibril_mutex_lock(&instance->guard); 108 140 109 assert(address > 0); 141 110 assert(address <= USB11_ADDRESS_MAX); 142 111 assert(instance->devices[address].occupied); 112 143 113 instance->devices[address].handle = handle; 144 114 fibril_mutex_unlock(&instance->guard); … … 159 129 fibril_mutex_lock(&instance->guard); 160 130 assert(instance->devices[address].occupied); 131 161 132 instance->devices[address].occupied = false; 162 133 fibril_mutex_unlock(&instance->guard); … … 177 148 while (address <= USB11_ADDRESS_MAX) { 178 149 if (instance->devices[address].handle == handle) { 150 assert(instance->devices[address].occupied); 179 151 fibril_mutex_unlock(&instance->guard); 180 152 return address; … … 198 170 assert(address >= 0); 199 171 assert(address <= USB11_ADDRESS_MAX); 172 200 173 return instance->devices[address].speed; 201 174 } -
uspace/lib/usb/src/host/endpoint.c
re3b5129 rc7dd69d 53 53 fibril_mutex_initialize(&instance->guard); 54 54 fibril_condvar_initialize(&instance->avail); 55 endpoint_clear_hc_data(instance); 55 56 return EOK; 56 57 } … … 61 62 assert(!instance->active); 62 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; 63 81 } 64 82 /*----------------------------------------------------------------------------*/ … … 85 103 { 86 104 assert(instance); 105 if (instance->hc_data.toggle_get) 106 instance->toggle = 107 instance->hc_data.toggle_get(instance->hc_data.data); 87 108 return (int)instance->toggle; 88 109 } … … 92 113 assert(instance); 93 114 assert(toggle == 0 || toggle == 1); 115 if (instance->hc_data.toggle_set) 116 instance->hc_data.toggle_set(instance->hc_data.data, toggle); 94 117 instance->toggle = toggle; 95 118 } … … 100 123 if (instance->address == target.address && 101 124 (instance->endpoint == target.endpoint || target.endpoint == 0)) 102 instance->toggle = 0;125 endpoint_toggle_set(instance, 0); 103 126 } 104 127 /** -
uspace/lib/usb/src/host/usb_endpoint_manager.c
re3b5129 rc7dd69d 211 211 212 212 node_t *node = hash_table_get_instance(item, node_t, link); 213 if (node->ep->active) 214 return EBUSY; 215 213 216 instance->free_bw += node->bw; 214 217 hash_table_remove(&instance->ep_table, key, MAX_KEYS); -
uspace/lib/usb/src/pipesinit.c
re3b5129 rc7dd69d 365 365 pipe->direction = direction; 366 366 pipe->refcount = 0; 367 pipe->auto_reset_halt = false; 367 368 368 369 return EOK; … … 385 386 0, USB_TRANSFER_CONTROL, CTRL_PIPE_MIN_PACKET_SIZE, 386 387 USB_DIRECTION_BOTH); 388 389 pipe->auto_reset_halt = true; 387 390 388 391 return rc; -
uspace/lib/usb/src/pipesio.c
re3b5129 rc7dd69d 49 49 #include <assert.h> 50 50 #include <usbhc_iface.h> 51 #include <usb/request.h> 51 52 #include "pipepriv.h" 52 53 … … 307 308 } 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; 327 } 328 309 329 310 330 /** Request a control read transfer, no checking of input parameters. … … 436 456 setup_buffer, setup_buffer_size, 437 457 data_buffer, data_buffer_size, &act_size); 458 459 if (rc == ESTALL) { 460 clear_self_endpoint_halt(pipe); 461 } 438 462 439 463 pipe_drop_ref(pipe); … … 563 587 setup_buffer, setup_buffer_size, data_buffer, data_buffer_size); 564 588 589 if (rc == ESTALL) { 590 clear_self_endpoint_halt(pipe); 591 } 592 565 593 pipe_drop_ref(pipe); 566 594 -
uspace/lib/usb/src/request.c
re3b5129 rc7dd69d 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.