Changes in uspace/lib/drv/generic/remote_usb.c [58563585:7f80313] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/drv/generic/remote_usb.c
r58563585 r7f80313 35 35 36 36 #include <async.h> 37 #include <errno.h> 37 38 #include <macros.h> 38 #include <errno.h>39 #include <devman.h>40 39 41 40 #include "usb_iface.h" 42 41 #include "ddf/driver.h" 43 42 43 typedef enum { 44 IPC_M_USB_GET_MY_ADDRESS, 45 IPC_M_USB_GET_MY_INTERFACE, 46 IPC_M_USB_GET_HOST_CONTROLLER_HANDLE, 47 } usb_iface_funcs_t; 44 48 45 usb_dev_session_t *usb_dev_connect(devman_handle_t handle) 49 /** Tell USB address assigned to device. 50 * @param exch Vaid IPC exchange 51 * @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) 46 57 { 47 return devman_device_connect(handle, IPC_FLAG_BLOCKING); 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; 48 67 } 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 61 typedef enum {62 IPC_M_USB_GET_MY_INTERFACE,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,72 } usb_iface_funcs_t;73 68 74 69 /** Tell interface number given device can use. … … 90 85 } 91 86 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 * 87 /** Tell devman handle of device host controller. 88 * @param[in] exch IPC communication exchange 89 * @param[out] hc_handle devman handle of the HC used by the target device. 97 90 * @return Error code. 98 *99 91 */ 100 int usb_get_ my_device_handle(async_exch_t *exch, devman_handle_t *handle)92 int usb_get_hc_handle(async_exch_t *exch, devman_handle_t *hc_handle) 101 93 { 102 devman_handle_t h = 0; 94 if (!exch) 95 return EBADMEM; 96 devman_handle_t h; 103 97 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 && h andle)106 *h andle = (devman_handle_t)h;98 IPC_M_USB_GET_HOST_CONTROLLER_HANDLE, &h); 99 if (ret == EOK && hc_handle) 100 *hc_handle = (devman_handle_t)h; 107 101 return ret; 108 102 } 109 103 110 /** Reserve default USB address.111 * @param[in] exch IPC communication exchange112 * @param[in] speed Communication speed of the newly attached device113 * @return Error code.114 */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 104 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); 152 return ret; 153 } 154 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 static void remote_usb_get_my_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 287 106 static void remote_usb_get_my_interface(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 static void remote_usb_get_hc_handle(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 297 108 298 109 /** Remote USB interface operations. */ 299 110 static const remote_iface_func_ptr_t remote_usb_iface_ops [] = { 111 [IPC_M_USB_GET_MY_ADDRESS] = remote_usb_get_my_address, 300 112 [IPC_M_USB_GET_MY_INTERFACE] = remote_usb_get_my_interface, 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 [IPC_M_USB_GET_HOST_CONTROLLER_HANDLE] = remote_usb_get_hc_handle, 310 114 }; 311 115 … … 314 118 const remote_iface_t remote_usb_iface = { 315 119 .method_count = ARRAY_SIZE(remote_usb_iface_ops), 316 .methods = remote_usb_iface_ops ,120 .methods = remote_usb_iface_ops 317 121 }; 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 } 318 142 319 143 void remote_usb_get_my_interface(ddf_fun_t *fun, void *iface, … … 336 160 } 337 161 338 void remote_usb_get_ my_device_handle(ddf_fun_t *fun, void *iface,162 void remote_usb_get_hc_handle(ddf_fun_t *fun, void *iface, 339 163 ipc_callid_t callid, ipc_call_t *call) 340 164 { 341 165 const usb_iface_t *usb_iface = (usb_iface_t *) iface; 342 166 343 if (usb_iface->get_ my_device_handle == NULL) {167 if (usb_iface->get_hc_handle == NULL) { 344 168 async_answer_0(callid, ENOTSUP); 345 169 return; … … 347 171 348 172 devman_handle_t handle; 349 const int ret = usb_iface->get_ my_device_handle(fun, &handle);173 const int ret = usb_iface->get_hc_handle(fun, &handle); 350 174 if (ret != EOK) { 351 175 async_answer_0(callid, ret); … … 354 178 async_answer_1(callid, EOK, (sysarg_t) handle); 355 179 } 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 }619 180 /** 620 181 * @}
Note:
See TracChangeset
for help on using the changeset viewer.