歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Android系統插入OTG後不休眠

這兩天一直忙著搞插入OTG死機的問題。有時候機器上面插入個U盤,鼠標,或者硬盤,如果這個時候沒有接充電器的話,有很大的概率機器直接死機了,而且必須插入充電器才能開機。實測電池電壓基本為0,原來是電池過流保護了。由於采購的電池保護點過低(1.5A的時候就掛了),只能想辦法把輸出電流降到最低了,嘗試過很多方法,調低背光亮度可以有效解決在正常使用中死機,但是插入OTG死機的問題一直沒有得到解決。

硬件部同事說在插入OTG的時候,充電芯片上仍然有500mA的電流輸入,奇怪,這個時候又不是USB充電狀態,怎麼會有電流呢?不管他,硬件做的事情,俺不懂。想辦法把這個電流去掉吧,查了下充電芯片的文檔,還真有防止OTG插入時回流的,設個寄存器,OK。

今天把OTG插上,接上串口,發現機器竟然不休眠了。問了下同事,說插入OTG就是不休眠的。於是看了下代碼,這裡就簡單分析下吧。

大家知道Android系統獨有的wakelock鎖,只要某個模塊還持有wakelock,系統就不能進入休眠。USB OTG 也是這麼干的。

       在drivers/usb/otg/otg-wakelock.c中

    wake_lock_init(&vbus_lock.wakelock, WAKE_LOCK_SUSPEND,
               vbus_lock.name); //這裡初始化一個wakelock鎖


    otgwl_nb.notifier_call = otgwl_otg_notifications;
    ret = otg_register_notifier(otgwl_xceiv, &otgwl_nb);


//這裡定義一個通知鏈,當有USB EVENT發生時(比如USB 的插入,拔掉),其他內核模塊會調用該通知鏈

由於都是在中斷上下文處理的,otg_register_notifier實現為atomic_notifier_chain_register

        看下otgwl_otg_notifications的實現吧

static int otgwl_otg_notifications(struct notifier_block *nb,
                   unsigned long event, void *unused)
{
    otgwl_handle_event(event);
    return NOTIFY_OK;
}


       可以看出來,該通知鏈就是用來處理OTG(應該所有的USB事件)事件的。

static void otgwl_handle_event(unsigned long event)
{
    unsigned long irqflags;


    spin_lock_irqsave(&otgwl_spinlock, irqflags);


    if (!enabled) {
        otgwl_drop(&vbus_lock);
        spin_unlock_irqrestore(&otgwl_spinlock, irqflags);
        return;
    }


    switch (event) {
    case USB_EVENT_VBUS:
    case USB_EVENT_ID:
    case USB_EVENT_ENUMERATED:
        otgwl_hold(&vbus_lock); //如果是這三種類型,則進行wakelock加鎖操作,從而不會進入休眠了。USB_EVENT_ID就是接OTG了,因為接了OTG,USB的ID會接地,所以這樣命名。

        break;


    case USB_EVENT_NONE: //拔掉USB的時候,加一個超時鎖,2s後自動解鎖
    case USB_EVENT_CHARGER:
        otgwl_temporary_hold(&vbus_lock);
        break;


    default:
        break;
    }


    spin_unlock_irqrestore(&otgwl_spinlock, irqflags);
}

 

 

      再看看在什麼地方通知的該通知鏈

drivers/usb/otg/twl6030-usb.c中的USB中斷處理函數中


      當插入或拔掉USB,會有一個中斷發生,在中斷處理函數中發通知

       atomic_notifier_call_chain(&twl->otg.notifier,
              status, &charger_type);


這樣就做到了當插入USB OTG的時候,系統不能進入休眠。還不知道為什麼這麼做。難道是怕插入U盤,拷貝東西的時候系統休眠從而導致一些問題?

Copyright © Linux教程網 All Rights Reserved