2017-11-17 11:40:34 -05:00
#!/usr/bin/env python
# Copyright 2017 Luiz Ribeiro <luizribeiro@gmail.com>, Sebastian Kaim <sebb@sebb767.de>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import print_function
import os
import sys
import time
import usb
def checkForKeyboardInNormalMode ( ) :
""" Returns a device if a ps2avrGB device in normal made (that is in keyboard mode) or None if it is not found. """
return usb . core . find ( idVendor = 0x20A0 , idProduct = 0x422D )
def checkForKeyboardInBootloaderMode ( ) :
""" Returns True if a ps2avrGB device in bootloader (flashable) mode is found and False otherwise. """
return ( usb . core . find ( idVendor = 0x16c0 , idProduct = 0x05df ) is not None )
def flashKeyboard ( firmware_file ) :
""" Calls bootloadHID to flash the given file to the device. """
print ( ' Flashing firmware to device ... ' )
if os . system ( ' bootloadHID -r " %s " ' % firmware_file ) == 0 :
print ( ' \n Done! ' )
else :
print ( ' \n bootloadHID returned an error. ' )
def printDeviceInfo ( dev ) :
""" Prints all infos for a given USB device """
print ( ' Device Information: ' )
print ( ' idVendor: %d (0x %04x ) ' % ( dev . idVendor , dev . idVendor ) )
print ( ' idProduct: %d (0x %04x ) ' % ( dev . idProduct , dev . idProduct ) )
print ( ' Manufacturer: %s ' % ( dev . iManufacturer ) )
print ( ' Serial: %s ' % ( dev . iSerialNumber ) )
print ( ' Product: %s ' % ( dev . iProduct ) , end = ' \n \n ' )
def sendDeviceToBootloaderMode ( dev ) :
""" Tries to send a given ps2avrGB keyboard to bootloader mode to allow flashing. """
try :
dev . set_configuration ( )
request_type = usb . util . build_request_type (
usb . util . CTRL_OUT ,
usb . util . CTRL_TYPE_CLASS ,
usb . util . CTRL_RECIPIENT_DEVICE )
USBRQ_HID_SET_REPORT = 0x09
HID_REPORT_OPTION = 0x0301
dev . ctrl_transfer ( request_type , USBRQ_HID_SET_REPORT , HID_REPORT_OPTION , 0 , [ 0 , 0 , 0xFF ] + [ 0 ] * 5 )
except usb . core . USBError :
# for some reason I keep getting USBError, but it works!
pass
if len ( sys . argv ) < 2 :
print ( ' Usage: %s <firmware.hex> ' % sys . argv [ 0 ] )
sys . exit ( 1 )
kb = checkForKeyboardInNormalMode ( )
if kb is not None :
2018-04-20 02:28:55 +10:00
print ( ' Found a keyboard in normal mode. Attempting to send it to bootloader mode ... ' , end = ' ' )
2017-11-17 11:40:34 -05:00
sendDeviceToBootloaderMode ( kb )
print ( ' done. ' )
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. " )
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 " )
attempts = 12 # 60 seconds
found = False
for attempt in range ( 1 , attempts + 1 ) :
print ( " Searching for keyboard in bootloader mode ( %i / %i ) ... " % ( attempt , attempts ) , end = ' ' )
if checkForKeyboardInBootloaderMode ( ) :
print ( ' Found ' , end = ' \n \n ' )
flashKeyboard ( sys . argv [ 1 ] )
found = True
break
else :
print ( ' Nothing. ' , end = ' ' )
if attempt != attempts : # no need to wait on the last attempt
print ( ' Sleeping 5 seconds. ' , end = ' ' )
time . sleep ( 5 )
# print a newline
print ( )
if not found :
print ( " Couldn ' t find a flashable keyboard. Aborting. " )
sys . exit ( 2 )