blob: 6ebfad31af8c7327f08406b6946709a96eae3460 [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
Paul Cercueil4213a432016-02-09 14:00:40 +010040struct iio_usb_io_endpoint {
41 unsigned char address;
42 bool in_use;
Paul Cercueil4acd6042015-11-30 12:10:43 +010043
Paul Cercueil4213a432016-02-09 14:00:40 +010044 struct iio_mutex *lock;
45};
Paul Cercueil4acd6042015-11-30 12:10:43 +010046
Paul Cercueile06f4ce2015-04-20 12:59:31 +020047struct iio_context_pdata {
48 libusb_context *ctx;
49 libusb_device_handle *hdl;
50
51 struct iiod_client *iiod_client;
52
53 /* Lock for non-streaming operations */
54 struct iio_mutex *lock;
Paul Cercueil4acd6042015-11-30 12:10:43 +010055
Paul Cercueil4213a432016-02-09 14:00:40 +010056 /* Lock for endpoint reservation */
57 struct iio_mutex *ep_lock;
58
59 struct iio_usb_io_endpoint *io_endpoints;
60 unsigned int nb_io_endpoints;
Paul Cercueil7a988892015-12-03 12:39:20 +010061
62 unsigned int timeout_ms;
Paul Cercueil4acd6042015-11-30 12:10:43 +010063};
64
65struct iio_device_pdata {
Paul Cercueil4acd6042015-11-30 12:10:43 +010066 struct iio_mutex *lock;
67
68 bool opened;
69 unsigned int ep;
Paul Cercueile06f4ce2015-04-20 12:59:31 +020070};
71
72static const unsigned int libusb_to_errno_codes[] = {
73 [- LIBUSB_ERROR_INVALID_PARAM] = EINVAL,
74 [- LIBUSB_ERROR_ACCESS] = EACCES,
75 [- LIBUSB_ERROR_NO_DEVICE] = ENODEV,
76 [- LIBUSB_ERROR_NOT_FOUND] = ENXIO,
77 [- LIBUSB_ERROR_BUSY] = EBUSY,
78 [- LIBUSB_ERROR_TIMEOUT] = ETIMEDOUT,
79 [- LIBUSB_ERROR_OVERFLOW] = EIO,
80 [- LIBUSB_ERROR_PIPE] = EPIPE,
81 [- LIBUSB_ERROR_INTERRUPTED] = EINTR,
82 [- LIBUSB_ERROR_NO_MEM] = ENOMEM,
83 [- LIBUSB_ERROR_NOT_SUPPORTED] = ENOSYS,
84};
85
86static unsigned int libusb_to_errno(int error)
87{
88 switch ((enum libusb_error) error) {
89 case LIBUSB_ERROR_INVALID_PARAM:
90 case LIBUSB_ERROR_ACCESS:
91 case LIBUSB_ERROR_NO_DEVICE:
92 case LIBUSB_ERROR_NOT_FOUND:
93 case LIBUSB_ERROR_BUSY:
94 case LIBUSB_ERROR_TIMEOUT:
95 case LIBUSB_ERROR_PIPE:
96 case LIBUSB_ERROR_INTERRUPTED:
97 case LIBUSB_ERROR_NO_MEM:
98 case LIBUSB_ERROR_NOT_SUPPORTED:
99 return libusb_to_errno_codes[- (int) error];
100 case LIBUSB_ERROR_IO:
101 case LIBUSB_ERROR_OTHER:
102 case LIBUSB_ERROR_OVERFLOW:
103 default:
104 return EIO;
105 }
106}
107
Paul Cercueilc11737c2015-11-26 14:44:46 +0100108static int usb_get_version(const struct iio_context *ctx,
109 unsigned int *major, unsigned int *minor, char git_tag[8])
110{
111 return iiod_client_get_version(ctx->pdata->iiod_client,
112 EP_OPS, major, minor, git_tag);
113}
114
Paul Cercueila5e4aa42016-02-09 13:31:01 +0100115static unsigned int usb_calculate_remote_timeout(unsigned int timeout)
116{
117 /* XXX(pcercuei): We currently hardcode timeout / 2 for the backend used
118 * by the remote. Is there something better to do here? */
119 return timeout / 2;
120}
121
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100122#define USB_PIPE_CTRL_TIMEOUT 200 /* These should not take long */
123
124#define IIO_USD_CMD_RESET_PIPES 0
125#define IIO_USD_CMD_OPEN_PIPE 1
126#define IIO_USD_CMD_CLOSE_PIPE 2
127
128static int usb_reset_pipes(libusb_device_handle *hdl)
129{
130 int ret;
131
132 ret = libusb_control_transfer(hdl, LIBUSB_REQUEST_TYPE_VENDOR |
133 LIBUSB_RECIPIENT_INTERFACE, IIO_USD_CMD_RESET_PIPES,
134 0, 0, NULL, 0, USB_PIPE_CTRL_TIMEOUT);
135 if (ret < 0)
Paul Cercueil67482202016-04-21 16:40:02 +0200136 return -(int) libusb_to_errno(ret);
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100137 return 0;
138}
139
140static int usb_open_pipe(libusb_device_handle *hdl, unsigned int ep)
141{
142 int ret;
143
144 ret = libusb_control_transfer(hdl, LIBUSB_REQUEST_TYPE_VENDOR |
145 LIBUSB_RECIPIENT_INTERFACE, IIO_USD_CMD_OPEN_PIPE,
146 ep - 1, 0, NULL, 0, USB_PIPE_CTRL_TIMEOUT);
147 if (ret < 0)
Paul Cercueil67482202016-04-21 16:40:02 +0200148 return -(int) libusb_to_errno(ret);
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100149 return 0;
150}
151
152static int usb_close_pipe(libusb_device_handle *hdl, unsigned int ep)
153{
154 int ret;
155
156 ret = libusb_control_transfer(hdl, LIBUSB_REQUEST_TYPE_VENDOR |
157 LIBUSB_RECIPIENT_INTERFACE, IIO_USD_CMD_CLOSE_PIPE,
158 ep - 1, 0, NULL, 0, USB_PIPE_CTRL_TIMEOUT);
159 if (ret < 0)
Paul Cercueil67482202016-04-21 16:40:02 +0200160 return -(int) libusb_to_errno(ret);
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100161 return 0;
162}
163
Paul Cercueil4213a432016-02-09 14:00:40 +0100164static int usb_reserve_ep_unlocked(const struct iio_device *dev)
165{
166 struct iio_context_pdata *pdata = dev->ctx->pdata;
167 unsigned int i;
168
169 for (i = 0; i < pdata->nb_io_endpoints; i++) {
170 struct iio_usb_io_endpoint *ep = &pdata->io_endpoints[i];
171
172 if (!ep->in_use) {
173 ep->in_use = true;
174
175 dev->pdata->ep = ep->address;
176 dev->pdata->lock = ep->lock;
177 return 0;
178 }
179 }
180
181 return -EBUSY;
182}
183
184static void usb_free_ep_unlocked(const struct iio_device *dev)
185{
186 struct iio_context_pdata *pdata = dev->ctx->pdata;
187 unsigned int i;
188
189 for (i = 0; i < pdata->nb_io_endpoints; i++) {
190 struct iio_usb_io_endpoint *ep = &pdata->io_endpoints[i];
191
192 if (ep->lock == dev->pdata->lock) {
193 ep->in_use = false;
194 return;
195 }
196 }
197}
198
Paul Cercueil4acd6042015-11-30 12:10:43 +0100199static int usb_open(const struct iio_device *dev,
200 size_t samples_count, bool cyclic)
201{
Paul Cercueila5e4aa42016-02-09 13:31:01 +0100202 struct iio_context_pdata *ctx_pdata = dev->ctx->pdata;
Paul Cercueil4acd6042015-11-30 12:10:43 +0100203 struct iio_device_pdata *pdata = dev->pdata;
204 int ret = -EBUSY;
205
Paul Cercueil4213a432016-02-09 14:00:40 +0100206 iio_mutex_lock(ctx_pdata->ep_lock);
Paul Cercueil4acd6042015-11-30 12:10:43 +0100207
Paul Cercueila5e4aa42016-02-09 13:31:01 +0100208 if (pdata->opened)
209 goto out_unlock;
210
Paul Cercueil4213a432016-02-09 14:00:40 +0100211 ret = usb_reserve_ep_unlocked(dev);
212 if (ret)
213 goto out_unlock;
214
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100215 ret = usb_open_pipe(ctx_pdata->hdl, pdata->ep);
216 if (ret) {
217 char err_str[1024];
218
219 iio_strerror(-ret, err_str, sizeof(err_str));
220 ERROR("Failed to open pipe: %s\n", err_str);
221 usb_free_ep_unlocked(dev);
222 goto out_unlock;
223 }
224
Paul Cercueil4213a432016-02-09 14:00:40 +0100225 iio_mutex_lock(pdata->lock);
226
Paul Cercueila5e4aa42016-02-09 13:31:01 +0100227 ret = iiod_client_open_unlocked(ctx_pdata->iiod_client,
228 pdata->ep, dev, samples_count, cyclic);
229
230 if (!ret) {
231 unsigned int remote_timeout =
232 usb_calculate_remote_timeout(ctx_pdata->timeout_ms);
233
234 ret = iiod_client_set_timeout(ctx_pdata->iiod_client,
235 pdata->ep, remote_timeout);
Paul Cercueil4acd6042015-11-30 12:10:43 +0100236 }
237
Paul Cercueila5e4aa42016-02-09 13:31:01 +0100238 pdata->opened = !ret;
239
Paul Cercueil4acd6042015-11-30 12:10:43 +0100240 iio_mutex_unlock(pdata->lock);
Paul Cercueil4213a432016-02-09 14:00:40 +0100241
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100242 if (ret) {
243 usb_close_pipe(ctx_pdata->hdl, pdata->ep);
Paul Cercueil4213a432016-02-09 14:00:40 +0100244 usb_free_ep_unlocked(dev);
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100245 }
Paul Cercueil4213a432016-02-09 14:00:40 +0100246
247out_unlock:
248 iio_mutex_unlock(ctx_pdata->ep_lock);
Paul Cercueil4acd6042015-11-30 12:10:43 +0100249 return ret;
250}
251
252static int usb_close(const struct iio_device *dev)
253{
Paul Cercueil4213a432016-02-09 14:00:40 +0100254 struct iio_context_pdata *ctx_pdata = dev->ctx->pdata;
Paul Cercueil4acd6042015-11-30 12:10:43 +0100255 struct iio_device_pdata *pdata = dev->pdata;
256 int ret = -EBADF;
257
Paul Cercueil4213a432016-02-09 14:00:40 +0100258 iio_mutex_lock(ctx_pdata->ep_lock);
259 if (!pdata->opened)
260 goto out_unlock;
Paul Cercueil4acd6042015-11-30 12:10:43 +0100261
Paul Cercueil4213a432016-02-09 14:00:40 +0100262 iio_mutex_lock(pdata->lock);
263 ret = iiod_client_close_unlocked(ctx_pdata->iiod_client,
264 pdata->ep, dev);
265 pdata->opened = false;
266
Paul Cercueil31492b32016-02-22 17:40:20 +0100267 iio_mutex_unlock(pdata->lock);
268
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100269 usb_close_pipe(ctx_pdata->hdl, pdata->ep);
270
Paul Cercueil4213a432016-02-09 14:00:40 +0100271 usb_free_ep_unlocked(dev);
272
273out_unlock:
274 iio_mutex_unlock(ctx_pdata->ep_lock);
Paul Cercueil4acd6042015-11-30 12:10:43 +0100275 return ret;
276}
277
Paul Cercueil04841832015-12-02 11:58:33 +0100278static ssize_t usb_read(const struct iio_device *dev, void *dst, size_t len,
279 uint32_t *mask, size_t words)
280{
281 struct iio_device_pdata *pdata = dev->pdata;
282 ssize_t ret;
283
284 iio_mutex_lock(pdata->lock);
285 ret = iiod_client_read_unlocked(dev->ctx->pdata->iiod_client,
286 pdata->ep, dev, dst, len, mask, words);
287 iio_mutex_unlock(pdata->lock);
288
289 return ret;
290}
291
Paul Cercueile78e9882015-12-04 16:31:10 +0100292static ssize_t usb_write(const struct iio_device *dev,
293 const void *src, size_t len)
294{
295 struct iio_device_pdata *pdata = dev->pdata;
296 ssize_t ret;
297
298 iio_mutex_lock(pdata->lock);
299 ret = iiod_client_write_unlocked(dev->ctx->pdata->iiod_client,
300 pdata->ep, dev, src, len);
301 iio_mutex_unlock(pdata->lock);
302
303 return ret;
304}
305
Paul Cercueil3069e3b2015-11-26 16:01:25 +0100306static ssize_t usb_read_dev_attr(const struct iio_device *dev,
307 const char *attr, char *dst, size_t len, bool is_debug)
308{
309 struct iio_context_pdata *pdata = dev->ctx->pdata;
310
311 return iiod_client_read_attr(pdata->iiod_client, EP_OPS, dev,
312 NULL, attr, dst, len, is_debug);
313}
314
315static ssize_t usb_write_dev_attr(const struct iio_device *dev,
316 const char *attr, const char *src, size_t len, bool is_debug)
317{
318 struct iio_context_pdata *pdata = dev->ctx->pdata;
319
320 return iiod_client_write_attr(pdata->iiod_client, EP_OPS, dev,
321 NULL, attr, src, len, is_debug);
322}
323
324static ssize_t usb_read_chn_attr(const struct iio_channel *chn,
325 const char *attr, char *dst, size_t len)
326{
327 struct iio_context_pdata *pdata = chn->dev->ctx->pdata;
328
329 return iiod_client_read_attr(pdata->iiod_client, EP_OPS, chn->dev,
330 chn, attr, dst, len, false);
331}
332
333static ssize_t usb_write_chn_attr(const struct iio_channel *chn,
334 const char *attr, const char *src, size_t len)
335{
336 struct iio_context_pdata *pdata = chn->dev->ctx->pdata;
337
338 return iiod_client_write_attr(pdata->iiod_client, EP_OPS, chn->dev,
339 chn, attr, src, len, false);
340}
341
Paul Cercueil6c8337e2015-11-27 11:13:09 +0100342static int usb_set_kernel_buffers_count(const struct iio_device *dev,
343 unsigned int nb_blocks)
344{
345 struct iio_context_pdata *pdata = dev->ctx->pdata;
346
347 return iiod_client_set_kernel_buffers_count(pdata->iiod_client,
348 EP_OPS, dev, nb_blocks);
349}
350
Paul Cercueil7a988892015-12-03 12:39:20 +0100351static int usb_set_timeout(struct iio_context *ctx, unsigned int timeout)
352{
353 struct iio_context_pdata *pdata = ctx->pdata;
354 unsigned int remote_timeout = usb_calculate_remote_timeout(timeout);
355 int ret;
356
357 ret = iiod_client_set_timeout(pdata->iiod_client,
358 EP_OPS, remote_timeout);
Paul Cercueila5e4aa42016-02-09 13:31:01 +0100359 if (!ret)
360 pdata->timeout_ms = timeout;
Paul Cercueil7a988892015-12-03 12:39:20 +0100361
Paul Cercueil7a988892015-12-03 12:39:20 +0100362 return ret;
363}
364
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200365static void usb_shutdown(struct iio_context *ctx)
366{
Paul Cercueil4213a432016-02-09 14:00:40 +0100367 unsigned int i;
368
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200369 iio_mutex_destroy(ctx->pdata->lock);
Paul Cercueil4213a432016-02-09 14:00:40 +0100370 iio_mutex_destroy(ctx->pdata->ep_lock);
371
372 for (i = 0; i < ctx->pdata->nb_io_endpoints; i++)
373 if (ctx->pdata->io_endpoints[i].lock)
374 iio_mutex_destroy(ctx->pdata->io_endpoints[i].lock);
375 if (ctx->pdata->io_endpoints)
376 free(ctx->pdata->io_endpoints);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200377
Lars-Peter Clausen33c64312016-02-19 13:32:08 +0100378 for (i = 0; i < ctx->nb_devices; i++) {
379 struct iio_device *dev = ctx->devices[i];
380
381 free(dev->pdata);
382 }
383
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200384 iiod_client_destroy(ctx->pdata->iiod_client);
385
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100386 usb_reset_pipes(ctx->pdata->hdl); /* Close everything */
387
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200388 libusb_close(ctx->pdata->hdl);
389 libusb_exit(ctx->pdata->ctx);
Lars-Peter Clausen33c64312016-02-19 13:32:08 +0100390 free(ctx->pdata);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200391}
392
393static const struct iio_backend_ops usb_ops = {
Paul Cercueilc11737c2015-11-26 14:44:46 +0100394 .get_version = usb_get_version,
Paul Cercueil4acd6042015-11-30 12:10:43 +0100395 .open = usb_open,
396 .close = usb_close,
Paul Cercueil04841832015-12-02 11:58:33 +0100397 .read = usb_read,
Paul Cercueile78e9882015-12-04 16:31:10 +0100398 .write = usb_write,
Paul Cercueil3069e3b2015-11-26 16:01:25 +0100399 .read_device_attr = usb_read_dev_attr,
400 .read_channel_attr = usb_read_chn_attr,
401 .write_device_attr = usb_write_dev_attr,
402 .write_channel_attr = usb_write_chn_attr,
Paul Cercueil6c8337e2015-11-27 11:13:09 +0100403 .set_kernel_buffers_count = usb_set_kernel_buffers_count,
Paul Cercueil7a988892015-12-03 12:39:20 +0100404 .set_timeout = usb_set_timeout,
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200405 .shutdown = usb_shutdown,
406};
407
408static ssize_t write_data_sync(struct iio_context_pdata *pdata,
409 int ep, const char *data, size_t len)
410{
411 int transferred, ret;
412
413 ret = libusb_bulk_transfer(pdata->hdl, ep | LIBUSB_ENDPOINT_OUT,
Lars-Peter Clausen8ba0d5b2016-02-17 11:30:23 +0100414 (unsigned char *) data, (int) len,
Paul Cercueile10d19a2016-02-09 13:30:12 +0100415 &transferred, pdata->timeout_ms);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200416 if (ret)
Paul Cercueil463fc782015-12-04 16:04:12 +0100417 return -(int) libusb_to_errno(ret);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200418 else
Lars-Peter Clausen8ba0d5b2016-02-17 11:30:23 +0100419 return (size_t) transferred != len ? -EIO : (ssize_t) len;
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200420}
421
422static ssize_t read_data_sync(struct iio_context_pdata *pdata,
423 int ep, char *buf, size_t len)
424{
425 int transferred, ret;
426
427 ret = libusb_bulk_transfer(pdata->hdl, ep | LIBUSB_ENDPOINT_IN,
Lars-Peter Clausen8ba0d5b2016-02-17 11:30:23 +0100428 (unsigned char *) buf, (int) len, &transferred, pdata->timeout_ms);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200429 if (ret)
Paul Cercueil463fc782015-12-04 16:04:12 +0100430 return -(int) libusb_to_errno(ret);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200431 else
432 return transferred;
433}
434
Lars-Peter Clausen09a59d72016-02-03 15:27:04 +0100435static const struct iiod_client_ops usb_iiod_client_ops = {
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200436 .write = write_data_sync,
437 .read = read_data_sync,
438 .read_line = read_data_sync,
439};
440
Paul Cercueil4213a432016-02-09 14:00:40 +0100441static int usb_count_io_eps(const struct libusb_interface_descriptor *iface)
442{
443 unsigned int eps = iface->bNumEndpoints;
444 unsigned int i, curr;
445
446 /* Check that for a number of endpoints X provided by the interface, we
447 * have the input and output endpoints in the address range [1, ... X/2]
448 * and that each input endpoint has a corresponding output endpoint at
449 * the same address. */
450
451 if (eps < 2 || eps % 2)
452 return -EINVAL;
453
454 for (curr = 1; curr < (eps / 2) + 1; curr++) {
455 bool found_in = false, found_out = false;
456
457 for (i = 0; !found_in && i < eps; i++)
458 found_in = iface->endpoint[i].bEndpointAddress ==
Paul Cercueil6733c4e2016-02-12 15:09:35 +0100459 (LIBUSB_ENDPOINT_IN | curr);
Paul Cercueil4213a432016-02-09 14:00:40 +0100460 if (!found_in)
461 return -EINVAL;
462
463 for (i = 0; !found_out && i < eps; i++)
464 found_out = iface->endpoint[i].bEndpointAddress ==
Paul Cercueil6733c4e2016-02-12 15:09:35 +0100465 (LIBUSB_ENDPOINT_OUT | curr);
Paul Cercueil4213a432016-02-09 14:00:40 +0100466 if (!found_out)
467 return -EINVAL;
468 }
469
470 /* -1: we reserve the first I/O endpoint couple for global operations */
471 return (int) curr - 1;
472}
473
Lars-Peter Clausen7a8e6b52016-02-22 13:25:12 +0100474struct iio_context * usb_create_context(unsigned int bus,
475 unsigned int address, unsigned int interface)
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200476{
477 libusb_context *usb_ctx;
478 libusb_device_handle *hdl;
Paul Cercueil4213a432016-02-09 14:00:40 +0100479 const struct libusb_interface_descriptor *iface;
Lars-Peter Clausen7a8e6b52016-02-22 13:25:12 +0100480 libusb_device *dev, *usb_dev;
Paul Cercueil4213a432016-02-09 14:00:40 +0100481 struct libusb_config_descriptor *conf_desc;
Lars-Peter Clausen7a8e6b52016-02-22 13:25:12 +0100482 libusb_device **device_list;
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200483 struct iio_context *ctx;
484 struct iio_context_pdata *pdata;
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100485 char err_str[1024];
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200486 unsigned int i;
487 int ret;
488
Lars-Peter Clausend1be8382016-02-24 11:13:45 +0100489 pdata = zalloc(sizeof(*pdata));
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200490 if (!pdata) {
491 ERROR("Unable to allocate pdata\n");
492 ret = -ENOMEM;
493 goto err_set_errno;
494 }
495
496 pdata->lock = iio_mutex_create();
497 if (!pdata->lock) {
498 ERROR("Unable to create mutex\n");
499 ret = -ENOMEM;
500 goto err_free_pdata;
501 }
502
Paul Cercueil4213a432016-02-09 14:00:40 +0100503 pdata->ep_lock = iio_mutex_create();
504 if (!pdata->ep_lock) {
Paul Cercueil4acd6042015-11-30 12:10:43 +0100505 ERROR("Unable to create mutex\n");
506 ret = -ENOMEM;
507 goto err_destroy_mutex;
508 }
509
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200510 pdata->iiod_client = iiod_client_new(pdata, pdata->lock,
511 &usb_iiod_client_ops);
512 if (!pdata->iiod_client) {
513 ERROR("Unable to create IIOD client\n");
514 ret = -errno;
Paul Cercueil4213a432016-02-09 14:00:40 +0100515 goto err_destroy_ep_mutex;
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200516 }
517
518 ret = libusb_init(&usb_ctx);
519 if (ret) {
Paul Cercueil463fc782015-12-04 16:04:12 +0100520 ret = -(int) libusb_to_errno(ret);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200521 ERROR("Unable to init libusb: %i\n", ret);
Paul Cercueil4acd6042015-11-30 12:10:43 +0100522 goto err_destroy_iiod_client;
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200523 }
524
Lars-Peter Clausen7a8e6b52016-02-22 13:25:12 +0100525 libusb_get_device_list(usb_ctx, &device_list);
526
527 usb_dev = NULL;
528
529 for (i = 0; device_list[i]; i++) {
530 dev = device_list[i];
531
532 if (bus == libusb_get_bus_number(dev) &&
533 address == libusb_get_device_address(dev)) {
534 usb_dev = dev;
535 libusb_ref_device(usb_dev);
536 break;
537 }
538 }
539
540 libusb_free_device_list(device_list, true);
541
542 if (!usb_dev)
543 goto err_libusb_exit;
544
545 ret = libusb_open(usb_dev, &hdl);
546 libusb_unref_device(usb_dev); /* Open gets us a extra ref */
547 if (ret) {
548 ret = -(int) libusb_to_errno(ret);
549 ERROR("Unable to open device\n");
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200550 goto err_libusb_exit;
551 }
552
553 libusb_set_auto_detach_kernel_driver(hdl, true);
554
Lars-Peter Clausen7a8e6b52016-02-22 13:25:12 +0100555 ret = libusb_claim_interface(hdl, interface);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200556 if (ret) {
Paul Cercueil463fc782015-12-04 16:04:12 +0100557 ret = -(int) libusb_to_errno(ret);
Lars-Peter Clausen7a8e6b52016-02-22 13:25:12 +0100558 ERROR("Unable to claim interface %u: %i\n", interface, ret);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200559 goto err_libusb_close;
560 }
561
Paul Cercueil4213a432016-02-09 14:00:40 +0100562 ret = libusb_get_active_config_descriptor(usb_dev, &conf_desc);
563 if (ret) {
564 ret = -(int) libusb_to_errno(ret);
565 ERROR("Unable to get config descriptor: %i\n", ret);
566 goto err_libusb_close;
567 }
568
Lars-Peter Clausen7a8e6b52016-02-22 13:25:12 +0100569 iface = &conf_desc->interface[interface].altsetting[0];
Paul Cercueil4213a432016-02-09 14:00:40 +0100570
571 ret = usb_count_io_eps(iface);
572 if (ret < 0) {
573 ERROR("Invalid configuration of endpoints\n");
574 goto err_free_config_descriptor;
575 }
576
577 pdata->nb_io_endpoints = ret;
578
579 DEBUG("Found %hhu usable i/o endpoints\n", pdata->nb_io_endpoints);
580
581 if (pdata->nb_io_endpoints) {
582 pdata->io_endpoints = calloc(pdata->nb_io_endpoints,
583 sizeof(*pdata->io_endpoints));
584 if (!pdata->io_endpoints) {
585 ERROR("Unable to allocate endpoints\n");
586 ret = -ENOMEM;
587 goto err_free_config_descriptor;
588 }
589
590 for (i = 0; i < pdata->nb_io_endpoints; i++) {
591 struct iio_usb_io_endpoint *ep =
592 &pdata->io_endpoints[i];
593
594 /* +2: endpoints start at number 1, and we skip the
595 * endpoint #1 that we reserve for global operations */
596 ep->address = i + 2;
597
598 ep->lock = iio_mutex_create();
599 if (!ep->lock) {
600 ERROR("Unable to create mutex\n");
601 ret = -ENOMEM;
602 goto err_free_endpoints;
603 }
604 }
605 }
606
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200607 pdata->ctx = usb_ctx;
608 pdata->hdl = hdl;
Paul Cercueil7a988892015-12-03 12:39:20 +0100609 pdata->timeout_ms = DEFAULT_TIMEOUT_MS;
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200610
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100611 ret = usb_reset_pipes(hdl);
612 if (ret) {
613 iio_strerror(-ret, err_str, sizeof(err_str));
614 ERROR("Failed to reset pipes: %s\n", err_str);
615 return NULL;
616 }
617
618 ret = usb_open_pipe(hdl, EP_OPS);
619 if (ret) {
620 iio_strerror(-ret, err_str, sizeof(err_str));
621 ERROR("Failed to open control pipe: %s\n", err_str);
622 return NULL;
623 }
624
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200625 ctx = iiod_client_create_context(pdata->iiod_client, EP_OPS);
626 if (!ctx)
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100627 goto err_reset_pipes;
Paul Cercueil4213a432016-02-09 14:00:40 +0100628
629 libusb_free_config_descriptor(conf_desc);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200630
631 ctx->name = "usb";
632 ctx->ops = &usb_ops;
633 ctx->pdata = pdata;
634
Paul Cercueil4acd6042015-11-30 12:10:43 +0100635 for (i = 0; i < ctx->nb_devices; i++) {
636 struct iio_device *dev = ctx->devices[i];
637
Lars-Peter Clausend1be8382016-02-24 11:13:45 +0100638 dev->pdata = zalloc(sizeof(*dev->pdata));
Paul Cercueil4acd6042015-11-30 12:10:43 +0100639 if (!dev->pdata) {
640 ERROR("Unable to allocate memory\n");
641 ret = -ENOMEM;
642 goto err_context_destroy;
643 }
Paul Cercueil4acd6042015-11-30 12:10:43 +0100644 }
645
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200646 return ctx;
647
648err_context_destroy:
649 iio_context_destroy(ctx);
650 errno = -ret;
651 return NULL;
652
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100653err_reset_pipes:
654 usb_reset_pipes(hdl); /* Close everything */
Paul Cercueil4213a432016-02-09 14:00:40 +0100655err_free_endpoints:
656 for (i = 0; i < pdata->nb_io_endpoints; i++)
657 if (pdata->io_endpoints[i].lock)
658 iio_mutex_destroy(pdata->io_endpoints[i].lock);
659 if (pdata->io_endpoints)
660 free(pdata->io_endpoints);
661err_free_config_descriptor:
662 libusb_free_config_descriptor(conf_desc);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200663err_libusb_close:
664 libusb_close(hdl);
665err_libusb_exit:
666 libusb_exit(usb_ctx);
667err_destroy_iiod_client:
668 iiod_client_destroy(pdata->iiod_client);
Paul Cercueil4213a432016-02-09 14:00:40 +0100669err_destroy_ep_mutex:
670 iio_mutex_destroy(pdata->ep_lock);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200671err_destroy_mutex:
672 iio_mutex_destroy(pdata->lock);
673err_free_pdata:
674 free(pdata);
675err_set_errno:
676 errno = -ret;
677 return NULL;
678}
Lars-Peter Clausen60f1c9a2016-02-22 13:20:40 +0100679
680struct iio_context * usb_create_context_from_uri(const char *uri)
681{
Paul Cercueil370bb362016-04-20 11:50:10 +0200682 long bus, address, interface;
683 char *end;
684 const char *ptr;
Lars-Peter Clausen60f1c9a2016-02-22 13:20:40 +0100685
686 if (strncmp(uri, "usb:", sizeof("usb:") - 1) != 0)
Paul Cercueil370bb362016-04-20 11:50:10 +0200687 goto err_bad_uri;
Lars-Peter Clausen60f1c9a2016-02-22 13:20:40 +0100688
Paul Cercueil370bb362016-04-20 11:50:10 +0200689 ptr = (const char *) ((uintptr_t) uri + sizeof("usb:") - 1);
690 if (!isdigit(*ptr))
691 goto err_bad_uri;
Lars-Peter Clausen60f1c9a2016-02-22 13:20:40 +0100692
Paul Cercueil370bb362016-04-20 11:50:10 +0200693 bus = strtol(ptr, &end, 10);
694 if (ptr == end || *end != '.')
695 goto err_bad_uri;
696
697 ptr = (const char *) ((uintptr_t) end + 1);
698 if (!isdigit(*ptr))
699 goto err_bad_uri;
700
701 address = strtol(ptr, &end, 10);
702 if (ptr == end || *end != '.')
703 goto err_bad_uri;
704
705 ptr = (const char *) ((uintptr_t) end + 1);
706 if (!isdigit(*ptr))
707 goto err_bad_uri;
708
709 interface = strtol(ptr, &end, 10);
710 if (ptr == end || *end != '\0')
711 goto err_bad_uri;
712
713 if (bus < 0 || address < 0 || interface < 0)
714 goto err_bad_uri;
715
716 return usb_create_context((unsigned int) bus,
717 (unsigned int) address, (unsigned int) interface);
718
719err_bad_uri:
720 ERROR("Bad URI: \'%s\'\n", uri);
721 errno = -EINVAL;
722 return NULL;
Lars-Peter Clausen60f1c9a2016-02-22 13:20:40 +0100723}