|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
USB port 如何识别不同的Charger类型2 s% H+ A& i( C2 g6 @+ t7 F0 h O
2013年10月03日 ⁄ 综合 ⁄ 共 8924字 ⁄ 字号 [url=]小[/url] [url=]中[/url] [url=]大[/url] ⁄ 评论关闭: @# ?/ Y+ h# ~! d8 j W: X' ~8 o
6 z9 U A, R* l
一,软件分析1. USB charger types & Power supply types' b1 L+ X5 ]7 W: A
USB_INVALID_CHARGER Invalid USB charger.
8 c2 b/ c. a4 P- G9 r1 sUSB_SDP_CHARGER Standard downstream port. Refers to a downstream port on USB2.0 compliant host/hub.; t' f, n4 H' N1 S
USB_DCP_CHARGER Dedicated charger port (AC charger/ Wall charger).( E/ I; O. S& T0 ]7 H
USB_CDP_CHARGER Charging downstream port. Enumeration can happen and IDEV_CHG_MAX can be drawn irrespective of USB state.
; o5 \2 c4 W3 bUSB_ACA_A_CHARGER 6 s/ X9 s2 M C0 K
B-device is connected on accessory port with charger connected on charging port. This configuration allows charging in host mode.
( r4 B1 ?8 T6 w. p& bUSB_ACA_B_CHARGER No device (or A-device without VBUS) is connected on accessory port with charger connected on charging port.$ L" ~1 D3 M( s6 L: g
USB_ACA_C_CHARGER A-device (with VBUS) is connected on accessory port with charger connected on charging port.
5 F+ A8 [$ e* o* rUSB_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
3 j2 y6 T$ z: U" G8 Oports.
8 L6 L9 L; u: R% F% o! ]* g# SUSB_PROPRIETARY_CHARGER A proprietary charger pull DP and DM to specific voltages between 2.0-3.3v for identification.
/ O9 {+ G/ p: g& K& s
% m/ g3 M( {4 Z5 c1 b& ^4 YPOWER_SUPPLY_TYPE_USB,
. ^4 a; ^* i# T0 F" l, U/* Standard Downstream Port */" u- v" g9 w( F2 i& Y+ ^; `9 |5 a
POWER_SUPPLY_TYPE_USB_DCP, /* Dedicated Charging Port */
. V1 c& ?. ?2 E5 [POWER_SUPPLY_TYPE_USB_CDP, /* Charging Downstream Port */
! _9 B$ K8 K( sPOWER_SUPPLY_TYPE_USB_ACA, /* Accessory Charger Adapters */
6 j9 t2 y$ E0 r2 RPOWER_SUPPLY_TYPE_BMS,
! D8 ]6 L# X7 ? o7 \& _/* Battery Monitor System */
$ b* V6 }, N) h) l+ Z 9 B. t0 K* m- W+ \, k
2. How to classify or identify charger?& h: b Z3 }* m. D" _- M
2 g1 z) ]! G$ C& ~) b# y1 c8 p4 I! L
USB_SDP_CHARGER
1 I0 V1 z& t+ f% W L7 @9 K | POWER_SUPPLY_TYPE_USB
+ {, p8 @# U6 n | USB Charger | USB_CDP_CHARGER
8 J& ^: ^6 G& r" {' C- g+ X9 _ | POWER_SUPPLY_TYPE_USB_CDP
4 i6 Z6 p7 L7 ?8 C9 l' g | USB_ACA_DOCK_CHARGER+ s$ P4 G" F" h6 X! y2 a( H# H
| POWER_SUPPLY_TYPE_USB_ACA | USB_ACA_A_CHARGER* v. q7 @+ Y: {/ Q+ |
| USB_ACA_B_CHARGER
# q M# s- Y! ?- q6 h1 X O | USB_ACA_C_CHARGER
) n1 Y1 ?4 \( x% o8 `2 u5 Q | USB_DCP_CHARGER% R( O2 {" b& g! ~$ {
| POWER_SUPPLY_TYPE_USB_DCP | AC Charger | USB_PROPRIETARY_CHARGER; @* _% p" P1 B$ l
|
1 S4 j- F8 T3 |) w1 B& rAs for the DMS, refer to bold font items, so it is USB charger.
# A2 U$ U9 y3 k6 W j& }4 R
/ Q9 r- s- i x( ?3 B! \8 k7 s3. Analysis about source codes
0 N6 T0 I9 j5 G7 E# ^% T9 }*******************************************************************1 ~# T1 n7 H* S- J
###用户空间的分析如下:
1 o/ _9 s4 W! m$ @% [( M1. 检查 /sys/class/power_supply/pm8921-dc/online和 \9 b( @+ c f3 C
/sys/class/power_supply/usb/online 的值,可以知道是何充电器类型
! v' p" G; S3 \9 c3 v5 x @frameworks/base/services/jni/com_android_server_batteryservice.cpp中有
- k/ ?* q% Z: M int register_android_server_BatteryService(JNIEnv* env)
* r* f/ D% d; g7 Q; z5 r {
; p2 z0 |% }; G8 Y: f9 m: Y, G if (strcmp(buf, "Mains") == 0) { ///sys/class/power_supply/pm8921-dc/type == Mains
6 d8 A+ e! S/ i: |. |4 z: Z9 A7 T+ o snprintf(path, sizeof(path), "%s/%s/online", POWER_SUPPLY_PATH, name);* E5 w7 e# f5 l# c/ g& ~0 g* A% m7 K
if (access(path, R_OK) == 0)' ]' Y! {/ ~; P( m: u5 v
gPaths.acOnlinePath = strdup(path);
; C' J1 p0 j, H" f6 i }: _5 X' `% W6 m! H, G5 S+ e
}$ G6 s# c! Q" l. ^ w
如果/sys/class/power_supply/pm8921-dc/online==1,则插入的充电器是wall
; c& T a: S! v% T$ e. Bcharger
5 r+ t8 [+ k6 q# j; o /sys/class/power_supply/usb/online==1,
* v! c8 h' D( i' H" V; u9 e则插入的充电器是usb charger
+ E$ g2 `& T7 Z5 ] 调试路径:/sys/kernel/debug/msm_otg
& }* Z4 m4 i, n. d6 g% x2. 分析frameworks/base/services/jni/com_android_server_batteryservice.cpp
- c9 S$ D; P' F9 X% g" Q/ U7 w( K; E9 i a.函数register_android_server_BatteryService将为被frameworks/base/services/jni/onload.cpp中的JNI_OnLoad调用,用于关联java和C++之间的变量
" m; [4 k3 r" k/ z% X- [ b.jclass clazz = env->FindClass("com/android/server/BatteryService"); //根据java的路径找到batteryservice.java对应的jclass
2 w6 c) a" _/ A# G gFieldIds.mAcOnline = env->GetFieldID(clazz, "mAcOnline", "Z");) ^) `/ G/ l3 d3 X: B, Y
gFieldIds.mUsbOnline = env->GetFieldID(clazz, "mUsbOnline", "Z"); //用于关联batteryservice.java中变量private" C" g1 S! y& Z
boolean mAcOnline和gFieldIds.mAcOnline
t( b1 |2 y2 g4 t! H7 L7 H c. android_server_BatteryService_update4 k+ X* o) M0 i4 i+ j
static JNINativeMethod sMethods[] = {3 H6 m2 Q9 a" h/ e1 y
/* name, signature, funcPtr */ I1 {( F/ g; }# X- P4 B: y7 b
{"native_update", "()V", (void*)android_server_BatteryService_update},, T6 }/ y2 s4 z6 E, {0 Y- Y
};
/ B$ {( e# w8 r7 G# [ 关联到native_update@frameworks/base/services/java/com/android/server/batteryservice.java
: V3 Y6 l5 Q* G) S, a* L3. 分析frameworks/base/services/java/com/android/server/batteryservice.java! L1 r1 E' _. m4 m
a. mPowerSupplyObserver.startObserving("SUBSYSTEM=power_supply"); //注册监听该uevent
, N- R2 B* P- i$ m* N b. private UEventObserver mPowerSupplyObserver = new UEventObserver() {
+ r- ^) ] X2 j- J/ r5 G; r public void onUEvent(UEventObserver.UEvent event) { //如果就收到来自kernel的uevent,触发该函数: a8 `6 O X' d
update(); //-->native_update();和processValues();
; `5 x9 z( P! [8 e9 Q; Q4 H }6 x/ j- D1 b) ^2 J/ _2 B! m |
};2 G \. G! H# W; f
c. native_update函数会通过JNI调用得到更新的mAcOnline和mUsbOnline值
$ A2 \' e* M, x: h& w d. processValues会根据mAcOnline和mUsbOnline值对mPlugType赋值- F- L4 o% M! T! A6 A' R) G
if (mAcOnline) {6 J% F. u Z/ N0 j, [. t
mPlugType = BatteryManager.BATTERY_PLUGGED_AC;+ r$ s& i* R4 c7 b7 {
} else if (mUsbOnline) {
) P& E8 S( X! O& `+ D( g mPlugType = BatteryManager.BATTERY_PLUGGED_USB;+ J; e# f5 Y- O' ]
} else {; ^8 }" Q# f) k" `( F. u4 l9 Z% F
mPlugType = BATTERY_PLUGGED_NONE;
1 d( V" z! R$ a: `, ]' @ }
# _1 Y4 d3 j1 B e. sendIntent函数会准备Intent并且broadcast这个Intent% W* a/ e7 c0 {7 Z6 c, A
Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED); //public static final String ACTION_BATTERY_CHANGED = "android.intent.action.BATTERY_CHANGED";@batteryservice.java
- Q6 z, `- E1 v0 c' ] intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
& M) i: I+ i D6 [/ z' ]/ I& \ | Intent.FLAG_RECEIVER_REPLACE_PENDING);
$ {3 h# |& w) v# l4 B
5 e' z6 K, K: L' h intent.putExtra(BatteryManager.EXTRA_PLUGGED, mPlugType);
' X2 }5 ?, g$ X2 U: s) k ActivityManagerNative.broadcastStickyIntent(intent, null);9 b; R8 y4 p3 \3 T. Q' e# p1 d
4. 分析vendor/sEMC/packages/apps/debugmenu/src/com/sonyericsson/debugmenu/battery.java. G' o3 A1 k" Y+ T# P
a. 接收intent* d$ }% @9 l2 }8 E" p# _: I
private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {
$ \& O' O' _0 N! D+ d( ]; N! U @Override
Y8 C/ A. h- m1 ~% V public void onReceive(Context arg0, Intent intent) {
4 A- X6 y w- W# h2 l if (intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) {
( q9 Z7 U6 L. M, k8 o6 e, D5 q% D& \ mPowerInformation.parseIntent(intent);
( }8 @0 d9 b. j4 ] a# G$ j$ R updateViews();9 s, t+ r4 |- ]; ^& u* D# g
}
( C1 ~2 {/ m9 h/ U }
0 Y- a9 W8 p w# Q) c9 ^. Z/ |$ l7 U/ _ };4 S, X4 u# ^7 L9 T& I# `
public void registerBroadcastReceivers() {
' {3 Q* R O. C/ ?0 d IntentFilter mIntentFilter;
* o3 M* x5 I v3 p f) A mIntentFilter = new IntentFilter();
4 Y. N( I$ o! b( B5 | mIntentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); //只接收Intent.ACTION_BATTERY_CHANGED的intent- b6 s8 n5 ?* f- Q
// Register battery receiver.
2 ]7 K6 I% W7 ]+ c3 V. J3 b6 W% e registerReceiver(mBatteryInfoReceiver, mIntentFilter);: Y3 A3 t# o2 f0 }3 y
} 9 v& c x6 H- h; e: {8 d
b. parseIntent 得到最新的"plugged"值赋给mPlugged
5 [6 k3 [# O6 u' s3 f c. updateViews 更新charger类型显示/ |. _+ W5 z! N4 }% ^/ Z
###内核空间! e$ }4 W( ?) l# H
1. 插入充电器触发的过程@kernel/drivers/usb/otg/msm_otg.c
6 Z, e3 N( V/ ?$ r a. CONFIG_PM_RUNTIME 定义 @kernel/arch/ARM/configs/viskan_huashan_defconfig
2 y0 s0 \: F$ e, G8 N5 v b.msm_otg_runtime_resume-->msm_otg_resume-->??-->msm_otg_sm_work f. M+ x7 K* ^
c.msm_otg_sm_work,先进入OTG_STATE_UNDEFINED case,然后进入OTG_STATE_B_IDLE
, j9 q$ o, n B% i- G) f% f( qcase-->motg->chg_state=USB_CHG_STATE_UNDEFINED-->启动msm_chg_detect_work
8 _7 L2 B7 u' b; v. W! b d.msm_chg_detect_work 该函数主要完成USB charger类型的识别
( q0 s$ S, I; e. Q- T4 G7 H USB_CHG_STATE_UNDEFINED //其中psy = power_supply_get_by_name("usb");很关键,表明只是获取usb的power_supply,实际上就是chip->usb_psy@pm8921-charger.c8 Y1 O; a( a# P6 \
USB_CHG_STATE_WAIT_FOR_DCD //Waiting for Data pins contact.
3 |, r% q, c! f G) L0 a* F 然后多次(MSM_CHG_DCD_MAX_RETRIES=6)检测USB状态,启动queue_delayed_work(motg->wq,
0 [, l5 b* t# y% f&motg->chg_work, delay); //motg->chg_work=msm_chg_detect_work
) E: D2 U& D6 O& r. ?* W; E USB_CHG_STATE_DETECTED //最后USB charge类型检测完毕+ g* J" b `! N( `& U8 r2 B" ?
e. 启动queue_work(motg->wq, &motg->sm_work); //motg->sm_work=msm_otg_sm_work3 c) U* [" V3 v) I, q% m! ^3 A4 B
f. 由于motg->chg_state==USB_CHG_STATE_DETECTED,
8 }; B1 l! k: V6 Q% d7 } motg->chg_type==USB_DCP_CHARGER -->msm_otg_notify_charger(motg,IDEV_CHG_MAX);//IDEV_CHG_MAX=1500
3 ~" O- ~* s- }% F6 O/ g2. 发送uevent到用户层
: _; i) ?4 g) J3 a# p4 d' o1 e a. msm_otg_notify_charger@kernel/drivers/usb/otg/msm_otg.c
+ w& g: u' g. ~3 r b6 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
% @) K s. [# @; N7 O8 v8 v$ {2 d c. -->power_supply_set_supply_type@power_supply_core.c // set type of the power supply
( F5 ?: X7 y1 Y9 q, s/ h d. -->psy->set_property(psy, POWER_SUPPLY_PROP_TYPE,&ret);
: P! c, g' y! H 那么在用usb_psy.get_property和dc_psy.get_property
Z* ` [$ G2 b8 ^3 X2 @(在函数中pm8921_charger_probe)读取property时1 A" f+ H/ ?+ K
如果是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
+ } I5 v. B9 ?charger' p; v8 a) ~: ~% `8 ]0 r. {: E m3 e
如果是AC type,则在pm_power_get_property_mains读取POWER_SUPPLY_PROP_ONLINE的值,只有POWER_SUPPLY_TYPE_USB_DCP为AC
: x9 ?0 `" O! J% Gcharger.6 {. Q: x" E t" D' r
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: S+ A4 W/ y* T) Z1 j
f. -->pm8921_set_usb_power_supply_type(val->intval)@pm8921-charger.c
! K6 o6 @) |' w q -->power_supply_changed(&the_chip->usb_psy);4 Y# Y3 C; Y( L# g, I2 P+ v& j% X: m
-->power_supply_changed(&the_chip->dc_psy);
9 J! X7 T* C5 M4 l+ D3 Y" u& Q/ k+ L g. power_supply_changed@pm8921-charger.c , 就会马上发送uevent给user3 }: G8 y* z' ?) K. t) `
space,然后user space通过sysfs得到USB+ U; M8 l; y* x- q9 o- }7 r" P
type变化后的信息,参考用户空间的分析( g: W- E1 d5 d
' s# Z7 k, k) j/ d1 @
二、硬件分析7 u/ X. w6 A; [' g$ Q3 p, L
![]()
/ k. G1 n+ N9 N主要是通过特殊设计的电路,检测不同的pin的状态,从而确定是何种类型的Charger. 更details的内容省略。
" y( [+ q7 k6 o7 e0 m6 d8 V" E) |8 U; l
: v5 g! U" O) W- _# J' K
$ p+ N! k4 h" t) P {" D1 | |
|