#include "stdafx.h" #include "sys_hid.h" #include "Emu/Memory/vm_var.h" #include "Emu/Cell/ErrorCodes.h" #include "Emu/Cell/PPUThread.h" #include "rpcsx/fw/ps3/cellPad.h" #include "sys_process.h" LOG_CHANNEL(sys_hid); error_code sys_hid_manager_open(ppu_thread &ppu, u64 device_type, u64 port_no, vm::ptr handle) { sys_hid.todo("sys_hid_manager_open(device_type=0x%llx, port_no=0x%llx, " "handle=*0x%llx)", device_type, port_no, handle); // device type == 1 = pad, 2 = kb, 3 = mouse if (device_type > 3) { return CELL_EINVAL; } if (!handle) { return CELL_EFAULT; } // 'handle' starts at 0x100 in realhw, and increments every time // sys_hid_manager_open is called however, sometimes the handle is reused when // opening sys_hid_manager again (even when the previous one hasn't been // closed yet) - maybe when processes/threads get killed/finish they also // release their handles? static u32 ctr = 0x100; *handle = ctr++; if (device_type == 1) { cellPadInit(ppu, 7); cellPadSetPortSetting(::narrow(port_no) /* 0 */, CELL_PAD_SETTING_LDD | CELL_PAD_SETTING_PRESS_ON | CELL_PAD_SETTING_SENSOR_ON); } return CELL_OK; } error_code sys_hid_manager_ioctl(u32 hid_handle, u32 pkg_id, vm::ptr buf, u64 buf_size) { sys_hid.todo("sys_hid_manager_ioctl(hid_handle=0x%x, pkg_id=0x%llx, " "buf=*0x%x, buf_size=0x%llx)", hid_handle, pkg_id, buf, buf_size); // clang-format off // From realhw syscall dump when vsh boots // SC count | handle | pkg_id | *buf (in) | *buf (out) | size -> ret // ---------|--------|--------|---------------------------------------------------------------------------|---------------------------------------------------------------------------|------------ // 28893 | 0x101 | 0x2 | 000000000000000000000000000000000000000000 | 054c02680102020000000000000008035000001c1f | 21 -> 0 // 28894 | 0x101 | 0x3 | 00000000 | 00000000 | 4 -> 0 // 28895 | 0x101 | 0x5 | 00000000 | 00000000 | 4 -> 0 // 28896 | 0x101 | 0x68 | 01000000d0031cb020169e502006b7f80000000000606098000000000000000000000000d | 01000000d0031cb020169e502006b7f80000000000606098000000000000000000000000d | 64 -> 0 // | | | 0031c90000000002006bac400000000d0031cb0000000002006b4d0 | 0031c90000000002006bac400000000d0031cb0000000002006b4d0 | // 28898 | 0x102 | 0x2 | 000000000000000000000000000000000000000000 | 054c02680102020000000000000008035000001c1f | 21 -> 0 // 28901 | 0x100 | 0x64 | 00000001 | 00000001 | 4 -> 0xffffffff80010002 # x3::hidportassign // 2890 | 0x100 | 0x65 | 6b49d200 | 6b49d200 | 4 -> 0xffffffff80010002 # x3::hidportassign // 28903 | 0x100 | 0x66 | 00000001 | 00000001 | 4 -> 0 # x3::hidportassign // 28904 | 0x100 | 0x0 | 00000001000000ff000000ff000000ff000000ff000000010000000100000001000000010 | 00000001000000ff000000ff000000ff000000ff000000010000000100000001000000010 | 68 -> 0 # x3::hidportassign // | | | 000000000000000000000000000000000000001000000010000000100000001 | 000000000000000000000000000000000000001000000010000000100000001 | // 28907 | 0x101 | 0x3 | 00000001 | 00000001 | 4 -> 0 // 28908 | 0x101 | 0x5 | 00000001 | 00000001 | 4 -> 0 // 29404 | 0x100 | 0x4 | 00 | ee | 1 -> 0 // *** repeats 30600, 31838, 33034, 34233, 35075 (35075 is x3::hidportassign) *** // 35076 | 0x100 | 0x0 | 00000001000000ff000000ff000000ff000000ff000000320000003200000032000000320 | 00000001000000ff000000ff000000ff000000ff000000320000003200000032000000320 | 68 -> 0 // | | | 000003200000032000000320000003200002710000027100000271000002710 | 000003200000032000000320000003200002710000027100000271000002710 | // *** more 0x4 that have buf(in)=00 and buf(out)=ee *** // clang-format on if (pkg_id == 2) { // Return what realhw seems to return // TODO: Figure out what this corresponds to auto info = vm::static_ptr_cast(buf); info->vid = 0x054C; info->pid = 0x0268; u8 realhw[17] = {0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x03, 0x50, 0x00, 0x00, 0x1c, 0x1f}; memcpy(info->unk, &realhw, 17); } else if (pkg_id == 5) { auto info = vm::static_ptr_cast(buf); info->vid = 0x054C; info->pid = 0x0268; } // pkg_id == 6 == setpressmode? else if (pkg_id == 0x68) { [[maybe_unused]] auto info = vm::static_ptr_cast(buf); // info->unk2 = 0; } return CELL_OK; } error_code sys_hid_manager_check_focus() { // spammy sys_hid.todo("sys_hid_manager_check_focus()"); return not_an_error(1); } error_code sys_hid_manager_513(u64 a1, u64 a2, vm::ptr buf, u64 buf_size) { sys_hid.todo("sys_hid_manager_513(%llx, %llx, buf=%llx, buf_size=%llx)", a1, a2, buf, buf_size); return CELL_OK; } error_code sys_hid_manager_514(u32 pkg_id, vm::ptr buf, u64 buf_size) { if (pkg_id == 0xE) { sys_hid.trace( "sys_hid_manager_514(pkg_id=0x%x, buf=*0x%x, buf_size=0x%llx)", pkg_id, buf, buf_size); } else { sys_hid.todo("sys_hid_manager_514(pkg_id=0x%x, buf=*0x%x, buf_size=0x%llx)", pkg_id, buf, buf_size); } if (pkg_id == 0xE) { // buf holds device_type // auto device_type = vm::static_ptr_cast(buf); // spammy sys_hid.todo("device_type: 0x%x", device_type[0]); // return 1 or 0? look like almost like another check_focus type check, // returning 0 looks to keep system focus } else if (pkg_id == 0xD) { auto inf = vm::static_ptr_cast(buf); // unk1 = (pad# << 24) | pad# | 0x100 // return value doesn't seem to be used again sys_hid.todo("unk1: 0x%x, unk2:0x%x", inf->unk1, inf->unk2); } return CELL_OK; } error_code sys_hid_manager_is_process_permission_root(u32 pid) { sys_hid.todo("sys_hid_manager_is_process_permission_root(pid=0x%x)", pid); return not_an_error(g_ps3_process_info.has_root_perm()); } error_code sys_hid_manager_add_hot_key_observer(u32 event_queue, vm::ptr unk) { sys_hid.todo( "sys_hid_manager_add_hot_key_observer(event_queue=0x%x, unk=*0x%x)", event_queue, unk); return CELL_OK; } error_code sys_hid_manager_read(u32 handle, u32 pkg_id, vm::ptr buf, u64 buf_size) { if (!buf) { return CELL_EFAULT; } (pkg_id == 2 || pkg_id == 0x81 ? sys_hid.trace : sys_hid.todo)( "sys_hid_manager_read(handle=0x%x, pkg_id=0x%x, buf=*0x%x, " "buf_size=0x%llx)", handle, pkg_id, buf, buf_size); if (pkg_id == 2) { // cellPadGetData // it returns just button array from 'CellPadData' // auto data = vm::static_ptr_cast(buf); // todo: use handle and dont call cellpad here vm::var tmpData; if ((cellPadGetData(0, +tmpData) == CELL_OK) && tmpData->len > 0) { u64 cpySize = std::min(static_cast(tmpData->len) * sizeof(u16), buf_size * sizeof(u16)); memcpy(buf.get_ptr(), &tmpData->button, cpySize); return not_an_error(cpySize); } } else if (pkg_id == 0x81) { // cellPadGetDataExtra? vm::var tmpData; if ((cellPadGetData(0, +tmpData) == CELL_OK) && tmpData->len > 0) { u64 cpySize = std::min(static_cast(tmpData->len) * sizeof(u16), buf_size * sizeof(u16)); memcpy(buf.get_ptr(), &tmpData->button, cpySize); return not_an_error(cpySize / 2); } } return CELL_OK; }