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

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

Hack for setting low speed/high speed

Currently, it is only a boolean. Will improve later.

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