2011年6月1日 星期三

[Embedded] How to Porting Qt to Target Board

本篇算是工作紀錄,說明如何移植Qt-4.6.2到某目標板,並能啟動examples下的fancybrowser,能支援中文字型,支援JavaScript,不喜勿入,也不說明是哪個板子,實際移植時還需視當時環境做調整

environment:
* host: ubuntu 10.04
* client: target board(?)

1. Get Source
host$ cd ~
host$ wget http://get.qt.nokia.com/qt/source/qt-everywhere-opensource-src-4.6.2.tar.gz
host$ tar zxvf qt-everywhere-opensource-src-4.6.2.tar.gz


2. Settup Toolchain
2-1) add toolchain to environment variable
host$ vim ~/.bashrc
export MY_TOOLCHAIN=/path/to/toolchain    # add this line
export PATH=$PATH:$MY_TOOLCHAIN           # add this line
host$ source ~/.bashrc


3. Qmake
3-1) http://en.wikipedia.org/wiki/Qmake

3-2) modify [/path/to/qt]/mkspecs/qws/linux-arm-g++/qmake.conf
include(../../common/g++.conf)
include(../../common/linux.conf)
include(../../common/qws.conf)
QMAKE_CC            = /path/to/toolchain/gcc
QMAKE_CXX           = /path/to/toolchain/g++
QMAKE_LINK          = /path/to/toolchain/g++
QMAKE_LINK_SHLIB    = /path/to/toolchain/g++
QMAKE_AR            = /path/to/toolchain/ar cqs
QMAKE_OBJCOPY       = /path/to/toolchain/objcopy
QMAKE_STRIP         = /path/to/toolchain/strip
load(qt_config)

3-3) modify fancybrowser
host$ cd ~/qt-everywhere-opensource-src-4.6.2/example/webkit/fancybrowser
host$ vim main.cpp
#include 
#include "mainwindow.h"

int main(int argc, char * argv[])
{
    QApplication app(argc, argv, QApplication::GuiServer);
    QTextCodec *codec = QTextCodec::codecForName("UTF-8");  // add this line for supporting UTF-8 encodeing
    QTextCodec::setCodecForLocale(codec);                   // add this line
    QTextCodec::setCodecForCStrings(codec);                 // add this line
    QTextCodec::setCodecForTr(codec);                       // add this line
    QFont font("wenquanyi",6);                              // add this line for setting font name
    app.setFont(font);                                      // add this line
    MainWindow browser;
    browser.show();
    return app.exec();
}

host$ vim mainwindow.cpp
//! [2]
    view = new QWebView(this);
    view->load(QUrl("http://www.google.com.tw/"));
    view->settings()->setAttribute(QWebSettings::PluginsEnabled, true);            // add this line
    view->settings()->setAttribute(QWebSettings::JavascriptEnabled, true);         // add this line
    view->settings()->setAttribute(QWebSettings::JavascriptCanOpenWindows, true);  // add this line
    connect(view, SIGNAL(loadFinished(bool)), SLOT(adjustLocation()));
    connect(view, SIGNAL(titleChanged(QString)), SLOT(adjustTitle()));
    connect(view, SIGNAL(loadProgress(int)), SLOT(setProgress(int)));
    connect(view, SIGNAL(loadFinished(bool)), SLOT(finishLoading(bool)));


4. Config Parameters & Install
4-1) important parameter
-embedded arm                  // cross-compile for arm platform
-xplatform qws/linux-arm-g++   // cross-compile for arm platform with linux-arm-g++ qmake
-plugin-gfx-directfb           // display with directfb through plugin

4-2) config with your library
host$ ./configure -embedded arm -xplatform qws/linux-arm-g++ -debug -fast -little-endian -no-largefile -accessibility -no-qt3support -webkit -javascript-jit -script -scripttools -qt-zlib -qt-gif -qt-libtiff -qt-libpng -qt-libmng -qt-libjpeg -no-dbus -no-mmx -no-3dnow -no-sse -no-sse2 -openssl -no-gtkstyle -no-nas-sound -no-opengl -no-openvg -no-sm -no-xshape -no-xsync -no-xinerama -xcursor -no-xfixes -no-xrandr -no-xrender -no-mitshm -no-fontconfig -no-xinput -no-xkb -freetype -no-neon -no-glib -plugin-gfx-directfb -I/path/to/directfb/header -ldirectfb -I/path/to/library/header -L/path/to/shared/library -lg -lssl -lcrypto -lz -lm -lpng -ljpeg -lfreetype -lpthread -v -confirm-license
host$ make
host$ sudo make install

4-3) add Chinese font support(download wenquanyi_120_50.qpf here)
host$ cd /usr/local/Trolltech/QtEmbedded-4.6.2-arm/lib
host$ sudo rm -f fonts/*
host$ sudo vim fontdir
wqx wenquanyi_120_50.qpf QPF n 50 120
wqx wenquanyi_120_75.qpf QPF n 75 120
wqx wenquanyi_130_50.qpf QPF n 50 130
wqx wenquanyi_130_75.qpf QPF n 75 130
wqx wenquanyi_150_50.qpf QPF n 50 150
wqx wenquanyi_150_75.qpf QPF n 75 150
wqx wenquanyi_160_50.qpf QPF n 50 160
wqx wenquanyi_160_75.qpf QPF n 75 160
host$ sudo cp [/path/to]/wenquanyi_120_50.qpf fonts

4-4) copy shared library instead of symbolic link
host$ cd /usr/local/Trolltech/QtEmbedded-4.6.2-arm/lib
host$ sudo cp libQtNetwork.so.4.6.2 libQtNetwork.so.4
host$ sudo cp libQtNetwork.so.4.6.2 libQtNetwork.so.4.6
host$ sudo cp libQtNetwork.so.4.6.2 libQtNetwork.so
host$ sudo cp libQtGui.so.4.6.2 libQtGui.so.4
host$ sudo cp libQtGui.so.4.6.2 libQtGui.so.4.6
host$ sudo cp libQtGui.so.4.6.2 libQtGui.so
host$ sudo cp libQtCore.so.4.6.2 libQtCore.so.4
host$ sudo cp libQtCore.so.4.6.2 libQtCore.so.4.6
host$ sudo cp libQtCore.so.4.6.2 libQtCore.so
host$ sudo cp libQtXml.so.4.6.2 libQtXml.so.4
host$ sudo cp libQtXml.so.4.6.2 libQtXml.so.4.6
host$ sudo cp libQtXml.so.4.6.2 libQtXml.so
host$ sudo cp libQtMultimedia.so.4.6.2 libQtMultimedia.so.4.6
host$ sudo cp libQtMultimedia.so.4.6.2 libQtMultimedia.so.4
host$ sudo cp libQtMultimedia.so.4.6.2 libQtMultimedia.so
host$ sudo cp libQtScript.so.4.6.2 libQtScript.so.4.6
host$ sudo cp libQtScript.so.4.6.2 libQtScript.so.4
host$ sudo cp libQtScript.so.4.6.2 libQtScript.so
host$ sudo cp libQtScriptTools.so.4.6.2 libQtScriptTools.so.4.6
host$ sudo cp libQtScriptTools.so.4.6.2 libQtScriptTools.so.4
host$ sudo cp libQtScriptTools.so.4.6.2 libQtScriptTools.so
host$ sudo cp libQtSvg.so.4.6.2 libQtSvg.so.4.6
host$ sudo cp libQtSvg.so.4.6.2 libQtSvg.so.4
host$ sudo cp libQtSvg.so.4.6.2 libQtSvg.so
host$ sudo cp libQtWebKit.so.4.6.2 libQtWebKit.so.4.6
host$ sudo cp libQtWebKit.so.4.6.2 libQtWebKit.so.4
host$ sudo cp libQtWebKit.so.4.6.2 libQtWebKit.so
host$ sudo cp libQtSql.so.4.6.2 libQtSql.so.4
host$ sudo cp libQtSql.so.4.6.2 libQtSql.so.4.6
host$ sudo cp libQtSql.so.4.6.2 libQtSql.so

4-5) copy 3rd library (if configure with -openssl)
host$ sudo cp /path/to/libcrypto.so.1.0.0 .
host$ sudo cp /path/to/libssl.so.1.0.0 .
host$ sudo cp /usr/local/Trolltech/QtEmbedded-4.6.2-arm/lib/libcrypto.so.1.0.0 libcrypto.so
host$ sudo cp /usr/local/Trolltech/QtEmbedded-4.6.2-arm/lib/libssl.so.1.0.0 libssl.so


5. Display Qt Application in Target Board
5-1) setting QtEmbedded-4.6.2-arm environment variable
client# QTDIR=/path/to/QtEmbedded-4.6.2-arm
client# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$QTDIR/lib
client# export QT_QWS_FONTDIR=$QTDIR/lib/fonts
client# export QT_PLUGIN_PATH=$QTDIR/plugins
client# export QWS_DISPLAY=directfb

5-2) execute fancybrowser
client# cd /path/to/QtEmbedded-4.6.2-arm
client# cd examples/webkit/fancybrowser
client# ./fancybrowser

reference: Qt for Embedded Linux Environment Variables

[Tips] 查詢Linux版本

以我自己的Ubuntu為例,

check kernel version
$ uname -a
Linux ubuntu 2.6.32-25-generic #45-Ubuntu SMP Sat Oct 16 19:48:22 UTC 2010 i686 GNU/Linux

check Linux distribution
$ cat /proc/version
Linux version 2.6.32-25-generic (buildd@palmer) (gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5) ) #45-Ubuntu SMP Sat Oct 16 19:48:22 UTC 2010
$ cat /etc/issue
Ubuntu 10.10 \n \l

Ubuntu需apt-get install lsb, Fedora需yum install redhat-lsb才能看到完整LSB資訊
$ lsb_release -a
LSB Version: core-2.0-ia32:core-2.0-noarch:core-3.0-ia32:core-3.0-noarch:core-3.1-ia32:core-3.1-noarch:core-3.2-ia32:core-3.2-noarch:core-4.0-ia32:core-4.0-noarch:cxx-3.0-ia32:cxx-3.0-noarch:cxx-3.1-ia32:cxx-3.1-noarch:cxx-3.2-ia32:cxx-3.2-noarch:cxx-4.0-ia32:cxx-4.0-noarch:desktop-3.1-ia32:desktop-3.1-noarch:desktop-3.2-ia32:desktop-3.2-noarch:desktop-4.0-ia32:desktop-4.0-noarch:graphics-2.0-ia32:graphics-2.0-noarch:graphics-3.0-ia32:graphics-3.0-noarch:graphics-3.1-ia32:graphics-3.1-noarch:graphics-3.2-ia32:graphics-3.2-noarch:graphics-4.0-ia32:graphics-4.0-noarch:printing-3.2-ia32:printing-3.2-noarch:printing-4.0-ia32:printing-4.0-noarch:qt4-3.1-ia32:qt4-3.1-noarch
Distributor ID: Ubuntu
Description: Ubuntu 10.10
Release: 10.10
Codename: maverick

2011年5月30日 星期一

[Tips] Message Boundary

最近看文件看到message boundary這個名詞,突然愣了一下,經過東翻西找後,發現Richard Stevens大師寫的真清楚,以下節錄自UNIX Network Programming, Volume 2, Second Edition: Interprocess Communications

4.10 Streams and Message (p.67)
No record boundaries exist - reads and writes do not examine the data at all. The data is a byte stream with no interpretation done by the system. If any interpretation is desired, the writing process and the reading process must agree to it a priori and do it themselves.
1.Special termination sequence in-band: many Unix applications use the newline character to delineate each message.
2.Explicit length: each record is preceded by its length. One advantage to this technique is that escaping a delimiter that appears in the data is unnecessary, because the receiver does not need to scan all the data,looking for the end of each record.
3.One record per connection: the application closes the connection to its peer to indicate the end of a record. The requires a new connection for every record, but is used with HTTP 1.0.

只會用不會說果然不是真懂阿...

2011年5月24日 星期二

[Qt] Qt學習網路資源

最近在搞Qt,官方網站提供了不少的資源,不但有pdf的講義,還有video的教學,另外Qt Developer Days的內容也值得參考

如果要看中文的內容,當然首推良葛格學習筆記,自由軟體技術支援庫也有不錯的介紹

未來有看到好的網站,也會持續更新

/** update @ 2011-10-13 **/
零基础学Qt4编程作者blog

/** update @ 2011-10-12 **/
對岸有個不錯的教學網,yafeilinux.com----開源 共享 自由

/** update @ 2011-05-31 **/
目前我看到資源最豐富的Qt技術部落格CuteQt Blog

2011年5月23日 星期一

[Network] Three-Way Handshake in TCP

TCP的three-way handshake是在哪一個階段發生的?

environment:
* foo: 192.168.104.1, 執行server.c
* bar: 192.168.104.100, 執行client.c

foo$ vim server.c
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main()
{
    int serverfd, clientfd;
    struct sockaddr_in server;
    struct sockaddr_in client;
    socklen_t len;
    server.sin_family = AF_INET;
    server.sin_port = htons(8080);
    server.sin_addr.s_addr = inet_addr("192.168.104.1");
    serverfd = socket(AF_INET, SOCK_STREAM, 0); 
    bind(serverfd, (struct sockaddr*)&server, sizeof(server));
    listen(serverfd, 10);
    len = sizeof(client);
    clientfd = accept(serverfd, (struct sockaddr*)&client, &len);
    close(clientfd);
    close(serverfd);
    return 0;
}
foo$ gcc -Wall -g server.c -o server

bar$ vim client.c
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main()
{
    int serverfd;
    struct sockaddr_in server;
    serverfd = socket(AF_INET, SOCK_STREAM, 0); 
    server.sin_family = AF_INET;
    server.sin_port = htons(8080);
    server.sin_addr.s_addr = inet_addr("192.168.104.1");
    connect(serverfd, (struct sockaddr*)&server, sizeof(server));
    close(serverfd);

    return 0;
}
bar$ gcc -Wall -g client.c -o client

單步執行server.c, 在accept()被block住
foo$ cgdb ./server

這時還沒有送出任何的封包

單步執行client.c到connect()
bar$ cgdb ./client

bar在connect()時進行three-way handshake,與foo傳送SYN,SYN/ACK,ACK封包

bar關閉socket,送出FIN封包(若由client關閉socket,則由foo送出FIN封包)

2011年5月10日 星期二

[Tips] Rebuild media file from wireshark logs

How to rebuild media file when doing RTSP packet captured by Wireshark?

1.in any RTP packet(sometimes 'video-stream' is shown), right click on the package->'Decode As' and choose 'RTP' in Transport tab
2.choose from context menu 'Analyze'->'follow UDP stream'
3.save as wherever you like...

references:
* Rebuild media file from wireshark logs

2011年5月7日 星期六

[Tips] 線上資源

紀錄一下目前常在用的線上資源,常保更新

* YouTube影片下載:
KeepVid

* Youtube/Vimeo/優酷/土豆網/Google Videos等影片下載
TubGet

* HTML編碼/解碼:
HTML Encoder

* 線上JavaScript排版:
Online javascript beautifier

* 線上程式排版(PHP/Java/C++/C/Perl/JavaScript/CSS):
Pretty Printer