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

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

 



Hi,
On 01/29/2014 01:39 PM, Michal Nazarewicz wrote:
> 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?

It's mistake. AIO_MAX should be used only for io_setup.

> 
> 
>> +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?

io_getevents is blocking with timeout==NULL, but we want to do something
in meantime (at least handle ep0 events).

> 
>> +			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.
> 
> 
> 

Thanks for advices, I will fix it.

Best regards
Robert Baldyga
Samsung R&D Institute Poland

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




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

  Powered by Linux