|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
USB port 如何识别不同的Charger类型' h1 F) f, w! \5 q2 F* ?& t) J
2013年10月03日 ⁄ 综合 ⁄ 共 8924字 ⁄ 字号 [url=]小[/url] [url=]中[/url] [url=]大[/url] ⁄ 评论关闭) M8 k! Y. @0 K1 u
) }6 V4 |( [% g7 B! J: B一,软件分析1. USB charger types & Power supply types# G9 Z( C' I0 d6 L- c( J# u
USB_INVALID_CHARGER Invalid USB charger.
+ t! F D, L! C Y7 O# J6 dUSB_SDP_CHARGER Standard downstream port. Refers to a downstream port on USB2.0 compliant host/hub.
( N4 @% t2 I& y, h. j+ [USB_DCP_CHARGER Dedicated charger port (AC charger/ Wall charger).
4 o7 T0 }6 a. gUSB_CDP_CHARGER Charging downstream port. Enumeration can happen and IDEV_CHG_MAX can be drawn irrespective of USB state.5 N6 I) L8 `$ e' [. U7 i
USB_ACA_A_CHARGER 4 G3 S8 ?. f$ i! E A7 D- V f
B-device is connected on accessory port with charger connected on charging port. This configuration allows charging in host mode.' c. o) X3 B* d# e F
USB_ACA_B_CHARGER No device (or A-device without VBUS) is connected on accessory port with charger connected on charging port.5 w1 f( y L3 }" J
USB_ACA_C_CHARGER A-device (with VBUS) is connected on accessory port with charger connected on charging port.
$ p0 @' B: I! @8 K0 s G8 MUSB_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
0 `. z H- C' Uports.
- @/ H, M) N1 ?3 S' mUSB_PROPRIETARY_CHARGER A proprietary charger pull DP and DM to specific voltages between 2.0-3.3v for identification.
1 i$ u( @) j: G3 b# ]; `8 m( q- X ! L. U* @' o0 T* [1 Y
POWER_SUPPLY_TYPE_USB, + x; ]5 X1 K7 G& D! \* s
/* Standard Downstream Port */7 u' X4 @/ A4 w
POWER_SUPPLY_TYPE_USB_DCP, /* Dedicated Charging Port *// r9 G6 o! R& O, b+ K( w. y
POWER_SUPPLY_TYPE_USB_CDP, /* Charging Downstream Port */
% ]6 x8 L2 _# T7 \2 w4 Q% rPOWER_SUPPLY_TYPE_USB_ACA, /* Accessory Charger Adapters */( u1 N9 m: i0 X* c$ V
POWER_SUPPLY_TYPE_BMS,
( M2 ~. P- T- z9 P9 u/* Battery Monitor System */4 @6 y8 @% t4 f
9 T8 e5 m( ^; l' W% Q# H2 h
2. How to classify or identify charger?
: W: c% {6 E( a2 @0 f1 b/ B
6 z C. |; M3 s' \USB_SDP_CHARGER
4 m" N& C6 X2 l7 m5 R6 @5 L! d | POWER_SUPPLY_TYPE_USB
* O" ^8 y+ K4 D | USB Charger | USB_CDP_CHARGER* r7 M ^6 B: ]# ?8 ]
| POWER_SUPPLY_TYPE_USB_CDP: m" _, o2 Z4 a0 x1 D" l
| USB_ACA_DOCK_CHARGER7 n! F2 N- k. J$ M
| POWER_SUPPLY_TYPE_USB_ACA | USB_ACA_A_CHARGER$ E9 \2 w% v0 w, W3 m2 Q0 q' q
| USB_ACA_B_CHARGER
$ t" a6 \9 X( d | USB_ACA_C_CHARGER
* \$ j; Q0 _1 k$ h7 [# ? | USB_DCP_CHARGER" z2 @% h) ^; E/ q T: _. H7 V
| POWER_SUPPLY_TYPE_USB_DCP | AC Charger | USB_PROPRIETARY_CHARGER0 T# }4 R% f7 f7 u
|
' r1 L) h, o5 lAs for the DMS, refer to bold font items, so it is USB charger./ Z# S/ ` i( C$ I( S* K3 h( n) w
0 @; Q! T: G( ?
3. Analysis about source codes
# f" } @9 n9 O! O- S*******************************************************************
0 X5 u! _& [" g( K###用户空间的分析如下:) x* M3 |% S) N X, F
1. 检查 /sys/class/power_supply/pm8921-dc/online和
% v; f/ @' e& T- J& p/sys/class/power_supply/usb/online 的值,可以知道是何充电器类型* S) @8 M6 a; O) S8 n4 j3 L0 Y
@frameworks/base/services/jni/com_android_server_batteryservice.cpp中有
* R( Q4 l, D* ?. O" c( @6 a int register_android_server_BatteryService(JNIEnv* env)
$ i$ _' S3 q* m+ k# V( R9 t" r {
; l) L1 E: U' n% B/ t6 J' p! a& A if (strcmp(buf, "Mains") == 0) { ///sys/class/power_supply/pm8921-dc/type == Mains& c! ^$ u' q7 m
snprintf(path, sizeof(path), "%s/%s/online", POWER_SUPPLY_PATH, name);
* n9 @" m( G& r8 h% \" j if (access(path, R_OK) == 0)
- Y5 Z9 V$ B% A2 h4 f7 ` gPaths.acOnlinePath = strdup(path);( |8 T9 `& S" Z; R! n8 a" ?
}
" V- `; p& K- F4 F }
- b L0 }, }" J) l2 w0 t* ^; v6 n6 \ 如果/sys/class/power_supply/pm8921-dc/online==1,则插入的充电器是wall
1 K. }& I* o/ q2 F- G+ Mcharger, e2 w0 K! i+ [2 c9 Y0 Y/ f
/sys/class/power_supply/usb/online==1, 9 y8 a0 o$ C( n# ?. z% `# V
则插入的充电器是usb charger
4 T8 E7 P. |1 ]5 d 调试路径:/sys/kernel/debug/msm_otg
8 w# v8 W. x# M* a$ }5 A2. 分析frameworks/base/services/jni/com_android_server_batteryservice.cpp$ M. }, r& `1 |( ~0 H" l( ~
a.函数register_android_server_BatteryService将为被frameworks/base/services/jni/onload.cpp中的JNI_OnLoad调用,用于关联java和C++之间的变量
$ e2 x3 R. A8 M b.jclass clazz = env->FindClass("com/android/server/BatteryService"); //根据java的路径找到batteryservice.java对应的jclass
8 H4 y5 {# y6 Y/ s! L5 J gFieldIds.mAcOnline = env->GetFieldID(clazz, "mAcOnline", "Z");$ C% b# p8 b& ]
gFieldIds.mUsbOnline = env->GetFieldID(clazz, "mUsbOnline", "Z"); //用于关联batteryservice.java中变量private
" Y/ n+ C1 _5 f6 hboolean mAcOnline和gFieldIds.mAcOnline
7 ^" ?! H& j6 W3 k2 \ c. android_server_BatteryService_update H" Q- M" J1 E& s# O# ]3 K
static JNINativeMethod sMethods[] = {
) [) ]9 W+ }: j; y5 x /* name, signature, funcPtr */
* O4 J7 x( B' w8 l* H {"native_update", "()V", (void*)android_server_BatteryService_update},4 v1 \6 X+ u. p1 a! V8 z
};
* S) ?6 l- t* Z) u/ H 关联到native_update@frameworks/base/services/java/com/android/server/batteryservice.java
% L0 ~* F+ N$ w- V3. 分析frameworks/base/services/java/com/android/server/batteryservice.java2 _! h$ [0 c9 {/ t* C2 z
a. mPowerSupplyObserver.startObserving("SUBSYSTEM=power_supply"); //注册监听该uevent
( a5 _3 H% b' z+ v3 Y( G* f# @2 x2 y b. private UEventObserver mPowerSupplyObserver = new UEventObserver() {# s3 B* ~% @) y! p
public void onUEvent(UEventObserver.UEvent event) { //如果就收到来自kernel的uevent,触发该函数" t- e& n7 J1 s. r: }( [
update(); //-->native_update();和processValues();6 p* K( J* a1 s1 [
}
8 |4 w* v* y5 b: e+ N };
6 b1 V/ E! f& d/ ^" c, w c. native_update函数会通过JNI调用得到更新的mAcOnline和mUsbOnline值
0 ^7 E O9 Y: a1 g/ j/ L2 n d. processValues会根据mAcOnline和mUsbOnline值对mPlugType赋值
$ R( s% k7 |+ R if (mAcOnline) {
; n) F! r2 n& D mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
- \1 s0 X6 X7 H: y$ `6 G } else if (mUsbOnline) {! J2 }8 d1 G- m
mPlugType = BatteryManager.BATTERY_PLUGGED_USB;
/ F" E1 R& O( O% Y; u } else {: m: n; u( S' P/ ^) V
mPlugType = BATTERY_PLUGGED_NONE;
+ m R: n# Z; [( Y% Z }
0 q1 W N; ~9 t i9 N/ A0 R e. sendIntent函数会准备Intent并且broadcast这个Intent
/ g) U" h8 p0 S! B Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED); //public static final String ACTION_BATTERY_CHANGED = "android.intent.action.BATTERY_CHANGED";@batteryservice.java. ~: `6 m3 M) S9 ~+ i% S
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY0 I4 @% x V& P, r( O, W% k2 p
| Intent.FLAG_RECEIVER_REPLACE_PENDING);" ~ T6 ?; b4 Y2 ^' p ^
4 z4 Y7 {5 I+ j1 N1 @- Z1 n# u intent.putExtra(BatteryManager.EXTRA_PLUGGED, mPlugType);4 a1 @" D4 Q- P* S
ActivityManagerNative.broadcastStickyIntent(intent, null);
+ E: q8 t8 b4 i9 V2 X4. 分析vendor/sEMC/packages/apps/debugmenu/src/com/sonyericsson/debugmenu/battery.java
( T; _# p% y+ ?8 P a. 接收intent) b$ S& N+ x# D3 i1 O$ }2 `
private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {
; W2 M/ b. z* n! v @Override$ k U3 a4 I5 W- Y" v: w# r8 R
public void onReceive(Context arg0, Intent intent) {
( |- E. X3 v2 M* N4 x3 w if (intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) {
/ z: [# A# l' h+ h, l mPowerInformation.parseIntent(intent);
% z; n0 x m: _6 W" e7 r8 C updateViews();& H) o s" s# P1 p
}
& A/ n2 N. z/ r- c9 G9 o( G$ y }
: A6 W5 l# p( [- l };5 z2 k, L' b# e+ L( H! y% C: I
public void registerBroadcastReceivers() {! {# n1 Y$ F: P7 q
IntentFilter mIntentFilter;4 v8 j2 `! Q" z) Q+ g% X! b
mIntentFilter = new IntentFilter();
& d& u' b& {6 }7 k ~ mIntentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); //只接收Intent.ACTION_BATTERY_CHANGED的intent% u0 F5 n3 J: t) {4 X7 z
// Register battery receiver.
- u( X" D' G% @5 u" s' O- r registerReceiver(mBatteryInfoReceiver, mIntentFilter);
5 `! N6 O6 V/ W- U7 t" V# } } 4 M, y7 Y! n* f c' ^2 h- q- C
b. parseIntent 得到最新的"plugged"值赋给mPlugged
& K! C8 u" x9 ^: C c. updateViews 更新charger类型显示
8 O9 W) P. \* z###内核空间
* b; ~0 ~& P! O1. 插入充电器触发的过程@kernel/drivers/usb/otg/msm_otg.c m2 a) z, T' n3 g0 f" Z
a. CONFIG_PM_RUNTIME 定义 @kernel/arch/ARM/configs/viskan_huashan_defconfig
5 V, d S/ c5 ^, m b.msm_otg_runtime_resume-->msm_otg_resume-->??-->msm_otg_sm_work
2 H, U& Y2 v2 y0 T c.msm_otg_sm_work,先进入OTG_STATE_UNDEFINED case,然后进入OTG_STATE_B_IDLE
$ f& P- G; s. b+ ncase-->motg->chg_state=USB_CHG_STATE_UNDEFINED-->启动msm_chg_detect_work6 ~. k' `1 f9 g9 y: n
d.msm_chg_detect_work 该函数主要完成USB charger类型的识别7 S. n7 ?5 B; r W7 G1 m3 h" D
USB_CHG_STATE_UNDEFINED //其中psy = power_supply_get_by_name("usb");很关键,表明只是获取usb的power_supply,实际上就是chip->usb_psy@pm8921-charger.c
) l7 z7 H7 K& E q! s) Y! c USB_CHG_STATE_WAIT_FOR_DCD //Waiting for Data pins contact.
$ \$ t7 F! h, w" F! f- { 然后多次(MSM_CHG_DCD_MAX_RETRIES=6)检测USB状态,启动queue_delayed_work(motg->wq,
+ ^3 t: Y* }" W. M, W+ k: ?&motg->chg_work, delay); //motg->chg_work=msm_chg_detect_work# u0 ]( @4 t) l2 j1 x
USB_CHG_STATE_DETECTED //最后USB charge类型检测完毕2 I1 q1 n# @4 _0 _8 D, V( n% ~
e. 启动queue_work(motg->wq, &motg->sm_work); //motg->sm_work=msm_otg_sm_work; L, u* J, ^+ k: G
f. 由于motg->chg_state==USB_CHG_STATE_DETECTED,: N; H) ?5 H& \( I
motg->chg_type==USB_DCP_CHARGER -->msm_otg_notify_charger(motg,IDEV_CHG_MAX);//IDEV_CHG_MAX=1500
% ~, X2 P! f3 ?) n+ r+ l2. 发送uevent到用户层7 O* K9 C0 n- w$ x
a. msm_otg_notify_charger@kernel/drivers/usb/otg/msm_otg.c/ y( L @5 h, _ v! 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_BATTERY3 g/ L# f8 k4 D
c. -->power_supply_set_supply_type@power_supply_core.c // set type of the power supply
2 x2 W" `( [7 c" b- I" j d. -->psy->set_property(psy, POWER_SUPPLY_PROP_TYPE,&ret);
% J, x- }% \: W+ }( J$ ~5 z* p& k 那么在用usb_psy.get_property和dc_psy.get_property* t/ a7 q/ M2 `8 a# E
(在函数中pm8921_charger_probe)读取property时
; i5 t b) m7 p' O$ 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$ S6 G3 q' w( N7 ~
charger: s$ J* m7 x, z, m) ^0 M& w
如果是AC type,则在pm_power_get_property_mains读取POWER_SUPPLY_PROP_ONLINE的值,只有POWER_SUPPLY_TYPE_USB_DCP为AC3 Y3 T* P) ]3 Y& H+ m$ Z) j. Z
charger.+ M/ i9 c4 r. R8 z/ M
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.c6 m9 ?, W) W$ F2 Z6 m
f. -->pm8921_set_usb_power_supply_type(val->intval)@pm8921-charger.c7 E; G* L2 n6 s6 d
-->power_supply_changed(&the_chip->usb_psy);
$ m @6 M6 m0 S) h) i* A1 U; d -->power_supply_changed(&the_chip->dc_psy);
3 f5 w% N8 z% m7 N g. power_supply_changed@pm8921-charger.c , 就会马上发送uevent给user
6 ]6 z6 y+ q' K1 w/ A- ^space,然后user space通过sysfs得到USB' h. u9 N* S1 H- O* Q1 j
type变化后的信息,参考用户空间的分析% N4 Z( w A2 s) c8 h) X' d
; r( P) M' n% V: o: {1 b y' H! ]二、硬件分析
: ?* n: F; A% h H 5 M7 S. o' c- L: s8 t* X' a
主要是通过特殊设计的电路,检测不同的pin的状态,从而确定是何种类型的Charger. 更details的内容省略。8 P! }" K/ J4 s' i" O+ _# S2 R
- g \9 o. _; f9 \9 P$ V+ u: i" e4 r/ I) p1 W* ^
* L& v4 x! B% m! f @ |
|