blob: 6994bbd96c71c79cf36e382e863d589d93adb19d [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;
44};
45
Paul Cercueil4213a432016-02-09 14:00:40 +010046struct iio_usb_io_endpoint {
47 unsigned char address;
48 bool in_use;
Paul Cercueil4acd6042015-11-30 12:10:43 +010049
Paul Cercueil4213a432016-02-09 14:00:40 +010050 struct iio_mutex *lock;
51};
Paul Cercueil4acd6042015-11-30 12:10:43 +010052
Paul Cercueile06f4ce2015-04-20 12:59:31 +020053struct iio_context_pdata {
54 libusb_context *ctx;
55 libusb_device_handle *hdl;
56
57 struct iiod_client *iiod_client;
58
59 /* Lock for non-streaming operations */
60 struct iio_mutex *lock;
Paul Cercueil4acd6042015-11-30 12:10:43 +010061
Paul Cercueil4213a432016-02-09 14:00:40 +010062 /* Lock for endpoint reservation */
63 struct iio_mutex *ep_lock;
64
65 struct iio_usb_io_endpoint *io_endpoints;
66 unsigned int nb_io_endpoints;
Paul Cercueil7a988892015-12-03 12:39:20 +010067
68 unsigned int timeout_ms;
Lars-Peter Clausenf0d8ff42016-07-04 10:41:53 +020069
70 struct iio_usb_io_context io_ctx;
Paul Cercueil4acd6042015-11-30 12:10:43 +010071};
72
73struct iio_device_pdata {
Paul Cercueil4acd6042015-11-30 12:10:43 +010074 struct iio_mutex *lock;
75
76 bool opened;
Lars-Peter Clausenf0d8ff42016-07-04 10:41:53 +020077 struct iio_usb_io_context io_ctx;
Paul Cercueile06f4ce2015-04-20 12:59:31 +020078};
79
80static const unsigned int libusb_to_errno_codes[] = {
81 [- LIBUSB_ERROR_INVALID_PARAM] = EINVAL,
82 [- LIBUSB_ERROR_ACCESS] = EACCES,
83 [- LIBUSB_ERROR_NO_DEVICE] = ENODEV,
84 [- LIBUSB_ERROR_NOT_FOUND] = ENXIO,
85 [- LIBUSB_ERROR_BUSY] = EBUSY,
86 [- LIBUSB_ERROR_TIMEOUT] = ETIMEDOUT,
87 [- LIBUSB_ERROR_OVERFLOW] = EIO,
88 [- LIBUSB_ERROR_PIPE] = EPIPE,
89 [- LIBUSB_ERROR_INTERRUPTED] = EINTR,
90 [- LIBUSB_ERROR_NO_MEM] = ENOMEM,
91 [- LIBUSB_ERROR_NOT_SUPPORTED] = ENOSYS,
92};
93
94static unsigned int libusb_to_errno(int error)
95{
96 switch ((enum libusb_error) error) {
97 case LIBUSB_ERROR_INVALID_PARAM:
98 case LIBUSB_ERROR_ACCESS:
99 case LIBUSB_ERROR_NO_DEVICE:
100 case LIBUSB_ERROR_NOT_FOUND:
101 case LIBUSB_ERROR_BUSY:
102 case LIBUSB_ERROR_TIMEOUT:
103 case LIBUSB_ERROR_PIPE:
104 case LIBUSB_ERROR_INTERRUPTED:
105 case LIBUSB_ERROR_NO_MEM:
106 case LIBUSB_ERROR_NOT_SUPPORTED:
107 return libusb_to_errno_codes[- (int) error];
108 case LIBUSB_ERROR_IO:
109 case LIBUSB_ERROR_OTHER:
110 case LIBUSB_ERROR_OVERFLOW:
111 default:
112 return EIO;
113 }
114}
115
Paul Cercueilc11737c2015-11-26 14:44:46 +0100116static int usb_get_version(const struct iio_context *ctx,
117 unsigned int *major, unsigned int *minor, char git_tag[8])
118{
119 return iiod_client_get_version(ctx->pdata->iiod_client,
Lars-Peter Clausenf0d8ff42016-07-04 10:41:53 +0200120 (uintptr_t) &ctx->pdata->io_ctx, major, minor, git_tag);
Paul Cercueilc11737c2015-11-26 14:44:46 +0100121}
122
Paul Cercueila5e4aa42016-02-09 13:31:01 +0100123static unsigned int usb_calculate_remote_timeout(unsigned int timeout)
124{
125 /* XXX(pcercuei): We currently hardcode timeout / 2 for the backend used
126 * by the remote. Is there something better to do here? */
127 return timeout / 2;
128}
129
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100130#define USB_PIPE_CTRL_TIMEOUT 200 /* These should not take long */
131
132#define IIO_USD_CMD_RESET_PIPES 0
133#define IIO_USD_CMD_OPEN_PIPE 1
134#define IIO_USD_CMD_CLOSE_PIPE 2
135
136static int usb_reset_pipes(libusb_device_handle *hdl)
137{
138 int ret;
139
140 ret = libusb_control_transfer(hdl, LIBUSB_REQUEST_TYPE_VENDOR |
141 LIBUSB_RECIPIENT_INTERFACE, IIO_USD_CMD_RESET_PIPES,
142 0, 0, NULL, 0, USB_PIPE_CTRL_TIMEOUT);
143 if (ret < 0)
Paul Cercueil67482202016-04-21 16:40:02 +0200144 return -(int) libusb_to_errno(ret);
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100145 return 0;
146}
147
148static int usb_open_pipe(libusb_device_handle *hdl, unsigned int ep)
149{
150 int ret;
151
152 ret = libusb_control_transfer(hdl, LIBUSB_REQUEST_TYPE_VENDOR |
153 LIBUSB_RECIPIENT_INTERFACE, IIO_USD_CMD_OPEN_PIPE,
154 ep - 1, 0, NULL, 0, USB_PIPE_CTRL_TIMEOUT);
155 if (ret < 0)
Paul Cercueil67482202016-04-21 16:40:02 +0200156 return -(int) libusb_to_errno(ret);
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100157 return 0;
158}
159
160static int usb_close_pipe(libusb_device_handle *hdl, unsigned int ep)
161{
162 int ret;
163
164 ret = libusb_control_transfer(hdl, LIBUSB_REQUEST_TYPE_VENDOR |
165 LIBUSB_RECIPIENT_INTERFACE, IIO_USD_CMD_CLOSE_PIPE,
166 ep - 1, 0, NULL, 0, USB_PIPE_CTRL_TIMEOUT);
167 if (ret < 0)
Paul Cercueil67482202016-04-21 16:40:02 +0200168 return -(int) libusb_to_errno(ret);
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100169 return 0;
170}
171
Paul Cercueil4213a432016-02-09 14:00:40 +0100172static int usb_reserve_ep_unlocked(const struct iio_device *dev)
173{
174 struct iio_context_pdata *pdata = dev->ctx->pdata;
175 unsigned int i;
176
177 for (i = 0; i < pdata->nb_io_endpoints; i++) {
178 struct iio_usb_io_endpoint *ep = &pdata->io_endpoints[i];
179
180 if (!ep->in_use) {
181 ep->in_use = true;
182
Lars-Peter Clausenf0d8ff42016-07-04 10:41:53 +0200183 dev->pdata->io_ctx.ep = ep->address;
Paul Cercueil4213a432016-02-09 14:00:40 +0100184 dev->pdata->lock = ep->lock;
185 return 0;
186 }
187 }
188
189 return -EBUSY;
190}
191
192static void usb_free_ep_unlocked(const struct iio_device *dev)
193{
194 struct iio_context_pdata *pdata = dev->ctx->pdata;
195 unsigned int i;
196
197 for (i = 0; i < pdata->nb_io_endpoints; i++) {
198 struct iio_usb_io_endpoint *ep = &pdata->io_endpoints[i];
199
200 if (ep->lock == dev->pdata->lock) {
201 ep->in_use = false;
202 return;
203 }
204 }
205}
206
Paul Cercueil4acd6042015-11-30 12:10:43 +0100207static int usb_open(const struct iio_device *dev,
208 size_t samples_count, bool cyclic)
209{
Paul Cercueila5e4aa42016-02-09 13:31:01 +0100210 struct iio_context_pdata *ctx_pdata = dev->ctx->pdata;
Paul Cercueil4acd6042015-11-30 12:10:43 +0100211 struct iio_device_pdata *pdata = dev->pdata;
212 int ret = -EBUSY;
213
Paul Cercueil4213a432016-02-09 14:00:40 +0100214 iio_mutex_lock(ctx_pdata->ep_lock);
Paul Cercueil4acd6042015-11-30 12:10:43 +0100215
Paul Cercueila5e4aa42016-02-09 13:31:01 +0100216 if (pdata->opened)
217 goto out_unlock;
218
Paul Cercueil4213a432016-02-09 14:00:40 +0100219 ret = usb_reserve_ep_unlocked(dev);
220 if (ret)
221 goto out_unlock;
222
Lars-Peter Clausenf0d8ff42016-07-04 10:41:53 +0200223 ret = usb_open_pipe(ctx_pdata->hdl, pdata->io_ctx.ep);
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100224 if (ret) {
225 char err_str[1024];
226
227 iio_strerror(-ret, err_str, sizeof(err_str));
228 ERROR("Failed to open pipe: %s\n", err_str);
229 usb_free_ep_unlocked(dev);
230 goto out_unlock;
231 }
232
Paul Cercueil4213a432016-02-09 14:00:40 +0100233 iio_mutex_lock(pdata->lock);
234
Paul Cercueila5e4aa42016-02-09 13:31:01 +0100235 ret = iiod_client_open_unlocked(ctx_pdata->iiod_client,
Lars-Peter Clausenf0d8ff42016-07-04 10:41:53 +0200236 (uintptr_t) &pdata->io_ctx, dev, samples_count, cyclic);
Paul Cercueila5e4aa42016-02-09 13:31:01 +0100237
238 if (!ret) {
239 unsigned int remote_timeout =
240 usb_calculate_remote_timeout(ctx_pdata->timeout_ms);
241
242 ret = iiod_client_set_timeout(ctx_pdata->iiod_client,
Lars-Peter Clausenf0d8ff42016-07-04 10:41:53 +0200243 (uintptr_t) &pdata->io_ctx, remote_timeout);
Paul Cercueil4acd6042015-11-30 12:10:43 +0100244 }
245
Paul Cercueila5e4aa42016-02-09 13:31:01 +0100246 pdata->opened = !ret;
247
Paul Cercueil4acd6042015-11-30 12:10:43 +0100248 iio_mutex_unlock(pdata->lock);
Paul Cercueil4213a432016-02-09 14:00:40 +0100249
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100250 if (ret) {
Lars-Peter Clausenf0d8ff42016-07-04 10:41:53 +0200251 usb_close_pipe(ctx_pdata->hdl, pdata->io_ctx.ep);
Paul Cercueil4213a432016-02-09 14:00:40 +0100252 usb_free_ep_unlocked(dev);
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100253 }
Paul Cercueil4213a432016-02-09 14:00:40 +0100254
255out_unlock:
256 iio_mutex_unlock(ctx_pdata->ep_lock);
Paul Cercueil4acd6042015-11-30 12:10:43 +0100257 return ret;
258}
259
260static int usb_close(const struct iio_device *dev)
261{
Paul Cercueil4213a432016-02-09 14:00:40 +0100262 struct iio_context_pdata *ctx_pdata = dev->ctx->pdata;
Paul Cercueil4acd6042015-11-30 12:10:43 +0100263 struct iio_device_pdata *pdata = dev->pdata;
264 int ret = -EBADF;
265
Paul Cercueil4213a432016-02-09 14:00:40 +0100266 iio_mutex_lock(ctx_pdata->ep_lock);
267 if (!pdata->opened)
268 goto out_unlock;
Paul Cercueil4acd6042015-11-30 12:10:43 +0100269
Paul Cercueil4213a432016-02-09 14:00:40 +0100270 iio_mutex_lock(pdata->lock);
271 ret = iiod_client_close_unlocked(ctx_pdata->iiod_client,
Lars-Peter Clausenf0d8ff42016-07-04 10:41:53 +0200272 (uintptr_t) &pdata->io_ctx, dev);
Paul Cercueil4213a432016-02-09 14:00:40 +0100273 pdata->opened = false;
274
Paul Cercueil31492b32016-02-22 17:40:20 +0100275 iio_mutex_unlock(pdata->lock);
276
Lars-Peter Clausenf0d8ff42016-07-04 10:41:53 +0200277 usb_close_pipe(ctx_pdata->hdl, pdata->io_ctx.ep);
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100278
Paul Cercueil4213a432016-02-09 14:00:40 +0100279 usb_free_ep_unlocked(dev);
280
281out_unlock:
282 iio_mutex_unlock(ctx_pdata->ep_lock);
Paul Cercueil4acd6042015-11-30 12:10:43 +0100283 return ret;
284}
285
Paul Cercueil04841832015-12-02 11:58:33 +0100286static ssize_t usb_read(const struct iio_device *dev, void *dst, size_t len,
287 uint32_t *mask, size_t words)
288{
289 struct iio_device_pdata *pdata = dev->pdata;
290 ssize_t ret;
291
292 iio_mutex_lock(pdata->lock);
293 ret = iiod_client_read_unlocked(dev->ctx->pdata->iiod_client,
Lars-Peter Clausenf0d8ff42016-07-04 10:41:53 +0200294 (uintptr_t) &pdata->io_ctx, dev, dst, len, mask, words);
Paul Cercueil04841832015-12-02 11:58:33 +0100295 iio_mutex_unlock(pdata->lock);
296
297 return ret;
298}
299
Paul Cercueile78e9882015-12-04 16:31:10 +0100300static ssize_t usb_write(const struct iio_device *dev,
301 const void *src, size_t len)
302{
303 struct iio_device_pdata *pdata = dev->pdata;
304 ssize_t ret;
305
306 iio_mutex_lock(pdata->lock);
307 ret = iiod_client_write_unlocked(dev->ctx->pdata->iiod_client,
Lars-Peter Clausenf0d8ff42016-07-04 10:41:53 +0200308 (uintptr_t) &pdata->io_ctx, dev, src, len);
Paul Cercueile78e9882015-12-04 16:31:10 +0100309 iio_mutex_unlock(pdata->lock);
310
311 return ret;
312}
313
Paul Cercueil3069e3b2015-11-26 16:01:25 +0100314static ssize_t usb_read_dev_attr(const struct iio_device *dev,
315 const char *attr, char *dst, size_t len, bool is_debug)
316{
317 struct iio_context_pdata *pdata = dev->ctx->pdata;
318
Lars-Peter Clausenf0d8ff42016-07-04 10:41:53 +0200319 return iiod_client_read_attr(pdata->iiod_client,
320 (uintptr_t) &pdata->io_ctx, dev, NULL, attr,
321 dst, len, is_debug);
Paul Cercueil3069e3b2015-11-26 16:01:25 +0100322}
323
324static ssize_t usb_write_dev_attr(const struct iio_device *dev,
325 const char *attr, const char *src, size_t len, bool is_debug)
326{
327 struct iio_context_pdata *pdata = dev->ctx->pdata;
328
Lars-Peter Clausenf0d8ff42016-07-04 10:41:53 +0200329 return iiod_client_write_attr(pdata->iiod_client,
330 (uintptr_t) &pdata->io_ctx, dev, NULL, attr,
331 src, len, is_debug);
Paul Cercueil3069e3b2015-11-26 16:01:25 +0100332}
333
334static ssize_t usb_read_chn_attr(const struct iio_channel *chn,
335 const char *attr, char *dst, size_t len)
336{
337 struct iio_context_pdata *pdata = chn->dev->ctx->pdata;
338
Lars-Peter Clausenf0d8ff42016-07-04 10:41:53 +0200339 return iiod_client_read_attr(pdata->iiod_client,
340 (uintptr_t) &pdata->io_ctx, chn->dev, chn, attr,
341 dst, len, false);
Paul Cercueil3069e3b2015-11-26 16:01:25 +0100342}
343
344static ssize_t usb_write_chn_attr(const struct iio_channel *chn,
345 const char *attr, const char *src, size_t len)
346{
347 struct iio_context_pdata *pdata = chn->dev->ctx->pdata;
348
Lars-Peter Clausenf0d8ff42016-07-04 10:41:53 +0200349 return iiod_client_write_attr(pdata->iiod_client,
350 (uintptr_t) &pdata->io_ctx, chn->dev, chn, attr,
351 src, len, false);
Paul Cercueil3069e3b2015-11-26 16:01:25 +0100352}
353
Paul Cercueil6c8337e2015-11-27 11:13:09 +0100354static int usb_set_kernel_buffers_count(const struct iio_device *dev,
355 unsigned int nb_blocks)
356{
357 struct iio_context_pdata *pdata = dev->ctx->pdata;
358
359 return iiod_client_set_kernel_buffers_count(pdata->iiod_client,
Lars-Peter Clausenf0d8ff42016-07-04 10:41:53 +0200360 (uintptr_t) &pdata->io_ctx, dev, nb_blocks);
Paul Cercueil6c8337e2015-11-27 11:13:09 +0100361}
362
Paul Cercueil7a988892015-12-03 12:39:20 +0100363static int usb_set_timeout(struct iio_context *ctx, unsigned int timeout)
364{
365 struct iio_context_pdata *pdata = ctx->pdata;
366 unsigned int remote_timeout = usb_calculate_remote_timeout(timeout);
367 int ret;
368
369 ret = iiod_client_set_timeout(pdata->iiod_client,
Lars-Peter Clausenf0d8ff42016-07-04 10:41:53 +0200370 (uintptr_t) &pdata->io_ctx, remote_timeout);
Paul Cercueila5e4aa42016-02-09 13:31:01 +0100371 if (!ret)
372 pdata->timeout_ms = timeout;
Paul Cercueil7a988892015-12-03 12:39:20 +0100373
Paul Cercueil7a988892015-12-03 12:39:20 +0100374 return ret;
375}
376
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200377static void usb_shutdown(struct iio_context *ctx)
378{
Paul Cercueil4213a432016-02-09 14:00:40 +0100379 unsigned int i;
380
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200381 iio_mutex_destroy(ctx->pdata->lock);
Paul Cercueil4213a432016-02-09 14:00:40 +0100382 iio_mutex_destroy(ctx->pdata->ep_lock);
383
384 for (i = 0; i < ctx->pdata->nb_io_endpoints; i++)
385 if (ctx->pdata->io_endpoints[i].lock)
386 iio_mutex_destroy(ctx->pdata->io_endpoints[i].lock);
387 if (ctx->pdata->io_endpoints)
388 free(ctx->pdata->io_endpoints);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200389
Lars-Peter Clausen33c64312016-02-19 13:32:08 +0100390 for (i = 0; i < ctx->nb_devices; i++) {
391 struct iio_device *dev = ctx->devices[i];
392
393 free(dev->pdata);
394 }
395
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200396 iiod_client_destroy(ctx->pdata->iiod_client);
397
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100398 usb_reset_pipes(ctx->pdata->hdl); /* Close everything */
399
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200400 libusb_close(ctx->pdata->hdl);
401 libusb_exit(ctx->pdata->ctx);
Lars-Peter Clausen33c64312016-02-19 13:32:08 +0100402 free(ctx->pdata);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200403}
404
Lars-Peter Clausen794ba032016-04-25 15:07:00 +0200405static int iio_usb_match_interface(const struct libusb_config_descriptor *desc,
406 struct libusb_device_handle *hdl, unsigned int interface)
407{
408 const struct libusb_interface *iface;
409 unsigned int i;
410
411 if (interface >= desc->bNumInterfaces)
412 return -EINVAL;
413
414 iface = &desc->interface[interface];
415
416 for (i = 0; i < (unsigned int) iface->num_altsetting; i++) {
417 const struct libusb_interface_descriptor *idesc =
418 &iface->altsetting[i];
419 char name[64];
420 int ret;
421
422 if (idesc->iInterface == 0)
423 continue;
424
425 ret = libusb_get_string_descriptor_ascii(hdl, idesc->iInterface,
426 (unsigned char *) name, sizeof(name));
427 if (ret < 0)
428 return ret;
429
430 if (!strcmp(name, IIO_INTERFACE_NAME))
431 return (int) i;
432 }
433
434 return -EPERM;
435}
436
437static int iio_usb_match_device(struct libusb_device *dev,
438 struct libusb_device_handle *hdl,
439 unsigned int *interface)
440{
441 struct libusb_config_descriptor *desc;
442 unsigned int i;
443 int ret;
444
445 ret = libusb_get_active_config_descriptor(dev, &desc);
446 if (ret)
447 return -(int) libusb_to_errno(ret);
448
449 for (i = 0, ret = -EPERM; ret == -EPERM &&
450 i < desc->bNumInterfaces; i++)
451 ret = iio_usb_match_interface(desc, hdl, i);
452
453 libusb_free_config_descriptor(desc);
454 if (ret < 0)
455 return ret;
456
457 DEBUG("Found IIO interface on device %u:%u using interface %u\n",
458 libusb_get_bus_number(dev),
459 libusb_get_device_address(dev), i - 1);
460
461 *interface = i - 1;
462 return ret;
463}
464
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200465static const struct iio_backend_ops usb_ops = {
Paul Cercueilc11737c2015-11-26 14:44:46 +0100466 .get_version = usb_get_version,
Paul Cercueil4acd6042015-11-30 12:10:43 +0100467 .open = usb_open,
468 .close = usb_close,
Paul Cercueil04841832015-12-02 11:58:33 +0100469 .read = usb_read,
Paul Cercueile78e9882015-12-04 16:31:10 +0100470 .write = usb_write,
Paul Cercueil3069e3b2015-11-26 16:01:25 +0100471 .read_device_attr = usb_read_dev_attr,
472 .read_channel_attr = usb_read_chn_attr,
473 .write_device_attr = usb_write_dev_attr,
474 .write_channel_attr = usb_write_chn_attr,
Paul Cercueil6c8337e2015-11-27 11:13:09 +0100475 .set_kernel_buffers_count = usb_set_kernel_buffers_count,
Paul Cercueil7a988892015-12-03 12:39:20 +0100476 .set_timeout = usb_set_timeout,
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200477 .shutdown = usb_shutdown,
478};
479
480static ssize_t write_data_sync(struct iio_context_pdata *pdata,
Lars-Peter Clausen7e69ae62016-06-22 10:56:41 +0200481 uintptr_t ep, const char *data, size_t len)
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200482{
483 int transferred, ret;
484
485 ret = libusb_bulk_transfer(pdata->hdl, ep | LIBUSB_ENDPOINT_OUT,
Lars-Peter Clausen8ba0d5b2016-02-17 11:30:23 +0100486 (unsigned char *) data, (int) len,
Paul Cercueile10d19a2016-02-09 13:30:12 +0100487 &transferred, pdata->timeout_ms);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200488 if (ret)
Paul Cercueil463fc782015-12-04 16:04:12 +0100489 return -(int) libusb_to_errno(ret);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200490 else
Lars-Peter Clausen8ba0d5b2016-02-17 11:30:23 +0100491 return (size_t) transferred != len ? -EIO : (ssize_t) len;
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200492}
493
494static ssize_t read_data_sync(struct iio_context_pdata *pdata,
Lars-Peter Clausen7e69ae62016-06-22 10:56:41 +0200495 uintptr_t ep, char *buf, size_t len)
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200496{
497 int transferred, ret;
498
499 ret = libusb_bulk_transfer(pdata->hdl, ep | LIBUSB_ENDPOINT_IN,
Lars-Peter Clausen8ba0d5b2016-02-17 11:30:23 +0100500 (unsigned char *) buf, (int) len, &transferred, pdata->timeout_ms);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200501 if (ret)
Paul Cercueil463fc782015-12-04 16:04:12 +0100502 return -(int) libusb_to_errno(ret);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200503 else
504 return transferred;
505}
506
Lars-Peter Clausen09a59d72016-02-03 15:27:04 +0100507static const struct iiod_client_ops usb_iiod_client_ops = {
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200508 .write = write_data_sync,
509 .read = read_data_sync,
510 .read_line = read_data_sync,
511};
512
Paul Cercueil4213a432016-02-09 14:00:40 +0100513static int usb_count_io_eps(const struct libusb_interface_descriptor *iface)
514{
515 unsigned int eps = iface->bNumEndpoints;
516 unsigned int i, curr;
517
518 /* Check that for a number of endpoints X provided by the interface, we
519 * have the input and output endpoints in the address range [1, ... X/2]
520 * and that each input endpoint has a corresponding output endpoint at
521 * the same address. */
522
523 if (eps < 2 || eps % 2)
524 return -EINVAL;
525
526 for (curr = 1; curr < (eps / 2) + 1; curr++) {
527 bool found_in = false, found_out = false;
528
529 for (i = 0; !found_in && i < eps; i++)
530 found_in = iface->endpoint[i].bEndpointAddress ==
Paul Cercueil6733c4e2016-02-12 15:09:35 +0100531 (LIBUSB_ENDPOINT_IN | curr);
Paul Cercueil4213a432016-02-09 14:00:40 +0100532 if (!found_in)
533 return -EINVAL;
534
535 for (i = 0; !found_out && i < eps; i++)
536 found_out = iface->endpoint[i].bEndpointAddress ==
Paul Cercueil6733c4e2016-02-12 15:09:35 +0100537 (LIBUSB_ENDPOINT_OUT | curr);
Paul Cercueil4213a432016-02-09 14:00:40 +0100538 if (!found_out)
539 return -EINVAL;
540 }
541
542 /* -1: we reserve the first I/O endpoint couple for global operations */
543 return (int) curr - 1;
544}
545
Lars-Peter Clausen7a8e6b52016-02-22 13:25:12 +0100546struct iio_context * usb_create_context(unsigned int bus,
547 unsigned int address, unsigned int interface)
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200548{
549 libusb_context *usb_ctx;
550 libusb_device_handle *hdl;
Paul Cercueil4213a432016-02-09 14:00:40 +0100551 const struct libusb_interface_descriptor *iface;
Lars-Peter Clausen7a8e6b52016-02-22 13:25:12 +0100552 libusb_device *dev, *usb_dev;
Paul Cercueil4213a432016-02-09 14:00:40 +0100553 struct libusb_config_descriptor *conf_desc;
Lars-Peter Clausen7a8e6b52016-02-22 13:25:12 +0100554 libusb_device **device_list;
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200555 struct iio_context *ctx;
556 struct iio_context_pdata *pdata;
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100557 char err_str[1024];
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200558 unsigned int i;
559 int ret;
560
Lars-Peter Clausend1be8382016-02-24 11:13:45 +0100561 pdata = zalloc(sizeof(*pdata));
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200562 if (!pdata) {
563 ERROR("Unable to allocate pdata\n");
564 ret = -ENOMEM;
565 goto err_set_errno;
566 }
567
568 pdata->lock = iio_mutex_create();
569 if (!pdata->lock) {
570 ERROR("Unable to create mutex\n");
571 ret = -ENOMEM;
572 goto err_free_pdata;
573 }
574
Paul Cercueil4213a432016-02-09 14:00:40 +0100575 pdata->ep_lock = iio_mutex_create();
576 if (!pdata->ep_lock) {
Paul Cercueil4acd6042015-11-30 12:10:43 +0100577 ERROR("Unable to create mutex\n");
578 ret = -ENOMEM;
579 goto err_destroy_mutex;
580 }
581
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200582 pdata->iiod_client = iiod_client_new(pdata, pdata->lock,
583 &usb_iiod_client_ops);
584 if (!pdata->iiod_client) {
585 ERROR("Unable to create IIOD client\n");
586 ret = -errno;
Paul Cercueil4213a432016-02-09 14:00:40 +0100587 goto err_destroy_ep_mutex;
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200588 }
589
590 ret = libusb_init(&usb_ctx);
591 if (ret) {
Paul Cercueil463fc782015-12-04 16:04:12 +0100592 ret = -(int) libusb_to_errno(ret);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200593 ERROR("Unable to init libusb: %i\n", ret);
Paul Cercueil4acd6042015-11-30 12:10:43 +0100594 goto err_destroy_iiod_client;
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200595 }
596
Lars-Peter Clausen7a8e6b52016-02-22 13:25:12 +0100597 libusb_get_device_list(usb_ctx, &device_list);
598
599 usb_dev = NULL;
600
601 for (i = 0; device_list[i]; i++) {
602 dev = device_list[i];
603
604 if (bus == libusb_get_bus_number(dev) &&
605 address == libusb_get_device_address(dev)) {
606 usb_dev = dev;
607 libusb_ref_device(usb_dev);
608 break;
609 }
610 }
611
612 libusb_free_device_list(device_list, true);
613
614 if (!usb_dev)
615 goto err_libusb_exit;
616
617 ret = libusb_open(usb_dev, &hdl);
618 libusb_unref_device(usb_dev); /* Open gets us a extra ref */
619 if (ret) {
620 ret = -(int) libusb_to_errno(ret);
621 ERROR("Unable to open device\n");
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200622 goto err_libusb_exit;
623 }
624
625 libusb_set_auto_detach_kernel_driver(hdl, true);
626
Lars-Peter Clausen7a8e6b52016-02-22 13:25:12 +0100627 ret = libusb_claim_interface(hdl, interface);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200628 if (ret) {
Paul Cercueil463fc782015-12-04 16:04:12 +0100629 ret = -(int) libusb_to_errno(ret);
Lars-Peter Clausen7a8e6b52016-02-22 13:25:12 +0100630 ERROR("Unable to claim interface %u: %i\n", interface, ret);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200631 goto err_libusb_close;
632 }
633
Paul Cercueil4213a432016-02-09 14:00:40 +0100634 ret = libusb_get_active_config_descriptor(usb_dev, &conf_desc);
635 if (ret) {
636 ret = -(int) libusb_to_errno(ret);
637 ERROR("Unable to get config descriptor: %i\n", ret);
638 goto err_libusb_close;
639 }
640
Lars-Peter Clausen7a8e6b52016-02-22 13:25:12 +0100641 iface = &conf_desc->interface[interface].altsetting[0];
Paul Cercueil4213a432016-02-09 14:00:40 +0100642
643 ret = usb_count_io_eps(iface);
644 if (ret < 0) {
645 ERROR("Invalid configuration of endpoints\n");
646 goto err_free_config_descriptor;
647 }
648
649 pdata->nb_io_endpoints = ret;
650
651 DEBUG("Found %hhu usable i/o endpoints\n", pdata->nb_io_endpoints);
652
653 if (pdata->nb_io_endpoints) {
654 pdata->io_endpoints = calloc(pdata->nb_io_endpoints,
655 sizeof(*pdata->io_endpoints));
656 if (!pdata->io_endpoints) {
657 ERROR("Unable to allocate endpoints\n");
658 ret = -ENOMEM;
659 goto err_free_config_descriptor;
660 }
661
662 for (i = 0; i < pdata->nb_io_endpoints; i++) {
663 struct iio_usb_io_endpoint *ep =
664 &pdata->io_endpoints[i];
665
666 /* +2: endpoints start at number 1, and we skip the
667 * endpoint #1 that we reserve for global operations */
668 ep->address = i + 2;
669
670 ep->lock = iio_mutex_create();
671 if (!ep->lock) {
672 ERROR("Unable to create mutex\n");
673 ret = -ENOMEM;
674 goto err_free_endpoints;
675 }
676 }
677 }
678
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200679 pdata->ctx = usb_ctx;
680 pdata->hdl = hdl;
Paul Cercueil7a988892015-12-03 12:39:20 +0100681 pdata->timeout_ms = DEFAULT_TIMEOUT_MS;
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200682
Lars-Peter Clausenf0d8ff42016-07-04 10:41:53 +0200683 pdata->io_ctx.ep = EP_OPS;
684
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100685 ret = usb_reset_pipes(hdl);
686 if (ret) {
687 iio_strerror(-ret, err_str, sizeof(err_str));
688 ERROR("Failed to reset pipes: %s\n", err_str);
Lars-Peter Clausen983e0522016-06-30 16:12:52 +0200689 goto err_free_endpoints;
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100690 }
691
692 ret = usb_open_pipe(hdl, EP_OPS);
693 if (ret) {
694 iio_strerror(-ret, err_str, sizeof(err_str));
695 ERROR("Failed to open control pipe: %s\n", err_str);
Lars-Peter Clausen983e0522016-06-30 16:12:52 +0200696 goto err_free_endpoints;
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100697 }
698
Lars-Peter Clausenf0d8ff42016-07-04 10:41:53 +0200699 ctx = iiod_client_create_context(pdata->iiod_client,
700 (uintptr_t) &pdata->io_ctx);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200701 if (!ctx)
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100702 goto err_reset_pipes;
Paul Cercueil4213a432016-02-09 14:00:40 +0100703
704 libusb_free_config_descriptor(conf_desc);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200705
706 ctx->name = "usb";
707 ctx->ops = &usb_ops;
708 ctx->pdata = pdata;
709
Paul Cercueil4acd6042015-11-30 12:10:43 +0100710 for (i = 0; i < ctx->nb_devices; i++) {
711 struct iio_device *dev = ctx->devices[i];
712
Lars-Peter Clausend1be8382016-02-24 11:13:45 +0100713 dev->pdata = zalloc(sizeof(*dev->pdata));
Paul Cercueil4acd6042015-11-30 12:10:43 +0100714 if (!dev->pdata) {
715 ERROR("Unable to allocate memory\n");
716 ret = -ENOMEM;
717 goto err_context_destroy;
718 }
Paul Cercueil4acd6042015-11-30 12:10:43 +0100719 }
720
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200721 return ctx;
722
723err_context_destroy:
724 iio_context_destroy(ctx);
725 errno = -ret;
726 return NULL;
727
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100728err_reset_pipes:
729 usb_reset_pipes(hdl); /* Close everything */
Paul Cercueil4213a432016-02-09 14:00:40 +0100730err_free_endpoints:
731 for (i = 0; i < pdata->nb_io_endpoints; i++)
732 if (pdata->io_endpoints[i].lock)
733 iio_mutex_destroy(pdata->io_endpoints[i].lock);
734 if (pdata->io_endpoints)
735 free(pdata->io_endpoints);
736err_free_config_descriptor:
737 libusb_free_config_descriptor(conf_desc);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200738err_libusb_close:
739 libusb_close(hdl);
740err_libusb_exit:
741 libusb_exit(usb_ctx);
742err_destroy_iiod_client:
743 iiod_client_destroy(pdata->iiod_client);
Paul Cercueil4213a432016-02-09 14:00:40 +0100744err_destroy_ep_mutex:
745 iio_mutex_destroy(pdata->ep_lock);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200746err_destroy_mutex:
747 iio_mutex_destroy(pdata->lock);
748err_free_pdata:
749 free(pdata);
750err_set_errno:
751 errno = -ret;
752 return NULL;
753}
Lars-Peter Clausen60f1c9a2016-02-22 13:20:40 +0100754
755struct iio_context * usb_create_context_from_uri(const char *uri)
756{
Paul Cercueil370bb362016-04-20 11:50:10 +0200757 long bus, address, interface;
758 char *end;
759 const char *ptr;
Lars-Peter Clausen60f1c9a2016-02-22 13:20:40 +0100760
761 if (strncmp(uri, "usb:", sizeof("usb:") - 1) != 0)
Paul Cercueil370bb362016-04-20 11:50:10 +0200762 goto err_bad_uri;
Lars-Peter Clausen60f1c9a2016-02-22 13:20:40 +0100763
Paul Cercueil370bb362016-04-20 11:50:10 +0200764 ptr = (const char *) ((uintptr_t) uri + sizeof("usb:") - 1);
765 if (!isdigit(*ptr))
766 goto err_bad_uri;
Lars-Peter Clausen60f1c9a2016-02-22 13:20:40 +0100767
Paul Cercueil370bb362016-04-20 11:50:10 +0200768 bus = strtol(ptr, &end, 10);
769 if (ptr == end || *end != '.')
770 goto err_bad_uri;
771
772 ptr = (const char *) ((uintptr_t) end + 1);
773 if (!isdigit(*ptr))
774 goto err_bad_uri;
775
776 address = strtol(ptr, &end, 10);
Paul Cercueild24f8ac2016-04-20 14:19:29 +0200777 if (ptr == end)
Paul Cercueil370bb362016-04-20 11:50:10 +0200778 goto err_bad_uri;
779
Paul Cercueild24f8ac2016-04-20 14:19:29 +0200780 if (*end == '\0') {
781 interface = 0;
782 } else if (*end == '.') {
783 ptr = (const char *) ((uintptr_t) end + 1);
784 if (!isdigit(*ptr))
785 goto err_bad_uri;
Paul Cercueil370bb362016-04-20 11:50:10 +0200786
Paul Cercueild24f8ac2016-04-20 14:19:29 +0200787 interface = strtol(ptr, &end, 10);
788 if (ptr == end || *end != '\0')
789 goto err_bad_uri;
790 } else {
Paul Cercueil370bb362016-04-20 11:50:10 +0200791 goto err_bad_uri;
Paul Cercueild24f8ac2016-04-20 14:19:29 +0200792 }
Paul Cercueil370bb362016-04-20 11:50:10 +0200793
794 if (bus < 0 || address < 0 || interface < 0)
795 goto err_bad_uri;
796
797 return usb_create_context((unsigned int) bus,
798 (unsigned int) address, (unsigned int) interface);
799
800err_bad_uri:
801 ERROR("Bad URI: \'%s\'\n", uri);
802 errno = -EINVAL;
803 return NULL;
Lars-Peter Clausen60f1c9a2016-02-22 13:20:40 +0100804}
Lars-Peter Clausen794ba032016-04-25 15:07:00 +0200805
806static int usb_fill_context_info(struct iio_context_info *info,
807 struct libusb_device *dev, struct libusb_device_handle *hdl,
808 unsigned int interface)
809{
810 struct libusb_device_descriptor desc;
811 char manufacturer[64], product[64];
812 char uri[sizeof("usb:127.255.255")];
813 char description[sizeof(manufacturer) + sizeof(product) +
814 sizeof("0000:0000 ( )")];
815 int ret;
816
817 libusb_get_device_descriptor(dev, &desc);
818
819 snprintf(uri, sizeof(uri), "usb:%d.%d.%u",
820 libusb_get_bus_number(dev), libusb_get_device_address(dev),
821 interface);
822
823 if (desc.iManufacturer == 0) {
824 manufacturer[0] = '\0';
825 } else {
826 ret = libusb_get_string_descriptor_ascii(hdl,
827 desc.iManufacturer,
828 (unsigned char *) manufacturer,
829 sizeof(manufacturer));
830 if (ret < 0)
831 manufacturer[0] = '\0';
832 }
833
834 if (desc.iProduct == 0) {
835 product[0] = '\0';
836 } else {
837 ret = libusb_get_string_descriptor_ascii(hdl,
838 desc.iProduct, (unsigned char *) product,
839 sizeof(product));
840 if (ret < 0)
841 product[0] = '\0';
842 }
843
844 snprintf(description, sizeof(description),
845 "%04x:%04x (%s %s)", desc.idVendor,
846 desc.idProduct, manufacturer, product);
847
848 info->uri = _strdup(uri);
849 if (!info->uri)
850 return -ENOMEM;
851
852 info->description = _strdup(description);
853 if (!info->description)
854 return -ENOMEM;
855
856 return 0;
857}
858
859struct iio_scan_backend_context {
860 libusb_context *ctx;
861};
862
863struct iio_scan_backend_context * usb_context_scan_init(void)
864{
865 struct iio_scan_backend_context *ctx;
866 int ret;
867
868 ctx = malloc(sizeof(*ctx));
869 if (!ctx) {
870 errno = ENOMEM;
871 return NULL;
872 }
873
874 ret = libusb_init(&ctx->ctx);
875 if (ret) {
876 free(ctx);
877 errno = (int) libusb_to_errno(ret);
878 return NULL;
879 }
880
881 return ctx;
882}
883
884void usb_context_scan_free(struct iio_scan_backend_context *ctx)
885{
886 libusb_exit(ctx->ctx);
887 free(ctx);
888}
889
890int usb_context_scan(struct iio_scan_backend_context *ctx,
891 struct iio_scan_result *scan_result)
892{
893 struct iio_context_info **info;
894 libusb_device **device_list;
895 unsigned int i;
896 int ret;
897
898 ret = libusb_get_device_list(ctx->ctx, &device_list);
899 if (ret < 0)
900 return -(int) libusb_to_errno(ret);
901
902 for (i = 0; device_list[i]; i++) {
903 struct libusb_device_handle *hdl;
904 struct libusb_device *dev = device_list[i];
905 unsigned int interface = 0;
906
907 ret = libusb_open(dev, &hdl);
908 if (ret)
909 continue;
910
911 if (!iio_usb_match_device(dev, hdl, &interface)) {
912 info = iio_scan_result_add(scan_result, 1);
913 if (!info)
914 ret = -ENOMEM;
915 else
916 ret = usb_fill_context_info(*info, dev, hdl,
917 interface);
918 }
919
920 libusb_close(hdl);
921 if (ret < 0)
922 goto cleanup_free_device_list;
923 }
924
925 ret = 0;
926
927cleanup_free_device_list:
928 libusb_free_device_list(device_list, true);
929 return ret;
930}