找回密码
 注册
关于网站域名变更的通知
查看: 2662|回复: 2
打印 上一主题 下一主题

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
USB port 如何识别不同的Charger类型
+ U8 J4 N# n$ ?0 l2013年10月03日 ⁄ 综合 ⁄ 共 8924字        ⁄ 字号 [url=]小[/url] [url=]中[/url] [url=]大[/url] ⁄ 评论关闭
, I  k& s# c) x, @9 d# k/ P4 \% O" ?! R, M
一,软件分析1.  USB charger types & Power supply types
5 }/ J. F7 h& TUSB_INVALID_CHARGER              Invalid USB charger.
, ~7 B3 f8 H$ Z  Z) @USB_SDP_CHARGER                       Standard downstream port. Refers to a downstream port  on USB2.0 compliant host/hub.) x3 ~; x3 ]. G% q. W
USB_DCP_CHARGER                      Dedicated charger port (AC charger/ Wall charger).
. Z! o6 A1 M: k. l" n/ e& |0 TUSB_CDP_CHARGER                      Charging downstream port. Enumeration can happen and IDEV_CHG_MAX can be drawn irrespective of USB state.
, s; D! y+ p. N2 J$ FUSB_ACA_A_CHARGER                                
3 v% E$ l# K$ C% }B-device is connected on accessory port with charger connected on charging port. This configuration allows charging in host mode.
# o; B: u, B9 h7 ]6 UUSB_ACA_B_CHARGER                 No device (or A-device without VBUS) is connected on accessory port with charger connected on charging port.8 W1 W! y8 ^( O0 W" E
USB_ACA_C_CHARGER                 A-device (with VBUS) is connected on accessory port with charger connected on charging port.: c$ [2 }$ b3 r5 e, ?2 \" W
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
  v" j- i4 Z. H, b' U: M: f8 ]ports.( t) ]4 b% j' y' P
USB_PROPRIETARY_CHARGER   A proprietary charger pull DP and DM to specific voltages between 2.0-3.3v for identification.% F# V2 A) K$ u1 I7 J
! P, l8 ^: _5 v
POWER_SUPPLY_TYPE_USB,                      # \- [- m$ o. I& u
/* Standard Downstream Port */
0 A) Q6 D; o# NPOWER_SUPPLY_TYPE_USB_DCP,           /* Dedicated Charging Port */8 {9 z0 Z' B. _
POWER_SUPPLY_TYPE_USB_CDP,           /* Charging Downstream Port */
6 s$ q( Z: }1 _* T; s1 J* I" yPOWER_SUPPLY_TYPE_USB_ACA,           /* Accessory Charger Adapters */$ h, Y; `# Y4 B4 |! V# N$ g7 r3 \& w
POWER_SUPPLY_TYPE_BMS,                     
7 E4 u  M4 a. r- ?/* Battery Monitor System */: J8 [. z8 r, x/ \

% n, G% V  Y; H5 a# f7 b: z2. How to classify or identify charger?: e& `5 v$ V: n# Q, V
) g- W# g* \% C' D$ V# f
USB_SDP_CHARGER
  B/ z. W. q4 `$ A$ R$ ~4 H  g
POWER_SUPPLY_TYPE_USB2 \# H7 l; A, y7 O! `  c( a
USB Charger
USB_CDP_CHARGER
* s2 g' t- S) A' y0 P5 ]9 y% h. i
POWER_SUPPLY_TYPE_USB_CDP  L! b( F8 v: D% o. L; E
USB_ACA_DOCK_CHARGER
5 [: t0 b1 H! q9 H) L
POWER_SUPPLY_TYPE_USB_ACA
USB_ACA_A_CHARGER
0 G7 e" v- m7 R/ M; s
USB_ACA_B_CHARGER# g7 B* ^7 T0 W/ |8 k. Q
USB_ACA_C_CHARGER
0 s! d. G. ]* R& {% A! M) H
USB_DCP_CHARGER) {* \" C1 h6 ~6 R" c. i0 K; m
POWER_SUPPLY_TYPE_USB_DCP
AC Charger
USB_PROPRIETARY_CHARGER
# n: V4 ]! O6 p- u

" h- a  {/ D6 I& q1 v. h- j" K9 s7 {" }As for the DMS, refer to bold font items, so it is USB charger.0 g: r6 X5 w; {8 P* S

. d+ t4 h" y6 P% M1 B+ V! O0 c3. Analysis about source codes
2 q  d, ]/ b1 Y4 Q$ l* D7 c*******************************************************************( O+ H7 E6 I: s. {5 a
###用户空间的分析如下:
: ^3 Q3 j" U4 o' U1. 检查 /sys/class/power_supply/pm8921-dc/online和8 M- Q" V( f; x, O' ?% T3 m8 N
/sys/class/power_supply/usb/online 的值,可以知道是何充电器类型( T$ }1 ~7 v% h9 T9 G
                @frameworks/base/services/jni/com_android_server_batteryservice.cpp中有
" R/ x) `" S5 ?                int register_android_server_BatteryService(JNIEnv* env)          & z4 e7 q# F7 y1 g5 s5 E! j" T
                {
" L4 ^7 m* b: H$ t                if (strcmp(buf, "Mains") == 0) { ///sys/class/power_supply/pm8921-dc/type == Mains
" Y. ]" D" n% g5 Y* C+ m+ c                    snprintf(path, sizeof(path), "%s/%s/online", POWER_SUPPLY_PATH, name);
& v  x1 C4 t' N1 T                    if (access(path, R_OK) == 0)
9 L& |, k' ?& G) H( [                        gPaths.acOnlinePath = strdup(path);8 r7 ?. `0 f$ P, X
                }
# n  [1 I! l& g1 U1 z                }
0 N5 @2 c3 b( w, ]- I* z   如果/sys/class/power_supply/pm8921-dc/online==1,则插入的充电器是wall
; n6 Z5 I/ U! Ccharger
$ D% E5 [: K- b+ [1 K& l
      /sys/class/power_supply/usb/online==1,
' ]! E6 K- P0 B1 X5 W: Q2 V则插入的充电器是usb charger
4 N8 N1 K$ }6 m( |& Q; v
   调试路径:/sys/kernel/debug/msm_otg+ G, F  O: n- J" q5 z8 c
2. 分析frameworks/base/services/jni/com_android_server_batteryservice.cpp
  u5 ]& ~. c* o  `: d                a.函数register_android_server_BatteryService将为被frameworks/base/services/jni/onload.cpp中的JNI_OnLoad调用,用于关联java和C++之间的变量- J; t" K& ?" L1 U+ g$ [5 Y( S
                b.jclass clazz = env->FindClass("com/android/server/BatteryService"); //根据java的路径找到batteryservice.java对应的jclass    2 o; U: M) l  |8 q9 ~' C8 _
                  gFieldIds.mAcOnline = env->GetFieldID(clazz, "mAcOnline", "Z");
3 M. \' v8 T& U# d, L7 X                  gFieldIds.mUsbOnline = env->GetFieldID(clazz, "mUsbOnline", "Z"); //用于关联batteryservice.java中变量private$ [. x; I* W4 Y, V- ^; S9 K
boolean mAcOnline和gFieldIds.mAcOnline
( J: B& y. g* P0 c                c. android_server_BatteryService_update
+ M7 j  o8 M: \; G; ^                                static JNINativeMethod sMethods[] = {
2 ^; o  M/ C9 _( `                                     /* name, signature, funcPtr */
9 _/ B9 }6 z) b! @                                                {"native_update", "()V", (void*)android_server_BatteryService_update},2 B/ F- H. I* b1 L1 `
                                };
8 f) a! D4 c. r' d1 e& U: [, t                   关联到native_update@frameworks/base/services/java/com/android/server/batteryservice.java5 h5 S0 U1 I" U/ G. I- j; k& f
3. 分析frameworks/base/services/java/com/android/server/batteryservice.java
1 e6 ^; U: ~/ ^                a. mPowerSupplyObserver.startObserving("SUBSYSTEM=power_supply"); //注册监听该uevent; @9 E; T( o& Q6 y* @
                b.     private UEventObserver mPowerSupplyObserver = new UEventObserver() {: |0 a- n4 R  l: v4 i
                                public void onUEvent(UEventObserver.UEvent event) { //如果就收到来自kernel的uevent,触发该函数
4 g) B6 @0 B% y- h: g; R                                    update(); //-->native_update();和processValues();
# ~  [3 v6 C+ @$ j                                }( g; H0 y8 k. L9 Z! F$ C
                       };
, z: a' A: I6 j  t                c. native_update函数会通过JNI调用得到更新的mAcOnline和mUsbOnline值) V8 G( \3 O" O' W
                d. processValues会根据mAcOnline和mUsbOnline值对mPlugType赋值7 q9 ~4 b9 s9 J5 ?3 k1 Y
                                if (mAcOnline) {" h* [8 }$ W  }  \3 b0 C
                                    mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
2 C  C1 u; ^4 m) b, @/ M2 O; v                                } else if (mUsbOnline) {7 v: S2 N5 _0 s$ g- D5 T
                                    mPlugType = BatteryManager.BATTERY_PLUGGED_USB;
9 s, ?5 I" e1 R  \, Q7 W4 q6 C                                } else {% S. i7 Q5 B# J* n8 j# N
                                    mPlugType = BATTERY_PLUGGED_NONE;: a, N% w" ~* \
                                }
! n6 L( o/ D- W+ `3 b# n$ }% C                e. sendIntent函数会准备Intent并且broadcast这个Intent9 n* f6 ~# ~  W. U
                                Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED); //public static final String ACTION_BATTERY_CHANGED = "android.intent.action.BATTERY_CHANGED";@batteryservice.java  J/ H1 _* w4 ?) `2 z1 W
                                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY$ u0 b4 R" d. z  Y' s: R
                                        | Intent.FLAG_RECEIVER_REPLACE_PENDING);
: u! `# [" e: A3 h+ H7 a 4 h7 L, _5 U( _& [$ I
                        intent.putExtra(BatteryManager.EXTRA_PLUGGED, mPlugType);/ L- W; _7 Z9 L6 a: A
                                ActivityManagerNative.broadcastStickyIntent(intent, null);# x* D& n+ H# c1 q" K
4. 分析vendor/sEMC/packages/apps/debugmenu/src/com/sonyericsson/debugmenu/battery.java1 M, h2 Z; T( `- k+ T- Q* B
                a. 接收intent9 h2 @: H2 w. o' Q5 M
                    private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {
) w1 |: E0 n: x9 f                                @Override
" N; `2 D. `* ]( J5 g/ J                                public void onReceive(Context arg0, Intent intent) {0 e( c9 c! f1 D0 M! ?7 w. P
                                    if (intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) {! I1 v7 v) m& ]& j
                                        mPowerInformation.parseIntent(intent);
. y, B7 O$ X& N. p) l  e  E                                        updateViews();
& m) L- n2 }. L. r( ?9 O' M1 e                                    }9 E' }( v5 Z* {: h1 f* _
                                }
1 ]: o' N# w, V$ r& u                    };
( j! N4 F( Z5 g/ }                    public void registerBroadcastReceivers() {
. M+ N; I: s) y, Q* }7 u" f# p4 q2 @) ?                                IntentFilter mIntentFilter;
9 I+ Q' s& y8 a+ E: U0 q0 ?; j                                mIntentFilter = new IntentFilter();8 r" O* w4 N( E* I5 k6 o
                                mIntentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); //只接收Intent.ACTION_BATTERY_CHANGED的intent. Q8 u% e8 G+ n1 m0 |  }' F! P
                                // Register battery receiver.8 p% e. v( K2 R# T' H
                                registerReceiver(mBatteryInfoReceiver, mIntentFilter);
' k" }: J. ]/ h' C& U6 p" q2 W/ M                    }         * p4 T2 R6 ^0 f& g
                b. parseIntent 得到最新的"plugged"值赋给mPlugged
4 i  a% [# H0 _, j: i# F5 M                c. updateViews 更新charger类型显示9 D- C& e, c  m& ?' {8 d
###内核空间- G+ \$ N9 n3 i' v- m9 m" s) H
1. 插入充电器触发的过程@kernel/drivers/usb/otg/msm_otg.c
  l* H2 ?. ]- H6 o3 f                a. CONFIG_PM_RUNTIME 定义 @kernel/arch/ARM/configs/viskan_huashan_defconfig6 _) S. t, g# p6 g2 n+ e4 {0 ^
                b.msm_otg_runtime_resume-->msm_otg_resume-->??-->msm_otg_sm_work# {7 g" m+ K& Z9 x( l7 P
                c.msm_otg_sm_work,先进入OTG_STATE_UNDEFINED case,然后进入OTG_STATE_B_IDLE
% _- s4 C. W5 M4 fcase-->motg->chg_state=USB_CHG_STATE_UNDEFINED-->启动msm_chg_detect_work. s1 j  w" n1 I, p: w& a% o
                d.msm_chg_detect_work 该函数主要完成USB charger类型的识别
8 C8 L! q; O  x! k: W                                USB_CHG_STATE_UNDEFINED //其中psy = power_supply_get_by_name("usb");很关键,表明只是获取usb的power_supply,实际上就是chip->usb_psy@pm8921-charger.c
& o8 Y( Y: S7 r: Z                                USB_CHG_STATE_WAIT_FOR_DCD         //Waiting for Data pins contact.
0 M  h6 i# e! A# ]* A: C# r                                然后多次(MSM_CHG_DCD_MAX_RETRIES=6)检测USB状态,启动queue_delayed_work(motg->wq,
4 [% {& j( F. ]/ t' @&motg->chg_work, delay); //motg->chg_work=msm_chg_detect_work; E+ g  b8 Q# K
                                USB_CHG_STATE_DETECTED //最后USB charge类型检测完毕  E) E; w, Q/ ~4 @  \2 g  P! J
                e. 启动queue_work(motg->wq, &motg->sm_work); //motg->sm_work=msm_otg_sm_work
- j! I  p$ t: W6 a3 Y2 X1 U( g) V0 D                f. 由于motg->chg_state==USB_CHG_STATE_DETECTED,
9 j8 j1 J: f: N/ S9 }" q4 q                                motg->chg_type==USB_DCP_CHARGER -->msm_otg_notify_charger(motg,IDEV_CHG_MAX);//IDEV_CHG_MAX=15009 T( _: E, q2 G9 d2 c0 v: N
2. 发送uevent到用户层
9 w4 a, g8 c% i% B) [9 o* ~                a. msm_otg_notify_charger@kernel/drivers/usb/otg/msm_otg.c
1 e" R6 n; B6 Z8 w0 g2 m                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. u2 [9 x& F8 B2 D( F0 w7 Q4 x0 c# ]
                c. -->power_supply_set_supply_type@power_supply_core.c // set type of the power supply; P! H+ B. a8 G! ^. k
                d. -->psy->set_property(psy, POWER_SUPPLY_PROP_TYPE,&ret);* ^& x9 h5 S. Y/ z* f) Z/ B
                                那么在用usb_psy.get_property和dc_psy.get_property
  l) t: y9 {2 f8 c1 n" D(在函数中pm8921_charger_probe)读取property时; ]; T/ m" I* e% J) t  Y
                                如果是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
# H. L/ l0 B  k: hcharger. W6 p) I) q; P, T' D" {, G  v
                                如果是AC type,则在pm_power_get_property_mains读取POWER_SUPPLY_PROP_ONLINE的值,只有POWER_SUPPLY_TYPE_USB_DCP为AC
. Q- T8 B0 s' k' w7 b; [# gcharger.
7 B7 r$ }+ K' y8 y& e' v0 l* U                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
  e) Q5 W) P! D) ]                f. -->pm8921_set_usb_power_supply_type(val->intval)@pm8921-charger.c0 S8 ]7 D5 O$ h+ r- S3 `8 \0 l, `
                                -->power_supply_changed(&the_chip->usb_psy);
1 Y$ B' s( f. J9 M& h7 {8 y                                -->power_supply_changed(&the_chip->dc_psy);5 ~3 G6 b' c: d* y0 ~. ^
                g. power_supply_changed@pm8921-charger.c , 就会马上发送uevent给user- m# p7 G! i5 t' c0 U/ t& t
space,然后user space通过sysfs得到USB# i% H# f# h/ b; `" Q! Y
type变化后的信息,参考用户空间的分析
" y- n3 [$ e. L. Q7 h
5 l8 d3 \! b/ g- p2 x+ y# |& P二、硬件分析
6 g0 C3 g0 I- g
2 u5 |! D5 ]2 S2 ?主要是通过特殊设计的电路,检测不同的pin的状态,从而确定是何种类型的Charger. 更details的内容省略。
* e6 x0 i2 A4 y$ B# @$ [9 ]- D1 T4 i
, P  A# T( Q: F" a' U2 p. f0 E
1 j* o6 g5 _1 j; C

该用户从未签到

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

本版积分规则

关闭

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

EDA365公众号

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

GMT+8, 2025-6-15 17:38 , Processed in 0.078125 second(s), 23 queries , Gzip On.

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

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

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