source: mainline/uspace/lib/usbdev/src/pipes.c@ 25effe2

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

libus*: remove optical separators

  • Property mode set to 100644
File size: 9.3 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 uint64_t setup_packet;
121 memcpy(&setup_packet, setup_buffer, 8);
122
123 size_t act_size = 0;
124 const int rc = usb_device_control_read(pipe->wire,
125 pipe->endpoint_no, setup_packet, buffer, buffer_size, &act_size);
126
127 if (rc == ESTALL) {
128 clear_self_endpoint_halt(pipe);
129 }
130
131 if (rc == EOK && transfered_size != NULL) {
132 *transfered_size = act_size;
133 }
134
135 return rc;
136}
137
138/** Request a control write transfer on an endpoint pipe.
139 *
140 * This function encapsulates all three stages of a control transfer.
141 *
142 * @param[in] pipe Pipe used for the transfer.
143 * @param[in] setup_buffer Buffer with the setup packet.
144 * @param[in] setup_buffer_size Size of the setup packet (in bytes).
145 * @param[in] data_buffer Buffer with data to be sent.
146 * @param[in] data_buffer_size Size of the buffer with outgoing data (in bytes).
147 * @return Error code.
148 */
149int usb_pipe_control_write(usb_pipe_t *pipe,
150 const void *setup_buffer, size_t setup_buffer_size,
151 const void *buffer, size_t buffer_size)
152{
153 assert(pipe);
154
155 if ((setup_buffer == NULL) || (setup_buffer_size != 8)) {
156 return EINVAL;
157 }
158
159 if ((buffer == NULL) && (buffer_size > 0)) {
160 return EINVAL;
161 }
162
163 if ((buffer != NULL) && (buffer_size == 0)) {
164 return EINVAL;
165 }
166
167 if ((pipe->direction != USB_DIRECTION_BOTH)
168 || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
169 return EBADF;
170 }
171
172 uint64_t setup_packet;
173 memcpy(&setup_packet, setup_buffer, 8);
174
175 const int rc = usb_device_control_write(pipe->wire,
176 pipe->endpoint_no, setup_packet, buffer, buffer_size);
177
178 if (rc == ESTALL) {
179 clear_self_endpoint_halt(pipe);
180 }
181
182 return rc;
183}
184
185/** Request a read (in) transfer on an endpoint pipe.
186 *
187 * @param[in] pipe Pipe used for the transfer.
188 * @param[out] buffer Buffer where to store the data.
189 * @param[in] size Size of the buffer (in bytes).
190 * @param[out] size_transfered Number of bytes that were actually transfered.
191 * @return Error code.
192 */
193int usb_pipe_read(usb_pipe_t *pipe,
194 void *buffer, size_t size, size_t *size_transfered)
195{
196 assert(pipe);
197
198 if (buffer == NULL) {
199 return EINVAL;
200 }
201
202 if (size == 0) {
203 return EINVAL;
204 }
205
206 if (pipe->direction != USB_DIRECTION_IN) {
207 return EBADF;
208 }
209
210 if (pipe->transfer_type == USB_TRANSFER_CONTROL) {
211 return EBADF;
212 }
213
214 /* Isochronous transfer are not supported (yet) */
215 if (pipe->transfer_type != USB_TRANSFER_INTERRUPT &&
216 pipe->transfer_type != USB_TRANSFER_BULK)
217 return ENOTSUP;
218
219 size_t act_size = 0;
220 const int rc = usb_device_read(pipe->wire,
221 pipe->endpoint_no, buffer, size, &act_size);
222
223 if (rc == EOK && size_transfered != NULL) {
224 *size_transfered = act_size;
225 }
226
227 return rc;
228}
229
230/** Request a write (out) transfer on an endpoint pipe.
231 *
232 * @param[in] pipe Pipe used for the transfer.
233 * @param[in] buffer Buffer with data to transfer.
234 * @param[in] size Size of the buffer (in bytes).
235 * @return Error code.
236 */
237int usb_pipe_write(usb_pipe_t *pipe, const void *buffer, size_t size)
238{
239 assert(pipe);
240
241 if (buffer == NULL || size == 0) {
242 return EINVAL;
243 }
244
245 if (pipe->direction != USB_DIRECTION_OUT) {
246 return EBADF;
247 }
248
249 if (pipe->transfer_type == USB_TRANSFER_CONTROL) {
250 return EBADF;
251 }
252
253 /* Isochronous transfer are not supported (yet) */
254 if (pipe->transfer_type != USB_TRANSFER_INTERRUPT &&
255 pipe->transfer_type != USB_TRANSFER_BULK)
256 return ENOTSUP;
257
258 return usb_device_write(pipe->wire,
259 pipe->endpoint_no, buffer, size);
260}
261
262/** Initialize USB endpoint pipe.
263 *
264 * @param pipe Endpoint pipe to be initialized.
265 * @param connection Connection to the USB device backing this pipe (the wire).
266 * @param endpoint_no Endpoint number (in USB 1.1 in range 0 to 15).
267 * @param transfer_type Transfer type (e.g. interrupt or bulk).
268 * @param max_packet_size Maximum packet size in bytes.
269 * @param direction Endpoint direction (in/out).
270 * @return Error code.
271 */
272int usb_pipe_initialize(usb_pipe_t *pipe,
273 usb_device_connection_t *connection, usb_endpoint_t endpoint_no,
274 usb_transfer_type_t transfer_type, size_t max_packet_size,
275 usb_direction_t direction)
276{
277 assert(pipe);
278 assert(connection);
279
280 pipe->wire = connection;
281 pipe->endpoint_no = endpoint_no;
282 pipe->transfer_type = transfer_type;
283 pipe->max_packet_size = max_packet_size;
284 pipe->direction = direction;
285 pipe->auto_reset_halt = false;
286
287 return EOK;
288}
289
290/** Initialize USB endpoint pipe as the default zero control pipe.
291 *
292 * @param pipe Endpoint pipe to be initialized.
293 * @param connection Connection to the USB device backing this pipe (the wire).
294 * @return Error code.
295 */
296int usb_pipe_initialize_default_control(usb_pipe_t *pipe,
297 usb_device_connection_t *connection)
298{
299 assert(pipe);
300 assert(connection);
301
302 int rc = usb_pipe_initialize(pipe, connection, 0, USB_TRANSFER_CONTROL,
303 CTRL_PIPE_MIN_PACKET_SIZE, USB_DIRECTION_BOTH);
304
305 pipe->auto_reset_halt = true;
306
307 return rc;
308}
309
310/** Register endpoint with the host controller.
311 *
312 * @param pipe Pipe to be registered.
313 * @param interval Polling interval.
314 * @return Error code.
315 */
316int usb_pipe_register(usb_pipe_t *pipe, unsigned interval)
317{
318 assert(pipe);
319 assert(pipe->wire);
320
321 return usb_device_register_endpoint(pipe->wire,
322 pipe->endpoint_no, pipe->transfer_type,
323 pipe->direction, pipe->max_packet_size, interval);
324}
325
326/** Revert endpoint registration with the host controller.
327 *
328 * @param pipe Pipe to be unregistered.
329 * @return Error code.
330 */
331int usb_pipe_unregister(usb_pipe_t *pipe)
332{
333 assert(pipe);
334 assert(pipe->wire);
335
336 return usb_device_unregister_endpoint(pipe->wire,
337 pipe->endpoint_no, pipe->direction);
338}
339
340/**
341 * @}
342 */
Note: See TracBrowser for help on using the repository browser.