source: mainline/uspace/lib/usbdev/src/pipes.c@ 1561e8b

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

libusbdev: Use provided usb_device_connection_t wrappers.

  • Property mode set to 100644
File size: 8.9 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 miscellaneous 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 * By a long transfer is mean transfer consisting of several
43 * requests to the HC.
44 * Calling such function is optional and it has positive effect of
45 * improved performance because IPC session is initiated only once.
46 *
47 * @param pipe Pipe over which the transfer will happen.
48 * @return Error code.
49 */
50int usb_pipe_start_long_transfer(usb_pipe_t *pipe)
51{
52 assert(pipe);
53 assert(pipe->wire);
54 assert(pipe->wire->hc_connection);
55 return usb_hc_connection_open(pipe->wire->hc_connection);
56}
57/*----------------------------------------------------------------------------*/
58/** Terminate a long transfer on a pipe.
59 *
60 * @see usb_pipe_start_long_transfer
61 *
62 * @param pipe Pipe where to end the long transfer.
63 */
64int usb_pipe_end_long_transfer(usb_pipe_t *pipe)
65{
66 assert(pipe);
67 assert(pipe->wire);
68 assert(pipe->wire->hc_connection);
69 return usb_hc_connection_close(pipe->wire->hc_connection);
70}
71/*----------------------------------------------------------------------------*/
72/** Request an in transfer, no checking of input parameters.
73 *
74 * @param[in] pipe Pipe used for the transfer.
75 * @param[out] buffer Buffer where to store the data.
76 * @param[in] size Size of the buffer (in bytes).
77 * @param[out] size_transfered Number of bytes that were actually transfered.
78 * @return Error code.
79 */
80static int usb_pipe_read_no_check(usb_pipe_t *pipe, uint64_t setup,
81 void *buffer, size_t size, size_t *size_transfered)
82{
83 /* Isochronous transfer are not supported (yet) */
84 if (pipe->transfer_type != USB_TRANSFER_INTERRUPT &&
85 pipe->transfer_type != USB_TRANSFER_BULK &&
86 pipe->transfer_type != USB_TRANSFER_CONTROL)
87 return ENOTSUP;
88
89 return usb_device_control_read(pipe->wire,
90 pipe->endpoint_no, setup, buffer, size, size_transfered);
91}
92/*----------------------------------------------------------------------------*/
93/** Request an out transfer, no checking of input parameters.
94 *
95 * @param[in] pipe Pipe used for the transfer.
96 * @param[in] buffer Buffer with data to transfer.
97 * @param[in] size Size of the buffer (in bytes).
98 * @return Error code.
99 */
100static int usb_pipe_write_no_check(usb_pipe_t *pipe, uint64_t setup,
101 const void *buffer, size_t size)
102{
103 /* Only interrupt and bulk transfers are supported */
104 if (pipe->transfer_type != USB_TRANSFER_INTERRUPT &&
105 pipe->transfer_type != USB_TRANSFER_BULK &&
106 pipe->transfer_type != USB_TRANSFER_CONTROL)
107 return ENOTSUP;
108
109 return usb_device_control_write(pipe->wire,
110 pipe->endpoint_no, setup, buffer, size);
111}
112/*----------------------------------------------------------------------------*/
113/** Try to clear endpoint halt of default control pipe.
114 *
115 * @param pipe Pipe for control endpoint zero.
116 */
117static void clear_self_endpoint_halt(usb_pipe_t *pipe)
118{
119 assert(pipe != NULL);
120
121 if (!pipe->auto_reset_halt || (pipe->endpoint_no != 0)) {
122 return;
123 }
124
125
126 /* Prevent infinite recursion. */
127 pipe->auto_reset_halt = false;
128 usb_request_clear_endpoint_halt(pipe, 0);
129 pipe->auto_reset_halt = true;
130}
131/*----------------------------------------------------------------------------*/
132/** Request a control read transfer on an endpoint pipe.
133 *
134 * This function encapsulates all three stages of a control transfer.
135 *
136 * @param[in] pipe Pipe used for the transfer.
137 * @param[in] setup_buffer Buffer with the setup packet.
138 * @param[in] setup_buffer_size Size of the setup packet (in bytes).
139 * @param[out] data_buffer Buffer for incoming data.
140 * @param[in] data_buffer_size Size of the buffer for incoming data (in bytes).
141 * @param[out] data_transfered_size Number of bytes that were actually
142 * transfered during the DATA stage.
143 * @return Error code.
144 */
145int usb_pipe_control_read(usb_pipe_t *pipe,
146 const void *setup_buffer, size_t setup_buffer_size,
147 void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size)
148{
149 assert(pipe);
150
151 if ((setup_buffer == NULL) || (setup_buffer_size != 8)) {
152 return EINVAL;
153 }
154
155 if ((data_buffer == NULL) || (data_buffer_size == 0)) {
156 return EINVAL;
157 }
158
159 if ((pipe->direction != USB_DIRECTION_BOTH)
160 || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
161 return EBADF;
162 }
163
164 uint64_t setup_packet;
165 memcpy(&setup_packet, setup_buffer, 8);
166
167 size_t act_size = 0;
168 const int rc = usb_pipe_read_no_check(pipe, setup_packet,
169 data_buffer, data_buffer_size, &act_size);
170
171 if (rc == ESTALL) {
172 clear_self_endpoint_halt(pipe);
173 }
174
175 if (rc == EOK && data_transfered_size != NULL) {
176 *data_transfered_size = act_size;
177 }
178
179 return rc;
180}
181/*----------------------------------------------------------------------------*/
182/** Request a control write transfer on an endpoint pipe.
183 *
184 * This function encapsulates all three stages of a control transfer.
185 *
186 * @param[in] pipe Pipe used for the transfer.
187 * @param[in] setup_buffer Buffer with the setup packet.
188 * @param[in] setup_buffer_size Size of the setup packet (in bytes).
189 * @param[in] data_buffer Buffer with data to be sent.
190 * @param[in] data_buffer_size Size of the buffer with outgoing data (in bytes).
191 * @return Error code.
192 */
193int usb_pipe_control_write(usb_pipe_t *pipe,
194 const void *setup_buffer, size_t setup_buffer_size,
195 const void *data_buffer, size_t data_buffer_size)
196{
197 assert(pipe);
198
199 if ((setup_buffer == NULL) || (setup_buffer_size != 8)) {
200 return EINVAL;
201 }
202
203 if ((data_buffer == NULL) && (data_buffer_size > 0)) {
204 return EINVAL;
205 }
206
207 if ((data_buffer != NULL) && (data_buffer_size == 0)) {
208 return EINVAL;
209 }
210
211 if ((pipe->direction != USB_DIRECTION_BOTH)
212 || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
213 return EBADF;
214 }
215
216 uint64_t setup_packet;
217 memcpy(&setup_packet, setup_buffer, 8);
218
219 const int rc = usb_pipe_write_no_check(pipe, setup_packet,
220 data_buffer, data_buffer_size);
221
222 if (rc == ESTALL) {
223 clear_self_endpoint_halt(pipe);
224 }
225
226 return rc;
227}
228/*----------------------------------------------------------------------------*/
229/** Request a read (in) transfer on an endpoint pipe.
230 *
231 * @param[in] pipe Pipe used for the transfer.
232 * @param[out] buffer Buffer where to store the data.
233 * @param[in] size Size of the buffer (in bytes).
234 * @param[out] size_transfered Number of bytes that were actually transfered.
235 * @return Error code.
236 */
237int usb_pipe_read(usb_pipe_t *pipe,
238 void *buffer, size_t size, size_t *size_transfered)
239{
240 assert(pipe);
241
242 if (buffer == NULL) {
243 return EINVAL;
244 }
245
246 if (size == 0) {
247 return EINVAL;
248 }
249
250 if (pipe->direction != USB_DIRECTION_IN) {
251 return EBADF;
252 }
253
254 if (pipe->transfer_type == USB_TRANSFER_CONTROL) {
255 return EBADF;
256 }
257
258 size_t act_size = 0;
259 const int rc = usb_pipe_read_no_check(pipe, 0, buffer, size, &act_size);
260
261
262 if (rc == EOK && size_transfered != NULL) {
263 *size_transfered = act_size;
264 }
265
266 return rc;
267}
268/*----------------------------------------------------------------------------*/
269/** Request a write (out) transfer on an endpoint pipe.
270 *
271 * @param[in] pipe Pipe used for the transfer.
272 * @param[in] buffer Buffer with data to transfer.
273 * @param[in] size Size of the buffer (in bytes).
274 * @return Error code.
275 */
276int usb_pipe_write(usb_pipe_t *pipe, const void *buffer, size_t size)
277{
278 assert(pipe);
279
280 if (buffer == NULL || size == 0) {
281 return EINVAL;
282 }
283
284 if (pipe->direction != USB_DIRECTION_OUT) {
285 return EBADF;
286 }
287
288 if (pipe->transfer_type == USB_TRANSFER_CONTROL) {
289 return EBADF;
290 }
291
292 return usb_pipe_write_no_check(pipe, 0, buffer, size);
293}
294/**
295 * @}
296 */
Note: See TracBrowser for help on using the repository browser.