source: mainline/uspace/lib/usb/src/remotedrv.c@ fe5e00d6

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

Remote interface can handle interrupt transfers

The HC framework can handle interrupt transfers from USB device drivers.

  • Property mode set to 100644
File size: 9.4 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 libusb usb
30 * @{
31 */
32/** @file
33 * @brief Driver communication for remote drivers (interface implementation).
34 */
35#include <usb/hcdhubd.h>
36#include <usbhc_iface.h>
37#include <driver.h>
38#include <bool.h>
39#include <errno.h>
40
41#include "hcdhubd_private.h"
42
43static int remote_get_address(device_t *, devman_handle_t, usb_address_t *);
44static int remote_interrupt_out(device_t *, usb_target_t, void *, size_t,
45 usbhc_iface_transfer_out_callback_t, void *);
46static int remote_interrupt_in(device_t *, usb_target_t, void *, size_t,
47 usbhc_iface_transfer_in_callback_t, void *);
48
49/** Implementation of USB HC interface. */
50usbhc_iface_t usbhc_interface = {
51 .tell_address = remote_get_address,
52 .interrupt_out = remote_interrupt_out,
53 .interrupt_in = remote_interrupt_in
54};
55
56/** Get USB address for remote USBHC interface.
57 *
58 * @param dev Device asked for the information.
59 * @param handle Devman handle of the USB device.
60 * @param address Storage for obtained address.
61 * @return Error code.
62 */
63int remote_get_address(device_t *dev, devman_handle_t handle,
64 usb_address_t *address)
65{
66 usb_address_t addr = usb_get_address_by_handle(handle);
67 if (addr < 0) {
68 return addr;
69 }
70
71 *address = addr;
72
73 return EOK;
74}
75
76/** Information about pending transaction on HC. */
77typedef struct {
78 /** Target device. */
79 usb_hcd_attached_device_info_t *device;
80 /** Target endpoint. */
81 usb_hc_endpoint_info_t *endpoint;
82
83 /** Callbacks. */
84 union {
85 /** Callback for outgoing transfers. */
86 usbhc_iface_transfer_out_callback_t out_callback;
87 /** Callback for incoming transfers. */
88 usbhc_iface_transfer_in_callback_t in_callback;
89 };
90
91 /** Custom argument for the callback. */
92 void *arg;
93} transfer_info_t;
94
95/** Create new transfer info.
96 *
97 * @param device Attached device.
98 * @param endpoint Endpoint.
99 * @param custom_arg Custom argument.
100 * @return Transfer info with pre-filled values.
101 */
102static transfer_info_t *transfer_info_create(
103 usb_hcd_attached_device_info_t *device, usb_hc_endpoint_info_t *endpoint,
104 void *custom_arg)
105{
106 transfer_info_t *transfer = malloc(sizeof(transfer_info_t));
107
108 transfer->device = device;
109 transfer->endpoint = endpoint;
110 transfer->arg = custom_arg;
111 transfer->out_callback = NULL;
112 transfer->in_callback = NULL;
113
114 return transfer;
115}
116
117/** Destroy transfer info.
118 *
119 * @param transfer Transfer to be destroyed.
120 */
121static void transfer_info_destroy(transfer_info_t *transfer)
122{
123 free(transfer->device);
124 free(transfer->endpoint);
125 free(transfer);
126}
127
128/** Create info about attached device.
129 *
130 * @param address Device address.
131 * @return Device info structure.
132 */
133static usb_hcd_attached_device_info_t *create_attached_device_info(
134 usb_address_t address)
135{
136 usb_hcd_attached_device_info_t *dev
137 = malloc(sizeof(usb_hcd_attached_device_info_t));
138
139 dev->address = address;
140 dev->endpoint_count = 0;
141 dev->endpoints = NULL;
142 list_initialize(&dev->link);
143
144 return dev;
145}
146
147/** Create info about device endpoint.
148 *
149 * @param endpoint Endpoint number.
150 * @param direction Endpoint data direction.
151 * @param transfer_type Transfer type of the endpoint.
152 * @return Endpoint info structure.
153 */
154static usb_hc_endpoint_info_t *create_endpoint_info(usb_endpoint_t endpoint,
155 usb_direction_t direction, usb_transfer_type_t transfer_type)
156{
157 usb_hc_endpoint_info_t *ep = malloc(sizeof(usb_hc_endpoint_info_t));
158 ep->data_toggle = 0;
159 ep->direction = direction;
160 ep->transfer_type = transfer_type;
161 ep->endpoint = endpoint;
162
163 return ep;
164}
165
166
167
168/** Callback for OUT transfers.
169 * This callback is called by implementation of HC operations.
170 *
171 * @param hc Host controller that processed the transfer.
172 * @param outcome Transfer outcome.
173 * @param arg Custom argument.
174 */
175static void remote_out_callback(usb_hc_device_t *hc,
176 usb_transaction_outcome_t outcome, void *arg)
177{
178 transfer_info_t *transfer = (transfer_info_t *) arg;
179 transfer->out_callback(hc->generic, outcome, transfer->arg);
180
181 transfer_info_destroy(transfer);
182}
183
184/** Start an OUT transfer.
185 *
186 * @param dev Device that shall process the transfer.
187 * @param target Target device for the data.
188 * @param transfer_type Transfer type.
189 * @param data Data buffer.
190 * @param size Size of data buffer.
191 * @param callback Callback after transfer is complete.
192 * @param arg Custom argument to the callback.
193 * @return Error code.
194 */
195static int remote_out_transfer(device_t *dev, usb_target_t target,
196 usb_transfer_type_t transfer_type, void *data, size_t size,
197 usbhc_iface_transfer_out_callback_t callback, void *arg)
198{
199 usb_hc_device_t *hc = (usb_hc_device_t *) dev->driver_data;
200
201 if ((hc->transfer_ops == NULL)
202 || (hc->transfer_ops->transfer_out == NULL)) {
203 return ENOTSUP;
204 }
205
206 transfer_info_t *transfer = transfer_info_create(
207 create_attached_device_info(target.address),
208 create_endpoint_info(target.endpoint,
209 USB_DIRECTION_OUT, transfer_type),
210 arg);
211 transfer->out_callback = callback;
212
213 int rc = hc->transfer_ops->transfer_out(hc,
214 transfer->device, transfer->endpoint,
215 data, size,
216 remote_out_callback, transfer);
217
218 if (rc != EOK) {
219 transfer_info_destroy(transfer);
220 return rc;
221 }
222
223 return EOK;
224}
225
226/** Callback for IN transfers.
227 * This callback is called by implementation of HC operations.
228 *
229 * @param hc Host controller that processed the transfer.
230 * @param outcome Transfer outcome.
231 * @param actual_size Size of actually received data.
232 * @param arg Custom argument.
233 */
234static void remote_in_callback(usb_hc_device_t *hc,
235 usb_transaction_outcome_t outcome, size_t actual_size, void *arg)
236{
237 transfer_info_t *transfer = (transfer_info_t *) arg;
238 transfer->in_callback(hc->generic, outcome, actual_size, transfer->arg);
239
240 transfer_info_destroy(transfer);
241}
242
243/** Start an IN transfer.
244 *
245 * @param dev Device that shall process the transfer.
246 * @param target Target device for the data.
247 * @param transfer_type Transfer type.
248 * @param data Data buffer.
249 * @param size Size of data buffer.
250 * @param callback Callback after transfer is complete.
251 * @param arg Custom argument to the callback.
252 * @return Error code.
253 */
254static int remote_in_transfer(device_t *dev, usb_target_t target,
255 usb_transfer_type_t transfer_type, void *data, size_t size,
256 usbhc_iface_transfer_in_callback_t callback, void *arg)
257{
258 usb_hc_device_t *hc = (usb_hc_device_t *) dev->driver_data;
259
260 if ((hc->transfer_ops == NULL)
261 || (hc->transfer_ops->transfer_in == NULL)) {
262 return ENOTSUP;
263 }
264
265 transfer_info_t *transfer = transfer_info_create(
266 create_attached_device_info(target.address),
267 create_endpoint_info(target.endpoint,
268 USB_DIRECTION_OUT, transfer_type),
269 arg);
270 transfer->in_callback = callback;
271
272 int rc = hc->transfer_ops->transfer_in(hc,
273 transfer->device, transfer->endpoint,
274 data, size,
275 remote_in_callback, transfer);
276
277 if (rc != EOK) {
278 transfer_info_destroy(transfer);
279 return rc;
280 }
281
282 return EOK;
283}
284
285/** Start outgoing interrupt transfer (USBHC remote interface).
286 *
287 * @param dev Host controller device processing the transfer.
288 * @param target Target USB device.
289 * @param buffer Data buffer.
290 * @param size Data buffer size.
291 * @param callback Callback after the transfer is completed.
292 * @param arg Custom argument to the callback.
293 * @return Error code.
294 */
295int remote_interrupt_out(device_t *dev, usb_target_t target,
296 void *buffer, size_t size,
297 usbhc_iface_transfer_out_callback_t callback, void *arg)
298{
299 return remote_out_transfer(dev, target, USB_TRANSFER_INTERRUPT,
300 buffer, size, callback, arg);
301}
302
303/** Start incoming interrupt transfer (USBHC remote interface).
304 *
305 * @param dev Host controller device processing the transfer.
306 * @param target Target USB device.
307 * @param buffer Data buffer.
308 * @param size Data buffer size.
309 * @param callback Callback after the transfer is completed.
310 * @param arg Custom argument to the callback.
311 * @return Error code.
312 */
313int remote_interrupt_in(device_t *dev, usb_target_t target,
314 void *buffer, size_t size,
315 usbhc_iface_transfer_in_callback_t callback, void *arg)
316{
317 return remote_in_transfer(dev, target, USB_TRANSFER_INTERRUPT,
318 buffer, size, callback, arg);
319}
320
321
322/**
323 * @}
324 */
Note: See TracBrowser for help on using the repository browser.