blob: bda5f652d58aac8d9ac27159e0d7146659ccf12a [file] [log] [blame] [edit]
#!/bin/bash
# Copyright 2022 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# shellcheck source=../../../scripts/lib/shflags/shflags
. /usr/share/misc/shflags
# shellcheck source=../common/scripts/chromeos-touch-common.sh
. /opt/google/touch/scripts/chromeos-touch-common.sh
DEFINE_string 'dev_name' '' 'device name' 'd'
DEFINE_string 'dev_i2c_path' '' 'device i2c path' 'p'
DEFINE_string 'dev_pid' '' 'device pid' 'i'
NVT_BRIDGE_PID='F7FC'
NVT_TS_FW_PATH_BASE='/lib/firmware/nvt_ts'
NVT_BRIDGE_FW_PATH_BASE='/lib/firmware/nvt_bridge'
NVT_TS_FW_UPDATE_USER='fwupdate-hidraw'
NVT_TS_FW_UPDATE_GROUP='fwupdate-hidraw'
NVT_TOUCHSCREEN_HIDRAW='/dev/nvt_ts_hidraw'
BRIDGE_TOOL='/usr/sbin/Bdg_Cmd_M252'
TS_TOOL='/usr/sbin/NT36523_Cmd_HID_I2C'
PANEL_NODE_TABLE=(
"/sys/firmware/devicetree/base/soc@0/mdss@ae00000\
/dsi@ae94000/panel@0/compatible" )
# Parse command line
FLAGS "$@" || exit 1
eval set -- "${FLAGS_ARGV}"
create_nvt_ts_hidraw() {
local hidraw_path
local dev_t_major
local dev_t_minor
if [ -e "${NVT_TOUCHSCREEN_HIDRAW}" ]; then
log_msg "${NVT_TOUCHSCREEN_HIDRAW} already exist, skipping..."
return 0
fi
hidraw_path="$(find_i2c_hid_device "${FLAGS_dev_name##*-}")"
if [ -e "${hidraw_path}" ]; then
dev_t_major="$(stat -c "%t" "${hidraw_path}")"
dev_t_minor="$(stat -c "%T" "${hidraw_path}")"
if ! mknod "${NVT_TOUCHSCREEN_HIDRAW}" \
c "0x${dev_t_major}" "0x${dev_t_minor}"; then
die "Failed create node: '${NVT_TOUCHSCREEN_HIDRAW}'."
fi
if ! chown "${NVT_TS_FW_UPDATE_USER}":"${NVT_TS_FW_UPDATE_GROUP}" \
"${NVT_TOUCHSCREEN_HIDRAW}"; then
die "Failed change owner of node: ${NVT_TOUCHSCREEN_HIDRAW}."
fi
if ! chmod 0660 "${NVT_TOUCHSCREEN_HIDRAW}"; then
die "Failed change mode of node: ${NVT_TOUCHSCREEN_HIDRAW}."
fi
else
die "No hidraw device found"
fi
}
# set 0/1 to disable/enable bridge handling interrupt requests
bridge_interrupt_handle() {
minijail0 -u "${NVT_TS_FW_UPDATE_USER}" -g "${NVT_TS_FW_UPDATE_GROUP}" \
-n -N -l --uts -e \
-S /opt/google/touch/policies/nvt_bridge_interrupt_handle.policy \
"${BRIDGE_TOOL}" "${NVT_TOUCHSCREEN_HIDRAW}" "-z" "$1"
}
get_bridge_fw_ver() {
minijail0 -u "${NVT_TS_FW_UPDATE_USER}" -g "${NVT_TS_FW_UPDATE_GROUP}" \
-n -N -l --uts -e \
-S /opt/google/touch/policies/nvt_bridge_update.query.policy \
"${BRIDGE_TOOL}" "${NVT_TOUCHSCREEN_HIDRAW}" "-vs"
}
get_ts_fw_ver() {
minijail0 -u "${NVT_TS_FW_UPDATE_USER}" -g "${NVT_TS_FW_UPDATE_GROUP}" \
-n -N -l --uts -e \
-S /opt/google/touch/policies/nvt_ts_update.query.policy \
"${TS_TOOL}" "${NVT_TOUCHSCREEN_HIDRAW}" "-vs"
}
update_bridge_fw() {
if minijail0 -u "${NVT_TS_FW_UPDATE_USER}" -g "${NVT_TS_FW_UPDATE_GROUP}" \
-n -N -l --uts -e \
-S /opt/google/touch/policies/nvt_bridge_update.update.policy \
"${BRIDGE_TOOL}" "${NVT_TOUCHSCREEN_HIDRAW}" "-u" "$1" "$2"; then
log_msg 'Bridge fw update pass'
else
die 'Bridge fw update fail'
fi
}
update_ts_fw() {
chromeos-boot-alert update_touchscreen_firmware
if minijail0 -u "${NVT_TS_FW_UPDATE_USER}" -g "${NVT_TS_FW_UPDATE_GROUP}" \
-n -N -l --uts -e \
-S /opt/google/touch/policies/nvt_ts_update.update.policy \
"${TS_TOOL}" "${NVT_TOUCHSCREEN_HIDRAW}" "-u" "$1"; then
log_msg 'Touchscreen fw update pass'
else
die 'Touchscreen fw update fail'
fi
}
main() {
local with_bridge=true
local node_path
local panel
local device_pid
local bridge_fw_link_path
local bridge_fw_path
local ts_fw_link_path
local ts_fw_path
local bridge_dev_fw_ver
local bridge_bin_fw_ver
local ts_dev_fw_ver
local ts_bin_fw_ver
# Get PID
for node_path in "${PANEL_NODE_TABLE[@]}"; do
panel=$(cat "${node_path}")
case ${panel} in
'boe,tv110c9m-ll3')
device_pid='604A'
log_msg "Panel boe,tv110c9m-ll3 detected, PID=${device_pid}"
;;
'innolux,hj110iz-01a')
device_pid='604C'
log_msg "Panel innolux,hj110iz-01a detected, PID=${device_pid}"
;;
*)
device_pid=${FLAGS_dev_pid}
with_bridge=false
log_msg "No special panel detected, PID=${device_pid}"
;;
esac
done
# Create custom /dev/nvt_ts_hidraw
create_nvt_ts_hidraw
# If bridge exist, check bridge version and update if needed
if ${with_bridge}; then
bridge_fw_link_path=${NVT_BRIDGE_FW_PATH_BASE}'_'${NVT_BRIDGE_PID}'.bin'
bridge_fw_path=$(readlink -f "${bridge_fw_link_path}")
log_msg "bridge_fw_link_path=${bridge_fw_link_path}"
log_msg "bridge_fw_path=${bridge_fw_path}"
if [ ! -e "${bridge_fw_link_path}" ] || [ ! -e "${bridge_fw_path}" ]; then
die "No valid bridge firmware for ${FLAGS_dev_i2c_path}"
fi
bridge_bin_fw_ver=$(echo "${bridge_fw_path#*"${NVT_BRIDGE_PID}_"}" \
| cut -d '.' -f 1)
bridge_dev_fw_ver=$(get_bridge_fw_ver)
if ! bridge_interrupt_handle 0; then
die "Can not disable bridge interrupt handling"
fi
log_msg "bridge_bin_fw_ver=${bridge_bin_fw_ver}"
log_msg "Before update bridge_dev_fw_ver=${bridge_dev_fw_ver}"
log_msg "Before update bridge PID=${FLAGS_dev_pid}"
if [ "${bridge_dev_fw_ver}" != "${bridge_bin_fw_ver}" ] || \
! [ "${device_pid}" == "${FLAGS_dev_pid}" ]; then
# Update bin and PID for bridge, it will also try to keep lock INT
if ! update_bridge_fw "${bridge_fw_path}" "${device_pid}"; then
die "Update failed or failed to lock bridge INT"
fi
sleep 0.5
bridge_dev_fw_ver=$(get_bridge_fw_ver)
if [ "${bridge_dev_fw_ver}" != "${bridge_bin_fw_ver}" ]; then
log_msg "After update bridge_dev_fw_ver=${bridge_dev_fw_ver}"
report_update_result "${FLAGS_dev_i2c_path}" \
"${REPORT_RESULT_FAILURE}" "${bridge_bin_fw_ver}"
die "Bridge fw update failed for ${FLAGS_dev_i2c_path}"
else
log_msg "Bridge fw update to ${bridge_dev_fw_ver}, " \
"PID update to ${device_pid}"
fi
rebind_driver "${FLAGS_dev_i2c_path}"
else
log_msg "No need to update bridge fw."
fi
fi
# Check touchscreen version and update if needed
ts_fw_link_path=${NVT_TS_FW_PATH_BASE}'_'${device_pid}'.bin'
ts_fw_path=$(readlink -f "${ts_fw_link_path}")
log_msg "ts_fw_link_path=${ts_fw_link_path}"
log_msg "ts_fw_path=${ts_fw_path}"
if [ ! -e "${ts_fw_link_path}" ] || [ ! -e "${ts_fw_path}" ]; then
die "No valid touchscreen firmware for ${FLAGS_dev_i2c_path}."
fi
ts_bin_fw_ver=$(echo "${ts_fw_path#*"${device_pid}_"}" | cut -d '.' -f 1)
ts_dev_fw_ver=$(get_ts_fw_ver)
log_msg "ts_bin_fw_ver=${ts_bin_fw_ver}"
log_msg "Before update ts_dev_fw_ver=${ts_dev_fw_ver}"
report_initial_version "${FLAGS_dev_i2c_path}" "nvt_ts" "${ts_dev_fw_ver}"
if [ "${ts_dev_fw_ver}" != "${ts_bin_fw_ver}" ]; then
update_ts_fw "${ts_fw_path}"
sleep 0.5
ts_dev_fw_ver=$(get_ts_fw_ver)
log_msg "After update ts_dev_fw_ver=${ts_dev_fw_ver}"
if [ "${ts_dev_fw_ver}" != "${ts_bin_fw_ver}" ]; then
report_update_result "${FLAGS_dev_i2c_path}" \
"${REPORT_RESULT_FAILURE}" "${ts_bin_fw_ver}"
die "Touchscreen fw update failed "\
"for ${FLAGS_dev_i2c_path}"
else
report_update_result "${FLAGS_dev_i2c_path}" \
"${REPORT_RESULT_SUCCESS}" "${ts_bin_fw_ver}"
log_msg "Touchscreen fw update to ${ts_dev_fw_ver}"
rebind_driver "${FLAGS_dev_i2c_path}"
fi
else
log_msg "No need to update touchscreen fw."
fi
if ${with_bridge}; then
if ! bridge_interrupt_handle 1; then
die "Can not enable bridge interrupt handling"
fi
fi
exit 0
}
main "$@"