source: mainline/uspace/lib/usbdev/src/pipes.c@ 22ecbde

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

libusbdev: Cleanup. Remove redundant functions.

  • Property mode set to 100644
File size: 10.7 KB
Line 
1/*
2 * Copyright (c) 2011 Vojtech Horky
3 * Copyright (c) 2011 Jan Vesely
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29/** @addtogroup libusbdev
30 * @{
31 */
32/** @file
33 * USB endpoint pipes functions.
34 */
35#include <usb/dev/pipes.h>
36#include <usb/dev/request.h>
37#include <errno.h>
38#include <assert.h>
39
40/** Prepare pipe for a long transfer.
41 *
42 * Long transfer is transfer consisting of several requests to the HC.
43 * Calling this function is optional and it has positive effect of
44 * improved performance because IPC session is initiated only once.
45 *
46 * @param pipe Pipe over which the transfer will happen.
47 * @return Error code.
48 */
49int usb_pipe_start_long_transfer(usb_pipe_t *pipe)
50{
51 assert(pipe);
52 assert(pipe->wire);
53 assert(pipe->wire->hc_connection);
54 return usb_hc_connection_open(pipe->wire->hc_connection);
55}
56/*----------------------------------------------------------------------------*/
57/** Terminate a long transfer on a pipe.
58 * @param pipe Pipe where to end the long transfer.
59 * @return Error code.
60 * @see usb_pipe_start_long_transfer
61 */
62int usb_pipe_end_long_transfer(usb_pipe_t *pipe)
63{
64 assert(pipe);
65 assert(pipe->wire);
66 assert(pipe->wire->hc_connection);
67 return usb_hc_connection_close(pipe->wire->hc_connection);
68}
69/*----------------------------------------------------------------------------*/
70/** Try to clear endpoint halt of default control pipe.
71 *
72 * @param pipe Pipe for control endpoint zero.
73 */
74static void clear_self_endpoint_halt(usb_pipe_t *pipe)
75{
76 assert(pipe != NULL);
77
78 if (!pipe->auto_reset_halt || (pipe->endpoint_no != 0)) {
79 return;
80 }
81
82 /* Prevent infinite recursion. */
83 pipe->auto_reset_halt = false;
84 usb_request_clear_endpoint_halt(pipe, 0);
85 pipe->auto_reset_halt = true;
86}
87/*----------------------------------------------------------------------------*/
88/** Request a control read transfer on an endpoint pipe.
89 *
90 * This function encapsulates all three stages of a control transfer.
91 *
92 * @param[in] pipe Pipe used for the transfer.
93 * @param[in] setup_buffer Buffer with the setup packet.
94 * @param[in] setup_buffer_size Size of the setup packet (in bytes).
95 * @param[out] data_buffer Buffer for incoming data.
96 * @param[in] data_buffer_size Size of the buffer for incoming data (in bytes).
97 * @param[out] data_transfered_size Number of bytes that were actually
98 * transfered during the DATA stage.
99 * @return Error code.
100 */
101int usb_pipe_control_read(usb_pipe_t *pipe,
102 const void *setup_buffer, size_t setup_buffer_size,
103 void *buffer, size_t buffer_size, size_t *transfered_size)
104{
105 assert(pipe);
106
107 if ((setup_buffer == NULL) || (setup_buffer_size != 8)) {
108 return EINVAL;
109 }
110
111 if ((buffer == NULL) || (buffer_size == 0)) {
112 return EINVAL;
113 }
114
115 if ((pipe->direction != USB_DIRECTION_BOTH)
116 || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
117 return EBADF;
118 }
119
120 /* Isochronous transfer are not supported (yet) */
121 if (pipe->transfer_type != USB_TRANSFER_INTERRUPT &&
122 pipe->transfer_type != USB_TRANSFER_BULK &&
123 pipe->transfer_type != USB_TRANSFER_CONTROL)
124 return ENOTSUP;
125
126 uint64_t setup_packet;
127 memcpy(&setup_packet, setup_buffer, 8);
128
129 size_t act_size = 0;
130 const int rc = usb_device_control_read(pipe->wire,
131 pipe->endpoint_no, setup_packet, buffer, buffer_size, &act_size);
132
133 if (rc == ESTALL) {
134 clear_self_endpoint_halt(pipe);
135 }
136
137 if (rc == EOK && transfered_size != NULL) {
138 *transfered_size = act_size;
139 }
140
141 return rc;
142}
143/*----------------------------------------------------------------------------*/
144/** Request a control write transfer on an endpoint pipe.
145 *
146 * This function encapsulates all three stages of a control transfer.
147 *
148 * @param[in] pipe Pipe used for the transfer.
149 * @param[in] setup_buffer Buffer with the setup packet.
150 * @param[in] setup_buffer_size Size of the setup packet (in bytes).
151 * @param[in] data_buffer Buffer with data to be sent.
152 * @param[in] data_buffer_size Size of the buffer with outgoing data (in bytes).
153 * @return Error code.
154 */
155int usb_pipe_control_write(usb_pipe_t *pipe,
156 const void *setup_buffer, size_t setup_buffer_size,
157 const void *buffer, size_t buffer_size)
158{
159 assert(pipe);
160
161 if ((setup_buffer == NULL) || (setup_buffer_size != 8)) {
162 return EINVAL;
163 }
164
165 if ((buffer == NULL) && (buffer_size > 0)) {
166 return EINVAL;
167 }
168
169 if ((buffer != NULL) && (buffer_size == 0)) {
170 return EINVAL;
171 }
172
173 if ((pipe->direction != USB_DIRECTION_BOTH)
174 || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
175 return EBADF;
176 }
177
178 /* Isochronous transfer are not supported (yet) */
179 if (pipe->transfer_type != USB_TRANSFER_INTERRUPT &&
180 pipe->transfer_type != USB_TRANSFER_BULK &&
181 pipe->transfer_type != USB_TRANSFER_CONTROL)
182 return ENOTSUP;
183
184 uint64_t setup_packet;
185 memcpy(&setup_packet, setup_buffer, 8);
186
187 const int rc = usb_device_control_write(pipe->wire,
188 pipe->endpoint_no, setup_packet, buffer, buffer_size);
189
190 if (rc == ESTALL) {
191 clear_self_endpoint_halt(pipe);
192 }
193
194 return rc;
195}
196/*----------------------------------------------------------------------------*/
197/** Request a read (in) transfer on an endpoint pipe.
198 *
199 * @param[in] pipe Pipe used for the transfer.
200 * @param[out] buffer Buffer where to store the data.
201 * @param[in] size Size of the buffer (in bytes).
202 * @param[out] size_transfered Number of bytes that were actually transfered.
203 * @return Error code.
204 */
205int usb_pipe_read(usb_pipe_t *pipe,
206 void *buffer, size_t size, size_t *size_transfered)
207{
208 assert(pipe);
209
210 if (buffer == NULL) {
211 return EINVAL;
212 }
213
214 if (size == 0) {
215 return EINVAL;
216 }
217
218 if (pipe->direction != USB_DIRECTION_IN) {
219 return EBADF;
220 }
221
222 if (pipe->transfer_type == USB_TRANSFER_CONTROL) {
223 return EBADF;
224 }
225
226 /* Isochronous transfer are not supported (yet) */
227 if (pipe->transfer_type != USB_TRANSFER_INTERRUPT &&
228 pipe->transfer_type != USB_TRANSFER_BULK &&
229 pipe->transfer_type != USB_TRANSFER_CONTROL)
230 return ENOTSUP;
231
232 size_t act_size = 0;
233 const int rc = usb_device_read(pipe->wire,
234 pipe->endpoint_no, buffer, size, &act_size);
235
236 if (rc == EOK && size_transfered != NULL) {
237 *size_transfered = act_size;
238 }
239
240 return rc;
241}
242/*----------------------------------------------------------------------------*/
243/** Request a write (out) transfer on an endpoint pipe.
244 *
245 * @param[in] pipe Pipe used for the transfer.
246 * @param[in] buffer Buffer with data to transfer.
247 * @param[in] size Size of the buffer (in bytes).
248 * @return Error code.
249 */
250int usb_pipe_write(usb_pipe_t *pipe, const void *buffer, size_t size)
251{
252 assert(pipe);
253
254 if (buffer == NULL || size == 0) {
255 return EINVAL;
256 }
257
258 if (pipe->direction != USB_DIRECTION_OUT) {
259 return EBADF;
260 }
261
262 if (pipe->transfer_type == USB_TRANSFER_CONTROL) {
263 return EBADF;
264 }
265
266 /* Isochronous transfer are not supported (yet) */
267 if (pipe->transfer_type != USB_TRANSFER_INTERRUPT &&
268 pipe->transfer_type != USB_TRANSFER_BULK &&
269 pipe->transfer_type != USB_TRANSFER_CONTROL)
270 return ENOTSUP;
271
272 return usb_device_write(pipe->wire,
273 pipe->endpoint_no, buffer, size);
274}
275/*----------------------------------------------------------------------------*/
276/** Initialize USB endpoint pipe.
277 *
278 * @param pipe Endpoint pipe to be initialized.
279 * @param connection Connection to the USB device backing this pipe (the wire).
280 * @param endpoint_no Endpoint number (in USB 1.1 in range 0 to 15).
281 * @param transfer_type Transfer type (e.g. interrupt or bulk).
282 * @param max_packet_size Maximum packet size in bytes.
283 * @param direction Endpoint direction (in/out).
284 * @return Error code.
285 */
286int usb_pipe_initialize(usb_pipe_t *pipe,
287 usb_device_connection_t *connection, usb_endpoint_t endpoint_no,
288 usb_transfer_type_t transfer_type, size_t max_packet_size,
289 usb_direction_t direction)
290{
291 assert(pipe);
292 assert(connection);
293
294 pipe->wire = connection;
295 pipe->endpoint_no = endpoint_no;
296 pipe->transfer_type = transfer_type;
297 pipe->max_packet_size = max_packet_size;
298 pipe->direction = direction;
299 pipe->auto_reset_halt = false;
300
301 return EOK;
302}
303/*----------------------------------------------------------------------------*/
304/** Initialize USB endpoint pipe as the default zero control pipe.
305 *
306 * @param pipe Endpoint pipe to be initialized.
307 * @param connection Connection to the USB device backing this pipe (the wire).
308 * @return Error code.
309 */
310int usb_pipe_initialize_default_control(usb_pipe_t *pipe,
311 usb_device_connection_t *connection)
312{
313 assert(pipe);
314 assert(connection);
315
316 int rc = usb_pipe_initialize(pipe, connection, 0, USB_TRANSFER_CONTROL,
317 CTRL_PIPE_MIN_PACKET_SIZE, USB_DIRECTION_BOTH);
318
319 pipe->auto_reset_halt = true;
320
321 return rc;
322}
323/*----------------------------------------------------------------------------*/
324/** Register endpoint with the host controller.
325 *
326 * @param pipe Pipe to be registered.
327 * @param interval Polling interval.
328 * @return Error code.
329 */
330int usb_pipe_register(usb_pipe_t *pipe, unsigned interval)
331{
332 assert(pipe);
333 assert(pipe->wire);
334
335 return usb_device_register_endpoint(pipe->wire,
336 pipe->endpoint_no, pipe->transfer_type,
337 pipe->direction, pipe->max_packet_size, interval);
338}
339/*----------------------------------------------------------------------------*/
340/** Revert endpoint registration with the host controller.
341 *
342 * @param pipe Pipe to be unregistered.
343 * @return Error code.
344 */
345int usb_pipe_unregister(usb_pipe_t *pipe)
346{
347 assert(pipe);
348 assert(pipe->wire);
349
350 return usb_device_unregister_endpoint(pipe->wire,
351 pipe->endpoint_no, pipe->direction);
352}
353
354/**
355 * @}
356 */
Note: See TracBrowser for help on using the repository browser.