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

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

Merge development/ changes

  • Property mode set to 100644
File size: 17.1 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
[ec59693]42#define HACK_MAX_PACKET_SIZE 8
43#define HACK_MAX_PACKET_SIZE_INTERRUPT_IN 4
[1b22bd4]44
[aae339e9]45static void remote_usbhc_get_address(device_t *, void *, ipc_callid_t, ipc_call_t *);
[cb59f787]46static void remote_usbhc_interrupt_out(device_t *, void *, ipc_callid_t, ipc_call_t *);
47static void remote_usbhc_interrupt_in(device_t *, void *, ipc_callid_t, ipc_call_t *);
[a3dfb2e]48static void remote_usbhc_control_write_setup(device_t *, void *, ipc_callid_t, ipc_call_t *);
49static void remote_usbhc_control_write_data(device_t *, void *, ipc_callid_t, ipc_call_t *);
50static void remote_usbhc_control_write_status(device_t *, void *, ipc_callid_t, ipc_call_t *);
51static void remote_usbhc_control_read_setup(device_t *, void *, ipc_callid_t, ipc_call_t *);
52static void remote_usbhc_control_read_data(device_t *, void *, ipc_callid_t, ipc_call_t *);
53static void remote_usbhc_control_read_status(device_t *, void *, ipc_callid_t, ipc_call_t *);
[9753220]54static void remote_usbhc_control_write(device_t *, void *, ipc_callid_t, ipc_call_t *);
55static void remote_usbhc_control_read(device_t *, void *, ipc_callid_t, ipc_call_t *);
[6f04905]56static void remote_usbhc_reserve_default_address(device_t *, void *, ipc_callid_t, ipc_call_t *);
57static void remote_usbhc_release_default_address(device_t *, void *, ipc_callid_t, ipc_call_t *);
58static void remote_usbhc_request_address(device_t *, void *, ipc_callid_t, ipc_call_t *);
[4689d40]59static void remote_usbhc_bind_address(device_t *, void *, ipc_callid_t, ipc_call_t *);
[6f04905]60static void remote_usbhc_release_address(device_t *, void *, ipc_callid_t, ipc_call_t *);
[a3dfb2e]61//static void remote_usbhc(device_t *, void *, ipc_callid_t, ipc_call_t *);
[91db50ac]62
[6edd494]63/** Remote USB host controller interface operations. */
[cb59f787]64static remote_iface_func_ptr_t remote_usbhc_iface_ops [] = {
[aae339e9]65 remote_usbhc_get_address,
[6f04905]66
67 remote_usbhc_reserve_default_address,
68 remote_usbhc_release_default_address,
69
70 remote_usbhc_request_address,
[4689d40]71 remote_usbhc_bind_address,
[6f04905]72 remote_usbhc_release_address,
73
[aae339e9]74 remote_usbhc_interrupt_out,
[a3dfb2e]75 remote_usbhc_interrupt_in,
[6f04905]76
[a3dfb2e]77 remote_usbhc_control_write_setup,
78 remote_usbhc_control_write_data,
79 remote_usbhc_control_write_status,
[6f04905]80
[a3dfb2e]81 remote_usbhc_control_read_setup,
82 remote_usbhc_control_read_data,
[9753220]83 remote_usbhc_control_read_status,
84
85 remote_usbhc_control_write,
86 remote_usbhc_control_read
[91db50ac]87};
88
[6edd494]89/** Remote USB host controller interface structure.
[91db50ac]90 */
[cb59f787]91remote_iface_t remote_usbhc_iface = {
92 .method_count = sizeof(remote_usbhc_iface_ops) /
93 sizeof(remote_usbhc_iface_ops[0]),
94 .methods = remote_usbhc_iface_ops
[91db50ac]95};
96
[1b22bd4]97typedef struct {
98 ipc_callid_t caller;
[0a6fa9f]99 ipc_callid_t data_caller;
[1b22bd4]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;
[0a6fa9f]129 trans->data_caller = 0;
[93f8da1]130 trans->buffer = NULL;
131 trans->setup_packet = NULL;
132 trans->size = 0;
133
134 return trans;
135}
136
[aae339e9]137void remote_usbhc_get_address(device_t *device, void *iface,
138 ipc_callid_t callid, ipc_call_t *call)
139{
140 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
141
142 if (!usb_iface->tell_address) {
[17aca1c]143 async_answer_0(callid, ENOTSUP);
[aae339e9]144 return;
145 }
146
[eac610e]147 devman_handle_t handle = DEV_IPC_GET_ARG1(*call);
[aae339e9]148
149 usb_address_t address;
150 int rc = usb_iface->tell_address(device, handle, &address);
151 if (rc != EOK) {
[17aca1c]152 async_answer_0(callid, rc);
[aae339e9]153 } else {
[17aca1c]154 async_answer_1(callid, EOK, address);
[aae339e9]155 }
156}
[91db50ac]157
[6f04905]158void remote_usbhc_reserve_default_address(device_t *device, void *iface,
159 ipc_callid_t callid, ipc_call_t *call)
160{
161 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
162
163 if (!usb_iface->reserve_default_address) {
[17aca1c]164 async_answer_0(callid, ENOTSUP);
[6f04905]165 return;
166 }
[6427cf67]167
[fa48ebe]168 usb_speed_t speed = DEV_IPC_GET_ARG1(*call);
[6427cf67]169
[fa48ebe]170 int rc = usb_iface->reserve_default_address(device, speed);
[6f04905]171
[17aca1c]172 async_answer_0(callid, rc);
[6f04905]173}
174
175void remote_usbhc_release_default_address(device_t *device, void *iface,
176 ipc_callid_t callid, ipc_call_t *call)
177{
178 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
179
180 if (!usb_iface->release_default_address) {
[17aca1c]181 async_answer_0(callid, ENOTSUP);
[6f04905]182 return;
183 }
184
185 int rc = usb_iface->release_default_address(device);
186
[17aca1c]187 async_answer_0(callid, rc);
[6f04905]188}
189
190void remote_usbhc_request_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->request_address) {
[17aca1c]196 async_answer_0(callid, ENOTSUP);
[6f04905]197 return;
198 }
[6427cf67]199
[fa48ebe]200 usb_speed_t speed = DEV_IPC_GET_ARG1(*call);
[6f04905]201
202 usb_address_t address;
[fa48ebe]203 int rc = usb_iface->request_address(device, speed, &address);
[6f04905]204 if (rc != EOK) {
[17aca1c]205 async_answer_0(callid, rc);
[6f04905]206 } else {
[17aca1c]207 async_answer_1(callid, EOK, (sysarg_t) address);
[6f04905]208 }
209}
210
[4689d40]211void remote_usbhc_bind_address(device_t *device, void *iface,
212 ipc_callid_t callid, ipc_call_t *call)
213{
214 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
215
216 if (!usb_iface->bind_address) {
[17aca1c]217 async_answer_0(callid, ENOTSUP);
[4689d40]218 return;
219 }
220
[eac610e]221 usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call);
222 devman_handle_t handle = (devman_handle_t) DEV_IPC_GET_ARG2(*call);
[4689d40]223
224 int rc = usb_iface->bind_address(device, address, handle);
225
[17aca1c]226 async_answer_0(callid, rc);
[4689d40]227}
228
[6f04905]229void remote_usbhc_release_address(device_t *device, void *iface,
230 ipc_callid_t callid, ipc_call_t *call)
231{
232 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
233
234 if (!usb_iface->release_address) {
[17aca1c]235 async_answer_0(callid, ENOTSUP);
[6f04905]236 return;
237 }
238
[eac610e]239 usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call);
[6f04905]240
241 int rc = usb_iface->release_address(device, address);
242
[17aca1c]243 async_answer_0(callid, rc);
[6f04905]244}
245
[1b22bd4]246
247static void callback_out(device_t *device,
[daec5e04]248 int outcome, void *arg)
[1b22bd4]249{
250 async_transaction_t *trans = (async_transaction_t *)arg;
251
[17aca1c]252 async_answer_0(trans->caller, outcome);
[1b22bd4]253
[93f8da1]254 async_transaction_destroy(trans);
[1b22bd4]255}
256
257static void callback_in(device_t *device,
[daec5e04]258 int outcome, size_t actual_size, void *arg)
[1b22bd4]259{
260 async_transaction_t *trans = (async_transaction_t *)arg;
261
[daec5e04]262 if (outcome != EOK) {
[17aca1c]263 async_answer_0(trans->caller, outcome);
[5842493]264 if (trans->data_caller) {
265 async_answer_0(trans->data_caller, EINTR);
266 }
[93f8da1]267 async_transaction_destroy(trans);
268 return;
269 }
[1b22bd4]270
271 trans->size = actual_size;
[0a6fa9f]272
273 if (trans->data_caller) {
274 async_data_read_finalize(trans->data_caller,
275 trans->buffer, actual_size);
276 }
277
[daec5e04]278 async_answer_0(trans->caller, EOK);
[1e64b250]279
280 async_transaction_destroy(trans);
[91db50ac]281}
282
[fb1dca09]283/** Process an outgoing transfer (both OUT and SETUP).
284 *
285 * @param device Target device.
286 * @param callid Initiating caller.
287 * @param call Initiating call.
288 * @param transfer_func Transfer function (might be NULL).
289 */
290static void remote_usbhc_out_transfer(device_t *device,
291 ipc_callid_t callid, ipc_call_t *call,
292 usbhc_iface_transfer_out_t transfer_func)
[91db50ac]293{
[fb1dca09]294 if (!transfer_func) {
[17aca1c]295 async_answer_0(callid, ENOTSUP);
[fb1dca09]296 return;
297 }
[1b22bd4]298
[eac610e]299 size_t expected_len = DEV_IPC_GET_ARG3(*call);
[1b22bd4]300 usb_target_t target = {
[eac610e]301 .address = DEV_IPC_GET_ARG1(*call),
302 .endpoint = DEV_IPC_GET_ARG2(*call)
[1b22bd4]303 };
304
305 size_t len = 0;
306 void *buffer = NULL;
307 if (expected_len > 0) {
308 int rc = async_data_write_accept(&buffer, false,
309 1, USB_MAX_PAYLOAD_SIZE,
310 0, &len);
311
312 if (rc != EOK) {
[17aca1c]313 async_answer_0(callid, rc);
[1b22bd4]314 return;
315 }
316 }
317
[93f8da1]318 async_transaction_t *trans = async_transaction_create(callid);
319 if (trans == NULL) {
320 if (buffer != NULL) {
321 free(buffer);
322 }
[17aca1c]323 async_answer_0(callid, ENOMEM);
[93f8da1]324 return;
325 }
326
[fb1dca09]327 trans->buffer = buffer;
328 trans->size = len;
[1b22bd4]329
[ec59693]330 int rc = transfer_func(device, target, HACK_MAX_PACKET_SIZE,
331 buffer, len,
[1b22bd4]332 callback_out, trans);
333
334 if (rc != EOK) {
[17aca1c]335 async_answer_0(callid, rc);
[93f8da1]336 async_transaction_destroy(trans);
[1b22bd4]337 }
[91db50ac]338}
339
[fb1dca09]340/** Process an incoming transfer.
341 *
342 * @param device Target device.
343 * @param callid Initiating caller.
344 * @param call Initiating call.
345 * @param transfer_func Transfer function (might be NULL).
346 */
347static void remote_usbhc_in_transfer(device_t *device,
348 ipc_callid_t callid, ipc_call_t *call,
349 usbhc_iface_transfer_in_t transfer_func)
[91db50ac]350{
[fb1dca09]351 if (!transfer_func) {
[17aca1c]352 async_answer_0(callid, ENOTSUP);
[fb1dca09]353 return;
354 }
[1b22bd4]355
[eac610e]356 size_t len = DEV_IPC_GET_ARG3(*call);
[1b22bd4]357 usb_target_t target = {
[eac610e]358 .address = DEV_IPC_GET_ARG1(*call),
359 .endpoint = DEV_IPC_GET_ARG2(*call)
[1b22bd4]360 };
361
[0a6fa9f]362 ipc_callid_t data_callid;
363 if (!async_data_read_receive(&data_callid, &len)) {
364 async_answer_0(callid, EPARTY);
365 return;
366 }
367
[93f8da1]368 async_transaction_t *trans = async_transaction_create(callid);
369 if (trans == NULL) {
[17aca1c]370 async_answer_0(callid, ENOMEM);
[93f8da1]371 return;
372 }
[0a6fa9f]373 trans->data_caller = data_callid;
[1b22bd4]374 trans->buffer = malloc(len);
375 trans->size = len;
376
[ec59693]377 int rc = transfer_func(device, target, HACK_MAX_PACKET_SIZE_INTERRUPT_IN,
378 trans->buffer, len,
[1b22bd4]379 callback_in, trans);
380
381 if (rc != EOK) {
[17aca1c]382 async_answer_0(callid, rc);
[93f8da1]383 async_transaction_destroy(trans);
[1b22bd4]384 }
[91db50ac]385}
386
[fb1dca09]387/** Process status part of control transfer.
388 *
389 * @param device Target device.
390 * @param callid Initiating caller.
391 * @param call Initiating call.
392 * @param direction Transfer direction (read ~ in, write ~ out).
393 * @param transfer_in_func Transfer function for control read (might be NULL).
394 * @param transfer_out_func Transfer function for control write (might be NULL).
395 */
396static void remote_usbhc_status_transfer(device_t *device,
397 ipc_callid_t callid, ipc_call_t *call,
398 usb_direction_t direction,
399 int (*transfer_in_func)(device_t *, usb_target_t,
400 usbhc_iface_transfer_in_callback_t, void *),
401 int (*transfer_out_func)(device_t *, usb_target_t,
402 usbhc_iface_transfer_out_callback_t, void *))
[a3dfb2e]403{
[fb1dca09]404 switch (direction) {
405 case USB_DIRECTION_IN:
406 if (!transfer_in_func) {
[17aca1c]407 async_answer_0(callid, ENOTSUP);
[fb1dca09]408 return;
409 }
410 break;
411 case USB_DIRECTION_OUT:
412 if (!transfer_out_func) {
[17aca1c]413 async_answer_0(callid, ENOTSUP);
[fb1dca09]414 return;
415 }
416 break;
417 default:
418 assert(false && "unreachable code");
419 break;
420 }
[a3dfb2e]421
422 usb_target_t target = {
[eac610e]423 .address = DEV_IPC_GET_ARG1(*call),
424 .endpoint = DEV_IPC_GET_ARG2(*call)
[a3dfb2e]425 };
426
[93f8da1]427 async_transaction_t *trans = async_transaction_create(callid);
428 if (trans == NULL) {
[17aca1c]429 async_answer_0(callid, ENOMEM);
[93f8da1]430 return;
431 }
[a3dfb2e]432
[fb1dca09]433 int rc;
434 switch (direction) {
435 case USB_DIRECTION_IN:
436 rc = transfer_in_func(device, target,
437 callback_in, trans);
438 break;
439 case USB_DIRECTION_OUT:
440 rc = transfer_out_func(device, target,
441 callback_out, trans);
442 break;
443 default:
444 assert(false && "unreachable code");
445 break;
446 }
[a3dfb2e]447
448 if (rc != EOK) {
[17aca1c]449 async_answer_0(callid, rc);
[93f8da1]450 async_transaction_destroy(trans);
[a3dfb2e]451 }
452}
453
[fb1dca09]454
455void remote_usbhc_interrupt_out(device_t *device, void *iface,
456 ipc_callid_t callid, ipc_call_t *call)
[a3dfb2e]457{
458 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
[fb1dca09]459 assert(usb_iface != NULL);
[a3dfb2e]460
[fb1dca09]461 return remote_usbhc_out_transfer(device, callid, call,
462 usb_iface->interrupt_out);
463}
[a3dfb2e]464
[fb1dca09]465void remote_usbhc_interrupt_in(device_t *device, void *iface,
466 ipc_callid_t callid, ipc_call_t *call)
467{
468 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
469 assert(usb_iface != NULL);
[a3dfb2e]470
[fb1dca09]471 return remote_usbhc_in_transfer(device, callid, call,
472 usb_iface->interrupt_in);
473}
[a3dfb2e]474
[fb1dca09]475void remote_usbhc_control_write_setup(device_t *device, void *iface,
476 ipc_callid_t callid, ipc_call_t *call)
477{
478 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
479 assert(usb_iface != NULL);
[a3dfb2e]480
[fb1dca09]481 return remote_usbhc_out_transfer(device, callid, call,
482 usb_iface->control_write_setup);
483}
[a3dfb2e]484
[fb1dca09]485void remote_usbhc_control_write_data(device_t *device, void *iface,
486 ipc_callid_t callid, ipc_call_t *call)
487{
488 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
489 assert(usb_iface != NULL);
[a3dfb2e]490
[fb1dca09]491 return remote_usbhc_out_transfer(device, callid, call,
492 usb_iface->control_write_data);
[a3dfb2e]493}
494
495void remote_usbhc_control_write_status(device_t *device, void *iface,
[fb1dca09]496 ipc_callid_t callid, ipc_call_t *call)
[a3dfb2e]497{
498 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
[fb1dca09]499 assert(usb_iface != NULL);
[a3dfb2e]500
[fb1dca09]501 return remote_usbhc_status_transfer(device, callid, call,
502 USB_DIRECTION_IN, usb_iface->control_write_status, NULL);
[a3dfb2e]503}
504
505void remote_usbhc_control_read_setup(device_t *device, void *iface,
[fb1dca09]506 ipc_callid_t callid, ipc_call_t *call)
[a3dfb2e]507{
508 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
[fb1dca09]509 assert(usb_iface != NULL);
[a3dfb2e]510
[fb1dca09]511 return remote_usbhc_out_transfer(device, callid, call,
512 usb_iface->control_read_setup);
[a3dfb2e]513}
514
515void remote_usbhc_control_read_data(device_t *device, void *iface,
516 ipc_callid_t callid, ipc_call_t *call)
517{
518 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
[fb1dca09]519 assert(usb_iface != NULL);
[a3dfb2e]520
[fb1dca09]521 return remote_usbhc_in_transfer(device, callid, call,
522 usb_iface->control_read_data);
[a3dfb2e]523}
524
525void remote_usbhc_control_read_status(device_t *device, void *iface,
526 ipc_callid_t callid, ipc_call_t *call)
527{
528 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
[fb1dca09]529 assert(usb_iface != NULL);
[a3dfb2e]530
[fb1dca09]531 return remote_usbhc_status_transfer(device, callid, call,
532 USB_DIRECTION_OUT, NULL, usb_iface->control_read_status);
[a3dfb2e]533}
534
[9753220]535void remote_usbhc_control_write(device_t *device, void *iface,
536ipc_callid_t callid, ipc_call_t *call)
537{
538 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
539 assert(usb_iface != NULL);
540
541 if (!usb_iface->control_write) {
[17aca1c]542 async_answer_0(callid, ENOTSUP);
[9753220]543 return;
544 }
545
546 usb_target_t target = {
547 .address = DEV_IPC_GET_ARG1(*call),
548 .endpoint = DEV_IPC_GET_ARG2(*call)
549 };
[3937bda]550 size_t data_buffer_len = DEV_IPC_GET_ARG3(*call);
[9753220]551
552 int rc;
553
554 void *setup_packet = NULL;
555 void *data_buffer = NULL;
556 size_t setup_packet_len = 0;
557
558 rc = async_data_write_accept(&setup_packet, false,
559 1, USB_MAX_PAYLOAD_SIZE, 0, &setup_packet_len);
560 if (rc != EOK) {
[17aca1c]561 async_answer_0(callid, rc);
[9753220]562 return;
563 }
[3937bda]564
565 if (data_buffer_len > 0) {
566 rc = async_data_write_accept(&data_buffer, false,
567 1, USB_MAX_PAYLOAD_SIZE, 0, &data_buffer_len);
568 if (rc != EOK) {
569 async_answer_0(callid, rc);
570 free(setup_packet);
571 return;
572 }
[9753220]573 }
574
[93f8da1]575 async_transaction_t *trans = async_transaction_create(callid);
576 if (trans == NULL) {
[17aca1c]577 async_answer_0(callid, ENOMEM);
[93f8da1]578 free(setup_packet);
579 free(data_buffer);
580 return;
581 }
[9753220]582 trans->setup_packet = setup_packet;
583 trans->buffer = data_buffer;
584 trans->size = data_buffer_len;
585
[ec59693]586 rc = usb_iface->control_write(device, target, HACK_MAX_PACKET_SIZE,
[9753220]587 setup_packet, setup_packet_len,
588 data_buffer, data_buffer_len,
589 callback_out, trans);
590
591 if (rc != EOK) {
[17aca1c]592 async_answer_0(callid, rc);
[93f8da1]593 async_transaction_destroy(trans);
[9753220]594 }
595}
596
597
598void remote_usbhc_control_read(device_t *device, void *iface,
599ipc_callid_t callid, ipc_call_t *call)
600{
601 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
602 assert(usb_iface != NULL);
603
604 if (!usb_iface->control_read) {
[17aca1c]605 async_answer_0(callid, ENOTSUP);
[9753220]606 return;
607 }
608
609 usb_target_t target = {
610 .address = DEV_IPC_GET_ARG1(*call),
611 .endpoint = DEV_IPC_GET_ARG2(*call)
612 };
613
614 int rc;
615
616 void *setup_packet = NULL;
617 size_t setup_packet_len = 0;
[3937bda]618 size_t data_len = 0;
[9753220]619
620 rc = async_data_write_accept(&setup_packet, false,
621 1, USB_MAX_PAYLOAD_SIZE, 0, &setup_packet_len);
622 if (rc != EOK) {
[17aca1c]623 async_answer_0(callid, rc);
[9753220]624 return;
625 }
626
[0a6fa9f]627 ipc_callid_t data_callid;
628 if (!async_data_read_receive(&data_callid, &data_len)) {
629 async_answer_0(callid, EPARTY);
630 free(setup_packet);
631 return;
632 }
633
[93f8da1]634 async_transaction_t *trans = async_transaction_create(callid);
635 if (trans == NULL) {
[17aca1c]636 async_answer_0(callid, ENOMEM);
[93f8da1]637 free(setup_packet);
638 return;
639 }
[0a6fa9f]640 trans->data_caller = data_callid;
[9753220]641 trans->setup_packet = setup_packet;
642 trans->size = data_len;
[93f8da1]643 trans->buffer = malloc(data_len);
644 if (trans->buffer == NULL) {
[17aca1c]645 async_answer_0(callid, ENOMEM);
[93f8da1]646 async_transaction_destroy(trans);
647 return;
648 }
[9753220]649
[ec59693]650 rc = usb_iface->control_read(device, target, HACK_MAX_PACKET_SIZE,
[9753220]651 setup_packet, setup_packet_len,
652 trans->buffer, trans->size,
653 callback_in, trans);
654
655 if (rc != EOK) {
[17aca1c]656 async_answer_0(callid, rc);
[93f8da1]657 async_transaction_destroy(trans);
[9753220]658 }
659}
660
[a3dfb2e]661
[1b22bd4]662
[91db50ac]663/**
664 * @}
665 */
Note: See TracBrowser for help on using the repository browser.