source: mainline/uspace/lib/drv/generic/remote_usb.c@ 8582076

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 8582076 was 71384bd3, checked in by Jan Vesely <jano.vesely@…>, 12 years ago

libdrv, usb: Rename session close to disconnect.

  • Property mode set to 100644
File size: 9.8 KB
Line 
1/*
2 * Copyright (c) 2010 Vojtech Horky
3 * Copyright (c) 2011 Jan Vesely
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/** @addtogroup libdrv
31 * @{
32 */
33/** @file
34 */
35
36#include <async.h>
37#include <macros.h>
38#include <errno.h>
39#include <devman.h>
40
41#include "usb_iface.h"
42#include "ddf/driver.h"
43
44
45usb_dev_session_t *usb_dev_connect(devman_handle_t handle)
46{
47 // TODO All usb requests are atomic so this is safe,
48 // it will need to change once USING EXCHANGE PARALLEL is safe with
49 // devman_device_connect
50 return devman_device_connect(EXCHANGE_ATOMIC, handle, IPC_FLAG_BLOCKING);
51}
52
53usb_dev_session_t *usb_dev_connect_to_self(ddf_dev_t *dev)
54{
55 // TODO All usb requests are atomic so this is safe,
56 // it will need to change once USING EXCHANGE PARALLEL is safe with
57 // devman_parent_device_connect
58 return devman_parent_device_connect(EXCHANGE_ATOMIC,
59 ddf_dev_get_handle(dev), IPC_FLAG_BLOCKING);
60}
61
62void usb_dev_disconnect(usb_dev_session_t *sess)
63{
64 if (sess)
65 async_hangup(sess);
66}
67
68typedef enum {
69 IPC_M_USB_GET_MY_ADDRESS,
70 IPC_M_USB_GET_MY_INTERFACE,
71 IPC_M_USB_GET_HOST_CONTROLLER_HANDLE,
72 IPC_M_USB_RESERVE_DEFAULT_ADDRESS,
73 IPC_M_USB_RELEASE_DEFAULT_ADDRESS,
74 IPC_M_USB_DEVICE_ENUMERATE,
75 IPC_M_USB_DEVICE_REMOVE,
76} usb_iface_funcs_t;
77
78/** Tell USB address assigned to device.
79 * @param exch Vaid IPC exchange
80 * @param address Pointer to address storage place.
81 * @return Error code.
82 *
83 * Exch param is an open communication to device implementing usb_iface.
84 */
85int usb_get_my_address(async_exch_t *exch, usb_address_t *address)
86{
87 if (!exch)
88 return EBADMEM;
89 sysarg_t addr;
90 const int ret = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
91 IPC_M_USB_GET_MY_ADDRESS, &addr);
92
93 if (ret == EOK && address != NULL)
94 *address = (usb_address_t) addr;
95 return ret;
96}
97
98/** Tell interface number given device can use.
99 * @param[in] exch IPC communication exchange
100 * @param[in] handle Id of the device
101 * @param[out] usb_iface Assigned USB interface
102 * @return Error code.
103 */
104int usb_get_my_interface(async_exch_t *exch, int *usb_iface)
105{
106 if (!exch)
107 return EBADMEM;
108 sysarg_t iface_no;
109 const int ret = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
110 IPC_M_USB_GET_MY_INTERFACE, &iface_no);
111 if (ret == EOK && usb_iface)
112 *usb_iface = (int)iface_no;
113 return ret;
114}
115
116/** Tell devman handle of device host controller.
117 * @param[in] exch IPC communication exchange
118 * @param[out] hc_handle devman handle of the HC used by the target device.
119 * @return Error code.
120 */
121int usb_get_hc_handle(async_exch_t *exch, devman_handle_t *hc_handle)
122{
123 if (!exch)
124 return EBADMEM;
125 devman_handle_t h;
126 const int ret = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
127 IPC_M_USB_GET_HOST_CONTROLLER_HANDLE, &h);
128 if (ret == EOK && hc_handle)
129 *hc_handle = (devman_handle_t)h;
130 return ret;
131}
132
133/** Reserve default USB address.
134 * @param[in] exch IPC communication exchange
135 * @param[in] speed Communication speed of the newly attached device
136 * @return Error code.
137 */
138int usb_reserve_default_address(async_exch_t *exch, usb_speed_t speed)
139{
140 if (!exch)
141 return EBADMEM;
142 return async_req_2_0(exch, DEV_IFACE_ID(USB_DEV_IFACE),
143 IPC_M_USB_RESERVE_DEFAULT_ADDRESS, speed);
144}
145
146/** Release default USB address.
147 * @param[in] exch IPC communication exchange
148 * @return Error code.
149 */
150int usb_release_default_address(async_exch_t *exch)
151{
152 if (!exch)
153 return EBADMEM;
154 return async_req_1_0(exch, DEV_IFACE_ID(USB_DEV_IFACE),
155 IPC_M_USB_RELEASE_DEFAULT_ADDRESS);
156}
157
158/** Trigger USB device enumeration
159 * @param[in] exch IPC communication exchange
160 * @param[out] handle Identifier of the newly added device (if successful)
161 * @return Error code.
162 */
163int usb_device_enumerate(async_exch_t *exch, usb_device_handle_t *handle)
164{
165 if (!exch || !handle)
166 return EBADMEM;
167 sysarg_t h;
168 const int ret = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
169 IPC_M_USB_DEVICE_ENUMERATE, &h);
170 if (ret == EOK)
171 *handle = (usb_device_handle_t)h;
172 return ret;
173}
174
175/** Trigger USB device enumeration
176 * @param[in] exch IPC communication exchange
177 * @param[in] handle Identifier of the device
178 * @return Error code.
179 */
180int usb_device_remove(async_exch_t *exch, usb_device_handle_t handle)
181{
182 if (!exch)
183 return EBADMEM;
184 return async_req_2_0(exch, DEV_IFACE_ID(USB_DEV_IFACE),
185 IPC_M_USB_DEVICE_REMOVE, handle);
186}
187
188static void remote_usb_get_my_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
189static void remote_usb_get_my_interface(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
190static void remote_usb_get_hc_handle(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
191
192static void remote_usb_reserve_default_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
193static void remote_usb_release_default_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
194static void remote_usb_device_enumerate(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
195static void remote_usb_device_remove(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
196
197/** Remote USB interface operations. */
198static remote_iface_func_ptr_t remote_usb_iface_ops [] = {
199 [IPC_M_USB_GET_MY_ADDRESS] = remote_usb_get_my_address,
200 [IPC_M_USB_GET_MY_INTERFACE] = remote_usb_get_my_interface,
201 [IPC_M_USB_GET_HOST_CONTROLLER_HANDLE] = remote_usb_get_hc_handle,
202 [IPC_M_USB_RESERVE_DEFAULT_ADDRESS] = remote_usb_reserve_default_address,
203 [IPC_M_USB_RELEASE_DEFAULT_ADDRESS] = remote_usb_release_default_address,
204 [IPC_M_USB_DEVICE_ENUMERATE] = remote_usb_device_enumerate,
205 [IPC_M_USB_DEVICE_REMOVE] = remote_usb_device_remove,
206};
207
208/** Remote USB interface structure.
209 */
210remote_iface_t remote_usb_iface = {
211 .method_count = ARRAY_SIZE(remote_usb_iface_ops),
212 .methods = remote_usb_iface_ops,
213};
214
215
216void remote_usb_get_my_address(ddf_fun_t *fun, void *iface,
217 ipc_callid_t callid, ipc_call_t *call)
218{
219 const usb_iface_t *usb_iface = (usb_iface_t *) iface;
220
221 if (usb_iface->get_my_address == NULL) {
222 async_answer_0(callid, ENOTSUP);
223 return;
224 }
225
226 usb_address_t address;
227 const int ret = usb_iface->get_my_address(fun, &address);
228 if (ret != EOK) {
229 async_answer_0(callid, ret);
230 } else {
231 async_answer_1(callid, EOK, address);
232 }
233}
234
235void remote_usb_get_my_interface(ddf_fun_t *fun, void *iface,
236 ipc_callid_t callid, ipc_call_t *call)
237{
238 const usb_iface_t *usb_iface = (usb_iface_t *) iface;
239
240 if (usb_iface->get_my_interface == NULL) {
241 async_answer_0(callid, ENOTSUP);
242 return;
243 }
244
245 int iface_no;
246 const int ret = usb_iface->get_my_interface(fun, &iface_no);
247 if (ret != EOK) {
248 async_answer_0(callid, ret);
249 } else {
250 async_answer_1(callid, EOK, iface_no);
251 }
252}
253
254void remote_usb_get_hc_handle(ddf_fun_t *fun, void *iface,
255 ipc_callid_t callid, ipc_call_t *call)
256{
257 const usb_iface_t *usb_iface = (usb_iface_t *) iface;
258
259 if (usb_iface->get_hc_handle == NULL) {
260 async_answer_0(callid, ENOTSUP);
261 return;
262 }
263
264 devman_handle_t handle;
265 const int ret = usb_iface->get_hc_handle(fun, &handle);
266 if (ret != EOK) {
267 async_answer_0(callid, ret);
268 }
269
270 async_answer_1(callid, EOK, (sysarg_t) handle);
271}
272
273void remote_usb_reserve_default_address(ddf_fun_t *fun, void *iface,
274 ipc_callid_t callid, ipc_call_t *call)
275{
276 const usb_iface_t *usb_iface = (usb_iface_t *) iface;
277
278 if (usb_iface->reserve_default_address == NULL) {
279 async_answer_0(callid, ENOTSUP);
280 return;
281 }
282
283 usb_speed_t speed = DEV_IPC_GET_ARG1(*call);
284 const int ret = usb_iface->reserve_default_address(fun, speed);
285 async_answer_0(callid, ret);
286}
287
288void remote_usb_release_default_address(ddf_fun_t *fun, void *iface,
289 ipc_callid_t callid, ipc_call_t *call)
290{
291 const usb_iface_t *usb_iface = (usb_iface_t *) iface;
292
293 if (usb_iface->release_default_address == NULL) {
294 async_answer_0(callid, ENOTSUP);
295 return;
296 }
297
298 const int ret = usb_iface->release_default_address(fun);
299 async_answer_0(callid, ret);
300}
301
302static void remote_usb_device_enumerate(ddf_fun_t *fun, void *iface,
303 ipc_callid_t callid, ipc_call_t *call)
304{
305 const usb_iface_t *usb_iface = (usb_iface_t *) iface;
306
307 if (usb_iface->device_enumerate == NULL) {
308 async_answer_0(callid, ENOTSUP);
309 return;
310 }
311
312 usb_device_handle_t handle = 0;
313 const int ret = usb_iface->device_enumerate(fun, &handle);
314 if (ret != EOK) {
315 async_answer_0(callid, ret);
316 }
317
318 async_answer_1(callid, EOK, (sysarg_t) handle);
319}
320
321static void remote_usb_device_remove(ddf_fun_t *fun, void *iface,
322 ipc_callid_t callid, ipc_call_t *call)
323{
324 const usb_iface_t *usb_iface = (usb_iface_t *) iface;
325
326 if (usb_iface->device_remove == NULL) {
327 async_answer_0(callid, ENOTSUP);
328 return;
329 }
330
331 usb_device_handle_t handle = DEV_IPC_GET_ARG1(*call);
332 const int ret = usb_iface->device_remove(fun, handle);
333 async_answer_0(callid, ret);
334}
335/**
336 * @}
337 */
Note: See TracBrowser for help on using the repository browser.