|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
USB port 如何识别不同的Charger类型7 e- j" @3 }" G' l. _4 i
2013年10月03日 ⁄ 综合 ⁄ 共 8924字 ⁄ 字号 [url=]小[/url] [url=]中[/url] [url=]大[/url] ⁄ 评论关闭& q) W0 F) T% [9 M9 u; Y* c
5 @4 R u7 |0 M, y4 j% V
一,软件分析1. USB charger types & Power supply types" k7 h6 s s4 }. F1 g; F# m5 }$ q; I
USB_INVALID_CHARGER Invalid USB charger.
% G& }2 X4 ]; H' P3 a9 xUSB_SDP_CHARGER Standard downstream port. Refers to a downstream port on USB2.0 compliant host/hub.
7 o8 p6 m$ C' Z2 N( L. C7 @USB_DCP_CHARGER Dedicated charger port (AC charger/ Wall charger).. Y& J3 c4 W* V) |4 r2 l0 p
USB_CDP_CHARGER Charging downstream port. Enumeration can happen and IDEV_CHG_MAX can be drawn irrespective of USB state.
0 F. |! G7 V9 P% O0 BUSB_ACA_A_CHARGER 4 K& ~1 U( k; E1 ^+ i$ Y+ H
B-device is connected on accessory port with charger connected on charging port. This configuration allows charging in host mode.0 Z. ^8 Q; T# Q* T+ b
USB_ACA_B_CHARGER No device (or A-device without VBUS) is connected on accessory port with charger connected on charging port.) i- V8 J+ o4 ?& s( Z& S- K
USB_ACA_C_CHARGER A-device (with VBUS) is connected on accessory port with charger connected on charging port.; M' [7 C% v5 f
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 accessory0 B7 N3 ?4 A1 z% L4 B# `+ f V
ports.
& P8 e6 _) B3 h, _USB_PROPRIETARY_CHARGER A proprietary charger pull DP and DM to specific voltages between 2.0-3.3v for identification.6 x# x1 q- F( B* g1 a+ O0 G
7 \6 l9 H6 `# @; }6 k; bPOWER_SUPPLY_TYPE_USB,
0 N& l7 H7 ~+ G9 R6 T! b. v/* Standard Downstream Port */
. r q" p+ h9 R' ~, j+ TPOWER_SUPPLY_TYPE_USB_DCP, /* Dedicated Charging Port */+ c: a6 A2 s6 e
POWER_SUPPLY_TYPE_USB_CDP, /* Charging Downstream Port */7 }% N* q% p/ s D3 K. c7 S7 b; b
POWER_SUPPLY_TYPE_USB_ACA, /* Accessory Charger Adapters */. D2 B0 E, u- C4 y& e; I
POWER_SUPPLY_TYPE_BMS,
+ C& p$ z$ Q" f& f& L8 I6 i6 Q/* Battery Monitor System */
9 h1 t' n! Q' _6 F' a9 p) b & h1 Z( w) ?' n, ]# M# p% j6 n7 [; F
2. How to classify or identify charger?
6 \3 y, v4 S; B# Y7 b8 t * x" y( `2 l0 `9 s, |) f4 {
USB_SDP_CHARGER
" l1 {( f* U# E7 B3 X3 M* \ | POWER_SUPPLY_TYPE_USB
$ ?$ L" V: K2 |! B6 C | USB Charger | USB_CDP_CHARGER
6 P } o* | l& m4 a) b: z | POWER_SUPPLY_TYPE_USB_CDP5 S8 |4 }# Q% J
| USB_ACA_DOCK_CHARGER
; s/ P# L" ^0 r2 k | POWER_SUPPLY_TYPE_USB_ACA | USB_ACA_A_CHARGER8 c( m3 {$ s+ R' @1 o. H
| USB_ACA_B_CHARGER
& a9 E' B p/ V1 G' M/ x: j | USB_ACA_C_CHARGER
6 m8 F9 |( y9 W, T0 O | USB_DCP_CHARGER" t/ g- O& ~% K0 j
| POWER_SUPPLY_TYPE_USB_DCP | AC Charger | USB_PROPRIETARY_CHARGER
9 b% o4 P1 [! q \ |
) |: S0 Z: \0 _As for the DMS, refer to bold font items, so it is USB charger.. b8 s. R4 D: j3 q8 J& G B5 K* J
! ~& g7 E! d6 |0 M$ a/ v3. Analysis about source codes( `! z3 i+ M2 Q( a& ]
*******************************************************************/ B2 P0 P) [ ?. ~5 z" r
###用户空间的分析如下:3 Y) B0 B# N. B! Z k- Q
1. 检查 /sys/class/power_supply/pm8921-dc/online和- t1 o- [2 v+ A+ k) `
/sys/class/power_supply/usb/online 的值,可以知道是何充电器类型- z7 _4 l, z# N7 k" t$ y) V: i
@frameworks/base/services/jni/com_android_server_batteryservice.cpp中有
; O) m3 e1 m5 V+ |' m: v int register_android_server_BatteryService(JNIEnv* env) 1 \8 A f N: s2 N% w
{% n- ~% C1 f/ E* P9 H! [
if (strcmp(buf, "Mains") == 0) { ///sys/class/power_supply/pm8921-dc/type == Mains5 ^. ?/ m; e: k. z
snprintf(path, sizeof(path), "%s/%s/online", POWER_SUPPLY_PATH, name);) k8 e. H Q1 n# g$ u! U: b9 v
if (access(path, R_OK) == 0)& N, d% \0 V. F$ z
gPaths.acOnlinePath = strdup(path);2 q% l: V" l! S$ H7 E, I
} L" m9 H! t/ B9 U3 C- S0 P
}
$ }, Y" K0 i9 h$ i: j+ }/ c 如果/sys/class/power_supply/pm8921-dc/online==1,则插入的充电器是wall* H( V1 z+ x) h+ o6 L
charger
2 [' ~' M" W- J' `& C, e /sys/class/power_supply/usb/online==1, ( L, U. z: `2 c
则插入的充电器是usb charger
q' U" @+ G; k) y 调试路径:/sys/kernel/debug/msm_otg; t! H8 H$ w; C7 t
2. 分析frameworks/base/services/jni/com_android_server_batteryservice.cpp
# j |* f! U1 P$ M9 c a.函数register_android_server_BatteryService将为被frameworks/base/services/jni/onload.cpp中的JNI_OnLoad调用,用于关联java和C++之间的变量
: d8 U& m7 b; H* u% ^ b.jclass clazz = env->FindClass("com/android/server/BatteryService"); //根据java的路径找到batteryservice.java对应的jclass
( N& o- v4 u) e) ^2 U6 P/ v gFieldIds.mAcOnline = env->GetFieldID(clazz, "mAcOnline", "Z");
' c8 o0 n2 g' u2 p7 o$ I; i u gFieldIds.mUsbOnline = env->GetFieldID(clazz, "mUsbOnline", "Z"); //用于关联batteryservice.java中变量private% b# @# H) z& u# T* G$ I% Y
boolean mAcOnline和gFieldIds.mAcOnline) R) m$ P2 S0 V: K4 \
c. android_server_BatteryService_update
5 f* X$ a$ `. [1 l* R8 D static JNINativeMethod sMethods[] = { K" m1 u5 m: c5 ?3 V
/* name, signature, funcPtr */! _" k# \* _" `( ?" `+ u _# D6 b
{"native_update", "()V", (void*)android_server_BatteryService_update},% y( v8 Z/ a" e! J4 J
};4 T+ A* C1 Q( F) B$ [
关联到native_update@frameworks/base/services/java/com/android/server/batteryservice.java7 [8 c4 o4 e, H% y& P
3. 分析frameworks/base/services/java/com/android/server/batteryservice.java( F/ F5 `, X" R. K1 X4 K7 w
a. mPowerSupplyObserver.startObserving("SUBSYSTEM=power_supply"); //注册监听该uevent
. Y ? X/ i4 G1 J' y b. private UEventObserver mPowerSupplyObserver = new UEventObserver() {
- x# |- |6 ~6 J public void onUEvent(UEventObserver.UEvent event) { //如果就收到来自kernel的uevent,触发该函数
; G2 F6 r% Z" H8 I3 t- ? update(); //-->native_update();和processValues();
7 m( E0 }* m. I5 H* o2 v& V q) Z- o }! H' o8 D2 F# N$ c* f
};
, d! v5 c6 w; K. V3 F' }/ W c. native_update函数会通过JNI调用得到更新的mAcOnline和mUsbOnline值
% K1 ^$ f' L: `! X. W8 y6 [2 G d. processValues会根据mAcOnline和mUsbOnline值对mPlugType赋值. U$ `4 ]: r# Q4 l, i8 E7 [5 }& E
if (mAcOnline) {( I8 T' @/ h0 a" v; m: k
mPlugType = BatteryManager.BATTERY_PLUGGED_AC;( q5 S' _5 m. b) q8 v( L# X
} else if (mUsbOnline) {
# B, ?5 X( _8 K$ o% ^& o. u, _4 T mPlugType = BatteryManager.BATTERY_PLUGGED_USB;
0 h' t4 b% d9 [& @0 ` } else {8 i4 I* C% C! V( j7 l
mPlugType = BATTERY_PLUGGED_NONE;
5 H: t4 @! m8 |- e0 f+ _. }3 s9 h }& [- w1 D0 _$ B' p+ w
e. sendIntent函数会准备Intent并且broadcast这个Intent+ n$ M K: s6 {& Q9 l
Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED); //public static final String ACTION_BATTERY_CHANGED = "android.intent.action.BATTERY_CHANGED";@batteryservice.java0 r/ i! y: ]; S& L0 }/ P( d
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
! u2 u+ \* b0 t8 c | Intent.FLAG_RECEIVER_REPLACE_PENDING); J: P6 z1 {: R o9 m# j
% f, u: M( }0 g! @$ [7 H1 R
intent.putExtra(BatteryManager.EXTRA_PLUGGED, mPlugType);% c" [: O$ R% K0 f
ActivityManagerNative.broadcastStickyIntent(intent, null);
% U. _4 ?: R. p( B! W4. 分析vendor/sEMC/packages/apps/debugmenu/src/com/sonyericsson/debugmenu/battery.java0 _. q* q& z8 v* o6 J
a. 接收intent
1 `. N J% t% W private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {! e, p9 f; N* G/ @ R
@Override
q9 D$ D* i$ j9 z( k4 _% s# m public void onReceive(Context arg0, Intent intent) {* }6 O( W# i6 @7 {% ]8 k
if (intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) {
0 r* \7 h& @9 W: N mPowerInformation.parseIntent(intent);
4 [* x+ q, y) |% ^ updateViews();' Y* h! o2 @ T9 E" @/ s
}
# N+ E. P* O. [0 ^3 f5 T }2 |# |/ W6 g% v3 F( r
};0 V: X% ?9 ?# F# a
public void registerBroadcastReceivers() {! |! L: R8 N: O( L3 y- ?
IntentFilter mIntentFilter;1 ~( O# L6 A: H; g& g
mIntentFilter = new IntentFilter();
% j/ \, h# w5 \, G3 D" ^! O! l7 H, G mIntentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); //只接收Intent.ACTION_BATTERY_CHANGED的intent7 v9 @$ @4 U% X3 A& E/ t$ Y
// Register battery receiver.3 V! ?. N5 X8 r
registerReceiver(mBatteryInfoReceiver, mIntentFilter);
2 k0 W+ q! T3 y# y }
( p* t/ R" p4 s2 N8 s b. parseIntent 得到最新的"plugged"值赋给mPlugged
# ?- \5 a& O8 z3 V+ @ @ c. updateViews 更新charger类型显示
: I$ e5 k2 T; \# q# W: q###内核空间6 L4 k& [5 N- X2 ^- [: m
1. 插入充电器触发的过程@kernel/drivers/usb/otg/msm_otg.c
% B) P1 C. [. h6 R) l0 T. {. d a. CONFIG_PM_RUNTIME 定义 @kernel/arch/ARM/configs/viskan_huashan_defconfig0 I3 ^; l7 f! j. H! H4 l
b.msm_otg_runtime_resume-->msm_otg_resume-->??-->msm_otg_sm_work; M9 ?0 q+ n0 D1 v* z
c.msm_otg_sm_work,先进入OTG_STATE_UNDEFINED case,然后进入OTG_STATE_B_IDLE
+ D4 z9 v+ G& K- _* b' @, ^& Mcase-->motg->chg_state=USB_CHG_STATE_UNDEFINED-->启动msm_chg_detect_work
e8 O Z: w/ D( R6 Y; R d.msm_chg_detect_work 该函数主要完成USB charger类型的识别
p! i8 h2 f# o% h& B1 ~& x+ w USB_CHG_STATE_UNDEFINED //其中psy = power_supply_get_by_name("usb");很关键,表明只是获取usb的power_supply,实际上就是chip->usb_psy@pm8921-charger.c
5 R. i! G: E& U6 s USB_CHG_STATE_WAIT_FOR_DCD //Waiting for Data pins contact.5 o# o& _: b4 {
然后多次(MSM_CHG_DCD_MAX_RETRIES=6)检测USB状态,启动queue_delayed_work(motg->wq,1 C8 r. e$ F8 t: l8 Y! Q9 v
&motg->chg_work, delay); //motg->chg_work=msm_chg_detect_work
, n0 w4 k D/ m3 ? USB_CHG_STATE_DETECTED //最后USB charge类型检测完毕
, d- _$ B9 g/ w0 N e. 启动queue_work(motg->wq, &motg->sm_work); //motg->sm_work=msm_otg_sm_work4 |3 x. o7 `, H" C) y
f. 由于motg->chg_state==USB_CHG_STATE_DETECTED,
& X/ E4 h$ ?% N4 P& R motg->chg_type==USB_DCP_CHARGER -->msm_otg_notify_charger(motg,IDEV_CHG_MAX);//IDEV_CHG_MAX=15002 J' v% _, p& @3 Z
2. 发送uevent到用户层
/ W+ u6 ~3 v! u3 E8 d a. msm_otg_notify_charger@kernel/drivers/usb/otg/msm_otg.c
$ R* }! o, R4 _& R: j/ P, x) x 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. V' D5 t# b& }6 [
c. -->power_supply_set_supply_type@power_supply_core.c // set type of the power supply
; t: F! S8 P l' ?% ?7 `5 [8 u/ W d. -->psy->set_property(psy, POWER_SUPPLY_PROP_TYPE,&ret);
/ X- f% k$ {: R$ u! a, n* e 那么在用usb_psy.get_property和dc_psy.get_property
3 B" D m6 r( r% t" E( k9 {(在函数中pm8921_charger_probe)读取property时
1 R7 x8 D, @% j" _' 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; q- ^0 v4 z" I# {- P, t
charger
8 Q0 ~0 h+ |2 o2 n% K4 }+ a: s5 a 如果是AC type,则在pm_power_get_property_mains读取POWER_SUPPLY_PROP_ONLINE的值,只有POWER_SUPPLY_TYPE_USB_DCP为AC8 e; v3 ]0 v3 @4 Z n: F
charger.
( G* m! v& o' A; T. I! 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' A5 T9 [# ?8 j/ t) z* g
f. -->pm8921_set_usb_power_supply_type(val->intval)@pm8921-charger.c6 O* Z# g& R0 \+ U5 K& ~
-->power_supply_changed(&the_chip->usb_psy);7 A0 ]: ?; o$ Q/ o/ }
-->power_supply_changed(&the_chip->dc_psy);
5 B+ z& `( O0 f g. power_supply_changed@pm8921-charger.c , 就会马上发送uevent给user
' | E1 R' t3 _7 P! O ?& Mspace,然后user space通过sysfs得到USB: |7 m/ ]7 {$ q! q( l
type变化后的信息,参考用户空间的分析4 @0 H% a) {! V! I" ~$ j
R9 ^$ X1 P! x/ |
二、硬件分析! v8 V, s: J/ y
![]()
+ d8 Z% j& {6 f主要是通过特殊设计的电路,检测不同的pin的状态,从而确定是何种类型的Charger. 更details的内容省略。
! T- ~- p% b& u) |& J1 k
8 x. K5 S9 o* c' ?
. h- G1 a, }* k+ L" j1 o$ ?8 J2 b& \5 G
|
|