|
EDA365欢迎您!
您需要 登录 才可以下载或查看,没有帐号?注册
x
USB port 如何识别不同的Charger类型! a; w* ~" j8 v: M7 s* I3 D( X, k
2013年10月03日 ⁄ 综合 ⁄ 共 8924字 ⁄ 字号 [url=]小[/url] [url=]中[/url] [url=]大[/url] ⁄ 评论关闭
( }" o% M( B9 c
+ h1 v6 K- ?" v. ?1 T4 E, U+ n一,软件分析1. USB charger types & Power supply types! @ N0 E3 g: T3 n
USB_INVALID_CHARGER Invalid USB charger.; Q5 X# @' h Z: e$ \
USB_SDP_CHARGER Standard downstream port. Refers to a downstream port on USB2.0 compliant host/hub.
& Y, ^0 V0 F( h0 S4 gUSB_DCP_CHARGER Dedicated charger port (AC charger/ Wall charger).
; B$ s! T) p" vUSB_CDP_CHARGER Charging downstream port. Enumeration can happen and IDEV_CHG_MAX can be drawn irrespective of USB state.
$ h- Q- _$ _' m) U6 W! ?2 \USB_ACA_A_CHARGER
6 V2 q9 A; b, N: d* f. J wB-device is connected on accessory port with charger connected on charging port. This configuration allows charging in host mode.
! @( a+ ?7 J: F. \1 n! i8 p0 [USB_ACA_B_CHARGER No device (or A-device without VBUS) is connected on accessory port with charger connected on charging port." o, P; O! x* r0 z+ C
USB_ACA_C_CHARGER A-device (with VBUS) is connected on accessory port with charger connected on charging port.1 _( J2 e* R( J; Y: ?$ {9 ]
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 accessory( Q. h P! G$ K$ U
ports.! ^. z. C! x: v7 `/ ]' U
USB_PROPRIETARY_CHARGER A proprietary charger pull DP and DM to specific voltages between 2.0-3.3v for identification.6 x2 m4 G, w! t* I7 ]9 w7 Z
8 v' d5 ^9 W; @" r# }
POWER_SUPPLY_TYPE_USB, 6 d2 i; M6 a# | z, c
/* Standard Downstream Port */
E1 R1 T/ z6 A- Z. W% yPOWER_SUPPLY_TYPE_USB_DCP, /* Dedicated Charging Port */
4 Z: |; k. J; ^* APOWER_SUPPLY_TYPE_USB_CDP, /* Charging Downstream Port */
. L; }1 X$ b! M8 ~. DPOWER_SUPPLY_TYPE_USB_ACA, /* Accessory Charger Adapters */( B1 v! X6 _* [9 q2 G9 q1 t% @, X _
POWER_SUPPLY_TYPE_BMS, ; D+ v3 `# q0 V; V1 N
/* Battery Monitor System */ ~! L! [: ~$ M( A
s* K# l" E4 I8 }$ f( b1 P) Y# U9 b
2. How to classify or identify charger?( y' S% b0 |% D2 V9 f7 z3 G& W
1 L3 ?2 @% z6 f0 ^
USB_SDP_CHARGER' }- T9 d; ^4 r) e* E4 \ b
| POWER_SUPPLY_TYPE_USB; _ l, n, b: r' v( Y& c6 k
| USB Charger | USB_CDP_CHARGER
- g0 _' p5 W0 n: V | POWER_SUPPLY_TYPE_USB_CDP: F# [5 D/ m; y
| USB_ACA_DOCK_CHARGER
D7 R; |# {. L | POWER_SUPPLY_TYPE_USB_ACA | USB_ACA_A_CHARGER* A$ V' J' \9 c
| USB_ACA_B_CHARGER
& U3 z3 ^% t8 ?1 |$ A | USB_ACA_C_CHARGER+ M2 e/ @1 }: X; q
| USB_DCP_CHARGER
2 c7 Q* e4 J4 I0 j | POWER_SUPPLY_TYPE_USB_DCP | AC Charger | USB_PROPRIETARY_CHARGER
; s: D5 T- @) e) W9 ] | / R+ U' f. a" p. ?; A! A
As for the DMS, refer to bold font items, so it is USB charger.& z2 S3 d: S4 p* {% A) n
P! G' i1 c$ V" }# X3. Analysis about source codes
+ r, D" J3 o# \9 k& o) J/ l \* @*******************************************************************
9 L) h* I+ R( f+ i5 n###用户空间的分析如下:0 P9 A/ m, K0 i
1. 检查 /sys/class/power_supply/pm8921-dc/online和
0 W7 Z' x2 G6 d+ K& u5 ]/sys/class/power_supply/usb/online 的值,可以知道是何充电器类型
- h% S& c% ~, b/ a" y$ Y. x @frameworks/base/services/jni/com_android_server_batteryservice.cpp中有
/ `; D& ~+ ^1 W, X/ Y: u int register_android_server_BatteryService(JNIEnv* env) 1 _7 H/ [2 \2 G3 m) H0 v/ L& _( }/ V
{
1 ?+ P0 q4 g! d! u if (strcmp(buf, "Mains") == 0) { ///sys/class/power_supply/pm8921-dc/type == Mains
' i$ I& N( ?& ^+ p1 M snprintf(path, sizeof(path), "%s/%s/online", POWER_SUPPLY_PATH, name);
) C. o3 j J# t& m if (access(path, R_OK) == 0)
- x4 n' |2 @- r1 {- c+ w gPaths.acOnlinePath = strdup(path);
4 r( U& w( \/ R7 F) f- _ W }+ A$ b$ K6 {# Y; l5 ?
}( }* l; _. R$ Q. |8 F
如果/sys/class/power_supply/pm8921-dc/online==1,则插入的充电器是wall; B& ?8 Z. A3 Y1 k& C% f
charger% \* s" ?7 {% Y+ ?
/sys/class/power_supply/usb/online==1,
& {/ e; R: d& ?则插入的充电器是usb charger
, W" L$ ], C3 ^: `' L2 E$ Q' V 调试路径:/sys/kernel/debug/msm_otg
. ?7 w0 |* O" X }5 @7 l7 G2. 分析frameworks/base/services/jni/com_android_server_batteryservice.cpp8 o; W7 q, w( z p* n
a.函数register_android_server_BatteryService将为被frameworks/base/services/jni/onload.cpp中的JNI_OnLoad调用,用于关联java和C++之间的变量7 i( B; Y7 Z$ H4 U4 w7 k9 B3 t
b.jclass clazz = env->FindClass("com/android/server/BatteryService"); //根据java的路径找到batteryservice.java对应的jclass
& W3 S6 i3 C9 r gFieldIds.mAcOnline = env->GetFieldID(clazz, "mAcOnline", "Z");; d5 `5 J$ P) E5 M, {5 V2 S- W5 P
gFieldIds.mUsbOnline = env->GetFieldID(clazz, "mUsbOnline", "Z"); //用于关联batteryservice.java中变量private
. D1 v; H4 [+ i3 c: [0 h1 u+ I2 bboolean mAcOnline和gFieldIds.mAcOnline. g% U3 ^3 c+ M1 N
c. android_server_BatteryService_update
- S/ J7 E0 p4 C' c5 K4 H& \ static JNINativeMethod sMethods[] = {
# y0 y3 O5 ]0 P& |+ O /* name, signature, funcPtr */
7 m- ?/ ^; T, s {"native_update", "()V", (void*)android_server_BatteryService_update},8 M& k9 q; F4 \ f0 N
};
Q l# h1 O. G' a$ Y2 B 关联到native_update@frameworks/base/services/java/com/android/server/batteryservice.java( j6 ^, f( O7 R7 X; C- C8 Q
3. 分析frameworks/base/services/java/com/android/server/batteryservice.java3 E) g& E) e A6 G- R! p( l
a. mPowerSupplyObserver.startObserving("SUBSYSTEM=power_supply"); //注册监听该uevent
+ `7 `+ _; W+ \+ D b. private UEventObserver mPowerSupplyObserver = new UEventObserver() {
4 i( I, }1 v- V) \# b6 E0 R' D' c public void onUEvent(UEventObserver.UEvent event) { //如果就收到来自kernel的uevent,触发该函数
$ n6 p+ r+ t! `6 i( Q' e6 t update(); //-->native_update();和processValues();
/ ^4 o4 y9 f9 l; m }
( F- s1 \1 i3 V2 Y6 R; o% |+ E& a };
3 R6 Y8 ~/ V* m c. native_update函数会通过JNI调用得到更新的mAcOnline和mUsbOnline值; O! h( a/ p3 ?) j* _' ~6 B
d. processValues会根据mAcOnline和mUsbOnline值对mPlugType赋值
* R4 a# t7 b0 s' X a, q if (mAcOnline) {" h- W- I& \ |9 D; k% B! }/ W; P
mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
$ u# b* O- n0 z0 \2 x6 W9 d+ R* A } else if (mUsbOnline) {) D- I; q4 j$ c, i2 C1 Q7 c# K
mPlugType = BatteryManager.BATTERY_PLUGGED_USB;
0 k! v2 v* m8 e0 ?! U- [! L) b } else {! K9 X' p( H! r K
mPlugType = BATTERY_PLUGGED_NONE;8 n! T" C4 k$ ^( H! V* n
}
! d, Z) H9 m! q7 A% \ e. sendIntent函数会准备Intent并且broadcast这个Intent# ?7 i: h4 [5 }# r; Z! x
Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED); //public static final String ACTION_BATTERY_CHANGED = "android.intent.action.BATTERY_CHANGED";@batteryservice.java
" n2 B' L0 f& Z9 I9 p, O7 H intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY0 E8 H3 @4 X! ]$ W% S5 r
| Intent.FLAG_RECEIVER_REPLACE_PENDING);
8 g* q7 b1 _# H' [4 Y . [6 t8 }' g# ~8 p h
intent.putExtra(BatteryManager.EXTRA_PLUGGED, mPlugType);
. @' X# V$ u" [# y3 ]( b0 D1 J ActivityManagerNative.broadcastStickyIntent(intent, null);
7 V* q# y- b0 B0 z( _5 e4. 分析vendor/semc/packages/apps/debugmenu/src/com/sonyericsson/debugmenu/battery.java* ?' y# O" e% N; B9 L
a. 接收intent6 X+ P6 D$ v9 N! m2 `# C% l: t
private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {
, ~ q) R+ @" u( F* I9 j# W9 O @Override
2 X3 s% y6 {$ `1 J2 } public void onReceive(Context arg0, Intent intent) {
2 f y: {0 _- K7 r0 ^ if (intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) {
2 R- G( L l7 w; s+ L' g mPowerInformation.parseIntent(intent);
2 Q5 C* j" a7 \* @3 R, q updateViews(); I1 y2 K; c. Q
}# |: i; ` R3 S: n8 O& s6 o
}
" E5 `5 \; K6 L, _ };' y- _8 ~! @9 Q8 ~ r
public void registerBroadcastReceivers() {
( E c; B& B( x1 x5 |$ n1 k IntentFilter mIntentFilter;
5 v8 b; Y# Y& X$ w9 I: Y mIntentFilter = new IntentFilter();
( }7 t6 N; X, d' K mIntentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); //只接收Intent.ACTION_BATTERY_CHANGED的intent
; a8 O1 R3 o# H$ P4 e // Register battery receiver. b- `' t9 G$ G
registerReceiver(mBatteryInfoReceiver, mIntentFilter);1 G5 z- `: u$ k9 o- t5 h
}
( ?, U3 E$ p6 h! D" Y# _' f b. parseIntent 得到最新的"plugged"值赋给mPlugged. T) v; y7 \( |+ R t
c. updateViews 更新charger类型显示
* ~2 e) K0 j6 K6 ^$ T###内核空间
0 S- E! G4 ^# b: H# M% L1. 插入充电器触发的过程@kernel/drivers/usb/otg/msm_otg.c
; V) \& J' O( W- o/ T0 G m3 S0 ^ a. CONFIG_PM_RUNTIME 定义 @kernel/arch/arm/configs/viskan_huashan_defconfig
T% r2 b" _8 H9 \& K. A b.msm_otg_runtime_resume-->msm_otg_resume-->??-->msm_otg_sm_work
7 l2 @( M$ }' e3 T+ T* q- I c.msm_otg_sm_work,先进入OTG_STATE_UNDEFINED case,然后进入OTG_STATE_B_IDLE
% Y- v" R5 x$ H7 m+ v k8 Ccase-->motg->chg_state=USB_CHG_STATE_UNDEFINED-->启动msm_chg_detect_work
Y. w! }( t1 L: B {2 T d.msm_chg_detect_work 该函数主要完成USB charger类型的识别
5 n& F" x" k0 X7 e2 } J) C( Z USB_CHG_STATE_UNDEFINED //其中psy = power_supply_get_by_name("usb");很关键,表明只是获取usb的power_supply,实际上就是chip->usb_psy@pm8921-charger.c! X9 e/ i% \3 {9 b& C( s
USB_CHG_STATE_WAIT_FOR_DCD //Waiting for Data pins contact.
9 [) c9 V+ r/ t% y/ t# c' V 然后多次(MSM_CHG_DCD_MAX_RETRIES=6)检测USB状态,启动queue_delayed_work(motg->wq,' h" v! \: k2 P; i5 r3 b, p6 L y
&motg->chg_work, delay); //motg->chg_work=msm_chg_detect_work
D0 ]" t7 V# R0 M. | USB_CHG_STATE_DETECTED //最后USB charge类型检测完毕
! {3 H% H3 w. p7 T e. 启动queue_work(motg->wq, &motg->sm_work); //motg->sm_work=msm_otg_sm_work
4 @ p4 g+ b! s" W) Z2 f f. 由于motg->chg_state==USB_CHG_STATE_DETECTED,7 N. i7 f% S K
motg->chg_type==USB_DCP_CHARGER -->msm_otg_notify_charger(motg,IDEV_CHG_MAX);//IDEV_CHG_MAX=15005 o4 r; S! a: j* Y( t7 e
2. 发送uevent到用户层
7 m8 N# S% |+ z- n) I: e a. msm_otg_notify_charger@kernel/drivers/usb/otg/msm_otg.c# s) @& t) Q4 C# o7 o
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- x1 O! {: j: Y) c) G; v( w# O
c. -->power_supply_set_supply_type@power_supply_core.c // set type of the power supply
( `! H' }0 G- ?5 b$ E) x0 H d. -->psy->set_property(psy, POWER_SUPPLY_PROP_TYPE,&ret);1 O2 t( u# u4 L5 L- ]" ~
那么在用usb_psy.get_property和dc_psy.get_property
7 P. M+ Y7 R9 V7 D2 ^+ s(在函数中pm8921_charger_probe)读取property时
7 Q+ n# {/ `# V. |2 U 如果是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
9 M( Y3 k( n! ~2 V, W% f* Qcharger' `9 Y, U x" w- D3 w
如果是AC type,则在pm_power_get_property_mains读取POWER_SUPPLY_PROP_ONLINE的值,只有POWER_SUPPLY_TYPE_USB_DCP为AC# F# y; s6 Y0 J
charger.
% V9 x" \8 F% |+ p9 D' i/ \ 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( T9 V/ H( M' h: M3 O
f. -->pm8921_set_usb_power_supply_type(val->intval)@pm8921-charger.c9 O% b1 m- [$ D5 b8 _
-->power_supply_changed(&the_chip->usb_psy);
2 h& O5 f! S$ ]/ z' y -->power_supply_changed(&the_chip->dc_psy);9 M+ L$ G# g; O2 J i
g. power_supply_changed@pm8921-charger.c , 就会马上发送uevent给user
8 z' X# L, W7 G: Mspace,然后user space通过sysfs得到USB
: @+ P; U& _8 \/ P* _( itype变化后的信息,参考用户空间的分析4 F& Q2 P. t8 ^! p- ^6 i6 j
5 R A) @! x: G7 o6 M( k5 l) \6 m+ B
二、硬件分析
! P4 _1 |1 b$ a- f% j, e# O9 l$ p3 f% R. F9 H0 g
主要是通过特殊设计的电路,检测不同的pin的状态,从而确定是何种类型的Charger. 更details的内容省略。
`; e7 P( P) ^0 d7 }0 n9 l
! p5 v: I% p) y I
% i$ v. t2 ^7 q$ u5 T2 @
! _2 F) O$ W! L5 ~& i |
|