2018年5月31日 星期四

MIPI-DSI 三種Video Mode 理解

原文: https://blog.csdn.net/eliot_shao/article/details/52474348

D- PHY的物理層支持HS(High Speed)和LP(Low Power)兩種工作模式
  • HS模式:低壓查分信號功耗大高速率(80M -1Gbps) 信號幅值(100mv-300mv)
  • LP模式:單端信號功耗小,速率低(< 10Mbps) 信號幅值(0-1.2V)
在高速模式下,通道狀態是差分的0或1,定義P比N高時定義為1,P比N低時定義為0,此時線上典型電壓為差分200mv
在LP模式下,只用lane0傳輸數據和時鐘,雙向數據傳輸。
鏈路層的模式分為:Command模式Video模式
  • 鏈路層選擇Command模式時,物理層可以為HS模式,也可以為LP模式;
  • 鏈路層選擇Video模式時,物理層只能選擇HS模式。

Video模式時,物理層只能選擇HS模式,下面是video模式下傳遞一個些圖片像素數據包(長包)。
和command模式不同的是Data Type,這裡的Data Type是3Eh,下面有一張Data Type的表。


下面介紹一下qualcomm平台dtsi配置文件中關於對video模式配置說明:
qcom,mdss-dsi-panel-type =“ dsi_video_mode ”;
qcom,mdss-dsi-on-command = [29 01 00 00 00 00 04 B9 FF 83 94
29 01 00 00 00 00 02 C6 EF
05 01 00 00 78 00 02 11 00
05 01 00 00 14 00 02 29 00];
qcom,mdss-dsi-off-command = [05 01 00 00 32 00 02 28 00
05 01 00 00 78 00 02 10 00];
qcom,mdss-dsi-on-command-state =“dsi_lp_mode”;
qcom,mdss-dsi-off-command-state =“dsi_hs_mode”;
qcom,mdss-dsi-on-command是在Mdss_dsi_panel.c (drivers\video\msm\mdss)的
static int mdss_dsi_panel_on(struct mdss_panel_data *pdata)函數里用到的,點亮LCM的指令,未來這個函數將會被FB驅動resume裡面調用到。
類似的,qcom,mdss-dsi-off-command 同樣在文件
Mdss_dsi_panel.c (drivers\video\msm\mdss)的static int mdss_dsi_panel_off(struct mdss_panel_data *pdata)用到,未來將會被FB驅動的suspend函數里調用,用於關掉LCM的指令。

定義這個panel為" dsi_video_mode ",在下發mdss-dsi-on-command之後會把DSI轉換到video-hs模式下。

那麼mdss-dsi-on-command和mdss-dsi-off-command是什麼時候調用的呢?
如果按照MTK平台對LCM處理的思維,大概是這樣的:
LCM_DRIVER nt52021_hd720_dsi_vdo_lcm_drv =
{
.name =“nt52021_hd720_dsi_vdo”,
.set_util_funcs = lcm_set_util_funcs,
.get_params = lcm_get_params,
.init = lcm_init,//reset 調用DSI發初始化數據
.suspend = lcm_suspend,//調用DSI發滅panel數據
.resume = lcm_resume,//reset 調用DSI發初始化數據
.compare_id = lcm_compare_id,
#if(LCM_DSI_CMD_MODE)
.update = lcm_update,
#ENDIF
};
而高通平台是則是在LCM的FB驅動裡面,probe通過調用MDP驅動結構體的初始化函數,調用DSI驅動想MDPcore註冊的回調函數,這些回調函數就是操作DSI發送不同的數據,而這些數據恰恰就是dtsi裡面需要配置的mdss-dsi-on-command和mdss-dsi-off-command。

言歸正傳,前面說明了DSI 在video模式下面發送一些像素圖片的數據包內容,但是在實際傳輸這些數據包的時候需要遵守一些時序控制。
Video模式又分三種子模式:
1 Non-burst Mode Sync pulses:在這種模式下,DSI基於各種不同的同步數據包來做數據同步。這種數據包括:重構,時間校準等。更具體的請參考DSI協議標準。
2 Non-burst Mode Sync event :這種模式和第一種模式很像,但是這種模式不會發重構和時間校準的數據包,它們只發送一種叫做”Sync event”的包。
3 Burst mode:在horizo​​ntal的時序是一樣的情況下DSI會把連接的速度提升到Panel支持的最大速度。在這種模式下發送RGB數據包的時間被壓縮,以留出更多的時間用來傳送其他的數據。
為了使能Video模式Host需要發送各種不同的包到panel用來設置開始和結束的Porch.以下是Video模式中用到的數據包:
•VSS:DSI同步事件包:V同步啟動
•VSE:DSI同步事件包:V同步結束
•BLLP:DSI數據包:任意序列的非限制性DSI數據包或低功耗模式,包括可選的BTA。
•HSS:DSI同步事件包:H同步開始
•HAS:DSI消隱數據包:水平同步活動或低功耗模式,無數據
•HSE:DSI同步事件包:H同步結束
•HFP:DSI消隱數據包:水平前沿或低功耗模式
•HBP:DSI消隱數據包:水平後沿或低功耗模式
•RGB:DSI包:像素流和空包的任意序列
•LPM:低功耗模式包含可選的BTA

上圖頂部有圓弧的代表數據包,長方形的代表時序的狀態。
那麼MIPI host如何輸入一幀的數據呢,下面分別是三種video mode下的數據傳輸時序圖:





結合屏的物理結構才看得動上面時序圖的含義:


以BURST mode為例:
首先會發送VSPW行(VSA lines)的空數據包,在發送VBP lines的空數據包,接著發送VACT lines(屏寬)的有效RGB數據,其中每一行數據都包含HSS 行開始信號+HBP數據包+RGB+HFP數據包。最後就是發送VFP lines的空數據包。這樣就刷滿了一整屏,也就是一幀的數據。

那麼這三種video模式的區別就是傳遞的數序和數據包位置的不同,至於最終在dtsi配置哪一個模式就要根據實際的panel IC所支持video 模式來。
dtsi對應項:
qcom,mdss-dsi-traffic-mode =“non_burst_sync_event”;

另外說明一下dtsi 裡面qcom,mdss-dsi-h-sync-pulse 的含義
在kernel/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt:196中說明了:

這裡所說的pulse mode就是Non-burst Mode Sync pulses模式。
根據時序圖,如果這個值為1就會發圖中紅色圈圈的部分,如果為0就不會發,不過這個只用於這種模式下有效。


2018年5月29日 星期二

Virtualization

http://www.usb-over-network.com/usb-over-network.html

2018年5月21日 星期一

How to update Ubuntu 14.04

[Kernel, for ex: 14.04.1 to 14.04.5]

sudo uname -a ; ls -l /
sudo apt-cache search linux-image
sudo apt-cache search linux-header
sudo apt-get install linux-image-extra-4.4.0-124-generic
sudo apt-get install linux-headers-4.4.0-124-generic
sudo vim /boot/grub/menu.lst
---------------------------------------------------------------------------------------------------
default=0
timeout=3

title vmlinuz-4.4.0-124-generic
root (hd0,0)
kernel /boot/vmlinuz-4.4.0-124-generic root=/dev/xvda console=hvc0 ro
initrd /boot/initrd.img-4.4.0-124-generic

title vmlinuz-3.13.0-147-generic
root (hd0,0)
kernel /boot/vmlinuz-3.13.0-147-generic root=/dev/xvda console=hvc0 ro
initrd /boot/initrd.img-3.13.0-147-generic
---------------------------------------------------------------------------------------------------
sudo reboot
sudo uname -a ; ls -l /


[Distribution, for ex: 14.04.1 to 14.04.5]

sudo apt-get update
sudo apt-get dist-upgrade


2018年5月15日 星期二

How to get MBIM log

原文 http://soflen.blogspot.tw/2015/05/driver-how-to-get-mbim-log.html

[Driver] How to get MBIM log

背景

3G/LTE (WWAN)上網功能在Windows OS上得仰賴OS內建的MBIM以及溝通上網等driver的幫忙。微軟提供一些方式方便工程師取得WWAN相關的log。因工作需求,最近研究這些WWAN debugging的方法,順便紀錄在此。


何謂MBIM


MBIM (Mobile Broadband Interface Model) 是專為走USB界面的3G/LTE網卡所建立的協定,可以把整個3G/LTE上網功能所用到的軟體大略可拆成3部份:
  1. 使用者控制界面。如顯示目前電信商名稱、網路連線狀態、訊號強度等...
  2. 流程控制。也就是MBIM,MBIM對上提供API讓使用者界面呼叫,對下與3G/LTE網卡溝通,設定參數、控制網卡、或處理網卡通知的事件
  3. 溝通橋樑。將MBIM控制命令包裝成USB界面所使用的封包,或是反過來將從網卡進來的封包轉換成上層看得懂的內容



使用內建的Netsh收集debug訊息


微軟特地為網路相關功能提供便於除錯的工具:Netsh。此工具可在命令提示字元下使用。這裡介紹與3G/LTE除錯相關常用的指令

  1. 開始紀錄除錯訊息(執行後即可開始複製問題)
    netsh trace start scenario=MBN globallevel=0xff persist=yes overwrite=yes
  2. 停止紀錄(問題成功複製後即可停止紀錄)
    netsh trace stop
  3. 將除錯訊息轉成文字
    netsh trace convert input=[xxx.etl] output=[xxx.txt]
  4. 顯示scenario mbn包含哪些provider(為了檢查是否支援Win8之後所新增的除錯訊息種類)
    netsh trace show scenario mbn

如何分析debug訊息


想分析有用的Netsh MBIM訊息必須先具備一些基本MBIM溝通原理,可以從這裡下載規格書。系統依照MBIM透過USB與3G/LTE網卡溝通的方式被定義了兩條邏輯通道,一條是給控制用的訊息往來用的;另一條是給資料傳遞用的。而這兩條邏輯通道又可再細分,控制通道可劃分出預設(Default)與中斷(Interrupt)管道;資料則根據方向劃分出輸入(Bulk-In)與輸出(Bulk-Out)。下方列表中的MBIM指的是3G/LTE網卡。

接著,考量到3G/LTE網卡算是週邊裝置的一種,其工作與運算效能一定沒有CPU(這裡稱Host)優秀,因此當Host與網卡交換訊息或資料時,如果要求Host發呆等待網卡處理完畢將會帶來極度系統資源的浪費。因此溝通方式會如下圖A,當Host有資料要給網卡(這裡稱為USB MBIM Function)時,只會要求網卡第一時間確認是否有正確收到訊息,接著CPU資源就會挪去處理其他工作,並且給予網卡時間慢慢處理此訊息或執行被要求的任務。待網卡處理完畢要通知Host的時候,網卡會先將訊息放在buffer中準備好並送出中斷訊息給Host,當Host找網卡領取buffer中訊息時,網卡就能夠第一時間把訊息傳遞給Host而不會耽誤系統資源。
圖A、Encapsulated command response sequence

那麼反過來,如果是網卡有事情要知會Host,其作法亦會類似圖A的最後四個步驟,圖B就是由網卡送訊息給Host的步驟。
圖B、Unsolicited event sequence 

回到Netsh,此工具在Win7和Win8之後的OS版本有很大的差異,使用netsh trace show scenario mbn可以發現Win8之後內建的netsh的mbn scenario包含了一個名為Microsoft-Windows-wmbclass的provider。有了它,你才能看到MBIM控制訊息。依照上一節所提供的步驟,應該可以抓到長的像下圖的log。

將log裡的訊息一步步分析可以得到與上圖A、Encapsulated command response的步驟一樣的流程,下圖畫出WWAN miniport driver初始化的溝通流程。將其中一個訊息的來回步驟再拆分就可以得到右邊與圖A相似的流程。

值得注意的是上圖左邊看到的CID。CID(Command Identifier)用來代表每個Host與網卡之間溝通的命令。搭配不同的UUID(在log裡面標示為Service Id)相同的CID會有不同的意思。舉例來說,當UUID為{a289cc33-bcbb-8b4f-b6b0-133ec2aae6df}代表UUID_BASIC_CONNECT,這時CID=1的命令是MBIM_CID_DEVICE_CAPS,用於在初始化過程中取得網卡能力資訊。當UUID為{533fbeeb-14fe-4467-9f90-33a223e56c3f},這時候的CID=1則作為寫入或讀取SMS設定用的MBIM_CID_SMS_CONFIGURATION。

所以除錯的方式可以看訊息交換的流程是否正確,訊息往來之間的延遲時間是否超過規格要求而被判定timeout等...

2018年5月12日 星期六

Disable a driver in Windows(7) device Manager

Upon any trouble, try below

  • Go to Start–>Search type in gpedit.msc
  • Click the file to open the Local Group Policy Editor and show Windows who is in control!! You want to go here: Computer Configuration->Administrative Templates->System->Device Installation. Click on the subfolder Device Installation Restrictions on the left and on the right side you will see the possible restrictions.
  • Right Click on Prevent Installation of Devices not described by other policy settings and edit this option, set it on ENABLED.
  • Reboot Windows and enjoy its inability to pollute your system with its standard driver, open gpedit.msc again and revert the change so you will be able to install your driver.

2018年5月10日 星期四

[android源碼分析]bluetoothd service的啟動的總體流程分析

原文 https://blog.csdn.net/u011960402/article/details/12966787

本篇文章將會從總體流程上解釋一下每一個函數的意義,具體的每一個函數的解釋將是一個很長的過程,後面的文章中我將會針對每一個有意義的函數來具體分析。
在具體分析bluetoothdservice的啟動之前,我們先來看一下bluetoothd service究竟是什麼,他同樣定義在init.rc中:
servicebluetoothd /system/bin/bluetoothd -n
         所以,很清楚,他就是執行bluetoothd這個應用。那麼bluetoothd是由哪個文件編譯出來的呢,搜索一下就會在bluez下面的src中的Android.mk發現其踪跡:
[plain] view plaincopy 
  1. #  
  2. # bluetoothd  
  3. #  
  4.   
  5. include $(CLEAR_VARS)  
  6.   
  7. LOCAL_SHARED_LIBRARIES := \  
  8.     libbluetoothd  
  9.   
  10. LOCAL_MODULE:=bluetoothd  
所以,很清楚了,我們就在src目錄下面看一下了,作為一個應用程序,第一個映入我們眼簾的肯定就是main了,正好下面有一個main.c,然後裡面還有一個main函數,哈哈,你懂的:
[cpp] view plaincopy 
  1. int  main( int  argc,  char  *argv[])  
  2. {  
  3.     GOptionContext *context;  
  4.     GError *err = NULL;  
  5.     struct  sigaction sa;  
  6.     uint16_t mtu = 0;  
  7.     GKeyFile *config;  
  8. //這個函數就是用來設置uid和capability的,他主要是使得該應用在訪問kernel的時候能夠有權限  
  9. //從註冊可以看到,說目前的android init rc並不支持權限的賦予,所以只能出此下策,毫無疑問,我們需要走到這個ifdef中  
  10. //當然我們也可以從理論上去check一下,在Android.mk中是有這個宏的define的  
  11. #ifdef ANDROID_SET_AID_AND_CAP  
  12.     /* Unfortunately Android's init.rc does not yet support applying 
  13.      * capabilities. So we must do it in-process. */  
  14.     void  *android_set_aid_and_cap( void );  
  15.     //這個就是設置uid為AID_BLUETOOTH,  
  16.     //設置capbility為CAP_NET_RAW| CAP_NET_ADMIN| CAP_NET_BIND_SERVICE  
  17.     android_set_aid_and_cap();  
  18. #endif  
  19.     //默認的初始化,詳細分析見2.2.1  
  20.     init_defaults();  
  21. //既然我們上面已經想法設法得到權限了,這裡就必然不會再把權限釋放了。  
  22. //這個ifdef是不會進去了  
  23. #ifdef HAVE_CAPNG  
  24.     /* Drop capabilities */  
  25.     capng_clear(CAPNG_SELECT_BOTH);  
  26.     capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE | CAPNG_PERMITTED,  
  27.                     CAP_NET_BIND_SERVICE, CAP_NET_ADMIN,  
  28.                         CAP_NET_RAW, CAP_IPC_LOCK, -1);  
  29.     capng_apply(CAPNG_SELECT_BOTH);  
  30. #endif  
  31.     //這裡是解析命令項  
  32.     //使用的是glib命令行解析庫  
  33.     context = g_option_context_new(NULL);  
  34.     //就是根據options定義的內容,自動解析到對應的變量中了  
  35.     //詳細見2.2.2  
  36.     g_option_context_add_main_entries(context, options, NULL);  
  37.   
  38.     if  (g_option_context_parse(context, &argc, &argv, &err) == FALSE) {  
  39.         if  (err != NULL) {  
  40.             g_printerr( "%s\n" , err->message);  
  41.             g_error_free(err);  
  42.         }  else  
  43.             g_printerr( "An unknown error occurred\n" );  
  44.         exit(1);  
  45.     }  
  46.   
  47.     g_option_context_free(context);  
  48.     //下面就是根據上面解析得到的值來看是否需要做一些對應的操作  
  49.     //從init rc中,我們可以看到只有一個-n的參數,但是,我們看是G_OPTION_FLAG_REVERS,猜猜看吧,是的,就是反轉的意思,所以option_detach還是false,其它的就都可以忽略了  
  50.     if  (option_version == TRUE) {  
  51.         printf( "%s\n" , VERSION);  
  52.         exit(0);  
  53.     }  
  54.   
  55.     if  (option_udev == TRUE) {  
  56.         int  err;  
  57.   
  58.         option_detach = TRUE;  
  59.         err = connect_dbus();  
  60.         if  (err < 0) {  
  61.             if  (err == -EALREADY)  
  62.                 exit(0);  
  63.             exit(1);  
  64.         }  
  65.     }  
  66.     //後台運行,這裡也就不去  
  67.     if  (option_detach == TRUE && option_udev == FALSE) {  
  68.         if  (daemon(0, 0)) {  
  69.             perror( "Can't start daemon" );  
  70.             exit(1);  
  71.         }  
  72.     }  
  73.     //重新設置權限  
  74.     umask(0077);  
  75.     //bt log的初始化,這裡就不關心了,android中若想打印log需要重新修改  
  76.     __btd_log_init(option_debug, option_detach);  
  77.     //設置一個signal的處理函數,不一一看了,關係不大  
  78.     memset(&sa, 0,  sizeof (sa));  
  79.     sa.sa_flags = SA_NOCLDSTOP;  
  80.     sa.sa_handler = sig_term;  
  81.     sigaction(SIGTERM, &sa, NULL);  
  82.     sigaction(SIGINT, &sa, NULL);  
  83.   
  84.     sa.sa_handler = sig_debug;  
  85.     sigaction(SIGUSR2, &sa, NULL);  
  86.   
  87.     sa.sa_handler = SIG_IGN;  
  88.     sigaction(SIGPIPE, &sa, NULL);  
  89.     //加載配置文件  
  90.     config = load_config(CONFIGDIR  "/main.conf" );  
  91.     //解析配置文件,這裡就是根據main.conf中的配置進行相應的設置  
  92.     //詳細分析見2.2.3  
  93.     parse_config(config);  
  94.     //這裡就是初始化dbus  
  95.     agent_init();  
  96.   
  97.     if  (option_udev == FALSE) {  
  98.         //連接dbus  
  99.         if  (connect_dbus() < 0) {  
  100.             error( "Unable to get on D-Bus" );  
  101.             exit(1);  
  102.         }  
  103.     }  else  {  
  104.         if  (daemon(0, 0)) {  
  105.             perror( "Can't start daemon" );  
  106.             exit(1);  
  107.         }  
  108.     }  
  109.     //啟動sdp server,詳細分析見2.2.4  
  110.     start_sdp_server(mtu, main_opts.deviceid, SDP_SERVER_COMPAT);  
  111.     //在main.conf中attrib_server=false,所以這裡就不進入了  
  112.     if  (main_opts.attrib_server) {  
  113.         if  (attrib_server_init() < 0)  
  114.             error( "Can't initialize attribute server" );  
  115.     }  
  116.     /* Loading plugins has to be done after D-Bus has been setup since 
  117.      * the plugins might wanna expose some paths on the bus. However the 
  118.      * best order of how to init various subsystems of the Bluetooth 
  119.      * daemon needs to be re-worked. */  
  120. //從註釋來看,plugins的加載最好是在D-Bus已經建立完成的基礎上。  
  121. //他們也認為這個地方做好再重寫一下,我們就先將就著看看吧  
  122. //這裡的option_plugin和option_noplugin都是null,因為我們的bluetoothd中並沒有他們的參數  
  123. //包含了hciops,audio,input,network,health  
  124. //具體參見2.2.5中  
  125.     plugin_init(config, option_plugin, option_noplugin);  
  126.     //創建主循環  
  127.     event_loop = g_main_loop_new(NULL, FALSE);  
  128.     //adapter的ops的建立,詳細分析見2.2.6  
  129.     if  (adapter_ops_setup() < 0) {  
  130.         error( "adapter_ops_setup failed" );  
  131.         exit(1);  
  132.     }  
  133.     //會根據remember_powered參數來決定是否需要做什麼,我們這裡是是false,所以,沒有做什麼,直接ruturn。  
  134.     rfkill_init();  
  135.   
  136.     DBG( "Entering main loop" );  
  137.     //進入主循環,就卡在這邊了。  
  138.     //對主循環的影響都在上面的那些signal的處理函數中,我們可以理解,沒有什麼異常就會卡在這邊了,知道藍牙關閉才會退出了  
  139.     g_main_loop_run(event_loop);  
  140.     //之後的內容就不再詳細分析了  
  141.     ……  
  142. }