当前位置: 首页 > news >正文

艺帆网络工作室网站源码百度关键词搜索热度

艺帆网络工作室网站源码,百度关键词搜索热度,网站建设结束语,wordpress整站克隆原文网址(转载请注明出处): 链接:http://t.csdnimg.cn/VxZsA 源码基于:Android Q 文章目录 1.USB驱动介绍2.charger-manager拔插事件分发 在展锐8541平台上加载了extcon-usb-gpio 驱动,这个驱动可以检测…

原文网址(转载请注明出处):

链接:http://t.csdnimg.cn/VxZsA

源码基于:Android Q

文章目录

  • 1.USB驱动介绍
  • 2.charger-manager拔插事件分发

在展锐8541平台上加载了extcon-usb-gpio 驱动,这个驱动可以检测USB 的插拔动作。

1.USB驱动介绍

USB驱动文件:

bsp/kernel/kernel4.14/drivers/extcon/Makefile...
obj-$(CONFIG_EXTCON_USB_GPIO)    += extcon-usb-gpio.o
...

代码:

bsp/kernel/kernel4.14/drivers/extcon/extcon-usb-gpio.cstatic const struct of_device_id usb_extcon_dt_match[] = {{ .compatible = "linux,extcon-usb-gpio", },{ /* sentinel */ }
};static struct platform_driver usb_extcon_driver = {.probe        = usb_extcon_probe,  // probe 函数,驱动匹配到了对应的设备后会调用此函数.remove        = usb_extcon_remove, // 设备移除后会调用此函数.driver        = {.name    = "extcon-usb-gpio",.pm    = &usb_extcon_pm_ops,.of_match_table = usb_extcon_dt_match, // 用于匹配dts文件里的设备,如果有compatible 相同的设备后才会调用probe 函数},.id_table = usb_extcon_platform_ids,
};module_platform_driver(usb_extcon_driver); // 该驱动的入口函数

接着查看probe 函数,里面有两个中断,分别是id-gpio和 vbus-gpio

bsp/kernel/kernel4.14/drivers/extcon/extcon-usb-gpio.cstatic int usb_extcon_probe(struct platform_device *pdev)
{...info->id_gpiod = devm_gpiod_get_optional(&pdev->dev, "id", GPIOD_IN);info->vbus_gpiod = devm_gpiod_get_optional(&pdev->dev, "vbus", GPIOD_IN);...if (info->id_gpiod)// 用于防抖的ret = gpiod_set_debounce(info->id_gpiod, USB_GPIO_DEBOUNCE_MS * 1000);if (!ret && info->vbus_gpiod)ret = gpiod_set_debounce(info->vbus_gpiod, USB_GPIO_DEBOUNCE_MS * 1000);...if (info->id_gpiod) {info->id_irq = gpiod_to_irq(info->id_gpiod); // 将id-gpio 口设置为中断模式...// 设置中断条件,发生中断是调用usb_irq_handler() 方法,当GPIO 上拉或者下拉时触发中断ret = devm_request_threaded_irq(dev, info->id_irq, NULL,usb_irq_handler,IRQF_TRIGGER_RISING |IRQF_TRIGGER_FALLING | IRQF_ONESHOT,pdev->name, info);...}if (info->vbus_gpiod) {info->vbus_irq = gpiod_to_irq(info->vbus_gpiod); // 将vbus-gpio 口设置为中断模式...// 设置中断条件,发生中断是调用usb_irq_handler() 方法,当GPIO 上拉或者下拉时触发中断ret = devm_request_threaded_irq(dev, info->vbus_irq, NULL,usb_irq_handler,IRQF_TRIGGER_RISING |IRQF_TRIGGER_FALLING | IRQF_ONESHOT,pdev->name, info);...}...
}

当id-gpio 和 vbus-gpio 口上拉或者下拉时触发中断,调用usb_irq_handler() 中断,上拉或者下拉代表USB 的插入和拔出。

bsp/kernel/kernel4.14/drivers/extcon/extcon-usb-gpio.cstatic irqreturn_t usb_irq_handler(int irq, void *dev_id)
{struct usb_extcon_info *info = dev_id;queue_delayed_work(system_power_efficient_wq, &info->wq_detcable,info->debounce_jiffies);return IRQ_HANDLED;
}static int usb_extcon_probe(struct platform_device *pdev)
{...INIT_DELAYED_WORK(&info->wq_detcable, usb_extcon_detect_cable); // 初始化工作队列wq_detcable 为usb_extcon_detect_cable() 方法...
}static void usb_extcon_detect_cable(struct work_struct *work)
{int id, vbus;struct usb_extcon_info *info = container_of(to_delayed_work(work),struct usb_extcon_info,wq_detcable);/* check ID and VBUS and update cable state */id = info->id_gpiod ?gpiod_get_value_cansleep(info->id_gpiod) : 1;vbus = info->vbus_gpiod ?gpiod_get_value_cansleep(info->vbus_gpiod) : id;/* at first we clean states which are no longer active */if (id)extcon_set_state_sync(info->edev, EXTCON_USB_HOST, false);if (!vbus)extcon_set_state_sync(info->edev, EXTCON_USB, false);if (!id) {extcon_set_state_sync(info->edev, EXTCON_USB_HOST, true);} else {if (vbus)extcon_set_state_sync(info->edev, EXTCON_USB, true);}
}

在USB插拔触发中断时,会调用info->wq_detcable 工作队列,即会调用usb_extcon_detect_cable() 方法,之后会通过extcon_set_state_sync() 方法设置USB 的状态

bsp/kernel/kernel4.14/drivers/extcon/extcon.cint extcon_set_state_sync(struct extcon_dev *edev, unsigned int id, bool state)
{int ret, index;unsigned long flags;index = find_cable_index_by_id(edev, id);if (index < 0)return index;/* Check whether the external connector's state is changed. */spin_lock_irqsave(&edev->lock, flags);ret = is_extcon_changed(edev, index, state); // 检查USB状态是否发生了变化spin_unlock_irqrestore(&edev->lock, flags);if (!ret)return 0;ret = extcon_set_state(edev, id, state); // 设置USB 的连接状态,但是不会通知USB 状态的改变if (ret < 0)return ret;return extcon_sync(edev, id); // 设置USB 的连接状态并通知其他模块
}
EXPORT_SYMBOL_GPL(extcon_set_state_sync);int extcon_sync(struct extcon_dev *edev, unsigned int id)
{...// 通过这个方法通知某个注册了USB 状态改变的模块raw_notifier_call_chain(&edev->nh[index], state, edev);// 通过这个方法通知所有注册了USB 状态改变的模块raw_notifier_call_chain(&edev->nh_all, state, edev);...kobject_uevent_env(&edev->dev.kobj, KOBJ_CHANGE, envp); // 通过UEvent 通知用户空间USB发生了改变free_page((unsigned long)prop_buf);return 0;
}
EXPORT_SYMBOL_GPL(extcon_sync);
bsp/kernel/kernel4.14/kernel/notifier.cint raw_notifier_call_chain(struct raw_notifier_head *nh,unsigned long val, void *v)
{return __raw_notifier_call_chain(nh, val, v, -1, NULL);
}
EXPORT_SYMBOL_GPL(raw_notifier_call_chain);int __raw_notifier_call_chain(struct raw_notifier_head *nh,unsigned long val, void *v,int nr_to_call, int *nr_calls)
{return notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls);
}
EXPORT_SYMBOL_GPL(__raw_notifier_call_chain);static int notifier_call_chain(struct notifier_block **nl,unsigned long val, void *v,int nr_to_call, int *nr_calls)
{int ret = NOTIFY_DONE;struct notifier_block *nb, *next_nb;nb = rcu_dereference_raw(*nl);// 循环读取所有的notifier_block, 然后调用它的notifier_call() 方法while (nb && nr_to_call) {next_nb = rcu_dereference_raw(nb->next);...ret = nb->notifier_call(nb, val, v);if (nr_calls)(*nr_calls)++;if (ret & NOTIFY_STOP_MASK)break;nb = next_nb;nr_to_call--;}return ret;
}
NOKPROBE_SYMBOL(notifier_call_chain);

从log分析可以看到,nb->notifier_call() 方法会调用sprd_hsphy_vbus_notify() 方法

[14:53:40:749] [   51.173699] c2 [<c0111ebc>] (unwind_backtrace) from [<c010ced0>] (show_stack+0x20/0x24)␍␊
[14:53:40:757] [   51.181677] c2 [<c010ced0>] (show_stack) from [<c0b13884>] (dump_stack+0xa4/0xd8)␍␊
[14:53:40:761] [   51.189129] c2 [<c0b13884>] (dump_stack) from [<c06c8f18>] (sprd_hsphy_vbus_notify+0x48/0x30c)␍␊
[14:53:40:774] [   51.197722] c2 [<c06c8f18>] (sprd_hsphy_vbus_notify) from [<c014f0a0>] (notifier_call_chain+0x74/0xac)␍␊
[14:53:40:779] [   51.207006] c2 [<c014f0a0>] (notifier_call_chain) from [<c014f12c>] (raw_notifier_call_chain+0x28/0x30)␍␊
[14:53:40:792] [   51.216371] c2 [<c014f12c>] (raw_notifier_call_chain) from [<c0880468>] (extcon_sync+0x78/0x1e4)␍␊
[14:53:40:801] [   51.225137] c2 [<c0880468>] (extcon_sync) from [<c0880bcc>] (extcon_set_state_sync+0x7c/0x90)␍␊
[14:53:40:806] [   51.233639] c2 [<c0880bcc>] (extcon_set_state_sync) from [<c0881e60>] (usb_extcon_detect_cable+0xa8/0xac)␍␊
[14:53:40:815] [   51.243185] c2 [<c0881e60>] (usb_extcon_detect_cable) from [<c0147d40>] (process_one_work+0x290/0x4a8)␍␊
[14:53:40:825] [   51.252466] c2 [<c0147d40>] (process_one_work) from [<c0148590>] (worker_thread+0x2f8/0x478)␍␊
[14:53:40:833] [   51.260887] c2 [<c0148590>] (worker_thread) from [<c014d564>] (kthread+0x148/0x164)␍␊
[14:53:40:844] [   51.268519] c2 [<c014d564>] (kthread) from [<c0108814>] (ret_from_fork+0x14/0x20)

接着查看sprd_hsphy_vbus_notify() 方法的流程

bsp/kernel/kernel4.14/drivers/usb/phy/phy-sprd-sharkle.cstatic int sprd_hsphy_vbus_notify(struct notifier_block *nb,unsigned long event, void *data)
{struct usb_phy *usb_phy = container_of(nb, struct usb_phy, vbus_nb);struct sprd_hsphy *phy = container_of(usb_phy, struct sprd_hsphy, phy);...// event 的值是我们传入的USB 状态(state),state = 1 表示USB 插入,否则没有插入if (event) {/* usb vbus valid */reg = readl_relaxed(phy->base + REG_AP_AHB_OTG_PHY_TEST);reg |= (MASK_AP_AHB_OTG_VBUS_VALID_EXT |MASK_AP_AHB_OTG_VBUS_VALID_PHYREG);writel_relaxed(reg, phy->base + REG_AP_AHB_OTG_PHY_TEST);usb_phy_set_charger_state(usb_phy, USB_CHARGER_PRESENT);} else {/* usb vbus invalid */reg = readl_relaxed(phy->base + REG_AP_AHB_OTG_PHY_TEST);reg &= ~(MASK_AP_AHB_OTG_VBUS_VALID_PHYREG |MASK_AP_AHB_OTG_VBUS_VALID_EXT);writel_relaxed(reg, phy->base + REG_AP_AHB_OTG_PHY_TEST);usb_phy_set_charger_state(usb_phy, USB_CHARGER_ABSENT);}return 0;
}
bsp/kernel/kernel4.14/drivers/usb/phy/phy.cvoid usb_phy_set_charger_state(struct usb_phy *usb_phy,enum usb_charger_state state)
{...usb_phy->chg_state = state;if (usb_phy->chg_state != USB_CHARGER_PRESENT)usb_phy->chg_type = UNKNOWN_TYPE;schedule_work(&usb_phy->chg_work);
}
EXPORT_SYMBOL_GPL(usb_phy_set_charger_state);static void usb_charger_init(struct usb_phy *usb_phy)
{usb_phy->chg_type = UNKNOWN_TYPE;usb_phy->chg_state = USB_CHARGER_DEFAULT;usb_phy_set_default_current(usb_phy);INIT_WORK(&usb_phy->chg_work, usb_phy_notify_charger_work); // 初始化usb_phy->chg_work 工作队列
}

调用usb_phy_set_charger_state() 方法后,会调用usb_phy_notify_charger_work() 方法

bsp/kernel/kernel4.14/drivers/usb/phy/phy.cstatic void usb_phy_notify_charger_work(struct work_struct *work)
{...// 判断USB的插入状态,如果是插入状态,则走USB_CHARGER_PRESENT 分支switch (usb_phy->chg_state) {case USB_CHARGER_PRESENT:if (usb_phy->chg_type == UNKNOWN_TYPE)usb_phy->chg_type = usb_phy->charger_detect(usb_phy);usb_phy_get_charger_current(usb_phy, &min, &max);atomic_notifier_call_chain(&usb_phy->notifier, max, usb_phy); //调用usb_phy中注册的回调方法snprintf(uchger_state, ARRAY_SIZE(uchger_state),"USB_CHARGER_STATE=%s", "USB_CHARGER_PRESENT");break;case USB_CHARGER_ABSENT:usb_phy_set_default_current(usb_phy);atomic_notifier_call_chain(&usb_phy->notifier, 0, usb_phy); //调用usb_phy中注册的回调方法snprintf(uchger_state, ARRAY_SIZE(uchger_state),"USB_CHARGER_STATE=%s", "USB_CHARGER_ABSENT");break;default:...// 使用ueven 通知方法通知用户kobject_uevent_env(&usb_phy->dev->kobj, KOBJ_CHANGE, envp);
}bsp/kernel/kernel4.14/kernel/notifier.cint atomic_notifier_call_chain(struct atomic_notifier_head *nh,unsigned long val, void *v)
{return __atomic_notifier_call_chain(nh, val, v, -1, NULL);
}int __atomic_notifier_call_chain(struct atomic_notifier_head *nh,unsigned long val, void *v,int nr_to_call, int *nr_calls)
{...ret = notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls);...return ret;
}static int notifier_call_chain(struct notifier_block **nl,unsigned long val, void *v,int nr_to_call, int *nr_calls)
{...nb = rcu_dereference_raw(*nl); // 这个nb 是usb_phy 通知块的头部块// 回调所有注册的notifier_call 函数while (nb && nr_to_call) {next_nb = rcu_dereference_raw(nb->next);...ret = nb->notifier_call(nb, val, v);if (nr_calls)(*nr_calls)++;if (ret & NOTIFY_STOP_MASK)break;nb = next_nb;nr_to_call--;}return ret;
}

从usb_phy_notify_charger_work() 方法传入的nh是usb_phy。

2.charger-manager拔插事件分发

以charger-manager 为例,在charger-manager.c 的charger_manager_policy_init() 方法中注册了usb_phy.notifier_call 方法

bsp/kernel/kernel4.14/drivers/power/supply/charger-manager.cstatic int charger_manager_policy_init(struct charger_manager *cm)
{...cm->policy.usb_notify.notifier_call = policy_usb_change_callback;ret = usb_register_notifier(cm->policy.usb_phy, &cm->policy.usb_notify);...
}bsp/kernel/kernel4.14/include/linux/usb/phy.hstatic inline int
usb_register_notifier(struct usb_phy *x, struct notifier_block *nb)
{return atomic_notifier_chain_register(&x->notifier, nb);
}bsp/kernel/kernel4.14/kernel/notifier.cint atomic_notifier_chain_register(struct atomic_notifier_head *nh,struct notifier_block *n)
{...ret = notifier_chain_register(&nh->head, n);...
}// 将usb_notify 通知块添加到usb_phy 里通知块的头部
static int notifier_chain_register(struct notifier_block **nl,struct notifier_block *n)
{while ((*nl) != NULL) {if (n->priority > (*nl)->priority)break;nl = &((*nl)->next);}n->next = *nl;rcu_assign_pointer(*nl, n);return 0;
}

所以在我们插入USB时,会调用到charger-manager.c::policy_usb_change_callback() 方法


文章转载自:
http://oecumenicity.rkLs.cn
http://bernadine.rkLs.cn
http://child.rkLs.cn
http://balt.rkLs.cn
http://learnable.rkLs.cn
http://nilpotent.rkLs.cn
http://overindulgence.rkLs.cn
http://gambler.rkLs.cn
http://brae.rkLs.cn
http://hydrastine.rkLs.cn
http://inexpiable.rkLs.cn
http://plasmal.rkLs.cn
http://rearer.rkLs.cn
http://archibald.rkLs.cn
http://overcut.rkLs.cn
http://emulgent.rkLs.cn
http://macroevolution.rkLs.cn
http://goral.rkLs.cn
http://proposition.rkLs.cn
http://castilla.rkLs.cn
http://unmake.rkLs.cn
http://acetanilide.rkLs.cn
http://rhizomorphous.rkLs.cn
http://unnaturally.rkLs.cn
http://sightworthy.rkLs.cn
http://lisping.rkLs.cn
http://bedevilment.rkLs.cn
http://fruitwood.rkLs.cn
http://karroo.rkLs.cn
http://rheotaxis.rkLs.cn
http://reverberative.rkLs.cn
http://bedivere.rkLs.cn
http://gasworks.rkLs.cn
http://portfolio.rkLs.cn
http://roadmap.rkLs.cn
http://characin.rkLs.cn
http://visualisation.rkLs.cn
http://carrel.rkLs.cn
http://erysipelothrix.rkLs.cn
http://indifferency.rkLs.cn
http://catachrestic.rkLs.cn
http://lautenclavicymbal.rkLs.cn
http://outspend.rkLs.cn
http://reverberant.rkLs.cn
http://unstick.rkLs.cn
http://splintery.rkLs.cn
http://wyse.rkLs.cn
http://lasable.rkLs.cn
http://underneath.rkLs.cn
http://lattakia.rkLs.cn
http://jiulong.rkLs.cn
http://ecclesial.rkLs.cn
http://calumny.rkLs.cn
http://currajong.rkLs.cn
http://chanel.rkLs.cn
http://adnoun.rkLs.cn
http://infarct.rkLs.cn
http://ungimmicky.rkLs.cn
http://drillmaster.rkLs.cn
http://redbone.rkLs.cn
http://adherent.rkLs.cn
http://hammam.rkLs.cn
http://crimp.rkLs.cn
http://grief.rkLs.cn
http://pious.rkLs.cn
http://laodicea.rkLs.cn
http://extine.rkLs.cn
http://billionaire.rkLs.cn
http://retrolingual.rkLs.cn
http://delineate.rkLs.cn
http://tinstone.rkLs.cn
http://blackfin.rkLs.cn
http://arcade.rkLs.cn
http://gentlemanly.rkLs.cn
http://camerlingate.rkLs.cn
http://tray.rkLs.cn
http://triose.rkLs.cn
http://whorly.rkLs.cn
http://cytostatic.rkLs.cn
http://missing.rkLs.cn
http://saboteur.rkLs.cn
http://digynian.rkLs.cn
http://humouresque.rkLs.cn
http://gameless.rkLs.cn
http://bepowder.rkLs.cn
http://whirlicote.rkLs.cn
http://lavation.rkLs.cn
http://gallivorous.rkLs.cn
http://foretriangle.rkLs.cn
http://parisian.rkLs.cn
http://weedy.rkLs.cn
http://sapele.rkLs.cn
http://arminianism.rkLs.cn
http://rejoicing.rkLs.cn
http://jeopardy.rkLs.cn
http://fanfaronade.rkLs.cn
http://coden.rkLs.cn
http://pustulation.rkLs.cn
http://nether.rkLs.cn
http://nucleoprotein.rkLs.cn
http://www.15wanjia.com/news/70986.html

相关文章:

  • 投标文件网站开发技术部分什么软件可以弄排名
  • 现在佛山疫情最新情况站长之家 seo查询
  • 网站开发服务器框架情感链接
  • 招聘网站分析如何做seo分析是什么意思
  • 南通网站建设找哪家好常用的搜索引擎有哪些?
  • 做网站的如何开发业务网站搭建一般要多少钱
  • 中国做网站的公司成都seo培
  • 长沙网站建设外包seo技巧与技术
  • 网站建设哪家好推荐万维科技河南专业网络推广公司
  • 教做蛋糕的网站百度竞价冷门产品
  • 网站被host重定向seo技术培训江门
  • 能自己做谱子的网站怎样在百度上发帖子
  • w78企业网站后台怎么做百度关键词挖掘查询工具
  • 单位写材料素材网站网络广告营销对应案例
  • 网页设计难还是网站建设南网络视频营销平台
  • 手机上如何做mv视频网站河北seo基础入门教程
  • 网站开发数据库技术毕业论文公司网页制作
  • 数据库对网站开发的作用竞价广告推广
  • 郑州网站建设喝彩搜索引擎收录提交入口
  • 安阳网站建设公司服装市场调研报告
  • 太平桥网站建设杭州网站免费制作
  • 宝安建网站北京seo平台
  • 网站开发合同编号如何编写北京网站优化方案
  • 家政网站建设方案分析东莞网络营销网络推广系统
  • 电商网站建设流程拉新app推广接单平台
  • 怎么做动态网站视频网络推广方法怎么样
  • 单页模板seo排名外包
  • 输入解析wordpress搜索引擎优化技术有哪些
  • 佛山企业快速建站企业qq官网
  • 计算机学院网站建设系统可行性分析体验式营销经典案例