source: mainline/uspace/lib/usb/src/localdrv.c@ be2ad7cf

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

Interrupt transfers ready for local drivers

  • Property mode set to 100644
File size: 8.0 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 local drivers (hubs).
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/** Information about pending transaction on HC. */
42typedef struct {
43 /** Storage for actual number of bytes transferred. */
44 size_t *size_transferred;
45
46 /** Target device. */
47 usb_hcd_attached_device_info_t *device;
48 /** Target endpoint. */
49 usb_hc_endpoint_info_t *endpoint;
50
51 /** Guard for the condition variable. */
52 fibril_mutex_t condvar_guard;
53 /** Condition variable for waiting for done. */
54 fibril_condvar_t condvar;
55
56 /** Flag whether the transfer is done. */
57 bool done;
58} transfer_info_t;
59
60/** Create new transfer info.
61 *
62 * @param device Attached device.
63 * @param endpoint Endpoint.
64 * @return Transfer info with pre-filled values.
65 */
66static transfer_info_t *transfer_info_create(
67 usb_hcd_attached_device_info_t *device, usb_hc_endpoint_info_t *endpoint)
68{
69 transfer_info_t *transfer = malloc(sizeof(transfer_info_t));
70
71 transfer->size_transferred = NULL;
72 fibril_condvar_initialize(&transfer->condvar);
73 fibril_mutex_initialize(&transfer->condvar_guard);
74 transfer->done = false;
75
76 transfer->device = device;
77 transfer->endpoint = endpoint;
78
79 return transfer;
80}
81
82/** Destroy transfer info.
83 *
84 * @param transfer Transfer to be destroyed.
85 */
86static void transfer_info_destroy(transfer_info_t *transfer)
87{
88 free(transfer->device);
89 free(transfer->endpoint);
90 free(transfer);
91}
92
93/** Create info about attached device.
94 *
95 * @param address Device address.
96 * @return Device info structure.
97 */
98static usb_hcd_attached_device_info_t *create_attached_device_info(
99 usb_address_t address)
100{
101 usb_hcd_attached_device_info_t *dev
102 = malloc(sizeof(usb_hcd_attached_device_info_t));
103
104 dev->address = address;
105 dev->endpoint_count = 0;
106 dev->endpoints = NULL;
107 list_initialize(&dev->link);
108
109 return dev;
110}
111
112/** Create info about device endpoint.
113 *
114 * @param endpoint Endpoint number.
115 * @param direction Endpoint data direction.
116 * @param transfer_type Transfer type of the endpoint.
117 * @return Endpoint info structure.
118 */
119static usb_hc_endpoint_info_t *create_endpoint_info(usb_endpoint_t endpoint,
120 usb_direction_t direction, usb_transfer_type_t transfer_type)
121{
122 usb_hc_endpoint_info_t *ep = malloc(sizeof(usb_hc_endpoint_info_t));
123 ep->data_toggle = 0;
124 ep->direction = direction;
125 ep->transfer_type = transfer_type;
126 ep->endpoint = endpoint;
127
128 return ep;
129}
130
131/** Marks given transfer as done.
132 *
133 * @param transfer Transfer to be completed.
134 */
135static void transfer_mark_complete(transfer_info_t *transfer)
136{
137 fibril_mutex_lock(&transfer->condvar_guard);
138 transfer->done = true;
139 fibril_condvar_signal(&transfer->condvar);
140 fibril_mutex_unlock(&transfer->condvar_guard);
141}
142
143/** Callback for OUT transfers.
144 *
145 * @param hc Host controller that processed the transfer.
146 * @param outcome Transfer outcome.
147 * @param arg Custom argument.
148 */
149static void callback_out(usb_hc_device_t *hc,
150 usb_transaction_outcome_t outcome, void *arg)
151{
152 transfer_info_t *transfer = (transfer_info_t *) arg;
153
154 /*
155 * For out transfers, marking them complete is enough.
156 * No other processing is necessary.
157 */
158 transfer_mark_complete(transfer);
159}
160
161/** Callback for IN transfers.
162 *
163 * @param hc Host controller that processed the transfer.
164 * @param actual_size Number of actually transferred bytes.
165 * @param outcome Transfer outcome.
166 * @param arg Custom argument.
167 */
168static void callback_in(usb_hc_device_t *hc,
169 size_t actual_size, usb_transaction_outcome_t outcome, void *arg)
170{
171 transfer_info_t *transfer = (transfer_info_t *) arg;
172
173 /*
174 * Set the number of actually transferred bytes and
175 * mark the transfer as complete.
176 */
177 if (transfer->size_transferred != NULL) {
178 *transfer->size_transferred = actual_size;
179 }
180
181 transfer_mark_complete(transfer);
182}
183
184/** Issue interrupt OUT transfer to HC driven by current task.
185 *
186 * @param hc Host controller to handle the transfer.
187 * @param target Target device address.
188 * @param buffer Data buffer.
189 * @param size Buffer size.
190 * @param handle Transfer handle.
191 * @return Error code.
192 */
193int usb_hc_async_interrupt_out(usb_hc_device_t *hc, usb_target_t target,
194 void *buffer, size_t size,
195 usb_handle_t *handle)
196{
197 if ((hc->transfer_ops == NULL)
198 || (hc->transfer_ops->transfer_out == NULL)) {
199 return ENOTSUP;
200 }
201
202 /* This creation of the device on the fly is just a workaround. */
203
204 transfer_info_t *transfer = transfer_info_create(
205 create_attached_device_info(target.address),
206 create_endpoint_info(target.endpoint,
207 USB_DIRECTION_OUT, USB_TRANSFER_INTERRUPT));
208
209 int rc = hc->transfer_ops->transfer_out(hc,
210 transfer->device, transfer->endpoint,
211 buffer, size,
212 callback_out, transfer);
213
214 if (rc != EOK) {
215 transfer_info_destroy(transfer);
216 return rc;
217 }
218
219 *handle = (usb_handle_t)transfer;
220
221 return EOK;
222}
223
224
225/** Issue interrupt IN transfer to HC driven by current task.
226 *
227 * @warning The @p buffer and @p actual_size parameters shall not be
228 * touched until this transfer is waited for by usb_hc_async_wait_for().
229 *
230 * @param hc Host controller to handle the transfer.
231 * @param target Target device address.
232 * @param buffer Data buffer.
233 * @param size Buffer size.
234 * @param actual_size Size of actually transferred data.
235 * @param handle Transfer handle.
236 * @return Error code.
237 */
238int usb_hc_async_interrupt_in(usb_hc_device_t *hc, usb_target_t target,
239 void *buffer, size_t size, size_t *actual_size,
240 usb_handle_t *handle)
241{
242 if ((hc->transfer_ops == NULL)
243 || (hc->transfer_ops->transfer_in == NULL)) {
244 return ENOTSUP;
245 }
246
247 /* This creation of the device on the fly is just a workaround. */
248
249 transfer_info_t *transfer = transfer_info_create(
250 create_attached_device_info(target.address),
251 create_endpoint_info(target.endpoint,
252 USB_DIRECTION_IN, USB_TRANSFER_INTERRUPT));
253 transfer->size_transferred = actual_size;
254
255 int rc = hc->transfer_ops->transfer_in(hc,
256 transfer->device, transfer->endpoint,
257 buffer, size,
258 callback_in, transfer);
259
260 if (rc != EOK) {
261 transfer_info_destroy(transfer);
262 return rc;
263 }
264
265 *handle = (usb_handle_t)transfer;
266
267 return EOK;
268}
269
270/** Wait for transfer to complete.
271 *
272 * @param handle Transfer handle.
273 * @return Error code.
274 */
275int usb_hc_async_wait_for(usb_handle_t handle)
276{
277 transfer_info_t *transfer = (transfer_info_t *) handle;
278 if (transfer == NULL) {
279 return ENOENT;
280 }
281
282 fibril_mutex_lock(&transfer->condvar_guard);
283 while (!transfer->done) {
284 fibril_condvar_wait(&transfer->condvar, &transfer->condvar_guard);
285 }
286 fibril_mutex_unlock(&transfer->condvar_guard);
287
288 transfer_info_destroy(transfer);
289
290 return EOK;
291}
292
293/**
294 * @}
295 */
Note: See TracBrowser for help on using the repository browser.