sh_eth: fix EESIPR values for SH77{34|63}
[linux/fpc-iii.git] / tools / usb / ffs-aio-example / multibuff / device_app / aio_multibuff.c
blobaaca1f44e7886011be0043e9a2ae062a42be06e7
1 /*
2 * This is free and unencumbered software released into the public domain.
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.
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.
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.
25 * For more information, please refer to <http://unlicense.org/>
28 #define _BSD_SOURCE /* for endian.h */
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>
45 #include "libaio.h"
46 #define IOCB_FLAG_RESFD (1 << 0)
48 #include <linux/usb/functionfs.h>
50 #define BUF_LEN 8192
51 #define BUFS_MAX 128
52 #define AIO_MAX (BUFS_MAX*2)
54 /******************** Descriptors and Strings *******************************/
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)),
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,
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,
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,
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,
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),
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),
120 #define STR_INTERFACE "AIO Test"
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),
135 .lang0 = {
136 htole16(0x0409), /* en-us */
137 STR_INTERFACE,
141 /********************** Buffer structure *******************************/
143 struct io_buffer {
144 struct iocb **iocb;
145 unsigned char **buf;
146 unsigned cnt;
147 unsigned len;
148 unsigned requested;
151 /******************** Endpoints handling *******************************/
153 static void display_event(struct usb_functionfs_event *event)
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",
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]);
176 static void handle_ep0(int ep0, bool *ready)
178 int ret;
179 struct usb_functionfs_event event;
181 ret = read(ep0, &event, sizeof(event));
182 if (!ret) {
183 perror("unable to read event from ep0");
184 return;
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;
195 case FUNCTIONFS_ENABLE:
196 *ready = true;
197 break;
199 case FUNCTIONFS_DISABLE:
200 *ready = false;
201 break;
203 default:
204 break;
208 void init_bufs(struct io_buffer *iobuf, unsigned n, unsigned len)
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));
220 iobuf->cnt = n;
223 void delete_bufs(struct io_buffer *iobuf)
225 unsigned i;
226 for (i = 0; i < iobuf->cnt; ++i) {
227 free(iobuf->buf[i]);
228 free(iobuf->iocb[i]);
230 free(iobuf->buf);
231 free(iobuf->iocb);
234 int main(int argc, char *argv[])
236 int ret;
237 unsigned i, j;
238 char *ep_path;
240 int ep0, ep1;
242 io_context_t ctx;
244 int evfd;
245 fd_set rfds;
247 struct io_buffer iobuf[2];
248 int actual = 0;
249 bool ready;
251 if (argc != 2) {
252 printf("ffs directory not specified!\n");
253 return 1;
256 ep_path = malloc(strlen(argv[1]) + 4 /* "/ep#" */ + 1 /* '\0' */);
257 if (!ep_path) {
258 perror("malloc");
259 return 1;
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;
269 if (write(ep0, &descriptors, sizeof(descriptors)) < 0) {
270 perror("unable do write descriptors");
271 return 1;
273 if (write(ep0, &strings, sizeof(strings)) < 0) {
274 perror("unable to write strings");
275 return 1;
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;
284 free(ep_path);
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;
293 evfd = eventfd(0, 0);
294 if (evfd < 0) {
295 perror("unable to open eventfd");
296 return 1;
299 for (i = 0; i < sizeof(iobuf)/sizeof(*iobuf); ++i)
300 init_bufs(&iobuf[i], BUFS_MAX, BUF_LEN);
302 while (1) {
303 FD_ZERO(&rfds);
304 FD_SET(ep0, &rfds);
305 FD_SET(evfd, &rfds);
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;
316 if (FD_ISSET(ep0, &rfds))
317 handle_ep0(ep0, &ready);
319 /* we are waiting for function ENABLE */
320 if (!ready)
321 continue;
324 * when we're preparing new data to submit,
325 * second buffer being transmitted
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;
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");
348 /* if event is ready to read */
349 if (!FD_ISSET(evfd, &rfds))
350 continue;
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;
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;
365 /* if all req's from iocb completed */
366 if (!iobuf[actual].requested)
367 actual = (actual + 1)%(sizeof(iobuf)/sizeof(*iobuf));
370 /* free resources */
372 for (i = 0; i < sizeof(iobuf)/sizeof(*iobuf); ++i)
373 delete_bufs(&iobuf[i]);
374 io_destroy(ctx);
376 close(ep1);
377 close(ep0);
379 return 0;