|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
USB port 如何识别不同的Charger类型& S5 y6 F9 U' r+ V$ }
2013年10月03日 ⁄ 综合 ⁄ 共 8924字 ⁄ 字号 [url=]小[/url] [url=]中[/url] [url=]大[/url] ⁄ 评论关闭
( {+ Q8 J& b4 u
6 w1 C# W: Q. Q5 H, s# E8 u4 h一,软件分析1. USB charger types & Power supply types
0 I* k0 D- Y* cUSB_INVALID_CHARGER Invalid USB charger.
* B$ Y' L3 a6 w" QUSB_SDP_CHARGER Standard downstream port. Refers to a downstream port on USB2.0 compliant host/hub.4 H9 `. m- C' s+ z6 j( c# o) V1 k
USB_DCP_CHARGER Dedicated charger port (AC charger/ Wall charger).0 S1 ]8 j: C/ _8 S* {; n9 g
USB_CDP_CHARGER Charging downstream port. Enumeration can happen and IDEV_CHG_MAX can be drawn irrespective of USB state.0 Y# I+ p6 a7 s F0 y
USB_ACA_A_CHARGER
3 g% x- G+ {) }' NB-device is connected on accessory port with charger connected on charging port. This configuration allows charging in host mode.4 `% M; {% [- k7 t0 f& G
USB_ACA_B_CHARGER No device (or A-device without VBUS) is connected on accessory port with charger connected on charging port.
( h" g/ L) w" N( T Y5 \1 P; x4 yUSB_ACA_C_CHARGER A-device (with VBUS) is connected on accessory port with charger connected on charging port.9 q6 G9 x7 R, d# @
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
" n, n. _- W/ Uports.- D" B; P& i' m( y) `0 {
USB_PROPRIETARY_CHARGER A proprietary charger pull DP and DM to specific voltages between 2.0-3.3v for identification.+ ^9 H; i0 S& M- y
8 o& b8 W4 F2 q; n7 o& G$ C
POWER_SUPPLY_TYPE_USB, 2 U: x7 E4 X- [, X" P
/* Standard Downstream Port */7 W/ B( R. _) N( @% T" Y, U( `2 O
POWER_SUPPLY_TYPE_USB_DCP, /* Dedicated Charging Port */
3 z$ B2 g E" r8 e7 WPOWER_SUPPLY_TYPE_USB_CDP, /* Charging Downstream Port */
8 H! J% M# b; E8 u1 P5 dPOWER_SUPPLY_TYPE_USB_ACA, /* Accessory Charger Adapters */
/ x9 K* r3 n6 pPOWER_SUPPLY_TYPE_BMS, ! y; A% }5 n- a5 {: e2 E
/* Battery Monitor System */6 @% a! B: _+ J9 T3 m& H) @; e5 M5 d* c
+ P. O! j) {+ c; u7 u }4 W2. How to classify or identify charger?% K& J) [& x9 I: |. ?
0 d' h3 ?$ u! E, b- y' d; S
USB_SDP_CHARGER+ ~" `: n9 X% s; w
| POWER_SUPPLY_TYPE_USB C) G+ l; _' _+ C0 ?* a( B/ C
| USB Charger | USB_CDP_CHARGER5 g( Z( Z' V2 Z
| POWER_SUPPLY_TYPE_USB_CDP
; X8 [ @) q# G5 H | USB_ACA_DOCK_CHARGER" e. L) b- d- b( w7 X
| POWER_SUPPLY_TYPE_USB_ACA | USB_ACA_A_CHARGER6 H) C0 n+ `) D! S9 x }
| USB_ACA_B_CHARGER# U( X$ f: {0 s/ F
| USB_ACA_C_CHARGER
. T; P* M, g5 }" j' x4 n | USB_DCP_CHARGER: x ~# A1 b2 n* Z
| POWER_SUPPLY_TYPE_USB_DCP | AC Charger | USB_PROPRIETARY_CHARGER
) M4 y9 a/ L0 t' n/ Q |
, a( O. {9 V0 gAs for the DMS, refer to bold font items, so it is USB charger.
) Y+ q2 |8 m" {$ g4 E# [& c' N & N, C/ _+ ?3 ~- v0 N. ^
3. Analysis about source codes
. b! B/ a. S& Y' Q! E2 q- c$ ]*******************************************************************
- ~- ~$ m! T! Q, R###用户空间的分析如下:
% q( z* ?% B2 \# h% a( y( d1 X1. 检查 /sys/class/power_supply/pm8921-dc/online和
1 i( r$ J h+ Y# L( ~/sys/class/power_supply/usb/online 的值,可以知道是何充电器类型) m5 T, A7 r2 z( }4 w+ |2 U7 @
@frameworks/base/services/jni/com_android_server_batteryservice.cpp中有
" c# o' G( n2 ]6 k3 p int register_android_server_BatteryService(JNIEnv* env)
, g% I# M( Q! k i {
$ C: c4 x8 a0 N- H( a7 O if (strcmp(buf, "Mains") == 0) { ///sys/class/power_supply/pm8921-dc/type == Mains
' D5 _* {/ V1 j* z7 u4 B snprintf(path, sizeof(path), "%s/%s/online", POWER_SUPPLY_PATH, name);& q( d8 i/ q4 `. d& R% y' V
if (access(path, R_OK) == 0)- }( x1 |9 @/ u" N
gPaths.acOnlinePath = strdup(path);
% U* h$ z6 G4 v. @ }/ R; E$ C0 P f, Z. b: M- L: S
}
) M8 {/ s5 R) ` 如果/sys/class/power_supply/pm8921-dc/online==1,则插入的充电器是wall
H( k0 V/ N2 o. tcharger
$ N% L; ^; f0 m4 X& P: \( | /sys/class/power_supply/usb/online==1, 6 |5 P# K; U2 u' [% U: U! G/ L
则插入的充电器是usb charger% I8 e s5 s* I! A$ j7 w8 B9 @, @! D. h
调试路径:/sys/kernel/debug/msm_otg3 ]0 R$ D+ b$ t% @
2. 分析frameworks/base/services/jni/com_android_server_batteryservice.cpp3 U. v: s2 n! A: m/ C
a.函数register_android_server_BatteryService将为被frameworks/base/services/jni/onload.cpp中的JNI_OnLoad调用,用于关联java和C++之间的变量! u) s% S, N6 }
b.jclass clazz = env->FindClass("com/android/server/BatteryService"); //根据java的路径找到batteryservice.java对应的jclass
! ^4 b0 q7 v% O! k2 p gFieldIds.mAcOnline = env->GetFieldID(clazz, "mAcOnline", "Z");
# w8 c8 t. R9 Z( e gFieldIds.mUsbOnline = env->GetFieldID(clazz, "mUsbOnline", "Z"); //用于关联batteryservice.java中变量private8 Y3 B% }0 Z, j2 M
boolean mAcOnline和gFieldIds.mAcOnline
4 ~+ u. p9 g+ o) i# A! u c. android_server_BatteryService_update* z7 a/ m2 l$ W2 Z
static JNINativeMethod sMethods[] = {
6 n& B# _* q' U* {8 n. l, ] /* name, signature, funcPtr */
/ P) f& q0 I# ^5 U( I" M j7 G {"native_update", "()V", (void*)android_server_BatteryService_update},- A1 K8 [9 u6 T
};8 Z. L' ~- M$ {7 n0 |; J
关联到native_update@frameworks/base/services/java/com/android/server/batteryservice.java
1 p2 N7 @ q" n4 u6 N6 z$ {3. 分析frameworks/base/services/java/com/android/server/batteryservice.java
. l- W' M+ {' {8 R1 C a. mPowerSupplyObserver.startObserving("SUBSYSTEM=power_supply"); //注册监听该uevent1 n) \6 }1 G2 \1 i9 R7 L @' m8 e
b. private UEventObserver mPowerSupplyObserver = new UEventObserver() {
# ^+ U$ K8 X( E7 z public void onUEvent(UEventObserver.UEvent event) { //如果就收到来自kernel的uevent,触发该函数+ Q0 L" E0 G! c. M
update(); //-->native_update();和processValues();8 ~( Z3 ?8 t$ ?9 |. |$ g
}
W# p* g+ u4 O) a8 R: f/ ~ };
6 W V8 O; w: D; X" M! ]" F c. native_update函数会通过JNI调用得到更新的mAcOnline和mUsbOnline值
& O" g( @* D: {5 z" F d. processValues会根据mAcOnline和mUsbOnline值对mPlugType赋值
' ]& q/ \0 Y3 f% a if (mAcOnline) {
/ x5 A! @- T& l' v4 F mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
# t1 J* G c; W. K- I6 o } else if (mUsbOnline) {
3 p5 I2 M) {4 D y: F mPlugType = BatteryManager.BATTERY_PLUGGED_USB;
3 ]; O' L- \# L E, u1 l } else {
6 |4 d: c7 d* i3 S8 S% a& a; o mPlugType = BATTERY_PLUGGED_NONE;+ v" _# ^- ~6 k
}
- c/ B+ c2 P4 f% D- [1 Y* B% A- ^& _7 a e. sendIntent函数会准备Intent并且broadcast这个Intent
/ C9 x% A& z1 v! x- O Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED); //public static final String ACTION_BATTERY_CHANGED = "android.intent.action.BATTERY_CHANGED";@batteryservice.java
6 N* H S% E1 A+ A; q! L) R! _9 J intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
1 Z* w& p" ?& s( ]6 q1 d | Intent.FLAG_RECEIVER_REPLACE_PENDING);. L- U# T0 K6 t: Z( o D3 w
9 u% T! e. D1 H0 N/ ^, o
intent.putExtra(BatteryManager.EXTRA_PLUGGED, mPlugType);. G6 G" ^+ }0 O' I/ u6 c/ e: a
ActivityManagerNative.broadcastStickyIntent(intent, null);
5 o, T$ \. T. Y; u( t f- C! q4. 分析vendor/sEMC/packages/apps/debugmenu/src/com/sonyericsson/debugmenu/battery.java: P9 T4 i7 X9 B7 d$ X+ I: z$ a: a8 V
a. 接收intent
3 `$ o9 S+ {! C- ]3 G) E" c" S private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {3 s5 I* M& N# j7 r* {$ F
@Override7 q" e$ j7 e& F) b0 K! [# ~6 S4 g
public void onReceive(Context arg0, Intent intent) {+ m" m& Z/ h) b: R! j" u
if (intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) {
# h7 A8 ]* t5 e+ _$ L- t" H3 l4 I mPowerInformation.parseIntent(intent);
. D. l9 E+ c2 F, K3 | Q( k updateViews();
7 }2 z# t' p$ v0 k }/ v& ^, |& P* L8 y
}3 H* m( c- b7 g* m) |! R$ c: s
};8 I- e) g+ L. u2 |' F
public void registerBroadcastReceivers() {
! }6 V- V* w$ ^* @ IntentFilter mIntentFilter;" X: Z" w! X( o8 S
mIntentFilter = new IntentFilter();
8 }% c* _9 H+ k8 L* g% d mIntentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); //只接收Intent.ACTION_BATTERY_CHANGED的intent+ ^6 x, Y0 {$ z! v8 B8 X
// Register battery receiver.
7 ^2 c" P2 D+ P registerReceiver(mBatteryInfoReceiver, mIntentFilter);2 x. z) `9 J/ X) z" M3 ~/ ~
}
( U# v5 C8 l1 O# G9 U b. parseIntent 得到最新的"plugged"值赋给mPlugged0 E# }5 \7 S( t+ o8 t
c. updateViews 更新charger类型显示
3 F5 W! w. ?) A###内核空间
) x5 j+ G5 o+ Z+ j* v* k9 j* R1. 插入充电器触发的过程@kernel/drivers/usb/otg/msm_otg.c
8 v( q; W' \2 [ a. CONFIG_PM_RUNTIME 定义 @kernel/arch/ARM/configs/viskan_huashan_defconfig5 n' r& v. z# n1 X+ c
b.msm_otg_runtime_resume-->msm_otg_resume-->??-->msm_otg_sm_work
* k, U7 y6 |0 |( u c.msm_otg_sm_work,先进入OTG_STATE_UNDEFINED case,然后进入OTG_STATE_B_IDLE: s+ t+ u! G0 C4 X& C7 W# ?; A
case-->motg->chg_state=USB_CHG_STATE_UNDEFINED-->启动msm_chg_detect_work
3 t/ B6 r" x+ @/ j8 h, _ d.msm_chg_detect_work 该函数主要完成USB charger类型的识别
$ s8 M0 A( O& [' s' D6 r USB_CHG_STATE_UNDEFINED //其中psy = power_supply_get_by_name("usb");很关键,表明只是获取usb的power_supply,实际上就是chip->usb_psy@pm8921-charger.c
) q7 ]" q% @5 Q USB_CHG_STATE_WAIT_FOR_DCD //Waiting for Data pins contact.
% E- `. A+ H1 o: i6 ? 然后多次(MSM_CHG_DCD_MAX_RETRIES=6)检测USB状态,启动queue_delayed_work(motg->wq,
; b8 D# k, P8 [& f* |&motg->chg_work, delay); //motg->chg_work=msm_chg_detect_work
' g6 w; V' I( _' l5 p4 F% | USB_CHG_STATE_DETECTED //最后USB charge类型检测完毕9 q, E: R$ t! e% [& @. d
e. 启动queue_work(motg->wq, &motg->sm_work); //motg->sm_work=msm_otg_sm_work; r" p0 o' R5 ?% b
f. 由于motg->chg_state==USB_CHG_STATE_DETECTED,( R( \ f$ i3 w4 E8 U4 L
motg->chg_type==USB_DCP_CHARGER -->msm_otg_notify_charger(motg,IDEV_CHG_MAX);//IDEV_CHG_MAX=1500
+ N9 d- j; ]' J6 E h N2. 发送uevent到用户层
5 s6 Y* U& x u6 l) X a. msm_otg_notify_charger@kernel/drivers/usb/otg/msm_otg.c! J0 Z: `6 }3 A2 @0 O# z6 X( N! H; 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
7 X2 F ^( c Y( h2 r; Y c. -->power_supply_set_supply_type@power_supply_core.c // set type of the power supply
$ I: X& U9 Q- [ d. -->psy->set_property(psy, POWER_SUPPLY_PROP_TYPE,&ret);$ o; X$ W" o+ }# ~
那么在用usb_psy.get_property和dc_psy.get_property
! ?0 P) {' ]1 J1 s/ D% F3 g(在函数中pm8921_charger_probe)读取property时4 V+ [8 {1 y E# }- H; f: Q
如果是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
' K6 s5 N3 y) D% V4 z, lcharger! U2 t5 Q9 v1 U/ ^3 i
如果是AC type,则在pm_power_get_property_mains读取POWER_SUPPLY_PROP_ONLINE的值,只有POWER_SUPPLY_TYPE_USB_DCP为AC9 F! Q5 `% c6 _3 p
charger.5 z) b: J" C I
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/ Z8 b+ i5 ]+ p D' L! }
f. -->pm8921_set_usb_power_supply_type(val->intval)@pm8921-charger.c
: {3 z( g" Q( V/ \* n: i# h -->power_supply_changed(&the_chip->usb_psy);1 L: m% `9 ]1 y2 G, v
-->power_supply_changed(&the_chip->dc_psy);
6 k# S! ~. f* A g. power_supply_changed@pm8921-charger.c , 就会马上发送uevent给user
& a! f/ E( q0 }+ r5 W- t! }space,然后user space通过sysfs得到USB
7 X( p' O D: ctype变化后的信息,参考用户空间的分析
3 C0 t. ~- J) }. D% T5 a% W' y
* r: Q8 o0 @$ V二、硬件分析 t# W& p- h- f% |
![]()
, W& f" j( ~: x- D c, C" |主要是通过特殊设计的电路,检测不同的pin的状态,从而确定是何种类型的Charger. 更details的内容省略。
& r; b3 } U- B& Q2 |# O& D: v/ j3 z* A' ?
. `9 _; m: N+ E& k, X
w, o6 g$ U! t5 i& k- M- } |
|