Changes in uspace/lib/drv/generic/remote_usbhc.c [25a179e:db51a6a6] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/drv/generic/remote_usbhc.c
r25a179e rdb51a6a6 1 1 /* 2 * Copyright (c) 2010 -2011Vojtech Horky2 * Copyright (c) 2010 Vojtech Horky 3 3 * Copyright (c) 2011 Jan Vesely 4 * Copyright (c) 2017 Ondrej Hlavaty 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> 40 41 41 42 #include "usbhc_iface.h" 42 43 #include "ddf/driver.h" 43 44 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 */ 45 86 46 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, 47 IPC_M_USB_DEFAULT_ADDRESS_RESERVATION, 48 IPC_M_USB_DEVICE_ENUMERATE, 49 IPC_M_USB_DEVICE_REMOVE, 50 IPC_M_USB_REGISTER_ENDPOINT, 51 IPC_M_USB_UNREGISTER_ENDPOINT, 52 IPC_M_USB_READ, 53 IPC_M_USB_WRITE, 96 54 } usbhc_iface_funcs_t; 97 55 98 int 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) 56 /** Reserve default USB address. 57 * @param[in] exch IPC communication exchange 58 * @return Error code. 59 */ 60 int 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 int 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 int usbhc_device_enumerate(async_exch_t *exch, unsigned port, usb_speed_t speed) 90 { 91 if (!exch) 92 return EBADMEM; 93 const int 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 int 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 int 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); 125 126 if (opening_request == 0) { 127 return ENOMEM; 128 } 129 130 int ret = async_data_write_start(exch, desc, sizeof(*desc)); 131 if (ret != EOK) { 132 async_forget(opening_request); 133 return ret; 134 } 135 136 /* Wait for the answer. */ 137 sysarg_t opening_request_rc; 138 async_wait_for(opening_request, &opening_request_rc); 139 140 if (opening_request_rc) 141 return (int) opening_request_rc; 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 152 return EOK; 153 } 154 155 int 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); 162 163 if (opening_request == 0) { 164 return ENOMEM; 165 } 166 167 const int 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 sysarg_t opening_request_rc; 175 async_wait_for(opening_request, &opening_request_rc); 176 177 return (int) opening_request_rc; 178 } 179 180 int usbhc_read(async_exch_t *exch, usb_endpoint_t endpoint, uint64_t setup, 181 void *data, size_t size, size_t *rec_size) 101 182 { 102 183 if (!exch) … … 106 187 return EOK; 107 188 108 const usb_target_t target =109 {{ .address = address, .endpoint = endpoint }};110 111 189 /* Make call identifying target USB device and type of transfer. */ 112 190 aid_t opening_request = async_send_4(exch, 113 DEV_IFACE_ID(USBHC_DEV_IFACE), 114 IPC_M_USBHC_READ, target.packed, 191 DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USB_READ, endpoint, 115 192 (setup & UINT32_MAX), (setup >> 32), NULL); 116 193 … … 131 208 132 209 /* Wait for the answer. */ 133 int data_request_rc;134 int opening_request_rc;210 sysarg_t data_request_rc; 211 sysarg_t opening_request_rc; 135 212 async_wait_for(data_request, &data_request_rc); 136 213 async_wait_for(opening_request, &opening_request_rc); … … 152 229 } 153 230 154 int usbhc_write(async_exch_t *exch, usb_ address_t address,155 usb_endpoint_t endpoint, uint64_t setup,const void *data, size_t size)231 int usbhc_write(async_exch_t *exch, usb_endpoint_t endpoint, uint64_t setup, 232 const void *data, size_t size) 156 233 { 157 234 if (!exch) … … 161 238 return EOK; 162 239 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, 240 aid_t opening_request = async_send_5(exch, 241 DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USB_WRITE, endpoint, size, 168 242 (setup & UINT32_MAX), (setup >> 32), NULL); 169 243 … … 182 256 183 257 /* Wait for the answer. */ 184 int opening_request_rc;258 sysarg_t opening_request_rc; 185 259 async_wait_for(opening_request, &opening_request_rc); 186 260 … … 188 262 } 189 263 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, 264 static void remote_usbhc_default_address_reservation(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 265 static void remote_usbhc_device_enumerate(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 266 static void remote_usbhc_device_remove(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 267 static void remote_usbhc_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 268 static void remote_usbhc_unregister_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 269 static void remote_usbhc_read(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call); 270 static void remote_usbhc_write(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call); 271 272 /** Remote USB interface operations. */ 273 static const remote_iface_func_ptr_t remote_usbhc_iface_ops [] = { 274 [IPC_M_USB_DEFAULT_ADDRESS_RESERVATION] = remote_usbhc_default_address_reservation, 275 [IPC_M_USB_DEVICE_ENUMERATE] = remote_usbhc_device_enumerate, 276 [IPC_M_USB_DEVICE_REMOVE] = remote_usbhc_device_remove, 277 [IPC_M_USB_REGISTER_ENDPOINT] = remote_usbhc_register_endpoint, 278 [IPC_M_USB_UNREGISTER_ENDPOINT] = remote_usbhc_unregister_endpoint, 279 [IPC_M_USB_READ] = remote_usbhc_read, 280 [IPC_M_USB_WRITE] = remote_usbhc_write, 197 281 }; 198 282 199 /** Remote USB host controllerinterface structure.283 /** Remote USB interface structure. 200 284 */ 201 285 const remote_iface_t remote_usbhc_iface = { 202 286 .method_count = ARRAY_SIZE(remote_usbhc_iface_ops), 203 .methods = remote_usbhc_iface_ops 287 .methods = remote_usbhc_iface_ops, 204 288 }; 205 289 … … 210 294 } async_transaction_t; 211 295 296 void remote_usbhc_default_address_reservation(ddf_fun_t *fun, void *iface, 297 ipc_callid_t callid, ipc_call_t *call) 298 { 299 const usbhc_iface_t *usbhc_iface = (usbhc_iface_t *) iface; 300 301 if (usbhc_iface->default_address_reservation == NULL) { 302 async_answer_0(callid, ENOTSUP); 303 return; 304 } 305 306 const bool reserve = IPC_GET_ARG2(*call); 307 const int ret = usbhc_iface->default_address_reservation(fun, reserve); 308 async_answer_0(callid, ret); 309 } 310 311 312 static void remote_usbhc_device_enumerate(ddf_fun_t *fun, void *iface, 313 ipc_callid_t callid, ipc_call_t *call) 314 { 315 const usbhc_iface_t *usbhc_iface = (usbhc_iface_t *) iface; 316 317 if (usbhc_iface->device_enumerate == NULL) { 318 async_answer_0(callid, ENOTSUP); 319 return; 320 } 321 322 const unsigned port = DEV_IPC_GET_ARG1(*call); 323 usb_speed_t speed = DEV_IPC_GET_ARG2(*call); 324 const int ret = usbhc_iface->device_enumerate(fun, port, speed); 325 async_answer_0(callid, ret); 326 } 327 328 static void remote_usbhc_device_remove(ddf_fun_t *fun, void *iface, 329 ipc_callid_t callid, ipc_call_t *call) 330 { 331 const usbhc_iface_t *usbhc_iface = (usbhc_iface_t *) iface; 332 333 if (usbhc_iface->device_remove == NULL) { 334 async_answer_0(callid, ENOTSUP); 335 return; 336 } 337 338 const unsigned port = DEV_IPC_GET_ARG1(*call); 339 const int ret = usbhc_iface->device_remove(fun, port); 340 async_answer_0(callid, ret); 341 } 342 343 static void remote_usbhc_register_endpoint(ddf_fun_t *fun, void *iface, 344 ipc_callid_t callid, ipc_call_t *call) 345 { 346 assert(fun); 347 assert(iface); 348 assert(call); 349 350 const usbhc_iface_t *usbhc_iface = iface; 351 352 if (!usbhc_iface->register_endpoint) { 353 async_answer_0(callid, ENOTSUP); 354 return; 355 } 356 357 usb_endpoint_descriptors_t ep_desc; 358 ipc_callid_t data_callid; 359 size_t len; 360 361 if (!async_data_write_receive(&data_callid, &len) 362 || len != sizeof(ep_desc)) { 363 async_answer_0(callid, EINVAL); 364 return; 365 } 366 async_data_write_finalize(data_callid, &ep_desc, sizeof(ep_desc)); 367 368 usb_pipe_desc_t pipe_desc; 369 370 const int rc = usbhc_iface->register_endpoint(fun, &pipe_desc, &ep_desc); 371 async_answer_0(callid, rc); 372 373 if (!async_data_read_receive(&data_callid, &len) 374 || len != sizeof(pipe_desc)) { 375 return; 376 } 377 async_data_read_finalize(data_callid, &pipe_desc, sizeof(pipe_desc)); 378 } 379 380 static void remote_usbhc_unregister_endpoint(ddf_fun_t *fun, void *iface, 381 ipc_callid_t callid, ipc_call_t *call) 382 { 383 assert(fun); 384 assert(iface); 385 assert(call); 386 387 const usbhc_iface_t *usbhc_iface = iface; 388 389 if (!usbhc_iface->unregister_endpoint) { 390 async_answer_0(callid, ENOTSUP); 391 return; 392 } 393 394 usb_pipe_desc_t pipe_desc; 395 ipc_callid_t data_callid; 396 size_t len; 397 398 if (!async_data_write_receive(&data_callid, &len) 399 || len != sizeof(pipe_desc)) { 400 async_answer_0(callid, EINVAL); 401 return; 402 } 403 async_data_write_finalize(data_callid, &pipe_desc, sizeof(pipe_desc)); 404 405 const int rc = usbhc_iface->unregister_endpoint(fun, &pipe_desc); 406 async_answer_0(callid, rc); 407 } 408 212 409 static void async_transaction_destroy(async_transaction_t *trans) 213 410 { 214 if (trans == NULL) 215 return; 216 217 if (trans->buffer != NULL) 411 if (trans == NULL) { 412 return; 413 } 414 if (trans->buffer != NULL) { 218 415 free(trans->buffer); 219 416 } 417 220 418 free(trans); 221 419 } … … 235 433 } 236 434 237 static void callback_out(int outcome, void *arg)435 static int callback_out(void *arg, int error, size_t transferred_size) 238 436 { 239 437 async_transaction_t *trans = arg; 240 438 241 async_answer_0(trans->caller, outcome);439 const int err = async_answer_0(trans->caller, error); 242 440 243 441 async_transaction_destroy(trans); 244 } 245 246 static void callback_in(int 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) { 442 443 return err; 444 } 445 446 static int callback_in(void *arg, int error, size_t transferred_size) 447 { 448 async_transaction_t *trans = arg; 449 450 if (trans->data_caller) { 451 if (error == EOK) { 452 error = async_data_read_finalize(trans->data_caller, 453 trans->buffer, transferred_size); 454 } else { 253 455 async_answer_0(trans->data_caller, EINTR); 254 456 } 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 457 } 458 459 const int err = async_answer_0(trans->caller, error); 266 460 async_transaction_destroy(trans); 461 return err; 267 462 } 268 463 … … 274 469 assert(call); 275 470 276 const usbhc_iface_t * hc_iface = iface;277 278 if (! hc_iface->read) {279 async_answer_0(callid, ENOTSUP); 280 return; 281 } 282 283 const usb_ target_t target = { .packed = DEV_IPC_GET_ARG1(*call) };471 const usbhc_iface_t *usbhc_iface = iface; 472 473 if (!usbhc_iface->read) { 474 async_answer_0(callid, ENOTSUP); 475 return; 476 } 477 478 const usb_endpoint_t ep = DEV_IPC_GET_ARG1(*call); 284 479 const uint64_t setup = 285 480 ((uint64_t)DEV_IPC_GET_ARG2(*call)) | … … 295 490 if (!async_data_read_receive(&trans->data_caller, &size)) { 296 491 async_answer_0(callid, EPARTY); 492 async_transaction_destroy(trans); 297 493 return; 298 494 } … … 306 502 } 307 503 308 const int rc = hc_iface->read( 504 const usb_target_t target = {{ 505 /* .address is initialized by read itself */ 506 .endpoint = ep, 507 }}; 508 509 const int rc = usbhc_iface->read( 309 510 fun, target, setup, trans->buffer, size, callback_in, trans); 310 511 … … 323 524 assert(call); 324 525 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) };526 const usbhc_iface_t *usbhc_iface = iface; 527 528 if (!usbhc_iface->write) { 529 async_answer_0(callid, ENOTSUP); 530 return; 531 } 532 533 const usb_endpoint_t ep = DEV_IPC_GET_ARG1(*call); 333 534 const size_t data_buffer_len = DEV_IPC_GET_ARG2(*call); 334 535 const uint64_t setup = … … 345 546 if (data_buffer_len > 0) { 346 547 const int rc = async_data_write_accept(&trans->buffer, false, 347 1, USB_MAX_PAYLOAD_SIZE, 348 0, &size); 548 1, data_buffer_len, 0, &size); 349 549 350 550 if (rc != EOK) { … … 355 555 } 356 556 357 const int rc = hc_iface->write( 557 const usb_target_t target = {{ 558 /* .address is initialized by write itself */ 559 .endpoint = ep, 560 /* streams are not given by the API call yet */ 561 .stream = 0, 562 }}; 563 564 const int rc = usbhc_iface->write( 358 565 fun, target, setup, trans->buffer, size, callback_out, trans); 359 566
Note:
See TracChangeset
for help on using the changeset viewer.