123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554 |
- #!/usr/bin/env python3
- #
- # Razer device commandline configuration tool
- #
- # Copyright (C) 2007-2011 Michael Buesch <m@bues.ch>
- #
- # 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
- import re
- from pyrazer import *
- from configparser import *
- try:
- PYRAZER_SETUP_PY == True
- except:
- print("ERROR: Found an old 'pyrazer' module.")
- print("You should uninstall razercfg from the system (see README)")
- print("and re-install it properly.")
- sys.exit(1)
- razer = None
- def getRazer():
- global razer
- if razer is None:
- razer = Razer()
- return razer
- class Operation:
- def parseProfileValueStr(self, parameter, idstr, nrValues=1):
- # Parse profile:value[:value]... string. Default to active
- # profile, if not given. May raise ValueError.
- split = parameter.split(":")
- if len(split) == nrValues:
- profile = None
- values = split
- elif len(split) == nrValues + 1:
- profile = int(split[0].strip())
- values = split[1:]
- if profile == 0:
- profile = getRazer().getActiveProfile(idstr) + 1
- if profile < 0:
- raise ValueError
- else:
- raise ValueError
- return (profile, values)
- class OpSleep(Operation):
- def __init__(self, seconds):
- self.seconds = seconds
- def run(self, idstr):
- time.sleep(self.seconds)
- class OpScan(Operation):
- def run(self, idstr):
- scanDevices()
- class OpReconfigure(Operation):
- def run(self, idstr):
- reconfigureDevices()
- class OpGetFwVer(Operation):
- def run(self, idstr):
- verTuple = getRazer().getFwVer(idstr)
- print("%s: Firmware version %d.%02d" %\
- (idstr, verTuple[0], verTuple[1]))
- class OpGetProfile(Operation):
- def run(self, idstr):
- profileId = getRazer().getActiveProfile(idstr)
- print("Active profile: %u" % (profileId + 1))
- class OpGetFreq(Operation):
- def run(self, idstr):
- freqs = getRazer().getSupportedFreqs(idstr)
- minfo = getRazer().getMouseInfo(idstr)
- curProf = getRazer().getActiveProfile(idstr)
- if minfo & Razer.MOUSEINFOFLG_GLOBAL_FREQ:
- curFreq = getRazer().getCurrentFreq(idstr)
- self.printFreq(freqs, curFreq)
- if minfo & Razer.MOUSEINFOFLG_PROFILE_FREQ:
- profiles = getRazer().getProfiles(idstr)
- for profile in profiles:
- sys.stdout.write("Profile %2u%s: " %\
- (profile + 1,
- "*" if profile == curProf else " "))
- curFreq = getRazer().getCurrentFreq(idstr, profile)
- self.printFreq(freqs, curFreq)
- def printFreq(self, freqs, curFreq):
- output = []
- for freq in freqs:
- pfx = "*" if freq == curFreq else " "
- output.append("%s%u Hz" % (pfx, freq))
- print(", ".join(output))
- class OpGetRes(Operation):
- def run(self, idstr):
- mappings = getRazer().getSupportedDpiMappings(idstr)
- profiles = getRazer().getProfiles(idstr)
- curProf = getRazer().getActiveProfile(idstr)
- for profile in profiles:
- sys.stdout.write("Profile %2u%s: " %\
- (profile + 1,
- "*" if profile == curProf else " "))
- curMapping = getRazer().getDpiMapping(idstr, profile)
- output = []
- pm = [m for m in mappings if m.profileMask == 0 or\
- m.profileMask & (1 << profile)]
- for mapping in pm:
- pfx = "*" if mapping.id == curMapping else " "
- r = [ "%u" % r for r in mapping.res if r is not None ]
- rStr = "/".join(r)
- output.append("%s%u (%s DPI)" % (pfx, mapping.id + 1, rStr))
- print(", ".join(output))
- class OpPrintLeds(Operation):
- def run(self, idstr):
- minfo = getRazer().getMouseInfo(idstr)
- if minfo & Razer.MOUSEINFOFLG_GLOBAL_LEDS:
- sys.stdout.write("Global LEDs: ")
- leds = getRazer().getLeds(idstr)
- self.printLeds(leds)
- if minfo & Razer.MOUSEINFOFLG_PROFILE_LEDS:
- profiles = getRazer().getProfiles(idstr)
- curProf = getRazer().getActiveProfile(idstr)
- for profile in profiles:
- sys.stdout.write("Profile %2u%s LEDs: " %\
- (profile + 1,
- "*" if profile == curProf else " "))
- leds = getRazer().getLeds(idstr, profile)
- self.printLeds(leds)
- def printLeds(self, leds):
- output = []
- for led in leds:
- state = "on" if led.state else "off"
- mode = led.mode.toString()
- color = ""
- if led.color is not None:
- color = "color#%02X%02X%02X" %\
- (led.color.r, led.color.g, led.color.b)
- output.append("%s => %s/%s/%s" % (led.name, state, mode, color))
- print(", ".join(output))
- class OpSetProfile(Operation):
- def __init__(self, param):
- self.param = param
- def run(self, idstr):
- try:
- profileId = int(self.param) - 1
- error = getRazer().setActiveProfile(idstr, profileId)
- if error:
- raise RazerEx("Failed to set active profile (%s)" %\
- Razer.strerror(error))
- except (ValueError) as e:
- raise RazerEx("Invalid parameter to --profile option")
- class OpSetLedState(Operation):
- def __init__(self, param):
- self.param = param
- def setLed(self, idstr, led, state):
- led.state = state
- error = getRazer().setLed(idstr, led)
- if error:
- raise RazerEx("Failed to set LED state (%s)" %\
- Razer.strerror(error))
- def run(self, idstr):
- try:
- (profile, config) = self.parseProfileValueStr(self.param, idstr, 2)
- ledName = config[0].strip().lower()
- newState = razer_str2bool(config[1])
- if profile is None:
- profile = Razer.PROFILE_INVALID
- else:
- profile -= 1
- leds = getRazer().getLeds(idstr, profile)
- if 'all' == ledName:
- for led in leds:
- self.setLed(idstr, led, newState)
- else:
- led = [led for led in leds if led.name.lower() == ledName.lower()][0]
- self.setLed(idstr, led, newState)
- except (IndexError, ValueError):
- raise RazerEx("Invalid parameter to --setled option")
- class OpSetLedColor(Operation):
- def __init__(self, param):
- self.param = param
- def run(self, idstr):
- try:
- (profile, config) = self.parseProfileValueStr(self.param, idstr, 2)
- ledName = config[0].strip()
- newColor = RazerRGB.fromString(config[1])
- if profile is None:
- profile = Razer.PROFILE_INVALID
- else:
- profile -= 1
- leds = getRazer().getLeds(idstr, profile)
- led = [led for led in leds if led.name.lower() == ledName.lower()][0]
- led.color = newColor
- error = getRazer().setLed(idstr, led)
- if error:
- raise RazerEx("Failed to set LED color (%s)" %\
- Razer.strerror(error))
- except (IndexError, ValueError):
- raise RazerEx("Invalid parameter to --setledcolor option")
- class OpSetLedMode(Operation):
- def __init__(self, param):
- self.param = param
- def run(self, idstr):
- try:
- (profile, config) = self.parseProfileValueStr(self.param, idstr, 2)
- ledName = config[0].strip().lower()
- newMode = RazerLEDMode.fromString(config[1].lower())
- if profile is None:
- profile = Razer.PROFILE_INVALID
- else:
- profile -= 1
- leds = getRazer().getLeds(idstr, profile)
- led = [led for led in leds if led.name.lower() == ledName.lower()][0]
- led.mode = newMode
- error = getRazer().setLed(idstr, led)
- if error:
- raise RazerEx("Failed to set LED mode (%s)" %\
- Razer.strerror(error))
- except (KeyError, IndexError, ValueError):
- raise RazerEx("Invalid parameter to --setledmode option")
- class OpSetRes(Operation):
- def __init__(self, param):
- self.param = param
- def setDpiMapping(self, idstr, profile, axisId, value):
- # Get profile mappings.
- mappings = [m for m in getRazer().getSupportedDpiMappings(idstr) \
- if m.profileMask == 0 or m.profileMask & (1 << profile)]
- if value >= 100:
- # Value is in DPI.
- mappings = [m for m in mappings if value in m.res]
- else:
- # Value is a mapping ID.
- mappings = [m for m in mappings if (value - 1) == m.id]
- try:
- mappingId = mappings[0].id
- except IndexError:
- raise RazerEx("Invalid resolution %d" % value)
- error = getRazer().setDpiMapping(idstr, profile - 1, mappingId, axisId=axisId)
- if error:
- raise RazerEx("Failed to set resolution to %u (%s)" %\
- (mappingId, Razer.strerror(error)))
- def run(self, idstr):
- try:
- (profile, values) = self.parseProfileValueStr(self.param, idstr)
- resolutions = []
- for arg in values[0].split(','):
- m = re.match('^\d+$', arg)
- if m is not None:
- resolutions.append((None, int(arg)))
- continue
- m = re.match('^(\d+)x(\d+)$', arg)
- if m is not None:
- resolutions.append((0, int(m.group(1))))
- resolutions.append((1, int(m.group(2))))
- continue
- raise ValueError
- except ValueError:
- raise RazerEx("Invalid parameter to --res option")
- if profile is None:
- # No profile number was specified. Get the current one.
- profile = getRazer().getActiveProfile(idstr) + 1
- for axisId, value in resolutions:
- self.setDpiMapping(idstr, profile, axisId, value)
- class OpSetFreq(Operation):
- def __init__(self, param):
- self.param = param
- def run(self, idstr):
- try:
- (profile, freq) = self.parseProfileValueStr(self.param, idstr)
- freq = int(freq[0])
- except ValueError:
- raise RazerEx("Invalid parameter to --freq option")
- if profile is None:
- profile = Razer.PROFILE_INVALID
- else:
- profile -= 1
- error = getRazer().setFrequency(idstr, profile, 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 reconfigureDevices():
- getRazer().rescanDevices()
- getRazer().reconfigureDevices()
- 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("-B|--background Fork into the background")
- print("-s|--scan Scan for devices and print the bus IDs")
- print("-K|--reconfigure Force-reconfigure all detected devices")
- 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("-p|--profile PROF Changes the active profile")
- print("-P|--getprofile Prints the active profile")
- print("-r|--res [PROF:]RES[xRES] Changes the scan resolution")
- print("-R|--getres Prints the resolutions")
- print("-f|--freq [PROF:]FREQ Changes the scan frequency")
- print("-F|--getfreq Prints the frequencies")
- print("-L|--leds List the device supported LED identifiers")
- print("-l|--setled [PROF:]LED:(on|off) Toggle the LED with the identifier \"LED\"")
- print(" Use the special identifier \"all\"")
- print(" to toggle all supported LEDs.")
- print("-c|--setledcolor [PROF:]LED:rrggbb Set LED color to RGB 'rrggbb'")
- print("-m|--setledmode [PROF:]LED:MODE Set LED mode to MODE ('static', 'spectrum'")
- print(" or 'breathing')")
- print("")
- print("-X|--flashfw FILE Flash a firmware image to the device")
- print("")
- print("The profile number \"PROF\" may be 0 for the current profile. If omitted,")
- print("the global settings are changed (not possible for every 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:],
- "hvBsKd:r:Rf:FLl:VS:X:c:p:Pm:",
- [ "help", "version", "background",
- "scan", "reconfigure", "device=", "res=",
- "getres", "freq=", "getfreq", "leds", "setled=",
- "fwver", "config=", "sleep=", "flashfw=",
- "setledcolor=", "setledmode=",
- "profile=", "getprofile", ])
- 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 ("-B", "--background"):
- if os.fork() != 0:
- exit(0) # Exit parent
- if o in ("-s", "--scan"):
- ops = currentDevOps
- if not currentDevOps:
- ops = DevOps(None)
- ops.add(OpScan())
- if not currentDevOps:
- devOpsList.append(ops)
- continue
- if o in ("-K", "--reconfigure"):
- ops = currentDevOps
- if not currentDevOps:
- ops = DevOps(None)
- ops.add(OpReconfigure())
- if not currentDevOps:
- devOpsList.append(ops)
- continue
- 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 ("-p", "--profile"):
- if not currentDevOps:
- currentDevOps = DevOps(findDevice())
- currentDevOps.add(OpSetProfile(v))
- continue
- if o in ("-P", "--getprofile"):
- if not currentDevOps:
- currentDevOps = DevOps(findDevice())
- currentDevOps.add(OpGetProfile())
- 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(OpSetLedState(v))
- continue
- if o in ("-c", "--setledcolor"):
- if not currentDevOps:
- currentDevOps = DevOps(findDevice())
- currentDevOps.add(OpSetLedColor(v))
- continue
- if o in ("-m", "--setledmode"):
- if not currentDevOps:
- currentDevOps = DevOps(findDevice())
- currentDevOps.add(OpSetLedMode(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) as e:
- print(e)
- return 1
- return 0
- if __name__ == "__main__":
- exit(main())
|