Changeset df6ded8 in mainline for uspace/lib/drv
- Timestamp:
- 2018-02-28T16:37:50Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 1b20da0
- Parents:
- f5e5f73 (diff), b2dca8de (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - git-author:
- Jakub Jermar <jakub@…> (2018-02-28 16:06:42)
- git-committer:
- Jakub Jermar <jakub@…> (2018-02-28 16:37:50)
- Location:
- uspace/lib/drv
- Files:
-
- 3 added
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/drv/Makefile
rf5e5f73 rdf6ded8 47 47 generic/remote_usb.c \ 48 48 generic/remote_pci.c \ 49 generic/remote_usbdiag.c \ 49 50 generic/remote_usbhc.c \ 50 51 generic/remote_usbhid.c \ -
uspace/lib/drv/generic/dev_iface.c
rf5e5f73 rdf6ded8 48 48 #include "remote_ieee80211.h" 49 49 #include "remote_usb.h" 50 #include "remote_usbdiag.h" 50 51 #include "remote_usbhc.h" 51 52 #include "remote_usbhid.h" … … 65 66 [PCI_DEV_IFACE] = &remote_pci_iface, 66 67 [USB_DEV_IFACE] = &remote_usb_iface, 68 [USBDIAG_DEV_IFACE] = &remote_usbdiag_iface, 67 69 [USBHC_DEV_IFACE] = &remote_usbhc_iface, 68 70 [USBHID_DEV_IFACE] = &remote_usbhid_iface, … … 85 87 if (iface_method_idx >= rem_iface->method_count) 86 88 return NULL; 87 89 88 90 return rem_iface->methods[iface_method_idx]; 89 91 } -
uspace/lib/drv/generic/driver.c
rf5e5f73 rdf6ded8 971 971 } 972 972 973 int ddf_driver_main(const driver_t *drv)973 errno_t ddf_driver_main(const driver_t *drv) 974 974 { 975 975 /* -
uspace/lib/drv/generic/private/remote_usbhc.h
rf5e5f73 rdf6ded8 1 1 /* 2 2 * Copyright (c) 2010 Vojtech Horky 3 * Copyright (c) 2017 Ondrej Hlavaty 3 4 * All rights reserved. 4 5 * -
uspace/lib/drv/generic/remote_usb.c
rf5e5f73 rdf6ded8 2 2 * Copyright (c) 2010 Vojtech Horky 3 3 * Copyright (c) 2011 Jan Vesely 4 * Copyright (c) 2018 Michal Staruch, Ondrej Hlavaty 4 5 * All rights reserved. 5 6 * … … 51 52 usb_dev_session_t *usb_dev_connect_to_self(ddf_dev_t *dev) 52 53 { 53 return devman_parent_device_connect(ddf_dev_get_handle(dev), IPC_FLAG_BLOCKING); 54 return devman_parent_device_connect(ddf_dev_get_handle(dev), 55 IPC_FLAG_BLOCKING); 54 56 } 55 57 … … 61 63 62 64 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, 65 IPC_M_USB_GET_MY_DESCRIPTION, 73 66 } usb_iface_funcs_t; 74 67 … … 79 72 * @return Error code. 80 73 */ 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) 74 errno_t usb_get_my_description(async_exch_t *exch, usb_device_desc_t *desc) 207 75 { 208 76 if (!exch) 209 77 return EBADMEM; 210 78 211 if (size == 0 && setup == 0) 212 return EOK; 79 usb_device_desc_t tmp_desc; 213 80 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; 81 const errno_t ret = async_req_1_5(exch, DEV_IFACE_ID(USB_DEV_IFACE), 82 IPC_M_USB_GET_MY_DESCRIPTION, 83 (sysarg_t *) &tmp_desc.address, 84 (sysarg_t *) &tmp_desc.depth, 85 (sysarg_t *) &tmp_desc.speed, 86 &tmp_desc.handle, 87 (sysarg_t *) &tmp_desc.iface); 88 if (ret == EOK && desc) 89 *desc = tmp_desc; 90 return ret; 254 91 } 255 92 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); 93 static void remote_usb_get_my_description(ddf_fun_t *, void *, 94 ipc_callid_t, ipc_call_t *); 299 95 300 96 /** Remote USB interface operations. */ 301 97 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, 98 [IPC_M_USB_GET_MY_DESCRIPTION] = remote_usb_get_my_description, 312 99 }; 313 100 … … 319 106 }; 320 107 321 void remote_usb_get_my_ interface(ddf_fun_t *fun, void *iface,108 void remote_usb_get_my_description(ddf_fun_t *fun, void *iface, 322 109 ipc_callid_t callid, ipc_call_t *call) 323 110 { 324 111 const usb_iface_t *usb_iface = (usb_iface_t *) iface; 325 112 326 if (usb_iface->get_my_ interface== NULL) {113 if (usb_iface->get_my_description == NULL) { 327 114 async_answer_0(callid, ENOTSUP); 328 115 return; 329 116 } 330 117 331 int iface_no;332 const errno_t ret = usb_iface->get_my_ interface(fun, &iface_no);118 usb_device_desc_t desc; 119 const errno_t ret = usb_iface->get_my_description(fun, &desc); 333 120 if (ret != EOK) { 334 121 async_answer_0(callid, ret); 335 122 } else { 336 async_answer_1(callid, EOK, iface_no); 123 async_answer_5(callid, EOK, 124 (sysarg_t) desc.address, 125 (sysarg_t) desc.depth, 126 (sysarg_t) desc.speed, 127 desc.handle, 128 desc.iface); 337 129 } 338 130 } 339 131 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 132 /** 622 133 * @} -
uspace/lib/drv/generic/remote_usbhc.c
rf5e5f73 rdf6ded8 1 1 /* 2 * Copyright (c) 2010 -2011Vojtech Horky2 * Copyright (c) 2010 Vojtech Horky 3 3 * Copyright (c) 2011 Jan Vesely 4 * Copyright (c) 2018 Ondrej Hlavaty, Petr Manek 4 5 * All rights reserved. 5 6 * … … 35 36 36 37 #include <async.h> 38 #include <macros.h> 37 39 #include <errno.h> 38 #include < assert.h>39 #include < macros.h>40 #include <devman.h> 41 #include <as.h> 40 42 41 43 #include "usbhc_iface.h" 42 44 #include "ddf/driver.h" 43 45 44 #define USB_MAX_PAYLOAD_SIZE 1020 45 46 /** IPC methods for communication with HC through DDF interface. 47 * 48 * Notes for async methods: 49 * 50 * Methods for sending data to device (OUT transactions) 51 * - e.g. IPC_M_USBHC_INTERRUPT_OUT - 52 * always use the same semantics: 53 * - first, IPC call with given method is made 54 * - argument #1 is target address 55 * - argument #2 is target endpoint 56 * - argument #3 is max packet size of the endpoint 57 * - this call is immediately followed by IPC data write (from caller) 58 * - the initial call (and the whole transaction) is answer after the 59 * transaction is scheduled by the HC and acknowledged by the device 60 * or immediately after error is detected 61 * - the answer carries only the error code 62 * 63 * Methods for retrieving data from device (IN transactions) 64 * - e.g. IPC_M_USBHC_INTERRUPT_IN - 65 * also use the same semantics: 66 * - first, IPC call with given method is made 67 * - argument #1 is target address 68 * - argument #2 is target endpoint 69 * - this call is immediately followed by IPC data read (async version) 70 * - the call is not answered until the device returns some data (or until 71 * error occurs) 72 * 73 * Some special methods (NO-DATA transactions) do not send any data. These 74 * might behave as both OUT or IN transactions because communication parts 75 * where actual buffers are exchanged are omitted. 76 ** 77 * For all these methods, wrap functions exists. Important rule: functions 78 * for IN transactions have (as parameters) buffers where retrieved data 79 * will be stored. These buffers must be already allocated and shall not be 80 * touch until the transaction is completed 81 * (e.g. not before calling usb_wait_for() with appropriate handle). 82 * OUT transactions buffers can be freed immediately after call is dispatched 83 * (i.e. after return from wrapping function). 84 * 85 */ 46 86 47 typedef enum { 87 /** Get data from device. 88 * See explanation at usb_iface_funcs_t (IN transaction). 89 */ 90 IPC_M_USBHC_READ, 91 92 /** Send data to device. 93 * See explanation at usb_iface_funcs_t (OUT transaction). 94 */ 95 IPC_M_USBHC_WRITE, 48 IPC_M_USB_DEFAULT_ADDRESS_RESERVATION, 49 IPC_M_USB_DEVICE_ENUMERATE, 50 IPC_M_USB_DEVICE_REMOVE, 51 IPC_M_USB_REGISTER_ENDPOINT, 52 IPC_M_USB_UNREGISTER_ENDPOINT, 53 IPC_M_USB_TRANSFER, 96 54 } usbhc_iface_funcs_t; 97 55 98 errno_t usbhc_read(async_exch_t *exch, usb_address_t address, 99 usb_endpoint_t endpoint, uint64_t setup, void *data, size_t size, 100 size_t *rec_size) 101 { 102 if (!exch) 103 return EBADMEM; 104 105 if (size == 0 && setup == 0) 106 return EOK; 107 108 const usb_target_t target = 109 {{ .address = address, .endpoint = endpoint }}; 110 111 /* Make call identifying target USB device and type of transfer. */ 112 aid_t opening_request = async_send_4(exch, 113 DEV_IFACE_ID(USBHC_DEV_IFACE), 114 IPC_M_USBHC_READ, target.packed, 115 (setup & UINT32_MAX), (setup >> 32), NULL); 56 /** Reserve default USB address. 57 * @param[in] exch IPC communication exchange 58 * @return Error code. 59 */ 60 errno_t usbhc_reserve_default_address(async_exch_t *exch) 61 { 62 if (!exch) 63 return EBADMEM; 64 return async_req_2_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USB_DEFAULT_ADDRESS_RESERVATION, true); 65 } 66 67 /** Release default USB address. 68 * 69 * @param[in] exch IPC communication exchange 70 * 71 * @return Error code. 72 */ 73 errno_t usbhc_release_default_address(async_exch_t *exch) 74 { 75 if (!exch) 76 return EBADMEM; 77 return async_req_2_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USB_DEFAULT_ADDRESS_RESERVATION, false); 78 } 79 80 /** 81 * Trigger USB device enumeration 82 * 83 * @param[in] exch IPC communication exchange 84 * @param[in] port Port number at which the device is attached 85 * @param[in] speed Communication speed of the newly attached device 86 * 87 * @return Error code. 88 */ 89 errno_t usbhc_device_enumerate(async_exch_t *exch, unsigned port, usb_speed_t speed) 90 { 91 if (!exch) 92 return EBADMEM; 93 const errno_t ret = async_req_3_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 94 IPC_M_USB_DEVICE_ENUMERATE, port, speed); 95 return ret; 96 } 97 98 /** Trigger USB device enumeration 99 * 100 * @param[in] exch IPC communication exchange 101 * @param[in] handle Identifier of the device 102 * 103 * @return Error code. 104 * 105 */ 106 errno_t usbhc_device_remove(async_exch_t *exch, unsigned port) 107 { 108 if (!exch) 109 return EBADMEM; 110 return async_req_2_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 111 IPC_M_USB_DEVICE_REMOVE, port); 112 } 113 114 errno_t usbhc_register_endpoint(async_exch_t *exch, usb_pipe_desc_t *pipe_desc, 115 const usb_endpoint_descriptors_t *desc) 116 { 117 if (!exch) 118 return EBADMEM; 119 120 if (!desc) 121 return EINVAL; 122 123 aid_t opening_request = async_send_1(exch, 124 DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USB_REGISTER_ENDPOINT, NULL); 116 125 117 126 if (opening_request == 0) { … … 119 128 } 120 129 121 /* Retrieve the data. */ 122 ipc_call_t data_request_call; 123 aid_t data_request = 124 async_data_read(exch, data, size, &data_request_call); 125 126 if (data_request == 0) { 127 // FIXME: How to let the other side know that we want to abort? 130 errno_t ret = async_data_write_start(exch, desc, sizeof(*desc)); 131 if (ret != EOK) { 128 132 async_forget(opening_request); 129 return ENOMEM;133 return ret; 130 134 } 131 135 132 136 /* Wait for the answer. */ 133 errno_t data_request_rc;134 137 errno_t opening_request_rc; 135 async_wait_for(data_request, &data_request_rc);136 138 async_wait_for(opening_request, &opening_request_rc); 137 139 138 if (data_request_rc != EOK) { 139 /* Prefer the return code of the opening request. */ 140 if (opening_request_rc != EOK) { 141 return (errno_t) opening_request_rc; 142 } else { 143 return (errno_t) data_request_rc; 144 } 145 } 146 if (opening_request_rc != EOK) { 140 if (opening_request_rc) 147 141 return (errno_t) opening_request_rc; 148 } 149 150 *rec_size = IPC_GET_ARG2(data_request_call); 142 143 usb_pipe_desc_t dest; 144 ret = async_data_read_start(exch, &dest, sizeof(dest)); 145 if (ret != EOK) { 146 return ret; 147 } 148 149 if (pipe_desc) 150 *pipe_desc = dest; 151 151 152 return EOK; 152 153 } 153 154 154 errno_t usbhc_write(async_exch_t *exch, usb_address_t address, 155 usb_endpoint_t endpoint, uint64_t setup, const void *data, size_t size) 156 { 157 if (!exch) 158 return EBADMEM; 159 160 if (size == 0 && setup == 0) 161 return EOK; 162 163 const usb_target_t target = 164 {{ .address = address, .endpoint = endpoint }}; 165 166 aid_t opening_request = async_send_5(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 167 IPC_M_USBHC_WRITE, target.packed, size, 168 (setup & UINT32_MAX), (setup >> 32), NULL); 155 errno_t usbhc_unregister_endpoint(async_exch_t *exch, const usb_pipe_desc_t *pipe_desc) 156 { 157 if (!exch) 158 return EBADMEM; 159 160 aid_t opening_request = async_send_1(exch, 161 DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USB_UNREGISTER_ENDPOINT, NULL); 169 162 170 163 if (opening_request == 0) { … … 172 165 } 173 166 174 /* Send the data if any. */ 175 if (size > 0) { 176 const errno_t ret = async_data_write_start(exch, data, size); 167 const errno_t ret = async_data_write_start(exch, pipe_desc, sizeof(*pipe_desc)); 168 if (ret != EOK) { 169 async_forget(opening_request); 170 return ret; 171 } 172 173 /* Wait for the answer. */ 174 errno_t opening_request_rc; 175 async_wait_for(opening_request, &opening_request_rc); 176 177 return (errno_t) opening_request_rc; 178 } 179 180 /** 181 * Issue a USB transfer with a data contained in memory area. That area is 182 * temporarily shared with the HC. 183 */ 184 errno_t usbhc_transfer(async_exch_t *exch, 185 const usbhc_iface_transfer_request_t *req, size_t *transferred) 186 { 187 if (transferred) 188 *transferred = 0; 189 190 if (!exch) 191 return EBADMEM; 192 193 ipc_call_t call; 194 195 aid_t opening_request = async_send_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 196 IPC_M_USB_TRANSFER, &call); 197 198 if (opening_request == 0) 199 return ENOMEM; 200 201 const errno_t ret = async_data_write_start(exch, req, sizeof(*req)); 202 if (ret != EOK) { 203 async_forget(opening_request); 204 return ret; 205 } 206 207 /* Share the data, if any. */ 208 if (req->size > 0) { 209 unsigned flags = (req->dir == USB_DIRECTION_IN) 210 ? AS_AREA_WRITE : AS_AREA_READ; 211 212 const errno_t ret = async_share_out_start(exch, req->buffer.virt, flags); 177 213 if (ret != EOK) { 178 214 async_forget(opening_request); … … 185 221 async_wait_for(opening_request, &opening_request_rc); 186 222 223 if (transferred) 224 *transferred = IPC_GET_ARG1(call); 225 187 226 return (errno_t) opening_request_rc; 188 227 } 189 228 190 static void remote_usbhc_read(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 191 static void remote_usbhc_write(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 192 193 /** Remote USB host controller interface operations. */ 194 static const remote_iface_func_ptr_t remote_usbhc_iface_ops[] = { 195 [IPC_M_USBHC_READ] = remote_usbhc_read, 196 [IPC_M_USBHC_WRITE] = remote_usbhc_write, 229 static void remote_usbhc_default_address_reservation(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 230 static void remote_usbhc_device_enumerate(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 231 static void remote_usbhc_device_remove(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 232 static void remote_usbhc_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 233 static void remote_usbhc_unregister_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 234 static void remote_usbhc_transfer(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call); 235 236 /** Remote USB interface operations. */ 237 static const remote_iface_func_ptr_t remote_usbhc_iface_ops [] = { 238 [IPC_M_USB_DEFAULT_ADDRESS_RESERVATION] = remote_usbhc_default_address_reservation, 239 [IPC_M_USB_DEVICE_ENUMERATE] = remote_usbhc_device_enumerate, 240 [IPC_M_USB_DEVICE_REMOVE] = remote_usbhc_device_remove, 241 [IPC_M_USB_REGISTER_ENDPOINT] = remote_usbhc_register_endpoint, 242 [IPC_M_USB_UNREGISTER_ENDPOINT] = remote_usbhc_unregister_endpoint, 243 [IPC_M_USB_TRANSFER] = remote_usbhc_transfer, 197 244 }; 198 245 199 /** Remote USB host controllerinterface structure.246 /** Remote USB interface structure. 200 247 */ 201 248 const remote_iface_t remote_usbhc_iface = { 202 249 .method_count = ARRAY_SIZE(remote_usbhc_iface_ops), 203 .methods = remote_usbhc_iface_ops 250 .methods = remote_usbhc_iface_ops, 204 251 }; 205 252 206 253 typedef struct { 207 254 ipc_callid_t caller; 208 ipc_callid_t data_caller; 209 void *buffer; 255 usbhc_iface_transfer_request_t request; 210 256 } async_transaction_t; 211 257 212 static void async_transaction_destroy(async_transaction_t *trans) 213 { 214 if (trans == NULL) 215 return; 216 217 if (trans->buffer != NULL) 218 free(trans->buffer); 219 220 free(trans); 221 } 222 223 static async_transaction_t *async_transaction_create(ipc_callid_t caller) 224 { 225 async_transaction_t *trans = malloc(sizeof(async_transaction_t)); 226 if (trans == NULL) { 227 return NULL; 228 } 229 230 trans->caller = caller; 231 trans->data_caller = 0; 232 trans->buffer = NULL; 233 234 return trans; 235 } 236 237 static void callback_out(errno_t outcome, void *arg) 238 { 239 async_transaction_t *trans = arg; 240 241 async_answer_0(trans->caller, outcome); 242 243 async_transaction_destroy(trans); 244 } 245 246 static void callback_in(errno_t outcome, size_t actual_size, void *arg) 247 { 248 async_transaction_t *trans = (async_transaction_t *)arg; 249 250 if (outcome != EOK) { 251 async_answer_0(trans->caller, outcome); 252 if (trans->data_caller) { 253 async_answer_0(trans->data_caller, EINTR); 254 } 255 async_transaction_destroy(trans); 256 return; 257 } 258 259 if (trans->data_caller) { 260 async_data_read_finalize(trans->data_caller, 261 trans->buffer, actual_size); 262 } 263 264 async_answer_0(trans->caller, EOK); 265 266 async_transaction_destroy(trans); 267 } 268 269 void remote_usbhc_read( 270 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call) 258 void remote_usbhc_default_address_reservation(ddf_fun_t *fun, void *iface, 259 ipc_callid_t callid, ipc_call_t *call) 260 { 261 const usbhc_iface_t *usbhc_iface = (usbhc_iface_t *) iface; 262 263 if (usbhc_iface->default_address_reservation == NULL) { 264 async_answer_0(callid, ENOTSUP); 265 return; 266 } 267 268 const bool reserve = IPC_GET_ARG2(*call); 269 const errno_t ret = usbhc_iface->default_address_reservation(fun, reserve); 270 async_answer_0(callid, ret); 271 } 272 273 274 static void remote_usbhc_device_enumerate(ddf_fun_t *fun, void *iface, 275 ipc_callid_t callid, ipc_call_t *call) 276 { 277 const usbhc_iface_t *usbhc_iface = (usbhc_iface_t *) iface; 278 279 if (usbhc_iface->device_enumerate == NULL) { 280 async_answer_0(callid, ENOTSUP); 281 return; 282 } 283 284 const unsigned port = DEV_IPC_GET_ARG1(*call); 285 usb_speed_t speed = DEV_IPC_GET_ARG2(*call); 286 const errno_t ret = usbhc_iface->device_enumerate(fun, port, speed); 287 async_answer_0(callid, ret); 288 } 289 290 static void remote_usbhc_device_remove(ddf_fun_t *fun, void *iface, 291 ipc_callid_t callid, ipc_call_t *call) 292 { 293 const usbhc_iface_t *usbhc_iface = (usbhc_iface_t *) iface; 294 295 if (usbhc_iface->device_remove == NULL) { 296 async_answer_0(callid, ENOTSUP); 297 return; 298 } 299 300 const unsigned port = DEV_IPC_GET_ARG1(*call); 301 const errno_t ret = usbhc_iface->device_remove(fun, port); 302 async_answer_0(callid, ret); 303 } 304 305 static void remote_usbhc_register_endpoint(ddf_fun_t *fun, void *iface, 306 ipc_callid_t callid, ipc_call_t *call) 271 307 { 272 308 assert(fun); … … 274 310 assert(call); 275 311 276 const usbhc_iface_t * hc_iface = iface;277 278 if (! hc_iface->read) {312 const usbhc_iface_t *usbhc_iface = iface; 313 314 if (!usbhc_iface->register_endpoint) { 279 315 async_answer_0(callid, ENOTSUP); 280 316 return; 281 317 } 282 318 283 const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) }; 284 const uint64_t setup = 285 ((uint64_t)DEV_IPC_GET_ARG2(*call)) | 286 (((uint64_t)DEV_IPC_GET_ARG3(*call)) << 32); 319 usb_endpoint_descriptors_t ep_desc; 320 ipc_callid_t data_callid; 321 size_t len; 322 323 if (!async_data_write_receive(&data_callid, &len) 324 || len != sizeof(ep_desc)) { 325 async_answer_0(callid, EINVAL); 326 return; 327 } 328 async_data_write_finalize(data_callid, &ep_desc, sizeof(ep_desc)); 329 330 usb_pipe_desc_t pipe_desc; 331 332 const errno_t rc = usbhc_iface->register_endpoint(fun, &pipe_desc, &ep_desc); 333 async_answer_0(callid, rc); 334 335 if (!async_data_read_receive(&data_callid, &len) 336 || len != sizeof(pipe_desc)) { 337 return; 338 } 339 async_data_read_finalize(data_callid, &pipe_desc, sizeof(pipe_desc)); 340 } 341 342 static void remote_usbhc_unregister_endpoint(ddf_fun_t *fun, void *iface, 343 ipc_callid_t callid, ipc_call_t *call) 344 { 345 assert(fun); 346 assert(iface); 347 assert(call); 348 349 const usbhc_iface_t *usbhc_iface = iface; 350 351 if (!usbhc_iface->unregister_endpoint) { 352 async_answer_0(callid, ENOTSUP); 353 return; 354 } 355 356 usb_pipe_desc_t pipe_desc; 357 ipc_callid_t data_callid; 358 size_t len; 359 360 if (!async_data_write_receive(&data_callid, &len) 361 || len != sizeof(pipe_desc)) { 362 async_answer_0(callid, EINVAL); 363 return; 364 } 365 async_data_write_finalize(data_callid, &pipe_desc, sizeof(pipe_desc)); 366 367 const errno_t rc = usbhc_iface->unregister_endpoint(fun, &pipe_desc); 368 async_answer_0(callid, rc); 369 } 370 371 static void async_transaction_destroy(async_transaction_t *trans) 372 { 373 if (trans == NULL) { 374 return; 375 } 376 if (trans->request.buffer.virt != NULL) { 377 as_area_destroy(trans->request.buffer.virt); 378 } 379 380 free(trans); 381 } 382 383 static async_transaction_t *async_transaction_create(ipc_callid_t caller) 384 { 385 async_transaction_t *trans = calloc(1, sizeof(async_transaction_t)); 386 387 if (trans != NULL) 388 trans->caller = caller; 389 390 return trans; 391 } 392 393 static errno_t transfer_finished(void *arg, errno_t error, size_t transferred_size) 394 { 395 async_transaction_t *trans = arg; 396 const errno_t err = async_answer_1(trans->caller, error, transferred_size); 397 async_transaction_destroy(trans); 398 return err; 399 } 400 401 static errno_t receive_memory_buffer(async_transaction_t *trans) 402 { 403 assert(trans); 404 assert(trans->request.size > 0); 405 406 const size_t required_size = trans->request.offset + trans->request.size; 407 const unsigned required_flags = 408 (trans->request.dir == USB_DIRECTION_IN) 409 ? AS_AREA_WRITE : AS_AREA_READ; 410 411 errno_t err; 412 ipc_callid_t data_callid; 413 size_t size; 414 unsigned flags; 415 416 if (!async_share_out_receive(&data_callid, &size, &flags)) 417 return EPARTY; 418 419 if (size < required_size || (flags & required_flags) != required_flags) { 420 async_answer_0(data_callid, EINVAL); 421 return EINVAL; 422 } 423 424 if ((err = async_share_out_finalize(data_callid, &trans->request.buffer.virt))) 425 return err; 426 427 /* 428 * As we're going to get physical addresses of the mapping, we must make 429 * sure the memory is actually mapped. We must do it right now, because 430 * the area might be read-only or write-only, and we may be unsure 431 * later. 432 */ 433 if (flags & AS_AREA_READ) { 434 char foo = 0; 435 volatile const char *buf = trans->request.buffer.virt + trans->request.offset; 436 for (size_t i = 0; i < size; i += PAGE_SIZE) 437 foo += buf[i]; 438 } else { 439 volatile char *buf = trans->request.buffer.virt + trans->request.offset; 440 for (size_t i = 0; i < size; i += PAGE_SIZE) 441 buf[i] = 0xff; 442 } 443 444 return EOK; 445 } 446 447 void remote_usbhc_transfer(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call) 448 { 449 assert(fun); 450 assert(iface); 451 assert(call); 452 453 const usbhc_iface_t *usbhc_iface = iface; 454 455 if (!usbhc_iface->transfer) { 456 async_answer_0(callid, ENOTSUP); 457 return; 458 } 287 459 288 460 async_transaction_t *trans = async_transaction_create(callid); … … 292 464 } 293 465 294 size_t size = 0; 295 if (!async_data_read_receive(&trans->data_caller, &size)) { 296 async_answer_0(callid, EPARTY); 297 return; 298 } 299 300 trans->buffer = malloc(size); 301 if (trans->buffer == NULL) { 302 async_answer_0(trans->data_caller, ENOMEM); 303 async_answer_0(callid, ENOMEM); 304 async_transaction_destroy(trans); 305 return; 306 } 307 308 const errno_t rc = hc_iface->read( 309 fun, target, setup, trans->buffer, size, callback_in, trans); 310 311 if (rc != EOK) { 312 async_answer_0(trans->data_caller, rc); 313 async_answer_0(callid, rc); 314 async_transaction_destroy(trans); 315 } 316 } 317 318 void remote_usbhc_write( 319 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call) 320 { 321 assert(fun); 322 assert(iface); 323 assert(call); 324 325 const usbhc_iface_t *hc_iface = iface; 326 327 if (!hc_iface->write) { 328 async_answer_0(callid, ENOTSUP); 329 return; 330 } 331 332 const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) }; 333 const size_t data_buffer_len = DEV_IPC_GET_ARG2(*call); 334 const uint64_t setup = 335 ((uint64_t)DEV_IPC_GET_ARG3(*call)) | 336 (((uint64_t)DEV_IPC_GET_ARG4(*call)) << 32); 337 338 async_transaction_t *trans = async_transaction_create(callid); 339 if (trans == NULL) { 340 async_answer_0(callid, ENOMEM); 341 return; 342 } 343 344 size_t size = 0; 345 if (data_buffer_len > 0) { 346 const errno_t rc = async_data_write_accept(&trans->buffer, false, 347 1, USB_MAX_PAYLOAD_SIZE, 348 0, &size); 349 350 if (rc != EOK) { 351 async_answer_0(callid, rc); 352 async_transaction_destroy(trans); 353 return; 354 } 355 } 356 357 const errno_t rc = hc_iface->write( 358 fun, target, setup, trans->buffer, size, callback_out, trans); 359 360 if (rc != EOK) { 361 async_answer_0(callid, rc); 362 async_transaction_destroy(trans); 363 } 364 } 466 errno_t err = EPARTY; 467 468 ipc_callid_t data_callid; 469 size_t len; 470 if (!async_data_write_receive(&data_callid, &len) 471 || len != sizeof(trans->request)) { 472 async_answer_0(data_callid, EINVAL); 473 goto err; 474 } 475 476 if ((err = async_data_write_finalize(data_callid, 477 &trans->request, sizeof(trans->request)))) 478 goto err; 479 480 if (trans->request.size > 0) { 481 if ((err = receive_memory_buffer(trans))) 482 goto err; 483 } else { 484 /* The value was valid on the other side, for us, its garbage. */ 485 trans->request.buffer.virt = NULL; 486 } 487 488 if ((err = usbhc_iface->transfer(fun, &trans->request, 489 &transfer_finished, trans))) 490 goto err; 491 492 /* The call will be answered asynchronously by the callback. */ 493 return; 494 495 err: 496 async_answer_0(callid, err); 497 async_transaction_destroy(trans); 498 } 499 365 500 /** 366 501 * @} -
uspace/lib/drv/include/usb_iface.h
rf5e5f73 rdf6ded8 1 1 /* 2 2 * Copyright (c) 2010 Vojtech Horky 3 * Copyright (c) 2018 Ondrej Hlavaty, Michal Staruch 3 4 * All rights reserved. 4 5 * … … 32 33 */ 33 34 /** @file 34 * @brief USB interface definition.35 * @brief USB device interface definition. 35 36 */ 36 37 … … 40 41 #include "ddf/driver.h" 41 42 #include <async.h> 43 #include <usbhc_iface.h> 42 44 43 45 typedef async_sess_t usb_dev_session_t; 44 46 45 /** USB speeds. */ 46 typedef enum { 47 /** USB 1.1 low speed (1.5Mbits/s). */ 48 USB_SPEED_LOW, 49 /** USB 1.1 full speed (12Mbits/s). */ 50 USB_SPEED_FULL, 51 /** USB 2.0 high speed (480Mbits/s). */ 52 USB_SPEED_HIGH, 53 /** Psuedo-speed serving as a boundary. */ 54 USB_SPEED_MAX 55 } usb_speed_t; 56 57 /** USB endpoint number type. 58 * Negative values could be used to indicate error. 59 */ 60 typedef int16_t usb_endpoint_t; 61 62 /** USB address type. 63 * Negative values could be used to indicate error. 64 */ 65 typedef int16_t usb_address_t; 66 67 /** USB transfer type. */ 68 typedef enum { 69 USB_TRANSFER_CONTROL = 0, 70 USB_TRANSFER_ISOCHRONOUS = 1, 71 USB_TRANSFER_BULK = 2, 72 USB_TRANSFER_INTERRUPT = 3 73 } usb_transfer_type_t; 74 75 /** USB data transfer direction. */ 76 typedef enum { 77 USB_DIRECTION_IN, 78 USB_DIRECTION_OUT, 79 USB_DIRECTION_BOTH 80 } usb_direction_t; 81 82 /** USB complete address type. 83 * Pair address + endpoint is identification of transaction recipient. 84 */ 85 typedef union { 86 struct { 87 usb_address_t address; 88 usb_endpoint_t endpoint; 89 } __attribute__((packed)); 90 uint32_t packed; 91 } usb_target_t; 47 typedef struct { 48 usb_address_t address; /**< Current USB address */ 49 uint8_t depth; /**< Depth in the hub hiearchy */ 50 usb_speed_t speed; /**< Speed of the device */ 51 devman_handle_t handle; /**< Handle to DDF function of the HC driver */ 52 /** Interface set by multi interface driver, -1 if none */ 53 int iface; 54 } usb_device_desc_t; 92 55 93 56 extern usb_dev_session_t *usb_dev_connect(devman_handle_t); … … 95 58 extern void usb_dev_disconnect(usb_dev_session_t *); 96 59 97 extern errno_t usb_get_my_interface(async_exch_t *, int *); 98 extern errno_t usb_get_my_device_handle(async_exch_t *, devman_handle_t *); 99 100 extern errno_t usb_reserve_default_address(async_exch_t *, usb_speed_t); 101 extern errno_t usb_release_default_address(async_exch_t *); 102 103 extern errno_t usb_device_enumerate(async_exch_t *, unsigned port); 104 extern errno_t usb_device_remove(async_exch_t *, unsigned port); 105 106 extern errno_t usb_register_endpoint(async_exch_t *, usb_endpoint_t, 107 usb_transfer_type_t, usb_direction_t, size_t, unsigned, unsigned); 108 extern errno_t usb_unregister_endpoint(async_exch_t *, usb_endpoint_t, 109 usb_direction_t); 110 extern errno_t usb_read(async_exch_t *, usb_endpoint_t, uint64_t, void *, size_t, 111 size_t *); 112 extern errno_t usb_write(async_exch_t *, usb_endpoint_t, uint64_t, const void *, 113 size_t); 114 115 /** Callback for outgoing transfer. */ 116 typedef void (*usb_iface_transfer_out_callback_t)(errno_t, void *); 117 118 /** Callback for incoming transfer. */ 119 typedef void (*usb_iface_transfer_in_callback_t)(errno_t, size_t, void *); 60 extern errno_t usb_get_my_description(async_exch_t *, usb_device_desc_t *); 120 61 121 62 /** USB device communication interface. */ 122 63 typedef struct { 123 errno_t (*get_my_interface)(ddf_fun_t *, int *); 124 errno_t (*get_my_device_handle)(ddf_fun_t *, devman_handle_t *); 125 126 errno_t (*reserve_default_address)(ddf_fun_t *, usb_speed_t); 127 errno_t (*release_default_address)(ddf_fun_t *); 128 129 errno_t (*device_enumerate)(ddf_fun_t *, unsigned); 130 errno_t (*device_remove)(ddf_fun_t *, unsigned); 131 132 errno_t (*register_endpoint)(ddf_fun_t *, usb_endpoint_t, 133 usb_transfer_type_t, usb_direction_t, size_t, unsigned, unsigned); 134 errno_t (*unregister_endpoint)(ddf_fun_t *, usb_endpoint_t, 135 usb_direction_t); 136 137 errno_t (*read)(ddf_fun_t *, usb_endpoint_t, uint64_t, uint8_t *, size_t, 138 usb_iface_transfer_in_callback_t, void *); 139 errno_t (*write)(ddf_fun_t *, usb_endpoint_t, uint64_t, const uint8_t *, 140 size_t, usb_iface_transfer_out_callback_t, void *); 64 errno_t (*get_my_description)(ddf_fun_t *, usb_device_desc_t *); 141 65 } usb_iface_t; 142 66 -
uspace/lib/drv/include/usbhc_iface.h
rf5e5f73 rdf6ded8 1 1 /* 2 2 * Copyright (c) 2010 Vojtech Horky 3 * Copyright (c) 201 1 Jan Vesely3 * Copyright (c) 2017 Ondrej Hlavaty 4 4 * All rights reserved. 5 5 * … … 32 32 * @{ 33 33 */ 34 35 34 /** @file 36 * @brief USB host controller interface definition. 35 * @brief USB host controler interface definition. This is the interface of 36 * USB host controller function, which can be used by usb device drivers. 37 37 */ 38 38 … … 41 41 42 42 #include "ddf/driver.h" 43 #include <usb_iface.h> 44 #include <stdbool.h> 45 46 extern errno_t usbhc_read(async_exch_t *, usb_address_t, usb_endpoint_t, 47 uint64_t, void *, size_t, size_t *); 48 extern errno_t usbhc_write(async_exch_t *, usb_address_t, usb_endpoint_t, 49 uint64_t, const void *, size_t); 50 51 /** Callback for outgoing transfer. */ 52 typedef void (*usbhc_iface_transfer_out_callback_t)(errno_t, void *); 53 54 /** Callback for incoming transfer. */ 55 typedef void (*usbhc_iface_transfer_in_callback_t)(errno_t, size_t, void *); 56 57 /** USB host controller communication interface. */ 43 #include <async.h> 44 45 /** USB speeds. */ 46 typedef enum { 47 /** USB 1.1 low speed (1.5Mbits/s). */ 48 USB_SPEED_LOW, 49 /** USB 1.1 full speed (12Mbits/s). */ 50 USB_SPEED_FULL, 51 /** USB 2.0 high speed (480Mbits/s). */ 52 USB_SPEED_HIGH, 53 /** USB 3.0 super speed (5Gbits/s). */ 54 USB_SPEED_SUPER, 55 /** Psuedo-speed serving as a boundary. */ 56 USB_SPEED_MAX 57 } usb_speed_t; 58 59 /** USB endpoint number type. 60 * Negative values could be used to indicate error. 61 */ 62 typedef uint16_t usb_endpoint_t; 63 64 /** USB address type. 65 * Negative values could be used to indicate error. 66 */ 67 typedef uint16_t usb_address_t; 68 69 /** 70 * USB Stream ID type. 71 */ 72 typedef uint16_t usb_stream_t; 73 74 /** USB transfer type. */ 75 typedef enum { 76 USB_TRANSFER_CONTROL = 0, 77 USB_TRANSFER_ISOCHRONOUS = 1, 78 USB_TRANSFER_BULK = 2, 79 USB_TRANSFER_INTERRUPT = 3, 80 } usb_transfer_type_t; 81 82 #define USB_TRANSFER_COUNT (USB_TRANSFER_INTERRUPT + 1) 83 84 /** USB data transfer direction. */ 85 typedef enum { 86 USB_DIRECTION_IN, 87 USB_DIRECTION_OUT, 88 USB_DIRECTION_BOTH, 89 } usb_direction_t; 90 91 #define USB_DIRECTION_COUNT (USB_DIRECTION_BOTH + 1) 92 93 /** USB complete address type. 94 * Pair address + endpoint is identification of transaction recipient. 95 */ 96 typedef union { 97 struct { 98 usb_address_t address; 99 usb_endpoint_t endpoint; 100 usb_stream_t stream; 101 } __attribute__((packed)); 102 uint64_t packed; 103 } usb_target_t; 104 105 // FIXME: DMA buffers shall be part of libdrv anyway. 106 typedef uintptr_t dma_policy_t; 107 108 typedef struct dma_buffer { 109 void *virt; 110 dma_policy_t policy; 111 } dma_buffer_t; 112 113 typedef struct usb_pipe_desc { 114 /** Endpoint number. */ 115 usb_endpoint_t endpoint_no; 116 117 /** Endpoint transfer type. */ 118 usb_transfer_type_t transfer_type; 119 120 /** Endpoint direction. */ 121 usb_direction_t direction; 122 123 /** 124 * Maximum size of one transfer. Non-periodic endpoints may handle 125 * bigger transfers, but those can be split into multiple USB transfers. 126 */ 127 size_t max_transfer_size; 128 129 /** Constraints on buffers to be transferred without copying */ 130 dma_policy_t transfer_buffer_policy; 131 } usb_pipe_desc_t; 132 133 typedef struct usb_pipe_transfer_request { 134 usb_direction_t dir; 135 usb_endpoint_t endpoint; 136 usb_stream_t stream; 137 138 uint64_t setup; /**< Valid iff the transfer is of control type */ 139 140 /** 141 * The DMA buffer to share. Must be at least offset + size large. Is 142 * patched after being transmitted over IPC, so the pointer is still 143 * valid. 144 */ 145 dma_buffer_t buffer; 146 size_t offset; /**< Offset to the buffer */ 147 size_t size; /**< Requested size. */ 148 } usbhc_iface_transfer_request_t; 149 150 /** This structure follows standard endpoint descriptor + superspeed companion 151 * descriptor, and exists to avoid dependency of libdrv on libusb. Keep the 152 * internal fields named exactly like their source (because we want to use the 153 * same macros to access them). 154 * Callers shall fill it with bare contents of respective descriptors (in usb endianity). 155 */ 156 typedef struct usb_endpoint_descriptors { 157 struct { 158 uint8_t endpoint_address; 159 uint8_t attributes; 160 uint16_t max_packet_size; 161 uint8_t poll_interval; 162 } endpoint; 163 164 /* Superspeed companion descriptor */ 165 struct companion_desc_t { 166 uint8_t max_burst; 167 uint8_t attributes; 168 uint16_t bytes_per_interval; 169 } companion; 170 } usb_endpoint_descriptors_t; 171 172 extern errno_t usbhc_reserve_default_address(async_exch_t *); 173 extern errno_t usbhc_release_default_address(async_exch_t *); 174 175 extern errno_t usbhc_device_enumerate(async_exch_t *, unsigned, usb_speed_t); 176 extern errno_t usbhc_device_remove(async_exch_t *, unsigned); 177 178 extern errno_t usbhc_register_endpoint(async_exch_t *, usb_pipe_desc_t *, const usb_endpoint_descriptors_t *); 179 extern errno_t usbhc_unregister_endpoint(async_exch_t *, const usb_pipe_desc_t *); 180 181 extern errno_t usbhc_transfer(async_exch_t *, const usbhc_iface_transfer_request_t *, size_t *); 182 183 /** Callback for outgoing transfer */ 184 typedef errno_t (*usbhc_iface_transfer_callback_t)(void *, int, size_t); 185 186 /** USB device communication interface. */ 58 187 typedef struct { 59 errno_t (*read)(ddf_fun_t *, usb_target_t, uint64_t, uint8_t *, size_t, 60 usbhc_iface_transfer_in_callback_t, void *); 61 errno_t (*write)(ddf_fun_t *, usb_target_t, uint64_t, const uint8_t *, 62 size_t, usbhc_iface_transfer_out_callback_t, void *); 188 errno_t (*default_address_reservation)(ddf_fun_t *, bool); 189 190 errno_t (*device_enumerate)(ddf_fun_t *, unsigned, usb_speed_t); 191 errno_t (*device_remove)(ddf_fun_t *, unsigned); 192 193 errno_t (*register_endpoint)(ddf_fun_t *, usb_pipe_desc_t *, const usb_endpoint_descriptors_t *); 194 errno_t (*unregister_endpoint)(ddf_fun_t *, const usb_pipe_desc_t *); 195 196 errno_t (*transfer)(ddf_fun_t *, const usbhc_iface_transfer_request_t *, 197 usbhc_iface_transfer_callback_t, void *); 63 198 } usbhc_iface_t; 64 65 199 66 200 #endif
Note:
See TracChangeset
for help on using the changeset viewer.