找回密码
 注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

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

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

[复制链接]

42

主题

78

帖子

523

积分

三级会员(30)

Rank: 3Rank: 3Rank: 3

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

EDA365欢迎您!

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

x
USB port 如何识别不同的Charger类型
: T0 I- `# E5 s1 L8 p8 N2013年10月03日 ⁄ 综合 ⁄ 共 8924字        ⁄ 字号 [url=]小[/url] [url=]中[/url] [url=]大[/url] ⁄ 评论关闭
+ x' {! l% X' e+ E: P" Q% [
  M& W* i; y# |8 x" i# x. R" t一,软件分析1.  USB charger types & Power supply types- K" @2 q! \- x- @! t/ c2 x
USB_INVALID_CHARGER              Invalid USB charger.
8 T" _0 J6 b' i, |! zUSB_SDP_CHARGER                       Standard downstream port. Refers to a downstream port  on USB2.0 compliant host/hub.
1 M2 s5 X! s+ [3 v! Q: VUSB_DCP_CHARGER                      Dedicated charger port (AC charger/ Wall charger)./ V: S+ ^$ b) O- d. X! E0 l
USB_CDP_CHARGER                      Charging downstream port. Enumeration can happen and IDEV_CHG_MAX can be drawn irrespective of USB state.
. }' p, k2 U' z- nUSB_ACA_A_CHARGER                                
- H; h/ s/ |, R; ?8 q' hB-device is connected on accessory port with charger connected on charging port. This configuration allows charging in host mode.+ E4 c' M/ d6 A" ?
USB_ACA_B_CHARGER                 No device (or A-device without VBUS) is connected on accessory port with charger connected on charging port.
. \3 X' M3 p4 h$ [7 T0 i, IUSB_ACA_C_CHARGER                 A-device (with VBUS) is connected on accessory port with charger connected on charging port.
/ P7 T4 W, V# [8 W% b# s/ dUSB_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- ~- k8 @1 W7 v1 w( F3 v
ports." m1 T5 x: A" g9 V. o3 M$ l
USB_PROPRIETARY_CHARGER   A proprietary charger pull DP and DM to specific voltages between 2.0-3.3v for identification.
+ p3 [: f$ p$ g7 q
0 K9 L  U# o- z; ]4 h+ i" a# u1 pPOWER_SUPPLY_TYPE_USB,                      2 j) p. d  P5 R; S' {
/* Standard Downstream Port */# ~1 W$ ?8 ?6 w: y
POWER_SUPPLY_TYPE_USB_DCP,           /* Dedicated Charging Port */0 Z- ~4 G% n6 {. V
POWER_SUPPLY_TYPE_USB_CDP,           /* Charging Downstream Port */& W5 v$ |1 V1 g7 @. r  U
POWER_SUPPLY_TYPE_USB_ACA,           /* Accessory Charger Adapters */
$ w4 s% J" }% ~( g$ T" vPOWER_SUPPLY_TYPE_BMS,                     ! a" o. M+ M- J0 t! P! F
/* Battery Monitor System */( M* E7 m, O4 q4 ?2 H5 y* r# b
0 Q6 _* I8 [! \" G7 C
2. How to classify or identify charger?
" r- F+ B+ z' u- \
7 P, K; p! ~0 J# a% f2 q& i7 Y
USB_SDP_CHARGER9 f* s% Q* U" S6 _, @6 m' g
POWER_SUPPLY_TYPE_USB
" P2 B. y. k" S, g
USB Charger
USB_CDP_CHARGER
. E- D' p+ M- H6 {3 O
POWER_SUPPLY_TYPE_USB_CDP
6 ^% a2 M4 K5 T0 D
USB_ACA_DOCK_CHARGER
6 X+ P/ G: q! t: P6 I8 o
POWER_SUPPLY_TYPE_USB_ACA
USB_ACA_A_CHARGER
& J* Z1 n9 P' S7 C3 s! y
USB_ACA_B_CHARGER: F7 C% j# |8 ~! d  h
USB_ACA_C_CHARGER& f# _# n) V5 h
USB_DCP_CHARGER
9 S% k, g3 G+ L0 @- o9 j+ N0 E
POWER_SUPPLY_TYPE_USB_DCP
AC Charger
USB_PROPRIETARY_CHARGER
3 |# j) p$ W6 t3 s- M
( C. W7 s" B2 ~1 \4 l" `9 _( t
As for the DMS, refer to bold font items, so it is USB charger.
9 F; L8 r/ _0 U( B   }2 k- I$ a/ U/ D7 ~# T, H
3. Analysis about source codes
4 v/ `( ^6 J% J! Y0 W( g& E# C) S9 n*******************************************************************
/ V; y5 R' ?9 r, I+ D6 c###用户空间的分析如下:
! g5 \5 P, P7 v0 f2 m$ J. Z1 j1. 检查 /sys/class/power_supply/pm8921-dc/online和
: P7 w. H! u1 f8 Y/sys/class/power_supply/usb/online 的值,可以知道是何充电器类型; M7 Y% K, p# m2 X6 S
                @frameworks/base/services/jni/com_android_server_batteryservice.cpp中有$ i* r/ |( i2 i2 R/ K1 M
                int register_android_server_BatteryService(JNIEnv* env)         
$ {) x$ {# v& v& h1 i- X                {
( C$ _' X( }4 j- o& e                if (strcmp(buf, "Mains") == 0) { ///sys/class/power_supply/pm8921-dc/type == Mains6 S' o9 C6 b. ]6 d4 ^4 D0 `
                    snprintf(path, sizeof(path), "%s/%s/online", POWER_SUPPLY_PATH, name);" w. |& @2 ]/ y
                    if (access(path, R_OK) == 0)
6 o. C. V4 f5 r% n0 q                        gPaths.acOnlinePath = strdup(path);# {' C/ \7 v3 |( D: C/ v7 W* d/ T$ y
                }' g7 n$ @$ b0 ]+ K# m3 [: a
                }
$ w. P- l% z% o' i4 ]: u/ y   如果/sys/class/power_supply/pm8921-dc/online==1,则插入的充电器是wall" |- F9 g, w3 M( M
charger
4 K4 G0 N: z" {# }3 H
      /sys/class/power_supply/usb/online==1,
/ M6 @0 [" n. a" \& O# M0 |则插入的充电器是usb charger

0 c- e* f8 T2 i7 z, d   调试路径:/sys/kernel/debug/msm_otg
5 P+ o3 r5 f/ T( C# i2. 分析frameworks/base/services/jni/com_android_server_batteryservice.cpp& v  q6 F8 L& [/ J9 K- _
                a.函数register_android_server_BatteryService将为被frameworks/base/services/jni/onload.cpp中的JNI_OnLoad调用,用于关联java和C++之间的变量
, c% o: I, D) F' ^                b.jclass clazz = env->FindClass("com/android/server/BatteryService"); //根据java的路径找到batteryservice.java对应的jclass    5 W! n! v8 V7 K; @
                  gFieldIds.mAcOnline = env->GetFieldID(clazz, "mAcOnline", "Z");1 [2 y& @# ?8 F" w  O
                  gFieldIds.mUsbOnline = env->GetFieldID(clazz, "mUsbOnline", "Z"); //用于关联batteryservice.java中变量private( ~0 F: H2 v  R1 b1 `, Y
boolean mAcOnline和gFieldIds.mAcOnline
# X  r8 b7 B+ f! Q, H' q                c. android_server_BatteryService_update( k  n4 f$ G3 I; l! G
                                static JNINativeMethod sMethods[] = {" Q& ~' Q/ a% k, p
                                     /* name, signature, funcPtr */
3 }+ b) X4 ]8 T. a9 p                                                {"native_update", "()V", (void*)android_server_BatteryService_update},, a) @' ~: f7 g8 J
                                };6 F5 y  |0 j  t. b
                   关联到native_update@frameworks/base/services/java/com/android/server/batteryservice.java
  t2 D8 z* Y9 z; N3. 分析frameworks/base/services/java/com/android/server/batteryservice.java+ t9 h# T$ p$ c. s$ x  ~
                a. mPowerSupplyObserver.startObserving("SUBSYSTEM=power_supply"); //注册监听该uevent
' S/ b. s( ^/ T) ^4 i                b.     private UEventObserver mPowerSupplyObserver = new UEventObserver() {
' ~6 j( Q% y7 |2 P+ b' g! ]' ^& b1 R                                public void onUEvent(UEventObserver.UEvent event) { //如果就收到来自kernel的uevent,触发该函数
8 C& P0 w" ?" u8 o                                    update(); //-->native_update();和processValues();( g- T7 d. d# n3 b/ P
                                }
( t* c8 U7 V; @$ p                       };
7 L  I2 V. a  ?1 A                c. native_update函数会通过JNI调用得到更新的mAcOnline和mUsbOnline值9 g  }( Q; l) |% ?& R
                d. processValues会根据mAcOnline和mUsbOnline值对mPlugType赋值
) p8 l# C) Z: g0 }                                if (mAcOnline) {
0 g/ p# P) i" d) s' p. Y& z                                    mPlugType = BatteryManager.BATTERY_PLUGGED_AC;, D% X6 i, K* Q& k0 S: n
                                } else if (mUsbOnline) {/ }' |5 [, a4 t4 D( H; w; A
                                    mPlugType = BatteryManager.BATTERY_PLUGGED_USB;
+ ]& Q. S. M" @" i8 Q2 U1 k                                } else {) B: @- F: t1 h$ A# j5 i
                                    mPlugType = BATTERY_PLUGGED_NONE;
$ F8 g3 ?, {$ E                                }
  t( {$ K" M% |# k4 a                e. sendIntent函数会准备Intent并且broadcast这个Intent
6 w3 A3 v0 k' v( _9 M                                Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED); //public static final String ACTION_BATTERY_CHANGED = "android.intent.action.BATTERY_CHANGED";@batteryservice.java
+ B0 q+ Q  c# j( a, G1 n                                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY8 i/ V$ N) @# i' h2 f& @( {
                                        | Intent.FLAG_RECEIVER_REPLACE_PENDING);
# H3 _2 x! f' b
4 D2 ~- D) C6 Q! _! X                        intent.putExtra(BatteryManager.EXTRA_PLUGGED, mPlugType);4 ^1 Y1 ^2 b8 D" V9 ], U) H3 w) @( W
                                ActivityManagerNative.broadcastStickyIntent(intent, null);
- d# g& L3 y* S: r7 X7 j  p4. 分析vendor/semc/packages/apps/debugmenu/src/com/sonyericsson/debugmenu/battery.java( N  _; b' x% t& v# V( ~( N' g3 U
                a. 接收intent
  ~3 w# Z  U1 `% \7 i/ D                    private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {
  M! a. S4 K+ Z6 s/ R/ f                                @Override
/ c8 Z3 Y& O( Z* Y+ E, m3 Q                                public void onReceive(Context arg0, Intent intent) {9 u, R7 Y( Y; x6 i' z. _3 f6 U6 Q
                                    if (intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) {7 t- G, C" Q1 }9 T. P4 T
                                        mPowerInformation.parseIntent(intent);: r5 N, h. E2 ]# J( x# t1 d
                                        updateViews();  U! r; x" T; V- M& b
                                    }
/ v1 D# t0 T5 x2 ~% ~6 s                                }4 C6 ?: T/ i) U# m+ f8 C
                    };: {! K( o# E% l
                    public void registerBroadcastReceivers() {2 H0 w. H3 U0 M/ U7 U' w
                                IntentFilter mIntentFilter;7 V8 v: V- T2 z! S+ R) a9 d
                                mIntentFilter = new IntentFilter();- w1 A% s/ W1 f  h7 p
                                mIntentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); //只接收Intent.ACTION_BATTERY_CHANGED的intent& |* t% h2 n4 [  T' H! o! s
                                // Register battery receiver.
9 y! n; |8 _) ?9 X3 i: t                                registerReceiver(mBatteryInfoReceiver, mIntentFilter);1 L) \+ \, _( X. p: \
                    }         
# A7 \" j5 c* p; ?3 X                b. parseIntent 得到最新的"plugged"值赋给mPlugged
. d0 Z- Q; Z* \* j0 C                c. updateViews 更新charger类型显示
; T' |! R+ N, J( m( G( s; f  T3 q###内核空间# q- b) J' y0 \( ?  m
1. 插入充电器触发的过程@kernel/drivers/usb/otg/msm_otg.c1 t+ U5 B1 @, Y6 z( C) o
                a. CONFIG_PM_RUNTIME 定义 @kernel/arch/arm/configs/viskan_huashan_defconfig
9 P" I, K! K2 [7 E                b.msm_otg_runtime_resume-->msm_otg_resume-->??-->msm_otg_sm_work
" P$ i' M' }$ G1 Z$ A( G                c.msm_otg_sm_work,先进入OTG_STATE_UNDEFINED case,然后进入OTG_STATE_B_IDLE& x6 c  M( u) }6 ?, @3 j0 T2 s
case-->motg->chg_state=USB_CHG_STATE_UNDEFINED-->启动msm_chg_detect_work6 p, A4 I: K4 b% [$ k& f9 {+ a' [, G. b( T
                d.msm_chg_detect_work 该函数主要完成USB charger类型的识别- Z4 ?: Q9 a' Z0 M9 i, F0 Q
                                USB_CHG_STATE_UNDEFINED //其中psy = power_supply_get_by_name("usb");很关键,表明只是获取usb的power_supply,实际上就是chip->usb_psy@pm8921-charger.c
& q" l3 ]8 e4 s" _, ~. R: d+ v- l: T                                USB_CHG_STATE_WAIT_FOR_DCD         //Waiting for Data pins contact.# q" k- n9 y7 \' s4 Z/ ^4 Y2 _% p; t. K# z
                                然后多次(MSM_CHG_DCD_MAX_RETRIES=6)检测USB状态,启动queue_delayed_work(motg->wq,
$ z4 ?! t# k' V# J/ l7 y1 Z$ p&motg->chg_work, delay); //motg->chg_work=msm_chg_detect_work
8 [: q- O- h4 V' j9 A# K' w                                USB_CHG_STATE_DETECTED //最后USB charge类型检测完毕
: q+ T  o7 ~  M4 B' V* a                e. 启动queue_work(motg->wq, &motg->sm_work); //motg->sm_work=msm_otg_sm_work# ^- o- R+ G: V6 w; \+ Z
                f. 由于motg->chg_state==USB_CHG_STATE_DETECTED,
8 }' Z, r2 T. W, l                                motg->chg_type==USB_DCP_CHARGER -->msm_otg_notify_charger(motg,IDEV_CHG_MAX);//IDEV_CHG_MAX=15005 v0 L6 o" g8 x% B- j
2. 发送uevent到用户层
) M' F3 h7 U) [0 t  T                a. msm_otg_notify_charger@kernel/drivers/usb/otg/msm_otg.c  Z+ x2 |. U- c1 S1 o5 J  B7 b6 L
                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
* v9 m: H9 N8 A3 B                c. -->power_supply_set_supply_type@power_supply_core.c // set type of the power supply' H' p7 i: W: f1 K* \$ x/ n, {
                d. -->psy->set_property(psy, POWER_SUPPLY_PROP_TYPE,&ret);
, B. c7 y, b* ~3 N1 B: _                                那么在用usb_psy.get_property和dc_psy.get_property
6 D* G! L4 V. N: K. h(在函数中pm8921_charger_probe)读取property时# e' u! O7 V+ ^, \7 t8 ~
                                如果是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" C- {( K. L+ c* F# H0 z
charger
% ~& M' t( ^+ `9 x2 S1 o                                如果是AC type,则在pm_power_get_property_mains读取POWER_SUPPLY_PROP_ONLINE的值,只有POWER_SUPPLY_TYPE_USB_DCP为AC3 s4 I6 ~+ C  J' T4 M, k
charger.
0 _) Y. c- L9 y$ r$ {2 y! w0 z                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- ?$ J$ t, f; K9 [& Q6 j( _
                f. -->pm8921_set_usb_power_supply_type(val->intval)@pm8921-charger.c
7 ?7 N5 ~+ J4 a/ W! V                                -->power_supply_changed(&the_chip->usb_psy);
2 P) K6 @* i) T$ C( R- _) \                                -->power_supply_changed(&the_chip->dc_psy);
+ h: A- ]9 R& p0 Z                g. power_supply_changed@pm8921-charger.c , 就会马上发送uevent给user  K- \2 J" x( {. x6 [- @$ T$ z
space,然后user space通过sysfs得到USB1 c9 D* m2 U* h6 i: J1 T
type变化后的信息,参考用户空间的分析
+ B, J+ r+ Z0 e* W! ?$ L* }/ C4 t4 }9 n2 p1 @2 y" U
二、硬件分析
; L2 q; {" a0 M0 @: q& s% x6 L2 d" D# \, |
主要是通过特殊设计的电路,检测不同的pin的状态,从而确定是何种类型的Charger. 更details的内容省略。. I9 `+ z- a0 O* j% x: o3 x

% W) }" x8 j) G  q5 t
7 J& D. H! Q! R
2 q7 ]! P, L7 q6 h3 b
分享到:  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, 2024-11-5 06:24 , Processed in 0.058639 second(s), 32 queries , Gzip On.

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

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

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