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

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
USB port 如何识别不同的Charger类型7 e- j" @3 }" G' l. _4 i
2013年10月03日 ⁄ 综合 ⁄ 共 8924字        ⁄ 字号 [url=]小[/url] [url=]中[/url] [url=]大[/url] ⁄ 评论关闭& q) W0 F) T% [9 M9 u; Y* c
5 @4 R  u7 |0 M, y4 j% V
一,软件分析1.  USB charger types & Power supply types" k7 h6 s  s4 }. F1 g; F# m5 }$ q; I
USB_INVALID_CHARGER              Invalid USB charger.
% G& }2 X4 ]; H' P3 a9 xUSB_SDP_CHARGER                       Standard downstream port. Refers to a downstream port  on USB2.0 compliant host/hub.
7 o8 p6 m$ C' Z2 N( L. C7 @USB_DCP_CHARGER                      Dedicated charger port (AC charger/ Wall charger).. Y& J3 c4 W* V) |4 r2 l0 p
USB_CDP_CHARGER                      Charging downstream port. Enumeration can happen and IDEV_CHG_MAX can be drawn irrespective of USB state.
0 F. |! G7 V9 P% O0 BUSB_ACA_A_CHARGER                                4 K& ~1 U( k; E1 ^+ i$ Y+ H
B-device is connected on accessory port with charger connected on charging port. This configuration allows charging in host mode.0 Z. ^8 Q; T# Q* T+ b
USB_ACA_B_CHARGER                 No device (or A-device without VBUS) is connected on accessory port with charger connected on charging port.) i- V8 J+ o4 ?& s( Z& S- K
USB_ACA_C_CHARGER                 A-device (with VBUS) is connected on accessory port with charger connected on charging port.; M' [7 C% v5 f
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  accessory0 B7 N3 ?4 A1 z% L4 B# `+ f  V
ports.
& P8 e6 _) B3 h, _USB_PROPRIETARY_CHARGER   A proprietary charger pull DP and DM to specific voltages between 2.0-3.3v for identification.6 x# x1 q- F( B* g1 a+ O0 G

7 \6 l9 H6 `# @; }6 k; bPOWER_SUPPLY_TYPE_USB,                     
0 N& l7 H7 ~+ G9 R6 T! b. v/* Standard Downstream Port */
. r  q" p+ h9 R' ~, j+ TPOWER_SUPPLY_TYPE_USB_DCP,           /* Dedicated Charging Port */+ c: a6 A2 s6 e
POWER_SUPPLY_TYPE_USB_CDP,           /* Charging Downstream Port */7 }% N* q% p/ s  D3 K. c7 S7 b; b
POWER_SUPPLY_TYPE_USB_ACA,           /* Accessory Charger Adapters */. D2 B0 E, u- C4 y& e; I
POWER_SUPPLY_TYPE_BMS,                     
+ C& p$ z$ Q" f& f& L8 I6 i6 Q/* Battery Monitor System */
9 h1 t' n! Q' _6 F' a9 p) b & h1 Z( w) ?' n, ]# M# p% j6 n7 [; F
2. How to classify or identify charger?
6 \3 y, v4 S; B# Y7 b8 t * x" y( `2 l0 `9 s, |) f4 {
USB_SDP_CHARGER
" l1 {( f* U# E7 B3 X3 M* \
POWER_SUPPLY_TYPE_USB
$ ?$ L" V: K2 |! B6 C
USB Charger
USB_CDP_CHARGER
6 P  }  o* |  l& m4 a) b: z
POWER_SUPPLY_TYPE_USB_CDP5 S8 |4 }# Q% J
USB_ACA_DOCK_CHARGER
; s/ P# L" ^0 r2 k
POWER_SUPPLY_TYPE_USB_ACA
USB_ACA_A_CHARGER8 c( m3 {$ s+ R' @1 o. H
USB_ACA_B_CHARGER
& a9 E' B  p/ V1 G' M/ x: j
USB_ACA_C_CHARGER
6 m8 F9 |( y9 W, T0 O
USB_DCP_CHARGER" t/ g- O& ~% K0 j
POWER_SUPPLY_TYPE_USB_DCP
AC Charger
USB_PROPRIETARY_CHARGER
9 b% o4 P1 [! q  \

) |: S0 Z: \0 _As for the DMS, refer to bold font items, so it is USB charger.. b8 s. R4 D: j3 q8 J& G  B5 K* J

! ~& g7 E! d6 |0 M$ a/ v3. Analysis about source codes( `! z3 i+ M2 Q( a& ]
*******************************************************************/ B2 P0 P) [  ?. ~5 z" r
###用户空间的分析如下:3 Y) B0 B# N. B! Z  k- Q
1. 检查 /sys/class/power_supply/pm8921-dc/online和- t1 o- [2 v+ A+ k) `
/sys/class/power_supply/usb/online 的值,可以知道是何充电器类型- z7 _4 l, z# N7 k" t$ y) V: i
                @frameworks/base/services/jni/com_android_server_batteryservice.cpp中有
; O) m3 e1 m5 V+ |' m: v                int register_android_server_BatteryService(JNIEnv* env)          1 \8 A  f  N: s2 N% w
                {% n- ~% C1 f/ E* P9 H! [
                if (strcmp(buf, "Mains") == 0) { ///sys/class/power_supply/pm8921-dc/type == Mains5 ^. ?/ m; e: k. z
                    snprintf(path, sizeof(path), "%s/%s/online", POWER_SUPPLY_PATH, name);) k8 e. H  Q1 n# g$ u! U: b9 v
                    if (access(path, R_OK) == 0)& N, d% \0 V. F$ z
                        gPaths.acOnlinePath = strdup(path);2 q% l: V" l! S$ H7 E, I
                }  L" m9 H! t/ B9 U3 C- S0 P
                }
$ }, Y" K0 i9 h$ i: j+ }/ c   如果/sys/class/power_supply/pm8921-dc/online==1,则插入的充电器是wall* H( V1 z+ x) h+ o6 L
charger

2 [' ~' M" W- J' `& C, e      /sys/class/power_supply/usb/online==1, ( L, U. z: `2 c
则插入的充电器是usb charger

  q' U" @+ G; k) y   调试路径:/sys/kernel/debug/msm_otg; t! H8 H$ w; C7 t
2. 分析frameworks/base/services/jni/com_android_server_batteryservice.cpp
# j  |* f! U1 P$ M9 c                a.函数register_android_server_BatteryService将为被frameworks/base/services/jni/onload.cpp中的JNI_OnLoad调用,用于关联java和C++之间的变量
: d8 U& m7 b; H* u% ^                b.jclass clazz = env->FindClass("com/android/server/BatteryService"); //根据java的路径找到batteryservice.java对应的jclass   
( N& o- v4 u) e) ^2 U6 P/ v                  gFieldIds.mAcOnline = env->GetFieldID(clazz, "mAcOnline", "Z");
' c8 o0 n2 g' u2 p7 o$ I; i  u                  gFieldIds.mUsbOnline = env->GetFieldID(clazz, "mUsbOnline", "Z"); //用于关联batteryservice.java中变量private% b# @# H) z& u# T* G$ I% Y
boolean mAcOnline和gFieldIds.mAcOnline) R) m$ P2 S0 V: K4 \
                c. android_server_BatteryService_update
5 f* X$ a$ `. [1 l* R8 D                                static JNINativeMethod sMethods[] = {  K" m1 u5 m: c5 ?3 V
                                     /* name, signature, funcPtr */! _" k# \* _" `( ?" `+ u  _# D6 b
                                                {"native_update", "()V", (void*)android_server_BatteryService_update},% y( v8 Z/ a" e! J4 J
                                };4 T+ A* C1 Q( F) B$ [
                   关联到native_update@frameworks/base/services/java/com/android/server/batteryservice.java7 [8 c4 o4 e, H% y& P
3. 分析frameworks/base/services/java/com/android/server/batteryservice.java( F/ F5 `, X" R. K1 X4 K7 w
                a. mPowerSupplyObserver.startObserving("SUBSYSTEM=power_supply"); //注册监听该uevent
. Y  ?  X/ i4 G1 J' y                b.     private UEventObserver mPowerSupplyObserver = new UEventObserver() {
- x# |- |6 ~6 J                                public void onUEvent(UEventObserver.UEvent event) { //如果就收到来自kernel的uevent,触发该函数
; G2 F6 r% Z" H8 I3 t- ?                                    update(); //-->native_update();和processValues();
7 m( E0 }* m. I5 H* o2 v& V  q) Z- o                                }! H' o8 D2 F# N$ c* f
                       };
, d! v5 c6 w; K. V3 F' }/ W                c. native_update函数会通过JNI调用得到更新的mAcOnline和mUsbOnline值
% K1 ^$ f' L: `! X. W8 y6 [2 G                d. processValues会根据mAcOnline和mUsbOnline值对mPlugType赋值. U$ `4 ]: r# Q4 l, i8 E7 [5 }& E
                                if (mAcOnline) {( I8 T' @/ h0 a" v; m: k
                                    mPlugType = BatteryManager.BATTERY_PLUGGED_AC;( q5 S' _5 m. b) q8 v( L# X
                                } else if (mUsbOnline) {
# B, ?5 X( _8 K$ o% ^& o. u, _4 T                                    mPlugType = BatteryManager.BATTERY_PLUGGED_USB;
0 h' t4 b% d9 [& @0 `                                } else {8 i4 I* C% C! V( j7 l
                                    mPlugType = BATTERY_PLUGGED_NONE;
5 H: t4 @! m8 |- e0 f+ _. }3 s9 h                                }& [- w1 D0 _$ B' p+ w
                e. sendIntent函数会准备Intent并且broadcast这个Intent+ n$ M  K: s6 {& Q9 l
                                Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED); //public static final String ACTION_BATTERY_CHANGED = "android.intent.action.BATTERY_CHANGED";@batteryservice.java0 r/ i! y: ]; S& L0 }/ P( d
                                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
! u2 u+ \* b0 t8 c                                        | Intent.FLAG_RECEIVER_REPLACE_PENDING);  J: P6 z1 {: R  o9 m# j
% f, u: M( }0 g! @$ [7 H1 R
                        intent.putExtra(BatteryManager.EXTRA_PLUGGED, mPlugType);% c" [: O$ R% K0 f
                                ActivityManagerNative.broadcastStickyIntent(intent, null);
% U. _4 ?: R. p( B! W4. 分析vendor/sEMC/packages/apps/debugmenu/src/com/sonyericsson/debugmenu/battery.java0 _. q* q& z8 v* o6 J
                a. 接收intent
1 `. N  J% t% W                    private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {! e, p9 f; N* G/ @  R
                                @Override
  q9 D$ D* i$ j9 z( k4 _% s# m                                public void onReceive(Context arg0, Intent intent) {* }6 O( W# i6 @7 {% ]8 k
                                    if (intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) {
0 r* \7 h& @9 W: N                                        mPowerInformation.parseIntent(intent);
4 [* x+ q, y) |% ^                                        updateViews();' Y* h! o2 @  T9 E" @/ s
                                    }
# N+ E. P* O. [0 ^3 f5 T                                }2 |# |/ W6 g% v3 F( r
                    };0 V: X% ?9 ?# F# a
                    public void registerBroadcastReceivers() {! |! L: R8 N: O( L3 y- ?
                                IntentFilter mIntentFilter;1 ~( O# L6 A: H; g& g
                                mIntentFilter = new IntentFilter();
% j/ \, h# w5 \, G3 D" ^! O! l7 H, G                                mIntentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); //只接收Intent.ACTION_BATTERY_CHANGED的intent7 v9 @$ @4 U% X3 A& E/ t$ Y
                                // Register battery receiver.3 V! ?. N5 X8 r
                                registerReceiver(mBatteryInfoReceiver, mIntentFilter);
2 k0 W+ q! T3 y# y                    }         
( p* t/ R" p4 s2 N8 s                b. parseIntent 得到最新的"plugged"值赋给mPlugged
# ?- \5 a& O8 z3 V+ @  @                c. updateViews 更新charger类型显示
: I$ e5 k2 T; \# q# W: q###内核空间6 L4 k& [5 N- X2 ^- [: m
1. 插入充电器触发的过程@kernel/drivers/usb/otg/msm_otg.c
% B) P1 C. [. h6 R) l0 T. {. d                a. CONFIG_PM_RUNTIME 定义 @kernel/arch/ARM/configs/viskan_huashan_defconfig0 I3 ^; l7 f! j. H! H4 l
                b.msm_otg_runtime_resume-->msm_otg_resume-->??-->msm_otg_sm_work; M9 ?0 q+ n0 D1 v* z
                c.msm_otg_sm_work,先进入OTG_STATE_UNDEFINED case,然后进入OTG_STATE_B_IDLE
+ D4 z9 v+ G& K- _* b' @, ^& Mcase-->motg->chg_state=USB_CHG_STATE_UNDEFINED-->启动msm_chg_detect_work
  e8 O  Z: w/ D( R6 Y; R                d.msm_chg_detect_work 该函数主要完成USB charger类型的识别
  p! i8 h2 f# o% h& B1 ~& x+ w                                USB_CHG_STATE_UNDEFINED //其中psy = power_supply_get_by_name("usb");很关键,表明只是获取usb的power_supply,实际上就是chip->usb_psy@pm8921-charger.c
5 R. i! G: E& U6 s                                USB_CHG_STATE_WAIT_FOR_DCD         //Waiting for Data pins contact.5 o# o& _: b4 {
                                然后多次(MSM_CHG_DCD_MAX_RETRIES=6)检测USB状态,启动queue_delayed_work(motg->wq,1 C8 r. e$ F8 t: l8 Y! Q9 v
&motg->chg_work, delay); //motg->chg_work=msm_chg_detect_work
, n0 w4 k  D/ m3 ?                                USB_CHG_STATE_DETECTED //最后USB charge类型检测完毕
, d- _$ B9 g/ w0 N                e. 启动queue_work(motg->wq, &motg->sm_work); //motg->sm_work=msm_otg_sm_work4 |3 x. o7 `, H" C) y
                f. 由于motg->chg_state==USB_CHG_STATE_DETECTED,
& X/ E4 h$ ?% N4 P& R                                motg->chg_type==USB_DCP_CHARGER -->msm_otg_notify_charger(motg,IDEV_CHG_MAX);//IDEV_CHG_MAX=15002 J' v% _, p& @3 Z
2. 发送uevent到用户层
/ W+ u6 ~3 v! u3 E8 d                a. msm_otg_notify_charger@kernel/drivers/usb/otg/msm_otg.c
$ R* }! o, R4 _& R: j/ P, x) x                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  z. V' D5 t# b& }6 [
                c. -->power_supply_set_supply_type@power_supply_core.c // set type of the power supply
; t: F! S8 P  l' ?% ?7 `5 [8 u/ W                d. -->psy->set_property(psy, POWER_SUPPLY_PROP_TYPE,&ret);
/ X- f% k$ {: R$ u! a, n* e                                那么在用usb_psy.get_property和dc_psy.get_property
3 B" D  m6 r( r% t" E( k9 {(在函数中pm8921_charger_probe)读取property时
1 R7 x8 D, @% j" _' t                                如果是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( Q; q- ^0 v4 z" I# {- P, t
charger
8 Q0 ~0 h+ |2 o2 n% K4 }+ a: s5 a                                如果是AC type,则在pm_power_get_property_mains读取POWER_SUPPLY_PROP_ONLINE的值,只有POWER_SUPPLY_TYPE_USB_DCP为AC8 e; v3 ]0 v3 @4 Z  n: F
charger.
( G* m! v& o' A; T. I! 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' A5 T9 [# ?8 j/ t) z* g
                f. -->pm8921_set_usb_power_supply_type(val->intval)@pm8921-charger.c6 O* Z# g& R0 \+ U5 K& ~
                                -->power_supply_changed(&the_chip->usb_psy);7 A0 ]: ?; o$ Q/ o/ }
                                -->power_supply_changed(&the_chip->dc_psy);
5 B+ z& `( O0 f                g. power_supply_changed@pm8921-charger.c , 就会马上发送uevent给user
' |  E1 R' t3 _7 P! O  ?& Mspace,然后user space通过sysfs得到USB: |7 m/ ]7 {$ q! q( l
type变化后的信息,参考用户空间的分析4 @0 H% a) {! V! I" ~$ j
  R9 ^$ X1 P! x/ |
二、硬件分析! v8 V, s: J/ y

+ d8 Z% j& {6 f主要是通过特殊设计的电路,检测不同的pin的状态,从而确定是何种类型的Charger. 更details的内容省略。
! T- ~- p% b& u) |& J1 k
8 x. K5 S9 o* c' ?

. h- G1 a, }* k+ L" j1 o$ ?8 J2 b& \5 G

该用户从未签到

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

本版积分规则

关闭

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

EDA365公众号

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

GMT+8, 2025-7-20 00:29 , Processed in 0.125000 second(s), 23 queries , Gzip On.

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

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

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