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 "../debug.h"
19 #include "../iio-private.h"
20 #include "ops.h"
21 #include "thread-pool.h"
22 
23 #include <fcntl.h>
24 #include <linux/usb/functionfs.h>
25 #include <stdint.h>
26 #include <string.h>
27 
28 /* u8"IIO" for non-c11 compilers */
29 #define NAME "\x0049\x0049\x004F"
30 
31 #define LE32(x) ((__BYTE_ORDER != __BIG_ENDIAN) ? (x) : __bswap_constant_32(x))
32 #define LE16(x) ((__BYTE_ORDER != __BIG_ENDIAN) ? (x) : __bswap_constant_16(x))
33 
34 #define IIO_USD_CMD_RESET_PIPES 0
35 #define IIO_USD_CMD_OPEN_PIPE 1
36 #define IIO_USD_CMD_CLOSE_PIPE 2
37 
38 
39 struct usb_ffs_header {
40 	struct usb_functionfs_descs_head_v2 header;
41 	uint32_t nb_fs, nb_hs, nb_ss;
42 } __attribute__((packed));
43 
44 struct usb_ffs_strings {
45 	struct usb_functionfs_strings_head head;
46 	uint16_t lang;
47 	const char string[sizeof(NAME)];
48 } __attribute__((packed));
49 
50 struct usbd_pdata {
51 	struct iio_context *ctx;
52 	char *ffs;
53 	int ep0_fd;
54 	bool debug, use_aio;
55 	struct thread_pool **pool;
56 	unsigned int nb_pipes;
57 };
58 
59 struct usbd_client_pdata {
60 	struct usbd_pdata *pdata;
61 	int ep_in, ep_out;
62 };
63 
64 static const struct usb_ffs_strings ffs_strings = {
65 	.head = {
66 		.magic = LE32(FUNCTIONFS_STRINGS_MAGIC),
67 		.length = LE32(sizeof(ffs_strings)),
68 		.str_count = LE32(1),
69 		.lang_count = LE32(1),
70 	},
71 
72 	.lang = LE16(0x409),
73 	.string = NAME,
74 };
75 
usbd_client_thread(struct thread_pool * pool,void * d)76 static void usbd_client_thread(struct thread_pool *pool, void *d)
77 {
78 	struct usbd_client_pdata *pdata = d;
79 
80 	interpreter(pdata->pdata->ctx, pdata->ep_in, pdata->ep_out,
81 			pdata->pdata->debug, false,
82 			pdata->pdata->use_aio, pool);
83 
84 	close(pdata->ep_in);
85 	close(pdata->ep_out);
86 	free(pdata);
87 }
88 
usb_open_pipe(struct usbd_pdata * pdata,unsigned int pipe_id)89 static int usb_open_pipe(struct usbd_pdata *pdata, unsigned int pipe_id)
90 {
91 	struct usbd_client_pdata *cpdata;
92 	char buf[256];
93 	int err;
94 
95 	if (pipe_id >= pdata->nb_pipes)
96 		return -EINVAL;
97 
98 	cpdata = malloc(sizeof(*cpdata));
99 	if (!pdata)
100 		return -ENOMEM;
101 
102 	/* Either we open this pipe for the first time, or it was closed before.
103 	 * In that case we called thread_pool_stop() without waiting for all the
104 	 * threads to finish. We do that here. Since the running thread might still
105 	 * have a open handle to the endpoints make sure that they have exited
106 	 * before opening the endpoints again. */
107 	thread_pool_stop_and_wait(pdata->pool[pipe_id]);
108 
109 	snprintf(buf, sizeof(buf), "%s/ep%u", pdata->ffs, pipe_id * 2 + 1);
110 	cpdata->ep_out = open(buf, O_WRONLY);
111 	if (cpdata->ep_out < 0) {
112 		err = -errno;
113 		goto err_free_cpdata;
114 	}
115 
116 	snprintf(buf, sizeof(buf), "%s/ep%u", pdata->ffs, pipe_id * 2 + 2);
117 	cpdata->ep_in = open(buf, O_RDONLY);
118 	if (cpdata->ep_in < 0) {
119 		err = -errno;
120 		goto err_close_ep_out;
121 	}
122 
123 	cpdata->pdata = pdata;
124 
125 	err = thread_pool_add_thread(pdata->pool[pipe_id],
126 			usbd_client_thread, cpdata, "usbd_client_thd");
127 	if (!err)
128 		return 0;
129 
130 	close(cpdata->ep_in);
131 err_close_ep_out:
132 	close(cpdata->ep_out);
133 err_free_cpdata:
134 	free(cpdata);
135 	return err;
136 }
137 
usb_close_pipe(struct usbd_pdata * pdata,unsigned int pipe_id)138 static int usb_close_pipe(struct usbd_pdata *pdata, unsigned int pipe_id)
139 {
140 	if (pipe_id >= pdata->nb_pipes)
141 		return -EINVAL;
142 
143 	thread_pool_stop(pdata->pool[pipe_id]);
144 	return 0;
145 }
146 
usb_close_pipes(struct usbd_pdata * pdata)147 static void usb_close_pipes(struct usbd_pdata *pdata)
148 {
149 	unsigned int i;
150 
151 	for (i = 0; i < pdata->nb_pipes; i++)
152 		usb_close_pipe(pdata, i);
153 }
154 
handle_event(struct usbd_pdata * pdata,const struct usb_functionfs_event * event)155 static int handle_event(struct usbd_pdata *pdata,
156 		const struct usb_functionfs_event *event)
157 {
158 	int ret = 0;
159 
160 	if (event->type == FUNCTIONFS_SETUP) {
161 		const struct usb_ctrlrequest *req = &event->u.setup;
162 
163 		switch (req->bRequest) {
164 		case IIO_USD_CMD_RESET_PIPES:
165 			usb_close_pipes(pdata);
166 			break;
167 		case IIO_USD_CMD_OPEN_PIPE:
168 			ret = usb_open_pipe(pdata, le16toh(req->wValue));
169 			break;
170 		case IIO_USD_CMD_CLOSE_PIPE:
171 			ret = usb_close_pipe(pdata, le16toh(req->wValue));
172 			break;
173 		}
174 	}
175 
176 	return ret;
177 }
178 
usbd_main(struct thread_pool * pool,void * d)179 static void usbd_main(struct thread_pool *pool, void *d)
180 {
181 	int stop_fd = thread_pool_get_poll_fd(pool);
182 	struct usbd_pdata *pdata = d;
183 	unsigned int i;
184 
185 	for (;;) {
186 		struct usb_functionfs_event event;
187 		struct pollfd pfd[2];
188 		int ret;
189 
190 		pfd[0].fd = pdata->ep0_fd;
191 		pfd[0].events = POLLIN;
192 		pfd[0].revents = 0;
193 		pfd[1].fd = stop_fd;
194 		pfd[1].events = POLLIN;
195 		pfd[1].revents = 0;
196 
197 		poll_nointr(pfd, 2);
198 
199 		if (pfd[1].revents & POLLIN) /* STOP event */
200 			break;
201 
202 		if (!(pfd[0].revents & POLLIN)) /* Should never happen. */
203 			continue;
204 
205 		ret = read(pdata->ep0_fd, &event, sizeof(event));
206 		if (ret != sizeof(event)) {
207 			WARNING("Short read!\n");
208 			continue;
209 		}
210 
211 		ret = handle_event(pdata, &event);
212 		if (ret) {
213 			ERROR("Unable to handle event: %i\n", ret);
214 			break;
215 		}
216 
217 		/* Clear out the errors on ep0 when we close endpoints */
218 		ret = read(pdata->ep0_fd, NULL, 0);
219 	}
220 
221 	for (i = 0; i < pdata->nb_pipes; i++) {
222 		thread_pool_stop_and_wait(pdata->pool[i]);
223 		thread_pool_destroy(pdata->pool[i]);
224 	}
225 
226 	close(pdata->ep0_fd);
227 	free(pdata->ffs);
228 	free(pdata->pool);
229 	free(pdata);
230 }
231 
create_header(unsigned int nb_pipes,uint32_t size)232 static struct usb_ffs_header * create_header(
233 		unsigned int nb_pipes, uint32_t size)
234 {
235 	/* Packet sizes for USB high-speed, full-speed, super-speed */
236 	const unsigned int packet_sizes[3] = { 64, 512, 1024, };
237 	struct usb_ffs_header *hdr;
238 	unsigned int i, pipe_id;
239 	uintptr_t ptr;
240 
241 	hdr = zalloc(size);
242 	if (!hdr) {
243 		errno = ENOMEM;
244 		return NULL;
245 	}
246 
247 	hdr->header.magic = LE32(FUNCTIONFS_DESCRIPTORS_MAGIC_V2);
248 	hdr->header.length = htole32(size);
249 	hdr->header.flags = LE32(FUNCTIONFS_HAS_FS_DESC |
250 			FUNCTIONFS_HAS_HS_DESC |
251 			FUNCTIONFS_HAS_SS_DESC);
252 
253 	hdr->nb_fs = htole32(nb_pipes * 2 + 1);
254 	hdr->nb_hs = htole32(nb_pipes * 2 + 1);
255 	hdr->nb_ss = htole32(nb_pipes * 4 + 1);
256 
257 	ptr = ((uintptr_t) hdr) + sizeof(*hdr);
258 
259 	for (i = 0; i < 3; i++) {
260 		struct usb_interface_descriptor *desc =
261 			(struct usb_interface_descriptor *) ptr;
262 		struct usb_endpoint_descriptor_no_audio *ep;
263 		struct usb_ss_ep_comp_descriptor *comp;
264 
265 		desc->bLength = sizeof(*desc);
266 		desc->bDescriptorType = USB_DT_INTERFACE;
267 		desc->bNumEndpoints = nb_pipes * 2;
268 		desc->bInterfaceClass = USB_CLASS_COMM;
269 		desc->iInterface = 1;
270 
271 		ep = (struct usb_endpoint_descriptor_no_audio *)
272 			(ptr + sizeof(*desc));
273 
274 		for (pipe_id = 0; pipe_id < nb_pipes; pipe_id++) {
275 			ep->bLength = sizeof(*ep);
276 			ep->bDescriptorType = USB_DT_ENDPOINT;
277 			ep->bEndpointAddress = (pipe_id + 1) | USB_DIR_IN;
278 			ep->bmAttributes = USB_ENDPOINT_XFER_BULK;
279 			ep->wMaxPacketSize = htole16(packet_sizes[i]);
280 			ep++;
281 
282 			if (i == 2) {
283 				comp = (struct usb_ss_ep_comp_descriptor *) ep;
284 				comp->bLength = USB_DT_SS_EP_COMP_SIZE;
285 				comp->bDescriptorType = USB_DT_SS_ENDPOINT_COMP;
286 				comp++;
287 				ep = (struct usb_endpoint_descriptor_no_audio *) comp;
288 			}
289 
290 			ep->bLength = sizeof(*ep);
291 			ep->bDescriptorType = USB_DT_ENDPOINT;
292 			ep->bEndpointAddress = (pipe_id + 1) | USB_DIR_OUT;
293 			ep->bmAttributes = USB_ENDPOINT_XFER_BULK;
294 			ep->wMaxPacketSize = htole16(packet_sizes[i]);
295 			ep++;
296 
297 			if (i == 2) {
298 				comp = (struct usb_ss_ep_comp_descriptor *) ep;
299 				comp->bLength = USB_DT_SS_EP_COMP_SIZE;
300 				comp->bDescriptorType = USB_DT_SS_ENDPOINT_COMP;
301 				comp++;
302 				ep = (struct usb_endpoint_descriptor_no_audio *) comp;
303 			}
304 		}
305 
306 		ptr += sizeof(*desc) + nb_pipes * 2 * sizeof(*ep);
307 	}
308 
309 	return hdr;
310 }
311 
write_header(int fd,unsigned int nb_pipes)312 static int write_header(int fd, unsigned int nb_pipes)
313 {
314 	uint32_t size = sizeof(struct usb_ffs_header) +
315 		3 * sizeof(struct usb_interface_descriptor) +
316 		6 * nb_pipes * sizeof(struct usb_endpoint_descriptor_no_audio) +
317 		2 * nb_pipes * sizeof(struct usb_ss_ep_comp_descriptor);
318 	struct usb_ffs_header *hdr;
319 	int ret;
320 
321 	hdr = create_header(nb_pipes, size);
322 	if (!hdr)
323 		return -errno;
324 
325 	ret = write(fd, hdr, size);
326 	free(hdr);
327 	if (ret < 0)
328 		return -errno;
329 
330 	ret = write(fd, &ffs_strings, sizeof(ffs_strings));
331 	if (ret < 0)
332 		return -errno;
333 
334 	return 0;
335 }
336 
start_usb_daemon(struct iio_context * ctx,const char * ffs,bool debug,bool use_aio,unsigned int nb_pipes,struct thread_pool * pool)337 int start_usb_daemon(struct iio_context *ctx, const char *ffs,
338 		bool debug, bool use_aio, unsigned int nb_pipes,
339 		struct thread_pool *pool)
340 {
341 	struct usbd_pdata *pdata;
342 	unsigned int i;
343 	char buf[256];
344 	int ret;
345 
346 	pdata = zalloc(sizeof(*pdata));
347 	if (!pdata)
348 		return -ENOMEM;
349 
350 	pdata->nb_pipes = nb_pipes;
351 
352 	pdata->pool = calloc(nb_pipes, sizeof(*pdata->pool));
353 	if (!pdata->pool) {
354 		ret = -ENOMEM;
355 		goto err_free_pdata;
356 	}
357 
358 	pdata->ffs = strdup(ffs);
359 	if (!pdata->ffs) {
360 		ret = -ENOMEM;
361 		goto err_free_pdata_pool;
362 	}
363 
364 	snprintf(buf, sizeof(buf), "%s/ep0", ffs);
365 
366 	pdata->ep0_fd = open(buf, O_RDWR);
367 	if (pdata->ep0_fd < 0) {
368 		ret = -errno;
369 		goto err_free_ffs;
370 	}
371 
372 	ret = write_header(pdata->ep0_fd, nb_pipes);
373 	if (ret < 0)
374 		goto err_close_ep0;
375 
376 	for (i = 0; i < nb_pipes; i++) {
377 		pdata->pool[i] = thread_pool_new();
378 		if (!pdata->pool[i]) {
379 			ret = -errno;
380 			goto err_free_pools;
381 		}
382 	}
383 
384 	pdata->ctx = ctx;
385 	pdata->debug = debug;
386 	pdata->use_aio = use_aio;
387 
388 	ret = thread_pool_add_thread(pool, usbd_main, pdata, "usbd_main_thd");
389 	if (!ret)
390 		return 0;
391 
392 err_free_pools:
393 	/* If we get here, usbd_main was not started, so the pools can be
394 	 * destroyed directly */
395 	for (i = 0; i < nb_pipes; i++) {
396 		if (pdata->pool[i])
397 			thread_pool_destroy(pdata->pool[i]);
398 	}
399 err_close_ep0:
400 	close(pdata->ep0_fd);
401 err_free_ffs:
402 	free(pdata->ffs);
403 err_free_pdata_pool:
404 	free(pdata->pool);
405 err_free_pdata:
406 	free(pdata);
407 	return ret;
408 }
409