Changes in uspace/lib/usbdev/src/pipesio.c [3875af65:3f0ad85a] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usbdev/src/pipesio.c
r3875af65 r3f0ad85a 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 /**
Note:
See TracChangeset
for help on using the changeset viewer.