【Qt】DebugView and qInstallMsgHandler


【目的】

  • 將 qDebug() 導入 DebugView。
  • 以下提供使用官方 API (OutputDebugString) 配合 qInstallMsgHandler 輸出到 DebugView 的方式。

【環境】

【說明】

先由一些資料建立觀念

  • 使用 qDebug() 時可以將 DebugView 打開看看,有時輸出訊息會直接導到 DebugView。
    左圖紅色框第二個為DebugView打開前, Application Output還可以看到訊息。
    第三個是DebugView 打開後,只會看到下面訊息,表示訊息已被導到 DebugView。
    Cannot retrieve debugging output!
    image   image
  • OutputDebugString (基本程式 main.cpp)
    • 官方輸出到 DebugView
      在user-space就是呼叫 OutputDebugString ,
      而kernel-space就是呼叫DbgPrint。以下列出主要程式。
      #include <QtGui/QApplication>
      #include "dialog.h"
      #include <windows.h>
      int main(int argc, char *argv[])
      {
          QApplication a(argc, argv);
          OutputDebugString(L"Echo Message to DebugView");
          Dialog w;
          w.show();
          return a.exec();
      }
    • 結果一樣可以在 DebugView 可以看到
      image
  • qInstallMsgHandler
    • qInstallMsgHandler 的用法類似下面,可以自己指定輸出的方式,
      不過卻卻無法輸出到 DebugView。
      #include <QtGui/QApplication>
      #include "dialog.h"
      #include <qDebug>
      
      void myMessageOutput(QtMsgType type, const char *msg)
       {
           switch (type) {
           case QtDebugMsg:
               fprintf(stderr, "Debug: %s\n", msg);
               break;
           case QtWarningMsg:
               fprintf(stderr, "Warning: %s\n", msg);
               break;
           case QtCriticalMsg:
               fprintf(stderr, "Critical: %s\n", msg);
               break;
           case QtFatalMsg:
               fprintf(stderr, "Fatal: %s\n", msg);
               abort();
           }
       }
      
      int main(int argc, char *argv[])
      {
          qInstallMsgHandler(myMessageOutput);
          QApplication a(argc, argv);
          Dialog w;
          w.show();
          qDebug("Dialog is shown");
          return a.exec();
      }
    • 要解決這個問題,需要修改讓訊息可輸出到 DebugView
      #include <QtGui/QApplication>
      #include "dialog.h"
      #include <qDebug>
      #include <windows.h>
      
      void myMessageOutput(QtMsgType type, const char *msg)
       {
          char str[255];
          switch (type) {
           case QtDebugMsg:
               sprintf(str, "Debug: %s", msg);
               break;
           case QtWarningMsg:
               sprintf(str, "Warning: %s", msg);
               break;
           case QtCriticalMsg:
               sprintf(str, "Critical: %s", msg);
               break;
           case QtFatalMsg:
               sprintf(str, "Fatal: %s", msg);
               abort();
           default:
               sprintf(str, "Unknown: %s", msg);
           }
          OutputDebugStringA(str);
       }
      
      int main(int argc, char *argv[])
      {
          qInstallMsgHandler(myMessageOutput);
          QApplication a(argc, argv);
          Dialog w;
          w.show();
          qDebug("Dialog is shown");
          qWarning("Dialog is shown");
          qCritical("Dialog is shown");
          //qFatal("Dialog is shown");
          return a.exec();
      }
    • 目前問題
  • 延伸到 Linux 平台
    • 如果要將訊息輸出到 syslog,先看一下基本用法
      #incluse <syslog.h>
      main(int argc,char *argv[]){
        char *str = "test";
        openlog(argv[0],LOG_PID,LOG_USER);
        syslog(LOG_INFO,"%s\n",str);
        closelog();
      }
    • 通常會寫成一個巨集比較方便
      #ifndef NDEBUG
      #define printd(msg, args...) \
        do { \
          openlog("[Log]",LOG_PID,LOG_USER); \
          syslog(LOG_INFO, msg, ##args); \
          closelog(); \
        }while(0)
      #else
      #define printd(msg, args...)    do { } while(0)
      #endif
    • 所以 myMessageOutput 可以改成如此
      void myMessageOutput(QtMsgType type, const char *msg)
      {
          openlog(argv[0],LOG_PID,LOG_USER);
          switch (type) {
              case QtDebugMsg:
                  syslog(LOG_INFO,"Debug   : %s\n",str);
                  break;
              case QtWarningMsg:
                  syslog(LOG_INFO,"Warning : %s\n",str);
                  break;
              case QtCriticalMsg:
                  syslog(LOG_INFO,"Critical: %s\n",str);
                  break;
              case QtFatalMsg:
                  syslog(LOG_INFO,"Fatal   : %s\n",str);
                  //abort();
              }
          closelog();
      }
    • 和 Windows平台的DebugView 作整合,目前的想法是透過 ifdefine 控制, 目前程式碼先省略。
  • 嘗試修改讓訊息輸出到 檔案
    直接將 Debug message 輸出到檔案也是一個不錯的方式 myMessageOutput 可以寫成這樣。
    請注意 fclose() 要放在 if 裡面,表示開檔成功才作關檔動作。
    const char* logfile = "/var/log/log.txt";
    void myMessageOutput(QtMsgType type, const char *msg)
    {
        FILE *fp = fopen(logfile, "a");
        if (fp)
        {
            switch (type) {
            case QtDebugMsg:
                fprintf(fp, "Debug   : %s\n", msg);
                break;
            case QtWarningMsg:
                fprintf(fp, "Warning : %s\n", msg);
                break;
            case QtCriticalMsg:
                fprintf(fp, "Critical: %s\n", msg);
                break;
            case QtFatalMsg:
                fprintf(fp, "Fatal   : %s\n", msg);
                //abort();
            }
            fclose(fp);
        }
    }
  • 輸出到Kiwi Syslog Server
    如果使用 busybox 的話建議直接啟用將 –R 參數將訊息往遠端機器丟,
    除非特殊需求否則不需自己調用 socket 。
    [參考] BusyBox - The Swiss Army Knife of Embedded Linux
    http://www.busybox.net/downloads/BusyBox.html
    busybox syslogd -R 192.168.1.1:601

【想法】

  • 其實調用 qDebug/qWarning/qCritical/qFatal 對除錯而言,幫助並不大,要做的應該是將要做的事按照
    Init/Process/Close … 作分類會比較好。

【參考】

【Google】Chrome


【目的】

  • 研究 Google Chrome 的書籤(Bookmarks)與歷史記錄(History)。

【環境】

【說明】

  1. Chrome 將使用者資料以 Sqlite/Json 的格式存在下面資料夾
    C:\Users\[User Name]\AppData\Local\Google\Chrome\User Data\Default
  2. History (歷史記錄),利用 Sqliteman 打開 History這檔案,其中的
    1. urls 代表造訪過的 url。
      以其中一筆資料為例,由前兩筆就可看出造訪資料。
      1. id: 編號 (ex. 2 )
      2. url: 網址 (ex.http://www.google.com.tw/search)
      3. title: 網址抬頭 (ex.MegaTouch Framework - Google 搜尋)
      4. visit_count: 造訪次數
      5. 以下省略
        image
    2. keyword_search_terms
      1. keyword_id: 編號 (ex.2 , [問題]為目前看到的都是 2)
      2. url_id: 關連到 urls 表格的 id (ex. 1815 代表關連到 urls 裡面 id=1815 的搜尋結果資料)
      3. lower_term: 使用者所搜尋過的字串,小寫方式(ex. sqlite 資料庫, s 會變小寫)
      4. term: 使用者所搜尋過的字串,大小寫不變(ex. Sqlite 資料庫)
        image
  3. Bookmarks(書籤)
    1. 採用的是JSON格式,請直接將內容貼到 JSON Editor(http://braincast.nl/samples/jsoneditor/)
      就可看到比較方便越讀的內容。
       image
  4. Cookies
    1. Cookies 資料,此處不詳述。
      image
  5. Thumbnails(縮圖)
    1. thumbnails 提供類似 Speed Dail 的功能
      1. url_id
      2. boring_score
      3. good_clipping
      4. at_top
      5. last_updated
      6. data: 採用 sqlite blob 格式,裡面的就是 直接將 png 格式圖檔存在資料庫。
        image
      7. 如果要直接編修圖形,直接 Double-Click {blob} 後就會出現下面視窗,使用 Open/Save 就可編輯。
        image 

【問題】

  1. 如何找出 Thumbnails 裡面的網址與說明。
  2. 如何將圖檔存入與讀出 Sqlite
    A: sqlite处理BLOB数据 http://sqlite.com.cn/bbs/topicdisp.asp?tid=34&topage=179

【參考】

【Qt】Sqlite


首先複習一下 sqlite shell 的用法,驗證幾個重點

【Sqlite】

  • Sqlite 支援的資料型態
    • TEXT
    • NUMERIC
    • INTEGER
    • REAL
    • NONE(BOOL)
  • 基本操作,假設我們要建立一個像下面一樣的資料庫來記錄姓名,
    中間混合繁體中文(Big5所謂的許功蓋問題),英文(Chen)與俄文(Ира)。
      firstname(名) lastname(姓)
    第一筆資料 功蓋 許
    第二筆資料 Ира Chen
  • 首先進入sqlite ,先建立名為 p.db 的資料庫來儲存上面資料。
    $ sqlite3 p.db
    SQLite version 3.6.16
    Enter ".help" for instructions
    Enter SQL statements terminated with a ";"
  • create: 先建立資料表,一個資料庫裡面可以有許多資料表。
    sqlite> create table person (firstname varchar(20), lastname varchar(20));
  • 列出資料表,確定上個動作已經是成功的。
    sqlite> .table
    person
  • 列出 schema,確認所建立的欄位。 
    sqlite> .schema person
    CREATE TABLE person (firstname varchar(20), lastname varchar(20));
  • insert: 開始新增我們所需要的那兩筆資料。
    sqlite> insert into person values('功蓋', '許');
    sqlite> insert into person values('Ира', 'Chen');
  • select: 查詢rowid
    sqlite> select rowid from person;
    1
    2
  • select: 查詢資料,確定新增兩筆資料成功。
    sqlite> select * from person;
    功蓋|許
    ира|Chen
  • where: 利用 select 配合 where 查詢符合姓為 Chen 這個人的資料。
    sqlite> select * from person where lastname='Chen';
    ира|Chen
  • 建立視圖,可區別一般使用者或管理者所要看到的資料。
    sqlite> create view pv as select lastname from person;
    sqlite> select * from pv;
    許
    Chen
  • 更新,把 Ира Chen 改成 May Chen。 
    sqlite> 
    sqlite> update person set firstname='May' where lastname='Chen';
    sqlite> select * from person;
    功蓋|許
    May|Chen
  • 刪除,把 第二筆資料刪除,這樣就只剩下 許功蓋 這個人
    sqlite> delete from person where lastname='Chen';
    sqlite> select * from person;
    功蓋|許
  • 新增欄位,假設我們新增加一個 id 的欄位
    sqlite> alter table person add id integer;
    sqlite>  .schema person
    CREATE TABLE person(firstname varchar(20), lastname varchar(20), id integer);
  • 刪除欄位
    目前好像不支援。 (http://www.sqlite.org/lang_altertable.html)
    解決想法是整個 table 刪掉並重建欄位。
    (1) 更名原始資料表,如由 table 改成 table_tmp  (2) 建立新Table,新Table是不包含要刪除的欄位的。
    (3) 由備份的 table_tmp 整個倒入新 table,不包含要拿掉欄位的資料。
  • 更名欄位
    目前好像不支援。 解決方式同上。只是在建立新table時,作欄位更名的動作。
  • 更名資料表,將 person 資料表改名成 p 資料表。 
    sqlite> alter table person remane to p;
    sqlite> .schema p
    CREATE TABLE "p"(firstname varchar(20), lastname varchar(20), id integer);
  • 資料庫匯出(未驗證)
    $sqlite3 p.db “.dump” > p.sql
  • 資料庫匯入(未驗證)
    $ sqlite3 p.db < p.sql
  • 離開
    sqlite> .quit 
    $ 

【Sqliteman】

  • 除了 sqlite shell 以外,還可以使用一套據說是 QT 寫的 sqliteman http://sqliteman.com/ 來觀察剛剛的結果。運行結果如下。可以看到 Tables 與 Views。
    image
  • 有時作者並不一定會在現行版本發行Windows版本,就要往回找之前發行的版本。
    下載網址 http://sourceforge.net/projects/sqliteman/files/image

【C】

在 C 的使用 (目前沒有用C特別處理 Unicode的問題,參考 http://evanjones.ca/unicode-in-c.html)

  1. 安裝套件
    $ apt-get install libsqlite3-dev
  2. 程式碼( 存成 p.c )
    #include <stdio.h> 
    #include <sqlite3.h>
     
    static int callback(void *NotUsed, int argc, char **argv, char **azColName){ 
    int i; 
    for(i=0; i<argc; i++){ 
    printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL"); 
    } 
    printf("\n"); 
    return 0; 
    } 
     
    int main(int argc, char **argv){ 
    sqlite3 *db; 
    char *zErrMsg = 0; 
    int rc; 
     
    if( argc!=3 ){ 
    fprintf(stderr, "Usage: %s DATABASE SQL-STATEMENT\n", argv[0]); 
    return 1;
    } 
    rc = sqlite3_open(argv[1], &db); 
    if( rc ){ 
    fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db)); 
    sqlite3_close(db); 
    return 1; 
    } 
    rc = sqlite3_exec(db, argv[2], callback, 0, &zErrMsg); 
    if( rc!=SQLITE_OK ){ 
    fprintf(stderr, "SQL error: %s\n", zErrMsg); 
    sqlite3_free(zErrMsg); 
    } 
    sqlite3_close(db); 
    return 0; 
    }
  3. 編譯(注意要加 –lsqlite3)
    $ gcc -o p p.c –lsqlite3 
  4. 執行
    $./p p.db "select * from person;"
    firstname = 功蓋
    lastname = 許
    id = NULL
    
    firstname = ира
    lastname = Chen
    id = NULL

【Qt】
配合QT的使用。其中需要注意的是,Sqlite內部編碼為 unicode, 而Qt 我們指定為 UTF-8。
Qt 寫入 Sqlite 需先將內容轉換成 Unicode,而Qt 讀取Sqlite時不需要,因 Qt 會自行偵測。
以下只擷取出重點程式碼。

  1. 記得載入 QtSql module。
    image
  2. dialog.h ( include  部分)
    #include <QtSql>
    #include <QTableView>
    #include <QMessageBox>
  3. dialog.cpp
    bool Dialog::SqliteTest()
    {
    
        QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
        db.setDatabaseName("database.dat");
        if (!db.open())
        {
            QMessageBox::warning(0, QObject::tr("Database Error"),
                                 db.lastError().text());
            return false;
        }
        QSqlQuery rs(db);
        rs.exec("CREATE TABLE person (firstname varchar(20), lastname varchar(20))");
        QByteArray strSql("insert into person(firstname,lastname) \
                       values('Ира', 'Chen')");
        QTextCodec *codec = QTextCodec::codecForName("UTF-8");
        QString string = codec->toUnicode(strSql);
        rs.exec(string);
    
        QSqlQueryModel *model = new QSqlQueryModel;
        model->setQuery("SELECT * FROM person");
        model->setHeaderData(0, Qt::Horizontal, "firstname");
        model->setHeaderData(1, Qt::Horizontal, "lastname");
    
        QTableView *view = new QTableView;
        view->setWindowTitle("QSqlQueryModel");
        view->setModel(model);
        view->show();
    
        db.close();
    }
  4. 執行結果
    image

【參考】

【Qt】SQLCipher


【目的】

  • 加密 Sqlite 資料。

【方法】

方法一

  1. 調用 C 的crypto libraries 將原始資料(如 Base64Encoder)加密。
  2. 將加密後的資料存入 Sqlite。
  3. 缺點就是資料量會變大,讀取速度變慢。

方法二

  1. 另一個方法據說原作者留有設定帳號密碼的function,不過這部分還得測試。
    且這部分須更改sqlite原始碼,較不適用已有Sqlite的現成平台。

方法三

  1. 利用現成的SQLCipher達到加密效果。此方法也適用用Xcode開發的程式。
  2. SQLCipher 利用的是 OpenSSL,AES-256…格式作加密。
  3. SQLCipher使用MIT-style license,這是一種比較寬鬆的版權協定。

【程式】

  • tbd

【參考】

【其它參考】

參考價值不大。

【Qt】Embedded Linux


Qt Embedded 分成 Linux/Windows CE/Symbian 三種,此處指 Linux 平台。

【目的】

  • 基本 Qt Embedded 環境設置。

【基本環境】

  1. Qt Creator。
  2. Ubuntu 套件(libxrender-dev不一定需要)。
    $apt-get install libxtst-dev libxrender-dev libdirectfb-dev

【步驟】

  1. 下載 Qt ,目前使用 4.6.3 ( Qte 和 Qt 的 tarball 都是同一個,可以透過 configure 來選擇)
    $ wget http://get.qt.nokia.com/qt/source/qt-everywhere-opensource-src-4.6.3.tar.gz 
  2. 編譯 Qte 
    $ tar zxvf qt-everywhere-opensource-src-4.6.3.tar.gz
    $ cd qt-everywhere-opensource-src-4.6.3
    $ ./configure -embedded x86 -qvfb
    $ make
    $ sudo make install
  3. 設定給 Qte 的環境變數
    $ vi ~/.bashrc
    加入下面的設定,主要是 QTEDIR/PATH/LD_LIBRARY_PATH 
    export QTEDIR=/usr/local/Trolltech/QtEmbedded-4.6.3
    export PATH=/usr/local/Trolltech/QtEmbedded-4.6.3/bin:$PATH
    export LD_LIBRARY_PATH=/usr/local/Trolltech/QtEmbedded-4.6.3/lib:$LD_LIBRARY_PATH
    之後記得使用 ldconfig 讓設定生效
    $ source ~/.bashrc
    $ ldconfig
  4. 編譯 Qt (因為不確定 make clean 能否清乾淨,所以把之前的 Qte 先移掉,再把 tarball 再直接解 tar)
    $ tar -zxvf qt-x11-opensource-src-4.6.3.tar.gz
    $ cd qt-x11-opensource-src-4.6.3
    $ ./configure
    $ make
    $ sudo make install
  5. 總結上面,目前 Qte/Qt-x11 安裝在下面目錄
    $ cd /usr/local/Trolltech
    $ ls
    Qt-4.6.3  QtEmbedded-4.6.3
  6. 編譯 qvfb,這是一個在 Host 端驗證 Qt 程式的模擬器。
    $ cd qt-x11-opensource-src-4.6.3/tools/qvfb
    $ make
    $ sudo make install
    $ cp qvfb /usr/bin
  7. 在 4.6.2 可能會安裝在底下目錄,若有需要請自行丟入 /usr/bin
    $ cd ~/qt-everywhere-opensource-src-4.6.2/tools/qvfb
    $ sudo make install
    install -m 644 -p "../../bin//`basename ../../bin/qvfb`.debug" "/usr/local/Trolltech/Qt-4.6.2/bin/`basename ../../bin/qvfb`.debug"
    install -m 755 -p "../../bin/qvfb" "/usr/local/Trolltech/Qt-4.6.2/bin/qvfb"
    strip "/usr/local/Trolltech/Qt-4.6.2/bin/qvfb"
    $ cp /usr/local/Trolltech/Qt-4.6.2/bin/qvfb /usr/bin
  8. qvfb ((Qt Virtual FrameBuffer))就是 編出來 Qte 的程式,
    可在 Host 先用 qvfb 測試在 Target 跑起來的樣子。使用方式如下
    $ cd ${QTEDIR}/demos/chip
    $ qvfb &
    $ ./chip -qws
  9. Nokia/Trolltech 也提供一個稱為 QtCreator 的整合性編輯器。以 QtCreator v1.3.1 為例。安裝方式
    $ wget http://get.qt.nokia.com/qtcreator/qt-creator-linux-x86-opensource-1.3.1.bin
    $ chmod 777 qt-creator-linux-x86-opensource-1.3.1.bin
    $ ./qt-creator-linux-x86-opensource-1.3.1.bin
    這樣就會帶出下面視窗進行安裝,一直按著下一步下一步就可以安裝完成了。
    image
  10. 安裝完成之後就開始設定 Qt 的編譯環境讓 Qt/Qte 都可以在這個 IDE 編譯。
    1. 在 QtCreator 點選 Tools | Options… 就會出現下面視窗。
    2. 接著點選 Qt4 | Qt Versions 進入 Qt Version 設定頁面。
    3. 按下右邊的 加號圖示 就可以編輯編譯所需要的參數( Qt Version/QMake Location )。
    4. 新增完之後記得按一下 Rebuild 確認。OK的話就會打勾。
    5. 目前的新增的就是Manual 那邊(上面紅色框框部分)。
    6. 而最後就是選一個目前要用的(下面紅色框框部分,目前是用 4.6.2(Qte)。
    7. 如果程式無法在 QtCreator 編譯成功,請留意是否為檔案/目錄 屬性/權限的問題。
      必要時請試試 chmod/chown/chgrp 。
      image
    8. 若有問題請確認 Projects 這邊,加入 Build Setting 之後記得 active 。
      image
  11. 編譯出來的 Qte 執行檔可以用 gvfb 在 Host 端先行除錯。
    $ /usr/local/Trolltech/Qt-4.6.2/bin/qvfb -depth 16 -width 1024 -height 768&
    $ qte-file -qws
      
  12. 編譯出來的 Qte 執行檔可以用 ldd 來看丟到實際機器所需要帶入的 Lib。
    $ ldd qte-file
    	linux-gate.so.1 =>  (0xb7f09000)
    	libQtGui.so.4 => /usr/local/Trolltech/QtEmbedded-4.6.2/lib/libQtGui.so.4 (0xb758e000)
    	libQtNetwork.so.4 => /usr/local/Trolltech/QtEmbedded-4.6.2/lib/libQtNetwork.so.4 (0xb74a3000)
    	libQtCore.so.4 => /usr/local/Trolltech/QtEmbedded-4.6.2/lib/libQtCore.so.4 (0xb7216000)
    	libpthread.so.0 => /lib/tls/i686/cmov/libpthread.so.0 (0xb71f0000)
    	libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0xb70fd000)
    	libm.so.6 => /lib/tls/i686/cmov/libm.so.6 (0xb70d8000)
    	libgcc_s.so.1 => /lib/libgcc_s.so.1 (0xb70cd000)
    	libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb6f7e000)
    	libdl.so.2 => /lib/tls/i686/cmov/libdl.so.2 (0xb6f79000)
    	libz.so.1 => /usr/lib/libz.so.1 (0xb6f64000)
    	librt.so.1 => /lib/tls/i686/cmov/librt.so.1 (0xb6f5b000)
    	/lib/ld-linux.so.2 (0xb7f0a000)

【問題】

  • 如何編譯給 arm 用的 Qte。

【參考】

【PicPick】Screen Capturer


桌面抓圖軟體,Vista適用。
PicPick Tools - All-in-one Design Tools http://picpick.wiziple.net/features

【功能】
抓取整個視窗:Print Screen
抓取活動視窗:Screen Capture->Active Window; 或 Alt+Print Screen。

image 


類似軟體:MWSnap

【參考】

【InDesign】教學


先收集一些資料

【參考】

【JOCR 】文字辨識軟體


Jocr http://home.megapass.net/~woosjung/Index_Download.html

【安裝】

  1. 須先確定有安裝 MS Office,否則會出現下列訊息。
    image
  2. 記得安裝時要選 MS Office Document Imaging
    image
  3. 接著直接啟動 Jocr 即可。
  4. 以下省略。

【參考】

【Ubuntu】Hardware Summit(TBD)


Ubuntu Hardware Summit Agenda

因為我沒機會去參加,就看一下簡報,記一下筆記(目前還是已 2009 年文件為主)。

P.6 Keynote Ubuntu : Past, Present and Future

  • p.23 Cherrypicking Android, Moblin & Maemo
  • p.25 Interacting with The Community - How 告訴你如何融入社群
  • p.34 Project Structure
  • p.35 Communication

P.41 Networking Architecture

  • p.44 DBUS的角色? Asynchronous Event Signalling
  • p.54 dhclient. via session DBUS?
  • p.55 Modem Manager 如何架構
  • p.57 VPN/OpenVPN/VPNC 如何架構
  • p.60 Station PS support?
  • p.62 Rfkill support may be an issue?
  • p.63 Closed Source Drivers continued
  • p.65 BIOS? rfkill是關於硬體的嗎
  • p.67 New modem implementations ( Modem Manager plugin)

P.69 An Introduction to the ACPI Extra Driver

  • p.74 LEDs – Initialisation, 再研究, 這是比較正規的作法
  • p.80 Communication

P.93 Ubuntu Desktop Roadmap
P.106 QA Process Within OEM Services

  • p.109 Ubuntu QA Workflow
  • p.112OEM QA Workflow 可以給QA部門參考
  • 比較偏QA,沒細看

P.125 給Subversion使用者的Git指南

  • p.130 版本控制的架構, git 屬於distributed架構
  • p.133 Subversion簡介, 說明架構
  • p.136 git簡介-操作指令

(TBD, 先跳過)

P.245 Working with the Linux Kernel Community

  • p.251 How big is the Linux kernel? CodeSize/Porting的參考
  • (TBD)跳過

P.276 Linux Kernel Debugging

  • (TBD)

先停一下,事情好多。

【參考】

  1. Born to MISrepresent 第六集:訪問 Canonical Taiwan 的 Kevin Huang ,談 Ubuntu Taiwan
    http://blog.roodo.com/ystuan/archives/6030209.html

【Ubuntu】USB


【步驟】

  1. 先列出 USB 資料,
    1. 以前都是去 查詢 /proc/bus/usb/devices
      $ cat /proc/bus/usb/devices
    2. Ubuntu 9.10 以後請改用
      $ usb-devices
      或
      $ lsusb (可以加上所需要的參數)
  2. 以 Touch Screen 為例,我們會得到下面資料。
    Manufacture/Product 可能和 lsusb 不同,因為 lsusb 是由 usb.ids 得到裝置名稱。
    1. 範例一(Cando)
      T:  Bus=04 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12  MxCh= 0
      D:  Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=32 #Cfgs=  1
      P:  Vendor=2087 ProdID=0b03 Rev=02.02
      S:  Manufacturer=Cando     
      S:  Product=11.6 
      C:  #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=100mA
      I:  If#= 0 Alt= 0 #EPs= 1 Cls=03(HID  ) Sub=00 Prot=00 Driver=usbhid
    2. 範例二(eGalax)
      T:  Bus=01 Lev=02 Prnt=02 Port=05 Cnt=03 Dev#=  5 Spd=12  MxCh= 0
      D:  Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs=  1
      P:  Vendor=0eef ProdID=72aa Rev=10.00
      S:  Manufacturer=eGalax Inc.
      S:  Product=USB TouchController
      C:  #Ifs= 1 Cfg#= 1 Atr=a0 MxPwr=100mA
      I:  If#= 0 Alt= 0 #EPs= 1 Cls=03(HID  ) Sub=01 Prot=02 Driver=usbhid
  3. 裡面的意思 (截錄自網路文章) (tbd)
    1. T is the topology.
      1. Bus indicates which bus the device is on.
      2. Lev level of the device, starting at level 00 for the root hub, level 01 for any device attached to the root hub, level 02 for devices attached to hubs at level 01, and so on
      3. Prnt is the parent device for this device (always 00 for the root hub, and 01 for the devices attached to the root hub).
      4. Port is the port on the parent device, starting at 00 for the first port on each device.
      5. Cnt is indicates what number device this is, at this level, based on the enumeration order within that level of the topology, starting at 01 for the first device.
      6. Dev# indicates what number device this is, irrespective of level, based on the bus enumeration order. This is unique per bus.
      7. Spd indicates what speed this device is running at, in Mbps (either 1.5 or 12 with the current version of USB).
      8. MxCh indicates how many devices can be connected to this device, and is 00 for anything except a hub.
    2. D information from the device descriptor.
      1. Ver indicates which USB specification version the device claims to meet.
      2. Cls indicates which device class the device is claiming to meet, in both hexadecimal and as a string. A Cls entry of 00(>ifc) indicates that the device class specification compliance is interface dependent, and the interface descriptor should be read for device class information.
      3. Sub indicates which sub-class (within the Cls entry), the device meets.
      4. Prot indicates which protocol within a class or sub-class the device claims to meet.
      5. MxPS indicates how big the packets from Endpoint 0 are.
      6. Cfgs indicates how many configurations this device has.
    3. P is information from the device descriptor. 
      1. Vendor indicates the Vendor Identification code for the device.
      2. ProdID indicates the Product Identification code for the device.
      3. Rev indicates the product revision number.
    4. R (目前沒有,先跳過)
    5. S are the vendor and product strings that the device returned.
      1. Manufacturer
      2. Product
    6. C information from the configuration descriptor
      1. #Ifs indicates how many interfaces the device has.
      2. Cfg# indicates which configuration is being described.
      3. Atr is a hexadecimal indication of the device attributes (0x80 for bus-powered, 0x40 for self-powered, 0x20 for remote wake-up capable).
      4. MxPwr is the maximum power draw for this device configuration, in milliamps.
    7. I is information from the interface descriptor.
      1. If #indicates which interface is being described within a given device configuration.
      2. Alt indicates which alternate setting of this interface is being described.
      3. #EPs indicates how many endpoints there are within the alternate setting for this endpoint.
      4. Cls indicates which class the alternate setting of the interface corresponds to, in both hexadecimal and as a character string.
      5. Sub indicates which sub-class the alternate setting of the interface belongs to.
      6. Prot indicates which interface protocol (within a class and sub-class tuple) the alternate setting of the interface conforms to.
      7. Driver indicates which of the various USB drivers has claimed this interface.

【其它】

  • 透過 usbview  顯示 eGalax TouchScreen的資料。 
    image
  • 上面兩個 TouchScreen的 protocol 是不一樣的(一個是02 ,一個是01)
    根據 Device Class Definition for HID 1.11/Device Class Definition for Human Interface Devices (HID)4.3 Protocols/Protocol Codes (http://www.usb.org/developers/devclass_docs/HID1_11.pdf)
    Protocol Code Description
    0 None
    1 Keyboard
    2 Mouse
    3-255 Reserved

【參考】

 

Ed32. Copyright 2008 All Rights Reserved Revolution Two Church theme by Brian Gardner Converted into Blogger Template by Bloganol dot com