找回密码
 注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

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

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

[复制链接]

42

主题

78

帖子

523

积分

三级会员(30)

Rank: 3Rank: 3Rank: 3

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

EDA365欢迎您!

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

x
USB port 如何识别不同的Charger类型
& \" Z5 [: j' o! i1 `# Y# y) G/ m8 k2013年10月03日 ⁄ 综合 ⁄ 共 8924字        ⁄ 字号 [url=]小[/url] [url=]中[/url] [url=]大[/url] ⁄ 评论关闭
+ o* @3 Y0 D. o; }! \, ]
- q8 @- h  B& s6 u: K. V一,软件分析1.  USB charger types & Power supply types
! p& G; R: a' m) CUSB_INVALID_CHARGER              Invalid USB charger.* P* A, N! p, |+ G7 Q
USB_SDP_CHARGER                       Standard downstream port. Refers to a downstream port  on USB2.0 compliant host/hub.
! o9 |; u! T) U' ?$ @  EUSB_DCP_CHARGER                      Dedicated charger port (AC charger/ Wall charger).
9 F. o' m7 q% |3 K, t5 O2 rUSB_CDP_CHARGER                      Charging downstream port. Enumeration can happen and IDEV_CHG_MAX can be drawn irrespective of USB state.( F, u" \* z) ^* _! `; m& F& ~
USB_ACA_A_CHARGER                                , h1 }+ T8 K. Y: N6 k( P
B-device is connected on accessory port with charger connected on charging port. This configuration allows charging in host mode.7 e9 g1 {% C4 A
USB_ACA_B_CHARGER                 No device (or A-device without VBUS) is connected on accessory port with charger connected on charging port.9 ?" y! i% N( k% i/ }3 A. z& i
USB_ACA_C_CHARGER                 A-device (with VBUS) is connected on accessory port with charger connected on charging port.( s: V7 V! X' V6 l
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- l4 H0 j2 [% L7 e
ports.
: A$ P3 U% U# q- }; j1 M6 BUSB_PROPRIETARY_CHARGER   A proprietary charger pull DP and DM to specific voltages between 2.0-3.3v for identification.2 i( T5 V% |8 |2 J

" w/ R, ]; y9 j& h! x' R( W( T2 N' WPOWER_SUPPLY_TYPE_USB,                     
- d% M2 V) j& E, h/* Standard Downstream Port */* k0 m0 U) Z  ^& ~4 Y7 T5 m
POWER_SUPPLY_TYPE_USB_DCP,           /* Dedicated Charging Port */* A9 C6 N; n2 {( q. R. ^) P& ]
POWER_SUPPLY_TYPE_USB_CDP,           /* Charging Downstream Port */& d* `3 Y2 U3 Z: U7 U
POWER_SUPPLY_TYPE_USB_ACA,           /* Accessory Charger Adapters */
4 q1 e9 C; |# r% ?POWER_SUPPLY_TYPE_BMS,                     
* F# c7 @$ a6 N2 G/* Battery Monitor System */
5 E6 Q* ^: \- ~% Z' }2 |# q/ |
9 `; ?. q8 l" }; _$ O2. How to classify or identify charger?  Y: f+ ~* k3 g8 c) L

& ~6 ^( w" ^8 r8 ?; _4 W
USB_SDP_CHARGER" Y  E; m( ^- g6 o8 [
POWER_SUPPLY_TYPE_USB
0 n- g; y5 x3 q% z# R
USB Charger
USB_CDP_CHARGER
* X% w/ }$ I$ e$ Q
POWER_SUPPLY_TYPE_USB_CDP- V- B' k9 N4 C+ ]8 n( J1 S
USB_ACA_DOCK_CHARGER# J! L3 p  g$ n6 ]: I, s5 L8 C
POWER_SUPPLY_TYPE_USB_ACA
USB_ACA_A_CHARGER- b  q+ j5 S, x5 Q/ M4 I3 v
USB_ACA_B_CHARGER
8 ?6 s# ]) a& x. K6 e: F+ Z) [
USB_ACA_C_CHARGER
# S- ?& N6 U% F& c# w  }
USB_DCP_CHARGER: u. I, Z6 z2 k
POWER_SUPPLY_TYPE_USB_DCP
AC Charger
USB_PROPRIETARY_CHARGER
- z3 C* @2 e! S2 w9 M/ y! h' d# R
" C8 P- H  Z: e- R3 ]8 h
As for the DMS, refer to bold font items, so it is USB charger.
# M6 w) d7 b! G" T% B) x % K0 R9 w! }% }
3. Analysis about source codes
8 U$ f7 Y: t4 U0 V*******************************************************************
/ n7 n; H3 H# K$ L8 O& n- E9 p###用户空间的分析如下:/ r6 u& r! o- ~# Q7 m* j) g
1. 检查 /sys/class/power_supply/pm8921-dc/online和
5 r9 K& V! g( f0 k3 ~: l/sys/class/power_supply/usb/online 的值,可以知道是何充电器类型) Z1 X9 K2 u' E4 u* t1 _& E  g3 _
                @frameworks/base/services/jni/com_android_server_batteryservice.cpp中有
. i/ K( x- ]% I7 g. i                int register_android_server_BatteryService(JNIEnv* env)         
$ y8 c) G; `5 M( w& ~                {
( Y& ?3 T2 g' \4 M7 ~1 s- _$ h                if (strcmp(buf, "Mains") == 0) { ///sys/class/power_supply/pm8921-dc/type == Mains( C/ Y  l! A" E- X0 {0 c
                    snprintf(path, sizeof(path), "%s/%s/online", POWER_SUPPLY_PATH, name);, y- ]. n# |. z* w1 V
                    if (access(path, R_OK) == 0)5 t* ]0 ^1 O$ g0 h7 M& h
                        gPaths.acOnlinePath = strdup(path);
  \1 {1 d3 B$ }5 x1 e1 b1 b                }
( ?% a& A- r; H8 {5 h                }  r$ }) t& y. I$ \+ n# ~4 ]+ A
   如果/sys/class/power_supply/pm8921-dc/online==1,则插入的充电器是wall
  T3 u5 B- Z$ n' O9 rcharger
& \1 m+ |# T, L
      /sys/class/power_supply/usb/online==1,
5 M5 B, X$ W# l6 i1 ~! s则插入的充电器是usb charger

+ ?* P/ \  r3 R, s  ^( T   调试路径:/sys/kernel/debug/msm_otg
6 |0 u7 i6 m& R  q+ k8 i& q2. 分析frameworks/base/services/jni/com_android_server_batteryservice.cpp
) R$ z, h; t- S1 P                a.函数register_android_server_BatteryService将为被frameworks/base/services/jni/onload.cpp中的JNI_OnLoad调用,用于关联java和C++之间的变量
8 L! h1 Y1 r. k% Z. B* F7 E% r: F                b.jclass clazz = env->FindClass("com/android/server/BatteryService"); //根据java的路径找到batteryservice.java对应的jclass    , f- J" \: n7 e# o4 E7 ]
                  gFieldIds.mAcOnline = env->GetFieldID(clazz, "mAcOnline", "Z");: v! x7 ]& P4 E
                  gFieldIds.mUsbOnline = env->GetFieldID(clazz, "mUsbOnline", "Z"); //用于关联batteryservice.java中变量private
. v5 f( B) c! g: e0 c# `boolean mAcOnline和gFieldIds.mAcOnline: ^8 T' Y9 P2 l0 y% G
                c. android_server_BatteryService_update1 \! C( k( J: f2 X" a& G/ {* n
                                static JNINativeMethod sMethods[] = {
2 B, N' @6 E" v" w# Z4 E' s                                     /* name, signature, funcPtr */9 B7 D! O) X' |( `) e
                                                {"native_update", "()V", (void*)android_server_BatteryService_update},+ c$ @$ g9 p1 q! Y2 }" e) O
                                };
$ D/ J+ N  Q7 m7 Z! k                   关联到native_update@frameworks/base/services/java/com/android/server/batteryservice.java- J" A) m$ H# U0 ?% s
3. 分析frameworks/base/services/java/com/android/server/batteryservice.java
; z1 A6 K8 q2 ]$ b( [, Q$ p+ g                a. mPowerSupplyObserver.startObserving("SUBSYSTEM=power_supply"); //注册监听该uevent
3 T8 q; e' t# J6 _                b.     private UEventObserver mPowerSupplyObserver = new UEventObserver() {) \% j; |% [, K$ v$ [
                                public void onUEvent(UEventObserver.UEvent event) { //如果就收到来自kernel的uevent,触发该函数" O; D$ v" B& y6 Q1 Q& \
                                    update(); //-->native_update();和processValues();
$ c, R3 h. K1 ?: x                                }$ A3 Q1 [, k+ E
                       };
6 h% f* |% N! |( O                c. native_update函数会通过JNI调用得到更新的mAcOnline和mUsbOnline值
1 e+ u* g, c( r; T% j                d. processValues会根据mAcOnline和mUsbOnline值对mPlugType赋值
# Y9 o$ ?; w# \- r6 V" Y  T& P                                if (mAcOnline) {
/ V6 }; G- @# C                                    mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
3 s& \6 P" R, x+ H- }) ~- s                                } else if (mUsbOnline) {
3 L* }2 L! _- h/ |4 v- Y                                    mPlugType = BatteryManager.BATTERY_PLUGGED_USB;% x  o$ n0 K& Y) s+ u( p
                                } else {
( l. U5 r3 T/ d; t" G! Q- _) }                                    mPlugType = BATTERY_PLUGGED_NONE;
, \  ^  N3 ?, j0 c0 k0 h                                }$ {  \2 }0 Y/ @8 n* g
                e. sendIntent函数会准备Intent并且broadcast这个Intent
" y/ L9 B4 W1 A                                Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED); //public static final String ACTION_BATTERY_CHANGED = "android.intent.action.BATTERY_CHANGED";@batteryservice.java
. H; M1 {( U& ^  ?2 U4 O3 G2 q                                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY2 ]' ~2 a1 @/ u( d  k3 u
                                        | Intent.FLAG_RECEIVER_REPLACE_PENDING);- _, Y! O0 z& N7 ]

9 \: `$ m( @$ i* }% E8 u                        intent.putExtra(BatteryManager.EXTRA_PLUGGED, mPlugType);, _! u, P6 N. U4 L
                                ActivityManagerNative.broadcastStickyIntent(intent, null);6 L6 h7 H, n; ]7 t+ @" w7 J3 e. y
4. 分析vendor/semc/packages/apps/debugmenu/src/com/sonyericsson/debugmenu/battery.java) T7 D7 k1 G' t2 {
                a. 接收intent0 w* ~* }1 p1 d% B0 @
                    private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {6 v7 p8 L9 R! \# \" ]
                                @Override
% [! o/ T. O/ s' _/ j/ A+ ]+ d: R# B                                public void onReceive(Context arg0, Intent intent) {
  L3 o- l* n( f- J  X3 E                                    if (intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) {1 h. n8 A" l* \+ f; o
                                        mPowerInformation.parseIntent(intent);
9 K; E9 S4 v; `# L3 c                                        updateViews();8 B- c% y8 o+ t
                                    }
- u$ D' Q4 ]' d) u9 S- d$ E+ ^2 a                                }3 Q1 E' f: r/ A: r  K) G/ Y
                    };# b, {6 X6 k( O  f$ U: s
                    public void registerBroadcastReceivers() {5 e# {: n4 o7 v1 Q3 E; a
                                IntentFilter mIntentFilter;
( V- G4 M  J: Q( ^2 }2 J0 _                                mIntentFilter = new IntentFilter();
0 I& `9 N+ ]% @; i                                mIntentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); //只接收Intent.ACTION_BATTERY_CHANGED的intent7 y( u6 I# N: I
                                // Register battery receiver.
1 S) S& N% i, h# q                                registerReceiver(mBatteryInfoReceiver, mIntentFilter);6 Q& c" g+ f0 s9 k
                    }         
0 I' Q9 ]. u  V3 n) q                b. parseIntent 得到最新的"plugged"值赋给mPlugged5 _0 S& {' M. K3 P2 Y/ c
                c. updateViews 更新charger类型显示
: o1 o) ?9 b2 o/ U###内核空间- F4 {1 n/ E$ B: P0 E; B2 c
1. 插入充电器触发的过程@kernel/drivers/usb/otg/msm_otg.c; s' ~) W, ?% I( G, @+ t4 O, I1 I
                a. CONFIG_PM_RUNTIME 定义 @kernel/arch/arm/configs/viskan_huashan_defconfig* V! Z% j  m/ S, S
                b.msm_otg_runtime_resume-->msm_otg_resume-->??-->msm_otg_sm_work! n, L; T% {+ Q0 W6 i6 s
                c.msm_otg_sm_work,先进入OTG_STATE_UNDEFINED case,然后进入OTG_STATE_B_IDLE
1 S0 }% ]3 A2 r5 fcase-->motg->chg_state=USB_CHG_STATE_UNDEFINED-->启动msm_chg_detect_work) g; @7 a# i: R7 Z# x2 y
                d.msm_chg_detect_work 该函数主要完成USB charger类型的识别
5 `' V/ @" m! C/ I) [! R+ D                                USB_CHG_STATE_UNDEFINED //其中psy = power_supply_get_by_name("usb");很关键,表明只是获取usb的power_supply,实际上就是chip->usb_psy@pm8921-charger.c
2 Y2 \; x+ {1 W  B2 K                                USB_CHG_STATE_WAIT_FOR_DCD         //Waiting for Data pins contact.- ]2 g0 i" \0 K  c- [1 i2 F
                                然后多次(MSM_CHG_DCD_MAX_RETRIES=6)检测USB状态,启动queue_delayed_work(motg->wq,
; ~3 U, D" d+ g$ Z- ?&motg->chg_work, delay); //motg->chg_work=msm_chg_detect_work% o- J$ x! [; p- ^7 C$ c  M
                                USB_CHG_STATE_DETECTED //最后USB charge类型检测完毕
3 l7 Q! ]2 ~, N9 \3 b5 J4 W                e. 启动queue_work(motg->wq, &motg->sm_work); //motg->sm_work=msm_otg_sm_work! ?8 ~* H4 z: O! j5 P
                f. 由于motg->chg_state==USB_CHG_STATE_DETECTED,
0 g  {: j2 V5 R3 Z3 J- B* r                                motg->chg_type==USB_DCP_CHARGER -->msm_otg_notify_charger(motg,IDEV_CHG_MAX);//IDEV_CHG_MAX=15001 A( H6 Y: T* [3 D
2. 发送uevent到用户层
+ ], Z- z% n1 Y* W& _/ Q+ @. R9 ^0 c                a. msm_otg_notify_charger@kernel/drivers/usb/otg/msm_otg.c
" L5 ^6 X' e3 V' j0 ^: E8 x  S                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) U# X0 g4 B: Z, E9 o
                c. -->power_supply_set_supply_type@power_supply_core.c // set type of the power supply
+ J: e6 P$ R% i, c" O+ I" X6 D                d. -->psy->set_property(psy, POWER_SUPPLY_PROP_TYPE,&ret);' }" N0 Z8 W0 P9 r: `8 R- a
                                那么在用usb_psy.get_property和dc_psy.get_property
6 [: T' ~* |+ H! m3 g$ Y(在函数中pm8921_charger_probe)读取property时' F/ S/ F7 T8 ]/ k. g1 z
                                如果是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都被归纳成USB5 c5 z6 \9 }: ^2 H( r, ~
charger
+ [6 S1 W& h! r                                如果是AC type,则在pm_power_get_property_mains读取POWER_SUPPLY_PROP_ONLINE的值,只有POWER_SUPPLY_TYPE_USB_DCP为AC: _9 h2 s6 g6 C, S4 }2 e: R/ ?
charger., B. Z: F3 k3 E2 K2 U5 v- e* M
                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' }! J9 P, @- {2 \3 H/ B
                f. -->pm8921_set_usb_power_supply_type(val->intval)@pm8921-charger.c
9 e1 `; j; l0 h+ R" M7 E                                -->power_supply_changed(&the_chip->usb_psy);* j) {0 ^/ z0 }9 _% P
                                -->power_supply_changed(&the_chip->dc_psy);
. ^/ p& u# t6 l5 h, a                g. power_supply_changed@pm8921-charger.c , 就会马上发送uevent给user% i: v+ K, V' f9 k' v
space,然后user space通过sysfs得到USB5 A3 A7 {( U3 s; Y
type变化后的信息,参考用户空间的分析; I4 R8 X5 N% L" O

& n, z$ H: j7 a# y/ x, F二、硬件分析4 f$ A3 w, }: q' \* v
2 z. o7 l/ L) q* [, a
主要是通过特殊设计的电路,检测不同的pin的状态,从而确定是何种类型的Charger. 更details的内容省略。
& N! V7 p! X0 z5 \9 ~9 e
# J9 E: k' ~  o+ ]- `
6 b- i( n. R. Y# s" K
  c1 A8 l" @9 H$ p6 y) A! S
分享到:  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-25 20:06 , Processed in 0.059514 second(s), 32 queries , Gzip On.

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

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

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