source: mainline/uspace/lib/drv/generic/remote_usb.c@ 479e32d

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 479e32d was 327f147, checked in by Ondřej Hlavatý <aearsis@…>, 8 years ago

usbhost: change parameters of methods

Pass (device_t, usb_target_t) to read and write, which finally allows to drop hash tables and access device right away. Then, all callbacks to complete transfer now uses usb_transfer_batch. This requires libdrv to include libusbhost, but it is not linked against it - it is there only to share definition of usb_transfer_batch_t.

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