- 注
- epl259x的驅動可以用於
- epl2590
- MN66213
- MN26233TKDN - id = 0x91
- MN25713EKDN - id = 0x81
- 8975 // 4個手勢方向 - 4顆sensor排列
- 2219 // 4個手勢方向
- als 室內光照下應該爲700左右
- ps 底噪值應該爲700左右 - *#*#3646633#*#* *#*#889988#*#* -> Hardware Testing ->Sensor ->Light/Proximity Sensor ->Ps Calibration ->Ps Calibration -> Calibration
- 閾值如果是(500,800),底噪700
- 靠近1500
- 遠離1200
- epl_sensor.ps.integration_time = EPL_PS_INTT_144; // 272 - qk
- dynk_low_offset = 500; // 100 - qk
- dynk_high_offset = 800; // 300 - qk
- 一、新增驅動方法一_適用androidO(示例: msensor mmc5603x)
- 1.添加kernel-4.4\drivers\misc\mediatek\sensors-1.0\magnetometer\mmc5603x文件夾(mmc5603x.c、mmc5603x.h、Kconfig、Makefile四個文件)
- st480.c
- st480.h
- Kconfig 建宏--MTK_MMC5603X
- Makefile
- 2.kernel-4.4\drivers\misc\mediatek\sensors-1.0\magnetometer\Kconfig 添加:
- + source "drivers/misc/mediatek/sensors-1.0/magnetometer/mmc5603x/Kconfig"
- 3.kernel-4.4\drivers\misc\mediatek\sensors-1.0\magnetometer\Makefile 添加:
- + obj-$(CONFIG_MTK_MMC5603X) += mmc5603x/
- 4.kernel-4.4\arch\arm\configs\k39tv1_bsp_1g_debug_defconfig、k39tv1_bsp_1g_defconfig 修改
- + CONFIG_CUSTOM_KERNEL_MAGNETOMETER=y
- + CONFIG_MTK_MMC5603X=y
- 5.添加vendor\microhand\msensor\mmc5603x_32bit文件夾(libmemsicd5603x.so一個文件,供應商提供)
- 6.device\mediateksample\k39tv1_bsp_1g\device.mk 添加,將算法庫拷貝到指定目錄
- + #add by msensor mmc5603x
- + PRODUCT_COPY_FILES += vendor/microhand/msensor/mmc5603x_32bit/libmemsicd5603x.so:vendor/lib/libmemsicd5603x.so
- 7.device\mediateksample\k39tv1_bsp_1g\ProjectConfig.mk
- + CUSTOM_KERNEL_MAGNETOMETER=yes
- 二、新增驅動方法二_適用androidM/N(示例: msensor st480)
- 1.添加kernel-3.18\drivers\misc\mediatek\magnetometer\st480文件夾(包含st480.c、st480.h、Kconfig、Makefile四個文件)
- st480.c
- st480.h
- Kconfig 建宏--MTK_ST480
- Makefile
- 2.kernel-3.18\drivers\misc\mediatek\magnetometer\Kconfig 添加:
- + source "drivers/misc/mediatek/magnetometer/st480/Kconfig"
- 3.kernel-3.18\drivers\misc\mediatek\magnetometer\Makefile 添加:
- + obj-$(CONFIG_MTK_ST480) += st480/
- 4.kernel-3.18\arch\arm\boot\dts\len6737m_35_m0.dts 添加:
- 注:這一段沒有的話(或名字不對應),會導致開機重啓
- cust_mag@0 {
- compatible = "mediatek,st480";
- i2c_num = <2>; // i2c控制器2(即i2c總線2),sensor都接在控制器2上--即i2c總線2
- i2c_addr = <0x0C 0 0 0>; // dws也寫了一個i2c地址,到底用哪個看驅動,通常寫在dws
- direction = <1>; // 方向 –> 唯一用到的
- power_id = <0xffff>;
- power_vol = <0>;
- is_batch_supported = <0>;
- };
- 4.1 修改dws: i2c總線數與i2c地址,驅動中會用到
- I2C:
- MSENSOR I2C_CHANNEL_2 0x30
- 5.kernel-3.18\arch\arm\configs\len6737m_35_m0_debug_defconfig、len6737m_35_m0_defconfig 修改
- - #CONFIG_CUSTOM_KERNEL_MAGNETOMETER=y
- + CONFIG_CUSTOM_KERNEL_MAGNETOMETER=y
- + CONFIG_MTK_ST480=y
- 6.添加vendor\lentek\libs\mt6737m\st480文件夾(包含st480、Android.mk、README、NOTICE)
- st480 是一個可執行文件---init.xxx.rc中運行的daemon進程
- Android.mk 是幹嘛的?
- README 解釋信息
- NOTICE 解釋信息
- 7.device\lentek\len6737m_35_m0\ProjectConfig.mk 修改:
- - CUSTOM_KERNEL_MAGNETOMETER = no
- + CUSTOM_KERNEL_MAGNETOMETER = yes
- 8.device\mediatek\mt6735\init.mt6735.rc 添加:
- service st480 /system/bin/st480 // 這是一個服務,服務的路徑
- disabled
- user system
- group system
- class main // 歸屬於main這個service,main啓動時啓動st480
- 9.device\lentek\len6737m_35_m0\factory_init.project.rc 添加:
- service st480 /system/bin/st480 // 這是一個服務,服務的路徑--應該是工廠模式用到的
- disabled
- user system
- group system
- 10.device\mediatek\common\sepolicy\file_contexts 添加:
- + /system/bin/st480 u:object_r:st480_exec:s0 // 當我們添加跑一個服務的時候就需要對其添加(開放)權限?哪些進程可以訪問它
- 11.添加device\mediatek\common\sepolicy\st480.te文件
- 12.device\mediatek\mt6735\device.mk 添加:
- + PRODUCT_PACKAGES += st480 // 複製st480,從…到/system/bin/
- 三、查看log:
- 1.查看上報數據
- cat /proc/kmsg | grep "***"
- 2.查看開機串口log
- 從串口測試點(TXD)接線出來,用usb轉串口線,配合xshell抓串口log(波特率:912600)
- 3.查看sensor型號:
- eng 版可以通過 命令查看: cat /sys/bus/platform/drivers/gsensor/chipinfo
- user版可以通過 命令查看: dmesg | grep "gsensor" -i // 按power鍵滅屏or亮屏時,會打開or關閉sensor,會有內核緩衝器會有log打出
- [ 1099.329303] (0)[934:android.ui]qma6981_enable_nodata 1964 : Gsensor not in suspend gsensor_SetPowerMode!, enable_status = 1
- [ 1102.168146] (0)[946:PowerManagerSer]qma6981_enable_nodata 1964 : Gsensor not in suspend gsensor_SetPowerMode!, enable_status = 0
- user版可以通過 命令查看: dmesg | grep "als" -i
- user版可以通過 命令查看: dmesg | grep "msensor" -i
- user版可以通過 命令查看: dmesg | grep "gyro" -i
- 四、根據input子系統的調試方法:
- getevent -i 查看所有的input設備
- getevent -t /dev/input/event4 獲取gsensor往上層上報的包(封裝過,加入time等信息,以16進制方式打印)
- 1. ps
- 靠近:
- [ 2208.288534] 0002 0002 00000001
- [ 2208.288534] 0002 0001 00000003
- [ 2208.288534] 0000 0000 00000000
- 遠離:
- [ 2212.838044] 0002 0002 00000002
- [ 2212.838044] 0002 0001 00000003
- [ 2212.838044] 0000 0000 00000000
- 2. cat /proc/kmsg | grep "liuzhigou"
- <4>[ 564.973691]<0> (0)[2935:kworker/0:3]liuzhigou epl_sensor_read_ps_status gRawData.raw_bytes[0] = 0xa
- <4>[ 564.973725]<0> (0)[2935:kworker/0:3]liuzhigou epl_sensor_read_ps_status epl_sensor.ps.compare_low = 0x8
- <4>[ 565.168562]<0> (0)[2935:kworker/0:3]liuzhigou epl_sensor_read_ps_status gRawData.raw_bytes[0] = 0xa
- <4>[ 565.168588]<0> (0)[2935:kworker/0:3]liuzhigou epl_sensor_read_ps_status epl_sensor.ps.compare_low = 0x8
- <4>[ 565.368485]<0> (0)[2935:kworker/0:3]liuzhigou epl_sensor_read_ps_status gRawData.raw_bytes[0] = 0xa
- <4>[ 565.368527]<0> (0)[2935:kworker/0:3]liuzhigou epl_sensor_read_ps_status epl_sensor.ps.compare_low = 0x8
- <4>[ 565.568808]<0> (0)[2935:kworker/0:3]liuzhigou epl_sensor_read_ps_status gRawData.raw_bytes[0] = 0xa
- <4>[ 565.568851]<0> (0)[2935:kworker/0:3]liuzhigou epl_sensor_read_ps_status epl_sensor.ps.compare_low = 0x8
- <4>[ 565.599273]<0> (0)[2935:kworker/0:3]liuzhigou epl_sensor_read_ps_status gRawData.raw_bytes[0] = 0x17
- <4>[ 565.599314]<0> (0)[2935:kworker/0:3]liuzhigou epl_sensor_read_ps_status epl_sensor.ps.compare_low = 0x0
- <4>[ 565.599982]<0> (0)[2935:kworker/0:3]liuzhigou [epl_sensor_report_ps_status]: epl_sensor.ps.data.data=18642, ps_status=0 // 靠近
- <4>[ 565.630511]<0> (0)[2935:kworker/0:3]liuzhigou epl_sensor_read_ps_status gRawData.raw_bytes[0] = 0xf
- <4>[ 565.630547]<0> (0)[2935:kworker/0:3]liuzhigou epl_sensor_read_ps_status epl_sensor.ps.compare_low = 0x8
- <4>[ 565.631129]<0> (0)[2935:kworker/0:3]liuzhigou [epl_sensor_report_ps_status]: epl_sensor.ps.data.data=17031, ps_status=1 // 遠離
- <4>[ 565.735292]<0> (0)[2935:kworker/0:3]liuzhigou epl_sensor_read_ps_status gRawData.raw_bytes[0] = 0x17
- <4>[ 565.735316]<0> (0)[2935:kworker/0:3]liuzhigou epl_sensor_read_ps_status epl_sensor.ps.compare_low = 0x0
- <4>[ 565.735765]<0> (0)[2935:kworker/0:3]liuzhigou [epl_sensor_report_ps_status]: epl_sensor.ps.data.data=17468, ps_status=0 // 靠近
- <4>[ 565.757034]<0> (0)[2935:kworker/0:3]liuzhigou epl_sensor_read_ps_status gRawData.raw_bytes[0] = 0xf
- <4>[ 565.757054]<0> (0)[2935:kworker/0:3]liuzhigou epl_sensor_read_ps_status epl_sensor.ps.compare_low = 0x8
- <4>[ 565.757495]<0> (0)[2935:kworker/0:3]liuzhigou [epl_sensor_report_ps_status]: epl_sensor.ps.data.data=16792, ps_status=1 // 遠離
- 五、跟讀代碼可知:以gsensor(mc3xxx_auto)爲例
- 通過sys文件系統接口調試
- 1.架構實現 - 兩個路徑的節點是一樣的,cat出來也是相同的,hal層走class
- /sys/class/misc/m_acc_misc/*** 有若干屬性,可以讀寫操作
- cat /sys/.../accenablenodata -- 不支持 echo 0/1 > 無作用
- cat /sys/.../accactive -- 1(使能) echo 0 > /sys/.../accactive -- disable
- cat /sys/.../accdelay(不常用)
- cat /sys/.../accbatch(不常用)
- cat /sys/.../accflush(不常用)
- cat /sys/.../accdevnum -- 4(/dev/input/event4)
- 2.驅動實現
- /sys/bus/platform/drivers/gsensor/*** 有若干屬性,可以讀寫操作
- * cat /sys/.../chipinfo -- MC3XXX Chip -- 直接打印MC3XXX Chip
- * cat /sys/.../sensordata -- 1758 0695 1b88 -- 讀地址0x00
- cat /sys/.../cali -- 三組校準數據 -- 第二組爲校準係數,上層未下發就爲0
- cat /sys/.../selftest -- 空(未設置)
- cat /sys/.../firlen -- 0 -- 濾波長度 - 從dts獲得 - 全部爲0
- cat /sys/.../trace -- 0x0000 -- mc3xxx_i2c_probe()把它設置爲0
- cat /sys/.../status -- CUST: 2 7 <-1 0> -- i2c_num direction <power_id power_vol> - 從dts獲取
- cat /sys/.../power -- 亮屏0x0041,滅屏0x0043 -- 讀地址0x07
- cat /sys/.../version -- 2.1.6 -- 打印驅動的宏
- * cat /sys/.../chipid -- 7C-5F-5E-46 -- 讀地址0x3C
- cat /sys/.../virtualz -- 不支持
- * cat /sys/.../regmap -- 打印所有寄存器的值
- * cat /sys/.../orientation -- 7 -- 從dts獲取 echo 7 > /sys/.../orientation
- cat /sys/.../accuracy -- 2(精度 - 宏設置)
- cat /sys/.../selfcheck -- 亂碼
- cat /sys/.../validate -- 0(驗證成功) -- 從0x3b讀出pcode - 匹配mc3***系列芯片 - 驗證成功返回0
- cat /sys/.../pdoc -- 0(不支持 - 宏未開)
- 六、sensor兼容:以gsensor爲例:
- Mtk的架構已經做了兼容,最多隻能兼容5個(gsensor_init_list[5])(tpd_driver_list[20])
- android5.1:
- 七、ps的閾值如何設定
- 1. androidL/M/N:
- kernel-3.10/drivers/misc/mediatek/alsps/epl259x/epl259x.c
- dynk_low_offset = 2000; //500; //100 - qk
- dynk_high_offset = 2300; //800; //300 - qk
- 將(500,800)改爲(2000,2300),距離約降低三分一,寫死在驅動不用dts
- 八、sensor數據上報有三種接口
- 1. 輪詢上報 --最終使用
- 2. sys文件系統 -- 調試使用
- 3. ioctl接口 -- ATA (工廠模式: 同時按住音量減和電源鍵開機)
- mtk原生:
- 關閉輪詢 - 無功能
- 關閉ioctl - 工廠模式無數據(音量減與電源鍵同時按住開機)
- 關閉sysfs - 有功能
- bose修改hal層框架後: - 由一個進程主動讀取
- 關閉輪詢 - 有功能
- 關閉ioctl - 工廠模式無數據(音量減與電源鍵同時按住開機)
- 關閉sysfs - 無功能
- 九、調試查看log
- 1. hal層enable與disable時候會打印:[logcat | grep "..."]
- vendor/mediatek/proprietary/hardware/sensor/nusensors.cpp
- int sensors_poll_context_t::activate(int handle, int enabled)
- {
- ALOGD( "activate handle =%d, enable = %d",handle, enabled );
- sensor編號:(kernel/.../hwmsensor.h中定義減1)
- accelerometer 0
- magnetometer 1
- orientation 2
- gyroscope 3
- ambient light sensor 4
- proximity sensor 7
- 十、*#0*#測試模式調用接口:
- codec_37_n_base\update\alps\kstpackages\apps\KSTFactoryTest\src\com\kingsentime\factorytest\TestSensor.java
- accelerometerSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
- lightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
- distanceSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
- 十一、msensor異常調試步驟:
- 1. 安裝打開APK : zhinanzhen.apk。劃八校準後查看是否正常: 不管手機如何轉動指針始終指北
- ==>指南針轉動,但並不始終指北 -->修改DTS中msensor的方向
- ==>指南針不動 -->安裝sensorlist.apk 查看指南針msensor是否有數據變化
- ==>無數據變化 -->查看開機log,查看是否有I2C通訊報錯,
- ==> 如i2c報錯 -->用萬用表檢查: 芯片供電電壓、連線(遇到過貼片沒貼好,重貼就ok)和i2c地址
- 2. 如果msensor方向調整對了,當指南針方向還是不對
- ==>檢查gsensor是否正常工作,因爲指南針會用到gsensor的數據
- 3. adb shell
- ps 查看指南針的daemon是否正常運行,如未正常運行,可adb push ;cd 到所在目錄; daemon名; 手動把daemon跑起來
- 注:
- 1.eng版纔有運行權限
- 2.cd /system/bin/; /daemon名; 運行, kill daemon; 停止
- 3.alps/out/target/product/magc6737m_65_n/system/bin/
- 4. 如指南針方向大致正確,但上下抖動(正負3度以外),檢查msensor擺件位置,
- 由於msensor檢測磁場,旁邊不能有:
- 帶磁元件(如馬達、camera)【遇到過帶磁螺絲導致方向不準,換螺絲】
- 大電流(cpu/flash/wifi芯片/百毫安的供電電流、需距離5mm以上)【遇到過兩次有大電流,改版】
- 如果有,需要硬件改版,將msensor挪到旁邊去
- 十二、gsensor、msensor、gyroscope的方向調試
- 1. 由於這些sensor都是三軸sensor,故均有0~7 八個方向。通常寫在dts,少數不規範的寫死在驅動
- 2. 先找到小原點即芯片原點座標(在芯片絲印上有)
- gsensor(3433/6981/bmc156)
- y
- __|__
- | o|
- | |-->x
- |__ __|
- gyroscope(bmg160)
- x
- __|__
- | o|
- y<--| |
- |__ __|
- 然後根據sensor的擺件位置,計算出sensor的方向,先把手機平方在桌面
- 2.1 如sensor貼在top層
- y軸指向聽筒位置(小圓點在右上角),方向爲0
- y軸指向左側位置(小圓點在左上角),方向爲1
- y軸指向home位置(小圓點在左下角),方向爲2
- y軸指向右側位置(小圓點在右下角),方向爲3
- (逆時針旋轉90度,方向+1)
- 2.2 如sensor貼在bottom層,相應的方向:4/5/6/7
- 3. 由於芯片常在屏蔽罩裏面,不便查看,可以由原理圖與layout 查看其小原點位置: pin腳1的位置
- 4. 何種現象顯示方向正確:
- gsensor : 手機界面會翻轉
- msensor : 安裝打開指南針apk,劃八校準後,不管手機如何轉動指針始終指北
- gyroscope: 安裝需要陀螺儀的遊戲apk(如打殭屍),運行遊戲看是否打得準
- 5. 何種現象顯示方向正確: 用sensorlist查看
- 5.1 gsensor
- 手機平放,z軸應爲9.8,xy爲0
- 手機豎立,y軸應爲9.8,zx爲0
- 手機側立,x軸應爲9.8,yz爲0 - 正面朝左
- 5.2 msensor,先用正常手機如iphone找到北邊
- x軸指北時,x軸數據達到最大;x軸反方向指北時,x軸數據達到負的最大
- y軸指北時,y軸數據達到最大;y軸反方向指北時,y軸數據達到負的最大
- z軸指北時,z軸數據達到最大;z軸反方向指北時,z軸數據達到負的最大
- 5.3 gyroscope,假設手機有長寬高三軸
- 沿着手機寬軸擺動手機,x軸數據變化比另兩軸大(先正後負)
- 沿着手機長軸擺動手機,y軸數據變化比另兩軸大
- 沿着手機高軸擺動手機,z軸數據變化比另兩軸大
- 6. 還可以通過sensorlist看到的xyz軸數據計算,與原本的方向計算出正確的方向
- value swap X with Y reverse sign X reverse sign Y reverse sign Z
- 0 0 0 0 0
- 1 0 1 0 1
- 2 0 1 1 0
- 3 0 0 1 1
- 4 1 1 0 0
- 5 1 0 1 0
- 6 1 0 0 1
- 7 1 1 1 1
- sensor調試案例:
- 案例一 : 兼容gsensor(mxc400x與mxc6225)
- 現象 :
- 平臺 : androidL,MTK6580
- 步驟 : 1.
- 2. !!!試驗這樣是不是i2c地址相同的就可以再次i2c_probe
- epl_sensor_i2c_probe()
- epl_sensor_i2c_client = client;
- exit:
- epl_sensor_i2c_client = NULL;
- alsps_init_flag = -1;
- 3.
- 總結 :
- 案例二 : gsensor(qma6981)由mtk老架構改mtk新架構
- 現象 :
- 平臺 : androidL,MTK6580
- 步驟 : 1. 思路:老的架構在模塊入口platform_driver_register()註冊一個平臺設備,probe中註冊i2c設備
- 新的架構在模塊入口acc_driver_add()將結構題註冊到list中,local_init中註冊i2c設備
- 2.#include <accel.h>
- static int __init qma6981_init(void)
- {
- - platform_driver_register(&qma6981_gsensor_driver)
- + acc_driver_add(&qma6981_init_info);
- return 0;
- }
- 3. static struct sensor_init_info qma6981_init_info = {
- .name = QMA6981_ACC_DEV_NAME,
- .init = qma6981_local_init,
- .uninit = qma6981_local_uninit,
- };
- 4.static int qma6981_local_init(void)
- {
- i2c_add_driver(&qma6981_i2c_driver)
- if(-1 == qma6981_init_flag)
- return -1;
- return 0;
- }
- 5.static int qma6981_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
- {
- - if((err = qma6981_create_attr(&qma6981_gsensor_driver.driver)))
- + if((err = qma6981_create_attr(&(qma6981_init_info.platform_diver_addr->driver))))
- exit:
- + qma6981_init_flag = -1;
- return err;
- }
- 總結 :
- 案例三 : 計步器的實現 - gsensor硬件中斷
- 現象 :
- 平臺 : androidL,MTK6737
- 步驟 : 1.
- 2.
- 3.
- 總結 :
- 案例四 : 調試新msensor(mmc3630x),bin文件沒有拷貝到out目錄 - 修改device.mk
- 現象 : msensor無功能
- 平臺 : androidN,MTK6737
- 排查過程: 1.在alps\vendor\magcomm\libs\mt6737m\目錄創建文件夾: memsicd3630x ,內部有bin文件 : memsicd3630x
- 修改alps\device\mediatek\mt6735\device.mk添加:
- PRODUCT_PACKAGES += memsicd3416x
- + PRODUCT_PACKAGES += memsicd3630x
- 2.out目錄沒有生成對應的bin文件:memsicd3630x
- android009@mht-09:~/liuzhigou/code2_37_m_base_v663_xiaoxing_k29d1_user$ find alps/out/ -name memsicd3*
- alps/out/target/product/magc6737m_65_c_m0/system/bin/memsicd3416x
- 3.修改alps\device\mediatek\mt6735\device.mk添加: (注意要精確到具體文件,而不是文件夾)
- + PRODUCT_COPY_FILES += vendor/magcomm/libs/mt6737m/memsicd3630x/memsicd3630x:system/bin/memsicd3630x
- 4.out目錄成功生成對應的bin文件:memsicd3630x
- android009@mht-09:~/liuzhigou/code2_37_m_base_v663_xiaoxing_k29d1_user$ find alps/out/ -name memsicd3*
- alps/out/target/product/magc6737m_65_c_m0/system/bin/memsicd3416x
- alps/out/target/product/magc6737m_65_c_m0/system/bin/memsicd3630x // 我們要的bin文件
- 處理方案: 修改device.mk
- 總結 : 上層的問題,及時請教上層的同事
- 案例三 : gsensor(qma6981) I2C不通 - 貼片沒有貼好
- 現象 : I2C不通
- 平臺 : androidN,MTK6737
- 步驟 : 1. gsensor無功能,打log,在串口log中發現
- [ 13.465281] .(3)[1:swapper/0][name:qma6981&][QMA-Gsensor] I2C_TxData 271 : I2C_TxData delay!
- [ 13.476575] .(3)[1:swapper/0][name:i2c&]ERROR,510: id=2,addr: 12, transfer error
- [ 13.477594] .(3)[1:swapper/0][name:i2c&]ERROR,516: I2C_ACKERR
- 2. 分析:由於sensor電源爲常供,無需上電,i2c不通的可能:
- (1)i2c地址不對
- (2)硬件有問題
- 3. 詢問FAE,確認i2c地址正確,排查硬件問題:將芯片取下,外接小板(小板上有芯片)
- 結果芯片工作正常
- 處理方案: -->把芯片重新貼好
- 總結 : 只有camera在i2c通訊之前要上電,其他都可以直接通訊,i2c不通只有兩種可能:
- (1)i2c地址不對
- (2)硬件有問題
- 案例四 :
- 現象 :
- 平臺 : androidN,MTK6737
- 步驟 : 1.
- 2.
- 案例五 : gsensor兼容(3433 & 6981)導致功耗大(70ma)
- 現象 :
- 平臺 : androidN,MTK6737
- 步驟 : 1. 休眠時候打log: adb shell dmesg > e:gsensor_3433_6981.log
- log顯示由於設備(2-004c - mc3433)休眠失敗,導致系統休眠失敗,重新喚醒,
- 系統一直處於: 休眠->休眠失敗->喚醒 ->休眠的循環中
- [ 207.629520] (1)[1066:system_server]qma6981_suspend 2894 : liuzhigou 20171018 qma6981_suspend start
- [ 207.635164] (1)[1066:system_server]qma6981_suspend 2914 : liuzhigou 20171018 qma6981_suspend end
- [ 207.635254] (1)[1066:system_server]liuzhigou 20171018 mc3xxx_suspend start
- [ 207.635291] (1)[1066:system_server]dpm_run_callback(): i2c_device_pm_suspend+0x0/0x38 returns -22
- [ 207.635324] (1)[1066:system_server]PM: Device 2-004c failed to suspend: error -22
- [ 207.635352] (1)[1066:system_server][name:suspend&]PM: Some devices failed to suspend, or early wake event detected
- 2. 在mc3433的休眠函數中,添加打印log:
- static int mc3xxx_suspend(struct i2c_client *client, pm_message_t msg)
- {
- struct mc3xxx_i2c_data *obj = i2c_get_clientdata(client);
- int err = 0;
- if(msg.event == PM_EVENT_SUSPEND) {
- if(obj == NULL) {
- + GSE_ERR("liuzhigou 20171025 %s obj == NULL\n",__FUNCTION__);
- return -EINVAL;
- }
- [ 116.917907] (0)[1150:system_server]liuzhigou 20171018 mc3xxx_suspend start
- [ 116.917926] (0)[1150:system_server]liuzhigou 20171018 mc3xxx_suspend msg.event == PM_EVENT_SUSPEND
- [ 116.917943] (0)[1150:system_server]liuzhigou 20171018 mc3xxx_suspend obj == NULL
- [ 116.917974] (0)[1150:system_server]dpm_run_callback(): i2c_device_pm_suspend+0x0/0x38 returns -22
- [ 116.917996] (0)[1150:system_server]PM: Device 2-004c failed to suspend: error -22
- [ 116.918016] (0)[1150:system_server]PM: Some devices failed to suspend, or early wake event detected
- 根據log,obj爲空指針,出錯判斷後返回錯誤值
- 3. 根據標誌位添加出錯判斷,如果沒加載3433就直接return 0(成功),終止3433的休眠函數
- static int mc3xxx_suspend(struct i2c_client *client, pm_message_t msg)
- {
- struct mc3xxx_i2c_data *obj = i2c_get_clientdata(client);
- int err = 0;
- if(msg.event == PM_EVENT_SUSPEND) {
- if(obj == NULL) {
- + if (MC3XXX_INIT_FAIL == s_nInitFlag){
- + GSE_ERR("liuzhigou 20171025 %s obj == NULL MC3XXX_INIT_FAIL == s_nInitFlag \n",__FUNCTION__);
- + return 0;
- + }
- + else{
- + GSE_ERR("liuzhigou 20171025 %s obj == NULL MC3XXX_INIT_FAIL != s_nInitFlag \n",__FUNCTION__);
- return -EINVAL;
- }
- }
- 總結 : 此log爲正常狀態: 0x4000爲pmu中斷
- [ 147.732936] -(0)[1066:system_server][name:mt_spm_internal&][SPM] wake up byEINT, timer_out = 18724959, r13 = 0x10001000, debug_flag = 0x9f
- [ 147.732936] -(0)[1066:system_server][name:mt_spm_internal&][SPM] r12 = 0x20, raw_sta = 0x20, idle_sta = 0x9fa, event_reg = 0x90100000, isr = 0x0
- [ 147.732936] -(0)[1066:system_server][name:mt_spm_sleep&][SPM] suspend dormant state = 0, md32_flag = 0x0, md32_flag2 = 0
- [ 147.732936] -(0)[1066:system_server][name:mt_spm_sleep&][SPM] log_wakesta_index = 5
- [ 147.732936] -(0)[1066:system_server][name:irq_mt_eic&]EINT_STA:
- [ 147.732936] -(0)[1066:system_server][name:irq_mt_eic&]EINT Module - index:192,EINT_STA = 0x4000
- [ 147.732936] -(0)[1066:system_server][name:irq_mt_eic&]EINT 206 is pending
- [ 147.732936] -(0)[1066:system_server][name:irq_mt_eic&]
- [ 147.732988] -(0)[1066:system_server][name:ccci&][ccci1/mcd]Resume cldma pdn register ...11
- [ 147.733070] -(0)[1066:system_server][name:irq_mt_eic&]EINT Module - expires:4294952066, jiffies:4294952065, deb_in_jiffies:1,
- [ 147.733091] -(0)[1066:system_server][name:irq_mt_eic&]deb:1000, in mt_eint_set_timer_event
- [ 147.733270] (0)[1066:system_server][name:cpu&]Enabling non-boot CPUs ...
- [ 147.733571] -(1)[0:swapper/1]CPU1: Booted secondary processor
- 案例六 : ATA測試中gsensor(qma6981)無數據 - 添加init() - 原因:i2c_probe的時候沒有跑init(),而正常開機在別處有init()
- 現象 : 正常開機有數據,ATA無數據
- 平臺 : androidM,MTK6580
- 步驟 : 1. 由於ATA 是通過ioctl接口獲取數據,在ioctl函數中添加log,顯示讀到的數據爲0
- 2. 在qma6981_unlocked_ioctl()中獲取數據之前進行初始化
- switch (cmd) {
- case GSENSOR_IOCTL_READ_SENSORDATA:
- + qma6981_initialize(client);
- ==> ok
- 案例七 : CTS測試報錯- 磁力傳感器 - 板子上內貼 - 從配置中移除
- 此法不通!!!案例八 : 打開自動背光,通話貼臉滅屏後,移開無法亮屏 - 沒找到死鎖的地方,直接更換一份版本較新的驅動
- 平臺 : androidN,MTK6737
- 步驟 : 1. 對比其他項目667,無此現象,查BOM
- 663 MN26233TKDN(問題項目)
- 667 MN25713EKDN
- 2. 進入"*#0*#"測試模式,交替打開als與ps,出現概率性的als無功能(數值不動)
- 分析懷疑是als與ps enable或disable的時候出問題
- 3. FAE現場支持,提供了一份最新的驅動,問題不再出現
- FAE說舊驅動中有死鎖,但是找不到
- 4. 嘗試註釋掉alps\kernel-3.18\drivers\misc\mediatek\alsps\epl259x\epl259x.c
- static int als_enable_nodata(int en)
- {
- if(enable_als != en)
- {
- + //epl_sensor_update_mode(obj->client);
- }
- }
- ==>功能正常
- 案例九 : als概率性無功能 - 有死鎖 - 沒找到死鎖的地方,直接更換一份版本較新的驅動
- 案例十 : 強光下,自動背光的亮度變化不明顯,弱光下,自動背光的亮度是正常的
- 平臺 : androidN,MTK6737
- 步驟 : 1. 修改als積分時間: alps/kernel-3.18/drivers/misc/mediatek/alsps/epl259x/epl259x.c
- - epl_sensor.als.integration_time = EPL_ALS_INTT_1024;
- + epl_sensor.als.integration_time = EPL_ALS_INTT_64;
- 案例十一 : 打開自動背光,遮擋光感,屏幕亮度無變化 - tp油墨遮擋
- 平臺 : androidN,MTK6737
- 步驟 : 1. 打開"*#0*#"測試模式,查看光感上報值,值偏小
- 對比亮度能夠自動調節的其他項目
- v618_p300 : 1969 lux
- v663_k38 : 328 lux(問題機)
- 懷疑是結構遮擋,導致進光量偏少
- 2. 結構同事分析:是tp開孔處油墨有問題,刮開tp油墨亮度2900 lux
- 案例十二 : gsensor(mxc4005)ATA中z軸數據爲0 - 需要factory_init.rc啓動一個daemon
- 平臺 : androidM,MTK6580
- 步驟 : 1. 正常開機三軸均有數據,ATA(音量減+電源鍵開機)中z軸數據爲0
- 2. 新建文件夾alps/vendor/magcomm/libs/mt6580/memsicp_f_32/
- 裏面新增4個文件: memsicp_f_32、Android.mk、NOTICE、README
- 其中memsicp_f_32需要供應商提供
- 3. alps/device/mediatek/mt6580/device.mk
- + PRODUCT_PACKAGES += memsicp_f_32
- 4. alps/device/mediatek/mt6580/factory_init.rc
- + service memsicp_f_32 /system/bin/memsicp_f_32
- + user system
- + group system
- + class main
- 總結 :
- 案例十三 : android8.1 sensor無法獲取dts數據 -- 寫死在驅動
- 現象 : 獲取不到dts數據
- 平臺 : androidO,MTK6737&MTK6739
- 步驟 : 1. 由於獲取不到dts、dws的數據,無法設置i2c地址、方向,可以寫死在驅動
- alps\kernel-4.4\drivers\misc\mediatek\sensors-1.0\accelerometer\mpu6050g\mpu6050.c
- mpu6050_i2c_probe(struct i2c_client *client)
- + client->addr = 0x69;
- + obj->hw.direction = 0;
- 2. 由於獲取不到dts的數據,無法設置中斷腳,可以寫死在驅動:
- alps\kernel-3.18\drivers\misc\mediatek\sensors-1.0\alsps\epl259x\epl259x.c
- obj->irq = irq_of_parse_and_map(obj->irq_node, 0);
- // 通過打印log可以看出GPIO65對應irq 爲353
- // 通過打印log可以看出GPIO3 對應irq 爲291
- // 可知GPIO口的中斷號是線性的
- printk("obj->irq = %d\n", obj->irq);
- + obj->irq = 291; // GPIO3 - liuzhigou add for v662
- request_irq(obj->irq, epl_sensor_eint_func, IRQF_TRIGGER_NONE, "ALS-eint", NULL)
- 3. 後面有空再好好分析一下如何才能獲取到dts數據
- 總結 :
- 案例十四 : android8.1 msensor(akm09918)無法打開算法庫(libakl.so)
- 現象 : 指南針不轉,打開sensorlist,指南針數據始終爲0
- 平臺 : androidO,MTK6739
- 步驟 : 1. 打印kernel log(導出mtklog或cat /dev/kmsg | grep "liuzhigou")看驅動是否有上報數據
- kernel-4.4\drivers\misc\mediatek\sensors-1.0\magnetometer\mag.c
- int mag_data_report(struct mag_data *data)
- {
- struct sensor_event event;
- int err = 0;
- + printk("liuzhigou update!valus: %d, %d, %d, %d\n" , data->x, data->y, data->z, data->status);
- log:
- -- 當打開sensorlist時,地磁數據上報正常
- Line 1233: <4>[ 113.500580] (3)[67:kworker/3:1]liuzhigou update!valus: 1500, -30400, 6000, 68
- Line 1241: <4>[ 113.699990] (3)[67:kworker/3:1]liuzhigou update!valus: 2400, -30000, 7100, 4
- Line 1246: <4>[ 113.902548] (3)[67:kworker/3:1]liuzhigou update!valus: 300, -28000, 6000, 116
- Line 1248: <4>[ 114.104571] (3)[67:kworker/3:1]liuzhigou update!valus: 1600, -29500, 8100, 100
- Line 1249: <4>[ 114.300017] (3)[67:kworker/3:1]liuzhigou update!valus: 200, -28600, 5400, 4
- Line 1257: <4>[ 114.500118] (3)[67:kworker/3:1]liuzhigou update!valus: 800, -30600, 7000, 100
- Line 1260: <4>[ 114.700351] (3)[67:kworker/3:1]liuzhigou update!valus: 1200, -29800, 4500, 36
- Line 1270: <4>[ 114.903466] (3)[67:kworker/3:1]liuzhigou update!valus: 1200, -29100, 6200, 116
- Line 1272: <4>[ 115.100006] (3)[67:kworker/3:1]liuzhigou update!valus: 1900, -29100, 6200, 36
- Line 1278: <4>[ 115.303492] (3)[67:kworker/3:1]liuzhigou update!valus: 1500, -29200, 4400, 4
- Line 1284: <4>[ 115.500014] (3)[67:kworker/3:1]liuzhigou update!valus: 400, -29300, 5200, 68
- Line 1298: <4>[ 115.700524] (3)[67:kworker/3:1]liuzhigou update!valus: 600, -29400, 4600, 52
- Line 1317: <4>[ 115.899930] (3)[67:kworker/3:1]liuzhigou update!valus: 800, -28700, 5100, 52
- 2. 查看算法庫加載: vendor\mediatek\proprietary\hardware\sensor\sensors-1.0\VendorInterface.cpp
- VendorInterface::VendorInterface() {
- ...
- strlcpy(buf, "lib", sizeof(buf));
- strlcat(buf, libinfo.libname, sizeof(buf));
- strlcat(buf, ".so", sizeof(buf));
- lib_handle = dlopen(buf, RTLD_NOW);
- + ALOGE("VendorInterface() buf = %s\n", buf);
- if (!lib_handle) {
- ALOGE("get lib_interface fail dlopen operation.\n"); // 報此錯誤
- lib_handle = NULL;
- return;
- }
- 供應商提供的算法庫打開失敗 -> 找供應商重新提供
- 3. 如果算法庫加載沒報錯,可以查看校準前後數據
- int VendorInterface::magCalibration(struct sensorData *inputData,struct sensorData *outputData)
- {
- struct magCaliDataInPut magInputData;
- struct magCaliDataOutPut magOutputData;
- int ret = 0;
- memset(&magInputData, 0, sizeof(struct magCaliDataInPut));
- memset(&magOutputData, 0, sizeof(struct magCaliDataOutPut));
- if (!lib_interface)
- return -1;
- if (!lib_interface->doCaliApi)
- return -1;
- magInputData.timeStamp = inputData->timeStamp;
- magInputData.x = inputData->data[0];
- magInputData.y = inputData->data[1];
- magInputData.z = inputData->data[2];
- magInputData.status = inputData->status;
- + ALOGE("magCalibration() before Calibration : magInputData.x = %f\n", magInputData.x);
- + ALOGE("magCalibration() before Calibration : magInputData.y = %f\n", magInputData.y);
- + ALOGE("magCalibration() before Calibration : magInputData.z = %f\n", magInputData.z);
- ret = lib_interface->doCaliApi(&magInputData, &magOutputData);
- + ALOGE("magCalibration() after Calibration : magInputData.x = %f\n", magInputData.x);
- + ALOGE("magCalibration() after Calibration : magInputData.y = %f\n", magInputData.y);
- + ALOGE("magCalibration() after Calibration : magInputData.z = %f\n", magInputData.z);
- outputData->timeStamp = magOutputData.timeStamp;
- outputData->data[0] = magOutputData.x;
- outputData->data[1] = magOutputData.y;
- outputData->data[2] = magOutputData.z;
- outputData->data[3] = magOutputData.x_bias;
- outputData->data[4] = magOutputData.y_bias;
- outputData->data[5] = magOutputData.z_bias;
- outputData->status = magOutputData.status;
- return ret;
- }
- 總結 : 最後因爲供應商無法提交現場支持,更換物料爲mmc5603x,合入一次成功
- 案例十五 : android8.1 msensor(mmc5603x)算法庫(libmemsicd5603x.so)有問題
- 現象 : 指南針不轉,打開sensorlist,指南針數據始終爲0
- 平臺 : androidO,MTK6580
- 步驟 : 1. 打印kernel log(導出mtklog或cat /dev/kmsg | grep "liuzhigou")看驅動是否有上報數據
- kernel-3.18\drivers\misc\mediatek\sensors-1.0\magnetometer\mag.c
- int mag_data_report(struct mag_data *data)
- {
- struct sensor_event event;
- int err = 0;
- + printk("liuzhigou update!valus: %d, %d, %d, %d\n" , data->x, data->y, data->z, data->status);
- log:
- -- 當打開sensorlist時,地磁數據上報正常
- 4,69949,1451351242,-; (0)[154:kworker/0:1]liuzhigou update!valus: -90, 126, -878, 3
- 4,69977,1451551292,-; (0)[154:kworker/0:1]liuzhigou update!valus: -88, 129, -879, 3
- 4,70042,1451751525,-; (0)[154:kworker/0:1]liuzhigou update!valus: -90, 125, -872, 3
- 4,70052,1451951410,-; (0)[154:kworker/0:1]liuzhigou update!valus: -87, 126, -878, 3
- 4,70065,1452151250,-; (0)[154:kworker/0:1]liuzhigou update!valus: -90, 120, -859, 3
- 4,70075,1452351395,-; (0)[154:kworker/0:1]liuzhigou update!valus: -89, 129, -878, 3
- 4,70083,1452551445,-; (0)[154:kworker/0:1]liuzhigou update!valus: -88, 133, -882, 3
- 2. 查看算法庫加載: vendor\mediatek\proprietary\hardware\sensor\sensors-1.0\Magnetic.cpp
- MagneticSensor::MagneticSensor(){
- ...
- strlcpy(buf, "lib", sizeof(buf));
- strlcat(buf, libinfo.libname, sizeof(buf));
- strlcat(buf, ".so", sizeof(buf));
- + ALOGE("liuzhigou MagneticSensor() buf = %s\n", buf); // 添加的log
- lib_handle = dlopen(buf, RTLD_NOW);
- if (!lib_handle) {
- ALOGE("dlopen fail\n");
- return;
- }
- + ALOGE("liuzhigou dlopen ok\n"); // 添加的log
- 查看log(mtklog中的main_log.boot):
- 01-01 07:03:28.286359 337 337 E Magnetic: liuzhigou MagneticSensor() buf = libmemsicd5603x.so
- 01-01 07:03:28.419057 337 337 E Magnetic: liuzhigou dlopen ok
- 3. 如果算法庫加載沒報錯,可以查看校準前後數據
- void MagneticSensor::processEvent(struct sensor_event const *event)
- {
- float magBias[3] = {0};
- struct magCaliDataInPut inputData;
- struct magCaliDataOutPut outputData;
- static int32_t lastStatus = 0;
- memset(&inputData, 0, sizeof(struct magCaliDataInPut));
- memset(&outputData, 0, sizeof(struct magCaliDataOutPut));
- if (event->flush_action == DATA_ACTION) {
- mPendingEvent.version = sizeof(sensors_event_t);
- mPendingEvent.sensor = ID_MAGNETIC;
- mPendingEvent.type = SENSOR_TYPE_MAGNETIC_FIELD;
- mPendingEvent.timestamp = event->time_stamp;
- mPendingEvent.magnetic.status = event->status;
- mPendingEvent.magnetic.x = (float)event->word[0] / (float)mDataDiv;
- mPendingEvent.magnetic.y = (float)event->word[1] / (float)mDataDiv;
- mPendingEvent.magnetic.z = (float)event->word[2] / (float)mDataDiv;
- inputData.x = mPendingEvent.magnetic.x ;
- inputData.y = mPendingEvent.magnetic.y ;
- inputData.z = mPendingEvent.magnetic.z ;
- + ALOGE("processEvent() before Calibration : inputData.x = %f\n", inputData.x);
- + ALOGE("processEvent() before Calibration : inputData.y = %f\n", inputData.y);
- + ALOGE("processEvent() before Calibration : inputData.z = %f\n", inputData.z);
- inputData.status = mPendingEvent.magnetic.status;
- inputData.timeStamp = mPendingEvent.timestamp;
- if (lib_interface != NULL) {
- lib_interface->doCaliApi(&inputData,&outputData);
- }
- + ALOGE("processEvent() after Calibration : outputData.x = %f\n", outputData.x);
- + ALOGE("processEvent() after Calibration : outputData.y = %f\n", outputData.y);
- + ALOGE("processEvent() after Calibration : outputData.z = %f\n", outputData.z);
- mPendingEvent.magnetic.x = outputData.x;
- mPendingEvent.magnetic.y = outputData.y;
- mPendingEvent.magnetic.z = outputData.z;
- mPendingEvent.magnetic.status = outputData.status;
- magBias[0] = outputData.x_bias;
- magBias[1] = outputData.y_bias;
- magBias[2] = outputData.z_bias;
- if (mPendingEvent.magnetic.status != lastStatus) {
- mSensorCali.saveCalibrationFloat(MAG_BIAS_SAVED_DIR, MAG_TAG_BIAS, magBias, 3);
- ALOGE("write bias: [%f, %f, %f]\n", magBias[0], magBias[1], magBias[2]);
- }
- lastStatus = mPendingEvent.magnetic.status;
- } else
- ALOGE("unknow action\n");
- }
- 查看log(mtklog中的main_log):
- Line 9864: 01-01 07:27:42.910853 339 339 E Magnetic: processEvent() before Calibration : inputData.x = -0.437500
- Line 9865: 01-01 07:27:42.911000 339 339 E Magnetic: processEvent() before Calibration : inputData.y = -0.211914
- Line 9866: 01-01 07:27:42.911080 339 339 E Magnetic: processEvent() before Calibration : inputData.z = -0.598633
- Line 9867: 01-01 07:27:42.911156 339 339 E Magnetic: processEvent() after Calibration : outputData.x = 0.000000
- Line 9868: 01-01 07:27:42.911228 339 339 E Magnetic: processEvent() after Calibration : outputData.y = 0.000000
- Line 9869: 01-01 07:27:42.911300 339 339 E Magnetic: processEvent() after Calibration : outputData.z = 0.000000
- Line 9887: 01-01 07:27:43.108972 339 731 E Magnetic: processEvent() before Calibration : inputData.x = -0.444336
- Line 9888: 01-01 07:27:43.109108 339 731 E Magnetic: processEvent() before Calibration : inputData.y = -0.207031
- Line 9889: 01-01 07:27:43.109195 339 731 E Magnetic: processEvent() before Calibration : inputData.z = -0.601562
- Line 9890: 01-01 07:27:43.109374 339 731 E Magnetic: processEvent() after Calibration : outputData.x = 0.000000
- Line 9891: 01-01 07:27:43.109454 339 731 E Magnetic: processEvent() after Calibration : outputData.y = 0.000000
- Line 9892: 01-01 07:27:43.109532 339 731 E Magnetic: processEvent() after Calibration : outputData.z = 0.000000
- 由log可知,so校準算法庫有問題
- 4. 查看是否沒有修改outputData的值
- void MagneticSensor::processEvent(struct sensor_event const *event)
- {
- ...
- + ALOGE("processEvent() before Calibration : inputData.x = %f\n", inputData.x);
- + ALOGE("processEvent() before Calibration : inputData.y = %f\n", inputData.y);
- + ALOGE("processEvent() before Calibration : inputData.z = %f\n", inputData.z);
- inputData.status = mPendingEvent.magnetic.status;
- inputData.timeStamp = mPendingEvent.timestamp;
- if (lib_interface != NULL) {
- + outputData.x = (float)1.23;
- + outputData.y = (float)1.23;
- + outputData.z = (float)1.23;
- lib_interface->doCaliApi(&inputData,&outputData);
- }
- + ALOGE("processEvent() after Calibration : outputData.x = %f\n", outputData.x);
- + ALOGE("processEvent() after Calibration : outputData.y = %f\n", outputData.y);
- + ALOGE("processEvent() after Calibration : outputData.z = %f\n", outputData.z);
- ...
- 查看log(mtklog中的main_log):
- 01-02 23:23:39.754 326 738 E Magnetic: processEvent() before Calibration : inputData.x = 25.878906
- 01-02 23:23:39.754 326 738 E Magnetic: processEvent() before Calibration : inputData.y = 12.109375
- 01-02 23:23:39.754 326 738 E Magnetic: processEvent() before Calibration : inputData.z = -40.136719
- 01-02 23:23:39.755 326 738 E Magnetic: processEvent() after Calibration : outputData.x = 1.230000
- 01-02 23:23:39.755 326 738 E Magnetic: processEvent() after Calibration : outputData.y = 1.230000
- 01-02 23:23:39.755 326 738 E Magnetic: processEvent() after Calibration : outputData.z = 1.230000
- 01-02 23:23:39.954 326 326 E Magnetic: processEvent() before Calibration : inputData.x = 25.683594
- 01-02 23:23:39.954 326 326 E Magnetic: processEvent() before Calibration : inputData.y = 12.109375
- 01-02 23:23:39.954 326 326 E Magnetic: processEvent() before Calibration : inputData.z = -39.746094
- 01-02 23:23:39.955 326 326 E Magnetic: processEvent() after Calibration : outputData.x = 1.230000
- 01-02 23:23:39.955 326 326 E Magnetic: processEvent() after Calibration : outputData.y = 1.230000
- 01-02 23:23:39.955 326 326 E Magnetic: processEvent() after Calibration : outputData.z = 1.230000
- 由log可知,outputData的值根本沒被修改
- 5.對比mt6737的hal層sensor架構,發現mt6580名爲sensor1.0,實際內容是sensor0.1
- 提eservice給mtk
14.sensor調試日誌
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.