本文共 8865 字,大约阅读时间需要 29 分钟。
下面跟踪进入设备控制器时的流程。 static void msm_otg_start_peripheral(struct otg_transceiver *xceiv, int on) { struct msm_otg *dev = container_of(xceiv, struct msm_otg, otg); ........... if (on) {//打开设备控制器 ........... usb_gadget_vbus_connect(xceiv->gadget); } else {//关闭设备控制器 atomic_set(&dev->chg_type, USB_CHG_TYPE__INVALID);//设置充电器的类型为无效 usb_gadget_vbus_disconnect(xceiv->gadget); ............... } } static inline int usb_gadget_vbus_connect(struct usb_gadget *gadget) { if (!gadget->ops->vbus_session) return -EOPNOTSUPP; return gadget->ops->vbus_session(gadget, 1); } static inline int usb_gadget_vbus_disconnect(struct usb_gadget *gadget) { if (!gadget->ops->vbus_session) return -EOPNOTSUPP; return gadget->ops->vbus_session(gadget, 0); } 上面两个函数都调用gadget->ops->vbus_session(gadget, 0/1)函数,该函数的回调注册的地方为: static const struct usb_gadget_ops msm72k_ops = { .get_frame = msm72k_get_frame, .vbus_session = msm72k_udc_vbus_session, .vbus_draw = msm72k_udc_vbus_draw, .pullup = msm72k_pullup, .wakeup = msm72k_wakeup, .set_selfpowered = msm72k_set_selfpowered, }; static int msm72k_probe(struct platform_device *pdev) { ............. ui->gadget.ops = &msm72k_ops; ............ } 看下回调函数的实现: static int msm72k_udc_vbus_session(struct usb_gadget *_gadget, int is_active) { struct usb_info *ui = container_of(_gadget, struct usb_info, gadget); struct msm_otg *otg = to_msm_otg(ui->xceiv); if (is_active || atomic_read(&otg->chg_type) == USB_CHG_TYPE__WALLCHARGER || atomic_read(&otg->chg_type) == USB_CHG_TYPE__DOCKCHARGER) wake_lock(&ui->wlock);//如果为active锁定wakelock msm_hsusb_set_vbus_state(is_active); return 0; } void msm_hsusb_set_vbus_state(int online) { unsigned long flags; struct usb_info *ui = the_usb_info; if (online) {//根据online的值,设置ui的状态 ui->usb_state = USB_STATE_POWERED; ui->flags |= USB_FLAG_VBUS_ONLINE; } else { ui->gadget.speed = USB_SPEED_UNKNOWN; ui->usb_state = USB_STATE_NOTATTACHED; ui->flags |= USB_FLAG_VBUS_OFFLINE; } if (in_interrupt()) {//如果处于中断中,则用系统是schedule_work调度 schedule_work(&ui->work); } else {//直接调度 spin_unlock_irqrestore(&ui->lock, flags); usb_do_work(&ui->work);//调度work return; } } static int __init android_probe(struct platform_device *pdev) { usb_composite_register(&android_usb_driver); usb_gadget_register_driver(&composite_driver); usb_start(ui); ui->flags |= USB_FLAG_START;//设置初始flag标记 schedule_work(&ui->work);//调度work----------------------------------------->111 } //下面看下调度的work static int usb_get_max_power(struct usb_info *ui) { suspended = ui->usb_state == USB_STATE_SUSPENDED ? 1 : 0;//如果为suspend状态,则返回0 configured = atomic_read(&ui->configured);// 如果没有配置也返回0 bmaxpow = ui->b_max_pow;//返回最大值 if (suspended || !configured) return 0; return bmaxpow; } 其中ui->b_max_pow的赋值流程如下: static irqreturn_t usb_interrupt()//中断中进行枚举 handle_setup(ui); ui->driver->setup(); composite_setup()//回调函数 static int set_config() usb_gadget_vbus_draw(gadget, power);//设置能拉到的电流 gadget->ops->vbus_draw(gadget, mA); msm72k_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA) ui->b_max_pow = mA;//保存到ui->b_max_pow中 ui->flags = USB_FLAG_CONFIGURED;//设置flag为config schedule_work(&ui->work);//调度work static void usb_do_work(struct work_struct *w) { struct usb_info *ui = container_of(w, struct usb_info, work); struct msm_otg *otg = to_msm_otg(ui->xceiv); unsigned flags, _vbus; for (;;) { flags = ui->flags;//读出flag ui->flags = 0;//读出后清零 _vbus = is_usb_online(ui);//第一次,结果为_vbus=0,插入是_vbus=1 /* give up if we have nothing to do */ if (flags == 0)//第一再次循环时,走到这里退出for循环 break; switch (ui->state) { case USB_STATE_IDLE://初始值为0 if (flags & USB_FLAG_START) {//第一次为USB_FLAG_START if (!_vbus) { ui->state = USB_STATE_OFFLINE;//第一次,置usb状态为USB_STATE_OFFLINE break;//跳出该switch语句 } break; case USB_STATE_ONLINE://继续从上一个状态循环 if (atomic_read(&ui->offline_pending)) {//控制器重启的时候会走该分支 switch_set_state(&ui->sdev, 0); atomic_set(&ui->offline_pending, 0); } if (flags & USB_FLAG_VBUS_OFFLINE) { ui->chg_current = 0;//设置当前充电电流为0 dev_dbg(&ui->pdev->dev,"msm72k_udc: ONLINE -> OFFLINE\n"); atomic_set(&ui->running, 0);//设置running为0 atomic_set(&ui->configured, 0);//设置配置为0 if (ui->driver) { dev_dbg(&ui->pdev->dev,"usb: notify offline\n"); ui->driver->disconnect(&ui->gadget);//调用driver的断开函数 } ............ msm72k_pullup_internal(&ui->gadget, 0);//下拉D+线电阻 ........... switch_set_state(&ui->sdev, 0);//上报offline的状态 ui->state = USB_STATE_OFFLINE;//设置usb的状态为USB_STATE_OFFLINE usb_do_work_check_vbus(ui);//判断是否处于离线状态,并设置ui->flags |= USB_FLAG_VBUS_ONLINE,或者USB_FLAG_VBUS_OFFLINE ................. break; } if (flags & USB_FLAG_SUSPEND) {//---------------------->222 int maxpower = usb_get_max_power(ui);//获得最大电流 if (maxpower < 0){//插入usb进入该状态时,进入该分支 break;} otg_set_power(ui->xceiv, 0);//设置最大电流为0 if (release_wlocks) wake_unlock(&ui->wlock); break; } if (flags & USB_FLAG_CONFIGURED) {//------------------------------->333 int maxpower = usb_get_max_power(ui);//获得最大电流 switch_set_state(&ui->sdev,atomic_read(&ui->configured));//发送sent uevent SWITCH_NAME=MSM72K_UDC , SWITCH_STATE=online. ui->chg_current = maxpower;//保存当前的充电电流 if (maxpower < 0) break; otg_set_power(ui->xceiv, maxpower);//设置最大电流 break; } if (flags & USB_FLAG_RESET) { dev_dbg(&ui->pdev->dev,"msm72k_udc: ONLINE -> RESET\n"); msm72k_pullup_internal(&ui->gadget, 0);//写寄存器USBCMD_RS,控制D+下拉 usb_reset(ui);//reset udc控制器,并atomic_set(&ui->running, 1); msm72k_pullup_internal(&ui->gadget, 1);//写寄存器USBCMD_RS,控制D+上拉 dev_dbg(&ui->pdev->dev,"msm72k_udc: RESET -> ONLINE\n"); break; } break; case USB_STATE_OFFLINE: if ((flags & USB_FLAG_VBUS_ONLINE) && _vbus) {//插入usb cable时进入该分支 ............... dev_dbg(&ui->pdev->dev,"msm72k_udc: OFFLINE -> ONLINE\n"); usb_reset(ui);//reset udc控制器,并atomic_set(&ui->running, 1); ui->state = USB_STATE_ONLINE;//改变ui->state的状态 usb_do_work_check_vbus(ui);//判断是否处于离线状态,并设置ui->flags |= USB_FLAG_VBUS_ONLINE,或者USB_FLAG_VBUS_OFFLINE ret = request_irq(otg->irq, usb_interrupt,IRQF_SHARED,ui->pdev->name, ui);//申请irq中断 ui->irq = otg->irq;//保存中断 enable_irq_wake(otg->irq);//设置该irq为系统唤醒源 if (!atomic_read(&ui->softconnect)) break; msm72k_pullup_internal(&ui->gadget, 1);//把D+数据线拉高 ................ } break; } if (is_usb_online(ui)) switch_set_state(&ui->sdev_cable, 1); else{//第一次初始化时,上报usb cable没有插入的状态 switch_set_state(&ui->sdev_cable, 0);} } } 下面分析下状态机的触发流程: 1、android_probe初始化,会调度usb_do_work,当没有usb cable插入的时候,ui->state = USB_STATE_IDLE,ui->flag = USB_FLAG_START,进入状态机,并判断_vbus,由于是第一次,_vbus为0,ui->state = USB_STATE_OFFLINE,然后上报usb cable没有插入,然后再次进入for循环,由于flag值没有变化为0,则跳出该for循环。 2、当插入usb cable时,由于调度了设备控制器的流程,然后调用usb_do_work,设置了标记ui->flags |= USB_FLAG_VBUS_ONLINE;由于没有插入前的状态为ui->state = USB_STATE_OFFLINE,所以 继续进入状态机,设置状态为ui->state = USB_STATE_ONLINE,然后检测flag的状态有没有改变,对ui->flag重新赋值,上报usb cable插入。然后usb_interruput触发了中断,设置ui->flags = USB_FLAG_SUSPEND,然后调度work,再次进入状态机。由于maxpower小于0,则退出switch语句,再次上报usb cable插入。继续进入for循环,由于flag状态没有改变,在退出for循环。在usb_interruput中,接收到端口变化中断,则置ui->flags = USB_FLAG_CONFIGURED,然后调度work,进入状态机,上报online状态。由于maxpower为0,则退出swtich语句,然后上报usb_cable插入。 3、当usb拔出的时候,先收到suspend中断,调度work,然后会关闭设备控制器,设置ui->flags |= USB_FLAG_VBUS_OFFLINE的状态,然后调度usb_do_work,进入状态机,上报offline的状态,设置usb的状态为USB_STATE_OFFLINE,设置running为0等,上报usb cable拔出,继续进入状态机循环,然后没有状态改变时退出for循环。 在usb中断中改变状态,然后调度work static irqreturn_t usb_interruput(int irq, void *data)//该中断和上面的msm_otg_irq为共享中断,公用中断号132 { struct usb_info *ui = data; unsigned n; unsigned long flags; n = readl(USB_USBSTS);//读取状态寄存器的值 writel(n, USB_USBSTS);//清除该状态寄存器 if (!atomic_read(&ui->running))//还在重启中是忽略该中断 return IRQ_HANDLED; if (n & STS_PCI) {//端口变化中断,当端口进入全速或者高速模式时,或者端口退出全速或高速模式由于接收到usb reset信号,或者suspend event。 msm_hsusb_set_speed(ui);//读取硬件寄存器USB_PORTSC,设置端口速度 if (atomic_read(&ui->configured)) {//查看配置是否为1? wake_lock(&ui->wlock);//锁定wakelock ui->usb_state = USB_STATE_CONFIGURED;//改变usb状态 ui->flags = USB_FLAG_CONFIGURED;//改变flag标记 ui->driver->resume(&ui->gadget);//唤醒gadget schedule_work(&ui->work);//调度work------------------------------->333 } else { msm_hsusb_set_state(USB_STATE_DEFAULT);//如果不为1,则设置the_usb_info->usb_state = USB_STATE_DEFAULT; } } if (n & STS_URI) {//当设备控制器检测到usb reset信号时,执行该分支,并且进入USB_STATE_DEFAULT的状态 dev_dbg(&ui->pdev->dev, "reset\n"); ui->gadget.speed = USB_SPEED_UNKNOWN;//设置usb的速度为unknow msm_hsusb_set_state(USB_STATE_DEFAULT);//设置usb的状态为默认状态 ............... if (atomic_read(&ui->configured)) {//如果有配置 /*做一些清理工作*/ } ............... } if (n & STS_SLI) {//处于suspend状态 dev_dbg(&ui->pdev->dev, "suspend\n"); ui->usb_state = USB_STATE_SUSPENDED;//改变状态 ui->flags = USB_FLAG_SUSPEND;//改变flag ui->driver->suspend(&ui->gadget); schedule_work(&ui->work);//调度usb_do_work-------------------------------------------->222 } if (n & STS_UI) {//由传输事务引起的中断,或者是接收到short packeage. n = readl(USB_ENDPTSETUPSTAT); if (n & EPT_RX(0)) handle_setup(ui);//usb枚举过程 n = readl(USB_ENDPTCOMPLETE); writel(n, USB_ENDPTCOMPLETE); while (n) { unsigned bit = __ffs(n); handle_endpoint(ui, bit);//处理端点传输 n = n & (~(1 << bit)); } } return IRQ_HANDLED; }转载地址:http://krdmi.baihongyu.com/