当前位置:网站首页>USB peripheral driver - configfs
USB peripheral driver - configfs
2022-06-23 08:25:00 【Be good to me】
1. configfs init
1.1 configfs usage
Reference documents :msm-kernel\Documentation\usb\gadget_configfs.rst
(1) Creating the gadgets:
mkdir /config/usb_gadget/g3 // mkdir $CONFIGFS_HOME/usb_gadget/<gadget name>
Bottom call gadget_make()
(2) Creating the configurations:
cd /config/usb_gadget/g3
mkdir configs/c.1 // mkdir configs/<name>.<number>
(3) Creating the functions:
mkdir functions/ncm.usb0 // mkdir functions/<name>.<instance name>
Bottom call function_make()
(4) Associating the functions with their configurations:
ln -s functions/ncm.usb0 configs/c.1 // ln -s functions/<name>.<instance name> configs/<name>.<number>
Bottom call :config_usb_cfg_link()
(5) Enabling the gadget:
echo <udc name> > UDC
echo "a600000.dwc3" > UDC
Bottom call :gadget_dev_desc_UDC_store()
1.2 configfs init file
== init.rc // Source path \system\core\rootdir\init.rc
== import /vendor/etc/init/hw/init.${
ro.hardware}.rc
== init.qcom.rc // Source path \device\qcom\common\rootdir\etc
== import init.qcom.usb.rc // filesystem route /vendor/etc/init/hw/
== import init.msm.usb.configfs.rc
== import init.target.rc
1.2.1 init.qcom.usb.rc
This configuration file is used for :
(1) Create device gadget;
(2) Create a configuration config;
(3) Create an interface function.
on boot
write /sys/class/android_usb/android0/iSerial ${
ro.serialno}
mount configfs none /config // mount configfs
mkdir /config/usb_gadget/g1 0770 // (1) Create device gadget
mkdir /config/usb_gadget/g2 0770
mkdir /config/usb_gadget/g1/strings/0x409 0770
mkdir /config/usb_gadget/g2/strings/0x409 0770
write /config/usb_gadget/g1/bcdUSB 0x0200
write /config/usb_gadget/g2/bcdUSB 0x0200
write /config/usb_gadget/g1/os_desc/use 1
write /config/usb_gadget/g1/strings/0x409/serialnumber ${
ro.serialno}
write /config/usb_gadget/g2/strings/0x409/serialnumber ${
ro.serialno}
write /config/usb_gadget/g1/strings/0x409/manufacturer ${
ro.product.manufacturer}
write /config/usb_gadget/g2/strings/0x409/manufacturer ${
ro.product.manufacturer}
write /config/usb_gadget/g1/strings/0x409/product ${
ro.product.model}
write /config/usb_gadget/g2/strings/0x409/product ${
ro.product.model}
mkdir /config/usb_gadget/g1/functions/mass_storage.0 // (3) Create an interface function
mkdir /config/usb_gadget/g1/functions/mtp.gs0
mkdir /config/usb_gadget/g1/functions/ptp.gs1
mkdir /config/usb_gadget/g1/functions/accessory.gs2
mkdir /config/usb_gadget/g1/functions/audio_source.gs3
mkdir /config/usb_gadget/g1/functions/midi.gs5
mkdir /config/usb_gadget/g1/functions/ffs.adb
mkdir /config/usb_gadget/g1/functions/diag.diag
mkdir /config/usb_gadget/g1/functions/diag.diag_mdm
mkdir /config/usb_gadget/g1/functions/cser.dun.0
mkdir /config/usb_gadget/g1/functions/cser.nmea.1
mkdir /config/usb_gadget/g1/functions/cser.dun.2
mkdir /config/usb_gadget/g1/functions/gsi.rmnet
mkdir /config/usb_gadget/g1/functions/gsi.rndis
mkdir /config/usb_gadget/g1/functions/gsi.dpl
mkdir /config/usb_gadget/g1/functions/qdss.qdss
mkdir /config/usb_gadget/g1/functions/qdss.qdss_mdm
mkdir /config/usb_gadget/g1/functions/rndis_bam.rndis
mkdir /config/usb_gadget/g1/functions/rndis.rndis
mkdir /config/usb_gadget/g1/functions/rmnet_bam.rmnet
mkdir /config/usb_gadget/g1/functions/rmnet_bam.dpl
mkdir /config/usb_gadget/g1/functions/rmnet_bam.rmnet_bam_dmux
mkdir /config/usb_gadget/g1/functions/rmnet_bam.dpl_bam_dmux
mkdir /config/usb_gadget/g1/functions/ncm.0
mkdir /config/usb_gadget/g1/functions/ccid.ccid
mkdir /config/usb_gadget/g1/functions/uac2.0
mkdir /config/usb_gadget/g1/functions/uvc.0
mkdir /config/usb_gadget/g1/functions/uvc.1
mkdir /config/usb_gadget/g1/functions/hid.0
mkdir /config/usb_gadget/g1/functions/hid.1
mkdir /config/usb_gadget/g1/functions/hid.2
mkdir /config/usb_gadget/g1/functions/hid.3
mkdir /config/usb_gadget/g1/functions/hid.4
mkdir /config/usb_gadget/g1/functions/hid.5
mkdir /config/usb_gadget/g1/configs/b.1 0770 //(2) Create a configuration config
mkdir /config/usb_gadget/g2/configs/b.1 0770
mkdir /config/usb_gadget/g1/configs/b.1/strings/0x409 0770
mkdir /config/usb_gadget/g2/configs/b.1/strings/0x409 0770
write /config/usb_gadget/g1/os_desc/b_vendor_code 0x1
write /config/usb_gadget/g1/os_desc/qw_sign "MSFT100"
symlink /config/usb_gadget/g1/configs/b.1 /config/usb_gadget/g1/os_desc/b.1
mkdir /dev/usb-ffs 0775 shell system
mkdir /dev/usb-ffs/adb 0770 shell system
mount functionfs adb /dev/usb-ffs/adb uid=2000,gid=1000,rmode=0770,fmode=0660
write /sys/class/android_usb/android0/f_ffs/aliases adb
setprop sys.usb.mtp.device_type 2
setprop vendor.usb.controller ${
sys.usb.controller}
enable vendor.qcom-usb-sh
1.2.1 init.msm.usb.configfs.rc
This configuration file is used to read the upper layer property, then enable Corresponding config All of the function.
// sys.usb.config=diag,adb Indicates that the configuration has diag and adb Two interface functions ;
// You can use getprop sys.usb.config The query ,setprop sys.usb.config=** Perform configuration switching
on property:sys.usb.ffs.ready=1 && property:sys.usb.config=diag,adb && property:sys.usb.configfs=1
write /config/usb_gadget/g1/configs/b.1/strings/0x409/configuration "diag_adb"
rm /config/usb_gadget/g1/configs/b.1/f1
rm /config/usb_gadget/g1/configs/b.1/f2
rm /config/usb_gadget/g1/configs/b.1/f3
rm /config/usb_gadget/g1/configs/b.1/f4
rm /config/usb_gadget/g1/configs/b.1/f5
rm /config/usb_gadget/g1/configs/b.1/f6
rm /config/usb_gadget/g1/configs/b.1/f7
rm /config/usb_gadget/g1/configs/b.1/f8
rm /config/usb_gadget/g1/configs/b.1/f9
rm /config/usb_gadget/g1/configs/b.1/f10
rm /config/usb_gadget/g1/configs/b.1/f11
write /config/usb_gadget/g1/idVendor 0x05C6
write /config/usb_gadget/g1/idProduct 0x901D
symlink /config/usb_gadget/g1/functions/diag.diag /config/usb_gadget/g1/configs/b.1/f1
symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f2
write /config/usb_gadget/g1/UDC ${
sys.usb.controller}
setprop sys.usb.state ${
sys.usb.config}
2. Driver module initialization
2.1 function Drive initialization
be-all function Drivers are registered in a linked list func_list, When configfs When the drive is started , Read the upper layer configuration function To match with the list .
stay \drivers\usb\gadget\function\f_fs.c in , Use the following macro to register function drive ( take usb_function_driver Join in func_list Linked list ), The init The operation will be executed when the system is initialized .
#define DECLARE_USB_FUNCTION_INIT(_name, _inst_alloc, _func_alloc) \ DECLARE_USB_FUNCTION(_name, _inst_alloc, _func_alloc) \ static int __init _name ## mod_init(void) \ {
\ return usb_function_register(&_name ## usb_func); \ } \ static void __exit _name ## mod_exit(void) \ {
\ usb_function_unregister(&_name ## usb_func); \ } \ module_init(_name ## mod_init); \ module_exit(_name ## mod_exit)
2.2 configfs Drive initialization
\drivers\usb\gadget\configfs.c
Initialize when the system loads the driver module gadget configfs, Including some operation interfaces provided to the upper layer (mkdir write…)
== module_init(gadget_cfs_init);
== configfs_register_subsystem(&gadget_subsys);
gadget_subsys == gadgets_type == gadgets_ops
== gadgets_make(); //gadget_make Will be executed at the upper level mkdir Called when
== struct gadget_info *gi; // structure gadget_info
== gi->composite.gadget_driver = configfs_driver_template; // structure usb_gadget_driver
struct gadget_info {
struct usb_composite_driver composite;
struct usb_composite_dev cdev;
};
static const struct usb_gadget_driver configfs_driver_template = {
//usb_gadget_driver
.bind = configfs_composite_bind,
.unbind = configfs_composite_unbind,
#ifdef CONFIG_USB_CONFIGFS_UEVENT
.setup = android_setup,
#else
.setup = configfs_composite_setup,
#endif
.reset = configfs_composite_reset,
.disconnect = configfs_composite_disconnect,
.suspend = configfs_composite_suspend,
.resume = configfs_composite_resume,
};
3. The bottom layer corresponds to the interface of the upper layer
3.1 function_make
The upper :mkdir /config/usb_gadget/g1/functions/diag.diag
Bottom :function_make()
static struct config_group *function_make(
struct config_group *group,
const char *name)
function_make Call the process :
== configfs_mkdir();
== function_make(struct config_group *group, const char *name);
== usb_get_function_instance();
== try_get_usb_function_instance(const char *name); // from func_list Find fd
fd->alloc_inst();
== ncm_alloc_inst();
== create_function_device();
== device_create();
== device_add();
3.2 gadget connect
The upper :echo “a600000.dwc3” > UDC
kernel 5.4:
== gadget_dev_desc_UDC_store(); // \drivers\usb\gadget\configfs.c
== usb_gadget_probe_driver(struct usb_gadget_driver *driver) // \drivers\usb\gadget\udc\core.c
== udc_bind_to_driver(); // binding usb_gadget_driver And usb_udc
== driver->bind(udc->gadget, driver);
== configfs_composite_bind();
== usb_add_function(c, f); // add to function, perform function Function of
== usb_gadget_udc_start(udc);
== udc->gadget->ops->udc_start(udc->gadget, udc->driver);
== dwc3_gadget_start();
== request_threaded_irq(irq, dwc3_interrupt, dwc3_thread_interrupt, IRQF_SHARED, "dwc3", dwc->ev_buf);
// register dwc3 interrupt , When host When you send a message , Trigger interrupt function
== usb_udc_connect_control(struct usb_udc *udc)
== usb_gadget_connect(struct usb_gadget *gadget)
== gadget->ops->pullup(gadget, 1);
== dwc3_gadget_pullup(struct usb_gadget *g, int is_on);
== dwc3_gadget_run_stop_util();
== dwc3_gadget_run_stop(dwc, true, false);
== __dwc3_gadget_start(dwc); //enable Endpoint transport
== __dwc3_gadget_ep_enable(struct dwc3_ep *dep, unsigned int action) // initializes a hw endpoint
3.2 gadget disconnect
The upper :echo “none” > UDC
== gadget_dev_desc_UDC_store
== unregister_gadget(struct gadget_info *gi)
== usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
== usb_gadget_remove_driver(struct usb_udc *udc)
static void usb_gadget_remove_driver(struct usb_udc *udc)
{
dev_dbg(&udc->dev, "unregistering UDC driver [%s]\n",
udc->driver->function);
kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE); // Produce a uevent Report
usb_gadget_disconnect(udc->gadget); //gadget Drive off
if (udc->gadget->irq)
synchronize_irq(udc->gadget->irq);
udc->driver->unbind(udc->gadget); // Cancel req(gadget The endpoint of 0 usb_ep)
usb_gadget_udc_stop(udc); //udc stop it
udc->driver = NULL;
udc->dev.driver = NULL;
udc->gadget->dev.driver = NULL;
}
3.2.1 disable The endpoint of the controller dwc3_ep(32 individual )
== usb_gadget_disconnect(struct usb_gadget *gadget)
gadget->ops->pullup(gadget, 0);
.pullup = dwc3_gadget_pullup,
== dwc3_gadget_pullup(struct usb_gadget *g, int is_on) // open / Close endpoint 、 Write register
== dwc3_stop_active_transfers(dwc); // Not 0 Endpoint
== dwc3_remove_requests(dwc, dep);
== __dwc3_gadget_stop(struct dwc3 *dwc) // disable Endpoint 0( Control endpoints ) transmission
== __dwc3_gadget_ep_disable(struct dwc3_ep *dep) // disables a hw endpoint
== dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep)
3.2.2 Cancel req(gadget The endpoint of 0 usb_ep)
== udc->driver->unbind(udc->gadget);
.unbind = composite_unbind,
.unbind = configfs_composite_unbind,
== configfs_composite_unbind(struct usb_gadget *gadget)
== composite_dev_cleanup(struct usb_composite_dev *cdev) // eliminate composite dev Upper req
== usb_ep_dequeue(struct usb_ep *ep, struct usb_request *req) // dequeues (cancels, unlinks) an I/O request from an endpoint
== ret = ep->ops->dequeue(ep, req);
.dequeue = dwc3_gadget_ep_dequeue, //usb_ep Turn into dwc3_ep
==dwc3_gadget_ep_dequeue(struct usb_ep *ep, struct usb_request *request)
4. Once complete Gadget Data flow
Configfs The data exchange between the subsystem and the controller is through struct usb_request *request Structure , A complete process is as follows :
4.1 function apply req
\drivers\usb\gadget\function\f_fs.c
(1) apply req:
== ffs->ep0req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL); trace_usb_ep_alloc_request(ep, req, req ? 0 : -ENOMEM);
== ep->ops->alloc_request(ep, gfp_flags);
== dwc3_gadget_ep_alloc_request(); trace_dwc3_alloc_request(req);
== ffs->ep0req->complete = ffs_ep0_complete; // req Completion function of
Release req:
== ffs_func_unbind();
== usb_ep_free_request(); trace_usb_ep_free_request(ep, req, 0);
== ep->ops->free_request(ep, req);
== dwc3_gadget_ep_free_request(); trace_dwc3_free_request();
(2) take req Submit to controller :
== usb_ep_queue(ffs->gadget->ep0, req, GFP_ATOMIC); trace_usb_ep_queue(ep, req, ret);
== ret = ep->ops->queue(ep, req, gfp_flags);
== dwc3_gadget_ep0_queue();
== __dwc3_gadget_ep0_queue();
== __dwc3_ep0_do_control_data();
== dwc3_ep0_start_trans();
== dwc3_send_gadget_ep_cmd(); trace_dwc3_gadget_ep_cmd(dep, cmd, params, cmd_status);
== dwc3_writel(dep->regs, DWC3_DEPCMDPAR0, params->param0);
4.2 Controller processing req ( Write register )
== dwc3_gadget_ep_queue();
== __dwc3_gadget_ep_queue();
== __dwc3_gadget_start_isoc(struct dwc3_ep *dep);
==__dwc3_gadget_kick_transfer(struct dwc3_ep *dep);
== dwc3_send_gadget_ep_cmd(); // This function will issue @cmd with given @params to @dep and wait for its completion.
== dwc3_writel(void __iomem *base, u32 offset, u32 value)
4.3 Controller return req ( Interrupt callback function )
== dwc3_gadget_start(); // Registration interrupted
== request_threaded_irq(irq, dwc3_interrupt, dwc3_thread_interrupt, IRQF_SHARED, "dwc3", dwc->ev_buf);
== dwc3_thread_interrupt(); // Interrupt generation (host Send a message ), Call callback function
== dwc3_process_event_buf(); // Handling interrupt events buf(dwc3_event_buffer )
== dwc3_process_event_entry(); trace_dwc3_event(event->raw, dwc);
== dwc3_endpoint_interrupt(); // Interruption of endpoint processing
== dwc3_ep0_interrupt(); // Control transmission if (epnum == 0 || epnum == 1)
== dwc3_ep0_xfer_complete(); //event->endpoint_event = DWC3_DEPEVT_XFERCOMPLETE
== dwc3_ep0_inspect_setup(); //dwc->ep0state = EP0_SETUP_PHASE
//dwc3_ep0_std_request() == dwc3_ep0_set_config()
== dwc3_ep0_delegate_req();
== dwc->gadget_driver->setup(&dwc->gadget, ctrl);
== configfs_composite_setup();
== composite_setup(); //setup Including getting descriptors , To configure , Address and other operations
== set_config(cdev, ctrl, w_value); ctrl->bRequest = USB_REQ_SET_CONFIGURATION
== dwc3_gadget_endpoint_transfer_complete(); // Transmission complete
== dwc3_gadget_endpoint_trbs_complete();
== dwc3_gadget_ep_cleanup_completed_requests()
== dwc3_gadget_giveback(); // The data returned
== dwc3_gadget_del_and_unmap_request(); trace_dwc3_gadget_giveback(req);
== usb_gadget_giveback_request() trace_usb_gadget_giveback_request(ep, req, 0);// give the request back to the gadget layer
== req->complete(ep, req);
== ffs_ep0_complete() // function Completion function of
== dwc3_gadget_interrupt(dwc, &event->devt); // Yes gadget The interruption of the device
== usb_gadget_vbus_draw(&dwc->gadget, 2); trace_usb_gadget_vbus_draw(gadget, ret);
== gadget->ops->vbus_draw(gadget, mA);
== dwc3_gadget_vbus_draw();
== dwc3_notify_event(dwc, DWC3_CONTROLLER_SET_CURRENT_DRAW_EVENT, 0);
边栏推荐
猜你喜欢

【论文笔记】Catching Both Gray and Black Swans: Open-set Supervised Anomaly Detection*

十多年前的入职第一天

观察者模式

Observer mode

为什么用生长型神经气体网络(GNG)?

Basic use of check boxes and implementation of select all and invert selection functions

船长阿布的灵魂拷问

What are the PCB characteristics inspection items?

What are open source software, free software, copyleft and CC? Can't you tell them clearly?

The first day of employment more than ten years ago
随机推荐
Imperva- method of finding regular match timeout
5-旋转的小菊-旋转画布和定时器
十多年前的入职第一天
List接口三个子实现类
Vulnhub | DC: 4 | [combat]
Derivation and loading of the trained random forest model
Lightweight UI control library worth collecting
After easynvr video is enabled, no video file is generated. How to solve this problem?
黄蓉真的存在吗?
Introduction to typescript and basic types of variable definitions
Self organizing map neural network (SOM)
正则表达式使用案例
Easygbs cannot play video streams in webrtc format. What is the reason?
Two bug fixes in aquatone tool
PHP serialization and deserialization CTF
C RichTextBox controls the maximum number of rows
Vulnhub | DC: 4 |【实战】
Tencent cloud account related
Keng dad's "dedication blessing": red packet technology explosion in Alipay Spring Festival Gala
Sequence table Curriculum