source: mainline/uspace/lib/drv/generic/remote_usbhc.c@ b4292e7

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since b4292e7 was 272f46f8, checked in by Jan Vesely <jano.vesely@…>, 14 years ago

libdrv/drvusbhc: Remove data_size field.

  • Property mode set to 100644
File size: 19.2 KB
RevLine 
[91db50ac]1/*
[9753220]2 * Copyright (c) 2010-2011 Vojtech Horky
[02fc5c4]3 * Copyright (c) 2011 Jan Vesely
[91db50ac]4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/** @addtogroup libdrv
31 * @{
32 */
33/** @file
34 */
35
36#include <async.h>
37#include <errno.h>
[eb1a2f4]38#include <assert.h>
[91db50ac]39
[cb59f787]40#include "usbhc_iface.h"
[eb1a2f4]41#include "ddf/driver.h"
[91db50ac]42
[1b22bd4]43#define USB_MAX_PAYLOAD_SIZE 1020
44
[02fc5c4]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 */
85typedef 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
163int 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/*----------------------------------------------------------------------------*/
176int 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/*----------------------------------------------------------------------------*/
185int 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/*----------------------------------------------------------------------------*/
198int 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/*----------------------------------------------------------------------------*/
206int 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/*----------------------------------------------------------------------------*/
223int 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/*----------------------------------------------------------------------------*/
232int 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/*----------------------------------------------------------------------------*/
287int 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
[eb1a2f4]323static void remote_usbhc_request_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
324static void remote_usbhc_bind_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
[02fc5c4]325static void remote_usbhc_get_handle(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
[eb1a2f4]326static void remote_usbhc_release_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
[b7d8fd9]327static void remote_usbhc_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
328static void remote_usbhc_unregister_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
[bbce2c2]329static void remote_usbhc_read(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
330static void remote_usbhc_write(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
[eb1a2f4]331//static void remote_usbhc(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
[91db50ac]332
[6edd494]333/** Remote USB host controller interface operations. */
[ffe3fe1]334static remote_iface_func_ptr_t remote_usbhc_iface_ops[] = {
335 [IPC_M_USBHC_REQUEST_ADDRESS] = remote_usbhc_request_address,
[27736cf]336 [IPC_M_USBHC_RELEASE_ADDRESS] = remote_usbhc_release_address,
[ffe3fe1]337 [IPC_M_USBHC_BIND_ADDRESS] = remote_usbhc_bind_address,
[02fc5c4]338 [IPC_M_USBHC_GET_HANDLE_BY_ADDRESS] = remote_usbhc_get_handle,
[6f04905]339
[1e647c7d]340 [IPC_M_USBHC_REGISTER_ENDPOINT] = remote_usbhc_register_endpoint,
341 [IPC_M_USBHC_UNREGISTER_ENDPOINT] = remote_usbhc_unregister_endpoint,
[0a46c41e]342
[bbce2c2]343 [IPC_M_USBHC_READ] = remote_usbhc_read,
344 [IPC_M_USBHC_WRITE] = remote_usbhc_write,
[91db50ac]345};
346
[6edd494]347/** Remote USB host controller interface structure.
[91db50ac]348 */
[cb59f787]349remote_iface_t remote_usbhc_iface = {
350 .method_count = sizeof(remote_usbhc_iface_ops) /
351 sizeof(remote_usbhc_iface_ops[0]),
352 .methods = remote_usbhc_iface_ops
[91db50ac]353};
354
[1b22bd4]355typedef struct {
356 ipc_callid_t caller;
[0a6fa9f]357 ipc_callid_t data_caller;
[1b22bd4]358 void *buffer;
359} async_transaction_t;
[91db50ac]360
[93f8da1]361static void async_transaction_destroy(async_transaction_t *trans)
362{
363 if (trans == NULL) {
364 return;
365 }
366 if (trans->buffer != NULL) {
367 free(trans->buffer);
368 }
369
370 free(trans);
371}
372
373static async_transaction_t *async_transaction_create(ipc_callid_t caller)
374{
375 async_transaction_t *trans = malloc(sizeof(async_transaction_t));
376 if (trans == NULL) {
377 return NULL;
378 }
379
380 trans->caller = caller;
[0a6fa9f]381 trans->data_caller = 0;
[93f8da1]382 trans->buffer = NULL;
383
384 return trans;
385}
[02fc5c4]386/*----------------------------------------------------------------------------*/
[eb1a2f4]387void remote_usbhc_request_address(ddf_fun_t *fun, void *iface,
[6f04905]388 ipc_callid_t callid, ipc_call_t *call)
389{
[02fc5c4]390 const usbhc_iface_t *usb_iface = iface;
[6f04905]391
392 if (!usb_iface->request_address) {
[17aca1c]393 async_answer_0(callid, ENOTSUP);
[6f04905]394 return;
395 }
[ffe3fe1]396
[67f55e7b]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);
[6f04905]400
[67f55e7b]401 const int rc = usb_iface->request_address(fun, &address, strict, speed);
[6f04905]402 if (rc != EOK) {
[17aca1c]403 async_answer_0(callid, rc);
[6f04905]404 } else {
[17aca1c]405 async_answer_1(callid, EOK, (sysarg_t) address);
[6f04905]406 }
407}
[02fc5c4]408/*----------------------------------------------------------------------------*/
[eb1a2f4]409void remote_usbhc_bind_address(ddf_fun_t *fun, void *iface,
[4689d40]410 ipc_callid_t callid, ipc_call_t *call)
411{
[02fc5c4]412 const usbhc_iface_t *usb_iface = iface;
[4689d40]413
414 if (!usb_iface->bind_address) {
[17aca1c]415 async_answer_0(callid, ENOTSUP);
[4689d40]416 return;
417 }
418
[02fc5c4]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);
[4689d40]421
[02fc5c4]422 const int ret = usb_iface->bind_address(fun, address, handle);
423 async_answer_0(callid, ret);
[4689d40]424}
[02fc5c4]425/*----------------------------------------------------------------------------*/
426void remote_usbhc_get_handle(ddf_fun_t *fun, void *iface,
[eb2f7dd]427 ipc_callid_t callid, ipc_call_t *call)
428{
[02fc5c4]429 const usbhc_iface_t *usb_iface = iface;
[eb2f7dd]430
[02fc5c4]431 if (!usb_iface->get_handle) {
[eb2f7dd]432 async_answer_0(callid, ENOTSUP);
433 return;
434 }
435
[02fc5c4]436 const usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call);
[eb2f7dd]437 devman_handle_t handle;
[02fc5c4]438 const int ret = usb_iface->get_handle(fun, address, &handle);
[eb2f7dd]439
[02fc5c4]440 if (ret == EOK) {
441 async_answer_1(callid, ret, handle);
[eb2f7dd]442 } else {
[02fc5c4]443 async_answer_0(callid, ret);
[eb2f7dd]444 }
445}
[02fc5c4]446/*----------------------------------------------------------------------------*/
[eb1a2f4]447void remote_usbhc_release_address(ddf_fun_t *fun, void *iface,
[6f04905]448 ipc_callid_t callid, ipc_call_t *call)
449{
[02fc5c4]450 const usbhc_iface_t *usb_iface = iface;
[6f04905]451
452 if (!usb_iface->release_address) {
[17aca1c]453 async_answer_0(callid, ENOTSUP);
[6f04905]454 return;
455 }
456
[02fc5c4]457 const usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call);
[6f04905]458
[02fc5c4]459 const int ret = usb_iface->release_address(fun, address);
460 async_answer_0(callid, ret);
[6f04905]461}
[02fc5c4]462/*----------------------------------------------------------------------------*/
[eb1a2f4]463static void callback_out(ddf_fun_t *fun,
[daec5e04]464 int outcome, void *arg)
[1b22bd4]465{
[272f46f8]466 async_transaction_t *trans = arg;
[1b22bd4]467
[17aca1c]468 async_answer_0(trans->caller, outcome);
[1b22bd4]469
[93f8da1]470 async_transaction_destroy(trans);
[1b22bd4]471}
[272f46f8]472/*----------------------------------------------------------------------------*/
[eb1a2f4]473static void callback_in(ddf_fun_t *fun,
[daec5e04]474 int outcome, size_t actual_size, void *arg)
[1b22bd4]475{
476 async_transaction_t *trans = (async_transaction_t *)arg;
477
[daec5e04]478 if (outcome != EOK) {
[17aca1c]479 async_answer_0(trans->caller, outcome);
[5842493]480 if (trans->data_caller) {
481 async_answer_0(trans->data_caller, EINTR);
482 }
[93f8da1]483 async_transaction_destroy(trans);
484 return;
485 }
[1b22bd4]486
[0a6fa9f]487 if (trans->data_caller) {
488 async_data_read_finalize(trans->data_caller,
489 trans->buffer, actual_size);
490 }
491
[daec5e04]492 async_answer_0(trans->caller, EOK);
[1e64b250]493
494 async_transaction_destroy(trans);
[91db50ac]495}
[272f46f8]496/*----------------------------------------------------------------------------*/
[b7d8fd9]497void 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
[1998bcd]507#define _INIT_FROM_HIGH_DATA2(type, var, arg_no) \
[27736cf]508 type var = (type) (DEV_IPC_GET_ARG##arg_no(*call) >> 16)
[1998bcd]509#define _INIT_FROM_LOW_DATA2(type, var, arg_no) \
[27736cf]510 type var = (type) (DEV_IPC_GET_ARG##arg_no(*call) & 0xffff)
[1998bcd]511
[365e29e2]512 const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) };
[1998bcd]513
[27736cf]514 _INIT_FROM_HIGH_DATA2(usb_transfer_type_t, transfer_type, 2);
515 _INIT_FROM_LOW_DATA2(usb_direction_t, direction, 2);
[1998bcd]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
[27736cf]523 int rc = usb_iface->register_endpoint(fun, target.address,
[bdd8ad2f]524 target.endpoint, transfer_type, direction, max_packet_size, interval);
[b7d8fd9]525
526 async_answer_0(callid, rc);
527}
528
529void 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
[bbce2c2]549void remote_usbhc_read(
[ffe3fe1]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
[365e29e2]563 const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) };
[bdd8ad2f]564 const uint64_t setup =
565 ((uint64_t)DEV_IPC_GET_ARG2(*call)) |
566 (((uint64_t)DEV_IPC_GET_ARG3(*call)) << 32);
[ffe3fe1]567
568 async_transaction_t *trans = async_transaction_create(callid);
569 if (trans == NULL) {
570 async_answer_0(callid, ENOMEM);
571 return;
572 }
573
[272f46f8]574 size_t size = 0;
575 if (!async_data_read_receive(&trans->data_caller, &size)) {
[ffe3fe1]576 async_answer_0(callid, EPARTY);
577 return;
578 }
579
[272f46f8]580 trans->buffer = malloc(size);
[ffe3fe1]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(
[272f46f8]588 fun, target, setup, trans->buffer, size, callback_in, trans);
[ffe3fe1]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}
[272f46f8]596/*----------------------------------------------------------------------------*/
[bbce2c2]597void remote_usbhc_write(
[ffe3fe1]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
[365e29e2]611 const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) };
[bdd8ad2f]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);
[ffe3fe1]616
617 async_transaction_t *trans = async_transaction_create(callid);
618 if (trans == NULL) {
619 async_answer_0(callid, ENOMEM);
620 return;
621 }
622
[272f46f8]623 size_t size = 0;
[bdd8ad2f]624 if (data_buffer_len > 0) {
[272f46f8]625 const int rc = async_data_write_accept(&trans->buffer, false,
[bdd8ad2f]626 1, USB_MAX_PAYLOAD_SIZE,
[272f46f8]627 0, &size);
[ffe3fe1]628
[bdd8ad2f]629 if (rc != EOK) {
630 async_answer_0(callid, rc);
631 async_transaction_destroy(trans);
632 return;
633 }
[ffe3fe1]634 }
635
[272f46f8]636 const int rc = hc_iface->write(
637 fun, target, setup, trans->buffer, size, callback_out, trans);
[ffe3fe1]638
639 if (rc != EOK) {
640 async_answer_0(callid, rc);
641 async_transaction_destroy(trans);
642 }
643}
[91db50ac]644/**
645 * @}
646 */
Note: See TracBrowser for help on using the repository browser.