Changes in uspace/lib/drv/generic/remote_usbhc.c [27736cf:272f46f8] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/drv/generic/remote_usbhc.c
r27736cf r272f46f8 1 1 /* 2 2 * Copyright (c) 2010-2011 Vojtech Horky 3 * Copyright (c) 2011 Jan Vesely 3 4 * All rights reserved. 4 5 * … … 42 43 #define USB_MAX_PAYLOAD_SIZE 1020 43 44 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 made 53 * - argument #1 is target address 54 * - argument #2 is target endpoint 55 * - argument #3 is max packet size of the endpoint 56 * - this call is immediately followed by IPC data write (from caller) 57 * - the initial call (and the whole transaction) is answer after the 58 * transaction is scheduled by the HC and acknowledged by the device 59 * or immediately after error is detected 60 * - the answer carries only the error code 61 * 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 made 66 * - argument #1 is target address 67 * - argument #2 is target endpoint 68 * - this call is immediately followed by IPC data read (async version) 69 * - the call is not answered until the device returns some data (or until 70 * error occurs) 71 * 72 * Some special methods (NO-DATA transactions) do not send any data. These 73 * might behave as both OUT or IN transactions because communication parts 74 * where actual buffers are exchanged are omitted. 75 ** 76 * For all these methods, wrap functions exists. Important rule: functions 77 * for IN transactions have (as parameters) buffers where retrieved data 78 * will be stored. These buffers must be already allocated and shall not be 79 * touch until the transaction is completed 80 * (e.g. not before calling usb_wait_for() with appropriate handle). 81 * OUT transactions buffers can be freed immediately after call is dispatched 82 * (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 address 89 * - EOK - address assigned 90 * Answer arguments: 91 * - assigned address 92 * 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 address 100 * - devman handle 101 * Answer: 102 * - EOK - address binded 103 * - ENOENT - address is not in use 104 */ 105 IPC_M_USBHC_BIND_ADDRESS, 106 107 /** Get handle binded with given USB address. 108 * Parameters 109 * - USB address 110 * Answer: 111 * - EOK - address binded, first parameter is the devman handle 112 * - ENOENT - address is not in use at the moment 113 */ 114 IPC_M_USBHC_GET_HANDLE_BY_ADDRESS, 115 116 /** Release address in use. 117 * Arguments: 118 * - address to be released 119 * Answer: 120 * - ENOENT - address not in use 121 * - EPERM - trying to release default USB address 122 */ 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 number 130 * - packed as ADDR << 16 + EP 131 * - speed + transfer type + direction 132 * - packed as ( SPEED << 8 + TYPE ) << 8 + DIR 133 * - maximum packet size + interval (in milliseconds) 134 * - packed as MPS << 16 + INT 135 * Answer: 136 * - EOK - reservation successful 137 * - ELIMIT - not enough bandwidth to satisfy the request 138 */ 139 IPC_M_USBHC_REGISTER_ENDPOINT, 140 141 /** Revert endpoint registration. 142 * Parameters: 143 * - USB address 144 * - endpoint number 145 * - data direction 146 * Answer: 147 * - EOK - endpoint unregistered 148 * - ENOENT - unknown endpoint 149 */ 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 _PACK2 221 } 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 44 323 static void remote_usbhc_request_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 45 324 static void remote_usbhc_bind_address(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 *);325 static void remote_usbhc_get_handle(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 47 326 static void remote_usbhc_release_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 48 327 static void remote_usbhc_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); … … 57 336 [IPC_M_USBHC_RELEASE_ADDRESS] = remote_usbhc_release_address, 58 337 [IPC_M_USBHC_BIND_ADDRESS] = remote_usbhc_bind_address, 59 [IPC_M_USBHC_GET_HANDLE_BY_ADDRESS] = remote_usbhc_ find_by_address,338 [IPC_M_USBHC_GET_HANDLE_BY_ADDRESS] = remote_usbhc_get_handle, 60 339 61 340 [IPC_M_USBHC_REGISTER_ENDPOINT] = remote_usbhc_register_endpoint, … … 78 357 ipc_callid_t data_caller; 79 358 void *buffer; 80 size_t size;81 359 } async_transaction_t; 82 360 … … 103 381 trans->data_caller = 0; 104 382 trans->buffer = NULL; 105 trans->size = 0;106 383 107 384 return trans; 108 385 } 109 386 /*----------------------------------------------------------------------------*/ 110 387 void remote_usbhc_request_address(ddf_fun_t *fun, void *iface, 111 388 ipc_callid_t callid, ipc_call_t *call) 112 389 { 113 usbhc_iface_t *usb_iface = (usbhc_iface_t *)iface;390 const usbhc_iface_t *usb_iface = iface; 114 391 115 392 if (!usb_iface->request_address) { … … 129 406 } 130 407 } 131 408 /*----------------------------------------------------------------------------*/ 132 409 void remote_usbhc_bind_address(ddf_fun_t *fun, void *iface, 133 410 ipc_callid_t callid, ipc_call_t *call) 134 411 { 135 usbhc_iface_t *usb_iface = (usbhc_iface_t *)iface;412 const usbhc_iface_t *usb_iface = iface; 136 413 137 414 if (!usb_iface->bind_address) { … … 140 417 } 141 418 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, 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, 151 427 ipc_callid_t callid, ipc_call_t *call) 152 428 { 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);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); 161 437 devman_handle_t handle; 162 int rc = usb_iface->find_by_address(fun, address, &handle);163 164 if (r c== EOK) {165 async_answer_1(callid, EOK, handle);438 const int ret = usb_iface->get_handle(fun, address, &handle); 439 440 if (ret == EOK) { 441 async_answer_1(callid, ret, handle); 166 442 } else { 167 async_answer_0(callid, r c);168 } 169 } 170 443 async_answer_0(callid, ret); 444 } 445 } 446 /*----------------------------------------------------------------------------*/ 171 447 void remote_usbhc_release_address(ddf_fun_t *fun, void *iface, 172 448 ipc_callid_t callid, ipc_call_t *call) 173 449 { 174 usbhc_iface_t *usb_iface = (usbhc_iface_t *)iface;450 const usbhc_iface_t *usb_iface = iface; 175 451 176 452 if (!usb_iface->release_address) { … … 179 455 } 180 456 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 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 /*----------------------------------------------------------------------------*/ 189 463 static void callback_out(ddf_fun_t *fun, 190 464 int outcome, void *arg) 191 465 { 192 async_transaction_t *trans = (async_transaction_t *)arg;466 async_transaction_t *trans = arg; 193 467 194 468 async_answer_0(trans->caller, outcome); … … 196 470 async_transaction_destroy(trans); 197 471 } 198 472 /*----------------------------------------------------------------------------*/ 199 473 static void callback_in(ddf_fun_t *fun, 200 474 int outcome, size_t actual_size, void *arg) … … 211 485 } 212 486 213 trans->size = actual_size;214 215 487 if (trans->data_caller) { 216 488 async_data_read_finalize(trans->data_caller, … … 222 494 async_transaction_destroy(trans); 223 495 } 224 496 /*----------------------------------------------------------------------------*/ 225 497 void remote_usbhc_register_endpoint(ddf_fun_t *fun, void *iface, 226 498 ipc_callid_t callid, ipc_call_t *call) … … 300 572 } 301 573 302 if (!async_data_read_receive(&trans->data_caller, &trans->size)) { 574 size_t size = 0; 575 if (!async_data_read_receive(&trans->data_caller, &size)) { 303 576 async_answer_0(callid, EPARTY); 304 577 return; 305 578 } 306 579 307 trans->buffer = malloc( trans->size);580 trans->buffer = malloc(size); 308 581 if (trans->buffer == NULL) { 309 582 async_answer_0(trans->data_caller, ENOMEM); … … 313 586 314 587 const int rc = hc_iface->read( 315 fun, target, setup, trans->buffer, trans->size, callback_in, trans);588 fun, target, setup, trans->buffer, size, callback_in, trans); 316 589 317 590 if (rc != EOK) { … … 321 594 } 322 595 } 323 596 /*----------------------------------------------------------------------------*/ 324 597 void remote_usbhc_write( 325 598 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call) … … 348 621 } 349 622 623 size_t size = 0; 350 624 if (data_buffer_len > 0) { 351 int rc = async_data_write_accept(&trans->buffer, false,625 const int rc = async_data_write_accept(&trans->buffer, false, 352 626 1, USB_MAX_PAYLOAD_SIZE, 353 0, & trans->size);627 0, &size); 354 628 355 629 if (rc != EOK) { … … 360 634 } 361 635 362 int rc = hc_iface->write(363 fun, target, setup, trans->buffer, trans->size, callback_out, trans);636 const int rc = hc_iface->write( 637 fun, target, setup, trans->buffer, size, callback_out, trans); 364 638 365 639 if (rc != EOK) { … … 368 642 } 369 643 } 370 371 372 644 /** 373 645 * @}
Note:
See TracChangeset
for help on using the changeset viewer.