Date: Mon, 14 Jan 2019 08:32:15 -0800 (PST) From: "Rodney W. Grimes" <freebsd@pdx.rh.CN85.dnsmgr.net> To: Lars Engels <lme@freebsd.org> Cc: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: Re: svn commit: r343020 - head/usr.sbin/bluetooth/bluetooth-config Message-ID: <201901141632.x0EGWFud035793@pdx.rh.CN85.dnsmgr.net> In-Reply-To: <201901140823.x0E8Nmll096242@repo.freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
> Author: lme (ports committer) > Date: Mon Jan 14 08:23:47 2019 > New Revision: 343020 > URL: https://svnweb.freebsd.org/changeset/base/343020 > > Log: > This new version of bluetooth-config.sh tries to follow the style of other > shell scripts in base, removes the bogus "copyleft", adds the BeerWare license > header and uses rc.subr(8) new 'enable' keyword for adding entries in > rc.conf(5). > > Submitted by: erdgeist <erdgeist@erdgeist.org> > Approved by: bapt > MFC after: 2 weeks > > Modified: > head/usr.sbin/bluetooth/bluetooth-config/bluetooth-config.sh > > Modified: head/usr.sbin/bluetooth/bluetooth-config/bluetooth-config.sh > ============================================================================== > --- head/usr.sbin/bluetooth/bluetooth-config/bluetooth-config.sh Mon Jan 14 07:54:11 2019 (r343019) > +++ head/usr.sbin/bluetooth/bluetooth-config/bluetooth-config.sh Mon Jan 14 08:23:47 2019 (r343020) > @@ -1,9 +1,12 @@ > #!/bin/sh > #- > -# Copyleft 2019 Dirk Engling > +# ---------------------------------------------------------------------------- > +# "THE BEER-WARE LICENSE" (Revision 42): > +# <erdgeist@erdgeist.org> wrote this file. As long as you retain this notice you > +# can do whatever you want with this stuff. If we meet some day, and you think > +# this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp > +# ---------------------------------------------------------------------------- Great step forward, but it needs a copyright, without one the Berne convention applies, and that just makes this a case of an undocumented copyright. I didnt think about that when you showed it with no copyright, there really should be one in every file to get out of that Berne "undocumented" state. Thanks, Rod > # > -# This script is released under the beerware license. > -# > # $FreeBSD$ > # > > @@ -11,8 +14,6 @@ > exerr () { echo -e "Error: $*" >&2 ; exit 1; } > print_syntax () { echo -e "Syntax: $0 scan [-d device] [-n node]"; exit 1; } > > -# Assuming we are called to do the pair-new-device subcommand first > - > main() { > unset node device started bdaddresses retry > > @@ -22,132 +23,140 @@ shift > > # Get command line options > while getopts :d:n: arg; do > - case ${arg} in > - d) device="$OPTARG";; > - n) node="$OPTARG";; > - ?) print_syntax;; > - esac > + case ${arg} in > + d) device="$OPTARG";; > + n) node="$OPTARG";; > + ?) print_syntax;; > + esac > done > > # No use running without super user rights > -[ $( id -u ) -eq 0 ] || exerr "$0 must modify files that belong to root. Re-run as root." > +if [ $( id -u ) -ne 0 ]; then > + exerr "$0 must modify files that belong to root. Re-run as root." > +fi > > -known_nodes=$(/usr/sbin/hccontrol read_node_list 2>/dev/null | \ > - /usr/bin/tail -n +2 | /usr/bin/cut -d ' ' -f 1) > +known_nodes=$( /usr/sbin/hccontrol read_node_list 2>/dev/null |\ > + /usr/bin/tail -n +2 | /usr/bin/cut -d ' ' -f 1 ) > > # Check if netgraph knows about any HCI nodes > if ! [ "${known_nodes}" ]; then > - ng_nodes=$(/usr/sbin/ngctl list 2>/dev/null | \ > - /usr/bin/grep -o "Name: .* Type: ubt" | /usr/bin/cut -d ' ' -f 2) > + ng_nodes=$( /usr/sbin/ngctl list 2>/dev/null | \ > + /usr/bin/grep -o "Name: .* Type: ubt" |/usr/bin/cut -d' ' -f2 ) > > - [ "${ng_nodes}" ] || exerr "No Bluetooth host controllers found." > + [ "${ng_nodes}" ] || exerr "No Bluetooth host controllers found." > > - unset found > - for n in ${ng_nodes}; do > - if [ "${n}" = "${node%hci}" ]; then > - # If we found the node but its stack is not set up, do it now > - /usr/sbin/service bluetooth start ${node%hci} || exit 1 > - found="YES" > - fi > - done > + unset found > + for n in ${ng_nodes}; do > + if [ "${n}" = "${node%hci}" ]; then > + # Found the node but its stack is not set up? Do it now. > + /usr/sbin/service bluetooth start ${node%hci} || exit 1 > + found="YES" > + fi > + done > > - # If we have Bluetooth controller nodes without a set up stack, > - # ask the user if we shall start it up > - if ! [ "${found}" ]; then > - printf "No usable Bluetooth host controllers were found.\n" > - printf "These host controllers exist in the system:\n %s" " ${ng_nodes}" > - read -p "Choose a host controller to set up: [${ng_nodes%% *}]" node > - : ${node:="${ng_nodes%% *}"} > - /usr/sbin/service bluetooth start ${node} || exit 1 > - fi > + # If we have Bluetooth controller nodes without a set up stack, > + # ask the user if we shall start it up > + if ! [ "${found}" ]; then > + printf "No usable Bluetooth host controllers were found.\n" > + printf "These host controllers exist in the system:\n" > + printf " %s\n" "${ng_nodes}" > + prompt="Choose a host controller to set up: [${ng_nodes%% *}]" > + read -p "${prompt}" node > + : ${node:="${ng_nodes%% *}"} > + /usr/sbin/service bluetooth start ${node} || exit 1 > + fi > > - # Re-read known nodes > - known_nodes=$(/usr/sbin/hccontrol read_node_list 2>/dev/null | \ > - /usr/bin/tail -n +2 | /usr/bin/cut -d ' ' -f 1) > - # check if we succeeded in bringing it up > - [ "${known_nodes}" ] || exerr "Failed to set up Bluetooth stack" > + # Re-read known nodes > + known_nodes=$(/usr/sbin/hccontrol read_node_list 2>/dev/null | > + /usr/bin/tail -n +2 | /usr/bin/cut -d ' ' -f 1 ) > + > + # check if we succeeded in bringing it up > + [ "${known_nodes}" ] || exerr "Failed to set up Bluetooth stack" > fi > > # if a node was requested on command line, check if it is there > if [ "${node}" ]; then > - unset found > - for n in ${known_nodes}; do > - [ "${n}" = "${node}" ] && found="YES" > - [ "${n}" = "${node}hci" ] && node="${node}hci" && found="YES" > - done > - [ "${found}" ] || exerr "Node ${node} not found" > + unset found > + for n in ${known_nodes}; do > + [ "${n}" = "${node}" ] && found="YES" > + [ "${n}" = "${node}hci" ] && node="${node}hci" && found="YES" > + done > + [ "${found}" ] || exerr "Node ${node} not found" > fi > > [ "${node}" ] && node="-n ${node}" > > while ! [ "${bdaddresses}" ]; do > - retry=X${retry} > - printf "Scanning for new Bluetooth devices (Attempt %d of 5) ... " ${#retry} > - bdaddresses=$( /usr/sbin/hccontrol -N ${node} inquiry 2>/dev/null | \ > - /usr/bin/grep -o "BD_ADDR: .*" | /usr/bin/cut -d ' ' -f 2 ) > + retry=X${retry} > + printf "Scanning for new Bluetooth devices (Attempt %d of 5) ... " \ > + ${#retry} > + bdaddresses=$( /usr/sbin/hccontrol -N ${node} inquiry 2>/dev/null | > + /usr/bin/grep -o "BD_ADDR: .*" | /usr/bin/cut -d ' ' -f 2 ) > > - # Count entries and, if a device was requested on command line, > - # try to find it > - unset found count > - for bdaddress in ${bdaddresses}; do > - count=X${count} > - if [ "${bdaddress}" = "${device}" ]; then > - found=YES > - bdaddresses="${device}" > - count=X > - break > - fi > - done > + # Count entries and, if a device was requested on command line, > + # try to find it > + unset found count > + for bdaddress in ${bdaddresses}; do > + count=X${count} > + if [ "${bdaddress}" = "${device}" ]; then > + found=YES > + bdaddresses="${device}" > + count=X > + break > + fi > + done > > - # If device was requested on command line but is not found, > - # or no devices found at all, rescan until retry is exhausted > - if ! [ "${found}" -o "${count}" -a -z "${device}" ]; then > - printf "failed.\n" > - if [ "${#retry}" -eq 5 ]; then > - [ "${device}" ] && exerr "Device ${device} not found" > - exerr "No new Bluetooth devices found" > - fi > - unset bdaddresses > - sleep 2 > - continue > - fi > + # If device was requested on command line but is not found, > + # or no devices found at all, rescan until retry is exhausted > + if ! [ "${found}" -o "${count}" -a -z "${device}" ]; then > + printf "failed.\n" > + if [ "${#retry}" -eq 5 ]; then > + [ "${device}" ] && exerr "Device ${device} not found" > + exerr "No new Bluetooth devices found" > + fi > + unset bdaddresses > + sleep 2 > + continue > + fi > > - [ ${#count} -gt 1 ] && plural=s || plural='' > - printf "done.\nFound %d new bluetooth device%s (scanning for names):\n" ${#count} ${plural} > + [ ${#count} -gt 1 ] && plural=s || plural='' > + printf "done.\nFound %d new bluetooth device%s " ${#count} ${plural} > + printf "(now scanning for names):\n" > > - # Looping again for the faster feedback > - unset count > - for bdaddress in ${bdaddresses}; do > - count=X${count} > - bdname=$( /usr/bin/bthost -b "${bdaddress}" 2>/dev/null ) > - friendlyname=$( /usr/sbin/hccontrol Remote_Name_Request ${bdaddress} 2> /dev/null | \ > - /usr/bin/grep -o "Name: .*" | /usr/bin/cut -d ' ' -f 2- ) > + # Looping again for the faster feedback > + unset count > + for bdaddress in ${bdaddresses}; do > + count=X${count} > + bdname=$( /usr/bin/bthost -b "${bdaddress}" 2>/dev/null ) > + friendlyname=$( /usr/sbin/hccontrol Remote_Name_Request \ > + ${bdaddress} 2> /dev/null | > + /usr/bin/grep -o "Name: .*" |/usr/bin/cut -d ' ' -f 2- ) > > - # sdpcontrol should be able to pull vendor and product id via sdp > - printf "[%2d] %s\t\"%s\" (%s)\n" ${#count} "${bdaddress}" "${friendlyname}" "${bdname}" > + # sdpcontrol should be able to pull vendor + product id via sdp > + printf "[%2d] %s\t\"%s\" (%s)\n" ${#count} "${bdaddress}" \ > + "${friendlyname}" "${bdname}" > > - eval bdaddress_${#count}=\${bdaddress} > - eval bdname_${#count}=\${bdname} > - eval friendlyname_${#count}=\${friendlyname} > - done > + eval bdaddress_${#count}=\${bdaddress} > + eval bdname_${#count}=\${bdname} > + eval friendlyname_${#count}=\${friendlyname} > + done > > - # If a device was pre-selected, do not query the user > - [ "${device}" ] && topair=1 || unset topair > + # If a device was pre-selected, do not query the user > + [ "${device}" ] && topair=1 || unset topair > > - # Even if only one device was found, user may chose 0 to rescan > - while ! [ "${topair}" ]; do > - if [ ${#count} -eq 1 ]; then > - read -p "Select device to pair with [1, or 0 to rescan]: " topair > - else > - read -p "Select device to pair with [1-${#count}, or 0 to rescan]: " topair > - fi > - if ! [ "${topair}" -ge 0 -a "${topair}" -le "${#count}" ] 2>/dev/null ; then > - printf "Value out of range: %s.\n" {topair} > - unset topair > - fi > - done > + # Even if only one device was found, user may chose 0 to rescan > + while ! [ "${topair}" ]; do > + prompt="Select device to pair with [1" > + [ ${#count} -gt 1 ] && prompt="${prompt}-${#count}" > + read -p "${prompt}, or 0 to rescan]: " topair > + if ! [ "${topair}" -ge 0 -a "${topair}" -le "${#count}" ] \ > + 2>/dev/null ; then > + printf "Value out of range: %s.\n" {topair} > + unset topair > + fi > + done > > - [ "${topair}" -eq "0" ] && unset bdaddresses retry > + [ "${topair}" -eq "0" ] && unset bdaddresses retry > done > > eval bdaddress=\${bdaddress_${topair}} > @@ -156,20 +165,24 @@ eval friendlyname=\${friendlyname_${topair}} > > # Do we need to add an entry to /etc/bluetooth/hosts? > if ! [ "${bdname}" ]; then > - printf "\nAdding device ${bdaddress} to /etc/bluetooth/hosts.\n" > + printf "\nAdding device ${bdaddress} to /etc/bluetooth/hosts.\n" > > - while ! [ "${bdname}" ]; do > - read -p "Enter friendly name. [${friendlyname}]: " REPLY > - : ${REPLY:="${friendlyname}"} > + while ! [ "${bdname}" ]; do > + read -p "Enter friendly name. [${friendlyname}]: " _r > + : ${_r:="${friendlyname}"} > > - if [ "${REPLY}" ]; then > - # Remove white space and non-friendly characters > - bdname=$( printf "%s" "${REPLY}" | tr -c '[:alnum:]-,.' _ ) > - [ "${REPLY}" != "${bdname}" ] && printf "Notice: Using sanitized name \"%s\" in /etc/bluetooth/hosts.\n" "${bdname}" > - fi > - done > + if [ "${_r}" ]; then > + # Remove white space and non-friendly characters > + bdname=$( printf "%s" "${_r}" | tr -c '[:alnum:]-,.' _ ) > + if [ "${_r}" != "${bdname}" ]; then > + printf "Notice: Using sanitized name" > + printf "\"%s\" in /etc/bluetooth/hosts.\n" \ > + "${bdname}" > + fi > + fi > + done > > - printf "%s\t%s\n" "${bdaddress}" "${bdname}" >> /etc/bluetooth/hosts > + printf "%s\t%s\n" "${bdaddress}" "${bdname}" >> /etc/bluetooth/hosts > fi > > # If scanning for the name did not succeed, resort to bdname > @@ -183,86 +196,109 @@ fi > # Also we cannot really modify the PIN in an existing entry. So we > # need to prompt the user to manually do it and restart this script > if ! /usr/sbin/service hcsecd enabled; then > - printf "\nWarning: hcsecd is not enabled.\nThis daemon manages pairing requests.\n" > - read -p "Enable hcsecd? [yes]: " REPLY > - case "${REPLY}" in no|n|NO|N|No|nO) ;; *) /usr/sbin/sysrc hcsecd_enable="YES";; esac > + printf "\nWarning: hcsecd is not enabled.\n" > + printf "This daemon manages pairing requests.\n" > + read -p "Enable hcsecd? [yes]: " _r > + case "${_r}" in > + no|n|NO|N|No|nO) ;; > + *) /usr/sbin/service hcsecd enable;; > + esac > fi > + > secd_config=$( /usr/sbin/sysrc -n hcsecd_config ) > -secd_entries=$( /usr/bin/grep -Eo "bdaddr[[:space:]]+(${bdaddress}|${bdname})" ${secd_config} | awk '{ print $2; }' ) > +secd_entries=$( /usr/bin/grep -Eo "bdaddr[[:space:]]+(${bdaddress}|${bdname})" \ > + ${secd_config} | awk '{ print $2; }' ) > > if [ "${secd_entries}" ]; then > - printf "\nWarning: An entry for device %s is already present in %s.\n" ${secd_entries} ${secd_config} > - printf "To modify pairing information, edit this file and run\n service hcsecd restart\n" > - read -p "Continue? [yes]: " REPLY > - case "${REPLY}" in no|n|NO|N|No|nO) exit;; esac > + printf "\nWarning: An entry for device %s is already present in %s.\n" \ > + ${secd_entries} ${secd_config} > + printf "To modify pairing information, edit this file and run\n" > + printf " service hcsecd restart\n" > + read -p "Continue? [yes]: " _r > + case "${_r}" in no|n|NO|N|No|nO) exit;; esac > else > - printf "\nWriting pairing information description block to %s.\n" ${secd_config} > - printf "(To get PIN, put device in pairing mode first.)\n" > - read -p "Enter PIN [nopin]: " pin > - [ "${pin}" ] && pin=\""${pin}"\" || pin="nopin" > + printf "\nWriting pairing information description block to %s.\n" \ > + ${secd_config} > + printf "(To get PIN, put device in pairing mode first.)\n" > + read -p "Enter PIN [nopin]: " pin > + [ "${pin}" ] && pin=\""${pin}"\" || pin="nopin" > > - # Write out new hcsecd config block > - printf "\ndevice {\n\tbdaddr\t%s;\n\tname\t\"%s\";\n\tkey\tnokey\;\n\tpin\t%s\;\n}\n" \ > - "${bdaddress}" "${friendlyname}" "${pin}" >> ${secd_config} > + # Write out new hcsecd config block > + printf "\ndevice {\n\tbdaddr\t%s;\n\tname\t\"%s\";\n\tkey\tnokey\;\n\tpin\t%s\;\n}\n" \ > + "${bdaddress}" "${friendlyname}" "${pin}" >> ${secd_config} > > - # ... and make daemon reload config, TODO: hcsecd should provide a reload hook > - /usr/sbin/service hcsecd restart > + # ... and make daemon reload config > + # TODO: hcsecd should provide a reload hook > + /usr/sbin/service hcsecd onerestart > > - # TODO: we should check if hcsecd succeeded pairing and revert to an old version > - # of hcsecd.conf so we can undo adding the block above and retry with a new PIN > - # also, if there's a way to force devices to re-pair, try this > + # TODO: we should check if hcsecd succeeded pairing and revert to an > + # old version of hcsecd.conf so we can undo adding the block above and > + # retry with a new PIN > + # also, if there's a way to force devices to re-pair, try this > fi > > # now check for specific services to be provided by the device > # first up: HID > > -if /usr/sbin/sdpcontrol -a "${bdaddress}" search HID | \ > - /usr/bin/grep -q "^Record Handle: "; then > +/usr/sbin/sdpcontrol -a "${bdaddress}" search HID | \ > + /usr/bin/grep -q "^Record Handle: " || exit 0 > > - printf "\nThis device provides human interface device services.\n" > - read -p "Set it up? [yes]: " REPLY > - case "${REPLY}" in no|n|NO|N|No|nO) ;; > - *) > - if ! /usr/sbin/service bthidd enabled; then > - printf "\nWarning: bthidd is not enabled." > - printf "\nThis daemon manages Bluetooth HID devices.\n" > - read -p "Enable bthidd? [yes]: " REPLY > - case "${REPLY}" in no|n|NO|N|No|nO) ;; *) /usr/sbin/sysrc bthidd_enable="YES";; esac > - fi > +printf "\nThis device provides human interface device services.\n" > +read -p "Set it up? [yes]: " _r > +case "${_r}" in > + no|n|NO|N|No|nO) exit 0;; > + *);; > +esac > > - # Check if bthidd already knows about this device > - bthidd_known=$( /usr/sbin/bthidcontrol -a "${bdaddress}" known | \ > - /usr/bin/grep "${bdaddress}" ) > - if [ "${bthidd_known}" ]; then > - printf "Notice: Device %s already known to bthidd.\n" "${bdaddress}" > - else > - bthidd_config=$( /usr/sbin/sysrc -n bthidd_config ) > - printf "Writing HID descriptor block to %s ... " "${bthidd_config}" > - /usr/sbin/bthidcontrol -a "${bdaddress}" query >> "${bthidd_config}" > +# Here we have found an HID and were asked to set it up > +# NOTE: look out for the two exit 0 above if you extend this script > > - # Re-read config to see if we succeeded adding the device > - bthidd_known=$( /usr/sbin/bthidcontrol -a "${bdaddress}" known | \ > - grep "${bdaddress}" ) > - if ! [ "${bthidd_known}" ]; then > - printf "failed.\n" > - else > - printf "success.\nTo re-read its config, bthidd must be restarted.\n" > - printf "Warning: If a Bluetooth keyboard is being used, the connection might be lost.\n" > - printf "It can be manually restarted later with\n service bthidd restart\n" > - read -p "Restart bthidd now? [yes]: " REPLY > - case "${REPLY}" in no|n|NO|N|No|nO) ;; *) /usr/sbin/service bthidd restart;; esac > - fi > - fi > - ;; > - esac > +if ! /usr/sbin/service bthidd enabled; then > + printf "\nWarning: bthidd is not enabled." > + printf "\nThis daemon manages Bluetooth HID devices.\n" > + read -p "Enable bthidd? [yes]: " _r > + case "${_r}" in > + no|n|NO|N|No|nO) ;; > + *) /usr/sbin/service bthidd enable;; > + esac > fi > > +# Check if bthidd already knows about this device > +bthidd_known=$( /usr/sbin/bthidcontrol -a "${bdaddress}" known | \ > + /usr/bin/grep "${bdaddress}" ) > + > +if [ "${bthidd_known}" ]; then > + printf "Notice: Device %s already known to bthidd.\n" "${bdaddress}" > + return 0 > +fi > + > +bthidd_config=$( /usr/sbin/sysrc -n bthidd_config ) > +printf "Writing HID descriptor block to %s ... " "${bthidd_config}" > +/usr/sbin/bthidcontrol -a "${bdaddress}" query >> "${bthidd_config}" > + > +# Re-read config to see if we succeeded adding the device > +bthidd_known=$( /usr/sbin/bthidcontrol -a "${bdaddress}" known | \ > + grep "${bdaddress}" ) > +if ! [ "${bthidd_known}" ]; then > + printf "failed.\n" > +else > + printf "success.\nTo re-read its config, bthidd must be restarted.\n" > + printf "Warning: If a Bluetooth keyboard is being used, the connection" > + printf "might be lost.\n" > + printf "It can be manually restarted later with\n" > + printf " service bthidd restart\n" > + read -p "Restart bthidd now? [yes]: " _r > + case "${_r}" in > + no|n|NO|N|No|nO) ;; > + *) /usr/sbin/service bthidd onerestart;; > + esac > +fi > + > } > > # After function definitions, main() can use them > main "$@" > - > -exit > +exit 0 > > # TODO > # * If device is a keyboard, offer a text entry test field and if it does > > -- Rod Grimes rgrimes@freebsd.org
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201901141632.x0EGWFud035793>