source: mainline/uspace/lib/usbdev/src/pipes.c@ 023a902

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

libusbdev: Move unctions from pipesio.c to pipes.c

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