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

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

Endpoint registration sends address as well

This is the first step towards using endpoint registration instead
of reservation of default address.

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