Android系统Diag命令分析 - 充电

本文介绍了如何使用高通Diag命令进行充电控制,包括命令的基本构成、Qxdm软件的使用方法以及代码分析。通过发送特定的Diag命令,可以实现充电开启和关闭,并探讨了Diag命令的注册和响应机制。同时,文章提到了在移植和使用过程中可能遇到的问题及解决办法。

高通Diag命令


1.根据《QualcommDiag Command List V0.8》文档,确定Diag命令的基本构成,不同命令码表示不同的测试功能。

2.使用Qxdm软件发送Diag命令查看手机是否可以正常反馈,保证Diag接口命令接收正常。


第一部分:

在前期将Diag命令移植过来的时候,手机发送命令无法收到信息反馈,比如说最简单的手机充电开启关闭指令,主要原因移植过来的Diag命令没有走通,不同公司都有自己的独有的Diag测试命令,所以移植过来的指令可能还需要自己调整,这份文档主要参考高通标准指令制定,在调试Diag命令时候如果把最基本的充电开启关闭命令调通了,其他命令也就相同了。


通过查看高通文档说明,通过发送以下指令可以完成充电操作:

如何使用Qxdm发送Diag命令?

方法:打开Qxdm软件->选择相关端口 ->选择“CommandOut”模式 ->发送栏输入发送命令。如图所示:

红色箭头指示地方表示需要发送的控制指令0x80 0xFA 0x79 0x00 0x01

需要注意发送格式“Send_data 0x80 0xFA 0x79 0x00 0x01”其中“0X”表示的十六进制数据,不可以省略。

如果发送后如果返回:

unkowncommand”表示输入框中发送的命令有问题

SendRawRequest- Failed to parse arguments”表示发送命令没有反馈,命令不通


第二部分:分析代码

这部分只要内容是挑选Diag充电命令来举例说明,相对比较简单。


//结构体数组主要包含“命令码”和“回调函数”

//DIAG_SUBSYS_ID_TCT_CHARGING_ON为命令码,充电命令为0x79

//tct_charging_on_func回调函数,当命令匹配时会到指定的函数执行操作

staticconst diagpkt_user_table_entry_type tct_charging_on_tbl[] =

{

{DIAG_SUBSYS_ID_TCT_CHARGING_ON,DIAG_SUBSYS_ID_TCT_CHARGING_ON, tct_charging_on_func},

};


PACK(void*) tct_charging_on_func(

        PACK(void*)req_pkt,

        uint16pkt_len 

)

{

……省略

/*Allocatethe same length as the request*/

rsp= (rsp_type_tct_charging_on_exec *) diagpkt_subsys_alloc_v2(

DIAG_TCT_FACTORY_COMMON,DIAG_SUBSYS_ID_TCT_CHARGING_ON,

sizeof(rsp_type_tct_charging_on_exec));

    if(switcher== 1)

    {

      //创建一个线程执行充电开启操作

if(pthread_create(&tid,NULL,(void*)&charging_on_thread,NULL)!=0)

      {

          printf("threadcreate failed\n");

      }

 }else {

//创建一个线程执行充电关闭操作

      if(pthread_create(&tid,NULL,(void*)&charging_off_thread,NULL)!=0)

      {

          printf("threadcreate failed\n");

      }

    }

    ……省略

    return(rsp);

}


//充电开启函数

voidcharging_on_thread()

{

//sleep(delay);

system("echo0x01>/sys/kernel/debug/spmi/spmi-0/count");

system("echo0x1347>/sys/kernel/debug/spmi/spmi-0/address");

system("echo0x00>/sys/kernel/debug/spmi/spmi-0/data");

}

//充电关闭函数

voidcharging_off_thread()

{

//sleep(delay);

system("echo0x01>/sys/kernel/debug/spmi/spmi-0/count");

system("echo 0x1347>/sys/kernel/debug/spmi/spmi-0/address");

system("echo0x01>/sys/kernel/debug/spmi/spmi-0/data");

}


//充电Diag注册函数,在初始化的时候会调用这部分函数

//DIAG_SUBSYS_CMD_VER_2_F是主命令码:0xFA

//DIAG_TCT_FACTORY_COMMON是次级命令:0x79

voidtct_charging_on_register()

{

DIAGPKT_DISPATCH_TABLE_REGISTER_V2_DELAY(DIAG_SUBSYS_CMD_VER_2_F,

DIAG_TCT_FACTORY_COMMON,tct_charging_on_tbl);

}


具体命令是如何组成的需要深入理解的话,请查看命令注册函数结构体。但是通过上面的命令格式可以发现只要在注册命令遵循一定规律就可以实现Diag命令的注册和响应。通过上面的描述,如果添加一个Diag命令只需要根据接收命令的格式要求,修改对应的DIAG_TCT_FACTORY_COMMONDIAG_SUBSYS_ID_TCT_CHARGING_ON等这些宏就可以了,对于命令所实现的功能需要在回调函数tct_charging_on_func内完成。


第三部分:移植


diag命令的添加都在/vendor/XXX文件夹/source/system/diag目录下

这个目录存放了Diag相关的命令,每个文件包含命令的注册函数,处理函数。每一个公司都有自己的存放目录,根据情况而定


第四部分:问题与处理方法

1.使用Qxdm发送Diag命令时候无法得到信息反馈?

答:首先adbshell进入到手机系统,查看后台进程是否正在运行,如下所示:

root@gflip2:/# ps | grep "tct"

root 257 1 6464 1088 ffffffff b6ed2520 S /system/bin/tctd

root 287 1 4516 1076 ffffffff b6f23520 S/system/bin/tct_diag

root@gflip2:/#

后台进程在运行正常的情况下,查看使用Qxdm发送的命令格式是否有问题,如果是“SendRawRequest- Failed to parsearguments”说明Diag程序无法处理你发送的命令,有可能后台相应的代码没有编译进去,你需要修改当前目录下的Makefile文件,也有可能添加Diag命令没有被注册。


2.后台守护进程无法运行?

答:在system/core/rootdir/下,修改init.rc实现开启自动运行。


 

Line 24050: 09-10 11:18:10.034 02967 03011 V UsbDeviceManager: onKeyguardStateChanged: isShowing:true secure:true user:0 Line 25136: 09-10 11:18:10.726 02967 05343 I UsbPortManager: ClientCallback V1_2: port0 Line 25141: 09-10 11:18:10.726 02967 03008 I UsbPortManager: USB port changed: port=UsbPort{id=port0, supportedModes=dual, audio_acc, supportedContaminantProtectionModes=0, supportsEnableContaminantPresenceProtection=false, supportsEnableContaminantPresenceDetection=false, supportsComplianceWarnings=false, status=UsbPortStatus{connected=false, currentMode=none, currentPowerRole=no-power, currentDataRole=no-data, supportedRoleCombinations=[no-power:no-data], contaminantDetectionStatus=0, contaminantProtectionStatus=0, usbDataStatus=unknown, isPowerTransferLimited=false, powerBrickConnectionStatus=unknown, complianceWarnings=[], plugState=0, displayPortAltModeInfo=null}, canChangeMode=true, canChangePowerRole=false, canChangeDataRole=false, connectedAtMillis=0, lastConnectDurationMillis=107508 Line 25173: 09-10 11:18:10.737 02967 03451 V UsbDeviceManager: USB UEVENT: {SUBSYSTEM=android_usb, SEQNUM=25950, ACTION=change, USB_STATE=DISCONNECTED, DEVPATH=/devices/virtual/android_usb/android0} Line 25178: 09-10 11:18:10.738 02967 03451 I UsbDeviceManager: mResetUsbGadgetDisableDebounce:false connected:0configured:0 Line 25179: 09-10 11:18:10.738 02967 03451 I UsbDeviceManager: removeMessages MSG_UPDATE_STATE Line 25856: 09-10 11:18:11.087 02967 02967 I UsbDeviceManager: updateHostState UsbPort{id=port0, supportedModes=dual, audio_acc, supportedContaminantProtectionModes=0, supportsEnableContaminantPresenceProtection=false, supportsEnableContaminantPresenceDetection=false, supportsComplianceWarnings=false status=UsbPortStatus{connected=false, currentMode=none, currentPowerRole=no-power, currentDataRole=no-data, supportedRoleCombinations=[no-power:no-data], contaminantDetectionStatus=0, contaminantProtectionStatus=0, usbDataStatus=unknown, isPowerTransferLimited=false, powerBrickConnectionStatus=unknown, complianceWarnings=[], plugState=0, displayPortAltModeInfo=null} Line 26091: 09-10 11:18:11.119 02967 04939 D UsbDeviceManager: setCurrentFunctions() Line 26093: 09-10 11:18:11.119 02967 04939 D UsbDeviceManager: printCallerPkg pid: 7094 Line 26122: 09-10 11:18:11.123 02967 03008 D UsbDeviceManager: setEnabledFunctions [functions= ,forceRestart=false ,usbDataUnlocked=false ,mUsbDataUnlocked=false ,operationId=1005] Line 26124: 09-10 11:18:11.124 02967 03008 D UsbDeviceManager: oplusFunctions: diag,adb Line 26126: 09-10 11:18:11.124 02967 03008 I UsbDeviceManager: boot reason is reboot Line 26127: 09-10 11:18:11.124 02967 03008 I UsbDeviceManager: boot reason is reboot Line 26128: 09-10 11:18:11.124 02967 03008 D UsbDeviceManager: UsbFunc: [functions: diag,adb, oemFunctions: diag,adb, mCurrentFunctionsStr: diag,adb, mCurrentOemFunctions: diag,adb, forceRestart: false, mCurrentFunctionsApplied: true] Line 28504: 09-10 11:18:11.877 02967 03008 I UsbDeviceManager: handleMessage MSG_UPDATE_STATE mConnected:false mConfigured:false Line 28610: 09-10 11:18:11.962 02967 03008 D UsbDeviceManager: broadcasting Intent { act=android.hardware.usb.action.USB_STATE flg=0x31100000 (has extras) } extras: Bundle[{host_connected=false, connected=false, unlocked=false, adb=true, configured=false}] Line 28704: 09-10 11:18:12.058 02967 03008 D UsbDeviceManager: setEnabledFunctions [functions= ,forceRestart=false ,usbDataUnlocked=false ,mUsbDataUnlocked=false ,operationId=76] Line 28868: 09-10 11:18:12.099 02967 03008 D UsbDeviceManager: oplusFunctions: diag,adb Line 28869: 09-10 11:18:12.099 02967 03008 I UsbDeviceManager: boot reason is reboot Line 28870: 09-10 11:18:12.099 02967 03008 I UsbDeviceManager: boot reason is reboot Line 28871: 09-10 11:18:12.099 02967 03008 D UsbDeviceManager: UsbFunc: [functions: diag,adb, oemFunctions: diag,adb, mCurrentFunctionsStr: diag,adb, mCurrentOemFunctions: diag,adb, forceRestart: false, mCurrentFunctionsApplied: true] Line 28872: 09-10 11:18:12.099 02967 03008 D UsbDeviceManager: updateMtpFunction , mtpEnabled: false, ptpEnabled: false, mIsMtpServiceBound: false解析这段log
09-13
<think>我们分析条件:`if (!download_diag_obj->numberOfConnections || download_diag_obj->numberOfConnections > download_diag_obj->downloadDiagnosticMaxConnections)` 这个条件由两个子条件通过逻辑或(OR)连接组成,判断的是连接数参数是否有效。 具体拆解: 1. `!download_diag_obj->numberOfConnections` - 含义:检查`numberOfConnections`是否为0(或假值)。在C语言中,数值为0时逻辑判断为假,取非则为真;非0为真,取非为假。 - 作用:判断连接数是否未设置(即为0)或者设置为0(因为0个连接没有意义)。 2. `download_diag_obj->numberOfConnections > download_diag_obj->downloadDiagnosticMaxConnections` - 含义:检查设置的连接数是否超过了最大允许连接数(`downloadDiagnosticMaxConnections`)。 因此,整个条件判断的是:如果连接数未设置(为0)或者设置的连接数超过了允许的最大值,则条件成立,进入错误处理分支。 在错误处理分支中: - 记录错误日志(TR143_ERROR) - 将配置中的连接数(`pCfg->num_of_conn`)设置为默认值(`download_diag_obj->X_TP_DownDefConns`) - 同时,修正源数据(`download_diag_obj->numberOfConnections`)为默认值,以确保后续使用的一致性。 如果条件不成立(即连接数有效,非0且不超过最大值),则直接使用设置的连接数。 所以,这个条件的作用是确保连接数在有效范围内(1到最大值之间),否则使用默认值并修正源数据。 §§相关问题§§ 1. 为什么在条件中要检查`numberOfConnections`为0(即`!download_diag_obj->numberOfConnections`)?在实际应用中,设置连接数为0可能表示什么? 2. 如果`downloadDiagnosticMaxConnections`的值被错误设置为0,这个条件判断会有什么后果? 3. 在错误处理分支中,为什么要同时修改配置结构体(`pCfg->num_of_conn`)和源数据对象(`download_diag_obj->numberOfConnections`)的值? 4. 这个条件判断是否考虑到了负数连接数的情况?如果传入负数会如何处理? 5. 在TR369模式下,同样的有效性判断使用了参数结构体`pParm`而非`download_diag_obj`,这是为什么? </think>以下是针对条件判断 `if (!download_diag_obj->numberOfConnections || download_diag_obj->numberOfConnections > download_diag_obj->downloadDiagnosticMaxConnections)` 的详细解析: ### 条件判断分析 该条件由两个子条件通过逻辑或(`||`)组合而成,用于验证连接数参数的有效性: #### 1. **第一子条件:`!download_diag_obj->numberOfConnections`** - **含义**:检测连接数是否为**无效值** - **具体判断**: - 当 `numberOfConnections` 等于 `0` 时成立(0 在布尔判断中为假,`!` 取反为真) - 当 `numberOfConnections` 为 `NULL` 时成立(指针类型的特殊判断) - **设计目的**: - 确保连接数配置不能为零(零连接无意义) - 防止未初始化的空指针导致程序崩溃 #### 2. **第二子条件:`numberOfConnections > downloadDiagnosticMaxConnections`** - **含义**:检测连接数是否**超过系统上限** - **具体判断**: - 当设置的连接数大于系统允许的最大连接数时成立 - **设计目的**: - 防止资源过载(如内存耗尽或网络拥塞) - 确保诊断测试在安全范围内运行 #### 3. **组合逻辑:逻辑或(`||`)** - **触发条件**:任意一个子条件成立即进入错误处理分支 - **错误处理内容**: ```c TR143_ERROR(...); // 记录错误日志 pCfg->num_of_conn = 默认值; // 使用默认连接数 download_diag_obj->numberOfConnections = 默认值; // 修正源数据 ``` ### 设计意图图解 ```mermaid graph TD A[连接数检查] --> B{是否为0/NULL?} A --> C{是否超过最大值?} B -->|是| D[判定无效] C -->|是| D D --> E[记录错误日志] E --> F[使用默认值] F --> G[修正源数据] B -->|否| H[有效] C -->|否| H H --> I[使用原值] ``` ### 典型应用场景 1. **新设备初始化**: - `numberOfConnections` 默认为0 - 触发条件一 → 使用默认值10 2. **错误配置**: - 管理员误设连接数=1000 - 系统上限=500 → 触发条件二 → 自动修正为默认值 3. **空指针防护**: - 内存分配失败导致指针为NULL - 触发条件一 → 避免程序崩溃
评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值