update.py 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. # greaseweazle/tools/update.py
  2. #
  3. # Greaseweazle control script: Firmware Update.
  4. #
  5. # Written & released by Keir Fraser <keir.xen@gmail.com>
  6. #
  7. # This is free and unencumbered software released into the public domain.
  8. # See the file COPYING for more details, or visit <http://unlicense.org>.
  9. import sys, argparse, serial, struct, os
  10. import crcmod.predefined
  11. from greaseweazle.tools import util
  12. from greaseweazle import version
  13. from greaseweazle import usb as USB
  14. # update_firmware:
  15. # Updates the Greaseweazle firmware using the specified Update File.
  16. def update_firmware(usb, args):
  17. filename = args.file
  18. if filename == "auto":
  19. # Get the absolute path to the root Greaseweazle folder.
  20. path = os.path.dirname(os.path.abspath(__file__))
  21. for _ in range(3):
  22. path = os.path.join(path, os.pardir)
  23. path = os.path.normpath(path)
  24. filename = os.path.join(path, "Greaseweazle-v%d.%d.upd"
  25. % (version.major, version.minor))
  26. # Read the entire update catalogue.
  27. with open(filename, "rb") as f:
  28. dat = f.read()
  29. # Search the catalogue for a match on our Weazle's hardware type.
  30. while dat:
  31. upd_len, hw_type = struct.unpack("<2H", dat[:4])
  32. if hw_type == usb.hw_type:
  33. # Match: Pull out the embedded update file.
  34. dat = dat[4:upd_len+4]
  35. break
  36. # Skip to the next catalogue entry.
  37. dat = dat[upd_len+4:]
  38. if not dat:
  39. print("%s: No match for hardware type %x" % (filename, usb.hw_type))
  40. return
  41. # Check the matching update file's footer.
  42. sig, maj, min, hw_type = struct.unpack("<2s2BH", dat[-8:-2])
  43. if len(dat) & 3 != 0 or sig != b'GW' or hw_type != usb.hw_type:
  44. print("%s: Bad update file" % (filename))
  45. return
  46. crc16 = crcmod.predefined.Crc('crc-ccitt-false')
  47. crc16.update(dat)
  48. if crc16.crcValue != 0:
  49. print("%s: Bad CRC" % (filename))
  50. return
  51. # Perform the update.
  52. print("Updating to v%u.%u..." % (maj, min))
  53. ack = usb.update_firmware(dat)
  54. if ack != 0:
  55. print("** UPDATE FAILED: Please retry!")
  56. return
  57. print("Done.")
  58. if usb.hw_type == 7:
  59. util.usb_reopen(usb, is_update=False)
  60. else:
  61. print("** Disconnect Greaseweazle and remove the Programming Jumper.")
  62. def main(argv):
  63. parser = argparse.ArgumentParser(
  64. formatter_class=argparse.ArgumentDefaultsHelpFormatter)
  65. parser.add_argument("file", nargs="?", default="auto",
  66. help="update filename")
  67. parser.add_argument("device", nargs="?", default="auto",
  68. help="serial device")
  69. parser.prog += ' ' + argv[1]
  70. args = parser.parse_args(argv[2:])
  71. usb = util.usb_open(args.device, is_update=True)
  72. try:
  73. update_firmware(usb, args)
  74. except USB.CmdError as error:
  75. print("Command Failed: %s" % error)
  76. if __name__ == "__main__":
  77. main(sys.argv)
  78. # Local variables:
  79. # python-indent: 4
  80. # End: