atmega32a_program.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. #!/usr/bin/env python
  2. # Copyright 2017 Luiz Ribeiro <luizribeiro@gmail.com>, Sebastian Kaim <sebb@sebb767.de>
  3. #
  4. # This program is free software: you can redistribute it and/or modify
  5. # it under the terms of the GNU General Public License as published by
  6. # the Free Software Foundation, either version 2 of the License, or
  7. # (at your option) any later version.
  8. #
  9. # This program is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. # GNU General Public License for more details.
  13. #
  14. # You should have received a copy of the GNU General Public License
  15. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. from __future__ import print_function
  17. import os
  18. import sys
  19. import time
  20. import argparse
  21. import usb
  22. def check_keyboard_normal_mode(vendor, product):
  23. """Returns a device if a ps2avrGB device in normal made (that is in keyboard mode) or None if it is not found."""
  24. return usb.core.find(idVendor=vendor, idProduct=product)
  25. def check_keyboard_bootloader_mode():
  26. """Returns True if a ps2avrGB device in bootloader (flashable) mode is found and False otherwise."""
  27. return (usb.core.find(idVendor=0x16c0, idProduct=0x05df) is not None)
  28. def flash_keyboard(firmware_file):
  29. """Calls bootloadHID to flash the given file to the device."""
  30. print('Flashing firmware to device ...')
  31. if os.system('bootloadHID -r "%s"' % firmware_file) == 0:
  32. print('\nDone!')
  33. else:
  34. print('\nbootloadHID returned an error.')
  35. def print_device_info(dev):
  36. """Prints all infos for a given USB device"""
  37. print('Device Information:')
  38. print(' idVendor: %d (0x%04x)' % (dev.idVendor, dev.idVendor))
  39. print(' idProduct: %d (0x%04x)' % (dev.idProduct, dev.idProduct))
  40. print('Manufacturer: %s' % (dev.iManufacturer))
  41. print('Serial: %s' % (dev.iSerialNumber))
  42. print('Product: %s' % (dev.iProduct), end='\n\n')
  43. def send_device_to_bootloader_mode(dev):
  44. """Tries to send a given ps2avrGB keyboard to bootloader mode to allow flashing."""
  45. try:
  46. dev.set_configuration()
  47. request_type = usb.util.build_request_type(
  48. usb.util.CTRL_OUT,
  49. usb.util.CTRL_TYPE_CLASS,
  50. usb.util.CTRL_RECIPIENT_DEVICE)
  51. USBRQ_HID_SET_REPORT = 0x09
  52. HID_REPORT_OPTION = 0x0301
  53. dev.ctrl_transfer(request_type, USBRQ_HID_SET_REPORT, HID_REPORT_OPTION, 0, [0, 0, 0xFF] + [0] * 5)
  54. except usb.core.USBError:
  55. # for some reason I keep getting USBError, but it works!
  56. pass
  57. def auto_int(value):
  58. """Helper for argparse to enable auto base detection"""
  59. return int(value, 0)
  60. parser = argparse.ArgumentParser(description='Flash bootloadHID device')
  61. parser.add_argument('--vendor', type=auto_int, default=0x20A0, help='Non bootloader idVendor to search for (default: 0x%(default)04x)')
  62. parser.add_argument('--product', type=auto_int, default=0x422D, help='Non bootloader idProduct to search for (default: 0x%(default)04x)')
  63. parser.add_argument('firmware_hex', type=argparse.FileType('r'), help='Firmware hex file to flash')
  64. args = parser.parse_args()
  65. kb = check_keyboard_normal_mode(args.vendor, args.product)
  66. if kb is not None:
  67. print('Found a keyboard in normal mode. Attempting to send it to bootloader mode ...', end='')
  68. send_device_to_bootloader_mode(kb)
  69. print(' done.')
  70. print("Hint: If your keyboard can't be set to bootloader mode automatically, plug it in while pressing the bootloader key to do so manually.")
  71. print(" You can find more infos about this here: https://github.com/qmk/qmk_firmware/tree/master/keyboards/ps2avrGB#setting-the-board-to-bootloader-mode")
  72. attempts = 12 # 60 seconds
  73. found = False
  74. for attempt in range(1, attempts + 1):
  75. print("Searching for keyboard in bootloader mode (%i/%i) ... " % (attempt, attempts), end='')
  76. if check_keyboard_bootloader_mode():
  77. print('Found', end='\n\n')
  78. flash_keyboard(args.firmware_hex.name)
  79. found = True
  80. break
  81. else:
  82. print('Nothing.', end='')
  83. if attempt != attempts: # no need to wait on the last attempt
  84. print(' Sleeping 5 seconds.', end='')
  85. time.sleep(5)
  86. # print a newline
  87. print()
  88. if not found:
  89. print("Couldn't find a flashable keyboard. Aborting.")
  90. sys.exit(2)