From 12ecba7d4962a142df8ff707d77fa05ef5d7b409 Mon Sep 17 00:00:00 2001 From: Zion Nimchuk Date: Thu, 19 Oct 2017 10:50:39 -0700 Subject: [PATCH] Initial work on sys_usbd syscalls --- rpcs3/Emu/Cell/lv2/sys_prx.cpp | 4 +- rpcs3/Emu/Cell/lv2/sys_usbd.cpp | 178 ++++++++++++++++++++++++++++---- rpcs3/Emu/Cell/lv2/sys_usbd.h | 50 +++++++-- 3 files changed, 201 insertions(+), 31 deletions(-) diff --git a/rpcs3/Emu/Cell/lv2/sys_prx.cpp b/rpcs3/Emu/Cell/lv2/sys_prx.cpp index 60bdaf7a09..cb67a4425c 100644 --- a/rpcs3/Emu/Cell/lv2/sys_prx.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_prx.cpp @@ -77,8 +77,6 @@ static const std::unordered_map s_prx_ignore { "/dev_flash/sys/external/libsysutil_video_export.sprx", 0 }, { "/dev_flash/sys/external/libsysutil_video_player.sprx", 0 }, { "/dev_flash/sys/external/libsysutil_video_upload.sprx", 0 }, - { "/dev_flash/sys/external/libusbd.sprx", 0 }, - { "/dev_flash/sys/external/libusbpspcm.sprx", 0 }, { "/dev_flash/sys/external/libvdec.sprx", 0 }, { "/dev_flash/sys/external/libvoice.sprx", 0 }, }; @@ -283,7 +281,7 @@ error_code _sys_prx_unload_module(u32 id, u64 flags, vm::ptrexit ? prx->exit() : CELL_OK; - + return CELL_OK; } diff --git a/rpcs3/Emu/Cell/lv2/sys_usbd.cpp b/rpcs3/Emu/Cell/lv2/sys_usbd.cpp index ecaa2a7ac0..ae5a0dcdd3 100644 --- a/rpcs3/Emu/Cell/lv2/sys_usbd.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_usbd.cpp @@ -4,14 +4,37 @@ #include "Emu/Cell/ErrorCodes.h" #include "sys_usbd.h" - +#include "sys_ppu_thread.h" namespace vm { using namespace ps3; } logs::channel sys_usbd("sys_usbd"); -s32 sys_usbd_initialize() +std::vector devices = { + // System devices + usbDevice{ DeviceListUnknownDataType{0x1, 0x2, 0x2, 0x44}, 50, deviceDescriptor{0x12, 0x1, 0x0200, 0, 0, 0, 0x40, 0x054C, 0x0250, 0x0009, 3, 4, 5, 1}}, + usbDevice{ DeviceListUnknownDataType{0x1, 0x3, 0x2, 0xAD}, 326, deviceDescriptor{0x12, 0x1, 0x0200, 0xE0, 0x1, 0x1, 0x40, 0x054C, 0x0267, 0x0001, 1, 2, 0, 1}}, + // USB Drive + usbDevice{ DeviceListUnknownDataType{0x0, 0x4, 0x2, 0x0}, 50, deviceDescriptor{0x12, 0x1, 0x0200, 0, 0, 0, 0x40, 0x1516, 0x1226, 0x0100, 1, 2, 3, 1}}, + // Skylanders Portal + usbDevice{ DeviceListUnknownDataType{0x0, 0x5, 0x2, 0xF8}, 59, deviceDescriptor{0x12, 0x1, 0x0200, 0, 0, 0, 0x20, 0x1430, 0x0150, 0x0100, 1, 2, 0, 1}}, +}; + +bool has_register_extra_ldd; +int receive_event_called_count; + +/* + * sys_usbd_initialize changes handle to a semi-unique identifier. + * identifier generation is speculated to be: + * f(n+1) = (f(n) + 2<<9) % 14847 + f_min (probably just f(0)-14847 but it could be different) + * Thanks to @flash-fire for thinking up the identifier generation code. + * TODO: try to get hardware to return not CELL_OK (perhaps set handle to NULL). + */ +s32 sys_usbd_initialize(vm::ptr handle) { - sys_usbd.todo("sys_usbd_initialize()"); + sys_usbd.warning("sys_usbd_initialize(0x%x)", handle.get_ptr()); + *handle = 805322496; + has_register_extra_ldd = false; + receive_event_called_count = 0; return CELL_OK; } @@ -21,21 +44,118 @@ s32 sys_usbd_finalize() return CELL_OK; } -s32 sys_usbd_get_device_list() +s32 sys_usbd_get_device_list(u32 handle, vm::ptr device_list, char unknown) { - sys_usbd.todo("sys_usbd_get_device_list()"); - return CELL_OK; + sys_usbd.warning("sys_usbd_get_device_list(handle=%d, device_list=0x%x, unknown=%c)", handle, device_list, unknown); + // Unknown is just 0x7F + for (int i = 0; i < devices.size(); i++) + { + device_list[i] = devices[i].basicDevice; + } + return devices.size(); } -s32 sys_usbd_get_descriptor_size() +s32 sys_usbd_register_extra_ldd(u32 handle, vm::ptr lddOps, u16 strLen, u16 vendorID, u16 productID, u16 unk1) { - sys_usbd.todo("sys_usbd_get_descriptor_size()"); - return CELL_OK; + sys_usbd.warning("sys_usbd_register_extra_ldd(handle=%u, lddOps=0x%x, unk1=%u, vendorID=%u, productID=%u, unk2=%u)", handle, lddOps, strLen, vendorID, productID, unk1); + has_register_extra_ldd = true; + + // No idea what 9 means. + return 9; } -s32 sys_usbd_get_descriptor() +s32 sys_usbd_get_descriptor_size(u32 handle, u8 deviceNumber) { - sys_usbd.todo("sys_usbd_get_descriptor()"); + sys_usbd.warning("sys_usbd_get_descriptor_size(handle=%u, deviceNumber=%u)", handle, deviceNumber); + return devices[deviceNumber-2].descSize; +} + +s32 sys_usbd_get_descriptor(u32 handle, u8 deviceNumber, vm::ptr descriptor, s64 descSize) +{ + sys_usbd.warning("sys_usbd_get_descriptor(handle=%u, deviceNumber=%u, descriptor=0x%x, descSize=%u)", handle, deviceNumber, descriptor, descSize); + + // Just gonna have to hack it for now + + u8 device = deviceNumber-2; + unsigned char* desc = (unsigned char*)descriptor.get_ptr(); + if (device == 0) + { + unsigned char bytes[] = {0x12, 0x1, 0x0, 0x2, 0x0, 0x0, 0x0, 0x40, 0x4c, 0x5, 0x50, 0x2, 0x9, 0x0, 0x3, 0x4, 0x5, 0x1, + 0x9, 0x2, 0x20, 0x0, 0x1, 0x1, 0x0, 0x80, 0xfa, + 0x9, 0x4, 0x0, 0x0, 0x2, 0x8, 0x5, 0x50, 0x0, + 0x7, 0x5, 0x81, 0x2, 0x0, 0x2, 0x0, + 0x7, 0x5, 0x2, 0x2, 0x0, 0x2, 0x0}; + memcpy(desc, bytes, descSize); + } + else if (device == 1) + { + unsigned char bytes[] = {0x12, 0x1, 0x0, 0x2, 0xe0, 0x1, 0x1, 0x40, 0x4c, 0x5, 0x67, 0x2, 0x0, 0x1, 0x1, 0x2, 0x0, 0x1, + 0x9, 0x2, 0x34, 0x1, 0x4, 0x1, 0x0, 0xc0, 0x0, + 0x9, 0x4, 0x0, 0x0, 0x3, 0xe0, 0x1, 0x1, 0x0, + 0x7, 0x5, 0x81, 0x3, 0x40, 0x0, 0x1, + 0x7, 0x5, 0x2, 0x2, 0x0, 0x2, 0x0, + 0x7, 0x5, 0x82, 0x2, 0x0, 0x2, 0x0, + 0x9, 0x4, 0x1, 0x0, 0x2, 0xe0, 0x1, 0x1, 0x0, + 0x7, 0x5, 0x3, 0x1, 0x0, 0x0, 0x4, + 0x7, 0x5, 0x83, 0x1, 0x0, 0x0, 0x4, + 0x9, 0x4, 0x1, 0x1, 0x2, 0xe0, 0x1, 0x1, 0x0, + 0x7, 0x5, 0x3, 0x1, 0xb, 0x0, 0x4, + 0x7, 0x5, 0x83, 0x1, 0xb, 0x0, 0x4, + 0x9, 0x4, 0x1, 0x2, 0x2, 0xe0, 0x1, 0x1, 0x0, + 0x7, 0x5, 0x3, 0x1, 0x13, 0x0, 0x4, + 0x7, 0x5, 0x83, 0x1, 0x13, 0x0, 0x4, + 0x9, 0x4, 0x1, 0x3, 0x2, 0xe0, 0x1, 0x1, 0x0, + 0x7, 0x5, 0x3, 0x1, 0x1b, 0x0, 0x4, + 0x7, 0x5, 0x83, 0x1, 0x1b, 0x0, 0x4, + 0x9, 0x4, 0x1, 0x4, 0x2, 0xe0, 0x1, 0x1, 0x0, + 0x7, 0x5, 0x3, 0x1, 0x23, 0x0, 0x4, + 0x7, 0x5, 0x83, 0x1, 0x23, 0x0, 0x4, + 0x9, 0x4, 0x1, 0x5, 0x2, 0xe0, 0x1, 0x1, 0x0, + 0x7, 0x5, 0x3, 0x1, 0x33, 0x0, 0x4, + 0x7, 0x5, 0x83, 0x1, 0x33, 0x0, 0x4, + 0x9, 0x4, 0x1, 0x6, 0x2, 0xe0, 0x1, 0x1, 0x0, + 0x7, 0x5, 0x3, 0x1, 0x40, 0x0, 0x4, + 0x7, 0x5, 0x83, 0x1, 0x40, 0x0, 0x4, + 0x9, 0x4, 0x2, 0x0, 0x2, 0xe0, 0x1, 0x1, 0x0, + 0x7, 0x5, 0x4, 0x3, 0x40, 0x0, 0x1, + 0x7, 0x5, 0x85, 0x3, 0x40, 0x0, 0x1, + 0x9, 0x4, 0x2, 0x1, 0x2, 0xe0, 0x1, 0x1, 0x0, + 0x7, 0x5, 0x4, 0x3, 0x80, 0x0, 0x1, + 0x7, 0x5, 0x85, 0x3, 0x80, 0x0, 0x1, + 0x9, 0x4, 0x2, 0x2, 0x2, 0xe0, 0x1, 0x1, 0x0, + 0x7, 0x5, 0x4, 0x3, 0x0, 0x1, 0x1, + 0x7, 0x5, 0x85, 0x3, 0x0, 0x1, 0x1, + 0x9, 0x4, 0x2, 0x3, 0x2, 0xe0, 0x1, 0x1, 0x0, + 0x7, 0x5, 0x4, 0x3, 0x0, 0x4, 0x1, + 0x7, 0x5, 0x85, 0x3, 0x0, 0x4, 0x1, + 0x9, 0x4, 0x3, 0x0, 0x0, 0xfe, 0x1, 0x0, 0x0, + 0x7, 0x21, 0x7, 0x88, 0x13, 0xff, 0x3}; + + memcpy(desc, bytes, descSize); + } + else if (device == 2) + { + // USB Drive + unsigned char bytes[] = {0x12, 0x1, 0x0, 0x2, 0x0, 0x0, 0x0, 0x40, 0x16, 0x15, 0x26, 0x12, 0x0, 0x1, 0x1, 0x2, 0x3, 0x1, + 0x9, 0x2, 0x20, 0x0, 0x1, 0x1, 0x0, 0x80, 0xfa, + 0x9, 0x4, 0x0, 0x0, 0x2, 0x8, 0x6, 0x50, 0x0, + 0x7, 0x5, 0x81, 0x2, 0x0, 0x2, 0x0, + 0x7, 0x5, 0x2, 0x2, 0x0, 0x2, 0x0}; + memcpy(desc, bytes, descSize); + } + else if (device == 3 || device == 4) + { + // Skylanders Portal + unsigned char bytes[] = {0x12, 0x1, 0x0, 0x2, 0x0, 0x0, 0x0, 0x20, 0x30, 0x14, 0x50, 0x1, 0x0, 0x1, 0x1, 0x2, 0x0, 0x1, + 0x9, 0x2, 0x29, 0x0, 0x1, 0x1, 0x0, 0x80, 0x96, + 0x9, 0x4, 0x0, 0x0, 0x2, 0x3, 0x0, 0x0, 0x0, + 0x9, 0x21, 0x11, 0x1, 0x0, 0x1, 0x22, 0x1d, 0x0, + 0x7, 0x5, 0x81, 0x3, 0x20, 0x0, 0x1, + 0x7, 0x5, 0x1, 0x3, 0x20, 0x0, 0x1}; + memcpy(desc, bytes, descSize); + } + else + return -1; return CELL_OK; } @@ -51,9 +171,9 @@ s32 sys_usbd_unregister_ldd() return CELL_OK; } -s32 sys_usbd_open_pipe() +s32 sys_usbd_open_pipe(u32 handle, vm::ptr endDisc) { - sys_usbd.todo("sys_usbd_open_pipe()"); + sys_usbd.todo("sys_usbd_open_pipe(handle=%d, endDisc=0x%x)", handle, endDisc); return CELL_OK; } @@ -69,9 +189,31 @@ s32 sys_usbd_close_pipe() return CELL_OK; } -s32 sys_usbd_receive_event() +s32 sys_usbd_receive_event(ppu_thread& ppu, u32 handle, vm::ptr arg1, vm::ptr arg2, vm::ptr arg3) { - sys_usbd.todo("sys_usbd_receive_event()"); + sys_usbd.todo("sys_usbd_receive_event(handle=%u, arg1=0x%x, arg2=0x%x, arg3=0x%x)", handle, arg1, arg2, arg3); + + if (!has_register_extra_ldd) {_sys_ppu_thread_exit(ppu, CELL_OK);} + + // TODO + /*if (receive_event_called_count == 0) + { + *arg1 = 2; + *arg2 = 5; + *arg3 = 0; + receive_event_called_count++; + } + else if (receive_event_called_count == 1) + { + *arg1 = 1; + *arg2 = 6; + *arg3 = 0; + receive_event_called_count++; + } + else + { + _sys_ppu_thread_exit(ppu, CELL_OK); + }*/ return CELL_OK; } @@ -140,9 +282,3 @@ s32 sys_usbd_get_device_speed() sys_usbd.todo("sys_usbd_get_device_speed()"); return CELL_OK; } - -s32 sys_usbd_register_extra_ldd() -{ - sys_usbd.todo("sys_usbd_register_extra_ldd()"); - return CELL_OK; -} diff --git a/rpcs3/Emu/Cell/lv2/sys_usbd.h b/rpcs3/Emu/Cell/lv2/sys_usbd.h index b01bb51f15..c31da5700f 100644 --- a/rpcs3/Emu/Cell/lv2/sys_usbd.h +++ b/rpcs3/Emu/Cell/lv2/sys_usbd.h @@ -1,18 +1,54 @@ #pragma once +namespace vm { using namespace ps3; } + // SysCalls -s32 sys_usbd_initialize(); +struct DeviceListUnknownDataType +{ + u8 unk1; + u8 deviceID; + u8 unk3; + u8 unk4; +} ; + +/* 0x01 device descriptor */ +struct deviceDescriptor +{ + u8 bLength; /* descriptor size in bytes */ + u8 bDescriptorType; /* constant USB_DESCRIPTOR_TYPE_DEVICE */ + u16 bcdUSB; /* USB spec release compliance number */ + u8 bDeviceClass; /* class code */ + u8 bDeviceSubClass; /* subclass code */ + u8 bDeviceProtocol; /* protocol code */ + u8 bMaxPacketSize0; /* max packet size for endpoint 0 */ + u16 idVendor; /* USB-IF Vendor ID (VID) */ + u16 idProduct; /* Product ID (PID) */ + u16 bcdDevice; /* device release number */ + u8 iManufacturer; /* manufacturer string descriptor index */ + u8 iProduct; /* product string desccriptor index */ + u8 iSerialNumber; /* serial number string descriptor index */ + u8 bNumConfigurations; /* number of configurations */ +}; + +struct usbDevice +{ + DeviceListUnknownDataType basicDevice; + s32 descSize; + deviceDescriptor descriptor; +}; + +s32 sys_usbd_initialize(vm::ptr handle); s32 sys_usbd_finalize(); -s32 sys_usbd_get_device_list(); -s32 sys_usbd_get_descriptor_size(); -s32 sys_usbd_get_descriptor(); +s32 sys_usbd_get_device_list(u32 handle, vm::ptr device_list, char unknown); +s32 sys_usbd_get_descriptor_size(u32 handle, u8 deviceNumber); +s32 sys_usbd_get_descriptor(u32 handle, u8 deviceNumber, vm::ptr descriptor, s64 descSize); s32 sys_usbd_register_ldd(); s32 sys_usbd_unregister_ldd(); -s32 sys_usbd_open_pipe(); +s32 sys_usbd_open_pipe(u32 handle, vm::ptr endDisc); s32 sys_usbd_open_default_pipe(); s32 sys_usbd_close_pipe(); -s32 sys_usbd_receive_event(); +s32 sys_usbd_receive_event(ppu_thread& ppu, u32 handle, vm::ptr arg1, vm::ptr arg2, vm::ptr arg3); s32 sys_usbd_detect_event(); s32 sys_usbd_attach(); s32 sys_usbd_transfer_data(); @@ -24,4 +60,4 @@ s32 sys_usbd_send_event(); s32 sys_usbd_allocate_memory(); s32 sys_usbd_free_memory(); s32 sys_usbd_get_device_speed(); -s32 sys_usbd_register_extra_ldd(); +s32 sys_usbd_register_extra_ldd(u32 handle, vm::ptr lddOps, u16 strLen, u16 vendorID, u16 productID, u16 unk1);