Changes in uspace/lib/drv/generic/remote_usbhc.c [272f46f8:27736cf] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/drv/generic/remote_usbhc.c
r272f46f8 r27736cf 1 1 /* 2 2 * Copyright (c) 2010-2011 Vojtech Horky 3 * Copyright (c) 2011 Jan Vesely4 3 * All rights reserved. 5 4 * … … 43 42 #define USB_MAX_PAYLOAD_SIZE 1020 44 43 45 /** IPC methods for communication with HC through DDF interface.46 *47 * Notes for async methods:48 *49 * Methods for sending data to device (OUT transactions)50 * - e.g. IPC_M_USBHC_INTERRUPT_OUT -51 * always use the same semantics:52 * - first, IPC call with given method is made53 * - argument #1 is target address54 * - argument #2 is target endpoint55 * - argument #3 is max packet size of the endpoint56 * - this call is immediately followed by IPC data write (from caller)57 * - the initial call (and the whole transaction) is answer after the58 * transaction is scheduled by the HC and acknowledged by the device59 * or immediately after error is detected60 * - the answer carries only the error code61 *62 * Methods for retrieving data from device (IN transactions)63 * - e.g. IPC_M_USBHC_INTERRUPT_IN -64 * also use the same semantics:65 * - first, IPC call with given method is made66 * - argument #1 is target address67 * - argument #2 is target endpoint68 * - this call is immediately followed by IPC data read (async version)69 * - the call is not answered until the device returns some data (or until70 * error occurs)71 *72 * Some special methods (NO-DATA transactions) do not send any data. These73 * might behave as both OUT or IN transactions because communication parts74 * where actual buffers are exchanged are omitted.75 **76 * For all these methods, wrap functions exists. Important rule: functions77 * for IN transactions have (as parameters) buffers where retrieved data78 * will be stored. These buffers must be already allocated and shall not be79 * touch until the transaction is completed80 * (e.g. not before calling usb_wait_for() with appropriate handle).81 * OUT transactions buffers can be freed immediately after call is dispatched82 * (i.e. after return from wrapping function).83 *84 */85 typedef enum {86 /** Asks for address assignment by host controller.87 * Answer:88 * - ELIMIT - host controller run out of address89 * - EOK - address assigned90 * Answer arguments:91 * - assigned address92 *93 * The address must be released by via IPC_M_USBHC_RELEASE_ADDRESS.94 */95 IPC_M_USBHC_REQUEST_ADDRESS,96 97 /** Bind USB address with devman handle.98 * Parameters:99 * - USB address100 * - devman handle101 * Answer:102 * - EOK - address binded103 * - ENOENT - address is not in use104 */105 IPC_M_USBHC_BIND_ADDRESS,106 107 /** Get handle binded with given USB address.108 * Parameters109 * - USB address110 * Answer:111 * - EOK - address binded, first parameter is the devman handle112 * - ENOENT - address is not in use at the moment113 */114 IPC_M_USBHC_GET_HANDLE_BY_ADDRESS,115 116 /** Release address in use.117 * Arguments:118 * - address to be released119 * Answer:120 * - ENOENT - address not in use121 * - EPERM - trying to release default USB address122 */123 IPC_M_USBHC_RELEASE_ADDRESS,124 125 /** Register endpoint attributes at host controller.126 * This is used to reserve portion of USB bandwidth.127 * When speed is invalid, speed of the device is used.128 * Parameters:129 * - USB address + endpoint number130 * - packed as ADDR << 16 + EP131 * - speed + transfer type + direction132 * - packed as ( SPEED << 8 + TYPE ) << 8 + DIR133 * - maximum packet size + interval (in milliseconds)134 * - packed as MPS << 16 + INT135 * Answer:136 * - EOK - reservation successful137 * - ELIMIT - not enough bandwidth to satisfy the request138 */139 IPC_M_USBHC_REGISTER_ENDPOINT,140 141 /** Revert endpoint registration.142 * Parameters:143 * - USB address144 * - endpoint number145 * - data direction146 * Answer:147 * - EOK - endpoint unregistered148 * - ENOENT - unknown endpoint149 */150 IPC_M_USBHC_UNREGISTER_ENDPOINT,151 152 /** Get data from device.153 * See explanation at usb_iface_funcs_t (IN transaction).154 */155 IPC_M_USBHC_READ,156 157 /** Send data to device.158 * See explanation at usb_iface_funcs_t (OUT transaction).159 */160 IPC_M_USBHC_WRITE,161 } usbhc_iface_funcs_t;162 163 int usbhc_request_address(async_exch_t *exch, usb_address_t *address,164 bool strict, usb_speed_t speed)165 {166 if (!exch || !address)167 return EINVAL;168 sysarg_t new_address;169 const int ret = async_req_4_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),170 IPC_M_USBHC_REQUEST_ADDRESS, *address, strict, speed, &new_address);171 if (ret == EOK)172 *address = (usb_address_t)new_address;173 return ret;174 }175 /*----------------------------------------------------------------------------*/176 int usbhc_bind_address(async_exch_t *exch, usb_address_t address,177 devman_handle_t handle)178 {179 if (!exch)180 return EINVAL;181 return async_req_3_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),182 IPC_M_USBHC_BIND_ADDRESS, address, handle);183 }184 /*----------------------------------------------------------------------------*/185 int usbhc_get_handle(async_exch_t *exch, usb_address_t address,186 devman_handle_t *handle)187 {188 if (!exch)189 return EINVAL;190 sysarg_t h;191 const int ret = async_req_2_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),192 IPC_M_USBHC_GET_HANDLE_BY_ADDRESS, address, &h);193 if (ret == EOK && handle)194 *handle = (devman_handle_t)h;195 return ret;196 }197 /*----------------------------------------------------------------------------*/198 int usbhc_release_address(async_exch_t *exch, usb_address_t address)199 {200 if (!exch)201 return EINVAL;202 return async_req_2_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),203 IPC_M_USBHC_RELEASE_ADDRESS, address);204 }205 /*----------------------------------------------------------------------------*/206 int usbhc_register_endpoint(async_exch_t *exch, usb_address_t address,207 usb_endpoint_t endpoint, usb_transfer_type_t type,208 usb_direction_t direction, size_t mps, unsigned interval)209 {210 if (!exch)211 return EINVAL;212 const usb_target_t target =213 {{ .address = address, .endpoint = endpoint }};214 #define _PACK2(high, low) (((high & 0xffff) << 16) | (low & 0xffff))215 216 return async_req_4_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),217 IPC_M_USBHC_REGISTER_ENDPOINT, target.packed,218 _PACK2(type, direction), _PACK2(mps, interval));219 220 #undef _PACK2221 }222 /*----------------------------------------------------------------------------*/223 int usbhc_unregister_endpoint(async_exch_t *exch, usb_address_t address,224 usb_endpoint_t endpoint, usb_direction_t direction)225 {226 if (!exch)227 return EINVAL;228 return async_req_4_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),229 IPC_M_USBHC_UNREGISTER_ENDPOINT, address, endpoint, direction);230 }231 /*----------------------------------------------------------------------------*/232 int usbhc_read(async_exch_t *exch, usb_address_t address,233 usb_endpoint_t endpoint, uint64_t setup, void *data, size_t size,234 size_t *rec_size)235 {236 if (size == 0 && setup == 0)237 return EOK;238 239 if (!exch)240 return EINVAL;241 const usb_target_t target =242 {{ .address = address, .endpoint = endpoint }};243 244 /* Make call identifying target USB device and type of transfer. */245 aid_t opening_request = async_send_4(exch,246 DEV_IFACE_ID(USBHC_DEV_IFACE),247 IPC_M_USBHC_READ, target.packed,248 (setup & UINT32_MAX), (setup >> 32), NULL);249 250 if (opening_request == 0) {251 return ENOMEM;252 }253 254 /* Retrieve the data. */255 ipc_call_t data_request_call;256 aid_t data_request =257 async_data_read(exch, data, size, &data_request_call);258 259 if (data_request == 0) {260 // FIXME: How to let the other side know that we want to abort?261 async_wait_for(opening_request, NULL);262 return ENOMEM;263 }264 265 /* Wait for the answer. */266 sysarg_t data_request_rc;267 sysarg_t opening_request_rc;268 async_wait_for(data_request, &data_request_rc);269 async_wait_for(opening_request, &opening_request_rc);270 271 if (data_request_rc != EOK) {272 /* Prefer the return code of the opening request. */273 if (opening_request_rc != EOK) {274 return (int) opening_request_rc;275 } else {276 return (int) data_request_rc;277 }278 }279 if (opening_request_rc != EOK) {280 return (int) opening_request_rc;281 }282 283 *rec_size = IPC_GET_ARG2(data_request_call);284 return EOK;285 }286 /*----------------------------------------------------------------------------*/287 int usbhc_write(async_exch_t *exch, usb_address_t address,288 usb_endpoint_t endpoint, uint64_t setup, const void *data, size_t size)289 {290 if (size == 0 && setup == 0)291 return EOK;292 293 if (!exch)294 return EINVAL;295 const usb_target_t target =296 {{ .address = address, .endpoint = endpoint }};297 298 aid_t opening_request = async_send_5(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),299 IPC_M_USBHC_WRITE, target.packed, size,300 (setup & UINT32_MAX), (setup >> 32), NULL);301 302 if (opening_request == 0) {303 return ENOMEM;304 }305 306 /* Send the data if any. */307 if (size > 0) {308 const int ret = async_data_write_start(exch, data, size);309 if (ret != EOK) {310 async_wait_for(opening_request, NULL);311 return ret;312 }313 }314 315 /* Wait for the answer. */316 sysarg_t opening_request_rc;317 async_wait_for(opening_request, &opening_request_rc);318 319 return (int) opening_request_rc;320 }321 /*----------------------------------------------------------------------------*/322 323 44 static void remote_usbhc_request_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 324 45 static void remote_usbhc_bind_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 325 static void remote_usbhc_ get_handle(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);46 static void remote_usbhc_find_by_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 326 47 static void remote_usbhc_release_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 327 48 static void remote_usbhc_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); … … 336 57 [IPC_M_USBHC_RELEASE_ADDRESS] = remote_usbhc_release_address, 337 58 [IPC_M_USBHC_BIND_ADDRESS] = remote_usbhc_bind_address, 338 [IPC_M_USBHC_GET_HANDLE_BY_ADDRESS] = remote_usbhc_ get_handle,59 [IPC_M_USBHC_GET_HANDLE_BY_ADDRESS] = remote_usbhc_find_by_address, 339 60 340 61 [IPC_M_USBHC_REGISTER_ENDPOINT] = remote_usbhc_register_endpoint, … … 357 78 ipc_callid_t data_caller; 358 79 void *buffer; 80 size_t size; 359 81 } async_transaction_t; 360 82 … … 381 103 trans->data_caller = 0; 382 104 trans->buffer = NULL; 105 trans->size = 0; 383 106 384 107 return trans; 385 108 } 386 /*----------------------------------------------------------------------------*/ 109 387 110 void remote_usbhc_request_address(ddf_fun_t *fun, void *iface, 388 111 ipc_callid_t callid, ipc_call_t *call) 389 112 { 390 const usbhc_iface_t *usb_iface =iface;113 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 391 114 392 115 if (!usb_iface->request_address) { … … 406 129 } 407 130 } 408 /*----------------------------------------------------------------------------*/ 131 409 132 void remote_usbhc_bind_address(ddf_fun_t *fun, void *iface, 410 133 ipc_callid_t callid, ipc_call_t *call) 411 134 { 412 const usbhc_iface_t *usb_iface =iface;135 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 413 136 414 137 if (!usb_iface->bind_address) { … … 417 140 } 418 141 419 const usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call); 420 const devman_handle_t handle = (devman_handle_t) DEV_IPC_GET_ARG2(*call); 421 422 const int ret = usb_iface->bind_address(fun, address, handle); 423 async_answer_0(callid, ret); 424 } 425 /*----------------------------------------------------------------------------*/ 426 void remote_usbhc_get_handle(ddf_fun_t *fun, void *iface, 427 ipc_callid_t callid, ipc_call_t *call) 428 { 429 const usbhc_iface_t *usb_iface = iface; 430 431 if (!usb_iface->get_handle) { 432 async_answer_0(callid, ENOTSUP); 433 return; 434 } 435 436 const usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call); 142 usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call); 143 devman_handle_t handle = (devman_handle_t) DEV_IPC_GET_ARG2(*call); 144 145 int rc = usb_iface->bind_address(fun, address, handle); 146 147 async_answer_0(callid, rc); 148 } 149 150 void remote_usbhc_find_by_address(ddf_fun_t *fun, void *iface, 151 ipc_callid_t callid, ipc_call_t *call) 152 { 153 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 154 155 if (!usb_iface->find_by_address) { 156 async_answer_0(callid, ENOTSUP); 157 return; 158 } 159 160 usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call); 437 161 devman_handle_t handle; 438 const int ret = usb_iface->get_handle(fun, address, &handle);439 440 if (r et== EOK) {441 async_answer_1(callid, ret, handle);162 int rc = usb_iface->find_by_address(fun, address, &handle); 163 164 if (rc == EOK) { 165 async_answer_1(callid, EOK, handle); 442 166 } else { 443 async_answer_0(callid, r et);444 } 445 } 446 /*----------------------------------------------------------------------------*/ 167 async_answer_0(callid, rc); 168 } 169 } 170 447 171 void remote_usbhc_release_address(ddf_fun_t *fun, void *iface, 448 172 ipc_callid_t callid, ipc_call_t *call) 449 173 { 450 const usbhc_iface_t *usb_iface =iface;174 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 451 175 452 176 if (!usb_iface->release_address) { … … 455 179 } 456 180 457 const usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call); 458 459 const int ret = usb_iface->release_address(fun, address); 460 async_answer_0(callid, ret); 461 } 462 /*----------------------------------------------------------------------------*/ 181 usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call); 182 183 int rc = usb_iface->release_address(fun, address); 184 185 async_answer_0(callid, rc); 186 } 187 188 463 189 static void callback_out(ddf_fun_t *fun, 464 190 int outcome, void *arg) 465 191 { 466 async_transaction_t *trans = arg;192 async_transaction_t *trans = (async_transaction_t *)arg; 467 193 468 194 async_answer_0(trans->caller, outcome); … … 470 196 async_transaction_destroy(trans); 471 197 } 472 /*----------------------------------------------------------------------------*/ 198 473 199 static void callback_in(ddf_fun_t *fun, 474 200 int outcome, size_t actual_size, void *arg) … … 485 211 } 486 212 213 trans->size = actual_size; 214 487 215 if (trans->data_caller) { 488 216 async_data_read_finalize(trans->data_caller, … … 494 222 async_transaction_destroy(trans); 495 223 } 496 /*----------------------------------------------------------------------------*/ 224 497 225 void remote_usbhc_register_endpoint(ddf_fun_t *fun, void *iface, 498 226 ipc_callid_t callid, ipc_call_t *call) … … 572 300 } 573 301 574 size_t size = 0; 575 if (!async_data_read_receive(&trans->data_caller, &size)) { 302 if (!async_data_read_receive(&trans->data_caller, &trans->size)) { 576 303 async_answer_0(callid, EPARTY); 577 304 return; 578 305 } 579 306 580 trans->buffer = malloc( size);307 trans->buffer = malloc(trans->size); 581 308 if (trans->buffer == NULL) { 582 309 async_answer_0(trans->data_caller, ENOMEM); … … 586 313 587 314 const int rc = hc_iface->read( 588 fun, target, setup, trans->buffer, size, callback_in, trans);315 fun, target, setup, trans->buffer, trans->size, callback_in, trans); 589 316 590 317 if (rc != EOK) { … … 594 321 } 595 322 } 596 /*----------------------------------------------------------------------------*/ 323 597 324 void remote_usbhc_write( 598 325 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call) … … 621 348 } 622 349 623 size_t size = 0;624 350 if (data_buffer_len > 0) { 625 constint rc = async_data_write_accept(&trans->buffer, false,351 int rc = async_data_write_accept(&trans->buffer, false, 626 352 1, USB_MAX_PAYLOAD_SIZE, 627 0, & size);353 0, &trans->size); 628 354 629 355 if (rc != EOK) { … … 634 360 } 635 361 636 constint rc = hc_iface->write(637 fun, target, setup, trans->buffer, size, callback_out, trans);362 int rc = hc_iface->write( 363 fun, target, setup, trans->buffer, trans->size, callback_out, trans); 638 364 639 365 if (rc != EOK) { … … 642 368 } 643 369 } 370 371 644 372 /** 645 373 * @}
Note:
See TracChangeset
for help on using the changeset viewer.