找回密码
 注册
查看: 2656|回复: 2
打印 上一主题 下一主题

USB port 如何识别不同的Charger类型

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2015-9-11 22:40 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
USB port 如何识别不同的Charger类型
  d  x8 T4 h! I; c9 G+ L5 f2013年10月03日 ⁄ 综合 ⁄ 共 8924字        ⁄ 字号 [url=]小[/url] [url=]中[/url] [url=]大[/url] ⁄ 评论关闭! ?. Z$ E( w0 K' C: l. X
/ {0 V. q1 W( J' H4 T$ K5 R- N
一,软件分析1.  USB charger types & Power supply types. v' Y; A3 z; I. [8 J/ [
USB_INVALID_CHARGER              Invalid USB charger.5 Z  `6 @! d& c- g9 }+ \. `, [
USB_SDP_CHARGER                       Standard downstream port. Refers to a downstream port  on USB2.0 compliant host/hub.
: R* w9 L' d6 v/ }USB_DCP_CHARGER                      Dedicated charger port (AC charger/ Wall charger).4 q$ c. G; Z/ V! G+ p
USB_CDP_CHARGER                      Charging downstream port. Enumeration can happen and IDEV_CHG_MAX can be drawn irrespective of USB state.
  O2 {5 T! C% K% J2 XUSB_ACA_A_CHARGER                                
, E, \6 [# h% n- [B-device is connected on accessory port with charger connected on charging port. This configuration allows charging in host mode.: @6 Y) b7 M( r: t/ _9 j) K4 ~
USB_ACA_B_CHARGER                 No device (or A-device without VBUS) is connected on accessory port with charger connected on charging port.+ W8 O% R# c  K& b# x/ M
USB_ACA_C_CHARGER                 A-device (with VBUS) is connected on accessory port with charger connected on charging port.
5 |  Z7 x* h+ _  n( 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& s( m' n' |( `- G$ G2 c
ports.' `) w# a; K5 _4 t3 o5 W  B) T
USB_PROPRIETARY_CHARGER   A proprietary charger pull DP and DM to specific voltages between 2.0-3.3v for identification.
( d7 O9 v2 B5 V . B9 r) i2 [3 J$ l* b/ k  C9 p0 w
POWER_SUPPLY_TYPE_USB,                     
9 C0 m8 Z) G9 B7 u/* Standard Downstream Port */
6 i& c1 V) B7 E0 wPOWER_SUPPLY_TYPE_USB_DCP,           /* Dedicated Charging Port */4 G& n/ ]2 X! U# i; S
POWER_SUPPLY_TYPE_USB_CDP,           /* Charging Downstream Port */
: N! q6 y0 |. D, wPOWER_SUPPLY_TYPE_USB_ACA,           /* Accessory Charger Adapters */( K( }+ z$ a( D# v: U' B
POWER_SUPPLY_TYPE_BMS,                     
; G. j3 v* j4 [; B/* Battery Monitor System */  D, ^# b& J! w8 I" ^/ H+ J

0 e/ V4 e" y. m0 M" s7 \! K2. How to classify or identify charger?- m5 t" D6 N' _/ g4 p- o

2 Z  g  {, [7 r7 F/ c5 v# V
USB_SDP_CHARGER7 B+ E( D! }" o8 i" T* q
POWER_SUPPLY_TYPE_USB0 h0 F' t% N: M; `- y6 R
USB Charger
USB_CDP_CHARGER
4 N& h+ [! c( e! N5 O
POWER_SUPPLY_TYPE_USB_CDP9 F/ O0 |7 u1 @! d5 }
USB_ACA_DOCK_CHARGER
5 F+ z  P' i- H, E' r* \/ s- b+ G0 o
POWER_SUPPLY_TYPE_USB_ACA
USB_ACA_A_CHARGER
$ c$ `+ B8 p+ Z( v' s
USB_ACA_B_CHARGER
" y9 }( C+ y2 m) _
USB_ACA_C_CHARGER0 x- B: m7 S/ m- G* F
USB_DCP_CHARGER/ k7 }" X( Z$ ?: |* c. a, ]
POWER_SUPPLY_TYPE_USB_DCP
AC Charger
USB_PROPRIETARY_CHARGER; Q% v. u! m9 V( ]( s2 y6 E

2 {( k0 @3 z8 L( P  yAs for the DMS, refer to bold font items, so it is USB charger.
& Z# _' R0 Q# M6 R+ e) M$ X. V) j
* @+ a1 r8 H/ ^0 a& Y( d. F3. Analysis about source codes
5 }* h! m4 ?3 z2 J*******************************************************************- E/ ?0 g9 _6 G. P5 \
###用户空间的分析如下:
4 W2 p# u* C3 h' s. p( f1. 检查 /sys/class/power_supply/pm8921-dc/online和( n; Y) j! C" O% ?+ x0 S1 v
/sys/class/power_supply/usb/online 的值,可以知道是何充电器类型
* W2 ~) @: [% M, p, ^                @frameworks/base/services/jni/com_android_server_batteryservice.cpp中有
( J5 D- _' n0 D* D4 O7 S                int register_android_server_BatteryService(JNIEnv* env)          - {9 d$ C# V/ G) N
                {
0 |: B7 }  W- g7 N- }: P                if (strcmp(buf, "Mains") == 0) { ///sys/class/power_supply/pm8921-dc/type == Mains
' f" w8 z" l+ K! Q* M9 ?& I                    snprintf(path, sizeof(path), "%s/%s/online", POWER_SUPPLY_PATH, name);
  Q! n9 U4 A3 l' g  O                    if (access(path, R_OK) == 0)1 Z% x% w* v3 z8 z' h
                        gPaths.acOnlinePath = strdup(path);
" N7 J7 v  K7 x: G, G                }( w7 h/ ?4 N2 j& `5 V" ~' Z
                }# y8 _8 ?3 d' o+ n) j* X
   如果/sys/class/power_supply/pm8921-dc/online==1,则插入的充电器是wall
; O$ u8 Q4 e: e/ }* w3 R! icharger

5 ?4 {! i/ T( m! v      /sys/class/power_supply/usb/online==1,
8 i$ m9 J& }% H. @- r( @) j则插入的充电器是usb charger

, C4 r9 x1 }! I* z' V" R0 y   调试路径:/sys/kernel/debug/msm_otg8 n( f- u$ g2 o8 P
2. 分析frameworks/base/services/jni/com_android_server_batteryservice.cpp
7 a* d0 C: h( D1 G& ^' s7 s- x! ^. d- {                a.函数register_android_server_BatteryService将为被frameworks/base/services/jni/onload.cpp中的JNI_OnLoad调用,用于关联java和C++之间的变量" C8 v# c: I; K3 J" M9 q$ I) F9 d
                b.jclass clazz = env->FindClass("com/android/server/BatteryService"); //根据java的路径找到batteryservice.java对应的jclass    # z1 {0 I2 o# B8 c( A$ ~
                  gFieldIds.mAcOnline = env->GetFieldID(clazz, "mAcOnline", "Z");
& W& E8 q* o# p% [5 O5 }                  gFieldIds.mUsbOnline = env->GetFieldID(clazz, "mUsbOnline", "Z"); //用于关联batteryservice.java中变量private
0 c% F7 v. X: p% |9 Rboolean mAcOnline和gFieldIds.mAcOnline
  o0 s( r3 G; K+ k: P( ?                c. android_server_BatteryService_update! y$ J- T& S# p& ?' |; Y9 l; e
                                static JNINativeMethod sMethods[] = {" U# e- q- t$ _! g! v
                                     /* name, signature, funcPtr */
6 }( i$ o! w0 ~2 Y) O8 b, U                                                {"native_update", "()V", (void*)android_server_BatteryService_update},
  @' t* q8 l$ L/ Z0 L  n3 u6 |                                };1 r1 D5 E: h7 x+ ~, x
                   关联到native_update@frameworks/base/services/java/com/android/server/batteryservice.java
+ G8 d% B! n( n, ]. L: g: v3. 分析frameworks/base/services/java/com/android/server/batteryservice.java- I* S% c& Q: P. L
                a. mPowerSupplyObserver.startObserving("SUBSYSTEM=power_supply"); //注册监听该uevent
( n: i. R0 `: Y, D                b.     private UEventObserver mPowerSupplyObserver = new UEventObserver() {% F! `) r( Y9 D7 i
                                public void onUEvent(UEventObserver.UEvent event) { //如果就收到来自kernel的uevent,触发该函数
0 y7 i& q* @. h" r5 l: [5 i6 r                                    update(); //-->native_update();和processValues();
% y- Q/ [2 {5 u4 g2 U' z                                }
6 t: \& N# n  K; f) r2 H                       };; ]; C% M1 j5 G% i  J6 T6 O. L
                c. native_update函数会通过JNI调用得到更新的mAcOnline和mUsbOnline值  v7 ]0 K; r) \$ ~) D0 t% U% M
                d. processValues会根据mAcOnline和mUsbOnline值对mPlugType赋值+ T* z# Y/ ?# L+ I- G) a
                                if (mAcOnline) {
5 U8 z& `/ E& F4 [  J                                    mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
! L0 [& K' \5 D                                } else if (mUsbOnline) {
+ T4 d* s  `+ J$ T2 a                                    mPlugType = BatteryManager.BATTERY_PLUGGED_USB;" A& b: c3 @9 o- j: f* H
                                } else {
) K( u0 L/ b  c6 V. y4 h                                    mPlugType = BATTERY_PLUGGED_NONE;- R( m& E4 u8 t! M
                                }1 t4 ?; m7 S2 f# _$ Z: M4 j& o
                e. sendIntent函数会准备Intent并且broadcast这个Intent
/ z$ }+ C# \8 S3 r2 w/ a                                Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED); //public static final String ACTION_BATTERY_CHANGED = "android.intent.action.BATTERY_CHANGED";@batteryservice.java: }' \* Q4 \/ B' ^% \8 Q* V
                                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY- I, i# D& a6 u
                                        | Intent.FLAG_RECEIVER_REPLACE_PENDING);
0 H/ q: H1 w% N# ]' N, l; X& u * \! d2 r. f5 C; x# m2 W0 C
                        intent.putExtra(BatteryManager.EXTRA_PLUGGED, mPlugType);
5 Q- K' I9 Q7 }. m( B  Y1 C8 A                                ActivityManagerNative.broadcastStickyIntent(intent, null);
# g7 N3 `) S4 `9 E4. 分析vendor/sEMC/packages/apps/debugmenu/src/com/sonyericsson/debugmenu/battery.java
8 v9 q& `" O' m, f) j# O+ G                a. 接收intent* J* s3 N4 p0 L- O8 D5 p
                    private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {( w0 Q3 w& N# N0 U) c+ k
                                @Override' u# ?& Y7 {; ~6 w" x+ u7 S/ K
                                public void onReceive(Context arg0, Intent intent) {
, t4 L7 R3 ~3 w, i                                    if (intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) {* F+ B4 I1 `9 A( n
                                        mPowerInformation.parseIntent(intent);
" p8 p9 N% Z% |                                        updateViews();+ @& X. W: r, J" |% Z
                                    }
) G; K* S. R. @, m, }& g3 Y                                }/ e3 f" B* W; R4 W7 V; C
                    };! O( G7 P6 o7 N9 @0 e
                    public void registerBroadcastReceivers() {
0 k9 F8 E! f, A                                IntentFilter mIntentFilter;4 ]1 a  n7 u1 r. T' E
                                mIntentFilter = new IntentFilter();
3 W' r6 G0 x1 A* e! I7 k0 U; P                                mIntentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); //只接收Intent.ACTION_BATTERY_CHANGED的intent
3 S: J6 L% G1 `  x) h2 V                                // Register battery receiver." ^/ {1 |, }3 z. G* S
                                registerReceiver(mBatteryInfoReceiver, mIntentFilter);, |' |# j, I9 L4 Y# n1 D) [
                    }         - ~- {- L+ c3 n1 B( y2 p5 o9 x* m0 Z  b
                b. parseIntent 得到最新的"plugged"值赋给mPlugged+ j1 [3 j) _( Q6 ]
                c. updateViews 更新charger类型显示
$ c0 H7 y. V9 z/ U( j* }###内核空间' l1 B$ t, n# E4 u! o) A# g2 _
1. 插入充电器触发的过程@kernel/drivers/usb/otg/msm_otg.c
$ }, L; H' h+ r                a. CONFIG_PM_RUNTIME 定义 @kernel/arch/ARM/configs/viskan_huashan_defconfig
) i. v! k% N% V( c3 t                b.msm_otg_runtime_resume-->msm_otg_resume-->??-->msm_otg_sm_work
5 q6 T( d7 ^3 Y                c.msm_otg_sm_work,先进入OTG_STATE_UNDEFINED case,然后进入OTG_STATE_B_IDLE$ s4 n$ H/ z( x
case-->motg->chg_state=USB_CHG_STATE_UNDEFINED-->启动msm_chg_detect_work
! p! i& D5 M; L: p                d.msm_chg_detect_work 该函数主要完成USB charger类型的识别
9 N; V) x+ C; [/ r                                USB_CHG_STATE_UNDEFINED //其中psy = power_supply_get_by_name("usb");很关键,表明只是获取usb的power_supply,实际上就是chip->usb_psy@pm8921-charger.c
$ i; I1 i' R5 h; T2 F) }  h                                USB_CHG_STATE_WAIT_FOR_DCD         //Waiting for Data pins contact.
( L, `0 K" v5 s. X& k                                然后多次(MSM_CHG_DCD_MAX_RETRIES=6)检测USB状态,启动queue_delayed_work(motg->wq,
+ K0 y" p) H9 ]" i5 i8 K&motg->chg_work, delay); //motg->chg_work=msm_chg_detect_work
- r9 c1 ^4 \5 v, [( l: ^                                USB_CHG_STATE_DETECTED //最后USB charge类型检测完毕
4 d% I6 K, t- ]' k                e. 启动queue_work(motg->wq, &motg->sm_work); //motg->sm_work=msm_otg_sm_work
+ K2 `- w1 Z' V$ a( z                f. 由于motg->chg_state==USB_CHG_STATE_DETECTED,
1 D; g2 _- y* r8 J3 E* d% T                                motg->chg_type==USB_DCP_CHARGER -->msm_otg_notify_charger(motg,IDEV_CHG_MAX);//IDEV_CHG_MAX=1500- ?* |& |7 U4 p6 E. q2 J4 _' y
2. 发送uevent到用户层
5 o6 Y" {) X9 \0 g0 y% I                a. msm_otg_notify_charger@kernel/drivers/usb/otg/msm_otg.c
1 W) f* p" ]! H5 D" U: S4 q0 t                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, f- @) z4 }/ V# |# N) l& `
                c. -->power_supply_set_supply_type@power_supply_core.c // set type of the power supply4 ~1 D5 {4 R3 k/ l
                d. -->psy->set_property(psy, POWER_SUPPLY_PROP_TYPE,&ret);% C4 h4 l4 X! @+ l
                                那么在用usb_psy.get_property和dc_psy.get_property- s# p" x- ~7 n
(在函数中pm8921_charger_probe)读取property时8 ^4 x" g7 [' x% ?5 K* e! q
                                如果是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( W* _7 S: p9 l; |) E
charger. R' z* o! K( A0 ~
                                如果是AC type,则在pm_power_get_property_mains读取POWER_SUPPLY_PROP_ONLINE的值,只有POWER_SUPPLY_TYPE_USB_DCP为AC2 Y& ]& @) [! Z5 n: ^, B+ o2 k
charger.- _2 P0 P" [3 d1 \" c
                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/ w4 w. h. J1 ?& R" J( h1 h
                f. -->pm8921_set_usb_power_supply_type(val->intval)@pm8921-charger.c
0 N+ l, U" m5 z/ C& q                                -->power_supply_changed(&the_chip->usb_psy);
6 }. ]& Z) Y+ z, ?& p+ ^0 z$ R                                -->power_supply_changed(&the_chip->dc_psy);; D( y- ]( F( o- C! q. U2 K7 A
                g. power_supply_changed@pm8921-charger.c , 就会马上发送uevent给user
* c5 Z+ ~4 d4 `" O7 k. i8 `  ~% t" jspace,然后user space通过sysfs得到USB2 N/ \+ G% [0 B0 |& N( S5 v/ q
type变化后的信息,参考用户空间的分析
6 V& l0 x3 h* i7 x
' x; I+ i( k: d# ~3 `二、硬件分析* a! F; n2 K0 [

1 f- q, i, r9 E( k, s7 ]% C2 g主要是通过特殊设计的电路,检测不同的pin的状态,从而确定是何种类型的Charger. 更details的内容省略。
, O6 B- z. Q3 [, Z4 n! N% `3 I6 p% E' K+ f/ U. g1 O! N  P# V

( ~6 y' {- H6 d* i% ], j& |- S, Q& i% T1 ]6 a# T

该用户从未签到

3#
发表于 2015-10-20 22:16 | 只看该作者
        顶一下,问题有点长。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-5-28 16:08 , Processed in 0.109375 second(s), 24 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表