找回密码
 注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

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

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

[复制链接]

42

主题

78

帖子

523

积分

三级会员(30)

Rank: 3Rank: 3Rank: 3

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

EDA365欢迎您!

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

x
USB port 如何识别不同的Charger类型! a; w* ~" j8 v: M7 s* I3 D( X, k
2013年10月03日 ⁄ 综合 ⁄ 共 8924字        ⁄ 字号 [url=]小[/url] [url=]中[/url] [url=]大[/url] ⁄ 评论关闭
( }" o% M( B9 c
+ h1 v6 K- ?" v. ?1 T4 E, U+ n一,软件分析1.  USB charger types & Power supply types! @  N0 E3 g: T3 n
USB_INVALID_CHARGER              Invalid USB charger.; Q5 X# @' h  Z: e$ \
USB_SDP_CHARGER                       Standard downstream port. Refers to a downstream port  on USB2.0 compliant host/hub.
& Y, ^0 V0 F( h0 S4 gUSB_DCP_CHARGER                      Dedicated charger port (AC charger/ Wall charger).
; B$ s! T) p" vUSB_CDP_CHARGER                      Charging downstream port. Enumeration can happen and IDEV_CHG_MAX can be drawn irrespective of USB state.
$ h- Q- _$ _' m) U6 W! ?2 \USB_ACA_A_CHARGER                                
6 V2 q9 A; b, N: d* f. J  wB-device is connected on accessory port with charger connected on charging port. This configuration allows charging in host mode.
! @( a+ ?7 J: F. \1 n! i8 p0 [USB_ACA_B_CHARGER                 No device (or A-device without VBUS) is connected on accessory port with charger connected on charging port." o, P; O! x* r0 z+ C
USB_ACA_C_CHARGER                 A-device (with VBUS) is connected on accessory port with charger connected on charging port.1 _( J2 e* R( J; Y: ?$ {9 ]
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( Q. h  P! G$ K$ U
ports.! ^. z. C! x: v7 `/ ]' U
USB_PROPRIETARY_CHARGER   A proprietary charger pull DP and DM to specific voltages between 2.0-3.3v for identification.6 x2 m4 G, w! t* I7 ]9 w7 Z
8 v' d5 ^9 W; @" r# }
POWER_SUPPLY_TYPE_USB,                      6 d2 i; M6 a# |  z, c
/* Standard Downstream Port */
  E1 R1 T/ z6 A- Z. W% yPOWER_SUPPLY_TYPE_USB_DCP,           /* Dedicated Charging Port */
4 Z: |; k. J; ^* APOWER_SUPPLY_TYPE_USB_CDP,           /* Charging Downstream Port */
. L; }1 X$ b! M8 ~. DPOWER_SUPPLY_TYPE_USB_ACA,           /* Accessory Charger Adapters */( B1 v! X6 _* [9 q2 G9 q1 t% @, X  _
POWER_SUPPLY_TYPE_BMS,                     ; D+ v3 `# q0 V; V1 N
/* Battery Monitor System */  ~! L! [: ~$ M( A
  s* K# l" E4 I8 }$ f( b1 P) Y# U9 b
2. How to classify or identify charger?( y' S% b0 |% D2 V9 f7 z3 G& W
1 L3 ?2 @% z6 f0 ^
USB_SDP_CHARGER' }- T9 d; ^4 r) e* E4 \  b
POWER_SUPPLY_TYPE_USB; _  l, n, b: r' v( Y& c6 k
USB Charger
USB_CDP_CHARGER
- g0 _' p5 W0 n: V
POWER_SUPPLY_TYPE_USB_CDP: F# [5 D/ m; y
USB_ACA_DOCK_CHARGER
  D7 R; |# {. L
POWER_SUPPLY_TYPE_USB_ACA
USB_ACA_A_CHARGER* A$ V' J' \9 c
USB_ACA_B_CHARGER
& U3 z3 ^% t8 ?1 |$ A
USB_ACA_C_CHARGER+ M2 e/ @1 }: X; q
USB_DCP_CHARGER
2 c7 Q* e4 J4 I0 j
POWER_SUPPLY_TYPE_USB_DCP
AC Charger
USB_PROPRIETARY_CHARGER
; s: D5 T- @) e) W9 ]
/ R+ U' f. a" p. ?; A! A
As for the DMS, refer to bold font items, so it is USB charger.& z2 S3 d: S4 p* {% A) n

  P! G' i1 c$ V" }# X3. Analysis about source codes
+ r, D" J3 o# \9 k& o) J/ l  \* @*******************************************************************
9 L) h* I+ R( f+ i5 n###用户空间的分析如下:0 P9 A/ m, K0 i
1. 检查 /sys/class/power_supply/pm8921-dc/online和
0 W7 Z' x2 G6 d+ K& u5 ]/sys/class/power_supply/usb/online 的值,可以知道是何充电器类型
- h% S& c% ~, b/ a" y$ Y. x                @frameworks/base/services/jni/com_android_server_batteryservice.cpp中有
/ `; D& ~+ ^1 W, X/ Y: u                int register_android_server_BatteryService(JNIEnv* env)          1 _7 H/ [2 \2 G3 m) H0 v/ L& _( }/ V
                {
1 ?+ P0 q4 g! d! u                if (strcmp(buf, "Mains") == 0) { ///sys/class/power_supply/pm8921-dc/type == Mains
' i$ I& N( ?& ^+ p1 M                    snprintf(path, sizeof(path), "%s/%s/online", POWER_SUPPLY_PATH, name);
) C. o3 j  J# t& m                    if (access(path, R_OK) == 0)
- x4 n' |2 @- r1 {- c+ w                        gPaths.acOnlinePath = strdup(path);
4 r( U& w( \/ R7 F) f- _  W                }+ A$ b$ K6 {# Y; l5 ?
                }( }* l; _. R$ Q. |8 F
   如果/sys/class/power_supply/pm8921-dc/online==1,则插入的充电器是wall; B& ?8 Z. A3 Y1 k& C% f
charger
% \* s" ?7 {% Y+ ?
      /sys/class/power_supply/usb/online==1,
& {/ e; R: d& ?则插入的充电器是usb charger

, W" L$ ], C3 ^: `' L2 E$ Q' V   调试路径:/sys/kernel/debug/msm_otg
. ?7 w0 |* O" X  }5 @7 l7 G2. 分析frameworks/base/services/jni/com_android_server_batteryservice.cpp8 o; W7 q, w( z  p* n
                a.函数register_android_server_BatteryService将为被frameworks/base/services/jni/onload.cpp中的JNI_OnLoad调用,用于关联java和C++之间的变量7 i( B; Y7 Z$ H4 U4 w7 k9 B3 t
                b.jclass clazz = env->FindClass("com/android/server/BatteryService"); //根据java的路径找到batteryservice.java对应的jclass   
& W3 S6 i3 C9 r                  gFieldIds.mAcOnline = env->GetFieldID(clazz, "mAcOnline", "Z");; d5 `5 J$ P) E5 M, {5 V2 S- W5 P
                  gFieldIds.mUsbOnline = env->GetFieldID(clazz, "mUsbOnline", "Z"); //用于关联batteryservice.java中变量private
. D1 v; H4 [+ i3 c: [0 h1 u+ I2 bboolean mAcOnline和gFieldIds.mAcOnline. g% U3 ^3 c+ M1 N
                c. android_server_BatteryService_update
- S/ J7 E0 p4 C' c5 K4 H& \                                static JNINativeMethod sMethods[] = {
# y0 y3 O5 ]0 P& |+ O                                     /* name, signature, funcPtr */
7 m- ?/ ^; T, s                                                {"native_update", "()V", (void*)android_server_BatteryService_update},8 M& k9 q; F4 \  f0 N
                                };
  Q  l# h1 O. G' a$ Y2 B                   关联到native_update@frameworks/base/services/java/com/android/server/batteryservice.java( j6 ^, f( O7 R7 X; C- C8 Q
3. 分析frameworks/base/services/java/com/android/server/batteryservice.java3 E) g& E) e  A6 G- R! p( l
                a. mPowerSupplyObserver.startObserving("SUBSYSTEM=power_supply"); //注册监听该uevent
+ `7 `+ _; W+ \+ D                b.     private UEventObserver mPowerSupplyObserver = new UEventObserver() {
4 i( I, }1 v- V) \# b6 E0 R' D' c                                public void onUEvent(UEventObserver.UEvent event) { //如果就收到来自kernel的uevent,触发该函数
$ n6 p+ r+ t! `6 i( Q' e6 t                                    update(); //-->native_update();和processValues();
/ ^4 o4 y9 f9 l; m                                }
( F- s1 \1 i3 V2 Y6 R; o% |+ E& a                       };
3 R6 Y8 ~/ V* m                c. native_update函数会通过JNI调用得到更新的mAcOnline和mUsbOnline值; O! h( a/ p3 ?) j* _' ~6 B
                d. processValues会根据mAcOnline和mUsbOnline值对mPlugType赋值
* R4 a# t7 b0 s' X  a, q                                if (mAcOnline) {" h- W- I& \  |9 D; k% B! }/ W; P
                                    mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
$ u# b* O- n0 z0 \2 x6 W9 d+ R* A                                } else if (mUsbOnline) {) D- I; q4 j$ c, i2 C1 Q7 c# K
                                    mPlugType = BatteryManager.BATTERY_PLUGGED_USB;
0 k! v2 v* m8 e0 ?! U- [! L) b                                } else {! K9 X' p( H! r  K
                                    mPlugType = BATTERY_PLUGGED_NONE;8 n! T" C4 k$ ^( H! V* n
                                }
! d, Z) H9 m! q7 A% \                e. sendIntent函数会准备Intent并且broadcast这个Intent# ?7 i: h4 [5 }# r; Z! x
                                Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED); //public static final String ACTION_BATTERY_CHANGED = "android.intent.action.BATTERY_CHANGED";@batteryservice.java
" n2 B' L0 f& Z9 I9 p, O7 H                                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY0 E8 H3 @4 X! ]$ W% S5 r
                                        | Intent.FLAG_RECEIVER_REPLACE_PENDING);
8 g* q7 b1 _# H' [4 Y . [6 t8 }' g# ~8 p  h
                        intent.putExtra(BatteryManager.EXTRA_PLUGGED, mPlugType);
. @' X# V$ u" [# y3 ]( b0 D1 J                                ActivityManagerNative.broadcastStickyIntent(intent, null);
7 V* q# y- b0 B0 z( _5 e4. 分析vendor/semc/packages/apps/debugmenu/src/com/sonyericsson/debugmenu/battery.java* ?' y# O" e% N; B9 L
                a. 接收intent6 X+ P6 D$ v9 N! m2 `# C% l: t
                    private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {
, ~  q) R+ @" u( F* I9 j# W9 O                                @Override
2 X3 s% y6 {$ `1 J2 }                                public void onReceive(Context arg0, Intent intent) {
2 f  y: {0 _- K7 r0 ^                                    if (intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) {
2 R- G( L  l7 w; s+ L' g                                        mPowerInformation.parseIntent(intent);
2 Q5 C* j" a7 \* @3 R, q                                        updateViews();  I1 y2 K; c. Q
                                    }# |: i; `  R3 S: n8 O& s6 o
                                }
" E5 `5 \; K6 L, _                    };' y- _8 ~! @9 Q8 ~  r
                    public void registerBroadcastReceivers() {
( E  c; B& B( x1 x5 |$ n1 k                                IntentFilter mIntentFilter;
5 v8 b; Y# Y& X$ w9 I: Y                                mIntentFilter = new IntentFilter();
( }7 t6 N; X, d' K                                mIntentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); //只接收Intent.ACTION_BATTERY_CHANGED的intent
; a8 O1 R3 o# H$ P4 e                                // Register battery receiver.  b- `' t9 G$ G
                                registerReceiver(mBatteryInfoReceiver, mIntentFilter);1 G5 z- `: u$ k9 o- t5 h
                    }         
( ?, U3 E$ p6 h! D" Y# _' f                b. parseIntent 得到最新的"plugged"值赋给mPlugged. T) v; y7 \( |+ R  t
                c. updateViews 更新charger类型显示
* ~2 e) K0 j6 K6 ^$ T###内核空间
0 S- E! G4 ^# b: H# M% L1. 插入充电器触发的过程@kernel/drivers/usb/otg/msm_otg.c
; V) \& J' O( W- o/ T0 G  m3 S0 ^                a. CONFIG_PM_RUNTIME 定义 @kernel/arch/arm/configs/viskan_huashan_defconfig
  T% r2 b" _8 H9 \& K. A                b.msm_otg_runtime_resume-->msm_otg_resume-->??-->msm_otg_sm_work
7 l2 @( M$ }' e3 T+ T* q- I                c.msm_otg_sm_work,先进入OTG_STATE_UNDEFINED case,然后进入OTG_STATE_B_IDLE
% Y- v" R5 x$ H7 m+ v  k8 Ccase-->motg->chg_state=USB_CHG_STATE_UNDEFINED-->启动msm_chg_detect_work
  Y. w! }( t1 L: B  {2 T                d.msm_chg_detect_work 该函数主要完成USB charger类型的识别
5 n& F" x" k0 X7 e2 }  J) C( Z                                USB_CHG_STATE_UNDEFINED //其中psy = power_supply_get_by_name("usb");很关键,表明只是获取usb的power_supply,实际上就是chip->usb_psy@pm8921-charger.c! X9 e/ i% \3 {9 b& C( s
                                USB_CHG_STATE_WAIT_FOR_DCD         //Waiting for Data pins contact.
9 [) c9 V+ r/ t% y/ t# c' V                                然后多次(MSM_CHG_DCD_MAX_RETRIES=6)检测USB状态,启动queue_delayed_work(motg->wq,' h" v! \: k2 P; i5 r3 b, p6 L  y
&motg->chg_work, delay); //motg->chg_work=msm_chg_detect_work
  D0 ]" t7 V# R0 M. |                                USB_CHG_STATE_DETECTED //最后USB charge类型检测完毕
! {3 H% H3 w. p7 T                e. 启动queue_work(motg->wq, &motg->sm_work); //motg->sm_work=msm_otg_sm_work
4 @  p4 g+ b! s" W) Z2 f                f. 由于motg->chg_state==USB_CHG_STATE_DETECTED,7 N. i7 f% S  K
                                motg->chg_type==USB_DCP_CHARGER -->msm_otg_notify_charger(motg,IDEV_CHG_MAX);//IDEV_CHG_MAX=15005 o4 r; S! a: j* Y( t7 e
2. 发送uevent到用户层
7 m8 N# S% |+ z- n) I: e                a. msm_otg_notify_charger@kernel/drivers/usb/otg/msm_otg.c# s) @& t) Q4 C# o7 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- x1 O! {: j: Y) c) G; v( w# O
                c. -->power_supply_set_supply_type@power_supply_core.c // set type of the power supply
( `! H' }0 G- ?5 b$ E) x0 H                d. -->psy->set_property(psy, POWER_SUPPLY_PROP_TYPE,&ret);1 O2 t( u# u4 L5 L- ]" ~
                                那么在用usb_psy.get_property和dc_psy.get_property
7 P. M+ Y7 R9 V7 D2 ^+ s(在函数中pm8921_charger_probe)读取property时
7 Q+ n# {/ `# V. |2 U                                如果是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
9 M( Y3 k( n! ~2 V, W% f* Qcharger' `9 Y, U  x" w- D3 w
                                如果是AC type,则在pm_power_get_property_mains读取POWER_SUPPLY_PROP_ONLINE的值,只有POWER_SUPPLY_TYPE_USB_DCP为AC# F# y; s6 Y0 J
charger.
% V9 x" \8 F% |+ p9 D' i/ \                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( T9 V/ H( M' h: M3 O
                f. -->pm8921_set_usb_power_supply_type(val->intval)@pm8921-charger.c9 O% b1 m- [$ D5 b8 _
                                -->power_supply_changed(&the_chip->usb_psy);
2 h& O5 f! S$ ]/ z' y                                -->power_supply_changed(&the_chip->dc_psy);9 M+ L$ G# g; O2 J  i
                g. power_supply_changed@pm8921-charger.c , 就会马上发送uevent给user
8 z' X# L, W7 G: Mspace,然后user space通过sysfs得到USB
: @+ P; U& _8 \/ P* _( itype变化后的信息,参考用户空间的分析4 F& Q2 P. t8 ^! p- ^6 i6 j
5 R  A) @! x: G7 o6 M( k5 l) \6 m+ B
二、硬件分析
! P4 _1 |1 b$ a- f% j, e# O9 l$ p3 f% R. F9 H0 g
主要是通过特殊设计的电路,检测不同的pin的状态,从而确定是何种类型的Charger. 更details的内容省略。
  `; e7 P( P) ^0 d7 }0 n9 l
! p5 v: I% p) y  I

% i$ v. t2 ^7 q$ u5 T2 @
! _2 F) O$ W! L5 ~& i
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
收藏收藏 支持!支持! 反对!反对!

1

主题

35

帖子

173

积分

二级会员(20)

Rank: 2Rank: 2

积分
173
3#
发表于 2015-10-20 22:16 | 只看该作者
        顶一下,问题有点长。

15

主题

158

帖子

429

积分

三级会员(30)

Rank: 3Rank: 3Rank: 3

积分
429
2#
发表于 2015-9-17 09:16 | 只看该作者
支持一下
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

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

巢课

技术风云榜

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

GMT+8, 2024-11-25 22:57 , Processed in 0.060894 second(s), 33 queries , Gzip On.

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

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

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