Changes in uspace/lib/drv/generic/remote_usb.c [90c340fb:41df71f9] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/drv/generic/remote_usb.c
r90c340fb r41df71f9 35 35 36 36 #include <async.h> 37 #include <assert.h>38 37 #include <macros.h> 39 38 #include <errno.h> 40 39 #include <devman.h> 40 #include <usb/host/usb_transfer_batch.h> 41 41 42 42 #include "usb_iface.h" … … 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 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 int 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 int 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 int 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 sysarg_t data_request_rc;236 sysarg_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 (int) opening_request_rc;244 } else {245 return (int) data_request_rc;246 }247 }248 if (opening_request_rc != EOK) {249 return (int) opening_request_rc;250 }251 252 *rec_size = IPC_GET_ARG2(data_request_call);253 return EOK;254 }255 256 int 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 int 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 sysarg_t opening_request_rc;284 async_wait_for(opening_request, &opening_request_rc);285 286 return (int) opening_request_rc;287 }288 289 103 static void remote_usb_get_my_interface(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 290 104 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);299 105 300 106 /** Remote USB interface operations. */ … … 302 108 [IPC_M_USB_GET_MY_INTERFACE] = remote_usb_get_my_interface, 303 109 [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,312 110 }; 313 111 … … 357 155 } 358 156 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 int 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 int 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 int 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 int 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 int 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 int 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(int 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(int 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 int 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 int 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 int 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 }621 157 /** 622 158 * @}
Note:
See TracChangeset
for help on using the changeset viewer.