#!/bin/sh
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
)
opt_device_regID=0;
opt_reportSize=8;
opt_hidFunction="";
opt_pid=0;
forked_pid=0;
opt_service_regID=0;
opt_command="";
funcType=0;
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 [ ${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 [ ${then
USERSPACE_EVENT_PROBE=""
USERSPACE_EVENT_PROBE_SUMMARY=""
fi
if [ ${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='
/* 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