123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263 |
- #!/usr/bin/python
- # -*- coding: utf-8 -*-
- # Copyright (c) 2007 Johannes Hölzl <johannes.hoelzl@gmx.de>
- #
- # This library is covered by the GNU LGPL, read LICENSE for details.
- """\
- Provides access to the EEPROM of a Silabs CP210x. The data can be directly
- read from or written to the device.
- """
- __author__ = "Johannes Hölzl <johannes.hoelzl@gmx.de>"
- __license__ = "GNU LGPL"
- __version__ = "1.0"
- import sys
- import re
- import string
- import traceback
- import optparse
- from cp210x import valuefile, cp210x
- from cp210x.eeprom import EEPROM, HexFileError
- from cp210x.valuefile import read_baudrate_info, update_values, ValuesFileError
- TRANS_UNDERSCORE = string.maketrans('_', '-')
-
- ERR_OK = 0
- ERR_WRONG_INPUT = -1
- ERR_INTERNAL = -2
- ERR_DEVICE_LOCKED = -3
- ERR_DEVICE_NOT_FOUND = -4
- ERR_DEVICE_ERROR = -5
- ERR_OTHER = -100
- def error(message, retval=-1):
- sys.stderr.write(message + "\n")
- sys.exit(retval)
-
- class Option(optparse.Option):
- TYPES = list(optparse.Option.TYPES)
- TYPE_CHECKER = dict(optparse.Option.TYPE_CHECKER)
- for type, (reader, _) in valuefile.TYPES.items():
- if type in TYPES:
- continue
- TYPES.append(type)
- def checker(self, name, value, reader=reader):
- try:
- return reader(value)
- except ValueError, err:
- raise optparse.OptionValueError("option %s: %s" % (name,
- str(err)))
- TYPE_CHECKER[type] = checker
-
- class OptionParser(optparse.OptionParser):
- def error(self, msg):
- error(msg, ERR_WRONG_INPUT)
- def __init__(self, *args, **kwargs):
- if 'option_class' not in kwargs:
- kwargs['option_class'] = Option
- optparse.OptionParser.__init__(self, *args, **kwargs)
-
- def input_file(arg):
- if arg is None or arg == '-':
- return sys.stdin
- else:
- return file(arg, 'rb')
- def output_file(arg):
- if arg is None or arg == '-':
- return sys.stdout
- else:
- return file(arg, 'wb')
- def options_to_values(options):
- values = {}
- for name, type in cp210x.VALUES:
- if name == "baudrate_table":
- continue
- value = getattr(options, name)
- if value is not None:
- values[name] = value
-
- if options.baudrate_table:
- baudrate_table = []
- for s in options.baudrate_table:
- try:
- baudrate, info = s.split(':')
- except TypeError:
- error("option --set-baudrate: need two parts separated by ':'",
- ERR_WRONG_INPUT)
- try:
- baudrate_table.append(read_baudrate_info(info) +
- (int(baudrate), ))
- except ValueError, err:
- error("option --set-baudrate: %s" % str(err),
- ERR_WRONG_INPUT)
-
- values['baudrate_table'] = baudrate_table
- return values
- def find_device(patterns):
- usb_patterns = []
- for pattern in patterns:
- if ':' in pattern:
- try:
- vidString, pidString = pattern.split(':')
- vid = int(vidString, 16)
- pid = int(pidString, 16)
-
- except (TypeError, ValueError):
- error("Match be either 'ddd/ddd' or 'hhhh:hhhh'.",
- ERR_WRONG_INPUT)
-
- usb_patterns.append(dict(idVendor=vid, idProduct=pid))
- elif '/' in pattern:
- try:
- busString, addressString = pattern.split('/')
- bus = int(busString)
- address = int(addressString)
- except (TypeError, ValueError):
- error("Match be either 'ddd/ddd' or 'hhhh:hhhh'.",
- ERR_WRONG_INPUT)
- usb_patterns.append(dict(bus=bus, address=address))
- else:
- error("Match be either 'ddd/ddd' or 'hhhh:hhhh'.",
- ERR_WRONG_INPUT)
-
- for dev in cp210x.Cp210xProgrammer.list_devices(usb_patterns):
- return dev
- error("No devices found", ERR_DEVICE_NOT_FOUND)
-
- def read_cp210x(options):
- usbdev = find_device(options.match)
- dev = cp210x.Cp210xProgrammer(usbdev)
- eeprom = EEPROM(dev)
-
- if options.hex_output:
- eeprom.write_hex_file(output_file(options.hex_output))
- if options.ini_output or not options.hex_output:
- valuefile.write_file(output_file(options.ini_output), eeprom.get_values())
- def write_cp210x(options):
- usbdev = find_device(options.match)
- dev = cp210x.Cp210xProgrammer(usbdev)
- if options.hex_input or options.force_eeprom:
-
- if options.hex_input:
- eeprom = EEPROM(input_file(options.hex_input))
- else:
- eeprom = EEPROM(dev)
-
- values = eeprom.get_values()
- if options.ini_input:
- values = valuefile.read_file(input_file(options.ini_input))
- update_values(values, options_to_values(options), eeprom)
-
- eeprom.set_values(values)
-
- eeprom.write_to_cp210x(dev)
- else:
- if options.ini_input:
- values = valuefile.read_file(input_file(options.ini_input))
- else:
- values = {}
- update_values(values, options_to_values(options), dev)
- dev.set_values(values)
-
- if options.reset_device:
- dev.reset()
- def change_hexfile(options):
- eeprom = EEPROM(input_file(options.hex_input))
- values = {}
- if options.ini_input:
- update_values(values,
- valuefile.read_file(input_file(options.ini_input)),
- eeprom)
- update_values(values, options_to_values(options), eeprom)
- eeprom.set_values(values)
- if options.ini_output:
- valuefile.write_file(output_file(options.ini_output),
- eeprom.get_values())
- eeprom.write_hex_file(output_file(options.hex_output))
-
- def parse_hexfile(options):
- eeprom = EEPROM(input_file(options.hex_input))
- valuefile.write_file(output_file(options.ini_output), eeprom.get_values())
-
- parser = OptionParser(version=__version__, description=__doc__)
- parser.add_option("-r", "--read-cp210x", const=read_cp210x,
- dest="action", action="store_const")
- parser.add_option("-w", "--write-cp210x", const=write_cp210x,
- dest="action", action="store_const")
- parser.add_option("-c", "--change-hexfile", const=change_hexfile,
- dest="action", action="store_const")
- parser.add_option("-p", "--parse-hexfile", const=parse_hexfile,
- dest="action", action="store_const")
- parser.add_option("-F", "--hex-input", metavar="FILE")
- parser.add_option("-f", "--hex-output", metavar="FILE")
- parser.add_option("-I", "--ini-input", metavar="FILE")
- parser.add_option("-i", "--ini-output", metavar="FILE")
- for name, type in cp210x.VALUES:
- if name == 'baudrate_table':
- continue
- parser.add_option("--set-" + name.translate(TRANS_UNDERSCORE),
- dest=name, metavar=name.upper(), type=type)
- parser.add_option("--set-baudrate", action="append", dest="baudrate_table")
- parser.add_option("-m", "--match", action="append", metavar="PATTERN")
- parser.add_option("--reset-device", action="store_true")
- parser.add_option("--force-eeprom", action="store_true")
- parser.set_defaults(
- action=read_cp210x,
- hex_input=None,
- hex_output=None,
- ini_input=None,
- ini_output=None,
- match=[],
- baudrate_table=[],
- reset_device=False,
- force_eeprom=False,
- )
- def main():
- (options, _) = parser.parse_args()
- if not options.match:
- options.match = ['10C4:EA60', '10C4:EA61']
- options.action(options)
- if __name__ == '__main__':
- try:
- main()
-
- except cp210x.DeviceLocked:
- error("Can not write data to device. Device is locked.",
- ERR_DEVICE_LOCKED)
- except cp210x.Cp210xError, err:
- error(str(err), ERR_DEVICE_ERROR)
- except IOError, err:
- error(str(err), ERR_OTHER)
- except HexFileError, err:
- error(str(err), ERR_OTHER)
-
- except ValuesFileError, err:
- error(str(err), ERR_OTHER)
- except SystemExit, err:
- raise
- except:
- traceback.print_exc()
- sys.exit(ERR_INTERNAL)
-
|