|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
USB port 如何识别不同的Charger类型4 n: N5 D7 r* X
2013年10月03日 ⁄ 综合 ⁄ 共 8924字 ⁄ 字号 [url=]小[/url] [url=]中[/url] [url=]大[/url] ⁄ 评论关闭
3 u% a! c/ n. Y: {- G! c4 J- }" C, ?9 T& u
一,软件分析1. USB charger types & Power supply types
8 X9 ^, ~+ _; F& A, dUSB_INVALID_CHARGER Invalid USB charger.! ^; ^2 W' n5 b* t Y/ T: `! r
USB_SDP_CHARGER Standard downstream port. Refers to a downstream port on USB2.0 compliant host/hub.+ v: ^& w( V$ R6 \8 t5 f
USB_DCP_CHARGER Dedicated charger port (AC charger/ Wall charger).
1 b! H5 B8 V% Z: K2 f# U5 ]USB_CDP_CHARGER Charging downstream port. Enumeration can happen and IDEV_CHG_MAX can be drawn irrespective of USB state./ F w% z5 N5 |/ ^& M
USB_ACA_A_CHARGER . W4 V! k7 q7 N7 s
B-device is connected on accessory port with charger connected on charging port. This configuration allows charging in host mode.9 m- {9 l2 Q- c* @
USB_ACA_B_CHARGER No device (or A-device without VBUS) is connected on accessory port with charger connected on charging port.
% K) s) ~8 D3 H- R7 \& sUSB_ACA_C_CHARGER A-device (with VBUS) is connected on accessory port with charger connected on charging port.
6 j* X# [. Z$ G& a o8 [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( _9 ^7 B8 r' m: P& @: q4 V
ports.
3 s) x G3 q: }/ TUSB_PROPRIETARY_CHARGER A proprietary charger pull DP and DM to specific voltages between 2.0-3.3v for identification.) m9 q: M2 x) M6 h+ }
/ U/ F* U) t& u6 R! i
POWER_SUPPLY_TYPE_USB,
9 g: K$ M ^* a7 B) d& A& p/* Standard Downstream Port */- q. G! c& [9 F+ r$ ~
POWER_SUPPLY_TYPE_USB_DCP, /* Dedicated Charging Port */9 U4 I! r5 m8 n$ Q, `/ W+ i2 d+ h! ~
POWER_SUPPLY_TYPE_USB_CDP, /* Charging Downstream Port */3 ^* X" O) R* W7 h
POWER_SUPPLY_TYPE_USB_ACA, /* Accessory Charger Adapters */
% A( u% f$ Z) H9 n# A% vPOWER_SUPPLY_TYPE_BMS,
1 I% u& `. j- n3 [$ t/* Battery Monitor System */
" i' _7 d# F z( U
* b1 S$ `6 }' z- T' |2. How to classify or identify charger?
4 ?" c2 r5 |) U
' |2 R9 j* [( J3 z6 Z: i+ T6 u& VUSB_SDP_CHARGER
5 m8 ]; x# ]- W% c, Z4 r% z | POWER_SUPPLY_TYPE_USB
% d- U+ {/ k3 m' B. y | USB Charger | USB_CDP_CHARGER5 X0 B3 [ s [0 L$ F7 j! L
| POWER_SUPPLY_TYPE_USB_CDP) ]; _0 M) I* n
| USB_ACA_DOCK_CHARGER2 @4 \2 h: u: ~* l0 ^; W M. e9 q
| POWER_SUPPLY_TYPE_USB_ACA | USB_ACA_A_CHARGER
0 [% R( d* y- }# l4 O | USB_ACA_B_CHARGER) w. h' O/ K$ _) M. d4 G
| USB_ACA_C_CHARGER
2 }: G! [0 o8 d' d | USB_DCP_CHARGER
3 K4 D2 ]4 W2 @2 T% f9 O5 _7 W | POWER_SUPPLY_TYPE_USB_DCP | AC Charger | USB_PROPRIETARY_CHARGER
! ]; F/ k |$ e | + W" E! m' ?( c1 t+ e) t
As for the DMS, refer to bold font items, so it is USB charger.
- P& b) R7 i6 S / T3 ]0 g8 j) h) u( [
3. Analysis about source codes
, N" [# R) J; I7 I) a$ f) |*******************************************************************
: Z) p1 l4 H: u% X; v###用户空间的分析如下:
3 q- \) u: U2 S+ d: ~2 u+ F1. 检查 /sys/class/power_supply/pm8921-dc/online和* u8 B0 B. C3 Y- V$ G9 s: o
/sys/class/power_supply/usb/online 的值,可以知道是何充电器类型) u! `; j7 s5 z
@frameworks/base/services/jni/com_android_server_batteryservice.cpp中有0 e" B1 |- S3 Z( s' t% U
int register_android_server_BatteryService(JNIEnv* env)
! ?& S8 o! }# A9 u7 L4 t4 ] {5 Z* N8 {2 Z# C
if (strcmp(buf, "Mains") == 0) { ///sys/class/power_supply/pm8921-dc/type == Mains
7 ?- O; p) |5 s4 Y snprintf(path, sizeof(path), "%s/%s/online", POWER_SUPPLY_PATH, name); r9 U. G, |% x
if (access(path, R_OK) == 0)% e! e& y; B: l& Z
gPaths.acOnlinePath = strdup(path);
& u( m0 s, W! Z# H) g* o H/ P6 q7 ] }8 D E3 t( D2 j, T
}& F4 Z, A4 H# I/ u3 z. t, B
如果/sys/class/power_supply/pm8921-dc/online==1,则插入的充电器是wall& @3 [2 K! e" t5 \9 e3 ]4 r
charger3 ^ `, {& p: v! F' ?
/sys/class/power_supply/usb/online==1, ( R) A0 H! [. p |1 e" d1 u F
则插入的充电器是usb charger9 ]& h0 X6 L4 G1 K$ Q6 S
调试路径:/sys/kernel/debug/msm_otg
7 v0 Z, z8 c) ?- ?. g2. 分析frameworks/base/services/jni/com_android_server_batteryservice.cpp
* c% } N; }# m2 ]1 h a.函数register_android_server_BatteryService将为被frameworks/base/services/jni/onload.cpp中的JNI_OnLoad调用,用于关联java和C++之间的变量) `3 `! E( e. ?6 a
b.jclass clazz = env->FindClass("com/android/server/BatteryService"); //根据java的路径找到batteryservice.java对应的jclass " I" W+ Z N8 L- ^* u' J; h5 b
gFieldIds.mAcOnline = env->GetFieldID(clazz, "mAcOnline", "Z");8 g( Z1 g4 E: ~/ M
gFieldIds.mUsbOnline = env->GetFieldID(clazz, "mUsbOnline", "Z"); //用于关联batteryservice.java中变量private* d, k# {2 l% W+ J. `
boolean mAcOnline和gFieldIds.mAcOnline& t9 O7 n% u5 J- A
c. android_server_BatteryService_update' h3 U+ j) J) O0 o- w6 S
static JNINativeMethod sMethods[] = {
: I3 T" g& T3 @/ c+ V( b /* name, signature, funcPtr */
+ m9 X' ]0 w- ? {"native_update", "()V", (void*)android_server_BatteryService_update},
$ n/ c6 J6 v+ X/ p$ t& J };
6 Y, I0 Y7 K8 M; q5 k. h' F: O 关联到native_update@frameworks/base/services/java/com/android/server/batteryservice.java* P9 r0 E$ x- K( d. E; d) W
3. 分析frameworks/base/services/java/com/android/server/batteryservice.java
8 m' c& \1 w* L a. mPowerSupplyObserver.startObserving("SUBSYSTEM=power_supply"); //注册监听该uevent+ u c4 Q7 e/ R, w! e
b. private UEventObserver mPowerSupplyObserver = new UEventObserver() {/ G* F; L& b# ~8 T$ w* q
public void onUEvent(UEventObserver.UEvent event) { //如果就收到来自kernel的uevent,触发该函数
/ ~0 h+ ?# i* u K6 Z8 L update(); //-->native_update();和processValues();7 m+ S3 w0 `: C% k! q- m. ^/ w
}
6 x2 }/ Q6 g8 s' N; ` };
. @5 V$ J9 V" A* u8 _3 V c. native_update函数会通过JNI调用得到更新的mAcOnline和mUsbOnline值
7 N# e, K* ?$ M7 o+ a7 F; d d. processValues会根据mAcOnline和mUsbOnline值对mPlugType赋值& E6 `6 ]& f# u* h' _
if (mAcOnline) {2 R6 k# b9 o' z4 y: x9 q# d6 S
mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
* G9 g! X8 ^! Y4 J } else if (mUsbOnline) {
" L1 m0 n$ e8 ] mPlugType = BatteryManager.BATTERY_PLUGGED_USB;" D. M9 }3 b. N5 q1 h L
} else {
# {; l8 l# m0 S, z$ y6 U- J0 ~( a mPlugType = BATTERY_PLUGGED_NONE;
' ~- L, @' J9 `1 x5 S* w- D; q }
. E; L _* |" { e. sendIntent函数会准备Intent并且broadcast这个Intent4 p- I0 t' w4 R1 x a% j
Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED); //public static final String ACTION_BATTERY_CHANGED = "android.intent.action.BATTERY_CHANGED";@batteryservice.java
# K3 P$ X- b+ ]( J$ V3 W) j3 | intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
6 f+ \9 G3 i, e$ W& X4 Y1 l/ H' e | Intent.FLAG_RECEIVER_REPLACE_PENDING);
: T6 p$ z5 {- F9 F5 [/ y) k/ m
/ Q, ~/ V8 x7 f2 m intent.putExtra(BatteryManager.EXTRA_PLUGGED, mPlugType);/ p& f4 X0 B' B: \
ActivityManagerNative.broadcastStickyIntent(intent, null);# e Z3 j; ~9 y! O
4. 分析vendor/sEMC/packages/apps/debugmenu/src/com/sonyericsson/debugmenu/battery.java
& J0 N+ A1 B, b" [ T8 M" A a. 接收intent
% N: K: N: O( R3 z( u! R" n private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {/ _$ u' c4 s8 A; R
@Override, |! h- ?5 `* ~* l( W
public void onReceive(Context arg0, Intent intent) {
( s( p6 d. c# z) q" F& z2 X1 g" n0 H1 N if (intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) {- L& s F7 |7 a1 @
mPowerInformation.parseIntent(intent);5 I' h# n1 H( m3 {* w* {; J
updateViews();
9 q0 _# A3 d) J3 K; T7 m }, Q' z& R! o3 g7 d
}' q/ `3 E7 X2 `! a+ a
};7 t/ v3 _. t) m, |
public void registerBroadcastReceivers() {" H: C0 l3 l7 p0 B* @/ c
IntentFilter mIntentFilter;! t) [( Z* Q* L1 s0 F, G) u3 U7 T
mIntentFilter = new IntentFilter();
* ^, z& k/ G9 o) r# Q7 b! [6 u mIntentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); //只接收Intent.ACTION_BATTERY_CHANGED的intent
/ t7 Q- [$ I" C4 F) O7 h: K+ ~ // Register battery receiver.
; P: ?. u8 r( h- F1 Y registerReceiver(mBatteryInfoReceiver, mIntentFilter);5 A$ J* a5 \* |# X: D' c
}
, l+ G* F7 A |2 u3 X+ _ b. parseIntent 得到最新的"plugged"值赋给mPlugged
5 l7 b4 b) y$ j W c. updateViews 更新charger类型显示
/ q! O. f3 _" I0 O2 w###内核空间" C2 }6 r7 n. k. I6 M8 `1 l
1. 插入充电器触发的过程@kernel/drivers/usb/otg/msm_otg.c
/ x& F4 j9 M) ~. q f8 Z+ e( j a. CONFIG_PM_RUNTIME 定义 @kernel/arch/ARM/configs/viskan_huashan_defconfig8 M6 i6 }" A8 [' e. G% a5 Y
b.msm_otg_runtime_resume-->msm_otg_resume-->??-->msm_otg_sm_work, M; m6 T7 a7 m4 O: r% Z0 S1 a+ w
c.msm_otg_sm_work,先进入OTG_STATE_UNDEFINED case,然后进入OTG_STATE_B_IDLE: `: Y; W: {+ P" U# ~% n
case-->motg->chg_state=USB_CHG_STATE_UNDEFINED-->启动msm_chg_detect_work
0 W, l; R" ^" q) D8 [ q; r d.msm_chg_detect_work 该函数主要完成USB charger类型的识别
3 v& L. t. n% J/ t. ^/ f# A USB_CHG_STATE_UNDEFINED //其中psy = power_supply_get_by_name("usb");很关键,表明只是获取usb的power_supply,实际上就是chip->usb_psy@pm8921-charger.c
, H* e1 r N+ }; s USB_CHG_STATE_WAIT_FOR_DCD //Waiting for Data pins contact.
* n* H, p, A t. B 然后多次(MSM_CHG_DCD_MAX_RETRIES=6)检测USB状态,启动queue_delayed_work(motg->wq,
1 O: m# V* k% v2 L3 k7 d' o&motg->chg_work, delay); //motg->chg_work=msm_chg_detect_work: L3 S4 K! {) u( S4 |9 _7 p
USB_CHG_STATE_DETECTED //最后USB charge类型检测完毕1 s, S/ }6 U7 Z
e. 启动queue_work(motg->wq, &motg->sm_work); //motg->sm_work=msm_otg_sm_work' f' k7 A3 R0 i/ H6 g
f. 由于motg->chg_state==USB_CHG_STATE_DETECTED,$ q- g- O6 I2 S/ r: Y1 [6 `' `# M
motg->chg_type==USB_DCP_CHARGER -->msm_otg_notify_charger(motg,IDEV_CHG_MAX);//IDEV_CHG_MAX=1500
- E% s5 C1 k. p* M( S2. 发送uevent到用户层4 r8 m* N3 w# _
a. msm_otg_notify_charger@kernel/drivers/usb/otg/msm_otg.c9 H5 m. r% G4 j& y9 T. _
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
, _' ?) Z/ r$ w/ M c. -->power_supply_set_supply_type@power_supply_core.c // set type of the power supply& M2 G) q5 L% ~2 J0 e2 x
d. -->psy->set_property(psy, POWER_SUPPLY_PROP_TYPE,&ret);
" u4 X+ f+ V' c7 F3 H 那么在用usb_psy.get_property和dc_psy.get_property
/ r3 F# T v T(在函数中pm8921_charger_probe)读取property时( l, B, N' c: K
如果是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都被归纳成USB6 x4 M$ D7 M" E8 m) _; U. V1 b# S
charger$ b' |6 u5 x W; D) l. B5 e
如果是AC type,则在pm_power_get_property_mains读取POWER_SUPPLY_PROP_ONLINE的值,只有POWER_SUPPLY_TYPE_USB_DCP为AC( w/ l4 J/ V: V4 t/ r
charger.+ W4 O$ h1 j$ k4 X8 v
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
& @8 q2 {. V" a& ~ f. -->pm8921_set_usb_power_supply_type(val->intval)@pm8921-charger.c( e2 Q4 i: A5 m: [/ \+ A( |8 n
-->power_supply_changed(&the_chip->usb_psy);8 \, }, Y5 V; M0 h1 l3 x
-->power_supply_changed(&the_chip->dc_psy);
+ S5 H0 O' d0 B* ~. m; n g. power_supply_changed@pm8921-charger.c , 就会马上发送uevent给user
9 j2 h; P% c2 nspace,然后user space通过sysfs得到USB5 V" t* O" G/ g6 p) u: }% f$ S
type变化后的信息,参考用户空间的分析: g2 }/ i8 \" v2 |2 T# C$ y( P
+ k* V9 H% f" t( _+ m v二、硬件分析
0 ^# H& N8 O* U) g, a 0 e9 e# l6 K+ A9 f# ]" ~
主要是通过特殊设计的电路,检测不同的pin的状态,从而确定是何种类型的Charger. 更details的内容省略。% _. F! Z" \8 p# J$ y) {/ d- E
: b, c- l/ P# O" o
3 y$ W- E+ w2 k" w% O3 \; f4 n7 Y( j9 `
|
|