9/02/2011

TI 128x BT/GPS/FM Share transport design and architecture


TI因為多了一個GPS...原本127x的BT/FM架構都完全不一樣了...T_T

沒想到TI的GPS也是利用UART來進行傳輸,看來GPS的資料量也不大嘛0.0

不過這個Share Transport的概念還真滿有意思的 !

但Porting到別的平台超複雜....= =

一出問題,如果不知道原理,根本無從查起....

所以紀錄一下今天study過後的整理.....

KIM = Kernel Initialization Manage
UIM = User space Initialization Manager

ST summary

ST(share transport)的設計理念是基於在OMAP程序中,實現BT、GPS、FM協議以及整合至軟體元件中,並提供一個界面對應各自不同的physcial ports。

它主要的工作是處理chip的整個初始化。而且還負責處理硬體去對每一個core(BT,GPS,FM)做enable/disable;而且BT則多了一項發送download script commands的工作。

除此之外,ST還負責chip與OMAP的之間的Power Managerment(PM),像是power saving/Wakup etc...,

ST driver其實是一個基於TTY driver的line discipline,在BT,GPS,FM元件之間開啟了一個具有分享作用的一個physical ports (像是UART,SPI or SlimBus等)

而這個分享的原理,是利用邏輯通道(logical channel)的設計理念來實現,如下定義 :

BT Protocol : Channel 1,2,3,4

FM Protocol : Channel 8

GPS Protocol : Channel 9

Power Managerment (HCILL) : Channel 30,31,32,33

ST Core driver中,利用KIM這個module,來處理並打開對BT,GPS,FM等元件的通信,並且會去下載init script到BT元件裡,還有最重要的一件事..

隨著FM和GPS driver註冊和註銷,KIM會去控制FM和GPS的GPIO。

而ST drvier則是會利用HCILL protocol發送message來控制chip的sleep or wakeup

KIM & UIM

1. Initialization

初始化時,ST driver會請求KIM開始對chip去做初始化(Control GPIO etc..,),在KIM對chip初始化過程中,KIM會要求UIM去打開TTY device並設定ST做為line discipline....

之後KIM會繼續初始化,然後再開啟各自chip core的GPIO和download script.

而卸載時,則跟上述步驟一樣...KIM會去要求UIM去 close TTY device and restore line discipline

2. Process

UIM是一支deamon,當它被運行時,會去install ST driver,在install ST driver期間,ST Core則會去install KIM module,並收到ST Core的要求去對chip做初始化,在這同時,KIM還會去建立一個sysfs entry --> "/sys/uim/pid"。

當install ST driver安裝完之後,這時UIM會用KIM所創的節點寫入它的Process ID(PID),然後等待信號(Signals)...等待從KIM發送過來的信號。

然後KIM會利用UIM剛寫入PID,對它發送信號,要求UIM去打開TTY device(對應physical ports)和安裝ST Line Discipline...

如果UIM是打開TTY device for UART的話,則設定baud為115200,這時TI的chip會follow這個設定去start...然後,UIM將會傳送一個HCI Vendor Specific(VS) Command去把baudrate設定成3M。

接著UIM會去call TTY function去安裝ST Line discipline driver...

整個過程跑完之後,UIM就會一直等待KIM的信號,讓它做restore and uinstall的動作。



ST Driver

ST layer主要是實現ST Line Discipline,這個Line discipline暴露(容許讓我用大陸名詞...因為不知道怎麼理解原文的意思....= =)在BT,GPS,FM driver之下。

ST driver包含3個sub-modules :

1. ST Core
2. ST Kernel space Initialization Manager (KIM)
3. ST HCILL

ST KIM在上面己經說了...它是會隨著UIM而緊密連接著...

ST Core則提供如下的作用 :
  •  Core will provide APIs for BT, FM, and GPS drivers to register, de-register, and send  protocol packets
  • If ST Core is busy sending current packet, it will buffer new requests to send protocol packets
  • ST Core will provide packets received from chip to BT, FM, and GPS drivers by calling callback routines registered by these protocol drivers
  • ST Core will maintain a finite state machine to handle multiple register, de-register, and send requests
  • When first register request is received, ST Core will interact with KIM to initialize transport and chip. When last de-register request is received, ST Core will interact with KIM to de-initialize transport and chip
  • ST Core will interact with ST HCILL to get state information of Connectivity chip and to  wakeup chip when required
ST Core使用特有的ID來區分不同的protocol driver,而BT,GPS,FM則會提供該ID來與ST driver註冊,寫在一個list當中,ST Core會去負責維護這個list來避免不當的操作。

8/30/2011

Setup Android build environment


因為自己很常把環境搞爛..要不然就是要幫別人重灌Linux

所以每次都要重新去install一堆有的沒的...

最主要是Android環境最不好弄,因為有些lib tool一定要裝..

其實這些在Google都有教學文件...

但常常因為要重建環境又再去看一次文件,實在很浪費時間..

所以自己就做了一隻script,讓它一次安裝到定位 (除了SDK)

=============

#!/bin/sh

#install jdk 6
sudo add-apt-repository "deb http://archive.canonical.com/ lucid partner"
sudo add-apt-repository "deb-src http://archive.canonical.com/ubuntu lucid partner"
sudo apt-get update
sudo apt-get install sun-java6-jdk

#install jdk 5
sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu dapper main multiverse"
sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu dapper-updates main multiverse"
sudo apt-get update
sudo apt-get install sun-java5-jdk

#install required packages with x86
sudo apt-get install git-core gnupg flex bison gperf build-essential zip curl zlib1g-dev libc6-dev x11proto-core-dev libx11- dev libgl1-mesa-dev g++-multilib tofrodos libncurses5-dev mingw32 libesd0-dev libwxgtk2.6-dev x-dev libstdc++6

# If x64 system, need these lib tool
#sudo apt-get install lib32readline5-dev libstdc++6 lib32z1 lib32z1-dev ia32-lib

Android 2.3 Gingerbread with x86


因為Android 2.3 Gingerbard original code是預設在x64上compile

所以如果你的Linux不是x64的話,是不會讓你compile的。

其實只要改幾個.mk而己 :

project build/
diff --git a/core/main.mk b/core/main.mk
index f761ba5..4ee4bf9 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -68,7 +68,7 @@ $(info Checking build tools versions...)

ifeq ($(BUILD_OS),linux)
build_arch := $(shell uname -m)
-ifneq (64,$(findstring 64,$(build_arch)))
+ifneq (i686,$(findstring i686,$(build_arch)))
$(warning ************************************************************)
$(warning You are attempting to build on a 32-bit system.)
$(warning Only 64-bit build environments are supported beyond froyo/2.2.)

project external/clearsilver/
diff --git a/cgi/Android.mk b/cgi/Android.mk
index 21c534b..37b8246 100644
--- a/cgi/Android.mk
+++ b/cgi/Android.mk
@@ -13,8 +13,8 @@ LOCAL_C_INCLUDES := $(LOCAL_PATH)/..
LOCAL_CFLAGS := -fPIC

# This forces a 64-bit build for Java6
-LOCAL_CFLAGS += -m64
-LOCAL_LDFLAGS += -m64

+LOCAL_CFLAGS += -m32
+LOCAL_LDFLAGS += -m32


LOCAL_NO_DEFAULT_COMPILER_FLAGS := true

diff --git a/cs/Android.mk b/cs/Android.mk
index 9f0e30a..275845d 100644
--- a/cs/Android.mk
+++ b/cs/Android.mk
@@ -9,8 +9,8 @@ LOCAL_C_INCLUDES := $(LOCAL_PATH)/..
LOCAL_CFLAGS := -fPIC

# This forces a 64-bit build for Java6
-LOCAL_CFLAGS += -m64
-LOCAL_LDFLAGS += -m64

+LOCAL_CFLAGS += -m32
+LOCAL_LDFLAGS += -m32

LOCAL_NO_DEFAULT_COMPILER_FLAGS := true

diff --git a/java-jni/Android.mk b/java-jni/Android.mk
index 21b4fd1..c1d38d2 100644
--- a/java-jni/Android.mk
+++ b/java-jni/Android.mk
@@ -34,8 +34,8 @@ LOCAL_C_INCLUDES := \
LOCAL_CFLAGS += -fPIC

# This forces a 64-bit build for Java6
-LOCAL_CFLAGS += -m64
-LOCAL_LDFLAGS += -m64

+LOCAL_CFLAGS += -m32
+LOCAL_LDFLAGS += -m32

LOCAL_NO_DEFAULT_COMPILER_FLAGS := true

diff --git a/util/Android.mk b/util/Android.mk
index 386f379..b694ef4 100644
--- a/util/Android.mk
+++ b/util/Android.mk
@@ -18,8 +18,8 @@ LOCAL_C_INCLUDES := $(LOCAL_PATH)/..
LOCAL_CFLAGS := -fPIC

# This forces a 64-bit build for Java6
-LOCAL_CFLAGS += -m64
-LOCAL_LDFLAGS += -m64

+LOCAL_CFLAGS += -m32
+LOCAL_LDFLAGS += -m32


LOCAL_NO_DEFAULT_COMPILER_FLAGS := true

7/12/2011

Covert string to char

這幾個禮拜 , 為了要在Android 2.3上implement HID profile 真的快把我給搞死...

不過還好 , 總算把bluetooth keyboard & mouse給弄出來了 !

過幾天再把一些心得和方法分享給在上面.

因為要自己寫JNI , 遇到上層的JAVA要傳一個字串下來 , 想當然爾JNI一定會宣告Jstring來接JAVA的字串.

但可不能直接把這個字串丟到C/C++的function , 一丟Android就直接process died....

這需要做一些轉換.

但說實在的 , JAVA 非常的不熟...所以直接從bluetooth的JNI抓出來看再改一改放到我的code裡面...

還滿簡單的.


/* Transfer jstring to C for */
const char *c_mac = env->GetStringUTFChars(address, 0);

size_t mac_sz = env->GetStringUTFLength(address) + 1;

char *c_mac_copy = (char *)malloc(mac_sz);

strncpy(c_mac_copy, c_mac, mac_sz);

hidd_command(c_mac_copy,mode);

env->ReleaseStringUTFChars(address, c_mac);



說穿了就是用GetSrtingUTFChars來轉 , 再用GetStringUTFLength來算長度 , 最後再用strncpy來把字串copy過去而己



但要注意的是,上面相對來說是指C++的JNI,如果是C的JNI,就要改成這樣了 :

const char *c_mac = (*env)->GetStringUTFChars(env,address, 0);

size_t mac_sz = (*env)->GetStringUTFLength(env,address) + 1;

char *c_mac_copy = (char *)malloc(mac_sz); // callback data

strncpy(c_mac_copy, c_mac, mac_sz);

hidd_command(c_mac_copy,mode);

(*env)->ReleaseStringUTFChars(env,address, c_mac);



原因在於jni.h的定義,路徑在 dalvik/libnativehelper/include/nativehelper/jni.h :

struct _JNIEnv;
struct _JavaVM;
typedef const struct JNINativeInterface* C_JNIEnv;

#if defined(__cplusplus)
typedef _JNIEnv JNIEnv;
typedef _JavaVM JavaVM;
#else
typedef const struct JNINativeInterface* JNIEnv;
typedef const struct JNIInvokeInterface* JavaVM;
#endif


要特別注意了.....這個差點搞死我了= =

6/13/2011

How to capture home key event

在Android 2.3 , 想要取得home key event來做特殊事件 , 應用層是收不到該事件的.

因為Android在framwork layer做掉 , 所以並沒往APP layer上送.

frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java


// First we always handle the home key here, so applications
// can never break it, although if keyguard is on, we do let
// it handle it, because that gives us the correct 5 second
// timeout.
if (keyCode == KeyEvent.KEYCODE_HOME) {
Log.i(TAG,"----2keyCode == KeyEvent.KEYCODE_HOME");
// If a system window has focus, then it doesn't make sense
// right now to interact with applications.
WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;
if (attrs != null) {
final int type = attrs.type;
if (type == WindowManager.LayoutParams.TYPE_KEYGUARD
|| type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG) {
// the "app" is keyguard, so give it the key
return false;
}
.............
.............
}


註釋寫的很清楚 , 而其中的重點在於type , 可以看出它有兩個type來判斷對該事件的處理 :

WindowManager.LayoutParams.TYPE_KEYGUARD
WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG

所以在APP層 , 想要接收home key event的話 , 改變activity的類型即可 :


/* capture home key event*/
@Override
public void onAttachedToWindow()
{
this.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
super.onAttachedToWindow();
}


其中的WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG可以改成WindowManager.LayoutParams.TYPE_KEYGUARD

但我測試過 , 用TYPE_KEYGUARD似乎會影響一些View的處理....

==========================

我發現..TYPE_KEYGUARD會使view變成懸浮視窗= =

非常怪異 !! 但實在想不出原因...最後只好自己硬幹 , 如果有人試出問題..別罵我QQ

上面提到定義了這些Typ......所以呢,我就自己定義一組Type !!

首先呢,可以在PhoneWindowManager.Java新增自己的Type :


if(type == WindowManager.LayoutParams.TYPE_DASHBOARD) {
Log.d("DASHBOARD","**** Send the home key event to app ****");
return false;
}


我自己定義了一個叫"TYPE_DASHBOARD"的東東,之後再到framwork/base/core/java/android/view/WindowManager.java去新增 :


@ViewDebug.ExportedProperty(mapping = {
.....
.....
@ViewDebug.IntToString(from = TYPE_DASHBOARD, to = "TYPE_DASHBOARD")
})

---------

public static final int TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+15;

/* Send Home key event to app layer */
public static final int TYPE_DASHBOARD = FIRST_SYSTEM_WINDOW+50;


當然了..那個後面數字隨便..50只是我的辛運數字 !!

改其它數字會不會出事就聽天命了...

還沒完 !! 再來到framwork/base/include/ui/InputDispatcher.h新增 :

// Window types from WindowManager.LayoutParams
enum {
.....
.....
TYPE_DASHBOARD = FIRST_SYSTEM_WINDOW+50,
}


到這裡,framwork的地方就改完了,接著只要在自己的APK加上這段 :

/* capture home key event*/
public static final int TYPE_DASHBOARD=2050;
@Override
public void onAttachedToWindow()
{
this.getWindow().setType(TYPE_DASHBOARD);
super.onAttachedToWindow();
}


嘿嘿,這樣接下來只要呼叫dispatchKeyEvent就可以收到Home key事件了 !! 而且不會有任何後遺症了喔 !!