source: mainline/uspace/lib/drv/generic/remote_usb.c@ 9b2f69e

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 9b2f69e was 816f5f4, checked in by Michal Staruch <salmelu@…>, 8 years ago

Remote USB (async) sending structures

remote_usb_register_endpoint is now sending a whole new structure, instead of 5 numeric arguments pulled out of structure.
This allows future extensibility for the structure as well as a working code to be used for other remote async calls.

  • Property mode set to 100644
File size: 17.0 KB
RevLine 
[56fb3732]1/*
2 * Copyright (c) 2010 Vojtech Horky
[56bdd9a4]3 * Copyright (c) 2011 Jan Vesely
[56fb3732]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>
[9be30cdf]37#include <macros.h>
[56fb3732]38#include <errno.h>
[e938fa6]39#include <devman.h>
[56fb3732]40
41#include "usb_iface.h"
[eb1a2f4]42#include "ddf/driver.h"
[56fb3732]43
[56bdd9a4]44
[94fbf78]45usb_dev_session_t *usb_dev_connect(devman_handle_t handle)
[56bdd9a4]46{
[b4b534ac]47 return devman_device_connect(handle, IPC_FLAG_BLOCKING);
[94fbf78]48}
[56bdd9a4]49
[94fbf78]50usb_dev_session_t *usb_dev_connect_to_self(ddf_dev_t *dev)
[e938fa6]51{
[b4b534ac]52 return devman_parent_device_connect(ddf_dev_get_handle(dev), IPC_FLAG_BLOCKING);
[e938fa6]53}
54
[71384bd3]55void usb_dev_disconnect(usb_dev_session_t *sess)
[e938fa6]56{
57 if (sess)
58 async_hangup(sess);
[56bdd9a4]59}
[a76b01b4]60
[56bdd9a4]61typedef enum {
62 IPC_M_USB_GET_MY_INTERFACE,
[3121b5f]63 IPC_M_USB_GET_MY_DEVICE_HANDLE,
[e938fa6]64 IPC_M_USB_RESERVE_DEFAULT_ADDRESS,
65 IPC_M_USB_RELEASE_DEFAULT_ADDRESS,
66 IPC_M_USB_DEVICE_ENUMERATE,
67 IPC_M_USB_DEVICE_REMOVE,
[70a422b]68 IPC_M_USB_REGISTER_ENDPOINT,
69 IPC_M_USB_UNREGISTER_ENDPOINT,
[64e1fb2]70 IPC_M_USB_READ,
71 IPC_M_USB_WRITE,
[56bdd9a4]72} usb_iface_funcs_t;
73
74/** Tell interface number given device can use.
75 * @param[in] exch IPC communication exchange
76 * @param[in] handle Id of the device
77 * @param[out] usb_iface Assigned USB interface
78 * @return Error code.
79 */
80int usb_get_my_interface(async_exch_t *exch, int *usb_iface)
81{
82 if (!exch)
[8afeb04]83 return EBADMEM;
[56bdd9a4]84 sysarg_t iface_no;
85 const int ret = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
86 IPC_M_USB_GET_MY_INTERFACE, &iface_no);
87 if (ret == EOK && usb_iface)
88 *usb_iface = (int)iface_no;
89 return ret;
90}
[a76b01b4]91
[9d15d1b]92/** Tell devman handle of the usb device function.
[58563585]93 *
94 * @param[in] exch IPC communication exchange
[9d15d1b]95 * @param[out] handle devman handle of the HC used by the target device.
[58563585]96 *
[56bdd9a4]97 * @return Error code.
[58563585]98 *
[56bdd9a4]99 */
[3121b5f]100int usb_get_my_device_handle(async_exch_t *exch, devman_handle_t *handle)
[9d15d1b]101{
102 devman_handle_t h = 0;
103 const int ret = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
[3121b5f]104 IPC_M_USB_GET_MY_DEVICE_HANDLE, &h);
[9d15d1b]105 if (ret == EOK && handle)
106 *handle = (devman_handle_t)h;
107 return ret;
108}
109
[e938fa6]110/** Reserve default USB address.
111 * @param[in] exch IPC communication exchange
112 * @param[in] speed Communication speed of the newly attached device
113 * @return Error code.
114 */
115int usb_reserve_default_address(async_exch_t *exch, usb_speed_t speed)
[56bdd9a4]116{
117 if (!exch)
[8afeb04]118 return EBADMEM;
[e938fa6]119 return async_req_2_0(exch, DEV_IFACE_ID(USB_DEV_IFACE),
120 IPC_M_USB_RESERVE_DEFAULT_ADDRESS, speed);
121}
122
123/** Release default USB address.
[58563585]124 *
[e938fa6]125 * @param[in] exch IPC communication exchange
[58563585]126 *
[e938fa6]127 * @return Error code.
[58563585]128 *
[e938fa6]129 */
130int usb_release_default_address(async_exch_t *exch)
131{
132 if (!exch)
133 return EBADMEM;
134 return async_req_1_0(exch, DEV_IFACE_ID(USB_DEV_IFACE),
135 IPC_M_USB_RELEASE_DEFAULT_ADDRESS);
136}
137
138/** Trigger USB device enumeration
[58563585]139 *
140 * @param[in] exch IPC communication exchange
[e938fa6]141 * @param[out] handle Identifier of the newly added device (if successful)
[58563585]142 *
[e938fa6]143 * @return Error code.
[58563585]144 *
[e938fa6]145 */
[0918382f]146int usb_device_enumerate(async_exch_t *exch, unsigned port)
[e938fa6]147{
[0918382f]148 if (!exch)
[e938fa6]149 return EBADMEM;
[0918382f]150 const int ret = async_req_2_0(exch, DEV_IFACE_ID(USB_DEV_IFACE),
151 IPC_M_USB_DEVICE_ENUMERATE, port);
[56bdd9a4]152 return ret;
153}
154
[e938fa6]155/** Trigger USB device enumeration
[58563585]156 *
157 * @param[in] exch IPC communication exchange
[e938fa6]158 * @param[in] handle Identifier of the device
[58563585]159 *
[e938fa6]160 * @return Error code.
[58563585]161 *
[e938fa6]162 */
[0918382f]163int usb_device_remove(async_exch_t *exch, unsigned port)
[e938fa6]164{
165 if (!exch)
166 return EBADMEM;
167 return async_req_2_0(exch, DEV_IFACE_ID(USB_DEV_IFACE),
[0918382f]168 IPC_M_USB_DEVICE_REMOVE, port);
[e938fa6]169}
[56fb3732]170
[4e732f1a]171int static_assert[sizeof(sysarg_t) >= 4 ? 1 : -1];
172typedef union {
173 uint8_t arr[sizeof(sysarg_t)];
174 sysarg_t arg;
175} pack8_t;
176
[816f5f4]177int usb_register_endpoint(async_exch_t *exch,
178 usb_endpoint_desc_t *endpoint_desc)
[70a422b]179{
180 if (!exch)
181 return EBADMEM;
182
[816f5f4]183 aid_t opening_request = async_send_1(exch,
184 DEV_IFACE_ID(USB_DEV_IFACE), IPC_M_USB_REGISTER_ENDPOINT, NULL);
[70a422b]185
[816f5f4]186 if (opening_request == 0) {
187 return ENOMEM;
188 }
189
190 const int ret = async_data_write_start(exch, (void *) endpoint_desc,
191 sizeof(usb_endpoint_desc_t));
192
193 if (ret != EOK) {
194 async_forget(opening_request);
195 return ret;
196 }
197
198 /* Wait for the answer. */
199 sysarg_t opening_request_rc;
200 async_wait_for(opening_request, &opening_request_rc);
201
202 return (int) opening_request_rc;
[70a422b]203}
204
[816f5f4]205int usb_unregister_endpoint(async_exch_t *exch,
206 usb_endpoint_desc_t *endpoint_desc)
[70a422b]207{
208 if (!exch)
209 return EBADMEM;
[816f5f4]210
211 aid_t opening_request = async_send_1(exch,
212 DEV_IFACE_ID(USB_DEV_IFACE), IPC_M_USB_UNREGISTER_ENDPOINT, NULL);
213
214 if (opening_request == 0) {
215 return ENOMEM;
216 }
217
218 const int ret = async_data_write_start(exch, endpoint_desc,
219 sizeof(usb_endpoint_desc_t));
220 if (ret != EOK) {
221 async_forget(opening_request);
222 return ret;
223 }
224
225 /* Wait for the answer. */
226 sysarg_t opening_request_rc;
227 async_wait_for(opening_request, &opening_request_rc);
228
229 return (int) opening_request_rc;
[70a422b]230}
231
[64e1fb2]232int usb_read(async_exch_t *exch, usb_endpoint_t endpoint, uint64_t setup,
233 void *data, size_t size, size_t *rec_size)
234{
235 if (!exch)
236 return EBADMEM;
237
238 if (size == 0 && setup == 0)
239 return EOK;
240
241 /* Make call identifying target USB device and type of transfer. */
242 aid_t opening_request = async_send_4(exch,
243 DEV_IFACE_ID(USB_DEV_IFACE), IPC_M_USB_READ, endpoint,
244 (setup & UINT32_MAX), (setup >> 32), NULL);
245
246 if (opening_request == 0) {
247 return ENOMEM;
248 }
249
250 /* Retrieve the data. */
251 ipc_call_t data_request_call;
252 aid_t data_request =
253 async_data_read(exch, data, size, &data_request_call);
254
255 if (data_request == 0) {
256 // FIXME: How to let the other side know that we want to abort?
257 async_forget(opening_request);
258 return ENOMEM;
259 }
260
261 /* Wait for the answer. */
262 sysarg_t data_request_rc;
263 sysarg_t opening_request_rc;
264 async_wait_for(data_request, &data_request_rc);
265 async_wait_for(opening_request, &opening_request_rc);
266
267 if (data_request_rc != EOK) {
268 /* Prefer the return code of the opening request. */
269 if (opening_request_rc != EOK) {
270 return (int) opening_request_rc;
271 } else {
272 return (int) data_request_rc;
273 }
274 }
275 if (opening_request_rc != EOK) {
276 return (int) opening_request_rc;
277 }
278
279 *rec_size = IPC_GET_ARG2(data_request_call);
280 return EOK;
281}
282
283int usb_write(async_exch_t *exch, usb_endpoint_t endpoint, uint64_t setup,
284 const void *data, size_t size)
285{
286 if (!exch)
287 return EBADMEM;
288
289 if (size == 0 && setup == 0)
290 return EOK;
291
292 aid_t opening_request = async_send_5(exch,
293 DEV_IFACE_ID(USB_DEV_IFACE), IPC_M_USB_WRITE, endpoint, size,
294 (setup & UINT32_MAX), (setup >> 32), NULL);
295
296 if (opening_request == 0) {
297 return ENOMEM;
298 }
299
300 /* Send the data if any. */
301 if (size > 0) {
302 const int ret = async_data_write_start(exch, data, size);
303 if (ret != EOK) {
304 async_forget(opening_request);
305 return ret;
306 }
307 }
308
309 /* Wait for the answer. */
310 sysarg_t opening_request_rc;
311 async_wait_for(opening_request, &opening_request_rc);
312
313 return (int) opening_request_rc;
314}
[56fb3732]315
[317a463]316static void remote_usb_get_my_interface(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
[3121b5f]317static void remote_usb_get_my_device_handle(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
[e938fa6]318static void remote_usb_reserve_default_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
319static void remote_usb_release_default_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
320static void remote_usb_device_enumerate(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
321static void remote_usb_device_remove(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
[70a422b]322static void remote_usb_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
323static void remote_usb_unregister_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
[64e1fb2]324static void remote_usb_read(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call);
325static void remote_usb_write(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call);
[56fb3732]326
327/** Remote USB interface operations. */
[9be30cdf]328static const remote_iface_func_ptr_t remote_usb_iface_ops [] = {
[317a463]329 [IPC_M_USB_GET_MY_INTERFACE] = remote_usb_get_my_interface,
[3121b5f]330 [IPC_M_USB_GET_MY_DEVICE_HANDLE] = remote_usb_get_my_device_handle,
[e938fa6]331 [IPC_M_USB_RESERVE_DEFAULT_ADDRESS] = remote_usb_reserve_default_address,
332 [IPC_M_USB_RELEASE_DEFAULT_ADDRESS] = remote_usb_release_default_address,
333 [IPC_M_USB_DEVICE_ENUMERATE] = remote_usb_device_enumerate,
334 [IPC_M_USB_DEVICE_REMOVE] = remote_usb_device_remove,
[70a422b]335 [IPC_M_USB_REGISTER_ENDPOINT] = remote_usb_register_endpoint,
336 [IPC_M_USB_UNREGISTER_ENDPOINT] = remote_usb_unregister_endpoint,
[64e1fb2]337 [IPC_M_USB_READ] = remote_usb_read,
338 [IPC_M_USB_WRITE] = remote_usb_write,
[56fb3732]339};
340
341/** Remote USB interface structure.
342 */
[7f80313]343const remote_iface_t remote_usb_iface = {
[9be30cdf]344 .method_count = ARRAY_SIZE(remote_usb_iface_ops),
[e938fa6]345 .methods = remote_usb_iface_ops,
[56fb3732]346};
347
[816f5f4]348typedef struct {
349 ipc_callid_t caller;
350 ipc_callid_t data_caller;
351 void *buffer;
352} async_transaction_t;
353
[317a463]354void remote_usb_get_my_interface(ddf_fun_t *fun, void *iface,
[357a302]355 ipc_callid_t callid, ipc_call_t *call)
356{
[56bdd9a4]357 const usb_iface_t *usb_iface = (usb_iface_t *) iface;
[357a302]358
[317a463]359 if (usb_iface->get_my_interface == NULL) {
[357a302]360 async_answer_0(callid, ENOTSUP);
361 return;
362 }
363
[95120c3]364 int iface_no;
[56bdd9a4]365 const int ret = usb_iface->get_my_interface(fun, &iface_no);
366 if (ret != EOK) {
367 async_answer_0(callid, ret);
[357a302]368 } else {
[95120c3]369 async_answer_1(callid, EOK, iface_no);
[357a302]370 }
371}
[a76b01b4]372
[3121b5f]373void remote_usb_get_my_device_handle(ddf_fun_t *fun, void *iface,
[95120c3]374 ipc_callid_t callid, ipc_call_t *call)
375{
[56bdd9a4]376 const usb_iface_t *usb_iface = (usb_iface_t *) iface;
[95120c3]377
[3121b5f]378 if (usb_iface->get_my_device_handle == NULL) {
[95120c3]379 async_answer_0(callid, ENOTSUP);
380 return;
381 }
382
[9d15d1b]383 devman_handle_t handle;
[3121b5f]384 const int ret = usb_iface->get_my_device_handle(fun, &handle);
[56bdd9a4]385 if (ret != EOK) {
386 async_answer_0(callid, ret);
[95120c3]387 }
[9d15d1b]388
389 async_answer_1(callid, EOK, (sysarg_t) handle);
[95120c3]390}
[a76b01b4]391
[e938fa6]392void remote_usb_reserve_default_address(ddf_fun_t *fun, void *iface,
[56fb3732]393 ipc_callid_t callid, ipc_call_t *call)
394{
[56bdd9a4]395 const usb_iface_t *usb_iface = (usb_iface_t *) iface;
[56fb3732]396
[e938fa6]397 if (usb_iface->reserve_default_address == NULL) {
[17aca1c]398 async_answer_0(callid, ENOTSUP);
[56fb3732]399 return;
400 }
401
[e938fa6]402 usb_speed_t speed = DEV_IPC_GET_ARG1(*call);
403 const int ret = usb_iface->reserve_default_address(fun, speed);
404 async_answer_0(callid, ret);
405}
406
407void remote_usb_release_default_address(ddf_fun_t *fun, void *iface,
408 ipc_callid_t callid, ipc_call_t *call)
409{
410 const usb_iface_t *usb_iface = (usb_iface_t *) iface;
411
412 if (usb_iface->release_default_address == NULL) {
413 async_answer_0(callid, ENOTSUP);
414 return;
[56fb3732]415 }
416
[e938fa6]417 const int ret = usb_iface->release_default_address(fun);
418 async_answer_0(callid, ret);
419}
420
421static void remote_usb_device_enumerate(ddf_fun_t *fun, void *iface,
422 ipc_callid_t callid, ipc_call_t *call)
423{
424 const usb_iface_t *usb_iface = (usb_iface_t *) iface;
425
426 if (usb_iface->device_enumerate == NULL) {
427 async_answer_0(callid, ENOTSUP);
428 return;
429 }
430
[0918382f]431 const unsigned port = DEV_IPC_GET_ARG1(*call);
432 const int ret = usb_iface->device_enumerate(fun, port);
433 async_answer_0(callid, ret);
[e938fa6]434}
435
436static void remote_usb_device_remove(ddf_fun_t *fun, void *iface,
437 ipc_callid_t callid, ipc_call_t *call)
438{
439 const usb_iface_t *usb_iface = (usb_iface_t *) iface;
440
441 if (usb_iface->device_remove == NULL) {
442 async_answer_0(callid, ENOTSUP);
443 return;
444 }
445
[0918382f]446 const unsigned port = DEV_IPC_GET_ARG1(*call);
447 const int ret = usb_iface->device_remove(fun, port);
[e938fa6]448 async_answer_0(callid, ret);
449}
[70a422b]450
451static void remote_usb_register_endpoint(ddf_fun_t *fun, void *iface,
452 ipc_callid_t callid, ipc_call_t *call)
453{
[816f5f4]454 assert(fun);
455 assert(iface);
456 assert(call);
457
458 const usb_iface_t *usb_iface = iface;
[70a422b]459
460 if (!usb_iface->register_endpoint) {
461 async_answer_0(callid, ENOTSUP);
462 return;
463 }
464
[816f5f4]465 void *buffer = malloc(sizeof(usb_endpoint_desc_t));
466 if (!buffer) {
467 async_answer_0(callid, ENOMEM);
468 return;
469 }
[70a422b]470
[816f5f4]471 size_t size = 0;
472 int rc = async_data_write_accept(&buffer, false,
473 1, sizeof(usb_endpoint_desc_t), 0, &size);
[70a422b]474
[816f5f4]475 if (rc != EOK) {
476 free(buffer);
477 async_answer_0(callid, rc);
478 return;
479 }
[70a422b]480
[816f5f4]481 usb_endpoint_desc_t *endpoint_desc = (usb_endpoint_desc_t *) buffer;
482 rc = usb_iface->register_endpoint(fun, endpoint_desc);
483
484 free(buffer);
485 async_answer_0(callid, rc);
[70a422b]486}
487
488static void remote_usb_unregister_endpoint(ddf_fun_t *fun, void *iface,
489 ipc_callid_t callid, ipc_call_t *call)
490{
[816f5f4]491 assert(fun);
492 assert(iface);
493 assert(call);
494
495 const usb_iface_t *usb_iface = iface;
[70a422b]496
497 if (!usb_iface->unregister_endpoint) {
498 async_answer_0(callid, ENOTSUP);
499 return;
500 }
501
[816f5f4]502 void *buffer = malloc(sizeof(usb_endpoint_desc_t));
503 if (!buffer) {
504 async_answer_0(callid, ENOMEM);
505 return;
506 }
[70a422b]507
[816f5f4]508 size_t size = 0;
509 int rc = async_data_write_accept(&buffer, false,
510 1, sizeof(usb_endpoint_desc_t), 0, &size);
[70a422b]511
[816f5f4]512 if (rc != EOK) {
513 free(buffer);
514 async_answer_0(callid, rc);
515 return;
516 }
[64e1fb2]517
[816f5f4]518 usb_endpoint_desc_t *endpoint_desc = (usb_endpoint_desc_t *) buffer;
519 usb_iface->unregister_endpoint(fun, endpoint_desc);
520
521 free(buffer);
522 if (rc != EOK) {
523 async_answer_0(callid, rc);
524 }
525}
[64e1fb2]526
527static void async_transaction_destroy(async_transaction_t *trans)
528{
529 if (trans == NULL) {
530 return;
531 }
532 if (trans->buffer != NULL) {
533 free(trans->buffer);
534 }
535
536 free(trans);
537}
538
539static async_transaction_t *async_transaction_create(ipc_callid_t caller)
540{
541 async_transaction_t *trans = malloc(sizeof(async_transaction_t));
542 if (trans == NULL) {
543 return NULL;
544 }
545
546 trans->caller = caller;
547 trans->data_caller = 0;
548 trans->buffer = NULL;
549
550 return trans;
551}
552
553static void callback_out(int outcome, void *arg)
554{
555 async_transaction_t *trans = arg;
556
557 async_answer_0(trans->caller, outcome);
558
559 async_transaction_destroy(trans);
560}
561
562static void callback_in(int outcome, size_t actual_size, void *arg)
563{
564 async_transaction_t *trans = (async_transaction_t *)arg;
565
566 if (outcome != EOK) {
567 async_answer_0(trans->caller, outcome);
568 if (trans->data_caller) {
569 async_answer_0(trans->data_caller, EINTR);
570 }
571 async_transaction_destroy(trans);
572 return;
573 }
574
575 if (trans->data_caller) {
576 async_data_read_finalize(trans->data_caller,
577 trans->buffer, actual_size);
578 }
579
580 async_answer_0(trans->caller, EOK);
581
582 async_transaction_destroy(trans);
583}
584
585void remote_usb_read(
586 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
587{
588 assert(fun);
589 assert(iface);
590 assert(call);
591
592 const usb_iface_t *usb_iface = iface;
593
594 if (!usb_iface->read) {
595 async_answer_0(callid, ENOTSUP);
596 return;
597 }
598
599 const usb_endpoint_t ep = DEV_IPC_GET_ARG1(*call);
600 const uint64_t setup =
601 ((uint64_t)DEV_IPC_GET_ARG2(*call)) |
602 (((uint64_t)DEV_IPC_GET_ARG3(*call)) << 32);
603
604 async_transaction_t *trans = async_transaction_create(callid);
605 if (trans == NULL) {
606 async_answer_0(callid, ENOMEM);
607 return;
608 }
609
610 size_t size = 0;
611 if (!async_data_read_receive(&trans->data_caller, &size)) {
612 async_answer_0(callid, EPARTY);
[1e5d01b]613 async_transaction_destroy(trans);
[64e1fb2]614 return;
615 }
616
617 trans->buffer = malloc(size);
618 if (trans->buffer == NULL) {
619 async_answer_0(trans->data_caller, ENOMEM);
620 async_answer_0(callid, ENOMEM);
621 async_transaction_destroy(trans);
[c7840e9]622 return;
[64e1fb2]623 }
624
625 const int rc = usb_iface->read(
626 fun, ep, setup, trans->buffer, size, callback_in, trans);
627
628 if (rc != EOK) {
629 async_answer_0(trans->data_caller, rc);
630 async_answer_0(callid, rc);
631 async_transaction_destroy(trans);
632 }
633}
634
635void remote_usb_write(
636 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
637{
638 assert(fun);
639 assert(iface);
640 assert(call);
641
642 const usb_iface_t *usb_iface = iface;
643
644 if (!usb_iface->write) {
645 async_answer_0(callid, ENOTSUP);
646 return;
647 }
648
649 const usb_endpoint_t ep = DEV_IPC_GET_ARG1(*call);
650 const size_t data_buffer_len = DEV_IPC_GET_ARG2(*call);
651 const uint64_t setup =
652 ((uint64_t)DEV_IPC_GET_ARG3(*call)) |
653 (((uint64_t)DEV_IPC_GET_ARG4(*call)) << 32);
654
655 async_transaction_t *trans = async_transaction_create(callid);
656 if (trans == NULL) {
657 async_answer_0(callid, ENOMEM);
658 return;
659 }
660
661 size_t size = 0;
662 if (data_buffer_len > 0) {
663 const int rc = async_data_write_accept(&trans->buffer, false,
664 1, data_buffer_len, 0, &size);
665
666 if (rc != EOK) {
667 async_answer_0(callid, rc);
668 async_transaction_destroy(trans);
669 return;
670 }
671 }
672
673 const int rc = usb_iface->write(
674 fun, ep, setup, trans->buffer, size, callback_out, trans);
675
676 if (rc != EOK) {
677 async_answer_0(callid, rc);
678 async_transaction_destroy(trans);
679 }
[56fb3732]680}
681/**
682 * @}
683 */
Note: See TracBrowser for help on using the repository browser.