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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since e29e09cf was 17aca1c, checked in by Vojtech Horky <vojtechhorky@…>, 14 years ago

Merge mainline changes

  • Property mode set to 100644
File size: 17.2 KB
RevLine 
[91db50ac]1/*
[9753220]2 * Copyright (c) 2010-2011 Vojtech Horky
[91db50ac]3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup libdrv
30 * @{
31 */
32/** @file
33 */
34
35#include <async.h>
36#include <errno.h>
37
[cb59f787]38#include "usbhc_iface.h"
[91db50ac]39#include "driver.h"
40
[1b22bd4]41#define USB_MAX_PAYLOAD_SIZE 1020
42
[aae339e9]43static void remote_usbhc_get_address(device_t *, void *, ipc_callid_t, ipc_call_t *);
[cb59f787]44static void remote_usbhc_get_buffer(device_t *, void *, ipc_callid_t, ipc_call_t *);
45static void remote_usbhc_interrupt_out(device_t *, void *, ipc_callid_t, ipc_call_t *);
46static void remote_usbhc_interrupt_in(device_t *, void *, ipc_callid_t, ipc_call_t *);
[a3dfb2e]47static void remote_usbhc_control_write_setup(device_t *, void *, ipc_callid_t, ipc_call_t *);
48static void remote_usbhc_control_write_data(device_t *, void *, ipc_callid_t, ipc_call_t *);
49static void remote_usbhc_control_write_status(device_t *, void *, ipc_callid_t, ipc_call_t *);
50static void remote_usbhc_control_read_setup(device_t *, void *, ipc_callid_t, ipc_call_t *);
51static void remote_usbhc_control_read_data(device_t *, void *, ipc_callid_t, ipc_call_t *);
52static void remote_usbhc_control_read_status(device_t *, void *, ipc_callid_t, ipc_call_t *);
[9753220]53static void remote_usbhc_control_write(device_t *, void *, ipc_callid_t, ipc_call_t *);
54static void remote_usbhc_control_read(device_t *, void *, ipc_callid_t, ipc_call_t *);
[6f04905]55static void remote_usbhc_reserve_default_address(device_t *, void *, ipc_callid_t, ipc_call_t *);
56static void remote_usbhc_release_default_address(device_t *, void *, ipc_callid_t, ipc_call_t *);
57static void remote_usbhc_request_address(device_t *, void *, ipc_callid_t, ipc_call_t *);
[4689d40]58static void remote_usbhc_bind_address(device_t *, void *, ipc_callid_t, ipc_call_t *);
[6f04905]59static void remote_usbhc_release_address(device_t *, void *, ipc_callid_t, ipc_call_t *);
[a3dfb2e]60//static void remote_usbhc(device_t *, void *, ipc_callid_t, ipc_call_t *);
[91db50ac]61
[6edd494]62/** Remote USB host controller interface operations. */
[cb59f787]63static remote_iface_func_ptr_t remote_usbhc_iface_ops [] = {
[aae339e9]64 remote_usbhc_get_address,
[6f04905]65
[aae339e9]66 remote_usbhc_get_buffer,
[6f04905]67
68 remote_usbhc_reserve_default_address,
69 remote_usbhc_release_default_address,
70
71 remote_usbhc_request_address,
[4689d40]72 remote_usbhc_bind_address,
[6f04905]73 remote_usbhc_release_address,
74
[aae339e9]75 remote_usbhc_interrupt_out,
[a3dfb2e]76 remote_usbhc_interrupt_in,
[6f04905]77
[a3dfb2e]78 remote_usbhc_control_write_setup,
79 remote_usbhc_control_write_data,
80 remote_usbhc_control_write_status,
[6f04905]81
[a3dfb2e]82 remote_usbhc_control_read_setup,
83 remote_usbhc_control_read_data,
[9753220]84 remote_usbhc_control_read_status,
85
86 remote_usbhc_control_write,
87 remote_usbhc_control_read
[91db50ac]88};
89
[6edd494]90/** Remote USB host controller interface structure.
[91db50ac]91 */
[cb59f787]92remote_iface_t remote_usbhc_iface = {
93 .method_count = sizeof(remote_usbhc_iface_ops) /
94 sizeof(remote_usbhc_iface_ops[0]),
95 .methods = remote_usbhc_iface_ops
[91db50ac]96};
97
[1b22bd4]98typedef struct {
99 ipc_callid_t caller;
100 void *buffer;
[9753220]101 void *setup_packet;
[1b22bd4]102 size_t size;
103} async_transaction_t;
[91db50ac]104
[93f8da1]105static void async_transaction_destroy(async_transaction_t *trans)
106{
107 if (trans == NULL) {
108 return;
109 }
110
111 if (trans->setup_packet != NULL) {
112 free(trans->setup_packet);
113 }
114 if (trans->buffer != NULL) {
115 free(trans->buffer);
116 }
117
118 free(trans);
119}
120
121static async_transaction_t *async_transaction_create(ipc_callid_t caller)
122{
123 async_transaction_t *trans = malloc(sizeof(async_transaction_t));
124 if (trans == NULL) {
125 return NULL;
126 }
127
128 trans->caller = caller;
129 trans->buffer = NULL;
130 trans->setup_packet = NULL;
131 trans->size = 0;
132
133 return trans;
134}
135
[aae339e9]136void remote_usbhc_get_address(device_t *device, void *iface,
137 ipc_callid_t callid, ipc_call_t *call)
138{
139 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
140
141 if (!usb_iface->tell_address) {
[17aca1c]142 async_answer_0(callid, ENOTSUP);
[aae339e9]143 return;
144 }
145
[eac610e]146 devman_handle_t handle = DEV_IPC_GET_ARG1(*call);
[aae339e9]147
148 usb_address_t address;
149 int rc = usb_iface->tell_address(device, handle, &address);
150 if (rc != EOK) {
[17aca1c]151 async_answer_0(callid, rc);
[aae339e9]152 } else {
[17aca1c]153 async_answer_1(callid, EOK, address);
[aae339e9]154 }
155}
[91db50ac]156
[cb59f787]157void remote_usbhc_get_buffer(device_t *device, void *iface,
[91db50ac]158 ipc_callid_t callid, ipc_call_t *call)
159{
[a9b6bec]160 sysarg_t buffer_hash = DEV_IPC_GET_ARG1(*call);
[1b22bd4]161 async_transaction_t * trans = (async_transaction_t *)buffer_hash;
162 if (trans == NULL) {
[17aca1c]163 async_answer_0(callid, ENOENT);
[1b22bd4]164 return;
165 }
166 if (trans->buffer == NULL) {
[17aca1c]167 async_answer_0(callid, EINVAL);
[93f8da1]168 async_transaction_destroy(trans);
[1b22bd4]169 return;
170 }
171
172 ipc_callid_t cid;
173 size_t accepted_size;
174 if (!async_data_read_receive(&cid, &accepted_size)) {
[17aca1c]175 async_answer_0(callid, EINVAL);
[93f8da1]176 async_transaction_destroy(trans);
[1b22bd4]177 return;
178 }
179
180 if (accepted_size > trans->size) {
181 accepted_size = trans->size;
182 }
[eac610e]183 async_data_read_finalize(cid, trans->buffer, accepted_size);
[1b22bd4]184
[17aca1c]185 async_answer_1(callid, EOK, accepted_size);
[1b22bd4]186
[93f8da1]187 async_transaction_destroy(trans);
[1b22bd4]188}
189
[6f04905]190void remote_usbhc_reserve_default_address(device_t *device, void *iface,
191 ipc_callid_t callid, ipc_call_t *call)
192{
193 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
194
195 if (!usb_iface->reserve_default_address) {
[17aca1c]196 async_answer_0(callid, ENOTSUP);
[6f04905]197 return;
198 }
199
200 int rc = usb_iface->reserve_default_address(device);
201
[17aca1c]202 async_answer_0(callid, rc);
[6f04905]203}
204
205void remote_usbhc_release_default_address(device_t *device, void *iface,
206 ipc_callid_t callid, ipc_call_t *call)
207{
208 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
209
210 if (!usb_iface->release_default_address) {
[17aca1c]211 async_answer_0(callid, ENOTSUP);
[6f04905]212 return;
213 }
214
215 int rc = usb_iface->release_default_address(device);
216
[17aca1c]217 async_answer_0(callid, rc);
[6f04905]218}
219
220void remote_usbhc_request_address(device_t *device, void *iface,
221 ipc_callid_t callid, ipc_call_t *call)
222{
223 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
224
225 if (!usb_iface->request_address) {
[17aca1c]226 async_answer_0(callid, ENOTSUP);
[6f04905]227 return;
228 }
229
230 usb_address_t address;
231 int rc = usb_iface->request_address(device, &address);
232 if (rc != EOK) {
[17aca1c]233 async_answer_0(callid, rc);
[6f04905]234 } else {
[17aca1c]235 async_answer_1(callid, EOK, (sysarg_t) address);
[6f04905]236 }
237}
238
[4689d40]239void remote_usbhc_bind_address(device_t *device, void *iface,
240 ipc_callid_t callid, ipc_call_t *call)
241{
242 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
243
244 if (!usb_iface->bind_address) {
[17aca1c]245 async_answer_0(callid, ENOTSUP);
[4689d40]246 return;
247 }
248
[eac610e]249 usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call);
250 devman_handle_t handle = (devman_handle_t) DEV_IPC_GET_ARG2(*call);
[4689d40]251
252 int rc = usb_iface->bind_address(device, address, handle);
253
[17aca1c]254 async_answer_0(callid, rc);
[4689d40]255}
256
[6f04905]257void remote_usbhc_release_address(device_t *device, void *iface,
258 ipc_callid_t callid, ipc_call_t *call)
259{
260 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
261
262 if (!usb_iface->release_address) {
[17aca1c]263 async_answer_0(callid, ENOTSUP);
[6f04905]264 return;
265 }
266
[eac610e]267 usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call);
[6f04905]268
269 int rc = usb_iface->release_address(device, address);
270
[17aca1c]271 async_answer_0(callid, rc);
[6f04905]272}
273
[1b22bd4]274
275static void callback_out(device_t *device,
276 usb_transaction_outcome_t outcome, void *arg)
277{
278 async_transaction_t *trans = (async_transaction_t *)arg;
279
[17aca1c]280 async_answer_0(trans->caller, outcome);
[1b22bd4]281
[93f8da1]282 async_transaction_destroy(trans);
[1b22bd4]283}
284
285static void callback_in(device_t *device,
286 usb_transaction_outcome_t outcome, size_t actual_size, void *arg)
287{
288 async_transaction_t *trans = (async_transaction_t *)arg;
289
[93f8da1]290 if (outcome != USB_OUTCOME_OK) {
[17aca1c]291 async_answer_0(trans->caller, outcome);
[93f8da1]292 async_transaction_destroy(trans);
293 return;
294 }
[1b22bd4]295
296 trans->size = actual_size;
[17aca1c]297 async_answer_1(trans->caller, USB_OUTCOME_OK, (sysarg_t)trans);
[91db50ac]298}
299
[fb1dca09]300/** Process an outgoing transfer (both OUT and SETUP).
301 *
302 * @param device Target device.
303 * @param callid Initiating caller.
304 * @param call Initiating call.
305 * @param transfer_func Transfer function (might be NULL).
306 */
307static void remote_usbhc_out_transfer(device_t *device,
308 ipc_callid_t callid, ipc_call_t *call,
309 usbhc_iface_transfer_out_t transfer_func)
[91db50ac]310{
[fb1dca09]311 if (!transfer_func) {
[17aca1c]312 async_answer_0(callid, ENOTSUP);
[fb1dca09]313 return;
314 }
[1b22bd4]315
[eac610e]316 size_t expected_len = DEV_IPC_GET_ARG3(*call);
[1b22bd4]317 usb_target_t target = {
[eac610e]318 .address = DEV_IPC_GET_ARG1(*call),
319 .endpoint = DEV_IPC_GET_ARG2(*call)
[1b22bd4]320 };
321
322 size_t len = 0;
323 void *buffer = NULL;
324 if (expected_len > 0) {
325 int rc = async_data_write_accept(&buffer, false,
326 1, USB_MAX_PAYLOAD_SIZE,
327 0, &len);
328
329 if (rc != EOK) {
[17aca1c]330 async_answer_0(callid, rc);
[1b22bd4]331 return;
332 }
333 }
334
[93f8da1]335 async_transaction_t *trans = async_transaction_create(callid);
336 if (trans == NULL) {
337 if (buffer != NULL) {
338 free(buffer);
339 }
[17aca1c]340 async_answer_0(callid, ENOMEM);
[93f8da1]341 return;
342 }
343
[fb1dca09]344 trans->buffer = buffer;
345 trans->size = len;
[1b22bd4]346
[fb1dca09]347 int rc = transfer_func(device, target, buffer, len,
[1b22bd4]348 callback_out, trans);
349
350 if (rc != EOK) {
[17aca1c]351 async_answer_0(callid, rc);
[93f8da1]352 async_transaction_destroy(trans);
[1b22bd4]353 }
[91db50ac]354}
355
[fb1dca09]356/** Process an incoming transfer.
357 *
358 * @param device Target device.
359 * @param callid Initiating caller.
360 * @param call Initiating call.
361 * @param transfer_func Transfer function (might be NULL).
362 */
363static void remote_usbhc_in_transfer(device_t *device,
364 ipc_callid_t callid, ipc_call_t *call,
365 usbhc_iface_transfer_in_t transfer_func)
[91db50ac]366{
[fb1dca09]367 if (!transfer_func) {
[17aca1c]368 async_answer_0(callid, ENOTSUP);
[fb1dca09]369 return;
370 }
[1b22bd4]371
[eac610e]372 size_t len = DEV_IPC_GET_ARG3(*call);
[1b22bd4]373 usb_target_t target = {
[eac610e]374 .address = DEV_IPC_GET_ARG1(*call),
375 .endpoint = DEV_IPC_GET_ARG2(*call)
[1b22bd4]376 };
377
[93f8da1]378 async_transaction_t *trans = async_transaction_create(callid);
379 if (trans == NULL) {
[17aca1c]380 async_answer_0(callid, ENOMEM);
[93f8da1]381 return;
382 }
[1b22bd4]383 trans->buffer = malloc(len);
384 trans->size = len;
385
[fb1dca09]386 int rc = transfer_func(device, target, trans->buffer, len,
[1b22bd4]387 callback_in, trans);
388
389 if (rc != EOK) {
[17aca1c]390 async_answer_0(callid, rc);
[93f8da1]391 async_transaction_destroy(trans);
[1b22bd4]392 }
[91db50ac]393}
394
[fb1dca09]395/** Process status part of control transfer.
396 *
397 * @param device Target device.
398 * @param callid Initiating caller.
399 * @param call Initiating call.
400 * @param direction Transfer direction (read ~ in, write ~ out).
401 * @param transfer_in_func Transfer function for control read (might be NULL).
402 * @param transfer_out_func Transfer function for control write (might be NULL).
403 */
404static void remote_usbhc_status_transfer(device_t *device,
405 ipc_callid_t callid, ipc_call_t *call,
406 usb_direction_t direction,
407 int (*transfer_in_func)(device_t *, usb_target_t,
408 usbhc_iface_transfer_in_callback_t, void *),
409 int (*transfer_out_func)(device_t *, usb_target_t,
410 usbhc_iface_transfer_out_callback_t, void *))
[a3dfb2e]411{
[fb1dca09]412 switch (direction) {
413 case USB_DIRECTION_IN:
414 if (!transfer_in_func) {
[17aca1c]415 async_answer_0(callid, ENOTSUP);
[fb1dca09]416 return;
417 }
418 break;
419 case USB_DIRECTION_OUT:
420 if (!transfer_out_func) {
[17aca1c]421 async_answer_0(callid, ENOTSUP);
[fb1dca09]422 return;
423 }
424 break;
425 default:
426 assert(false && "unreachable code");
427 break;
428 }
[a3dfb2e]429
430 usb_target_t target = {
[eac610e]431 .address = DEV_IPC_GET_ARG1(*call),
432 .endpoint = DEV_IPC_GET_ARG2(*call)
[a3dfb2e]433 };
434
[93f8da1]435 async_transaction_t *trans = async_transaction_create(callid);
436 if (trans == NULL) {
[17aca1c]437 async_answer_0(callid, ENOMEM);
[93f8da1]438 return;
439 }
[a3dfb2e]440
[fb1dca09]441 int rc;
442 switch (direction) {
443 case USB_DIRECTION_IN:
444 rc = transfer_in_func(device, target,
445 callback_in, trans);
446 break;
447 case USB_DIRECTION_OUT:
448 rc = transfer_out_func(device, target,
449 callback_out, trans);
450 break;
451 default:
452 assert(false && "unreachable code");
453 break;
454 }
[a3dfb2e]455
456 if (rc != EOK) {
[17aca1c]457 async_answer_0(callid, rc);
[93f8da1]458 async_transaction_destroy(trans);
[a3dfb2e]459 }
460}
461
[fb1dca09]462
463void remote_usbhc_interrupt_out(device_t *device, void *iface,
464 ipc_callid_t callid, ipc_call_t *call)
[a3dfb2e]465{
466 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
[fb1dca09]467 assert(usb_iface != NULL);
[a3dfb2e]468
[fb1dca09]469 return remote_usbhc_out_transfer(device, callid, call,
470 usb_iface->interrupt_out);
471}
[a3dfb2e]472
[fb1dca09]473void remote_usbhc_interrupt_in(device_t *device, void *iface,
474 ipc_callid_t callid, ipc_call_t *call)
475{
476 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
477 assert(usb_iface != NULL);
[a3dfb2e]478
[fb1dca09]479 return remote_usbhc_in_transfer(device, callid, call,
480 usb_iface->interrupt_in);
481}
[a3dfb2e]482
[fb1dca09]483void remote_usbhc_control_write_setup(device_t *device, void *iface,
484 ipc_callid_t callid, ipc_call_t *call)
485{
486 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
487 assert(usb_iface != NULL);
[a3dfb2e]488
[fb1dca09]489 return remote_usbhc_out_transfer(device, callid, call,
490 usb_iface->control_write_setup);
491}
[a3dfb2e]492
[fb1dca09]493void remote_usbhc_control_write_data(device_t *device, void *iface,
494 ipc_callid_t callid, ipc_call_t *call)
495{
496 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
497 assert(usb_iface != NULL);
[a3dfb2e]498
[fb1dca09]499 return remote_usbhc_out_transfer(device, callid, call,
500 usb_iface->control_write_data);
[a3dfb2e]501}
502
503void remote_usbhc_control_write_status(device_t *device, void *iface,
[fb1dca09]504 ipc_callid_t callid, ipc_call_t *call)
[a3dfb2e]505{
506 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
[fb1dca09]507 assert(usb_iface != NULL);
[a3dfb2e]508
[fb1dca09]509 return remote_usbhc_status_transfer(device, callid, call,
510 USB_DIRECTION_IN, usb_iface->control_write_status, NULL);
[a3dfb2e]511}
512
513void remote_usbhc_control_read_setup(device_t *device, void *iface,
[fb1dca09]514 ipc_callid_t callid, ipc_call_t *call)
[a3dfb2e]515{
516 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
[fb1dca09]517 assert(usb_iface != NULL);
[a3dfb2e]518
[fb1dca09]519 return remote_usbhc_out_transfer(device, callid, call,
520 usb_iface->control_read_setup);
[a3dfb2e]521}
522
523void remote_usbhc_control_read_data(device_t *device, void *iface,
524 ipc_callid_t callid, ipc_call_t *call)
525{
526 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
[fb1dca09]527 assert(usb_iface != NULL);
[a3dfb2e]528
[fb1dca09]529 return remote_usbhc_in_transfer(device, callid, call,
530 usb_iface->control_read_data);
[a3dfb2e]531}
532
533void remote_usbhc_control_read_status(device_t *device, void *iface,
534 ipc_callid_t callid, ipc_call_t *call)
535{
536 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
[fb1dca09]537 assert(usb_iface != NULL);
[a3dfb2e]538
[fb1dca09]539 return remote_usbhc_status_transfer(device, callid, call,
540 USB_DIRECTION_OUT, NULL, usb_iface->control_read_status);
[a3dfb2e]541}
542
[9753220]543void remote_usbhc_control_write(device_t *device, void *iface,
544ipc_callid_t callid, ipc_call_t *call)
545{
546 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
547 assert(usb_iface != NULL);
548
549 if (!usb_iface->control_write) {
[17aca1c]550 async_answer_0(callid, ENOTSUP);
[9753220]551 return;
552 }
553
554 usb_target_t target = {
555 .address = DEV_IPC_GET_ARG1(*call),
556 .endpoint = DEV_IPC_GET_ARG2(*call)
557 };
558
559 int rc;
560
561 void *setup_packet = NULL;
562 void *data_buffer = NULL;
563 size_t setup_packet_len = 0;
564 size_t data_buffer_len = 0;
565
566 rc = async_data_write_accept(&setup_packet, false,
567 1, USB_MAX_PAYLOAD_SIZE, 0, &setup_packet_len);
568 if (rc != EOK) {
[17aca1c]569 async_answer_0(callid, rc);
[9753220]570 return;
571 }
572 rc = async_data_write_accept(&data_buffer, false,
573 1, USB_MAX_PAYLOAD_SIZE, 0, &data_buffer_len);
574 if (rc != EOK) {
[17aca1c]575 async_answer_0(callid, rc);
[93f8da1]576 free(setup_packet);
[9753220]577 return;
578 }
579
[93f8da1]580 async_transaction_t *trans = async_transaction_create(callid);
581 if (trans == NULL) {
[17aca1c]582 async_answer_0(callid, ENOMEM);
[93f8da1]583 free(setup_packet);
584 free(data_buffer);
585 return;
586 }
[9753220]587 trans->setup_packet = setup_packet;
588 trans->buffer = data_buffer;
589 trans->size = data_buffer_len;
590
591 rc = usb_iface->control_write(device, target,
592 setup_packet, setup_packet_len,
593 data_buffer, data_buffer_len,
594 callback_out, trans);
595
596 if (rc != EOK) {
[17aca1c]597 async_answer_0(callid, rc);
[93f8da1]598 async_transaction_destroy(trans);
[9753220]599 }
600}
601
602
603void remote_usbhc_control_read(device_t *device, void *iface,
604ipc_callid_t callid, ipc_call_t *call)
605{
606 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
607 assert(usb_iface != NULL);
608
609 if (!usb_iface->control_read) {
[17aca1c]610 async_answer_0(callid, ENOTSUP);
[9753220]611 return;
612 }
613
614 size_t data_len = DEV_IPC_GET_ARG3(*call);
615 usb_target_t target = {
616 .address = DEV_IPC_GET_ARG1(*call),
617 .endpoint = DEV_IPC_GET_ARG2(*call)
618 };
619
620 int rc;
621
622 void *setup_packet = NULL;
623 size_t setup_packet_len = 0;
624
625 rc = async_data_write_accept(&setup_packet, false,
626 1, USB_MAX_PAYLOAD_SIZE, 0, &setup_packet_len);
627 if (rc != EOK) {
[17aca1c]628 async_answer_0(callid, rc);
[9753220]629 return;
630 }
631
[93f8da1]632 async_transaction_t *trans = async_transaction_create(callid);
633 if (trans == NULL) {
[17aca1c]634 async_answer_0(callid, ENOMEM);
[93f8da1]635 free(setup_packet);
636 return;
637 }
[9753220]638 trans->setup_packet = setup_packet;
639 trans->size = data_len;
[93f8da1]640 trans->buffer = malloc(data_len);
641 if (trans->buffer == NULL) {
[17aca1c]642 async_answer_0(callid, ENOMEM);
[93f8da1]643 async_transaction_destroy(trans);
644 return;
645 }
[9753220]646
647 rc = usb_iface->control_read(device, target,
648 setup_packet, setup_packet_len,
649 trans->buffer, trans->size,
650 callback_in, trans);
651
652 if (rc != EOK) {
[17aca1c]653 async_answer_0(callid, rc);
[93f8da1]654 async_transaction_destroy(trans);
[9753220]655 }
656}
657
[a3dfb2e]658
[1b22bd4]659
[91db50ac]660/**
661 * @}
662 */
Note: See TracBrowser for help on using the repository browser.