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

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

Add method for getting device address to USBHC interface

  • Property mode set to 100644
File size: 5.8 KB
Line 
1/*
2 * Copyright (c) 2010 Vojtech Horky
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 <ipc/ipc.h>
36#include <async.h>
37#include <errno.h>
38
39#include "usbhc_iface.h"
40#include "driver.h"
41
42#define USB_MAX_PAYLOAD_SIZE 1020
43
44static void remote_usbhc_get_address(device_t *, void *, ipc_callid_t, ipc_call_t *);
45static void remote_usbhc_get_buffer(device_t *, void *, ipc_callid_t, ipc_call_t *);
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 *);
48//static void remote_usb(device_t *, void *, ipc_callid_t, ipc_call_t *);
49
50/** Remote USB interface operations. */
51static remote_iface_func_ptr_t remote_usbhc_iface_ops [] = {
52 remote_usbhc_get_address,
53 remote_usbhc_get_buffer,
54 remote_usbhc_interrupt_out,
55 remote_usbhc_interrupt_in
56};
57
58/** Remote USB interface structure.
59 */
60remote_iface_t remote_usbhc_iface = {
61 .method_count = sizeof(remote_usbhc_iface_ops) /
62 sizeof(remote_usbhc_iface_ops[0]),
63 .methods = remote_usbhc_iface_ops
64};
65
66typedef struct {
67 ipc_callid_t caller;
68 void *buffer;
69 size_t size;
70} async_transaction_t;
71
72void remote_usbhc_get_address(device_t *device, void *iface,
73 ipc_callid_t callid, ipc_call_t *call)
74{
75 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
76
77 if (!usb_iface->tell_address) {
78 ipc_answer_0(callid, ENOTSUP);
79 return;
80 }
81
82 devman_handle_t handle = IPC_GET_ARG1(*call);
83
84 usb_address_t address;
85 int rc = usb_iface->tell_address(device, handle, &address);
86 if (rc != EOK) {
87 ipc_answer_0(callid, rc);
88 } else {
89 ipc_answer_1(callid, EOK, address);
90 }
91}
92
93void remote_usbhc_get_buffer(device_t *device, void *iface,
94 ipc_callid_t callid, ipc_call_t *call)
95{
96 ipcarg_t buffer_hash = IPC_GET_ARG1(*call);
97 async_transaction_t * trans = (async_transaction_t *)buffer_hash;
98 if (trans == NULL) {
99 ipc_answer_0(callid, ENOENT);
100 return;
101 }
102 if (trans->buffer == NULL) {
103 ipc_answer_0(callid, EINVAL);
104 free(trans);
105 return;
106 }
107
108 ipc_callid_t cid;
109 size_t accepted_size;
110 if (!async_data_read_receive(&cid, &accepted_size)) {
111 ipc_answer_0(callid, EINVAL);
112 return;
113 }
114
115 if (accepted_size > trans->size) {
116 accepted_size = trans->size;
117 }
118 async_data_read_finalize(callid, trans->buffer, accepted_size);
119
120 ipc_answer_1(callid, EOK, accepted_size);
121
122 free(trans->buffer);
123 free(trans);
124}
125
126
127static void callback_out(device_t *device,
128 usb_transaction_outcome_t outcome, void *arg)
129{
130 async_transaction_t *trans = (async_transaction_t *)arg;
131
132 // FIXME - answer according to outcome
133 ipc_answer_0(trans->caller, EOK);
134
135 free(trans);
136}
137
138static void callback_in(device_t *device,
139 usb_transaction_outcome_t outcome, size_t actual_size, void *arg)
140{
141 async_transaction_t *trans = (async_transaction_t *)arg;
142
143 // FIXME - answer according to outcome
144 ipc_answer_1(trans->caller, EOK, (ipcarg_t)trans);
145
146 trans->size = actual_size;
147}
148
149void remote_usbhc_interrupt_out(device_t *device, void *iface,
150 ipc_callid_t callid, ipc_call_t *call)
151{
152 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
153
154 size_t expected_len = IPC_GET_ARG3(*call);
155 usb_target_t target = {
156 .address = IPC_GET_ARG1(*call),
157 .endpoint = IPC_GET_ARG2(*call)
158 };
159
160 size_t len = 0;
161 void *buffer = NULL;
162 if (expected_len > 0) {
163 int rc = async_data_write_accept(&buffer, false,
164 1, USB_MAX_PAYLOAD_SIZE,
165 0, &len);
166
167 if (rc != EOK) {
168 ipc_answer_0(callid, rc);
169 return;
170 }
171 }
172
173 if (!usb_iface->interrupt_out) {
174 ipc_answer_0(callid, ENOTSUP);
175 return;
176 }
177
178 async_transaction_t *trans = malloc(sizeof(async_transaction_t));
179 trans->caller = callid;
180 trans->buffer = NULL;
181 trans->size = 0;
182
183 int rc = usb_iface->interrupt_out(device, target, buffer, len,
184 callback_out, trans);
185
186 if (rc != EOK) {
187 ipc_answer_0(callid, rc);
188 free(trans);
189 }
190}
191
192void remote_usbhc_interrupt_in(device_t *device, void *iface,
193 ipc_callid_t callid, ipc_call_t *call)
194{
195 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
196
197 size_t len = IPC_GET_ARG3(*call);
198 usb_target_t target = {
199 .address = IPC_GET_ARG1(*call),
200 .endpoint = IPC_GET_ARG2(*call)
201 };
202
203 if (!usb_iface->interrupt_in) {
204 ipc_answer_0(callid, ENOTSUP);
205 return;
206 }
207
208 async_transaction_t *trans = malloc(sizeof(async_transaction_t));
209 trans->caller = callid;
210 trans->buffer = malloc(len);
211 trans->size = len;
212
213 int rc = usb_iface->interrupt_in(device, target, trans->buffer, len,
214 callback_in, trans);
215
216 if (rc != EOK) {
217 ipc_answer_0(callid, rc);
218 free(trans->buffer);
219 free(trans);
220 }
221}
222
223
224/**
225 * @}
226 */
Note: See TracBrowser for help on using the repository browser.