Changeset c48f6ab in mainline for uspace/lib/usbdev
- Timestamp:
- 2011-11-30T20:14:37Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 1f5c9c96
- Parents:
- fb48a0e (diff), f9776ae5 (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/usbdev
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usbdev/include/usb/dev/pipes.h
rfb48a0e rc48f6ab 179 179 180 180 int usb_pipe_read(usb_pipe_t *, void *, size_t, size_t *); 181 int usb_pipe_write(usb_pipe_t *, void *, size_t);181 int usb_pipe_write(usb_pipe_t *, const void *, size_t); 182 182 183 183 int usb_pipe_control_read(usb_pipe_t *, const void *, size_t, -
uspace/lib/usbdev/include/usb/dev/request.h
rfb48a0e rc48f6ab 82 82 */ 83 83 uint8_t request_type; 84 #define SETUP_REQUEST_TYPE_DEVICE_TO_HOST (1 << 7) 85 84 86 /** Request identification. */ 85 87 uint8_t request; -
uspace/lib/usbdev/src/altiface.c
rfb48a0e rc48f6ab 65 65 size_t alternate_count = 0; 66 66 67 const uint8_t *iface_ptr = usb_dp_get_nested_descriptor(&dp_parser,68 &dp_data, config_descr);67 const void *iface_ptr = 68 usb_dp_get_nested_descriptor(&dp_parser, &dp_data, config_descr); 69 69 while (iface_ptr != NULL) { 70 usb_standard_interface_descriptor_t *iface 71 = (usb_standard_interface_descriptor_t *) iface_ptr; 72 if (iface->descriptor_type == USB_DESCTYPE_INTERFACE) { 73 if (iface->interface_number == interface_no) { 74 alternate_count++; 75 } 70 const usb_standard_interface_descriptor_t *iface = iface_ptr; 71 if (iface->descriptor_type == USB_DESCTYPE_INTERFACE 72 && iface->interface_number == interface_no) { 73 ++alternate_count; 76 74 } 77 75 iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data, … … 82 80 } 83 81 84 /** Create alternate interface representation structure.82 /** Initialize alternate interface representation structure. 85 83 * 84 * @param[in] alternates Pointer to allocated structure. 86 85 * @param[in] config_descr Configuration descriptor. 87 86 * @param[in] config_descr_size Size of configuration descriptor. 88 87 * @param[in] interface_number Interface number. 89 * @param[out] alternates_ptr Where to store pointer to allocated structure.90 88 * @return Error code. 91 89 */ … … 101 99 alternates->current = 0; 102 100 101 /* No interfaces. */ 103 102 if (interface_number < 0) { 104 103 return EOK; … … 107 106 alternates->alternative_count 108 107 = usb_interface_count_alternates(config_descr, config_descr_size, 109 interface_number);108 interface_number); 110 109 111 110 if (alternates->alternative_count == 0) { … … 128 127 }; 129 128 130 usb_alternate_interface_descriptors_t * cur_alt_iface129 usb_alternate_interface_descriptors_t *iterator 131 130 = &alternates->alternatives[0]; 132 131 133 const uint8_t *iface_ptr = usb_dp_get_nested_descriptor(&dp_parser, 134 &dp_data, dp_data.data); 135 while (iface_ptr != NULL) { 136 usb_standard_interface_descriptor_t *iface 137 = (usb_standard_interface_descriptor_t *) iface_ptr; 132 const usb_alternate_interface_descriptors_t *end 133 = &alternates->alternatives[alternates->alternative_count]; 134 135 const void *iface_ptr = 136 usb_dp_get_nested_descriptor(&dp_parser, &dp_data, dp_data.data); 137 138 while (iface_ptr != NULL && iterator < end) { 139 const usb_standard_interface_descriptor_t *iface = iface_ptr; 140 138 141 if ((iface->descriptor_type != USB_DESCTYPE_INTERFACE) 139 142 || (iface->interface_number != interface_number)) { 143 /* This is not a valid alternate interface descriptor 144 * for interface with number == interface_number. */ 140 145 iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, 141 146 &dp_data, dp_data.data, iface_ptr); … … 143 148 } 144 149 145 cur_alt_iface->interface = iface;146 cur_alt_iface->nested_descriptors = iface_ptr + sizeof(*iface);150 iterator->interface = iface; 151 iterator->nested_descriptors = iface_ptr + sizeof(*iface); 147 152 148 153 /* Find next interface to count size of nested descriptors. */ 149 154 iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data, 150 155 dp_data.data, iface_ptr); 151 if (iface_ptr == NULL) {152 const uint8_t *next = dp_data.data + dp_data.size;153 cur_alt_iface->nested_descriptors_size154 = next - cur_alt_iface->nested_descriptors;155 } else {156 cur_alt_iface->nested_descriptors_size157 = iface_ptr - cur_alt_iface->nested_descriptors;158 }159 156 160 cur_alt_iface++; 157 const uint8_t *next = (iface_ptr == NULL) ? 158 dp_data.data + dp_data.size : iface_ptr; 159 160 iterator->nested_descriptors_size 161 = next - iterator->nested_descriptors; 162 163 ++iterator; 161 164 } 162 165 -
uspace/lib/usbdev/src/devpoll.c
rfb48a0e rc48f6ab 46 46 /** Data needed for polling. */ 47 47 typedef struct { 48 int debug; 49 size_t max_failures; 50 useconds_t delay; 51 bool auto_clear_halt; 52 bool (*on_data)(usb_device_t *, uint8_t *, size_t, void *); 53 void (*on_polling_end)(usb_device_t *, bool, void *); 54 bool (*on_error)(usb_device_t *, int, void *); 48 usb_device_auto_polling_t auto_polling; 55 49 56 50 usb_device_t *dev; … … 69 63 static int polling_fibril(void *arg) 70 64 { 71 polling_data_t *polling_data = (polling_data_t *) arg; 72 assert(polling_data); 65 assert(arg); 66 const polling_data_t *data = arg; 67 /* Helper to reduce typing. */ 68 const usb_device_auto_polling_t *params = &data->auto_polling; 73 69 74 70 usb_pipe_t *pipe 75 = & polling_data->dev->pipes[polling_data->pipe_index].pipe;76 77 if (p olling_data->debug > 0) {78 usb_endpoint_mapping_t *mapping79 = & polling_data->dev->pipes[polling_data->pipe_index];71 = &data->dev->pipes[data->pipe_index].pipe; 72 73 if (params->debug > 0) { 74 const usb_endpoint_mapping_t *mapping 75 = &data->dev->pipes[data->pipe_index]; 80 76 usb_log_debug("Poll%p: started polling of `%s' - " \ 81 77 "interface %d (%s,%d,%d), %zuB/%zu.\n", 82 polling_data, 83 polling_data->dev->ddf_dev->name, 78 data, data->dev->ddf_dev->name, 84 79 (int) mapping->interface->interface_number, 85 80 usb_str_class(mapping->interface->interface_class), 86 81 (int) mapping->interface->interface_subclass, 87 82 (int) mapping->interface->interface_protocol, 88 polling_data->request_size, pipe->max_packet_size); 89 } 90 83 data->request_size, pipe->max_packet_size); 84 } 85 86 usb_pipe_start_long_transfer(pipe); 91 87 size_t failed_attempts = 0; 92 while (failed_attempts <= polling_data->max_failures) { 93 int rc; 94 88 while (failed_attempts <= params->max_failures) { 95 89 size_t actual_size; 96 rc = usb_pipe_read(pipe, polling_data->buffer,97 polling_data->request_size, &actual_size);98 99 if (p olling_data->debug > 1) {90 const int rc = usb_pipe_read(pipe, data->buffer, 91 data->request_size, &actual_size); 92 93 if (params->debug > 1) { 100 94 if (rc == EOK) { 101 95 usb_log_debug( 102 96 "Poll%p: received: '%s' (%zuB).\n", 103 polling_data,104 usb_debug_str_buffer( polling_data->buffer,97 data, 98 usb_debug_str_buffer(data->buffer, 105 99 actual_size, 16), 106 100 actual_size); … … 108 102 usb_log_debug( 109 103 "Poll%p: polling failed: %s.\n", 110 polling_data, str_error(rc));104 data, str_error(rc)); 111 105 } 112 106 } 113 107 114 108 /* If the pipe stalled, we can try to reset the stall. */ 115 if ((rc == ESTALL) && (p olling_data->auto_clear_halt)) {109 if ((rc == ESTALL) && (params->auto_clear_halt)) { 116 110 /* 117 111 * We ignore error here as this is usually a futile … … 119 113 */ 120 114 usb_request_clear_endpoint_halt( 121 &polling_data->dev->ctrl_pipe, 122 pipe->endpoint_no); 115 &data->dev->ctrl_pipe, pipe->endpoint_no); 123 116 } 124 117 125 118 if (rc != EOK) { 126 if (polling_data->on_error != NULL) { 127 bool cont = polling_data->on_error( 128 polling_data->dev, rc, 129 polling_data->custom_arg); 130 if (!cont) { 131 failed_attempts 132 = polling_data->max_failures; 133 } 119 ++failed_attempts; 120 const bool cont = (params->on_error == NULL) ? true : 121 params->on_error(data->dev, rc, data->custom_arg); 122 if (!cont) { 123 failed_attempts = params->max_failures; 134 124 } 135 failed_attempts++;136 125 continue; 137 126 } 138 127 139 128 /* We have the data, execute the callback now. */ 140 bool carry_on = polling_data->on_data(polling_data->dev,141 polling_data->buffer, actual_size,142 polling_data->custom_arg);129 assert(params->on_data); 130 const bool carry_on = params->on_data( 131 data->dev, data->buffer, actual_size, data->custom_arg); 143 132 144 133 if (!carry_on) { 134 /* This is user requested abort, erases failures. */ 145 135 failed_attempts = 0; 146 136 break; … … 151 141 152 142 /* Take a rest before next request. */ 153 async_usleep(polling_data->delay); 154 } 155 156 if (polling_data->on_polling_end != NULL) { 157 polling_data->on_polling_end(polling_data->dev, 158 failed_attempts > 0, polling_data->custom_arg); 159 } 160 161 if (polling_data->debug > 0) { 162 if (failed_attempts > 0) { 163 usb_log_error( 164 "Polling of device `%s' terminated: %s.\n", 165 polling_data->dev->ddf_dev->name, 166 "recurring failures"); 143 async_usleep(params->delay); 144 } 145 146 usb_pipe_end_long_transfer(pipe); 147 148 const bool failed = failed_attempts > 0; 149 150 if (params->on_polling_end != NULL) { 151 params->on_polling_end(data->dev, failed, data->custom_arg); 152 } 153 154 if (params->debug > 0) { 155 if (failed) { 156 usb_log_error("Polling of device `%s' terminated: " 157 "recurring failures.\n", data->dev->ddf_dev->name); 167 158 } else { 168 usb_log_debug( 169 "Polling of device `%s' terminated by user.\n", 170 polling_data->dev->ddf_dev->name 171 ); 159 usb_log_debug("Polling of device `%s' terminated: " 160 "driver request.\n", data->dev->ddf_dev->name); 172 161 } 173 162 } 174 163 175 164 /* Free the allocated memory. */ 176 free( polling_data->buffer);177 free( polling_data);165 free(data->buffer); 166 free(data); 178 167 179 168 return EOK; … … 202 191 usb_polling_terminted_callback_t terminated_callback, void *arg) 203 192 { 204 if ((dev == NULL) || (callback == NULL)) {205 return EBADMEM;206 }207 if (request_size == 0) {208 return EINVAL;209 }210 if ((dev->pipes[pipe_index].pipe.transfer_type != USB_TRANSFER_INTERRUPT)211 || (dev->pipes[pipe_index].pipe.direction != USB_DIRECTION_IN)) {212 return EINVAL;213 }214 215 193 const usb_device_auto_polling_t auto_polling = { 216 194 .debug = 1, … … 248 226 size_t request_size, void *arg) 249 227 { 250 if ( dev == NULL) {228 if ((dev == NULL) || (polling == NULL) || (polling->on_data == NULL)) { 251 229 return EBADMEM; 252 230 } 253 if (pipe_index >= dev->pipes_count) { 231 232 if (pipe_index >= dev->pipes_count || request_size == 0) { 254 233 return EINVAL; 255 234 } … … 257 236 || (dev->pipes[pipe_index].pipe.direction != USB_DIRECTION_IN)) { 258 237 return EINVAL; 259 }260 if ((polling == NULL) || (polling->on_data == NULL)) {261 return EBADMEM;262 238 } 263 239 … … 278 254 polling_data->custom_arg = arg; 279 255 280 polling_data->debug = polling->debug; 281 polling_data->max_failures = polling->max_failures; 282 if (polling->delay >= 0) { 283 polling_data->delay = (useconds_t) polling->delay; 284 } else { 285 polling_data->delay = (useconds_t) dev->pipes[pipe_index] 286 .descriptor->poll_interval; 287 } 288 polling_data->auto_clear_halt = polling->auto_clear_halt; 289 290 polling_data->on_data = polling->on_data; 291 polling_data->on_polling_end = polling->on_polling_end; 292 polling_data->on_error = polling->on_error; 256 /* Copy provided settings. */ 257 polling_data->auto_polling = *polling; 258 259 /* Negative value means use descriptor provided value. */ 260 if (polling->delay < 0) { 261 polling_data->auto_polling.delay = 262 (int) dev->pipes[pipe_index].descriptor->poll_interval; 263 } 293 264 294 265 fid_t fibril = fibril_create(polling_fibril, polling_data); -
uspace/lib/usbdev/src/hub.c
rfb48a0e rc48f6ab 76 76 { 77 77 CHECK_CONNECTION(connection); 78 78 79 79 async_exch_t *exch = async_exchange_begin(connection->hc_sess); 80 81 sysarg_t address; 82 int rc = async_req_4_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 83 IPC_M_USBHC_REQUEST_ADDRESS, preferred, strict, speed, &address); 84 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 85 86 async_exchange_end(exch); 86 87 if (rc != EOK) 88 return (usb_address_t) rc; 89 90 return (usb_address_t) address; 87 return ret == EOK ? address : ret; 91 88 } 92 89 … … 97 94 * @return Error code. 98 95 */ 99 int usb_hc_register_device(usb_hc_connection_t * 96 int usb_hc_register_device(usb_hc_connection_t *connection, 100 97 const usb_hub_attached_device_t *attached_device) 101 98 { 102 99 CHECK_CONNECTION(connection); 103 104 if (attached_device == NULL) 105 return EBADMEM; 106 100 if (attached_device == NULL || attached_device->fun == NULL) 101 return EINVAL; 102 107 103 async_exch_t *exch = async_exchange_begin(connection->hc_sess); 108 int rc = async_req_3_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 109 IPC_M_USBHC_BIND_ADDRESS, 104 if (!exch) 105 return ENOMEM; 106 const int ret = usbhc_bind_address(exch, 110 107 attached_device->address, attached_device->fun->handle); 111 108 async_exchange_end(exch); 112 113 return r c;109 110 return ret; 114 111 } 115 112 … … 124 121 { 125 122 CHECK_CONNECTION(connection); 126 123 127 124 async_exch_t *exch = async_exchange_begin(connection->hc_sess); 128 int rc = async_req_2_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 129 IPC_M_USBHC_RELEASE_ADDRESS, address); 125 if (!exch) 126 return ENOMEM; 127 const int ret = usbhc_release_address(exch, address); 130 128 async_exchange_end(exch); 131 132 return r c;129 130 return ret; 133 131 } 134 132 … … 221 219 * request or requests for descriptors when creating match ids). 222 220 */ 223 int usb_hc_new_device_wrapper(ddf_dev_t *parent, usb_hc_connection_t *connection,224 usb_ speed_t dev_speed,221 int usb_hc_new_device_wrapper(ddf_dev_t *parent, 222 usb_hc_connection_t *connection, usb_speed_t dev_speed, 225 223 int (*enable_port)(void *arg), void *arg, usb_address_t *assigned_address, 226 224 ddf_dev_ops_t *dev_ops, void *new_dev_data, ddf_fun_t **new_fun) … … 229 227 return EINVAL; 230 228 231 // FIXME: this is awful, we are accessing directly the structure.232 229 // TODO: Why not use provided connection? 233 usb_hc_connection_t hc_conn = { 234 .hc_handle = connection->hc_handle, 235 .hc_sess = NULL 236 }; 230 usb_hc_connection_t hc_conn; 231 usb_hc_connection_initialize(&hc_conn, connection->hc_handle); 237 232 238 233 int rc; -
uspace/lib/usbdev/src/pipepriv.c
rfb48a0e rc48f6ab 87 87 88 88 if (pipe->refcount == 0) { 89 assert(pipe->hc_sess == NULL); 89 90 /* Need to open the phone by ourselves. */ 90 91 async_sess_t *sess = -
uspace/lib/usbdev/src/pipes.c
rfb48a0e rc48f6ab 54 54 static usb_address_t get_my_address(async_sess_t *sess, const ddf_dev_t *dev) 55 55 { 56 assert(sess); 56 57 async_exch_t *exch = async_exchange_begin(sess); 57 58 sysarg_t address; 59 int rc = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE), 60 IPC_M_USB_GET_MY_ADDRESS, &address); 61 58 if (!exch) 59 return ENOMEM; 60 61 usb_address_t address; 62 const int ret = usb_get_my_address(exch, &address); 63 62 64 async_exchange_end(exch); 63 64 if (rc != EOK) 65 return rc; 66 67 return (usb_address_t) address; 65 66 return (ret == EOK) ? address : ret; 68 67 } 69 68 … … 71 70 * 72 71 * @param device Device in question. 73 * @return Interface number (negative codemeans any).72 * @return Error code (ENOTSUP means any). 74 73 */ 75 74 int usb_device_get_assigned_interface(const ddf_dev_t *device) … … 80 79 IPC_FLAG_BLOCKING); 81 80 if (!parent_sess) 82 return -1;83 81 return ENOMEM; 82 84 83 async_exch_t *exch = async_exchange_begin(parent_sess); 85 86 sysarg_t iface_no; 87 int rc = async_req_2_1(exch, DEV_IFACE_ID(USB_DEV_IFACE), 88 IPC_M_USB_GET_INTERFACE, device->handle, &iface_no); 89 90 async_exchange_end(exch); 91 async_hangup(parent_sess); 92 93 if (rc != EOK) 94 return -1; 95 96 return (int) iface_no; 84 if (!exch) { 85 async_hangup(parent_sess); 86 return ENOMEM; 87 } 88 89 int iface_no; 90 const int ret = usb_get_my_interface(exch, &iface_no); 91 92 return ret == EOK ? iface_no : ret; 97 93 } 98 94 -
uspace/lib/usbdev/src/pipesinit.c
rfb48a0e rc48f6ab 54 54 55 55 /** Nesting pairs of standard descriptors. */ 56 static usb_dp_descriptor_nesting_t descriptor_nesting[] = {56 static const usb_dp_descriptor_nesting_t descriptor_nesting[] = { 57 57 NESTING(CONFIGURATION, INTERFACE), 58 58 NESTING(INTERFACE, ENDPOINT), … … 405 405 } 406 406 407 #define TRY_LOOP(attempt_var) \408 for (attempt_var = 0; attempt_var < 3; attempt_var++)409 410 size_t failed_attempts;411 int rc;412 407 413 408 usb_pipe_start_long_transfer(pipe); … … 415 410 uint8_t dev_descr_start[CTRL_PIPE_MIN_PACKET_SIZE]; 416 411 size_t transferred_size; 417 TRY_LOOP(failed_attempts) { 412 int rc; 413 for (size_t attempt_var = 0; attempt_var < 3; ++attempt_var) { 418 414 rc = usb_request_get_descriptor(pipe, USB_REQUEST_TYPE_STANDARD, 419 415 USB_REQUEST_RECIPIENT_DEVICE, USB_DESCTYPE_DEVICE, … … 450 446 { 451 447 assert(pipe); 448 assert(pipe->wire); 452 449 assert(hc_connection); 453 450 454 451 if (!usb_hc_connection_is_opened(hc_connection)) 455 452 return EBADF; 456 457 const usb_target_t target =458 {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }};459 #define _PACK2(high, low) (((high & 0xffff) << 16) | (low & 0xffff))460 461 453 async_exch_t *exch = async_exchange_begin(hc_connection->hc_sess); 462 int rc = async_req_4_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 463 IPC_M_USBHC_REGISTER_ENDPOINT, target.packed, 464 _PACK2(pipe->transfer_type, pipe->direction), 465 _PACK2(pipe->max_packet_size, interval)); 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 466 460 async_exchange_end(exch); 467 468 #undef _PACK2 469 return rc; 461 return ret; 470 462 } 471 463 … … 482 474 assert(pipe->wire); 483 475 assert(hc_connection); 484 476 485 477 if (!usb_hc_connection_is_opened(hc_connection)) 486 478 return EBADF; 487 479 488 480 async_exch_t *exch = async_exchange_begin(hc_connection->hc_sess); 489 int rc = async_req_4_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 490 IPC_M_USBHC_UNREGISTER_ENDPOINT, 481 if (!exch) 482 return ENOMEM; 483 const int ret = usbhc_unregister_endpoint(exch, 491 484 pipe->wire->address, pipe->endpoint_no, pipe->direction); 492 485 async_exchange_end(exch); 493 494 return r c;486 487 return ret; 495 488 } 496 489 -
uspace/lib/usbdev/src/pipesio.c
rfb48a0e rc48f6ab 62 62 * @return Error code. 63 63 */ 64 static int usb_pipe_read_no_check s(usb_pipe_t *pipe,64 static int usb_pipe_read_no_check(usb_pipe_t *pipe, uint64_t setup, 65 65 void *buffer, size_t size, size_t *size_transfered) 66 66 { 67 /* Only interrupt and bulk transfers are supported*/67 /* Isochronous transfer are not supported (yet) */ 68 68 if (pipe->transfer_type != USB_TRANSFER_INTERRUPT && 69 pipe->transfer_type != USB_TRANSFER_BULK) 69 pipe->transfer_type != USB_TRANSFER_BULK && 70 pipe->transfer_type != USB_TRANSFER_CONTROL) 70 71 return ENOTSUP; 71 72 72 const usb_target_t target = 73 {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }}; 74 73 int ret = pipe_add_ref(pipe, false); 74 if (ret != EOK) { 75 return ret; 76 } 77 75 78 /* Ensure serialization over the phone. */ 76 79 pipe_start_transaction(pipe); 77 80 async_exch_t *exch = async_exchange_begin(pipe->hc_sess); 78 79 /* 80 * Make call identifying target USB device and type of transfer. 81 */ 82 aid_t opening_request = async_send_2(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 83 IPC_M_USBHC_READ, target.packed, NULL); 84 85 if (opening_request == 0) { 86 async_exchange_end(exch); 81 if (!exch) { 87 82 pipe_end_transaction(pipe); 83 pipe_drop_ref(pipe); 88 84 return ENOMEM; 89 85 } 90 91 /* 92 * Retrieve the data. 93 */ 94 ipc_call_t data_request_call; 95 aid_t data_request = async_data_read(exch, buffer, size, 96 &data_request_call); 97 98 /* 99 * Since now on, someone else might access the backing phone 100 * without breaking the transfer IPC protocol. 101 */ 86 87 ret = usbhc_read(exch, pipe->wire->address, pipe->endpoint_no, 88 setup, buffer, size, size_transfered); 102 89 async_exchange_end(exch); 103 90 pipe_end_transaction(pipe); 104 105 if (data_request == 0) {106 /*107 * FIXME:108 * How to let the other side know that we want to abort?109 */110 async_wait_for(opening_request, NULL);111 return ENOMEM;112 }113 114 /*115 * Wait for the answer.116 */117 sysarg_t data_request_rc;118 sysarg_t opening_request_rc;119 async_wait_for(data_request, &data_request_rc);120 async_wait_for(opening_request, &opening_request_rc);121 122 if (data_request_rc != EOK) {123 /* Prefer the return code of the opening request. */124 if (opening_request_rc != EOK) {125 return (int) opening_request_rc;126 } else {127 return (int) data_request_rc;128 }129 }130 if (opening_request_rc != EOK) {131 return (int) opening_request_rc;132 }133 134 *size_transfered = IPC_GET_ARG2(data_request_call);135 136 return EOK;137 }138 139 140 /** Request a read (in) transfer on an endpoint pipe.141 *142 * @param[in] pipe Pipe used for the transfer.143 * @param[out] buffer Buffer where to store the data.144 * @param[in] size Size of the buffer (in bytes).145 * @param[out] size_transfered Number of bytes that were actually transfered.146 * @return Error code.147 */148 int usb_pipe_read(usb_pipe_t *pipe,149 void *buffer, size_t size, size_t *size_transfered)150 {151 assert(pipe);152 153 if (buffer == NULL) {154 return EINVAL;155 }156 157 if (size == 0) {158 return EINVAL;159 }160 161 if (pipe->direction != USB_DIRECTION_IN) {162 return EBADF;163 }164 165 if (pipe->transfer_type == USB_TRANSFER_CONTROL) {166 return EBADF;167 }168 169 int rc;170 rc = pipe_add_ref(pipe, false);171 if (rc != EOK) {172 return rc;173 }174 175 176 size_t act_size = 0;177 178 rc = usb_pipe_read_no_checks(pipe, buffer, size, &act_size);179 180 91 pipe_drop_ref(pipe); 181 182 if (rc != EOK) { 183 return rc; 184 } 185 186 if (size_transfered != NULL) { 187 *size_transfered = act_size; 188 } 189 190 return EOK; 191 } 192 193 194 92 return ret; 93 } 195 94 196 95 /** Request an out transfer, no checking of input parameters. … … 201 100 * @return Error code. 202 101 */ 203 static int usb_pipe_write_no_check(usb_pipe_t *pipe, 204 void *buffer, size_t size)102 static int usb_pipe_write_no_check(usb_pipe_t *pipe, uint64_t setup, 103 const void *buffer, size_t size) 205 104 { 206 105 /* Only interrupt and bulk transfers are supported */ 207 106 if (pipe->transfer_type != USB_TRANSFER_INTERRUPT && 208 pipe->transfer_type != USB_TRANSFER_BULK) 107 pipe->transfer_type != USB_TRANSFER_BULK && 108 pipe->transfer_type != USB_TRANSFER_CONTROL) 209 109 return ENOTSUP; 210 110 211 const usb_target_t target = 212 {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }}; 111 int ret = pipe_add_ref(pipe, false); 112 if (ret != EOK) { 113 return ret; 114 } 213 115 214 116 /* Ensure serialization over the phone. */ 215 117 pipe_start_transaction(pipe); 216 118 async_exch_t *exch = async_exchange_begin(pipe->hc_sess); 217 218 /* 219 * Make call identifying target USB device and type of transfer. 220 */ 221 aid_t opening_request = async_send_3(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 222 IPC_M_USBHC_WRITE, target.packed, size, NULL); 223 224 if (opening_request == 0) { 225 async_exchange_end(exch); 119 if (!exch) { 226 120 pipe_end_transaction(pipe); 121 pipe_drop_ref(pipe); 227 122 return ENOMEM; 228 123 } 229 230 /* 231 * Send the data. 232 */ 233 int rc = async_data_write_start(exch, buffer, size); 234 235 /* 236 * Since now on, someone else might access the backing phone 237 * without breaking the transfer IPC protocol. 238 */ 124 ret = usbhc_write(exch, pipe->wire->address, pipe->endpoint_no, 125 setup, buffer, size); 239 126 async_exchange_end(exch); 240 127 pipe_end_transaction(pipe); 241 242 if (rc != EOK) {243 async_wait_for(opening_request, NULL);244 return rc;245 }246 247 /*248 * Wait for the answer.249 */250 sysarg_t opening_request_rc;251 async_wait_for(opening_request, &opening_request_rc);252 253 return (int) opening_request_rc;254 }255 256 /** Request a write (out) transfer on an endpoint pipe.257 *258 * @param[in] pipe Pipe used for the transfer.259 * @param[in] buffer Buffer with data to transfer.260 * @param[in] size Size of the buffer (in bytes).261 * @return Error code.262 */263 int usb_pipe_write(usb_pipe_t *pipe,264 void *buffer, size_t size)265 {266 assert(pipe);267 268 if (buffer == NULL) {269 return EINVAL;270 }271 272 if (size == 0) {273 return EINVAL;274 }275 276 if (pipe->direction != USB_DIRECTION_OUT) {277 return EBADF;278 }279 280 if (pipe->transfer_type == USB_TRANSFER_CONTROL) {281 return EBADF;282 }283 284 int rc;285 286 rc = pipe_add_ref(pipe, false);287 if (rc != EOK) {288 return rc;289 }290 291 rc = usb_pipe_write_no_check(pipe, buffer, size);292 293 128 pipe_drop_ref(pipe); 294 295 return rc; 129 return ret; 296 130 } 297 131 … … 309 143 310 144 311 /* Prevent in definite recursion. */145 /* Prevent infinite recursion. */ 312 146 pipe->auto_reset_halt = false; 313 147 usb_request_clear_endpoint_halt(pipe, 0); … … 315 149 } 316 150 317 318 /** Request a control read transfer, no checking of input parameters. 151 /** Request a control read transfer on an endpoint pipe. 152 * 153 * This function encapsulates all three stages of a control transfer. 319 154 * 320 155 * @param[in] pipe Pipe used for the transfer. … … 327 162 * @return Error code. 328 163 */ 329 static int usb_pipe_control_read_no_check(usb_pipe_t *pipe,330 const void *setup_buffer, size_t setup_buffer_size,331 void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size)332 {333 /* Ensure serialization over the phone. */334 pipe_start_transaction(pipe);335 336 const usb_target_t target =337 {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }};338 339 assert(setup_buffer_size == 8);340 uint64_t setup_packet;341 memcpy(&setup_packet, setup_buffer, 8);342 /*343 * Make call identifying target USB device and control transfer type.344 */345 async_exch_t *exch = async_exchange_begin(pipe->hc_sess);346 aid_t opening_request = async_send_4(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),347 IPC_M_USBHC_READ, target.packed,348 (setup_packet & UINT32_MAX), (setup_packet >> 32), NULL);349 350 if (opening_request == 0) {351 async_exchange_end(exch);352 return ENOMEM;353 }354 355 /*356 * Retrieve the data.357 */358 ipc_call_t data_request_call;359 aid_t data_request = async_data_read(exch, data_buffer,360 data_buffer_size, &data_request_call);361 362 /*363 * Since now on, someone else might access the backing phone364 * without breaking the transfer IPC protocol.365 */366 async_exchange_end(exch);367 pipe_end_transaction(pipe);368 369 if (data_request == 0) {370 async_wait_for(opening_request, NULL);371 return ENOMEM;372 }373 374 /*375 * Wait for the answer.376 */377 sysarg_t data_request_rc;378 sysarg_t opening_request_rc;379 async_wait_for(data_request, &data_request_rc);380 async_wait_for(opening_request, &opening_request_rc);381 382 if (data_request_rc != EOK) {383 /* Prefer the return code of the opening request. */384 if (opening_request_rc != EOK) {385 return (int) opening_request_rc;386 } else {387 return (int) data_request_rc;388 }389 }390 if (opening_request_rc != EOK) {391 return (int) opening_request_rc;392 }393 394 *data_transfered_size = IPC_GET_ARG2(data_request_call);395 396 return EOK;397 }398 399 /** Request a control read transfer on an endpoint pipe.400 *401 * This function encapsulates all three stages of a control transfer.402 *403 * @param[in] pipe Pipe used for the transfer.404 * @param[in] setup_buffer Buffer with the setup packet.405 * @param[in] setup_buffer_size Size of the setup packet (in bytes).406 * @param[out] data_buffer Buffer for incoming data.407 * @param[in] data_buffer_size Size of the buffer for incoming data (in bytes).408 * @param[out] data_transfered_size Number of bytes that were actually409 * transfered during the DATA stage.410 * @return Error code.411 */412 164 int usb_pipe_control_read(usb_pipe_t *pipe, 413 165 const void *setup_buffer, size_t setup_buffer_size, … … 416 168 assert(pipe); 417 169 418 if ((setup_buffer == NULL) || (setup_buffer_size == 0)) {170 if ((setup_buffer == NULL) || (setup_buffer_size != 8)) { 419 171 return EINVAL; 420 172 } … … 429 181 } 430 182 431 int rc; 432 433 rc = pipe_add_ref(pipe, false); 434 if (rc != EOK) { 435 return rc; 436 } 183 uint64_t setup_packet; 184 memcpy(&setup_packet, setup_buffer, 8); 437 185 438 186 size_t act_size = 0; 439 rc = usb_pipe_control_read_no_check(pipe, 440 setup_buffer, setup_buffer_size, 187 const int rc = usb_pipe_read_no_check(pipe, setup_packet, 441 188 data_buffer, data_buffer_size, &act_size); 442 189 … … 445 192 } 446 193 447 pipe_drop_ref(pipe); 448 449 if (rc != EOK) { 450 return rc; 451 } 452 453 if (data_transfered_size != NULL) { 194 if (rc == EOK && data_transfered_size != NULL) { 454 195 *data_transfered_size = act_size; 455 196 } 456 197 457 return EOK; 458 } 459 460 461 /** Request a control write transfer, no checking of input parameters. 198 return rc; 199 } 200 201 /** Request a control write transfer on an endpoint pipe. 202 * 203 * This function encapsulates all three stages of a control transfer. 462 204 * 463 205 * @param[in] pipe Pipe used for the transfer. … … 468 210 * @return Error code. 469 211 */ 470 static int usb_pipe_control_write_no_check(usb_pipe_t *pipe,471 const void *setup_buffer, size_t setup_buffer_size,472 const void *data_buffer, size_t data_buffer_size)473 {474 /* Ensure serialization over the phone. */475 pipe_start_transaction(pipe);476 477 const usb_target_t target =478 {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }};479 assert(setup_buffer_size == 8);480 uint64_t setup_packet;481 memcpy(&setup_packet, setup_buffer, 8);482 483 /*484 * Make call identifying target USB device and control transfer type.485 */486 async_exch_t *exch = async_exchange_begin(pipe->hc_sess);487 aid_t opening_request = async_send_5(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),488 IPC_M_USBHC_WRITE, target.packed, data_buffer_size,489 (setup_packet & UINT32_MAX), (setup_packet >> 32), NULL);490 491 if (opening_request == 0) {492 async_exchange_end(exch);493 pipe_end_transaction(pipe);494 return ENOMEM;495 }496 497 /*498 * Send the data (if any).499 */500 if (data_buffer_size > 0) {501 int rc = async_data_write_start(exch, data_buffer, data_buffer_size);502 503 /* All data sent, pipe can be released. */504 async_exchange_end(exch);505 pipe_end_transaction(pipe);506 507 if (rc != EOK) {508 async_wait_for(opening_request, NULL);509 return rc;510 }511 } else {512 /* No data to send, we can release the pipe for others. */513 async_exchange_end(exch);514 pipe_end_transaction(pipe);515 }516 517 /*518 * Wait for the answer.519 */520 sysarg_t opening_request_rc;521 async_wait_for(opening_request, &opening_request_rc);522 523 return (int) opening_request_rc;524 }525 526 /** Request a control write transfer on an endpoint pipe.527 *528 * This function encapsulates all three stages of a control transfer.529 *530 * @param[in] pipe Pipe used for the transfer.531 * @param[in] setup_buffer Buffer with the setup packet.532 * @param[in] setup_buffer_size Size of the setup packet (in bytes).533 * @param[in] data_buffer Buffer with data to be sent.534 * @param[in] data_buffer_size Size of the buffer with outgoing data (in bytes).535 * @return Error code.536 */537 212 int usb_pipe_control_write(usb_pipe_t *pipe, 538 213 const void *setup_buffer, size_t setup_buffer_size, … … 541 216 assert(pipe); 542 217 543 if ((setup_buffer == NULL) || (setup_buffer_size == 0)) {218 if ((setup_buffer == NULL) || (setup_buffer_size != 8)) { 544 219 return EINVAL; 545 220 } … … 558 233 } 559 234 560 int rc; 561 562 rc = pipe_add_ref(pipe, false); 563 if (rc != EOK) { 564 return rc; 565 } 566 567 rc = usb_pipe_control_write_no_check(pipe, 568 setup_buffer, setup_buffer_size, data_buffer, data_buffer_size); 235 uint64_t setup_packet; 236 memcpy(&setup_packet, setup_buffer, 8); 237 238 const int rc = usb_pipe_write_no_check(pipe, setup_packet, 239 data_buffer, data_buffer_size); 569 240 570 241 if (rc == ESTALL) { … … 572 243 } 573 244 574 pipe_drop_ref(pipe);575 576 245 return rc; 577 246 } 578 247 248 /** Request a read (in) transfer on an endpoint pipe. 249 * 250 * @param[in] pipe Pipe used for the transfer. 251 * @param[out] buffer Buffer where to store the data. 252 * @param[in] size Size of the buffer (in bytes). 253 * @param[out] size_transfered Number of bytes that were actually transfered. 254 * @return Error code. 255 */ 256 int usb_pipe_read(usb_pipe_t *pipe, 257 void *buffer, size_t size, size_t *size_transfered) 258 { 259 assert(pipe); 260 261 if (buffer == NULL) { 262 return EINVAL; 263 } 264 265 if (size == 0) { 266 return EINVAL; 267 } 268 269 if (pipe->direction != USB_DIRECTION_IN) { 270 return EBADF; 271 } 272 273 if (pipe->transfer_type == USB_TRANSFER_CONTROL) { 274 return EBADF; 275 } 276 277 size_t act_size = 0; 278 const int rc = usb_pipe_read_no_check(pipe, 0, buffer, size, &act_size); 279 280 281 if (rc == EOK && size_transfered != NULL) { 282 *size_transfered = act_size; 283 } 284 285 return rc; 286 } 287 288 /** Request a write (out) transfer on an endpoint pipe. 289 * 290 * @param[in] pipe Pipe used for the transfer. 291 * @param[in] buffer Buffer with data to transfer. 292 * @param[in] size Size of the buffer (in bytes). 293 * @return Error code. 294 */ 295 int usb_pipe_write(usb_pipe_t *pipe, const void *buffer, size_t size) 296 { 297 assert(pipe); 298 299 if (buffer == NULL || size == 0) { 300 return EINVAL; 301 } 302 303 if (pipe->direction != USB_DIRECTION_OUT) { 304 return EBADF; 305 } 306 307 if (pipe->transfer_type == USB_TRANSFER_CONTROL) { 308 return EBADF; 309 } 310 311 return usb_pipe_write_no_check(pipe, 0, buffer, size); 312 } 579 313 580 314 /** -
uspace/lib/usbdev/src/request.c
rfb48a0e rc48f6ab 143 143 */ 144 144 145 usb_device_request_setup_packet_t setup_packet; 146 setup_packet.request_type = 128 | (request_type << 5) | recipient; 147 setup_packet.request = request; 148 setup_packet.value = value; 149 setup_packet.index = index; 150 setup_packet.length = (uint16_t) data_size; 151 152 int rc = usb_pipe_control_read(pipe, 153 &setup_packet, sizeof(setup_packet), 145 const usb_device_request_setup_packet_t setup_packet = { 146 .request_type = SETUP_REQUEST_TYPE_DEVICE_TO_HOST 147 | (request_type << 5) | recipient, 148 .request = request, 149 .value = value, 150 .index = index, 151 .length = (uint16_t) data_size, 152 }; 153 154 return usb_pipe_control_read(pipe, &setup_packet, sizeof(setup_packet), 154 155 data, data_size, actual_data_size); 155 156 return rc;157 156 } 158 157 … … 276 275 } 277 276 278 uint16_t wValue = descriptor_index | (descriptor_type << 8);277 const uint16_t wValue = descriptor_index | (descriptor_type << 8); 279 278 280 279 return usb_control_request_get(pipe,
Note:
See TracChangeset
for help on using the changeset viewer.