reform

MNT Reform: Open Source Portable Computer
Log (Feed) | Files | Refs (Tags) | README

flash.sh (4581B)


      1 #!/bin/sh
      2 
      3 set -eu
      4 
      5 if [ ! -e ./keyboard.hex ]; then
      6 	echo "keyboard.hex doesn't exist. build it or use ./download-fw.sh to download it." >&2
      7 	exit 1
      8 fi
      9 
     10 if [ "$(id -u)" -ne 0 ]; then
     11 	echo "you need to run this as root (for example by using sudo)" >&2
     12 	exit 1
     13 fi
     14 
     15 get_property() {
     16 	path="$1"
     17 	property="$2"
     18 	if [ "$(udevadm --version)" -lt 250 ]; then
     19 		# no udevadm --property before version 250
     20 		udevadm info --query=property "$path" | sed -ne "s/^$property=//p"
     21 	else
     22 		udevadm info --query=property --property="$property" --value "$path"
     23 	fi
     24 }
     25 
     26 find_usb_device() {
     27 	result=
     28 	for p in /sys/bus/usb/devices/*; do
     29 		[ -e "$p/idVendor" ] || continue
     30 		[ "$(cat "$p/idVendor")" = "$1" ] || continue
     31 		[ -e "$p/idProduct" ] || continue
     32 		[ "$(cat "$p/idProduct")" = "$2" ] || continue
     33 		[ "$(get_property "$p" "ID_MODEL")" = "$3" ] || continue
     34 		if [ -n "$result" ]; then
     35 			echo "found more than one device matching $1 $2 $3" >&2
     36 			exit 1
     37 		fi
     38 		result="$(realpath -e "$p")"
     39 	done
     40 	echo "$result"
     41 }
     42 
     43 remove_prefix_char() {
     44 	result="$1"
     45 	char="$2"
     46 	while :; do
     47 		case $result in
     48 			"$char"*) result=${result#"$char"};;
     49 			*) break;;
     50 		esac
     51 	done
     52 	echo "$result"
     53 }
     54 
     55 path_keyboard=$(find_usb_device 03eb 2042 Reform_Keyboard)
     56 
     57 busnum_keyboard=
     58 devnum_keyboard=
     59 if [ -n "$path_keyboard" ] && [ -e "$path_keyboard" ]; then
     60 	busnum_keyboard="$(get_property "$path_keyboard" "BUSNUM")"
     61 	devnum_keyboard="$(get_property "$path_keyboard" "DEVNUM")"
     62 	echo " 1. Find out your keyboard firmware version in the 'System Status' by pressing" >&2
     63 	echo "    the circle key followed by the S key. The keyboard firmware version is on" >&2
     64 	echo "    on the last line in a date-based format YYYYMMDD. Then either:"
     65 	echo >&2
     66 	echo " 2.A. If you are on keyboard firmware version 20231124 or newer:" >&2
     67 	echo >&2
     68 	echo "       2.A.1. Press the circle key followed by the X key to enter firmware update mode." >&2
     69 	echo >&2
     70 	echo " 2.B. If you are on keyboard firmware version older than 20231124:" >&2
     71 	echo >&2
     72 	echo "       2.B.1. Toggle the programming DIP switch SW84 on the keyboard to “ON”." >&2
     73 	echo "       2.B.2. Press the reset button SW83." >&2
     74 	echo >&2
     75 	echo "    ATTENTION: Do not remove the keyboard bezel without having disconnected" >&2
     76 	echo "               both battery boards first. If you don't want to remove the" >&2
     77 	echo "               bezel you can reach both the programming DIP switch as well" >&2
     78 	echo "               as the reset button with a non-conductive thin stick (like" >&2
     79 	echo "               a wooden toothpick) behind the F4 key." >&2
     80 	echo >&2
     81 	if [ "$(udevadm --version)" -lt 251 ]; then
     82 		# no udevadm wait before version 251
     83 		echo " 3. Press the Enter key once you are ready" >&2
     84 		# shellcheck disable=SC2034
     85 		read -r enter
     86 	else
     87 		echo " 3. Waiting for the keyboard to disappear..." >&2
     88 		udevadm wait --removed "$path_keyboard"
     89 		echo " 4. Waiting for the Atmel DFU bootloader USB device to appear..." >&2
     90 		udevadm wait --settle "$path_keyboard"
     91 	fi
     92 fi
     93 
     94 path=$(find_usb_device 03eb 2ff4 ATm32U4DFU)
     95 if [ -z "$path" ] || [ ! -e "$path" ]; then
     96 	echo "cannot find Atmel DFU bootloader USB device" >&2
     97 	exit 1
     98 fi
     99 
    100 busnum="$(get_property "$path" "BUSNUM")"
    101 devnum="$(get_property "$path" "DEVNUM")"
    102 
    103 # do some extra checks if we saw the usb device as a keyboard before
    104 if [ -n "$path_keyboard" ] && [ -e "$path_keyboard" ]; then
    105 	if [ "$path_keyboard" != "$path" ]; then
    106 		echo "path of Atmel DFU bootloader USB device is different from the keyboard" >&2
    107 		exit 1
    108 	fi
    109 	if [ "$busnum_keyboard" != "$busnum" ]; then
    110 		echo "busnum of Atmel DFU bootloader USB device is different from the keyboard" >&2
    111 		exit 1
    112 	fi
    113 	# the devnum of the atmel increments by 1 on every press of the reset
    114 	# button (why?), so no sense comparing those
    115 	#if [ "$((devnum_keyboard+1))" != "$devnum" ]; then
    116 	#	echo "devnum of Atmel DFU bootloader USB device is different from the keyboard" >&2
    117 	#	exit 1
    118 	#fi
    119 fi
    120 
    121 device="atmega32u4:$(remove_prefix_char "$busnum" 0),$(remove_prefix_char "$devnum" 0)"
    122 
    123 dfu-programmer "$device" erase --suppress-bootloader-mem
    124 
    125 dfu-programmer "$device" flash ./keyboard.hex --suppress-bootloader-mem
    126 
    127 dfu-programmer "$device" start
    128 
    129 if [ "$(udevadm --version)" -ge 251 ]; then
    130 	echo "Waiting for the Atmel DFU bootloader USB device to disappear..." >&2
    131 	udevadm wait --removed "$path"
    132 	echo "Waiting for the keyboard to re-appear..." >&2
    133 	udevadm wait --settle "$path"
    134 fi
    135 
    136 echo "All done!" >&2
    137 echo >&2
    138 echo "If you were on an old firmware, don't forget to toggle the programming DIP switch SW84 on the keyboard to “OFF” again" >&2