f_sourcesink.c里面在执行set_alt方法后就调用source_sink_start_ep(),这里面就有usb_ep_queue()可以认为开始进行数据交互。后期我要改一下这个过程,通过一个简单的misc驱动去分开调用接受发送
我们现在看
static int source_sink_start_ep(struct f_sourcesink *ss,boolis_in)
{
structusb_ep *ep;
structusb_request *req;
int status;
ep = is_in ? ss->in_ep :ss->out_ep;
//是in还是out,
req = alloc_ep_req(ep);
if(!req)
return-ENOMEM;
req->complete =source_sink_complete;//下面来说
if(is_in)// 这里要说的就是in是对于主机来说
reinit_write_data(ep, req);//把数据写到req的buf中
else
memset(req->buf, 0x55,req->length);//初始化req->buf
status = usb_ep_queue(ep, req,GFP_ATOMIC);//提交req到硬件fifo
if(status) {
structusb_composite_dev *cdev;
cdev =ss->function.config->cdev;
free_ep_req(ep, req);
}
/*
这里总结一下数据交互过程
1. 动态申请空间。
2. 设置完成函数。
3. 是in就或取数据(操作硬件的话,可能用到别的驱动),是out就初始化req->buf。
4. 提交req到硬件fifo。
万变不离其宗,大概就这样。
*/
returnstatus;
}
看完成函数
static void source_sink_complete(struct usb_ep *ep,structusb_request *req)
{
structf_sourcesink *ss = ep->driver_data;
structusb_composite_dev *cdev = ss->function.config->cdev;
int status = req->status;
switch(status) {
case0: /*normal completion? */
/*
正常,继续操作req。
*/
if(ep == ss->out_ep) {
check_read_data(ss,req);//f_sourcesink提供,MOD63或0
memset(req->buf,0x55, req->length);
} else
reinit_write_data(ep,req);
break;
/*this endpoint is normally active while we're configured */
case-ECONNABORTED: /* hardware forced ep reset */
case-ECONNRESET: /*request dequeued */
case-ESHUTDOWN: /*disconnect from host *///这几个说明传输停止
if(ep == ss->out_ep)
check_read_data(ss,req);
free_ep_req(ep, req);
return;
case-EOVERFLOW: /*buffer overrun on read means that
* we didn't provide a big enough
* buffer.
*/
default:
case-EREMOTEIO: /*short read *///一些错误,没有操作buf,相当于重发
break;
}
status = usb_ep_queue(ep, req,GFP_ATOMIC);
//继续提交,几乎所有的complete都要做的,正常就要继续
}
/*
总结一下complete
1.是否有一些错误,根据错误判断是停止还是重发。
2.正常就要继续提交req。
*/
最后是setup
这个要从udc说起
看s3c2410,假设ep0中断,且是置位了setup_end位
会调用
dev->driver->setup(&dev->gadget,crq);
就是它,事实这就是和usb枚举相关
static int
composite_setup(struct usb_gadget *gadget,conststructusb_ctrlrequest *ctrl)//ctrl是硬件获得的
{
u8 intf = w_index & 0xFF;
structusb_function *f = NULL;
//省掉了一大堆
switch(ctrl->bRequest) {
//对于各请求,composite_setup写成了一个统一的,我们只要实现接口就可以了
caseUSB_REQ_GET_DESCRIPTOR:
/* any number of configs can work */
caseUSB_REQ_SET_CONFIGURATION:
caseUSB_REQ_GET_CONFIGURATION:
caseUSB_REQ_SET_INTERFACE:
caseUSB_REQ_GET_INTERFACE:
caseUSB_REQ_GET_STATUS:
caseUSB_REQ_CLEAR_FEATURE:
caseUSB_REQ_SET_FEATURE:
break;
default:
switch(ctrl->bRequestType & USB_RECIP_MASK) {//接受对象
caseUSB_RECIP_INTERFACE://intf = w_index & 0xFF,对应的接口号
if (!cdev->config || intf >=MAX_CONFIG_INTERFACES)
break;
f =cdev->config->interface[intf];
break;
caseUSB_RECIP_ENDPOINT:
endp = ((w_index &0x80) >> 3) | (w_index & 0x0f);
/*
这个操作过后,endp的第4位是方向,0~3是地址,对应set_config()中的
addr =((ep->bEndpointAddress & 0x80) >> 3)
| (ep->bEndpointAddress & 0x0f);
set_bit(addr,f->endpoints);
*/
list_for_each_entry(f,&cdev->config->functions, list) {
if (test_bit(endp, f->endpoints))
break;
}
if (&f->list == &cdev->config->functions)
f = NULL;
break;
}//上面就是找对应的struct usb_function
if(f && f->setup)// structusb_function中的setup优先使用,f_sourcesink没实现
value = f->setup(f,ctrl);
else{
struct usb_configuration *c;
c = cdev->config;
if (c && c->setup)
value =c->setup(c, ctrl); //对我们来说就是sourcesink_setup()
}
gotodone;
}
}
static int sourcesink_setup(struct usb_configuration *c,
conststruct usb_ctrlrequest *ctrl)
{
structusb_request *req = c->cdev->req;
int value = -EOPNOTSUPP;
u16 w_index = le16_to_cpu(ctrl->wIndex);//小端转换要注意一下
u16 w_value = le16_to_cpu(ctrl->wValue);
u16 w_length = le16_to_cpu(ctrl->wLength);
req->length = USB_BUFSIZ;
//我们知道请求分标准和非标准,这下面两个就是非标准,
//控制端口允许多包请求,为了测试
switch(ctrl->bRequest) {
case0x5b: //控制写。 填充buffer
if(ctrl->bRequestType != (USB_DIR_OUT|USB_TYPE_VENDOR))
goto unknown;
if(w_value || w_index)
break;
if(w_length > req->length)//大于USB_BUFSIZ,就用USB_BUFSIZ
break;
value = w_length;//请求的数据长度
break;
case0x5c: //控制读。 返回buffer
if(ctrl->bRequestType != (USB_DIR_IN|USB_TYPE_VENDOR))
goto unknown;
if(w_value || w_index)
break;
if(w_length > req->length)
break;
value = w_length;
break;
default:
unknown:
}
if(value >= 0) {
req->zero = 0;
req->length = value;
value =usb_ep_queue(c->cdev->gadget->ep0, req, GFP_ATOMIC);//看到是从控制端口输出的,对于上面的多包请求,这就是最特别的一点
}
returnvalue;
}
/*
总结一下setup
1. composite_setup()为我们考虑了标准请求。
2. struct usb_function和struct usb_configuration只要实现一个setup,都实现的话会用struct usb_function。
3. 我们实现的setup从上面看主要是处理特殊请求。
*/
好了,基础的模块都说完了。下期再见!