blob: 549f7a3d379084993738d0685238d0ab8d8a5c19 [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
23#include <errno.h>
24#include <libusb-1.0/libusb.h>
25#include <stdbool.h>
26#include <string.h>
27
Paul Cercueil3c1e7852015-12-04 16:14:28 +010028#ifdef ERROR
29#undef ERROR
30#endif
31
32#include "debug.h"
33
Paul Cercueile06f4ce2015-04-20 12:59:31 +020034#define DEFAULT_TIMEOUT_MS 5000
35
36/* Endpoint for non-streaming operations */
37#define EP_OPS 1
38
Paul Cercueil4213a432016-02-09 14:00:40 +010039struct iio_usb_io_endpoint {
40 unsigned char address;
41 bool in_use;
Paul Cercueil4acd6042015-11-30 12:10:43 +010042
Paul Cercueil4213a432016-02-09 14:00:40 +010043 struct iio_mutex *lock;
44};
Paul Cercueil4acd6042015-11-30 12:10:43 +010045
Paul Cercueile06f4ce2015-04-20 12:59:31 +020046struct iio_context_pdata {
47 libusb_context *ctx;
48 libusb_device_handle *hdl;
49
50 struct iiod_client *iiod_client;
51
52 /* Lock for non-streaming operations */
53 struct iio_mutex *lock;
Paul Cercueil4acd6042015-11-30 12:10:43 +010054
Paul Cercueil4213a432016-02-09 14:00:40 +010055 /* Lock for endpoint reservation */
56 struct iio_mutex *ep_lock;
57
58 struct iio_usb_io_endpoint *io_endpoints;
59 unsigned int nb_io_endpoints;
Paul Cercueil7a988892015-12-03 12:39:20 +010060
61 unsigned int timeout_ms;
Paul Cercueil4acd6042015-11-30 12:10:43 +010062};
63
64struct iio_device_pdata {
Paul Cercueil4acd6042015-11-30 12:10:43 +010065 struct iio_mutex *lock;
66
67 bool opened;
68 unsigned int ep;
Paul Cercueile06f4ce2015-04-20 12:59:31 +020069};
70
71static const unsigned int libusb_to_errno_codes[] = {
72 [- LIBUSB_ERROR_INVALID_PARAM] = EINVAL,
73 [- LIBUSB_ERROR_ACCESS] = EACCES,
74 [- LIBUSB_ERROR_NO_DEVICE] = ENODEV,
75 [- LIBUSB_ERROR_NOT_FOUND] = ENXIO,
76 [- LIBUSB_ERROR_BUSY] = EBUSY,
77 [- LIBUSB_ERROR_TIMEOUT] = ETIMEDOUT,
78 [- LIBUSB_ERROR_OVERFLOW] = EIO,
79 [- LIBUSB_ERROR_PIPE] = EPIPE,
80 [- LIBUSB_ERROR_INTERRUPTED] = EINTR,
81 [- LIBUSB_ERROR_NO_MEM] = ENOMEM,
82 [- LIBUSB_ERROR_NOT_SUPPORTED] = ENOSYS,
83};
84
85static unsigned int libusb_to_errno(int error)
86{
87 switch ((enum libusb_error) error) {
88 case LIBUSB_ERROR_INVALID_PARAM:
89 case LIBUSB_ERROR_ACCESS:
90 case LIBUSB_ERROR_NO_DEVICE:
91 case LIBUSB_ERROR_NOT_FOUND:
92 case LIBUSB_ERROR_BUSY:
93 case LIBUSB_ERROR_TIMEOUT:
94 case LIBUSB_ERROR_PIPE:
95 case LIBUSB_ERROR_INTERRUPTED:
96 case LIBUSB_ERROR_NO_MEM:
97 case LIBUSB_ERROR_NOT_SUPPORTED:
98 return libusb_to_errno_codes[- (int) error];
99 case LIBUSB_ERROR_IO:
100 case LIBUSB_ERROR_OTHER:
101 case LIBUSB_ERROR_OVERFLOW:
102 default:
103 return EIO;
104 }
105}
106
Paul Cercueilc11737c2015-11-26 14:44:46 +0100107static int usb_get_version(const struct iio_context *ctx,
108 unsigned int *major, unsigned int *minor, char git_tag[8])
109{
110 return iiod_client_get_version(ctx->pdata->iiod_client,
111 EP_OPS, major, minor, git_tag);
112}
113
Paul Cercueila5e4aa42016-02-09 13:31:01 +0100114static unsigned int usb_calculate_remote_timeout(unsigned int timeout)
115{
116 /* XXX(pcercuei): We currently hardcode timeout / 2 for the backend used
117 * by the remote. Is there something better to do here? */
118 return timeout / 2;
119}
120
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100121#define USB_PIPE_CTRL_TIMEOUT 200 /* These should not take long */
122
123#define IIO_USD_CMD_RESET_PIPES 0
124#define IIO_USD_CMD_OPEN_PIPE 1
125#define IIO_USD_CMD_CLOSE_PIPE 2
126
127static int usb_reset_pipes(libusb_device_handle *hdl)
128{
129 int ret;
130
131 ret = libusb_control_transfer(hdl, LIBUSB_REQUEST_TYPE_VENDOR |
132 LIBUSB_RECIPIENT_INTERFACE, IIO_USD_CMD_RESET_PIPES,
133 0, 0, NULL, 0, USB_PIPE_CTRL_TIMEOUT);
134 if (ret < 0)
Paul Cercueil67482202016-04-21 16:40:02 +0200135 return -(int) libusb_to_errno(ret);
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100136 return 0;
137}
138
139static int usb_open_pipe(libusb_device_handle *hdl, unsigned int ep)
140{
141 int ret;
142
143 ret = libusb_control_transfer(hdl, LIBUSB_REQUEST_TYPE_VENDOR |
144 LIBUSB_RECIPIENT_INTERFACE, IIO_USD_CMD_OPEN_PIPE,
145 ep - 1, 0, NULL, 0, USB_PIPE_CTRL_TIMEOUT);
146 if (ret < 0)
Paul Cercueil67482202016-04-21 16:40:02 +0200147 return -(int) libusb_to_errno(ret);
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100148 return 0;
149}
150
151static int usb_close_pipe(libusb_device_handle *hdl, unsigned int ep)
152{
153 int ret;
154
155 ret = libusb_control_transfer(hdl, LIBUSB_REQUEST_TYPE_VENDOR |
156 LIBUSB_RECIPIENT_INTERFACE, IIO_USD_CMD_CLOSE_PIPE,
157 ep - 1, 0, NULL, 0, USB_PIPE_CTRL_TIMEOUT);
158 if (ret < 0)
Paul Cercueil67482202016-04-21 16:40:02 +0200159 return -(int) libusb_to_errno(ret);
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100160 return 0;
161}
162
Paul Cercueil4213a432016-02-09 14:00:40 +0100163static int usb_reserve_ep_unlocked(const struct iio_device *dev)
164{
165 struct iio_context_pdata *pdata = dev->ctx->pdata;
166 unsigned int i;
167
168 for (i = 0; i < pdata->nb_io_endpoints; i++) {
169 struct iio_usb_io_endpoint *ep = &pdata->io_endpoints[i];
170
171 if (!ep->in_use) {
172 ep->in_use = true;
173
174 dev->pdata->ep = ep->address;
175 dev->pdata->lock = ep->lock;
176 return 0;
177 }
178 }
179
180 return -EBUSY;
181}
182
183static void usb_free_ep_unlocked(const struct iio_device *dev)
184{
185 struct iio_context_pdata *pdata = dev->ctx->pdata;
186 unsigned int i;
187
188 for (i = 0; i < pdata->nb_io_endpoints; i++) {
189 struct iio_usb_io_endpoint *ep = &pdata->io_endpoints[i];
190
191 if (ep->lock == dev->pdata->lock) {
192 ep->in_use = false;
193 return;
194 }
195 }
196}
197
Paul Cercueil4acd6042015-11-30 12:10:43 +0100198static int usb_open(const struct iio_device *dev,
199 size_t samples_count, bool cyclic)
200{
Paul Cercueila5e4aa42016-02-09 13:31:01 +0100201 struct iio_context_pdata *ctx_pdata = dev->ctx->pdata;
Paul Cercueil4acd6042015-11-30 12:10:43 +0100202 struct iio_device_pdata *pdata = dev->pdata;
203 int ret = -EBUSY;
204
Paul Cercueil4213a432016-02-09 14:00:40 +0100205 iio_mutex_lock(ctx_pdata->ep_lock);
Paul Cercueil4acd6042015-11-30 12:10:43 +0100206
Paul Cercueila5e4aa42016-02-09 13:31:01 +0100207 if (pdata->opened)
208 goto out_unlock;
209
Paul Cercueil4213a432016-02-09 14:00:40 +0100210 ret = usb_reserve_ep_unlocked(dev);
211 if (ret)
212 goto out_unlock;
213
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100214 ret = usb_open_pipe(ctx_pdata->hdl, pdata->ep);
215 if (ret) {
216 char err_str[1024];
217
218 iio_strerror(-ret, err_str, sizeof(err_str));
219 ERROR("Failed to open pipe: %s\n", err_str);
220 usb_free_ep_unlocked(dev);
221 goto out_unlock;
222 }
223
Paul Cercueil4213a432016-02-09 14:00:40 +0100224 iio_mutex_lock(pdata->lock);
225
Paul Cercueila5e4aa42016-02-09 13:31:01 +0100226 ret = iiod_client_open_unlocked(ctx_pdata->iiod_client,
227 pdata->ep, dev, samples_count, cyclic);
228
229 if (!ret) {
230 unsigned int remote_timeout =
231 usb_calculate_remote_timeout(ctx_pdata->timeout_ms);
232
233 ret = iiod_client_set_timeout(ctx_pdata->iiod_client,
234 pdata->ep, remote_timeout);
Paul Cercueil4acd6042015-11-30 12:10:43 +0100235 }
236
Paul Cercueila5e4aa42016-02-09 13:31:01 +0100237 pdata->opened = !ret;
238
Paul Cercueil4acd6042015-11-30 12:10:43 +0100239 iio_mutex_unlock(pdata->lock);
Paul Cercueil4213a432016-02-09 14:00:40 +0100240
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100241 if (ret) {
242 usb_close_pipe(ctx_pdata->hdl, pdata->ep);
Paul Cercueil4213a432016-02-09 14:00:40 +0100243 usb_free_ep_unlocked(dev);
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100244 }
Paul Cercueil4213a432016-02-09 14:00:40 +0100245
246out_unlock:
247 iio_mutex_unlock(ctx_pdata->ep_lock);
Paul Cercueil4acd6042015-11-30 12:10:43 +0100248 return ret;
249}
250
251static int usb_close(const struct iio_device *dev)
252{
Paul Cercueil4213a432016-02-09 14:00:40 +0100253 struct iio_context_pdata *ctx_pdata = dev->ctx->pdata;
Paul Cercueil4acd6042015-11-30 12:10:43 +0100254 struct iio_device_pdata *pdata = dev->pdata;
255 int ret = -EBADF;
256
Paul Cercueil4213a432016-02-09 14:00:40 +0100257 iio_mutex_lock(ctx_pdata->ep_lock);
258 if (!pdata->opened)
259 goto out_unlock;
Paul Cercueil4acd6042015-11-30 12:10:43 +0100260
Paul Cercueil4213a432016-02-09 14:00:40 +0100261 iio_mutex_lock(pdata->lock);
262 ret = iiod_client_close_unlocked(ctx_pdata->iiod_client,
263 pdata->ep, dev);
264 pdata->opened = false;
265
Paul Cercueil31492b32016-02-22 17:40:20 +0100266 iio_mutex_unlock(pdata->lock);
267
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100268 usb_close_pipe(ctx_pdata->hdl, pdata->ep);
269
Paul Cercueil4213a432016-02-09 14:00:40 +0100270 usb_free_ep_unlocked(dev);
271
272out_unlock:
273 iio_mutex_unlock(ctx_pdata->ep_lock);
Paul Cercueil4acd6042015-11-30 12:10:43 +0100274 return ret;
275}
276
Paul Cercueil04841832015-12-02 11:58:33 +0100277static ssize_t usb_read(const struct iio_device *dev, void *dst, size_t len,
278 uint32_t *mask, size_t words)
279{
280 struct iio_device_pdata *pdata = dev->pdata;
281 ssize_t ret;
282
283 iio_mutex_lock(pdata->lock);
284 ret = iiod_client_read_unlocked(dev->ctx->pdata->iiod_client,
285 pdata->ep, dev, dst, len, mask, words);
286 iio_mutex_unlock(pdata->lock);
287
288 return ret;
289}
290
Paul Cercueile78e9882015-12-04 16:31:10 +0100291static ssize_t usb_write(const struct iio_device *dev,
292 const void *src, size_t len)
293{
294 struct iio_device_pdata *pdata = dev->pdata;
295 ssize_t ret;
296
297 iio_mutex_lock(pdata->lock);
298 ret = iiod_client_write_unlocked(dev->ctx->pdata->iiod_client,
299 pdata->ep, dev, src, len);
300 iio_mutex_unlock(pdata->lock);
301
302 return ret;
303}
304
Paul Cercueil3069e3b2015-11-26 16:01:25 +0100305static ssize_t usb_read_dev_attr(const struct iio_device *dev,
306 const char *attr, char *dst, size_t len, bool is_debug)
307{
308 struct iio_context_pdata *pdata = dev->ctx->pdata;
309
310 return iiod_client_read_attr(pdata->iiod_client, EP_OPS, dev,
311 NULL, attr, dst, len, is_debug);
312}
313
314static ssize_t usb_write_dev_attr(const struct iio_device *dev,
315 const char *attr, const char *src, size_t len, bool is_debug)
316{
317 struct iio_context_pdata *pdata = dev->ctx->pdata;
318
319 return iiod_client_write_attr(pdata->iiod_client, EP_OPS, dev,
320 NULL, attr, src, len, is_debug);
321}
322
323static ssize_t usb_read_chn_attr(const struct iio_channel *chn,
324 const char *attr, char *dst, size_t len)
325{
326 struct iio_context_pdata *pdata = chn->dev->ctx->pdata;
327
328 return iiod_client_read_attr(pdata->iiod_client, EP_OPS, chn->dev,
329 chn, attr, dst, len, false);
330}
331
332static ssize_t usb_write_chn_attr(const struct iio_channel *chn,
333 const char *attr, const char *src, size_t len)
334{
335 struct iio_context_pdata *pdata = chn->dev->ctx->pdata;
336
337 return iiod_client_write_attr(pdata->iiod_client, EP_OPS, chn->dev,
338 chn, attr, src, len, false);
339}
340
Paul Cercueil6c8337e2015-11-27 11:13:09 +0100341static int usb_set_kernel_buffers_count(const struct iio_device *dev,
342 unsigned int nb_blocks)
343{
344 struct iio_context_pdata *pdata = dev->ctx->pdata;
345
346 return iiod_client_set_kernel_buffers_count(pdata->iiod_client,
347 EP_OPS, dev, nb_blocks);
348}
349
Paul Cercueil7a988892015-12-03 12:39:20 +0100350static int usb_set_timeout(struct iio_context *ctx, unsigned int timeout)
351{
352 struct iio_context_pdata *pdata = ctx->pdata;
353 unsigned int remote_timeout = usb_calculate_remote_timeout(timeout);
354 int ret;
355
356 ret = iiod_client_set_timeout(pdata->iiod_client,
357 EP_OPS, remote_timeout);
Paul Cercueila5e4aa42016-02-09 13:31:01 +0100358 if (!ret)
359 pdata->timeout_ms = timeout;
Paul Cercueil7a988892015-12-03 12:39:20 +0100360
Paul Cercueil7a988892015-12-03 12:39:20 +0100361 return ret;
362}
363
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200364static void usb_shutdown(struct iio_context *ctx)
365{
Paul Cercueil4213a432016-02-09 14:00:40 +0100366 unsigned int i;
367
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200368 iio_mutex_destroy(ctx->pdata->lock);
Paul Cercueil4213a432016-02-09 14:00:40 +0100369 iio_mutex_destroy(ctx->pdata->ep_lock);
370
371 for (i = 0; i < ctx->pdata->nb_io_endpoints; i++)
372 if (ctx->pdata->io_endpoints[i].lock)
373 iio_mutex_destroy(ctx->pdata->io_endpoints[i].lock);
374 if (ctx->pdata->io_endpoints)
375 free(ctx->pdata->io_endpoints);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200376
Lars-Peter Clausen33c64312016-02-19 13:32:08 +0100377 for (i = 0; i < ctx->nb_devices; i++) {
378 struct iio_device *dev = ctx->devices[i];
379
380 free(dev->pdata);
381 }
382
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200383 iiod_client_destroy(ctx->pdata->iiod_client);
384
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100385 usb_reset_pipes(ctx->pdata->hdl); /* Close everything */
386
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200387 libusb_close(ctx->pdata->hdl);
388 libusb_exit(ctx->pdata->ctx);
Lars-Peter Clausen33c64312016-02-19 13:32:08 +0100389 free(ctx->pdata);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200390}
391
392static const struct iio_backend_ops usb_ops = {
Paul Cercueilc11737c2015-11-26 14:44:46 +0100393 .get_version = usb_get_version,
Paul Cercueil4acd6042015-11-30 12:10:43 +0100394 .open = usb_open,
395 .close = usb_close,
Paul Cercueil04841832015-12-02 11:58:33 +0100396 .read = usb_read,
Paul Cercueile78e9882015-12-04 16:31:10 +0100397 .write = usb_write,
Paul Cercueil3069e3b2015-11-26 16:01:25 +0100398 .read_device_attr = usb_read_dev_attr,
399 .read_channel_attr = usb_read_chn_attr,
400 .write_device_attr = usb_write_dev_attr,
401 .write_channel_attr = usb_write_chn_attr,
Paul Cercueil6c8337e2015-11-27 11:13:09 +0100402 .set_kernel_buffers_count = usb_set_kernel_buffers_count,
Paul Cercueil7a988892015-12-03 12:39:20 +0100403 .set_timeout = usb_set_timeout,
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200404 .shutdown = usb_shutdown,
405};
406
407static ssize_t write_data_sync(struct iio_context_pdata *pdata,
408 int ep, const char *data, size_t len)
409{
410 int transferred, ret;
411
412 ret = libusb_bulk_transfer(pdata->hdl, ep | LIBUSB_ENDPOINT_OUT,
Lars-Peter Clausen8ba0d5b2016-02-17 11:30:23 +0100413 (unsigned char *) data, (int) len,
Paul Cercueile10d19a2016-02-09 13:30:12 +0100414 &transferred, pdata->timeout_ms);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200415 if (ret)
Paul Cercueil463fc782015-12-04 16:04:12 +0100416 return -(int) libusb_to_errno(ret);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200417 else
Lars-Peter Clausen8ba0d5b2016-02-17 11:30:23 +0100418 return (size_t) transferred != len ? -EIO : (ssize_t) len;
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200419}
420
421static ssize_t read_data_sync(struct iio_context_pdata *pdata,
422 int ep, char *buf, size_t len)
423{
424 int transferred, ret;
425
426 ret = libusb_bulk_transfer(pdata->hdl, ep | LIBUSB_ENDPOINT_IN,
Lars-Peter Clausen8ba0d5b2016-02-17 11:30:23 +0100427 (unsigned char *) buf, (int) len, &transferred, pdata->timeout_ms);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200428 if (ret)
Paul Cercueil463fc782015-12-04 16:04:12 +0100429 return -(int) libusb_to_errno(ret);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200430 else
431 return transferred;
432}
433
Lars-Peter Clausen09a59d72016-02-03 15:27:04 +0100434static const struct iiod_client_ops usb_iiod_client_ops = {
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200435 .write = write_data_sync,
436 .read = read_data_sync,
437 .read_line = read_data_sync,
438};
439
Paul Cercueil4213a432016-02-09 14:00:40 +0100440static int usb_count_io_eps(const struct libusb_interface_descriptor *iface)
441{
442 unsigned int eps = iface->bNumEndpoints;
443 unsigned int i, curr;
444
445 /* Check that for a number of endpoints X provided by the interface, we
446 * have the input and output endpoints in the address range [1, ... X/2]
447 * and that each input endpoint has a corresponding output endpoint at
448 * the same address. */
449
450 if (eps < 2 || eps % 2)
451 return -EINVAL;
452
453 for (curr = 1; curr < (eps / 2) + 1; curr++) {
454 bool found_in = false, found_out = false;
455
456 for (i = 0; !found_in && i < eps; i++)
457 found_in = iface->endpoint[i].bEndpointAddress ==
Paul Cercueil6733c4e2016-02-12 15:09:35 +0100458 (LIBUSB_ENDPOINT_IN | curr);
Paul Cercueil4213a432016-02-09 14:00:40 +0100459 if (!found_in)
460 return -EINVAL;
461
462 for (i = 0; !found_out && i < eps; i++)
463 found_out = iface->endpoint[i].bEndpointAddress ==
Paul Cercueil6733c4e2016-02-12 15:09:35 +0100464 (LIBUSB_ENDPOINT_OUT | curr);
Paul Cercueil4213a432016-02-09 14:00:40 +0100465 if (!found_out)
466 return -EINVAL;
467 }
468
469 /* -1: we reserve the first I/O endpoint couple for global operations */
470 return (int) curr - 1;
471}
472
Lars-Peter Clausen7a8e6b52016-02-22 13:25:12 +0100473struct iio_context * usb_create_context(unsigned int bus,
474 unsigned int address, unsigned int interface)
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200475{
476 libusb_context *usb_ctx;
477 libusb_device_handle *hdl;
Paul Cercueil4213a432016-02-09 14:00:40 +0100478 const struct libusb_interface_descriptor *iface;
Lars-Peter Clausen7a8e6b52016-02-22 13:25:12 +0100479 libusb_device *dev, *usb_dev;
Paul Cercueil4213a432016-02-09 14:00:40 +0100480 struct libusb_config_descriptor *conf_desc;
Lars-Peter Clausen7a8e6b52016-02-22 13:25:12 +0100481 libusb_device **device_list;
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200482 struct iio_context *ctx;
483 struct iio_context_pdata *pdata;
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100484 char err_str[1024];
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200485 unsigned int i;
486 int ret;
487
Lars-Peter Clausend1be8382016-02-24 11:13:45 +0100488 pdata = zalloc(sizeof(*pdata));
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200489 if (!pdata) {
490 ERROR("Unable to allocate pdata\n");
491 ret = -ENOMEM;
492 goto err_set_errno;
493 }
494
495 pdata->lock = iio_mutex_create();
496 if (!pdata->lock) {
497 ERROR("Unable to create mutex\n");
498 ret = -ENOMEM;
499 goto err_free_pdata;
500 }
501
Paul Cercueil4213a432016-02-09 14:00:40 +0100502 pdata->ep_lock = iio_mutex_create();
503 if (!pdata->ep_lock) {
Paul Cercueil4acd6042015-11-30 12:10:43 +0100504 ERROR("Unable to create mutex\n");
505 ret = -ENOMEM;
506 goto err_destroy_mutex;
507 }
508
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200509 pdata->iiod_client = iiod_client_new(pdata, pdata->lock,
510 &usb_iiod_client_ops);
511 if (!pdata->iiod_client) {
512 ERROR("Unable to create IIOD client\n");
513 ret = -errno;
Paul Cercueil4213a432016-02-09 14:00:40 +0100514 goto err_destroy_ep_mutex;
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200515 }
516
517 ret = libusb_init(&usb_ctx);
518 if (ret) {
Paul Cercueil463fc782015-12-04 16:04:12 +0100519 ret = -(int) libusb_to_errno(ret);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200520 ERROR("Unable to init libusb: %i\n", ret);
Paul Cercueil4acd6042015-11-30 12:10:43 +0100521 goto err_destroy_iiod_client;
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200522 }
523
Lars-Peter Clausen7a8e6b52016-02-22 13:25:12 +0100524 libusb_get_device_list(usb_ctx, &device_list);
525
526 usb_dev = NULL;
527
528 for (i = 0; device_list[i]; i++) {
529 dev = device_list[i];
530
531 if (bus == libusb_get_bus_number(dev) &&
532 address == libusb_get_device_address(dev)) {
533 usb_dev = dev;
534 libusb_ref_device(usb_dev);
535 break;
536 }
537 }
538
539 libusb_free_device_list(device_list, true);
540
541 if (!usb_dev)
542 goto err_libusb_exit;
543
544 ret = libusb_open(usb_dev, &hdl);
545 libusb_unref_device(usb_dev); /* Open gets us a extra ref */
546 if (ret) {
547 ret = -(int) libusb_to_errno(ret);
548 ERROR("Unable to open device\n");
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200549 goto err_libusb_exit;
550 }
551
552 libusb_set_auto_detach_kernel_driver(hdl, true);
553
Lars-Peter Clausen7a8e6b52016-02-22 13:25:12 +0100554 ret = libusb_claim_interface(hdl, interface);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200555 if (ret) {
Paul Cercueil463fc782015-12-04 16:04:12 +0100556 ret = -(int) libusb_to_errno(ret);
Lars-Peter Clausen7a8e6b52016-02-22 13:25:12 +0100557 ERROR("Unable to claim interface %u: %i\n", interface, ret);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200558 goto err_libusb_close;
559 }
560
Paul Cercueil4213a432016-02-09 14:00:40 +0100561 ret = libusb_get_active_config_descriptor(usb_dev, &conf_desc);
562 if (ret) {
563 ret = -(int) libusb_to_errno(ret);
564 ERROR("Unable to get config descriptor: %i\n", ret);
565 goto err_libusb_close;
566 }
567
Lars-Peter Clausen7a8e6b52016-02-22 13:25:12 +0100568 iface = &conf_desc->interface[interface].altsetting[0];
Paul Cercueil4213a432016-02-09 14:00:40 +0100569
570 ret = usb_count_io_eps(iface);
571 if (ret < 0) {
572 ERROR("Invalid configuration of endpoints\n");
573 goto err_free_config_descriptor;
574 }
575
576 pdata->nb_io_endpoints = ret;
577
578 DEBUG("Found %hhu usable i/o endpoints\n", pdata->nb_io_endpoints);
579
580 if (pdata->nb_io_endpoints) {
581 pdata->io_endpoints = calloc(pdata->nb_io_endpoints,
582 sizeof(*pdata->io_endpoints));
583 if (!pdata->io_endpoints) {
584 ERROR("Unable to allocate endpoints\n");
585 ret = -ENOMEM;
586 goto err_free_config_descriptor;
587 }
588
589 for (i = 0; i < pdata->nb_io_endpoints; i++) {
590 struct iio_usb_io_endpoint *ep =
591 &pdata->io_endpoints[i];
592
593 /* +2: endpoints start at number 1, and we skip the
594 * endpoint #1 that we reserve for global operations */
595 ep->address = i + 2;
596
597 ep->lock = iio_mutex_create();
598 if (!ep->lock) {
599 ERROR("Unable to create mutex\n");
600 ret = -ENOMEM;
601 goto err_free_endpoints;
602 }
603 }
604 }
605
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200606 pdata->ctx = usb_ctx;
607 pdata->hdl = hdl;
Paul Cercueil7a988892015-12-03 12:39:20 +0100608 pdata->timeout_ms = DEFAULT_TIMEOUT_MS;
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200609
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100610 ret = usb_reset_pipes(hdl);
611 if (ret) {
612 iio_strerror(-ret, err_str, sizeof(err_str));
613 ERROR("Failed to reset pipes: %s\n", err_str);
614 return NULL;
615 }
616
617 ret = usb_open_pipe(hdl, EP_OPS);
618 if (ret) {
619 iio_strerror(-ret, err_str, sizeof(err_str));
620 ERROR("Failed to open control pipe: %s\n", err_str);
621 return NULL;
622 }
623
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200624 ctx = iiod_client_create_context(pdata->iiod_client, EP_OPS);
625 if (!ctx)
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100626 goto err_reset_pipes;
Paul Cercueil4213a432016-02-09 14:00:40 +0100627
628 libusb_free_config_descriptor(conf_desc);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200629
630 ctx->name = "usb";
631 ctx->ops = &usb_ops;
632 ctx->pdata = pdata;
633
Paul Cercueil4acd6042015-11-30 12:10:43 +0100634 for (i = 0; i < ctx->nb_devices; i++) {
635 struct iio_device *dev = ctx->devices[i];
636
Lars-Peter Clausend1be8382016-02-24 11:13:45 +0100637 dev->pdata = zalloc(sizeof(*dev->pdata));
Paul Cercueil4acd6042015-11-30 12:10:43 +0100638 if (!dev->pdata) {
639 ERROR("Unable to allocate memory\n");
640 ret = -ENOMEM;
641 goto err_context_destroy;
642 }
Paul Cercueil4acd6042015-11-30 12:10:43 +0100643 }
644
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200645 return ctx;
646
647err_context_destroy:
648 iio_context_destroy(ctx);
649 errno = -ret;
650 return NULL;
651
Lars-Peter Clausen2eba3632016-03-08 14:33:21 +0100652err_reset_pipes:
653 usb_reset_pipes(hdl); /* Close everything */
Paul Cercueil4213a432016-02-09 14:00:40 +0100654err_free_endpoints:
655 for (i = 0; i < pdata->nb_io_endpoints; i++)
656 if (pdata->io_endpoints[i].lock)
657 iio_mutex_destroy(pdata->io_endpoints[i].lock);
658 if (pdata->io_endpoints)
659 free(pdata->io_endpoints);
660err_free_config_descriptor:
661 libusb_free_config_descriptor(conf_desc);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200662err_libusb_close:
663 libusb_close(hdl);
664err_libusb_exit:
665 libusb_exit(usb_ctx);
666err_destroy_iiod_client:
667 iiod_client_destroy(pdata->iiod_client);
Paul Cercueil4213a432016-02-09 14:00:40 +0100668err_destroy_ep_mutex:
669 iio_mutex_destroy(pdata->ep_lock);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200670err_destroy_mutex:
671 iio_mutex_destroy(pdata->lock);
672err_free_pdata:
673 free(pdata);
674err_set_errno:
675 errno = -ret;
676 return NULL;
677}
Lars-Peter Clausen60f1c9a2016-02-22 13:20:40 +0100678
679struct iio_context * usb_create_context_from_uri(const char *uri)
680{
681 unsigned int bus, address, interface;
682
683 if (strncmp(uri, "usb:", sizeof("usb:") - 1) != 0)
684 return NULL;
685
686 sscanf(uri+4, "%u.%u.%u", &bus, &address, &interface);
687
688 return usb_create_context(bus, address, interface);
689}