USB OTG通知链机制分析

时间:2024-03-03 17:13:57

static struct platform_driver ehci_msm_driver = {
    .probe    = ehci_msm_probe,
    .remove    = __exit_p(ehci_msm_remove),
    .driver    = {.name = "msm_hsusb_host",
            .pm = &ehci_msm_dev_pm_ops, },
};
ehci_msm_probe(struct platform_device *pdev)
     msm_xusb_init_host(pdev, mhcd);
        otg_set_host(mhcd->xceiv, &hcd->self);
            otg->set_host(otg, host);
                msm_otg_set_host(struct otg_transceiver *xceiv, struct usb_bus *host)
                        dev->usbdev_nb.notifier_call = usbdev_notify;//挂载通知函数
                        usb_register_notify(&dev->usbdev_nb);//注册通知链
                        queue_work(dev->wq, &dev->sm_work);//驱动otg状态机
//--------------------------------------------------------------------------------------------------------
//下面看下通知函数
static int usbdev_notify(struct notifier_block *self,unsigned long action, void *device)
{
    enum usb_otg_state state;
    struct msm_otg *dev = container_of(self, struct msm_otg, usbdev_nb);
    struct usb_device *udev = device;
    int work = 1;
    unsigned long flags;

    if (!udev->parent || udev->parent->parent)//直接插入hub中
        goto out;

    spin_lock_irqsave(&dev->lock, flags);
    state = dev->otg.state;//取出当前otg状态
    spin_unlock_irqrestore(&dev->lock, flags);

    switch (state) {
    case OTG_STATE_A_WAIT_BCON:
        if (action == USB_DEVICE_ADD) {
            pr_debug("B_CONN set\n");
            set_bit(B_CONN, &dev->inputs);//改变位域的值
            if (udev->actconfig) {
                set_aca_bmaxpower(dev,udev->actconfig->desc.bMaxPower * 2);
                goto do_work;
            }
            if (udev->portnum == udev->bus->otg_port)
                set_aca_bmaxpower(dev, USB_IB_UNCFG);
            else
                set_aca_bmaxpower(dev, 100);
        }
        break;
    case OTG_STATE_A_HOST:
        if (action == USB_DEVICE_REMOVE) {
            pr_debug("B_CONN clear\n");
            clear_bit(B_CONN, &dev->inputs);//改变位域的值
            set_aca_bmaxpower(dev, 0);
        }
        break;
    default:
        work = 0;
        break;
    }
do_work:
    if (work) {
        wake_lock(&dev->wlock);
        queue_work(dev->wq, &dev->sm_work);//调度work,驱动otg状态机
    }
out:
    return NOTIFY_OK;
}
//下面是该通知链调用的时机
static int generic_probe(struct usb_device *udev)
{
    ................
    /* USB device state == configured ... usable */
    usb_notify_add_device(udev);//调用通知链函数

    return 0;
}