blob: 16792e6e8ee2b78ab60777af7ec328e95a62be4f [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 {
65 bool is_tx;
66 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
Paul Cercueil4213a432016-02-09 14:00:40 +0100122static int usb_reserve_ep_unlocked(const struct iio_device *dev)
123{
124 struct iio_context_pdata *pdata = dev->ctx->pdata;
125 unsigned int i;
126
127 for (i = 0; i < pdata->nb_io_endpoints; i++) {
128 struct iio_usb_io_endpoint *ep = &pdata->io_endpoints[i];
129
130 if (!ep->in_use) {
131 ep->in_use = true;
132
133 dev->pdata->ep = ep->address;
134 dev->pdata->lock = ep->lock;
135 return 0;
136 }
137 }
138
139 return -EBUSY;
140}
141
142static void usb_free_ep_unlocked(const struct iio_device *dev)
143{
144 struct iio_context_pdata *pdata = dev->ctx->pdata;
145 unsigned int i;
146
147 for (i = 0; i < pdata->nb_io_endpoints; i++) {
148 struct iio_usb_io_endpoint *ep = &pdata->io_endpoints[i];
149
150 if (ep->lock == dev->pdata->lock) {
151 ep->in_use = false;
152 return;
153 }
154 }
155}
156
Paul Cercueil4acd6042015-11-30 12:10:43 +0100157static int usb_open(const struct iio_device *dev,
158 size_t samples_count, bool cyclic)
159{
Paul Cercueila5e4aa42016-02-09 13:31:01 +0100160 struct iio_context_pdata *ctx_pdata = dev->ctx->pdata;
Paul Cercueil4acd6042015-11-30 12:10:43 +0100161 struct iio_device_pdata *pdata = dev->pdata;
162 int ret = -EBUSY;
163
Paul Cercueil4213a432016-02-09 14:00:40 +0100164 iio_mutex_lock(ctx_pdata->ep_lock);
Paul Cercueil4acd6042015-11-30 12:10:43 +0100165
Paul Cercueila5e4aa42016-02-09 13:31:01 +0100166 if (pdata->opened)
167 goto out_unlock;
168
Paul Cercueil4213a432016-02-09 14:00:40 +0100169 ret = usb_reserve_ep_unlocked(dev);
170 if (ret)
171 goto out_unlock;
172
173 iio_mutex_lock(pdata->lock);
174
Paul Cercueila5e4aa42016-02-09 13:31:01 +0100175 ret = iiod_client_open_unlocked(ctx_pdata->iiod_client,
176 pdata->ep, dev, samples_count, cyclic);
177
178 if (!ret) {
179 unsigned int remote_timeout =
180 usb_calculate_remote_timeout(ctx_pdata->timeout_ms);
181
182 ret = iiod_client_set_timeout(ctx_pdata->iiod_client,
183 pdata->ep, remote_timeout);
Paul Cercueil4acd6042015-11-30 12:10:43 +0100184 }
185
Paul Cercueila5e4aa42016-02-09 13:31:01 +0100186 pdata->opened = !ret;
187
Paul Cercueil4acd6042015-11-30 12:10:43 +0100188 iio_mutex_unlock(pdata->lock);
Paul Cercueil4213a432016-02-09 14:00:40 +0100189
190 if (ret)
191 usb_free_ep_unlocked(dev);
192
193out_unlock:
194 iio_mutex_unlock(ctx_pdata->ep_lock);
Paul Cercueil4acd6042015-11-30 12:10:43 +0100195 return ret;
196}
197
198static int usb_close(const struct iio_device *dev)
199{
Paul Cercueil4213a432016-02-09 14:00:40 +0100200 struct iio_context_pdata *ctx_pdata = dev->ctx->pdata;
Paul Cercueil4acd6042015-11-30 12:10:43 +0100201 struct iio_device_pdata *pdata = dev->pdata;
202 int ret = -EBADF;
203
Paul Cercueil4213a432016-02-09 14:00:40 +0100204 iio_mutex_lock(ctx_pdata->ep_lock);
205 if (!pdata->opened)
206 goto out_unlock;
Paul Cercueil4acd6042015-11-30 12:10:43 +0100207
Paul Cercueil4213a432016-02-09 14:00:40 +0100208 iio_mutex_lock(pdata->lock);
209 ret = iiod_client_close_unlocked(ctx_pdata->iiod_client,
210 pdata->ep, dev);
211 pdata->opened = false;
212
Paul Cercueil31492b32016-02-22 17:40:20 +0100213 iio_mutex_unlock(pdata->lock);
214
Paul Cercueil4213a432016-02-09 14:00:40 +0100215 usb_free_ep_unlocked(dev);
216
217out_unlock:
218 iio_mutex_unlock(ctx_pdata->ep_lock);
Paul Cercueil4acd6042015-11-30 12:10:43 +0100219 return ret;
220}
221
Paul Cercueil04841832015-12-02 11:58:33 +0100222static ssize_t usb_read(const struct iio_device *dev, void *dst, size_t len,
223 uint32_t *mask, size_t words)
224{
225 struct iio_device_pdata *pdata = dev->pdata;
226 ssize_t ret;
227
228 iio_mutex_lock(pdata->lock);
229 ret = iiod_client_read_unlocked(dev->ctx->pdata->iiod_client,
230 pdata->ep, dev, dst, len, mask, words);
231 iio_mutex_unlock(pdata->lock);
232
233 return ret;
234}
235
Paul Cercueile78e9882015-12-04 16:31:10 +0100236static ssize_t usb_write(const struct iio_device *dev,
237 const void *src, size_t len)
238{
239 struct iio_device_pdata *pdata = dev->pdata;
240 ssize_t ret;
241
242 iio_mutex_lock(pdata->lock);
243 ret = iiod_client_write_unlocked(dev->ctx->pdata->iiod_client,
244 pdata->ep, dev, src, len);
245 iio_mutex_unlock(pdata->lock);
246
247 return ret;
248}
249
Paul Cercueil3069e3b2015-11-26 16:01:25 +0100250static ssize_t usb_read_dev_attr(const struct iio_device *dev,
251 const char *attr, char *dst, size_t len, bool is_debug)
252{
253 struct iio_context_pdata *pdata = dev->ctx->pdata;
254
255 return iiod_client_read_attr(pdata->iiod_client, EP_OPS, dev,
256 NULL, attr, dst, len, is_debug);
257}
258
259static ssize_t usb_write_dev_attr(const struct iio_device *dev,
260 const char *attr, const char *src, size_t len, bool is_debug)
261{
262 struct iio_context_pdata *pdata = dev->ctx->pdata;
263
264 return iiod_client_write_attr(pdata->iiod_client, EP_OPS, dev,
265 NULL, attr, src, len, is_debug);
266}
267
268static ssize_t usb_read_chn_attr(const struct iio_channel *chn,
269 const char *attr, char *dst, size_t len)
270{
271 struct iio_context_pdata *pdata = chn->dev->ctx->pdata;
272
273 return iiod_client_read_attr(pdata->iiod_client, EP_OPS, chn->dev,
274 chn, attr, dst, len, false);
275}
276
277static ssize_t usb_write_chn_attr(const struct iio_channel *chn,
278 const char *attr, const char *src, size_t len)
279{
280 struct iio_context_pdata *pdata = chn->dev->ctx->pdata;
281
282 return iiod_client_write_attr(pdata->iiod_client, EP_OPS, chn->dev,
283 chn, attr, src, len, false);
284}
285
Paul Cercueil6c8337e2015-11-27 11:13:09 +0100286static int usb_set_kernel_buffers_count(const struct iio_device *dev,
287 unsigned int nb_blocks)
288{
289 struct iio_context_pdata *pdata = dev->ctx->pdata;
290
291 return iiod_client_set_kernel_buffers_count(pdata->iiod_client,
292 EP_OPS, dev, nb_blocks);
293}
294
Paul Cercueil7a988892015-12-03 12:39:20 +0100295static int usb_set_timeout(struct iio_context *ctx, unsigned int timeout)
296{
297 struct iio_context_pdata *pdata = ctx->pdata;
298 unsigned int remote_timeout = usb_calculate_remote_timeout(timeout);
299 int ret;
300
301 ret = iiod_client_set_timeout(pdata->iiod_client,
302 EP_OPS, remote_timeout);
Paul Cercueila5e4aa42016-02-09 13:31:01 +0100303 if (!ret)
304 pdata->timeout_ms = timeout;
Paul Cercueil7a988892015-12-03 12:39:20 +0100305
Paul Cercueil7a988892015-12-03 12:39:20 +0100306 return ret;
307}
308
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200309static void usb_shutdown(struct iio_context *ctx)
310{
Paul Cercueil4213a432016-02-09 14:00:40 +0100311 unsigned int i;
312
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200313 iio_mutex_destroy(ctx->pdata->lock);
Paul Cercueil4213a432016-02-09 14:00:40 +0100314 iio_mutex_destroy(ctx->pdata->ep_lock);
315
316 for (i = 0; i < ctx->pdata->nb_io_endpoints; i++)
317 if (ctx->pdata->io_endpoints[i].lock)
318 iio_mutex_destroy(ctx->pdata->io_endpoints[i].lock);
319 if (ctx->pdata->io_endpoints)
320 free(ctx->pdata->io_endpoints);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200321
Lars-Peter Clausen33c64312016-02-19 13:32:08 +0100322 for (i = 0; i < ctx->nb_devices; i++) {
323 struct iio_device *dev = ctx->devices[i];
324
325 free(dev->pdata);
326 }
327
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200328 iiod_client_destroy(ctx->pdata->iiod_client);
329
330 libusb_close(ctx->pdata->hdl);
331 libusb_exit(ctx->pdata->ctx);
Lars-Peter Clausen33c64312016-02-19 13:32:08 +0100332 free(ctx->pdata);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200333}
334
335static const struct iio_backend_ops usb_ops = {
Paul Cercueilc11737c2015-11-26 14:44:46 +0100336 .get_version = usb_get_version,
Paul Cercueil4acd6042015-11-30 12:10:43 +0100337 .open = usb_open,
338 .close = usb_close,
Paul Cercueil04841832015-12-02 11:58:33 +0100339 .read = usb_read,
Paul Cercueile78e9882015-12-04 16:31:10 +0100340 .write = usb_write,
Paul Cercueil3069e3b2015-11-26 16:01:25 +0100341 .read_device_attr = usb_read_dev_attr,
342 .read_channel_attr = usb_read_chn_attr,
343 .write_device_attr = usb_write_dev_attr,
344 .write_channel_attr = usb_write_chn_attr,
Paul Cercueil6c8337e2015-11-27 11:13:09 +0100345 .set_kernel_buffers_count = usb_set_kernel_buffers_count,
Paul Cercueil7a988892015-12-03 12:39:20 +0100346 .set_timeout = usb_set_timeout,
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200347 .shutdown = usb_shutdown,
348};
349
350static ssize_t write_data_sync(struct iio_context_pdata *pdata,
351 int ep, const char *data, size_t len)
352{
353 int transferred, ret;
354
355 ret = libusb_bulk_transfer(pdata->hdl, ep | LIBUSB_ENDPOINT_OUT,
Lars-Peter Clausen8ba0d5b2016-02-17 11:30:23 +0100356 (unsigned char *) data, (int) len,
Paul Cercueile10d19a2016-02-09 13:30:12 +0100357 &transferred, pdata->timeout_ms);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200358 if (ret)
Paul Cercueil463fc782015-12-04 16:04:12 +0100359 return -(int) libusb_to_errno(ret);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200360 else
Lars-Peter Clausen8ba0d5b2016-02-17 11:30:23 +0100361 return (size_t) transferred != len ? -EIO : (ssize_t) len;
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200362}
363
364static ssize_t read_data_sync(struct iio_context_pdata *pdata,
365 int ep, char *buf, size_t len)
366{
367 int transferred, ret;
368
369 ret = libusb_bulk_transfer(pdata->hdl, ep | LIBUSB_ENDPOINT_IN,
Lars-Peter Clausen8ba0d5b2016-02-17 11:30:23 +0100370 (unsigned char *) buf, (int) len, &transferred, pdata->timeout_ms);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200371 if (ret)
Paul Cercueil463fc782015-12-04 16:04:12 +0100372 return -(int) libusb_to_errno(ret);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200373 else
374 return transferred;
375}
376
Lars-Peter Clausen09a59d72016-02-03 15:27:04 +0100377static const struct iiod_client_ops usb_iiod_client_ops = {
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200378 .write = write_data_sync,
379 .read = read_data_sync,
380 .read_line = read_data_sync,
381};
382
Paul Cercueil4213a432016-02-09 14:00:40 +0100383static int usb_count_io_eps(const struct libusb_interface_descriptor *iface)
384{
385 unsigned int eps = iface->bNumEndpoints;
386 unsigned int i, curr;
387
388 /* Check that for a number of endpoints X provided by the interface, we
389 * have the input and output endpoints in the address range [1, ... X/2]
390 * and that each input endpoint has a corresponding output endpoint at
391 * the same address. */
392
393 if (eps < 2 || eps % 2)
394 return -EINVAL;
395
396 for (curr = 1; curr < (eps / 2) + 1; curr++) {
397 bool found_in = false, found_out = false;
398
399 for (i = 0; !found_in && i < eps; i++)
400 found_in = iface->endpoint[i].bEndpointAddress ==
Paul Cercueil6733c4e2016-02-12 15:09:35 +0100401 (LIBUSB_ENDPOINT_IN | curr);
Paul Cercueil4213a432016-02-09 14:00:40 +0100402 if (!found_in)
403 return -EINVAL;
404
405 for (i = 0; !found_out && i < eps; i++)
406 found_out = iface->endpoint[i].bEndpointAddress ==
Paul Cercueil6733c4e2016-02-12 15:09:35 +0100407 (LIBUSB_ENDPOINT_OUT | curr);
Paul Cercueil4213a432016-02-09 14:00:40 +0100408 if (!found_out)
409 return -EINVAL;
410 }
411
412 /* -1: we reserve the first I/O endpoint couple for global operations */
413 return (int) curr - 1;
414}
415
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200416struct iio_context * usb_create_context(unsigned short vid, unsigned short pid)
417{
418 libusb_context *usb_ctx;
Paul Cercueil4213a432016-02-09 14:00:40 +0100419 libusb_device *usb_dev;
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200420 libusb_device_handle *hdl;
Paul Cercueil4213a432016-02-09 14:00:40 +0100421 const struct libusb_interface_descriptor *iface;
422 struct libusb_config_descriptor *conf_desc;
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200423 struct iio_context *ctx;
424 struct iio_context_pdata *pdata;
425 unsigned int i;
426 int ret;
427
428 pdata = calloc(1, sizeof(*pdata));
429 if (!pdata) {
430 ERROR("Unable to allocate pdata\n");
431 ret = -ENOMEM;
432 goto err_set_errno;
433 }
434
435 pdata->lock = iio_mutex_create();
436 if (!pdata->lock) {
437 ERROR("Unable to create mutex\n");
438 ret = -ENOMEM;
439 goto err_free_pdata;
440 }
441
Paul Cercueil4213a432016-02-09 14:00:40 +0100442 pdata->ep_lock = iio_mutex_create();
443 if (!pdata->ep_lock) {
Paul Cercueil4acd6042015-11-30 12:10:43 +0100444 ERROR("Unable to create mutex\n");
445 ret = -ENOMEM;
446 goto err_destroy_mutex;
447 }
448
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200449 pdata->iiod_client = iiod_client_new(pdata, pdata->lock,
450 &usb_iiod_client_ops);
451 if (!pdata->iiod_client) {
452 ERROR("Unable to create IIOD client\n");
453 ret = -errno;
Paul Cercueil4213a432016-02-09 14:00:40 +0100454 goto err_destroy_ep_mutex;
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200455 }
456
457 ret = libusb_init(&usb_ctx);
458 if (ret) {
Paul Cercueil463fc782015-12-04 16:04:12 +0100459 ret = -(int) libusb_to_errno(ret);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200460 ERROR("Unable to init libusb: %i\n", ret);
Paul Cercueil4acd6042015-11-30 12:10:43 +0100461 goto err_destroy_iiod_client;
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200462 }
463
464 hdl = libusb_open_device_with_vid_pid(usb_ctx, vid, pid);
465 if (!hdl) {
466 ERROR("Unable to find device 0x%04hx:0x%04hx\n", vid, pid);
467 ret = -ENODEV;
468 goto err_libusb_exit;
469 }
470
471 libusb_set_auto_detach_kernel_driver(hdl, true);
472
473 ret = libusb_claim_interface(hdl, 0);
474 if (ret) {
Paul Cercueil463fc782015-12-04 16:04:12 +0100475 ret = -(int) libusb_to_errno(ret);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200476 ERROR("Unable to claim interface 0: %i\n", ret);
477 goto err_libusb_close;
478 }
479
Paul Cercueil4213a432016-02-09 14:00:40 +0100480 usb_dev = libusb_get_device(hdl);
481
482 ret = libusb_get_active_config_descriptor(usb_dev, &conf_desc);
483 if (ret) {
484 ret = -(int) libusb_to_errno(ret);
485 ERROR("Unable to get config descriptor: %i\n", ret);
486 goto err_libusb_close;
487 }
488
489 iface = &conf_desc->interface[0].altsetting[0];
490
491 ret = usb_count_io_eps(iface);
492 if (ret < 0) {
493 ERROR("Invalid configuration of endpoints\n");
494 goto err_free_config_descriptor;
495 }
496
497 pdata->nb_io_endpoints = ret;
498
499 DEBUG("Found %hhu usable i/o endpoints\n", pdata->nb_io_endpoints);
500
501 if (pdata->nb_io_endpoints) {
502 pdata->io_endpoints = calloc(pdata->nb_io_endpoints,
503 sizeof(*pdata->io_endpoints));
504 if (!pdata->io_endpoints) {
505 ERROR("Unable to allocate endpoints\n");
506 ret = -ENOMEM;
507 goto err_free_config_descriptor;
508 }
509
510 for (i = 0; i < pdata->nb_io_endpoints; i++) {
511 struct iio_usb_io_endpoint *ep =
512 &pdata->io_endpoints[i];
513
514 /* +2: endpoints start at number 1, and we skip the
515 * endpoint #1 that we reserve for global operations */
516 ep->address = i + 2;
517
518 ep->lock = iio_mutex_create();
519 if (!ep->lock) {
520 ERROR("Unable to create mutex\n");
521 ret = -ENOMEM;
522 goto err_free_endpoints;
523 }
524 }
525 }
526
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200527 pdata->ctx = usb_ctx;
528 pdata->hdl = hdl;
Paul Cercueil7a988892015-12-03 12:39:20 +0100529 pdata->timeout_ms = DEFAULT_TIMEOUT_MS;
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200530
531 ctx = iiod_client_create_context(pdata->iiod_client, EP_OPS);
532 if (!ctx)
Paul Cercueil4213a432016-02-09 14:00:40 +0100533 goto err_free_endpoints;
534
535 libusb_free_config_descriptor(conf_desc);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200536
537 ctx->name = "usb";
538 ctx->ops = &usb_ops;
539 ctx->pdata = pdata;
540
541 DEBUG("Initializing context...\n");
542 ret = iio_context_init(ctx);
543 if (ret < 0)
544 goto err_context_destroy;
545
Paul Cercueil4acd6042015-11-30 12:10:43 +0100546 for (i = 0; i < ctx->nb_devices; i++) {
547 struct iio_device *dev = ctx->devices[i];
548
549 dev->pdata = calloc(1, sizeof(*dev->pdata));
550 if (!dev->pdata) {
551 ERROR("Unable to allocate memory\n");
552 ret = -ENOMEM;
553 goto err_context_destroy;
554 }
555
556 dev->pdata->is_tx = iio_device_is_tx(dev);
Paul Cercueil4acd6042015-11-30 12:10:43 +0100557 }
558
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200559 return ctx;
560
561err_context_destroy:
562 iio_context_destroy(ctx);
563 errno = -ret;
564 return NULL;
565
Paul Cercueil4213a432016-02-09 14:00:40 +0100566err_free_endpoints:
567 for (i = 0; i < pdata->nb_io_endpoints; i++)
568 if (pdata->io_endpoints[i].lock)
569 iio_mutex_destroy(pdata->io_endpoints[i].lock);
570 if (pdata->io_endpoints)
571 free(pdata->io_endpoints);
572err_free_config_descriptor:
573 libusb_free_config_descriptor(conf_desc);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200574err_libusb_close:
575 libusb_close(hdl);
576err_libusb_exit:
577 libusb_exit(usb_ctx);
578err_destroy_iiod_client:
579 iiod_client_destroy(pdata->iiod_client);
Paul Cercueil4213a432016-02-09 14:00:40 +0100580err_destroy_ep_mutex:
581 iio_mutex_destroy(pdata->ep_lock);
Paul Cercueile06f4ce2015-04-20 12:59:31 +0200582err_destroy_mutex:
583 iio_mutex_destroy(pdata->lock);
584err_free_pdata:
585 free(pdata);
586err_set_errno:
587 errno = -ret;
588 return NULL;
589}