Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to support option usb data in ep0 control command? #65

Closed
dukezuoHZ opened this issue Jan 5, 2024 · 14 comments
Closed

How to support option usb data in ep0 control command? #65

dukezuoHZ opened this issue Jan 5, 2024 · 14 comments

Comments

@dukezuoHZ
Copy link

Hi,
We need some customed usb request_type command from host pc and send to device by libusb in our project just like
char test_str = "hello,world!";
r=libusb_control_transfer(dev_handle,0xc0,0,0x33,0x44,(unsigned char
)test_str,strlen(test_str),1000);
usleep(10001000);
r=libusb_control_transfer(dev_handle,0x40,0,0x11,0x22,(unsigned char
)test_str,strlen(test_str),1000);
But i found i can't get the test data "hello,world!" in gadget.c, It print customed request_type index,value ok in case USB_TYPE_VENDOR of function ep0_request(), but I can't get extra data of control command from struct usb_ctrlrequest...
what can i do ?any advice will been appreciated,thanks!

@dukezuoHZ dukezuoHZ changed the title how to suport option data in epo setup steps? How to support option usb data in ep0 control command? Jan 5, 2024
@xairy
Copy link
Owner

xairy commented Jan 6, 2024

0xc0 has USB_DIR_IN (0x80) bit set, which makes it an IN request. So the host doesn't send data to the device but expects the device to send it. You need to use an OUT request if you want to send data to the device.

@xairy xairy closed this as completed Jan 6, 2024
@dukezuoHZ
Copy link
Author

thanks xairy,but I can't get data when used 0x40 too. how can i do?

@xairy
Copy link
Owner

xairy commented Jan 8, 2024

I would first make sure that the USB request is sent from the host as expected via usbmon.

How exactly does getting data fail for you? Do you get bad wLength from USB_RAW_IOCTL_EVENT_FETCH? Or does USB_RAW_IOCTL_EP0_READ fail?

@dukezuoHZ
Copy link
Author

the wLength received is ok, but when USB_RAW_IOCTL_EP0_READ is wrong,this is my source:
if (event.ctrl.bRequestType==0x40) //add by duke 2023.12.25
{
PTRACE("received customed command! 0x40");
if (ep0_cbFunc!=NULL) //customed command
{
usb_raw_ep0_read(usb_fd, (struct usb_raw_ep_io )&io);
PTRACE("epo read :%s",io.data);
ep0_cbFunc(ep0_cbArgs,event.ctrl.wIndex,event.ctrl.wValue,(char
)&io.data[0],event.ctrl.wLength);
}
}
else
{
rv = usb_raw_ep0_read(usb_fd, (struct usb_raw_ep_io *)&io);
printf("ep0: transferred %d bytes (out)\n", rv);
if (event.ctrl.wLength>0)
printf("read control %s\n",io.data[0]);
}
it will print info:
event: control, length: 8
bRequestType: 0x40 (OUT), bRequest: 0x0, wValue: 0x11, wIndex: 0x22, wLength: 12
type = USB_TYPE_VENDOR
req = unknown = 0x0
fail: no response USB_TYPE_VENDOR
11:21:59 : usb_gadget.cpp(968) received customed command! 0x40
ioctl(USB_RAW_IOCTL_EP0_READ): Invalid argument

@xairy
Copy link
Owner

xairy commented Jan 8, 2024

Invalid argument means there's something wrong with the arguments you provide to USB_RAW_IOCTL_EP0_READ. The code that you shared doesn't show that part, so I don't know what is wrong.

Enabling debug output as described here and potentially adding more debug messages into the USB_RAW_IOCTL_EP0_READ handler should help you figure out what's wrong.

@dukezuoHZ
Copy link
Author

dukezuoHZ commented Jan 9, 2024

ok,I give my full code here which refered from gadget.c:

void usb_gadget::ep0_loop() 
{
	PTRACE("*****enter ep0_read_loop******");
	while (usbRuning) 
	{
		struct usb_raw_control_event event;
		event.inner.type = 0;
		event.inner.length = sizeof(event.ctrl);

		usb_raw_event_fetch(usb_fd, (struct usb_raw_event *)&event);
		log_event((struct usb_raw_event *)&event);

		if (event.inner.type == USB_RAW_EVENT_CONNECT) {
			process_eps_info(usb_fd);
			continue;
		}

		if (event.inner.type != USB_RAW_EVENT_CONTROL)
			continue;

		struct usb_raw_control_io io;
		io.inner.ep = 0;
		io.inner.flags = 0;
		io.inner.length = 0;//event.ctrl.wLength;//0;

		bool reply = ep0_request(usb_fd, &event, &io);
		if (!reply) {
			printf("ep0: stalling\n");
			usb_raw_ep0_stall(usb_fd);
			continue;
		}

		if (event.ctrl.wLength < io.inner.length)
			io.inner.length = event.ctrl.wLength;

		int rv = -1;
#if 1
		if (event.ctrl.bRequestType & USB_DIR_IN) //to host
		{	
			if (event.ctrl.bRequestType==0xc0) //add by duke 2023.12.25
			{	
				PTRACE("received customed command! 0xc0");
				if (ep0_cbFunc!=NULL) //customed command
				{
					 //if (event.ctrl.wLength>0)
					// usb_raw_ep0_read(usb_fd, (struct usb_raw_ep_io *)&io);
					ep0_cbFunc(ep0_cbArgs,event.ctrl.wIndex,event.ctrl.wValue,(char *)&io.data[0],event.ctrl.wLength);
				}
			}
			//else
			{			
				rv = usb_raw_ep0_write(usb_fd, (struct usb_raw_ep_io *)&io);
				printf("ep0: transferred %d bytes (in)\n", rv);
			}
		} 
		else //to device 
		{
			if (event.ctrl.bRequestType==0x40) //add by duke 2023.12.25
			{	
				PTRACE("received customed command! 0x40");
				if (ep0_cbFunc!=NULL) //customed command
				{
					usb_raw_ep0_read(usb_fd, (struct usb_raw_ep_io *)&io);
					PTRACE("epo read :%s",io.data);
					ep0_cbFunc(ep0_cbArgs,event.ctrl.wIndex,event.ctrl.wValue,(char*)&io.data[0],event.ctrl.wLength);
				}
			}
			else
			{
				rv = usb_raw_ep0_read(usb_fd, (struct usb_raw_ep_io *)&io);
				printf("ep0: transferred %d bytes (out)\n", rv);			
				if (event.ctrl.wLength>0)
					printf("read control %s\n",io.data[0]);	
			}
		}
#else
		if (event.ctrl.bRequestType & USB_DIR_IN) {
			rv = usb_raw_ep0_write(usb_fd, (struct usb_raw_ep_io *)&io);
			printf("ep0: transferred %d bytes (in)\n", rv);
		} else {
			rv = usb_raw_ep0_read(usb_fd, (struct usb_raw_ep_io *)&io);
			printf("ep0: transferred %d bytes (out)\n", rv);
		}
#endif
		
		if ((event.ctrl.bRequestType & USB_TYPE_MASK) ==
				USB_TYPE_VENDOR &&
					event.ctrl.bRequest == VENDOR_REQ_OUT)
			memcpy(&vendor_buffer[0], &io.data[0], rv);
	}
	PTRACE("*****exit ep0_read_loop******");
}

@xairy
Copy link
Owner

xairy commented Jan 9, 2024

Do you initialize io->inner.length to be event.ctrl.wLength in ep0_request for your custom requests? If not, you need to do this.

If fixing this doesn't help, please enable the debug output for the Raw Gadget module and share the messages it prints to the kernel log.

@dukezuoHZ
Copy link
Author

thanks xairy, I can got "hello world!" ,it fee well. now when i add one code in ep0_request()
default:
io->inner.length = event->ctrl.wLength;//add by duke 2024.1.9
printf("fail: no response USB_TYPE_VENDOR\n");
//exit(EXIT_FAILURE);
break;

If i ack the usb control , How can i return usb_ctrlrequest data?

@dukezuoHZ
Copy link
Author

Hi,xairy,We used ctrl endpoint to chat with host PC,I have write a function send_ctrl_data(),but if i called ,crashed....I post my code file here.please help me review it.thanks a lot!
gadget_test.zip

@dukezuoHZ
Copy link
Author

to xairy: in our project,we need ep0 control channel to chat with pc for most customed command,We have done it ok in movidus platform,now we change device from movidus platform to nvidia platform

@xairy
Copy link
Owner

xairy commented Jan 12, 2024

Hi,xairy,We used ctrl endpoint to chat with host PC,I have write a function send_ctrl_data(),but if i called ,crashed....I post my code file here.please help me review it.thanks a lot!

I'd be happy to answer any Raw Gadget-related questions, but I don't have the throughput to debug crashes in your code unfortunately :(

If i ack the usb control , How can i return usb_ctrlrequest data?

If I understand your question correctly: When you fetch a USB_RAW_EVENT_CONNECT event, usb_ctrlrequest is provided in the data field of usb_raw_event. This happens before you ack the request via USB_RAW_IOCTL_EP0_WRITE/READ.

@dukezuoHZ
Copy link
Author

I have debug ok and it work now

@dukezuoHZ
Copy link
Author

but i find it work on usb2.0,not work usb3.0..... ^_^,print error:
event: control, length: 8
bRequestType: 0x0 (OUT), bRequest: 0x9, wValue: 0x1, wIndex: 0x0, wLength: 0
type = USB_TYPE_STANDARD
req = USB_REQ_SET_CONFIGURATION
ioctl(USB_RAW_IOCTL_EP_ENABLE): Invalid argument
bulk_out: ep = #-1

@xairy
Copy link
Owner

xairy commented Jan 12, 2024

Raw Gadget doesn't support USB 3, see #61. You can enable debugging output for the Raw Gadget module to see what exactly is failing. I would expect that the USB stack expects a USB endpoint companion descriptor, which Raw Gadget doesn't provide.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants