def __init__(self): self._capabilities = { evdev.ecodes.EV_SYN: [1, 2, 3], evdev.ecodes.EV_FF: [1, 2, 3], EV_ABS: [(1, evdev.AbsInfo(value=None, min=None, max=1234, fuzz=None, flat=None, resolution=None)), (2, evdev.AbsInfo(value=None, min=50, max=2345, fuzz=None, flat=None, resolution=None)), 3] }
def capabilities(self, absinfo=True, verbose=False): result = copy.deepcopy(fixtures[self.path]['capabilities']) if absinfo and evdev.ecodes.EV_ABS in result: absinfo_obj = evdev.AbsInfo( value=None, min=MIN_ABS, fuzz=None, flat=None, resolution=None, max=MAX_ABS ) result[evdev.ecodes.EV_ABS] = [ (stuff, absinfo_obj) for stuff in result[evdev.ecodes.EV_ABS] ] return result
def test_copy_capabilities(self): self.mapping.change(Key(EV_KEY, 60, 1), self.macro.code) # I don't know what ABS_VOLUME is, for now I would like to just always # remove it until somebody complains, since its presence broke stuff self.injector = Injector(groups.find(name='foo'), self.mapping) self.fake_device._capabilities = { EV_ABS: [ABS_VOLUME, (ABS_X, evdev.AbsInfo(0, 0, 500, 0, 0, 0))], EV_KEY: [1, 2, 3], EV_REL: [11, 12, 13], evdev.ecodes.EV_SYN: [1], evdev.ecodes.EV_FF: [2], } capabilities = self.injector._copy_capabilities(self.fake_device) self.assertNotIn(ABS_VOLUME, capabilities[EV_ABS]) self.assertNotIn(evdev.ecodes.EV_SYN, capabilities) self.assertNotIn(evdev.ecodes.EV_FF, capabilities) self.assertListEqual(capabilities[EV_KEY], [1, 2, 3]) self.assertListEqual(capabilities[EV_REL], [11, 12, 13]) self.assertEqual(capabilities[EV_ABS][0][1].max, 500)
def make_cap(config): axes = [] buttons = [] # loops through keys of dictionary for ctrl in config['controls']: (ctrl_type, ctrl_id) = config['controls'][ctrl] if ctrl_type == evdev.ecodes.EV_KEY: buttons.append(ctrl_id) else: axes.append((ctrl_id, evdev.AbsInfo(0, 255, 0, 15, 0, 0))) # sort the arrays axes.sort() buttons.sort() cap = {} if axes: cap[evdev.ecodes.EV_ABS] = axes; if buttons: cap[evdev.ecodes.EV_KEY] = buttons; return cap
def start(): path = os.path.join(os.path.dirname(__file__), "config.yaml") # Loading tablet configuration with open(path, "r") as f: config = yaml.load(f, Loader=yaml.FullLoader) # Get the required ecodes from configuration required_ecodes = [] for k, v in config["actions"].items(): if isinstance(v, list): required_ecodes.extend(v) else: required_ecodes.append(v) temp = [] for c in required_ecodes: temp.extend([evdev.ecodes.ecodes[x] for x in c.split("+")]) required_ecodes = temp pen_events = { evdev.ecodes.EV_KEY: required_ecodes, evdev.ecodes.EV_ABS: [ #AbsInfo input: value, min, max, fuzz, flat (evdev.ecodes.ABS_X, evdev.AbsInfo(0, 0, config['pen']['max_x'], 0, 0, config["pen"]["resolution_x"])), (evdev.ecodes.ABS_Y, evdev.AbsInfo(0, 0, config['pen']['max_y'], 0, 0, config["pen"]["resolution_y"])), (evdev.ecodes.ABS_PRESSURE, evdev.AbsInfo(0, 0, config['pen']['max_pressure'], 0, 0, 0)) ], } # Find the device dev = usb.core.find(idVendor=config["vendor_id"], idProduct=config["product_id"]) # Select end point for reading second interface [2] for actual data # I don't know what [0] and [1] are used for ep = dev[0].interfaces()[2].endpoints()[0] # Reset the device (don't know why, but till it works don't touch it) dev.reset() # Drop default kernel driver from all devices for j in [0, 1, 2]: if dev.is_kernel_driver_active(j): dev.detach_kernel_driver(j) # Set new configuration dev.set_configuration() vpen = evdev.UInput(events=pen_events, name=config["xinput_name"], version=0x3) pressed = -1 # Infinite loop while True: try: data = dev.read(ep.bEndpointAddress, ep.wMaxPacketSize) if data[1] in [192, 193]: # Pen actions pen_x = config['pen']['max_x'] - (data[5] * 255 + data[4]) pen_y = data[3] * 255 + data[2] pen_pressure = data[7] * 255 + data[6] vpen.write(evdev.ecodes.EV_ABS, evdev.ecodes.ABS_X, pen_x) vpen.write(evdev.ecodes.EV_ABS, evdev.ecodes.ABS_Y, pen_y) vpen.write(evdev.ecodes.EV_ABS, evdev.ecodes.ABS_PRESSURE, pen_pressure) if data[1] == 192: # Pen touch vpen.write(evdev.ecodes.EV_KEY, evdev.ecodes.BTN_TOUCH, 0) else: vpen.write(evdev.ecodes.EV_KEY, evdev.ecodes.BTN_TOUCH, 1) elif data[0] == 2: # Tablet button actions # press types: 0 - up; 1 - down; 2 - hold press_type = 1 if data[1] == 2: # First button pressed = 0 elif data[1] == 4: # Second button pressed = 1 elif data[3] == 44: # Third button pressed = 2 elif data[3] == 43: # Fourth button pressed = 3 else: press_type = 0 key_codes = config["actions"]["tablet_buttons"][pressed].split( "+") for key in key_codes: act = evdev.ecodes.ecodes[key] vpen.write(evdev.ecodes.EV_KEY, act, press_type) # Flush vpen.syn() except usb.core.USBError as e: if e.args[0] == 19: vpen.close() raise Exception('Device has been disconnected')
def __str__(self): return f"<actually_an_axis object {self.axis_cap} * {self.multiplier}>" # FIXME: Do I really need to use the list length as the keys? # Only really tested with X-Box One & X-Box 360 controllers assumed_button_caps = { 17: [ evdev.ecodes.BTN_A, evdev.ecodes.BTN_B, evdev.ecodes.BTN_X, evdev.ecodes.BTN_Y, evdev.ecodes.BTN_TL, evdev.ecodes.BTN_TR, actually_an_axis(evdev.ecodes.ABS_Z, evdev.AbsInfo(value=0, min=0, max=1023, fuzz=0, flat=0, resolution=0)), actually_an_axis(evdev.ecodes.ABS_RZ, evdev.AbsInfo(value=0, min=0, max=1023, fuzz=0, flat=0, resolution=0)), evdev.ecodes.BTN_SELECT, evdev.ecodes.BTN_START, evdev.ecodes.BTN_THUMBL, evdev.ecodes.BTN_THUMBR, actually_an_axis(evdev.ecodes.ABS_HAT0Y, evdev.AbsInfo(value=0, min=-1, max=1, fuzz=0, flat=0, resolution=0), multiplier=-1), # noqa: E501 actually_an_axis(evdev.ecodes.ABS_HAT0Y, evdev.AbsInfo(value=0, min=-1, max=1, fuzz=0, flat=0, resolution=0)), actually_an_axis(evdev.ecodes.ABS_HAT0X, evdev.AbsInfo(value=0, min=-1, max=1, fuzz=0, flat=0, resolution=0), multiplier=-1), # noqa: E501 actually_an_axis(evdev.ecodes.ABS_HAT0X, evdev.AbsInfo(value=0, min=-1, max=1, fuzz=0, flat=0, resolution=0)), evdev.ecodes.BTN_MODE, ], 16: [ evdev.ecodes.BTN_A, evdev.ecodes.BTN_B, evdev.ecodes.BTN_X,
if device.name == "Sony Computer Entertainment Wireless Controller": ds3 = device ds3.grab() print("Identified DS3: " + ds3.fn) break if ds3 is None: print("DS3 Not found") exit(1) # Create a Fake360 UInput Device. # Button codes were chosen to be roughly accurate while still being placed in # the right order, which it turns out is a surprisingly tall order. x360 = evdev.UInput( { ec.EV_ABS: [ (ec.ABS_X, evdev.AbsInfo(0, 0, 255, 1, 15, 0)), (ec.ABS_Y, evdev.AbsInfo(0, 0, 255, 1, 15, 0)), (ec.ABS_RX, evdev.AbsInfo(0, 0, 255, 1, 15, 0)), (ec.ABS_RY, evdev.AbsInfo(0, 0, 255, 1, 15, 0)), (ec.ABS_HAT0X, evdev.AbsInfo(0, -1, 1, 0, 0, 0)), (ec.ABS_HAT0Y, evdev.AbsInfo(0, -1, 1, 0, 0, 0)), (ec.ABS_TILT_X, evdev.AbsInfo(0, -255, 255, 1, 0, 0)), #LT (ec.ABS_TILT_Y, evdev.AbsInfo(0, -255, 255, 1, 0, 0)), #RT ], ec.EV_KEY: [ ec.BTN_A, ec.BTN_B, ec.BTN_X, ec.BTN_Y, ec.BTN_TL, #LB ec.BTN_TR, #RB
def doServer(): # create new socket object with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind((HOST, PORT)) # bind our socket to our port s.listen() # listen for connections # outside loop to enable restarting the server while True: conn, addr = s.accept( ) # once connection available, accept it (THIS IS BLOCKING) try: with conn: # Start by getting controller information json (first packet received) # print("Connected to", addr) # print who we are connected with data: bytes = b"" while not data: data += conn.recv(4096) # if message post-curser not found, keep polling the socket if (EOM not in data): continue split = data.index(EOM) controllerInformation = data[:split] data = data[split + len(EOM):] controllerInformation = controllerInformation.decode() try: controllerInformation = json.loads( controllerInformation) except JSONDecodeError: # JSONDecode error here is FATAL, abort the connection (and retry connection) Logger.logError(format_exc()) s.close() raise ConnectionAbortedError # TODO: MAKE OBSOLETE # parse any events grabbed from socket at this time events: List[List] = [] while EOM in data: split = data.index(EOM) try: events.append( json.loads(data[:split].decode().replace( '\n', ''))) except JSONDecodeError: Logger.logError(format_exc()) data = data[split + len( EOM ):] # if we cut off data, leave cut off data in buffer # once we start getting data, get the first thing sent (our controller information) devices_json = controllerInformation devices = [] for device_json in devices_json: capabilities = {} for k, v in device_json['capabilities'].items( ): # parse capabilities json capabilities[int(k)] = [ x if not isinstance(x, list) else (x[0], evdev.AbsInfo(**x[1])) for x in v ] # create new EVDev device devices.append( evdev.UInput(capabilities, name=device_json['name'], vendor=device_json["vendor"], product=device_json["product"], version=device_json["version"])) Logger.log('Controller Device created') # while we are connected read controller data (and try not to miss any events) while True: # poll the socket start = time.time() while EOM not in data: # grab data until EOM character reached data += conn.recv(4096) if (not data and time.time() - start > 60 ): # 60 second timeout for controller server raise ConnectionResetError # parse data # deocde, remove EOM character, split events into list dataLST: List[str] = data.decode()[:len(data) - len(EOM)].split( '\n') for possibleEvent in dataLST: if (possibleEvent == '' ): # check if event is valid continue try: events.append( json.loads(possibleEvent.replace('\n', '')) ) # get rid of unwanted \n's if they exist except JSONDecodeError: # Error here is not FATAL, ignore the event and continue parsing events Logger.logError(format_exc()) continue # apply pending events for event in events: if (event == ''): continue # write events to applicable device devices[int(event[0])].write( int(event[1]), int(event[2]), int(event[3])) events = [] # connection was reset from other side (or maybe your network dropped) except ConnectionResetError: Logger.logError(format_exc()) time.sleep(1) # wait second before retrying connection continue
import json import evdev from nuuJoyLib.Socket.tcpipv4 import server_socket __version__ = (2021,2,17,'beta') ds4_events = { evdev.ecodes.EV_ABS:[ (evdev.ecodes.ABS_X,evdev.AbsInfo(value=0,min=-32767,max=32767,fuzz=0,flat=0,resolution=0)), (evdev.ecodes.ABS_Y,evdev.AbsInfo(value=0,min=-32767,max=32767,fuzz=0,flat=0,resolution=0)), (evdev.ecodes.ABS_Z,evdev.AbsInfo(value=-32767,min=-32767,max=32767,fuzz=0,flat=0,resolution=0)), (evdev.ecodes.ABS_RX,evdev.AbsInfo(value=0,min=-32767,max=32767,fuzz=0,flat=0,resolution=0)), (evdev.ecodes.ABS_RY,evdev.AbsInfo(value=0,min=-32767,max=32767,fuzz=0,flat=0,resolution=0)), (evdev.ecodes.ABS_RZ,evdev.AbsInfo(value=-32767,min=-32767,max=32767,fuzz=0,flat=0,resolution=0)), (evdev.ecodes.ABS_HAT0X,evdev.AbsInfo(value=0,min=-32767,max=32767,fuzz=0,flat=0,resolution=0)), (evdev.ecodes.ABS_HAT0Y,evdev.AbsInfo(value=0,min=-32767,max=32767,fuzz=0,flat=0,resolution=0)), ], evdev.ecodes.EV_KEY:[ evdev.ecodes.BTN_TR2, evdev.ecodes.BTN_MODE, evdev.ecodes.BTN_TL2, evdev.ecodes.BTN_B, evdev.ecodes.BTN_C, evdev.ecodes.BTN_A, evdev.ecodes.BTN_X, evdev.ecodes.BTN_Y, evdev.ecodes.BTN_Z,
def startControllerServer(): # create new socket object with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind((HOST, PORT)) # bind our socket to our port # outside loop to enable restarting the server while True: print("Listening for connections") s.listen() # wait for connection conn, addr = s.accept( ) # once connection available, accept it (THIS IS BLOCKING) try: with conn: print("Connected to", addr) # print who we are connected with data = b"" while not data: data += conn.recv(2048) # if message post-curser not found, keep polling the socket if (b"<" not in data): continue data = data.decode().split('\n') controllerInformation = json.loads(data[0][0:len(data[0]) - 1]) events = [] if (len(data) > 1): for i in range(1, len(data)): events.append(data[i]) # once we start getting data, get the first thing sent (our controller information) devices_json = controllerInformation devices = [] for device_json in devices_json: capabilities = {} for k, v in device_json['capabilities'].items(): capabilities[int(k)] = [ x if not isinstance(x, list) else (x[0], evdev.AbsInfo(**x[1])) for x in v ] devices.append( evdev.UInput(capabilities, name=device_json['name'], vendor=1118, product=746, version=769)) print('Device created') data = b"" # while we are connected read controller data (and try not to miss any events) while True: # poll the socket start = time.time() while not data: # if socket was empty, keep trying data += conn.recv(2048) if (b"<" not in data): # wait until EOM character if ( data == b"" and time.time() - start > 60 ): # 60 second timeout for controller server raise ConnectionResetError continue # split by line data = data.decode().split('\n') data[-1].replace('<', '') # trash EOM character # parse data for event in data: if (event == ''): continue events.append( json.loads(event.replace('\n', '')) ) # get rid of nasty \n characters if they exist # apply pending events for event in events: if (event == ''): continue devices[int(event[0])].write( int(event[1]), int(event[2]), int(event[3])) data = b"" events = [] # connection was reset from other side (or maybe your network dropped) except ConnectionResetError: print("Connection with", addr, " forcibly closed") continue