|
EDA365欢迎您!
您需要 登录 才可以下载或查看,没有帐号?注册
x
USB port 如何识别不同的Charger类型
& \" Z5 [: j' o! i1 `# Y# y) G/ m8 k2013年10月03日 ⁄ 综合 ⁄ 共 8924字 ⁄ 字号 [url=]小[/url] [url=]中[/url] [url=]大[/url] ⁄ 评论关闭
+ o* @3 Y0 D. o; }! \, ]
- q8 @- h B& s6 u: K. V一,软件分析1. USB charger types & Power supply types
! p& G; R: a' m) CUSB_INVALID_CHARGER Invalid USB charger.* P* A, N! p, |+ G7 Q
USB_SDP_CHARGER Standard downstream port. Refers to a downstream port on USB2.0 compliant host/hub.
! o9 |; u! T) U' ?$ @ EUSB_DCP_CHARGER Dedicated charger port (AC charger/ Wall charger).
9 F. o' m7 q% |3 K, t5 O2 rUSB_CDP_CHARGER Charging downstream port. Enumeration can happen and IDEV_CHG_MAX can be drawn irrespective of USB state.( F, u" \* z) ^* _! `; m& F& ~
USB_ACA_A_CHARGER , h1 }+ T8 K. Y: N6 k( P
B-device is connected on accessory port with charger connected on charging port. This configuration allows charging in host mode.7 e9 g1 {% C4 A
USB_ACA_B_CHARGER No device (or A-device without VBUS) is connected on accessory port with charger connected on charging port.9 ?" y! i% N( k% i/ }3 A. z& i
USB_ACA_C_CHARGER A-device (with VBUS) is connected on accessory port with charger connected on charging port.( s: V7 V! X' V6 l
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- l4 H0 j2 [% L7 e
ports.
: A$ P3 U% U# q- }; j1 M6 BUSB_PROPRIETARY_CHARGER A proprietary charger pull DP and DM to specific voltages between 2.0-3.3v for identification.2 i( T5 V% |8 |2 J
" w/ R, ]; y9 j& h! x' R( W( T2 N' WPOWER_SUPPLY_TYPE_USB,
- d% M2 V) j& E, h/* Standard Downstream Port */* k0 m0 U) Z ^& ~4 Y7 T5 m
POWER_SUPPLY_TYPE_USB_DCP, /* Dedicated Charging Port */* A9 C6 N; n2 {( q. R. ^) P& ]
POWER_SUPPLY_TYPE_USB_CDP, /* Charging Downstream Port */& d* `3 Y2 U3 Z: U7 U
POWER_SUPPLY_TYPE_USB_ACA, /* Accessory Charger Adapters */
4 q1 e9 C; |# r% ?POWER_SUPPLY_TYPE_BMS,
* F# c7 @$ a6 N2 G/* Battery Monitor System */
5 E6 Q* ^: \- ~% Z' }2 |# q/ |
9 `; ?. q8 l" }; _$ O2. How to classify or identify charger? Y: f+ ~* k3 g8 c) L
& ~6 ^( w" ^8 r8 ?; _4 WUSB_SDP_CHARGER" Y E; m( ^- g6 o8 [
| POWER_SUPPLY_TYPE_USB
0 n- g; y5 x3 q% z# R | USB Charger | USB_CDP_CHARGER
* X% w/ }$ I$ e$ Q | POWER_SUPPLY_TYPE_USB_CDP- V- B' k9 N4 C+ ]8 n( J1 S
| USB_ACA_DOCK_CHARGER# J! L3 p g$ n6 ]: I, s5 L8 C
| POWER_SUPPLY_TYPE_USB_ACA | USB_ACA_A_CHARGER- b q+ j5 S, x5 Q/ M4 I3 v
| USB_ACA_B_CHARGER
8 ?6 s# ]) a& x. K6 e: F+ Z) [ | USB_ACA_C_CHARGER
# S- ?& N6 U% F& c# w } | USB_DCP_CHARGER: u. I, Z6 z2 k
| POWER_SUPPLY_TYPE_USB_DCP | AC Charger | USB_PROPRIETARY_CHARGER
- z3 C* @2 e! S2 w9 M/ y! h' d# R | " C8 P- H Z: e- R3 ]8 h
As for the DMS, refer to bold font items, so it is USB charger.
# M6 w) d7 b! G" T% B) x % K0 R9 w! }% }
3. Analysis about source codes
8 U$ f7 Y: t4 U0 V*******************************************************************
/ n7 n; H3 H# K$ L8 O& n- E9 p###用户空间的分析如下:/ r6 u& r! o- ~# Q7 m* j) g
1. 检查 /sys/class/power_supply/pm8921-dc/online和
5 r9 K& V! g( f0 k3 ~: l/sys/class/power_supply/usb/online 的值,可以知道是何充电器类型) Z1 X9 K2 u' E4 u* t1 _& E g3 _
@frameworks/base/services/jni/com_android_server_batteryservice.cpp中有
. i/ K( x- ]% I7 g. i int register_android_server_BatteryService(JNIEnv* env)
$ y8 c) G; `5 M( w& ~ {
( Y& ?3 T2 g' \4 M7 ~1 s- _$ h if (strcmp(buf, "Mains") == 0) { ///sys/class/power_supply/pm8921-dc/type == Mains( C/ Y l! A" E- X0 {0 c
snprintf(path, sizeof(path), "%s/%s/online", POWER_SUPPLY_PATH, name);, y- ]. n# |. z* w1 V
if (access(path, R_OK) == 0)5 t* ]0 ^1 O$ g0 h7 M& h
gPaths.acOnlinePath = strdup(path);
\1 {1 d3 B$ }5 x1 e1 b1 b }
( ?% a& A- r; H8 {5 h } r$ }) t& y. I$ \+ n# ~4 ]+ A
如果/sys/class/power_supply/pm8921-dc/online==1,则插入的充电器是wall
T3 u5 B- Z$ n' O9 rcharger& \1 m+ |# T, L
/sys/class/power_supply/usb/online==1,
5 M5 B, X$ W# l6 i1 ~! s则插入的充电器是usb charger
+ ?* P/ \ r3 R, s ^( T 调试路径:/sys/kernel/debug/msm_otg
6 |0 u7 i6 m& R q+ k8 i& q2. 分析frameworks/base/services/jni/com_android_server_batteryservice.cpp
) R$ z, h; t- S1 P a.函数register_android_server_BatteryService将为被frameworks/base/services/jni/onload.cpp中的JNI_OnLoad调用,用于关联java和C++之间的变量
8 L! h1 Y1 r. k% Z. B* F7 E% r: F b.jclass clazz = env->FindClass("com/android/server/BatteryService"); //根据java的路径找到batteryservice.java对应的jclass , f- J" \: n7 e# o4 E7 ]
gFieldIds.mAcOnline = env->GetFieldID(clazz, "mAcOnline", "Z");: v! x7 ]& P4 E
gFieldIds.mUsbOnline = env->GetFieldID(clazz, "mUsbOnline", "Z"); //用于关联batteryservice.java中变量private
. v5 f( B) c! g: e0 c# `boolean mAcOnline和gFieldIds.mAcOnline: ^8 T' Y9 P2 l0 y% G
c. android_server_BatteryService_update1 \! C( k( J: f2 X" a& G/ {* n
static JNINativeMethod sMethods[] = {
2 B, N' @6 E" v" w# Z4 E' s /* name, signature, funcPtr */9 B7 D! O) X' |( `) e
{"native_update", "()V", (void*)android_server_BatteryService_update},+ c$ @$ g9 p1 q! Y2 }" e) O
};
$ D/ J+ N Q7 m7 Z! k 关联到native_update@frameworks/base/services/java/com/android/server/batteryservice.java- J" A) m$ H# U0 ?% s
3. 分析frameworks/base/services/java/com/android/server/batteryservice.java
; z1 A6 K8 q2 ]$ b( [, Q$ p+ g a. mPowerSupplyObserver.startObserving("SUBSYSTEM=power_supply"); //注册监听该uevent
3 T8 q; e' t# J6 _ b. private UEventObserver mPowerSupplyObserver = new UEventObserver() {) \% j; |% [, K$ v$ [
public void onUEvent(UEventObserver.UEvent event) { //如果就收到来自kernel的uevent,触发该函数" O; D$ v" B& y6 Q1 Q& \
update(); //-->native_update();和processValues();
$ c, R3 h. K1 ?: x }$ A3 Q1 [, k+ E
};
6 h% f* |% N! |( O c. native_update函数会通过JNI调用得到更新的mAcOnline和mUsbOnline值
1 e+ u* g, c( r; T% j d. processValues会根据mAcOnline和mUsbOnline值对mPlugType赋值
# Y9 o$ ?; w# \- r6 V" Y T& P if (mAcOnline) {
/ V6 }; G- @# C mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
3 s& \6 P" R, x+ H- }) ~- s } else if (mUsbOnline) {
3 L* }2 L! _- h/ |4 v- Y mPlugType = BatteryManager.BATTERY_PLUGGED_USB;% x o$ n0 K& Y) s+ u( p
} else {
( l. U5 r3 T/ d; t" G! Q- _) } mPlugType = BATTERY_PLUGGED_NONE;
, \ ^ N3 ?, j0 c0 k0 h }$ { \2 }0 Y/ @8 n* g
e. sendIntent函数会准备Intent并且broadcast这个Intent
" y/ L9 B4 W1 A Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED); //public static final String ACTION_BATTERY_CHANGED = "android.intent.action.BATTERY_CHANGED";@batteryservice.java
. H; M1 {( U& ^ ?2 U4 O3 G2 q intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY2 ]' ~2 a1 @/ u( d k3 u
| Intent.FLAG_RECEIVER_REPLACE_PENDING);- _, Y! O0 z& N7 ]
9 \: `$ m( @$ i* }% E8 u intent.putExtra(BatteryManager.EXTRA_PLUGGED, mPlugType);, _! u, P6 N. U4 L
ActivityManagerNative.broadcastStickyIntent(intent, null);6 L6 h7 H, n; ]7 t+ @" w7 J3 e. y
4. 分析vendor/semc/packages/apps/debugmenu/src/com/sonyericsson/debugmenu/battery.java) T7 D7 k1 G' t2 {
a. 接收intent0 w* ~* }1 p1 d% B0 @
private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {6 v7 p8 L9 R! \# \" ]
@Override
% [! o/ T. O/ s' _/ j/ A+ ]+ d: R# B public void onReceive(Context arg0, Intent intent) {
L3 o- l* n( f- J X3 E if (intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) {1 h. n8 A" l* \+ f; o
mPowerInformation.parseIntent(intent);
9 K; E9 S4 v; `# L3 c updateViews();8 B- c% y8 o+ t
}
- u$ D' Q4 ]' d) u9 S- d$ E+ ^2 a }3 Q1 E' f: r/ A: r K) G/ Y
};# b, {6 X6 k( O f$ U: s
public void registerBroadcastReceivers() {5 e# {: n4 o7 v1 Q3 E; a
IntentFilter mIntentFilter;
( V- G4 M J: Q( ^2 }2 J0 _ mIntentFilter = new IntentFilter();
0 I& `9 N+ ]% @; i mIntentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); //只接收Intent.ACTION_BATTERY_CHANGED的intent7 y( u6 I# N: I
// Register battery receiver.
1 S) S& N% i, h# q registerReceiver(mBatteryInfoReceiver, mIntentFilter);6 Q& c" g+ f0 s9 k
}
0 I' Q9 ]. u V3 n) q b. parseIntent 得到最新的"plugged"值赋给mPlugged5 _0 S& {' M. K3 P2 Y/ c
c. updateViews 更新charger类型显示
: o1 o) ?9 b2 o/ U###内核空间- F4 {1 n/ E$ B: P0 E; B2 c
1. 插入充电器触发的过程@kernel/drivers/usb/otg/msm_otg.c; s' ~) W, ?% I( G, @+ t4 O, I1 I
a. CONFIG_PM_RUNTIME 定义 @kernel/arch/arm/configs/viskan_huashan_defconfig* V! Z% j m/ S, S
b.msm_otg_runtime_resume-->msm_otg_resume-->??-->msm_otg_sm_work! n, L; T% {+ Q0 W6 i6 s
c.msm_otg_sm_work,先进入OTG_STATE_UNDEFINED case,然后进入OTG_STATE_B_IDLE
1 S0 }% ]3 A2 r5 fcase-->motg->chg_state=USB_CHG_STATE_UNDEFINED-->启动msm_chg_detect_work) g; @7 a# i: R7 Z# x2 y
d.msm_chg_detect_work 该函数主要完成USB charger类型的识别
5 `' V/ @" m! C/ I) [! R+ D USB_CHG_STATE_UNDEFINED //其中psy = power_supply_get_by_name("usb");很关键,表明只是获取usb的power_supply,实际上就是chip->usb_psy@pm8921-charger.c
2 Y2 \; x+ {1 W B2 K USB_CHG_STATE_WAIT_FOR_DCD //Waiting for Data pins contact.- ]2 g0 i" \0 K c- [1 i2 F
然后多次(MSM_CHG_DCD_MAX_RETRIES=6)检测USB状态,启动queue_delayed_work(motg->wq,
; ~3 U, D" d+ g$ Z- ?&motg->chg_work, delay); //motg->chg_work=msm_chg_detect_work% o- J$ x! [; p- ^7 C$ c M
USB_CHG_STATE_DETECTED //最后USB charge类型检测完毕
3 l7 Q! ]2 ~, N9 \3 b5 J4 W e. 启动queue_work(motg->wq, &motg->sm_work); //motg->sm_work=msm_otg_sm_work! ?8 ~* H4 z: O! j5 P
f. 由于motg->chg_state==USB_CHG_STATE_DETECTED,
0 g {: j2 V5 R3 Z3 J- B* r motg->chg_type==USB_DCP_CHARGER -->msm_otg_notify_charger(motg,IDEV_CHG_MAX);//IDEV_CHG_MAX=15001 A( H6 Y: T* [3 D
2. 发送uevent到用户层
+ ], Z- z% n1 Y* W& _/ Q+ @. R9 ^0 c a. msm_otg_notify_charger@kernel/drivers/usb/otg/msm_otg.c
" L5 ^6 X' e3 V' j0 ^: E8 x S 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) U# X0 g4 B: Z, E9 o
c. -->power_supply_set_supply_type@power_supply_core.c // set type of the power supply
+ J: e6 P$ R% i, c" O+ I" X6 D d. -->psy->set_property(psy, POWER_SUPPLY_PROP_TYPE,&ret);' }" N0 Z8 W0 P9 r: `8 R- a
那么在用usb_psy.get_property和dc_psy.get_property
6 [: T' ~* |+ H! m3 g$ Y(在函数中pm8921_charger_probe)读取property时' F/ S/ F7 T8 ]/ k. g1 z
如果是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都被归纳成USB5 c5 z6 \9 }: ^2 H( r, ~
charger
+ [6 S1 W& h! r 如果是AC type,则在pm_power_get_property_mains读取POWER_SUPPLY_PROP_ONLINE的值,只有POWER_SUPPLY_TYPE_USB_DCP为AC: _9 h2 s6 g6 C, S4 }2 e: R/ ?
charger., B. Z: F3 k3 E2 K2 U5 v- e* M
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.c' }! J9 P, @- {2 \3 H/ B
f. -->pm8921_set_usb_power_supply_type(val->intval)@pm8921-charger.c
9 e1 `; j; l0 h+ R" M7 E -->power_supply_changed(&the_chip->usb_psy);* j) {0 ^/ z0 }9 _% P
-->power_supply_changed(&the_chip->dc_psy);
. ^/ p& u# t6 l5 h, a g. power_supply_changed@pm8921-charger.c , 就会马上发送uevent给user% i: v+ K, V' f9 k' v
space,然后user space通过sysfs得到USB5 A3 A7 {( U3 s; Y
type变化后的信息,参考用户空间的分析; I4 R8 X5 N% L" O
& n, z$ H: j7 a# y/ x, F二、硬件分析4 f$ A3 w, }: q' \* v
2 z. o7 l/ L) q* [, a
主要是通过特殊设计的电路,检测不同的pin的状态,从而确定是何种类型的Charger. 更details的内容省略。
& N! V7 p! X0 z5 \9 ~9 e
# J9 E: k' ~ o+ ]- `6 b- i( n. R. Y# s" K
c1 A8 l" @9 H$ p6 y) A! S
|
|