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