Changeset bd575647 in mainline
- Timestamp:
- 2011-12-11T16:30:42Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 7d5ef94
- Parents:
- 2c202c5
- Location:
- uspace/lib/usbdev
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usbdev/Makefile
r2c202c5 rbd575647 40 40 src/dp.c \ 41 41 src/hub.c \ 42 src/pipepriv.c \43 src/pipepriv.h \44 42 src/pipes.c \ 45 43 src/pipesinit.c \ -
uspace/lib/usbdev/include/usb/dev/driver.h
r2c202c5 rbd575647 72 72 /** USB device structure. */ 73 73 typedef struct { 74 usb_hc_connection_t hc_conn; 74 75 /** Connection backing the pipes. 75 76 * Typically, you will not need to use this attribute at all. -
uspace/lib/usbdev/include/usb/dev/pipes.h
r2c202c5 rbd575647 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 29 28 /** @addtogroup libusbdev 30 29 * @{ … … 38 37 #include <sys/types.h> 39 38 #include <usb/usb.h> 40 #include <usb/ hc.h>39 #include <usb/dev.h> 41 40 #include <usb/descriptor.h> 42 41 #include <ipc/devman.h> … … 44 43 #include <fibril_synch.h> 45 44 #include <async.h> 46 47 /** Abstraction of a physical connection to the device.48 * This type is an abstraction of the USB wire that connects the host and49 * the function (device).50 */51 typedef struct {52 /** Handle of the host controller device is connected to. */53 devman_handle_t hc_handle;54 /** Address of the device. */55 usb_address_t address;56 } usb_device_connection_t;57 45 58 46 /** Abstraction of a logical connection to USB device endpoint. … … 85 73 /** Maximum packet size for the endpoint. */ 86 74 size_t max_packet_size; 87 88 /** Session to the host controller.89 * NULL when no session is active.90 * It is an error to access this member without @c hc_sess_mutex91 * being locked.92 * If call over the phone is to be made, it must be preceeded by93 * call to pipe_add_ref() [internal libusb function].94 */95 async_sess_t *hc_sess;96 97 /** Guard for serialization of requests over the session. */98 fibril_mutex_t hc_sess_mutex;99 100 /** Number of active transfers over the pipe. */101 int refcount;102 /** Number of failed attempts to open the HC phone.103 * When user requests usb_pipe_start_long_transfer() and the operation104 * fails, there is no way to report this to the user.105 * That the soft reference counter is increased to record the attempt.106 * When the user then request e.g. usb_pipe_read(), it will try to107 * add reference as well.108 * If that fails, it is reported to the user. If it is okay, the109 * real reference counter is incremented.110 * The problem might arise when ending the long transfer (since111 * the number of references would be only 1, but logically it shall be112 * two).113 * Decrementing the soft counter first shall solve this.114 */115 int refcount_soft;116 75 117 76 /** Whether to automatically reset halt on the endpoint. … … 156 115 } usb_endpoint_mapping_t; 157 116 158 int usb_device_connection_initialize_on_default_address(159 usb_device_connection_t *, usb_hc_connection_t *);160 int usb_device_connection_initialize_from_device(usb_device_connection_t *,161 const ddf_dev_t *);162 int usb_device_connection_initialize(usb_device_connection_t *,163 devman_handle_t, usb_address_t);164 117 165 118 int usb_device_get_assigned_interface(const ddf_dev_t *); … … 169 122 int usb_pipe_initialize_default_control(usb_pipe_t *, 170 123 usb_device_connection_t *); 124 171 125 int usb_pipe_probe_default_control(usb_pipe_t *); 172 126 int usb_pipe_initialize_from_configuration(usb_endpoint_mapping_t *, 173 127 size_t, const uint8_t *, size_t, usb_device_connection_t *); 174 int usb_pipe_register(usb_pipe_t *, unsigned int, usb_hc_connection_t *);175 int usb_pipe_unregister(usb_pipe_t * , usb_hc_connection_t *);128 int usb_pipe_register(usb_pipe_t *, unsigned); 129 int usb_pipe_unregister(usb_pipe_t *); 176 130 177 131 void usb_pipe_start_long_transfer(usb_pipe_t *); -
uspace/lib/usbdev/src/devdrv.c
r2c202c5 rbd575647 373 373 } 374 374 375 /* Register the endpoints with HC. */376 usb_hc_connection_t hc_conn;377 rc = usb_hc_connection_initialize_from_device(&hc_conn, dev);378 if (rc != EOK) {379 goto rollback_free_only;380 }381 382 rc = usb_hc_connection_open(&hc_conn);383 if (rc != EOK) {384 goto rollback_free_only;385 }386 387 375 for (i = 0; i < pipe_count; i++) { 388 376 if (pipes[i].present) { 389 377 rc = usb_pipe_register(&pipes[i].pipe, 390 pipes[i].descriptor->poll_interval , &hc_conn);378 pipes[i].descriptor->poll_interval); 391 379 if (rc != EOK) { 392 380 goto rollback_unregister_endpoints; … … 394 382 } 395 383 } 396 397 if (usb_hc_connection_close(&hc_conn) != EOK)398 usb_log_warning("%s: Failed to close connection.\n",399 __FUNCTION__);400 384 401 385 *pipes_ptr = pipes; … … 415 399 for (i = 0; i < pipe_count; i++) { 416 400 if (pipes[i].present) { 417 usb_pipe_unregister(&pipes[i].pipe , &hc_conn);401 usb_pipe_unregister(&pipes[i].pipe); 418 402 } 419 403 } 420 421 if (usb_hc_connection_close(&hc_conn) != EOK)422 usb_log_warning("usb_device_create_pipes(): "423 "Failed to close connection.\n");424 404 425 405 /* … … 470 450 i, pipes[i].present ? "" : "not "); 471 451 if (pipes[i].present) 472 usb_pipe_unregister(&pipes[i].pipe, &hc_conn); 473 } 474 475 if (usb_hc_connection_close(&hc_conn) != EOK) 476 usb_log_warning("usb_device_destroy_pipes(): " 477 "Failed to close connection.\n"); 452 usb_pipe_unregister(&pipes[i].pipe); 453 } 478 454 479 455 free(pipes); … … 505 481 usb_dev->pipes = NULL; 506 482 483 usb_hc_connection_initialize_from_device(&usb_dev->hc_conn, ddf_dev); 484 const usb_address_t address = 485 usb_get_address_by_handle(ddf_dev->handle); 507 486 /* Initialize backing wire and control pipe. */ 508 int rc = usb_device_connection_initialize _from_device(509 &usb_dev->wire, ddf_dev);487 int rc = usb_device_connection_initialize( 488 &usb_dev->wire, &usb_dev->hc_conn, address); 510 489 if (rc != EOK) { 511 490 *errstr_ptr = "device connection initialization"; -
uspace/lib/usbdev/src/hub.c
r2c202c5 rbd575647 63 63 } while (false) 64 64 65 /** Ask host controller for free address assignment.66 *67 * @param connection Opened connection to host controller.68 * @param preferred Preferred SUB address.69 * @param strict Fail if the preferred address is not avialable.70 * @param speed Speed of the new device (device that will be assigned71 * the returned address).72 * @return Assigned USB address or negative error code.73 */74 usb_address_t usb_hc_request_address(usb_hc_connection_t *connection,75 usb_address_t preferred, bool strict, usb_speed_t speed)76 {77 CHECK_CONNECTION(connection);78 79 async_exch_t *exch = async_exchange_begin(connection->hc_sess);80 if (!exch)81 return (usb_address_t)ENOMEM;82 83 usb_address_t address = preferred;84 const int ret = usbhc_request_address(exch, &address, strict, speed);85 86 async_exchange_end(exch);87 return ret == EOK ? address : ret;88 }89 65 90 66 /** Inform host controller about new device. … … 97 73 const usb_hub_attached_device_t *attached_device) 98 74 { 99 CHECK_CONNECTION(connection);75 // CHECK_CONNECTION(connection); 100 76 if (attached_device == NULL || attached_device->fun == NULL) 101 77 return EINVAL; … … 120 96 usb_address_t address) 121 97 { 122 CHECK_CONNECTION(connection);98 // CHECK_CONNECTION(connection); 123 99 124 100 async_exch_t *exch = async_exchange_begin(connection->hc_sess); … … 166 142 167 143 /* TODO: prevent others from accessing the wire now. */ 168 if (usb_pipe_unregister(pipe , hc_conn) != EOK) {144 if (usb_pipe_unregister(pipe) != EOK) { 169 145 usb_log_warning( 170 146 "Failed to unregister the old pipe on address change.\n"); … … 172 148 /* The address is already changed so set it in the wire */ 173 149 pipe->wire->address = new_address; 174 rc = usb_pipe_register(pipe, 0 , hc_conn);150 rc = usb_pipe_register(pipe, 0); 175 151 if (rc != EOK) 176 152 return EADDRNOTAVAIL; … … 288 264 289 265 /* Register control pipe on default address. */ 290 rc = usb_pipe_register(&ctrl_pipe, 0 , &hc_conn);266 rc = usb_pipe_register(&ctrl_pipe, 0); 291 267 if (rc != EOK) { 292 268 rc = ENOTCONN; … … 385 361 leave_release_free_address: 386 362 /* This might be either 0:0 or dev_addr:0 */ 387 if (usb_pipe_unregister(&ctrl_pipe , &hc_conn) != EOK)363 if (usb_pipe_unregister(&ctrl_pipe) != EOK) 388 364 usb_log_warning("%s: Failed to unregister default pipe.\n", 389 365 __FUNCTION__); -
uspace/lib/usbdev/src/pipepriv.c
r2c202c5 rbd575647 90 90 /* Need to open the phone by ourselves. */ 91 91 async_sess_t *sess = 92 devman_device_connect(EXCHANGE_SERIALIZE, pipe->wire->hc_ handle, 0);92 devman_device_connect(EXCHANGE_SERIALIZE, pipe->wire->hc_connection->hc_handle, 0); 93 93 if (!sess) { 94 94 if (hide_failure) { -
uspace/lib/usbdev/src/pipepriv.h
r2c202c5 rbd575647 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 29 28 /** @addtogroup libusbdev 30 29 * @{ -
uspace/lib/usbdev/src/pipes.c
r2c202c5 rbd575647 1 1 /* 2 2 * Copyright (c) 2011 Vojtech Horky 3 * Copyright (c) 2011 Jan Vesely 3 4 * All rights reserved. 4 5 * … … 26 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 */ 28 29 29 /** @addtogroup libusbdev 30 30 * @{ … … 33 33 * USB endpoint pipes miscellaneous functions. 34 34 */ 35 #include <usb /usb.h>35 #include <usb_iface.h> 36 36 #include <usb/dev/pipes.h> 37 #include <usb/debug.h> 38 #include <usb/hc.h> 39 #include <usbhc_iface.h> 40 #include <usb_iface.h> 41 #include <devman.h> 37 #include <usb/dev.h> 42 38 #include <errno.h> 43 39 #include <assert.h> 44 40 #include "pipepriv.h" 45 46 #define IPC_AGAIN_DELAY (1000 * 2) /* 2ms */47 48 /** Tell USB address assigned to given device.49 *50 * @param sess Session to parent device.51 * @param dev Device in question.52 * @return USB address or error code.53 */54 static usb_address_t get_my_address(async_sess_t *sess, const ddf_dev_t *dev)55 {56 assert(sess);57 async_exch_t *exch = async_exchange_begin(sess);58 if (!exch)59 return ENOMEM;60 61 usb_address_t address;62 const int ret = usb_get_my_address(exch, &address);63 64 async_exchange_end(exch);65 66 return (ret == EOK) ? address : ret;67 }68 41 69 42 /** Tell USB interface assigned to given device. … … 91 64 92 65 return ret == EOK ? iface_no : ret; 93 }94 95 /** Initialize connection to USB device.96 *97 * @param connection Connection structure to be initialized.98 * @param dev Generic device backing the USB device.99 * @return Error code.100 */101 int usb_device_connection_initialize_from_device(102 usb_device_connection_t *connection, const ddf_dev_t *dev)103 {104 assert(connection);105 assert(dev);106 107 int rc;108 devman_handle_t hc_handle;109 usb_address_t my_address;110 111 rc = usb_hc_find(dev->handle, &hc_handle);112 if (rc != EOK)113 return rc;114 115 async_sess_t *parent_sess =116 devman_parent_device_connect(EXCHANGE_ATOMIC, dev->handle,117 IPC_FLAG_BLOCKING);118 if (!parent_sess)119 return ENOMEM;120 121 /*122 * Asking for "my" address may require several attempts.123 * That is because following scenario may happen:124 * - parent driver (i.e. driver of parent device) announces new device125 * and devman launches current driver126 * - parent driver is preempted and thus does not send address-handle127 * binding to HC driver128 * - this driver gets here and wants the binding129 * - the HC does not know the binding yet and thus it answers ENOENT130 * So, we need to wait for the HC to learn the binding.131 */132 133 do {134 my_address = get_my_address(parent_sess, dev);135 136 if (my_address == ENOENT) {137 /* Be nice, let other fibrils run and try again. */138 async_usleep(IPC_AGAIN_DELAY);139 } else if (my_address < 0) {140 /* Some other problem, no sense trying again. */141 rc = my_address;142 goto leave;143 }144 145 } while (my_address < 0);146 147 rc = usb_device_connection_initialize(connection,148 hc_handle, my_address);149 150 leave:151 async_hangup(parent_sess);152 return rc;153 }154 155 /** Initialize connection to USB device.156 *157 * @param connection Connection structure to be initialized.158 * @param host_controller_handle Devman handle of host controller device is159 * connected to.160 * @param device_address Device USB address.161 * @return Error code.162 */163 int usb_device_connection_initialize(usb_device_connection_t *connection,164 devman_handle_t host_controller_handle, usb_address_t device_address)165 {166 assert(connection);167 168 if ((device_address < 0) || (device_address >= USB11_ADDRESS_MAX)) {169 return EINVAL;170 }171 172 connection->hc_handle = host_controller_handle;173 connection->address = device_address;174 175 return EOK;176 }177 178 /** Initialize connection to USB device on default address.179 *180 * @param dev_connection Device connection structure to be initialized.181 * @param hc_connection Initialized connection to host controller.182 * @return Error code.183 */184 int usb_device_connection_initialize_on_default_address(185 usb_device_connection_t *dev_connection,186 usb_hc_connection_t *hc_connection)187 {188 assert(dev_connection);189 190 if (hc_connection == NULL) {191 return EBADMEM;192 }193 194 return usb_device_connection_initialize(dev_connection,195 hc_connection->hc_handle, (usb_address_t) 0);196 66 } 197 67 -
uspace/lib/usbdev/src/pipesinit.c
r2c202c5 rbd575647 349 349 fibril_mutex_initialize(&pipe->guard); 350 350 pipe->wire = connection; 351 pipe->hc_sess = NULL;352 fibril_mutex_initialize(&pipe->hc_sess_mutex);353 351 pipe->endpoint_no = endpoint_no; 354 352 pipe->transfer_type = transfer_type; 355 353 pipe->max_packet_size = max_packet_size; 356 354 pipe->direction = direction; 357 pipe->refcount = 0;358 pipe->refcount_soft = 0;359 355 pipe->auto_reset_halt = false; 360 356 … … 442 438 * @return Error code. 443 439 */ 444 int usb_pipe_register(usb_pipe_t *pipe, unsigned interval, 445 usb_hc_connection_t *hc_connection) 440 int usb_pipe_register(usb_pipe_t *pipe, unsigned interval) 446 441 { 447 442 assert(pipe); 448 443 assert(pipe->wire); 449 assert(hc_connection); 450 451 if (!usb_hc_connection_is_opened(hc_connection)) 452 return EBADF; 453 async_exch_t *exch = async_exchange_begin(hc_connection->hc_sess); 454 if (!exch) 455 return ENOMEM; 456 const int ret = usbhc_register_endpoint(exch, 457 pipe->wire->address, pipe->endpoint_no, pipe->transfer_type, 458 pipe->direction, pipe->max_packet_size, interval); 459 460 async_exchange_end(exch); 461 return ret; 444 assert(pipe->wire->hc_connection); 445 446 return usb_hc_register_endpoint(pipe->wire->hc_connection, 447 pipe->wire->address, pipe->endpoint_no, pipe->transfer_type, 448 pipe->direction, pipe->max_packet_size, interval); 462 449 } 463 450 … … 468 455 * @return Error code. 469 456 */ 470 int usb_pipe_unregister(usb_pipe_t *pipe, 471 usb_hc_connection_t *hc_connection) 457 int usb_pipe_unregister(usb_pipe_t *pipe) 472 458 { 473 459 assert(pipe); 474 460 assert(pipe->wire); 475 assert(hc_connection); 476 477 if (!usb_hc_connection_is_opened(hc_connection)) 478 return EBADF; 479 480 async_exch_t *exch = async_exchange_begin(hc_connection->hc_sess); 481 if (!exch) 482 return ENOMEM; 483 const int ret = usbhc_unregister_endpoint(exch, 461 assert(pipe->wire->hc_connection); 462 463 return usb_hc_unregister_endpoint(pipe->wire->hc_connection, 484 464 pipe->wire->address, pipe->endpoint_no, pipe->direction); 485 async_exchange_end(exch);486 487 return ret;488 465 } 489 466 -
uspace/lib/usbdev/src/pipesio.c
r2c202c5 rbd575647 71 71 return ENOTSUP; 72 72 73 int ret = pipe_add_ref(pipe, false); 74 if (ret != EOK) { 75 return ret; 76 } 77 78 /* Ensure serialization over the phone. */ 79 pipe_start_transaction(pipe); 80 async_exch_t *exch = async_exchange_begin(pipe->hc_sess); 81 if (!exch) { 82 pipe_end_transaction(pipe); 83 pipe_drop_ref(pipe); 84 return ENOMEM; 85 } 86 87 ret = usbhc_read(exch, pipe->wire->address, pipe->endpoint_no, 88 setup, buffer, size, size_transfered); 89 async_exchange_end(exch); 90 pipe_end_transaction(pipe); 91 pipe_drop_ref(pipe); 92 return ret; 73 return usb_hc_control_read(pipe->wire->hc_connection, 74 pipe->wire->address, pipe->endpoint_no, setup, buffer, size, 75 size_transfered); 93 76 } 94 77 … … 109 92 return ENOTSUP; 110 93 111 int ret = pipe_add_ref(pipe, false); 112 if (ret != EOK) { 113 return ret; 114 } 115 116 /* Ensure serialization over the phone. */ 117 pipe_start_transaction(pipe); 118 async_exch_t *exch = async_exchange_begin(pipe->hc_sess); 119 if (!exch) { 120 pipe_end_transaction(pipe); 121 pipe_drop_ref(pipe); 122 return ENOMEM; 123 } 124 ret = usbhc_write(exch, pipe->wire->address, pipe->endpoint_no, 125 setup, buffer, size); 126 async_exchange_end(exch); 127 pipe_end_transaction(pipe); 128 pipe_drop_ref(pipe); 129 return ret; 94 return usb_hc_control_write(pipe->wire->hc_connection, 95 pipe->wire->address, pipe->endpoint_no, setup, buffer, size); 130 96 } 131 97
Note:
See TracChangeset
for help on using the changeset viewer.