Changeset df6ded8 in mainline for uspace/lib/usbdev/src
- Timestamp:
- 2018-02-28T16:37:50Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 1b20da0
- Parents:
- f5e5f73 (diff), b2dca8de (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. - git-author:
- Jakub Jermar <jakub@…> (2018-02-28 16:06:42)
- git-committer:
- Jakub Jermar <jakub@…> (2018-02-28 16:37:50)
- Location:
- uspace/lib/usbdev/src
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usbdev/src/devdrv.c
rf5e5f73 rdf6ded8 2 2 * Copyright (c) 2011 Vojtech Horky 3 3 * Copyright (c) 2011 Jan Vesely 4 * Copyright (c) 2018 Ondrej Hlavaty, Petr Manek, Michal Staruch 4 5 * All rights reserved. 5 6 * … … 48 49 #include <devman.h> 49 50 #include <errno.h> 51 #include <str_error.h> 50 52 #include <stdlib.h> 51 53 … … 56 58 /** Connection to device on USB bus */ 57 59 usb_dev_session_t *bus_session; 58 60 59 61 /** devman handle */ 60 62 devman_handle_t handle; 61 63 62 64 /** The default control pipe. */ 63 65 usb_pipe_t ctrl_pipe; 64 66 65 67 /** Other endpoint pipes. 66 68 * … … 69 71 */ 70 72 usb_endpoint_mapping_t *pipes; 71 73 72 74 /** Number of other endpoint pipes. */ 73 75 size_t pipes_count; 74 76 77 /** USB address of this device */ 78 usb_address_t address; 79 80 /** Depth in the USB hub hiearchy */ 81 unsigned depth; 82 83 /** USB speed of this device */ 84 usb_speed_t speed; 85 75 86 /** Current interface. 76 87 * … … 79 90 */ 80 91 int interface_no; 81 92 82 93 /** Alternative interfaces. */ 83 94 usb_alternate_interfaces_t alternate_interfaces; 84 95 85 96 /** Some useful descriptors for USB device. */ 86 97 usb_device_descriptors_t descriptors; 87 98 88 99 /** Generic DDF device backing this one. DO NOT TOUCH! */ 89 100 ddf_dev_t *ddf_dev; 90 101 91 102 /** Custom driver data. 92 103 * … … 146 157 return rc; 147 158 } 148 159 149 160 /* Change current alternative */ 150 161 usb_dev->alternate_interfaces.current = alternate_setting; … … 255 266 256 267 /* Register created pipes. */ 268 unsigned pipes_registered = 0; 257 269 for (size_t i = 0; i < pipe_count; i++) { 258 270 if (pipes[i].present) { 259 rc = usb_pipe_register(&pipes[i].pipe, 260 pipes[i].descriptor->poll_interval); 271 rc = usb_pipe_register(&pipes[i].pipe, pipes[i].descriptor, pipes[i].companion_descriptor); 261 272 if (rc != EOK) { 262 273 goto rollback_unregister_endpoints; 263 274 } 264 275 } 276 pipes_registered++; 265 277 } 266 278 … … 277 289 */ 278 290 rollback_unregister_endpoints: 279 for (size_t i = 0; i < pipe _count; i++) {291 for (size_t i = 0; i < pipes_registered; i++) { 280 292 if (pipes[i].present) { 281 293 usb_pipe_unregister(&pipes[i].pipe); … … 296 308 assert(usb_dev); 297 309 assert(usb_dev->pipes || usb_dev->pipes_count == 0); 298 310 299 311 /* Destroy the pipes. */ 312 int rc; 300 313 for (size_t i = 0; i < usb_dev->pipes_count; ++i) { 301 usb_log_debug2("Unregistering pipe %zu: %spresent. \n",314 usb_log_debug2("Unregistering pipe %zu: %spresent.", 302 315 i, usb_dev->pipes[i].present ? "" : "not "); 303 if (usb_dev->pipes[i].present) 304 usb_pipe_unregister(&usb_dev->pipes[i].pipe); 305 } 306 316 317 rc = usb_device_unmap_ep(usb_dev->pipes + i); 318 if (rc != EOK && rc != ENOENT) 319 usb_log_warning("Unregistering pipe %zu failed: %s", i, str_error(rc)); 320 } 321 307 322 free(usb_dev->pipes); 308 323 usb_dev->pipes = NULL; … … 327 342 } 328 343 329 usb_endpoint_mapping_t * usb_device_get_mapped_ep( 330 usb_device_t *usb_dev, usb_endpoint_t ep) 331 { 332 assert(usb_dev); 333 for (unsigned i = 0; i < usb_dev->pipes_count; ++i) { 334 if (usb_dev->pipes[i].pipe.endpoint_no == ep) 335 return &usb_dev->pipes[i]; 336 } 337 return NULL; 338 } 339 340 int usb_device_get_iface_number(usb_device_t *usb_dev) 344 int usb_device_unmap_ep(usb_endpoint_mapping_t *epm) 345 { 346 assert(epm); 347 348 if (!epm->present) 349 return ENOENT; 350 351 const int rc = usb_pipe_unregister(&epm->pipe); 352 if (rc != EOK) 353 return rc; 354 355 epm->present = false; 356 return EOK; 357 } 358 359 usb_address_t usb_device_get_address(const usb_device_t *usb_dev) 360 { 361 assert(usb_dev); 362 return usb_dev->depth; 363 } 364 365 unsigned usb_device_get_depth(const usb_device_t *usb_dev) 366 { 367 assert(usb_dev); 368 return usb_dev->depth; 369 } 370 371 usb_speed_t usb_device_get_speed(const usb_device_t *usb_dev) 372 { 373 assert(usb_dev); 374 return usb_dev->speed; 375 } 376 377 int usb_device_get_iface_number(const usb_device_t *usb_dev) 341 378 { 342 379 assert(usb_dev); … … 344 381 } 345 382 346 devman_handle_t usb_device_get_devman_handle( usb_device_t *usb_dev)383 devman_handle_t usb_device_get_devman_handle(const usb_device_t *usb_dev) 347 384 { 348 385 assert(usb_dev); … … 394 431 */ 395 432 static errno_t usb_device_init(usb_device_t *usb_dev, ddf_dev_t *ddf_dev, 396 const usb_endpoint_description_t **endpoints, const char **errstr_ptr, 397 devman_handle_t handle, int interface_no) 433 const usb_endpoint_description_t **endpoints, const char **errstr_ptr) 398 434 { 399 435 assert(usb_dev != NULL); … … 403 439 404 440 usb_dev->ddf_dev = ddf_dev; 405 usb_dev->handle = handle;406 usb_dev->interface_no = interface_no;407 441 usb_dev->driver_data = NULL; 408 442 usb_dev->descriptors.full_config = NULL; … … 411 445 usb_dev->pipes = NULL; 412 446 413 usb_dev->bus_session = usb_dev_connect( handle);447 usb_dev->bus_session = usb_dev_connect(usb_dev->handle); 414 448 415 449 if (!usb_dev->bus_session) { … … 420 454 /* This pipe was registered by the hub driver, 421 455 * during device initialization. */ 422 errno_t rc = usb_pipe_initialize_default_control( 423 &usb_dev->ctrl_pipe, usb_dev->bus_session); 456 errno_t rc = usb_pipe_initialize_default_control(&usb_dev->ctrl_pipe, usb_dev->bus_session); 424 457 if (rc != EOK) { 425 458 usb_dev_disconnect(usb_dev->bus_session); … … 440 473 * it makes no sense to speak about alternate interfaces when 441 474 * controlling a device. */ 442 rc =usb_alternate_interfaces_init(&usb_dev->alternate_interfaces,475 usb_alternate_interfaces_init(&usb_dev->alternate_interfaces, 443 476 usb_dev->descriptors.full_config, 444 477 usb_dev->descriptors.full_config_size, usb_dev->interface_no); … … 457 490 } 458 491 459 static errno_t usb_device_get_info(async_sess_t *sess, devman_handle_t *handle, 460 int *iface_no) 461 { 462 assert(handle); 463 assert(iface_no); 464 492 static errno_t usb_device_get_info(async_sess_t *sess, usb_device_t *dev) 493 { 494 assert(dev); 495 465 496 async_exch_t *exch = async_exchange_begin(sess); 466 497 if (!exch) 467 498 return EPARTY; 468 469 errno_t ret = usb_get_my_device_handle(exch, handle); 499 500 usb_device_desc_t dev_desc; 501 const errno_t ret = usb_get_my_description(exch, &dev_desc); 502 470 503 if (ret == EOK) { 471 ret = usb_get_my_interface(exch, iface_no);472 if (ret == ENOTSUP) {473 *iface_no = -1;474 ret = EOK;475 }476 } 477 504 dev->address = dev_desc.address; 505 dev->depth = dev_desc.depth; 506 dev->speed = dev_desc.speed; 507 dev->handle = dev_desc.handle; 508 dev->interface_no = dev_desc.iface; 509 } 510 478 511 async_exchange_end(exch); 479 512 return ret; … … 485 518 assert(ddf_dev); 486 519 assert(err); 487 488 devman_handle_t h = 0;489 int iface_no = -1;490 520 491 521 async_sess_t *sess = ddf_dev_parent_sess_get(ddf_dev); 492 522 if (sess == NULL) 493 523 return ENOMEM; 494 const errno_t ret = usb_device_get_info(sess, &h, &iface_no);495 if (ret != EOK)496 return ret;497 524 498 525 usb_device_t *usb_dev = … … 502 529 return ENOMEM; 503 530 } 504 505 return usb_device_init(usb_dev, ddf_dev, desc, err, h, iface_no); 531 532 const errno_t ret = usb_device_get_info(sess, usb_dev); 533 if (ret != EOK) 534 return ret; 535 536 return usb_device_init(usb_dev, ddf_dev, desc, err); 506 537 } 507 538 … … 517 548 usb_device_t * usb_device_create(devman_handle_t handle) 518 549 { 519 devman_handle_t h = 0;520 int iface_no = -1;521 522 async_sess_t *sess = devman_device_connect(handle, IPC_FLAG_BLOCKING);523 errno_t ret = usb_device_get_info(sess, &h, &iface_no);524 if (sess)525 async_hangup(sess);526 if (ret != EOK)527 return NULL;528 529 550 usb_device_t *usb_dev = malloc(sizeof(usb_device_t)); 530 551 if (!usb_dev) 531 552 return NULL; 532 553 554 async_sess_t *sess = devman_device_connect(handle, IPC_FLAG_BLOCKING); 555 errno_t ret = usb_device_get_info(sess, usb_dev); 556 if (sess) 557 async_hangup(sess); 558 if (ret != EOK) { 559 free(usb_dev); 560 return NULL; 561 } 562 533 563 const char* dummy = NULL; 534 ret = usb_device_init(usb_dev, NULL, NULL, &dummy , handle, iface_no);564 ret = usb_device_init(usb_dev, NULL, NULL, &dummy); 535 565 if (ret != EOK) { 536 566 free(usb_dev); -
uspace/lib/usbdev/src/devpoll.c
rf5e5f73 rdf6ded8 1 1 /* 2 2 * Copyright (c) 2011 Vojtech Horky 3 * Copyright (c) 2017 Petr Manek 3 4 * All rights reserved. 4 5 * … … 47 48 #include <errno.h> 48 49 #include <fibril.h> 50 #include <fibril_synch.h> 49 51 #include <stdbool.h> 50 52 #include <stdlib.h> … … 53 55 #include <stdint.h> 54 56 55 /** Maximum number of failed consecutive requests before announcing failure. */ 56 #define MAX_FAILED_ATTEMPTS 3 57 58 /** Data needed for polling. */ 59 typedef struct { 60 /** Parameters for automated polling. */ 61 usb_device_auto_polling_t auto_polling; 62 63 /** USB device to poll. */ 64 usb_device_t *dev; 65 /** Device enpoint mapping to use for polling. */ 66 usb_endpoint_mapping_t *polling_mapping; 67 /** Size of the recieved data. */ 68 size_t request_size; 69 /** Data buffer. */ 70 uint8_t *buffer; 71 } polling_data_t; 57 58 /** Initialize the polling data structure, its internals and configuration 59 * with default values. 60 * 61 * @param polling Valid polling data structure. 62 * @return Error code. 63 * @retval EOK Polling data structure is ready to be used. 64 */ 65 int usb_polling_init(usb_polling_t *polling) 66 { 67 if (!polling) 68 return EBADMEM; 69 70 /* Zero out everything */ 71 memset(polling, 0, sizeof(usb_polling_t)); 72 73 /* Internal initializers. */ 74 fibril_mutex_initialize(&polling->guard); 75 fibril_condvar_initialize(&polling->cv); 76 77 /* Default configuration. */ 78 polling->auto_clear_halt = true; 79 polling->delay = -1; 80 polling->max_failures = 3; 81 82 return EOK; 83 } 84 85 86 /** Destroy the polling data structure. 87 * This function does nothing but a safety check whether the polling 88 * was joined successfully. 89 * 90 * @param polling Polling data structure. 91 */ 92 void usb_polling_fini(usb_polling_t *polling) 93 { 94 /* Nothing done at the moment. */ 95 assert(polling); 96 assert(!polling->running); 97 } 72 98 73 99 74 100 /** Polling fibril. 75 101 * 76 * @param arg Pointer to polling_data_t.102 * @param arg Pointer to usb_polling_t. 77 103 * @return Always EOK. 78 104 */ … … 80 106 { 81 107 assert(arg); 82 polling_data_t *data = arg; 83 /* Helper to reduce typing. */ 84 const usb_device_auto_polling_t *params = &data->auto_polling; 85 86 usb_pipe_t *pipe = &data->polling_mapping->pipe; 87 88 if (params->debug > 0) { 108 usb_polling_t *polling = arg; 109 110 fibril_mutex_lock(&polling->guard); 111 polling->running = true; 112 fibril_mutex_unlock(&polling->guard); 113 114 usb_pipe_t *pipe = &polling->ep_mapping->pipe; 115 116 if (polling->debug > 0) { 89 117 const usb_endpoint_mapping_t *mapping = 90 data->polling_mapping;118 polling->ep_mapping; 91 119 usb_log_debug("Poll (%p): started polling of `%s' - " \ 92 120 "interface %d (%s,%d,%d), %zuB/%zu.\n", 93 data, usb_device_get_name(data->dev),121 polling, usb_device_get_name(polling->device), 94 122 (int) mapping->interface->interface_number, 95 123 usb_str_class(mapping->interface->interface_class), 96 124 (int) mapping->interface->interface_subclass, 97 125 (int) mapping->interface->interface_protocol, 98 data->request_size, pipe->max_packet_size);126 polling->request_size, pipe->desc.max_transfer_size); 99 127 } 100 128 101 129 size_t failed_attempts = 0; 102 while (failed_attempts <= p arams->max_failures) {130 while (failed_attempts <= polling->max_failures) { 103 131 size_t actual_size; 104 const errno_t rc = usb_pipe_read(pipe, data->buffer,105 data->request_size, &actual_size);132 const errno_t rc = usb_pipe_read(pipe, polling->buffer, 133 polling->request_size, &actual_size); 106 134 107 135 if (rc == EOK) { 108 if (p arams->debug > 1) {136 if (polling->debug > 1) { 109 137 usb_log_debug( 110 138 "Poll%p: received: '%s' (%zuB).\n", 111 data,112 usb_debug_str_buffer( data->buffer,139 polling, 140 usb_debug_str_buffer(polling->buffer, 113 141 actual_size, 16), 114 142 actual_size); … … 117 145 usb_log_debug( 118 146 "Poll%p: polling failed: %s.\n", 119 data, str_error(rc));147 polling, str_error(rc)); 120 148 } 121 149 122 150 /* If the pipe stalled, we can try to reset the stall. */ 123 if ( (rc == ESTALL) && (params->auto_clear_halt)) {151 if (rc == ESTALL && polling->auto_clear_halt) { 124 152 /* 125 153 * We ignore error here as this is usually a futile 126 154 * attempt anyway. 127 155 */ 128 usb_request_clear_endpoint_halt( 129 usb_device_get_default_pipe(data->dev), 130 pipe->endpoint_no); 156 usb_pipe_clear_halt( 157 usb_device_get_default_pipe(polling->device), pipe); 131 158 } 132 159 133 160 if (rc != EOK) { 134 161 ++failed_attempts; 135 const bool cont = (params->on_error == NULL) ? true : 136 params->on_error(data->dev, rc, params->arg); 137 if (!cont) { 138 failed_attempts = params->max_failures; 162 const bool carry_on = !polling->on_error ? true : 163 polling->on_error(polling->device, rc, polling->arg); 164 165 if (!carry_on || polling->joining) { 166 /* This is user requested abort, erases failures. */ 167 failed_attempts = 0; 168 break; 139 169 } 140 170 continue; … … 142 172 143 173 /* We have the data, execute the callback now. */ 144 assert(p arams->on_data);145 const bool carry_on = p arams->on_data(146 data->dev, data->buffer, actual_size, params->arg);174 assert(polling->on_data); 175 const bool carry_on = polling->on_data(polling->device, 176 polling->buffer, actual_size, polling->arg); 147 177 148 178 if (!carry_on) { … … 156 186 157 187 /* Take a rest before next request. */ 158 188 159 189 // FIXME TODO: This is broken, the time is in ms not us. 160 190 // but first we need to fix drivers to actually stop using this, 161 191 // since polling delay should be implemented in HC schedule 162 async_usleep(p arams->delay);192 async_usleep(polling->delay); 163 193 } 164 194 165 195 const bool failed = failed_attempts > 0; 166 196 167 if (params->on_polling_end != NULL) { 168 params->on_polling_end(data->dev, failed, params->arg); 169 } 170 171 if (params->debug > 0) { 197 if (polling->on_polling_end) 198 polling->on_polling_end(polling->device, failed, polling->arg); 199 200 if (polling->debug > 0) { 172 201 if (failed) { 173 202 usb_log_error("Polling of device `%s' terminated: " 174 203 "recurring failures.\n", 175 usb_device_get_name( data->dev));204 usb_device_get_name(polling->device)); 176 205 } else { 177 206 usb_log_debug("Polling of device `%s' terminated: " 178 207 "driver request.\n", 179 usb_device_get_name( data->dev));208 usb_device_get_name(polling->device)); 180 209 } 181 210 } 182 211 183 /* Free the allocated memory. */ 184 free(data->buffer); 185 free(data); 186 212 fibril_mutex_lock(&polling->guard); 213 polling->running = false; 214 fibril_mutex_unlock(&polling->guard); 215 216 /* Notify joiners, if any. */ 217 fibril_condvar_broadcast(&polling->cv); 187 218 return EOK; 188 219 } … … 198 229 * first request would be executed prior to return from this function). 199 230 * 200 * @param dev Device to be periodically polled. 201 * @param epm Endpoint mapping to use. 202 * @param polling Polling settings. 203 * @param request_size How many bytes to ask for in each request. 204 * @param arg Custom argument (passed as is to the callbacks). 231 * @param polling Polling data structure. 205 232 * @return Error code. 206 233 * @retval EOK New fibril polling the device was already started. 207 234 */ 208 static errno_t usb_device_auto_polling_internal(usb_device_t *dev, 209 usb_endpoint_mapping_t *epm, const usb_device_auto_polling_t *polling, 210 size_t request_size) 211 { 212 if ((dev == NULL) || (polling == NULL) || (polling->on_data == NULL)) { 235 errno_t usb_polling_start(usb_polling_t *polling) 236 { 237 if (!polling || !polling->device || !polling->ep_mapping || !polling->on_data) 213 238 return EBADMEM; 214 } 215 216 if (request_size == 0) 239 240 if (!polling->request_size) 217 241 return EINVAL; 218 219 if (! epm || (epm->pipe.transfer_type != USB_TRANSFER_INTERRUPT) ||220 (epm->pipe.direction != USB_DIRECTION_IN))242 243 if (!polling->ep_mapping || (polling->ep_mapping->pipe.desc.transfer_type != USB_TRANSFER_INTERRUPT) 244 || (polling->ep_mapping->pipe.desc.direction != USB_DIRECTION_IN)) 221 245 return EINVAL; 222 223 224 polling_data_t *polling_data = malloc(sizeof(polling_data_t)); 225 if (polling_data == NULL) { 246 247 /* Negative value means use descriptor provided value. */ 248 if (polling->delay < 0) 249 polling->delay = polling->ep_mapping->descriptor->poll_interval; 250 251 polling->fibril = fibril_create(polling_fibril, polling); 252 if (!polling->fibril) 226 253 return ENOMEM; 227 } 228 229 /* Fill-in the data. */ 230 polling_data->buffer = malloc(sizeof(request_size)); 231 if (polling_data->buffer == NULL) { 232 free(polling_data); 233 return ENOMEM; 234 } 235 polling_data->request_size = request_size; 236 polling_data->dev = dev; 237 polling_data->polling_mapping = epm; 238 239 /* Copy provided settings. */ 240 polling_data->auto_polling = *polling; 241 242 /* Negative value means use descriptor provided value. */ 243 if (polling->delay < 0) { 244 polling_data->auto_polling.delay = 245 epm->descriptor->poll_interval; 246 } 247 248 fid_t fibril = fibril_create(polling_fibril, polling_data); 249 if (fibril == 0) { 250 free(polling_data->buffer); 251 free(polling_data); 252 return ENOMEM; 253 } 254 fibril_add_ready(fibril); 254 255 fibril_add_ready(polling->fibril); 255 256 256 257 /* Fibril launched. That fibril will free the allocated data. */ 257 258 258 return EOK; 259 259 } 260 /** Start automatic device polling over interrupt in pipe. 261 * 262 * The polling settings is copied thus it is okay to destroy the structure 263 * after this function returns. 264 * 265 * @warning There is no guarantee when the request to the device 266 * will be sent for the first time (it is possible that this 267 * first request would be executed prior to return from this function). 268 * 269 * @param dev Device to be periodically polled. 270 * @param pipe_index Index of the endpoint pipe used for polling. 271 * @param polling Polling settings. 272 * @param req_size How many bytes to ask for in each request. 273 * @param arg Custom argument (passed as is to the callbacks). 274 * @return Error code. 275 * @retval EOK New fibril polling the device was already started. 276 */ 277 errno_t usb_device_auto_polling(usb_device_t *usb_dev, usb_endpoint_t ep, 278 const usb_device_auto_polling_t *polling, size_t req_size) 279 { 280 usb_endpoint_mapping_t *epm = usb_device_get_mapped_ep(usb_dev, ep); 281 return usb_device_auto_polling_internal(usb_dev, epm, polling, req_size); 282 } 283 284 /** Start automatic device polling over interrupt in pipe. 285 * 286 * @warning It is up to the callback to produce delays between individual 287 * requests. 288 * 289 * @warning There is no guarantee when the request to the device 290 * will be sent for the first time (it is possible that this 291 * first request would be executed prior to return from this function). 292 * 293 * @param dev Device to be periodically polled. 294 * @param ep Endpoint used for polling. 295 * @param callback Callback when data are available. 296 * @param request_size How many bytes to ask for in each request. 297 * @param delay NUmber of ms to wait between queries, -1 to use descriptor val. 298 * @param terminated_callback Callback when polling is terminated. 299 * @param arg Custom argument (passed as is to the callbacks). 300 * @return Error code. 301 * @retval EOK New fibril polling the device was already started. 302 */ 303 errno_t usb_device_auto_poll(usb_device_t *dev, usb_endpoint_t ep, 304 usb_polling_callback_t callback, size_t request_size, int delay, 305 usb_polling_terminted_callback_t terminated_callback, void *arg) 306 { 307 const usb_device_auto_polling_t auto_polling = { 308 .debug = 1, 309 .auto_clear_halt = true, 310 .delay = delay, 311 .max_failures = MAX_FAILED_ATTEMPTS, 312 .on_data = callback, 313 .on_polling_end = terminated_callback, 314 .on_error = NULL, 315 .arg = arg, 316 }; 317 318 usb_endpoint_mapping_t *epm = usb_device_get_mapped_ep(dev, ep); 319 return usb_device_auto_polling_internal( 320 dev, epm, &auto_polling, request_size); 321 } 322 323 errno_t usb_device_auto_polling_desc(usb_device_t *usb_dev, 324 const usb_endpoint_description_t *desc, 325 const usb_device_auto_polling_t *polling, size_t req_size) 326 { 327 usb_endpoint_mapping_t *epm = 328 usb_device_get_mapped_ep_desc(usb_dev, desc); 329 return usb_device_auto_polling_internal(usb_dev, epm, polling, req_size); 330 } 331 332 errno_t usb_device_auto_poll_desc(usb_device_t * usb_dev, 333 const usb_endpoint_description_t *desc, usb_polling_callback_t callback, 334 size_t req_size, int delay, 335 usb_polling_terminted_callback_t terminated_callback, void *arg) 336 { 337 const usb_device_auto_polling_t auto_polling = { 338 .debug = 1, 339 .auto_clear_halt = true, 340 .delay = delay, 341 .max_failures = MAX_FAILED_ATTEMPTS, 342 .on_data = callback, 343 .on_polling_end = terminated_callback, 344 .on_error = NULL, 345 .arg = arg, 346 }; 347 348 usb_endpoint_mapping_t *epm = 349 usb_device_get_mapped_ep_desc(usb_dev, desc); 350 return usb_device_auto_polling_internal( 351 usb_dev, epm, &auto_polling, req_size); 260 261 /** Close the polling pipe permanently and synchronously wait 262 * until the automatic polling fibril terminates. 263 * 264 * It is safe to deallocate the polling data structure (and its 265 * data buffer) only after a successful call to this function. 266 * 267 * @warning Call to this function will trigger execution of the 268 * on_error() callback with EINTR error code. 269 * 270 * @parram polling Polling data structure. 271 * @return Error code. 272 * @retval EOK Polling fibril has been successfully terminated. 273 */ 274 errno_t usb_polling_join(usb_polling_t *polling) 275 { 276 errno_t rc; 277 if (!polling) 278 return EBADMEM; 279 280 /* Check if the fibril already terminated. */ 281 if (!polling->running) 282 return EOK; 283 284 /* Set the flag */ 285 polling->joining = true; 286 287 /* Unregister the pipe. */ 288 rc = usb_device_unmap_ep(polling->ep_mapping); 289 if (rc != EOK && rc != ENOENT && rc != EHANGUP) 290 return rc; 291 292 /* Wait for the fibril to terminate. */ 293 fibril_mutex_lock(&polling->guard); 294 while (polling->running) 295 fibril_condvar_wait(&polling->cv, &polling->guard); 296 fibril_mutex_unlock(&polling->guard); 297 298 return EOK; 352 299 } 353 300 -
uspace/lib/usbdev/src/dp.c
rf5e5f73 rdf6ded8 62 62 NESTING(CONFIGURATION, INTERFACE), 63 63 NESTING(INTERFACE, ENDPOINT), 64 NESTING(ENDPOINT, SSPEED_EP_COMPANION), 64 65 NESTING(INTERFACE, HUB), 65 66 NESTING(INTERFACE, HID), … … 126 127 * @retval -1 Invalid input. 127 128 */ 128 static int get_descriptor_type(const usb_dp_parser_data_t *data, const uint8_t *start) 129 static int get_descriptor_type(const usb_dp_parser_data_t *data, 130 const uint8_t *start) 129 131 { 130 132 if (start == NULL) { … … 257 259 int parent_type = get_descriptor_type(data, parent); 258 260 int possible_sibling_type = get_descriptor_type(data, possible_sibling); 259 if (is_nested_descriptor_type(parser, possible_sibling_type, parent_type)) { 261 if (is_nested_descriptor_type(parser, 262 possible_sibling_type, parent_type)) { 260 263 return possible_sibling; 261 264 } else { -
uspace/lib/usbdev/src/driver.c
rf5e5f73 rdf6ded8 2 2 * Copyright (c) 2011 Vojtech Horky 3 3 * Copyright (c) 2013 Jan Vesely 4 * Copyright (c) 2018 Petr Manek 4 5 * All rights reserved. 5 6 * … … 62 63 errno_t rc = usb_device_create_ddf(gen_dev, driver->endpoints, &err_msg); 63 64 if (rc != EOK) { 64 usb_log_error("USB device `%s' init failed (%s): %s. \n",65 usb_log_error("USB device `%s' init failed (%s): %s.", 65 66 ddf_dev_get_name(gen_dev), err_msg, str_error(rc)); 66 67 return rc; … … 85 86 assert(driver); 86 87 assert(driver->ops); 87 if (driver->ops->device_rem == NULL)88 if (driver->ops->device_remove == NULL) 88 89 return ENOTSUP; 90 89 91 /* Just tell the driver to stop whatever it is doing */ 90 92 usb_device_t *usb_dev = ddf_dev_data_get(gen_dev); 91 const errno_t ret = driver->ops->device_rem (usb_dev);93 const errno_t ret = driver->ops->device_remove(usb_dev); 92 94 if (ret != EOK) 93 95 return ret; 96 94 97 usb_device_destroy_ddf(gen_dev); 95 98 return EOK; … … 117 120 } 118 121 122 /** Callback when the driver is asked to online a specific function. 123 * 124 * This callback is a wrapper for USB specific version of @c fun_online. 125 * 126 * @param gen_dev Device function structure as prepared by DDF. 127 * @return Error code. 128 */ 129 static int generic_function_online(ddf_fun_t *fun) 130 { 131 assert(driver); 132 assert(driver->ops); 133 if (driver->ops->function_online == NULL) 134 return ENOTSUP; 135 return driver->ops->function_online(fun); 136 } 137 138 /** Callback when the driver is asked to offline a specific function. 139 * 140 * This callback is a wrapper for USB specific version of @c fun_offline. 141 * 142 * @param gen_dev Device function structure as prepared by DDF. 143 * @return Error code. 144 */ 145 static int generic_function_offline(ddf_fun_t *fun) 146 { 147 assert(driver); 148 assert(driver->ops); 149 if (driver->ops->function_offline == NULL) 150 return ENOTSUP; 151 return driver->ops->function_offline(fun); 152 } 153 119 154 static driver_ops_t generic_driver_ops = { 120 155 .dev_add = generic_device_add, 121 156 .dev_remove = generic_device_remove, 122 157 .dev_gone = generic_device_gone, 158 .fun_online = generic_function_online, 159 .fun_offline = generic_function_offline, 123 160 }; 124 161 static driver_t generic_driver = { -
uspace/lib/usbdev/src/pipes.c
rf5e5f73 rdf6ded8 2 2 * Copyright (c) 2011 Vojtech Horky 3 3 * Copyright (c) 2011 Jan Vesely 4 * Copyright (c) 2018 Ondrej Hlavaty, Michal Staruch 4 5 * All rights reserved. 5 6 * … … 36 37 #include <usb/dev/request.h> 37 38 #include <usb/usb.h> 38 #include <usb _iface.h>39 #include <usb/dma_buffer.h> 39 40 40 41 #include <assert.h> 42 #include <bitops.h> 41 43 #include <async.h> 44 #include <as.h> 42 45 #include <errno.h> 43 46 #include <mem.h> … … 51 54 assert(pipe != NULL); 52 55 53 if (!pipe->auto_reset_halt || (pipe-> endpoint_no != 0)) {56 if (!pipe->auto_reset_halt || (pipe->desc.endpoint_no != 0)) { 54 57 return; 55 58 } … … 57 60 /* Prevent infinite recursion. */ 58 61 pipe->auto_reset_halt = false; 59 usb_ request_clear_endpoint_halt(pipe, 0);62 usb_pipe_clear_halt(pipe, pipe); 60 63 pipe->auto_reset_halt = true; 64 } 65 66 /* Helper structure to avoid passing loads of arguments through */ 67 typedef struct { 68 usb_pipe_t *pipe; 69 usb_direction_t dir; 70 bool is_control; // Only for checking purposes 71 72 usbhc_iface_transfer_request_t req; 73 74 size_t transferred_size; 75 } transfer_t; 76 77 /** 78 * Issue a transfer in a separate exchange. 79 */ 80 static errno_t transfer_common(transfer_t *t) 81 { 82 if (!t->pipe) 83 return EBADMEM; 84 85 /* Only control writes make sense without buffer */ 86 if ((t->dir != USB_DIRECTION_OUT || !t->is_control) && t->req.size == 0) 87 return EINVAL; 88 89 /* Nonzero size requires buffer */ 90 if (!dma_buffer_is_set(&t->req.buffer) && t->req.size != 0) 91 return EINVAL; 92 93 /* Check expected direction */ 94 if (t->pipe->desc.direction != USB_DIRECTION_BOTH && 95 t->pipe->desc.direction != t->dir) 96 return EBADF; 97 98 /* Check expected transfer type */ 99 if ((t->pipe->desc.transfer_type == USB_TRANSFER_CONTROL) != t->is_control) 100 return EBADF; 101 102 async_exch_t *exch = async_exchange_begin(t->pipe->bus_session); 103 if (!exch) 104 return ENOMEM; 105 106 t->req.dir = t->dir; 107 t->req.endpoint = t->pipe->desc.endpoint_no; 108 109 const errno_t rc = usbhc_transfer(exch, &t->req, &t->transferred_size); 110 111 async_exchange_end(exch); 112 113 if (rc == ESTALL) 114 clear_self_endpoint_halt(t->pipe); 115 116 return rc; 117 } 118 119 /** 120 * Setup the transfer request inside transfer according to dma buffer provided. 121 * 122 * TODO: The buffer could have been allocated as a more strict one. Currently, 123 * we assume that the policy is just the requested one. 124 */ 125 static void setup_dma_buffer(transfer_t *t, void *base, void *ptr, size_t size) 126 { 127 t->req.buffer.virt = base; 128 t->req.buffer.policy = t->pipe->desc.transfer_buffer_policy; 129 t->req.offset = ptr - base; 130 t->req.size = size; 131 } 132 133 /** 134 * Compatibility wrapper for reads/writes without preallocated buffer. 135 */ 136 static errno_t transfer_wrap_dma(transfer_t *t, void *buf, size_t size) 137 { 138 if (size == 0) { 139 setup_dma_buffer(t, NULL, NULL, 0); 140 return transfer_common(t); 141 } 142 143 void *dma_buf = usb_pipe_alloc_buffer(t->pipe, size); 144 setup_dma_buffer(t, dma_buf, dma_buf, size); 145 146 if (t->dir == USB_DIRECTION_OUT) 147 memcpy(dma_buf, buf, size); 148 149 const errno_t err = transfer_common(t); 150 151 if (!err && t->dir == USB_DIRECTION_IN) 152 memcpy(buf, dma_buf, t->transferred_size); 153 154 usb_pipe_free_buffer(t->pipe, dma_buf); 155 return err; 156 } 157 158 static errno_t prepare_control(transfer_t *t, const void *setup, size_t setup_size) 159 { 160 if ((setup == NULL) || (setup_size != 8)) 161 return EINVAL; 162 163 memcpy(&t->req.setup, setup, 8); 164 return EOK; 61 165 } 62 166 … … 70 174 * @param[out] data_buffer Buffer for incoming data. 71 175 * @param[in] data_buffer_size Size of the buffer for incoming data (in bytes). 72 * @param[out] data_transfer ed_size Number of bytes that were actually73 * transfer ed during the DATA stage.176 * @param[out] data_transferred_size Number of bytes that were actually 177 * transferred during the DATA stage. 74 178 * @return Error code. 75 179 */ 76 180 errno_t usb_pipe_control_read(usb_pipe_t *pipe, 77 181 const void *setup_buffer, size_t setup_buffer_size, 78 void *buffer, size_t buffer_size, size_t *transfered_size) 79 { 80 assert(pipe); 81 82 if ((setup_buffer == NULL) || (setup_buffer_size != 8)) { 83 return EINVAL; 84 } 85 86 if ((buffer == NULL) || (buffer_size == 0)) { 87 return EINVAL; 88 } 89 90 if ((pipe->direction != USB_DIRECTION_BOTH) 91 || (pipe->transfer_type != USB_TRANSFER_CONTROL)) { 92 return EBADF; 93 } 94 95 uint64_t setup_packet; 96 memcpy(&setup_packet, setup_buffer, 8); 97 98 async_exch_t *exch = async_exchange_begin(pipe->bus_session); 99 size_t act_size = 0; 100 const errno_t rc = usb_read(exch, pipe->endpoint_no, setup_packet, buffer, 101 buffer_size, &act_size); 102 async_exchange_end(exch); 103 104 if (rc == ESTALL) { 105 clear_self_endpoint_halt(pipe); 106 } 107 108 if (rc == EOK && transfered_size != NULL) { 109 *transfered_size = act_size; 110 } 111 112 return rc; 182 void *buffer, size_t buffer_size, size_t *transferred_size) 183 { 184 errno_t err; 185 transfer_t transfer = { 186 .pipe = pipe, 187 .dir = USB_DIRECTION_IN, 188 .is_control = true, 189 }; 190 191 if ((err = prepare_control(&transfer, setup_buffer, setup_buffer_size))) 192 return err; 193 194 if ((err = transfer_wrap_dma(&transfer, buffer, buffer_size))) 195 return err; 196 197 if (transferred_size) 198 *transferred_size = transfer.transferred_size; 199 200 return EOK; 113 201 } 114 202 … … 129 217 { 130 218 assert(pipe); 131 132 if ((setup_buffer == NULL) || (setup_buffer_size != 8)) { 133 return EINVAL; 134 } 135 136 if ((buffer == NULL) && (buffer_size > 0)) { 137 return EINVAL; 138 } 139 140 if ((buffer != NULL) && (buffer_size == 0)) { 141 return EINVAL; 142 } 143 144 if ((pipe->direction != USB_DIRECTION_BOTH) 145 || (pipe->transfer_type != USB_TRANSFER_CONTROL)) { 146 return EBADF; 147 } 148 149 uint64_t setup_packet; 150 memcpy(&setup_packet, setup_buffer, 8); 151 152 async_exch_t *exch = async_exchange_begin(pipe->bus_session); 153 const errno_t rc = usb_write(exch, 154 pipe->endpoint_no, setup_packet, buffer, buffer_size); 155 async_exchange_end(exch); 156 157 if (rc == ESTALL) { 158 clear_self_endpoint_halt(pipe); 159 } 160 161 return rc; 219 errno_t err; 220 transfer_t transfer = { 221 .pipe = pipe, 222 .dir = USB_DIRECTION_OUT, 223 .is_control = true, 224 }; 225 226 if ((err = prepare_control(&transfer, setup_buffer, setup_buffer_size))) 227 return err; 228 229 return transfer_wrap_dma(&transfer, (void *) buffer, buffer_size); 230 } 231 232 /** 233 * Allocate a buffer for data transmission, that satisfies the constraints 234 * imposed by the host controller. 235 * 236 * @param[in] pipe Pipe for which the buffer is allocated 237 * @param[in] size Size of the required buffer 238 */ 239 void *usb_pipe_alloc_buffer(usb_pipe_t *pipe, size_t size) 240 { 241 dma_buffer_t buf; 242 if (dma_buffer_alloc_policy(&buf, size, pipe->desc.transfer_buffer_policy)) 243 return NULL; 244 245 return buf.virt; 246 } 247 248 void usb_pipe_free_buffer(usb_pipe_t *pipe, void *buffer) 249 { 250 dma_buffer_t buf; 251 buf.virt = buffer; 252 dma_buffer_free(&buf); 162 253 } 163 254 … … 167 258 * @param[out] buffer Buffer where to store the data. 168 259 * @param[in] size Size of the buffer (in bytes). 169 * @param[out] size_transfer ed Number of bytes that were actually transfered.260 * @param[out] size_transferred Number of bytes that were actually transferred. 170 261 * @return Error code. 171 262 */ 172 263 errno_t usb_pipe_read(usb_pipe_t *pipe, 173 void *buffer, size_t size, size_t *size_transfered) 174 { 175 assert(pipe); 176 177 if (buffer == NULL) { 178 return EINVAL; 179 } 180 181 if (size == 0) { 182 return EINVAL; 183 } 184 185 if (pipe->direction != USB_DIRECTION_IN) { 186 return EBADF; 187 } 188 189 if (pipe->transfer_type == USB_TRANSFER_CONTROL) { 190 return EBADF; 191 } 192 193 /* Isochronous transfer are not supported (yet) */ 194 if (pipe->transfer_type != USB_TRANSFER_INTERRUPT && 195 pipe->transfer_type != USB_TRANSFER_BULK) 196 return ENOTSUP; 197 198 async_exch_t *exch = async_exchange_begin(pipe->bus_session); 199 size_t act_size = 0; 200 const errno_t rc = 201 usb_read(exch, pipe->endpoint_no, 0, buffer, size, &act_size); 202 async_exchange_end(exch); 203 204 if (rc == EOK && size_transfered != NULL) { 205 *size_transfered = act_size; 206 } 207 208 return rc; 264 void *buffer, size_t size, size_t *size_transferred) 265 { 266 assert(pipe); 267 errno_t err; 268 transfer_t transfer = { 269 .pipe = pipe, 270 .dir = USB_DIRECTION_IN, 271 }; 272 273 if ((err = transfer_wrap_dma(&transfer, buffer, size))) 274 return err; 275 276 if (size_transferred) 277 *size_transferred = transfer.transferred_size; 278 279 return EOK; 209 280 } 210 281 … … 219 290 { 220 291 assert(pipe); 221 222 if (buffer == NULL || size == 0) { 223 return EINVAL; 224 } 225 226 if (pipe->direction != USB_DIRECTION_OUT) { 227 return EBADF; 228 } 229 230 if (pipe->transfer_type == USB_TRANSFER_CONTROL) { 231 return EBADF; 232 } 233 234 /* Isochronous transfer are not supported (yet) */ 235 if (pipe->transfer_type != USB_TRANSFER_INTERRUPT && 236 pipe->transfer_type != USB_TRANSFER_BULK) 237 return ENOTSUP; 238 239 async_exch_t *exch = async_exchange_begin(pipe->bus_session); 240 const errno_t rc = usb_write(exch, pipe->endpoint_no, 0, buffer, size); 241 async_exchange_end(exch); 242 return rc; 292 transfer_t transfer = { 293 .pipe = pipe, 294 .dir = USB_DIRECTION_OUT, 295 }; 296 297 return transfer_wrap_dma(&transfer, (void *) buffer, size); 298 } 299 300 /** 301 * Request a read (in) transfer on an endpoint pipe, declaring that buffer 302 * is pointing to a memory area previously allocated by usb_pipe_alloc_buffer. 303 * 304 * @param[in] pipe Pipe used for the transfer. 305 * @param[in] buffer Buffer, previously allocated with usb_pipe_alloc_buffer. 306 * @param[in] size Size of the buffer (in bytes). 307 * @param[out] size_transferred Number of bytes that were actually transferred. 308 * @return Error code. 309 */ 310 errno_t usb_pipe_read_dma(usb_pipe_t *pipe, void *base, void *ptr, size_t size, 311 size_t *size_transferred) 312 { 313 assert(pipe); 314 errno_t err; 315 transfer_t transfer = { 316 .pipe = pipe, 317 .dir = USB_DIRECTION_IN, 318 }; 319 320 setup_dma_buffer(&transfer, base, ptr, size); 321 322 if ((err = transfer_common(&transfer))) 323 return err; 324 325 if (size_transferred) 326 *size_transferred = transfer.transferred_size; 327 328 return EOK; 329 } 330 331 /** 332 * Request a write (out) transfer on an endpoint pipe, declaring that buffer 333 * is pointing to a memory area previously allocated by usb_pipe_alloc_buffer. 334 * 335 * @param[in] pipe Pipe used for the transfer. 336 * @param[in] buffer Buffer, previously allocated with usb_pipe_alloc_buffer. 337 * @param[in] size Size of the buffer (in bytes). 338 * @return Error code. 339 */ 340 errno_t usb_pipe_write_dma(usb_pipe_t *pipe, void *base, void *ptr, size_t size) 341 { 342 assert(pipe); 343 transfer_t transfer = { 344 .pipe = pipe, 345 .dir = USB_DIRECTION_OUT, 346 }; 347 348 setup_dma_buffer(&transfer, base, ptr, size); 349 350 return transfer_common(&transfer); 243 351 } 244 352 … … 246 354 * 247 355 * @param pipe Endpoint pipe to be initialized. 248 * @param endpoint_no Endpoint number (in USB 1.1 in range 0 to 15). 249 * @param transfer_type Transfer type (e.g. interrupt or bulk). 250 * @param max_packet_size Maximum packet size in bytes. 251 * @param direction Endpoint direction (in/out). 252 * @return Error code. 253 */ 254 errno_t usb_pipe_initialize(usb_pipe_t *pipe, usb_endpoint_t endpoint_no, 255 usb_transfer_type_t transfer_type, size_t max_packet_size, 256 usb_direction_t direction, unsigned packets, usb_dev_session_t *bus_session) 257 { 258 assert(pipe); 259 260 pipe->endpoint_no = endpoint_no; 261 pipe->transfer_type = transfer_type; 262 pipe->packets = packets; 263 pipe->max_packet_size = max_packet_size; 264 pipe->direction = direction; 356 * @param bus_session Endpoint pipe to be initialized. 357 * @return Error code. 358 */ 359 errno_t usb_pipe_initialize(usb_pipe_t *pipe, usb_dev_session_t *bus_session) 360 { 361 assert(pipe); 362 265 363 pipe->auto_reset_halt = false; 266 364 pipe->bus_session = bus_session; … … 269 367 } 270 368 271 /** Initialize USB endpoint pipe as the default zero control pipe. 369 static const usb_pipe_desc_t default_control_pipe = { 370 .endpoint_no = 0, 371 .transfer_type = USB_TRANSFER_CONTROL, 372 .direction = USB_DIRECTION_BOTH, 373 .max_transfer_size = CTRL_PIPE_MIN_PACKET_SIZE, 374 .transfer_buffer_policy = DMA_POLICY_STRICT, 375 }; 376 377 /** Initialize USB default control pipe. 378 * 379 * This one is special because it must not be registered, it is registered 380 * automatically. 272 381 * 273 382 * @param pipe Endpoint pipe to be initialized. 383 * @param bus_session Endpoint pipe to be initialized. 274 384 * @return Error code. 275 385 */ … … 277 387 usb_dev_session_t *bus_session) 278 388 { 279 assert(pipe);280 281 const errno_t rc = usb_pipe_initialize(pipe, 0, USB_TRANSFER_CONTROL,282 CTRL_PIPE_MIN_PACKET_SIZE, USB_DIRECTION_BOTH, 1, bus_session); 283 389 const errno_t ret = usb_pipe_initialize(pipe, bus_session); 390 if (ret) 391 return ret; 392 393 pipe->desc = default_control_pipe; 284 394 pipe->auto_reset_halt = true; 285 395 286 return rc;396 return EOK; 287 397 } 288 398 … … 290 400 * 291 401 * @param pipe Pipe to be registered. 292 * @param interval Polling interval. 293 * @return Error code. 294 */ 295 errno_t usb_pipe_register(usb_pipe_t *pipe, unsigned interval) 402 * @param ep_desc Matched endpoint descriptor 403 * @param comp_desc Matched superspeed companion descriptro, if any 404 * @return Error code. 405 */ 406 errno_t usb_pipe_register(usb_pipe_t *pipe, 407 const usb_standard_endpoint_descriptor_t *ep_desc, 408 const usb_superspeed_endpoint_companion_descriptor_t *comp_desc) 409 { 410 assert(pipe); 411 assert(pipe->bus_session); 412 assert(ep_desc); 413 414 async_exch_t *exch = async_exchange_begin(pipe->bus_session); 415 if (!exch) 416 return ENOMEM; 417 418 usb_endpoint_descriptors_t descriptors = { 0 }; 419 420 #define COPY(field) descriptors.endpoint.field = ep_desc->field 421 COPY(endpoint_address); 422 COPY(attributes); 423 COPY(max_packet_size); 424 COPY(poll_interval); 425 #undef COPY 426 427 #define COPY(field) descriptors.companion.field = comp_desc->field 428 if (comp_desc) { 429 COPY(max_burst); 430 COPY(attributes); 431 COPY(bytes_per_interval); 432 } 433 #undef COPY 434 435 const errno_t ret = usbhc_register_endpoint(exch, 436 &pipe->desc, &descriptors); 437 async_exchange_end(exch); 438 return ret; 439 } 440 441 /** Revert endpoint registration with the host controller. 442 * 443 * @param pipe Pipe to be unregistered. 444 * @return Error code. 445 */ 446 errno_t usb_pipe_unregister(usb_pipe_t *pipe) 296 447 { 297 448 assert(pipe); … … 300 451 if (!exch) 301 452 return ENOMEM; 302 const errno_t ret = usb_register_endpoint(exch, pipe->endpoint_no, 303 pipe->transfer_type, pipe->direction, pipe->max_packet_size,304 pipe->packets, interval); 453 454 const errno_t ret = usbhc_unregister_endpoint(exch, &pipe->desc); 455 305 456 async_exchange_end(exch); 306 457 return ret; 307 458 } 308 459 309 /** Revert endpoint registration with the host controller.310 *311 * @param pipe Pipe to be unregistered.312 * @return Error code.313 */314 errno_t usb_pipe_unregister(usb_pipe_t *pipe)315 {316 assert(pipe);317 assert(pipe->bus_session);318 async_exch_t *exch = async_exchange_begin(pipe->bus_session);319 if (!exch)320 return ENOMEM;321 const errno_t ret = usb_unregister_endpoint(exch, pipe->endpoint_no,322 pipe->direction);323 async_exchange_end(exch);324 return ret;325 }326 327 460 /** 328 461 * @} -
uspace/lib/usbdev/src/pipesinit.c
rf5e5f73 rdf6ded8 1 1 /* 2 2 * Copyright (c) 2011 Vojtech Horky 3 * Copyright (c) 2018 Ondrej Hlavaty, Michal Staruch 3 4 * All rights reserved. 4 5 * … … 38 39 #include <usb/dev/request.h> 39 40 #include <usb/usb.h> 41 #include <usb/debug.h> 40 42 #include <usb/descriptor.h> 41 43 … … 59 61 NESTING(INTERFACE, HID), 60 62 NESTING(HID, HID_REPORT), 63 NESTING(ENDPOINT, SSPEED_EP_COMPANION), 61 64 LAST_NESTING 62 65 }; … … 70 73 { 71 74 return descriptor[1] == USB_DESCTYPE_ENDPOINT; 75 } 76 77 /** Tells whether given descriptor is of superspeed companion type. 78 * 79 * @param descriptor Descriptor in question. 80 * @return Whether the given descriptor is superspeed companion descriptor. 81 */ 82 static inline bool is_superspeed_companion_descriptor(const uint8_t *descriptor) 83 { 84 return descriptor[1] == USB_DESCTYPE_SSPEED_EP_COMPANION; 72 85 } 73 86 … … 134 147 if (interface_number_fits 135 148 && interface_setting_fits 136 && endpoint_descriptions_fits) { 149 && endpoint_descriptions_fits 150 && !mapping->present) { 137 151 return mapping; 138 152 } … … 141 155 mapping_count--; 142 156 } 157 143 158 return NULL; 144 159 } … … 150 165 * @param interface Interface descriptor under which belongs the @p endpoint. 151 166 * @param endpoint Endpoint descriptor. 167 * @param companion Superspeed companion descriptor. 152 168 * @return Error code. 153 169 */ … … 156 172 usb_standard_interface_descriptor_t *interface, 157 173 usb_standard_endpoint_descriptor_t *endpoint_desc, 174 usb_superspeed_endpoint_companion_descriptor_t *companion_desc, 158 175 usb_dev_session_t *bus_session) 159 176 { … … 162 179 * Get endpoint characteristics. 163 180 */ 164 165 /* Actual endpoint number is in bits 0..3 */166 const usb_endpoint_t ep_no = endpoint_desc->endpoint_address & 0x0F;167 168 181 const usb_endpoint_description_t description = { 169 /* Endpoint direction is set by bit 7 */ 170 .direction = (endpoint_desc->endpoint_address & 128) 171 ? USB_DIRECTION_IN : USB_DIRECTION_OUT, 172 /* Transfer type is in bits 0..2 and 173 * the enum values corresponds 1:1 */ 174 .transfer_type = endpoint_desc->attributes & 3, 182 .transfer_type = USB_ED_GET_TRANSFER_TYPE(*endpoint_desc), 183 .direction = USB_ED_GET_DIR(*endpoint_desc), 175 184 176 185 /* Get interface characteristics. */ … … 194 203 } 195 204 196 errno_t rc = usb_pipe_initialize(&ep_mapping->pipe, 197 ep_no, description.transfer_type, 198 ED_MPS_PACKET_SIZE_GET( 199 uint16_usb2host(endpoint_desc->max_packet_size)), 200 description.direction, 201 ED_MPS_TRANS_OPPORTUNITIES_GET( 202 uint16_usb2host(endpoint_desc->max_packet_size)), bus_session); 203 if (rc != EOK) { 204 return rc; 205 } 205 errno_t err = usb_pipe_initialize(&ep_mapping->pipe, bus_session); 206 if (err) 207 return err; 206 208 207 209 ep_mapping->present = true; 208 210 ep_mapping->descriptor = endpoint_desc; 211 ep_mapping->companion_descriptor = companion_desc; 209 212 ep_mapping->interface = interface; 210 213 … … 235 238 do { 236 239 if (is_endpoint_descriptor(descriptor)) { 240 /* Check if companion descriptor is present too, it should immediatelly follow. */ 241 const uint8_t *companion_desc = usb_dp_get_nested_descriptor(parser, 242 parser_data, descriptor); 243 if (companion_desc && !is_superspeed_companion_descriptor(companion_desc)) { 244 /* Not what we wanted, don't pass it further. */ 245 companion_desc = NULL; 246 } 247 237 248 (void) process_endpoint(mapping, mapping_count, 238 249 (usb_standard_interface_descriptor_t *) … … 240 251 (usb_standard_endpoint_descriptor_t *) 241 252 descriptor, 253 (usb_superspeed_endpoint_companion_descriptor_t *) 254 companion_desc, 242 255 bus_session); 243 256 } … … 288 301 if (config_descriptor == NULL) 289 302 return EBADMEM; 290 303 291 304 if (config_descriptor_size < 292 305 sizeof(usb_standard_configuration_descriptor_t)) { … … 328 341 } 329 342 330 /** Probe default control pipe for max packet size.331 *332 * The function tries to get the correct value of max packet size several333 * time before giving up.334 *335 * The session on the pipe shall not be started.336 *337 * @param pipe Default control pipe.338 * @return Error code.339 */340 errno_t usb_pipe_probe_default_control(usb_pipe_t *pipe)341 {342 assert(pipe);343 static_assert(DEV_DESCR_MAX_PACKET_SIZE_OFFSET < CTRL_PIPE_MIN_PACKET_SIZE);344 345 if ((pipe->direction != USB_DIRECTION_BOTH) ||346 (pipe->transfer_type != USB_TRANSFER_CONTROL) ||347 (pipe->endpoint_no != 0)) {348 return EINVAL;349 }350 351 uint8_t dev_descr_start[CTRL_PIPE_MIN_PACKET_SIZE];352 size_t transferred_size;353 errno_t rc;354 for (size_t attempt_var = 0; attempt_var < 3; ++attempt_var) {355 rc = usb_request_get_descriptor(pipe, USB_REQUEST_TYPE_STANDARD,356 USB_REQUEST_RECIPIENT_DEVICE, USB_DESCTYPE_DEVICE,357 0, 0, dev_descr_start, CTRL_PIPE_MIN_PACKET_SIZE,358 &transferred_size);359 if (rc == EOK) {360 if (transferred_size != CTRL_PIPE_MIN_PACKET_SIZE) {361 rc = ELIMIT;362 continue;363 }364 break;365 }366 }367 if (rc != EOK) {368 return rc;369 }370 371 pipe->max_packet_size372 = dev_descr_start[DEV_DESCR_MAX_PACKET_SIZE_OFFSET];373 374 return EOK;375 }376 377 343 /** 378 344 * @} -
uspace/lib/usbdev/src/request.c
rf5e5f73 rdf6ded8 1 1 /* 2 2 * Copyright (c) 2011 Vojtech Horky 3 * Copyright (c) 2018 Ondrej Hlavaty 3 4 * All rights reserved. 4 5 * … … 118 119 * @param data_size Size of the @p data buffer 119 120 * (in native endianness). 120 * @param actual_data_size Actual size of transfer ed data121 * @param actual_data_size Actual size of transferred data 121 122 * (in native endianness). 122 123 * … … 183 184 184 185 uint16_t status_usb_endianess; 185 size_t data_transfer ed_size;186 size_t data_transferred_size; 186 187 errno_t rc = usb_control_request_get(pipe, USB_REQUEST_TYPE_STANDARD, 187 188 recipient, USB_DEVREQ_GET_STATUS, 0, uint16_host2usb(index), 188 &status_usb_endianess, 2, &data_transfer ed_size);189 if (rc != EOK) { 190 return rc; 191 } 192 if (data_transfer ed_size != 2) {189 &status_usb_endianess, 2, &data_transferred_size); 190 if (rc != EOK) { 191 return rc; 192 } 193 if (data_transferred_size != 2) { 193 194 return ELIMIT; 194 195 } … … 314 315 */ 315 316 uint8_t tmp_buffer; 316 size_t bytes_transfer ed;317 size_t bytes_transferred; 317 318 rc = usb_request_get_descriptor(pipe, request_type, recipient, 318 319 descriptor_type, descriptor_index, language, 319 &tmp_buffer, sizeof(tmp_buffer), &bytes_transfer ed);320 if (rc != EOK) { 321 return rc; 322 } 323 if (bytes_transfer ed != 1) {320 &tmp_buffer, sizeof(tmp_buffer), &bytes_transferred); 321 if (rc != EOK) { 322 return rc; 323 } 324 if (bytes_transferred != 1) { 324 325 return ELIMIT; 325 326 } … … 340 341 rc = usb_request_get_descriptor(pipe, request_type, recipient, 341 342 descriptor_type, descriptor_index, language, 342 buffer, size, &bytes_transfer ed);343 buffer, size, &bytes_transferred); 343 344 if (rc != EOK) { 344 345 free(buffer); 345 346 return rc; 346 347 } 347 if (bytes_transfer ed != size) {348 if (bytes_transferred != size) { 348 349 free(buffer); 349 350 return ELIMIT; … … 824 825 * @return Error code. 825 826 */ 826 errno_t usb_request_clear_endpoint_halt(usb_pipe_t *pipe, uint16_t ep_index)827 static errno_t usb_request_clear_endpoint_halt(usb_pipe_t *pipe, uint16_t ep_index) 827 828 { 828 829 return usb_request_clear_feature(pipe, … … 843 844 return EINVAL; 844 845 } 845 return usb_request_clear_endpoint_halt(ctrl_pipe, 846 target_pipe->endpoint_no); 846 847 uint16_t index = target_pipe->desc.endpoint_no; 848 index |= (target_pipe->desc.direction == USB_DIRECTION_IN) << 7; 849 return usb_request_clear_endpoint_halt(ctrl_pipe, index); 847 850 } 848 851 … … 858 861 { 859 862 uint16_t status_tmp; 860 uint16_t pipe_index = (uint16_t) pipe-> endpoint_no;863 uint16_t pipe_index = (uint16_t) pipe->desc.endpoint_no; 861 864 errno_t rc = usb_request_get_status(ctrl_pipe, 862 865 USB_REQUEST_RECIPIENT_ENDPOINT, uint16_host2usb(pipe_index),
Note:
See TracChangeset
for help on using the changeset viewer.