|
EDA365欢迎您!
您需要 登录 才可以下载或查看,没有帐号?注册
x
USB port 如何识别不同的Charger类型
5 O6 I* D- `; s1 |0 R3 }6 f2013年10月03日 ⁄ 综合 ⁄ 共 8924字 ⁄ 字号 [url=]小[/url] [url=]中[/url] [url=]大[/url] ⁄ 评论关闭' u- o; K# r. m8 B4 }
- n& s! E) S% l1 ?8 a, D一,软件分析1. USB charger types & Power supply types
" q% {7 N! J# I8 Q( iUSB_INVALID_CHARGER Invalid USB charger.
( O4 B4 x( v# h8 JUSB_SDP_CHARGER Standard downstream port. Refers to a downstream port on USB2.0 compliant host/hub.) e# j; g7 T4 ^& u7 D6 c0 H
USB_DCP_CHARGER Dedicated charger port (AC charger/ Wall charger).
+ I$ k5 D% o6 v8 L% d5 T) k5 m6 gUSB_CDP_CHARGER Charging downstream port. Enumeration can happen and IDEV_CHG_MAX can be drawn irrespective of USB state.. c3 ?) p* \' |3 h$ j) q' [
USB_ACA_A_CHARGER : H: I3 K F% a' ^
B-device is connected on accessory port with charger connected on charging port. This configuration allows charging in host mode./ g, [/ a- }0 K! ~5 L9 v5 M1 ~
USB_ACA_B_CHARGER No device (or A-device without VBUS) is connected on accessory port with charger connected on charging port.
# R6 k- B: w' Z* iUSB_ACA_C_CHARGER A-device (with VBUS) is connected on accessory port with charger connected on charging port.
; ~ `1 w/ ~5 A+ ]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
6 t" C1 O1 i9 ~( y* @/ Jports., t c3 S7 s: O; j& C
USB_PROPRIETARY_CHARGER A proprietary charger pull DP and DM to specific voltages between 2.0-3.3v for identification.
; I, D; a# E% L# {2 D7 J! }: @ " v: ^$ W: m+ W: D- P1 l, M1 G
POWER_SUPPLY_TYPE_USB,
3 l* q# z( S7 f! `/* Standard Downstream Port */
; O& A. r2 M& e/ hPOWER_SUPPLY_TYPE_USB_DCP, /* Dedicated Charging Port */7 J0 ]8 o4 Z) N0 I; a1 k/ F
POWER_SUPPLY_TYPE_USB_CDP, /* Charging Downstream Port */
( q& T+ N* `! M: I/ _: yPOWER_SUPPLY_TYPE_USB_ACA, /* Accessory Charger Adapters */
0 O! ]) D0 e7 M7 D( yPOWER_SUPPLY_TYPE_BMS,
" u) u% O7 M, N; D% ~$ J/* Battery Monitor System *// D. A3 Y* |! N% A1 B. z6 b
( O7 M4 v( P3 ]' d( V5 ]6 I; D8 u2. How to classify or identify charger?
- w; Q8 r. \! F# Y- W
- r& |+ k0 V6 k: Q% \9 MUSB_SDP_CHARGER+ v2 F; B. y9 ? k
| POWER_SUPPLY_TYPE_USB# ?' e5 `8 Y9 _$ D% C* C
| USB Charger | USB_CDP_CHARGER
7 O2 r5 e; i5 W' S1 T s2 s( C* a | POWER_SUPPLY_TYPE_USB_CDP( @2 A y5 H9 L
| USB_ACA_DOCK_CHARGER
& m5 L) L, ]- U6 r. c' O | POWER_SUPPLY_TYPE_USB_ACA | USB_ACA_A_CHARGER. G$ ]* g# \5 z* j! f$ E* D
| USB_ACA_B_CHARGER
; p" `$ p8 @! J | USB_ACA_C_CHARGER
. E: ?& q( w, W$ c# A( p3 g* S | USB_DCP_CHARGER* ]; @( }: c) i( d) k+ s
| POWER_SUPPLY_TYPE_USB_DCP | AC Charger | USB_PROPRIETARY_CHARGER- }3 c; d3 @( d& a: }; S5 v
|
& T/ g% d: R( W+ ~9 j/ JAs for the DMS, refer to bold font items, so it is USB charger.
1 p. P+ u7 e m" S1 _1 e k* }
' x3 F) Z5 D) J f3. Analysis about source codes
$ D/ `/ j/ V* o+ G& n( X" n*******************************************************************( q" y! M/ H1 P: ]7 Q8 S2 |
###用户空间的分析如下:) _. |- }* Q O, a9 d& l' ?
1. 检查 /sys/class/power_supply/pm8921-dc/online和0 j) z" `! @2 F
/sys/class/power_supply/usb/online 的值,可以知道是何充电器类型
7 ~% W3 I% H# x5 H+ x5 f @frameworks/base/services/jni/com_android_server_batteryservice.cpp中有
9 F! u7 k% m P/ C' R int register_android_server_BatteryService(JNIEnv* env)
+ J9 E# j+ |- Z' i, o% t- L- c2 S {8 v0 V8 @/ Q2 Z5 V) O1 s
if (strcmp(buf, "Mains") == 0) { ///sys/class/power_supply/pm8921-dc/type == Mains
* S# x/ F6 r9 I3 J snprintf(path, sizeof(path), "%s/%s/online", POWER_SUPPLY_PATH, name);
+ Q% X9 Z) Q+ ?& O U if (access(path, R_OK) == 0)
# H$ i7 i$ x0 t7 u* F6 g1 Q gPaths.acOnlinePath = strdup(path);
& [% W/ Q5 W$ ~3 G- D }
& ~; n, n6 d% k- \: j+ m) o/ x }" Z, C/ j) [# R* ?
如果/sys/class/power_supply/pm8921-dc/online==1,则插入的充电器是wall5 K/ ]' q p' O
charger) g" I0 z* z. B; J W8 M z3 n' |- A& ^
/sys/class/power_supply/usb/online==1,
0 r7 K9 o, J: N; [% S4 W- b! @则插入的充电器是usb charger
2 D/ ?" \. Y5 ~6 ~6 V+ ` 调试路径:/sys/kernel/debug/msm_otg4 j' ]9 b% f2 {/ {2 Y! B& F2 I" h
2. 分析frameworks/base/services/jni/com_android_server_batteryservice.cpp
' @% t* g8 z+ C; @4 h# Q a.函数register_android_server_BatteryService将为被frameworks/base/services/jni/onload.cpp中的JNI_OnLoad调用,用于关联java和C++之间的变量( ~* Z8 q; S, N* G. P1 w
b.jclass clazz = env->FindClass("com/android/server/BatteryService"); //根据java的路径找到batteryservice.java对应的jclass ; z3 V6 r& g: O$ p# L
gFieldIds.mAcOnline = env->GetFieldID(clazz, "mAcOnline", "Z");# C1 U6 e7 g" t" r5 d( a* S* s6 Q
gFieldIds.mUsbOnline = env->GetFieldID(clazz, "mUsbOnline", "Z"); //用于关联batteryservice.java中变量private
1 y% T3 l3 J" ^+ Kboolean mAcOnline和gFieldIds.mAcOnline, a: H% ~! T& l/ X( P
c. android_server_BatteryService_update
k/ m8 F1 W! q u. P static JNINativeMethod sMethods[] = {6 v# W; ^9 A2 e! h, Y
/* name, signature, funcPtr */
1 Y( a! G1 r H |& J {"native_update", "()V", (void*)android_server_BatteryService_update},+ V/ D! x; a# X
};
. [7 H! M) ^7 N' ~- s 关联到native_update@frameworks/base/services/java/com/android/server/batteryservice.java
! a8 Y. y: x: z) u3. 分析frameworks/base/services/java/com/android/server/batteryservice.java3 x; S! `3 z* d4 Q/ F
a. mPowerSupplyObserver.startObserving("SUBSYSTEM=power_supply"); //注册监听该uevent
% U+ d) a8 X2 g" F4 c: p& D b. private UEventObserver mPowerSupplyObserver = new UEventObserver() {
9 c! ?4 Q, R% S) D/ Z public void onUEvent(UEventObserver.UEvent event) { //如果就收到来自kernel的uevent,触发该函数 S0 s. Q9 i' C( U
update(); //-->native_update();和processValues();
/ v" p5 b, z9 _7 t/ Y8 s }
E1 u- t2 \8 A };
# A" o6 ?6 H+ J$ u4 G( C3 _. i3 Q. u c. native_update函数会通过JNI调用得到更新的mAcOnline和mUsbOnline值
# l: u% Z# o# n9 T! Y1 Z M d. processValues会根据mAcOnline和mUsbOnline值对mPlugType赋值
$ t5 r" o" E( T if (mAcOnline) {- ?. O% x; \* W* G" T6 ?0 t
mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
1 p7 |2 ~: N" Q# E& D2 G/ z& H } else if (mUsbOnline) {' t8 W6 h$ m0 \; j& ?- u
mPlugType = BatteryManager.BATTERY_PLUGGED_USB;& W% G6 a; f3 W( n, W
} else {
- O8 G4 H$ ?' E+ G, L5 e mPlugType = BATTERY_PLUGGED_NONE;
$ o& f0 J! S+ L" _ }
2 l) y- U6 O+ d/ D e. sendIntent函数会准备Intent并且broadcast这个Intent8 }* S. w; n" |/ V. j+ Z+ r: B" f
Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED); //public static final String ACTION_BATTERY_CHANGED = "android.intent.action.BATTERY_CHANGED";@batteryservice.java2 Y# P1 C, e2 t4 Q; }/ a
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY) P* l0 ^4 K1 F6 M7 ]$ t
| Intent.FLAG_RECEIVER_REPLACE_PENDING);/ [; c) z P1 Z( ^2 M5 b4 I3 X8 I* t/ U7 s
$ o/ x; O+ P. _+ g) o
intent.putExtra(BatteryManager.EXTRA_PLUGGED, mPlugType);/ T+ }0 k w9 _9 d( x
ActivityManagerNative.broadcastStickyIntent(intent, null);
; {+ `3 G, [6 ]6 {5 x4. 分析vendor/semc/packages/apps/debugmenu/src/com/sonyericsson/debugmenu/battery.java( M" ?7 w, P# e9 q
a. 接收intent
. v% w! s/ I! Z. [+ } private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {) U, N5 e. s8 N, [: e! ?+ Z9 n
@Override, i; a. }/ k6 r6 C1 \6 L" P
public void onReceive(Context arg0, Intent intent) {1 J9 W' L2 @7 t
if (intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) {$ y5 |$ M3 d p$ n$ r0 a; q
mPowerInformation.parseIntent(intent);! o# m! _! Y+ D( P: J' Y6 B
updateViews();
: Z& i- p. C& T( y% y }' Z4 r8 u9 S% h3 z( ]* R V0 a0 P# {
}
: m8 v9 A6 ~9 x$ w1 ?& j };5 n" b; m4 N4 m
public void registerBroadcastReceivers() {
+ c& Z- D, o8 k* M) T6 J IntentFilter mIntentFilter;
# C! b0 {6 o6 x r+ O" z mIntentFilter = new IntentFilter();
u- \4 w0 b+ a2 G: S# q. W mIntentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); //只接收Intent.ACTION_BATTERY_CHANGED的intent
7 s, u8 H( N2 H E" H8 K // Register battery receiver.' [, c& h Z4 s: a
registerReceiver(mBatteryInfoReceiver, mIntentFilter);
) D3 m! E" u; _, p3 R- P4 n* p3 h }
4 ^5 l; v% k# p. q* a1 S* M b. parseIntent 得到最新的"plugged"值赋给mPlugged& I- f# @, y4 d X5 ?
c. updateViews 更新charger类型显示4 A: g% S- Q$ i7 t; I, A
###内核空间7 d, r1 K ~8 t" R% j% ^
1. 插入充电器触发的过程@kernel/drivers/usb/otg/msm_otg.c
& N2 V0 V1 J, q9 ~3 [ a. CONFIG_PM_RUNTIME 定义 @kernel/arch/arm/configs/viskan_huashan_defconfig
9 o0 G* d$ V0 y% V0 B3 | b.msm_otg_runtime_resume-->msm_otg_resume-->??-->msm_otg_sm_work
+ K7 _2 r( T& Y( ]* X( y c.msm_otg_sm_work,先进入OTG_STATE_UNDEFINED case,然后进入OTG_STATE_B_IDLE
2 q( E" a! Z: a! Z) ~case-->motg->chg_state=USB_CHG_STATE_UNDEFINED-->启动msm_chg_detect_work
) J! R, M2 ?8 o7 _4 d d.msm_chg_detect_work 该函数主要完成USB charger类型的识别$ K6 U" T; U* f& M; d0 |
USB_CHG_STATE_UNDEFINED //其中psy = power_supply_get_by_name("usb");很关键,表明只是获取usb的power_supply,实际上就是chip->usb_psy@pm8921-charger.c
+ j( F4 _& Z5 ]! [4 x USB_CHG_STATE_WAIT_FOR_DCD //Waiting for Data pins contact.
6 n b4 \& b+ f: ]0 u$ F, r; z 然后多次(MSM_CHG_DCD_MAX_RETRIES=6)检测USB状态,启动queue_delayed_work(motg->wq,
! G, N% [0 B! W0 d4 J K9 k" \- H&motg->chg_work, delay); //motg->chg_work=msm_chg_detect_work
! M! o- F- W; |; A9 S" M% i" N2 Y USB_CHG_STATE_DETECTED //最后USB charge类型检测完毕
) c# U7 G! d+ J' Q- ` e. 启动queue_work(motg->wq, &motg->sm_work); //motg->sm_work=msm_otg_sm_work
5 e; {) i6 x+ E! b, V' c5 ^0 K. ~ f. 由于motg->chg_state==USB_CHG_STATE_DETECTED,
8 j# _; p! E% @1 \ motg->chg_type==USB_DCP_CHARGER -->msm_otg_notify_charger(motg,IDEV_CHG_MAX);//IDEV_CHG_MAX=1500% }4 Z! H I5 f
2. 发送uevent到用户层8 J7 U; w( W2 l5 W/ Q
a. msm_otg_notify_charger@kernel/drivers/usb/otg/msm_otg.c
* E% \& e( I9 S) h, w8 e. 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
* X3 w @0 p" T( S, R5 A' P* w c. -->power_supply_set_supply_type@power_supply_core.c // set type of the power supply
6 ?3 [' s! h9 u. d* T: Q d. -->psy->set_property(psy, POWER_SUPPLY_PROP_TYPE,&ret);6 |' j& g) j0 ^% w: \
那么在用usb_psy.get_property和dc_psy.get_property
( n$ {/ L1 a$ C9 E* b) k(在函数中pm8921_charger_probe)读取property时$ B, c7 r' d" r, A z( O7 ^
如果是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* G/ L, I1 K$ A5 l' S
charger/ L9 k. _" ]- X+ N" C- O
如果是AC type,则在pm_power_get_property_mains读取POWER_SUPPLY_PROP_ONLINE的值,只有POWER_SUPPLY_TYPE_USB_DCP为AC$ o* G" ~! m# f# U% Q' Y
charger.
4 h0 r2 ]* M( D' p 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" a2 y. h* ~' @1 D' X, J
f. -->pm8921_set_usb_power_supply_type(val->intval)@pm8921-charger.c
( p- a) `$ U2 {* a -->power_supply_changed(&the_chip->usb_psy);, p0 W/ C7 Q/ u# g6 K
-->power_supply_changed(&the_chip->dc_psy);7 W0 z" g3 y8 _4 I% X0 V
g. power_supply_changed@pm8921-charger.c , 就会马上发送uevent给user
' @; Z# G$ u) T. K' _: |& w$ pspace,然后user space通过sysfs得到USB
, B* ~) R& p% }% K# P* {type变化后的信息,参考用户空间的分析
/ Q% Q* i; O. @: X6 h; T" ^: y$ P% T$ z, p. L% ?* a
二、硬件分析1 q% Q8 G- K2 s
0 ^* D# E4 i; {" p# Z3 \, f# Q2 \
主要是通过特殊设计的电路,检测不同的pin的状态,从而确定是何种类型的Charger. 更details的内容省略。. b' n/ t* |& i, }0 u7 d% M
$ {% Z3 j; O2 A$ [2 B0 F
4 v) P/ b* _. B: X) w& S4 V3 t! @1 R% L# d* _. [2 S7 z! z
|
|