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