Rename QK_TMK(_MAX) to QK_BASIC (#6509)
[jackhill/qmk/firmware.git] / util / atmega32a_program.py
CommitLineData
f2c32b3e
JH
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
17from __future__ import print_function
18
19import os
20import sys
21import time
0e88d756 22import argparse
f2c32b3e
JH
23import usb
24
25
0e88d756 26def check_keyboard_normal_mode(vendor, product):
f2c32b3e 27 """Returns a device if a ps2avrGB device in normal made (that is in keyboard mode) or None if it is not found."""
0e88d756 28 return usb.core.find(idVendor=vendor, idProduct=product)
f2c32b3e 29
0e88d756 30def check_keyboard_bootloader_mode():
f2c32b3e
JH
31 """Returns True if a ps2avrGB device in bootloader (flashable) mode is found and False otherwise."""
32 return (usb.core.find(idVendor=0x16c0, idProduct=0x05df) is not None)
33
0e88d756 34def flash_keyboard(firmware_file):
f2c32b3e
JH
35 """Calls bootloadHID to flash the given file to the device."""
36 print('Flashing firmware to device ...')
37 if os.system('bootloadHID -r "%s"' % firmware_file) == 0:
38 print('\nDone!')
39 else:
40 print('\nbootloadHID returned an error.')
41
0e88d756 42def print_device_info(dev):
f2c32b3e
JH
43 """Prints all infos for a given USB device"""
44 print('Device Information:')
6832a067 45 print(' idVendor: %d (0x%04x)' % (dev.idVendor, dev.idVendor))
46 print(' idProduct: %d (0x%04x)' % (dev.idProduct, dev.idProduct))
f2c32b3e
JH
47 print('Manufacturer: %s' % (dev.iManufacturer))
48 print('Serial: %s' % (dev.iSerialNumber))
49 print('Product: %s' % (dev.iProduct), end='\n\n')
50
0e88d756 51def send_device_to_bootloader_mode(dev):
f2c32b3e
JH
52 """Tries to send a given ps2avrGB keyboard to bootloader mode to allow flashing."""
53 try:
54 dev.set_configuration()
55
56 request_type = usb.util.build_request_type(
0e88d756 57 usb.util.CTRL_OUT,
58 usb.util.CTRL_TYPE_CLASS,
59 usb.util.CTRL_RECIPIENT_DEVICE)
f2c32b3e
JH
60
61 USBRQ_HID_SET_REPORT = 0x09
62 HID_REPORT_OPTION = 0x0301
63
64 dev.ctrl_transfer(request_type, USBRQ_HID_SET_REPORT, HID_REPORT_OPTION, 0, [0, 0, 0xFF] + [0] * 5)
65 except usb.core.USBError:
66 # for some reason I keep getting USBError, but it works!
67 pass
68
0e88d756 69def auto_int(value):
70 """Helper for argparse to enable auto base detection"""
71 return int(value, 0)
f2c32b3e 72
0e88d756 73parser = argparse.ArgumentParser(description='Flash bootloadHID device')
6832a067 74parser.add_argument('--vendor', type=auto_int, default=0x20A0, help='Non bootloader idVendor to search for (default: 0x%(default)04x)')
75parser.add_argument('--product', type=auto_int, default=0x422D, help='Non bootloader idProduct to search for (default: 0x%(default)04x)')
0e88d756 76parser.add_argument('firmware_hex', type=argparse.FileType('r'), help='Firmware hex file to flash')
77args = parser.parse_args()
f2c32b3e 78
0e88d756 79kb = check_keyboard_normal_mode(args.vendor, args.product)
f2c32b3e
JH
80
81if kb is not None:
d3c6da7a 82 print('Found a keyboard in normal mode. Attempting to send it to bootloader mode ...', end='')
0e88d756 83 send_device_to_bootloader_mode(kb)
f2c32b3e
JH
84 print(' done.')
85 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.")
86 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")
87
88attempts = 12 # 60 seconds
89found = False
90for attempt in range(1, attempts + 1):
91 print("Searching for keyboard in bootloader mode (%i/%i) ... " % (attempt, attempts), end='')
92
0e88d756 93 if check_keyboard_bootloader_mode():
f2c32b3e 94 print('Found', end='\n\n')
0e88d756 95 flash_keyboard(args.firmware_hex.name)
f2c32b3e
JH
96 found = True
97 break
98 else:
99 print('Nothing.', end='')
100
101 if attempt != attempts: # no need to wait on the last attempt
102 print(' Sleeping 5 seconds.', end='')
103 time.sleep(5)
104
105 # print a newline
106 print()
107
108if not found:
109 print("Couldn't find a flashable keyboard. Aborting.")
110 sys.exit(2)