blob: 7de0cdfd3c2a641d6dc547d70b0b1c710f2ea596 [file] [log] [blame]
Paul Cercueile06f4ce2015-04-20 12:59:31 +02001/*
2 * libiio - Library for interfacing industrial I/O (IIO) devices
3 *
4 * Copyright (C) 2015 Analog Devices, Inc.
5 * Author: Paul Cercueil <paul.cercueil@analog.com>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * */
18
Paul Cercueile06f4ce2015-04-20 12:59:31 +020019#include "iio-lock.h"
20#include "iio-private.h"
21#include "iiod-client.h"
22
Paul Cercueil370bb362016-04-20 11:50:10 +020023#include <ctype.h>
Paul Cercueile06f4ce2015-04-20 12:59:31 +020024#include <errno.h>
25#include <libusb-1.0/libusb.h>
26#include <stdbool.h>
27#include <string.h>
28
Paul Cercueil3c1e7852015-12-04 16:14:28 +010029#ifdef ERROR
30#undef ERROR
31#endif
32
33#include "debug.h"
34
Paul Cercueile06f4ce2015-04-20 12:59:31 +020035#define DEFAULT_TIMEOUT_MS 5000
36
37/* Endpoint for non-streaming operations */
38#define EP_OPS 1
39
Lars-Peter Clausen794ba032016-04-25 15:07:00 +020040#define IIO_INTERFACE_NAME "IIO"
41
Lars-Peter Clausenf0d8ff42016-07-04 10:41:53 +020042struct iio_usb_io_context {
43 unsigned int ep;
Lars-Peter Clausene5c04e02016-06-22 16:52:36 +020044
45 struct iio_mutex *lock;
46 bool cancelled;
47 struct libusb_transfer *transfer;
Lars-Peter Clausenf0d8ff42016-07-04 10:41:53 +020048};
49
Paul Cercueil4213a432016-02-09 14:00:40 +010050struct iio_usb_io_endpoint {
51 unsigned char address;
52 bool in_use;
Paul Cercueil4acd6042015-11-30 12:10:43 +010053
Paul Cercueil4213a432016-02-09 14:00:40 +010054 struct iio_mutex *lock;
55};
Paul Cercueil4acd6042015-11-30 12:10:43 +010056
Paul Cercueile06f4ce2015-04-20 12:59:31 +020057struct iio_context_pdata {
58 libusb_context *ctx;
59 libusb_device_handle *hdl;
60
61 struct iiod_client *iiod_client;
62
63 /* Lock for non-streaming operations */
64 struct iio_mutex *lock;
Paul Cercueil4acd6042015-11-30 12:10:43 +010065
Paul Cercueil4213a432016-02-09 14:00:40 +010066 /* Lock for endpoint reservation */
67 struct iio_mutex *ep_lock;
68
69 struct iio_usb_io_endpoint *io_endpoints;
70 unsigned int nb_io_endpoints;
Paul Cercueil7a988892015-12-03 12:39:20 +010071
72 unsigned int timeout_ms;
Lars-Peter Clausenf0d8ff42016-07-04 10:41:53 +020073
74 struct iio_usb_io_context io_ctx;
Paul Cercueil4acd6042015-11-30 12:10:43 +010075};
76
77struct iio_device_pdata {
Paul Cercueil4acd6042015-11-30 12:10:43 +010078 struct iio_mutex *lock;
79
80 bool opened;
Lars-Peter Clausenf0d8ff42016-07-04 10:41:53 +020081 struct iio_usb_io_context io_ctx;
Paul Cercueile06f4ce2015-04-20 12:59:31 +020082};
83
84static const unsigned int libusb_to_errno_codes[] = {
85 [- LIBUSB_ERROR_INVALID_PARAM] = EINVAL,
86 [- LIBUSB_ERROR_ACCESS] = EACCES,
87 [- LIBUSB_ERROR_NO_DEVICE] = ENODEV,
88 [- LIBUSB_ERROR_NOT_FOUND] = ENXIO,
89 [- LIBUSB_ERROR_BUSY] = EBUSY,
90 [- LIBUSB_ERROR_TIMEOUT] = ETIMEDOUT,
91 [- LIBUSB_ERROR_OVERFLOW] = EIO,
92 [- LIBUSB_ERROR_PIPE] = EPIPE,
93 [- LIBUSB_ERROR_INTERRUPTED] = EINTR,
94 [- LIBUSB_ERROR_NO_MEM] = ENOMEM,
95 [- LIBUSB_ERROR_NOT_SUPPORTED] = ENOSYS,
96};
97
98static unsigned int libusb_to_errno(int error)
99{
100 switch ((enum libusb_error) error) {
101 case LIBUSB_ERROR_INVALID_PARAM:
102 case LIBUSB_ERROR_ACCESS:
103 case LIBUSB_ERROR_NO_DEVICE:
104 case LIBUSB_ERROR_NOT_FOUND:
105 case LIBUSB_ERROR_BUSY:
106 case LIBUSB_ERROR_TIMEOUT:
107 case LIBUSB_ERROR_PIPE:
108 case LIBUSB_ERROR_INTERRUPTED:
109 case LIBUSB_ERROR_NO_MEM:
110 case LIBUSB_ERROR_NOT_SUPPORTED:
111 return libusb_to_errno_codes[- (int) error];
112 case LIBUSB_ERROR_IO:
113 case LIBUSB_ERROR_OTHER:
114 case LIBUSB_ERROR_OVERFLOW:
115 default:
116 return EIO;
117 }
118}
119
Lars-Peter Clausene5c04e02016-06-22 16:52:36 +0200120static int usb_io_context_init(struct iio_usb_io_context *io_ctx)
121{
122 io_ctx->lock = iio_mutex_create();
123 if (!io_ctx->lock)
124 return -ENOMEM;
125
126 return 0;
127}
128
129static void usb_io_context_exit(struct iio_usb_io_context *io_ctx)
130{
131 if (io_ctx->lock) {
132 iio_mutex_destroy(io_ctx->lock);
133 io_ctx->lock = NULL;
134 }
135}
136
Paul Cercueilc11737c2015-11-26 14:44:46 +0100137static int usb_get_version(const struct iio_context *ctx,
138 unsigned int *major, unsigned int *minor, char git_tag[8])
139{
140 return iiod_client_get_version(ctx->pdata->iiod_client,
Lars-Peter Clausen2767d4d2016-06-23 14:19:02 +0200141 &ctx->pdata->io_ctx, major, minor, git_tag);
Paul Cercueilc11737c2015-11-26 14:44:46 +0100142}
143
Paul Cercueila5e4aa42016-02-09 13:31:01 +0100144static unsigned int usb_calculate_remote_timeout(unsigned int timeout)
145{
146 /* XXX(pcercuei): We currently hardcode timeout / 2 for the backend used
147 * by the remote. Is there something better to do here? */
148 return timeout / 2;
149}
150
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100151#define USB_PIPE_CTRL_TIMEOUT 200 /* These should not take long */
152
153#define IIO_USD_CMD_RESET_PIPES 0
154#define IIO_USD_CMD_OPEN_PIPE 1
155#define IIO_USD_CMD_CLOSE_PIPE 2
156
157static int usb_reset_pipes(libusb_device_handle *hdl)
158{
159 int ret;
160
161 ret = libusb_control_transfer(hdl, LIBUSB_REQUEST_TYPE_VENDOR |
162 LIBUSB_RECIPIENT_INTERFACE, IIO_USD_CMD_RESET_PIPES,
163 0, 0, NULL, 0, USB_PIPE_CTRL_TIMEOUT);
164 if (ret < 0)
Paul Cercueil67482202016-04-21 16:40:02 +0200165 return -(int) libusb_to_errno(ret);
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100166 return 0;
167}
168
169static int usb_open_pipe(libusb_device_handle *hdl, unsigned int ep)
170{
171 int ret;
172
173 ret = libusb_control_transfer(hdl, LIBUSB_REQUEST_TYPE_VENDOR |
174 LIBUSB_RECIPIENT_INTERFACE, IIO_USD_CMD_OPEN_PIPE,
175 ep - 1, 0, NULL, 0, USB_PIPE_CTRL_TIMEOUT);
176 if (ret < 0)
Paul Cercueil67482202016-04-21 16:40:02 +0200177 return -(int) libusb_to_errno(ret);
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100178 return 0;
179}
180
181static int usb_close_pipe(libusb_device_handle *hdl, unsigned int ep)
182{
183 int ret;
184
185 ret = libusb_control_transfer(hdl, LIBUSB_REQUEST_TYPE_VENDOR |
186 LIBUSB_RECIPIENT_INTERFACE, IIO_USD_CMD_CLOSE_PIPE,
187 ep - 1, 0, NULL, 0, USB_PIPE_CTRL_TIMEOUT);
188 if (ret < 0)
Paul Cercueil67482202016-04-21 16:40:02 +0200189 return -(int) libusb_to_errno(ret);
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100190 return 0;
191}
192
Paul Cercueil4213a432016-02-09 14:00:40 +0100193static int usb_reserve_ep_unlocked(const struct iio_device *dev)
194{
195 struct iio_context_pdata *pdata = dev->ctx->pdata;
196 unsigned int i;
197
198 for (i = 0; i < pdata->nb_io_endpoints; i++) {
199 struct iio_usb_io_endpoint *ep = &pdata->io_endpoints[i];
200
201 if (!ep->in_use) {
202 ep->in_use = true;
203
Lars-Peter Clausenf0d8ff42016-07-04 10:41:53 +0200204 dev->pdata->io_ctx.ep = ep->address;
Paul Cercueil4213a432016-02-09 14:00:40 +0100205 dev->pdata->lock = ep->lock;
206 return 0;
207 }
208 }
209
210 return -EBUSY;
211}
212
213static void usb_free_ep_unlocked(const struct iio_device *dev)
214{
215 struct iio_context_pdata *pdata = dev->ctx->pdata;
216 unsigned int i;
217
218 for (i = 0; i < pdata->nb_io_endpoints; i++) {
219 struct iio_usb_io_endpoint *ep = &pdata->io_endpoints[i];
220
221 if (ep->lock == dev->pdata->lock) {
222 ep->in_use = false;
223 return;
224 }
225 }
226}
227
Paul Cercueil4acd6042015-11-30 12:10:43 +0100228static int usb_open(const struct iio_device *dev,
229 size_t samples_count, bool cyclic)
230{
Paul Cercueila5e4aa42016-02-09 13:31:01 +0100231 struct iio_context_pdata *ctx_pdata = dev->ctx->pdata;
Paul Cercueil4acd6042015-11-30 12:10:43 +0100232 struct iio_device_pdata *pdata = dev->pdata;
233 int ret = -EBUSY;
234
Paul Cercueil4213a432016-02-09 14:00:40 +0100235 iio_mutex_lock(ctx_pdata->ep_lock);
Paul Cercueil4acd6042015-11-30 12:10:43 +0100236
Lars-Peter Clausene5c04e02016-06-22 16:52:36 +0200237 pdata->io_ctx.cancelled = false;
238
Paul Cercueila5e4aa42016-02-09 13:31:01 +0100239 if (pdata->opened)
240 goto out_unlock;
241
Paul Cercueil4213a432016-02-09 14:00:40 +0100242 ret = usb_reserve_ep_unlocked(dev);
243 if (ret)
244 goto out_unlock;
245
Lars-Peter Clausenf0d8ff42016-07-04 10:41:53 +0200246 ret = usb_open_pipe(ctx_pdata->hdl, pdata->io_ctx.ep);
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100247 if (ret) {
248 char err_str[1024];
249
250 iio_strerror(-ret, err_str, sizeof(err_str));
251 ERROR("Failed to open pipe: %s\n", err_str);
252 usb_free_ep_unlocked(dev);
253 goto out_unlock;
254 }
255
Paul Cercueil4213a432016-02-09 14:00:40 +0100256 iio_mutex_lock(pdata->lock);
257
Lars-Peter Clausen2767d4d2016-06-23 14:19:02 +0200258 ret = iiod_client_open_unlocked(ctx_pdata->iiod_client, &pdata->io_ctx,
259 dev, samples_count, cyclic);
Paul Cercueila5e4aa42016-02-09 13:31:01 +0100260
261 if (!ret) {
262 unsigned int remote_timeout =
263 usb_calculate_remote_timeout(ctx_pdata->timeout_ms);
264
265 ret = iiod_client_set_timeout(ctx_pdata->iiod_client,
Lars-Peter Clausen2767d4d2016-06-23 14:19:02 +0200266 &pdata->io_ctx, remote_timeout);
Paul Cercueil4acd6042015-11-30 12:10:43 +0100267 }
268
Paul Cercueila5e4aa42016-02-09 13:31:01 +0100269 pdata->opened = !ret;
270
Paul Cercueil4acd6042015-11-30 12:10:43 +0100271 iio_mutex_unlock(pdata->lock);
Paul Cercueil4213a432016-02-09 14:00:40 +0100272
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100273 if (ret) {
Lars-Peter Clausenf0d8ff42016-07-04 10:41:53 +0200274 usb_close_pipe(ctx_pdata->hdl, pdata->io_ctx.ep);
Paul Cercueil4213a432016-02-09 14:00:40 +0100275 usb_free_ep_unlocked(dev);
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100276 }
Paul Cercueil4213a432016-02-09 14:00:40 +0100277
278out_unlock:
279 iio_mutex_unlock(ctx_pdata->ep_lock);
Paul Cercueil4acd6042015-11-30 12:10:43 +0100280 return ret;
281}
282
283static int usb_close(const struct iio_device *dev)
284{
Paul Cercueil4213a432016-02-09 14:00:40 +0100285 struct iio_context_pdata *ctx_pdata = dev->ctx->pdata;
Paul Cercueil4acd6042015-11-30 12:10:43 +0100286 struct iio_device_pdata *pdata = dev->pdata;
287 int ret = -EBADF;
288
Paul Cercueil4213a432016-02-09 14:00:40 +0100289 iio_mutex_lock(ctx_pdata->ep_lock);
290 if (!pdata->opened)
291 goto out_unlock;
Paul Cercueil4acd6042015-11-30 12:10:43 +0100292
Paul Cercueil4213a432016-02-09 14:00:40 +0100293 iio_mutex_lock(pdata->lock);
Lars-Peter Clausen2767d4d2016-06-23 14:19:02 +0200294 ret = iiod_client_close_unlocked(ctx_pdata->iiod_client, &pdata->io_ctx,
295 dev);
Paul Cercueil4213a432016-02-09 14:00:40 +0100296 pdata->opened = false;
297
Paul Cercueil31492b32016-02-22 17:40:20 +0100298 iio_mutex_unlock(pdata->lock);
299
Lars-Peter Clausenf0d8ff42016-07-04 10:41:53 +0200300 usb_close_pipe(ctx_pdata->hdl, pdata->io_ctx.ep);
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100301
Paul Cercueil4213a432016-02-09 14:00:40 +0100302 usb_free_ep_unlocked(dev);
303
304out_unlock:
305 iio_mutex_unlock(ctx_pdata->ep_lock);
Paul Cercueil4acd6042015-11-30 12:10:43 +0100306 return ret;
307}
308
Paul Cercueil04841832015-12-02 11:58:33 +0100309static ssize_t usb_read(const struct iio_device *dev, void *dst, size_t len,
310 uint32_t *mask, size_t words)
311{
312 struct iio_device_pdata *pdata = dev->pdata;
313 ssize_t ret;
314
315 iio_mutex_lock(pdata->lock);
316 ret = iiod_client_read_unlocked(dev->ctx->pdata->iiod_client,
Lars-Peter Clausen2767d4d2016-06-23 14:19:02 +0200317 &pdata->io_ctx, dev, dst, len, mask, words);
Paul Cercueil04841832015-12-02 11:58:33 +0100318 iio_mutex_unlock(pdata->lock);
319
320 return ret;
321}
322
Paul Cercueile78e9882015-12-04 16:31:10 +0100323static ssize_t usb_write(const struct iio_device *dev,
324 const void *src, size_t len)
325{
326 struct iio_device_pdata *pdata = dev->pdata;
327 ssize_t ret;
328
329 iio_mutex_lock(pdata->lock);
330 ret = iiod_client_write_unlocked(dev->ctx->pdata->iiod_client,
Lars-Peter Clausen2767d4d2016-06-23 14:19:02 +0200331 &pdata->io_ctx, dev, src, len);
Paul Cercueile78e9882015-12-04 16:31:10 +0100332 iio_mutex_unlock(pdata->lock);
333
334 return ret;
335}
336
Paul Cercueil3069e3b2015-11-26 16:01:25 +0100337static ssize_t usb_read_dev_attr(const struct iio_device *dev,
338 const char *attr, char *dst, size_t len, bool is_debug)
339{
340 struct iio_context_pdata *pdata = dev->ctx->pdata;
341
Lars-Peter Clausenf0d8ff42016-07-04 10:41:53 +0200342 return iiod_client_read_attr(pdata->iiod_client,
Lars-Peter Clausen2767d4d2016-06-23 14:19:02 +0200343 &pdata->io_ctx, dev, NULL, attr,
Lars-Peter Clausenf0d8ff42016-07-04 10:41:53 +0200344 dst, len, is_debug);
Paul Cercueil3069e3b2015-11-26 16:01:25 +0100345}
346
347static ssize_t usb_write_dev_attr(const struct iio_device *dev,
348 const char *attr, const char *src, size_t len, bool is_debug)
349{
350 struct iio_context_pdata *pdata = dev->ctx->pdata;
351
Lars-Peter Clausenf0d8ff42016-07-04 10:41:53 +0200352 return iiod_client_write_attr(pdata->iiod_client,
Lars-Peter Clausen2767d4d2016-06-23 14:19:02 +0200353 &pdata->io_ctx, dev, NULL, attr,
Lars-Peter Clausenf0d8ff42016-07-04 10:41:53 +0200354 src, len, is_debug);
Paul Cercueil3069e3b2015-11-26 16:01:25 +0100355}
356
357static ssize_t usb_read_chn_attr(const struct iio_channel *chn,
358 const char *attr, char *dst, size_t len)
359{
360 struct iio_context_pdata *pdata = chn->dev->ctx->pdata;
361
Lars-Peter Clausenf0d8ff42016-07-04 10:41:53 +0200362 return iiod_client_read_attr(pdata->iiod_client,
Lars-Peter Clausen2767d4d2016-06-23 14:19:02 +0200363 &pdata->io_ctx, chn->dev, chn, attr,
Lars-Peter Clausenf0d8ff42016-07-04 10:41:53 +0200364 dst, len, false);
Paul Cercueil3069e3b2015-11-26 16:01:25 +0100365}
366
367static ssize_t usb_write_chn_attr(const struct iio_channel *chn,
368 const char *attr, const char *src, size_t len)
369{
370 struct iio_context_pdata *pdata = chn->dev->ctx->pdata;
371
Lars-Peter Clausenf0d8ff42016-07-04 10:41:53 +0200372 return iiod_client_write_attr(pdata->iiod_client,
Lars-Peter Clausen2767d4d2016-06-23 14:19:02 +0200373 &pdata->io_ctx, chn->dev, chn, attr,
Lars-Peter Clausenf0d8ff42016-07-04 10:41:53 +0200374 src, len, false);
Paul Cercueil3069e3b2015-11-26 16:01:25 +0100375}
376
Paul Cercueil6c8337e2015-11-27 11:13:09 +0100377static int usb_set_kernel_buffers_count(const struct iio_device *dev,
378 unsigned int nb_blocks)
379{
380 struct iio_context_pdata *pdata = dev->ctx->pdata;
381
382 return iiod_client_set_kernel_buffers_count(pdata->iiod_client,
Lars-Peter Clausen2767d4d2016-06-23 14:19:02 +0200383 &pdata->io_ctx, dev, nb_blocks);
Paul Cercueil6c8337e2015-11-27 11:13:09 +0100384}
385
Paul Cercueil7a988892015-12-03 12:39:20 +0100386static int usb_set_timeout(struct iio_context *ctx, unsigned int timeout)
387{
388 struct iio_context_pdata *pdata = ctx->pdata;
389 unsigned int remote_timeout = usb_calculate_remote_timeout(timeout);
390 int ret;
391
392 ret = iiod_client_set_timeout(pdata->iiod_client,
Lars-Peter Clausen2767d4d2016-06-23 14:19:02 +0200393 &pdata->io_ctx, remote_timeout);
Paul Cercueila5e4aa42016-02-09 13:31:01 +0100394 if (!ret)
395 pdata->timeout_ms = timeout;
Paul Cercueil7a988892015-12-03 12:39:20 +0100396
Paul Cercueil7a988892015-12-03 12:39:20 +0100397 return ret;
398}
399
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200400static void usb_shutdown(struct iio_context *ctx)
401{
Paul Cercueil4213a432016-02-09 14:00:40 +0100402 unsigned int i;
403
Lars-Peter Clausene5c04e02016-06-22 16:52:36 +0200404 usb_io_context_exit(&ctx->pdata->io_ctx);
Paul Cercueile916d892016-08-01 16:00:49 +0200405
406 for (i = 0; i < ctx->nb_devices; i++)
407 usb_close(ctx->devices[i]);
408
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200409 iio_mutex_destroy(ctx->pdata->lock);
Paul Cercueil4213a432016-02-09 14:00:40 +0100410 iio_mutex_destroy(ctx->pdata->ep_lock);
411
412 for (i = 0; i < ctx->pdata->nb_io_endpoints; i++)
413 if (ctx->pdata->io_endpoints[i].lock)
414 iio_mutex_destroy(ctx->pdata->io_endpoints[i].lock);
415 if (ctx->pdata->io_endpoints)
416 free(ctx->pdata->io_endpoints);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200417
Lars-Peter Clausen33c64312016-02-19 13:32:08 +0100418 for (i = 0; i < ctx->nb_devices; i++) {
419 struct iio_device *dev = ctx->devices[i];
420
Lars-Peter Clausene5c04e02016-06-22 16:52:36 +0200421 usb_io_context_exit(&dev->pdata->io_ctx);
Lars-Peter Clausen33c64312016-02-19 13:32:08 +0100422 free(dev->pdata);
423 }
424
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200425 iiod_client_destroy(ctx->pdata->iiod_client);
426
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100427 usb_reset_pipes(ctx->pdata->hdl); /* Close everything */
428
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200429 libusb_close(ctx->pdata->hdl);
430 libusb_exit(ctx->pdata->ctx);
Lars-Peter Clausen33c64312016-02-19 13:32:08 +0100431 free(ctx->pdata);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200432}
433
Lars-Peter Clausen794ba032016-04-25 15:07:00 +0200434static int iio_usb_match_interface(const struct libusb_config_descriptor *desc,
435 struct libusb_device_handle *hdl, unsigned int interface)
436{
437 const struct libusb_interface *iface;
438 unsigned int i;
439
440 if (interface >= desc->bNumInterfaces)
441 return -EINVAL;
442
443 iface = &desc->interface[interface];
444
445 for (i = 0; i < (unsigned int) iface->num_altsetting; i++) {
446 const struct libusb_interface_descriptor *idesc =
447 &iface->altsetting[i];
448 char name[64];
449 int ret;
450
451 if (idesc->iInterface == 0)
452 continue;
453
454 ret = libusb_get_string_descriptor_ascii(hdl, idesc->iInterface,
455 (unsigned char *) name, sizeof(name));
456 if (ret < 0)
457 return ret;
458
459 if (!strcmp(name, IIO_INTERFACE_NAME))
460 return (int) i;
461 }
462
463 return -EPERM;
464}
465
466static int iio_usb_match_device(struct libusb_device *dev,
467 struct libusb_device_handle *hdl,
468 unsigned int *interface)
469{
470 struct libusb_config_descriptor *desc;
471 unsigned int i;
472 int ret;
473
474 ret = libusb_get_active_config_descriptor(dev, &desc);
475 if (ret)
476 return -(int) libusb_to_errno(ret);
477
478 for (i = 0, ret = -EPERM; ret == -EPERM &&
479 i < desc->bNumInterfaces; i++)
480 ret = iio_usb_match_interface(desc, hdl, i);
481
482 libusb_free_config_descriptor(desc);
483 if (ret < 0)
484 return ret;
485
486 DEBUG("Found IIO interface on device %u:%u using interface %u\n",
487 libusb_get_bus_number(dev),
488 libusb_get_device_address(dev), i - 1);
489
490 *interface = i - 1;
491 return ret;
492}
493
Lars-Peter Clausene5c04e02016-06-22 16:52:36 +0200494static void usb_cancel(const struct iio_device *dev)
495{
496 struct iio_device_pdata *ppdata = dev->pdata;
497
498 iio_mutex_lock(ppdata->io_ctx.lock);
499 if (ppdata->io_ctx.transfer && !ppdata->io_ctx.cancelled)
500 libusb_cancel_transfer(ppdata->io_ctx.transfer);
501 ppdata->io_ctx.cancelled = true;
502 iio_mutex_unlock(ppdata->io_ctx.lock);
503}
504
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200505static const struct iio_backend_ops usb_ops = {
Paul Cercueilc11737c2015-11-26 14:44:46 +0100506 .get_version = usb_get_version,
Paul Cercueil4acd6042015-11-30 12:10:43 +0100507 .open = usb_open,
508 .close = usb_close,
Paul Cercueil04841832015-12-02 11:58:33 +0100509 .read = usb_read,
Paul Cercueile78e9882015-12-04 16:31:10 +0100510 .write = usb_write,
Paul Cercueil3069e3b2015-11-26 16:01:25 +0100511 .read_device_attr = usb_read_dev_attr,
512 .read_channel_attr = usb_read_chn_attr,
513 .write_device_attr = usb_write_dev_attr,
514 .write_channel_attr = usb_write_chn_attr,
Paul Cercueil6c8337e2015-11-27 11:13:09 +0100515 .set_kernel_buffers_count = usb_set_kernel_buffers_count,
Paul Cercueil7a988892015-12-03 12:39:20 +0100516 .set_timeout = usb_set_timeout,
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200517 .shutdown = usb_shutdown,
Lars-Peter Clausene5c04e02016-06-22 16:52:36 +0200518
519 .cancel = usb_cancel,
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200520};
521
Lars-Peter Clausenee508922016-04-22 15:38:20 +0200522static void LIBUSB_CALL sync_transfer_cb(struct libusb_transfer *transfer)
523{
524 int *completed = transfer->user_data;
525 *completed = 1;
526}
527
528static int usb_sync_transfer(struct iio_context_pdata *pdata,
529 struct iio_usb_io_context *io_ctx, unsigned int ep_type,
530 char *data, size_t len, int *transferred)
531{
532 struct libusb_transfer *transfer;
533 int completed = 0;
534 int ret;
535
Lars-Peter Clausene5c04e02016-06-22 16:52:36 +0200536 /*
537 * For cancellation support the check whether the buffer has already been
538 * cancelled and the allocation as well as the assignment of the new
539 * transfer needs to happen in one atomic step. Otherwise it is possible
540 * that the cancellation is missed and transfer is not aborted.
541 */
542 iio_mutex_lock(io_ctx->lock);
543 if (io_ctx->cancelled) {
544 ret = -EBADF;
545 goto unlock;
546 }
547
Lars-Peter Clausenee508922016-04-22 15:38:20 +0200548 transfer = libusb_alloc_transfer(0);
Lars-Peter Clausene5c04e02016-06-22 16:52:36 +0200549 if (!transfer) {
550 ret = -ENOMEM;
551 goto unlock;
552 }
Lars-Peter Clausenee508922016-04-22 15:38:20 +0200553
554 transfer->user_data = &completed;
555
556 libusb_fill_bulk_transfer(transfer, pdata->hdl, io_ctx->ep | ep_type,
557 (unsigned char *) data, (int) len, sync_transfer_cb,
558 &completed, pdata->timeout_ms);
559 transfer->type = LIBUSB_TRANSFER_TYPE_BULK;
560
561 ret = libusb_submit_transfer(transfer);
Paul Cercueil1f987912016-09-28 10:44:10 +0200562 if (ret) {
563 ret = -(int) libusb_to_errno(ret);
Lars-Peter Clausenee508922016-04-22 15:38:20 +0200564 libusb_free_transfer(transfer);
Lars-Peter Clausene5c04e02016-06-22 16:52:36 +0200565 goto unlock;
Lars-Peter Clausenee508922016-04-22 15:38:20 +0200566 }
567
Lars-Peter Clausene5c04e02016-06-22 16:52:36 +0200568 io_ctx->transfer = transfer;
569unlock:
570 iio_mutex_unlock(io_ctx->lock);
571 if (ret)
572 return ret;
573
Lars-Peter Clausenee508922016-04-22 15:38:20 +0200574 while (!completed) {
575 ret = libusb_handle_events_completed(pdata->ctx, &completed);
576 if (ret < 0) {
577 if (ret == LIBUSB_ERROR_INTERRUPTED)
578 continue;
579 libusb_cancel_transfer(transfer);
580 continue;
581 }
582 }
583
584 switch (transfer->status) {
585 case LIBUSB_TRANSFER_COMPLETED:
586 *transferred = transfer->actual_length;
587 ret = 0;
588 break;
589 case LIBUSB_TRANSFER_TIMED_OUT:
590 ret = -ETIMEDOUT;
591 break;
592 case LIBUSB_TRANSFER_STALL:
593 ret = -EPIPE;
594 break;
595 case LIBUSB_TRANSFER_NO_DEVICE:
596 ret = -ENODEV;
597 break;
598 case LIBUSB_TRANSFER_CANCELLED:
599 ret = -EBADF;
600 break;
601 default:
602 ret = -EIO;
603 break;
604 }
605
Lars-Peter Clausene5c04e02016-06-22 16:52:36 +0200606 /* Same as above. This needs to be atomic in regards to usb_cancel(). */
607 iio_mutex_lock(io_ctx->lock);
608 io_ctx->transfer = NULL;
609 iio_mutex_unlock(io_ctx->lock);
610
Lars-Peter Clausenee508922016-04-22 15:38:20 +0200611 libusb_free_transfer(transfer);
612
613 return ret;
614}
615
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200616static ssize_t write_data_sync(struct iio_context_pdata *pdata,
Lars-Peter Clausen2767d4d2016-06-23 14:19:02 +0200617 void *ep, const char *data, size_t len)
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200618{
619 int transferred, ret;
620
Lars-Peter Clausen2767d4d2016-06-23 14:19:02 +0200621 ret = usb_sync_transfer(pdata, ep, LIBUSB_ENDPOINT_OUT, (char *) data,
622 len, &transferred);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200623 if (ret)
Paul Cercueil1f987912016-09-28 10:44:10 +0200624 return ret;
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200625 else
Lars-Peter Clausen8ba0d5b2016-02-17 11:30:23 +0100626 return (size_t) transferred != len ? -EIO : (ssize_t) len;
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200627}
628
629static ssize_t read_data_sync(struct iio_context_pdata *pdata,
Lars-Peter Clausen2767d4d2016-06-23 14:19:02 +0200630 void *ep, char *buf, size_t len)
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200631{
632 int transferred, ret;
633
Lars-Peter Clausen2767d4d2016-06-23 14:19:02 +0200634 ret = usb_sync_transfer(pdata, ep, LIBUSB_ENDPOINT_IN, buf, len,
635 &transferred);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200636 if (ret)
Paul Cercueil1f987912016-09-28 10:44:10 +0200637 return ret;
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200638 else
639 return transferred;
640}
641
Lars-Peter Clausen09a59d72016-02-03 15:27:04 +0100642static const struct iiod_client_ops usb_iiod_client_ops = {
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200643 .write = write_data_sync,
644 .read = read_data_sync,
645 .read_line = read_data_sync,
646};
647
Paul Cercueil4213a432016-02-09 14:00:40 +0100648static int usb_count_io_eps(const struct libusb_interface_descriptor *iface)
649{
650 unsigned int eps = iface->bNumEndpoints;
651 unsigned int i, curr;
652
653 /* Check that for a number of endpoints X provided by the interface, we
654 * have the input and output endpoints in the address range [1, ... X/2]
655 * and that each input endpoint has a corresponding output endpoint at
656 * the same address. */
657
658 if (eps < 2 || eps % 2)
659 return -EINVAL;
660
661 for (curr = 1; curr < (eps / 2) + 1; curr++) {
662 bool found_in = false, found_out = false;
663
664 for (i = 0; !found_in && i < eps; i++)
665 found_in = iface->endpoint[i].bEndpointAddress ==
Paul Cercueil6733c4e2016-02-12 15:09:35 +0100666 (LIBUSB_ENDPOINT_IN | curr);
Paul Cercueil4213a432016-02-09 14:00:40 +0100667 if (!found_in)
668 return -EINVAL;
669
670 for (i = 0; !found_out && i < eps; i++)
671 found_out = iface->endpoint[i].bEndpointAddress ==
Paul Cercueil6733c4e2016-02-12 15:09:35 +0100672 (LIBUSB_ENDPOINT_OUT | curr);
Paul Cercueil4213a432016-02-09 14:00:40 +0100673 if (!found_out)
674 return -EINVAL;
675 }
676
677 /* -1: we reserve the first I/O endpoint couple for global operations */
678 return (int) curr - 1;
679}
680
Lars-Peter Clausen7a8e6b52016-02-22 13:25:12 +0100681struct iio_context * usb_create_context(unsigned int bus,
682 unsigned int address, unsigned int interface)
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200683{
684 libusb_context *usb_ctx;
685 libusb_device_handle *hdl;
Paul Cercueil4213a432016-02-09 14:00:40 +0100686 const struct libusb_interface_descriptor *iface;
Lars-Peter Clausen7a8e6b52016-02-22 13:25:12 +0100687 libusb_device *dev, *usb_dev;
Paul Cercueil4213a432016-02-09 14:00:40 +0100688 struct libusb_config_descriptor *conf_desc;
Lars-Peter Clausen7a8e6b52016-02-22 13:25:12 +0100689 libusb_device **device_list;
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200690 struct iio_context *ctx;
691 struct iio_context_pdata *pdata;
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100692 char err_str[1024];
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200693 unsigned int i;
694 int ret;
695
Lars-Peter Clausend1be8382016-02-24 11:13:45 +0100696 pdata = zalloc(sizeof(*pdata));
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200697 if (!pdata) {
698 ERROR("Unable to allocate pdata\n");
699 ret = -ENOMEM;
700 goto err_set_errno;
701 }
702
703 pdata->lock = iio_mutex_create();
704 if (!pdata->lock) {
705 ERROR("Unable to create mutex\n");
706 ret = -ENOMEM;
707 goto err_free_pdata;
708 }
709
Paul Cercueil4213a432016-02-09 14:00:40 +0100710 pdata->ep_lock = iio_mutex_create();
711 if (!pdata->ep_lock) {
Paul Cercueil4acd6042015-11-30 12:10:43 +0100712 ERROR("Unable to create mutex\n");
713 ret = -ENOMEM;
714 goto err_destroy_mutex;
715 }
716
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200717 pdata->iiod_client = iiod_client_new(pdata, pdata->lock,
718 &usb_iiod_client_ops);
719 if (!pdata->iiod_client) {
720 ERROR("Unable to create IIOD client\n");
721 ret = -errno;
Paul Cercueil4213a432016-02-09 14:00:40 +0100722 goto err_destroy_ep_mutex;
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200723 }
724
725 ret = libusb_init(&usb_ctx);
726 if (ret) {
Paul Cercueil463fc782015-12-04 16:04:12 +0100727 ret = -(int) libusb_to_errno(ret);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200728 ERROR("Unable to init libusb: %i\n", ret);
Paul Cercueil4acd6042015-11-30 12:10:43 +0100729 goto err_destroy_iiod_client;
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200730 }
731
Lars-Peter Clausen7a8e6b52016-02-22 13:25:12 +0100732 libusb_get_device_list(usb_ctx, &device_list);
733
734 usb_dev = NULL;
735
736 for (i = 0; device_list[i]; i++) {
737 dev = device_list[i];
738
739 if (bus == libusb_get_bus_number(dev) &&
740 address == libusb_get_device_address(dev)) {
741 usb_dev = dev;
742 libusb_ref_device(usb_dev);
743 break;
744 }
745 }
746
747 libusb_free_device_list(device_list, true);
748
749 if (!usb_dev)
750 goto err_libusb_exit;
751
752 ret = libusb_open(usb_dev, &hdl);
753 libusb_unref_device(usb_dev); /* Open gets us a extra ref */
754 if (ret) {
755 ret = -(int) libusb_to_errno(ret);
756 ERROR("Unable to open device\n");
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200757 goto err_libusb_exit;
758 }
759
760 libusb_set_auto_detach_kernel_driver(hdl, true);
761
Lars-Peter Clausen7a8e6b52016-02-22 13:25:12 +0100762 ret = libusb_claim_interface(hdl, interface);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200763 if (ret) {
Paul Cercueil463fc782015-12-04 16:04:12 +0100764 ret = -(int) libusb_to_errno(ret);
Lars-Peter Clausen7a8e6b52016-02-22 13:25:12 +0100765 ERROR("Unable to claim interface %u: %i\n", interface, ret);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200766 goto err_libusb_close;
767 }
768
Paul Cercueil4213a432016-02-09 14:00:40 +0100769 ret = libusb_get_active_config_descriptor(usb_dev, &conf_desc);
770 if (ret) {
771 ret = -(int) libusb_to_errno(ret);
772 ERROR("Unable to get config descriptor: %i\n", ret);
773 goto err_libusb_close;
774 }
775
Lars-Peter Clausen7a8e6b52016-02-22 13:25:12 +0100776 iface = &conf_desc->interface[interface].altsetting[0];
Paul Cercueil4213a432016-02-09 14:00:40 +0100777
778 ret = usb_count_io_eps(iface);
779 if (ret < 0) {
780 ERROR("Invalid configuration of endpoints\n");
781 goto err_free_config_descriptor;
782 }
783
784 pdata->nb_io_endpoints = ret;
785
786 DEBUG("Found %hhu usable i/o endpoints\n", pdata->nb_io_endpoints);
787
788 if (pdata->nb_io_endpoints) {
789 pdata->io_endpoints = calloc(pdata->nb_io_endpoints,
790 sizeof(*pdata->io_endpoints));
791 if (!pdata->io_endpoints) {
792 ERROR("Unable to allocate endpoints\n");
793 ret = -ENOMEM;
794 goto err_free_config_descriptor;
795 }
796
797 for (i = 0; i < pdata->nb_io_endpoints; i++) {
798 struct iio_usb_io_endpoint *ep =
799 &pdata->io_endpoints[i];
800
801 /* +2: endpoints start at number 1, and we skip the
802 * endpoint #1 that we reserve for global operations */
803 ep->address = i + 2;
804
805 ep->lock = iio_mutex_create();
806 if (!ep->lock) {
807 ERROR("Unable to create mutex\n");
808 ret = -ENOMEM;
809 goto err_free_endpoints;
810 }
811 }
812 }
813
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200814 pdata->ctx = usb_ctx;
815 pdata->hdl = hdl;
Paul Cercueil7a988892015-12-03 12:39:20 +0100816 pdata->timeout_ms = DEFAULT_TIMEOUT_MS;
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200817
Lars-Peter Clausene5c04e02016-06-22 16:52:36 +0200818 ret = usb_io_context_init(&pdata->io_ctx);
819 if (ret)
820 goto err_free_endpoints;
821
Lars-Peter Clausenf0d8ff42016-07-04 10:41:53 +0200822 pdata->io_ctx.ep = EP_OPS;
823
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100824 ret = usb_reset_pipes(hdl);
825 if (ret) {
826 iio_strerror(-ret, err_str, sizeof(err_str));
827 ERROR("Failed to reset pipes: %s\n", err_str);
Lars-Peter Clausene5c04e02016-06-22 16:52:36 +0200828 goto err_io_context_exit;
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100829 }
830
831 ret = usb_open_pipe(hdl, EP_OPS);
832 if (ret) {
833 iio_strerror(-ret, err_str, sizeof(err_str));
834 ERROR("Failed to open control pipe: %s\n", err_str);
Lars-Peter Clausene5c04e02016-06-22 16:52:36 +0200835 goto err_io_context_exit;
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100836 }
837
Lars-Peter Clausen2767d4d2016-06-23 14:19:02 +0200838 ctx = iiod_client_create_context(pdata->iiod_client, &pdata->io_ctx);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200839 if (!ctx)
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100840 goto err_reset_pipes;
Paul Cercueil4213a432016-02-09 14:00:40 +0100841
842 libusb_free_config_descriptor(conf_desc);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200843
844 ctx->name = "usb";
845 ctx->ops = &usb_ops;
846 ctx->pdata = pdata;
847
Paul Cercueil4acd6042015-11-30 12:10:43 +0100848 for (i = 0; i < ctx->nb_devices; i++) {
849 struct iio_device *dev = ctx->devices[i];
850
Lars-Peter Clausend1be8382016-02-24 11:13:45 +0100851 dev->pdata = zalloc(sizeof(*dev->pdata));
Paul Cercueil4acd6042015-11-30 12:10:43 +0100852 if (!dev->pdata) {
853 ERROR("Unable to allocate memory\n");
854 ret = -ENOMEM;
855 goto err_context_destroy;
856 }
Lars-Peter Clausene5c04e02016-06-22 16:52:36 +0200857
858 ret = usb_io_context_init(&dev->pdata->io_ctx);
859 if (ret)
860 goto err_context_destroy;
Paul Cercueil4acd6042015-11-30 12:10:43 +0100861 }
862
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200863 return ctx;
864
865err_context_destroy:
866 iio_context_destroy(ctx);
867 errno = -ret;
868 return NULL;
869
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100870err_reset_pipes:
871 usb_reset_pipes(hdl); /* Close everything */
Lars-Peter Clausene5c04e02016-06-22 16:52:36 +0200872err_io_context_exit:
873 usb_io_context_exit(&pdata->io_ctx);
Paul Cercueil4213a432016-02-09 14:00:40 +0100874err_free_endpoints:
875 for (i = 0; i < pdata->nb_io_endpoints; i++)
876 if (pdata->io_endpoints[i].lock)
877 iio_mutex_destroy(pdata->io_endpoints[i].lock);
878 if (pdata->io_endpoints)
879 free(pdata->io_endpoints);
880err_free_config_descriptor:
881 libusb_free_config_descriptor(conf_desc);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200882err_libusb_close:
883 libusb_close(hdl);
884err_libusb_exit:
885 libusb_exit(usb_ctx);
886err_destroy_iiod_client:
887 iiod_client_destroy(pdata->iiod_client);
Paul Cercueil4213a432016-02-09 14:00:40 +0100888err_destroy_ep_mutex:
889 iio_mutex_destroy(pdata->ep_lock);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200890err_destroy_mutex:
891 iio_mutex_destroy(pdata->lock);
892err_free_pdata:
893 free(pdata);
894err_set_errno:
895 errno = -ret;
896 return NULL;
897}
Lars-Peter Clausen60f1c9a2016-02-22 13:20:40 +0100898
899struct iio_context * usb_create_context_from_uri(const char *uri)
900{
Paul Cercueil370bb362016-04-20 11:50:10 +0200901 long bus, address, interface;
902 char *end;
903 const char *ptr;
Lars-Peter Clausen60f1c9a2016-02-22 13:20:40 +0100904
905 if (strncmp(uri, "usb:", sizeof("usb:") - 1) != 0)
Paul Cercueil370bb362016-04-20 11:50:10 +0200906 goto err_bad_uri;
Lars-Peter Clausen60f1c9a2016-02-22 13:20:40 +0100907
Paul Cercueil370bb362016-04-20 11:50:10 +0200908 ptr = (const char *) ((uintptr_t) uri + sizeof("usb:") - 1);
909 if (!isdigit(*ptr))
910 goto err_bad_uri;
Lars-Peter Clausen60f1c9a2016-02-22 13:20:40 +0100911
Paul Cercueil370bb362016-04-20 11:50:10 +0200912 bus = strtol(ptr, &end, 10);
913 if (ptr == end || *end != '.')
914 goto err_bad_uri;
915
916 ptr = (const char *) ((uintptr_t) end + 1);
917 if (!isdigit(*ptr))
918 goto err_bad_uri;
919
920 address = strtol(ptr, &end, 10);
Paul Cercueild24f8ac2016-04-20 14:19:29 +0200921 if (ptr == end)
Paul Cercueil370bb362016-04-20 11:50:10 +0200922 goto err_bad_uri;
923
Paul Cercueild24f8ac2016-04-20 14:19:29 +0200924 if (*end == '\0') {
925 interface = 0;
926 } else if (*end == '.') {
927 ptr = (const char *) ((uintptr_t) end + 1);
928 if (!isdigit(*ptr))
929 goto err_bad_uri;
Paul Cercueil370bb362016-04-20 11:50:10 +0200930
Paul Cercueild24f8ac2016-04-20 14:19:29 +0200931 interface = strtol(ptr, &end, 10);
932 if (ptr == end || *end != '\0')
933 goto err_bad_uri;
934 } else {
Paul Cercueil370bb362016-04-20 11:50:10 +0200935 goto err_bad_uri;
Paul Cercueild24f8ac2016-04-20 14:19:29 +0200936 }
Paul Cercueil370bb362016-04-20 11:50:10 +0200937
938 if (bus < 0 || address < 0 || interface < 0)
939 goto err_bad_uri;
940
941 return usb_create_context((unsigned int) bus,
942 (unsigned int) address, (unsigned int) interface);
943
944err_bad_uri:
945 ERROR("Bad URI: \'%s\'\n", uri);
946 errno = -EINVAL;
947 return NULL;
Lars-Peter Clausen60f1c9a2016-02-22 13:20:40 +0100948}
Lars-Peter Clausen794ba032016-04-25 15:07:00 +0200949
950static int usb_fill_context_info(struct iio_context_info *info,
951 struct libusb_device *dev, struct libusb_device_handle *hdl,
952 unsigned int interface)
953{
954 struct libusb_device_descriptor desc;
955 char manufacturer[64], product[64];
956 char uri[sizeof("usb:127.255.255")];
957 char description[sizeof(manufacturer) + sizeof(product) +
958 sizeof("0000:0000 ( )")];
959 int ret;
960
961 libusb_get_device_descriptor(dev, &desc);
962
963 snprintf(uri, sizeof(uri), "usb:%d.%d.%u",
964 libusb_get_bus_number(dev), libusb_get_device_address(dev),
965 interface);
966
967 if (desc.iManufacturer == 0) {
968 manufacturer[0] = '\0';
969 } else {
970 ret = libusb_get_string_descriptor_ascii(hdl,
971 desc.iManufacturer,
972 (unsigned char *) manufacturer,
973 sizeof(manufacturer));
974 if (ret < 0)
975 manufacturer[0] = '\0';
976 }
977
978 if (desc.iProduct == 0) {
979 product[0] = '\0';
980 } else {
981 ret = libusb_get_string_descriptor_ascii(hdl,
982 desc.iProduct, (unsigned char *) product,
983 sizeof(product));
984 if (ret < 0)
985 product[0] = '\0';
986 }
987
988 snprintf(description, sizeof(description),
989 "%04x:%04x (%s %s)", desc.idVendor,
990 desc.idProduct, manufacturer, product);
991
Paul Cercueilcaf0e712016-08-25 17:27:02 +0200992 info->uri = iio_strdup(uri);
Lars-Peter Clausen794ba032016-04-25 15:07:00 +0200993 if (!info->uri)
994 return -ENOMEM;
995
Paul Cercueilcaf0e712016-08-25 17:27:02 +0200996 info->description = iio_strdup(description);
Lars-Peter Clausen794ba032016-04-25 15:07:00 +0200997 if (!info->description)
998 return -ENOMEM;
999
1000 return 0;
1001}
1002
1003struct iio_scan_backend_context {
1004 libusb_context *ctx;
1005};
1006
1007struct iio_scan_backend_context * usb_context_scan_init(void)
1008{
1009 struct iio_scan_backend_context *ctx;
1010 int ret;
1011
1012 ctx = malloc(sizeof(*ctx));
1013 if (!ctx) {
1014 errno = ENOMEM;
1015 return NULL;
1016 }
1017
1018 ret = libusb_init(&ctx->ctx);
1019 if (ret) {
1020 free(ctx);
1021 errno = (int) libusb_to_errno(ret);
1022 return NULL;
1023 }
1024
1025 return ctx;
1026}
1027
1028void usb_context_scan_free(struct iio_scan_backend_context *ctx)
1029{
1030 libusb_exit(ctx->ctx);
1031 free(ctx);
1032}
1033
1034int usb_context_scan(struct iio_scan_backend_context *ctx,
1035 struct iio_scan_result *scan_result)
1036{
1037 struct iio_context_info **info;
1038 libusb_device **device_list;
1039 unsigned int i;
1040 int ret;
1041
1042 ret = libusb_get_device_list(ctx->ctx, &device_list);
1043 if (ret < 0)
1044 return -(int) libusb_to_errno(ret);
1045
1046 for (i = 0; device_list[i]; i++) {
1047 struct libusb_device_handle *hdl;
1048 struct libusb_device *dev = device_list[i];
1049 unsigned int interface = 0;
1050
1051 ret = libusb_open(dev, &hdl);
1052 if (ret)
1053 continue;
1054
1055 if (!iio_usb_match_device(dev, hdl, &interface)) {
1056 info = iio_scan_result_add(scan_result, 1);
1057 if (!info)
1058 ret = -ENOMEM;
1059 else
1060 ret = usb_fill_context_info(*info, dev, hdl,
1061 interface);
1062 }
1063
1064 libusb_close(hdl);
1065 if (ret < 0)
1066 goto cleanup_free_device_list;
1067 }
1068
1069 ret = 0;
1070
1071cleanup_free_device_list:
1072 libusb_free_device_list(device_list, true);
1073 return ret;
1074}