Changeset 00aece0 in mainline for uspace/lib/drv/generic/remote_usbhc.c
- Timestamp:
- 2012-02-18T16:47:38Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 4449c6c
- Parents:
- bd5f3b7 (diff), f943dd3 (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. - File:
-
- 1 edited
-
uspace/lib/drv/generic/remote_usbhc.c (modified) (13 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/drv/generic/remote_usbhc.c
rbd5f3b7 r00aece0 1 1 /* 2 2 * Copyright (c) 2010-2011 Vojtech Horky 3 * Copyright (c) 2011 Jan Vesely 3 4 * All rights reserved. 4 5 * … … 41 42 42 43 #define USB_MAX_PAYLOAD_SIZE 1020 43 #define HACK_MAX_PACKET_SIZE 8 44 #define HACK_MAX_PACKET_SIZE_INTERRUPT_IN 4 45 46 static void remote_usbhc_interrupt_out(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 47 static void remote_usbhc_interrupt_in(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 48 static void remote_usbhc_bulk_out(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 49 static void remote_usbhc_bulk_in(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 50 static void remote_usbhc_control_write(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 51 static void remote_usbhc_control_read(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 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 52 323 static void remote_usbhc_request_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 53 324 static void remote_usbhc_bind_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 54 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 *); 55 326 static void remote_usbhc_release_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 56 327 static void remote_usbhc_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 57 328 static void remote_usbhc_unregister_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 329 static void remote_usbhc_read(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 330 static void remote_usbhc_write(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 58 331 //static void remote_usbhc(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 59 332 60 333 /** Remote USB host controller interface operations. */ 61 static remote_iface_func_ptr_t remote_usbhc_iface_ops [] = { 62 remote_usbhc_request_address, 63 remote_usbhc_bind_address, 64 remote_usbhc_find_by_address, 65 remote_usbhc_release_address, 66 67 remote_usbhc_interrupt_out, 68 remote_usbhc_interrupt_in, 69 70 remote_usbhc_bulk_out, 71 remote_usbhc_bulk_in, 72 73 remote_usbhc_control_write, 74 remote_usbhc_control_read, 75 76 remote_usbhc_register_endpoint, 77 remote_usbhc_unregister_endpoint 334 static remote_iface_func_ptr_t remote_usbhc_iface_ops[] = { 335 [IPC_M_USBHC_REQUEST_ADDRESS] = remote_usbhc_request_address, 336 [IPC_M_USBHC_RELEASE_ADDRESS] = remote_usbhc_release_address, 337 [IPC_M_USBHC_BIND_ADDRESS] = remote_usbhc_bind_address, 338 [IPC_M_USBHC_GET_HANDLE_BY_ADDRESS] = remote_usbhc_get_handle, 339 340 [IPC_M_USBHC_REGISTER_ENDPOINT] = remote_usbhc_register_endpoint, 341 [IPC_M_USBHC_UNREGISTER_ENDPOINT] = remote_usbhc_unregister_endpoint, 342 343 [IPC_M_USBHC_READ] = remote_usbhc_read, 344 [IPC_M_USBHC_WRITE] = remote_usbhc_write, 78 345 }; 79 346 … … 90 357 ipc_callid_t data_caller; 91 358 void *buffer; 92 void *setup_packet;93 size_t size;94 359 } async_transaction_t; 95 360 … … 98 363 if (trans == NULL) { 99 364 return; 100 }101 102 if (trans->setup_packet != NULL) {103 free(trans->setup_packet);104 365 } 105 366 if (trans->buffer != NULL) { … … 120 381 trans->data_caller = 0; 121 382 trans->buffer = NULL; 122 trans->setup_packet = NULL;123 trans->size = 0;124 383 125 384 return trans; 126 385 } 127 386 /*----------------------------------------------------------------------------*/ 128 387 void remote_usbhc_request_address(ddf_fun_t *fun, void *iface, 129 388 ipc_callid_t callid, ipc_call_t *call) 130 389 { 131 usbhc_iface_t *usb_iface = (usbhc_iface_t *)iface;390 const usbhc_iface_t *usb_iface = iface; 132 391 133 392 if (!usb_iface->request_address) { … … 135 394 return; 136 395 } 137 138 usb_speed_t speed = DEV_IPC_GET_ARG1(*call); 139 140 usb_address_t address; 141 int rc = usb_iface->request_address(fun, speed, &address); 396 397 usb_address_t address = DEV_IPC_GET_ARG1(*call); 398 const bool strict = DEV_IPC_GET_ARG2(*call); 399 const usb_speed_t speed = DEV_IPC_GET_ARG3(*call); 400 401 const int rc = usb_iface->request_address(fun, &address, strict, speed); 142 402 if (rc != EOK) { 143 403 async_answer_0(callid, rc); … … 146 406 } 147 407 } 148 408 /*----------------------------------------------------------------------------*/ 149 409 void remote_usbhc_bind_address(ddf_fun_t *fun, void *iface, 150 410 ipc_callid_t callid, ipc_call_t *call) 151 411 { 152 usbhc_iface_t *usb_iface = (usbhc_iface_t *)iface;412 const usbhc_iface_t *usb_iface = iface; 153 413 154 414 if (!usb_iface->bind_address) { … … 157 417 } 158 418 159 usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call); 160 devman_handle_t handle = (devman_handle_t) DEV_IPC_GET_ARG2(*call); 161 162 int rc = usb_iface->bind_address(fun, address, handle); 163 164 async_answer_0(callid, rc); 165 } 166 167 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, 168 427 ipc_callid_t callid, ipc_call_t *call) 169 428 { 170 usbhc_iface_t *usb_iface = (usbhc_iface_t *)iface;171 172 if (!usb_iface-> find_by_address) {173 async_answer_0(callid, ENOTSUP); 174 return; 175 } 176 177 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); 178 437 devman_handle_t handle; 179 int rc = usb_iface->find_by_address(fun, address, &handle);180 181 if (r c== EOK) {182 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); 183 442 } else { 184 async_answer_0(callid, r c);185 } 186 } 187 443 async_answer_0(callid, ret); 444 } 445 } 446 /*----------------------------------------------------------------------------*/ 188 447 void remote_usbhc_release_address(ddf_fun_t *fun, void *iface, 189 448 ipc_callid_t callid, ipc_call_t *call) 190 449 { 191 usbhc_iface_t *usb_iface = (usbhc_iface_t *)iface;450 const usbhc_iface_t *usb_iface = iface; 192 451 193 452 if (!usb_iface->release_address) { … … 196 455 } 197 456 198 usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call); 199 200 int rc = usb_iface->release_address(fun, address); 201 202 async_answer_0(callid, rc); 203 } 204 205 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 /*----------------------------------------------------------------------------*/ 206 463 static void callback_out(ddf_fun_t *fun, 207 464 int outcome, void *arg) 208 465 { 209 async_transaction_t *trans = (async_transaction_t *)arg;466 async_transaction_t *trans = arg; 210 467 211 468 async_answer_0(trans->caller, outcome); … … 213 470 async_transaction_destroy(trans); 214 471 } 215 472 /*----------------------------------------------------------------------------*/ 216 473 static void callback_in(ddf_fun_t *fun, 217 474 int outcome, size_t actual_size, void *arg) … … 228 485 } 229 486 230 trans->size = actual_size;231 232 487 if (trans->data_caller) { 233 488 async_data_read_finalize(trans->data_caller, … … 239 494 async_transaction_destroy(trans); 240 495 } 241 242 /** Process an outgoing transfer (both OUT and SETUP). 243 * 244 * @param device Target device. 245 * @param callid Initiating caller. 246 * @param call Initiating call. 247 * @param transfer_func Transfer function (might be NULL). 248 */ 249 static void remote_usbhc_out_transfer(ddf_fun_t *fun, 250 ipc_callid_t callid, ipc_call_t *call, 251 usbhc_iface_transfer_out_t transfer_func) 252 { 253 if (!transfer_func) { 254 async_answer_0(callid, ENOTSUP); 255 return; 256 } 257 258 usb_target_t target = { 259 .address = DEV_IPC_GET_ARG1(*call), 260 .endpoint = DEV_IPC_GET_ARG2(*call) 261 }; 262 263 size_t len = 0; 264 void *buffer = NULL; 265 266 int rc = async_data_write_accept(&buffer, false, 267 1, USB_MAX_PAYLOAD_SIZE, 268 0, &len); 269 270 if (rc != EOK) { 271 async_answer_0(callid, rc); 272 return; 273 } 496 /*----------------------------------------------------------------------------*/ 497 void remote_usbhc_register_endpoint(ddf_fun_t *fun, void *iface, 498 ipc_callid_t callid, ipc_call_t *call) 499 { 500 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 501 502 if (!usb_iface->register_endpoint) { 503 async_answer_0(callid, ENOTSUP); 504 return; 505 } 506 507 #define _INIT_FROM_HIGH_DATA2(type, var, arg_no) \ 508 type var = (type) (DEV_IPC_GET_ARG##arg_no(*call) >> 16) 509 #define _INIT_FROM_LOW_DATA2(type, var, arg_no) \ 510 type var = (type) (DEV_IPC_GET_ARG##arg_no(*call) & 0xffff) 511 512 const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) }; 513 514 _INIT_FROM_HIGH_DATA2(usb_transfer_type_t, transfer_type, 2); 515 _INIT_FROM_LOW_DATA2(usb_direction_t, direction, 2); 516 517 _INIT_FROM_HIGH_DATA2(size_t, max_packet_size, 3); 518 _INIT_FROM_LOW_DATA2(unsigned int, interval, 3); 519 520 #undef _INIT_FROM_HIGH_DATA2 521 #undef _INIT_FROM_LOW_DATA2 522 523 int rc = usb_iface->register_endpoint(fun, target.address, 524 target.endpoint, transfer_type, direction, max_packet_size, interval); 525 526 async_answer_0(callid, rc); 527 } 528 529 void remote_usbhc_unregister_endpoint(ddf_fun_t *fun, void *iface, 530 ipc_callid_t callid, ipc_call_t *call) 531 { 532 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 533 534 if (!usb_iface->unregister_endpoint) { 535 async_answer_0(callid, ENOTSUP); 536 return; 537 } 538 539 usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call); 540 usb_endpoint_t endpoint = (usb_endpoint_t) DEV_IPC_GET_ARG2(*call); 541 usb_direction_t direction = (usb_direction_t) DEV_IPC_GET_ARG3(*call); 542 543 int rc = usb_iface->unregister_endpoint(fun, 544 address, endpoint, direction); 545 546 async_answer_0(callid, rc); 547 } 548 549 void remote_usbhc_read( 550 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call) 551 { 552 assert(fun); 553 assert(iface); 554 assert(call); 555 556 const usbhc_iface_t *hc_iface = iface; 557 558 if (!hc_iface->read) { 559 async_answer_0(callid, ENOTSUP); 560 return; 561 } 562 563 const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) }; 564 const uint64_t setup = 565 ((uint64_t)DEV_IPC_GET_ARG2(*call)) | 566 (((uint64_t)DEV_IPC_GET_ARG3(*call)) << 32); 274 567 275 568 async_transaction_t *trans = async_transaction_create(callid); 276 569 if (trans == NULL) { 277 if (buffer != NULL) { 278 free(buffer); 570 async_answer_0(callid, ENOMEM); 571 return; 572 } 573 574 size_t size = 0; 575 if (!async_data_read_receive(&trans->data_caller, &size)) { 576 async_answer_0(callid, EPARTY); 577 return; 578 } 579 580 trans->buffer = malloc(size); 581 if (trans->buffer == NULL) { 582 async_answer_0(trans->data_caller, ENOMEM); 583 async_answer_0(callid, ENOMEM); 584 async_transaction_destroy(trans); 585 } 586 587 const int rc = hc_iface->read( 588 fun, target, setup, trans->buffer, size, callback_in, trans); 589 590 if (rc != EOK) { 591 async_answer_0(trans->data_caller, rc); 592 async_answer_0(callid, rc); 593 async_transaction_destroy(trans); 594 } 595 } 596 /*----------------------------------------------------------------------------*/ 597 void remote_usbhc_write( 598 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call) 599 { 600 assert(fun); 601 assert(iface); 602 assert(call); 603 604 const usbhc_iface_t *hc_iface = iface; 605 606 if (!hc_iface->write) { 607 async_answer_0(callid, ENOTSUP); 608 return; 609 } 610 611 const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) }; 612 const size_t data_buffer_len = DEV_IPC_GET_ARG2(*call); 613 const uint64_t setup = 614 ((uint64_t)DEV_IPC_GET_ARG3(*call)) | 615 (((uint64_t)DEV_IPC_GET_ARG4(*call)) << 32); 616 617 async_transaction_t *trans = async_transaction_create(callid); 618 if (trans == NULL) { 619 async_answer_0(callid, ENOMEM); 620 return; 621 } 622 623 size_t size = 0; 624 if (data_buffer_len > 0) { 625 const int rc = async_data_write_accept(&trans->buffer, false, 626 1, USB_MAX_PAYLOAD_SIZE, 627 0, &size); 628 629 if (rc != EOK) { 630 async_answer_0(callid, rc); 631 async_transaction_destroy(trans); 632 return; 279 633 } 280 async_answer_0(callid, ENOMEM); 281 return; 282 } 283 284 trans->buffer = buffer; 285 trans->size = len; 286 287 rc = transfer_func(fun, target, 288 buffer, len, 289 callback_out, trans); 634 } 635 636 const int rc = hc_iface->write( 637 fun, target, setup, trans->buffer, size, callback_out, trans); 290 638 291 639 if (rc != EOK) { … … 294 642 } 295 643 } 296 297 /** Process an incoming transfer.298 *299 * @param device Target device.300 * @param callid Initiating caller.301 * @param call Initiating call.302 * @param transfer_func Transfer function (might be NULL).303 */304 static void remote_usbhc_in_transfer(ddf_fun_t *fun,305 ipc_callid_t callid, ipc_call_t *call,306 usbhc_iface_transfer_in_t transfer_func)307 {308 if (!transfer_func) {309 async_answer_0(callid, ENOTSUP);310 return;311 }312 313 usb_target_t target = {314 .address = DEV_IPC_GET_ARG1(*call),315 .endpoint = DEV_IPC_GET_ARG2(*call)316 };317 318 size_t len;319 ipc_callid_t data_callid;320 if (!async_data_read_receive(&data_callid, &len)) {321 async_answer_0(callid, EPARTY);322 return;323 }324 325 async_transaction_t *trans = async_transaction_create(callid);326 if (trans == NULL) {327 async_answer_0(data_callid, ENOMEM);328 async_answer_0(callid, ENOMEM);329 return;330 }331 trans->data_caller = data_callid;332 trans->buffer = malloc(len);333 trans->size = len;334 335 int rc = transfer_func(fun, target,336 trans->buffer, len,337 callback_in, trans);338 339 if (rc != EOK) {340 async_answer_0(data_callid, rc);341 async_answer_0(callid, rc);342 async_transaction_destroy(trans);343 }344 }345 346 void remote_usbhc_interrupt_out(ddf_fun_t *fun, void *iface,347 ipc_callid_t callid, ipc_call_t *call)348 {349 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;350 assert(usb_iface != NULL);351 352 return remote_usbhc_out_transfer(fun, callid, call,353 usb_iface->interrupt_out);354 }355 356 void remote_usbhc_interrupt_in(ddf_fun_t *fun, void *iface,357 ipc_callid_t callid, ipc_call_t *call)358 {359 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;360 assert(usb_iface != NULL);361 362 return remote_usbhc_in_transfer(fun, callid, call,363 usb_iface->interrupt_in);364 }365 366 void remote_usbhc_bulk_out(ddf_fun_t *fun, void *iface,367 ipc_callid_t callid, ipc_call_t *call)368 {369 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;370 assert(usb_iface != NULL);371 372 return remote_usbhc_out_transfer(fun, callid, call,373 usb_iface->bulk_out);374 }375 376 void remote_usbhc_bulk_in(ddf_fun_t *fun, void *iface,377 ipc_callid_t callid, ipc_call_t *call)378 {379 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;380 assert(usb_iface != NULL);381 382 return remote_usbhc_in_transfer(fun, callid, call,383 usb_iface->bulk_in);384 }385 386 void remote_usbhc_control_write(ddf_fun_t *fun, void *iface,387 ipc_callid_t callid, ipc_call_t *call)388 {389 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;390 assert(usb_iface != NULL);391 392 if (!usb_iface->control_write) {393 async_answer_0(callid, ENOTSUP);394 return;395 }396 397 usb_target_t target = {398 .address = DEV_IPC_GET_ARG1(*call),399 .endpoint = DEV_IPC_GET_ARG2(*call)400 };401 size_t data_buffer_len = DEV_IPC_GET_ARG3(*call);402 403 int rc;404 405 void *setup_packet = NULL;406 void *data_buffer = NULL;407 size_t setup_packet_len = 0;408 409 rc = async_data_write_accept(&setup_packet, false,410 1, USB_MAX_PAYLOAD_SIZE, 0, &setup_packet_len);411 if (rc != EOK) {412 async_answer_0(callid, rc);413 return;414 }415 416 if (data_buffer_len > 0) {417 rc = async_data_write_accept(&data_buffer, false,418 1, USB_MAX_PAYLOAD_SIZE, 0, &data_buffer_len);419 if (rc != EOK) {420 async_answer_0(callid, rc);421 free(setup_packet);422 return;423 }424 }425 426 async_transaction_t *trans = async_transaction_create(callid);427 if (trans == NULL) {428 async_answer_0(callid, ENOMEM);429 free(setup_packet);430 free(data_buffer);431 return;432 }433 trans->setup_packet = setup_packet;434 trans->buffer = data_buffer;435 trans->size = data_buffer_len;436 437 rc = usb_iface->control_write(fun, target,438 setup_packet, setup_packet_len,439 data_buffer, data_buffer_len,440 callback_out, trans);441 442 if (rc != EOK) {443 async_answer_0(callid, rc);444 async_transaction_destroy(trans);445 }446 }447 448 449 void remote_usbhc_control_read(ddf_fun_t *fun, void *iface,450 ipc_callid_t callid, ipc_call_t *call)451 {452 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;453 assert(usb_iface != NULL);454 455 if (!usb_iface->control_read) {456 async_answer_0(callid, ENOTSUP);457 return;458 }459 460 usb_target_t target = {461 .address = DEV_IPC_GET_ARG1(*call),462 .endpoint = DEV_IPC_GET_ARG2(*call)463 };464 465 int rc;466 467 void *setup_packet = NULL;468 size_t setup_packet_len = 0;469 size_t data_len = 0;470 471 rc = async_data_write_accept(&setup_packet, false,472 1, USB_MAX_PAYLOAD_SIZE, 0, &setup_packet_len);473 if (rc != EOK) {474 async_answer_0(callid, rc);475 return;476 }477 478 ipc_callid_t data_callid;479 if (!async_data_read_receive(&data_callid, &data_len)) {480 async_answer_0(callid, EPARTY);481 free(setup_packet);482 return;483 }484 485 async_transaction_t *trans = async_transaction_create(callid);486 if (trans == NULL) {487 async_answer_0(data_callid, ENOMEM);488 async_answer_0(callid, ENOMEM);489 free(setup_packet);490 return;491 }492 trans->data_caller = data_callid;493 trans->setup_packet = setup_packet;494 trans->size = data_len;495 trans->buffer = malloc(data_len);496 if (trans->buffer == NULL) {497 async_answer_0(data_callid, ENOMEM);498 async_answer_0(callid, ENOMEM);499 async_transaction_destroy(trans);500 return;501 }502 503 rc = usb_iface->control_read(fun, target,504 setup_packet, setup_packet_len,505 trans->buffer, trans->size,506 callback_in, trans);507 508 if (rc != EOK) {509 async_answer_0(data_callid, rc);510 async_answer_0(callid, rc);511 async_transaction_destroy(trans);512 }513 }514 515 516 void remote_usbhc_register_endpoint(ddf_fun_t *fun, void *iface,517 ipc_callid_t callid, ipc_call_t *call)518 {519 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;520 521 if (!usb_iface->register_endpoint) {522 async_answer_0(callid, ENOTSUP);523 return;524 }525 526 #define _INIT_FROM_HIGH_DATA2(type, var, arg_no) \527 type var = (type) DEV_IPC_GET_ARG##arg_no(*call) / (1 << 16)528 #define _INIT_FROM_LOW_DATA2(type, var, arg_no) \529 type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % (1 << 16)530 #define _INIT_FROM_HIGH_DATA3(type, var, arg_no) \531 type var = (type) DEV_IPC_GET_ARG##arg_no(*call) / (1 << 16)532 #define _INIT_FROM_MIDDLE_DATA3(type, var, arg_no) \533 type var = (type) (DEV_IPC_GET_ARG##arg_no(*call) / (1 << 8)) % (1 << 8)534 #define _INIT_FROM_LOW_DATA3(type, var, arg_no) \535 type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % (1 << 8)536 537 _INIT_FROM_HIGH_DATA2(usb_address_t, address, 1);538 _INIT_FROM_LOW_DATA2(usb_endpoint_t, endpoint, 1);539 540 _INIT_FROM_HIGH_DATA3(usb_speed_t, speed, 2);541 _INIT_FROM_MIDDLE_DATA3(usb_transfer_type_t, transfer_type, 2);542 _INIT_FROM_LOW_DATA3(usb_direction_t, direction, 2);543 544 _INIT_FROM_HIGH_DATA2(size_t, max_packet_size, 3);545 _INIT_FROM_LOW_DATA2(unsigned int, interval, 3);546 547 #undef _INIT_FROM_HIGH_DATA2548 #undef _INIT_FROM_LOW_DATA2549 #undef _INIT_FROM_HIGH_DATA3550 #undef _INIT_FROM_MIDDLE_DATA3551 #undef _INIT_FROM_LOW_DATA3552 553 int rc = usb_iface->register_endpoint(fun, address, speed, endpoint,554 transfer_type, direction, max_packet_size, interval);555 556 async_answer_0(callid, rc);557 }558 559 560 void remote_usbhc_unregister_endpoint(ddf_fun_t *fun, void *iface,561 ipc_callid_t callid, ipc_call_t *call)562 {563 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;564 565 if (!usb_iface->unregister_endpoint) {566 async_answer_0(callid, ENOTSUP);567 return;568 }569 570 usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call);571 usb_endpoint_t endpoint = (usb_endpoint_t) DEV_IPC_GET_ARG2(*call);572 usb_direction_t direction = (usb_direction_t) DEV_IPC_GET_ARG3(*call);573 574 int rc = usb_iface->unregister_endpoint(fun,575 address, endpoint, direction);576 577 async_answer_0(callid, rc);578 }579 580 581 644 /** 582 645 * @}
Note:
See TracChangeset
for help on using the changeset viewer.
