source: mainline/uspace/lib/usb/src/pipes.c@ 3937bda

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

Endpoint pipes has maximum packet size

  • Property mode set to 100644
File size: 14.1 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
29/** @addtogroup libusb
30 * @{
31 */
32/** @file
33 * Communication between device drivers and host controller driver.
34 *
35 * Note on synchronousness of the operations: there is ABSOLUTELY NO
36 * guarantee that a call to particular function will not trigger a fibril
37 * switch.
38 * The initialization functions may actually involve contacting some other
39 * task, starting/ending a session might involve asynchronous IPC and since
40 * the transfer functions uses IPC, asynchronous nature of them is obvious.
41 * The pseudo synchronous versions for the transfers internally call the
42 * asynchronous ones and so fibril switch is possible in them as well.
43 */
44#include <usb/usb.h>
45#include <usb/pipes.h>
46#include <errno.h>
47#include <assert.h>
48#include <usb/usbdrv.h>
49
50#define _PREPARE_TARGET(varname, pipe) \
51 usb_target_t varname = { \
52 .address = (pipe)->wire->address, \
53 .endpoint = (pipe)->endpoint_no \
54 }
55
56/** Initialize connection to USB device.
57 *
58 * @param connection Connection structure to be initialized.
59 * @param device Generic device backing the USB device.
60 * @return Error code.
61 */
62int usb_device_connection_initialize_from_device(
63 usb_device_connection_t *connection, device_t *device)
64{
65 assert(connection);
66 assert(device);
67
68 int rc;
69 devman_handle_t hc_handle;
70 usb_address_t my_address;
71
72 rc = usb_drv_find_hc(device, &hc_handle);
73 if (rc != EOK) {
74 return rc;
75 }
76
77 int hc_phone = devman_device_connect(hc_handle, 0);
78 if (hc_phone < 0) {
79 return hc_phone;
80 }
81
82 my_address = usb_drv_get_my_address(hc_phone, device);
83 if (my_address < 0) {
84 rc = my_address;
85 goto leave;
86 }
87
88 rc = usb_device_connection_initialize(connection,
89 hc_handle, my_address);
90
91leave:
92 async_hangup(hc_phone);
93 return rc;
94}
95
96/** Initialize connection to USB device.
97 *
98 * @param connection Connection structure to be initialized.
99 * @param host_controller_handle Devman handle of host controller device is
100 * connected to.
101 * @param device_address Device USB address.
102 * @return Error code.
103 */
104int usb_device_connection_initialize(usb_device_connection_t *connection,
105 devman_handle_t host_controller_handle, usb_address_t device_address)
106{
107 assert(connection);
108
109 if ((device_address < 0) || (device_address >= USB11_ADDRESS_MAX)) {
110 return EINVAL;
111 }
112
113 connection->hc_handle = host_controller_handle;
114 connection->address = device_address;
115
116 return EOK;
117}
118
119/** Initialize USB endpoint pipe.
120 *
121 * @param pipe Endpoint pipe to be initialized.
122 * @param connection Connection to the USB device backing this pipe (the wire).
123 * @param endpoint_no Endpoint number (in USB 1.1 in range 0 to 15).
124 * @param transfer_type Transfer type (e.g. interrupt or bulk).
125 * @param max_packet_size Maximum packet size in bytes.
126 * @param direction Endpoint direction (in/out).
127 * @return Error code.
128 */
129int usb_endpoint_pipe_initialize(usb_endpoint_pipe_t *pipe,
130 usb_device_connection_t *connection, usb_endpoint_t endpoint_no,
131 usb_transfer_type_t transfer_type, size_t max_packet_size,
132 usb_direction_t direction)
133{
134 assert(pipe);
135 assert(connection);
136
137 pipe->wire = connection;
138 pipe->hc_phone = -1;
139 pipe->endpoint_no = endpoint_no;
140 pipe->transfer_type = transfer_type;
141 pipe->max_packet_size = max_packet_size;
142 pipe->direction = direction;
143
144 return EOK;
145}
146
147
148/** Initialize USB endpoint pipe as the default zero control pipe.
149 *
150 * @param pipe Endpoint pipe to be initialized.
151 * @param connection Connection to the USB device backing this pipe (the wire).
152 * @return Error code.
153 */
154int usb_endpoint_pipe_initialize_default_control(usb_endpoint_pipe_t *pipe,
155 usb_device_connection_t *connection)
156{
157 assert(pipe);
158 assert(connection);
159
160 int rc = usb_endpoint_pipe_initialize(pipe, connection,
161 0, USB_TRANSFER_CONTROL, 8, USB_DIRECTION_BOTH);
162
163 return rc;
164}
165
166
167/** Start a session on the endpoint pipe.
168 *
169 * A session is something inside what any communication occurs.
170 * It is expected that sessions would be started right before the transfer
171 * and ended - see usb_endpoint_pipe_end_session() - after the last
172 * transfer.
173 * The reason for this is that session actually opens some communication
174 * channel to the host controller (or to the physical hardware if you
175 * wish) and thus it involves acquiring kernel resources.
176 * Since they are limited, sessions shall not be longer than strictly
177 * necessary.
178 *
179 * @param pipe Endpoint pipe to start the session on.
180 * @return Error code.
181 */
182int usb_endpoint_pipe_start_session(usb_endpoint_pipe_t *pipe)
183{
184 assert(pipe);
185
186 if (pipe->hc_phone >= 0) {
187 return EBUSY;
188 }
189
190 int phone = devman_device_connect(pipe->wire->hc_handle, 0);
191 if (phone < 0) {
192 return phone;
193 }
194
195 pipe->hc_phone = phone;
196
197 return EOK;
198}
199
200
201/** Ends a session on the endpoint pipe.
202 *
203 * @see usb_endpoint_pipe_start_session
204 *
205 * @param pipe Endpoint pipe to end the session on.
206 * @return Error code.
207 */
208int usb_endpoint_pipe_end_session(usb_endpoint_pipe_t *pipe)
209{
210 assert(pipe);
211
212 if (pipe->hc_phone < 0) {
213 return ENOENT;
214 }
215
216 int rc = async_hangup(pipe->hc_phone);
217 if (rc != EOK) {
218 return rc;
219 }
220
221 pipe->hc_phone = -1;
222
223 return EOK;
224}
225
226
227/** Request a read (in) transfer on an endpoint pipe.
228 *
229 * @param[in] pipe Pipe used for the transfer.
230 * @param[out] buffer Buffer where to store the data.
231 * @param[in] size Size of the buffer (in bytes).
232 * @param[out] size_transfered Number of bytes that were actually transfered.
233 * @return Error code.
234 */
235int usb_endpoint_pipe_read(usb_endpoint_pipe_t *pipe,
236 void *buffer, size_t size, size_t *size_transfered)
237{
238 assert(pipe);
239
240 int rc;
241 usb_handle_t handle;
242
243 rc = usb_endpoint_pipe_async_read(pipe, buffer, size, size_transfered,
244 &handle);
245 if (rc != EOK) {
246 return rc;
247 }
248
249 rc = usb_endpoint_pipe_wait_for(pipe, handle);
250 return rc;
251}
252
253/** Request a write (out) transfer on an endpoint pipe.
254 *
255 * @param[in] pipe Pipe used for the transfer.
256 * @param[in] buffer Buffer with data to transfer.
257 * @param[in] size Size of the buffer (in bytes).
258 * @return Error code.
259 */
260int usb_endpoint_pipe_write(usb_endpoint_pipe_t *pipe,
261 void *buffer, size_t size)
262{
263 assert(pipe);
264
265 int rc;
266 usb_handle_t handle;
267
268 rc = usb_endpoint_pipe_async_write(pipe, buffer, size, &handle);
269 if (rc != EOK) {
270 return rc;
271 }
272
273 rc = usb_endpoint_pipe_wait_for(pipe, handle);
274 return rc;
275}
276
277
278/** Request a control read transfer on an endpoint pipe.
279 *
280 * This function encapsulates all three stages of a control transfer.
281 *
282 * @param[in] pipe Pipe used for the transfer.
283 * @param[in] setup_buffer Buffer with the setup packet.
284 * @param[in] setup_buffer_size Size of the setup packet (in bytes).
285 * @param[out] data_buffer Buffer for incoming data.
286 * @param[in] data_buffer_size Size of the buffer for incoming data (in bytes).
287 * @param[out] data_transfered_size Number of bytes that were actually
288 * transfered during the DATA stage.
289 * @return Error code.
290 */
291int usb_endpoint_pipe_control_read(usb_endpoint_pipe_t *pipe,
292 void *setup_buffer, size_t setup_buffer_size,
293 void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size)
294{
295 assert(pipe);
296
297 int rc;
298 usb_handle_t handle;
299
300 rc = usb_endpoint_pipe_async_control_read(pipe,
301 setup_buffer, setup_buffer_size,
302 data_buffer, data_buffer_size, data_transfered_size,
303 &handle);
304 if (rc != EOK) {
305 return rc;
306 }
307
308 rc = usb_endpoint_pipe_wait_for(pipe, handle);
309 return rc;
310}
311
312
313/** Request a control write transfer on an endpoint pipe.
314 *
315 * This function encapsulates all three stages of a control transfer.
316 *
317 * @param[in] pipe Pipe used for the transfer.
318 * @param[in] setup_buffer Buffer with the setup packet.
319 * @param[in] setup_buffer_size Size of the setup packet (in bytes).
320 * @param[in] data_buffer Buffer with data to be sent.
321 * @param[in] data_buffer_size Size of the buffer with outgoing data (in bytes).
322 * @return Error code.
323 */
324int usb_endpoint_pipe_control_write(usb_endpoint_pipe_t *pipe,
325 void *setup_buffer, size_t setup_buffer_size,
326 void *data_buffer, size_t data_buffer_size)
327{
328 assert(pipe);
329
330 int rc;
331 usb_handle_t handle;
332
333 rc = usb_endpoint_pipe_async_control_write(pipe,
334 setup_buffer, setup_buffer_size,
335 data_buffer, data_buffer_size,
336 &handle);
337 if (rc != EOK) {
338 return rc;
339 }
340
341 rc = usb_endpoint_pipe_wait_for(pipe, handle);
342 return rc;
343}
344
345
346/** Request a read (in) transfer on an endpoint pipe (asynchronous version).
347 *
348 * @param[in] pipe Pipe used for the transfer.
349 * @param[out] buffer Buffer where to store the data.
350 * @param[in] size Size of the buffer (in bytes).
351 * @param[out] size_transfered Number of bytes that were actually transfered.
352 * @param[out] handle Handle of the transfer.
353 * @return Error code.
354 */
355int usb_endpoint_pipe_async_read(usb_endpoint_pipe_t *pipe,
356 void *buffer, size_t size, size_t *size_transfered,
357 usb_handle_t *handle)
358{
359 assert(pipe);
360
361 if (pipe->hc_phone < 0) {
362 return EBADF;
363 }
364
365 if (pipe->direction != USB_DIRECTION_IN) {
366 return EBADF;
367 }
368
369 int rc;
370 _PREPARE_TARGET(target, pipe);
371
372 switch (pipe->transfer_type) {
373 case USB_TRANSFER_INTERRUPT:
374 rc = usb_drv_async_interrupt_in(pipe->hc_phone, target,
375 buffer, size, size_transfered, handle);
376 break;
377 case USB_TRANSFER_CONTROL:
378 rc = EBADF;
379 break;
380 default:
381 rc = ENOTSUP;
382 break;
383 }
384
385 return rc;
386}
387
388
389/** Request a write (out) transfer on an endpoint pipe (asynchronous version).
390 *
391 * @param[in] pipe Pipe used for the transfer.
392 * @param[in] buffer Buffer with data to transfer.
393 * @param[in] size Size of the buffer (in bytes).
394 * @param[out] handle Handle of the transfer.
395 * @return Error code.
396 */
397int usb_endpoint_pipe_async_write(usb_endpoint_pipe_t *pipe,
398 void *buffer, size_t size,
399 usb_handle_t *handle)
400{
401 assert(pipe);
402
403 if (pipe->hc_phone < 0) {
404 return EBADF;
405 }
406
407 if (pipe->direction != USB_DIRECTION_OUT) {
408 return EBADF;
409 }
410
411 int rc;
412 _PREPARE_TARGET(target, pipe);
413
414 switch (pipe->transfer_type) {
415 case USB_TRANSFER_INTERRUPT:
416 rc = usb_drv_async_interrupt_out(pipe->hc_phone, target,
417 buffer, size, handle);
418 break;
419 case USB_TRANSFER_CONTROL:
420 rc = EBADF;
421 break;
422 default:
423 rc = ENOTSUP;
424 break;
425 }
426
427 return rc;
428}
429
430
431/** Request a control read transfer on an endpoint pipe (asynchronous version).
432 *
433 * This function encapsulates all three stages of a control transfer.
434 *
435 * @param[in] pipe Pipe used for the transfer.
436 * @param[in] setup_buffer Buffer with the setup packet.
437 * @param[in] setup_buffer_size Size of the setup packet (in bytes).
438 * @param[out] data_buffer Buffer for incoming data.
439 * @param[in] data_buffer_size Size of the buffer for incoming data (in bytes).
440 * @param[out] data_transfered_size Number of bytes that were actually
441 * transfered during the DATA stage.
442 * @param[out] handle Handle of the transfer.
443 * @return Error code.
444 */
445int usb_endpoint_pipe_async_control_read(usb_endpoint_pipe_t *pipe,
446 void *setup_buffer, size_t setup_buffer_size,
447 void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size,
448 usb_handle_t *handle)
449{
450 assert(pipe);
451
452 if (pipe->hc_phone < 0) {
453 return EBADF;
454 }
455
456 if ((pipe->direction != USB_DIRECTION_BOTH)
457 || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
458 return EBADF;
459 }
460
461 int rc;
462 _PREPARE_TARGET(target, pipe);
463
464 rc = usb_drv_async_control_read(pipe->hc_phone, target,
465 setup_buffer, setup_buffer_size,
466 data_buffer, data_buffer_size, data_transfered_size,
467 handle);
468
469 return rc;
470}
471
472
473/** Request a control write transfer on an endpoint pipe (asynchronous version).
474 *
475 * This function encapsulates all three stages of a control transfer.
476 *
477 * @param[in] pipe Pipe used for the transfer.
478 * @param[in] setup_buffer Buffer with the setup packet.
479 * @param[in] setup_buffer_size Size of the setup packet (in bytes).
480 * @param[in] data_buffer Buffer with data to be sent.
481 * @param[in] data_buffer_size Size of the buffer with outgoing data (in bytes).
482 * @param[out] handle Handle of the transfer.
483 * @return Error code.
484 */
485int usb_endpoint_pipe_async_control_write(usb_endpoint_pipe_t *pipe,
486 void *setup_buffer, size_t setup_buffer_size,
487 void *data_buffer, size_t data_buffer_size,
488 usb_handle_t *handle)
489{
490 assert(pipe);
491
492 if (pipe->hc_phone < 0) {
493 return EBADF;
494 }
495
496 if ((pipe->direction != USB_DIRECTION_BOTH)
497 || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
498 return EBADF;
499 }
500
501 int rc;
502 _PREPARE_TARGET(target, pipe);
503
504 rc = usb_drv_async_control_write(pipe->hc_phone, target,
505 setup_buffer, setup_buffer_size,
506 data_buffer, data_buffer_size,
507 handle);
508
509 return rc;
510}
511
512/** Wait for transfer completion.
513 *
514 * The function blocks the caller fibril until the transfer associated
515 * with given @p handle is completed.
516 *
517 * @param[in] pipe Pipe the transfer executed on.
518 * @param[in] handle Transfer handle.
519 * @return Error code.
520 */
521int usb_endpoint_pipe_wait_for(usb_endpoint_pipe_t *pipe, usb_handle_t handle)
522{
523 return usb_drv_async_wait_for(handle);
524}
525
526
527/**
528 * @}
529 */
Note: See TracBrowser for help on using the repository browser.