ubuntu 在 R40e 上 還有 Debian 在 Sempron 2600 上

2011年11月28日 星期一

libusb-1.0.0.8 for android

就 這篇 http://android.serverbox.ch/?p=151http://my0613.blogspot.com/2010/11/porting-lsusb-libusb-on-android.html 分別是 libusb 和 lsusb。

porting lib 還是和以前一樣,要先run ./configure. 產生 config.h,然後再自己改成 for android 的配置。

然後加入 Android.mk (兩個)

再修改一下 build error 的 file



我的 config.h: /* config.h. Generated from config.h.in by configure. */ /* config.h.in. Generated from configure.ac by autoheader. */ /* Default visibility */ #define API_EXPORTED __attribute__((visibility("default"))) /* Debug message logging */ /* #undef ENABLE_DEBUG_LOGGING */ /* Message logging */ #define ENABLE_LOGGING 1 /* Define to 1 if you have the header file. */ #define HAVE_DLFCN_H 1 /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H 1 /* Define to 1 if you have the `rt' library (-lrt). */ #define HAVE_LIBRT 1 /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STRINGS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TYPES_H 1 /* Define to 1 if you have the header file. */ #define HAVE_UNISTD_H 1 /* Define to the sub-directory in which libtool stores uninstalled libraries. */ #define LT_OBJDIR ".libs/" /* Define to 1 if your C compiler doesn't accept -c and -o together. */ /* #undef NO_MINUS_C_MINUS_O */ /* Darwin backend */ /* #undef OS_DARWIN */ /* Linux backend */ #define OS_LINUX /**/ /* Name of package */ #define PACKAGE "libusb" /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "" /* Define to the full name of this package. */ #define PACKAGE_NAME "libusb" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "libusb 1.0.8" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "libusb" /* Define to the home page for this package. */ #define PACKAGE_URL "" /* Define to the version of this package. */ #define PACKAGE_VERSION "1.0.8" /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Backend handles timeout */ /* #undef USBI_OS_HANDLES_TIMEOUT */ /* timerfd headers available */ /* #undef USBI_TIMERFD_AVAILABLE */ /* Version number of package */ #define VERSION "1.0.8" /* Use GNU extensions */ #define _GNU_SOURCE /**/ /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus /* #undef inline */ #endif
我的 external/libusb-1.0.0.8/Android.mk: LOCAL_PATH := $(call my-dir) subdirs := $(addprefix $(LOCAL_PATH)/,$(addsuffix /Android.mk, \ libusb \ examples \ )) include $(subdirs)
我的 external/libusb-1.0.0.8/libusb/Android.mk LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE_TAGS:= tests LOCAL_PRELINK_MODULE:= false LOCAL_SRC_FILES:= \ core.c \ descriptor.c \ io.c \ sync.c \ os/linux_usbfs.c LOCAL_C_INCLUDES += \ external/libusb-1.0.8/ \ external/libusb-1.0.8/libusb/ \ external/libusb-1.0.8/libusb/os LOCAL_MODULE:= libusb include $(BUILD_SHARED_LIBRARY)
我的 external/libusb-1.0.0.8/example/Android.mk LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE_TAGS := tests LOCAL_SRC_FILES := lsusb.c LOCAL_MODULE := lsusb LOCAL_C_INCLUDES += external/libusb-1.0.8/ LOCAL_SHARED_LIBRARIES := libc libusb include $(BUILD_EXECUTABLE)



  1. download libusb-1.0.0.8, unzip to external (result in a external/libusb-1.0.0.8)
  2. run ./configure -disable-timerfd
  3. modify libusb/io.c
    加上#define TIMESPEC_TO_TIMEVAL(tv, ts) \ do { \ (tv)->tv_sec = (ts)->tv_sec; \ (tv)->tv_usec = (ts)->tv_nsec / 1000; \ } while (0)
  4. add 3 Android.mk files
OK to build, mm
sync to target, run bash-3.2# lsusb 1d6b:0002 (bus 1, device 1) 1d6b:0002 (bus 2, device 1) 0424:2517 (bus 2, device 2) 0a12:0001 (bus 2, device 3) 13fe:1d00 (bus 2, device 4)
不用 mount usbfs /proc/bus/usbfs 就可以動作(?)

查 libusb/os/linux_usbfs.c : static const char *find_usbfs_path(void) { const char *path = "/dev/bus/usb"; const char *ret = NULL; if (check_usb_vfs(path)) { ret = path; } else { path = "/proc/bus/usb"; if (check_usb_vfs(path)) ret = path; } usbi_dbg("found usbfs at %s", ret); return ret; } 用的是 /dev/bus/usb



2008 這篇 http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=483392 有說不要再 mount /proc/bus/usbfs,請直接用 /dev/bus/usb..

但是到現在好像還很多人在用...

2011年11月24日 星期四

Keyboard shortcut (Hotkey) in Android

Android 有 keyboard shortcut 功能,就是自己定義按著 Search 時,同時按下某個 key 就 啟動 XX app (可以自訂)。

但是要在有 keyboard 的 機器 上那個設定畫面才會出現。

這個功能一樣做在 PhoneWindowManager.java 的 interceptKeyBeforeDispatching
在 HOME, MENU, CALL,, 等等 KEYCODE 的判斷後面...
// Shortcuts are invoked through Search+key, so intercept those here if (mSearchKeyPressed) { if (down && repeatCount == 0 && !keyguardOn) { Intent shortcutIntent = mShortcutManager.getIntent(keyCode, metaState); if (shortcutIntent != null) { shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mContext.startActivity(shortcutIntent); /* * We launched an app, so the up-event of the search key * should be consumed */ mConsumeSearchKeyUp = true; return true; } } } 一樣用 startActivity( ) 叫起 app (intent),那個 對應哪個 key,都在ShorcutManager 的 database (bookmark) 中紀錄。



Setting 部份的 source code 在 src/com/android/settings/ApplicationSettings.java
如果沒有 physical keyboard,就移除這個 Setting: if (getResources().getConfiguration().keyboard == Configuration.KEYBOARD_NOKEYS) { // No hard keyboard, remove the setting for quick launch Preference quickLaunchSetting = findPreference(KEY_QUICK_LAUNCH); getPreferenceScreen().removePreference(quickLaunchSetting); }
實際設定的 class 是 quicklaunch


如果要作假...
以叫起 browser (S-B) 為例..,
  1. 送出一個 SEARCH KEY Down : 217, down
  2. 送出一個 b Key down, up : 48, down,up
  3. 這時候就可以看到 browser 已經被叫起來了
  4. 送出一個 SEARCH KEY Up : 217 up
keycode 定義可以看 ./include/linux/input.h
-- 新版 (3.0.X) 在 /include/uapi/linux/input.h



自己紀錄一下,就是:
  1. cd /sys/devices/platform/virkeyboard/
  2. echo D217 > vmevent
  3. echo 48 > vmevent -- 可以看到 browser 起來了
  4. echo U217 > vmevent

HOTKEY to launch HOME launcher

收到 KEYCODE_HOME 後: launchHomeFromHotKey();
launchHomeFromHotKey 中 laucn Home 的 code: try { ActivityManagerNative.getDefault().stopAppSwitches(); } catch (RemoteException e) { } sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY); startDockOrHome();
  1. stopAppSwitches()
  2. sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY)
  3. startDockOrHome()



stopAppSwitches():

好像是停止 app switch 5 sec.


sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY):

是 call : ActivityManagerNative.getDefault().closeSystemDialogs(reason); 就是把 windws map 叫出來,一個一個 send message: Message msg = Message.obtain(); msg.what = CLOSE_SYSTEM_DIALOGS; msg.obj = reason; sendMessage(msg);

startDockOrHome:
mHomeIntent = new Intent(Intent.ACTION_MAIN, null); mHomeIntent.addCategory(Intent.CATEGORY_HOME); mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); ........ startActivity(mHomeIntent)

... framework 自己也用 startActivity...

Add app project in android build system

google 的說明文件有 如何用 android 的 build 系統 build apk:
http://www.kandroid.org/online-pdk/guide/build_cookbook.html

copy 一些過來:

Android system 用 Android.mk,簡單的 apk 可以用: LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) # Build all java files in the java subdirectory LOCAL_SRC_FILES := $(call all-subdir-java-files) # Name of the APK to build LOCAL_PACKAGE_NAME := LocalPackage # Tell it to build an APK include $(BUILD_PACKAGE) 把這個 Android.mk 放在 app 的 folder 中就可以。
... LocalPackage 就是最後 apk 的 filename


這一篇是說明把 Eclipse create 的 project folder 搬到 Android root 中 build 的方法:
http://owenhuangtw.pixnet.net/blog/post/23935524-using-android-bluetoothdevice-class-to-control-blue-deivce

.. 好像就是把 Android.mk 放進去就可以了 (?)

用 eclipse create 的 project 如果有 build 過,搬到 android root 後,要把 gen, bin 清掉,不然 build 會有 R.jar 的 error。

其實 developement/sample 下每一個 project 都是 用這個方法。
可以參考


很奇怪,給 file path 就不行,可以的是用 MediaScanner scan 過後,再傳 uri 過去。
所以可能要自己 scan,
example 在 development/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java:

scan 單檔的 方法:
            File path = Environment.getExternalStoragePublicDirectory(
                    Environment.DIRECTORY_PICTURES);
            File file = new File(path, "DemoPicture.jpg");
            .....
            .....
            // Tell the media scanner about the new file so that it is
            // immediately available to the user.
            MediaScannerConnection.scanFile(this,
                    new String[] { file.toString() }, null,
                    new MediaScannerConnection.OnScanCompletedListener() {
                public void onScanCompleted(String path, Uri uri) {
                    Log.i("ExternalStorage", "Scanned " + path + ":");
                    Log.i("ExternalStorage", "-> uri=" + uri);
                }
            });

2011年11月23日 星期三

forceStopPackage

ActivityManager.java: public void forceStopPackage(String packageName) { try { ActivityManagerNative.getDefault().forceStopPackage(packageName); } catch (RemoteException e) { } }
call 的是ActivivityManagerProxy Implement IActivityManager: public void forceStopPackage(String packageName) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeString(packageName); mRemote.transact(FORCE_STOP_PACKAGE_TRANSACTION, data, reply, 0); reply.readException(); data.recycle(); reply.recycle(); }
mRemote transact 經由 IBinder 傳送 FORCE_STO_PACKAGE_TRANSACTION 需求。
收到並執行的是
在 ActivityManagerNative 的 onTransact(): case FORCE_STOP_PACKAGE_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); String packageName = data.readString(); forceStopPackage(packageName); reply.writeNoException(); return true; }
onTransact 的 case handler
呼叫的是ActivityManagerService 的 forceStopPackage(?): IPackageManager pm = AppGlobals.getPackageManager(); int pkgUid = pm.getPackageUid(packageName); forceStopPackageLocked(packageName, pkgUid);
就是從 package manager 找出 packageName 的 pid,然後 call forceStopPackageLocked( ) 結束他。


其中的 forceStopPackageLocked 是: private void forceStopPackageLocked(final String packageName, int uid) { forceStopPackageLocked(packageName, uid, false, false, true); Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED, Uri.fromParts("package", packageName, null)); if (!mProcessesReady) { intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); } intent.putExtra(Intent.EXTRA_UID, uid); broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null, false, false, MY_PID, Process.SYSTEM_UID); } 就是call forceStopPackageLocked( ) 結束他,然後再 broadcast ACTION_PACKAGE_RESTARTED.. (叫他再起來?)

Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator(); while (badApps.hasNext()) { SparseArray ba = badApps.next(); if (ba.get(uid) != null) { badApps.remove(); } } 把 mProcessCrashTime (上次system crash 時的 proces map) 中,同 uid 的 process data 從 record map 中移除。


boolean didSomething = killPackageProcessesLocked(name, uid, -100, callerWillRestart, doit); 然後 killPackageProcessLocked( ).


for (i=mMainStack.mHistory.size()-1; i>=0; i--) { ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i); if (r.packageName.equals(name)) { if (!doit) { return true; } didSomething = true; Slog.i(TAG, " Force finishing activity " + r); if (r.app != null) { r.app.removed = true; } r.app = null; r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall"); } } 然後再從 目前系統 activiry stack (所有執行過的 activity) 中,找出符合name 的package,作 RESULT_CANCELED 的 finishActivityLocked( )。



後面看起來會把 activity stack 中 下一個 activity resume 回來 (到 top)。

如果 stack 是空的,就 launch home launcher
trace code 的其中一點,最後是用 kill 把 process 殺掉。

2011年11月17日 星期四

Keypad action in Android Framework

keyboard input (包含 home, power, menu, back..etc) 的動作是在 framework/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java

public boolean interceptKeyBeforeDispatching(WindowState win, int action, int flags, int keyCode, int scanCode, int metaState, int repeatCount, int policyFlags) { 可以看到這個 function 根據狀況決定HOME key 要不要處理。
同時還處理 SEARCH , MENU。

所有的 keyevent,會先進到這裡,再到其他地方。

經過這個篩選後,key 會到 framwork/base/policy/src/com/android/internal/policy/impl/PhoneWindow.java
  1. protected boolean onKeyDown(int featureId, int keyCode, KeyEvent event)
  2. protected boolean onKeyUp(int featureId, int keyCode, KeyEvent event)
keydown 是主要作動作的地方,keyup 只是detect longpress 的 cancel。
像 KEYCODE_CAMERA 就會執行下面的code: sendCloseSystemWindows(); // Broadcast an intent that the Camera button was longpressed Intent intent = new Intent(Intent.ACTION_CAMERA_BUTTON, null); intent.putExtra(Intent.EXTRA_KEY_EVENT, event); getContext().sendOrderedBroadcast(intent, null); .. close current window & launch CAMERA app

在這裡處理的還有:
  1. KEYCODE_VOLUME_UP/DOWN
  2. KEYCODE_MEDIA_PLAY_PAUSE
  3. KEYCODE_MUTE:KEYCODE_HEADSETHOOK.KEYCODE_MEDIA_STOP:KEYCODE_MEDIA_NEXT:KEYCODE_MEDIA_PREVIOUS:KEYCODE_MEDIA_REWIND:KEYCODE_MEDIA_FAST_FORWARD:
  4. KEYCODE_MENU
  5. KEYCODE_BACK
  6. KEYCODE_CALL
  7. KEYCODE_SEARCH
所以有 自己新增的 button 要作到 HOT-KEY 功能的,都可以作到這裡。

2011年11月14日 星期一

Matthew Garrett 解決 2.6.38 開始,耗電增加 30% 的問題:ASPM

http://www.phoronix.com/scan.php?page=article&item=linux_aspm_solution

這篇說明 linux kernel 從 2.6.37 進到 2.6. 38 後,耗電增加 30% 的問題。
因為 38 開始依照 bios 回報的內容,開啟/關閉對 PCIe 裝置的電源管理功能...
...
結果...
.. 一堆裝置都回報他門沒有電源管理功能...
.. 所以 kernel 就不管他門了...就放著耗電...


後來 Matthew Garrett 參考 Windows Vista,發現 windows 都還是有管耶。
然後就 follow hardware 的 window driver inf 檔,決定要不要管。 (而不是依照 hardware 的回報)。

就這樣...



... 就說...照 datasheet 寫code的是笨蛋.. (一定會被騙...)

imx51 : SION bit in GPIO config

http://imxcommunity.org/forum/topics/how-to-use-the-sion-bit
說明. GPIO 的 SION bit 就是把 gpio 的 pad 接到 input 端 -- 不管是configure 成 output 還是 input。

說明是以 SD_CMD 為範例。
CMD 是雙向 ,output 完馬上就改 input, read ack。
所以要把 CMD pin 的 SION bit 打開

2011年11月11日 星期五

android, bionic , overview & test program

android 的 bionic 沒有 support pthread_cancel。
 -- 其實還有很多不 support 的,說明在 libc/doc/overview.txt.

另外 android 也提供 bionic libc test code,在
/system/extras/tests/bionic/libc
一般是不會 build 進 system。

可以用
    cd system/extras/tests/bionic/libc
    mm BIONIC_TESTS=1



  1. 這一篇有很好的說明:http://codingrelic.geekhold.com/2008/11/six-million-dollar-libc.html
  2. 這一篇遇到pthread_cancel 不 support ,他workaround 又遇到Dalvik 共用..之後的解決方法: http://blogs.mentor.com/hollisblanchard/blog/tag/android/

2011年11月10日 星期四

ADV7180 detect the video signal discontinue

ADV7180 的 STATUS 3 :
  • bit 4 FREE_RUN_ACT : 沒偵測到signal,所以 output blue screen 中
  • bit 5 STD FLD LEN : 使用目前的 standard 解 video frame 得到的 Field Length 是正確的
  • bit 6 Interlaced : 偵測到 interlaced frame
有些low-end, ill-designed, 亂寫code的 video output device,輸出不太正確的 video signal,會導致 application processor 的 camera input module 錯誤。
可以利用這幾個 bit 來偵測。

當 4 出現代表目前沒信號。
當 5 沒出現,代表 scan line 有錯
當 6 沒出現,代表 沒有偵測到 interlaced frame


但是要用這個 register 有一個限制,要在每一個 frame 都讀一次,否則會被新的 frame 狀態 update ,就抓不到 frame lost 的瞬間了...

2011年11月9日 星期三

dynamic_debug in kernel

kernel 裡面有很多 pr_debug,這是被合 dynamic_debug 這個功能的 printk function。
在 Documentation/dynamic-debug-howto.txt 有說明。

大概就是:
  1. menuconfig 圈選 dynamic_debugCONFIG_DYNAMIC_DEBUG=y
  2. 系統啟動後,手動 mount debugfs : #mkdir /mnt/debugfs #mount -t debugfs none /mnt/debugfs
  3. 把 /mnt/debugfs/dynamic_debug/control 打開來看..
  4. control 會列出所有 pr_debug 所在的source file 和位置,用 echo ... 可以把該 pr_debug 打開或關閉


control 檔的內容大概是: ... drivers/i2c/busses/mxc_i2c_hs.c:154 [mxc_i2c_hs]mxci2c_hs_bus_busy - "%s: Bus Busy!\012" drivers/media/video/mxc/capture/mxc_v4l2_capture.c:264 [mxc_v4l2_capture]mxc_free_frames - "In MVC:mxc_free_frames\012" drivers/media/video/mxc/capture/mxc_v4l2_capture.c:413 [mxc_v4l2_capture]mxc_streamoff - "In MVC:mxc_streamoff\012" drivers/media/video/mxc/capture/mxc_v4l2_capture.c:2825 [mxc_v4l2_capture]camera_init - "In MVC:camera_init\012" drivers/media/video/mxc/capture/mxc_v4l2_capture.c:574 [mxc_v4l2_capture]start_preview - "MVC: start_preview\012" drivers/media/video/mxc/capture/mxc_v4l2_capture.c:592 [mxc_v4l2_capture]start_preview - "End of %s: v2f pix widthxheight %d x %d\012" drivers/media/video/mxc/capture/mxc_v4l2_capture.c:595 [mxc_v4l2_capture]start_preview - "End of %s: crop_bounds widthxheight %d x %d\012" drivers/media/video/mxc/capture/mxc_v4l2_capture.c:598 [mxc_v4l2_capture]start_preview - "End of %s: crop_defrect widthxheight %d x %d\012" drivers/media/video/mxc/capture/mxc_v4l2_capture.c:601 [mxc_v4l2_capture]start_preview - "End of %s: crop_current widthxheight %d x %d\012" drivers/media/video/mxc/capture/mxc_v4l2_capture.c:617 [mxc_v4l2_capture]stop_preview - "MVC: stop preview\012" drivers/media/video/mxc/capture/mxc_v4l2_capture.c:335 [mxc_v4l2_capture]mxc_streamon - "In MVC:mxc_streamon\012" drivers/media/video/mxc/capture/mxc_v4l2_capture.c:2714 [mxc_v4l2_capture]mxc_v4l2_resume p "In MVC:mxc_v4l2_resume\012" drivers/media/video/mxc/capture/mxc_v4l2_capture.c:2681 [mxc_v4l2_capture]mxc_v4l2_suspend - "In MVC:mxc_v4l2_suspend\012" drivers/media/video/mxc/capture/mxc_v4l2_capture.c:2812 [mxc_v4l2_capture]mxc_v4l2_master_detach - "In MVC:mxc_v4l2_master_detach\012" drivers/media/video/mxc/capture/mxc_v4l2_capture.c:2756 [mxc_v4l2_capture]mxc_v4l2_master_attach - "In MVC: mxc_v4l2_master_attach\012" drivers/media/video/mxc/capture/mxc_v4l2_capture.c:2757 [mxc_v4l2_capture]mxc_v4l2_master_attach - " slave.name = %s\012" drivers/media/video/mxc/capture/mxc_v4l2_capture.c:2758 [mxc_v4l2_capture]mxc_v4l2_master_attach - " master.name = %s\012" .. 中間那個 "-" 就代表不印出來,
若是 "p" 就代表要印出來。

所以要是希望 mxc_v4l2_capture.c 裡所有的 pr_debug 都印出來,可以用: echo 'file mxc_v4l2_capture.c +p' > control 如果不要了,就用: echo 'file mxc_v4l2_capture.c -p' > control 如果只是要第 617 行的 stop preview 印出來,就用: echo 'file mxc_v4l2_capture.c line 617 +p' > control
  1. 雖然是enable print,但是 print level 還是follow 當初source code 寫得,所以有些還是要用 dmesg 才會看得到。
  2. 可以對 control 使用grep command,不必每次都cat 出來

2011年11月4日 星期五

Lost Lock in a short period

在接外部影像信號的時候,常常會發生信號短時間中斷的情況。
例如一些糟糕的 dvr 和 media player,在切換畫面 : 播放 --- 設定 時,會有很短一下的信號中斷現象。

而一些爛爛的 application processor 的 bt656 input 端,會發生不同步。最後就導致畫面有 scrolling 的現象。

video converter ADV7180 的 register : status 有一個 bit : LOST_LOCK
可以用來偵測這個現象。

他的定義是:
Lost lock (since last read of this register)

有 "Since last read of this register" 很重要。
這樣就不用設定很高的 polling freq,來抓 lost lock 的瞬間了。



但是有些 dvr 因為畫面切換信號中斷的時間很短,所以 ADV7180 也抓不到。
這個方法就失效了 ....

標籤

網誌存檔