1 /*
2 * libiio - Library for interfacing industrial I/O (IIO) devices
3 *
4 * Copyright (C) 2016 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 #include "iio-config.h"
19 #include "iio-private.h"
20
21 #include <errno.h>
22 #include <stdbool.h>
23 #include <string.h>
24
25 struct iio_scan_context {
26 #ifdef WITH_USB_BACKEND
27 struct iio_scan_backend_context *usb_ctx;
28 #endif
29 bool scan_local;
30 };
31
iio_context_info_get_description(const struct iio_context_info * info)32 const char * iio_context_info_get_description(
33 const struct iio_context_info *info)
34 {
35 return info->description;
36 }
37
iio_context_info_get_uri(const struct iio_context_info * info)38 const char * iio_context_info_get_uri(
39 const struct iio_context_info *info)
40 {
41 return info->uri;
42 }
43
iio_scan_context_get_info_list(struct iio_scan_context * ctx,struct iio_context_info *** info)44 ssize_t iio_scan_context_get_info_list(struct iio_scan_context *ctx,
45 struct iio_context_info ***info)
46 {
47 struct iio_scan_result scan_result = { 0, NULL };
48
49 #ifdef WITH_LOCAL_BACKEND
50 if (ctx->scan_local) {
51 int ret = local_context_scan(&scan_result);
52 if (ret < 0) {
53 if (scan_result.info)
54 iio_context_info_list_free(scan_result.info);
55 return ret;
56 }
57 }
58 #endif
59
60 #ifdef WITH_USB_BACKEND
61 if (ctx->usb_ctx) {
62 int ret = usb_context_scan(ctx->usb_ctx, &scan_result);
63 if (ret < 0) {
64 if (scan_result.info)
65 iio_context_info_list_free(scan_result.info);
66 return ret;
67 }
68 }
69 #endif
70
71 *info = scan_result.info;
72
73 return (ssize_t) scan_result.size;
74 }
75
iio_context_info_list_free(struct iio_context_info ** list)76 void iio_context_info_list_free(struct iio_context_info **list)
77 {
78 struct iio_context_info **it;
79
80 if (!list)
81 return;
82
83 for (it = list; *it; it++) {
84 struct iio_context_info *info = *it;
85
86 if (info->description)
87 free(info->description);
88 if (info->uri)
89 free(info->uri);
90 free(info);
91 }
92
93 free(list);
94 }
95
iio_scan_result_add(struct iio_scan_result * scan_result,size_t num)96 struct iio_context_info ** iio_scan_result_add(
97 struct iio_scan_result *scan_result, size_t num)
98 {
99 struct iio_context_info **info;
100 size_t old_size, new_size;
101 size_t i;
102
103 old_size = scan_result->size;
104 new_size = old_size + num;
105
106 info = realloc(scan_result->info, (new_size + 1) * sizeof(*info));
107 if (!info)
108 return NULL;
109
110 scan_result->info = info;
111 scan_result->size = new_size;
112
113 for (i = old_size; i < new_size; i++) {
114 /* Make sure iio_context_info_list_free won't overflow */
115 info[i + 1] = NULL;
116
117 info[i] = zalloc(sizeof(**info));
118 if (!info[i])
119 return NULL;
120 }
121
122 return &info[old_size];
123 }
124
iio_create_scan_context(const char * backend,unsigned int flags)125 struct iio_scan_context * iio_create_scan_context(
126 const char *backend, unsigned int flags)
127 {
128 struct iio_scan_context *ctx;
129
130 /* "flags" must be zero for now */
131 if (flags != 0) {
132 errno = EINVAL;
133 return NULL;
134 }
135
136 ctx = calloc(1, sizeof(*ctx));
137 if (!ctx) {
138 errno = ENOMEM;
139 return NULL;
140 }
141
142 if (!backend || !strcmp(backend, "local"))
143 ctx->scan_local = true;
144
145 #ifdef WITH_USB_BACKEND
146 if (!backend || !strcmp(backend, "usb"))
147 ctx->usb_ctx = usb_context_scan_init();
148 #endif
149
150 return ctx;
151 }
152
iio_scan_context_destroy(struct iio_scan_context * ctx)153 void iio_scan_context_destroy(struct iio_scan_context *ctx)
154 {
155 #ifdef WITH_USB_BACKEND
156 if (ctx->usb_ctx)
157 usb_context_scan_free(ctx->usb_ctx);
158 #endif
159 free(ctx);
160 }
161
162 #ifdef WITH_MATLAB_BINDINGS_API
163
164 struct iio_scan_block {
165 struct iio_scan_context *ctx;
166 struct iio_context_info **info;
167 ssize_t ctx_cnt;
168 };
169
iio_scan_block_scan(struct iio_scan_block * blk)170 ssize_t iio_scan_block_scan(struct iio_scan_block *blk)
171 {
172 iio_context_info_list_free(blk->info);
173 blk->info = NULL;
174 blk->ctx_cnt = iio_scan_context_get_info_list(blk->ctx, &blk->info);
175 return blk->ctx_cnt;
176 }
177
iio_scan_block_get_info(struct iio_scan_block * blk,unsigned int index)178 struct iio_context_info *iio_scan_block_get_info(
179 struct iio_scan_block *blk, unsigned int index)
180 {
181 if (!blk->info || (ssize_t)index >= blk->ctx_cnt) {
182 errno = EINVAL;
183 return NULL;
184 }
185 return blk->info[index];
186 }
187
iio_create_scan_block(const char * backend,unsigned int flags)188 struct iio_scan_block *iio_create_scan_block(
189 const char *backend, unsigned int flags)
190 {
191 struct iio_scan_block *blk;
192
193 blk = calloc(1, sizeof(*blk));
194 if (!blk) {
195 errno = ENOMEM;
196 return NULL;
197 }
198
199 blk->ctx = iio_create_scan_context(backend, flags);
200 if (!blk->ctx) {
201 free(blk);
202 return NULL;
203 }
204
205 return blk;
206 }
207
iio_scan_block_destroy(struct iio_scan_block * blk)208 void iio_scan_block_destroy(struct iio_scan_block *blk)
209 {
210 iio_context_info_list_free(blk->info);
211 iio_scan_context_destroy(blk->ctx);
212 free(blk);
213 }
214 #endif
215