hiddtraceutil   [plain text]



#!/bin/sh
## HID Trace util ####

KERNEL_REPORT_DATA_PROBE=$(cat<<-'END'

fbt::*hid_trace*:entry/OPT_device_regID ? arg1 == OPT_device_regID : 1  && expected_funcType ? expected_funcType == arg0 : 1/ {

printf("\n ----- kernel -----\n");
printf(" RegistryID: 0x%llx, ReportID: %lld, ReportLength: %lld, Timestamp: %lld " , arg1, arg2, arg3, arg5);
printf(" ReportData: ");
tracemem(arg4,OPT_reportSize);
hid_kernel_interrupt_report_count =  arg0 == 3 ? hid_kernel_interrupt_report_count + 1 : 0;
hid_kernel_get_report_count =  arg0 == 1 ? hid_kernel_get_report_count + 1 : 0;
hid_kernel_set_report_count =  arg0 == 2 ? hid_kernel_set_report_count + 1 : 0;
}

END
)

USERSPACE_EVENT_PROBE=$(cat<<-'END'

iohidfamily$target::*:log_hid_event/OPT_service_regID ? arg1 == OPT_service_regID : 1/ {

printf("\n ----- Userspace -----\n");
printf(" RegistryID: 0x%llx, Event Type: 0x%llx, Timestamp: 0x%llx\n" , arg1, arg2, arg5);
hid_event_count = hid_event_count + 1;
}

END
)

USERSPACE_REPORT_DATA_PROBE=$(cat<<-'END'

iohidfamily$target::*:hid_trace/OPT_device_regID ? arg1 == OPT_device_regID : 1/ {

printf("\n ----- Userspace -----\n");
printf(" RegistryID: 0x%llx, ReportID: %lld, ReportLength: %lld, Timestamp: %lld\n" , arg1, arg2, arg3, arg4);
printf(" ReportData   : \n");
this->mem = copyin(arg5, OPT_reportSize);
tracemem(this->mem, OPT_reportSize);
hid_userspace_interrupt_report_count = hid_userspace_interrupt_report_count + 1;
}

END
)

KERNEL_INTERRUPT_PROBE_SUMMARY=$(cat<<-'END'

printf("Kernel Interrupt Report Count : %llu\n",hid_kernel_interrupt_report_count);

END
)

KERNEL_GET_PROBE_SUMMARY=$(cat<<-'END'

printf("Kernel Get Report Count : %llu\n",hid_kernel_get_report_count);

END
)

KERNEL_SET_PROBE_SUMMARY=$(cat<<-'END'

printf("Kernel Set Report Count : %llu\n",hid_kernel_set_report_count);

END
)


USERSPACE_EVENT_PROBE_SUMMARY=$(cat<<-'END'

printf("Userspace Event Count : %llu\n",hid_event_count);

END
)

USERSPACE_REPORT_PROBE_SUMMARY=$(cat<<-'END'

printf("Userspace Interrupt Report Count : %llu\n",hid_userspace_interrupt_report_count);

END
)


## OPTIONS
opt_device_regID=0;
opt_reportSize=8;
opt_hidFunction="";
opt_pid=0;
forked_pid=0;
opt_service_regID=0;
opt_command="";
funcType=0;

## Get options
while getopts hd:l:f:p:s:c: opt
do
case $opt in
d) opt_device_regID=$OPTARG ;;
l) opt_reportSize=$OPTARG ;;
f) opt_hidFunction=$OPTARG ;;
p) opt_pid=$OPTARG ;;
s) opt_service_regID=$OPTARG ;;
c) opt_command=$OPTARG ;;
h|?)
USAGE=$(cat<<-'END' >&2

USAGE: hiddtraceutil [-d device_registry_id] [-s service_registry_id] [-l report_length] [-f hid_function] [-p pid] [-c command]

device_registry_id    ...... Registry ID of HID device.
service_registry_id   ...... Registry ID of HID Event Service.
report_length         ...... Size of HID report {Input / Feature / Output }.
hid_function          ...... HID Function {getReport / setReport / handleReport}.
pid                   ...... PID of process {pid = 0 track kernel functions only}.
command               ...... Command to execute for starting process.

)
echo $USAGE
exit 1
esac
done
shift `expr $OPTIND - 1`


if [ ${#opt_command} != 0 ]
then
$opt_command > /dev/null 2>&1 &
forked_pid=$!
opt_pid=$forked_pid
fi

processProbe="iohidfamily"$opt_pid;
grepStrEvent=".*"$processProbe".*trace_hid_event$";
grepStrReport=".*"$processProbe".*hid_trace$";
validEventProbe=$(echo $(/usr/sbin/dtrace -l | grep $grepStrEvent | cut -d' ' -f 2) | cut -d' ' -f 1)
validReportProbe=$(echo $(/usr/sbin/dtrace -l | grep $grepStrReport | cut -d' ' -f 2) | cut -d' ' -f 1)

if [ ${#validEventProbe} == 0 -o "$validEventProbe" != "$processProbe" ]
then
USERSPACE_EVENT_PROBE=""
USERSPACE_EVENT_PROBE_SUMMARY=""
fi

if [ ${#validReportProbe} == 0 -o "$validReportProbe" != "$processProbe" ]
then
USERSPACE_REPORT_DATA_PROBE=""
USERSPACE_REPORT_PROBE_SUMMARY=""
fi


if [ "$opt_hidFunction" != "handleReport" -o $opt_pid == 0 ]
then
USERSPACE_REPORT_DATA_PROBE=""
USERSPACE_EVENT_PROBE=""
USERSPACE_REPORT_PROBE_SUMMARY=""
USERSPACE_EVENT_PROBE_SUMMARY=""
fi

if [ $opt_service_regID == 0 ]
then
USERSPACE_EVENT_PROBE=""
USERSPACE_EVENT_PROBE_SUMMARY=""
fi

if [ "$opt_hidFunction" == "handleReport" ]
then
funcType=0
KERNEL_GET_PROBE_SUMMARY=""
KERNEL_SET_PROBE_SUMMARY=""
fi

if [ "$opt_hidFunction" == "getReport" ]
then
funcType=1
KERNEL_INTERRUPT_PROBE_SUMMARY=""
KERNEL_SET_PROBE_SUMMARY=""
fi

if [ "$opt_hidFunction" == "setReport" ]
then
funcType=2
KERNEL_INTERRUPT_PROBE_SUMMARY=""
KERNEL_GET_PROBE_SUMMARY=""
fi

#Dtrace
dtrace='

#pragma D option quiet

/* Global varibles */

inline uint64_t OPT_device_regID  = '$opt_device_regID';
inline uint32_t OPT_reportSize = '$opt_reportSize';
inline uint64_t OPT_service_regID = '$opt_service_regID';
inline uint8_t  expected_funcType = '$funcType';
uint64_t hid_kernel_interrupt_report_count;
uint64_t hid_userspace_interrupt_report_count;
uint64_t hid_event_count;
uint64_t hid_kernel_get_report_count;
uint64_t hid_kernel_set_report_count;


BEGIN {
printf("***** HID Probe Start *********\n");
hid_kernel_interrupt_report_count = 0;
hid_kernel_get_report_count = 0;
hid_kernel_set_report_count = 0;
hid_userspace_interrupt_report_count = 0;
hid_event_count = 0;
}

fbt::*Device*'$opt_hidFunction'*:entry {
}

'$KERNEL_REPORT_DATA_PROBE'

'$USERSPACE_REPORT_DATA_PROBE'

'$USERSPACE_EVENT_PROBE'

fbt::*Device*'$opt_hidFunction'*:return {
}

END {

printf("***** HID Probe End *********\n");
printf("\nSummary :\n\n");

'$KERNEL_INTERRUPT_PROBE_SUMMARY'

'$KERNEL_GET_PROBE_SUMMARY'

'$KERNEL_SET_PROBE_SUMMARY'

'$USERSPACE_REPORT_PROBE_SUMMARY'

'$USERSPACE_EVENT_PROBE_SUMMARY'
}

'

if [ $opt_pid == 0 ]
then
/usr/sbin/dtrace -n "$dtrace" >&2
else
/usr/sbin/dtrace -n "$dtrace" -p "$opt_pid" >&2
fi

if [ $forked_pid != 0 ]
then
kill -9 $forked_pid
fi