| #!/bin/sh |
| |
| # Copyright (c) 2013 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| I2C_DEVICES_PATH="/sys/bus/i2c/devices" |
| |
| # Find touchscreen/pad path in i2c devices given it's device name and a list |
| # of the sysfs entries it is expect to have (this can help skip over some |
| # bogus devices that have already been disconnected) |
| # The required sysfs filenames could be supplied as a space-delimited string |
| find_i2c_device_by_name() { |
| local dev="" |
| local name_to_find="$1" |
| local required_sysfs="$2" |
| |
| for dev in "${I2C_DEVICES_PATH}"/*/name; do |
| local dev_name="$(cat "${dev}")" |
| if [ "${name_to_find}" = "${dev_name}" ]; then |
| local missing_sysfs_entry=0 |
| local path="${dev%/name}" |
| |
| for sysfs in $required_sysfs; do |
| if [ ! -e "${path}/${sysfs}" ]; then |
| missing_sysfs_entry=1 |
| fi |
| done |
| |
| if [ "${missing_sysfs_entry}" -eq 0 ]; then |
| echo "${path}" |
| return 0 |
| fi |
| fi |
| done |
| return 1 |
| } |
| |
| find_i2c_hid_device() { |
| local dev="" |
| local path="" |
| local vid="${1%_*}" |
| local pid="${1#*_}" |
| |
| for dev in "${I2C_DEVICES_PATH}"/*/; do |
| local driver_name="$(readlink -f ${dev}/driver | xargs basename)" |
| if [ "i2c_hid" = "${driver_name}" ]; then |
| local hid_path=$(echo ${dev}/*:${vid}:${pid}.*) |
| if [ -d "${hid_path}" ]; then |
| local hidraw_sysfs_path=$(echo ${hid_path}/hidraw/hidraw*) |
| path="/dev/${hidraw_sysfs_path##*/}" |
| break |
| fi |
| fi |
| done |
| echo "${path}" |
| } |
| |
| find_fw_link_path() { |
| # Given a hardware version (or product ID depending on the device) |
| # determine which fw symlink in /lib/firmware it should try to load |
| local hw_version="$1" |
| local fw_link_name="$2" |
| local specific_fw_link_path="" |
| local generic_fw_link_path="" |
| local fw_link_name_extension="`expr "$fw_link_name" : ".*\(\..*\)"`" |
| local fw_link_name_base="${fw_link_name%$fw_link_name_extension}" |
| |
| case ${fw_link_name_base} in |
| /*) fw_link_path="${fw_link_name_base}" ;; |
| *) fw_link_path="/lib/firmware/${fw_link_name_base}" ;; |
| esac |
| |
| specific_fw_link_path="${fw_link_path}_${hw_version}${fw_link_name_extension}" |
| generic_fw_link_path="${fw_link_path}${fw_link_name_extension}" |
| |
| if [ -e "${specific_fw_link_path}" ]; then |
| echo "${specific_fw_link_path}" |
| else |
| echo "${generic_fw_link_path}" |
| fi |
| } |
| |
| standard_update_firmware() { |
| # Update a touch device by piping a "1" into a sysfs entry called update_fw |
| # This is a common method for triggering a FW update, and it used by several |
| # different touch vendors. |
| local touch_device_path="$1" |
| local i="" |
| local ret="" |
| |
| for i in $(seq 5); do |
| printf 1 > "${touch_device_path}/update_fw" |
| ret=$? |
| if [ ${ret} -eq 0 ]; then |
| return 0 |
| fi |
| log_msg "update_firmware try #${i} failed... retrying." |
| done |
| die "Error updating touch firmware. ${ret}" |
| } |
| |
| get_active_firmware_version_from_sysfs() { |
| local sysfs_name="$1" |
| local touch_device_path="$2" |
| local fw_version_sysfs_path="${touch_device_path}/${sysfs_name}" |
| |
| if [ -e "${fw_version_sysfs_path}" ]; then |
| cat "${fw_version_sysfs_path}" |
| else |
| die "No firmware version sysfs at ${fw_version_sysfs_path}." |
| fi |
| } |
| |
| rebind_driver() { |
| # Unbind and then bind the driver for this touchpad incase the recent FW |
| # update changed the way it talks to the OS. |
| local touch_device_path="$1" |
| local bus_id="$(basename ${touch_device_path})" |
| local driver_path="$(readlink -f ${touch_device_path}/driver)" |
| |
| log_msg "Attempting to re-bind '${bus_id}' to driver '${driver_path}'" |
| echo "${bus_id}" > "${driver_path}/unbind" |
| if [ "$?" -ne "0" ]; then |
| log_msg "Unable to unbind." |
| else |
| echo "${bus_id}" > "${driver_path}/bind" |
| if [ "$?" -ne "0" ]; then |
| log_msg "Unable to bind the device back to the driver." |
| else |
| log_msg "Success." |
| fi |
| fi |
| } |
| |
| hex_to_decimal() { |
| printf "%d" "0x""$1" |
| } |
| |
| log_msg() { |
| local script_filename="$(basename $0)" |
| logger -t "${script_filename%.*}[${PPID}]-${FLAGS_device}" "$@" |
| echo "$@" |
| } |
| |
| die() { |
| log_msg "error: $*" |
| exit 1 |
| } |
| |
| |
| # These flags can be used as "update types" to indicate updater state |
| UPDATE_NEEDED_OUT_OF_DATE="1" |
| UPDATE_NEEDED_RECOVERY="2" |
| UPDATE_NOT_NEEDED_UP_TO_DATE="3" |
| UPDATE_NOT_NEEDED_AHEAD_OF_DATE="4" |
| |
| log_update_type() { |
| # Given the update type, print a corresponding message into the logs. |
| local update_type="$1" |
| if [ "${update_type}" -eq "${UPDATE_NEEDED_OUT_OF_DATE}" ]; then |
| log_msg "Update needed, firmware out of date." |
| elif [ "${update_type}" -eq "${UPDATE_NEEDED_RECOVERY}" ]; then |
| log_msg "Recovery firmware update. Rolling back." |
| elif [ "${update_type}" -eq "${UPDATE_NOT_NEEDED_UP_TO_DATE}" ]; then |
| log_msg "Firmware up to date." |
| elif [ "${update_type}" -eq "${UPDATE_NOT_NEEDED_AHEAD_OF_DATE}" ]; then |
| log_msg "Active firmware is ahead of updater, no update needed." |
| else |
| log_msg "Unknow update type '${update_type}'." |
| fi |
| } |
| |
| is_update_needed() { |
| # Given an update type, this function returns a boolean indicating if the |
| # updater should trigger an update at all. |
| local update_type="$1" |
| if [ "${update_type}" -eq "${UPDATE_NEEDED_OUT_OF_DATE}" ] || |
| [ "${update_type}" -eq "${UPDATE_NEEDED_RECOVERY}" ]; then |
| echo ${FLAGS_TRUE} |
| else |
| echo ${FLAGS_FALSE} |
| fi |
| } |
| |
| compare_multipart_version() { |
| # Compare firmware versions that are of the form A.B...Y.Z |
| # The numbers must all be devimal integers for this to work, so |
| # do your conversions before calling the function. |
| # To call this function interleave the two version strings by |
| # importance, starting with the active FW version. |
| # eg: If your active version is A.B.C and the fw updater is X.Y.Z |
| # you should call compare_multipart_version A X B Y C Z |
| local update_type="" |
| local num_parts="$(($# / 2))" |
| |
| # Starting with the most significant values, compare them one |
| # by one until we find a difference or run out of values. |
| for i in `seq "$num_parts"`; do |
| local active_component="$1" |
| local updater_component="$2" |
| if [ -z "${update_type}" ]; then |
| if [ "${active_component}" -lt "${updater_component}" ]; then |
| update_type="${UPDATE_NEEDED_OUT_OF_DATE}" |
| elif [ "${active_component}" -gt "${updater_component}" ]; then |
| update_type="${UPDATE_NOT_NEEDED_AHEAD_OF_DATE}" |
| fi |
| fi |
| shift |
| shift |
| done |
| |
| if [ -z "${update_type}" ]; then |
| update_type="${UPDATE_NOT_NEEDED_UP_TO_DATE}" |
| elif [ "${FLAGS_recovery}" -eq "${FLAGS_TRUE}" ] && |
| [ "${update_type}" = "${UPDATE_NOT_NEEDED_AHEAD_OF_DATE}" ]; then |
| update_type="${UPDATE_NEEDED_RECOVERY}" |
| fi |
| |
| echo "${update_type}" |
| } |
| |
| |
| get_customization_id() { |
| # Get the "customization id" from the Chromebook's VPD. This ID is |
| # mandatory for Zerg systems (where 2 different devices use the same build) |
| # and can be used to differentiate them. If the entry doesn't exist, this |
| # will simply not print anything. Note that is is only required to remain |
| # constant *after* a machine has reached MP -- if you don't know what you're |
| # doing you're probably better off using get_board_name which wraps this. |
| vpd_get_value customization_id |
| } |
| |
| get_board_name_from_vpd() { |
| # Get the name of this specific board. This is done to differentiate which |
| # board is being used, and the board name is determined by looking at the |
| # customization_id in VPD which is supposed to be of the format: |
| # "${OEM_NAME}-${BOARD_NAME}" By stripping off the OEM name we allow the |
| # customization_id to change to mask the OEM name during early stages of |
| # development without having to modify the firmware filenames. |
| local customization_id="$(get_customization_id)" |
| if [ -z "${customization_id}" ]; then |
| echo "" |
| fi |
| |
| echo "${customization_id##*-}" |
| } |