source: mainline/uspace/drv/ohci/iface.c@ 2bf8f8c

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

Implement interface, add stub batch functions

  • Property mode set to 100644
File size: 16.6 KB
Line 
1/*
2 * Copyright (c) 2011 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/** @addtogroup drvusbohci
29 * @{
30 */
31/** @file
32 * USB-HC interface implementation.
33 */
34#include <ddf/driver.h>
35#include <ddf/interrupt.h>
36#include <device/hw_res.h>
37#include <errno.h>
38#include <str_error.h>
39
40#include <usb_iface.h>
41#include <usb/ddfiface.h>
42#include <usb/debug.h>
43
44#include "iface.h"
45#include "hc.h"
46
47#define UNSUPPORTED(methodname) \
48 usb_log_warning("Unsupported interface method `%s()' in %s:%d.\n", \
49 methodname, __FILE__, __LINE__)
50
51/** Reserve default address.
52 *
53 * This function may block the caller.
54 *
55 * @param[in] fun Device function the action was invoked on.
56 * @param[in] speed Speed of the device for which the default address is
57 * reserved.
58 * @return Error code.
59 */
60static int reserve_default_address(ddf_fun_t *fun, usb_speed_t speed)
61{
62 assert(fun);
63 hc_t *hc = fun_to_hc(fun);
64 assert(hc);
65 usb_log_debug("Default address request with speed %d.\n", speed);
66 device_keeper_reserve_default(&hc->manager, speed);
67 return EOK;
68}
69/*----------------------------------------------------------------------------*/
70/** Release default address.
71 *
72 * @param[in] fun Device function the action was invoked on.
73 * @return Error code.
74 */
75static int release_default_address(ddf_fun_t *fun)
76{
77 assert(fun);
78 hc_t *hc = fun_to_hc(fun);
79 assert(hc);
80 usb_log_debug("Default address release.\n");
81 device_keeper_release_default(&hc->manager);
82 return EOK;
83}
84/*----------------------------------------------------------------------------*/
85/** Found free USB address.
86 *
87 * @param[in] fun Device function the action was invoked on.
88 * @param[in] speed Speed of the device that will get this address.
89 * @param[out] address Non-null pointer where to store the free address.
90 * @return Error code.
91 */
92static int request_address(ddf_fun_t *fun, usb_speed_t speed,
93 usb_address_t *address)
94{
95 assert(fun);
96 hc_t *hc = fun_to_hc(fun);
97 assert(hc);
98 assert(address);
99
100 usb_log_debug("Address request with speed %d.\n", speed);
101 *address = device_keeper_request(&hc->manager, speed);
102 usb_log_debug("Address request with result: %d.\n", *address);
103 if (*address <= 0)
104 return *address;
105 return EOK;
106}
107/*----------------------------------------------------------------------------*/
108/** Bind USB address with device devman handle.
109 *
110 * @param[in] fun Device function the action was invoked on.
111 * @param[in] address USB address of the device.
112 * @param[in] handle Devman handle of the device.
113 * @return Error code.
114 */
115static int bind_address(ddf_fun_t *fun,
116 usb_address_t address, devman_handle_t handle)
117{
118 assert(fun);
119 hc_t *hc = fun_to_hc(fun);
120 assert(hc);
121 usb_log_debug("Address bind %d-%d.\n", address, handle);
122 device_keeper_bind(&hc->manager, address, handle);
123 return EOK;
124}
125/*----------------------------------------------------------------------------*/
126/** Release previously requested address.
127 *
128 * @param[in] fun Device function the action was invoked on.
129 * @param[in] address USB address to be released.
130 * @return Error code.
131 */
132static int release_address(ddf_fun_t *fun, usb_address_t address)
133{
134 assert(fun);
135 hc_t *hc = fun_to_hc(fun);
136 assert(hc);
137 usb_log_debug("Address release %d.\n", address);
138 device_keeper_release(&hc->manager, address);
139 return EOK;
140}
141
142/** Register endpoint for bandwidth reservation.
143 *
144 * @param[in] fun Device function the action was invoked on.
145 * @param[in] address USB address of the device.
146 * @param[in] endpoint Endpoint number.
147 * @param[in] transfer_type USB transfer type.
148 * @param[in] direction Endpoint data direction.
149 * @param[in] max_packet_size Max packet size of the endpoint.
150 * @param[in] interval Polling interval.
151 * @return Error code.
152 */
153static int register_endpoint(ddf_fun_t *fun,
154 usb_address_t address, usb_endpoint_t endpoint,
155 usb_transfer_type_t transfer_type, usb_direction_t direction,
156 size_t max_packet_size, unsigned int interval)
157{
158 UNSUPPORTED("register_endpoint");
159
160 return ENOTSUP;
161}
162
163/** Unregister endpoint (free some bandwidth reservation).
164 *
165 * @param[in] fun Device function the action was invoked on.
166 * @param[in] address USB address of the device.
167 * @param[in] endpoint Endpoint number.
168 * @param[in] direction Endpoint data direction.
169 * @return Error code.
170 */
171static int unregister_endpoint(ddf_fun_t *fun, usb_address_t address,
172 usb_endpoint_t endpoint, usb_direction_t direction)
173{
174 UNSUPPORTED("unregister_endpoint");
175
176 return ENOTSUP;
177}
178/*----------------------------------------------------------------------------*/
179/** Schedule interrupt out transfer.
180 *
181 * The callback is supposed to be called once the transfer (on the wire) is
182 * complete regardless of the outcome.
183 * However, the callback could be called only when this function returns
184 * with success status (i.e. returns EOK).
185 *
186 * @param[in] fun Device function the action was invoked on.
187 * @param[in] target Target pipe (address and endpoint number) specification.
188 * @param[in] max_packet_size Max packet size for the transfer.
189 * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
190 * by the caller).
191 * @param[in] size Size of the @p data buffer in bytes.
192 * @param[in] callback Callback to be issued once the transfer is complete.
193 * @param[in] arg Pass-through argument to the callback.
194 * @return Error code.
195 */
196static int interrupt_out(ddf_fun_t *fun, usb_target_t target,
197 size_t max_packet_size, void *data, size_t size,
198 usbhc_iface_transfer_out_callback_t callback, void *arg)
199{
200 hc_t *hc = fun_to_hc(fun);
201 assert(hc);
202 usb_speed_t speed = device_keeper_speed(&hc->manager, target.address);
203
204 usb_log_debug("Interrupt OUT %d:%d %zu(%zu).\n",
205 target.address, target.endpoint, size, max_packet_size);
206
207 batch_t *batch = batch_get(fun, target, USB_TRANSFER_INTERRUPT,
208 max_packet_size, speed, data, size, NULL, 0, NULL, callback, arg,
209 &hc->manager);
210 if (!batch)
211 return ENOMEM;
212 batch_interrupt_out(batch);
213 const int ret = hc_schedule(hc, batch);
214 if (ret != EOK) {
215 batch_dispose(batch);
216 return ret;
217 }
218 return EOK;
219}
220/*----------------------------------------------------------------------------*/
221/** Schedule interrupt in transfer.
222 *
223 * The callback is supposed to be called once the transfer (on the wire) is
224 * complete regardless of the outcome.
225 * However, the callback could be called only when this function returns
226 * with success status (i.e. returns EOK).
227 *
228 * @param[in] fun Device function the action was invoked on.
229 * @param[in] target Target pipe (address and endpoint number) specification.
230 * @param[in] max_packet_size Max packet size for the transfer.
231 * @param[in] data Buffer where to store the data (in USB endianess,
232 * allocated and deallocated by the caller).
233 * @param[in] size Size of the @p data buffer in bytes.
234 * @param[in] callback Callback to be issued once the transfer is complete.
235 * @param[in] arg Pass-through argument to the callback.
236 * @return Error code.
237 */
238static int interrupt_in(ddf_fun_t *fun, usb_target_t target,
239 size_t max_packet_size, void *data, size_t size,
240 usbhc_iface_transfer_in_callback_t callback, void *arg)
241{
242 assert(fun);
243 hc_t *hc = fun_to_hc(fun);
244 assert(hc);
245 usb_speed_t speed = device_keeper_speed(&hc->manager, target.address);
246 usb_log_debug("Interrupt IN %d:%d %zu(%zu).\n",
247 target.address, target.endpoint, size, max_packet_size);
248
249 batch_t *batch = batch_get(fun, target, USB_TRANSFER_INTERRUPT,
250 max_packet_size, speed, data, size, NULL, 0, callback, NULL, arg,
251 &hc->manager);
252 if (!batch)
253 return ENOMEM;
254 batch_interrupt_in(batch);
255 const int ret = hc_schedule(hc, batch);
256 if (ret != EOK) {
257 batch_dispose(batch);
258 return ret;
259 }
260 return EOK;
261}
262/*----------------------------------------------------------------------------*/
263/** Schedule bulk out transfer.
264 *
265 * The callback is supposed to be called once the transfer (on the wire) is
266 * complete regardless of the outcome.
267 * However, the callback could be called only when this function returns
268 * with success status (i.e. returns EOK).
269 *
270 * @param[in] fun Device function the action was invoked on.
271 * @param[in] target Target pipe (address and endpoint number) specification.
272 * @param[in] max_packet_size Max packet size for the transfer.
273 * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
274 * by the caller).
275 * @param[in] size Size of the @p data buffer in bytes.
276 * @param[in] callback Callback to be issued once the transfer is complete.
277 * @param[in] arg Pass-through argument to the callback.
278 * @return Error code.
279 */
280static int bulk_out(ddf_fun_t *fun, usb_target_t target,
281 size_t max_packet_size, void *data, size_t size,
282 usbhc_iface_transfer_out_callback_t callback, void *arg)
283{
284 assert(fun);
285 hc_t *hc = fun_to_hc(fun);
286 assert(hc);
287 usb_speed_t speed = device_keeper_speed(&hc->manager, target.address);
288
289 usb_log_debug("Bulk OUT %d:%d %zu(%zu).\n",
290 target.address, target.endpoint, size, max_packet_size);
291
292 batch_t *batch = batch_get(fun, target, USB_TRANSFER_BULK,
293 max_packet_size, speed, data, size, NULL, 0, NULL, callback, arg,
294 &hc->manager);
295 if (!batch)
296 return ENOMEM;
297 batch_bulk_out(batch);
298 const int ret = hc_schedule(hc, batch);
299 if (ret != EOK) {
300 batch_dispose(batch);
301 return ret;
302 }
303 return EOK;
304
305}
306/*----------------------------------------------------------------------------*/
307/** Schedule bulk in transfer.
308 *
309 * The callback is supposed to be called once the transfer (on the wire) is
310 * complete regardless of the outcome.
311 * However, the callback could be called only when this function returns
312 * with success status (i.e. returns EOK).
313 *
314 * @param[in] fun Device function the action was invoked on.
315 * @param[in] target Target pipe (address and endpoint number) specification.
316 * @param[in] max_packet_size Max packet size for the transfer.
317 * @param[in] data Buffer where to store the data (in USB endianess,
318 * allocated and deallocated by the caller).
319 * @param[in] size Size of the @p data buffer in bytes.
320 * @param[in] callback Callback to be issued once the transfer is complete.
321 * @param[in] arg Pass-through argument to the callback.
322 * @return Error code.
323 */
324static int bulk_in(ddf_fun_t *fun, usb_target_t target,
325 size_t max_packet_size, void *data, size_t size,
326 usbhc_iface_transfer_in_callback_t callback, void *arg)
327{
328 assert(fun);
329 hc_t *hc = fun_to_hc(fun);
330 assert(hc);
331 usb_speed_t speed = device_keeper_speed(&hc->manager, target.address);
332 usb_log_debug("Bulk IN %d:%d %zu(%zu).\n",
333 target.address, target.endpoint, size, max_packet_size);
334
335 batch_t *batch = batch_get(fun, target, USB_TRANSFER_BULK,
336 max_packet_size, speed, data, size, NULL, 0, callback, NULL, arg,
337 &hc->manager);
338 if (!batch)
339 return ENOMEM;
340 batch_bulk_in(batch);
341 const int ret = hc_schedule(hc, batch);
342 if (ret != EOK) {
343 batch_dispose(batch);
344 return ret;
345 }
346 return EOK;
347}
348/*----------------------------------------------------------------------------*/
349/** Schedule control write transfer.
350 *
351 * The callback is supposed to be called once the transfer (on the wire) is
352 * complete regardless of the outcome.
353 * However, the callback could be called only when this function returns
354 * with success status (i.e. returns EOK).
355 *
356 * @param[in] fun Device function the action was invoked on.
357 * @param[in] target Target pipe (address and endpoint number) specification.
358 * @param[in] max_packet_size Max packet size for the transfer.
359 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
360 * and deallocated by the caller).
361 * @param[in] setup_packet_size Size of @p setup_packet buffer in bytes.
362 * @param[in] data_buffer Data buffer (in USB endianess, allocated and
363 * deallocated by the caller).
364 * @param[in] data_buffer_size Size of @p data_buffer buffer in bytes.
365 * @param[in] callback Callback to be issued once the transfer is complete.
366 * @param[in] arg Pass-through argument to the callback.
367 * @return Error code.
368 */
369static int control_write(ddf_fun_t *fun, usb_target_t target,
370 size_t max_packet_size,
371 void *setup_data, size_t setup_size,
372 void *data, size_t size,
373 usbhc_iface_transfer_out_callback_t callback, void *arg)
374{
375 assert(fun);
376 hc_t *hc = fun_to_hc(fun);
377 assert(hc);
378 usb_speed_t speed = device_keeper_speed(&hc->manager, target.address);
379 usb_log_debug("Control WRITE (%d) %d:%d %zu(%zu).\n",
380 speed, target.address, target.endpoint, size, max_packet_size);
381
382 if (setup_size != 8)
383 return EINVAL;
384
385 batch_t *batch = batch_get(fun, target, USB_TRANSFER_CONTROL,
386 max_packet_size, speed, data, size, setup_data, setup_size,
387 NULL, callback, arg, &hc->manager);
388 if (!batch)
389 return ENOMEM;
390 device_keeper_reset_if_need(&hc->manager, target, setup_data);
391 batch_control_write(batch);
392 const int ret = hc_schedule(hc, batch);
393 if (ret != EOK) {
394 batch_dispose(batch);
395 return ret;
396 }
397 return EOK;
398}
399/*----------------------------------------------------------------------------*/
400/** Schedule control read transfer.
401 *
402 * The callback is supposed to be called once the transfer (on the wire) is
403 * complete regardless of the outcome.
404 * However, the callback could be called only when this function returns
405 * with success status (i.e. returns EOK).
406 *
407 * @param[in] fun Device function the action was invoked on.
408 * @param[in] target Target pipe (address and endpoint number) specification.
409 * @param[in] max_packet_size Max packet size for the transfer.
410 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
411 * and deallocated by the caller).
412 * @param[in] setup_packet_size Size of @p setup_packet buffer in bytes.
413 * @param[in] data_buffer Buffer where to store the data (in USB endianess,
414 * allocated and deallocated by the caller).
415 * @param[in] data_buffer_size Size of @p data_buffer buffer in bytes.
416 * @param[in] callback Callback to be issued once the transfer is complete.
417 * @param[in] arg Pass-through argument to the callback.
418 * @return Error code.
419 */
420static int control_read(ddf_fun_t *fun, usb_target_t target,
421 size_t max_packet_size,
422 void *setup_data, size_t setup_size,
423 void *data, size_t size,
424 usbhc_iface_transfer_in_callback_t callback, void *arg)
425{
426 assert(fun);
427 hc_t *hc = fun_to_hc(fun);
428 assert(hc);
429 usb_speed_t speed = device_keeper_speed(&hc->manager, target.address);
430
431 usb_log_debug("Control READ(%d) %d:%d %zu(%zu).\n",
432 speed, target.address, target.endpoint, size, max_packet_size);
433 batch_t *batch = batch_get(fun, target, USB_TRANSFER_CONTROL,
434 max_packet_size, speed, data, size, setup_data, setup_size, callback,
435 NULL, arg, &hc->manager);
436 if (!batch)
437 return ENOMEM;
438 batch_control_read(batch);
439 const int ret = hc_schedule(hc, batch);
440 if (ret != EOK) {
441 batch_dispose(batch);
442 return ret;
443 }
444 return EOK;
445}
446/*----------------------------------------------------------------------------*/
447/** Host controller interface implementation for OHCI. */
448usbhc_iface_t hc_iface = {
449 .reserve_default_address = reserve_default_address,
450 .release_default_address = release_default_address,
451 .request_address = request_address,
452 .bind_address = bind_address,
453 .release_address = release_address,
454
455 .register_endpoint = register_endpoint,
456 .unregister_endpoint = unregister_endpoint,
457
458 .interrupt_out = interrupt_out,
459 .interrupt_in = interrupt_in,
460
461 .bulk_out = bulk_out,
462 .bulk_in = bulk_in,
463
464 .control_write = control_write,
465 .control_read = control_read
466};
467
468/**
469 * @}
470 */
Note: See TracBrowser for help on using the repository browser.