Changes in uspace/lib/drv/generic/remote_usb.c [b7fd2a0:5a6cc679] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/drv/generic/remote_usb.c
rb7fd2a0 r5a6cc679 61 61 62 62 typedef enum { 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, 63 IPC_M_USB_GET_MY_DESCRIPTION, 73 64 } usb_iface_funcs_t; 74 65 … … 79 70 * @return Error code. 80 71 */ 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; 90 return ret; 91 } 92 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) 72 errno_t usb_get_my_description(async_exch_t *exch, usb_device_desc_t *desc) 207 73 { 208 74 if (!exch) 209 75 return EBADMEM; 210 76 211 if (size == 0 && setup == 0) 212 return EOK; 77 usb_device_desc_t tmp_desc; 213 78 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; 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; 88 return ret; 254 89 } 255 90 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); 91 static void remote_usb_get_my_description(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 299 92 300 93 /** Remote USB interface operations. */ 301 94 static const remote_iface_func_ptr_t remote_usb_iface_ops [] = { 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, 95 [IPC_M_USB_GET_MY_DESCRIPTION] = remote_usb_get_my_description, 312 96 }; 313 97 … … 319 103 }; 320 104 321 void remote_usb_get_my_ interface(ddf_fun_t *fun, void *iface,105 void remote_usb_get_my_description(ddf_fun_t *fun, void *iface, 322 106 ipc_callid_t callid, ipc_call_t *call) 323 107 { 324 108 const usb_iface_t *usb_iface = (usb_iface_t *) iface; 325 109 326 if (usb_iface->get_my_ interface== NULL) {110 if (usb_iface->get_my_description == NULL) { 327 111 async_answer_0(callid, ENOTSUP); 328 112 return; 329 113 } 330 114 331 int iface_no;332 const errno_t ret = usb_iface->get_my_ interface(fun, &iface_no);115 usb_device_desc_t desc; 116 const errno_t ret = usb_iface->get_my_description(fun, &desc); 333 117 if (ret != EOK) { 334 118 async_answer_0(callid, ret); 335 119 } else { 336 async_answer_1(callid, EOK, iface_no); 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); 337 126 } 338 127 } 339 128 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 }621 129 /** 622 130 * @}
Note:
See TracChangeset
for help on using the changeset viewer.