Isochronous endpoint I/O
[platform/upstream/libusb.git] / libusb / sync.c
1 /*
2  * Synchronous I/O functions for libusb
3  * Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19
20 #include <config.h>
21 #include <errno.h>
22 #include <stdint.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include "libusbi.h"
27
28 /**
29  * @defgroup syncio Synchronous device I/O
30  *
31  * This page documents libusb's synchronous (blocking) API for USB device I/O.
32  * This interface is easy to use but has some limitations. More advanced users
33  * may wish to consider using the \ref asyncio "asynchronous I/O API" instead.
34  */
35
36 static void ctrl_transfer_cb(struct libusb_transfer *transfer)
37 {
38         int *completed = transfer->user_data;
39         *completed = 1;
40         usbi_dbg("actual_length=%d", transfer->actual_length);
41         /* caller interprets result and frees transfer */
42 }
43
44 /* FIXME: does this support partial transfers? */
45 /** \ingroup syncio
46  * Perform a USB control transfer. The direction of the transfer is inferred
47  * from the bmRequestType field of the setup packet.
48  *
49  * \param dev_handle a handle for the device to communicate with
50  * \param bmRequestType the request type field for the setup packet
51  * \param bRequest the request field for the setup packet
52  * \param wValue the value field for the setup packet
53  * \param wIndex the index field for the setup packet
54  * \param data a suitably-sized data buffer for either input or output
55  * (depending on direction bits within bmRequestType)
56  * \param wLength the length field for the setup packet. The data buffer should
57  * be at least this size.
58  * \param timeout timeout (in millseconds) that this function should wait
59  * before giving up due to no response being received. For no timeout, use
60  * value 0.
61  * \returns 0 on success
62  * \returns -ETIMEDOUT if the transfer timed out
63  * \returns other negative code on error
64  */
65 API_EXPORTED int libusb_control_transfer(libusb_device_handle *dev_handle,
66         uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
67         unsigned char *data, uint16_t wLength, unsigned int timeout)
68 {
69         struct libusb_transfer *transfer = libusb_alloc_transfer(0);
70         unsigned char *buffer;
71         int completed = 0;
72         int r;
73
74         if (!transfer)
75                 return -ENOMEM;
76         
77         buffer = malloc(LIBUSB_CONTROL_SETUP_SIZE + wLength);
78         if (!buffer) {
79                 libusb_free_transfer(transfer);
80                 return -ENOMEM;
81         }
82
83         libusb_fill_control_setup(buffer, bmRequestType, bRequest, wValue, wIndex,
84                 wLength);
85         if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT)
86                 memcpy(buffer + LIBUSB_CONTROL_SETUP_SIZE, data, wLength);
87
88         libusb_fill_control_transfer(transfer, dev_handle, buffer,
89                 ctrl_transfer_cb, &completed, timeout);
90         r = libusb_submit_transfer(transfer);
91         if (r < 0) {
92                 libusb_free_transfer(transfer);
93                 return r;
94         }
95
96         while (!completed) {
97                 r = libusb_poll();
98                 if (r < 0) {
99                         libusb_cancel_transfer_sync(transfer);
100                         libusb_free_transfer(transfer);
101                         return r;
102                 }
103         }
104
105         if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN)
106                 memcpy(data, libusb_control_transfer_get_data(transfer),
107                         transfer->actual_length);
108
109         switch (transfer->status) {
110         case LIBUSB_TRANSFER_COMPLETED:
111                 r = transfer->actual_length;
112                 break;
113         case LIBUSB_TRANSFER_TIMED_OUT:
114                 r = -ETIMEDOUT;
115                 break;
116         default:
117                 usbi_warn("unrecognised status code %d", transfer->status);
118                 r = -1;
119         }
120
121         libusb_free_transfer(transfer);
122         return r;
123 }
124
125 static void bulk_transfer_cb(struct libusb_transfer *transfer)
126 {
127         int *completed = transfer->user_data;
128         *completed = 1;
129         usbi_dbg("actual_length=%d", transfer->actual_length);
130         /* caller interprets results and frees transfer */
131 }
132
133 static int do_sync_bulk_transfer(struct libusb_device_handle *dev_handle,
134         unsigned char endpoint, unsigned char *buffer, int length,
135         int *transferred, unsigned int timeout, unsigned char endpoint_type)
136 {
137         struct libusb_transfer *transfer = libusb_alloc_transfer(0);
138         int completed = 0;
139         int r;
140
141         if (!transfer)
142                 return -ENOMEM;
143
144         libusb_fill_bulk_transfer(transfer, dev_handle, endpoint, buffer, length,
145                 bulk_transfer_cb, &completed, timeout);
146         transfer->endpoint_type = endpoint_type;
147
148         r = libusb_submit_transfer(transfer);
149         if (r < 0) {
150                 libusb_free_transfer(transfer);
151                 return r;
152         }
153
154         while (!completed) {
155                 r = libusb_poll();
156                 if (r < 0) {
157                         libusb_cancel_transfer_sync(transfer);
158                         libusb_free_transfer(transfer);
159                         return r;
160                 }
161         }
162
163         *transferred = transfer->actual_length;
164         switch (transfer->status) {
165         case LIBUSB_TRANSFER_COMPLETED:
166                 r = 0;
167                 break;
168         case LIBUSB_TRANSFER_TIMED_OUT:
169                 r = -ETIMEDOUT;
170                 break;
171         default:
172                 usbi_warn("unrecognised status code %d", transfer->status);
173                 r = -1;
174         }
175
176         libusb_free_transfer(transfer);
177         return r;
178 }
179
180 /* FIXME: document timeout handling vs URB splitting */
181 /** \ingroup syncio
182  * Perform a USB bulk transfer. The direction of the transfer is inferred from
183  * the direction bits of the endpoint address.
184  *
185  * \param dev_handle a handle for the device to communicate with
186  * \param endpoint the address of a valid endpoint to communicate with
187  * \param data a suitably-sized data buffer for either input or output
188  * (depending on endpoint)
189  * \param length for bulk writes, the number of bytes from data to be sent. for
190  * bulk reads, the maximum number of bytes to receive into the data buffer.
191  * \param transferred output location for the number of bytes actually
192  * transferred.
193  * \param timeout timeout (in millseconds) that this function should wait
194  * before giving up due to no response being received. For no timeout, use
195  * value 0.
196  *
197  * \returns 0 on success (and populates <tt>transferred</tt>)
198  * \returns -ETIMEDOUT if the transfer timed out
199  * \returns other negative code on error
200  */
201 API_EXPORTED int libusb_bulk_transfer(struct libusb_device_handle *dev_handle,
202         unsigned char endpoint, unsigned char *data, int length, int *transferred,
203         unsigned int timeout)
204 {
205         return do_sync_bulk_transfer(dev_handle, endpoint, data, length,
206                 transferred, timeout, LIBUSB_ENDPOINT_TYPE_BULK);
207 }
208
209 /* FIXME: do we need an interval param here? usbfs doesn't expose it? */
210 /** \ingroup syncio
211  * Perform a USB interrupt transfer. The direction of the transfer is inferred
212  * from the direction bits of the endpoint address.
213  *
214  * \param dev_handle a handle for the device to communicate with
215  * \param endpoint the address of a valid endpoint to communicate with
216  * \param data a suitably-sized data buffer for either input or output
217  * (depending on endpoint)
218  * \param length for bulk writes, the number of bytes from data to be sent. for
219  * bulk reads, the maximum number of bytes to receive into the data buffer.
220  * \param transferred output location for the number of bytes actually
221  * transferred.
222  * \param timeout timeout (in millseconds) that this function should wait
223  * before giving up due to no response being received. For no timeout, use
224  * value 0.
225  *
226  * \returns 0 on success (and populates <tt>transferred</tt>)
227  * \returns -ETIMEDOUT if the transfer timed out
228  * \returns other negative code on error
229  */
230 API_EXPORTED int libusb_interrupt_transfer(
231         struct libusb_device_handle *dev_handle, unsigned char endpoint,
232         unsigned char *data, int length, int *transferred, unsigned int timeout)
233 {
234         return do_sync_bulk_transfer(dev_handle, endpoint, data, length,
235                 transferred, timeout, LIBUSB_ENDPOINT_TYPE_INTERRUPT);
236 }
237