当前位置:网站首页>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);
边栏推荐
- The kernel fails to shut down when the easygbs program stops. How should I optimize it? [code attached]
- Easygbs cannot play video streams in webrtc format. What is the reason?
- Why do we say that the data service API is the standard configuration of the data midrange?
- The rtsp/onvif protocol video platform easynvr startup service reports an error "service not found". How to solve it?
- Idea true permanent activation method and permanent activation code tutorial
- You have a string of code, but do not support the lower version of go; Judge the go version number, you deserve it!
- How to mine keywords and improve user experience before website construction?
- INT 104_ LEC 06
- 看了5本书,我总结出财富自由的这些理论
- Cloud computing "half peak"
猜你喜欢

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

数据资产为王,解析企业数字化转型与数据资产管理的关系

Data assets are king, analyzing the relationship between enterprise digital transformation and data asset management

Analysis of JMeter pressure measurement results

PCB电路板特性检查项目都有哪些?

Openvino series 19 Openvino and paddleocr for real-time video OCR processing

QT irregular shape antialiasing

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

jmeter压测结果分析

Commonly used bypass methods for SQL injection -ctf
随机推荐
typeScript的介绍与变量定义的基本类型
Generate code 39 extension code in batch through Excel file
Google common syntax
List interface three sub implementation classes
After easynvr video is enabled, no video file is generated. How to solve this problem?
Two bug fixes in aquatone tool
Focus! Ten minutes to master Newton convex optimization
transform的结构及用法
Markdown learning
Deep learning ----- convolution (conv2d) bottom layer
【云计算】GFS思想优势以及架构
坑爹的“敬业福”:支付宝春晚红包技术大爆发
Go 数据类型篇(二)之Go 支持的数据类型概述及布尔类型
Openvino series 19 Openvino and paddleocr for real-time video OCR processing
Multi-scale feature combination in target detection
odoo项目 发送信息到微信公众号或企业微信的做法
Why use growth neural gas network (GNG)?
词性家族
训练后的随机森林模型导出和加载
Azure Active Directory brute force attack