|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
USB port 如何识别不同的Charger类型9 H, U1 g6 k8 v! f" d
2013年10月03日 ⁄ 综合 ⁄ 共 8924字 ⁄ 字号 [url=]小[/url] [url=]中[/url] [url=]大[/url] ⁄ 评论关闭* o3 ^% G3 |- a' o1 Y$ q$ M
! a. L9 ^% l" P1 g. N6 ^一,软件分析1. USB charger types & Power supply types
/ {) d& h; w8 I1 Q7 SUSB_INVALID_CHARGER Invalid USB charger.& b z/ U5 c9 l1 p$ E" a" R$ Q* Y
USB_SDP_CHARGER Standard downstream port. Refers to a downstream port on USB2.0 compliant host/hub.( K6 ~/ M0 p7 B: p
USB_DCP_CHARGER Dedicated charger port (AC charger/ Wall charger).
( F" ]; P$ H/ S* Y$ mUSB_CDP_CHARGER Charging downstream port. Enumeration can happen and IDEV_CHG_MAX can be drawn irrespective of USB state.% ^& f) Z2 v8 j& j+ Y J+ v
USB_ACA_A_CHARGER
& l3 v! p' p" L u3 n+ f( E# l, R. X. QB-device is connected on accessory port with charger connected on charging port. This configuration allows charging in host mode.
$ \/ ~# m* p7 Y; w; AUSB_ACA_B_CHARGER No device (or A-device without VBUS) is connected on accessory port with charger connected on charging port.
2 |# a6 H4 L( ~USB_ACA_C_CHARGER A-device (with VBUS) is connected on accessory port with charger connected on charging port.
, O' a$ }+ A. g) a5 \3 aUSB_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& j8 [. `& m* Q! f
ports.9 v4 T1 l7 m, R
USB_PROPRIETARY_CHARGER A proprietary charger pull DP and DM to specific voltages between 2.0-3.3v for identification.
* _8 q5 D; W( X t
1 t7 U B0 n/ `3 P* [POWER_SUPPLY_TYPE_USB, ; x. x- Z; E, k2 M( n0 b: y
/* Standard Downstream Port */: n: E( a K7 @
POWER_SUPPLY_TYPE_USB_DCP, /* Dedicated Charging Port */* ~9 T2 H4 d$ H6 s" q' w
POWER_SUPPLY_TYPE_USB_CDP, /* Charging Downstream Port */
+ H( F/ v" A* ]. U8 \1 r* ~) v8 A: ]POWER_SUPPLY_TYPE_USB_ACA, /* Accessory Charger Adapters */
' E6 v' p" u) V7 H, i wPOWER_SUPPLY_TYPE_BMS,
( D3 U1 |' B* C6 V$ A( f- T" A/* Battery Monitor System */
# `5 l$ n t( Y3 W" P) j& n S
; l; C5 ~6 Z( m2. How to classify or identify charger?
# Y# `* P( m/ B& c
' f! h2 p( s7 k+ p; r2 P% i1 ]USB_SDP_CHARGER
; S* ]" u! B: A. w Z3 j4 N | POWER_SUPPLY_TYPE_USB! V8 `# k H2 o' A9 j
| USB Charger | USB_CDP_CHARGER
! c) J& O4 X' e" D | POWER_SUPPLY_TYPE_USB_CDP
) i, n1 ]/ l k+ U3 j! w! S/ f( ^/ Y8 } | USB_ACA_DOCK_CHARGER6 i3 X# E9 T& c3 k6 g
| POWER_SUPPLY_TYPE_USB_ACA | USB_ACA_A_CHARGER
" z1 J$ A* }( H. U! p$ j | USB_ACA_B_CHARGER
0 O9 O+ M- e. ~4 P4 D | USB_ACA_C_CHARGER
/ [% i, A7 D! r0 \% { | USB_DCP_CHARGER
1 K6 X. l1 V1 `* K3 T, h C* V | POWER_SUPPLY_TYPE_USB_DCP | AC Charger | USB_PROPRIETARY_CHARGER( f7 A7 m: k/ q% K% o8 E& {
|
. f/ ~9 p3 }# z1 @/ X5 {: N4 xAs for the DMS, refer to bold font items, so it is USB charger.# ^ A' Q% \0 |9 X8 d
0 a, e" w# P: s1 z9 a3. Analysis about source codes$ ^5 u6 f0 `& t* p- J7 g
*******************************************************************! { C- I' P% P% R( G+ h
###用户空间的分析如下:
5 Q7 [8 G; x8 D4 J5 |" k3 n( B1. 检查 /sys/class/power_supply/pm8921-dc/online和
) K. F, q! c$ B/ x4 d% t/sys/class/power_supply/usb/online 的值,可以知道是何充电器类型
e- H/ W2 s' T* a) I8 Q @frameworks/base/services/jni/com_android_server_batteryservice.cpp中有( d( h" F& N9 @& U, I& i ]
int register_android_server_BatteryService(JNIEnv* env)
9 p8 t) F3 l+ B5 K. q. v" g& |5 Z D {4 C, X; N' i2 F. _6 S
if (strcmp(buf, "Mains") == 0) { ///sys/class/power_supply/pm8921-dc/type == Mains
# E1 Z$ K5 p3 b( Q* Q snprintf(path, sizeof(path), "%s/%s/online", POWER_SUPPLY_PATH, name);# x. [7 l' v- {2 N* K( i
if (access(path, R_OK) == 0)4 x7 v# h$ E) {" ]. h3 A
gPaths.acOnlinePath = strdup(path);6 X4 M* }' ^2 S" E* ]* j' X
}
6 S, t6 W6 o I5 @! e }) c1 K4 b# p; n8 p0 p/ ?
如果/sys/class/power_supply/pm8921-dc/online==1,则插入的充电器是wall3 s8 P( c+ u( ?' v; F6 f$ f( d
charger
( m& r. w) d1 J* i9 z4 w, V! n0 ` h /sys/class/power_supply/usb/online==1,
2 J. |) r7 t$ I, z/ n3 G: A' {! y& p5 |则插入的充电器是usb charger1 K( k: P p$ W# ~( G# N
调试路径:/sys/kernel/debug/msm_otg
% x6 c' v8 `2 G f( ^( L2. 分析frameworks/base/services/jni/com_android_server_batteryservice.cpp
1 V: w" f. g j* U- B8 U a.函数register_android_server_BatteryService将为被frameworks/base/services/jni/onload.cpp中的JNI_OnLoad调用,用于关联java和C++之间的变量+ k6 J6 |% x u
b.jclass clazz = env->FindClass("com/android/server/BatteryService"); //根据java的路径找到batteryservice.java对应的jclass
* V8 X G4 t2 `8 L gFieldIds.mAcOnline = env->GetFieldID(clazz, "mAcOnline", "Z");
8 t' d$ R* R0 h* E" ]6 n$ {6 I gFieldIds.mUsbOnline = env->GetFieldID(clazz, "mUsbOnline", "Z"); //用于关联batteryservice.java中变量private/ ?! z2 \/ ]! T! E% _2 l8 H! o
boolean mAcOnline和gFieldIds.mAcOnline
" U( \8 k2 b _$ Y4 D c. android_server_BatteryService_update
6 H, Z) i6 Q6 y" G static JNINativeMethod sMethods[] = {
$ U+ m {+ L% s P; `' c* \0 i; | /* name, signature, funcPtr */
) E% R d7 a4 s' S; |5 J4 j- M {"native_update", "()V", (void*)android_server_BatteryService_update},
# f2 w0 S/ f& h4 y6 ~7 P( L9 w K };
$ d3 `, N! O+ W; I; _+ t4 k% ] 关联到native_update@frameworks/base/services/java/com/android/server/batteryservice.java
' c6 `( [6 j" {3. 分析frameworks/base/services/java/com/android/server/batteryservice.java* l9 S" [6 Q: L/ ]1 S' ]* f1 j
a. mPowerSupplyObserver.startObserving("SUBSYSTEM=power_supply"); //注册监听该uevent
6 l( M$ R% r6 [ b. private UEventObserver mPowerSupplyObserver = new UEventObserver() {
! i# R8 o+ r: E9 e public void onUEvent(UEventObserver.UEvent event) { //如果就收到来自kernel的uevent,触发该函数# t% d8 D- w& x2 z3 m, S- O+ N
update(); //-->native_update();和processValues();* f/ y1 z7 q* p; N! {
}& L* `5 G: |4 p2 R: X
};
0 M5 I* w! p* n* {+ Z c. native_update函数会通过JNI调用得到更新的mAcOnline和mUsbOnline值
' O B, G0 k: S2 q& [; A. l d. processValues会根据mAcOnline和mUsbOnline值对mPlugType赋值
5 N. r, e) w4 C) A6 ~& @* z if (mAcOnline) {# X- L" x) U' S$ d
mPlugType = BatteryManager.BATTERY_PLUGGED_AC;8 u3 ?! ?) {. K1 h2 a. _' C% l
} else if (mUsbOnline) {2 y% d2 Y5 B. ~* b
mPlugType = BatteryManager.BATTERY_PLUGGED_USB;: z* ~% c: e; f" n! h
} else {3 }& ^# l3 R ]) W" g% b' r: r
mPlugType = BATTERY_PLUGGED_NONE;# a) j* y# n/ o( S3 U/ {3 f: f
}
H% w% H$ b4 r- G1 r0 I. L j e. sendIntent函数会准备Intent并且broadcast这个Intent; F( s7 W' d' N
Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED); //public static final String ACTION_BATTERY_CHANGED = "android.intent.action.BATTERY_CHANGED";@batteryservice.java7 L3 H9 ~/ N& _$ G
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
- T! b3 ]. G; ~7 L4 {4 e7 w | Intent.FLAG_RECEIVER_REPLACE_PENDING);
' J5 W( f1 O4 z' v: y$ D
) v- K% @) M( h d" }. @' J8 y intent.putExtra(BatteryManager.EXTRA_PLUGGED, mPlugType);
+ o; F/ l1 P8 a9 ~) ? ActivityManagerNative.broadcastStickyIntent(intent, null);+ a) n2 N7 ]# D
4. 分析vendor/sEMC/packages/apps/debugmenu/src/com/sonyericsson/debugmenu/battery.java* g$ w. u7 z/ J7 F! }
a. 接收intent
: y$ t: m" J3 h1 x3 t( p' N private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {3 N6 v& z" W& g
@Override
. c$ G) D. q/ e8 T- w! E public void onReceive(Context arg0, Intent intent) {! ]7 P2 p# h" v+ ^, c0 w
if (intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) {0 b* P$ e2 p+ J) B6 l, v; z0 E
mPowerInformation.parseIntent(intent);
- g4 O: S: z5 d* p updateViews();$ v" W9 Q+ [% r7 r$ u8 y
}
+ S: o' p) c' ^% l }% @/ q/ w0 w1 ], C. |8 u
};
* F+ F0 K* O! C& l" [ public void registerBroadcastReceivers() {
W' z+ Z* f* |! D IntentFilter mIntentFilter;5 z( \( F. a0 @1 o& F" f* ]% j
mIntentFilter = new IntentFilter();" l) h- l; H5 g/ _6 [, ]& x
mIntentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); //只接收Intent.ACTION_BATTERY_CHANGED的intent
$ k6 h9 L! I9 ~; D // Register battery receiver.
. l& _ n6 B1 _5 s) p registerReceiver(mBatteryInfoReceiver, mIntentFilter);
. s( R, d9 h$ J" e# A* w ] }
8 o- v' V+ U3 p2 S! |$ `2 j2 _ b. parseIntent 得到最新的"plugged"值赋给mPlugged
! T3 f3 v8 ?$ m% S c. updateViews 更新charger类型显示
* s5 Q' I. k' K. q2 l###内核空间
5 k' c& C5 T" ` g1. 插入充电器触发的过程@kernel/drivers/usb/otg/msm_otg.c4 a: L0 d4 z$ R! Q* l, ]
a. CONFIG_PM_RUNTIME 定义 @kernel/arch/ARM/configs/viskan_huashan_defconfig/ q! Z5 s1 C8 k$ w1 V, h
b.msm_otg_runtime_resume-->msm_otg_resume-->??-->msm_otg_sm_work' E7 O4 z. I- f& S( u1 l' X
c.msm_otg_sm_work,先进入OTG_STATE_UNDEFINED case,然后进入OTG_STATE_B_IDLE
3 G7 X8 v* ^0 U! ?case-->motg->chg_state=USB_CHG_STATE_UNDEFINED-->启动msm_chg_detect_work5 q9 o. W& Y/ Q' U
d.msm_chg_detect_work 该函数主要完成USB charger类型的识别
2 h5 C. Y: i7 ?5 r USB_CHG_STATE_UNDEFINED //其中psy = power_supply_get_by_name("usb");很关键,表明只是获取usb的power_supply,实际上就是chip->usb_psy@pm8921-charger.c
9 l5 p7 ^7 m% M* l9 Y& E USB_CHG_STATE_WAIT_FOR_DCD //Waiting for Data pins contact.
8 ?( T3 W( [2 g+ @ 然后多次(MSM_CHG_DCD_MAX_RETRIES=6)检测USB状态,启动queue_delayed_work(motg->wq,# |" r" ?4 _. @7 F* ^
&motg->chg_work, delay); //motg->chg_work=msm_chg_detect_work
4 y" k. M( ?7 W, z a. D USB_CHG_STATE_DETECTED //最后USB charge类型检测完毕 `0 S% |/ U9 U6 o, D5 {
e. 启动queue_work(motg->wq, &motg->sm_work); //motg->sm_work=msm_otg_sm_work
; y, C: t' I0 m$ i# P f. 由于motg->chg_state==USB_CHG_STATE_DETECTED,
# @2 s1 l5 {. _2 M& m( V" l motg->chg_type==USB_DCP_CHARGER -->msm_otg_notify_charger(motg,IDEV_CHG_MAX);//IDEV_CHG_MAX=1500* r0 X/ c: M; p& a% k9 E
2. 发送uevent到用户层5 F7 v! s, V8 j; Z! @3 ]7 L7 Z
a. msm_otg_notify_charger@kernel/drivers/usb/otg/msm_otg.c% l+ j+ L6 P' y z) p2 m G- B; K3 F
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
2 Y- l" ^2 M- S" { c. -->power_supply_set_supply_type@power_supply_core.c // set type of the power supply
7 o; y" e; h. Q d. -->psy->set_property(psy, POWER_SUPPLY_PROP_TYPE,&ret);
5 J! V% N! B% j8 V5 Z( l$ I$ [, q( a 那么在用usb_psy.get_property和dc_psy.get_property: v4 e- T$ S3 h1 O1 O3 Q
(在函数中pm8921_charger_probe)读取property时" R# a/ r# Y: c" ]1 f) ?8 N$ T
如果是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
: Q {' I3 d* k3 i. \- k# {1 }charger
( i/ b" L, Y3 j- I 如果是AC type,则在pm_power_get_property_mains读取POWER_SUPPLY_PROP_ONLINE的值,只有POWER_SUPPLY_TYPE_USB_DCP为AC
1 K: Q3 u- [' D( L* u& mcharger.
4 Z4 Q- \% o" q) q6 K2 _: U 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( b8 b8 A# e6 m, d) q5 F( D
f. -->pm8921_set_usb_power_supply_type(val->intval)@pm8921-charger.c0 c( x2 B' u9 j; L& u! c
-->power_supply_changed(&the_chip->usb_psy);1 O0 t8 B# z- x6 i% H
-->power_supply_changed(&the_chip->dc_psy);# W9 k# Q2 `. U1 R
g. power_supply_changed@pm8921-charger.c , 就会马上发送uevent给user+ l" K% e: u& `2 t2 e( p8 E
space,然后user space通过sysfs得到USB0 U7 u$ h5 T* v$ r* F, t- l
type变化后的信息,参考用户空间的分析* L" r) {6 Z5 H" j( N
" G% a- K9 U6 y' ]二、硬件分析- h6 d9 n% x$ W6 v; K0 u
4 O3 I8 o6 e& _0 o) U8 } l
主要是通过特殊设计的电路,检测不同的pin的状态,从而确定是何种类型的Charger. 更details的内容省略。
; t4 O1 F0 J" r0 t: j
* P' \! L5 V4 ]5 T& |9 v
1 ^1 t& z0 @% W' @/ R0 A8 N }4 k+ n0 C
|
|