| #!/bin/bash |
| |
| # Copyright (c) 2012 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. |
| |
| # This is a wrapper around a lot of different DBus calls, written in sh; this is |
| # meant to replace parts of flimflam-test, and also to be callable from crosh. |
| |
| . /usr/lib/connectivity-common.sh |
| . /usr/lib/modem-common.sh |
| |
| # Wait for a modem to reset itself and come back with a new DBus name |
| # args: |
| # $1 - dbus name of the modem before reset |
| # $2 - timeout in seconds |
| wait_for_modem_reset() { |
| local modem |
| local oldmodem="$1" |
| local timeout="$2" |
| local status="Timed out" |
| echo -n "Waiting..." |
| while test ${timeout} -gt 0; do |
| modem=$(default_modem) |
| if [ -n "${modem}" -a "${modem}" != "${oldmodem}" ]; then |
| status="Done" |
| break |
| fi |
| sleep 1 |
| timeout=$((timeout - 1)) |
| echo -n "." |
| done |
| echo "${status}" |
| } |
| |
| # Wait for a modem to reset itself and come back with a new DBus name, |
| # or for the activation state to change from "1" |
| # MM_MODEM_ACTIVATION_STATE_ACTIVATING to something else |
| # Success is determined by the activation state changing or by having |
| # the newly assigned MDN. |
| # |
| # args: |
| # $1 - dbus name of the modem before activation |
| # $2 - activation state of modem before activation call |
| # $3 - timeout in seconds |
| # $4 - new mdn |
| # |
| wait_for_activation_change() { |
| local modem |
| local oldmodem="$1" |
| local oldstate="$2" |
| local timeout="$3" |
| local expected_mdn="$4" |
| local status="Timed out" |
| local activation_state |
| echo -n "Waiting..." |
| while test ${timeout} -gt 0 ; do |
| modem=$(default_modem) |
| if [ -n "${modem}" -a "${modem}" != "${oldmodem}" ]; then |
| status="Done" |
| break |
| fi |
| if [ -n "${modem}" ]; then |
| activation_state=$(mm_modem_activation_state "${modem}") |
| if [ -n "${activation_state}" ]; then |
| if [ ${activation_state} -gt 1 ]; then |
| status="Done" |
| break |
| fi |
| fi |
| fi |
| sleep 1 |
| timeout=$((timeout - 1)) |
| echo -n "." |
| done |
| activation_state=$(mm_modem_activation_state "${modem}") |
| if [ -z "${activation_state}" ]; then |
| status="Failed" |
| elif [ ${activation_state} -le ${oldstate} ]; then |
| status="Failed" |
| fi |
| if [ -n "${expected_mdn}" ]; then |
| local mdn=$(mm_modem_status "${modem}" mdn) |
| if [ "${expected_mdn}" = "${mdn}" ]; then |
| status="Done" |
| fi |
| fi |
| echo "${status}" |
| } |
| |
| activate_manual() { |
| $(arg_or_default modem $(default_modem)) |
| [ -z "${modem}" ] && error_exit "No modem found." |
| local args=$(echo "$@" | sed -e 's/ /,/g') |
| |
| if is_mm1_modem "${modem}"; then |
| error_exit "Manual activation is not supported on this modem." |
| fi |
| |
| args=$(require "${args}" min) |
| args=$(require "${args}" mdn) |
| args=$(require "${args}" spc) |
| args=$(require "${args}" system_id) |
| local oldstate=$(mm_modem_activation_state "${modem}") |
| dbus_call "${MM}" "${modem}" "${MM_IMODEM_CDMA}.ActivateManualDebug" \ |
| "dict:string:string:${args}" |
| local mdn=$(echo "${args}" | sed -e s'/.*mdn,\([^,]*\).*/\1/g') |
| wait_for_activation_change "${modem}" "${oldstate}" 40 "${mdn}" |
| } |
| |
| activate() { |
| $(arg_or_default modem $(default_modem)) |
| [ -z "${modem}" ] && error_exit "No modem found." |
| # Work around braindead crosh quoting semantics (i.e., there are none, |
| # arguments are tokenized on spaces). Sigh. |
| local carrier=$(echo "$@") |
| |
| if is_mm1_modem "${modem}"; then |
| mmcli -m "${modem}" --cdma-activate="${carrier}" |
| return |
| fi |
| |
| # TODO(jglasgow): verify that we can pass an empty string |
| local oldstate=$(mm_modem_activation_state "${modem}") |
| local status=$(dbus_call "${MM}" "${modem}" "${MM_IMODEM_CDMA}.Activate" \ |
| "string:${carrier}") |
| if [ ${status} != 0 ]; then |
| error "Failed to activate (error ${status})." |
| else |
| wait_for_activation_change "${modem}" "${oldstate}" 40 |
| fi |
| } |
| |
| connect() { |
| $(arg_or_default modem $(default_modem)) |
| [ -z "${modem}" ] && error_exit "No modem found." |
| # Work around braindead quoting again... |
| local args=$(echo "$@") |
| |
| if is_mm1_modem "${modem}"; then |
| [ -n "${args}" ] && args="number=${args}" |
| mmcli -m "${modem}" --simple-connect="${args}" |
| return |
| fi |
| |
| [ -z "${args}" ] && args='ignored' |
| dbus_call "${MM}" "${modem}" "${MM_IMODEM}.Connect" "string:${args}" |
| } |
| |
| factory_reset() { |
| $(arg_or_default modem $(default_modem)) |
| [ -z "${modem}" ] && error_exit "No modem found." |
| $(arg_or_prompt spc 000000) |
| |
| if is_mm1_modem "${modem}"; then |
| # TODO(benchan): Evaluate if a warning should be given when factory |
| # resetting under certain modem configurations. |
| mmcli -m "${modem}" --factory-reset="${spc}" |
| return |
| fi |
| |
| technology=$(mm_modem_status "${modem}" technology) |
| if [ "${technology}" = "CDMA" ]; then |
| cat <<-EOF |
| |
| WARNING: Unless you have been instructed to do so by a cellular service |
| provider customer service representative, factory resetting your modem will |
| prevent you from re-connecting to your cellular service. |
| |
| If you have been instructed to issue the 'modem factory-reset' command, |
| please make sure to issue the 'modem activate' command afterwards to |
| re-activate your modem. Do not use the graphic user interface to do so. |
| |
| EOF |
| $(arg_or_prompt continue n) |
| if [ "${continue}" != "y" -a "${continue}" != "Y" ]; then |
| echo "Factory reset cancelled." |
| return |
| fi |
| fi |
| dbus_call "${MM}" "${modem}" "${MM_IMODEM}.FactoryReset" "string:${spc}" |
| wait_for_modem_reset "${modem}" 40 |
| } |
| |
| reset() { |
| $(arg_or_default modem $(default_modem)) |
| [ -z "${modem}" ] && error_exit "No modem found." |
| |
| if is_mm1_modem "${modem}"; then |
| mmcli -m "${modem}" --reset |
| else |
| dbus_call "${MM}" "${modem}" org.chromium.ModemManager.Modem.Gobi.SoftReset |
| fi |
| |
| wait_for_modem_reset "${modem}" 40 |
| } |
| |
| status() { |
| all_modem_status 2>/dev/null |
| } |
| |
| status_feedback() { |
| all_modem_status 2>/dev/null | mask_modem_properties |
| } |
| |
| update_prl() { |
| local modem |
| local mdn |
| local min |
| $(arg_or_default modem $(default_modem)) |
| [ -z "${modem}" ] && error_exit "No modem found." |
| |
| if is_mm1_modem "${modem}"; then |
| error_exit "Updating PRL is not supported on this modem." |
| fi |
| |
| $(needarg prlfile) |
| mdn=$(mm_modem_status "${modem}" mdn) |
| min=$(mm_modem_status "${modem}" min) |
| if [ -z "${mdn}" -o -z "${min}" ]; then |
| error_exit "Cannot update PRL: MDN/MIN are unknown." |
| fi |
| if [ ! -r "${prlfile}" ]; then |
| error_exit "Cannot read PRL file \"${prlfile}\"." |
| fi |
| # Because cromo runs as a different user than this script, |
| # it may not have access to the specified file, even when |
| # the script does. A specific example is the Downloads folder, |
| # which only the "chronos" user has access to. To work |
| # around this problem, we copy the PRL file to /tmp. |
| local tmpfile=$(mktemp --tmpdir prl.XXXXXXXXXX) |
| trap "rm -f ${tmpfile}" 1 2 13 15 |
| cp "${prlfile}" "${tmpfile}" |
| if [ $? -ne 0 ]; then |
| rm -f "${tmpfile}" |
| error_exit "Cannot copy \"${prlfile}\" to \"${tmpfile}\" directory." |
| fi |
| chmod 644 "${tmpfile}" |
| local oldstate=$(mm_modem_activation_state "${modem}") |
| args="mdn,${mdn},min,${min},prlfile,${tmpfile}" |
| dbus_call "${MM}" "${modem}" "${MM_IMODEM_CDMA}.ActivateManualDebug" \ |
| "dict:string:string:${args}" |
| wait_for_modem_reset "${modem}" 40 |
| rm -f "${tmpfile}" |
| } |
| |
| ussd() { |
| local modem |
| local operation="$1" |
| local data="$2" |
| |
| $(arg_or_default modem $(default_modem)) |
| [ -z "${modem}" ] && error_exit "No modem found." |
| |
| if ! is_mm1_modem "${modem}"; then |
| error_exit "USSD is not supported on this modem." |
| fi |
| |
| if [ -z "${operation}" ]; then |
| echo "Valid USSD operations are: status, initiate, respond, cancel" |
| return |
| fi |
| |
| case "${operation}" in |
| status) |
| mmcli -m "${modem}" --3gpp-ussd-status |
| ;; |
| initiate) |
| [ -z "${data}" ] && error_exit "Missing USSD data." |
| mmcli -m "${modem}" --3gpp-ussd-initiate="${data}" |
| ;; |
| respond) |
| [ -z "${data}" ] && error_exit "Missing USSD data." |
| mmcli -m "${modem}" --3gpp-ussd-respond="${data}" |
| ;; |
| cancel) |
| mmcli -m "${modem}" --3gpp-ussd-cancel |
| ;; |
| *) |
| error_exit "'${operation}' is not valid USSD operation." |
| ;; |
| esac |
| } |
| |
| set_carrier() { |
| local modem |
| |
| $(arg_or_default modem $(default_modem)) |
| [ -z "${modem}" ] && error_exit "No modem found." |
| |
| if is_mm1_modem "${modem}"; then |
| error_exit "Setting carrier is not supported on this modem." |
| fi |
| |
| if [ $# -eq 0 ]; then |
| echo "Missing argument: carrier" |
| usage |
| fi |
| local carrier="$*" |
| |
| echo "Setting carrier to ${carrier}. This could take up to two minutes." |
| echo "Using modem ${modem}" |
| |
| dbus-send \ |
| --reply-timeout=120000 \ |
| --system \ |
| --print-reply \ |
| --dest="${MM}" \ |
| "${modem}" \ |
| org.chromium.ModemManager.Modem.Gobi.SetCarrier \ |
| "string:${carrier}" |
| } |
| |
| set_logging() { |
| local level="$1" |
| local manager |
| |
| if [ -z "${level}" ]; then |
| echo "Valid logging levels are: debug, info, warn, error" |
| return |
| fi |
| |
| case "${level}" in |
| debug|info|warn|error) |
| for manager in $(modem_managers); do |
| set_modem_manager_logging "${manager}" "${level}" |
| done |
| ;; |
| *) |
| error_exit "'${level}' is not a valid logging level." |
| ;; |
| esac |
| } |
| |
| MADISON_CONFIG_GROUP_LOCATION=/var/lib/cromo/madison-config-group |
| |
| set_madison_config() { |
| local group="$*" |
| |
| if [ -z "${group}" ]; then |
| echo "No config group specified." |
| echo "Usage: modem set-madison-config <config-group-name>" |
| return |
| fi |
| |
| if [ ! -w "${MADISON_CONFIG_GROUP_LOCATION}" ]; then |
| echo "${MADISON_CONFIG_GROUP_LOCATION} is not a writable file." |
| echo "Please reboot (or restart cromo) and try again."; |
| return |
| fi |
| |
| if [ "$(readlink -f ${MADISON_CONFIG_GROUP_LOCATION})" != \ |
| "${MADISON_CONFIG_GROUP_LOCATION}" ]; then |
| echo "${MADISON_CONFIG_GROUP_LOCATION} points somewhere strange." |
| echo "Please reboot (or restart cromo) and try again." |
| return |
| fi |
| |
| echo "Setting madison config group to ${group}." |
| |
| echo "${group}" > "${MADISON_CONFIG_GROUP_LOCATION}" |
| |
| echo "Please reboot (or restart cromo) to use the new config group." |
| } |
| |
| run_modem_command() { |
| $(needarg cmd) |
| dbus-send --system --print-reply --dest=org.chromium.debugd \ |
| /org/chromium/debugd org.chromium.debugd.RunModemCommand "string:${cmd}" |
| } |
| |
| usage() { |
| echo "Usage: $(basename $0) <command> [args...]" |
| echo " activate [-modem <modem>] [<carrier>] Activate modem" |
| echo " activate-manual [-modem <modem>] [args...] Activate modem manually" |
| echo " ciprl-update " \ |
| "Enable and perform client initiated PRL update" |
| echo " connect [-modem <modem>] [phone number] Connect modem" |
| echo " factory-reset [-modem <modem>] [<spc>] Factory-reset the modem" |
| echo " get-oma-status Current OMA-DM setting" |
| echo " get-prl Current PRL" |
| echo " get-service " \ |
| "Integer index of data service" |
| echo " reset [-modem <modem>] Reset the modem" |
| echo " set-carrier [-modem <modem>] <carrier-name> " \ |
| "Set modem carrier firmware" |
| echo " set-logging (debug|info|warn|error) Set logging level" |
| echo " set-madison-config <config-group-name> Set Madison config group" |
| echo " start-oma " \ |
| "Enable and launch OMA session" |
| echo " status Display modem status" |
| echo " update-prl [-modem <modem>] <prl-file-name> Install a PRL file" |
| echo " ussd [-modem <modem>] status " \ |
| "Show status of ongoing USSD session" |
| echo " ussd [-modem <modem>] initiate <command> Initiate a USSD session" |
| echo " ussd [-modem <modem>] respond <response> " \ |
| "Respond to a USSD request" |
| echo " ussd [-modem <modem>] cancel " \ |
| "Cancel ongoing USSD session" |
| exit 0 |
| } |
| |
| $(needarg cmd) |
| case "${cmd}" in |
| activate) |
| activate "$@" |
| ;; |
| activate-manual) |
| activate_manual "$@" |
| ;; |
| ciprl-update) |
| run_modem_command ciprl-update |
| ;; |
| connect) |
| connect "$@" |
| ;; |
| factory-reset) |
| factory_reset "$@" |
| ;; |
| get-oma-status) |
| run_modem_command get-oma-status |
| ;; |
| get-prl) |
| run_modem_command get-prl |
| ;; |
| get-service) |
| run_modem_command get-service |
| ;; |
| reset) |
| reset "$@" |
| ;; |
| set-carrier) |
| set_carrier "$@" |
| ;; |
| set-logging) |
| set_logging "$@" |
| ;; |
| set-madison-config) |
| set_madison_config "$@" |
| ;; |
| start-oma) |
| run_modem_command start-oma |
| ;; |
| status) |
| status "$@" |
| ;; |
| status-feedback) |
| status_feedback "$@" |
| ;; |
| update-prl) |
| update_prl "$@" |
| ;; |
| ussd) |
| ussd "$@" |
| ;; |
| *) |
| usage |
| ;; |
| esac |