找回密码
 注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

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

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

[复制链接]

42

主题

78

帖子

523

积分

三级会员(30)

Rank: 3Rank: 3Rank: 3

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

EDA365欢迎您!

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

x
USB port 如何识别不同的Charger类型1 C# k! G; `; g) o, v8 n7 |% p
2013年10月03日 ⁄ 综合 ⁄ 共 8924字        ⁄ 字号 [url=]小[/url] [url=]中[/url] [url=]大[/url] ⁄ 评论关闭
- t. m1 R% w' O. M1 ^, Y; i1 z0 f
$ j2 [6 m9 D/ S一,软件分析1.  USB charger types & Power supply types
. {, |1 x8 e" }7 F/ BUSB_INVALID_CHARGER              Invalid USB charger.$ F$ E( Y1 V: M/ v
USB_SDP_CHARGER                       Standard downstream port. Refers to a downstream port  on USB2.0 compliant host/hub.5 P) M6 }0 z- }0 \& F
USB_DCP_CHARGER                      Dedicated charger port (AC charger/ Wall charger).0 D" S" q- F2 g, |. b  o% @
USB_CDP_CHARGER                      Charging downstream port. Enumeration can happen and IDEV_CHG_MAX can be drawn irrespective of USB state.9 P# g+ H" n* @: {4 Q
USB_ACA_A_CHARGER                                
  s: M8 t" S3 v  X. BB-device is connected on accessory port with charger connected on charging port. This configuration allows charging in host mode.
7 c0 w3 k3 I" c0 U) X% UUSB_ACA_B_CHARGER                 No device (or A-device without VBUS) is connected on accessory port with charger connected on charging port.
( p8 T1 X" T9 p& o. u( oUSB_ACA_C_CHARGER                 A-device (with VBUS) is connected on accessory port with charger connected on charging port.' E6 [- g0 L; r8 X' [  {$ n0 z
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
2 P: R; `4 a7 \6 e! }! aports.7 B8 g- a9 J$ s3 F5 L( Y
USB_PROPRIETARY_CHARGER   A proprietary charger pull DP and DM to specific voltages between 2.0-3.3v for identification.
8 r2 ^7 ^' U! P  ?; M . _- E1 @2 q& i/ b# u
POWER_SUPPLY_TYPE_USB,                      4 v5 F; Y0 L  O  p2 [3 L! }7 k
/* Standard Downstream Port */7 E% z( x" J* Q) G0 Z! T
POWER_SUPPLY_TYPE_USB_DCP,           /* Dedicated Charging Port */* Y% n1 F5 S% W6 f! y$ O0 C
POWER_SUPPLY_TYPE_USB_CDP,           /* Charging Downstream Port */  v& ~) y9 Q2 T, s+ k9 `) }
POWER_SUPPLY_TYPE_USB_ACA,           /* Accessory Charger Adapters */- n3 L1 x7 P0 ]2 X
POWER_SUPPLY_TYPE_BMS,                     * {; @1 z) p; b3 h4 @5 Q7 V
/* Battery Monitor System */
- y# d7 e5 D% h; h% }; V9 { 8 ?7 U8 A" l6 c8 w# G$ H! d- Y
2. How to classify or identify charger?
6 B* L0 T; R4 B  M( T. C* G , Y8 _7 g5 w* Z3 B& Y- b
USB_SDP_CHARGER" H. ^9 W1 O. E: w/ F$ P8 B
POWER_SUPPLY_TYPE_USB
) O1 k1 c2 b- b/ A$ @- g& x5 ^
USB Charger
USB_CDP_CHARGER9 \8 v3 l4 e$ O2 \& u  F$ t
POWER_SUPPLY_TYPE_USB_CDP/ J) X4 H6 L; x- {: i3 t+ M
USB_ACA_DOCK_CHARGER0 K& j3 b$ A! e. o) y1 R
POWER_SUPPLY_TYPE_USB_ACA
USB_ACA_A_CHARGER
/ l5 r( i3 m3 W1 _! r& H' A# d# |/ ]) w
USB_ACA_B_CHARGER
2 Z' h# R6 M# l7 M4 Z6 c- }
USB_ACA_C_CHARGER& m4 c9 n. ^. B  f5 T6 W6 R6 |! B
USB_DCP_CHARGER( {$ p, Z7 @2 j, I( f0 I
POWER_SUPPLY_TYPE_USB_DCP
AC Charger
USB_PROPRIETARY_CHARGER
" a& q; u. T" {: c% ^" v
5 E4 w* W, r# L& ?9 u
As for the DMS, refer to bold font items, so it is USB charger.
7 Y; Y$ s5 M, w , ]9 H6 Z& A: `, ]/ c2 v* S
3. Analysis about source codes
% r" W( a# `9 w+ f# }*******************************************************************
" I, b  I, p; Y' d* P###用户空间的分析如下:
6 H% K5 u4 p5 h# d1. 检查 /sys/class/power_supply/pm8921-dc/online和* n* U  K7 Z1 ~% m" I; ?. n! q* X
/sys/class/power_supply/usb/online 的值,可以知道是何充电器类型
3 a4 P3 }0 T, ~* M# T1 K                @frameworks/base/services/jni/com_android_server_batteryservice.cpp中有
, ~0 y6 a) C( K/ f# o2 _' K                int register_android_server_BatteryService(JNIEnv* env)         
& f0 f) ?6 i$ _, t# I0 h1 X# x                {8 o$ I# d- `  C1 O: P1 a
                if (strcmp(buf, "Mains") == 0) { ///sys/class/power_supply/pm8921-dc/type == Mains
/ b7 K" `2 I$ |                    snprintf(path, sizeof(path), "%s/%s/online", POWER_SUPPLY_PATH, name);5 ?  x4 i2 X& y' R" n* u+ L, T7 C
                    if (access(path, R_OK) == 0)3 }  {( z( |" k8 V
                        gPaths.acOnlinePath = strdup(path);
+ S- F: \- D# s( D; x  A+ W9 p                }
% H( U. c: i- E6 M3 ]" Y                }$ K* `5 ]) x3 a/ t0 V* d
   如果/sys/class/power_supply/pm8921-dc/online==1,则插入的充电器是wall
' p4 z7 D7 q; ~# W8 ccharger
; C( C, {- f* w9 b5 @# w
      /sys/class/power_supply/usb/online==1,
. }0 R/ s# t+ A, ~1 g# F则插入的充电器是usb charger

! ^+ Q9 M' I9 M  B9 p   调试路径:/sys/kernel/debug/msm_otg' @$ x8 w: f% W7 H/ @
2. 分析frameworks/base/services/jni/com_android_server_batteryservice.cpp
; m& E: i7 w$ C5 f. \5 |                a.函数register_android_server_BatteryService将为被frameworks/base/services/jni/onload.cpp中的JNI_OnLoad调用,用于关联java和C++之间的变量' ^3 P6 _0 o; |% C3 _9 p
                b.jclass clazz = env->FindClass("com/android/server/BatteryService"); //根据java的路径找到batteryservice.java对应的jclass    / @! Y4 Q/ f4 i8 [
                  gFieldIds.mAcOnline = env->GetFieldID(clazz, "mAcOnline", "Z");
& x8 W- y9 E9 T5 F7 O- b4 U                  gFieldIds.mUsbOnline = env->GetFieldID(clazz, "mUsbOnline", "Z"); //用于关联batteryservice.java中变量private
5 T- D0 U" K7 R* jboolean mAcOnline和gFieldIds.mAcOnline; V! ], y5 @2 R
                c. android_server_BatteryService_update% @% {) ?  Q) c
                                static JNINativeMethod sMethods[] = {
; F; n  J3 h: @+ h0 I. A# I                                     /* name, signature, funcPtr */
" F- f0 v( {! q& d+ Y# K                                                {"native_update", "()V", (void*)android_server_BatteryService_update},) j; W+ Q' H. M% H
                                };
# o; ?/ A8 h4 R6 |5 E2 |0 e  u                   关联到native_update@frameworks/base/services/java/com/android/server/batteryservice.java
( {- t! u- p8 N( C: g2 D3. 分析frameworks/base/services/java/com/android/server/batteryservice.java# k' s" {2 \- \1 ?. e
                a. mPowerSupplyObserver.startObserving("SUBSYSTEM=power_supply"); //注册监听该uevent
6 y3 i  z2 W+ h! [# r                b.     private UEventObserver mPowerSupplyObserver = new UEventObserver() {
3 W3 F$ s- y% A( n2 |! B                                public void onUEvent(UEventObserver.UEvent event) { //如果就收到来自kernel的uevent,触发该函数6 O4 I0 k8 f) k6 x& @1 S
                                    update(); //-->native_update();和processValues();4 H. [) ]  a0 r
                                }
( J! d+ E' _/ u  d: K                       };& V; I9 c9 C3 L# Z
                c. native_update函数会通过JNI调用得到更新的mAcOnline和mUsbOnline值" o6 {) x; ~' k! _& @. T8 ~7 H
                d. processValues会根据mAcOnline和mUsbOnline值对mPlugType赋值
, C0 n" n' c$ d% R# G; y8 A                                if (mAcOnline) {. K4 W  f3 u2 F
                                    mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
( G) m& k8 D' M0 Q4 C) M                                } else if (mUsbOnline) {8 p0 _6 C6 W5 j9 T& N; i  Q
                                    mPlugType = BatteryManager.BATTERY_PLUGGED_USB;
( y; f8 Y3 T+ x& F  R& _                                } else {
1 _. g4 f( q# u4 r) \$ Z                                    mPlugType = BATTERY_PLUGGED_NONE;) S. {6 R5 Q( Q3 M: v2 G
                                }
3 q, i8 L, Y$ b                e. sendIntent函数会准备Intent并且broadcast这个Intent; a" T% U* t8 ?/ r& l
                                Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED); //public static final String ACTION_BATTERY_CHANGED = "android.intent.action.BATTERY_CHANGED";@batteryservice.java
) c/ D" e! f+ E$ Q- X) @1 p8 w                                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
. z1 W4 \# W$ D0 V" C! \                                        | Intent.FLAG_RECEIVER_REPLACE_PENDING);
* Y: w5 J! u( \# H* Q ' b5 H9 w- A6 y" U( k7 S/ @  p
                        intent.putExtra(BatteryManager.EXTRA_PLUGGED, mPlugType);. q4 x0 ]; [+ W+ S
                                ActivityManagerNative.broadcastStickyIntent(intent, null);1 i: d( R$ v! b2 J( f
4. 分析vendor/semc/packages/apps/debugmenu/src/com/sonyericsson/debugmenu/battery.java# Y8 P+ U# [7 M4 `" j5 N3 g
                a. 接收intent' o  ^$ S2 J- [# u% M% [/ _2 m
                    private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {. _) @5 ~$ `  T3 O4 M
                                @Override5 A% n1 O+ o! P' B
                                public void onReceive(Context arg0, Intent intent) {
, y$ F1 W" {0 f                                    if (intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) {
. @0 L6 `- b; f. k                                        mPowerInformation.parseIntent(intent);  B. s9 F5 H. j0 z% ~" F/ W
                                        updateViews();8 p2 r4 G* g% E. a) _# E
                                    }0 K( w/ q# V$ c
                                }
0 `+ x% X. J2 E2 P  w7 Z& |8 h                    };
1 h4 z& O, z% B                    public void registerBroadcastReceivers() {# v$ M# S3 S. R5 c7 p
                                IntentFilter mIntentFilter;* D8 d4 m9 |5 t& A9 F7 d) \- N
                                mIntentFilter = new IntentFilter();2 S8 z% D% e+ K
                                mIntentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); //只接收Intent.ACTION_BATTERY_CHANGED的intent
& n* u1 m8 Q- `" i+ o                                // Register battery receiver.
4 ?: V; v$ x5 @: b* ]7 n9 U6 S                                registerReceiver(mBatteryInfoReceiver, mIntentFilter);
/ N0 O$ h: l. C4 c- }                    }         
8 X9 T) R/ a% n2 K. N                b. parseIntent 得到最新的"plugged"值赋给mPlugged
5 O7 j$ c5 x3 |, y) T) g, c% r$ E                c. updateViews 更新charger类型显示
5 R, D2 ]% Z7 J' N* b! f* ?) H% d###内核空间
* t: T4 [2 g8 p. V1. 插入充电器触发的过程@kernel/drivers/usb/otg/msm_otg.c2 t( g' j( s! i
                a. CONFIG_PM_RUNTIME 定义 @kernel/arch/arm/configs/viskan_huashan_defconfig
: I+ Z1 W! C1 t' V) S1 ]( k4 K                b.msm_otg_runtime_resume-->msm_otg_resume-->??-->msm_otg_sm_work- L  k. C: I7 ]# \4 T- m
                c.msm_otg_sm_work,先进入OTG_STATE_UNDEFINED case,然后进入OTG_STATE_B_IDLE" d4 v5 {1 }4 D6 f" f% ^$ u
case-->motg->chg_state=USB_CHG_STATE_UNDEFINED-->启动msm_chg_detect_work' f  [( I! w1 j
                d.msm_chg_detect_work 该函数主要完成USB charger类型的识别
/ W# W# g5 p) U( W                                USB_CHG_STATE_UNDEFINED //其中psy = power_supply_get_by_name("usb");很关键,表明只是获取usb的power_supply,实际上就是chip->usb_psy@pm8921-charger.c
8 @' j/ Q/ k9 ]1 U                                USB_CHG_STATE_WAIT_FOR_DCD         //Waiting for Data pins contact.
* c" C$ D( G. Z$ m# h! \                                然后多次(MSM_CHG_DCD_MAX_RETRIES=6)检测USB状态,启动queue_delayed_work(motg->wq," Q- A' W# J+ O' K' }& x( I
&motg->chg_work, delay); //motg->chg_work=msm_chg_detect_work
4 _: F; K/ P3 G! V8 z& N                                USB_CHG_STATE_DETECTED //最后USB charge类型检测完毕
9 i8 G( V% ^1 F4 {1 a: L                e. 启动queue_work(motg->wq, &motg->sm_work); //motg->sm_work=msm_otg_sm_work& L0 r+ W; F0 |$ }& ?4 w
                f. 由于motg->chg_state==USB_CHG_STATE_DETECTED,6 G6 v3 b% [" N* v( u# m
                                motg->chg_type==USB_DCP_CHARGER -->msm_otg_notify_charger(motg,IDEV_CHG_MAX);//IDEV_CHG_MAX=1500
% R$ ~7 P, t7 Y  A! o# l6 R2. 发送uevent到用户层
: C3 U9 ?3 }9 P/ `$ B# n' n4 r                a. msm_otg_notify_charger@kernel/drivers/usb/otg/msm_otg.c. [1 p9 D" ^$ B# x# v
                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% M4 R( Q% C0 a/ M9 w) K
                c. -->power_supply_set_supply_type@power_supply_core.c // set type of the power supply
6 V7 p% h) V' E4 N" s                d. -->psy->set_property(psy, POWER_SUPPLY_PROP_TYPE,&ret);- s+ e2 b9 ^9 G& ]
                                那么在用usb_psy.get_property和dc_psy.get_property
: V6 I& ]. M0 ?4 V, ]0 d- g(在函数中pm8921_charger_probe)读取property时" _$ R. m1 h" W/ v
                                如果是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
) O! l7 ]. f% q* k' q# ccharger
/ K4 _9 [$ Y4 @, z. a( S! {                                如果是AC type,则在pm_power_get_property_mains读取POWER_SUPPLY_PROP_ONLINE的值,只有POWER_SUPPLY_TYPE_USB_DCP为AC# v: b( `% Y' P4 k, ^. U
charger.5 o/ u4 G' G# O) Q' u9 \
                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
  O6 x& T0 M  k' c% J" @" @+ d3 c                f. -->pm8921_set_usb_power_supply_type(val->intval)@pm8921-charger.c' a: n5 Z/ A, B1 _- r
                                -->power_supply_changed(&the_chip->usb_psy);
1 S4 o6 r, z& x; X                                -->power_supply_changed(&the_chip->dc_psy);
1 r% {6 I3 J2 `  b7 h: C                g. power_supply_changed@pm8921-charger.c , 就会马上发送uevent给user
% S3 d  X- d( i1 r! ^0 [9 }) ~space,然后user space通过sysfs得到USB
% @0 t$ P9 f$ B5 _* Qtype变化后的信息,参考用户空间的分析
1 U/ n. v7 Z* D* u* A5 a3 E5 y8 R0 i
+ L1 W! Q; p6 d4 ^7 R; Z* A/ K二、硬件分析' _. g8 _9 h" |" U2 e
  q2 m/ F+ Q$ T& p8 ?# I
主要是通过特殊设计的电路,检测不同的pin的状态,从而确定是何种类型的Charger. 更details的内容省略。; m+ l: [, ?  C# O
& y( N9 x! [) s9 J: v. q/ u

( M: N2 n, K& ?9 {: A3 u5 h7 |( B. s  B$ u$ z8 d9 ^3 c( |$ P' ?
分享到:  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 22:53 , Processed in 0.059015 second(s), 31 queries , Gzip On.

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

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

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