usb设备驱动程序usb gadget driver4.docx
- 文档编号:23132471
- 上传时间:2023-05-08
- 格式:DOCX
- 页数:4
- 大小:17KB
usb设备驱动程序usb gadget driver4.docx
《usb设备驱动程序usb gadget driver4.docx》由会员分享,可在线阅读,更多相关《usb设备驱动程序usb gadget driver4.docx(4页珍藏版)》请在冰豆网上搜索。
usb设备驱动程序usbgadgetdriver4
USB设备驱动程序-USBGadgetDriver(4)
Gadget功能层Gadget功能层完成USB设备的具体功能,其表现的形式各不相同,如键盘、鼠标、存储和网卡等等。
功能层不仅涉及到Gadget驱动相关的内容,还涉及到其功能相关的内核子系统。
如存储还涉及到内核存储子系统,网卡还涉及到网络驱动子系统。
因此,Gadget功能的代码非常复杂。
这里以zero.c为例,这个模块只是简单地将接收的数据回显回去。
一、数据结构首先需要实现usb_composite_driver函数集:
staticstructusb_composite_driverzero_driver={.name="zero",.dev=&device_desc,.strings=dev_strings,.bind=zero_bind,.unbind=zero_unbind,.suspend=zero_suspend,.resume=zero_resume,};二、主要函数这个模块的实现就是这么简单:
staticint__initinit(void){returnusb_composite_register(&zero_driver);}module_init(init);staticvoid__exitcleanup(void){usb_composite_unregister(&zero_driver);}Bind函数是功能层需要实现与设备层关联的重要函数:
staticint__initzero_bind(structusb_composite_dev*cdev){intgcnum;structusb_gadget*gadget=cdev->gadget;//Gadget设备intid;/*Allocatestringdescriptornumbers...notethatstring*contentscanbeoverriddenbythecomposite_devglue.*//*分配字符串描述符的id,并赋值给设备描述符中字符串索引*/id=usb_string_id(cdev);strings_dev[STRING_MANUFACTURER_IDX].id=id;device_desc.iManufacturer=id;id=usb_string_id(cdev);istrings_dev[STRING_PRODUCT_IDX].id=id;device_desc.iProduct=id;id=usb_string_id(cdev);strings_dev[STRING_SERIAL_IDX].id=id;device_desc.iSerialNumber=id;/*设置挂起后,设备自动恢复的定时器*/setup_timer(&autoresume_timer,zero_autoresume,(unsignedlong)cdev);/*核心代码,实现功能*/if(loopdefault){loopback_add(cdev,autoresume!
=0);//数据简单回显功能if(!
gadget_is_sh(gadget))sourcesink_add(cdev,autoresume!
=0);}else{sourcesink_add(cdev,autoresume!
=0);if(!
gadget_is_sh(gadget))loopback_add(cdev,autoresume!
=0);}/*初始化设备描述符*/gcnum=usb_gadget_controller_number(gadget);if(gcnum>=0)device_desc.bcdDevice=cpu_to_le16(0x0200+gcnum);else{device_desc.bcdDevice=cpu_to_le16(0x9999);}return0;}/*增加数据简单回显功能*/int__initloopback_add(structusb_composite_dev*cdev,boolautoresume){intid;/*获取字符串描述符id索引*/id=usb_string_id(cdev);strings_loopback[0].id=id;loopback_intf.iInterface=id;loopback_driver.iConfiguration=id;/*supportautoresumeforremotewakeuptesting*/if(autoresume)sourcesink_driver.bmAttributes|=USB_CONFIG_ATT_WAKEUP;/*supportOTGsystems*/if(gadget_is_otg(cdev->gadget)){loopback_driver.descriptors=otg_desc;loopback_driver.bmAttributes|=USB_CONFIG_ATT_WAKEUP;}returnusb_add_config(cdev,&loopback_driver);//增加一个配置}/*loopback配置*/staticstructusb_configurationloopback_driver={.label="loopback",.strings=loopback_strings,.bind=loopback_bind_config,.bConfigurationValue=2,.bmAttributes=USB_CONFIG_ATT_SELFPOWER,/*.iConfiguration=DYNAMIC*/};将增加配置的usb_add_config函数中会调用其bind函数,即loopback_bind_config函数,来分配这个配置所需要的资源。
structf_loopback{structusb_functionfunction;structusb_ep*in_ep;structusb_ep*out_ep;};staticint__initloopback_bind_config(structusb_configuration*c){structf_loopback*loop;intstatus;loop=kzalloc(sizeof*loop,GFP_KERNEL);//分配一个loop结构if(!
loop)return-ENOMEM;/*初始化一个功能*/loop->function.name="loopback";loop->function.descriptors=fs_loopback_descs;loop->function.bind=loopback_bind;loop->function.unbind=loopback_unbind;loop->function.set_alt=loopback_set_alt;loop->function.disable=loopback_disable;status=usb_add_function(c,&loop->function);//加入这个功能if(status)kfree(loop);returnstatus;}在usb_add_function函数中,又会调用这个功能的bind函数,即loopback_bind函数:
staticint__initloopback_bind(structusb_configuration*c,structusb_function*f){structusb_composite_dev*cdev=c->cdev;structf_loopback*loop=func_to_loop(f);intid;/*allocateinterfaceID(s)*/id=usb_interface_id(c,f);//分配一个接口idif(id<0)returnid;loopback_intf.bInterfaceNumber=id;/*allocateendpoints*//*返回一个输入端点*/loop->in_ep=usb_ep_autoconfig(cdev->gadget,&fs_loop_source_desc);if(!
loop->in_ep){autoconf_fail:
ERROR(cdev,"%s:
can'tautoconfigureon%s\n",f->name,cdev->gadget->name);return-ENODEV;}loop->in_ep->driver_data=cdev;/*claim*//*返回一个输出端点,返回合适的端点*/loop->out_ep=usb_ep_autoconfig(cdev->gadget,&fs_loop_sink_desc);if(!
loop->out_ep)gotoautoconf_fail;loop->out_ep->driver_data=cdev;/*claim*//*supporthighspeedhardware*/if(gadget_is_dualspeed(c->cdev->gadget)){hs_loop_source_desc.bEndpointAddress=fs_loop_source_desc.bEndpointAddress;hs_loop_sink_desc.bEndpointAddress=fs_loop_sink_desc.bEndpointAddress;f->hs_descriptors=hs_loopback_descs;}DBG(cdev,"%sspeed%s:
IN/%s,OUT/%s\n",gadget_is_dualspeed(c->cdev->gadget)?
"dual":
"full",f->name,loop->in_ep->name,loop->out_ep->name);return0;}功能的实现Loopback_set_alt函数将在设备层的setup函数中被调用,控制通信设置接口。
staticintloopback_set_alt(structusb_function*f,unsignedintf,unsignedalt){structf_loopback*loop=func_to_loop(f);structusb_composite_dev*cdev=f->config->cdev;/*weknowaltiszero*/if(loop->in_ep->driver_data)disable_loopback(loop);returnenable_loopback(cdev,loop);//开启功能}staticintenable_loopback(structusb_composite_dev*cdev,structf_loopback*loop){intresult=0;conststructusb_endpoint_descriptor*src,*sink;structusb_ep*ep;structusb_request*req;unsignedi;/*选择端点描述符*/src=ep_choose(cdev->gadget,&hs_loop_source_desc,&fs_loop_source_desc);sink=ep_choose(cdev->gadget,&hs_loop_sink_desc,&fs_loop_sink_desc);/*oneendpointwritesdatabackINtothehost*//*输入输出端点使能*/ep=loop->in_ep;result=usb_ep_enable(ep,src);if(result<0)returnresult;ep->driver_data=loop;/*oneendpointjustreadsOUTpackets*/ep=loop->out_ep;result=usb_ep_enable(ep,sink);if(result<0){fail0:
ep=loop->in_ep;usb_ep_disable(ep);ep->driver_data=NULL;returnresult;}ep->driver_data=loop;/*allocateabunchofreadbuffersandqueuethemallatonce.*webufferatmost'qlen'transfers;fewerifanyneedmore*than'buflen'byteseach.*//*qlen=32,分配32个请求,将这个请求放入输出端点队列,等待接收数据*/for(i=0;i<qlen&&result==0;i++){req=alloc_ep_req(ep);if(req){req->complete=loopback_complete;result=usb_ep_queue(ep,req,GFP_ATOMIC);if(result)ERROR(cdev,"%squeuereq-->%d\n",ep->name,result);}else{usb_ep_disable(ep);ep->driver_data=NULL;result=-ENOMEM;gotofail0;}}DBG(cdev,"%senabled\n",loop->function.name);returnresult;}/*接收到数据之后,将调用这个完成函数*/staticvoidloopback_complete(structusb_ep*ep,structusb_request*req){structf_loopback*loop=ep->driver_data;structusb_composite_dev*cdev=loop->function.config->cdev;intstatus=req->status;switch(status){case0:
/*normalcompletion?
*/if(ep==loop->out_ep){//将接收到的数据放入输入端点,返回给主机/*loopthisOUTpacketbackINtothehost*/req->zero=(req->actual<req->length);req->length=req->actual;status=usb_ep_queue(loop->in_ep,req,GFP_ATOMIC);if(status==0)return;/*"shouldnevergethere"*/ERROR(cdev,"can'tloop%sto%s:
%d\n",ep->name,loop->in_ep->name,status);}/*queuethebufferforsomelaterOUTpacket*/req->length=buflen;//将输入端点完成的申请,重新放入输出队列,等待接收新的数据status=usb_ep_queue(loop->out_ep,req,GFP_ATOMIC);if(status==0)return;/*"shouldnevergethere"*//*FALLTHROUGH*/default:
ERROR(cdev,"%sloopcomplete-->%d,%d/%d\n",ep->name,status,req->actual,req->length);/*FALLTHROUGH*//*NOTE:
sincethisdriverdoesn'tmaintainanexplicitrecord*ofrequestsitsubmitted(justmaintainsqlencount),we*relyonthehardwaredrivertocleanupondisconnector*endpointdisable.*/case-ECONNABORTED:
/*hardwareforcedepreset*/case-ECONNRESET:
/*requestdequeued*/case-ESHUTDOWN:
/*disconnectfromhost*/free_ep_req(ep,req);return;}}
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- usb设备驱动程序usb gadget driver4 usb 设备 驱动程序