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

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
USB port 如何识别不同的Charger类型6 [" [0 o! Y, {5 Z2 F, s' W
2013年10月03日 ⁄ 综合 ⁄ 共 8924字        ⁄ 字号 [url=]小[/url] [url=]中[/url] [url=]大[/url] ⁄ 评论关闭5 C- U  [2 K( ~9 c- e

8 w5 D  Z3 Q7 p' {/ Z& c( \/ E: P一,软件分析1.  USB charger types & Power supply types
8 C$ q: |3 D( M( NUSB_INVALID_CHARGER              Invalid USB charger.. @6 ]0 Z! z# C7 d0 T6 p  _
USB_SDP_CHARGER                       Standard downstream port. Refers to a downstream port  on USB2.0 compliant host/hub.
; s9 l, z0 b: y# T( J( W# [USB_DCP_CHARGER                      Dedicated charger port (AC charger/ Wall charger).
) Z# @; g: J. s+ |USB_CDP_CHARGER                      Charging downstream port. Enumeration can happen and IDEV_CHG_MAX can be drawn irrespective of USB state.
* w6 P9 z2 {' M: }5 VUSB_ACA_A_CHARGER                                9 b4 o4 x7 J, R& Y% o3 D
B-device is connected on accessory port with charger connected on charging port. This configuration allows charging in host mode.
( c: g+ N! e1 \) J& Q2 C3 {USB_ACA_B_CHARGER                 No device (or A-device without VBUS) is connected on accessory port with charger connected on charging port.
2 _( }  }9 e; [  @& o3 \3 ^! \USB_ACA_C_CHARGER                 A-device (with VBUS) is connected on accessory port with charger connected on charging port.
3 T/ O# z5 x) M  [+ j! a) YUSB_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! m) `( G5 h% ^3 a6 y
ports.8 J7 t  L% ?$ `2 q( e1 s
USB_PROPRIETARY_CHARGER   A proprietary charger pull DP and DM to specific voltages between 2.0-3.3v for identification.
+ o, }& R9 C4 J" P- J1 W7 l 6 u' t$ f2 V- |9 @
POWER_SUPPLY_TYPE_USB,                     
8 w; S; D" \- c3 J- ~8 D/* Standard Downstream Port */
. |4 @" r) R5 l, pPOWER_SUPPLY_TYPE_USB_DCP,           /* Dedicated Charging Port */' b7 S' f3 ?, j) [: ?9 V5 _# b
POWER_SUPPLY_TYPE_USB_CDP,           /* Charging Downstream Port */7 T' e1 M+ P# Q/ L7 \$ _4 ]
POWER_SUPPLY_TYPE_USB_ACA,           /* Accessory Charger Adapters */& p+ Y4 `! i& I" v
POWER_SUPPLY_TYPE_BMS,                     $ \/ s6 q9 A* a; N% G
/* Battery Monitor System */
; ~& L, K% V1 v& z% f. h
4 M* z5 N4 Q0 D5 h8 g/ _2. How to classify or identify charger?
. a$ T: Y; v# U! [
( g! {8 Q; r0 u1 B4 k; M2 H
USB_SDP_CHARGER
' \% f' L3 M" v* o
POWER_SUPPLY_TYPE_USB
. U# \( p7 b7 X0 A1 ]" X: M7 K$ I5 i
USB Charger
USB_CDP_CHARGER( C: ?1 m& z& X1 o7 R# N/ `/ a, C' l
POWER_SUPPLY_TYPE_USB_CDP
9 |6 t* D2 }& T- y  N3 C. G
USB_ACA_DOCK_CHARGER- F: @& W9 a/ y' n7 i' ~
POWER_SUPPLY_TYPE_USB_ACA
USB_ACA_A_CHARGER* v# N9 V) X' V: @3 L
USB_ACA_B_CHARGER
. C# s1 y/ Z! I1 w/ `
USB_ACA_C_CHARGER- R6 Y2 y* e6 l9 }8 ?" N& i5 P
USB_DCP_CHARGER
. m: E! x  Q( J8 J1 Z( E
POWER_SUPPLY_TYPE_USB_DCP
AC Charger
USB_PROPRIETARY_CHARGER
2 ^. B# E; ^( b1 `7 Y  n- S
- L. D8 m( X3 a( Q) W- d
As for the DMS, refer to bold font items, so it is USB charger.  q  Y) b9 A" e+ \$ i" F9 O
) }: \! ^& G6 j
3. Analysis about source codes: t. V  G5 F/ q2 R
*******************************************************************! f) T( @5 \1 i  g6 m
###用户空间的分析如下:1 A) l' d' r) Z) i! [
1. 检查 /sys/class/power_supply/pm8921-dc/online和4 ]; R9 Y5 C+ ^( c& h% @
/sys/class/power_supply/usb/online 的值,可以知道是何充电器类型# z7 ~+ q+ X* W# K% f4 r) o7 O
                @frameworks/base/services/jni/com_android_server_batteryservice.cpp中有( H6 U. H7 B! P& V6 S$ x
                int register_android_server_BatteryService(JNIEnv* env)          ' M0 P0 Z6 W( v' \
                {
# d. c2 t4 U$ t. Y                if (strcmp(buf, "Mains") == 0) { ///sys/class/power_supply/pm8921-dc/type == Mains# m7 V; R1 ]$ ~0 x; s9 N
                    snprintf(path, sizeof(path), "%s/%s/online", POWER_SUPPLY_PATH, name);
% b/ B8 S8 T3 u3 O' F                    if (access(path, R_OK) == 0)2 _& T& Q6 B& k7 R& g7 H
                        gPaths.acOnlinePath = strdup(path);  H* h4 ~1 l. T5 S+ s$ i# ^  k
                }
2 [3 Z% ]# b# v                }, z; f/ @! @2 \4 O1 _
   如果/sys/class/power_supply/pm8921-dc/online==1,则插入的充电器是wall
' f+ _/ u' D" [5 p1 u1 f+ h7 B; jcharger
# n8 f( q% \  P7 W  V& p3 |9 e$ ^
      /sys/class/power_supply/usb/online==1, & O7 x3 d& l: J. [+ B9 h9 i2 S
则插入的充电器是usb charger

6 w( H4 f7 i, a   调试路径:/sys/kernel/debug/msm_otg! z1 X# N+ X9 L3 R+ P! T: B
2. 分析frameworks/base/services/jni/com_android_server_batteryservice.cpp) ]; Z6 |" R/ T- H& l' N/ n8 \. D
                a.函数register_android_server_BatteryService将为被frameworks/base/services/jni/onload.cpp中的JNI_OnLoad调用,用于关联java和C++之间的变量7 T1 e2 N9 f# t1 A9 {& B, F
                b.jclass clazz = env->FindClass("com/android/server/BatteryService"); //根据java的路径找到batteryservice.java对应的jclass    ; i( F3 l  p4 r6 x: ]
                  gFieldIds.mAcOnline = env->GetFieldID(clazz, "mAcOnline", "Z");7 R/ i9 s' {) I- _: C2 F
                  gFieldIds.mUsbOnline = env->GetFieldID(clazz, "mUsbOnline", "Z"); //用于关联batteryservice.java中变量private
7 L: W) Y+ V* ?9 H7 tboolean mAcOnline和gFieldIds.mAcOnline' `  \, t, q7 t5 k
                c. android_server_BatteryService_update
7 [# o; \2 x& s1 g% F5 d                                static JNINativeMethod sMethods[] = {
, R1 \; `' n# {5 w' f" e' E0 p* X                                     /* name, signature, funcPtr */
% |. M- B* h( k2 R+ P# |5 U/ `$ r' u                                                {"native_update", "()V", (void*)android_server_BatteryService_update},- i# _5 ^- v; E
                                };
' c+ C5 k# B2 r( s) D' [' }2 ^                   关联到native_update@frameworks/base/services/java/com/android/server/batteryservice.java( ^( q0 U5 N2 ^  }5 Z
3. 分析frameworks/base/services/java/com/android/server/batteryservice.java) W2 ?  S2 N6 Y6 B
                a. mPowerSupplyObserver.startObserving("SUBSYSTEM=power_supply"); //注册监听该uevent
/ k9 S  V  d1 t: k, _1 F                b.     private UEventObserver mPowerSupplyObserver = new UEventObserver() {
0 R- t, H! P- K) z                                public void onUEvent(UEventObserver.UEvent event) { //如果就收到来自kernel的uevent,触发该函数
% |/ D/ k/ l1 x% L8 J. h                                    update(); //-->native_update();和processValues();
  u" ~! `8 U: k0 _1 N9 ~+ Q1 L% j                                }: n" r4 V4 }9 B" u" [
                       };
: j7 O" x- L0 U- B- c& o8 _6 b                c. native_update函数会通过JNI调用得到更新的mAcOnline和mUsbOnline值
0 c- D2 x* T7 D7 Y' A# V/ S& i  X                d. processValues会根据mAcOnline和mUsbOnline值对mPlugType赋值
! h: l. r  V5 Y9 q5 J/ B                                if (mAcOnline) {
" R. V1 d) H; o& Z8 t  T+ p" h; B                                    mPlugType = BatteryManager.BATTERY_PLUGGED_AC;- G& q% `3 z/ Z: j* k9 X2 H" o
                                } else if (mUsbOnline) {
9 D4 F) E' S$ {1 V& B' r                                    mPlugType = BatteryManager.BATTERY_PLUGGED_USB;2 V2 L3 V- t  Z6 A$ ]( B
                                } else {
2 w! \3 A6 l  p0 i4 k                                    mPlugType = BATTERY_PLUGGED_NONE;
6 X- k- i* y2 P4 ]5 A' E& B9 f                                }) d8 Q# e! J" p5 t$ D' G! [
                e. sendIntent函数会准备Intent并且broadcast这个Intent) f) ^, T+ y& c$ f5 K( }( I& O# v
                                Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED); //public static final String ACTION_BATTERY_CHANGED = "android.intent.action.BATTERY_CHANGED";@batteryservice.java
  \+ l- t7 P+ p4 ]2 T1 J                                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY6 _( u: o( J3 E! j
                                        | Intent.FLAG_RECEIVER_REPLACE_PENDING);5 x* \& j0 `$ M$ L1 X( _' R8 U8 s
3 g5 ~# @! x' J  C# e
                        intent.putExtra(BatteryManager.EXTRA_PLUGGED, mPlugType);
! D/ |, u7 p5 j                                ActivityManagerNative.broadcastStickyIntent(intent, null);
: w, p+ Z2 ?8 v1 r0 H3 O: E4. 分析vendor/sEMC/packages/apps/debugmenu/src/com/sonyericsson/debugmenu/battery.java* d- k7 G$ @5 {6 {0 g
                a. 接收intent9 T) {2 C( I& R/ a
                    private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {8 `$ K) N0 w, X# ^. d/ e1 U
                                @Override. {9 [+ g' m+ Z- G+ A0 d* `
                                public void onReceive(Context arg0, Intent intent) {
/ ~7 C% q' B. ~& a; n: T  D2 Z                                    if (intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) {
, @/ X- S. q  G5 X9 z' h) p                                        mPowerInformation.parseIntent(intent);* s; t9 t- _, D- `9 j2 Y9 e
                                        updateViews();7 i5 c3 o8 S/ q
                                    }6 A1 J/ R: G1 q. P" N2 N) V* Z
                                }
$ S+ r. B& c4 p) g                    };
) c- i/ u6 s6 ~; \                    public void registerBroadcastReceivers() {. ~- N$ }- G* I( N, V) E: k
                                IntentFilter mIntentFilter;9 m: I# _7 `" j$ E! }
                                mIntentFilter = new IntentFilter();
) v9 G6 `  ^1 q+ p: t0 G% g                                mIntentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); //只接收Intent.ACTION_BATTERY_CHANGED的intent
3 c* N$ D9 B) G                                // Register battery receiver.
, \" Q1 f: }# u/ b: {$ q                                registerReceiver(mBatteryInfoReceiver, mIntentFilter);
( x* {( |$ A# T3 I! z; y' U& m                    }         
& q  D0 U9 x4 @4 {' q+ W# {                b. parseIntent 得到最新的"plugged"值赋给mPlugged
% L0 H9 P) a! o) P" h5 y                c. updateViews 更新charger类型显示: c8 J8 m5 b5 w
###内核空间
, T+ n/ n# A1 ?2 w9 w- v9 o1. 插入充电器触发的过程@kernel/drivers/usb/otg/msm_otg.c
$ y6 |4 P; A7 p' {5 Y                a. CONFIG_PM_RUNTIME 定义 @kernel/arch/ARM/configs/viskan_huashan_defconfig
: z8 N! o' {4 p$ @5 M. M                b.msm_otg_runtime_resume-->msm_otg_resume-->??-->msm_otg_sm_work6 t0 T" `$ y: s" Z
                c.msm_otg_sm_work,先进入OTG_STATE_UNDEFINED case,然后进入OTG_STATE_B_IDLE* Y4 T0 x5 `" I
case-->motg->chg_state=USB_CHG_STATE_UNDEFINED-->启动msm_chg_detect_work2 Q5 Q, G0 S. k, H( Z
                d.msm_chg_detect_work 该函数主要完成USB charger类型的识别% |# S4 v9 ~* h  z" @% u
                                USB_CHG_STATE_UNDEFINED //其中psy = power_supply_get_by_name("usb");很关键,表明只是获取usb的power_supply,实际上就是chip->usb_psy@pm8921-charger.c
& S# a, t0 F/ x: _3 q5 }                                USB_CHG_STATE_WAIT_FOR_DCD         //Waiting for Data pins contact.& r) K$ Y' `, s& S# o% v- Y% _
                                然后多次(MSM_CHG_DCD_MAX_RETRIES=6)检测USB状态,启动queue_delayed_work(motg->wq,0 b$ s; _# f- [4 m% |! k7 S2 ^
&motg->chg_work, delay); //motg->chg_work=msm_chg_detect_work
, G; X  s4 n% b. I0 C                                USB_CHG_STATE_DETECTED //最后USB charge类型检测完毕
7 V  l8 G6 Y' k* l; a: ]                e. 启动queue_work(motg->wq, &motg->sm_work); //motg->sm_work=msm_otg_sm_work; @' ^) ^5 u+ n6 o0 M6 @: f9 O
                f. 由于motg->chg_state==USB_CHG_STATE_DETECTED,9 Q) [0 W7 x  q, _2 r8 x, T; j' f
                                motg->chg_type==USB_DCP_CHARGER -->msm_otg_notify_charger(motg,IDEV_CHG_MAX);//IDEV_CHG_MAX=15005 F" U; W8 R* Y# ~
2. 发送uevent到用户层: `& p* j9 n: z1 [
                a. msm_otg_notify_charger@kernel/drivers/usb/otg/msm_otg.c
4 V/ D2 S6 I- w/ O( [: N4 w                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
0 D: f4 H& l. O) U' M- z                c. -->power_supply_set_supply_type@power_supply_core.c // set type of the power supply' |- Z* ^6 Y( W0 o+ P' S' _' E
                d. -->psy->set_property(psy, POWER_SUPPLY_PROP_TYPE,&ret);) q0 Y2 l8 _; W7 N
                                那么在用usb_psy.get_property和dc_psy.get_property( a: r# {% V& u7 u# `) J
(在函数中pm8921_charger_probe)读取property时) M; O) n  x: {- 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  k$ W3 f  u( e' U6 _% {
charger$ B. p" T7 p0 W3 d& x( l, Y
                                如果是AC type,则在pm_power_get_property_mains读取POWER_SUPPLY_PROP_ONLINE的值,只有POWER_SUPPLY_TYPE_USB_DCP为AC, t8 Y* B3 }" [( V% `  S1 Z
charger.
; K4 Q3 h$ U0 _$ c8 h4 e* {. V" I, G% ^                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.c4 [: X1 \0 ~5 l8 s  x
                f. -->pm8921_set_usb_power_supply_type(val->intval)@pm8921-charger.c' F0 Q1 q( z; _; ^
                                -->power_supply_changed(&the_chip->usb_psy);
# b: n2 }( D# `) F# K" P( }$ l5 x% c                                -->power_supply_changed(&the_chip->dc_psy);- k! o# z* b/ h+ h5 n) u
                g. power_supply_changed@pm8921-charger.c , 就会马上发送uevent给user7 U3 {4 I. W/ h; E; ~9 D
space,然后user space通过sysfs得到USB9 e6 f3 \- V& i. g
type变化后的信息,参考用户空间的分析, I) U  x- c9 B- T. g
0 o8 A% x7 H% o9 f2 p) I5 a6 m! z" f$ @5 R
二、硬件分析
% O- t& y9 V5 t! A: L% k5 N* {5 Y* h7 E  g- A+ P2 @2 E: M9 }0 N
主要是通过特殊设计的电路,检测不同的pin的状态,从而确定是何种类型的Charger. 更details的内容省略。  P) H0 A; e1 L1 {- E& q1 y* |
+ h' X  m7 b8 {
2 L7 |. {1 s* ^8 ^/ Y  y0 J& s7 |

3 _) o' y4 u2 \1 C; p4 D( y

该用户从未签到

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

本版积分规则

关闭

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

EDA365公众号

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

GMT+8, 2025-8-2 12:06 , Processed in 0.125000 second(s), 23 queries , Gzip On.

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

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

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