当前位置:网站首页>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 first day of employment more than ten years ago
- usb peripheral 驱动 - configfs
- Multi Chain and cross chain are the future
- Tencent cloud account related
- C restart application
- Copy image bitmap by C # memory method
- Production environment server environment setup + project release process
- Moodle e-learning platform fixes the session hijacking error that leads to pre authorized rce
- 9 ways in which network security may change in 2022
- 6-闪耀的激光-CALayer 的应用
猜你喜欢

观察者模式

自组织映射神经网络(SOM)

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

Create an orderly sequence table and perform the following operations: 1 Insert element x into the table and keep it in order; 2. find the element with the value of X, and delete it if found; 3. outpu

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

Deep learning ----- different methods to realize vgg16
![[paper notes] catching both gray and black swans: open set supervised analog detection*](/img/52/787b25a9818cfc6a1897af81d41ab2.png)
[paper notes] catching both gray and black swans: open set supervised analog detection*

Use of tensorboard

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

INT 104_ LEC 06
随机推荐
transform的结构及用法
Tensorboard的使用
Huawei ECS EIP cannot be pinged
如何在conda虚拟环境开启jupyter-notebook
词性家族
Apache Solr arbitrary file read replication
[cross border e-commerce solutions] lighthouse will be used for pure IP expansion of new business - continuous efforts!
Leetcode 173 Binary search tree iterator (2022.06.22)
训练后的随机森林模型导出和加载
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
Odoo project sends information to wechat official account or enterprise wechat
Openvino series 19 Openvino and paddleocr for real-time video OCR processing
kibana 重建index后,如何恢复Visualizations和 Dashboards
【云计算】GFS思想优势以及架构
Map接口及其子实现类
Idea true permanent activation method and permanent activation code tutorial
What is a dedicated server line
odoo项目 发送信息到微信公众号或企业微信的做法
3-ProgressBar和二次裁剪
给你的win10装一个wget