找回密码
 注册
查看: 2659|回复: 2
打印 上一主题 下一主题

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
USB port 如何识别不同的Charger类型' h1 F) f, w! \5 q2 F* ?& t) J
2013年10月03日 ⁄ 综合 ⁄ 共 8924字        ⁄ 字号 [url=]小[/url] [url=]中[/url] [url=]大[/url] ⁄ 评论关闭) M8 k! Y. @0 K1 u

) }6 V4 |( [% g7 B! J: B一,软件分析1.  USB charger types & Power supply types# G9 Z( C' I0 d6 L- c( J# u
USB_INVALID_CHARGER              Invalid USB charger.
+ t! F  D, L! C  Y7 O# J6 dUSB_SDP_CHARGER                       Standard downstream port. Refers to a downstream port  on USB2.0 compliant host/hub.
( N4 @% t2 I& y, h. j+ [USB_DCP_CHARGER                      Dedicated charger port (AC charger/ Wall charger).
4 o7 T0 }6 a. gUSB_CDP_CHARGER                      Charging downstream port. Enumeration can happen and IDEV_CHG_MAX can be drawn irrespective of USB state.5 N6 I) L8 `$ e' [. U7 i
USB_ACA_A_CHARGER                                4 G3 S8 ?. f$ i! E  A7 D- V  f
B-device is connected on accessory port with charger connected on charging port. This configuration allows charging in host mode.' c. o) X3 B* d# e  F
USB_ACA_B_CHARGER                 No device (or A-device without VBUS) is connected on accessory port with charger connected on charging port.5 w1 f( y  L3 }" J
USB_ACA_C_CHARGER                 A-device (with VBUS) is connected on accessory port with charger connected on charging port.
$ p0 @' B: I! @8 K0 s  G8 MUSB_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
0 `. z  H- C' Uports.
- @/ H, M) N1 ?3 S' mUSB_PROPRIETARY_CHARGER   A proprietary charger pull DP and DM to specific voltages between 2.0-3.3v for identification.
1 i$ u( @) j: G3 b# ]; `8 m( q- X ! L. U* @' o0 T* [1 Y
POWER_SUPPLY_TYPE_USB,                      + x; ]5 X1 K7 G& D! \* s
/* Standard Downstream Port */7 u' X4 @/ A4 w
POWER_SUPPLY_TYPE_USB_DCP,           /* Dedicated Charging Port *// r9 G6 o! R& O, b+ K( w. y
POWER_SUPPLY_TYPE_USB_CDP,           /* Charging Downstream Port */
% ]6 x8 L2 _# T7 \2 w4 Q% rPOWER_SUPPLY_TYPE_USB_ACA,           /* Accessory Charger Adapters */( u1 N9 m: i0 X* c$ V
POWER_SUPPLY_TYPE_BMS,                     
( M2 ~. P- T- z9 P9 u/* Battery Monitor System */4 @6 y8 @% t4 f
9 T8 e5 m( ^; l' W% Q# H2 h
2. How to classify or identify charger?
: W: c% {6 E( a2 @0 f1 b/ B
6 z  C. |; M3 s' \
USB_SDP_CHARGER
4 m" N& C6 X2 l7 m5 R6 @5 L! d
POWER_SUPPLY_TYPE_USB
* O" ^8 y+ K4 D
USB Charger
USB_CDP_CHARGER* r7 M  ^6 B: ]# ?8 ]
POWER_SUPPLY_TYPE_USB_CDP: m" _, o2 Z4 a0 x1 D" l
USB_ACA_DOCK_CHARGER7 n! F2 N- k. J$ M
POWER_SUPPLY_TYPE_USB_ACA
USB_ACA_A_CHARGER$ E9 \2 w% v0 w, W3 m2 Q0 q' q
USB_ACA_B_CHARGER
$ t" a6 \9 X( d
USB_ACA_C_CHARGER
* \$ j; Q0 _1 k$ h7 [# ?
USB_DCP_CHARGER" z2 @% h) ^; E/ q  T: _. H7 V
POWER_SUPPLY_TYPE_USB_DCP
AC Charger
USB_PROPRIETARY_CHARGER0 T# }4 R% f7 f7 u

' r1 L) h, o5 lAs for the DMS, refer to bold font items, so it is USB charger./ Z# S/ `  i( C$ I( S* K3 h( n) w
0 @; Q! T: G( ?
3. Analysis about source codes
# f" }  @9 n9 O! O- S*******************************************************************
0 X5 u! _& [" g( K###用户空间的分析如下:) x* M3 |% S) N  X, F
1. 检查 /sys/class/power_supply/pm8921-dc/online和
% v; f/ @' e& T- J& p/sys/class/power_supply/usb/online 的值,可以知道是何充电器类型* S) @8 M6 a; O) S8 n4 j3 L0 Y
                @frameworks/base/services/jni/com_android_server_batteryservice.cpp中有
* R( Q4 l, D* ?. O" c( @6 a                int register_android_server_BatteryService(JNIEnv* env)         
$ i$ _' S3 q* m+ k# V( R9 t" r                {
; l) L1 E: U' n% B/ t6 J' p! a& A                if (strcmp(buf, "Mains") == 0) { ///sys/class/power_supply/pm8921-dc/type == Mains& c! ^$ u' q7 m
                    snprintf(path, sizeof(path), "%s/%s/online", POWER_SUPPLY_PATH, name);
* n9 @" m( G& r8 h% \" j                    if (access(path, R_OK) == 0)
- Y5 Z9 V$ B% A2 h4 f7 `                        gPaths.acOnlinePath = strdup(path);( |8 T9 `& S" Z; R! n8 a" ?
                }
" V- `; p& K- F4 F                }
- b  L0 }, }" J) l2 w0 t* ^; v6 n6 \   如果/sys/class/power_supply/pm8921-dc/online==1,则插入的充电器是wall
1 K. }& I* o/ q2 F- G+ Mcharger
, e2 w0 K! i+ [2 c9 Y0 Y/ f
      /sys/class/power_supply/usb/online==1, 9 y8 a0 o$ C( n# ?. z% `# V
则插入的充电器是usb charger

4 T8 E7 P. |1 ]5 d   调试路径:/sys/kernel/debug/msm_otg
8 w# v8 W. x# M* a$ }5 A2. 分析frameworks/base/services/jni/com_android_server_batteryservice.cpp$ M. }, r& `1 |( ~0 H" l( ~
                a.函数register_android_server_BatteryService将为被frameworks/base/services/jni/onload.cpp中的JNI_OnLoad调用,用于关联java和C++之间的变量
$ e2 x3 R. A8 M                b.jclass clazz = env->FindClass("com/android/server/BatteryService"); //根据java的路径找到batteryservice.java对应的jclass   
8 H4 y5 {# y6 Y/ s! L5 J                  gFieldIds.mAcOnline = env->GetFieldID(clazz, "mAcOnline", "Z");$ C% b# p8 b& ]
                  gFieldIds.mUsbOnline = env->GetFieldID(clazz, "mUsbOnline", "Z"); //用于关联batteryservice.java中变量private
" Y/ n+ C1 _5 f6 hboolean mAcOnline和gFieldIds.mAcOnline
7 ^" ?! H& j6 W3 k2 \                c. android_server_BatteryService_update  H" Q- M" J1 E& s# O# ]3 K
                                static JNINativeMethod sMethods[] = {
) [) ]9 W+ }: j; y5 x                                     /* name, signature, funcPtr */
* O4 J7 x( B' w8 l* H                                                {"native_update", "()V", (void*)android_server_BatteryService_update},4 v1 \6 X+ u. p1 a! V8 z
                                };
* S) ?6 l- t* Z) u/ H                   关联到native_update@frameworks/base/services/java/com/android/server/batteryservice.java
% L0 ~* F+ N$ w- V3. 分析frameworks/base/services/java/com/android/server/batteryservice.java2 _! h$ [0 c9 {/ t* C2 z
                a. mPowerSupplyObserver.startObserving("SUBSYSTEM=power_supply"); //注册监听该uevent
( a5 _3 H% b' z+ v3 Y( G* f# @2 x2 y                b.     private UEventObserver mPowerSupplyObserver = new UEventObserver() {# s3 B* ~% @) y! p
                                public void onUEvent(UEventObserver.UEvent event) { //如果就收到来自kernel的uevent,触发该函数" t- e& n7 J1 s. r: }( [
                                    update(); //-->native_update();和processValues();6 p* K( J* a1 s1 [
                                }
8 |4 w* v* y5 b: e+ N                       };
6 b1 V/ E! f& d/ ^" c, w                c. native_update函数会通过JNI调用得到更新的mAcOnline和mUsbOnline值
0 ^7 E  O9 Y: a1 g/ j/ L2 n                d. processValues会根据mAcOnline和mUsbOnline值对mPlugType赋值
$ R( s% k7 |+ R                                if (mAcOnline) {
; n) F! r2 n& D                                    mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
- \1 s0 X6 X7 H: y$ `6 G                                } else if (mUsbOnline) {! J2 }8 d1 G- m
                                    mPlugType = BatteryManager.BATTERY_PLUGGED_USB;
/ F" E1 R& O( O% Y; u                                } else {: m: n; u( S' P/ ^) V
                                    mPlugType = BATTERY_PLUGGED_NONE;
+ m  R: n# Z; [( Y% Z                                }
0 q1 W  N; ~9 t  i9 N/ A0 R                e. sendIntent函数会准备Intent并且broadcast这个Intent
/ g) U" h8 p0 S! B                                Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED); //public static final String ACTION_BATTERY_CHANGED = "android.intent.action.BATTERY_CHANGED";@batteryservice.java. ~: `6 m3 M) S9 ~+ i% S
                                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY0 I4 @% x  V& P, r( O, W% k2 p
                                        | Intent.FLAG_RECEIVER_REPLACE_PENDING);" ~  T6 ?; b4 Y2 ^' p  ^

4 z4 Y7 {5 I+ j1 N1 @- Z1 n# u                        intent.putExtra(BatteryManager.EXTRA_PLUGGED, mPlugType);4 a1 @" D4 Q- P* S
                                ActivityManagerNative.broadcastStickyIntent(intent, null);
+ E: q8 t8 b4 i9 V2 X4. 分析vendor/sEMC/packages/apps/debugmenu/src/com/sonyericsson/debugmenu/battery.java
( T; _# p% y+ ?8 P                a. 接收intent) b$ S& N+ x# D3 i1 O$ }2 `
                    private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {
; W2 M/ b. z* n! v                                @Override$ k  U3 a4 I5 W- Y" v: w# r8 R
                                public void onReceive(Context arg0, Intent intent) {
( |- E. X3 v2 M* N4 x3 w                                    if (intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) {
/ z: [# A# l' h+ h, l                                        mPowerInformation.parseIntent(intent);
% z; n0 x  m: _6 W" e7 r8 C                                        updateViews();& H) o  s" s# P1 p
                                    }
& A/ n2 N. z/ r- c9 G9 o( G$ y                                }
: A6 W5 l# p( [- l                    };5 z2 k, L' b# e+ L( H! y% C: I
                    public void registerBroadcastReceivers() {! {# n1 Y$ F: P7 q
                                IntentFilter mIntentFilter;4 v8 j2 `! Q" z) Q+ g% X! b
                                mIntentFilter = new IntentFilter();
& d& u' b& {6 }7 k  ~                                mIntentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); //只接收Intent.ACTION_BATTERY_CHANGED的intent% u0 F5 n3 J: t) {4 X7 z
                                // Register battery receiver.
- u( X" D' G% @5 u" s' O- r                                registerReceiver(mBatteryInfoReceiver, mIntentFilter);
5 `! N6 O6 V/ W- U7 t" V# }                    }         4 M, y7 Y! n* f  c' ^2 h- q- C
                b. parseIntent 得到最新的"plugged"值赋给mPlugged
& K! C8 u" x9 ^: C                c. updateViews 更新charger类型显示
8 O9 W) P. \* z###内核空间
* b; ~0 ~& P! O1. 插入充电器触发的过程@kernel/drivers/usb/otg/msm_otg.c  m2 a) z, T' n3 g0 f" Z
                a. CONFIG_PM_RUNTIME 定义 @kernel/arch/ARM/configs/viskan_huashan_defconfig
5 V, d  S/ c5 ^, m                b.msm_otg_runtime_resume-->msm_otg_resume-->??-->msm_otg_sm_work
2 H, U& Y2 v2 y0 T                c.msm_otg_sm_work,先进入OTG_STATE_UNDEFINED case,然后进入OTG_STATE_B_IDLE
$ f& P- G; s. b+ ncase-->motg->chg_state=USB_CHG_STATE_UNDEFINED-->启动msm_chg_detect_work6 ~. k' `1 f9 g9 y: n
                d.msm_chg_detect_work 该函数主要完成USB charger类型的识别7 S. n7 ?5 B; r  W7 G1 m3 h" D
                                USB_CHG_STATE_UNDEFINED //其中psy = power_supply_get_by_name("usb");很关键,表明只是获取usb的power_supply,实际上就是chip->usb_psy@pm8921-charger.c
) l7 z7 H7 K& E  q! s) Y! c                                USB_CHG_STATE_WAIT_FOR_DCD         //Waiting for Data pins contact.
$ \$ t7 F! h, w" F! f- {                                然后多次(MSM_CHG_DCD_MAX_RETRIES=6)检测USB状态,启动queue_delayed_work(motg->wq,
+ ^3 t: Y* }" W. M, W+ k: ?&motg->chg_work, delay); //motg->chg_work=msm_chg_detect_work# u0 ]( @4 t) l2 j1 x
                                USB_CHG_STATE_DETECTED //最后USB charge类型检测完毕2 I1 q1 n# @4 _0 _8 D, V( n% ~
                e. 启动queue_work(motg->wq, &motg->sm_work); //motg->sm_work=msm_otg_sm_work; L, u* J, ^+ k: G
                f. 由于motg->chg_state==USB_CHG_STATE_DETECTED,: N; H) ?5 H& \( I
                                motg->chg_type==USB_DCP_CHARGER -->msm_otg_notify_charger(motg,IDEV_CHG_MAX);//IDEV_CHG_MAX=1500
% ~, X2 P! f3 ?) n+ r+ l2. 发送uevent到用户层7 O* K9 C0 n- w$ x
                a. msm_otg_notify_charger@kernel/drivers/usb/otg/msm_otg.c/ y( L  @5 h, _  v! 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_BATTERY3 g/ L# f8 k4 D
                c. -->power_supply_set_supply_type@power_supply_core.c // set type of the power supply
2 x2 W" `( [7 c" b- I" j                d. -->psy->set_property(psy, POWER_SUPPLY_PROP_TYPE,&ret);
% J, x- }% \: W+ }( J$ ~5 z* p& k                                那么在用usb_psy.get_property和dc_psy.get_property* t/ a7 q/ M2 `8 a# E
(在函数中pm8921_charger_probe)读取property时
; i5 t  b) m7 p' O$ h                                如果是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$ S6 G3 q' w( N7 ~
charger: s$ J* m7 x, z, m) ^0 M& w
                                如果是AC type,则在pm_power_get_property_mains读取POWER_SUPPLY_PROP_ONLINE的值,只有POWER_SUPPLY_TYPE_USB_DCP为AC3 Y3 T* P) ]3 Y& H+ m$ Z) j. Z
charger.+ M/ i9 c4 r. R8 z/ 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.c6 m9 ?, W) W$ F2 Z6 m
                f. -->pm8921_set_usb_power_supply_type(val->intval)@pm8921-charger.c7 E; G* L2 n6 s6 d
                                -->power_supply_changed(&the_chip->usb_psy);
$ m  @6 M6 m0 S) h) i* A1 U; d                                -->power_supply_changed(&the_chip->dc_psy);
3 f5 w% N8 z% m7 N                g. power_supply_changed@pm8921-charger.c , 就会马上发送uevent给user
6 ]6 z6 y+ q' K1 w/ A- ^space,然后user space通过sysfs得到USB' h. u9 N* S1 H- O* Q1 j
type变化后的信息,参考用户空间的分析% N4 Z( w  A2 s) c8 h) X' d

; r( P) M' n% V: o: {1 b  y' H! ]二、硬件分析
: ?* n: F; A% h  H5 M7 S. o' c- L: s8 t* X' a
主要是通过特殊设计的电路,检测不同的pin的状态,从而确定是何种类型的Charger. 更details的内容省略。8 P! }" K/ J4 s' i" O+ _# S2 R

- g  \9 o. _; f9 \9 P
$ V+ u: i" e4 r/ I) p1 W* ^

* L& v4 x! B% m! f  @

该用户从未签到

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

本版积分规则

关闭

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

EDA365公众号

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

GMT+8, 2025-5-31 21:45 , Processed in 0.078125 second(s), 23 queries , Gzip On.

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

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

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