|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
USB port 如何识别不同的Charger类型2 O) P/ z0 X9 B1 |" \6 @" e% c
2013年10月03日 ⁄ 综合 ⁄ 共 8924字 ⁄ 字号 [url=]小[/url] [url=]中[/url] [url=]大[/url] ⁄ 评论关闭3 \1 k6 G8 k8 e
3 J i1 l( v8 H, R L0 p* J/ L一,软件分析1. USB charger types & Power supply types
# J- I5 d' M( s" tUSB_INVALID_CHARGER Invalid USB charger.
6 E1 h- u" _' x6 q# V. S0 Z. e, _USB_SDP_CHARGER Standard downstream port. Refers to a downstream port on USB2.0 compliant host/hub.
- r) q& [9 {* y' d$ H; e+ |& ~USB_DCP_CHARGER Dedicated charger port (AC charger/ Wall charger).
5 |) D7 K! Z) t, wUSB_CDP_CHARGER Charging downstream port. Enumeration can happen and IDEV_CHG_MAX can be drawn irrespective of USB state., G% {& Z3 k! u
USB_ACA_A_CHARGER
, h2 Q" _: H4 A* x& }" T% I$ h; rB-device is connected on accessory port with charger connected on charging port. This configuration allows charging in host mode.
7 U9 |! ?; q% W6 \USB_ACA_B_CHARGER No device (or A-device without VBUS) is connected on accessory port with charger connected on charging port.
F/ z1 u% G6 yUSB_ACA_C_CHARGER A-device (with VBUS) is connected on accessory port with charger connected on charging port.. L+ x8 [; c" R" f
USB_ACA_DOCK_CHARGER A docking station that has one upstream port and one or more downstream ports. Capable of supplying IDEV_CHG_MAX irrespective of devices connected on accessory
* v5 l) `9 y3 z5 P( F! @' B2 p+ @* Kports.% c. Q- a0 f$ z8 x# j
USB_PROPRIETARY_CHARGER A proprietary charger pull DP and DM to specific voltages between 2.0-3.3v for identification.1 ] W$ B7 A7 f H, a' Y
! \6 J* U0 |. ?3 _9 I" B
POWER_SUPPLY_TYPE_USB,
4 z6 u2 }6 J5 { ^1 e% S! H/* Standard Downstream Port */5 V- I9 @# b) ?) P
POWER_SUPPLY_TYPE_USB_DCP, /* Dedicated Charging Port */
" X6 i- G5 p9 X3 ~POWER_SUPPLY_TYPE_USB_CDP, /* Charging Downstream Port */
' R9 k: ?0 m7 r' uPOWER_SUPPLY_TYPE_USB_ACA, /* Accessory Charger Adapters */; U( B! F N* Z. e) ^3 g- Y
POWER_SUPPLY_TYPE_BMS, 6 C, v0 ^% _- e# m
/* Battery Monitor System */
% l. o' u& W# a$ f1 @; C2 c" v) h
: \, ^: T" `2 t$ l( E6 S2. How to classify or identify charger?
2 s- A' c. C6 g, a! O( ]+ R) W
- x) D* a- E) A4 @USB_SDP_CHARGER7 M) X& J# Y. M( h
| POWER_SUPPLY_TYPE_USB
# v8 w) W7 U4 r' g | USB Charger | USB_CDP_CHARGER& b$ ~' [' b' F U: H
| POWER_SUPPLY_TYPE_USB_CDP
) T' ~2 U6 i$ f( h0 U; l | USB_ACA_DOCK_CHARGER" a" g6 V2 r, h+ ], q! }; e
| POWER_SUPPLY_TYPE_USB_ACA | USB_ACA_A_CHARGER3 W5 D/ D8 B- @7 ?9 {; x \, b
| USB_ACA_B_CHARGER
% J& E: Y- Z3 l. Z& o" n7 ] | USB_ACA_C_CHARGER6 c$ v7 U( N! H+ m
| USB_DCP_CHARGER
0 b/ A i6 j i8 K: h+ R+ Y | POWER_SUPPLY_TYPE_USB_DCP | AC Charger | USB_PROPRIETARY_CHARGER
0 l+ L7 _" ?0 u; k$ | |
# j. R7 c0 e( L$ \1 K* {As for the DMS, refer to bold font items, so it is USB charger.
- w3 M1 p, u$ K, F1 x( q0 i
7 ]. C3 a) r+ V$ ?6 H3. Analysis about source codes. E' ^! u# Y- e4 q" H2 D
*******************************************************************$ Q1 K- [# D# ~, \4 `2 N
###用户空间的分析如下:
- U Z. a) t$ A3 ?1. 检查 /sys/class/power_supply/pm8921-dc/online和
" G! g! ~3 A# \/sys/class/power_supply/usb/online 的值,可以知道是何充电器类型
0 q4 r3 V1 d7 {. ^/ _: w @frameworks/base/services/jni/com_android_server_batteryservice.cpp中有- m6 G G3 R% @6 |, \+ a, w
int register_android_server_BatteryService(JNIEnv* env)
7 f* L& z" G7 r# N {" i* N; x, l: S) a! ^
if (strcmp(buf, "Mains") == 0) { ///sys/class/power_supply/pm8921-dc/type == Mains9 o9 l" x' q/ n# o e; Z
snprintf(path, sizeof(path), "%s/%s/online", POWER_SUPPLY_PATH, name);- M( `: X3 T" N. _9 |
if (access(path, R_OK) == 0)
! G3 E7 g; n9 M gPaths.acOnlinePath = strdup(path);
4 f& R7 o2 l1 I0 v" T }' {! F- K4 Z/ b! Q
}- R) m5 L2 _5 o, }8 k: Y, ? [
如果/sys/class/power_supply/pm8921-dc/online==1,则插入的充电器是wall& c! E3 t- o t
charger. Z) V. B: Z0 J, F& E& _. t
/sys/class/power_supply/usb/online==1,
}: n/ X& j3 h3 y则插入的充电器是usb charger$ L$ Z. B0 w r7 ]5 o
调试路径:/sys/kernel/debug/msm_otg$ g3 \% j6 V% s, k# G* [2 }: f y
2. 分析frameworks/base/services/jni/com_android_server_batteryservice.cpp
, x- g: u: L9 D5 h9 w! [ a.函数register_android_server_BatteryService将为被frameworks/base/services/jni/onload.cpp中的JNI_OnLoad调用,用于关联java和C++之间的变量
9 n( x; r: |( E b.jclass clazz = env->FindClass("com/android/server/BatteryService"); //根据java的路径找到batteryservice.java对应的jclass 1 A+ T" e+ A9 m4 n5 h: l" [2 @$ C, k& R
gFieldIds.mAcOnline = env->GetFieldID(clazz, "mAcOnline", "Z");! P% J9 [" b1 `
gFieldIds.mUsbOnline = env->GetFieldID(clazz, "mUsbOnline", "Z"); //用于关联batteryservice.java中变量private
& ^6 R0 Z6 P( H/ B/ Y4 L* r4 Vboolean mAcOnline和gFieldIds.mAcOnline* d0 s8 j8 k9 i$ @- y
c. android_server_BatteryService_update
* @) W, S5 Y( ] J, x. g8 \ static JNINativeMethod sMethods[] = {
5 L+ j. q! k* K8 E/ l' J8 a7 U$ S /* name, signature, funcPtr */$ |8 Y# U! d- t6 p z ]9 D
{"native_update", "()V", (void*)android_server_BatteryService_update},4 D5 n4 r0 h! Y3 J8 T, e
};
4 i4 N1 u' l! z0 u4 l; k5 A4 U2 U 关联到native_update@frameworks/base/services/java/com/android/server/batteryservice.java' N) j/ A; g) s1 f8 W
3. 分析frameworks/base/services/java/com/android/server/batteryservice.java0 V* Q' c" ]+ `$ M
a. mPowerSupplyObserver.startObserving("SUBSYSTEM=power_supply"); //注册监听该uevent
& e# y1 D e; I: T8 B' k b. private UEventObserver mPowerSupplyObserver = new UEventObserver() {
( u: ]$ F9 \6 K: B/ j public void onUEvent(UEventObserver.UEvent event) { //如果就收到来自kernel的uevent,触发该函数 j ?/ U7 @ ?# Q0 O, J, C
update(); //-->native_update();和processValues();/ T, o8 Z' u. e
}" X& \9 _6 v" j& g6 D
};
9 Q& _- R' Q2 ~+ t7 \+ O/ Z* r c. native_update函数会通过JNI调用得到更新的mAcOnline和mUsbOnline值. m, P) O: R* p5 `
d. processValues会根据mAcOnline和mUsbOnline值对mPlugType赋值
) _# M- j% P7 x8 I$ B5 C if (mAcOnline) {: G2 Y1 }7 f- f5 i0 n/ @
mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
! G) _7 k# F: d4 @; p } else if (mUsbOnline) {
8 T. Z/ P9 W9 S { mPlugType = BatteryManager.BATTERY_PLUGGED_USB;1 \& ]* C$ A# e3 `3 k% t! K
} else {
; L* l3 b/ `0 S% B# V mPlugType = BATTERY_PLUGGED_NONE;0 y5 y2 H& Q: D8 b6 K- T. w7 R! N' v
}. l W& O9 i: W
e. sendIntent函数会准备Intent并且broadcast这个Intent
8 B) y9 z0 S; s8 M8 j, N Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED); //public static final String ACTION_BATTERY_CHANGED = "android.intent.action.BATTERY_CHANGED";@batteryservice.java
9 w9 @) x0 m1 h$ C/ o intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
3 ?, Q' x% J: E) F% _8 J1 \9 b | Intent.FLAG_RECEIVER_REPLACE_PENDING);( t, w% `4 ^4 r" l
# _6 ?' z1 a) G& O, W3 x
intent.putExtra(BatteryManager.EXTRA_PLUGGED, mPlugType);
: B! |/ { O8 I3 _% F/ ?; x9 a% e ActivityManagerNative.broadcastStickyIntent(intent, null);
0 x6 g0 g9 R! X% K4. 分析vendor/sEMC/packages/apps/debugmenu/src/com/sonyericsson/debugmenu/battery.java1 @6 _# d7 }/ v# s) _" F8 i$ @
a. 接收intent. M* t* _+ v g& S' B" ]
private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {
# Z2 P% A" u+ G" B6 ^; O @Override
! _) ^+ m$ b3 J; O; R public void onReceive(Context arg0, Intent intent) {
1 }2 s# Y. y# G6 O if (intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) {* L; h3 a9 F( v9 x- g. l4 d
mPowerInformation.parseIntent(intent);3 X4 r! H9 ]8 l( F& P9 b
updateViews();
! R }# u0 G$ Y: `7 P, j- r }% C8 e3 h5 q! S
}4 M6 ^+ a, Z; y- w, E/ f
};
0 n5 v# n( `% W* z public void registerBroadcastReceivers() {: s) A; x$ M' ^4 T, N k0 }. O
IntentFilter mIntentFilter;
8 q) ^8 I5 E8 U& g4 ] mIntentFilter = new IntentFilter();& H3 U; Q9 y$ L0 M8 X% q( N9 ^
mIntentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); //只接收Intent.ACTION_BATTERY_CHANGED的intent
7 r+ F9 K/ J8 J // Register battery receiver.1 y9 ^( R! f: ~8 W( q
registerReceiver(mBatteryInfoReceiver, mIntentFilter);' c& C- K* g' ~) w) L, ~
}
8 W* x) c3 b* \: i. X- g b. parseIntent 得到最新的"plugged"值赋给mPlugged
) Q/ A! M8 u% X* v4 I c. updateViews 更新charger类型显示
! h2 s4 b& ^- N) f e; B U###内核空间( |, u( j! \$ j( G4 h3 w6 r
1. 插入充电器触发的过程@kernel/drivers/usb/otg/msm_otg.c. ?. M7 W' C* @
a. CONFIG_PM_RUNTIME 定义 @kernel/arch/ARM/configs/viskan_huashan_defconfig
4 `8 t% g2 J: l/ h$ E b.msm_otg_runtime_resume-->msm_otg_resume-->??-->msm_otg_sm_work
# f5 K7 N& }0 `/ E c.msm_otg_sm_work,先进入OTG_STATE_UNDEFINED case,然后进入OTG_STATE_B_IDLE
* \2 t! j3 J. N7 L; W: k D! T" R9 |case-->motg->chg_state=USB_CHG_STATE_UNDEFINED-->启动msm_chg_detect_work" B4 g+ P) W/ |4 N
d.msm_chg_detect_work 该函数主要完成USB charger类型的识别/ T4 e: `+ g( t" v- K1 {. e g3 T
USB_CHG_STATE_UNDEFINED //其中psy = power_supply_get_by_name("usb");很关键,表明只是获取usb的power_supply,实际上就是chip->usb_psy@pm8921-charger.c. D0 K& l2 q t9 q) b
USB_CHG_STATE_WAIT_FOR_DCD //Waiting for Data pins contact.
5 [* w" n& M4 X) X 然后多次(MSM_CHG_DCD_MAX_RETRIES=6)检测USB状态,启动queue_delayed_work(motg->wq,
! n+ s1 k+ m3 B A&motg->chg_work, delay); //motg->chg_work=msm_chg_detect_work( l6 a4 ^% \- n1 G) g& ^# U
USB_CHG_STATE_DETECTED //最后USB charge类型检测完毕( Y0 r3 d) {- o* t' c9 v( |
e. 启动queue_work(motg->wq, &motg->sm_work); //motg->sm_work=msm_otg_sm_work
i1 h4 G& i. k' J0 O; u f. 由于motg->chg_state==USB_CHG_STATE_DETECTED,. S3 { T) B( l( T! C
motg->chg_type==USB_DCP_CHARGER -->msm_otg_notify_charger(motg,IDEV_CHG_MAX);//IDEV_CHG_MAX=15007 u4 {1 ^/ M& ^. u5 z1 Z# ` | M4 @
2. 发送uevent到用户层
( { y9 ^" W% W& t a. msm_otg_notify_charger@kernel/drivers/usb/otg/msm_otg.c
& G( l: C a: G# c0 }- D7 n b. -->msm_otg_notify_chg_type@msm_otg.c,该函数中充电类型只归纳成4种:POWER_SUPPLY_TYPE_USB,POWER_SUPPLY_TYPE_USB_CDP,POWER_SUPPLY_TYPE_USB_DCP,POWER_SUPPLY_TYPE_USB_ACA,POWER_SUPPLY_TYPE_BATTERY; L( S5 ]5 L( Q* H2 g
c. -->power_supply_set_supply_type@power_supply_core.c // set type of the power supply8 }3 m x8 `- ?0 {4 W/ {4 k# p
d. -->psy->set_property(psy, POWER_SUPPLY_PROP_TYPE,&ret);' t. v5 ~4 X! k" c2 |5 {
那么在用usb_psy.get_property和dc_psy.get_property
1 K7 [0 h+ F: m; ^" \* x(在函数中pm8921_charger_probe)读取property时' }6 D" f; N9 I! z: g* J2 f1 c
如果是USB type,则在pm_power_get_property_usb读取POWER_SUPPLY_PROP_ONLINE的值,其中POWER_SUPPLY_TYPE_USB,POWER_SUPPLY_TYPE_USB_CDP和POWER_SUPPLY_TYPE_USB_ACA都被归纳成USB" D5 e0 e" s- B0 s
charger
4 H9 }4 w+ U& q2 D. {$ k 如果是AC type,则在pm_power_get_property_mains读取POWER_SUPPLY_PROP_ONLINE的值,只有POWER_SUPPLY_TYPE_USB_DCP为AC
* E) d) @/ e! r/ d; O" u" \charger.
) C$ m1 h# w" ~' E" v9 S! }, } e. psy=chip->[url=http://www.16rd.com/mailto:usb_psy@pm8921-charger.c,%E6%89%80%E4%BB%A5%E7%BB%A7%E7%BB%AD%E8%B0%83%E7%94%A8%E7%9A%84%E6%98%AFpm_power_set_property_usb@pm8921-charger.c]usb_psy@pm8921-charger.c,所以继续调用的是[/url]pm_power_set_property_usb@pm8921-charger.c3 L7 H5 r, j; X7 A9 @1 h6 G: y
f. -->pm8921_set_usb_power_supply_type(val->intval)@pm8921-charger.c
9 d/ T- |1 T/ e4 a$ c$ b3 ?- B -->power_supply_changed(&the_chip->usb_psy);
& x# O/ H# |( U+ H6 g -->power_supply_changed(&the_chip->dc_psy);
& U( u/ w) y- z5 L0 B0 o( R g. power_supply_changed@pm8921-charger.c , 就会马上发送uevent给user
! Q8 I7 N; ~6 [( n9 i# I" Jspace,然后user space通过sysfs得到USB
4 r* p: t8 H, A& w6 Vtype变化后的信息,参考用户空间的分析
$ U1 r( r U% h+ }) D( }) A3 q# \% V9 e7 W2 k `/ ]
二、硬件分析2 F6 l/ Q @2 y: c
![]()
- N2 t! n3 I; X0 D0 [6 t) A8 W主要是通过特殊设计的电路,检测不同的pin的状态,从而确定是何种类型的Charger. 更details的内容省略。
5 U3 O1 w: x: B5 [1 v% ]3 y
8 E* J& i9 p% K
( t D( F! X9 B+ b) k+ [; y: p; Y4 C! p
2 k) A" O& X: K: Z, i$ D9 R |
|