Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / tools / usb / ffs-aio-example / multibuff / device_app / aio_multibuff.c
1 /*
2  * This is free and unencumbered software released into the public domain.
3  *
4  * Anyone is free to copy, modify, publish, use, compile, sell, or
5  * distribute this software, either in source code form or as a compiled
6  * binary, for any purpose, commercial or non-commercial, and by any
7  * means.
8  *
9  * In jurisdictions that recognize copyright laws, the author or authors
10  * of this software dedicate any and all copyright interest in the
11  * software to the public domain. We make this dedication for the benefit
12  * of the public at large and to the detriment of our heirs and
13  * successors. We intend this dedication to be an overt act of
14  * relinquishment in perpetuity of all present and future rights to this
15  * software under copyright law.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23  * OTHER DEALINGS IN THE SOFTWARE.
24  *
25  * For more information, please refer to <http://unlicense.org/>
26  */
27
28 #define _BSD_SOURCE /* for endian.h */
29
30 #include <endian.h>
31 #include <errno.h>
32 #include <fcntl.h>
33 #include <stdarg.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <sys/ioctl.h>
38 #include <sys/stat.h>
39 #include <sys/types.h>
40 #include <sys/poll.h>
41 #include <unistd.h>
42 #include <stdbool.h>
43 #include <sys/eventfd.h>
44
45 #include "libaio.h"
46 #define IOCB_FLAG_RESFD         (1 << 0)
47
48 #include <linux/usb/functionfs.h>
49
50 #define BUF_LEN         8192
51 #define BUFS_MAX        128
52 #define AIO_MAX         (BUFS_MAX*2)
53
54 /******************** Descriptors and Strings *******************************/
55
56 static const struct {
57         struct usb_functionfs_descs_head_v2 header;
58         __le32 fs_count;
59         __le32 hs_count;
60         struct {
61                 struct usb_interface_descriptor intf;
62                 struct usb_endpoint_descriptor_no_audio bulk_sink;
63                 struct usb_endpoint_descriptor_no_audio bulk_source;
64         } __attribute__ ((__packed__)) fs_descs, hs_descs;
65 } __attribute__ ((__packed__)) descriptors = {
66         .header = {
67                 .magic = htole32(FUNCTIONFS_DESCRIPTORS_MAGIC_V2),
68                 .flags = htole32(FUNCTIONFS_HAS_FS_DESC |
69                                      FUNCTIONFS_HAS_HS_DESC),
70                 .length = htole32(sizeof(descriptors)),
71         },
72         .fs_count = htole32(3),
73         .fs_descs = {
74                 .intf = {
75                         .bLength = sizeof(descriptors.fs_descs.intf),
76                         .bDescriptorType = USB_DT_INTERFACE,
77                         .bNumEndpoints = 2,
78                         .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
79                         .iInterface = 1,
80                 },
81                 .bulk_sink = {
82                         .bLength = sizeof(descriptors.fs_descs.bulk_sink),
83                         .bDescriptorType = USB_DT_ENDPOINT,
84                         .bEndpointAddress = 1 | USB_DIR_IN,
85                         .bmAttributes = USB_ENDPOINT_XFER_BULK,
86                 },
87                 .bulk_source = {
88                         .bLength = sizeof(descriptors.fs_descs.bulk_source),
89                         .bDescriptorType = USB_DT_ENDPOINT,
90                         .bEndpointAddress = 2 | USB_DIR_OUT,
91                         .bmAttributes = USB_ENDPOINT_XFER_BULK,
92                 },
93         },
94         .hs_count = htole32(3),
95         .hs_descs = {
96                 .intf = {
97                         .bLength = sizeof(descriptors.hs_descs.intf),
98                         .bDescriptorType = USB_DT_INTERFACE,
99                         .bNumEndpoints = 2,
100                         .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
101                         .iInterface = 1,
102                 },
103                 .bulk_sink = {
104                         .bLength = sizeof(descriptors.hs_descs.bulk_sink),
105                         .bDescriptorType = USB_DT_ENDPOINT,
106                         .bEndpointAddress = 1 | USB_DIR_IN,
107                         .bmAttributes = USB_ENDPOINT_XFER_BULK,
108                         .wMaxPacketSize = htole16(512),
109                 },
110                 .bulk_source = {
111                         .bLength = sizeof(descriptors.hs_descs.bulk_source),
112                         .bDescriptorType = USB_DT_ENDPOINT,
113                         .bEndpointAddress = 2 | USB_DIR_OUT,
114                         .bmAttributes = USB_ENDPOINT_XFER_BULK,
115                         .wMaxPacketSize = htole16(512),
116                 },
117         },
118 };
119
120 #define STR_INTERFACE "AIO Test"
121
122 static const struct {
123         struct usb_functionfs_strings_head header;
124         struct {
125                 __le16 code;
126                 const char str1[sizeof(STR_INTERFACE)];
127         } __attribute__ ((__packed__)) lang0;
128 } __attribute__ ((__packed__)) strings = {
129         .header = {
130                 .magic = htole32(FUNCTIONFS_STRINGS_MAGIC),
131                 .length = htole32(sizeof(strings)),
132                 .str_count = htole32(1),
133                 .lang_count = htole32(1),
134         },
135         .lang0 = {
136                 htole16(0x0409), /* en-us */
137                 STR_INTERFACE,
138         },
139 };
140
141 /********************** Buffer structure *******************************/
142
143 struct io_buffer {
144         struct iocb **iocb;
145         unsigned char **buf;
146         unsigned cnt;
147         unsigned len;
148         unsigned requested;
149 };
150
151 /******************** Endpoints handling *******************************/
152
153 static void display_event(struct usb_functionfs_event *event)
154 {
155         static const char *const names[] = {
156                 [FUNCTIONFS_BIND] = "BIND",
157                 [FUNCTIONFS_UNBIND] = "UNBIND",
158                 [FUNCTIONFS_ENABLE] = "ENABLE",
159                 [FUNCTIONFS_DISABLE] = "DISABLE",
160                 [FUNCTIONFS_SETUP] = "SETUP",
161                 [FUNCTIONFS_SUSPEND] = "SUSPEND",
162                 [FUNCTIONFS_RESUME] = "RESUME",
163         };
164         switch (event->type) {
165         case FUNCTIONFS_BIND:
166         case FUNCTIONFS_UNBIND:
167         case FUNCTIONFS_ENABLE:
168         case FUNCTIONFS_DISABLE:
169         case FUNCTIONFS_SETUP:
170         case FUNCTIONFS_SUSPEND:
171         case FUNCTIONFS_RESUME:
172                 printf("Event %s\n", names[event->type]);
173         }
174 }
175
176 static void handle_ep0(int ep0, bool *ready)
177 {
178         int ret;
179         struct usb_functionfs_event event;
180
181         ret = read(ep0, &event, sizeof(event));
182         if (!ret) {
183                 perror("unable to read event from ep0");
184                 return;
185         }
186         display_event(&event);
187         switch (event.type) {
188         case FUNCTIONFS_SETUP:
189                 if (event.u.setup.bRequestType & USB_DIR_IN)
190                         write(ep0, NULL, 0);
191                 else
192                         read(ep0, NULL, 0);
193                 break;
194
195         case FUNCTIONFS_ENABLE:
196                 *ready = true;
197                 break;
198
199         case FUNCTIONFS_DISABLE:
200                 *ready = false;
201                 break;
202
203         default:
204                 break;
205         }
206 }
207
208 void init_bufs(struct io_buffer *iobuf, unsigned n, unsigned len)
209 {
210         unsigned i;
211         iobuf->buf = malloc(n*sizeof(*iobuf->buf));
212         iobuf->iocb = malloc(n*sizeof(*iobuf->iocb));
213         iobuf->cnt = n;
214         iobuf->len = len;
215         iobuf->requested = 0;
216         for (i = 0; i < n; ++i) {
217                 iobuf->buf[i] = malloc(len*sizeof(**iobuf->buf));
218                 iobuf->iocb[i] = malloc(sizeof(**iobuf->iocb));
219         }
220         iobuf->cnt = n;
221 }
222
223 void delete_bufs(struct io_buffer *iobuf)
224 {
225         unsigned i;
226         for (i = 0; i < iobuf->cnt; ++i) {
227                 free(iobuf->buf[i]);
228                 free(iobuf->iocb[i]);
229         }
230         free(iobuf->buf);
231         free(iobuf->iocb);
232 }
233
234 int main(int argc, char *argv[])
235 {
236         int ret;
237         unsigned i, j;
238         char *ep_path;
239
240         int ep0, ep1;
241
242         io_context_t ctx;
243
244         int evfd;
245         fd_set rfds;
246
247         struct io_buffer iobuf[2];
248         int actual = 0;
249         bool ready;
250
251         if (argc != 2) {
252                 printf("ffs directory not specified!\n");
253                 return 1;
254         }
255
256         ep_path = malloc(strlen(argv[1]) + 4 /* "/ep#" */ + 1 /* '\0' */);
257         if (!ep_path) {
258                 perror("malloc");
259                 return 1;
260         }
261
262         /* open endpoint files */
263         sprintf(ep_path, "%s/ep0", argv[1]);
264         ep0 = open(ep_path, O_RDWR);
265         if (ep0 < 0) {
266                 perror("unable to open ep0");
267                 return 1;
268         }
269         if (write(ep0, &descriptors, sizeof(descriptors)) < 0) {
270                 perror("unable do write descriptors");
271                 return 1;
272         }
273         if (write(ep0, &strings, sizeof(strings)) < 0) {
274                 perror("unable to write strings");
275                 return 1;
276         }
277         sprintf(ep_path, "%s/ep1", argv[1]);
278         ep1 = open(ep_path, O_RDWR);
279         if (ep1 < 0) {
280                 perror("unable to open ep1");
281                 return 1;
282         }
283
284         free(ep_path);
285
286         memset(&ctx, 0, sizeof(ctx));
287         /* setup aio context to handle up to AIO_MAX requests */
288         if (io_setup(AIO_MAX, &ctx) < 0) {
289                 perror("unable to setup aio");
290                 return 1;
291         }
292
293         evfd = eventfd(0, 0);
294         if (evfd < 0) {
295                 perror("unable to open eventfd");
296                 return 1;
297         }
298
299         for (i = 0; i < sizeof(iobuf)/sizeof(*iobuf); ++i)
300                 init_bufs(&iobuf[i], BUFS_MAX, BUF_LEN);
301
302         while (1) {
303                 FD_ZERO(&rfds);
304                 FD_SET(ep0, &rfds);
305                 FD_SET(evfd, &rfds);
306
307                 ret = select(((ep0 > evfd) ? ep0 : evfd)+1,
308                              &rfds, NULL, NULL, NULL);
309                 if (ret < 0) {
310                         if (errno == EINTR)
311                                 continue;
312                         perror("select");
313                         break;
314                 }
315
316                 if (FD_ISSET(ep0, &rfds))
317                         handle_ep0(ep0, &ready);
318
319                 /* we are waiting for function ENABLE */
320                 if (!ready)
321                         continue;
322
323                 /*
324                  * when we're preparing new data to submit,
325                  * second buffer being transmitted
326                  */
327                 for (i = 0; i < sizeof(iobuf)/sizeof(*iobuf); ++i) {
328                         if (iobuf[i].requested)
329                                 continue;
330                         /* prepare requests */
331                         for (j = 0; j < iobuf[i].cnt; ++j) {
332                                 io_prep_pwrite(iobuf[i].iocb[j], ep1,
333                                                iobuf[i].buf[j],
334                                                iobuf[i].len, 0);
335                                 /* enable eventfd notification */
336                                 iobuf[i].iocb[j]->u.c.flags |= IOCB_FLAG_RESFD;
337                                 iobuf[i].iocb[j]->u.c.resfd = evfd;
338                         }
339                         /* submit table of requests */
340                         ret = io_submit(ctx, iobuf[i].cnt, iobuf[i].iocb);
341                         if (ret >= 0) {
342                                 iobuf[i].requested = ret;
343                                 printf("submit: %d requests buf: %d\n", ret, i);
344                         } else
345                                 perror("unable to submit requests");
346                 }
347
348                 /* if event is ready to read */
349                 if (!FD_ISSET(evfd, &rfds))
350                         continue;
351
352                 uint64_t ev_cnt;
353                 ret = read(evfd, &ev_cnt, sizeof(ev_cnt));
354                 if (ret < 0) {
355                         perror("unable to read eventfd");
356                         break;
357                 }
358
359                 struct io_event e[BUFS_MAX];
360                 /* we read aio events */
361                 ret = io_getevents(ctx, 1, BUFS_MAX, e, NULL);
362                 if (ret > 0) /* if we got events */
363                         iobuf[actual].requested -= ret;
364
365                 /* if all req's from iocb completed */
366                 if (!iobuf[actual].requested)
367                         actual = (actual + 1)%(sizeof(iobuf)/sizeof(*iobuf));
368         }
369
370         /* free resources */
371
372         for (i = 0; i < sizeof(iobuf)/sizeof(*iobuf); ++i)
373                 delete_bufs(&iobuf[i]);
374         io_destroy(ctx);
375
376         close(ep1);
377         close(ep0);
378
379         return 0;
380 }