Re: [PATCH] tools: usb: aio example applications

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Jan 28 2014, Robert Baldyga wrote:
> diff --git a/tools/usb/aio_multibuff/device_app/aio_multibuff.c b/tools/usb/aio_multibuff/device_app/aio_multibuff.c
> new file mode 100644
> index 0000000..df1db84
> --- /dev/null
> +++ b/tools/usb/aio_multibuff/device_app/aio_multibuff.c

> +#define USBFFS_DIR	"usbffs/"

Uh?

> +int ready = 0;

static bool ready;

> +
> +static void handle_ep0(int ep0) {
> +	struct usb_functionfs_event event;
> +	int ret;
> +
> +	struct pollfd pfds[1];
> +	pfds[0].fd = ep0;
> +	pfds[0].events = POLLIN;
> +
> +	poll(pfds, 1, 0);

You should check return code of the function.

> +
> +	if((pfds[0].revents & POLLIN)) {
> +		ret = read(ep0, &event, sizeof(struct usb_functionfs_event));
> +		if(!ret)
> +			return;
> +		display_event(&event);
> +		if (event.type == FUNCTIONFS_SETUP) {
> +			if (event.u.setup.bRequestType & USB_DIR_IN)
> +				write(ep0, NULL, 0);
> +			else
> +				read(ep0, NULL, 0);
> +		}
> +		if (event.type == FUNCTIONFS_ENABLE)

+		} else if (event.type == FUNCTIONFS_ENABLE) {

It's more obvious what's happening here with else-if.

> +			ready = 1;

+		}

Furthermore, you should also handle FUNCTIONFS_DISABLE.

> +	}
> +}
> +
> +#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[AIO_MAX];
> +unsigned char *buf2[AIO_MAX];

Only half of those buffers are initialised in init_buffs.

> +
> +void init_bufs() {
> +	int i, j;
> +	for (i=0; i<BUFS_MAX; ++i) {

	for (i = 0; i < sizeof(buf1) / sizeof(*buf1); ++i) {

Applies for all other for loops.

> +		buf1[i] = malloc(BUF_LEN);
> +		buf2[i] = malloc(BUF_LEN);
> +		for (j=0; j<BUF_LEN; ++j) {
> +			buf1[i][j] = j%64;
> +			buf2[i][j] = j%64;

Is “% 64” really needed here for anything?  Why not let it wrap around
256 automatically?

> +		}
> +	}
> +	for (i=0; i<AIO_MAX; ++i) {
> +		iocb1[i] = malloc(sizeof(struct iocb));
> +		iocb2[i] = malloc(sizeof(struct iocb));

+		iocb1[i] = malloc(sizeof(**iocb1));
+		iocb2[i] = malloc(sizeof(**iocb2));

> +	}
> +}

> +int main() {
> +	int i, ret;
> +	char ep_path[64];

Magic number.  “char ep_path[sizeof(USBFFS_DIR) + 3 /* ep# */];” would
be much better.

> +
> +	int ep0;
> +	int ep[2];
> +
> +	io_context_t ctx;
> +
> +	int requested1 = 0;
> +	int requested2 = 0;
> +
> +	/* open endpoint files */
> +	if((ep0 = open(USBFFS_DIR"ep0", O_RDWR)) < 0) printf("unable to open ep0\n");

USBFFS_DIR should be taken as argument or assumed to be “./”.  Why
“usbffs/”? What if someone wished to mount two FFS gadgets and run this
program twice.

> +	if(write(ep0, (void*)&descriptors, sizeof descriptors) < 0) printf("unable do write descriptors\n");
> +	if(write(ep0, (void*)&strings, sizeof strings) < 0) printf("unable to write strings\n");

This is C, there's no need to cast to (void *).
Also, you should probably “return 1” on error instead of continuing, not
to mention that it would be nice to actually see the returned code.
perror may be your friend here.  Applies to other places as well.

> +	for(i=0; i<2; ++i) {
> +		sprintf(ep_path, USBFFS_DIR"ep%d", i+1);

snprintf!

> +		if((ep[i] = open(ep_path, O_RDWR | O_NONBLOCK, 0)) < 0)
> +			printf("unable to open ep%d\n", i+1);
> +	}
> +
> +	memset(&ctx, 0, sizeof(ctx));
> +	io_setup(AIO_MAX, &ctx); /* setup aio context to handle up to AIO_MAX requests */
> +
> +	init_bufs();
> +
> +	while(1) {
> +		handle_ep0(ep0);
> +		/* we are waiting for function ENABLE */
> +		if(!ready) continue;

It would be much better if handle_ep0 took pointer to ready as an
argument.  This would avoid unnecessary global variable.

> +		/*
> +		 * when we're preparing new data to submit,
> +		 * second buffer being transmitted
> +		 */
> +		if (!requested1) { /* if all req's from iocb1 completed */
> +			for(i=0; i<BUFS_MAX; ++i) /* prepare requests */
> +				io_prep_pwrite(iocb1[i], ep[0], 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 */
> +			for(i=0; i<BUFS_MAX; ++i) /* prepare requests */
> +				io_prep_pwrite(iocb2[i], ep[0], 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);
> +			if(ret > 0) { /* if we got event */
> +				if (e.obj->aio_fildes == ep[0])
> +					requested1--;
> +				if (e.obj->aio_fildes == ep[1])
> +					requested2--;
> +			}
> +		}
> +	}
> +
> +	/* free resources */
> +
> +	delete_bufs();
> +	io_destroy(ctx);
> +
> +	for(i=0; i<2; ++i) close(ep[i]);
> +	close(ep0);
> +
> +	return 0;
> +}

Haven't looked at any 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


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux