/src/libusb/libusb/sync.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */ |
2 | | /* |
3 | | * Synchronous I/O functions for libusb |
4 | | * Copyright © 2007-2008 Daniel Drake <dsd@gentoo.org> |
5 | | * Copyright © 2019 Nathan Hjelm <hjelmn@cs.unm.edu> |
6 | | * Copyright © 2019 Google LLC. All rights reserved. |
7 | | * |
8 | | * This library is free software; you can redistribute it and/or |
9 | | * modify it under the terms of the GNU Lesser General Public |
10 | | * License as published by the Free Software Foundation; either |
11 | | * version 2.1 of the License, or (at your option) any later version. |
12 | | * |
13 | | * This library is distributed in the hope that it will be useful, |
14 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
16 | | * Lesser General Public License for more details. |
17 | | * |
18 | | * You should have received a copy of the GNU Lesser General Public |
19 | | * License along with this library; if not, write to the Free Software |
20 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
21 | | */ |
22 | | |
23 | | #include "libusbi.h" |
24 | | |
25 | | #include <string.h> |
26 | | |
27 | | /** |
28 | | * @defgroup libusb_syncio Synchronous device I/O |
29 | | * |
30 | | * This page documents libusb's synchronous (blocking) API for USB device I/O. |
31 | | * This interface is easy to use but has some limitations. More advanced users |
32 | | * may wish to consider using the \ref libusb_asyncio "asynchronous I/O API" instead. |
33 | | */ |
34 | | |
35 | | static void LIBUSB_CALL sync_transfer_cb(struct libusb_transfer *transfer) |
36 | 0 | { |
37 | 0 | usbi_dbg(TRANSFER_CTX(transfer), "actual_length=%d", transfer->actual_length); |
38 | |
|
39 | 0 | int *completed = transfer->user_data; |
40 | 0 | *completed = 1; |
41 | | /* |
42 | | * Right after setting 'completed', another thread might free the transfer, so don't |
43 | | * access it beyond this point. The instantiating thread (not necessarily the |
44 | | * current one) interprets the result and frees the transfer. |
45 | | */ |
46 | 0 | } |
47 | | |
48 | | static void sync_transfer_wait_for_completion(struct libusb_transfer *transfer) |
49 | 0 | { |
50 | 0 | int r, *completed = transfer->user_data; |
51 | 0 | struct libusb_context *ctx = HANDLE_CTX(transfer->dev_handle); |
52 | |
|
53 | 0 | while (!*completed) { |
54 | 0 | r = libusb_handle_events_completed(ctx, completed); |
55 | 0 | if (r < 0) { |
56 | 0 | if (r == LIBUSB_ERROR_INTERRUPTED) |
57 | 0 | continue; |
58 | 0 | usbi_err(ctx, "libusb_handle_events failed: %s, cancelling transfer and retrying", |
59 | 0 | libusb_error_name(r)); |
60 | 0 | libusb_cancel_transfer(transfer); |
61 | 0 | continue; |
62 | 0 | } |
63 | 0 | if (NULL == transfer->dev_handle) { |
64 | | /* transfer completion after libusb_close() */ |
65 | 0 | transfer->status = LIBUSB_TRANSFER_NO_DEVICE; |
66 | 0 | *completed = 1; |
67 | 0 | } |
68 | 0 | } |
69 | 0 | } |
70 | | |
71 | | /** \ingroup libusb_syncio |
72 | | * Perform a USB control transfer. |
73 | | * |
74 | | * The direction of the transfer is inferred from the bmRequestType field of |
75 | | * the setup packet. |
76 | | * |
77 | | * The wValue, wIndex and wLength fields values should be given in host-endian |
78 | | * byte order. |
79 | | * |
80 | | * \param dev_handle a handle for the device to communicate with |
81 | | * \param bmRequestType the request type field for the setup packet |
82 | | * \param bRequest the request field for the setup packet |
83 | | * \param wValue the value field for the setup packet |
84 | | * \param wIndex the index field for the setup packet |
85 | | * \param data a suitably-sized data buffer for either input or output |
86 | | * (depending on direction bits within bmRequestType) |
87 | | * \param wLength the length field for the setup packet. The data buffer should |
88 | | * be at least this size. |
89 | | * \param timeout timeout (in milliseconds) that this function should wait |
90 | | * before giving up due to no response being received. For an unlimited |
91 | | * timeout, use value 0. |
92 | | * \returns on success, the number of bytes actually transferred |
93 | | * \returns \ref LIBUSB_ERROR_TIMEOUT if the transfer timed out |
94 | | * \returns \ref LIBUSB_ERROR_PIPE if the control request was not supported by the |
95 | | * device |
96 | | * \returns \ref LIBUSB_ERROR_NO_DEVICE if the device has been disconnected |
97 | | * \returns \ref LIBUSB_ERROR_BUSY if called from event handling context |
98 | | * \returns \ref LIBUSB_ERROR_INVALID_PARAM if the transfer size is larger than |
99 | | * the operating system and/or hardware can support (see \ref asynclimits) |
100 | | * \returns another LIBUSB_ERROR code on other failures |
101 | | */ |
102 | | int API_EXPORTED libusb_control_transfer(libusb_device_handle *dev_handle, |
103 | | uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, |
104 | | unsigned char *data, uint16_t wLength, unsigned int timeout) |
105 | 0 | { |
106 | 0 | struct libusb_transfer *transfer; |
107 | 0 | unsigned char *buffer; |
108 | 0 | int completed = 0; |
109 | 0 | int r; |
110 | |
|
111 | 0 | if (usbi_handling_events(HANDLE_CTX(dev_handle))) |
112 | 0 | return LIBUSB_ERROR_BUSY; |
113 | | |
114 | 0 | transfer = libusb_alloc_transfer(0); |
115 | 0 | if (!transfer) |
116 | 0 | return LIBUSB_ERROR_NO_MEM; |
117 | | |
118 | 0 | buffer = malloc(LIBUSB_CONTROL_SETUP_SIZE + wLength); |
119 | 0 | if (!buffer) { |
120 | 0 | libusb_free_transfer(transfer); |
121 | 0 | return LIBUSB_ERROR_NO_MEM; |
122 | 0 | } |
123 | | |
124 | 0 | libusb_fill_control_setup(buffer, bmRequestType, bRequest, wValue, wIndex, |
125 | 0 | wLength); |
126 | 0 | if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT) |
127 | 0 | memcpy(buffer + LIBUSB_CONTROL_SETUP_SIZE, data, wLength); |
128 | |
|
129 | 0 | libusb_fill_control_transfer(transfer, dev_handle, buffer, |
130 | 0 | sync_transfer_cb, &completed, timeout); |
131 | 0 | transfer->flags = LIBUSB_TRANSFER_FREE_BUFFER; |
132 | 0 | r = libusb_submit_transfer(transfer); |
133 | 0 | if (r < 0) { |
134 | 0 | libusb_free_transfer(transfer); |
135 | 0 | return r; |
136 | 0 | } |
137 | | |
138 | 0 | sync_transfer_wait_for_completion(transfer); |
139 | |
|
140 | 0 | if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN) |
141 | 0 | memcpy(data, libusb_control_transfer_get_data(transfer), |
142 | 0 | transfer->actual_length); |
143 | |
|
144 | 0 | switch (transfer->status) { |
145 | 0 | case LIBUSB_TRANSFER_COMPLETED: |
146 | 0 | r = transfer->actual_length; |
147 | 0 | break; |
148 | 0 | case LIBUSB_TRANSFER_TIMED_OUT: |
149 | 0 | r = LIBUSB_ERROR_TIMEOUT; |
150 | 0 | break; |
151 | 0 | case LIBUSB_TRANSFER_STALL: |
152 | 0 | r = LIBUSB_ERROR_PIPE; |
153 | 0 | break; |
154 | 0 | case LIBUSB_TRANSFER_NO_DEVICE: |
155 | 0 | r = LIBUSB_ERROR_NO_DEVICE; |
156 | 0 | break; |
157 | 0 | case LIBUSB_TRANSFER_OVERFLOW: |
158 | 0 | r = LIBUSB_ERROR_OVERFLOW; |
159 | 0 | break; |
160 | 0 | case LIBUSB_TRANSFER_ERROR: |
161 | 0 | case LIBUSB_TRANSFER_CANCELLED: |
162 | 0 | r = LIBUSB_ERROR_IO; |
163 | 0 | break; |
164 | 0 | default: |
165 | 0 | usbi_warn(HANDLE_CTX(dev_handle), |
166 | 0 | "unrecognised status code %d", transfer->status); |
167 | 0 | r = LIBUSB_ERROR_OTHER; |
168 | 0 | } |
169 | | |
170 | 0 | libusb_free_transfer(transfer); |
171 | 0 | return r; |
172 | 0 | } |
173 | | |
174 | | static int do_sync_bulk_transfer(struct libusb_device_handle *dev_handle, |
175 | | unsigned char endpoint, unsigned char *buffer, int length, |
176 | | int *transferred, unsigned int timeout, unsigned char type) |
177 | 0 | { |
178 | 0 | struct libusb_transfer *transfer; |
179 | 0 | int completed = 0; |
180 | 0 | int r; |
181 | |
|
182 | 0 | if (usbi_handling_events(HANDLE_CTX(dev_handle))) |
183 | 0 | return LIBUSB_ERROR_BUSY; |
184 | | |
185 | 0 | transfer = libusb_alloc_transfer(0); |
186 | 0 | if (!transfer) |
187 | 0 | return LIBUSB_ERROR_NO_MEM; |
188 | | |
189 | 0 | libusb_fill_bulk_transfer(transfer, dev_handle, endpoint, buffer, length, |
190 | 0 | sync_transfer_cb, &completed, timeout); |
191 | 0 | transfer->type = type; |
192 | |
|
193 | 0 | r = libusb_submit_transfer(transfer); |
194 | 0 | if (r < 0) { |
195 | 0 | libusb_free_transfer(transfer); |
196 | 0 | return r; |
197 | 0 | } |
198 | | |
199 | 0 | sync_transfer_wait_for_completion(transfer); |
200 | |
|
201 | 0 | if (transferred) |
202 | 0 | *transferred = transfer->actual_length; |
203 | |
|
204 | 0 | switch (transfer->status) { |
205 | 0 | case LIBUSB_TRANSFER_COMPLETED: |
206 | 0 | r = 0; |
207 | 0 | break; |
208 | 0 | case LIBUSB_TRANSFER_TIMED_OUT: |
209 | 0 | r = LIBUSB_ERROR_TIMEOUT; |
210 | 0 | break; |
211 | 0 | case LIBUSB_TRANSFER_STALL: |
212 | 0 | r = LIBUSB_ERROR_PIPE; |
213 | 0 | break; |
214 | 0 | case LIBUSB_TRANSFER_OVERFLOW: |
215 | 0 | r = LIBUSB_ERROR_OVERFLOW; |
216 | 0 | break; |
217 | 0 | case LIBUSB_TRANSFER_NO_DEVICE: |
218 | 0 | r = LIBUSB_ERROR_NO_DEVICE; |
219 | 0 | break; |
220 | 0 | case LIBUSB_TRANSFER_ERROR: |
221 | 0 | case LIBUSB_TRANSFER_CANCELLED: |
222 | 0 | r = LIBUSB_ERROR_IO; |
223 | 0 | break; |
224 | 0 | default: |
225 | 0 | usbi_warn(HANDLE_CTX(dev_handle), |
226 | 0 | "unrecognised status code %d", transfer->status); |
227 | 0 | r = LIBUSB_ERROR_OTHER; |
228 | 0 | } |
229 | | |
230 | 0 | libusb_free_transfer(transfer); |
231 | 0 | return r; |
232 | 0 | } |
233 | | |
234 | | /** \ingroup libusb_syncio |
235 | | * Perform a USB bulk transfer. The direction of the transfer is inferred from |
236 | | * the direction bits of the endpoint address. |
237 | | * |
238 | | * For bulk reads, the <tt>length</tt> field indicates the maximum length of |
239 | | * data you are expecting to receive. If less data arrives than expected, |
240 | | * this function will return that data, so be sure to check the |
241 | | * <tt>transferred</tt> output parameter. |
242 | | * |
243 | | * You should also check the <tt>transferred</tt> parameter for bulk writes. |
244 | | * Not all of the data may have been written. |
245 | | * |
246 | | * Also check <tt>transferred</tt> when dealing with a timeout error code. |
247 | | * libusb may have to split your transfer into a number of chunks to satisfy |
248 | | * underlying O/S requirements, meaning that the timeout may expire after |
249 | | * the first few chunks have completed. libusb is careful not to lose any data |
250 | | * that may have been transferred; do not assume that timeout conditions |
251 | | * indicate a complete lack of I/O. See \ref asynctimeout for more details. |
252 | | * |
253 | | * \param dev_handle a handle for the device to communicate with |
254 | | * \param endpoint the address of a valid endpoint to communicate with |
255 | | * \param data a suitably-sized data buffer for either input or output |
256 | | * (depending on endpoint) |
257 | | * \param length for bulk writes, the number of bytes from data to be sent. for |
258 | | * bulk reads, the maximum number of bytes to receive into the data buffer. |
259 | | * \param transferred output location for the number of bytes actually |
260 | | * transferred. Since version 1.0.21 (\ref LIBUSB_API_VERSION >= 0x01000105), |
261 | | * it is legal to pass a NULL pointer if you do not wish to receive this |
262 | | * information. |
263 | | * \param timeout timeout (in milliseconds) that this function should wait |
264 | | * before giving up due to no response being received. For an unlimited |
265 | | * timeout, use value 0. |
266 | | * |
267 | | * \returns 0 on success (and populates <tt>transferred</tt>) |
268 | | * \returns \ref LIBUSB_ERROR_TIMEOUT if the transfer timed out (and populates |
269 | | * <tt>transferred</tt>) |
270 | | * \returns \ref LIBUSB_ERROR_PIPE if the endpoint halted |
271 | | * \returns \ref LIBUSB_ERROR_OVERFLOW if the device offered more data, see |
272 | | * \ref libusb_packetoverflow |
273 | | * \returns \ref LIBUSB_ERROR_NO_DEVICE if the device has been disconnected |
274 | | * \returns \ref LIBUSB_ERROR_BUSY if called from event handling context |
275 | | * \returns \ref LIBUSB_ERROR_INVALID_PARAM if the transfer size is larger than |
276 | | * the operating system and/or hardware can support (see \ref asynclimits) |
277 | | * \returns another LIBUSB_ERROR code on other failures |
278 | | */ |
279 | | int API_EXPORTED libusb_bulk_transfer(libusb_device_handle *dev_handle, |
280 | | unsigned char endpoint, unsigned char *data, int length, |
281 | | int *transferred, unsigned int timeout) |
282 | 0 | { |
283 | 0 | return do_sync_bulk_transfer(dev_handle, endpoint, data, length, |
284 | 0 | transferred, timeout, LIBUSB_TRANSFER_TYPE_BULK); |
285 | 0 | } |
286 | | |
287 | | /** \ingroup libusb_syncio |
288 | | * Perform a USB interrupt transfer. The direction of the transfer is inferred |
289 | | * from the direction bits of the endpoint address. |
290 | | * |
291 | | * For interrupt reads, the <tt>length</tt> field indicates the maximum length |
292 | | * of data you are expecting to receive. If less data arrives than expected, |
293 | | * this function will return that data, so be sure to check the |
294 | | * <tt>transferred</tt> output parameter. |
295 | | * |
296 | | * You should also check the <tt>transferred</tt> parameter for interrupt |
297 | | * writes. Not all of the data may have been written. |
298 | | * |
299 | | * Also check <tt>transferred</tt> when dealing with a timeout error code. |
300 | | * libusb may have to split your transfer into a number of chunks to satisfy |
301 | | * underlying O/S requirements, meaning that the timeout may expire after |
302 | | * the first few chunks have completed. libusb is careful not to lose any data |
303 | | * that may have been transferred; do not assume that timeout conditions |
304 | | * indicate a complete lack of I/O. See \ref asynctimeout for more details. |
305 | | * |
306 | | * The default endpoint bInterval value is used as the polling interval. |
307 | | * |
308 | | * \param dev_handle a handle for the device to communicate with |
309 | | * \param endpoint the address of a valid endpoint to communicate with |
310 | | * \param data a suitably-sized data buffer for either input or output |
311 | | * (depending on endpoint) |
312 | | * \param length for bulk writes, the number of bytes from data to be sent. for |
313 | | * bulk reads, the maximum number of bytes to receive into the data buffer. |
314 | | * \param transferred output location for the number of bytes actually |
315 | | * transferred. Since version 1.0.21 (\ref LIBUSB_API_VERSION >= 0x01000105), |
316 | | * it is legal to pass a NULL pointer if you do not wish to receive this |
317 | | * information. |
318 | | * \param timeout timeout (in milliseconds) that this function should wait |
319 | | * before giving up due to no response being received. For an unlimited |
320 | | * timeout, use value 0. |
321 | | * |
322 | | * \returns 0 on success (and populates <tt>transferred</tt>) |
323 | | * \returns \ref LIBUSB_ERROR_TIMEOUT if the transfer timed out |
324 | | * \returns \ref LIBUSB_ERROR_PIPE if the endpoint halted |
325 | | * \returns \ref LIBUSB_ERROR_OVERFLOW if the device offered more data, see |
326 | | * \ref libusb_packetoverflow |
327 | | * \returns \ref LIBUSB_ERROR_NO_DEVICE if the device has been disconnected |
328 | | * \returns \ref LIBUSB_ERROR_BUSY if called from event handling context |
329 | | * \returns \ref LIBUSB_ERROR_INVALID_PARAM if the transfer size is larger than |
330 | | * the operating system and/or hardware can support (see \ref asynclimits) |
331 | | * \returns another LIBUSB_ERROR code on other error |
332 | | */ |
333 | | int API_EXPORTED libusb_interrupt_transfer(libusb_device_handle *dev_handle, |
334 | | unsigned char endpoint, unsigned char *data, int length, |
335 | | int *transferred, unsigned int timeout) |
336 | 0 | { |
337 | 0 | return do_sync_bulk_transfer(dev_handle, endpoint, data, length, |
338 | 0 | transferred, timeout, LIBUSB_TRANSFER_TYPE_INTERRUPT); |
339 | 0 | } |