Changes in uspace/lib/drv/generic/remote_usbhc.c [41df71f9:99172baf] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/drv/generic/remote_usbhc.c
r41df71f9 r99172baf 1 1 /* 2 * Copyright (c) 2010 Vojtech Horky2 * Copyright (c) 2010-2011 Vojtech Horky 3 3 * Copyright (c) 2011 Jan Vesely 4 * Copyright (c) 2017 Ondrej Hlavaty5 4 * All rights reserved. 6 5 * … … 36 35 37 36 #include <async.h> 37 #include <errno.h> 38 #include <assert.h> 38 39 #include <macros.h> 39 #include <errno.h>40 #include <devman.h>41 #include <usb/host/usb_transfer_batch.h>42 40 43 41 #include "usbhc_iface.h" 44 42 #include "ddf/driver.h" 45 43 46 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 */ 47 86 typedef enum { 48 IPC_M_USB_RESERVE_DEFAULT_ADDRESS, 49 IPC_M_USB_RELEASE_DEFAULT_ADDRESS, 50 IPC_M_USB_DEVICE_ENUMERATE, 51 IPC_M_USB_DEVICE_REMOVE, 52 IPC_M_USB_REGISTER_ENDPOINT, 53 IPC_M_USB_UNREGISTER_ENDPOINT, 54 IPC_M_USB_READ, 55 IPC_M_USB_WRITE, 87 /** Asks for address assignment by host controller. 88 * Answer: 89 * - ELIMIT - host controller run out of address 90 * - EOK - address assigned 91 * Answer arguments: 92 * - assigned address 93 * 94 * The address must be released by via IPC_M_USBHC_RELEASE_ADDRESS. 95 */ 96 IPC_M_USBHC_REQUEST_ADDRESS, 97 98 /** Bind USB address with devman handle. 99 * Parameters: 100 * - USB address 101 * - devman handle 102 * Answer: 103 * - EOK - address binded 104 * - ENOENT - address is not in use 105 */ 106 IPC_M_USBHC_BIND_ADDRESS, 107 108 /** Get handle binded with given USB address. 109 * Parameters 110 * - USB address 111 * Answer: 112 * - EOK - address binded, first parameter is the devman handle 113 * - ENOENT - address is not in use at the moment 114 */ 115 IPC_M_USBHC_GET_HANDLE_BY_ADDRESS, 116 117 /** Release address in use. 118 * Arguments: 119 * - address to be released 120 * Answer: 121 * - ENOENT - address not in use 122 * - EPERM - trying to release default USB address 123 */ 124 IPC_M_USBHC_RELEASE_ADDRESS, 125 126 /** Register endpoint attributes at host controller. 127 * This is used to reserve portion of USB bandwidth. 128 * When speed is invalid, speed of the device is used. 129 * Parameters: 130 * - USB address + endpoint number 131 * - packed as ADDR << 16 + EP 132 * - speed + transfer type + direction 133 * - packed as ( SPEED << 8 + TYPE ) << 8 + DIR 134 * - maximum packet size + interval (in milliseconds) 135 * - packed as MPS << 16 + INT 136 * Answer: 137 * - EOK - reservation successful 138 * - ELIMIT - not enough bandwidth to satisfy the request 139 */ 140 IPC_M_USBHC_REGISTER_ENDPOINT, 141 142 /** Revert endpoint registration. 143 * Parameters: 144 * - USB address 145 * - endpoint number 146 * - data direction 147 * Answer: 148 * - EOK - endpoint unregistered 149 * - ENOENT - unknown endpoint 150 */ 151 IPC_M_USBHC_UNREGISTER_ENDPOINT, 152 153 /** Get data from device. 154 * See explanation at usb_iface_funcs_t (IN transaction). 155 */ 156 IPC_M_USBHC_READ, 157 158 /** Send data to device. 159 * See explanation at usb_iface_funcs_t (OUT transaction). 160 */ 161 IPC_M_USBHC_WRITE, 56 162 } usbhc_iface_funcs_t; 57 163 58 /** Reserve default USB address. 59 * @param[in] exch IPC communication exchange 60 * @param[in] speed Communication speed of the newly attached device 61 * @return Error code. 62 */ 63 int usbhc_reserve_default_address(async_exch_t *exch, usb_speed_t speed) 164 int usbhc_request_address(async_exch_t *exch, usb_address_t *address, 165 bool strict, usb_speed_t speed) 166 { 167 if (!exch || !address) 168 return EBADMEM; 169 sysarg_t new_address; 170 const int ret = async_req_4_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 171 IPC_M_USBHC_REQUEST_ADDRESS, *address, strict, speed, &new_address); 172 if (ret == EOK) 173 *address = (usb_address_t)new_address; 174 return ret; 175 } 176 177 int usbhc_bind_address(async_exch_t *exch, usb_address_t address, 178 devman_handle_t handle) 64 179 { 65 180 if (!exch) 66 181 return EBADMEM; 182 return async_req_3_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 183 IPC_M_USBHC_BIND_ADDRESS, address, handle); 184 } 185 186 int usbhc_get_handle(async_exch_t *exch, usb_address_t address, 187 devman_handle_t *handle) 188 { 189 if (!exch) 190 return EBADMEM; 191 sysarg_t h; 192 const int ret = async_req_2_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 193 IPC_M_USBHC_GET_HANDLE_BY_ADDRESS, address, &h); 194 if (ret == EOK && handle) 195 *handle = (devman_handle_t)h; 196 return ret; 197 } 198 199 int usbhc_release_address(async_exch_t *exch, usb_address_t address) 200 { 201 if (!exch) 202 return EBADMEM; 67 203 return async_req_2_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 68 IPC_M_USB_RESERVE_DEFAULT_ADDRESS, speed); 69 } 70 71 /** Release default USB address. 72 * 73 * @param[in] exch IPC communication exchange 74 * 75 * @return Error code. 76 * 77 */ 78 int usbhc_release_default_address(async_exch_t *exch) 204 IPC_M_USBHC_RELEASE_ADDRESS, address); 205 } 206 207 int usbhc_register_endpoint(async_exch_t *exch, usb_address_t address, 208 usb_endpoint_t endpoint, usb_transfer_type_t type, 209 usb_direction_t direction, size_t mps, unsigned interval) 79 210 { 80 211 if (!exch) 81 212 return EBADMEM; 82 return async_req_1_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),83 IPC_M_USB_RELEASE_DEFAULT_ADDRESS);84 } 85 86 /** Trigger USB device enumeration 87 * 88 * @param[in] exch IPC communication exchange 89 * @param[out] handle Identifier of the newly added device (if successful) 90 * 91 * @return Error code. 92 * 93 */ 94 int usbhc_device_enumerate(async_exch_t *exch, unsigned port)213 const usb_target_t target = 214 {{ .address = address, .endpoint = endpoint }}; 215 #define _PACK2(high, low) (((high & 0xffff) << 16) | (low & 0xffff)) 216 217 return async_req_4_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 218 IPC_M_USBHC_REGISTER_ENDPOINT, target.packed, 219 _PACK2(type, direction), _PACK2(mps, interval)); 220 221 #undef _PACK2 222 } 223 224 int usbhc_unregister_endpoint(async_exch_t *exch, usb_address_t address, 225 usb_endpoint_t endpoint, usb_direction_t direction) 95 226 { 96 227 if (!exch) 97 228 return EBADMEM; 98 const int ret = async_req_2_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 99 IPC_M_USB_DEVICE_ENUMERATE, port); 100 return ret; 101 } 102 103 /** Trigger USB device enumeration 104 * 105 * @param[in] exch IPC communication exchange 106 * @param[in] handle Identifier of the device 107 * 108 * @return Error code. 109 * 110 */ 111 int usbhc_device_remove(async_exch_t *exch, unsigned port) 112 { 113 if (!exch) 114 return EBADMEM; 115 return async_req_2_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 116 IPC_M_USB_DEVICE_REMOVE, port); 117 } 118 119 int static_assert[sizeof(sysarg_t) >= 4 ? 1 : -1]; 120 typedef union { 121 uint8_t arr[sizeof(sysarg_t)]; 122 sysarg_t arg; 123 } pack8_t; 124 125 int usbhc_register_endpoint(async_exch_t *exch, 126 usb_endpoint_desc_t *endpoint_desc) 127 { 128 if (!exch) 129 return EBADMEM; 130 131 aid_t opening_request = async_send_1(exch, 132 DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USB_REGISTER_ENDPOINT, NULL); 133 134 if (opening_request == 0) { 135 return ENOMEM; 136 } 137 138 const int ret = async_data_write_start(exch, (void *) endpoint_desc, 139 sizeof(usb_endpoint_desc_t)); 140 141 if (ret != EOK) { 142 async_forget(opening_request); 143 return ret; 144 } 145 146 /* Wait for the answer. */ 147 sysarg_t opening_request_rc; 148 async_wait_for(opening_request, &opening_request_rc); 149 150 return (int) opening_request_rc; 151 } 152 153 int usbhc_unregister_endpoint(async_exch_t *exch, 154 usb_endpoint_desc_t *endpoint_desc) 155 { 156 if (!exch) 157 return EBADMEM; 158 159 aid_t opening_request = async_send_1(exch, 160 DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USB_UNREGISTER_ENDPOINT, NULL); 161 162 if (opening_request == 0) { 163 return ENOMEM; 164 } 165 166 const int ret = async_data_write_start(exch, endpoint_desc, 167 sizeof(usb_endpoint_desc_t)); 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) 229 return async_req_4_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 230 IPC_M_USBHC_UNREGISTER_ENDPOINT, address, endpoint, direction); 231 } 232 233 int usbhc_read(async_exch_t *exch, usb_address_t address, 234 usb_endpoint_t endpoint, uint64_t setup, void *data, size_t size, 235 size_t *rec_size) 182 236 { 183 237 if (!exch) … … 187 241 return EOK; 188 242 243 const usb_target_t target = 244 {{ .address = address, .endpoint = endpoint }}; 245 189 246 /* Make call identifying target USB device and type of transfer. */ 190 247 aid_t opening_request = async_send_4(exch, 191 DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USB_READ, endpoint, 248 DEV_IFACE_ID(USBHC_DEV_IFACE), 249 IPC_M_USBHC_READ, target.packed, 192 250 (setup & UINT32_MAX), (setup >> 32), NULL); 193 251 … … 229 287 } 230 288 231 int usbhc_write(async_exch_t *exch, usb_ endpoint_t endpoint, uint64_t setup,232 const void *data, size_t size)289 int usbhc_write(async_exch_t *exch, usb_address_t address, 290 usb_endpoint_t endpoint, uint64_t setup, const void *data, size_t size) 233 291 { 234 292 if (!exch) … … 238 296 return EOK; 239 297 240 aid_t opening_request = async_send_5(exch, 241 DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USB_WRITE, endpoint, size, 298 const usb_target_t target = 299 {{ .address = address, .endpoint = endpoint }}; 300 301 aid_t opening_request = async_send_5(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 302 IPC_M_USBHC_WRITE, target.packed, size, 242 303 (setup & UINT32_MAX), (setup >> 32), NULL); 243 304 … … 262 323 } 263 324 264 static void remote_usbhc_reserve_default_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 265 static void remote_usbhc_release_default_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 266 static void remote_usbhc_device_enumerate(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 267 static void remote_usbhc_device_remove(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 325 326 static void remote_usbhc_request_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 327 static void remote_usbhc_bind_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 328 static void remote_usbhc_get_handle(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 329 static void remote_usbhc_release_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 268 330 static void remote_usbhc_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 269 331 static void remote_usbhc_unregister_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 270 static void remote_usbhc_read(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call); 271 static void remote_usbhc_write(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call); 272 273 /** Remote USB interface operations. */ 274 static const remote_iface_func_ptr_t remote_usbhc_iface_ops [] = { 275 [IPC_M_USB_RESERVE_DEFAULT_ADDRESS] = remote_usbhc_reserve_default_address, 276 [IPC_M_USB_RELEASE_DEFAULT_ADDRESS] = remote_usbhc_release_default_address, 277 [IPC_M_USB_DEVICE_ENUMERATE] = remote_usbhc_device_enumerate, 278 [IPC_M_USB_DEVICE_REMOVE] = remote_usbhc_device_remove, 279 [IPC_M_USB_REGISTER_ENDPOINT] = remote_usbhc_register_endpoint, 280 [IPC_M_USB_UNREGISTER_ENDPOINT] = remote_usbhc_unregister_endpoint, 281 [IPC_M_USB_READ] = remote_usbhc_read, 282 [IPC_M_USB_WRITE] = remote_usbhc_write, 332 static void remote_usbhc_read(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 333 static void remote_usbhc_write(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 334 //static void remote_usbhc(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 335 336 /** Remote USB host controller interface operations. */ 337 static const remote_iface_func_ptr_t remote_usbhc_iface_ops[] = { 338 [IPC_M_USBHC_REQUEST_ADDRESS] = remote_usbhc_request_address, 339 [IPC_M_USBHC_RELEASE_ADDRESS] = remote_usbhc_release_address, 340 [IPC_M_USBHC_BIND_ADDRESS] = remote_usbhc_bind_address, 341 [IPC_M_USBHC_GET_HANDLE_BY_ADDRESS] = remote_usbhc_get_handle, 342 343 [IPC_M_USBHC_REGISTER_ENDPOINT] = remote_usbhc_register_endpoint, 344 [IPC_M_USBHC_UNREGISTER_ENDPOINT] = remote_usbhc_unregister_endpoint, 345 346 [IPC_M_USBHC_READ] = remote_usbhc_read, 347 [IPC_M_USBHC_WRITE] = remote_usbhc_write, 283 348 }; 284 349 285 /** Remote USB interface structure.350 /** Remote USB host controller interface structure. 286 351 */ 287 352 const remote_iface_t remote_usbhc_iface = { 288 353 .method_count = ARRAY_SIZE(remote_usbhc_iface_ops), 289 .methods = remote_usbhc_iface_ops ,354 .methods = remote_usbhc_iface_ops 290 355 }; 291 356 … … 296 361 } async_transaction_t; 297 362 298 void remote_usbhc_reserve_default_address(ddf_fun_t *fun, void *iface, 363 static void async_transaction_destroy(async_transaction_t *trans) 364 { 365 if (trans == NULL) 366 return; 367 368 if (trans->buffer != NULL) 369 free(trans->buffer); 370 371 free(trans); 372 } 373 374 static async_transaction_t *async_transaction_create(ipc_callid_t caller) 375 { 376 async_transaction_t *trans = malloc(sizeof(async_transaction_t)); 377 if (trans == NULL) { 378 return NULL; 379 } 380 381 trans->caller = caller; 382 trans->data_caller = 0; 383 trans->buffer = NULL; 384 385 return trans; 386 } 387 388 void remote_usbhc_request_address(ddf_fun_t *fun, void *iface, 299 389 ipc_callid_t callid, ipc_call_t *call) 300 390 { 301 const usbhc_iface_t *usbhc_iface = (usbhc_iface_t *) iface; 302 303 if (usbhc_iface->reserve_default_address == NULL) { 304 async_answer_0(callid, ENOTSUP); 305 return; 306 } 307 308 usb_speed_t speed = DEV_IPC_GET_ARG1(*call); 309 const int ret = usbhc_iface->reserve_default_address(fun, speed); 391 const usbhc_iface_t *usb_iface = iface; 392 393 if (!usb_iface->request_address) { 394 async_answer_0(callid, ENOTSUP); 395 return; 396 } 397 398 usb_address_t address = DEV_IPC_GET_ARG1(*call); 399 const bool strict = DEV_IPC_GET_ARG2(*call); 400 const usb_speed_t speed = DEV_IPC_GET_ARG3(*call); 401 402 const int rc = usb_iface->request_address(fun, &address, strict, speed); 403 if (rc != EOK) { 404 async_answer_0(callid, rc); 405 } else { 406 async_answer_1(callid, EOK, (sysarg_t) address); 407 } 408 } 409 410 void remote_usbhc_bind_address(ddf_fun_t *fun, void *iface, 411 ipc_callid_t callid, ipc_call_t *call) 412 { 413 const usbhc_iface_t *usb_iface = iface; 414 415 if (!usb_iface->bind_address) { 416 async_answer_0(callid, ENOTSUP); 417 return; 418 } 419 420 const usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call); 421 const devman_handle_t handle = (devman_handle_t) DEV_IPC_GET_ARG2(*call); 422 423 const int ret = usb_iface->bind_address(fun, address, handle); 310 424 async_answer_0(callid, ret); 311 425 } 312 426 313 void remote_usbhc_ release_default_address(ddf_fun_t *fun, void *iface,427 void remote_usbhc_get_handle(ddf_fun_t *fun, void *iface, 314 428 ipc_callid_t callid, ipc_call_t *call) 315 429 { 316 const usbhc_iface_t *usbhc_iface = (usbhc_iface_t *) iface; 317 318 if (usbhc_iface->release_default_address == NULL) { 319 async_answer_0(callid, ENOTSUP); 320 return; 321 } 322 323 const int ret = usbhc_iface->release_default_address(fun); 430 const usbhc_iface_t *usb_iface = iface; 431 432 if (!usb_iface->get_handle) { 433 async_answer_0(callid, ENOTSUP); 434 return; 435 } 436 437 const usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call); 438 devman_handle_t handle; 439 const int ret = usb_iface->get_handle(fun, address, &handle); 440 441 if (ret == EOK) { 442 async_answer_1(callid, ret, handle); 443 } else { 444 async_answer_0(callid, ret); 445 } 446 } 447 448 void remote_usbhc_release_address(ddf_fun_t *fun, void *iface, 449 ipc_callid_t callid, ipc_call_t *call) 450 { 451 const usbhc_iface_t *usb_iface = iface; 452 453 if (!usb_iface->release_address) { 454 async_answer_0(callid, ENOTSUP); 455 return; 456 } 457 458 const usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call); 459 460 const int ret = usb_iface->release_address(fun, address); 324 461 async_answer_0(callid, ret); 325 462 } 326 463 327 static void remote_usbhc_device_enumerate(ddf_fun_t *fun, void *iface, 464 static void callback_out(ddf_fun_t *fun, 465 int outcome, void *arg) 466 { 467 async_transaction_t *trans = arg; 468 469 async_answer_0(trans->caller, outcome); 470 471 async_transaction_destroy(trans); 472 } 473 474 static void callback_in(ddf_fun_t *fun, 475 int outcome, size_t actual_size, void *arg) 476 { 477 async_transaction_t *trans = (async_transaction_t *)arg; 478 479 if (outcome != EOK) { 480 async_answer_0(trans->caller, outcome); 481 if (trans->data_caller) { 482 async_answer_0(trans->data_caller, EINTR); 483 } 484 async_transaction_destroy(trans); 485 return; 486 } 487 488 if (trans->data_caller) { 489 async_data_read_finalize(trans->data_caller, 490 trans->buffer, actual_size); 491 } 492 493 async_answer_0(trans->caller, EOK); 494 495 async_transaction_destroy(trans); 496 } 497 498 void remote_usbhc_register_endpoint(ddf_fun_t *fun, void *iface, 328 499 ipc_callid_t callid, ipc_call_t *call) 329 500 { 330 const usbhc_iface_t *usbhc_iface = (usbhc_iface_t *) iface; 331 332 if (usbhc_iface->device_enumerate == NULL) { 333 async_answer_0(callid, ENOTSUP); 334 return; 335 } 336 337 const unsigned port = DEV_IPC_GET_ARG1(*call); 338 const int ret = usbhc_iface->device_enumerate(fun, port); 339 async_answer_0(callid, ret); 340 } 341 342 static void remote_usbhc_device_remove(ddf_fun_t *fun, void *iface, 501 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 502 503 if (!usb_iface->register_endpoint) { 504 async_answer_0(callid, ENOTSUP); 505 return; 506 } 507 508 #define _INIT_FROM_HIGH_DATA2(type, var, arg_no) \ 509 type var = (type) (DEV_IPC_GET_ARG##arg_no(*call) >> 16) 510 #define _INIT_FROM_LOW_DATA2(type, var, arg_no) \ 511 type var = (type) (DEV_IPC_GET_ARG##arg_no(*call) & 0xffff) 512 513 const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) }; 514 515 _INIT_FROM_HIGH_DATA2(usb_transfer_type_t, transfer_type, 2); 516 _INIT_FROM_LOW_DATA2(usb_direction_t, direction, 2); 517 518 _INIT_FROM_HIGH_DATA2(size_t, max_packet_size, 3); 519 _INIT_FROM_LOW_DATA2(unsigned int, interval, 3); 520 521 #undef _INIT_FROM_HIGH_DATA2 522 #undef _INIT_FROM_LOW_DATA2 523 524 int rc = usb_iface->register_endpoint(fun, target.address, 525 target.endpoint, transfer_type, direction, max_packet_size, interval); 526 527 async_answer_0(callid, rc); 528 } 529 530 void remote_usbhc_unregister_endpoint(ddf_fun_t *fun, void *iface, 343 531 ipc_callid_t callid, ipc_call_t *call) 344 532 { 345 const usbhc_iface_t *usbhc_iface = (usbhc_iface_t *) iface; 346 347 if (usbhc_iface->device_remove == NULL) { 348 async_answer_0(callid, ENOTSUP); 349 return; 350 } 351 352 const unsigned port = DEV_IPC_GET_ARG1(*call); 353 const int ret = usbhc_iface->device_remove(fun, port); 354 async_answer_0(callid, ret); 355 } 356 357 static void remote_usbhc_register_endpoint(ddf_fun_t *fun, void *iface, 358 ipc_callid_t callid, ipc_call_t *call) 533 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 534 535 if (!usb_iface->unregister_endpoint) { 536 async_answer_0(callid, ENOTSUP); 537 return; 538 } 539 540 usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call); 541 usb_endpoint_t endpoint = (usb_endpoint_t) DEV_IPC_GET_ARG2(*call); 542 usb_direction_t direction = (usb_direction_t) DEV_IPC_GET_ARG3(*call); 543 544 int rc = usb_iface->unregister_endpoint(fun, 545 address, endpoint, direction); 546 547 async_answer_0(callid, rc); 548 } 549 550 void remote_usbhc_read( 551 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call) 359 552 { 360 553 assert(fun); … … 362 555 assert(call); 363 556 364 const usbhc_iface_t *usbhc_iface = iface; 365 366 if (!usbhc_iface->register_endpoint) { 367 async_answer_0(callid, ENOTSUP); 368 return; 369 } 370 371 void *buffer = NULL; 372 size_t size = 0; 373 int rc = async_data_write_accept(&buffer, false, 374 sizeof(usb_endpoint_desc_t), sizeof(usb_endpoint_desc_t), 0, &size); 375 376 if (rc != EOK) { 377 free(buffer); 378 async_answer_0(callid, rc); 379 return; 380 } 381 382 usb_endpoint_desc_t *endpoint_desc = (usb_endpoint_desc_t *) buffer; 383 rc = usbhc_iface->register_endpoint(fun, endpoint_desc); 384 385 free(buffer); 386 async_answer_0(callid, rc); 387 } 388 389 static void remote_usbhc_unregister_endpoint(ddf_fun_t *fun, void *iface, 390 ipc_callid_t callid, ipc_call_t *call) 391 { 392 assert(fun); 393 assert(iface); 394 assert(call); 395 396 const usbhc_iface_t *usbhc_iface = iface; 397 398 if (!usbhc_iface->unregister_endpoint) { 399 async_answer_0(callid, ENOTSUP); 400 return; 401 } 402 403 void *buffer = NULL; 404 size_t size = 0; 405 int rc = async_data_write_accept(&buffer, false, 406 sizeof(usb_endpoint_desc_t), sizeof(usb_endpoint_desc_t), 0, &size); 407 408 if (rc != EOK) { 409 free(buffer); 410 async_answer_0(callid, rc); 411 return; 412 } 413 414 usb_endpoint_desc_t *endpoint_desc = (usb_endpoint_desc_t *) buffer; 415 usbhc_iface->unregister_endpoint(fun, endpoint_desc); 416 417 free(buffer); 418 async_answer_0(callid, rc); 419 } 420 421 static void async_transaction_destroy(async_transaction_t *trans) 422 { 423 if (trans == NULL) { 424 return; 425 } 426 if (trans->buffer != NULL) { 427 free(trans->buffer); 428 } 429 430 free(trans); 431 } 432 433 static async_transaction_t *async_transaction_create(ipc_callid_t caller) 434 { 435 async_transaction_t *trans = malloc(sizeof(async_transaction_t)); 436 if (trans == NULL) { 437 return NULL; 438 } 439 440 trans->caller = caller; 441 trans->data_caller = 0; 442 trans->buffer = NULL; 443 444 return trans; 445 } 446 447 static int callback_out(usb_transfer_batch_t *batch) 448 { 449 async_transaction_t *trans = batch->on_complete_data; 450 451 const int err = async_answer_0(trans->caller, batch->error); 452 453 async_transaction_destroy(trans); 454 455 return err; 456 } 457 458 static int callback_in(usb_transfer_batch_t *batch) 459 { 460 async_transaction_t *trans = batch->on_complete_data; 461 462 if (trans->data_caller) { 463 if (batch->error == EOK) { 464 batch->error = async_data_read_finalize(trans->data_caller, 465 trans->buffer, batch->transfered_size); 466 } else { 467 async_answer_0(trans->data_caller, EINTR); 468 } 469 } 470 471 const int err = async_answer_0(trans->caller, batch->error); 472 async_transaction_destroy(trans); 473 return err; 474 } 475 476 void remote_usbhc_read( 477 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call) 478 { 479 assert(fun); 480 assert(iface); 481 assert(call); 482 483 const usbhc_iface_t *usbhc_iface = iface; 484 485 if (!usbhc_iface->read) { 486 async_answer_0(callid, ENOTSUP); 487 return; 488 } 489 490 const usb_endpoint_t ep = DEV_IPC_GET_ARG1(*call); 557 const usbhc_iface_t *hc_iface = iface; 558 559 if (!hc_iface->read) { 560 async_answer_0(callid, ENOTSUP); 561 return; 562 } 563 564 const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) }; 491 565 const uint64_t setup = 492 566 ((uint64_t)DEV_IPC_GET_ARG2(*call)) | … … 502 576 if (!async_data_read_receive(&trans->data_caller, &size)) { 503 577 async_answer_0(callid, EPARTY); 504 async_transaction_destroy(trans);505 578 return; 506 579 } … … 514 587 } 515 588 516 const usb_target_t target = {{ 517 /* .address is initialized by read itself */ 518 .endpoint = ep, 519 }}; 520 521 const int rc = usbhc_iface->read( 589 const int rc = hc_iface->read( 522 590 fun, target, setup, trans->buffer, size, callback_in, trans); 523 591 … … 536 604 assert(call); 537 605 538 const usbhc_iface_t * usbhc_iface = iface;539 540 if (! usbhc_iface->write) {541 async_answer_0(callid, ENOTSUP); 542 return; 543 } 544 545 const usb_ endpoint_t ep = DEV_IPC_GET_ARG1(*call);606 const usbhc_iface_t *hc_iface = iface; 607 608 if (!hc_iface->write) { 609 async_answer_0(callid, ENOTSUP); 610 return; 611 } 612 613 const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) }; 546 614 const size_t data_buffer_len = DEV_IPC_GET_ARG2(*call); 547 615 const uint64_t setup = … … 558 626 if (data_buffer_len > 0) { 559 627 const int rc = async_data_write_accept(&trans->buffer, false, 560 1, data_buffer_len, 0, &size); 628 1, USB_MAX_PAYLOAD_SIZE, 629 0, &size); 561 630 562 631 if (rc != EOK) { … … 567 636 } 568 637 569 const usb_target_t target = {{ 570 /* .address is initialized by write itself */ 571 .endpoint = ep, 572 }}; 573 574 const int rc = usbhc_iface->write( 638 const int rc = hc_iface->write( 575 639 fun, target, setup, trans->buffer, size, callback_out, trans); 576 640
Note:
See TracChangeset
for help on using the changeset viewer.