abschlussarbeit/_trash/bin/ftconf.py

194 lines
8 KiB
Python
Executable file

#!/home/pi/git/abschlussarbeit/bin/python3
"""Simple FTDI EEPROM configurator.
"""
# Copyright (c) 2019-2024, Emmanuel Blot <emmanuel.blot@free.fr>
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
from argparse import ArgumentParser, FileType
from io import StringIO
from logging import Formatter, StreamHandler, DEBUG, ERROR
from sys import exit as sys_exit, modules, stderr, stdout
from textwrap import fill
from traceback import format_exc
from pyftdi import FtdiLogger
from pyftdi.eeprom import FtdiEeprom
from pyftdi.ftdi import Ftdi
from pyftdi.misc import add_custom_devices, hexdump
# pylint: disable=too-many-locals
# pylint: disable=too-many-branches
# pylint: disable=too-many-statements
def main():
"""Main routine"""
debug = False
try:
argparser = ArgumentParser(description=modules[__name__].__doc__)
argparser.add_argument('device', nargs='?', default='ftdi:///?',
help='serial port device name')
files = argparser.add_argument_group(title='Files')
files.add_argument('-i', '--input', type=FileType('rt'),
help='input ini file to load EEPROM content')
files.add_argument('-l', '--load', default='all',
choices=('all', 'raw', 'values'),
help='section(s) to load from input file')
files.add_argument('-o', '--output',
help='output ini file to save EEPROM content')
files.add_argument('-V', '--virtual', type=FileType('r'),
help='use a virtual device, specified as YaML')
device = argparser.add_argument_group(title='Device')
device.add_argument('-P', '--vidpid', action='append',
help='specify a custom VID:PID device ID '
'(search for FTDI devices)')
device.add_argument('-M', '--eeprom',
help='force an EEPROM model')
device.add_argument('-S', '--size', type=int,
choices=FtdiEeprom.eeprom_sizes,
help='force an EEPROM size')
fmt = argparser.add_argument_group(title='Format')
fmt.add_argument('-x', '--hexdump', action='store_true',
help='dump EEPROM content as ASCII')
fmt.add_argument('-X', '--hexblock', type=int,
help='dump EEPROM as indented hexa blocks')
config = argparser.add_argument_group(title='Configuration')
config.add_argument('-s', '--serial-number',
help='set serial number')
config.add_argument('-m', '--manufacturer',
help='set manufacturer name')
config.add_argument('-p', '--product',
help='set product name')
config.add_argument('-c', '--config', action='append',
help='change/configure a property as key=value '
'pair')
config.add_argument('--vid', type=lambda x: int(x, 16),
help='shortcut to configure the USB vendor ID')
config.add_argument('--pid', type=lambda x: int(x, 16),
help='shortcut to configure the USB product ID')
action = argparser.add_argument_group(title='Action')
action.add_argument('-e', '--erase', action='store_true',
help='erase the whole EEPROM content')
action.add_argument('-E', '--full-erase', action='store_true',
default=False,
help='erase the whole EEPROM content, including '
'the CRC')
action.add_argument('-u', '--update', action='store_true',
help='perform actual update, use w/ care')
extra = argparser.add_argument_group(title='Extras')
extra.add_argument('-v', '--verbose', action='count', default=0,
help='increase verbosity')
extra.add_argument('-d', '--debug', action='store_true',
help='enable debug mode')
args = argparser.parse_args()
debug = args.debug
if not args.device:
argparser.error('Serial device not specified')
loglevel = max(DEBUG, ERROR - (10 * args.verbose))
loglevel = min(ERROR, loglevel)
if debug:
formatter = Formatter('%(asctime)s.%(msecs)03d %(name)-20s '
'%(message)s', '%H:%M:%S')
else:
formatter = Formatter('%(message)s')
FtdiLogger.set_formatter(formatter)
FtdiLogger.set_level(loglevel)
FtdiLogger.log.addHandler(StreamHandler(stderr))
if args.virtual:
# pylint: disable=import-outside-toplevel
from pyftdi.usbtools import UsbTools
# Force PyUSB to use PyFtdi test framework for USB backends
UsbTools.BACKENDS = ('pyftdi.tests.backend.usbvirt', )
# Ensure the virtual backend can be found and is loaded
backend = UsbTools.find_backend()
loader = backend.create_loader()()
loader.load(args.virtual)
try:
add_custom_devices(Ftdi, args.vidpid, force_hex=True)
except ValueError as exc:
argparser.error(str(exc))
eeprom = FtdiEeprom()
eeprom.open(args.device, size=args.size, model=args.eeprom)
if args.erase or args.full_erase:
eeprom.erase()
if args.input:
eeprom.load_config(args.input, args.load)
if args.serial_number:
eeprom.set_serial_number(args.serial_number)
if args.manufacturer:
eeprom.set_manufacturer_name(args.manufacturer)
if args.product:
eeprom.set_product_name(args.product)
for conf in args.config or []:
if conf in ('?', 'help'):
helpstr = ', '.join(sorted(eeprom.properties))
print(fill(helpstr, initial_indent=' ',
subsequent_indent=' '))
sys_exit(1)
for sep in ':=':
if sep in conf:
name, value = conf.split(sep, 1)
if not value:
argparser.error(f'Configuration {conf} without value')
if value == 'help':
value = '?'
helpio = StringIO()
eeprom.set_property(name, value, helpio)
helpstr = helpio.getvalue()
if helpstr:
print(fill(helpstr, initial_indent=' ',
subsequent_indent=' '))
sys_exit(1)
break
else:
argparser.error(f'Missing name:value separator in {conf}')
if args.vid:
eeprom.set_property('vendor_id', args.vid)
if args.pid:
eeprom.set_property('product_id', args.pid)
if args.hexdump:
print(hexdump(eeprom.data))
if args.hexblock is not None:
indent = ' ' * args.hexblock
for pos in range(0, len(eeprom.data), 16):
hexa = ' '.join([f'{x:02x}' for x in eeprom.data[pos:pos+16]])
print(indent, hexa, sep='')
if args.update:
if eeprom.commit(False, no_crc=args.full_erase):
eeprom.reset_device()
if args.verbose > 0:
eeprom.dump_config()
if args.output:
if args.output == '-':
eeprom.save_config(stdout)
else:
with open(args.output, 'wt') as ofp:
eeprom.save_config(ofp)
except (ImportError, IOError, NotImplementedError, ValueError) as exc:
print(f'\nError: {exc}', file=stderr)
if debug:
print(format_exc(chain=False), file=stderr)
sys_exit(1)
except KeyboardInterrupt:
sys_exit(2)
finally:
eeprom.close()
if __name__ == '__main__':
main()