|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
USB port 如何识别不同的Charger类型6 [" [0 o! Y, {5 Z2 F, s' W
2013年10月03日 ⁄ 综合 ⁄ 共 8924字 ⁄ 字号 [url=]小[/url] [url=]中[/url] [url=]大[/url] ⁄ 评论关闭5 C- U [2 K( ~9 c- e
8 w5 D Z3 Q7 p' {/ Z& c( \/ E: P一,软件分析1. USB charger types & Power supply types
8 C$ q: |3 D( M( NUSB_INVALID_CHARGER Invalid USB charger.. @6 ]0 Z! z# C7 d0 T6 p _
USB_SDP_CHARGER Standard downstream port. Refers to a downstream port on USB2.0 compliant host/hub.
; s9 l, z0 b: y# T( J( W# [USB_DCP_CHARGER Dedicated charger port (AC charger/ Wall charger).
) Z# @; g: J. s+ |USB_CDP_CHARGER Charging downstream port. Enumeration can happen and IDEV_CHG_MAX can be drawn irrespective of USB state.
* w6 P9 z2 {' M: }5 VUSB_ACA_A_CHARGER 9 b4 o4 x7 J, R& Y% o3 D
B-device is connected on accessory port with charger connected on charging port. This configuration allows charging in host mode.
( c: g+ N! e1 \) J& Q2 C3 {USB_ACA_B_CHARGER No device (or A-device without VBUS) is connected on accessory port with charger connected on charging port.
2 _( } }9 e; [ @& o3 \3 ^! \USB_ACA_C_CHARGER A-device (with VBUS) is connected on accessory port with charger connected on charging port.
3 T/ O# z5 x) M [+ j! a) YUSB_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! m) `( G5 h% ^3 a6 y
ports.8 J7 t L% ?$ `2 q( e1 s
USB_PROPRIETARY_CHARGER A proprietary charger pull DP and DM to specific voltages between 2.0-3.3v for identification.
+ o, }& R9 C4 J" P- J1 W7 l 6 u' t$ f2 V- |9 @
POWER_SUPPLY_TYPE_USB,
8 w; S; D" \- c3 J- ~8 D/* Standard Downstream Port */
. |4 @" r) R5 l, pPOWER_SUPPLY_TYPE_USB_DCP, /* Dedicated Charging Port */' b7 S' f3 ?, j) [: ?9 V5 _# b
POWER_SUPPLY_TYPE_USB_CDP, /* Charging Downstream Port */7 T' e1 M+ P# Q/ L7 \$ _4 ]
POWER_SUPPLY_TYPE_USB_ACA, /* Accessory Charger Adapters */& p+ Y4 `! i& I" v
POWER_SUPPLY_TYPE_BMS, $ \/ s6 q9 A* a; N% G
/* Battery Monitor System */
; ~& L, K% V1 v& z% f. h
4 M* z5 N4 Q0 D5 h8 g/ _2. How to classify or identify charger?
. a$ T: Y; v# U! [
( g! {8 Q; r0 u1 B4 k; M2 HUSB_SDP_CHARGER
' \% f' L3 M" v* o | POWER_SUPPLY_TYPE_USB
. U# \( p7 b7 X0 A1 ]" X: M7 K$ I5 i | USB Charger | USB_CDP_CHARGER( C: ?1 m& z& X1 o7 R# N/ `/ a, C' l
| POWER_SUPPLY_TYPE_USB_CDP
9 |6 t* D2 }& T- y N3 C. G | USB_ACA_DOCK_CHARGER- F: @& W9 a/ y' n7 i' ~
| POWER_SUPPLY_TYPE_USB_ACA | USB_ACA_A_CHARGER* v# N9 V) X' V: @3 L
| USB_ACA_B_CHARGER
. C# s1 y/ Z! I1 w/ ` | USB_ACA_C_CHARGER- R6 Y2 y* e6 l9 }8 ?" N& i5 P
| USB_DCP_CHARGER
. m: E! x Q( J8 J1 Z( E | POWER_SUPPLY_TYPE_USB_DCP | AC Charger | USB_PROPRIETARY_CHARGER
2 ^. B# E; ^( b1 `7 Y n- S | - L. D8 m( X3 a( Q) W- d
As for the DMS, refer to bold font items, so it is USB charger. q Y) b9 A" e+ \$ i" F9 O
) }: \! ^& G6 j
3. Analysis about source codes: t. V G5 F/ q2 R
*******************************************************************! f) T( @5 \1 i g6 m
###用户空间的分析如下:1 A) l' d' r) Z) i! [
1. 检查 /sys/class/power_supply/pm8921-dc/online和4 ]; R9 Y5 C+ ^( c& h% @
/sys/class/power_supply/usb/online 的值,可以知道是何充电器类型# z7 ~+ q+ X* W# K% f4 r) o7 O
@frameworks/base/services/jni/com_android_server_batteryservice.cpp中有( H6 U. H7 B! P& V6 S$ x
int register_android_server_BatteryService(JNIEnv* env) ' M0 P0 Z6 W( v' \
{
# d. c2 t4 U$ t. Y if (strcmp(buf, "Mains") == 0) { ///sys/class/power_supply/pm8921-dc/type == Mains# m7 V; R1 ]$ ~0 x; s9 N
snprintf(path, sizeof(path), "%s/%s/online", POWER_SUPPLY_PATH, name);
% b/ B8 S8 T3 u3 O' F if (access(path, R_OK) == 0)2 _& T& Q6 B& k7 R& g7 H
gPaths.acOnlinePath = strdup(path); H* h4 ~1 l. T5 S+ s$ i# ^ k
}
2 [3 Z% ]# b# v }, z; f/ @! @2 \4 O1 _
如果/sys/class/power_supply/pm8921-dc/online==1,则插入的充电器是wall
' f+ _/ u' D" [5 p1 u1 f+ h7 B; jcharger# n8 f( q% \ P7 W V& p3 |9 e$ ^
/sys/class/power_supply/usb/online==1, & O7 x3 d& l: J. [+ B9 h9 i2 S
则插入的充电器是usb charger
6 w( H4 f7 i, a 调试路径:/sys/kernel/debug/msm_otg! z1 X# N+ X9 L3 R+ P! T: B
2. 分析frameworks/base/services/jni/com_android_server_batteryservice.cpp) ]; Z6 |" R/ T- H& l' N/ n8 \. D
a.函数register_android_server_BatteryService将为被frameworks/base/services/jni/onload.cpp中的JNI_OnLoad调用,用于关联java和C++之间的变量7 T1 e2 N9 f# t1 A9 {& B, F
b.jclass clazz = env->FindClass("com/android/server/BatteryService"); //根据java的路径找到batteryservice.java对应的jclass ; i( F3 l p4 r6 x: ]
gFieldIds.mAcOnline = env->GetFieldID(clazz, "mAcOnline", "Z");7 R/ i9 s' {) I- _: C2 F
gFieldIds.mUsbOnline = env->GetFieldID(clazz, "mUsbOnline", "Z"); //用于关联batteryservice.java中变量private
7 L: W) Y+ V* ?9 H7 tboolean mAcOnline和gFieldIds.mAcOnline' ` \, t, q7 t5 k
c. android_server_BatteryService_update
7 [# o; \2 x& s1 g% F5 d static JNINativeMethod sMethods[] = {
, R1 \; `' n# {5 w' f" e' E0 p* X /* name, signature, funcPtr */
% |. M- B* h( k2 R+ P# |5 U/ `$ r' u {"native_update", "()V", (void*)android_server_BatteryService_update},- i# _5 ^- v; E
};
' c+ C5 k# B2 r( s) D' [' }2 ^ 关联到native_update@frameworks/base/services/java/com/android/server/batteryservice.java( ^( q0 U5 N2 ^ }5 Z
3. 分析frameworks/base/services/java/com/android/server/batteryservice.java) W2 ? S2 N6 Y6 B
a. mPowerSupplyObserver.startObserving("SUBSYSTEM=power_supply"); //注册监听该uevent
/ k9 S V d1 t: k, _1 F b. private UEventObserver mPowerSupplyObserver = new UEventObserver() {
0 R- t, H! P- K) z public void onUEvent(UEventObserver.UEvent event) { //如果就收到来自kernel的uevent,触发该函数
% |/ D/ k/ l1 x% L8 J. h update(); //-->native_update();和processValues();
u" ~! `8 U: k0 _1 N9 ~+ Q1 L% j }: n" r4 V4 }9 B" u" [
};
: j7 O" x- L0 U- B- c& o8 _6 b c. native_update函数会通过JNI调用得到更新的mAcOnline和mUsbOnline值
0 c- D2 x* T7 D7 Y' A# V/ S& i X d. processValues会根据mAcOnline和mUsbOnline值对mPlugType赋值
! h: l. r V5 Y9 q5 J/ B if (mAcOnline) {
" R. V1 d) H; o& Z8 t T+ p" h; B mPlugType = BatteryManager.BATTERY_PLUGGED_AC;- G& q% `3 z/ Z: j* k9 X2 H" o
} else if (mUsbOnline) {
9 D4 F) E' S$ {1 V& B' r mPlugType = BatteryManager.BATTERY_PLUGGED_USB;2 V2 L3 V- t Z6 A$ ]( B
} else {
2 w! \3 A6 l p0 i4 k mPlugType = BATTERY_PLUGGED_NONE;
6 X- k- i* y2 P4 ]5 A' E& B9 f }) d8 Q# e! J" p5 t$ D' G! [
e. sendIntent函数会准备Intent并且broadcast这个Intent) f) ^, T+ y& c$ f5 K( }( I& O# v
Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED); //public static final String ACTION_BATTERY_CHANGED = "android.intent.action.BATTERY_CHANGED";@batteryservice.java
\+ l- t7 P+ p4 ]2 T1 J intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY6 _( u: o( J3 E! j
| Intent.FLAG_RECEIVER_REPLACE_PENDING);5 x* \& j0 `$ M$ L1 X( _' R8 U8 s
3 g5 ~# @! x' J C# e
intent.putExtra(BatteryManager.EXTRA_PLUGGED, mPlugType);
! D/ |, u7 p5 j ActivityManagerNative.broadcastStickyIntent(intent, null);
: w, p+ Z2 ?8 v1 r0 H3 O: E4. 分析vendor/sEMC/packages/apps/debugmenu/src/com/sonyericsson/debugmenu/battery.java* d- k7 G$ @5 {6 {0 g
a. 接收intent9 T) {2 C( I& R/ a
private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {8 `$ K) N0 w, X# ^. d/ e1 U
@Override. {9 [+ g' m+ Z- G+ A0 d* `
public void onReceive(Context arg0, Intent intent) {
/ ~7 C% q' B. ~& a; n: T D2 Z if (intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) {
, @/ X- S. q G5 X9 z' h) p mPowerInformation.parseIntent(intent);* s; t9 t- _, D- `9 j2 Y9 e
updateViews();7 i5 c3 o8 S/ q
}6 A1 J/ R: G1 q. P" N2 N) V* Z
}
$ S+ r. B& c4 p) g };
) c- i/ u6 s6 ~; \ public void registerBroadcastReceivers() {. ~- N$ }- G* I( N, V) E: k
IntentFilter mIntentFilter;9 m: I# _7 `" j$ E! }
mIntentFilter = new IntentFilter();
) v9 G6 ` ^1 q+ p: t0 G% g mIntentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); //只接收Intent.ACTION_BATTERY_CHANGED的intent
3 c* N$ D9 B) G // Register battery receiver.
, \" Q1 f: }# u/ b: {$ q registerReceiver(mBatteryInfoReceiver, mIntentFilter);
( x* {( |$ A# T3 I! z; y' U& m }
& q D0 U9 x4 @4 {' q+ W# { b. parseIntent 得到最新的"plugged"值赋给mPlugged
% L0 H9 P) a! o) P" h5 y c. updateViews 更新charger类型显示: c8 J8 m5 b5 w
###内核空间
, T+ n/ n# A1 ?2 w9 w- v9 o1. 插入充电器触发的过程@kernel/drivers/usb/otg/msm_otg.c
$ y6 |4 P; A7 p' {5 Y a. CONFIG_PM_RUNTIME 定义 @kernel/arch/ARM/configs/viskan_huashan_defconfig
: z8 N! o' {4 p$ @5 M. M b.msm_otg_runtime_resume-->msm_otg_resume-->??-->msm_otg_sm_work6 t0 T" `$ y: s" Z
c.msm_otg_sm_work,先进入OTG_STATE_UNDEFINED case,然后进入OTG_STATE_B_IDLE* Y4 T0 x5 `" I
case-->motg->chg_state=USB_CHG_STATE_UNDEFINED-->启动msm_chg_detect_work2 Q5 Q, G0 S. k, H( Z
d.msm_chg_detect_work 该函数主要完成USB charger类型的识别% |# S4 v9 ~* h z" @% u
USB_CHG_STATE_UNDEFINED //其中psy = power_supply_get_by_name("usb");很关键,表明只是获取usb的power_supply,实际上就是chip->usb_psy@pm8921-charger.c
& S# a, t0 F/ x: _3 q5 } USB_CHG_STATE_WAIT_FOR_DCD //Waiting for Data pins contact.& r) K$ Y' `, s& S# o% v- Y% _
然后多次(MSM_CHG_DCD_MAX_RETRIES=6)检测USB状态,启动queue_delayed_work(motg->wq,0 b$ s; _# f- [4 m% |! k7 S2 ^
&motg->chg_work, delay); //motg->chg_work=msm_chg_detect_work
, G; X s4 n% b. I0 C USB_CHG_STATE_DETECTED //最后USB charge类型检测完毕
7 V l8 G6 Y' k* l; a: ] e. 启动queue_work(motg->wq, &motg->sm_work); //motg->sm_work=msm_otg_sm_work; @' ^) ^5 u+ n6 o0 M6 @: f9 O
f. 由于motg->chg_state==USB_CHG_STATE_DETECTED,9 Q) [0 W7 x q, _2 r8 x, T; j' f
motg->chg_type==USB_DCP_CHARGER -->msm_otg_notify_charger(motg,IDEV_CHG_MAX);//IDEV_CHG_MAX=15005 F" U; W8 R* Y# ~
2. 发送uevent到用户层: `& p* j9 n: z1 [
a. msm_otg_notify_charger@kernel/drivers/usb/otg/msm_otg.c
4 V/ D2 S6 I- w/ O( [: N4 w 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
0 D: f4 H& l. O) U' M- z c. -->power_supply_set_supply_type@power_supply_core.c // set type of the power supply' |- Z* ^6 Y( W0 o+ P' S' _' E
d. -->psy->set_property(psy, POWER_SUPPLY_PROP_TYPE,&ret);) q0 Y2 l8 _; W7 N
那么在用usb_psy.get_property和dc_psy.get_property( a: r# {% V& u7 u# `) J
(在函数中pm8921_charger_probe)读取property时) M; O) n x: {- h: }
如果是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 k$ W3 f u( e' U6 _% {
charger$ B. p" T7 p0 W3 d& x( l, Y
如果是AC type,则在pm_power_get_property_mains读取POWER_SUPPLY_PROP_ONLINE的值,只有POWER_SUPPLY_TYPE_USB_DCP为AC, t8 Y* B3 }" [( V% ` S1 Z
charger.
; K4 Q3 h$ U0 _$ c8 h4 e* {. V" I, G% ^ 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.c4 [: X1 \0 ~5 l8 s x
f. -->pm8921_set_usb_power_supply_type(val->intval)@pm8921-charger.c' F0 Q1 q( z; _; ^
-->power_supply_changed(&the_chip->usb_psy);
# b: n2 }( D# `) F# K" P( }$ l5 x% c -->power_supply_changed(&the_chip->dc_psy);- k! o# z* b/ h+ h5 n) u
g. power_supply_changed@pm8921-charger.c , 就会马上发送uevent给user7 U3 {4 I. W/ h; E; ~9 D
space,然后user space通过sysfs得到USB9 e6 f3 \- V& i. g
type变化后的信息,参考用户空间的分析, I) U x- c9 B- T. g
0 o8 A% x7 H% o9 f2 p) I5 a6 m! z" f$ @5 R
二、硬件分析
% O- t& y9 V5 t! A: L% k5 N* {5 Y * h7 E g- A+ P2 @2 E: M9 }0 N
主要是通过特殊设计的电路,检测不同的pin的状态,从而确定是何种类型的Charger. 更details的内容省略。 P) H0 A; e1 L1 {- E& q1 y* |
+ h' X m7 b8 {
2 L7 |. {1 s* ^8 ^/ Y y0 J& s7 |
3 _) o' y4 u2 \1 C; p4 D( y |
|