当前位置:网站首页>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);
边栏推荐
- Set the time zone in ci4 (CodeIgniter 4)
- Why do we say that the data service API is the standard configuration of the data midrange?
- 观察者模式
- Vulnhub | dc: 4 | [actual combat]
- 点云库pcl从入门到精通 第十章
- List interface three sub implementation classes
- What is a dedicated server line
- Deep learning ----- different methods to realize vgg16
- Dongyuhui, the "square face teacher", responded that the popularity was declining: do a good job of live broadcasting of agricultural products to benefit farmers and consider supporting education
- The first day of employment more than ten years ago
猜你喜欢
![Vulnhub | dc: 4 | [actual combat]](/img/33/b7422bdb18f39e9eb55855dbf1d584.png)
Vulnhub | dc: 4 | [actual combat]

鸿蒙读取资源文件

Object.defineProperty() 和 数据代理

81 sentences worth repeating

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

transform的结构及用法

论文阅读【Quo Vadis, Action Recognition? A New Model and the Kinetics Dataset】

Imperva- method of finding regular match timeout

给你的win10装一个wget

Multi-scale feature combination in target detection
随机推荐
Configuration asmx not accessible
Map interface and its sub implementation classes
How to mine keywords and improve user experience before website construction?
7-调色板-CALayer和触摸
How to start Jupiter notebook in CONDA virtual environment
INT 104_ LEC 06
aquatone工具 中的2個bug修複
Image segmentation - improved network structure
目标检测中的多尺度特征结合方式
Self organizing map neural network (SOM)
APM performance monitoring practice of jubasha app
渲染效果图哪家好?2022最新实测(四)
黄蓉真的存在吗?
Generate code 39 extension code in batch through Excel file
The kernel fails to shut down when the easygbs program stops. How should I optimize it? [code attached]
如何评价代码质量
【论文笔记】Catching Both Gray and Black Swans: Open-set Supervised Anomaly Detection*
Quickly create a consumer cluster
Install a WGet for your win10
Dongyuhui, the "square face teacher", responded that the popularity was declining: do a good job of live broadcasting of agricultural products to benefit farmers and consider supporting education