|
EDA365欢迎您!
您需要 登录 才可以下载或查看,没有帐号?注册
x
USB port 如何识别不同的Charger类型' z$ \6 `5 D. i0 L
2013年10月03日 ⁄ 综合 ⁄ 共 8924字 ⁄ 字号 [url=]小[/url] [url=]中[/url] [url=]大[/url] ⁄ 评论关闭8 b0 F, ^% s$ e$ U0 t
1 j0 b. B$ w0 B0 w: I
一,软件分析1. USB charger types & Power supply types
0 @+ J" O& z+ _1 j( U/ ^4 o6 s+ d, LUSB_INVALID_CHARGER Invalid USB charger.' F5 I6 a8 `7 k/ h) J" [4 Z
USB_SDP_CHARGER Standard downstream port. Refers to a downstream port on USB2.0 compliant host/hub.) L, Z. k& w7 _% Y3 g2 C
USB_DCP_CHARGER Dedicated charger port (AC charger/ Wall charger)./ |( d1 g/ G( I9 w
USB_CDP_CHARGER Charging downstream port. Enumeration can happen and IDEV_CHG_MAX can be drawn irrespective of USB state.
/ h& l' V! W B- M5 t+ D! y3 D, IUSB_ACA_A_CHARGER
2 t. L* ]& i6 ^- [6 M6 qB-device is connected on accessory port with charger connected on charging port. This configuration allows charging in host mode.
: ?- _2 M7 m6 T: x6 GUSB_ACA_B_CHARGER No device (or A-device without VBUS) is connected on accessory port with charger connected on charging port.
4 C3 a2 p% V$ N1 V& sUSB_ACA_C_CHARGER A-device (with VBUS) is connected on accessory port with charger connected on charging port.2 h7 K, N; a0 q7 R
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 accessory2 \" W( k/ w# y2 d) t
ports.
; _; i, f! j( c. YUSB_PROPRIETARY_CHARGER A proprietary charger pull DP and DM to specific voltages between 2.0-3.3v for identification.1 r1 ?5 ~1 N5 x! X, l# l
; A- W1 G0 r+ y% {8 g \POWER_SUPPLY_TYPE_USB,
" X. y6 x2 p0 W/ J2 E/* Standard Downstream Port */
6 r+ X# r; ?0 O4 C% d/ U% ], tPOWER_SUPPLY_TYPE_USB_DCP, /* Dedicated Charging Port */
$ o* w/ S* l% }* I7 r6 L% qPOWER_SUPPLY_TYPE_USB_CDP, /* Charging Downstream Port */# t! V/ w" @9 p+ O. V" k. y4 T
POWER_SUPPLY_TYPE_USB_ACA, /* Accessory Charger Adapters */
9 ]: o3 P: z/ ^- O: r: `POWER_SUPPLY_TYPE_BMS,
& c, `5 M/ Z! ~2 m) E- ~/ D/* Battery Monitor System */- r$ \5 g2 F7 T7 Q; n! O0 m) f
. c1 t: K+ }/ Y" ]: q$ J
2. How to classify or identify charger?
; B4 N' S5 A+ G7 V: ^
( J& G" k* K! Y7 {; K" oUSB_SDP_CHARGER
: v1 Y8 a# F8 u2 {# m8 `7 N2 p | POWER_SUPPLY_TYPE_USB
% g& g7 _; r) [5 t. e2 a) Z! b | USB Charger | USB_CDP_CHARGER' i9 K" @ U, ^5 x6 f
| POWER_SUPPLY_TYPE_USB_CDP
) \; I" n5 b* G | USB_ACA_DOCK_CHARGER
3 |; i \, _% L3 a( |6 b/ F u | POWER_SUPPLY_TYPE_USB_ACA | USB_ACA_A_CHARGER
- V& X1 m: f$ n A+ n# G | USB_ACA_B_CHARGER
7 i. [ p7 X( T# ^% [ | USB_ACA_C_CHARGER
& M2 X# _0 U) c$ j, V# F+ H | USB_DCP_CHARGER
5 M s) i( s( d# \ | POWER_SUPPLY_TYPE_USB_DCP | AC Charger | USB_PROPRIETARY_CHARGER
) u' X, K% M. ^7 J; t1 L7 k |
+ z. g6 n5 Y. u2 [. _$ ]5 jAs for the DMS, refer to bold font items, so it is USB charger.
( H9 L& h: w, l: _5 j 1 `7 Q+ m# u! |5 r! ]) _
3. Analysis about source codes
; s. i$ e. C; j; L( ^ P*******************************************************************
' f! ]$ I8 Y" A. e###用户空间的分析如下:* E! e5 L) ^( |
1. 检查 /sys/class/power_supply/pm8921-dc/online和
. y3 B6 P& k: H; G/ f- X* o/sys/class/power_supply/usb/online 的值,可以知道是何充电器类型# H9 r9 w3 O) `6 U7 o: l/ k: j, ^
@frameworks/base/services/jni/com_android_server_batteryservice.cpp中有/ r; H" B) v" L5 ^) _
int register_android_server_BatteryService(JNIEnv* env) $ H! p( |0 X: D6 B1 K
{
0 C% v0 L/ e+ l& c8 w, k if (strcmp(buf, "Mains") == 0) { ///sys/class/power_supply/pm8921-dc/type == Mains
2 D/ I! B+ h' m9 C+ y% I snprintf(path, sizeof(path), "%s/%s/online", POWER_SUPPLY_PATH, name);( y9 _5 H5 e& ?. o* A
if (access(path, R_OK) == 0)
2 B0 [/ u' E5 Z t& J gPaths.acOnlinePath = strdup(path);" }% E2 }# G3 o6 M
}* M" {% o k' ~* ^2 R
}( @) o5 b$ M/ j0 @
如果/sys/class/power_supply/pm8921-dc/online==1,则插入的充电器是wall
6 b( Z" Q! j. I4 k9 s# }charger
( {5 x) @# |2 _3 h3 [5 _ /sys/class/power_supply/usb/online==1, & I( V5 q# H' l1 A; Q
则插入的充电器是usb charger
$ Y7 q4 R t0 P4 f 调试路径:/sys/kernel/debug/msm_otg0 K; r8 G$ K8 V7 `( w
2. 分析frameworks/base/services/jni/com_android_server_batteryservice.cpp
4 x+ C9 V) M, U" d: L+ f; ? a.函数register_android_server_BatteryService将为被frameworks/base/services/jni/onload.cpp中的JNI_OnLoad调用,用于关联java和C++之间的变量
! |( r7 w0 w) o# N6 i b.jclass clazz = env->FindClass("com/android/server/BatteryService"); //根据java的路径找到batteryservice.java对应的jclass
* T$ L+ m- S6 C9 g gFieldIds.mAcOnline = env->GetFieldID(clazz, "mAcOnline", "Z");
R7 P5 n: p1 \& Z# D gFieldIds.mUsbOnline = env->GetFieldID(clazz, "mUsbOnline", "Z"); //用于关联batteryservice.java中变量private
* }% L5 @ H# J0 zboolean mAcOnline和gFieldIds.mAcOnline
6 Q A# T( D m$ P c. android_server_BatteryService_update; i. V7 L, m- g$ h7 ]
static JNINativeMethod sMethods[] = {- Z7 P( g! D. C
/* name, signature, funcPtr */
& \! m1 S' w$ [8 g {"native_update", "()V", (void*)android_server_BatteryService_update},
P/ w. E: |. v5 p9 N };
# x4 ~4 G/ D4 X0 \% w/ { 关联到native_update@frameworks/base/services/java/com/android/server/batteryservice.java
2 x0 u( X) @% L# i* |5 W! V) _9 Y3. 分析frameworks/base/services/java/com/android/server/batteryservice.java8 t3 x i' S G+ B+ ?& }
a. mPowerSupplyObserver.startObserving("SUBSYSTEM=power_supply"); //注册监听该uevent
# x/ E/ N% ]1 a. v' d b. private UEventObserver mPowerSupplyObserver = new UEventObserver() {% x+ Q5 E8 ?* k7 S4 f, Z
public void onUEvent(UEventObserver.UEvent event) { //如果就收到来自kernel的uevent,触发该函数. e2 E) U1 {8 ^. J
update(); //-->native_update();和processValues();9 B# d% j2 s5 I6 Y! r$ L
}
& H" H# l+ K! r% ]7 l };
( d9 R3 u! Z: g' l c. native_update函数会通过JNI调用得到更新的mAcOnline和mUsbOnline值' b) T/ |3 q1 }
d. processValues会根据mAcOnline和mUsbOnline值对mPlugType赋值' i0 A S; |) H# G2 S$ P/ m
if (mAcOnline) {: \2 p- a% R" M6 x8 P
mPlugType = BatteryManager.BATTERY_PLUGGED_AC;" k: A1 M9 p5 u M v8 U
} else if (mUsbOnline) {
, D$ f" ?4 e7 |2 q9 t mPlugType = BatteryManager.BATTERY_PLUGGED_USB;
: S6 q0 C3 z4 @6 h' E } else {
( ~7 g9 x, h4 S( i& P, p mPlugType = BATTERY_PLUGGED_NONE;
8 I8 T7 G( R: {+ b { }( y9 W0 @ f3 b; ]# K- f
e. sendIntent函数会准备Intent并且broadcast这个Intent
, ^, n! s5 \5 ^: X' D' }" ~# R Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED); //public static final String ACTION_BATTERY_CHANGED = "android.intent.action.BATTERY_CHANGED";@batteryservice.java
1 \ ]- _, [* b& O intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY! D4 b. v2 b/ {$ u. p4 s
| Intent.FLAG_RECEIVER_REPLACE_PENDING); O5 w3 P7 Q- H) C
5 V5 M3 u X, Q- l
intent.putExtra(BatteryManager.EXTRA_PLUGGED, mPlugType);
# ]& n+ R0 ?/ h! V+ N' v4 B: C ActivityManagerNative.broadcastStickyIntent(intent, null);% P* Q5 K* r9 ~. Q
4. 分析vendor/semc/packages/apps/debugmenu/src/com/sonyericsson/debugmenu/battery.java1 C1 K: V5 b g5 i
a. 接收intent8 O* q! K5 o0 V
private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {1 E/ e, c+ X) `+ i- @# Q* R
@Override
; q+ L2 B/ R) e' Q" }( R public void onReceive(Context arg0, Intent intent) {
$ k' Q0 {. L1 C a! ~" ? if (intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) {2 M# Y+ t' {* g0 N; s b1 j, _
mPowerInformation.parseIntent(intent);
0 s4 x( r$ Y# _. P9 j updateViews();& b0 m! L! R Y
}, T+ D& I% n$ q" ~ h* r6 y/ m6 _
}3 ~* X2 ~& L* n/ I
};7 a) e! {- H; H8 i, w/ R
public void registerBroadcastReceivers() {
+ Q" s/ o+ z2 }; w IntentFilter mIntentFilter;
6 V5 m1 ~1 K4 H9 l J; |, o6 x mIntentFilter = new IntentFilter();
~8 O6 c$ I- N! F- e* n mIntentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); //只接收Intent.ACTION_BATTERY_CHANGED的intent( d3 L% k) \/ U1 z1 T5 ^) z
// Register battery receiver.8 [/ ?; U1 F; g, j/ c5 P
registerReceiver(mBatteryInfoReceiver, mIntentFilter);3 r( g4 U: d7 j2 T
} 2 A* y0 @. V1 f1 u" A6 p% |
b. parseIntent 得到最新的"plugged"值赋给mPlugged
- V: p3 g* {7 V. F+ I3 `( M c. updateViews 更新charger类型显示
/ A- R' F) m q###内核空间
" |; ~" i2 T% O- R% B1. 插入充电器触发的过程@kernel/drivers/usb/otg/msm_otg.c" r: F7 R$ G2 g/ x
a. CONFIG_PM_RUNTIME 定义 @kernel/arch/arm/configs/viskan_huashan_defconfig
- z# Y0 p9 [5 d" Z b.msm_otg_runtime_resume-->msm_otg_resume-->??-->msm_otg_sm_work
0 L$ }/ k( q) D) {4 s# V8 i c.msm_otg_sm_work,先进入OTG_STATE_UNDEFINED case,然后进入OTG_STATE_B_IDLE
/ g- Y. O. Q) e2 n0 zcase-->motg->chg_state=USB_CHG_STATE_UNDEFINED-->启动msm_chg_detect_work
) Z. Y" a& G6 D d.msm_chg_detect_work 该函数主要完成USB charger类型的识别
- h" h; ^! a& | USB_CHG_STATE_UNDEFINED //其中psy = power_supply_get_by_name("usb");很关键,表明只是获取usb的power_supply,实际上就是chip->usb_psy@pm8921-charger.c
0 S( @. p# i: a9 K$ P USB_CHG_STATE_WAIT_FOR_DCD //Waiting for Data pins contact.
6 n8 E5 }* i% n; b$ ?* o 然后多次(MSM_CHG_DCD_MAX_RETRIES=6)检测USB状态,启动queue_delayed_work(motg->wq,( i- ~0 C- @5 r5 J6 V. _: z
&motg->chg_work, delay); //motg->chg_work=msm_chg_detect_work' L0 q% y, Z p" l4 E
USB_CHG_STATE_DETECTED //最后USB charge类型检测完毕
I9 b7 m7 ~( K) I: \ e. 启动queue_work(motg->wq, &motg->sm_work); //motg->sm_work=msm_otg_sm_work! X, F' n; j* T+ `5 g. a/ y! @2 g3 M
f. 由于motg->chg_state==USB_CHG_STATE_DETECTED,
% h9 _& Y) p2 `( J) x motg->chg_type==USB_DCP_CHARGER -->msm_otg_notify_charger(motg,IDEV_CHG_MAX);//IDEV_CHG_MAX=1500
, o4 ^. i# O6 @% r2. 发送uevent到用户层/ V% i" {7 `* I" P7 a
a. msm_otg_notify_charger@kernel/drivers/usb/otg/msm_otg.c
$ }- o6 x) G/ b# D$ Y 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_BATTERY1 i# p0 m2 Y' ?2 U' b
c. -->power_supply_set_supply_type@power_supply_core.c // set type of the power supply
! s0 t3 C7 W+ S/ y n) h d. -->psy->set_property(psy, POWER_SUPPLY_PROP_TYPE,&ret);
8 [) K& I! e5 J$ G ?! q5 C 那么在用usb_psy.get_property和dc_psy.get_property
7 v( f$ X$ |% L(在函数中pm8921_charger_probe)读取property时: Y( O1 }9 H9 W/ `
如果是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都被归纳成USB0 G- P7 n5 V7 F3 K( z2 Y
charger
$ C q, x- x4 S6 M0 f 如果是AC type,则在pm_power_get_property_mains读取POWER_SUPPLY_PROP_ONLINE的值,只有POWER_SUPPLY_TYPE_USB_DCP为AC
, D/ i8 C' d3 o$ |7 x9 hcharger.& }# v' b; s0 o4 c5 r% H
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.c6 \' z( D9 ^" r- ?. o$ g) i8 s9 u
f. -->pm8921_set_usb_power_supply_type(val->intval)@pm8921-charger.c
3 R' I9 v# o. ]$ Y' Y% t+ b -->power_supply_changed(&the_chip->usb_psy);
$ I* }* x9 s: \1 X% a# g -->power_supply_changed(&the_chip->dc_psy);2 N- p7 ~0 ?0 s& S
g. power_supply_changed@pm8921-charger.c , 就会马上发送uevent给user. v: _; _0 l/ i
space,然后user space通过sysfs得到USB
+ Q t' A& ^+ s9 z4 Ttype变化后的信息,参考用户空间的分析
3 u4 |% y% ^. t, ]% s0 { ?* v& n0 `3 A E1 u0 T
二、硬件分析9 ?( e0 n7 A4 p% p
9 M7 w, }( c. R& x5 B
主要是通过特殊设计的电路,检测不同的pin的状态,从而确定是何种类型的Charger. 更details的内容省略。
6 Y* H* C/ f+ U0 A$ W/ m' q7 g
- F" |+ @, P# D O _; {
* ` K- T0 I. h% S1 x; l
+ {: p& j) k" X. G5 k |
|