Changeset 41df71f9 in mainline for uspace/lib/drv/generic/remote_usb.c
- Timestamp:
- 2017-11-02T14:29:15Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 887c9de
- Parents:
- 479e32d
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/drv/generic/remote_usb.c
r479e32d r41df71f9 63 63 IPC_M_USB_GET_MY_INTERFACE, 64 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,73 65 } usb_iface_funcs_t; 74 66 … … 109 101 } 110 102 111 /** Reserve default USB address.112 * @param[in] exch IPC communication exchange113 * @param[in] speed Communication speed of the newly attached device114 * @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 *126 * @param[in] exch IPC communication exchange127 *128 * @return Error code.129 *130 */131 int 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 enumeration140 *141 * @param[in] exch IPC communication exchange142 * @param[out] handle Identifier of the newly added device (if successful)143 *144 * @return Error code.145 *146 */147 int usb_device_enumerate(async_exch_t *exch, unsigned port)148 {149 if (!exch)150 return EBADMEM;151 const int 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 enumeration157 *158 * @param[in] exch IPC communication exchange159 * @param[in] handle Identifier of the device160 *161 * @return Error code.162 *163 */164 int 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 int static_assert[sizeof(sysarg_t) >= 4 ? 1 : -1];173 typedef union {174 uint8_t arr[sizeof(sysarg_t)];175 sysarg_t arg;176 } pack8_t;177 178 int usb_register_endpoint(async_exch_t *exch,179 usb_endpoint_desc_t *endpoint_desc)180 {181 if (!exch)182 return EBADMEM;183 184 aid_t opening_request = async_send_1(exch,185 DEV_IFACE_ID(USB_DEV_IFACE), IPC_M_USB_REGISTER_ENDPOINT, NULL);186 187 if (opening_request == 0) {188 return ENOMEM;189 }190 191 const int ret = async_data_write_start(exch, (void *) endpoint_desc,192 sizeof(usb_endpoint_desc_t));193 194 if (ret != EOK) {195 async_forget(opening_request);196 return ret;197 }198 199 /* Wait for the answer. */200 sysarg_t opening_request_rc;201 async_wait_for(opening_request, &opening_request_rc);202 203 return (int) opening_request_rc;204 }205 206 int usb_unregister_endpoint(async_exch_t *exch,207 usb_endpoint_desc_t *endpoint_desc)208 {209 if (!exch)210 return EBADMEM;211 212 aid_t opening_request = async_send_1(exch,213 DEV_IFACE_ID(USB_DEV_IFACE), IPC_M_USB_UNREGISTER_ENDPOINT, NULL);214 215 if (opening_request == 0) {216 return ENOMEM;217 }218 219 const int ret = async_data_write_start(exch, endpoint_desc,220 sizeof(usb_endpoint_desc_t));221 if (ret != EOK) {222 async_forget(opening_request);223 return ret;224 }225 226 /* Wait for the answer. */227 sysarg_t opening_request_rc;228 async_wait_for(opening_request, &opening_request_rc);229 230 return (int) opening_request_rc;231 }232 233 int usb_read(async_exch_t *exch, usb_endpoint_t endpoint, uint64_t setup,234 void *data, size_t size, size_t *rec_size)235 {236 if (!exch)237 return EBADMEM;238 239 if (size == 0 && setup == 0)240 return EOK;241 242 /* Make call identifying target USB device and type of transfer. */243 aid_t opening_request = async_send_4(exch,244 DEV_IFACE_ID(USB_DEV_IFACE), IPC_M_USB_READ, endpoint,245 (setup & UINT32_MAX), (setup >> 32), NULL);246 247 if (opening_request == 0) {248 return ENOMEM;249 }250 251 /* Retrieve the data. */252 ipc_call_t data_request_call;253 aid_t data_request =254 async_data_read(exch, data, size, &data_request_call);255 256 if (data_request == 0) {257 // FIXME: How to let the other side know that we want to abort?258 async_forget(opening_request);259 return ENOMEM;260 }261 262 /* Wait for the answer. */263 sysarg_t data_request_rc;264 sysarg_t opening_request_rc;265 async_wait_for(data_request, &data_request_rc);266 async_wait_for(opening_request, &opening_request_rc);267 268 if (data_request_rc != EOK) {269 /* Prefer the return code of the opening request. */270 if (opening_request_rc != EOK) {271 return (int) opening_request_rc;272 } else {273 return (int) data_request_rc;274 }275 }276 if (opening_request_rc != EOK) {277 return (int) opening_request_rc;278 }279 280 *rec_size = IPC_GET_ARG2(data_request_call);281 return EOK;282 }283 284 int usb_write(async_exch_t *exch, usb_endpoint_t endpoint, uint64_t setup,285 const void *data, size_t size)286 {287 if (!exch)288 return EBADMEM;289 290 if (size == 0 && setup == 0)291 return EOK;292 293 aid_t opening_request = async_send_5(exch,294 DEV_IFACE_ID(USB_DEV_IFACE), IPC_M_USB_WRITE, endpoint, size,295 (setup & UINT32_MAX), (setup >> 32), NULL);296 297 if (opening_request == 0) {298 return ENOMEM;299 }300 301 /* Send the data if any. */302 if (size > 0) {303 const int ret = async_data_write_start(exch, data, size);304 if (ret != EOK) {305 async_forget(opening_request);306 return ret;307 }308 }309 310 /* Wait for the answer. */311 sysarg_t opening_request_rc;312 async_wait_for(opening_request, &opening_request_rc);313 314 return (int) opening_request_rc;315 }316 317 103 static void remote_usb_get_my_interface(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 318 104 static void remote_usb_get_my_device_handle(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 319 static void remote_usb_reserve_default_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);320 static void remote_usb_release_default_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);321 static void remote_usb_device_enumerate(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);322 static void remote_usb_device_remove(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);323 static void remote_usb_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);324 static void remote_usb_unregister_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);325 static void remote_usb_read(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call);326 static void remote_usb_write(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call);327 105 328 106 /** Remote USB interface operations. */ … … 330 108 [IPC_M_USB_GET_MY_INTERFACE] = remote_usb_get_my_interface, 331 109 [IPC_M_USB_GET_MY_DEVICE_HANDLE] = remote_usb_get_my_device_handle, 332 [IPC_M_USB_RESERVE_DEFAULT_ADDRESS] = remote_usb_reserve_default_address,333 [IPC_M_USB_RELEASE_DEFAULT_ADDRESS] = remote_usb_release_default_address,334 [IPC_M_USB_DEVICE_ENUMERATE] = remote_usb_device_enumerate,335 [IPC_M_USB_DEVICE_REMOVE] = remote_usb_device_remove,336 [IPC_M_USB_REGISTER_ENDPOINT] = remote_usb_register_endpoint,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,340 110 }; 341 111 … … 346 116 .methods = remote_usb_iface_ops, 347 117 }; 348 349 typedef struct {350 ipc_callid_t caller;351 ipc_callid_t data_caller;352 void *buffer;353 } async_transaction_t;354 118 355 119 void remote_usb_get_my_interface(ddf_fun_t *fun, void *iface, … … 391 155 } 392 156 393 void remote_usb_reserve_default_address(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->reserve_default_address == NULL) {399 async_answer_0(callid, ENOTSUP);400 return;401 }402 403 usb_speed_t speed = DEV_IPC_GET_ARG1(*call);404 const int ret = usb_iface->reserve_default_address(fun, speed);405 async_answer_0(callid, ret);406 }407 408 void remote_usb_release_default_address(ddf_fun_t *fun, void *iface,409 ipc_callid_t callid, ipc_call_t *call)410 {411 const usb_iface_t *usb_iface = (usb_iface_t *) iface;412 413 if (usb_iface->release_default_address == NULL) {414 async_answer_0(callid, ENOTSUP);415 return;416 }417 418 const int ret = usb_iface->release_default_address(fun);419 async_answer_0(callid, ret);420 }421 422 static void remote_usb_device_enumerate(ddf_fun_t *fun, void *iface,423 ipc_callid_t callid, ipc_call_t *call)424 {425 const usb_iface_t *usb_iface = (usb_iface_t *) iface;426 427 if (usb_iface->device_enumerate == NULL) {428 async_answer_0(callid, ENOTSUP);429 return;430 }431 432 const unsigned port = DEV_IPC_GET_ARG1(*call);433 const int ret = usb_iface->device_enumerate(fun, port);434 async_answer_0(callid, ret);435 }436 437 static void remote_usb_device_remove(ddf_fun_t *fun, void *iface,438 ipc_callid_t callid, ipc_call_t *call)439 {440 const usb_iface_t *usb_iface = (usb_iface_t *) iface;441 442 if (usb_iface->device_remove == NULL) {443 async_answer_0(callid, ENOTSUP);444 return;445 }446 447 const unsigned port = DEV_IPC_GET_ARG1(*call);448 const int ret = usb_iface->device_remove(fun, port);449 async_answer_0(callid, ret);450 }451 452 static void remote_usb_register_endpoint(ddf_fun_t *fun, void *iface,453 ipc_callid_t callid, ipc_call_t *call)454 {455 assert(fun);456 assert(iface);457 assert(call);458 459 const usb_iface_t *usb_iface = iface;460 461 if (!usb_iface->register_endpoint) {462 async_answer_0(callid, ENOTSUP);463 return;464 }465 466 void *buffer = NULL;467 size_t size = 0;468 int rc = async_data_write_accept(&buffer, false,469 sizeof(usb_endpoint_desc_t), sizeof(usb_endpoint_desc_t), 0, &size);470 471 if (rc != EOK) {472 free(buffer);473 async_answer_0(callid, rc);474 return;475 }476 477 usb_endpoint_desc_t *endpoint_desc = (usb_endpoint_desc_t *) buffer;478 rc = usb_iface->register_endpoint(fun, endpoint_desc);479 480 free(buffer);481 async_answer_0(callid, rc);482 }483 484 static void remote_usb_unregister_endpoint(ddf_fun_t *fun, void *iface,485 ipc_callid_t callid, ipc_call_t *call)486 {487 assert(fun);488 assert(iface);489 assert(call);490 491 const usb_iface_t *usb_iface = iface;492 493 if (!usb_iface->unregister_endpoint) {494 async_answer_0(callid, ENOTSUP);495 return;496 }497 498 void *buffer = NULL;499 size_t size = 0;500 int rc = async_data_write_accept(&buffer, false,501 sizeof(usb_endpoint_desc_t), sizeof(usb_endpoint_desc_t), 0, &size);502 503 if (rc != EOK) {504 free(buffer);505 async_answer_0(callid, rc);506 return;507 }508 509 usb_endpoint_desc_t *endpoint_desc = (usb_endpoint_desc_t *) buffer;510 usb_iface->unregister_endpoint(fun, endpoint_desc);511 512 free(buffer);513 async_answer_0(callid, rc);514 }515 516 static void async_transaction_destroy(async_transaction_t *trans)517 {518 if (trans == NULL) {519 return;520 }521 if (trans->buffer != NULL) {522 free(trans->buffer);523 }524 525 free(trans);526 }527 528 static async_transaction_t *async_transaction_create(ipc_callid_t caller)529 {530 async_transaction_t *trans = malloc(sizeof(async_transaction_t));531 if (trans == NULL) {532 return NULL;533 }534 535 trans->caller = caller;536 trans->data_caller = 0;537 trans->buffer = NULL;538 539 return trans;540 }541 542 static int callback_out(usb_transfer_batch_t *batch)543 {544 async_transaction_t *trans = batch->on_complete_data;545 546 const int err = async_answer_0(trans->caller, batch->error);547 548 async_transaction_destroy(trans);549 550 return err;551 }552 553 static int callback_in(usb_transfer_batch_t *batch)554 {555 async_transaction_t *trans = batch->on_complete_data;556 557 if (trans->data_caller) {558 if (batch->error == EOK) {559 batch->error = async_data_read_finalize(trans->data_caller,560 trans->buffer, batch->transfered_size);561 } else {562 async_answer_0(trans->data_caller, EINTR);563 }564 }565 566 const int err = async_answer_0(trans->caller, batch->error);567 async_transaction_destroy(trans);568 return err;569 }570 571 void remote_usb_read(572 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)573 {574 assert(fun);575 assert(iface);576 assert(call);577 578 const usb_iface_t *usb_iface = iface;579 580 if (!usb_iface->read) {581 async_answer_0(callid, ENOTSUP);582 return;583 }584 585 const usb_endpoint_t ep = DEV_IPC_GET_ARG1(*call);586 const uint64_t setup =587 ((uint64_t)DEV_IPC_GET_ARG2(*call)) |588 (((uint64_t)DEV_IPC_GET_ARG3(*call)) << 32);589 590 async_transaction_t *trans = async_transaction_create(callid);591 if (trans == NULL) {592 async_answer_0(callid, ENOMEM);593 return;594 }595 596 size_t size = 0;597 if (!async_data_read_receive(&trans->data_caller, &size)) {598 async_answer_0(callid, EPARTY);599 async_transaction_destroy(trans);600 return;601 }602 603 trans->buffer = malloc(size);604 if (trans->buffer == NULL) {605 async_answer_0(trans->data_caller, ENOMEM);606 async_answer_0(callid, ENOMEM);607 async_transaction_destroy(trans);608 return;609 }610 611 const usb_target_t target = {{612 /* .address is initialized by read itself */613 .endpoint = ep,614 }};615 616 const int rc = usb_iface->read(617 fun, target, setup, trans->buffer, size, callback_in, trans);618 619 if (rc != EOK) {620 async_answer_0(trans->data_caller, rc);621 async_answer_0(callid, rc);622 async_transaction_destroy(trans);623 }624 }625 626 void remote_usb_write(627 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)628 {629 assert(fun);630 assert(iface);631 assert(call);632 633 const usb_iface_t *usb_iface = iface;634 635 if (!usb_iface->write) {636 async_answer_0(callid, ENOTSUP);637 return;638 }639 640 const usb_endpoint_t ep = DEV_IPC_GET_ARG1(*call);641 const size_t data_buffer_len = DEV_IPC_GET_ARG2(*call);642 const uint64_t setup =643 ((uint64_t)DEV_IPC_GET_ARG3(*call)) |644 (((uint64_t)DEV_IPC_GET_ARG4(*call)) << 32);645 646 async_transaction_t *trans = async_transaction_create(callid);647 if (trans == NULL) {648 async_answer_0(callid, ENOMEM);649 return;650 }651 652 size_t size = 0;653 if (data_buffer_len > 0) {654 const int rc = async_data_write_accept(&trans->buffer, false,655 1, data_buffer_len, 0, &size);656 657 if (rc != EOK) {658 async_answer_0(callid, rc);659 async_transaction_destroy(trans);660 return;661 }662 }663 664 const usb_target_t target = {{665 /* .address is initialized by write itself */666 .endpoint = ep,667 }};668 669 const int rc = usb_iface->write(670 fun, target, setup, trans->buffer, size, callback_out, trans);671 672 if (rc != EOK) {673 async_answer_0(callid, rc);674 async_transaction_destroy(trans);675 }676 }677 157 /** 678 158 * @}
Note:
See TracChangeset
for help on using the changeset viewer.