Changes in uspace/lib/drv/generic/remote_usb.c [9d58539:58563585] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/drv/generic/remote_usb.c
r9d58539 r58563585 35 35 36 36 #include <async.h> 37 #include <macros.h> 37 38 #include <errno.h> 39 #include <devman.h> 38 40 39 41 #include "usb_iface.h" 40 42 #include "ddf/driver.h" 41 43 44 45 usb_dev_session_t *usb_dev_connect(devman_handle_t handle) 46 { 47 return devman_device_connect(handle, IPC_FLAG_BLOCKING); 48 } 49 50 usb_dev_session_t *usb_dev_connect_to_self(ddf_dev_t *dev) 51 { 52 return devman_parent_device_connect(ddf_dev_get_handle(dev), IPC_FLAG_BLOCKING); 53 } 54 55 void usb_dev_disconnect(usb_dev_session_t *sess) 56 { 57 if (sess) 58 async_hangup(sess); 59 } 60 42 61 typedef enum { 43 IPC_M_USB_GET_MY_ADDRESS,44 62 IPC_M_USB_GET_MY_INTERFACE, 45 IPC_M_USB_GET_HOST_CONTROLLER_HANDLE, 63 IPC_M_USB_GET_MY_DEVICE_HANDLE, 64 IPC_M_USB_RESERVE_DEFAULT_ADDRESS, 65 IPC_M_USB_RELEASE_DEFAULT_ADDRESS, 66 IPC_M_USB_DEVICE_ENUMERATE, 67 IPC_M_USB_DEVICE_REMOVE, 68 IPC_M_USB_REGISTER_ENDPOINT, 69 IPC_M_USB_UNREGISTER_ENDPOINT, 70 IPC_M_USB_READ, 71 IPC_M_USB_WRITE, 46 72 } usb_iface_funcs_t; 47 73 48 /** Tell USB address assigned to device.49 * @param exch Vaid IPC exchange50 * @param address Pointer to address storage place.51 * @return Error code.52 *53 * Exch param is an open communication to device implementing usb_iface.54 */55 int usb_get_my_address(async_exch_t *exch, usb_address_t *address)56 {57 if (!exch)58 return EINVAL;59 sysarg_t addr;60 const int ret = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),61 IPC_M_USB_GET_MY_ADDRESS, &addr);62 63 if (ret == EOK && address != NULL)64 *address = (usb_address_t) addr;65 return ret;66 }67 /*----------------------------------------------------------------------------*/68 74 /** Tell interface number given device can use. 69 75 * @param[in] exch IPC communication exchange … … 75 81 { 76 82 if (!exch) 77 return E INVAL;83 return EBADMEM; 78 84 sysarg_t iface_no; 79 85 const int ret = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE), … … 83 89 return ret; 84 90 } 85 /*----------------------------------------------------------------------------*/ 86 /** Tell devman handle of device host controller. 91 92 /** Tell devman handle of the usb device function. 93 * 94 * @param[in] exch IPC communication exchange 95 * @param[out] handle devman handle of the HC used by the target device. 96 * 97 * @return Error code. 98 * 99 */ 100 int usb_get_my_device_handle(async_exch_t *exch, devman_handle_t *handle) 101 { 102 devman_handle_t h = 0; 103 const int ret = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE), 104 IPC_M_USB_GET_MY_DEVICE_HANDLE, &h); 105 if (ret == EOK && handle) 106 *handle = (devman_handle_t)h; 107 return ret; 108 } 109 110 /** Reserve default USB address. 87 111 * @param[in] exch IPC communication exchange 88 * @param[ out] hc_handle devman handle of the HC used by the target device.112 * @param[in] speed Communication speed of the newly attached device 89 113 * @return Error code. 90 114 */ 91 int usb_get_hc_handle(async_exch_t *exch, devman_handle_t *hc_handle) 92 { 93 if (!exch) 94 return EINVAL; 95 devman_handle_t h; 96 const int ret = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE), 97 IPC_M_USB_GET_HOST_CONTROLLER_HANDLE, &h); 98 if (ret == EOK && hc_handle) 99 *hc_handle = (devman_handle_t)h; 115 int usb_reserve_default_address(async_exch_t *exch, usb_speed_t speed) 116 { 117 if (!exch) 118 return EBADMEM; 119 return async_req_2_0(exch, DEV_IFACE_ID(USB_DEV_IFACE), 120 IPC_M_USB_RESERVE_DEFAULT_ADDRESS, speed); 121 } 122 123 /** Release default USB address. 124 * 125 * @param[in] exch IPC communication exchange 126 * 127 * @return Error code. 128 * 129 */ 130 int usb_release_default_address(async_exch_t *exch) 131 { 132 if (!exch) 133 return EBADMEM; 134 return async_req_1_0(exch, DEV_IFACE_ID(USB_DEV_IFACE), 135 IPC_M_USB_RELEASE_DEFAULT_ADDRESS); 136 } 137 138 /** Trigger USB device enumeration 139 * 140 * @param[in] exch IPC communication exchange 141 * @param[out] handle Identifier of the newly added device (if successful) 142 * 143 * @return Error code. 144 * 145 */ 146 int usb_device_enumerate(async_exch_t *exch, unsigned port) 147 { 148 if (!exch) 149 return EBADMEM; 150 const int ret = async_req_2_0(exch, DEV_IFACE_ID(USB_DEV_IFACE), 151 IPC_M_USB_DEVICE_ENUMERATE, port); 100 152 return ret; 101 153 } 102 154 103 104 static void remote_usb_get_my_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 155 /** Trigger USB device enumeration 156 * 157 * @param[in] exch IPC communication exchange 158 * @param[in] handle Identifier of the device 159 * 160 * @return Error code. 161 * 162 */ 163 int usb_device_remove(async_exch_t *exch, unsigned port) 164 { 165 if (!exch) 166 return EBADMEM; 167 return async_req_2_0(exch, DEV_IFACE_ID(USB_DEV_IFACE), 168 IPC_M_USB_DEVICE_REMOVE, port); 169 } 170 171 int static_assert[sizeof(sysarg_t) >= 4 ? 1 : -1]; 172 typedef union { 173 uint8_t arr[sizeof(sysarg_t)]; 174 sysarg_t arg; 175 } pack8_t; 176 177 int usb_register_endpoint(async_exch_t *exch, usb_endpoint_t endpoint, 178 usb_transfer_type_t type, usb_direction_t direction, 179 size_t mps, unsigned packets, unsigned interval) 180 { 181 if (!exch) 182 return EBADMEM; 183 pack8_t pack; 184 pack.arr[0] = type; 185 pack.arr[1] = direction; 186 pack.arr[2] = interval; 187 pack.arr[3] = packets; 188 189 return async_req_4_0(exch, DEV_IFACE_ID(USB_DEV_IFACE), 190 IPC_M_USB_REGISTER_ENDPOINT, endpoint, pack.arg, mps); 191 192 } 193 194 int usb_unregister_endpoint(async_exch_t *exch, usb_endpoint_t endpoint, 195 usb_direction_t direction) 196 { 197 if (!exch) 198 return EBADMEM; 199 return async_req_3_0(exch, DEV_IFACE_ID(USB_DEV_IFACE), 200 IPC_M_USB_UNREGISTER_ENDPOINT, endpoint, direction); 201 } 202 203 int usb_read(async_exch_t *exch, usb_endpoint_t endpoint, uint64_t setup, 204 void *data, size_t size, size_t *rec_size) 205 { 206 if (!exch) 207 return EBADMEM; 208 209 if (size == 0 && setup == 0) 210 return EOK; 211 212 /* Make call identifying target USB device and type of transfer. */ 213 aid_t opening_request = async_send_4(exch, 214 DEV_IFACE_ID(USB_DEV_IFACE), IPC_M_USB_READ, endpoint, 215 (setup & UINT32_MAX), (setup >> 32), NULL); 216 217 if (opening_request == 0) { 218 return ENOMEM; 219 } 220 221 /* Retrieve the data. */ 222 ipc_call_t data_request_call; 223 aid_t data_request = 224 async_data_read(exch, data, size, &data_request_call); 225 226 if (data_request == 0) { 227 // FIXME: How to let the other side know that we want to abort? 228 async_forget(opening_request); 229 return ENOMEM; 230 } 231 232 /* Wait for the answer. */ 233 sysarg_t data_request_rc; 234 sysarg_t opening_request_rc; 235 async_wait_for(data_request, &data_request_rc); 236 async_wait_for(opening_request, &opening_request_rc); 237 238 if (data_request_rc != EOK) { 239 /* Prefer the return code of the opening request. */ 240 if (opening_request_rc != EOK) { 241 return (int) opening_request_rc; 242 } else { 243 return (int) data_request_rc; 244 } 245 } 246 if (opening_request_rc != EOK) { 247 return (int) opening_request_rc; 248 } 249 250 *rec_size = IPC_GET_ARG2(data_request_call); 251 return EOK; 252 } 253 254 int usb_write(async_exch_t *exch, usb_endpoint_t endpoint, uint64_t setup, 255 const void *data, size_t size) 256 { 257 if (!exch) 258 return EBADMEM; 259 260 if (size == 0 && setup == 0) 261 return EOK; 262 263 aid_t opening_request = async_send_5(exch, 264 DEV_IFACE_ID(USB_DEV_IFACE), IPC_M_USB_WRITE, endpoint, size, 265 (setup & UINT32_MAX), (setup >> 32), NULL); 266 267 if (opening_request == 0) { 268 return ENOMEM; 269 } 270 271 /* Send the data if any. */ 272 if (size > 0) { 273 const int ret = async_data_write_start(exch, data, size); 274 if (ret != EOK) { 275 async_forget(opening_request); 276 return ret; 277 } 278 } 279 280 /* Wait for the answer. */ 281 sysarg_t opening_request_rc; 282 async_wait_for(opening_request, &opening_request_rc); 283 284 return (int) opening_request_rc; 285 } 286 105 287 static void remote_usb_get_my_interface(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 106 static void remote_usb_get_hc_handle(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 288 static void remote_usb_get_my_device_handle(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 289 static void remote_usb_reserve_default_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 290 static void remote_usb_release_default_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 291 static void remote_usb_device_enumerate(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 292 static void remote_usb_device_remove(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 293 static void remote_usb_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 294 static void remote_usb_unregister_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 295 static void remote_usb_read(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call); 296 static void remote_usb_write(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call); 107 297 108 298 /** Remote USB interface operations. */ 109 static remote_iface_func_ptr_t remote_usb_iface_ops [] = { 110 [IPC_M_USB_GET_MY_ADDRESS] = remote_usb_get_my_address, 299 static const remote_iface_func_ptr_t remote_usb_iface_ops [] = { 111 300 [IPC_M_USB_GET_MY_INTERFACE] = remote_usb_get_my_interface, 112 [IPC_M_USB_GET_HOST_CONTROLLER_HANDLE] = remote_usb_get_hc_handle, 301 [IPC_M_USB_GET_MY_DEVICE_HANDLE] = remote_usb_get_my_device_handle, 302 [IPC_M_USB_RESERVE_DEFAULT_ADDRESS] = remote_usb_reserve_default_address, 303 [IPC_M_USB_RELEASE_DEFAULT_ADDRESS] = remote_usb_release_default_address, 304 [IPC_M_USB_DEVICE_ENUMERATE] = remote_usb_device_enumerate, 305 [IPC_M_USB_DEVICE_REMOVE] = remote_usb_device_remove, 306 [IPC_M_USB_REGISTER_ENDPOINT] = remote_usb_register_endpoint, 307 [IPC_M_USB_UNREGISTER_ENDPOINT] = remote_usb_unregister_endpoint, 308 [IPC_M_USB_READ] = remote_usb_read, 309 [IPC_M_USB_WRITE] = remote_usb_write, 113 310 }; 114 311 115 312 /** Remote USB interface structure. 116 313 */ 117 remote_iface_t remote_usb_iface = { 118 .method_count = sizeof(remote_usb_iface_ops) / 119 sizeof(remote_usb_iface_ops[0]), 120 .methods = remote_usb_iface_ops 314 const remote_iface_t remote_usb_iface = { 315 .method_count = ARRAY_SIZE(remote_usb_iface_ops), 316 .methods = remote_usb_iface_ops, 121 317 }; 122 318 123 /*----------------------------------------------------------------------------*/124 void remote_usb_get_my_address(ddf_fun_t *fun, void *iface,125 ipc_callid_t callid, ipc_call_t *call)126 {127 const usb_iface_t *usb_iface = (usb_iface_t *) iface;128 129 if (usb_iface->get_my_address == NULL) {130 async_answer_0(callid, ENOTSUP);131 return;132 }133 134 usb_address_t address;135 const int ret = usb_iface->get_my_address(fun, &address);136 if (ret != EOK) {137 async_answer_0(callid, ret);138 } else {139 async_answer_1(callid, EOK, address);140 }141 }142 /*----------------------------------------------------------------------------*/143 319 void remote_usb_get_my_interface(ddf_fun_t *fun, void *iface, 144 320 ipc_callid_t callid, ipc_call_t *call) … … 159 335 } 160 336 } 161 /*----------------------------------------------------------------------------*/ 162 void remote_usb_get_ hc_handle(ddf_fun_t *fun, void *iface,337 338 void remote_usb_get_my_device_handle(ddf_fun_t *fun, void *iface, 163 339 ipc_callid_t callid, ipc_call_t *call) 164 340 { 165 341 const usb_iface_t *usb_iface = (usb_iface_t *) iface; 166 342 167 if (usb_iface->get_ hc_handle == NULL) {343 if (usb_iface->get_my_device_handle == NULL) { 168 344 async_answer_0(callid, ENOTSUP); 169 345 return; … … 171 347 172 348 devman_handle_t handle; 173 const int ret = usb_iface->get_ hc_handle(fun, &handle);349 const int ret = usb_iface->get_my_device_handle(fun, &handle); 174 350 if (ret != EOK) { 175 351 async_answer_0(callid, ret); … … 178 354 async_answer_1(callid, EOK, (sysarg_t) handle); 179 355 } 356 357 void remote_usb_reserve_default_address(ddf_fun_t *fun, void *iface, 358 ipc_callid_t callid, ipc_call_t *call) 359 { 360 const usb_iface_t *usb_iface = (usb_iface_t *) iface; 361 362 if (usb_iface->reserve_default_address == NULL) { 363 async_answer_0(callid, ENOTSUP); 364 return; 365 } 366 367 usb_speed_t speed = DEV_IPC_GET_ARG1(*call); 368 const int ret = usb_iface->reserve_default_address(fun, speed); 369 async_answer_0(callid, ret); 370 } 371 372 void remote_usb_release_default_address(ddf_fun_t *fun, void *iface, 373 ipc_callid_t callid, ipc_call_t *call) 374 { 375 const usb_iface_t *usb_iface = (usb_iface_t *) iface; 376 377 if (usb_iface->release_default_address == NULL) { 378 async_answer_0(callid, ENOTSUP); 379 return; 380 } 381 382 const int ret = usb_iface->release_default_address(fun); 383 async_answer_0(callid, ret); 384 } 385 386 static void remote_usb_device_enumerate(ddf_fun_t *fun, void *iface, 387 ipc_callid_t callid, ipc_call_t *call) 388 { 389 const usb_iface_t *usb_iface = (usb_iface_t *) iface; 390 391 if (usb_iface->device_enumerate == NULL) { 392 async_answer_0(callid, ENOTSUP); 393 return; 394 } 395 396 const unsigned port = DEV_IPC_GET_ARG1(*call); 397 const int ret = usb_iface->device_enumerate(fun, port); 398 async_answer_0(callid, ret); 399 } 400 401 static void remote_usb_device_remove(ddf_fun_t *fun, void *iface, 402 ipc_callid_t callid, ipc_call_t *call) 403 { 404 const usb_iface_t *usb_iface = (usb_iface_t *) iface; 405 406 if (usb_iface->device_remove == NULL) { 407 async_answer_0(callid, ENOTSUP); 408 return; 409 } 410 411 const unsigned port = DEV_IPC_GET_ARG1(*call); 412 const int ret = usb_iface->device_remove(fun, port); 413 async_answer_0(callid, ret); 414 } 415 416 static void remote_usb_register_endpoint(ddf_fun_t *fun, void *iface, 417 ipc_callid_t callid, ipc_call_t *call) 418 { 419 usb_iface_t *usb_iface = (usb_iface_t *) iface; 420 421 if (!usb_iface->register_endpoint) { 422 async_answer_0(callid, ENOTSUP); 423 return; 424 } 425 426 const usb_endpoint_t endpoint = DEV_IPC_GET_ARG1(*call); 427 const pack8_t pack = { .arg = DEV_IPC_GET_ARG2(*call)}; 428 const size_t max_packet_size = DEV_IPC_GET_ARG3(*call); 429 430 const usb_transfer_type_t transfer_type = pack.arr[0]; 431 const usb_direction_t direction = pack.arr[1]; 432 unsigned packets = pack.arr[2]; 433 unsigned interval = pack.arr[3]; 434 435 const int ret = usb_iface->register_endpoint(fun, endpoint, 436 transfer_type, direction, max_packet_size, packets, interval); 437 438 async_answer_0(callid, ret); 439 } 440 441 static void remote_usb_unregister_endpoint(ddf_fun_t *fun, void *iface, 442 ipc_callid_t callid, ipc_call_t *call) 443 { 444 usb_iface_t *usb_iface = (usb_iface_t *) iface; 445 446 if (!usb_iface->unregister_endpoint) { 447 async_answer_0(callid, ENOTSUP); 448 return; 449 } 450 451 usb_endpoint_t endpoint = (usb_endpoint_t) DEV_IPC_GET_ARG1(*call); 452 usb_direction_t direction = (usb_direction_t) DEV_IPC_GET_ARG2(*call); 453 454 int rc = usb_iface->unregister_endpoint(fun, endpoint, direction); 455 456 async_answer_0(callid, rc); 457 } 458 459 typedef struct { 460 ipc_callid_t caller; 461 ipc_callid_t data_caller; 462 void *buffer; 463 } async_transaction_t; 464 465 static void async_transaction_destroy(async_transaction_t *trans) 466 { 467 if (trans == NULL) { 468 return; 469 } 470 if (trans->buffer != NULL) { 471 free(trans->buffer); 472 } 473 474 free(trans); 475 } 476 477 static async_transaction_t *async_transaction_create(ipc_callid_t caller) 478 { 479 async_transaction_t *trans = malloc(sizeof(async_transaction_t)); 480 if (trans == NULL) { 481 return NULL; 482 } 483 484 trans->caller = caller; 485 trans->data_caller = 0; 486 trans->buffer = NULL; 487 488 return trans; 489 } 490 491 static void callback_out(int outcome, void *arg) 492 { 493 async_transaction_t *trans = arg; 494 495 async_answer_0(trans->caller, outcome); 496 497 async_transaction_destroy(trans); 498 } 499 500 static void callback_in(int outcome, size_t actual_size, void *arg) 501 { 502 async_transaction_t *trans = (async_transaction_t *)arg; 503 504 if (outcome != EOK) { 505 async_answer_0(trans->caller, outcome); 506 if (trans->data_caller) { 507 async_answer_0(trans->data_caller, EINTR); 508 } 509 async_transaction_destroy(trans); 510 return; 511 } 512 513 if (trans->data_caller) { 514 async_data_read_finalize(trans->data_caller, 515 trans->buffer, actual_size); 516 } 517 518 async_answer_0(trans->caller, EOK); 519 520 async_transaction_destroy(trans); 521 } 522 523 void remote_usb_read( 524 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call) 525 { 526 assert(fun); 527 assert(iface); 528 assert(call); 529 530 const usb_iface_t *usb_iface = iface; 531 532 if (!usb_iface->read) { 533 async_answer_0(callid, ENOTSUP); 534 return; 535 } 536 537 const usb_endpoint_t ep = DEV_IPC_GET_ARG1(*call); 538 const uint64_t setup = 539 ((uint64_t)DEV_IPC_GET_ARG2(*call)) | 540 (((uint64_t)DEV_IPC_GET_ARG3(*call)) << 32); 541 542 async_transaction_t *trans = async_transaction_create(callid); 543 if (trans == NULL) { 544 async_answer_0(callid, ENOMEM); 545 return; 546 } 547 548 size_t size = 0; 549 if (!async_data_read_receive(&trans->data_caller, &size)) { 550 async_answer_0(callid, EPARTY); 551 async_transaction_destroy(trans); 552 return; 553 } 554 555 trans->buffer = malloc(size); 556 if (trans->buffer == NULL) { 557 async_answer_0(trans->data_caller, ENOMEM); 558 async_answer_0(callid, ENOMEM); 559 async_transaction_destroy(trans); 560 return; 561 } 562 563 const int rc = usb_iface->read( 564 fun, ep, setup, trans->buffer, size, callback_in, trans); 565 566 if (rc != EOK) { 567 async_answer_0(trans->data_caller, rc); 568 async_answer_0(callid, rc); 569 async_transaction_destroy(trans); 570 } 571 } 572 573 void remote_usb_write( 574 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call) 575 { 576 assert(fun); 577 assert(iface); 578 assert(call); 579 580 const usb_iface_t *usb_iface = iface; 581 582 if (!usb_iface->write) { 583 async_answer_0(callid, ENOTSUP); 584 return; 585 } 586 587 const usb_endpoint_t ep = DEV_IPC_GET_ARG1(*call); 588 const size_t data_buffer_len = DEV_IPC_GET_ARG2(*call); 589 const uint64_t setup = 590 ((uint64_t)DEV_IPC_GET_ARG3(*call)) | 591 (((uint64_t)DEV_IPC_GET_ARG4(*call)) << 32); 592 593 async_transaction_t *trans = async_transaction_create(callid); 594 if (trans == NULL) { 595 async_answer_0(callid, ENOMEM); 596 return; 597 } 598 599 size_t size = 0; 600 if (data_buffer_len > 0) { 601 const int rc = async_data_write_accept(&trans->buffer, false, 602 1, data_buffer_len, 0, &size); 603 604 if (rc != EOK) { 605 async_answer_0(callid, rc); 606 async_transaction_destroy(trans); 607 return; 608 } 609 } 610 611 const int rc = usb_iface->write( 612 fun, ep, setup, trans->buffer, size, callback_out, trans); 613 614 if (rc != EOK) { 615 async_answer_0(callid, rc); 616 async_transaction_destroy(trans); 617 } 618 } 180 619 /** 181 620 * @}
Note:
See TracChangeset
for help on using the changeset viewer.