#!/usr/bin/env python # Compatible with python 3.11, NOT TESTED IN OLD VERSIONS OF PYTHON from __future__ import print_function import socket, struct, time # EVDEV: https://python-evdev.readthedocs.io/en/latest/tutorial.html#specifying-uinput-device-options import evdev from evdev import UInput, AbsInfo, ecodes as e ########################################################## # CONFIGURABLE REGION START - Don't touch anything above # ########################################################## port = 42020 # Set the debug variable to 1 to print Debug information debug = 1 # Valid values can be found in any of these locations on your Linux system (some may not exist): # /usr/include/linux/input-event-codes.h # The virtual device is defined on the device variable and the mapping of the keys on btn_map # RECAP keynames (DO NOT TOUCH) are the keys that we expect commming from the 3ds, device is # the virtual device that we define and btn_map maps what we recieve with our virtual device btn_map = { "A": e.BTN_A, "B": e.BTN_B, "X": e.BTN_X, "Y": e.BTN_Y, "L": e.BTN_TL, "R": e.BTN_TR, "ZL": e.BTN_THUMBL, "ZR": e.BTN_THUMBR, "Left": e.BTN_DPAD_LEFT, "Right": e.BTN_DPAD_RIGHT, "Up": e.BTN_DPAD_UP, "Down": e.BTN_DPAD_DOWN, "Start": e.BTN_START, "Select": e.BTN_SELECT, "Tap": e.BTN_MODE } device = { # EV_ABS is for Absolute movement with static values, # like the sticks and the volume e.EV_ABS: [ (e.ABS_X, AbsInfo(0, -159, 159, 0, 10, 0)), (e.ABS_Y, AbsInfo(0, -159, 159, 0, 10, 0)), (e.ABS_RX, AbsInfo(0, -146, 146, 0, 16, 0)), (e.ABS_RY, AbsInfo(0, -146, 146, 0, 16, 0)), (e.ABS_VOLUME, AbsInfo(0, 0, 63, 0, 0, 0)), ], # The keys lol e.EV_KEY: [ e.BTN_A, e.BTN_B, e.BTN_X, e.BTN_Y, e.BTN_TL, e.BTN_TR, e.BTN_THUMBL, e.BTN_THUMBR, e.BTN_DPAD_LEFT, e.BTN_DPAD_RIGHT, e.BTN_DPAD_UP, e.BTN_DPAD_DOWN, e.BTN_START, e.BTN_SELECT, e.BTN_MODE, ], } ui = UInput(device, name="3DS", phys="3ds", bustype=0x6) gyroAxis = { e.EV_ABS: [ (e.ABS_X, AbsInfo(0, 0, 0, 2, 0, 2048)), (e.ABS_Y, AbsInfo(0, 0, 0, 2, 0, 2048)), (e.ABS_Z, AbsInfo(0, 0, 0, 2, 0, 2048)), (e.ABS_RX, AbsInfo(0, -1024, 1024, 2, 8, 64)), (e.ABS_RY, AbsInfo(0, -1024, 1024, 2, 8, 64)), (e.ABS_RZ, AbsInfo(0, -1024, 1024, 2, 8, 64)) ], e.EV_MSC: [ e.MSC_TIMESTAMP ] } uiGyro = UInput(gyroAxis, name="3DS Motion Sensors", phys="3ds", bustype=0x6, input_props=[6]) if (debug): print (ui) ######################################################## # CONFIGURABLE REGION END - Don't touch anything below # ######################################################## class x: pass command = x() command.CONNECT = 0 command.KEYS = 1 command.SCREENSHOT = 2 keynames = [ "A", "B", "Select", "Start", "Right", "Left", "Up", "Down", "R", "L", "X", "Y", None, None, "ZL", "ZR", None, None, None, None, "Tap", None, None, None, "CSRight", "CSLeft", "CSUp", "CSDown", "CRight", "CLeft", "CUp", "CDown", ] keys = x() keys.A = 1<<0 keys.B = 1<<1 keys.Select = 1<<2 keys.Start = 1<<3 keys.Right = 1<<4 keys.Left = 1<<5 keys.Up = 1<<6 keys.Down = 1<<7 keys.R = 1<<8 keys.L = 1<<9 keys.X = 1<<10 keys.Y = 1<<11 keys.ZL = 1<<14 # (new 3DS only) keys.ZR = 1<<15 # (new 3DS only) keys.Tap = 1<<20 # Not actually provided by HID keys.CSRight = 1<<24 # c-stick (new 3DS only) keys.CSLeft = 1<<25 # c-stick (new 3DS only) keys.CSUp = 1<<26 # c-stick (new 3DS only) keys.CSDown = 1<<27 # c-stick (new 3DS only) keys.CRight = 1<<28 # circle pad keys.CLeft = 1<<29 # circle pad keys.CUp = 1<<30 # circle pad keys.CDown = 1<<31 # circle pad def press_key(key): ui.write(e.EV_KEY, key, 1) ui.syn() def release_key(key): ui.write(e.EV_KEY,key, 0) ui.syn() sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.bind(("", port)) prevkeys = 0 touch_start = 0 touch_last_x = 0 touch_last_y = 0 while True: rawdata, addr = sock.recvfrom(4092) rawdata = bytearray(rawdata) # print("Received message", rawdata) if rawdata[0]==command.CONNECT: print("Connected with 3DS at address", addr) pass # CONNECT packets are empty if rawdata[0]==command.KEYS: # Just to explain this fuckery of struct.unpack: #