Changeset 64e1fb2 in mainline for uspace/lib/drv/generic/remote_usb.c
- Timestamp:
- 2013-08-02T14:57:26Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 1845003
- Parents:
- 1298a8fa
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/drv/generic/remote_usb.c
r1298a8fa r64e1fb2 74 74 IPC_M_USB_REGISTER_ENDPOINT, 75 75 IPC_M_USB_UNREGISTER_ENDPOINT, 76 IPC_M_USB_READ, 77 IPC_M_USB_WRITE, 76 78 } usb_iface_funcs_t; 77 79 … … 223 225 } 224 226 227 int usb_read(async_exch_t *exch, usb_endpoint_t endpoint, uint64_t setup, 228 void *data, size_t size, size_t *rec_size) 229 { 230 if (!exch) 231 return EBADMEM; 232 233 if (size == 0 && setup == 0) 234 return EOK; 235 236 /* Make call identifying target USB device and type of transfer. */ 237 aid_t opening_request = async_send_4(exch, 238 DEV_IFACE_ID(USB_DEV_IFACE), IPC_M_USB_READ, endpoint, 239 (setup & UINT32_MAX), (setup >> 32), NULL); 240 241 if (opening_request == 0) { 242 return ENOMEM; 243 } 244 245 /* Retrieve the data. */ 246 ipc_call_t data_request_call; 247 aid_t data_request = 248 async_data_read(exch, data, size, &data_request_call); 249 250 if (data_request == 0) { 251 // FIXME: How to let the other side know that we want to abort? 252 async_forget(opening_request); 253 return ENOMEM; 254 } 255 256 /* Wait for the answer. */ 257 sysarg_t data_request_rc; 258 sysarg_t opening_request_rc; 259 async_wait_for(data_request, &data_request_rc); 260 async_wait_for(opening_request, &opening_request_rc); 261 262 if (data_request_rc != EOK) { 263 /* Prefer the return code of the opening request. */ 264 if (opening_request_rc != EOK) { 265 return (int) opening_request_rc; 266 } else { 267 return (int) data_request_rc; 268 } 269 } 270 if (opening_request_rc != EOK) { 271 return (int) opening_request_rc; 272 } 273 274 *rec_size = IPC_GET_ARG2(data_request_call); 275 return EOK; 276 } 277 278 int usb_write(async_exch_t *exch, usb_endpoint_t endpoint, uint64_t setup, 279 const void *data, size_t size) 280 { 281 if (!exch) 282 return EBADMEM; 283 284 if (size == 0 && setup == 0) 285 return EOK; 286 287 aid_t opening_request = async_send_5(exch, 288 DEV_IFACE_ID(USB_DEV_IFACE), IPC_M_USB_WRITE, endpoint, size, 289 (setup & UINT32_MAX), (setup >> 32), NULL); 290 291 if (opening_request == 0) { 292 return ENOMEM; 293 } 294 295 /* Send the data if any. */ 296 if (size > 0) { 297 const int ret = async_data_write_start(exch, data, size); 298 if (ret != EOK) { 299 async_forget(opening_request); 300 return ret; 301 } 302 } 303 304 /* Wait for the answer. */ 305 sysarg_t opening_request_rc; 306 async_wait_for(opening_request, &opening_request_rc); 307 308 return (int) opening_request_rc; 309 } 310 225 311 static void remote_usb_get_my_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 226 312 static void remote_usb_get_my_interface(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); … … 234 320 static void remote_usb_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 235 321 static void remote_usb_unregister_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 322 static void remote_usb_read(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call); 323 324 static void remote_usb_write(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call); 236 325 237 326 /** Remote USB interface operations. */ … … 247 336 [IPC_M_USB_REGISTER_ENDPOINT] = remote_usb_register_endpoint, 248 337 [IPC_M_USB_UNREGISTER_ENDPOINT] = remote_usb_unregister_endpoint, 338 [IPC_M_USB_READ] = remote_usb_read, 339 [IPC_M_USB_WRITE] = remote_usb_write, 249 340 }; 250 341 … … 445 536 async_answer_0(callid, rc); 446 537 } 538 539 typedef struct { 540 ipc_callid_t caller; 541 ipc_callid_t data_caller; 542 void *buffer; 543 } async_transaction_t; 544 545 static void async_transaction_destroy(async_transaction_t *trans) 546 { 547 if (trans == NULL) { 548 return; 549 } 550 if (trans->buffer != NULL) { 551 free(trans->buffer); 552 } 553 554 free(trans); 555 } 556 557 static async_transaction_t *async_transaction_create(ipc_callid_t caller) 558 { 559 async_transaction_t *trans = malloc(sizeof(async_transaction_t)); 560 if (trans == NULL) { 561 return NULL; 562 } 563 564 trans->caller = caller; 565 trans->data_caller = 0; 566 trans->buffer = NULL; 567 568 return trans; 569 } 570 571 static void callback_out(int outcome, void *arg) 572 { 573 async_transaction_t *trans = arg; 574 575 async_answer_0(trans->caller, outcome); 576 577 async_transaction_destroy(trans); 578 } 579 580 static void callback_in(int outcome, size_t actual_size, void *arg) 581 { 582 async_transaction_t *trans = (async_transaction_t *)arg; 583 584 if (outcome != EOK) { 585 async_answer_0(trans->caller, outcome); 586 if (trans->data_caller) { 587 async_answer_0(trans->data_caller, EINTR); 588 } 589 async_transaction_destroy(trans); 590 return; 591 } 592 593 if (trans->data_caller) { 594 async_data_read_finalize(trans->data_caller, 595 trans->buffer, actual_size); 596 } 597 598 async_answer_0(trans->caller, EOK); 599 600 async_transaction_destroy(trans); 601 } 602 603 void remote_usb_read( 604 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call) 605 { 606 assert(fun); 607 assert(iface); 608 assert(call); 609 610 const usb_iface_t *usb_iface = iface; 611 612 if (!usb_iface->read) { 613 async_answer_0(callid, ENOTSUP); 614 return; 615 } 616 617 const usb_endpoint_t ep = DEV_IPC_GET_ARG1(*call); 618 const uint64_t setup = 619 ((uint64_t)DEV_IPC_GET_ARG2(*call)) | 620 (((uint64_t)DEV_IPC_GET_ARG3(*call)) << 32); 621 622 async_transaction_t *trans = async_transaction_create(callid); 623 if (trans == NULL) { 624 async_answer_0(callid, ENOMEM); 625 return; 626 } 627 628 size_t size = 0; 629 if (!async_data_read_receive(&trans->data_caller, &size)) { 630 async_answer_0(callid, EPARTY); 631 return; 632 } 633 634 trans->buffer = malloc(size); 635 if (trans->buffer == NULL) { 636 async_answer_0(trans->data_caller, ENOMEM); 637 async_answer_0(callid, ENOMEM); 638 async_transaction_destroy(trans); 639 } 640 641 const int rc = usb_iface->read( 642 fun, ep, setup, trans->buffer, size, callback_in, trans); 643 644 if (rc != EOK) { 645 async_answer_0(trans->data_caller, rc); 646 async_answer_0(callid, rc); 647 async_transaction_destroy(trans); 648 } 649 } 650 651 void remote_usb_write( 652 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call) 653 { 654 assert(fun); 655 assert(iface); 656 assert(call); 657 658 const usb_iface_t *usb_iface = iface; 659 660 if (!usb_iface->write) { 661 async_answer_0(callid, ENOTSUP); 662 return; 663 } 664 665 const usb_endpoint_t ep = DEV_IPC_GET_ARG1(*call); 666 const size_t data_buffer_len = DEV_IPC_GET_ARG2(*call); 667 const uint64_t setup = 668 ((uint64_t)DEV_IPC_GET_ARG3(*call)) | 669 (((uint64_t)DEV_IPC_GET_ARG4(*call)) << 32); 670 671 async_transaction_t *trans = async_transaction_create(callid); 672 if (trans == NULL) { 673 async_answer_0(callid, ENOMEM); 674 return; 675 } 676 677 size_t size = 0; 678 if (data_buffer_len > 0) { 679 const int rc = async_data_write_accept(&trans->buffer, false, 680 1, data_buffer_len, 0, &size); 681 682 if (rc != EOK) { 683 async_answer_0(callid, rc); 684 async_transaction_destroy(trans); 685 return; 686 } 687 } 688 689 const int rc = usb_iface->write( 690 fun, ep, setup, trans->buffer, size, callback_out, trans); 691 692 if (rc != EOK) { 693 async_answer_0(callid, rc); 694 async_transaction_destroy(trans); 695 } 696 } 447 697 /** 448 698 * @}
Note:
See TracChangeset
for help on using the changeset viewer.