g_zero不能正常工作的调试笔记
使用friendly提供的2.26.32内核在micro2440平台上做linux usb gadget 测试时,发现g_zero.ko虽然可以加载,加载后也可以在电脑上认出设备,但是该设备不能正常工作,经过一天的调试和代码修改,终于使其可以正常工作了;
发现f_sourcesink.c中的enable_source_sink(。。。)函数中,usb_ep_enable函数返回参数是-22(-EINVAL;不正确的参数);该函数对应的源码为kernel/driver/usb/gadget/s3c2410_udc.c中的s3c2410_udc_ep_enable()函数;相关代码贴如下
static int s3c2410_udc_ep_enable(struct usb_ep *_ep,
const struct usb_endpoint_descriptor *desc)
{
struct s3c2410_udc *dev;
struct s3c2410_ep *ep;
u32 max, tmp;
unsigned long flags;
u32 csr1,csr2;
u32 int_en_reg;
ep = to_s3c2410_ep(_ep);
if (!_ep || !desc || ep->desc
|| _ep->name == ep0name
|| desc->bDescriptorType != USB_DT_ENDPOINT)
return -EINVAL;
其中!_ep||!Desc||_ep->name==ep0name确定为0,
则可能的原因在于ep->desc 或 desc->bDescriptorType != USB_DT_ENDPOINT
ep = to_s3c2410_ep(_ep);中函数 to_s3c2410_ep(。。。)的原型是
static inline struct s3c2410_ep *to_s3c2410_ep(struct usb_ep *ep)
{
return container_of(ep, struct s3c2410_ep, ep);
}
还有
struct s3c2410_ep {
struct list_head queue;
unsigned long last_io; /* jiffies timestamp */
struct usb_gadget *gadget;
struct s3c2410_udc *dev;
const struct usb_endpoint_descriptor *desc;
struct usb_ep ep;
u8 num;
unsigned short fifo_size;
u8 bEndpointAddress;
u8 bmAttributes;
unsigned halted : 1;
unsigned already_seen : 1;
unsigned setup_stage : 1;
};
如果是因为ep->desc,则说明是某处给s3c2410_ep赋值但没有清除,这个赋值可能不是我们主动做的而是系统函数做的;解决办法是在usb_ep_enable调用之前始终调用usb_ep_disable函数;
发现src = ep_choose(cdev->gadget, &hs_source_desc, &fs_source_desc);也会导致usb_ep_enable()出错,修改为sink=&fs_sink_desc;时可以解决问题(S3C2440的udc是full speed的,所以这样改不会出现问题),说明在速度判断方面也存在问题,需要进一步探讨。