On Wed, Jan 29 2014, Robert Baldyga wrote: > +++ b/tools/usb/aio_multibuff/device_app/aio_multibuff.c > +#define BUF_LEN 8192 > +#define BUFS_MAX 128 > +#define AIO_MAX (BUFS_MAX*2) > + > +struct iocb *iocb1[AIO_MAX]; > +struct iocb *iocb2[AIO_MAX]; > + > +unsigned char *buf1[BUFS_MAX]; > +unsigned char *buf2[BUFS_MAX]; Why are there twice as many iocb structures as there are buffers? > +static void display_event(struct usb_functionfs_event *event) > +{ > + static const char *const names[] = { > + [FUNCTIONFS_BIND] = "BIND", > + [FUNCTIONFS_UNBIND] = "UNBIND", > + [FUNCTIONFS_ENABLE] = "ENABLE", > + [FUNCTIONFS_DISABLE] = "DISABLE", > + [FUNCTIONFS_SETUP] = "SETUP", > + [FUNCTIONFS_SUSPEND] = "SUSPEND", > + [FUNCTIONFS_RESUME] = "RESUME", > + }; > + switch (event->type) { > + case FUNCTIONFS_BIND: > + case FUNCTIONFS_UNBIND: > + case FUNCTIONFS_ENABLE: > + case FUNCTIONFS_DISABLE: > + case FUNCTIONFS_SETUP: > + case FUNCTIONFS_SUSPEND: > + case FUNCTIONFS_RESUME: > + printf("Event %s\n", names[event->type]); > + default: > + break; > + } Weird indent level throughout the function. > +} > + > +static void handle_ep0(int ep0, bool *ready) > +{ > + struct usb_functionfs_event event; > + int ret; > + > + struct pollfd pfds[1]; > + pfds[0].fd = ep0; > + pfds[0].events = POLLIN; > + > + ret = poll(pfds, 1, 0); > + > + if (ret && (pfds[0].revents & POLLIN)) { > + ret = read(ep0, &event, sizeof(struct usb_functionfs_event)); ret = read(ep0, &event, sizeof(event)); > + if (!ret) > + return; At the very least call perror. > + display_event(&event); > + switch (event.type) { > + case FUNCTIONFS_SETUP: > + if (event.u.setup.bRequestType & USB_DIR_IN) > + write(ep0, NULL, 0); > + else > + read(ep0, NULL, 0); > + break; > + > + case FUNCTIONFS_ENABLE: > + *ready = true; > + break; > + > + case FUNCTIONFS_DISABLE: > + *ready = false; > + break; > + > + default: > + break; > + } > + } > +} > +int main(int argc, char *argv[]) > +{ > + int i, ret; > + char ep_path[64]; Better yet, allocate this dynamically. Just before the first snprintf. > + > + int ep0, ep1; > + > + io_context_t ctx; > + > + int requested1 = 0, requested2 = 0; > + int actual; > + bool ready; > + > + if (argc != 2) { > + printf("ffs directory not specified!\n"); > + return 1; > + } > + > + /* open endpoint files */ ep_path = malloc(strlen(argv[1]) + 4 /* "/ep#" */ + 1 /* '\0' */); if (!ep_path) { perror("malloc"); return 1; } At this point you could get away with sprintf. > + snprintf(ep_path, sizeof(ep_path), "%s/ep0", argv[1]); > + ep0 = open(ep_path, O_RDWR); > + if (ep0 < 0) { > + perror("unable to open ep0"); > + return 1; > + } > + if (write(ep0, &descriptors, sizeof(descriptors)) < 0) { > + perror("unable do write descriptors"); > + return 1; > + } > + if (write(ep0, &strings, sizeof(strings)) < 0) { > + perror("unable to write strings"); > + return 1; > + } > + snprintf(ep_path, sizeof(ep_path), "%s/ep1", argv[1]); > + ep1 = open(ep_path, O_RDWR); > + if (ep1 < 0) { > + perror("unable to open ep1"); > + return 1; > + } > + > + memset(&ctx, 0, sizeof(ctx)); > + /* setup aio context to handle up to AIO_MAX requests */ > + io_setup(AIO_MAX, &ctx); > + > + init_bufs(); > + > + while (1) { > + handle_ep0(ep0, &ready); > + /* we are waiting for function ENABLE */ > + if (!ready) > + continue; > + /* > + * when we're preparing new data to submit, > + * second buffer being transmitted > + */ > + if (!requested1) { /* if all req's from iocb1 completed */ > + actual = 2; > + for (i = 0; i < BUFS_MAX; ++i) /* prepare requests */ > + io_prep_pwrite(iocb1[i], ep1, buf1[i], > + BUF_LEN, 0); > + /* submit table of requests */ > + ret = io_submit(ctx, BUFS_MAX, iocb1); > + requested1 = ret; > + printf("submit: %d requests from buf 1\n", ret); > + } > + if (!requested2) { /* if all req's from iocb2 completed */ > + actual = 1; > + for (i = 0; i < BUFS_MAX; ++i) /* prepare requests */ > + io_prep_pwrite(iocb2[i], ep1, buf2[i], > + BUF_LEN, 0); > + /* submit table of requests */ > + ret = io_submit(ctx, BUFS_MAX, iocb2); > + requested2 = ret; > + printf("submit: %d requests from buf 2\n", ret); > + } > + /* if something was submitted we wait for event */ > + if (requested1 || requested2) { > + struct io_event e; > + struct timespec timeout = {0, 1000}; > + /* we wait for one event */ > + ret = io_getevents(ctx, 1, 1, &e, &timeout); What's the purpose of the timeout? > + if (ret > 0) { /* if we got event */ > + if (actual == 1) > + requested1--; > + else > + requested2--; > + } This whole loop would look cleaner if buf, iocb and requested variables were two-element arrays. Or better yet, if you had a structure with a buffer, iocb and requested count. With a structure, you could easily go away without a global variables, if init_bufs and delete_bufs took the structure as an argument. > + } > + } > + > + /* free resources */ > + > + delete_bufs(); > + io_destroy(ctx); > + > + close(ep1); > + close(ep0); > + > + return 0; > +} Haven't looked at the other files. -- Best regards, _ _ .o. | Liege of Serenely Enlightened Majesty of o' \,=./ `o ..o | Computer Science, Michał “mina86” Nazarewicz (o o) ooo +--<mpn@xxxxxxxxxx>--<xmpp:mina86@xxxxxxxxxx>--ooO--(_)--Ooo--
Attachment:
signature.asc
Description: PGP signature