program 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  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 usb
  21. def checkForKeyboardInNormalMode():
  22. """Returns a device if a ps2avrGB device in normal made (that is in keyboard mode) or None if it is not found."""
  23. return usb.core.find(idVendor=0x20A0, idProduct=0x422D)
  24. def checkForKeyboardInBootloaderMode():
  25. """Returns True if a ps2avrGB device in bootloader (flashable) mode is found and False otherwise."""
  26. return (usb.core.find(idVendor=0x16c0, idProduct=0x05df) is not None)
  27. def flashKeyboard(firmware_file):
  28. """Calls bootloadHID to flash the given file to the device."""
  29. print('Flashing firmware to device ...')
  30. if os.system('bootloadHID -r "%s"' % firmware_file) == 0:
  31. print('\nDone!')
  32. else:
  33. print('\nbootloadHID returned an error.')
  34. def printDeviceInfo(dev):
  35. """Prints all infos for a given USB device"""
  36. print('Device Information:')
  37. print(' idVendor: %d (0x%04x)' % (dev.idVendor, dev.idVendor))
  38. print(' idProduct: %d (0x%04x)' % (dev.idProduct, dev.idProduct))
  39. print('Manufacturer: %s' % (dev.iManufacturer))
  40. print('Serial: %s' % (dev.iSerialNumber))
  41. print('Product: %s' % (dev.iProduct), end='\n\n')
  42. def sendDeviceToBootloaderMode(dev):
  43. """Tries to send a given ps2avrGB keyboard to bootloader mode to allow flashing."""
  44. try:
  45. dev.set_configuration()
  46. request_type = usb.util.build_request_type(
  47. usb.util.CTRL_OUT,
  48. usb.util.CTRL_TYPE_CLASS,
  49. usb.util.CTRL_RECIPIENT_DEVICE)
  50. USBRQ_HID_SET_REPORT = 0x09
  51. HID_REPORT_OPTION = 0x0301
  52. dev.ctrl_transfer(request_type, USBRQ_HID_SET_REPORT, HID_REPORT_OPTION, 0, [0, 0, 0xFF] + [0] * 5)
  53. except usb.core.USBError:
  54. # for some reason I keep getting USBError, but it works!
  55. pass
  56. if len(sys.argv) < 2:
  57. print('Usage: %s <firmware.hex>' % sys.argv[0])
  58. sys.exit(1)
  59. kb = checkForKeyboardInNormalMode()
  60. if kb is not None:
  61. print('Found a keyboad in normal mode. Attempting to send it to bootloader mode ...', end='')
  62. sendDeviceToBootloaderMode(kb)
  63. print(' done.')
  64. print("Hint: If your keyboard can't be set to bootloader mode automatically, plug it in while pressing left control to do so manually.")
  65. attempts = 12 # 60 seconds
  66. found = False
  67. for attempt in range(1, attempts + 1):
  68. print("Searching for keyboard in bootloader mode (%i/%i) ... " % (attempt, attempts), end='')
  69. if checkForKeyboardInBootloaderMode():
  70. print('Found', end='\n\n')
  71. flashKeyboard(sys.argv[1])
  72. found = True
  73. break
  74. else:
  75. print('Nothing.', end='')
  76. if attempt != attempts: # no need to wait on the last attempt
  77. print(' Sleeping 5 seconds.', end='')
  78. time.sleep(5)
  79. # print a newline
  80. print()
  81. if not found:
  82. print("Couldn't find a flashable keyboard. Aborting.")
  83. sys.exit(2)