#!/usr/bin/env python # # Razer device commandline configuration tool # # Copyright (C) 2007-2009 Michael Buesch # # 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. import sys import os import getopt import time from ConfigParser import * from pyrazer import * razer = None def getRazer(): global razer if razer is None: razer = Razer() return razer class Operation: def parseProfileValuePair(self, parameter, idstr): # Parse profile:value pair string. Default to active # profile, if not given. May raise ValueError. split = parameter.split(":") if len(split) == 1: profile = getRazer().getActiveProfile(idstr) + 1 value = int(split[0].strip()) elif len(split) == 2: profile = int(split[0].strip()) value = int(split[1].strip()) else: raise ValueError if profile < 1: raise ValueError return (profile, value) class OpSleep(Operation): def __init__(self, seconds): self.seconds = seconds def run(self, idstr): time.sleep(self.seconds) class OpGetFwVer(Operation): def run(self, idstr): verTuple = getRazer().getFwVer(idstr) print "%s: Firmware version %d.%d" %\ (idstr, verTuple[0], verTuple[1]) class OpGetFreq(Operation): def run(self, idstr): freqs = getRazer().getSupportedFreqs(idstr) profiles = getRazer().getProfiles(idstr) for profile in profiles: sys.stdout.write("Profile %2u: " % (profile + 1)) curFreq = getRazer().getCurrentFreq(idstr, profile) output = [] for freq in freqs: if freq == curFreq: output.append("*%u Hz" % freq) else: output.append(" %u Hz" % freq) print ", ".join(output) class OpGetRes(Operation): def run(self, idstr): mappings = getRazer().getSupportedDpiMappings(idstr) profiles = getRazer().getProfiles(idstr) for profile in profiles: sys.stdout.write("Profile %2u: " % (profile + 1)) curMapping = getRazer().getDpiMapping(idstr, profile) output = [] for mapping in mappings: if mapping[0] == curMapping: output.append("*%u (%u DPI)" % (mapping[0] + 1, mapping[1])) else: output.append(" %u (%u DPI)" % (mapping[0] + 1, mapping[1])) print ", ".join(output) class OpPrintLeds(Operation): def run(self, idstr): leds = getRazer().getLeds(idstr) output = [] for led in leds: if led[1] == 0: state = "off" elif led[1] == 1: state = "on" else: state = "unknown" output.append("%s => %s" % (led[0], state)) print ", ".join(output) class OpSetLed(Operation): def __init__(self, cfgStr): self.cfgStr = cfgStr def run(self, idstr): cfgStr = self.cfgStr.split(":") try: newState = cfgStr[-1].strip().lower() ledName = ":".join(cfgStr[:-1]) if not ledName: raise ValueError() if newState in ["0", "off", "false"]: newState = False elif newState in ["1", "on", "true"]: newState = True else: raise ValueError() except (IndexError, ValueError): raise RazerEx("Invalid parameter to --setled option") error = getRazer().setLed(idstr, ledName, newState) if error: raise RazerEx("Failed to set LED state (%s)" % Razer.strerror(error)) class OpSetRes(Operation): def __init__(self, param): self.param = param def run(self, idstr): try: (profile, mapping) = self.parseProfileValuePair(self.param, idstr) except ValueError: raise RazerEx("Invalid parameter to --res option") if mapping >= 100: # Mapping is in DPI. Get the mapping ID. mappings = getRazer().getSupportedDpiMappings(idstr) try: (mapping, res, mutable) = filter(lambda x: x[1] == mapping, mappings)[0] except IndexError: raise RazerEx("Invalid resolution %d" % mapping) else: mapping = mapping - 1 error = getRazer().setDpiMapping(idstr, profile - 1, mapping) if error: raise RazerEx("Failed to set resolution to %u (%s)" %\ (mapping, Razer.strerror(error))) class OpSetFreq(Operation): def __init__(self, param): self.param = param def run(self, idstr): try: (profile, freq) = self.parseProfileValuePair(self.param, idstr) except ValueError: raise RazerEx("Invalid parameter to --freq option") error = getRazer().setFrequency(idstr, profile - 1, freq) if error: raise RazerEx("Failed to set frequency to %d Hz (%s)" %\ (freq, Razer.strerror(error))) class OpFlashFw(Operation): def __init__(self, filename): self.filename = filename def run(self, idstr): p = RazerFirmwareParser(self.filename) data = p.getImage() print "Flashing firmware on %s ..." % idstr print "!!! DO NOT DISCONNECT ANY DEVICE !!!" print "Sending %d bytes..." % len(data) error = getRazer().flashFirmware(idstr, data) if error: raise RazerEx("Failed to flash firmware (%s)" % Razer.strerror(error)) print "Firmware successfully flashed." # List of operations class DevOps: def __init__(self, idstr): self.idstr = idstr self.ops = [] def add(self, op): self.ops.append(op) def runAll(self): for op in self.ops: op.run(self.idstr) def scanDevices(): getRazer().rescanMice() mice = getRazer().getMice() for mouse in mice: print mouse def backgroundRescan(): if os.fork() == 0: getRazer().rescanMice() def exit(exitcode): sys.exit(exitcode) def prVersion(): print "Razer device configuration tool" print "Version", RAZER_VERSION def usage(): prVersion() print "" print "Usage: razercfg [OPTIONS] [-d DEV DEVOPS] [-d DEV DEVOPS]..." print "" print "-h|--help Print this help text" print "-v|--version Print the program version number" print "-s|--scan Scan for devices and print the bus IDs" print "" print "-d|--device DEV Selects the device with the bus ID \"DEV\"" print " Use the special value \"mouse\" for DEV to select" print " the first razer mouse device found in the system." print " If this option is omitted, the first Razer device found is selected." print "" print "-S|--sleep SECS Sleep SECS seconds." print "" print "Device operations (DEVOPS):" print "These options apply to the device that is specified with -d" print "" print "Options for mice:" print "-V|--fwver Print the firmware version number" print "-r|--res [profile:]DPI Changes the scan resolution. profile is optional." print "-R|--getres Prints the resolutions" print "-f|--freq [profile:]FREQ Changes the scan frequency. profile is optional." print "-F|--getfreq Prints the frequencies" print "-L|--leds Print the identifiers of the LEDs on the device" print "-l|--setled LED:off Toggle the LED with the identifier \"LED\" ON or OFF" print "-X|--flashfw FILE Flash a firmware image to the device" def findDevice(deviceType=None): if deviceType is None or deviceType == "mouse": getRazer().rescanMice() mice = getRazer().getMice() if mice: return mice[0] # Return the first idstr if deviceType: raise RazerEx("No Razer mouse found in the system") raise RazerEx("No Razer device found in the system") def parse_args(): devOpsList = [] currentDevOps = None try: (opts, args) = getopt.getopt(sys.argv[1:], "hvsd:r:Rf:FLl:Vc:S:X:", [ "help", "version", "scan", "bg-rescan", "device=", "res=", "getres", "freq=", "getfreq", "leds", "setled=", "fwver", "config=", "sleep=", "flashfw=", ]) except getopt.GetoptError: usage() exit(1) for (o, v) in opts: if o in ("-h", "--help"): usage() exit(0) if o in ("-v", "--version"): prVersion() exit(0) if o in ("-s", "--scan"): scanDevices() exit(0) if o in ("--bg-rescan", ): backgroundRescan() exit(0) if o in ("-d", "--device"): if v == "mouse": # magic; select the first mouse v = findDevice("mouse") if currentDevOps and currentDevOps.ops: devOpsList.append(currentDevOps) currentDevOps = DevOps(v) continue if o in ("-r", "--res"): if not currentDevOps: currentDevOps = DevOps(findDevice()) currentDevOps.add(OpSetRes(v)) continue if o in ("-R", "--getres"): if not currentDevOps: currentDevOps = DevOps(findDevice()) currentDevOps.add(OpGetRes()) continue if o in ("-f", "--freq"): if not currentDevOps: currentDevOps = DevOps(findDevice()) currentDevOps.add(OpSetFreq(v)) continue if o in ("-F", "--getfreq"): if not currentDevOps: currentDevOps = DevOps(findDevice()) currentDevOps.add(OpGetFreq()) continue if o in ("-L", "--leds"): if not currentDevOps: currentDevOps = DevOps(findDevice()) currentDevOps.add(OpPrintLeds()) continue if o in ("-l", "--setled"): if not currentDevOps: currentDevOps = DevOps(findDevice()) currentDevOps.add(OpSetLed(v)) continue if o in ("-V", "--fwver"): if not currentDevOps: currentDevOps = DevOps(findDevice()) currentDevOps.add(OpGetFwVer()) continue if o in ("-S", "--sleep"): ops = currentDevOps if not currentDevOps: ops = DevOps(None) try: v = float(v) except ValueError: raise RazerEx("Value for -S|--sleep must be a floating point value") ops.add(OpSleep(v)) if not currentDevOps: devOpsList.append(ops) continue if o in ("-X", "--flashfw"): if not currentDevOps: raise RazerEx("Must specify a device (-d) before -X|--flashfw") currentDevOps.add(OpFlashFw(v)) continue if currentDevOps and currentDevOps.ops: devOpsList.append(currentDevOps) if not devOpsList: usage() exit(1) return devOpsList def main(): try: devOpsList = parse_args() for devOps in devOpsList: devOps.runAll() except (RazerEx), e: print e return 1 return 0 if __name__ == "__main__": exit(main())