source: mainline/uspace/lib/usb/src/pipes.c@ 3e9074f

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

Rename connection initialization function

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