diff --git a/drc-info.py b/drc-info.py new file mode 100644 index 0000000..78c81d3 --- /dev/null +++ b/drc-info.py @@ -0,0 +1,76 @@ +import select +import socket +import time +from threading import Thread + +from src.server.data import constants + +sock_cmd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +sock_cmd.bind(("192.168.1.10", constants.PORT_WII_CMD)) +sock_msg = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +sock_msg.bind(("192.168.1.10", constants.PORT_WII_MSG)) +sock_hid = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +sock_hid.bind(("192.168.1.10", constants.PORT_WII_HID)) +sock_vid = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +sock_vid.bind(("192.168.1.10", constants.PORT_WII_VID)) +sock_aud = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +sock_aud.bind(("192.168.1.10", constants.PORT_WII_AUD)) + + +def print_packet(s, name, do_print=True): + data = s.recv(2048) + if do_print: + print "%s: %s" % (name, data.encode('hex')) + + +def send_cmd(data): + sock_cmd.sendto(data, ("192.168.1.11", constants.PORT_WII_CMD + 100)) + + +def cmd_request(): + sid = 0 + while True: + data = { + 0: {0: {0: "000000000c00%s087e0115880040000000000000", + 10: "000000000d00%s007e0101780040000a0000000100"}, + 4: {4: "000000000c00%s007e0109780040040400000000"}, + 5: {6: "000000000c00%s007e0101a80040050600000000", + 12: "000000001100%s007e0102f80040050c000000050e0300870f", + 24: "000000001600%s007e0101c8004005180000000a54313936333030303030"} + }, + 1: {0: {0: "000001003000%s1a010000000000000000000000803e000000010002000000000000000070000000404003002d00000" + "10000000000000000" # Just CMD 1 - keys 0 0 are there so it fits nicely with the for loop + } + } + } + for command in data.keys(): + for primary_id in data[command].keys(): + for secondary_id in data[command][primary_id].keys(): + h = hex(sid).replace("0x", "") + if len(h) == 1: + h = "0" + h + send_data = bytes((data[command][primary_id][secondary_id] % h).decode("hex")) + print "Sending command %d %d %d" % (command, primary_id, secondary_id) + send_cmd(send_data) + sid += 1 + time.sleep(1) + + +if __name__ == '__main__': + Thread(target=cmd_request).start() + + while True: + rlist, wlist, xlist = select.select((sock_cmd, sock_msg, sock_hid, sock_vid, sock_aud), (), (), 1) + if rlist: + for s in rlist: + if s == sock_hid: + print_packet(s, "hid", False) + pass + elif s == sock_aud: + print_packet(s, "aud") + elif s == sock_vid: + print_packet(s, "vid") + elif s == sock_cmd: + print_packet(s, "cmd") + elif s == sock_msg: + print_packet(s, "msg") diff --git a/drc-sim-backend.py b/drc-sim-backend.py index 8bf7e39..c7edfe2 100644 --- a/drc-sim-backend.py +++ b/drc-sim-backend.py @@ -61,7 +61,7 @@ def main(): ConfigServer.load() ConfigServer.save() init_loggers() - Logger.info("Initializing drc-sim-backend") + Logger.info("Initializing drc-sim-backend version %s", constants.VERSION) Logger.info("Using \"%s\" as home folder.", constants.PATH_ROOT) log_level() OsUtil.log_info(Logger) diff --git a/resources/command/na.json b/resources/command/na.json new file mode 100644 index 0000000..c73d208 --- /dev/null +++ b/resources/command/na.json @@ -0,0 +1,17 @@ +{ + "0": { + "0": { + "0": "0200000014000c087e0115880009000000000008190c0117190c0117", + "10": "02000000100007007e0101780009000a0000000400170200" + }, + "4": { + "4": "02000000280008007e010978000904040000001c0000000b00000040190c011728000058000800000c0221fe00001c58" + }, + "5": { + "6": "0200000010030a007e0101a80009050600000304280000580057696955333461663263613034626336000000000000000000000000000000001000800365636130366162363637646637326130646563393237626462656134366130356266353262633366623436643863653861353561303966643761303466343838405132000206d336213160525064cbe7470cca8a7e79f3b470ea34af2ca04bc67049010e1e24a16800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000031c3d8b5c35010e1e15ab48000000000000000000000000000000b8f006ff10abbcff200011ff6f1f611f551e6052c50000f0ffff0900003a5c02325702d05b02c8d26600000000000000000000000000000000000035001e002203c30153015d0ea90e9b0166aee41703a0b5430000000000000000000000000000000000000000008b5c35010e1e15ab48000000000000000000000000000000b8f006ff10abbcff200011ff6f1f611f551e6052c50000f0ffff0900003a5c02325702d05b02c8d26600000000000000000000000000000000000035001e002203c30153015d0ea90e9b0166aee41703a0b543000000000000000000000000000000000000052a5800870f00870f010e1e00000000001900161d6fbcff200011ff6f1f611f551e605200000000000000000000000000000000000000000000000000000000000000000000005d007800f8028201fc01920bf10d6c03481a01000217144800000003ba31e41703a0b54300000000000000000000000000870f15012d014d017a01b701ff0103268c04a34954313936335331333737780100870f00870f010e1effff0000870f00870f020008c30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004a349", + "12": "020000000c0009007e0102f80009050c00000000", + "24": "020000000c0003007e0101c80009051800000000" + } + }, + "1": "0200010010000b1a000000009e0000008000400000000158" +} \ No newline at end of file diff --git a/setup.py b/setup.py index c86e546..7d31876 100644 --- a/setup.py +++ b/setup.py @@ -4,8 +4,10 @@ from setuptools import find_packages +from src.server.data import constants + setup(name='drcsim', - version='1.3', + version=constants.VERSION, description='Wii U gamepad simulator.', install_requires=['construct<2.8', 'Pillow==3.4.2', 'cffi==1.9.1', 'netifaces==0.10.5', 'pexpect==4.2.1'], packages=find_packages(), @@ -17,6 +19,9 @@ 'resources/image/heart.gif', 'resources/image/spade.gif', 'resources/image/icon.gif' + ]), + ('resources/command', [ + 'resources/command/na.json' ])], scripts=['drc-sim-backend.py'] ) diff --git a/src/server/data/constants.py b/src/server/data/constants.py index fd5fbeb..46dbc80 100644 --- a/src/server/data/constants.py +++ b/src/server/data/constants.py @@ -1,5 +1,8 @@ import os +# Info +VERSION = "1.4" + # Port PORT_WII_MSG = 50010 PORT_WII_VID = 50020 diff --git a/src/server/net/wii/command.py b/src/server/net/wii/command.py index 6b5cfeb..b7e03e0 100644 --- a/src/server/net/wii/command.py +++ b/src/server/net/wii/command.py @@ -1,6 +1,9 @@ +import ast + import construct from src.server.data import constants +from src.server.data.resource import Resource from src.server.net import sockets from src.server.util.logging.logger_backend import LoggerBackend @@ -62,29 +65,42 @@ def __init__(self): 1: self.cmd1, 2: self.cmd2 } - self.cmd0_handlers = { - 5: {6: self.cmd0_5_6}, - } - - # noinspection PyUnusedLocal - def cmd0_5_6(self, h, packet): - # Returns the 4 byte UIC firmware version followed by the first 768 bytes of the UIC EEPROM. - # Send null data TODO get updated firmware - r = '\x00' * 772 - self.send_response_cmd0(h, r) + self.command_json = {} + self.set_region() + + def set_region(self, region=None): + # Empty command data + if not region or region.upper() == "NONE": + self.command_json = ast.literal_eval(Resource("command/na.json").resource) + for command in self.command_json.keys(): + if isinstance(self.command_json[command], str): + self.command_json[command] = "0" * len(self.command_json[command]) + else: + for id_primary in self.command_json[command].keys(): + for id_secondary in self.command_json[command][id_primary].keys(): + self.command_json[command][id_primary][id_secondary] = \ + "0" * len(self.command_json[command][id_primary][id_secondary]) + # Region specific command data + else: + self.command_json = ast.literal_eval(Resource("command/%s.json" % region.lower()).resource) def cmd0(self, h, packet): - LoggerBackend.debug('CMD0:%i:%i' % (h.id_primary, h.id_secondary)) - if h.id_primary not in self.cmd0_handlers or h.id_secondary not in self.cmd0_handlers[h.id_primary]: - LoggerBackend.debug('unhandled: ' + packet.encode('hex')) + id_primary = str(h.id_primary) + id_secondary = str(h.id_secondary) + LoggerBackend.debug('CMD0:%s:%s' % (id_primary, id_secondary)) + if id_primary not in self.command_json["0"] or id_secondary not in self.command_json["0"][id_primary]: + LoggerBackend.debug('unhandled CMD0 %s %s: %s', id_primary, id_secondary, packet.encode('hex')) return - self.cmd0_handlers[h.id_primary][h.id_secondary](h, packet) + response = self.command_json["0"][id_primary][id_secondary] + response = bytes(response[40:].decode("hex")) + self.send_response_cmd0(h, response) # noinspection PyUnusedLocal def cmd1(self, h, packet): LoggerBackend.extra('CMD1: ' + packet[8:].encode('hex')) - r = '\x00' * 16 - self.send_response(h, r) + response = self.command_json["1"] + response = bytes(response[16:].decode("hex")) + self.send_response(h, response) # noinspection PyUnusedLocal def cmd2(self, h, packet): diff --git a/src/server/ui/gui/frame/frame_run_server.py b/src/server/ui/gui/frame/frame_run_server.py index c76b64f..e6249f2 100644 --- a/src/server/ui/gui/frame/frame_run_server.py +++ b/src/server/ui/gui/frame/frame_run_server.py @@ -3,6 +3,8 @@ from ttk import Label, Button, Combobox from src.server.control.gamepad import Gamepad +from src.server.net import socket_handlers, sockets +from src.server.net.wii.command import CommandHandler from src.server.util.wpa_supplicant import WpaSupplicant from src.server.data import constants from src.server.ui.gui.frame.frame_tab import FrameTab @@ -30,6 +32,8 @@ def __init__(self, master=None, **kw): self.dropdown_wiiu_interface = Combobox(self, state="readonly") self.dropdown_normal_interface = Combobox(self, state="readonly") self.label_interface_info = Label(self) + self.label_region = Label(self, text="Region") + self.dropdown_region = Combobox(self, state="readonly") # Events self.button_start.bind("", self.start_server) self.button_stop.bind("", self.stop_server) @@ -42,9 +46,11 @@ def __init__(self, master=None, **kw): self.label_normal_interface.grid(column=0, row=3) self.dropdown_wiiu_interface.grid(column=1, row=2, columnspan=2) self.dropdown_normal_interface.grid(column=1, row=3, columnspan=2) - self.button_start.grid(column=1, row=4) - self.button_stop.grid(column=2, row=4) - self.label_interface_info.grid(column=0, row=5, columnspan=3) + self.label_region.grid(column=0, row=4) + self.dropdown_region.grid(column=1, row=4, columnspan=2) + self.button_start.grid(column=1, row=5) + self.button_stop.grid(column=2, row=5) + self.label_interface_info.grid(column=0, row=6, columnspan=3) LoggerGui.extra("Initialized FrameRunServer") def start_server(self, event=None): @@ -106,6 +112,8 @@ def wpa_status_changed(self, status): self.gamepad = Gamepad() self.gamepad.add_status_change_listener(self.backend_status_changed) self.gamepad.start() + CommandHandler.set_region(socket_handlers.SocketHandlers.wii_handlers[sockets.Sockets.WII_CMD_S], + self.dropdown_region.get()) self.label_interface_info.config(text="Server IP: " + InterfaceUtil.get_ip(self.normal_interface) + "\n" + os.uname()[1]) elif status in (WpaSupplicant.DISCONNECTED, WpaSupplicant.TERMINATED): @@ -143,8 +151,7 @@ def activate(self): LoggerGui.debug("FrameRunServer activated") self.dropdown_wiiu_interface["values"] = InterfaceUtil.get_wiiu_compatible_interfaces() self.dropdown_normal_interface["values"] = InterfaceUtil.get_all_interfaces() - self.dropdown_wiiu_interface.set("") - self.dropdown_normal_interface.set("") + self.dropdown_region["values"] = ["NONE", "NA"] self.label_wpa_status["text"] = WpaSupplicant.DISCONNECTED self.label_backend_status["text"] = Gamepad.STOPPED self.button_start.config(state="normal")