Changeset dc4c19e in mainline for uspace/lib
- Timestamp:
- 2011-04-10T12:18:09Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 60c0573
- Parents:
- a49e171 (diff), 82e8861 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - Location:
- uspace/lib
- Files:
-
- 2 added
- 23 edited
-
drv/generic/remote_usbhc.c (modified) (12 diffs)
-
drv/include/usbhc_iface.h (modified) (7 diffs)
-
usb/Makefile (modified) (1 diff)
-
usb/include/usb/classes/hub.h (modified) (2 diffs)
-
usb/include/usb/devdrv.h (modified) (1 diff)
-
usb/include/usb/host/batch.h (modified) (1 diff)
-
usb/include/usb/host/device_keeper.h (modified) (2 diffs)
-
usb/include/usb/host/endpoint.h (modified) (3 diffs)
-
usb/include/usb/host/usb_endpoint_manager.h (modified) (1 diff)
-
usb/include/usb/hub.h (modified) (1 diff)
-
usb/include/usb/pipes.h (modified) (5 diffs)
-
usb/include/usb/usb.h (modified) (1 diff)
-
usb/src/devdrv.c (modified) (7 diffs)
-
usb/src/devpoll.c (modified) (1 diff)
-
usb/src/host/batch.c (modified) (3 diffs)
-
usb/src/host/device_keeper.c (modified) (3 diffs)
-
usb/src/host/endpoint.c (modified) (4 diffs)
-
usb/src/host/usb_endpoint_manager.c (modified) (3 diffs)
-
usb/src/hub.c (modified) (8 diffs)
-
usb/src/pipepriv.c (added)
-
usb/src/pipepriv.h (added)
-
usb/src/pipes.c (modified) (6 diffs)
-
usb/src/pipesinit.c (modified) (5 diffs)
-
usb/src/pipesio.c (modified) (19 diffs)
-
usb/src/recognise.c (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/drv/generic/remote_usbhc.c
ra49e171 rdc4c19e 50 50 static void remote_usbhc_control_write(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 51 51 static void remote_usbhc_control_read(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 52 static void remote_usbhc_reserve_default_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);53 static void remote_usbhc_release_default_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);54 52 static void remote_usbhc_request_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 55 53 static void remote_usbhc_bind_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); … … 61 59 /** Remote USB host controller interface operations. */ 62 60 static remote_iface_func_ptr_t remote_usbhc_iface_ops [] = { 63 remote_usbhc_reserve_default_address,64 remote_usbhc_release_default_address,65 66 61 remote_usbhc_request_address, 67 62 remote_usbhc_bind_address, … … 129 124 } 130 125 131 void remote_usbhc_reserve_default_address(ddf_fun_t *fun, void *iface,132 ipc_callid_t callid, ipc_call_t *call)133 {134 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;135 136 if (!usb_iface->reserve_default_address) {137 async_answer_0(callid, ENOTSUP);138 return;139 }140 141 usb_speed_t speed = DEV_IPC_GET_ARG1(*call);142 143 int rc = usb_iface->reserve_default_address(fun, speed);144 145 async_answer_0(callid, rc);146 }147 148 void remote_usbhc_release_default_address(ddf_fun_t *fun, void *iface,149 ipc_callid_t callid, ipc_call_t *call)150 {151 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;152 153 if (!usb_iface->release_default_address) {154 async_answer_0(callid, ENOTSUP);155 return;156 }157 158 int rc = usb_iface->release_default_address(fun);159 160 async_answer_0(callid, rc);161 }162 163 126 void remote_usbhc_request_address(ddf_fun_t *fun, void *iface, 164 127 ipc_callid_t callid, ipc_call_t *call) … … 270 233 } 271 234 272 size_t max_packet_size = DEV_IPC_GET_ARG3(*call);273 235 usb_target_t target = { 274 236 .address = DEV_IPC_GET_ARG1(*call), … … 300 262 trans->size = len; 301 263 302 rc = transfer_func(fun, target, max_packet_size,264 rc = transfer_func(fun, target, 303 265 buffer, len, 304 266 callback_out, trans); … … 326 288 } 327 289 328 size_t max_packet_size = DEV_IPC_GET_ARG3(*call);329 290 usb_target_t target = { 330 291 .address = DEV_IPC_GET_ARG1(*call), … … 348 309 trans->size = len; 349 310 350 int rc = transfer_func(fun, target, max_packet_size,311 int rc = transfer_func(fun, target, 351 312 trans->buffer, len, 352 313 callback_in, trans); … … 414 375 }; 415 376 size_t data_buffer_len = DEV_IPC_GET_ARG3(*call); 416 size_t max_packet_size = DEV_IPC_GET_ARG4(*call);417 377 418 378 int rc; … … 450 410 trans->size = data_buffer_len; 451 411 452 rc = usb_iface->control_write(fun, target, max_packet_size,412 rc = usb_iface->control_write(fun, target, 453 413 setup_packet, setup_packet_len, 454 414 data_buffer, data_buffer_len, … … 477 437 .endpoint = DEV_IPC_GET_ARG2(*call) 478 438 }; 479 size_t max_packet_size = DEV_IPC_GET_ARG3(*call);480 439 481 440 int rc; … … 515 474 } 516 475 517 rc = usb_iface->control_read(fun, target, max_packet_size,476 rc = usb_iface->control_read(fun, target, 518 477 setup_packet, setup_packet_len, 519 478 trans->buffer, trans->size, … … 537 496 } 538 497 539 #define INIT_FROM_HIGH_DATA(type, var, arg_no) \ 540 type var = (type) DEV_IPC_GET_ARG##arg_no(*call) / 256 541 #define INIT_FROM_LOW_DATA(type, var, arg_no) \ 542 type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % 256 543 544 INIT_FROM_HIGH_DATA(usb_address_t, address, 1); 545 INIT_FROM_LOW_DATA(usb_endpoint_t, endpoint, 1); 546 INIT_FROM_HIGH_DATA(usb_transfer_type_t, transfer_type, 2); 547 INIT_FROM_LOW_DATA(usb_direction_t, direction, 2); 548 549 #undef INIT_FROM_HIGH_DATA 550 #undef INIT_FROM_LOW_DATA 551 552 size_t max_packet_size = (size_t) DEV_IPC_GET_ARG3(*call); 553 unsigned int interval = (unsigned int) DEV_IPC_GET_ARG4(*call); 554 555 int rc = usb_iface->register_endpoint(fun, address, endpoint, 498 #define _INIT_FROM_HIGH_DATA2(type, var, arg_no) \ 499 type var = (type) DEV_IPC_GET_ARG##arg_no(*call) / (1 << 16) 500 #define _INIT_FROM_LOW_DATA2(type, var, arg_no) \ 501 type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % (1 << 16) 502 #define _INIT_FROM_HIGH_DATA3(type, var, arg_no) \ 503 type var = (type) DEV_IPC_GET_ARG##arg_no(*call) / (1 << 16) 504 #define _INIT_FROM_MIDDLE_DATA3(type, var, arg_no) \ 505 type var = (type) (DEV_IPC_GET_ARG##arg_no(*call) / (1 << 8)) % (1 << 8) 506 #define _INIT_FROM_LOW_DATA3(type, var, arg_no) \ 507 type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % (1 << 8) 508 509 _INIT_FROM_HIGH_DATA2(usb_address_t, address, 1); 510 _INIT_FROM_LOW_DATA2(usb_endpoint_t, endpoint, 1); 511 512 _INIT_FROM_HIGH_DATA3(usb_speed_t, speed, 2); 513 _INIT_FROM_MIDDLE_DATA3(usb_transfer_type_t, transfer_type, 2); 514 _INIT_FROM_LOW_DATA3(usb_direction_t, direction, 2); 515 516 _INIT_FROM_HIGH_DATA2(size_t, max_packet_size, 3); 517 _INIT_FROM_LOW_DATA2(unsigned int, interval, 3); 518 519 #undef _INIT_FROM_HIGH_DATA2 520 #undef _INIT_FROM_LOW_DATA2 521 #undef _INIT_FROM_HIGH_DATA3 522 #undef _INIT_FROM_MIDDLE_DATA3 523 #undef _INIT_FROM_LOW_DATA3 524 525 int rc = usb_iface->register_endpoint(fun, address, speed, endpoint, 556 526 transfer_type, direction, max_packet_size, interval); 557 527 -
uspace/lib/drv/include/usbhc_iface.h
ra49e171 rdc4c19e 66 66 * - argument #1 is target address 67 67 * - argument #2 is target endpoint 68 * - argument #3 is max packet size of the endpoint69 68 * - this call is immediately followed by IPC data read (async version) 70 69 * - the call is not answered until the device returns some data (or until … … 85 84 */ 86 85 typedef enum { 87 /** Reserve usage of default address.88 * This call informs the host controller that the caller will be89 * using default USB address. It is duty of the HC driver to ensure90 * that only single entity will have it reserved.91 * The address is returned via IPC_M_USBHC_RELEASE_DEFAULT_ADDRESS.92 * The caller can start using the address after receiving EOK93 * answer.94 */95 IPC_M_USBHC_RESERVE_DEFAULT_ADDRESS,96 97 /** Release usage of default address.98 * @see IPC_M_USBHC_RESERVE_DEFAULT_ADDRESS99 */100 IPC_M_USBHC_RELEASE_DEFAULT_ADDRESS,101 102 86 /** Asks for address assignment by host controller. 103 87 * Answer: … … 169 153 /** Register endpoint attributes at host controller. 170 154 * This is used to reserve portion of USB bandwidth. 155 * When speed is invalid, speed of the device is used. 171 156 * Parameters: 172 * - USB address + endpoint number (ADDR * 256 + EP) 173 * - transfer type + direction (TYPE * 256 + DIR) 174 * - maximum packet size 175 * - interval (in milliseconds) 157 * - USB address + endpoint number 158 * - packed as ADDR << 16 + EP 159 * - speed + transfer type + direction 160 * - packed as ( SPEED << 8 + TYPE ) << 8 + DIR 161 * - maximum packet size + interval (in milliseconds) 162 * - packed as MPS << 16 + INT 176 163 * Answer: 177 164 * - EOK - reservation successful … … 202 189 203 190 /** Out transfer processing function prototype. */ 204 typedef int (*usbhc_iface_transfer_out_t)(ddf_fun_t *, usb_target_t, size_t,191 typedef int (*usbhc_iface_transfer_out_t)(ddf_fun_t *, usb_target_t, 205 192 void *, size_t, 206 193 usbhc_iface_transfer_out_callback_t, void *); … … 210 197 211 198 /** In transfer processing function prototype. */ 212 typedef int (*usbhc_iface_transfer_in_t)(ddf_fun_t *, usb_target_t, size_t,199 typedef int (*usbhc_iface_transfer_in_t)(ddf_fun_t *, usb_target_t, 213 200 void *, size_t, 214 201 usbhc_iface_transfer_in_callback_t, void *); … … 222 209 int (*release_address)(ddf_fun_t *, usb_address_t); 223 210 224 int (*register_endpoint)(ddf_fun_t *, usb_address_t, usb_endpoint_t, 211 int (*register_endpoint)(ddf_fun_t *, 212 usb_address_t, usb_speed_t, usb_endpoint_t, 225 213 usb_transfer_type_t, usb_direction_t, size_t, unsigned int); 226 214 int (*unregister_endpoint)(ddf_fun_t *, usb_address_t, usb_endpoint_t, … … 234 222 235 223 int (*control_write)(ddf_fun_t *, usb_target_t, 236 size_t,237 224 void *, size_t, void *, size_t, 238 225 usbhc_iface_transfer_out_callback_t, void *); 239 226 240 227 int (*control_read)(ddf_fun_t *, usb_target_t, 241 size_t,242 228 void *, size_t, void *, size_t, 243 229 usbhc_iface_transfer_in_callback_t, void *); -
uspace/lib/usb/Makefile
ra49e171 rdc4c19e 43 43 src/hidparser.c \ 44 44 src/hub.c \ 45 src/pipepriv.c \ 45 46 src/pipes.c \ 46 47 src/pipesinit.c \ -
uspace/lib/usb/include/usb/classes/hub.h
ra49e171 rdc4c19e 43 43 */ 44 44 typedef enum { 45 USB_HUB_FEATURE_HUB_LOCAL_POWER = 0, 46 USB_HUB_FEATURE_HUB_OVER_CURRENT = 1, 45 47 USB_HUB_FEATURE_C_HUB_LOCAL_POWER = 0, 46 48 USB_HUB_FEATURE_C_HUB_OVER_CURRENT = 1, … … 59 61 /* USB_HUB_FEATURE_ = , */ 60 62 } usb_hub_class_feature_t; 63 61 64 62 65 /** Header of standard hub descriptor without the "variadic" part. */ -
uspace/lib/usb/include/usb/devdrv.h
ra49e171 rdc4c19e 169 169 usb_polling_callback_t, size_t, usb_polling_terminted_callback_t, void *); 170 170 171 int usb_device_retrieve_descriptors(usb_pipe_t *, usb_device_descriptors_t *); 172 int usb_device_create_pipes(ddf_dev_t *, usb_device_connection_t *, 173 usb_endpoint_description_t **, uint8_t *, size_t, int, int, 174 usb_endpoint_mapping_t **, size_t *); 175 int usb_device_destroy_pipes(ddf_dev_t *, usb_endpoint_mapping_t *, size_t); 176 177 size_t usb_interface_count_alternates(uint8_t *, size_t, uint8_t); 178 171 179 #endif 172 180 /** -
uspace/lib/usb/include/usb/host/batch.h
ra49e171 rdc4c19e 92 92 void usb_transfer_batch_call_in(usb_transfer_batch_t *instance); 93 93 void usb_transfer_batch_call_out(usb_transfer_batch_t *instance); 94 void usb_transfer_batch_finish(usb_transfer_batch_t *instance, int error); 94 void usb_transfer_batch_finish(usb_transfer_batch_t *instance); 95 96 static inline void usb_transfer_batch_finish_error( 97 usb_transfer_batch_t *instance, int error) 98 { 99 assert(instance); 100 instance->error = error; 101 usb_transfer_batch_finish(instance); 102 } 95 103 96 104 #endif -
uspace/lib/usb/include/usb/host/device_keeper.h
ra49e171 rdc4c19e 71 71 void usb_device_keeper_init(usb_device_keeper_t *instance); 72 72 73 void usb_device_keeper_add_ep(74 usb_device_keeper_t *instance, usb_address_t address, endpoint_t *ep);75 76 73 void usb_device_keeper_reserve_default_address( 77 74 usb_device_keeper_t *instance, usb_speed_t speed); … … 96 93 usb_speed_t usb_device_keeper_get_speed(usb_device_keeper_t *instance, 97 94 usb_address_t address); 98 99 void usb_device_keeper_use_control(usb_device_keeper_t *instance,100 usb_target_t target);101 102 void usb_device_keeper_release_control(usb_device_keeper_t *instance,103 usb_target_t target);104 105 95 #endif 106 96 /** -
uspace/lib/usb/include/usb/host/endpoint.h
ra49e171 rdc4c19e 39 39 #include <bool.h> 40 40 #include <adt/list.h> 41 #include <fibril_synch.h> 42 41 43 #include <usb/usb.h> 42 44 … … 48 50 usb_speed_t speed; 49 51 size_t max_packet_size; 50 bool active;51 52 unsigned toggle:1; 52 link_t same_device_eps; 53 fibril_mutex_t guard; 54 fibril_condvar_t avail; 55 volatile bool active; 53 56 } endpoint_t; 54 57 … … 59 62 void endpoint_destroy(endpoint_t *instance); 60 63 64 void endpoint_use(endpoint_t *instance); 65 66 void endpoint_release(endpoint_t *instance); 67 61 68 int endpoint_toggle_get(endpoint_t *instance); 62 69 63 70 void endpoint_toggle_set(endpoint_t *instance, int toggle); 64 71 65 void endpoint_toggle_reset(link_t *ep); 66 67 void endpoint_toggle_reset_filtered(link_t *ep, usb_endpoint_t epn); 68 72 void endpoint_toggle_reset_filtered(endpoint_t *instance, usb_target_t target); 69 73 #endif 70 74 /** -
uspace/lib/usb/include/usb/host/usb_endpoint_manager.h
ra49e171 rdc4c19e 78 78 size_t *bw); 79 79 80 void usb_endpoint_manager_reset_if_need( 81 usb_endpoint_manager_t *instance, usb_target_t target, const uint8_t *data); 80 82 #endif 81 83 /** -
uspace/lib/usb/include/usb/hub.h
ra49e171 rdc4c19e 59 59 } usb_hc_attached_device_t; 60 60 61 int usb_hc_reserve_default_address(usb_hc_connection_t *, usb_speed_t);62 int usb_hc_release_default_address(usb_hc_connection_t *);63 64 61 usb_address_t usb_hc_request_address(usb_hc_connection_t *, usb_speed_t); 65 62 int usb_hc_register_device(usb_hc_connection_t *, -
uspace/lib/usb/include/usb/pipes.h
ra49e171 rdc4c19e 42 42 #include <ipc/devman.h> 43 43 #include <ddf/driver.h> 44 #include <fibril_synch.h> 44 45 45 46 /** Abstraction of a physical connection to the device. … … 59 60 * This endpoint must be bound with existing usb_device_connection_t 60 61 * (i.e. the wire to send data over). 62 * 63 * Locking order: if you want to lock both mutexes 64 * (@c guard and @c hc_phone_mutex), lock @c guard first. 65 * It is not necessary to lock @c guard if you want to lock @c hc_phone_mutex 66 * only. 61 67 */ 62 68 typedef struct { 69 /** Guard of the whole pipe. */ 70 fibril_mutex_t guard; 71 63 72 /** The connection used for sending the data. */ 64 73 usb_device_connection_t *wire; … … 78 87 /** Phone to the host controller. 79 88 * Negative when no session is active. 89 * It is an error to access this member without @c hc_phone_mutex 90 * being locked. 91 * If call over the phone is to be made, it must be preceeded by 92 * call to pipe_add_ref() [internal libusb function]. 80 93 */ 81 94 int hc_phone; 95 96 /** Guard for serialization of requests over the phone. */ 97 fibril_mutex_t hc_phone_mutex; 98 99 /** Number of active transfers over the pipe. */ 100 int refcount; 82 101 } usb_pipe_t; 83 102 … … 134 153 int usb_pipe_initialize_from_configuration(usb_endpoint_mapping_t *, 135 154 size_t, uint8_t *, size_t, usb_device_connection_t *); 155 int usb_pipe_register_with_speed(usb_pipe_t *, usb_speed_t, 156 unsigned int, usb_hc_connection_t *); 136 157 int usb_pipe_register(usb_pipe_t *, unsigned int, usb_hc_connection_t *); 137 158 int usb_pipe_unregister(usb_pipe_t *, usb_hc_connection_t *); … … 140 161 int usb_pipe_end_session(usb_pipe_t *); 141 162 bool usb_pipe_is_session_started(usb_pipe_t *); 163 164 int usb_pipe_start_long_transfer(usb_pipe_t *); 165 void usb_pipe_end_long_transfer(usb_pipe_t *); 142 166 143 167 int usb_pipe_read(usb_pipe_t *, void *, size_t, size_t *); -
uspace/lib/usb/include/usb/usb.h
ra49e171 rdc4c19e 77 77 USB_SPEED_FULL, 78 78 /** USB 2.0 high speed (480Mbits/s). */ 79 USB_SPEED_HIGH 79 USB_SPEED_HIGH, 80 /** Psuedo-speed serving as a boundary. */ 81 USB_SPEED_MAX 80 82 } usb_speed_t; 81 83 -
uspace/lib/usb/src/devdrv.c
ra49e171 rdc4c19e 72 72 } 73 73 74 /** Log out of memory error on given device.75 *76 * @param dev Device causing the trouble.77 */78 static void usb_log_oom(ddf_dev_t *dev)79 {80 usb_log_error("Out of memory when adding device `%s'.\n",81 dev->name);82 }83 84 74 /** Count number of pipes the driver expects. 85 75 * … … 108 98 */ 109 99 static int initialize_other_pipes(usb_endpoint_description_t **endpoints, 110 usb_device_t *dev) 111 { 112 int rc; 113 114 size_t pipe_count = count_other_pipes(endpoints); 115 if (pipe_count == 0) { 116 return EOK; 117 } 118 119 dev->pipes = malloc(sizeof(usb_endpoint_mapping_t) * pipe_count); 120 if (dev->pipes == NULL) { 121 usb_log_oom(dev->ddf_dev); 122 return ENOMEM; 123 } 124 125 size_t i; 126 127 /* Initialize to NULL first for rollback purposes. */ 128 for (i = 0; i < pipe_count; i++) { 129 dev->pipes[i].pipe = NULL; 130 } 131 132 for (i = 0; i < pipe_count; i++) { 133 dev->pipes[i].pipe = malloc(sizeof(usb_pipe_t)); 134 if (dev->pipes[i].pipe == NULL) { 135 usb_log_oom(dev->ddf_dev); 136 rc = ENOMEM; 137 goto rollback; 138 } 139 140 dev->pipes[i].description = endpoints[i]; 141 dev->pipes[i].interface_no = dev->interface_no; 142 dev->pipes[i].interface_setting = 0; 143 } 144 145 rc = usb_pipe_initialize_from_configuration(dev->pipes, pipe_count, 100 usb_device_t *dev, int alternate_setting) 101 { 102 usb_endpoint_mapping_t *pipes; 103 size_t pipes_count; 104 105 int rc = usb_device_create_pipes(dev->ddf_dev, &dev->wire, endpoints, 146 106 dev->descriptors.configuration, dev->descriptors.configuration_size, 147 &dev->wire); 148 if (rc != EOK) { 149 usb_log_error("Failed initializing USB endpoints: %s.\n", 150 str_error(rc)); 151 goto rollback; 152 } 153 154 /* Register the endpoints. */ 155 usb_hc_connection_t hc_conn; 156 rc = usb_hc_connection_initialize_from_device(&hc_conn, dev->ddf_dev); 107 dev->interface_no, alternate_setting, 108 &pipes, &pipes_count); 109 157 110 if (rc != EOK) { 158 111 usb_log_error( 159 "Failed initializing connection to host controller: %s.\n", 160 str_error(rc)); 161 goto rollback; 162 } 163 rc = usb_hc_connection_open(&hc_conn); 164 if (rc != EOK) { 165 usb_log_error("Failed to connect to host controller: %s.\n", 166 str_error(rc)); 167 goto rollback; 168 } 169 for (i = 0; i < pipe_count; i++) { 170 if (dev->pipes[i].present) { 171 rc = usb_pipe_register(dev->pipes[i].pipe, 172 dev->pipes[i].descriptor->poll_interval, 173 &hc_conn); 174 /* Ignore error when operation not supported by HC. */ 175 if ((rc != EOK) && (rc != ENOTSUP)) { 176 /* FIXME: what shall we do? */ 177 dev->pipes[i].present = false; 178 free(dev->pipes[i].pipe); 179 dev->pipes[i].pipe = NULL; 180 } 181 } 182 } 183 /* Ignoring errors here. */ 184 usb_hc_connection_close(&hc_conn); 185 186 dev->pipes_count = pipe_count; 112 "Failed to create endpoint pipes for `%s': %s.\n", 113 dev->ddf_dev->name, str_error(rc)); 114 return rc; 115 } 116 117 dev->pipes = pipes; 118 dev->pipes_count = pipes_count; 187 119 188 120 return EOK; 189 190 rollback:191 for (i = 0; i < pipe_count; i++) {192 if (dev->pipes[i].pipe != NULL) {193 free(dev->pipes[i].pipe);194 }195 }196 free(dev->pipes);197 198 return rc;199 121 } 200 122 … … 239 161 240 162 /* 241 * For further actions, we need open session on default control pipe. 163 * We will do some querying of the device, it is worth to prepare 164 * the long transfer. 242 165 */ 243 rc = usb_pipe_start_ session(&dev->ctrl_pipe);244 if (rc != EOK) { 245 usb_log_error("Failed to start an IPC session: %s.\n",166 rc = usb_pipe_start_long_transfer(&dev->ctrl_pipe); 167 if (rc != EOK) { 168 usb_log_error("Failed to start transfer: %s.\n", 246 169 str_error(rc)); 247 170 return rc; 248 171 } 249 172 250 /* Get the device descriptor. */ 251 rc = usb_request_get_device_descriptor(&dev->ctrl_pipe, 252 &dev->descriptors.device); 253 if (rc != EOK) { 254 usb_log_error("Failed to retrieve device descriptor: %s.\n", 255 str_error(rc)); 256 return rc; 257 } 258 259 /* Get the full configuration descriptor. */ 260 rc = usb_request_get_full_configuration_descriptor_alloc( 261 &dev->ctrl_pipe, 0, (void **) &dev->descriptors.configuration, 262 &dev->descriptors.configuration_size); 263 if (rc != EOK) { 264 usb_log_error("Failed retrieving configuration descriptor: %s. %s\n", 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", 265 179 dev->ddf_dev->name, str_error(rc)); 266 180 return rc; 267 181 } 268 182 183 269 184 if (driver->endpoints != NULL) { 270 rc = initialize_other_pipes(driver->endpoints, dev); 271 } 272 273 /* No checking here. */ 274 usb_pipe_end_session(&dev->ctrl_pipe); 185 rc = initialize_other_pipes(driver->endpoints, dev, 0); 186 } 187 188 usb_pipe_end_long_transfer(&dev->ctrl_pipe); 275 189 276 190 /* Rollback actions. */ … … 291 205 * @return Number of alternate interfaces for @p interface_no interface. 292 206 */ 293 s tatic size_t count_alternate_interfaces(uint8_t *config_descr,294 size_t config_descr_size, int interface_no)207 size_t usb_interface_count_alternates(uint8_t *config_descr, 208 size_t config_descr_size, uint8_t interface_no) 295 209 { 296 210 assert(config_descr != NULL); 211 assert(config_descr_size > 0); 212 297 213 usb_dp_parser_t dp_parser = { 298 214 .nesting = usb_dp_standard_descriptor_nesting … … 343 259 344 260 alternates->alternative_count 345 = count_alternate_interfaces(dev->descriptors.configuration,261 = usb_interface_count_alternates(dev->descriptors.configuration, 346 262 dev->descriptors.configuration_size, dev->interface_no); 347 263 … … 457 373 static int destroy_current_pipes(usb_device_t *dev) 458 374 { 459 size_t i; 460 int rc; 461 462 /* TODO: this shall be done under some device mutex. */ 463 464 /* First check that no session is opened. */ 465 for (i = 0; i < dev->pipes_count; i++) { 466 if (usb_pipe_is_session_started(dev->pipes[i].pipe)) { 467 return EBUSY; 468 } 469 } 470 471 /* Prepare connection to HC. */ 472 usb_hc_connection_t hc_conn; 473 rc = usb_hc_connection_initialize_from_device(&hc_conn, dev->ddf_dev); 474 if (rc != EOK) { 475 return rc; 476 } 477 rc = usb_hc_connection_open(&hc_conn); 478 if (rc != EOK) { 479 return rc; 480 } 481 482 /* Destroy the pipes. */ 483 for (i = 0; i < dev->pipes_count; i++) { 484 usb_pipe_unregister(dev->pipes[i].pipe, &hc_conn); 485 free(dev->pipes[i].pipe); 486 } 487 488 usb_hc_connection_close(&hc_conn); 489 490 free(dev->pipes); 375 int rc = usb_device_destroy_pipes(dev->ddf_dev, 376 dev->pipes, dev->pipes_count); 377 if (rc != EOK) { 378 return rc; 379 } 380 491 381 dev->pipes = NULL; 492 382 dev->pipes_count = 0; … … 535 425 536 426 /* Create new pipes. */ 537 rc = initialize_other_pipes(endpoints, dev );427 rc = initialize_other_pipes(endpoints, dev, (int) alternate_setting); 538 428 539 429 return rc; 430 } 431 432 /** Retrieve basic descriptors from the device. 433 * 434 * @param[in] ctrl_pipe Control pipe with opened session. 435 * @param[out] descriptors Where to store the descriptors. 436 * @return Error code. 437 */ 438 int usb_device_retrieve_descriptors(usb_pipe_t *ctrl_pipe, 439 usb_device_descriptors_t *descriptors) 440 { 441 assert(descriptors != NULL); 442 assert(usb_pipe_is_session_started(ctrl_pipe)); 443 444 descriptors->configuration = NULL; 445 446 int rc; 447 448 /* Get the device descriptor. */ 449 rc = usb_request_get_device_descriptor(ctrl_pipe, &descriptors->device); 450 if (rc != EOK) { 451 return rc; 452 } 453 454 /* Get the full configuration descriptor. */ 455 rc = usb_request_get_full_configuration_descriptor_alloc( 456 ctrl_pipe, 0, (void **) &descriptors->configuration, 457 &descriptors->configuration_size); 458 if (rc != EOK) { 459 return rc; 460 } 461 462 return EOK; 463 } 464 465 /** Create pipes for a device. 466 * 467 * This is more or less a wrapper that does following actions: 468 * - allocate and initialize pipes 469 * - map endpoints to the pipes based on the descriptions 470 * - registers endpoints with the host controller 471 * 472 * @param[in] dev Generic DDF device backing the USB one. 473 * @param[in] wire Initialized backing connection to the host controller. 474 * @param[in] endpoints Endpoints description, NULL terminated. 475 * @param[in] config_descr Configuration descriptor of active configuration. 476 * @param[in] config_descr_size Size of @p config_descr in bytes. 477 * @param[in] interface_no Interface to map from. 478 * @param[in] interface_setting Interface setting (default is usually 0). 479 * @param[out] pipes_ptr Where to store array of created pipes 480 * (not NULL terminated). 481 * @param[out] pipes_count_ptr Where to store number of pipes 482 * (set to if you wish to ignore the count). 483 * @return Error code. 484 */ 485 int usb_device_create_pipes(ddf_dev_t *dev, usb_device_connection_t *wire, 486 usb_endpoint_description_t **endpoints, 487 uint8_t *config_descr, size_t config_descr_size, 488 int interface_no, int interface_setting, 489 usb_endpoint_mapping_t **pipes_ptr, size_t *pipes_count_ptr) 490 { 491 assert(dev != NULL); 492 assert(wire != NULL); 493 assert(endpoints != NULL); 494 assert(config_descr != NULL); 495 assert(config_descr_size > 0); 496 assert(pipes_ptr != NULL); 497 498 size_t i; 499 int rc; 500 501 size_t pipe_count = count_other_pipes(endpoints); 502 if (pipe_count == 0) { 503 *pipes_ptr = NULL; 504 return EOK; 505 } 506 507 usb_endpoint_mapping_t *pipes 508 = malloc(sizeof(usb_endpoint_mapping_t) * pipe_count); 509 if (pipes == NULL) { 510 return ENOMEM; 511 } 512 513 /* Initialize to NULL to allow smooth rollback. */ 514 for (i = 0; i < pipe_count; i++) { 515 pipes[i].pipe = NULL; 516 } 517 518 /* Now allocate and fully initialize. */ 519 for (i = 0; i < pipe_count; i++) { 520 pipes[i].pipe = malloc(sizeof(usb_pipe_t)); 521 if (pipes[i].pipe == NULL) { 522 rc = ENOMEM; 523 goto rollback_free_only; 524 } 525 pipes[i].description = endpoints[i]; 526 pipes[i].interface_no = interface_no; 527 pipes[i].interface_setting = interface_setting; 528 } 529 530 /* Find the mapping from configuration descriptor. */ 531 rc = usb_pipe_initialize_from_configuration(pipes, pipe_count, 532 config_descr, config_descr_size, wire); 533 if (rc != EOK) { 534 goto rollback_free_only; 535 } 536 537 /* Register the endpoints with HC. */ 538 usb_hc_connection_t hc_conn; 539 rc = usb_hc_connection_initialize_from_device(&hc_conn, dev); 540 if (rc != EOK) { 541 goto rollback_free_only; 542 } 543 544 rc = usb_hc_connection_open(&hc_conn); 545 if (rc != EOK) { 546 goto rollback_free_only; 547 } 548 549 for (i = 0; i < pipe_count; i++) { 550 if (pipes[i].present) { 551 rc = usb_pipe_register(pipes[i].pipe, 552 pipes[i].descriptor->poll_interval, &hc_conn); 553 if (rc != EOK) { 554 goto rollback_unregister_endpoints; 555 } 556 } 557 } 558 559 usb_hc_connection_close(&hc_conn); 560 561 *pipes_ptr = pipes; 562 if (pipes_count_ptr != NULL) { 563 *pipes_count_ptr = pipe_count; 564 } 565 566 return EOK; 567 568 /* 569 * Jump here if something went wrong after endpoints have 570 * been registered. 571 * This is also the target when the registration of 572 * endpoints fails. 573 */ 574 rollback_unregister_endpoints: 575 for (i = 0; i < pipe_count; i++) { 576 if (pipes[i].present) { 577 usb_pipe_unregister(pipes[i].pipe, &hc_conn); 578 } 579 } 580 581 usb_hc_connection_close(&hc_conn); 582 583 /* 584 * Jump here if something went wrong before some actual communication 585 * with HC. Then the only thing that needs to be done is to free 586 * allocated memory. 587 */ 588 rollback_free_only: 589 for (i = 0; i < pipe_count; i++) { 590 if (pipes[i].pipe != NULL) { 591 free(pipes[i].pipe); 592 } 593 } 594 free(pipes); 595 596 return rc; 597 } 598 599 /** Destroy pipes previously created by usb_device_create_pipes. 600 * 601 * @param[in] dev Generic DDF device backing the USB one. 602 * @param[in] pipes Endpoint mapping to be destroyed. 603 * @param[in] pipes_count Number of endpoints. 604 */ 605 int usb_device_destroy_pipes(ddf_dev_t *dev, 606 usb_endpoint_mapping_t *pipes, size_t pipes_count) 607 { 608 assert(dev != NULL); 609 assert(((pipes != NULL) && (pipes_count > 0)) 610 || ((pipes == NULL) && (pipes_count == 0))); 611 612 if (pipes_count == 0) { 613 return EOK; 614 } 615 616 int rc; 617 618 /* Prepare connection to HC to allow endpoint unregistering. */ 619 usb_hc_connection_t hc_conn; 620 rc = usb_hc_connection_initialize_from_device(&hc_conn, dev); 621 if (rc != EOK) { 622 return rc; 623 } 624 rc = usb_hc_connection_open(&hc_conn); 625 if (rc != EOK) { 626 return rc; 627 } 628 629 /* Destroy the pipes. */ 630 size_t i; 631 for (i = 0; i < pipes_count; i++) { 632 usb_pipe_unregister(pipes[i].pipe, &hc_conn); 633 free(pipes[i].pipe); 634 } 635 636 usb_hc_connection_close(&hc_conn); 637 638 free(pipes); 639 640 return EOK; 540 641 } 541 642 -
uspace/lib/usb/src/devpoll.c
ra49e171 rdc4c19e 77 77 int rc; 78 78 79 rc = usb_pipe_start_session(pipe);80 if (rc != EOK) {81 failed_attempts++;82 continue;83 }84 85 79 size_t actual_size; 86 80 rc = usb_pipe_read(pipe, polling_data->buffer, 87 81 polling_data->request_size, &actual_size); 88 82 89 /* Quit the session regardless of errors. */90 usb_pipe_end_session(pipe);91 83 92 84 // if (rc == ESTALL) { -
uspace/lib/usb/src/host/batch.c
ra49e171 rdc4c19e 63 63 instance->transfer_type = transfer_type; 64 64 instance->speed = speed; 65 instance->direction = USB_DIRECTION_BOTH;65 instance->direction = ep->direction; 66 66 instance->callback_in = func_in; 67 67 instance->callback_out = func_out; … … 79 79 instance->error = EOK; 80 80 instance->ep = ep; 81 endpoint_use(instance->ep); 81 82 } 82 83 /*----------------------------------------------------------------------------*/ … … 86 87 * 87 88 */ 88 void usb_transfer_batch_finish(usb_transfer_batch_t *instance , int error)89 void usb_transfer_batch_finish(usb_transfer_batch_t *instance) 89 90 { 90 91 assert(instance); 91 instance->error = error; 92 assert(instance->ep); 93 endpoint_release(instance->ep); 92 94 instance->next_step(instance); 93 95 } -
uspace/lib/usb/src/host/device_keeper.c
ra49e171 rdc4c19e 54 54 for (; i < USB_ADDRESS_COUNT; ++i) { 55 55 instance->devices[i].occupied = false; 56 instance->devices[i].control_used = 0;57 56 instance->devices[i].handle = 0; 58 list_initialize(&instance->devices[i].endpoints);57 instance->devices[i].speed = USB_SPEED_MAX; 59 58 } 60 } 61 /*----------------------------------------------------------------------------*/ 62 void usb_device_keeper_add_ep( 63 usb_device_keeper_t *instance, usb_address_t address, endpoint_t *ep) 64 { 65 assert(instance); 66 fibril_mutex_lock(&instance->guard); 67 assert(instance->devices[address].occupied); 68 list_append(&ep->same_device_eps, &instance->devices[address].endpoints); 69 fibril_mutex_unlock(&instance->guard); 59 // TODO: is this hack enough? 60 // (it is needed to allow smooth registration at default address) 61 instance->devices[0].occupied = true; 70 62 } 71 63 /*----------------------------------------------------------------------------*/ … … 102 94 } 103 95 /*----------------------------------------------------------------------------*/ 104 /** Check setup packet data for signs of toggle reset.105 *106 * @param[in] instance Device keeper structure to use.107 * @param[in] target Device to receive setup packet.108 * @param[in] data Setup packet data.109 *110 * Really ugly one.111 */112 void usb_device_keeper_reset_if_need(113 usb_device_keeper_t *instance, usb_target_t target, const uint8_t *data)114 {115 assert(instance);116 fibril_mutex_lock(&instance->guard);117 if (target.endpoint > 15 || target.endpoint < 0118 || target.address >= USB_ADDRESS_COUNT || target.address < 0119 || !instance->devices[target.address].occupied) {120 fibril_mutex_unlock(&instance->guard);121 usb_log_error("Invalid data when checking for toggle reset.\n");122 return;123 }124 125 switch (data[1])126 {127 case 0x01: /*clear feature*/128 /* recipient is endpoint, value is zero (ENDPOINT_STALL) */129 if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) {130 link_t *current =131 instance->devices[target.address].endpoints.next;132 while (current !=133 &instance->devices[target.address].endpoints)134 {135 /* endpoint number is < 16, thus first byte is enough */136 endpoint_toggle_reset_filtered(137 current, data[4]);138 current = current->next;139 }140 }141 break;142 143 case 0x9: /* set configuration */144 case 0x11: /* set interface */145 /* target must be device */146 if ((data[0] & 0xf) == 0) {147 link_t *current =148 instance->devices[target.address].endpoints.next;149 while (current !=150 &instance->devices[target.address].endpoints)151 {152 endpoint_toggle_reset(current);153 current = current->next;154 }155 }156 break;157 }158 fibril_mutex_unlock(&instance->guard);159 }160 96 /*----------------------------------------------------------------------------*/ 161 97 /** Get a free USB address … … 264 200 return instance->devices[address].speed; 265 201 } 266 /*----------------------------------------------------------------------------*/267 void usb_device_keeper_use_control(268 usb_device_keeper_t *instance, usb_target_t target)269 {270 assert(instance);271 const uint16_t ep = 1 << target.endpoint;272 fibril_mutex_lock(&instance->guard);273 while (instance->devices[target.address].control_used & ep) {274 fibril_condvar_wait(&instance->change, &instance->guard);275 }276 instance->devices[target.address].control_used |= ep;277 fibril_mutex_unlock(&instance->guard);278 }279 /*----------------------------------------------------------------------------*/280 void usb_device_keeper_release_control(281 usb_device_keeper_t *instance, usb_target_t target)282 {283 assert(instance);284 const uint16_t ep = 1 << target.endpoint;285 fibril_mutex_lock(&instance->guard);286 assert((instance->devices[target.address].control_used & ep) != 0);287 instance->devices[target.address].control_used &= ~ep;288 fibril_mutex_unlock(&instance->guard);289 fibril_condvar_signal(&instance->change);290 }291 202 /** 292 203 * @} -
uspace/lib/usb/src/host/endpoint.c
ra49e171 rdc4c19e 34 34 */ 35 35 36 #include <assert.h> 36 37 #include <errno.h> 37 38 #include <usb/host/endpoint.h> … … 49 50 instance->max_packet_size = max_packet_size; 50 51 instance->toggle = 0; 51 link_initialize(&instance->same_device_eps); 52 instance->active = false; 53 fibril_mutex_initialize(&instance->guard); 54 fibril_condvar_initialize(&instance->avail); 52 55 return EOK; 53 56 } … … 56 59 { 57 60 assert(instance); 58 list_remove(&instance->same_device_eps);61 assert(!instance->active); 59 62 free(instance); 63 } 64 /*----------------------------------------------------------------------------*/ 65 void endpoint_use(endpoint_t *instance) 66 { 67 assert(instance); 68 fibril_mutex_lock(&instance->guard); 69 while (instance->active) 70 fibril_condvar_wait(&instance->avail, &instance->guard); 71 instance->active = true; 72 fibril_mutex_unlock(&instance->guard); 73 } 74 /*----------------------------------------------------------------------------*/ 75 void endpoint_release(endpoint_t *instance) 76 { 77 assert(instance); 78 fibril_mutex_lock(&instance->guard); 79 instance->active = false; 80 fibril_mutex_unlock(&instance->guard); 81 fibril_condvar_signal(&instance->avail); 60 82 } 61 83 /*----------------------------------------------------------------------------*/ … … 73 95 } 74 96 /*----------------------------------------------------------------------------*/ 75 void endpoint_toggle_reset (link_t *ep)97 void endpoint_toggle_reset_filtered(endpoint_t *instance, usb_target_t target) 76 98 { 77 endpoint_t *instance =78 list_get_instance(ep, endpoint_t, same_device_eps);79 99 assert(instance); 80 instance->toggle = 0; 81 } 82 /*----------------------------------------------------------------------------*/ 83 void endpoint_toggle_reset_filtered(link_t *ep, usb_endpoint_t epn) 84 { 85 endpoint_t *instance = 86 list_get_instance(ep, endpoint_t, same_device_eps); 87 assert(instance); 88 if (instance->endpoint == epn) 100 if (instance->address == target.address && 101 (instance->endpoint == target.endpoint || target.endpoint == 0)) 89 102 instance->toggle = 0; 90 103 } -
uspace/lib/usb/src/host/usb_endpoint_manager.c
ra49e171 rdc4c19e 31 31 #include <errno.h> 32 32 33 #include <usb/debug.h> 33 34 #include <usb/host/usb_endpoint_manager.h> 34 35 … … 80 81 endpoint_destroy(node->ep); 81 82 free(node); 83 } 84 /*----------------------------------------------------------------------------*/ 85 static void node_toggle_reset_filtered(link_t *item, void *arg) 86 { 87 assert(item); 88 node_t *node = hash_table_get_instance(item, node_t, link); 89 usb_target_t *target = arg; 90 endpoint_toggle_reset_filtered(node->ep, *target); 82 91 } 83 92 /*----------------------------------------------------------------------------*/ … … 230 239 return node->ep; 231 240 } 241 /*----------------------------------------------------------------------------*/ 242 /** Check setup packet data for signs of toggle reset. 243 * 244 * @param[in] instance Device keeper structure to use. 245 * @param[in] target Device to receive setup packet. 246 * @param[in] data Setup packet data. 247 * 248 * Really ugly one. 249 */ 250 void usb_endpoint_manager_reset_if_need( 251 usb_endpoint_manager_t *instance, usb_target_t target, const uint8_t *data) 252 { 253 assert(instance); 254 if (target.endpoint > 15 || target.endpoint < 0 255 || target.address >= USB11_ADDRESS_MAX || target.address < 0) { 256 usb_log_error("Invalid data when checking for toggle reset.\n"); 257 return; 258 } 259 260 switch (data[1]) 261 { 262 case 0x01: /*clear feature*/ 263 /* recipient is endpoint, value is zero (ENDPOINT_STALL) */ 264 if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) { 265 /* endpoint number is < 16, thus first byte is enough */ 266 usb_target_t reset_target = 267 { .address = target.address, data[4] }; 268 fibril_mutex_lock(&instance->guard); 269 hash_table_apply(&instance->ep_table, 270 node_toggle_reset_filtered, &reset_target); 271 fibril_mutex_unlock(&instance->guard); 272 } 273 break; 274 275 case 0x9: /* set configuration */ 276 case 0x11: /* set interface */ 277 /* target must be device */ 278 if ((data[0] & 0xf) == 0) { 279 usb_target_t reset_target = 280 { .address = target.address, 0 }; 281 fibril_mutex_lock(&instance->guard); 282 hash_table_apply(&instance->ep_table, 283 node_toggle_reset_filtered, &reset_target); 284 fibril_mutex_unlock(&instance->guard); 285 } 286 break; 287 } 288 } -
uspace/lib/usb/src/hub.c
ra49e171 rdc4c19e 40 40 #include <errno.h> 41 41 #include <assert.h> 42 #include <usb/debug.h> 43 44 /** How much time to wait between attempts to register endpoint 0:0. 45 * The value is based on typical value for port reset + some overhead. 46 */ 47 #define ENDPOINT_0_0_REGISTER_ATTEMPT_DELAY_USEC (1000 * (10 + 2)) 42 48 43 49 /** Check that HC connection is alright. … … 53 59 } while (false) 54 60 55 56 /** Tell host controller to reserve default address.57 *58 * @param connection Opened connection to host controller.59 * @param speed Speed of the device that will respond on the default address.60 * @return Error code.61 */62 int usb_hc_reserve_default_address(usb_hc_connection_t *connection,63 usb_speed_t speed)64 {65 CHECK_CONNECTION(connection);66 67 return async_req_2_0(connection->hc_phone,68 DEV_IFACE_ID(USBHC_DEV_IFACE),69 IPC_M_USBHC_RESERVE_DEFAULT_ADDRESS, speed);70 }71 72 /** Tell host controller to release default address.73 *74 * @param connection Opened connection to host controller.75 * @return Error code.76 */77 int usb_hc_release_default_address(usb_hc_connection_t *connection)78 {79 CHECK_CONNECTION(connection);80 81 return async_req_1_0(connection->hc_phone,82 DEV_IFACE_ID(USBHC_DEV_IFACE),83 IPC_M_USBHC_RELEASE_DEFAULT_ADDRESS);84 }85 86 61 /** Ask host controller for free address assignment. 87 62 * … … 178 153 * error codes than those listed as return codes by this function itself). 179 154 * 155 * The @p connection representing connection with host controller does not 156 * need to be started. 157 * This function duplicates the connection to allow simultaneous calls of 158 * this function (i.e. from different fibrils). 159 * 180 160 * @param[in] parent Parent device (i.e. the hub device). 181 * @param[in] connection Opened connection to host controller.161 * @param[in] connection Connection to host controller. 182 162 * @param[in] dev_speed New device speed. 183 163 * @param[in] enable_port Function for enabling signaling through the port the … … 206 186 ddf_dev_ops_t *dev_ops, void *new_dev_data, ddf_fun_t **new_fun) 207 187 { 208 CHECK_CONNECTION(connection); 188 assert(connection != NULL); 189 // FIXME: this is awful, we are accessing directly the structure. 190 usb_hc_connection_t hc_conn = { 191 .hc_handle = connection->hc_handle, 192 .hc_phone = -1 193 }; 194 195 int rc; 196 197 rc = usb_hc_connection_open(&hc_conn); 198 if (rc != EOK) { 199 return rc; 200 } 201 209 202 210 203 /* 211 204 * Request new address. 212 205 */ 213 usb_address_t dev_addr = usb_hc_request_address( connection, dev_speed);206 usb_address_t dev_addr = usb_hc_request_address(&hc_conn, dev_speed); 214 207 if (dev_addr < 0) { 208 usb_hc_connection_close(&hc_conn); 215 209 return EADDRNOTAVAIL; 216 210 } 217 211 218 int rc; 219 220 /* 221 * Reserve the default address. 222 */ 223 rc = usb_hc_reserve_default_address(connection, dev_speed); 224 if (rc != EOK) { 225 rc = EBUSY; 226 goto leave_release_free_address; 227 } 228 229 /* 230 * Enable the port (i.e. allow signaling through this port). 231 */ 232 rc = enable_port(port_no, arg); 233 if (rc != EOK) { 234 goto leave_release_default_address; 235 } 236 237 /* 238 * Change the address from default to the free one. 239 * We need to create a new control pipe for that. 212 /* 213 * We will not register control pipe on default address. 214 * The registration might fail. That means that someone else already 215 * registered that endpoint. We will simply wait and try again. 216 * (Someone else already wants to add a new device.) 240 217 */ 241 218 usb_device_connection_t dev_conn; 242 219 rc = usb_device_connection_initialize_on_default_address(&dev_conn, 243 connection);220 &hc_conn); 244 221 if (rc != EOK) { 245 222 rc = ENOTCONN; 246 goto leave_release_ default_address;223 goto leave_release_free_address; 247 224 } 248 225 … … 252 229 if (rc != EOK) { 253 230 rc = ENOTCONN; 231 goto leave_release_free_address; 232 } 233 234 do { 235 rc = usb_pipe_register_with_speed(&ctrl_pipe, dev_speed, 0, 236 &hc_conn); 237 if (rc != EOK) { 238 /* Do not overheat the CPU ;-). */ 239 async_usleep(ENDPOINT_0_0_REGISTER_ATTEMPT_DELAY_USEC); 240 } 241 } while (rc != EOK); 242 243 /* 244 * Endpoint is registered. We can enable the port and change 245 * device address. 246 */ 247 rc = enable_port(port_no, arg); 248 if (rc != EOK) { 254 249 goto leave_release_default_address; 255 250 } 256 251 257 /* Before sending any traffic, we need to register this 258 * endpoint. 259 */ 260 rc = usb_pipe_register(&ctrl_pipe, 0, connection); 261 if (rc != EOK) { 262 rc = EREFUSED; 252 rc = usb_pipe_probe_default_control(&ctrl_pipe); 253 if (rc != EOK) { 254 rc = ESTALL; 263 255 goto leave_release_default_address; 264 256 } 265 rc = usb_pipe_probe_default_control(&ctrl_pipe); 266 if (rc != EOK) { 267 rc = ENOTCONN; 257 258 rc = usb_request_set_address(&ctrl_pipe, dev_addr); 259 if (rc != EOK) { 260 rc = ESTALL; 268 261 goto leave_release_default_address; 269 262 } 270 263 271 rc = usb_pipe_start_session(&ctrl_pipe); 272 if (rc != EOK) { 273 rc = ENOTCONN; 274 goto leave_unregister_endpoint; 275 } 276 277 rc = usb_request_set_address(&ctrl_pipe, dev_addr); 278 if (rc != EOK) { 279 rc = ESTALL; 280 goto leave_stop_session; 281 } 282 283 usb_pipe_end_session(&ctrl_pipe); 284 285 /* 286 * Register the control endpoint for the new device. 287 */ 288 rc = usb_pipe_register(&ctrl_pipe, 0, connection); 289 if (rc != EOK) { 290 rc = EREFUSED; 291 goto leave_unregister_endpoint; 292 } 293 294 /* 295 * Release the original endpoint. 296 */ 297 unregister_control_endpoint_on_default_address(connection); 298 299 /* 300 * Once the address is changed, we can return the default address. 301 */ 302 usb_hc_release_default_address(connection); 303 264 /* 265 * Address changed. We can release the original endpoint, thus 266 * allowing other to access the default address. 267 */ 268 unregister_control_endpoint_on_default_address(&hc_conn); 269 270 /* 271 * Time to register the new endpoint. 272 */ 273 rc = usb_pipe_register(&ctrl_pipe, 0, &hc_conn); 274 if (rc != EOK) { 275 goto leave_release_free_address; 276 } 304 277 305 278 /* … … 316 289 } 317 290 318 319 320 291 /* 321 292 * And now inform the host controller about the handle. … … 325 296 .handle = child_handle 326 297 }; 327 rc = usb_hc_register_device( connection, &new_device);298 rc = usb_hc_register_device(&hc_conn, &new_device); 328 299 if (rc != EOK) { 329 300 rc = EDESTADDRREQ; … … 349 320 * Completely ignoring errors here. 350 321 */ 351 352 leave_stop_session:353 usb_pipe_end_session(&ctrl_pipe);354 355 leave_unregister_endpoint:356 usb_pipe_unregister(&ctrl_pipe, connection);357 358 322 leave_release_default_address: 359 usb_ hc_release_default_address(connection);323 usb_pipe_unregister(&ctrl_pipe, &hc_conn); 360 324 361 325 leave_release_free_address: 362 usb_hc_unregister_device(connection, dev_addr); 326 usb_hc_unregister_device(&hc_conn, dev_addr); 327 328 usb_hc_connection_close(&hc_conn); 363 329 364 330 return rc; -
uspace/lib/usb/src/pipes.c
ra49e171 rdc4c19e 41 41 #include <errno.h> 42 42 #include <assert.h> 43 #include "pipepriv.h" 43 44 44 45 #define IPC_AGAIN_DELAY (1000 * 2) /* 2ms */ … … 241 242 * necessary. 242 243 * 244 * @deprecated 245 * Obsoleted with introduction of usb_pipe_start_long_transfer 246 * 243 247 * @param pipe Endpoint pipe to start the session on. 244 248 * @return Error code. … … 246 250 int usb_pipe_start_session(usb_pipe_t *pipe) 247 251 { 248 assert(pipe); 249 250 if (usb_pipe_is_session_started(pipe)) { 251 return EBUSY; 252 } 253 254 int phone = devman_device_connect(pipe->wire->hc_handle, 0); 255 if (phone < 0) { 256 return phone; 257 } 258 259 pipe->hc_phone = phone; 260 252 usb_log_warning("usb_pipe_start_session() was deprecated.\n"); 261 253 return EOK; 262 254 } … … 265 257 /** Ends a session on the endpoint pipe. 266 258 * 259 * @deprecated 260 * Obsoleted with introduction of usb_pipe_end_long_transfer 261 * 267 262 * @see usb_pipe_start_session 268 263 * … … 272 267 int usb_pipe_end_session(usb_pipe_t *pipe) 273 268 { 274 assert(pipe); 275 276 if (!usb_pipe_is_session_started(pipe)) { 277 return ENOENT; 278 } 279 280 int rc = async_hangup(pipe->hc_phone); 281 if (rc != EOK) { 282 return rc; 283 } 284 285 pipe->hc_phone = -1; 286 269 usb_log_warning("usb_pipe_end_session() was deprecated.\n"); 287 270 return EOK; 288 271 } … … 298 281 bool usb_pipe_is_session_started(usb_pipe_t *pipe) 299 282 { 300 return (pipe->hc_phone >= 0); 283 pipe_acquire(pipe); 284 bool started = pipe->refcount > 0; 285 pipe_release(pipe); 286 return started; 287 } 288 289 /** Prepare pipe for a long transfer. 290 * 291 * By a long transfer is mean transfer consisting of several 292 * requests to the HC. 293 * Calling such function is optional and it has positive effect of 294 * improved performance because IPC session is initiated only once. 295 * 296 * @param pipe Pipe over which the transfer will happen. 297 * @return Error code. 298 */ 299 int usb_pipe_start_long_transfer(usb_pipe_t *pipe) 300 { 301 return pipe_add_ref(pipe); 302 } 303 304 /** Terminate a long transfer on a pipe. 305 * 306 * @see usb_pipe_start_long_transfer 307 * 308 * @param pipe Pipe where to end the long transfer. 309 */ 310 void usb_pipe_end_long_transfer(usb_pipe_t *pipe) 311 { 312 pipe_drop_ref(pipe); 301 313 } 302 314 -
uspace/lib/usb/src/pipesinit.c
ra49e171 rdc4c19e 356 356 assert(connection); 357 357 358 fibril_mutex_initialize(&pipe->guard); 358 359 pipe->wire = connection; 359 360 pipe->hc_phone = -1; 361 fibril_mutex_initialize(&pipe->hc_phone_mutex); 360 362 pipe->endpoint_no = endpoint_no; 361 363 pipe->transfer_type = transfer_type; 362 364 pipe->max_packet_size = max_packet_size; 363 365 pipe->direction = direction; 366 pipe->refcount = 0; 364 367 365 368 return EOK; … … 413 416 int rc; 414 417 415 TRY_LOOP(failed_attempts) { 416 rc = usb_pipe_start_session(pipe); 417 if (rc == EOK) { 418 break; 419 } 420 } 418 rc = usb_pipe_start_long_transfer(pipe); 421 419 if (rc != EOK) { 422 420 return rc; … … 439 437 } 440 438 } 441 usb_pipe_end_ session(pipe);439 usb_pipe_end_long_transfer(pipe); 442 440 if (rc != EOK) { 443 441 return rc; … … 461 459 usb_hc_connection_t *hc_connection) 462 460 { 461 return usb_pipe_register_with_speed(pipe, USB_SPEED_MAX + 1, 462 interval, hc_connection); 463 } 464 465 /** Register endpoint with a speed at the host controller. 466 * 467 * You will rarely need to use this function because it is needed only 468 * if the registered endpoint is of address 0 and there is no other way 469 * to tell speed of the device at address 0. 470 * 471 * @param pipe Pipe to be registered. 472 * @param speed Speed of the device 473 * (invalid speed means use previously specified one). 474 * @param interval Polling interval. 475 * @param hc_connection Connection to the host controller (must be opened). 476 * @return Error code. 477 */ 478 int usb_pipe_register_with_speed(usb_pipe_t *pipe, usb_speed_t speed, 479 unsigned int interval, 480 usb_hc_connection_t *hc_connection) 481 { 463 482 assert(pipe); 464 483 assert(hc_connection); … … 468 487 } 469 488 470 #define _PACK(high, low) ((high) * 256 + (low)) 471 472 return async_req_5_0(hc_connection->hc_phone, 489 #define _PACK2(high, low) (((high) << 16) + (low)) 490 #define _PACK3(high, middle, low) (((((high) << 8) + (middle)) << 8) + (low)) 491 492 return async_req_4_0(hc_connection->hc_phone, 473 493 DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_REGISTER_ENDPOINT, 474 _PACK(pipe->wire->address, pipe->endpoint_no), 475 _PACK(pipe->transfer_type, pipe->direction), 476 pipe->max_packet_size, interval); 477 478 #undef _PACK 494 _PACK2(pipe->wire->address, pipe->endpoint_no), 495 _PACK3(speed, pipe->transfer_type, pipe->direction), 496 _PACK2(pipe->max_packet_size, interval)); 497 498 #undef _PACK2 499 #undef _PACK3 479 500 } 480 501 -
uspace/lib/usb/src/pipesio.c
ra49e171 rdc4c19e 49 49 #include <assert.h> 50 50 #include <usbhc_iface.h> 51 #include "pipepriv.h" 51 52 52 53 /** Request an in transfer, no checking of input parameters. … … 78 79 } 79 80 81 /* Ensure serialization over the phone. */ 82 pipe_start_transaction(pipe); 83 80 84 /* 81 85 * Make call identifying target USB device and type of transfer. 82 86 */ 83 aid_t opening_request = async_send_ 4(pipe->hc_phone,87 aid_t opening_request = async_send_3(pipe->hc_phone, 84 88 DEV_IFACE_ID(USBHC_DEV_IFACE), ipc_method, 85 89 pipe->wire->address, pipe->endpoint_no, 86 pipe->max_packet_size,87 90 NULL); 88 91 if (opening_request == 0) { 92 pipe_end_transaction(pipe); 89 93 return ENOMEM; 90 94 } … … 96 100 aid_t data_request = async_data_read(pipe->hc_phone, buffer, size, 97 101 &data_request_call); 102 103 /* 104 * Since now on, someone else might access the backing phone 105 * without breaking the transfer IPC protocol. 106 */ 107 pipe_end_transaction(pipe); 98 108 99 109 if (data_request == 0) { … … 146 156 147 157 if (buffer == NULL) { 148 return EINVAL;158 return EINVAL; 149 159 } 150 160 151 161 if (size == 0) { 152 162 return EINVAL; 153 }154 155 if (!usb_pipe_is_session_started(pipe)) {156 return EBADF;157 163 } 158 164 … … 165 171 } 166 172 173 int rc; 174 rc = pipe_add_ref(pipe); 175 if (rc != EOK) { 176 return rc; 177 } 178 179 167 180 size_t act_size = 0; 168 int rc;169 181 170 182 rc = usb_pipe_read_no_checks(pipe, buffer, size, &act_size); 183 184 pipe_drop_ref(pipe); 185 171 186 if (rc != EOK) { 172 187 return rc; … … 210 225 } 211 226 227 /* Ensure serialization over the phone. */ 228 pipe_start_transaction(pipe); 229 212 230 /* 213 231 * Make call identifying target USB device and type of transfer. 214 232 */ 215 aid_t opening_request = async_send_ 4(pipe->hc_phone,233 aid_t opening_request = async_send_3(pipe->hc_phone, 216 234 DEV_IFACE_ID(USBHC_DEV_IFACE), ipc_method, 217 235 pipe->wire->address, pipe->endpoint_no, 218 pipe->max_packet_size,219 236 NULL); 220 237 if (opening_request == 0) { 238 pipe_end_transaction(pipe); 221 239 return ENOMEM; 222 240 } … … 226 244 */ 227 245 int rc = async_data_write_start(pipe->hc_phone, buffer, size); 246 247 /* 248 * Since now on, someone else might access the backing phone 249 * without breaking the transfer IPC protocol. 250 */ 251 pipe_end_transaction(pipe); 252 228 253 if (rc != EOK) { 229 254 async_wait_for(opening_request, NULL); … … 260 285 } 261 286 262 if (!usb_pipe_is_session_started(pipe)) {263 return EBADF;264 }265 266 287 if (pipe->direction != USB_DIRECTION_OUT) { 267 288 return EBADF; … … 272 293 } 273 294 274 int rc = usb_pipe_write_no_check(pipe, buffer, size); 295 int rc; 296 297 rc = pipe_add_ref(pipe); 298 if (rc != EOK) { 299 return rc; 300 } 301 302 rc = usb_pipe_write_no_check(pipe, buffer, size); 303 304 pipe_drop_ref(pipe); 275 305 276 306 return rc; … … 293 323 void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size) 294 324 { 325 /* Ensure serialization over the phone. */ 326 pipe_start_transaction(pipe); 327 295 328 /* 296 329 * Make call identifying target USB device and control transfer type. 297 330 */ 298 aid_t opening_request = async_send_ 4(pipe->hc_phone,331 aid_t opening_request = async_send_3(pipe->hc_phone, 299 332 DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_CONTROL_READ, 300 333 pipe->wire->address, pipe->endpoint_no, 301 pipe->max_packet_size,302 334 NULL); 303 335 if (opening_request == 0) { … … 311 343 setup_buffer, setup_buffer_size); 312 344 if (rc != EOK) { 345 pipe_end_transaction(pipe); 313 346 async_wait_for(opening_request, NULL); 314 347 return rc; … … 322 355 data_buffer, data_buffer_size, 323 356 &data_request_call); 357 358 /* 359 * Since now on, someone else might access the backing phone 360 * without breaking the transfer IPC protocol. 361 */ 362 pipe_end_transaction(pipe); 363 364 324 365 if (data_request == 0) { 325 366 async_wait_for(opening_request, NULL); … … 379 420 } 380 421 381 if (!usb_pipe_is_session_started(pipe)) {382 return EBADF;383 }384 385 422 if ((pipe->direction != USB_DIRECTION_BOTH) 386 423 || (pipe->transfer_type != USB_TRANSFER_CONTROL)) { … … 388 425 } 389 426 427 int rc; 428 429 rc = pipe_add_ref(pipe); 430 if (rc != EOK) { 431 return rc; 432 } 433 390 434 size_t act_size = 0; 391 intrc = usb_pipe_control_read_no_check(pipe,435 rc = usb_pipe_control_read_no_check(pipe, 392 436 setup_buffer, setup_buffer_size, 393 437 data_buffer, data_buffer_size, &act_size); 438 439 pipe_drop_ref(pipe); 394 440 395 441 if (rc != EOK) { … … 418 464 void *data_buffer, size_t data_buffer_size) 419 465 { 466 /* Ensure serialization over the phone. */ 467 pipe_start_transaction(pipe); 468 420 469 /* 421 470 * Make call identifying target USB device and control transfer type. 422 471 */ 423 aid_t opening_request = async_send_ 5(pipe->hc_phone,472 aid_t opening_request = async_send_4(pipe->hc_phone, 424 473 DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_CONTROL_WRITE, 425 474 pipe->wire->address, pipe->endpoint_no, 426 475 data_buffer_size, 427 pipe->max_packet_size,428 476 NULL); 429 477 if (opening_request == 0) { 478 pipe_end_transaction(pipe); 430 479 return ENOMEM; 431 480 } … … 437 486 setup_buffer, setup_buffer_size); 438 487 if (rc != EOK) { 488 pipe_end_transaction(pipe); 439 489 async_wait_for(opening_request, NULL); 440 490 return rc; … … 447 497 rc = async_data_write_start(pipe->hc_phone, 448 498 data_buffer, data_buffer_size); 499 500 /* All data sent, pipe can be released. */ 501 pipe_end_transaction(pipe); 502 449 503 if (rc != EOK) { 450 504 async_wait_for(opening_request, NULL); 451 505 return rc; 452 506 } 507 } else { 508 /* No data to send, we can release the pipe for others. */ 509 pipe_end_transaction(pipe); 453 510 } 454 511 … … 491 548 } 492 549 493 if (!usb_pipe_is_session_started(pipe)) {494 return EBADF;495 }496 497 550 if ((pipe->direction != USB_DIRECTION_BOTH) 498 551 || (pipe->transfer_type != USB_TRANSFER_CONTROL)) { … … 500 553 } 501 554 502 int rc = usb_pipe_control_write_no_check(pipe, 555 int rc; 556 557 rc = pipe_add_ref(pipe); 558 if (rc != EOK) { 559 return rc; 560 } 561 562 rc = usb_pipe_control_write_no_check(pipe, 503 563 setup_buffer, setup_buffer_size, data_buffer, data_buffer_size); 564 565 pipe_drop_ref(pipe); 504 566 505 567 return rc; -
uspace/lib/usb/src/recognise.c
ra49e171 rdc4c19e 404 404 child->driver_data = dev_data; 405 405 406 rc = usb_pipe_start_session(&ctrl_pipe);407 if (rc != EOK) {408 goto failure;409 }410 411 406 rc = usb_device_create_match_ids(&ctrl_pipe, &child->match_ids); 412 if (rc != EOK) {413 goto failure;414 }415 416 rc = usb_pipe_end_session(&ctrl_pipe);417 407 if (rc != EOK) { 418 408 goto failure;
Note:
See TracChangeset
for help on using the changeset viewer.
