EDA365电子工程师网

标题: USB port 如何识别不同的Charger类型 [打印本页]

作者: tianpu0501    时间: 2015-9-11 22:40
标题: USB port 如何识别不同的Charger类型
USB port 如何识别不同的Charger类型% l  p! f2 G8 u- T: {
2013年10月03日 ⁄ 综合 ⁄ 共 8924字        ⁄ 字号 [url=]小[/url] [url=]中[/url] [url=]大[/url] ⁄ 评论关闭4 P' Z7 _4 O; W/ q3 K

6 L9 X6 P7 I+ _4 \" O一,软件分析1.  USB charger types & Power supply types$ P& p2 z: v. e. s
USB_INVALID_CHARGER              Invalid USB charger.
& V/ T* x! _2 ?9 U2 k5 Q% `0 oUSB_SDP_CHARGER                       Standard downstream port. Refers to a downstream port  on USB2.0 compliant host/hub." W# X/ q) T( x8 k+ w* h
USB_DCP_CHARGER                      Dedicated charger port (AC charger/ Wall charger).' h8 ]9 Q3 r+ B4 o
USB_CDP_CHARGER                      Charging downstream port. Enumeration can happen and IDEV_CHG_MAX can be drawn irrespective of USB state.
9 x* j- U# g. D. ?" VUSB_ACA_A_CHARGER                                
: N; N* v4 y0 Q) ]* M6 [' vB-device is connected on accessory port with charger connected on charging port. This configuration allows charging in host mode.
+ P4 |8 F' _- u: X# b& h2 p9 WUSB_ACA_B_CHARGER                 No device (or A-device without VBUS) is connected on accessory port with charger connected on charging port.
; _  j. `! v. Q& [2 UUSB_ACA_C_CHARGER                 A-device (with VBUS) is connected on accessory port with charger connected on charging port.
) ~& A" ^; w: L5 y$ xUSB_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  accessory4 ]- J. T$ |, o: w# J
ports.
  d, F4 I! O1 w' b5 ^( [0 s* qUSB_PROPRIETARY_CHARGER   A proprietary charger pull DP and DM to specific voltages between 2.0-3.3v for identification.6 w9 c- p! W2 L/ S' B
$ r5 y- g$ @$ E% [3 R: G; e
POWER_SUPPLY_TYPE_USB,                      * C3 _! P8 T$ H" Q0 W  I$ T" s* D
/* Standard Downstream Port */
  C, F5 s/ }/ m+ P' D* J1 mPOWER_SUPPLY_TYPE_USB_DCP,           /* Dedicated Charging Port */
, m' k9 R( a5 `( D8 y. W9 GPOWER_SUPPLY_TYPE_USB_CDP,           /* Charging Downstream Port */6 r# z  d8 a4 `- x) q6 ^3 R3 A
POWER_SUPPLY_TYPE_USB_ACA,           /* Accessory Charger Adapters */  X# o7 r# r% @2 ?9 C
POWER_SUPPLY_TYPE_BMS,                     
- j! Q5 k* s! V2 U/* Battery Monitor System */( T2 R- \, f! u/ u9 u2 {$ {$ h

5 g4 V" x" T# }) v, r9 j2. How to classify or identify charger?( W) X* a8 k; r2 h' R. b

, ^$ h& r/ [1 G' z* P3 P
USB_SDP_CHARGER( G# W, X% S% Q8 {7 [/ [
POWER_SUPPLY_TYPE_USB# U/ R! \: O/ v1 r8 |3 i
USB Charger
USB_CDP_CHARGER% m0 D. |4 L( j, G5 N/ D
POWER_SUPPLY_TYPE_USB_CDP1 E: e9 b$ m. _' ]5 G; K- z" z
USB_ACA_DOCK_CHARGER# ?2 I8 q( ]) F5 y
POWER_SUPPLY_TYPE_USB_ACA
USB_ACA_A_CHARGER! U# s: s+ u3 y/ s3 T7 y* I- v
USB_ACA_B_CHARGER
' M0 E7 [/ J! h# J; ^
USB_ACA_C_CHARGER+ p6 d( O6 Y* z+ l- \5 r% U, p
USB_DCP_CHARGER+ p1 S& U0 G- Z' Y) _2 D6 m0 K
POWER_SUPPLY_TYPE_USB_DCP
AC Charger
USB_PROPRIETARY_CHARGER
) h! b0 G" P( l/ t; x  g: R

: Z: o' P) b+ b+ Q, K4 ]5 n  IAs for the DMS, refer to bold font items, so it is USB charger.9 J0 X% Q; T) N

1 R* A( e4 W+ Z: Q3. Analysis about source codes
5 h* b% G* Q& y2 c*******************************************************************
5 L3 l! `& x& M5 ^3 L+ [; K###用户空间的分析如下:, j* y( E7 B: Z. D4 X
1. 检查 /sys/class/power_supply/pm8921-dc/online和5 n# `( z% c) f, u1 V  D- P* j. C
/sys/class/power_supply/usb/online 的值,可以知道是何充电器类型% @7 e) o! Y4 q' V+ B
                @frameworks/base/services/jni/com_android_server_batteryservice.cpp中有
% P' {, {- ?$ m/ Q, J- m+ `                int register_android_server_BatteryService(JNIEnv* env)         
1 t& X- Y' H7 D. h+ O$ r# l/ S. b( G7 r                {
2 S1 A* Y; H% P# `                if (strcmp(buf, "Mains") == 0) { ///sys/class/power_supply/pm8921-dc/type == Mains: c# j: c' Z* N
                    snprintf(path, sizeof(path), "%s/%s/online", POWER_SUPPLY_PATH, name);  P* p1 w8 w; Q( \6 t3 G, I1 X
                    if (access(path, R_OK) == 0)
6 x6 k) k, }+ W                        gPaths.acOnlinePath = strdup(path);7 p6 B9 x9 z) i$ ?+ H" H) |
                }& U1 m8 F6 m, Z; m* `" E8 r; M
                }' I" \  \/ p3 P1 F0 l
   如果/sys/class/power_supply/pm8921-dc/online==1,则插入的充电器是wall
0 _) u' T5 a0 a$ H& T# a  |charger
8 K( l3 ?9 m: {' A0 `7 Y: U
      /sys/class/power_supply/usb/online==1, ! Y; R( d. F2 T3 W
则插入的充电器是usb charger

' s7 \; c+ y7 _. _6 u- Y7 F   调试路径:/sys/kernel/debug/msm_otg6 W' |. P0 R$ N- a
2. 分析frameworks/base/services/jni/com_android_server_batteryservice.cpp  z/ s! M4 u1 d2 ^
                a.函数register_android_server_BatteryService将为被frameworks/base/services/jni/onload.cpp中的JNI_OnLoad调用,用于关联java和C++之间的变量! h* I4 W( j9 e, w
                b.jclass clazz = env->FindClass("com/android/server/BatteryService"); //根据java的路径找到batteryservice.java对应的jclass    $ h0 _5 W/ \9 Z7 b8 _
                  gFieldIds.mAcOnline = env->GetFieldID(clazz, "mAcOnline", "Z");1 a0 D: v8 ~+ o! a+ {2 h
                  gFieldIds.mUsbOnline = env->GetFieldID(clazz, "mUsbOnline", "Z"); //用于关联batteryservice.java中变量private
  q: F: L% t" [boolean mAcOnline和gFieldIds.mAcOnline4 ~2 M- g5 T: [% s! O; p  P
                c. android_server_BatteryService_update! L% _* t9 E; {, h  K7 ?8 f/ d
                                static JNINativeMethod sMethods[] = {' R& E# J2 a! E* d% g
                                     /* name, signature, funcPtr */, r) l" q# k# S/ Z$ \0 t( F( t; R
                                                {"native_update", "()V", (void*)android_server_BatteryService_update},
# b/ W1 T& V0 c) K6 r                                };$ Y5 R5 D$ D. J; D. R
                   关联到native_update@frameworks/base/services/java/com/android/server/batteryservice.java9 ]6 A/ C5 v+ ~. S8 I7 i& F+ \
3. 分析frameworks/base/services/java/com/android/server/batteryservice.java# f, l" R% o& O5 Y- |
                a. mPowerSupplyObserver.startObserving("SUBSYSTEM=power_supply"); //注册监听该uevent( W  E6 A6 e' F; R: ?
                b.     private UEventObserver mPowerSupplyObserver = new UEventObserver() {
' X5 J) n- Z% {  Z  y' ]                                public void onUEvent(UEventObserver.UEvent event) { //如果就收到来自kernel的uevent,触发该函数
& S" ^2 A' F4 o5 z/ O8 J8 z                                    update(); //-->native_update();和processValues();
, Z+ y- p. c5 W  q  K, {# F/ U                                }' c8 C, i% |' k( B
                       };
6 d( N3 @- y% p" L0 N; I( T                c. native_update函数会通过JNI调用得到更新的mAcOnline和mUsbOnline值
1 I4 Q  K0 b0 c                d. processValues会根据mAcOnline和mUsbOnline值对mPlugType赋值. p2 A8 W/ \- k
                                if (mAcOnline) {  |; I+ Z0 X* Y; Y. f4 T5 u
                                    mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
  {; e1 `* a+ k1 E. \                                } else if (mUsbOnline) {
" h5 F4 f4 o* o* O" j                                    mPlugType = BatteryManager.BATTERY_PLUGGED_USB;. U7 [6 H2 w  h1 I: W) N
                                } else {9 [' U, n9 e9 h+ X8 E/ R
                                    mPlugType = BATTERY_PLUGGED_NONE;
% P. [, H6 ?3 l                                }# H% L1 F1 I6 _0 b% I- k2 G
                e. sendIntent函数会准备Intent并且broadcast这个Intent. G2 ?- A" {: d( F
                                Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED); //public static final String ACTION_BATTERY_CHANGED = "android.intent.action.BATTERY_CHANGED";@batteryservice.java! N! ]$ w2 {9 \) D$ x# F1 X
                                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
" I, o! ~! b% }4 S% \                                        | Intent.FLAG_RECEIVER_REPLACE_PENDING);
, ?( z$ X' p, e) {% e& Q5 e. k
8 g0 Z1 |; Q& L) |: [2 t. r, C                        intent.putExtra(BatteryManager.EXTRA_PLUGGED, mPlugType);5 c( L( Y" M* C3 ]
                                ActivityManagerNative.broadcastStickyIntent(intent, null);
2 C4 u3 d, @2 {& [) V# v* ^4. 分析vendor/semc/packages/apps/debugmenu/src/com/sonyericsson/debugmenu/battery.java
/ f$ m3 V4 y1 u7 O$ h% r( n                a. 接收intent
; @; U/ h6 F* ^1 W# s! Q8 @                    private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {* b5 i: a* t( |# F" T# z, w
                                @Override8 J+ Y* q" G- ]7 p
                                public void onReceive(Context arg0, Intent intent) {8 f; W5 ?4 _$ X( H2 X
                                    if (intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) {
' K- {7 c+ t  M, ]! h                                        mPowerInformation.parseIntent(intent);
" g2 {5 z1 C" L( g8 s1 X" K' q0 t                                        updateViews();
3 W3 w7 {/ C% a3 y                                    }
4 I7 |% R- r& _                                }
& L3 d$ |( b9 f                    };
  Y; t  E: z; W& s! Y  h9 ~0 X" g                    public void registerBroadcastReceivers() {
- H4 ~0 |3 C# g& d; A4 g$ c( I                                IntentFilter mIntentFilter;
9 B7 {# N, s! m, ?# ~                                mIntentFilter = new IntentFilter();
3 l, x& F, z4 g/ e                                mIntentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); //只接收Intent.ACTION_BATTERY_CHANGED的intent
8 P/ ]5 L; Y/ v& R! q                                // Register battery receiver.: B+ I4 S& f# e& j' k" |$ ~* ]
                                registerReceiver(mBatteryInfoReceiver, mIntentFilter);5 Z7 F! h7 N* K) p
                    }         
2 c8 g* f; M! Q+ d$ X                b. parseIntent 得到最新的"plugged"值赋给mPlugged
, [  m. `: Y1 a( W; k1 L                c. updateViews 更新charger类型显示
% s" }8 I- {! ^, E) Z7 \/ q* ^###内核空间7 o7 d* Z0 h6 j0 {+ _
1. 插入充电器触发的过程@kernel/drivers/usb/otg/msm_otg.c8 t' l  F7 M" O7 t
                a. CONFIG_PM_RUNTIME 定义 @kernel/arch/arm/configs/viskan_huashan_defconfig; J+ I8 i7 k1 O  O/ ^% d
                b.msm_otg_runtime_resume-->msm_otg_resume-->??-->msm_otg_sm_work9 n0 M- X8 Q" m* [
                c.msm_otg_sm_work,先进入OTG_STATE_UNDEFINED case,然后进入OTG_STATE_B_IDLE
& u( y. }/ ?- Z0 X8 T9 lcase-->motg->chg_state=USB_CHG_STATE_UNDEFINED-->启动msm_chg_detect_work
9 P2 V' U$ ^) |: N% _! M8 }1 J7 Z                d.msm_chg_detect_work 该函数主要完成USB charger类型的识别
. }: m) {5 h$ v4 S0 z                                USB_CHG_STATE_UNDEFINED //其中psy = power_supply_get_by_name("usb");很关键,表明只是获取usb的power_supply,实际上就是chip->usb_psy@pm8921-charger.c4 G; _& S& i) |' y+ v  L2 U
                                USB_CHG_STATE_WAIT_FOR_DCD         //Waiting for Data pins contact.
9 ], u" F5 _1 z/ M5 J                                然后多次(MSM_CHG_DCD_MAX_RETRIES=6)检测USB状态,启动queue_delayed_work(motg->wq,( d/ Y* F3 H' L# q
&motg->chg_work, delay); //motg->chg_work=msm_chg_detect_work
/ [! X) n' P" f! |  m8 x/ ]6 e  u                                USB_CHG_STATE_DETECTED //最后USB charge类型检测完毕) g9 N$ R, n% H# q  C; a
                e. 启动queue_work(motg->wq, &motg->sm_work); //motg->sm_work=msm_otg_sm_work3 e8 ?" \  Y3 \4 y
                f. 由于motg->chg_state==USB_CHG_STATE_DETECTED,
2 T4 X0 }* A! S5 f- E5 C* N* x                                motg->chg_type==USB_DCP_CHARGER -->msm_otg_notify_charger(motg,IDEV_CHG_MAX);//IDEV_CHG_MAX=1500
; @! o+ m3 G: u. o0 L4 S$ S2. 发送uevent到用户层0 t2 h0 v9 D2 H0 i4 c
                a. msm_otg_notify_charger@kernel/drivers/usb/otg/msm_otg.c/ r: b& v: Z! q; r
                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' P3 u1 f2 P! P+ s: X6 A
                c. -->power_supply_set_supply_type@power_supply_core.c // set type of the power supply
+ Z* q+ F! Q# H  K                d. -->psy->set_property(psy, POWER_SUPPLY_PROP_TYPE,&ret);% u/ w  W( H0 w  f% t4 }3 N
                                那么在用usb_psy.get_property和dc_psy.get_property
! c% z& R( N; I4 L1 d(在函数中pm8921_charger_probe)读取property时9 o$ n- w6 K' q& N/ H2 F' \8 y( `
                                如果是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
) Y6 G2 ^* @" t  h  v$ |charger
! Y3 D8 Q+ ?4 n                                如果是AC type,则在pm_power_get_property_mains读取POWER_SUPPLY_PROP_ONLINE的值,只有POWER_SUPPLY_TYPE_USB_DCP为AC
; c7 o4 }' L. C4 dcharger.
2 A# a2 Y, v. d: @                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
  Y& [; B# h* m/ ^- Z( ]4 T                f. -->pm8921_set_usb_power_supply_type(val->intval)@pm8921-charger.c  }, Z5 e. _# y
                                -->power_supply_changed(&the_chip->usb_psy);' C2 F' H6 f3 C8 G5 |) J
                                -->power_supply_changed(&the_chip->dc_psy);
* `2 L: v7 y% G& r" y                g. power_supply_changed@pm8921-charger.c , 就会马上发送uevent给user
0 [8 _2 ?$ |3 ?& G( F1 Kspace,然后user space通过sysfs得到USB9 r7 s6 v' ^4 a7 Y% f
type变化后的信息,参考用户空间的分析
$ l$ r5 n' o% G" e0 _+ z5 X9 p# L' X1 \
二、硬件分析
7 v0 V8 u6 ~$ H3 j  ?6 g! O- s9 Z
7 a9 F, M9 v, U- [% ?% u主要是通过特殊设计的电路,检测不同的pin的状态,从而确定是何种类型的Charger. 更details的内容省略。
" j% I' u! B" c) y* w, `6 q; }& ]- B- K5 }

6 b/ o2 D3 T( `' [; R" w7 q& }  |
: ~; i' z5 Q0 S
作者: 天天在线    时间: 2015-9-17 09:16
支持一下
作者: IterSu    时间: 2015-10-20 22:16
        顶一下,问题有点长。




欢迎光临 EDA365电子工程师网 (https://bbs.elecnest.cn/) Powered by Discuz! X3.2