找回密码
 注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

巢课
电巢直播8月计划
查看: 1224|回复: 2
打印 上一主题 下一主题

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

[复制链接]

42

主题

78

帖子

523

积分

三级会员(30)

Rank: 3Rank: 3Rank: 3

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

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 M
USB_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
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
收藏收藏 支持!支持! 反对!反对!

15

主题

158

帖子

429

积分

三级会员(30)

Rank: 3Rank: 3Rank: 3

积分
429
2#
发表于 2015-9-17 09:16 | 只看该作者
支持一下

1

主题

35

帖子

173

积分

二级会员(20)

Rank: 2Rank: 2

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

本版积分规则

关闭

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

巢课

技术风云榜

关于我们|手机版|EDA365 ( 粤ICP备18020198号 )

GMT+8, 2025-2-20 22:15 , Processed in 0.057237 second(s), 32 queries , Gzip On.

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

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

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