From f5c7f61ed355c96e82c3c25e37d95a20bf4a345a Mon Sep 17 00:00:00 2001 From: masken Date: Sun, 7 Sep 2008 18:54:33 +0000 Subject: [PATCH] Wiimote: added a bunch of HID packet handling. LogManager: removed double line breaks in Win32 log files. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@469 8ced0084-cf51-0410-be5f-012b33b47a6e --- .../Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp | 3 +- .../Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp | 182 +++++++++++++++++- .../Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.h | 17 ++ Source/Core/Core/Src/IPC_HLE/wiimote_hid.h | 73 +++++++ Source/Core/Core/Src/LogManager.cpp | 42 ++-- 5 files changed, 286 insertions(+), 31 deletions(-) create mode 100644 Source/Core/Core/Src/IPC_HLE/wiimote_hid.h diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp index 01a6cfbbb3..efb360c409 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp @@ -25,6 +25,7 @@ CWII_IPC_HLE_Device_usb_oh1_57e_305::CWII_IPC_HLE_Device_usb_oh1_57e_305(u32 _De , m_pHCIBuffer(NULL) , m_State(STATE_NONE) , scan_enable(0) +, m_DelayedEvent(EVENT_NONE) { m_WiiMotes.push_back(CWII_IPC_HLE_WiiMote(this, 0)); @@ -341,7 +342,7 @@ u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update() SendEventConnectionComplete(); break; default: - PanicAlert("Unknown Event in USBDev"); + PanicAlert("Unknown Event in USBDev: %i", m_DelayedEvent); } m_DelayedEvent = EVENT_NONE; diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp index 13371918d8..290d7c2ed6 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp @@ -19,6 +19,7 @@ #include "WII_IPC_HLE_WiiMote.h" #include "l2cap.h" +#include "wiimote_hid.h" #if defined(_MSC_VER) #pragma pack(push, 1) @@ -28,7 +29,8 @@ #define HIDP_OUTPUT_CHANNEL 0x11 #define HIDP_INPUT_CHANNEL 0x13 - +#define HID_OUTPUT_SCID 0x1234 +#define HID_INPUT_SCID 0x5678 struct SL2CAP_Header @@ -117,11 +119,29 @@ struct SL2CAP_CommandConfigurationResponse // 0x05 #pragma pack(pop) #endif +static const u8 EepromData_0[] = { + 0xA1, 0xAA, 0x8B, 0x99, 0xAE, 0x9E, 0x78, 0x30, + 0xA7, 0x74, 0xD3, 0xA1, 0xAA, 0x8B, 0x99, 0xAE, + 0x9E, 0x78, 0x30, 0xA7, 0x74, 0xD3, 0x82, 0x82, + 0x82, 0x15, 0x9C, 0x9C, 0x9E, 0x38, 0x40, 0x3E, + 0x82, 0x82, 0x82, 0x15, 0x9C, 0x9C, 0x9E, 0x38, + 0x40, 0x3E +}; + +static const u8 EepromData_16D0[] = { + 0x00, 0x00, 0x00, 0xFF, 0x11, 0xEE, 0x00, 0x00, + 0x33, 0xCC, 0x44, 0xBB, 0x00, 0x00, 0x66, 0x99, + 0x77, 0x88, 0x00, 0x00, 0x2B, 0x01, 0xE8, 0x13 +}; CWII_IPC_HLE_WiiMote::CWII_IPC_HLE_WiiMote(CWII_IPC_HLE_Device_usb_oh1_57e_305* _pHost, int _Number) : m_Name("Nintendo RVL-CNT-01") , m_pHost(_pHost) { + memset(m_Eeprom, 0, WIIMOTE_EEPROM_SIZE); + memcpy(m_Eeprom, EepromData_0, sizeof(EepromData_0)); + memcpy(m_Eeprom + 0x16D0, EepromData_16D0, sizeof(EepromData_16D0)); + m_BD.b[0] = 0x11; m_BD.b[1] = 0x02; m_BD.b[2] = 0x19; @@ -163,14 +183,21 @@ void CWII_IPC_HLE_WiiMote::SendACLFrame(u8* _pData, u32 _Size) // parse the command SL2CAP_Header* pHeader = (SL2CAP_Header*)_pData; u8* pData = _pData + sizeof(SL2CAP_Header); - u32 DataSize = _Size -sizeof(SL2CAP_Header); + u32 DataSize = _Size - sizeof(SL2CAP_Header); - switch (pHeader->CID) + LOG(WIIMOTE, "L2Cap-SendFrame: Len 0x%x, Channel 0x%04x", + pHeader->Length, pHeader->CID); + + _dbg_assert_(WIIMOTE, pHeader->Length == DataSize); + + switch (pHeader->CID) { case 0x0001: - LOG(WIIMOTE, "L2Cap-SendFrame: SignalChannel (0x%04x)", pHeader->CID); SignalChannel(pData, DataSize); break; + case HID_OUTPUT_SCID: + HidOutput(pData, DataSize); + break; default: PanicAlert("SendACLFrame to unknown channel"); @@ -206,8 +233,8 @@ void CWII_IPC_HLE_WiiMote::SendCommandToACL(u8 _Ident, u8 _Code, u8 _CommandLeng } void CWII_IPC_HLE_WiiMote::Connect() { - SendConnectionRequest(0x1234, HIDP_OUTPUT_CHANNEL); - SendConnectionRequest(0x5678, HIDP_INPUT_CHANNEL); + SendConnectionRequest(HID_OUTPUT_SCID, HIDP_OUTPUT_CHANNEL); + SendConnectionRequest(HID_INPUT_SCID, HIDP_INPUT_CHANNEL); } void CWII_IPC_HLE_WiiMote::SendConnectionRequest(u16 scid, u16 psm) { @@ -273,9 +300,13 @@ void CWII_IPC_HLE_WiiMote::SignalChannel(u8* _pData, u32 _Size) CommandCofigurationResponse(pCommand->ident, _pData, pCommand->len); break; + case L2CAP_COMMAND_REJ: + PanicAlert("SignalChannel - L2CAP_COMMAND_REJ (something went wrong)",pCommand->code); + break; + default: - PanicAlert("SignalChannel %x",pCommand->code); LOG(WIIMOTE, " Unknown Command-Code (0x%02x)", pCommand->code); + PanicAlert("SignalChannel %x",pCommand->code); return; } @@ -283,6 +314,143 @@ void CWII_IPC_HLE_WiiMote::SignalChannel(u8* _pData, u32 _Size) } } + +void CWII_IPC_HLE_WiiMote::HidOutput(u8* _pData, u32 _Size) +{ + // dump raw data + { + LOG(WIIMOTE, "HidOutput"); + std::string Temp; + for (u32 j=0; j<_Size; j++) + { + char Buffer[128]; + sprintf(Buffer, "%02x ", _pData[j]); + Temp.append(Buffer); + } + LOG(WIIMOTE, " Data: %s", Temp.c_str()); + } + + hid_packet* hidp = (hid_packet*) _pData; + + if(hidp->type == HID_TYPE_SET_REPORT && + hidp->param == HID_PARAM_OUTPUT) + { + HidOutputReport((wm_report*)hidp->data); + } else if(hidp->type == HID_TYPE_HANDSHAKE && + hidp->param == HID_HANDSHAKE_WIIMOTE) + { + PanicAlert("HidOutput: Wiimote handshake?"); + } else { + PanicAlert("HidOutput: Unknown type 0x%02x", _pData[0]); + } + + //return handshake + hid_packet handshake; + handshake.type = HID_TYPE_HANDSHAKE; + handshake.param = HID_HANDSHAKE_SUCCESS; + SendL2capData(HID_OUTPUT_SCID, &handshake, 1); +} + +static u32 convert24bit(const u8* src) { + return (src[0] << 16) | (src[1] << 8) | src[2]; +} + +static u16 convert16bit(const u8* src) { + return (src[0] << 8) | src[1]; +} + +void CWII_IPC_HLE_WiiMote::HidOutputReport(wm_report* sr) { + LOG(WIIMOTE, " HidOutputReport(0x%02x)", sr->channel); + + switch(sr->channel) + { + case WM_LEDS: + WmLeds((wm_leds*)sr->data); + break; + case WM_READ_DATA: + WmReadData((wm_read_data*)sr->data); + break; + + default: + PanicAlert("HidOutputReport: Unknown channel 0x%02x", sr->channel); + return; + } +} + +void CWII_IPC_HLE_WiiMote::WmLeds(wm_leds* leds) { + LOG(WIIMOTE, " Set LEDs"); + LOG(WIIMOTE, " Leds: %x", leds->leds); + LOG(WIIMOTE, " Rumble: %x", leds->rumble); +} + +void CWII_IPC_HLE_WiiMote::WmReadData(wm_read_data* rd) { + u32 address = convert24bit(rd->address); + u16 size = convert16bit(rd->size); + LOG(WIIMOTE, " Read data"); + LOG(WIIMOTE, " Address space: %x", rd->space); + LOG(WIIMOTE, " Address: 0x%06x", address); + LOG(WIIMOTE, " Size: 0x%04x", size); + LOG(WIIMOTE, " Rumble: %x", rd->rumble); + + if(size <= 16 && rd->space == 0) { + SendReadDataReply(m_Eeprom, address, (u8)size); + } else { + //TODO: return input reports, fragmented and padded on 16 bytes of data. + PanicAlert("WmReadData: unimplemented parameters!"); + } +} + +void CWII_IPC_HLE_WiiMote::SendReadDataReply(void* _Base, u16 _Address, u8 _Size) +{ + u8 DataFrame[1024]; + u32 Offset = 0; + + hid_packet* pHidHeader = (hid_packet*)(DataFrame + Offset); + Offset += sizeof(hid_packet); + pHidHeader->type = HID_TYPE_DATA; + pHidHeader->param = HID_PARAM_INPUT; + + wm_report* pReport = (wm_report*)(DataFrame + Offset); + Offset += sizeof(wm_report); + pReport->channel = WM_READ_DATA_REPLY; + + _dbg_assert_(WIIMOTE, _Size <= 16); + + wm_read_data_reply* pReply = (wm_read_data_reply*)(DataFrame + Offset); + Offset += sizeof(wm_read_data_reply); + pReply->buttons = 0; + pReply->error = 0; + pReply->size = _Size; + pReply->address = Common::swap16(_Address); + memcpy(pReply->data, _Base, _Size); + if(_Size < 16) { + memset(pReply->data + _Size, 0, 16 - _Size); + } + SendL2capData(HID_INPUT_SCID, DataFrame, Offset); +} + +void CWII_IPC_HLE_WiiMote::SendL2capData(u16 scid, void* _pData, u32 _Size) +{ + //allocate + u8 DataFrame[1024]; + u32 Offset = 0; + SL2CAP_Header* pHeader = (SL2CAP_Header*)DataFrame; + Offset += sizeof(SL2CAP_Header); + + _dbg_assert_(WIIMOTE, DoesChannelExist(scid)); + SChannel& rChannel = m_Channel[scid]; + + //assemble + pHeader->CID = rChannel.DCID; + pHeader->Length = _Size; + + memcpy(DataFrame + Offset, _pData, _Size); + Offset += _Size; + + //send + m_pHost->SendACLFrame(GetConnectionHandle(), DataFrame, Offset); +} + void CWII_IPC_HLE_WiiMote::CommandConnectionReq(u8 _Ident, u8* _pData, u32 _Size) { SL2CAP_CommandConnectionReq* pCommandConnectionReq = (SL2CAP_CommandConnectionReq*)_pData; diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.h b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.h index d60760e828..5f8f05f853 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.h +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.h @@ -20,7 +20,13 @@ #include #include "WII_IPC_HLE_Device_usb.h" +#define WIIMOTE_EEPROM_SIZE (16*1024) + class CWII_IPC_HLE_Device_usb_oh1_57e_305; +struct wm_report; +struct wm_leds; +struct wm_read_data; + class CWII_IPC_HLE_WiiMote { public: @@ -55,6 +61,8 @@ private: u8 features[HCI_FEATURES_SIZE]; + u8 m_Eeprom[WIIMOTE_EEPROM_SIZE]; + std::string m_Name; CWII_IPC_HLE_Device_usb_oh1_57e_305* m_pHost; @@ -76,13 +84,22 @@ private: return m_Channel.find(_SCID) != m_Channel.end(); } + void SendL2capData(u16 scid, void* _pData, u32 _Size); void SendCommandToACL(u8 _Ident, u8 _Code, u8 _CommandLength, u8* _pCommandData); void SignalChannel(u8* _pData, u32 _Size); + void HidOutput(u8* _pData, u32 _Size); + + void HidOutputReport(wm_report* sr); + + void WmLeds(wm_leds* leds); + void WmReadData(wm_read_data* leds); + void SendConnectionRequest(u16 scid, u16 psm); void SendConfigurationRequest(u16 scid); + void SendReadDataReply(void* _Base, u16 _Address, u8 _Size); void CommandConnectionReq(u8 _Ident, u8* _pData, u32 _Size); void CommandCofigurationReq(u8 _Ident, u8* _pData, u32 _Size); diff --git a/Source/Core/Core/Src/IPC_HLE/wiimote_hid.h b/Source/Core/Core/Src/IPC_HLE/wiimote_hid.h new file mode 100644 index 0000000000..9f8d910a55 --- /dev/null +++ b/Source/Core/Core/Src/IPC_HLE/wiimote_hid.h @@ -0,0 +1,73 @@ +#ifndef WIIMOTE_HID_H +#define WIIMOTE_HID_H + +#include + +#ifdef _MSC_VER +#pragma warning(disable:4200) +#pragma pack(push, 1) +#endif + +//source: HID_010_SPC_PFL/1.0 (official HID specification) + +struct hid_packet { + u8 param : 4; + u8 type : 4; + u8 data[0]; +}; + +#define HID_TYPE_SET_REPORT 5 +#define HID_TYPE_DATA 0xA + +#define HID_TYPE_HANDSHAKE 0 +#define HID_HANDSHAKE_SUCCESS 0 +#define HID_HANDSHAKE_WIIMOTE 8 //custom, reserved in HID specs. + +#define HID_PARAM_INPUT 1 +#define HID_PARAM_OUTPUT 2 + +//source: http://wiibrew.org/wiki/Wiimote + +struct wm_report { + u8 channel; + u8 data[0]; +}; + +#define WM_LEDS 0x11 +struct wm_leds { + u8 rumble : 1; + u8 : 3; + u8 leds : 4; +}; + +#define WM_READ_DATA 0x17 +struct wm_read_data { + u8 rumble : 1; + u8 space : 2; //see WM_SPACE_* + u8 : 5; + u8 address[3]; + u8 size[2]; +}; + +#define WM_SPACE_EEPROM 0 +#define WM_SPACE_REGS1 1 +#define WM_SPACE_REGS2 2 +#define WM_SPACE_INVALID 3 + +#define WM_READ_DATA_REPLY 0x21 +struct wm_read_data_reply { + u16 buttons; + u8 error : 4; //see WM_RDERR_* + u8 size : 4; + u16 address; + u8 data[16]; +}; + +#define WM_RDERR_WOREG 7 +#define WM_RDERR_NOMEM 8 + +#if defined(_MSC_VER) +#pragma pack(pop) +#endif + +#endif //WIIMOTE_HID_H diff --git a/Source/Core/Core/Src/LogManager.cpp b/Source/Core/Core/Src/LogManager.cpp index 6d2e497e61..dc07f58e53 100644 --- a/Source/Core/Core/Src/LogManager.cpp +++ b/Source/Core/Core/Src/LogManager.cpp @@ -66,7 +66,7 @@ CDebugger_Log::~CDebugger_Log(void) void CDebugger_Log::Init() { - m_pFile = fopen(m_szFilename, "wt"); + m_pFile = fopen(m_szFilename, "wtb"); } void CDebugger_Log::Shutdown() @@ -163,39 +163,35 @@ void LogManager::Log(LogTypes::LOG_TYPE _type, const char *_fmt, ...) SMessage& Message = m_Messages[m_nextMessages]; - static u32 count = 0; + static u32 count = 0; - char* Msg2 = (char*)alloca(strlen(_fmt)+512); + char* Msg2 = (char*)alloca(strlen(_fmt)+512); int Index = 0; //Debugger::FindSymbol(PC); -#ifdef _WIN32 - const char *eol = "\x0D\x0A"; -#else const char *eol = "\n"; -#endif - if (Index > 0) - { - // const Debugger::Symbol& symbol = Debugger::GetSymbol(Index); + if (Index > 0) + { + // const Debugger::Symbol& symbol = Debugger::GetSymbol(Index); sprintf(Msg2, "%i: %x %s (%s, %08x ) : %s%s", - ++count, - PowerPC::ppcState.DebugCount, - m_Log[_type]->m_szShortName, - "", //symbol.GetName().c_str(), - PC, - Msg, eol); - } - else - { + ++count, + PowerPC::ppcState.DebugCount, + m_Log[_type]->m_szShortName, + "", //symbol.GetName().c_str(), + PC, + Msg, eol); + } + else + { sprintf(Msg2, "%i: %x %s ( %08x ) : %s%s", ++count, PowerPC::ppcState.DebugCount, m_Log[_type]->m_szShortName, PC, Msg, eol); - } + } Message.Set(_type, Msg2); if (m_Log[_type]->m_pFile && m_Log[_type]->m_bLogToFile) - fprintf(m_Log[_type]->m_pFile, Msg2); + fprintf(m_Log[_type]->m_pFile, "%s", Msg2); if (m_Log[LogTypes::MASTER_LOG] && m_Log[LogTypes::MASTER_LOG]->m_pFile && m_Log[_type]->m_bShowInLog) - fprintf(m_Log[LogTypes::MASTER_LOG]->m_pFile, Msg2); - + fprintf(m_Log[LogTypes::MASTER_LOG]->m_pFile, "%s", Msg2); + printf("%s", Msg2); m_nextMessages++;