Changes in uspace/lib/usbdev/src/pipesio.c [3f0ad85a:3875af65] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usbdev/src/pipesio.c
r3f0ad85a r3875af65 62 62 * @return Error code. 63 63 */ 64 static int usb_pipe_read_no_check (usb_pipe_t *pipe, uint64_t setup,64 static int usb_pipe_read_no_checks(usb_pipe_t *pipe, 65 65 void *buffer, size_t size, size_t *size_transfered) 66 66 { 67 /* Isochronous transfer are not supported (yet)*/67 /* Only interrupt and bulk transfers are supported */ 68 68 if (pipe->transfer_type != USB_TRANSFER_INTERRUPT && 69 pipe->transfer_type != USB_TRANSFER_BULK && 70 pipe->transfer_type != USB_TRANSFER_CONTROL) 69 pipe->transfer_type != USB_TRANSFER_BULK) 71 70 return ENOTSUP; 72 71 73 int ret = pipe_add_ref(pipe, false); 74 if (ret != EOK) { 75 return ret; 76 } 77 72 const usb_target_t target = 73 {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }}; 74 78 75 /* Ensure serialization over the phone. */ 79 76 pipe_start_transaction(pipe); 80 77 async_exch_t *exch = async_exchange_begin(pipe->hc_sess); 81 if (!exch) { 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); 82 87 pipe_end_transaction(pipe); 83 pipe_drop_ref(pipe);84 88 return ENOMEM; 85 89 } 86 87 ret = usbhc_read(exch, pipe->wire->address, pipe->endpoint_no, 88 setup, buffer, size, size_transfered); 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 */ 89 102 async_exchange_end(exch); 90 103 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 91 180 pipe_drop_ref(pipe); 92 return ret; 93 } 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 94 195 95 196 /** Request an out transfer, no checking of input parameters. … … 100 201 * @return Error code. 101 202 */ 102 static int usb_pipe_write_no_check(usb_pipe_t *pipe, uint64_t setup,103 constvoid *buffer, size_t size)203 static int usb_pipe_write_no_check(usb_pipe_t *pipe, 204 void *buffer, size_t size) 104 205 { 105 206 /* Only interrupt and bulk transfers are supported */ 106 207 if (pipe->transfer_type != USB_TRANSFER_INTERRUPT && 107 pipe->transfer_type != USB_TRANSFER_BULK && 108 pipe->transfer_type != USB_TRANSFER_CONTROL) 208 pipe->transfer_type != USB_TRANSFER_BULK) 109 209 return ENOTSUP; 110 210 111 int ret = pipe_add_ref(pipe, false); 112 if (ret != EOK) { 113 return ret; 114 } 211 const usb_target_t target = 212 {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }}; 115 213 116 214 /* Ensure serialization over the phone. */ 117 215 pipe_start_transaction(pipe); 118 216 async_exch_t *exch = async_exchange_begin(pipe->hc_sess); 119 if (!exch) { 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); 120 226 pipe_end_transaction(pipe); 121 pipe_drop_ref(pipe);122 227 return ENOMEM; 123 228 } 124 ret = usbhc_write(exch, pipe->wire->address, pipe->endpoint_no, 125 setup, buffer, size); 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 */ 126 239 async_exchange_end(exch); 127 240 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 128 293 pipe_drop_ref(pipe); 129 return ret; 294 295 return rc; 130 296 } 131 297 … … 143 309 144 310 145 /* Prevent in finite recursion. */311 /* Prevent indefinite recursion. */ 146 312 pipe->auto_reset_halt = false; 147 313 usb_request_clear_endpoint_halt(pipe, 0); … … 149 315 } 150 316 151 /** Request a control read transfer on an endpoint pipe. 152 * 153 * This function encapsulates all three stages of a control transfer. 317 318 /** Request a control read transfer, no checking of input parameters. 154 319 * 155 320 * @param[in] pipe Pipe used for the transfer. … … 162 327 * @return Error code. 163 328 */ 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 phone 364 * 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 actually 409 * transfered during the DATA stage. 410 * @return Error code. 411 */ 164 412 int usb_pipe_control_read(usb_pipe_t *pipe, 165 413 const void *setup_buffer, size_t setup_buffer_size, … … 168 416 assert(pipe); 169 417 170 if ((setup_buffer == NULL) || (setup_buffer_size != 8)) {418 if ((setup_buffer == NULL) || (setup_buffer_size == 0)) { 171 419 return EINVAL; 172 420 } … … 181 429 } 182 430 183 uint64_t setup_packet; 184 memcpy(&setup_packet, setup_buffer, 8); 431 int rc; 432 433 rc = pipe_add_ref(pipe, false); 434 if (rc != EOK) { 435 return rc; 436 } 185 437 186 438 size_t act_size = 0; 187 const int rc = usb_pipe_read_no_check(pipe, setup_packet, 439 rc = usb_pipe_control_read_no_check(pipe, 440 setup_buffer, setup_buffer_size, 188 441 data_buffer, data_buffer_size, &act_size); 189 442 … … 192 445 } 193 446 194 if (rc == EOK && data_transfered_size != NULL) { 447 pipe_drop_ref(pipe); 448 449 if (rc != EOK) { 450 return rc; 451 } 452 453 if (data_transfered_size != NULL) { 195 454 *data_transfered_size = act_size; 196 455 } 197 456 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. 457 return EOK; 458 } 459 460 461 /** Request a control write transfer, no checking of input parameters. 204 462 * 205 463 * @param[in] pipe Pipe used for the transfer. … … 210 468 * @return Error code. 211 469 */ 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 */ 212 537 int usb_pipe_control_write(usb_pipe_t *pipe, 213 538 const void *setup_buffer, size_t setup_buffer_size, … … 216 541 assert(pipe); 217 542 218 if ((setup_buffer == NULL) || (setup_buffer_size != 8)) {543 if ((setup_buffer == NULL) || (setup_buffer_size == 0)) { 219 544 return EINVAL; 220 545 } … … 233 558 } 234 559 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); 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); 240 569 241 570 if (rc == ESTALL) { … … 243 572 } 244 573 574 pipe_drop_ref(pipe); 575 245 576 return rc; 246 577 } 247 578 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 }313 579 314 580 /**
Note:
See TracChangeset
for help on using the changeset viewer.