wiimote emulation improvements... wpad tries now to read out the HID attribs per SDP

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@902 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
fires.gc 2008-10-17 18:01:13 +00:00
parent 469310dc14
commit 636dfdd177
11 changed files with 1066 additions and 543 deletions

View File

@ -1344,6 +1344,14 @@
RelativePath=".\Src\VolumeHandler.h" RelativePath=".\Src\VolumeHandler.h"
> >
</File> </File>
<File
RelativePath=".\Src\IPC_HLE\WiiMote_HID_Attr.cpp"
>
</File>
<File
RelativePath=".\Src\IPC_HLE\WiiMote_HID_Attr.h"
>
</File>
</Files> </Files>
<Globals> <Globals>
</Globals> </Globals>

File diff suppressed because it is too large Load Diff

View File

@ -41,6 +41,22 @@ union UACLHeader
u32 Hex; u32 Hex;
}; };
struct SQueuedEvent
{
u8 m_buffer[1024];
size_t m_size;
SQueuedEvent(size_t size) :
m_size(size)
{}
};
struct ACLFrame
{
u16 ConnectionHandle;
u8* data;
u32 size;
};
class CWII_IPC_HLE_Device_usb_oh1_57e_305 : public IWII_IPC_HLE_Device class CWII_IPC_HLE_Device_usb_oh1_57e_305 : public IWII_IPC_HLE_Device
{ {
public: public:
@ -60,6 +76,15 @@ public:
private: private:
typedef std::queue<SQueuedEvent> CEventQueue;
CEventQueue m_EventQueue;
void AddEventToQueue(const SQueuedEvent& _event)
{
m_EventQueue.push(_event);
}
enum enum
{ {
USB_IOCTL_HCI_COMMAND_MESSAGE = 0, USB_IOCTL_HCI_COMMAND_MESSAGE = 0,
@ -95,10 +120,9 @@ private:
// STATE_TO_SAVE // STATE_TO_SAVE
std::queue<SHCICommandMessage> m_HCICommandMessageQueue; std::queue<SHCICommandMessage> m_HCICommandMessageQueue;
std::queue<ACLFrame> m_AclFrameQue;
bool m_ACLAnswer;
SIOCtlVBuffer* m_pACLBuffer; SIOCtlVBuffer* m_pACLBuffer;
SIOCtlVBuffer* m_pHCIBuffer; SIOCtlVBuffer* m_pHCIBuffer;
bool SendEventCommandStatus(u16 _Opcode); bool SendEventCommandStatus(u16 _Opcode);
@ -107,12 +131,14 @@ private:
bool SendEventInquiryResponse(); bool SendEventInquiryResponse();
bool SendEventInquiryComplete(); bool SendEventInquiryComplete();
bool SendEventRemoteNameReq(); bool SendEventRemoteNameReq(bdaddr_t _bd);
bool SendEventRequestConnection(); bool SendEventRequestConnection();
bool SendEventConnectionComplete(); bool SendEventConnectionComplete(bdaddr_t _bd);
bool SendEventReadClockOffsetComplete(); bool SendEventReadClockOffsetComplete(u16 _connectionHandle);
bool SendEventReadRemoteVerInfo(); bool SendEventReadRemoteVerInfo(u16 _connectionHandle);
bool SendEventReadRemoteFeatures(); bool SendEventReadRemoteFeatures(u16 _connectionHandle);
bool SendEventRoleChange(bdaddr_t _bd);
bool SendEventNumberOfCompletedPackets(u16 _connectionHandle);
void ExecuteHCICommandMessage(const SHCICommandMessage& _rCtrlMessage); void ExecuteHCICommandMessage(const SHCICommandMessage& _rCtrlMessage);
@ -147,45 +173,10 @@ private:
void SendToDevice(u16 _ConnectionHandle, u8* _pData, u32 _Size); void SendToDevice(u16 _ConnectionHandle, u8* _pData, u32 _Size);
enum EState
{
STATE_NONE,
STATE_INQUIRY_RESPONSE,
STATE_INQUIRY_COMPLETE,
STATE_START_REMOTE_NAME_REQ,
STATE_REMOTE_NAME_REQ,
STATE_CONNECTION_COMPLETE_EVENT,
STATE_READ_CLOCK_OFFSET,
STATE_READ_REMOTE_VER_INFO,
STATE_READ_REMOTE_FEATURES,
STATE_CONNECT_WIIMOTE
};
EState m_State;
u32 m_UpdateWaitCount; u32 m_UpdateWaitCount;
bdaddr_t m_StateTempBD;
u16 m_StateTempConnectionHandle;
struct ACLFrame {
u16 ConnectionHandle;
u8* data;
u32 size;
};
std::queue<ACLFrame> m_AclFrameQue;
u8 scan_enable; u8 scan_enable;
//TODO: get rid of these, integrate into EState.
enum EDelayedEvent
{
EVENT_NONE,
EVENT_REQUEST_CONNECTION,
EVENT_CONNECTION_COMPLETE
};
EDelayedEvent m_DelayedEvent;
void SetDelayedEvent(EDelayedEvent e);
bdaddr_t m_ControllerBD; bdaddr_t m_ControllerBD;
u8 m_ClassOfDevice[HCI_CLASS_SIZE]; u8 m_ClassOfDevice[HCI_CLASS_SIZE];
char m_LocalName[HCI_UNIT_NAME_SIZE]; char m_LocalName[HCI_UNIT_NAME_SIZE];
@ -203,8 +194,6 @@ public: //hack for wiimote plugin
std::vector<CWII_IPC_HLE_WiiMote> m_WiiMotes; std::vector<CWII_IPC_HLE_WiiMote> m_WiiMotes;
CWII_IPC_HLE_WiiMote* AccessWiiMote(const bdaddr_t& _rAddr); CWII_IPC_HLE_WiiMote* AccessWiiMote(const bdaddr_t& _rAddr);
CWII_IPC_HLE_WiiMote* AccessWiiMote(u16 _ConnectionHandle); CWII_IPC_HLE_WiiMote* AccessWiiMote(u16 _ConnectionHandle);
void ClearBD(bdaddr_t& _rAddr);
}; };
#endif #endif

View File

@ -20,6 +20,7 @@
#include "WII_IPC_HLE_WiiMote.h" #include "WII_IPC_HLE_WiiMote.h"
#include "l2cap.h" #include "l2cap.h"
#include "WiiMote_HID_Attr.h"
#if defined(_MSC_VER) #if defined(_MSC_VER)
#pragma pack(push, 1) #pragma pack(push, 1)
@ -29,10 +30,13 @@
#define HIDP_OUTPUT_CHANNEL 0x11 #define HIDP_OUTPUT_CHANNEL 0x11
#define HIDP_INPUT_CHANNEL 0x13 #define HIDP_INPUT_CHANNEL 0x13
#define HID_OUTPUT_SCID 0x1234 // #define HID_OUTPUT_SCID 0x1234
#define HID_INPUT_SCID 0x5678 // #define HID_INPUT_SCID 0x5678
#define HID_OUTPUT_SCID 0x0040
#define HID_INPUT_SCID 0x0040
struct SL2CAP_Header struct SL2CAP_Header
{ {
u16 Length; u16 Length;
@ -128,8 +132,8 @@ namespace Core {
} }
CWII_IPC_HLE_WiiMote::CWII_IPC_HLE_WiiMote(CWII_IPC_HLE_Device_usb_oh1_57e_305* _pHost, int _Number) 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_Name("Nintendo RVL-CNT-01")
, m_pHost(_pHost) , m_pHost(_pHost)
{ {
s_Usb = _pHost; s_Usb = _pHost;
LOG(WIIMOTE, "Wiimote %i constructed", _Number); LOG(WIIMOTE, "Wiimote %i constructed", _Number);
@ -143,9 +147,9 @@ CWII_IPC_HLE_WiiMote::CWII_IPC_HLE_WiiMote(CWII_IPC_HLE_Device_usb_oh1_57e_305*
m_ControllerConnectionHandle = 0x100 + _Number; m_ControllerConnectionHandle = 0x100 + _Number;
uclass[0]= 0x04; uclass[0]= 0x00;
uclass[1]= 0x25; uclass[1]= 0x04;
uclass[2]= 0x00; uclass[2]= 0x48;
features[0] = 0xBC; features[0] = 0xBC;
features[1] = 0x02; features[1] = 0x02;
@ -155,6 +159,9 @@ CWII_IPC_HLE_WiiMote::CWII_IPC_HLE_WiiMote(CWII_IPC_HLE_Device_usb_oh1_57e_305*
features[5] = 0x00; features[5] = 0x00;
features[6] = 0x00; features[6] = 0x00;
features[7] = 0x00; features[7] = 0x00;
lmp_version = 0x2;
lmp_subversion = 0x229;
} }
void CWII_IPC_HLE_WiiMote::SendACLFrame(u8* _pData, u32 _Size) void CWII_IPC_HLE_WiiMote::SendACLFrame(u8* _pData, u32 _Size)
@ -190,12 +197,32 @@ void CWII_IPC_HLE_WiiMote::SendACLFrame(u8* _pData, u32 _Size)
case 0x0001: case 0x0001:
SignalChannel(pData, DataSize); SignalChannel(pData, DataSize);
break; break;
case HID_OUTPUT_SCID:
HidOutput(pData, DataSize);
break;
default: default:
PanicAlert("SendACLFrame to unknown channel"); {
CChannelMap::iterator itr= m_Channel.find(pHeader->CID);
if (itr != m_Channel.end())
{
SChannel& rChannel = itr->second;
switch(rChannel.PSM)
{
case 0x01: //SDP
{
HandleSDP(pHeader->CID, pData, DataSize);
}
break;
default:
PanicAlert("channel %i has unknow PSM %x", pHeader->CID);
break;
}
}
else
{
PanicAlert("SendACLFrame to unknown channel %i", pHeader->CID);
}
}
break; break;
} }
} }
@ -223,16 +250,29 @@ void CWII_IPC_HLE_WiiMote::SendCommandToACL(u8 _Ident, u8 _Code, u8 _CommandLeng
// send .... // send ....
m_pHost->SendACLFrame(GetConnectionHandle(), DataFrame, pHeader->Length + sizeof(SL2CAP_Header)); m_pHost->SendACLFrame(GetConnectionHandle(), DataFrame, pHeader->Length + sizeof(SL2CAP_Header));
// stupid self-test
// SendACLFrame(DataFrame, pHeader->Length + sizeof(SL2CAP_Header)); // dump raw data
{
LOG(WIIMOTE, "m_pHost->SendACLFrame: 0x%x", GetConnectionHandle());
std::string Temp;
for (u32 j=0; j<pHeader->Length + sizeof(SL2CAP_Header); j++)
{
char Buffer[128];
sprintf(Buffer, "%02x ", DataFrame[j]);
Temp.append(Buffer);
}
LOG(WIIMOTE, " Data: %s", Temp.c_str());
}
} }
void CWII_IPC_HLE_WiiMote::Connect() { void CWII_IPC_HLE_WiiMote::Connect()
{
SendConnectionRequest(HID_OUTPUT_SCID, HIDP_OUTPUT_CHANNEL); SendConnectionRequest(HID_OUTPUT_SCID, HIDP_OUTPUT_CHANNEL);
SendConnectionRequest(HID_INPUT_SCID, HIDP_INPUT_CHANNEL); SendConnectionRequest(HID_INPUT_SCID, HIDP_INPUT_CHANNEL);
} }
void CWII_IPC_HLE_WiiMote::SendConnectionRequest(u16 scid, u16 psm) { void CWII_IPC_HLE_WiiMote::SendConnectionRequest(u16 scid, u16 psm)
{
// create the channel // create the channel
SChannel& rChannel = m_Channel[scid]; SChannel& rChannel = m_Channel[scid];
rChannel.PSM = psm; rChannel.PSM = psm;
@ -253,15 +293,33 @@ void CWII_IPC_HLE_WiiMote::SendConfigurationRequest(u16 scid) {
_dbg_assert_(WIIMOTE, DoesChannelExist(scid)); _dbg_assert_(WIIMOTE, DoesChannelExist(scid));
SChannel& rChannel = m_Channel[scid]; SChannel& rChannel = m_Channel[scid];
l2cap_conf_req cr; u8 Buffer[1024];
cr.dcid = rChannel.DCID; int Offset = 0;
cr.flags = 0; //what goes here? check libogc.
l2cap_conf_req* cr = (l2cap_conf_req*)Buffer;
cr->dcid = rChannel.DCID;
cr->flags = 0; //what goes here? check libogc.
Offset += 2;
/*
controller doesnt know this...
Buffer[Offset++] = 1;
Buffer[Offset++] = 2;
Buffer[Offset++] = 0;
Buffer[Offset++] = 1;*/
Buffer[Offset++] = 2;
Buffer[Offset++] = 2;
Buffer[Offset++] = 0xff;
Buffer[Offset++] = 0xff;
LOG(WIIMOTE, " SendConfigurationRequest()"); LOG(WIIMOTE, " SendConfigurationRequest()");
LOG(WIIMOTE, " Dcid: 0x%04x", cr.dcid); LOG(WIIMOTE, " Dcid: 0x%04x", cr->dcid);
LOG(WIIMOTE, " Flags: 0x%04x", cr.flags); LOG(WIIMOTE, " Flags: 0x%04x", cr->flags);
SendCommandToACL(L2CAP_CONF_REQ, L2CAP_CONF_REQ, sizeof(cr), (u8*)&cr); SendCommandToACL(L2CAP_CONF_REQ, L2CAP_CONF_REQ, Offset, Buffer);
} }
@ -367,6 +425,46 @@ void CWII_IPC_HLE_WiiMote::CommandConnectionReq(u8 _Ident, u8* _pData, u32 _Size
SendCommandToACL(_Ident, L2CAP_CONN_RSP, sizeof(SL2CAP_ConnectionResponse), (u8*)&Rsp); SendCommandToACL(_Ident, L2CAP_CONN_RSP, sizeof(SL2CAP_ConnectionResponse), (u8*)&Rsp);
} }
class CConfigurationResponse
{
public:
CConfigurationResponse(u8 identifier, u16 scid, u16 flags, u16 result)
{
buffer[0] = 0x05;
buffer[1] = identifier;
*(u16*)&buffer[4] = scid;
*(u16*)&buffer[6] = flags;
*(u16*)&buffer[8] = result;
length = 10;
UpdateLen();
}
void AddConfig(u8 type, u8 len, void* data)
{
buffer[length++] = type;
buffer[length++] = len;
memcpy(&buffer[length], data, len);
length += len;
UpdateLen();
}
u16 getLen() { return length; }
u8* getBuffer() { return buffer; }
private:
void UpdateLen()
{
*(u16*)&buffer[2] = length;
}
u8 buffer[1024];
u16 length;
};
void CWII_IPC_HLE_WiiMote::CommandCofigurationReq(u8 _Ident, u8* _pData, u32 _Size) void CWII_IPC_HLE_WiiMote::CommandCofigurationReq(u8 _Ident, u8* _pData, u32 _Size)
{ {
u32 Offset = 0; u32 Offset = 0;
@ -437,6 +535,9 @@ void CWII_IPC_HLE_WiiMote::CommandCofigurationReq(u8 _Ident, u8* _pData, u32 _Si
SendCommandToACL(_Ident, L2CAP_CONF_RSP, RespLen, TempBuffer); SendCommandToACL(_Ident, L2CAP_CONF_RSP, RespLen, TempBuffer);
// ugly
SendConfigurationRequest(Rsp->scid);
} }
void CWII_IPC_HLE_WiiMote::CommandConnectionResponse(u8 _Ident, u8* _pData, u32 _Size) void CWII_IPC_HLE_WiiMote::CommandConnectionResponse(u8 _Ident, u8* _pData, u32 _Size)
@ -475,3 +576,219 @@ void CWII_IPC_HLE_WiiMote::CommandCofigurationResponse(u8 _Ident, u8* _pData, u3
_dbg_assert_(WIIMOTE, rsp->result == 0); _dbg_assert_(WIIMOTE, rsp->result == 0);
} }
/////////////////////////////////////////////////////////////////////////////////////////////////
#define SDP_UINT8 0x08
#define SDP_UINT16 0x09
#define SDP_UINT32 0x0A
#define SDP_SEQ8 0x35
#define SDP_SEQ16 0x36
void CWII_IPC_HLE_WiiMote::SDPSendServiceSearchResponse(u16 cid, u16 TransactionID, u8* pServiceSearchPattern, u16 MaximumServiceRecordCount)
{
// verify block... we hanlde search pattern for HID service only
{
CBigEndianBuffer buffer(pServiceSearchPattern);
_dbg_assert_(WIIMOTE, buffer.Read8(0) == SDP_SEQ8); // data sequence
_dbg_assert_(WIIMOTE, buffer.Read8(1) == 0x03); // sequence size
// HIDClassID
_dbg_assert_(WIIMOTE, buffer.Read8(2) == 0x19);
_dbg_assert_(WIIMOTE, buffer.Read16(3) == 0x1124);
}
u8 DataFrame[1000];
CBigEndianBuffer buffer(DataFrame);
int Offset = 0;
SL2CAP_Header* pHeader = (SL2CAP_Header*)&DataFrame[Offset]; Offset += sizeof(SL2CAP_Header);
pHeader->CID = cid;
pHeader->Length = 0x14;
buffer.Write8 (Offset, 0x03); Offset++;
buffer.Write16(Offset, TransactionID); Offset += 2; // transaction ID
buffer.Write16(Offset, 0x0009); Offset += 2; // param length
buffer.Write16(Offset, 0x0001); Offset += 2; // TotalServiceRecordCount
buffer.Write16(Offset, 0x0001); Offset += 2; // CurrentServiceRecordCount
buffer.Write32(Offset, 0x1234ABCD); Offset += 4; // ServiceRecordHandleList[4]
buffer.Write8( Offset, 0x00); Offset++; // no continuation state;
pHeader->Length = Offset - sizeof(SL2CAP_Header);
m_pHost->SendACLFrame(GetConnectionHandle(), DataFrame, Offset);
}
void GetStartAndEndID(u8* pAttribIDList, u16& _startID, u16& _endID)
{
u32 attribOffset = 0;
CBigEndianBuffer attribList(pAttribIDList);
u8 sequence = attribList.Read8(attribOffset); attribOffset++; _dbg_assert_(WIIMOTE, sequence == SDP_SEQ8);
u8 seqSize = attribList.Read8(attribOffset); attribOffset++;
u8 typeID = attribList.Read8(attribOffset); attribOffset++;
if (typeID == SDP_UINT32)
{
_startID = attribList.Read16(attribOffset); attribOffset += 2;
_endID = attribList.Read16(attribOffset); attribOffset += 2;
}
else
{
_startID = attribList.Read8(attribOffset); attribOffset += 2;
_endID = _startID;
PanicAlert("Read just a single attrib - not tested");
}
}
void CWII_IPC_HLE_WiiMote::SDPSendServiceAttributeResponse(u16 cid, u16 TransactionID, u32 ServiceHandle, u8* pAttribIDList, u16 AttribListIDSize)
{
u8 DataFrame[1000];
CBigEndianBuffer buffer(DataFrame);
int Offset = 0;
SL2CAP_Header* pHeader = (SL2CAP_Header*)&DataFrame[Offset]; Offset += sizeof(SL2CAP_Header);
pHeader->CID = cid;
buffer.Write8 (Offset, 0x05); Offset++;
buffer.Write16(Offset, TransactionID); Offset += 2; // transaction ID
{
u32 paraLenOffset = Offset; Offset += 2;
u32 AttributeListByteCountOffset = Offset; Offset += 2;
buffer.Write8(Offset, SDP_SEQ16); Offset ++; // write 16 bit sequencer
u32 sequenceSizeOffset = Offset; Offset += 2;
// get attrib range
u16 startAttrID;
u16 endAttrID;
GetStartAndEndID(pAttribIDList, startAttrID, endAttrID);
// walk through the table
const CAttribTable& rAttribTable = GetAttribTable();
CAttribTable::const_iterator itr = rAttribTable.begin();
u32 sequenceSize = 0;
while(itr != rAttribTable.end())
{
const SAttrib& rAttrib = *itr;
if ((rAttrib.ID >= startAttrID) && (rAttrib.ID <= endAttrID))
{
_dbg_assert_(WIIMOTE, rAttrib.size <= 230);
// ATTRIB TYPE ID
buffer.Write8(Offset, SDP_UINT16); Offset ++;
buffer.Write16(Offset, rAttrib.ID); Offset += 2;
sequenceSize += 3;
// RAW ATTRIB DATA SEQ HEADER
buffer.Write8(Offset, SDP_SEQ8); Offset ++;
buffer.Write8(Offset, rAttrib.size); Offset ++;
sequenceSize += 2;
// RAW ATTRIB DATA
memcpy(buffer.GetPointer(Offset), rAttrib.pData, rAttrib.size);
Offset += rAttrib.size;
sequenceSize += rAttrib.size;
}
itr++;
}
buffer.Write16(sequenceSizeOffset, sequenceSize);
buffer.Write16(AttributeListByteCountOffset, sequenceSize + 4); // AttributeListByteCount
buffer.Write16(paraLenOffset, sequenceSize + 4 + 3); // param length
}
buffer.Write8(Offset, 0x00); Offset++; // no continuation state;
pHeader->Length = Offset - sizeof(SL2CAP_Header);
// dump raw data
{
LOG(WIIMOTE, "test response: 0x%x", GetConnectionHandle());
std::string Temp;
for (u32 j=0; j<pHeader->Length + sizeof(SL2CAP_Header); j++)
{
char Buffer[128];
sprintf(Buffer, "%02x ", DataFrame[j]);
Temp.append(Buffer);
}
LOG(WIIMOTE, " Data: %s", Temp.c_str());
}
m_pHost->SendACLFrame(GetConnectionHandle(), DataFrame, pHeader->Length + sizeof(SL2CAP_Header));
}
void CWII_IPC_HLE_WiiMote::HandleSDP(u16 cid, u8* _pData, u32 _Size)
{
// dump raw data
{
LOG(WIIMOTE, "HandleSDP: 0x%x", GetConnectionHandle());
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());
}
CBigEndianBuffer buffer(_pData);
switch(buffer.Read8(0))
{
// SDP_ServiceSearchRequest
case 0x02:
{
LOG(WIIMOTE, "!!! SDP_ServiceSearchRequest !!!");
_dbg_assert_(WIIMOTE, _Size == 13);
u16 TransactionID = buffer.Read16(1);
u16 ParameterLength = buffer.Read16(3);
u8* pServiceSearchPattern = buffer.GetPointer(5);
u16 MaximumServiceRecordCount = buffer.Read16(10);
u8 ContinuationState = buffer.Read8(12);
SDPSendServiceSearchResponse(cid, TransactionID, pServiceSearchPattern, MaximumServiceRecordCount);
}
break;
// SDP_ServiceAttributeRequest
case 0x04:
{
LOG(WIIMOTE, "!!! SDP_ServiceAttributeRequest !!!");
u16 TransactionID = buffer.Read16(1);
u16 ParameterLength = buffer.Read16(3);
u32 ServiceHandle = buffer.Read32(5);
u16 MaximumAttributeByteCount = buffer.Read16(9); // MaximumAttributeByteCount
u8* pAttribIDList = buffer.GetPointer(11);
u8 ContinuationState = buffer.Read8(16);
u8 AttribListIDSize = ParameterLength - sizeof(ContinuationState) - sizeof(ServiceHandle) -sizeof(MaximumAttributeByteCount);
SDPSendServiceAttributeResponse(cid, TransactionID, ServiceHandle, pAttribIDList, AttribListIDSize);
}
break;
default:
PanicAlert("Unknown SDP command %x", _pData[0]);
break;
}
}

View File

@ -22,6 +22,56 @@
class CWII_IPC_HLE_Device_usb_oh1_57e_305; class CWII_IPC_HLE_Device_usb_oh1_57e_305;
class CBigEndianBuffer
{
public:
CBigEndianBuffer(u8* pBuffer)
: m_pBuffer(pBuffer)
{
}
u8 Read8(u32 offset)
{
return m_pBuffer[offset];
}
u16 Read16(u32 offset)
{
return Common::swap16(*(u16*)&m_pBuffer[offset]);
}
u32 Read32(u32 offset)
{
return Common::swap32(*(u32*)&m_pBuffer[offset]);
}
void Write8(u32 offset, u8 data)
{
m_pBuffer[offset] = data;
}
void Write16(u32 offset, u16 data)
{
*(u16*)&m_pBuffer[offset] = Common::swap16(data);
}
void Write32(u32 offset, u32 data)
{
*(u32*)&m_pBuffer[offset] = Common::swap32(data);
}
u8* GetPointer(u32 offset)
{
return &m_pBuffer[offset];
}
private:
u8* m_pBuffer;
};
class CWII_IPC_HLE_WiiMote class CWII_IPC_HLE_WiiMote
{ {
public: public:
@ -41,6 +91,12 @@ public:
const char* GetName() const { return m_Name.c_str(); } const char* GetName() const { return m_Name.c_str(); }
u8 GetLMPVersion() const { return lmp_version; }
u16 GetLMPSubVersion() const { return lmp_subversion; }
u8 GetManufactorID() const { return 0xF; } // Broadcom Corporation
void SendACLFrame(u8* _pData, u32 _Size); //to wiimote void SendACLFrame(u8* _pData, u32 _Size); //to wiimote
void Connect(); void Connect();
@ -58,6 +114,11 @@ private:
u8 features[HCI_FEATURES_SIZE]; u8 features[HCI_FEATURES_SIZE];
u8 lmp_version;
u16 lmp_subversion;
std::string m_Name; std::string m_Name;
CWII_IPC_HLE_Device_usb_oh1_57e_305* m_pHost; CWII_IPC_HLE_Device_usb_oh1_57e_305* m_pHost;
@ -71,7 +132,9 @@ private:
u16 MTU; u16 MTU;
u16 FlushTimeOut; u16 FlushTimeOut;
}; };
std::map<u32, SChannel> m_Channel;
typedef std::map<u32, SChannel> CChannelMap;
CChannelMap m_Channel;
bool DoesChannelExist(u16 _SCID) bool DoesChannelExist(u16 _SCID)
{ {
@ -91,5 +154,18 @@ private:
void CommandCofigurationReq(u8 _Ident, u8* _pData, u32 _Size); void CommandCofigurationReq(u8 _Ident, u8* _pData, u32 _Size);
void CommandConnectionResponse(u8 _Ident, u8* _pData, u32 _Size); void CommandConnectionResponse(u8 _Ident, u8* _pData, u32 _Size);
void CommandCofigurationResponse(u8 _Ident, u8* _pData, u32 _Size); void CommandCofigurationResponse(u8 _Ident, u8* _pData, u32 _Size);
//////////////////
// some new ugly stuff
//
// should be inside the plugin
//
void HandleSDP(u16 cid, u8* _pData, u32 _Size);
void SDPSendServiceSearchResponse(u16 cid, u16 TransactionID, u8* pServiceSearchPattern, u16 MaximumServiceRecordCount);
void SDPSendServiceAttributeResponse(u16 cid, u16 TransactionID, u32 ServiceHandle, u8* pAttribIDList, u16 AttribListIDSize);
u16 AddAttribToList(int attribID, u8* pBuffer);
}; };
#endif #endif

View File

@ -0,0 +1,175 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include <vector>
#include "WiiMote_HID_Attr.h"
CAttribTable m_AttribTable;
// 0x00
u8 ServiceRecordHandle[] = { 0x0a, 0x00, 0x01, 0x00, 0x00 };
// 0x01
u8 SrvClassIDList[] = { 0x35, 0x03,
0x19, 0x11, 0x24 };
// 0x04
u8 ProtocolDescriptorList[] = { 0x35, 0x0D,
0x35, 0x06,
0x19, 0x01, 0x00, // Element 0
0x09, 0x00, 0x11, // Element 1
0x35, 0x03,
0x19, 0x00, 0x11}; // Element 0
// 0x5
u8 BrowseGroupList[] = { 0x35, 0x03, 0x09, 0x10, 0x02 };
// 0x6
u8 LanguageBaseAttributeIDList[] = { 0x35, 0x09,
0x09, 0x65, 0x6e,
0x09, 0x00, 0x6a,
0x09, 0x01, 0x00 };
// 0x09
u8 BluetoothProfileDescriptorList[] = { 0x35, 0x08,
0x35, 0x06,
0x19, 0x00, 0x11,
0x09, 0x01, 0x00 };
// 0x0D
u8 AdditionalProtocolDescriptorLists[] = { 0x35, 0x0a,
0x35, 0x03,
0x19, 0x01, 0x00,
0x09, 0x00, 0x13,
0x35, 0x03,
0x19, 0x00, 0x11 };
// 0x100
u8 ServiceName[] = { 0x25, 0x13, 'N','i','n','t','e','n','d','o',' ','R','V','L','-','C','N','T','-','0','1' };
// 0x101
u8 ServiceDescription[] = { 0x25, 0x13, 'N','i','n','t','e','n','d','o',' ','R','V','L','-','C','N','T','-','0','1' };
// 0x102
u8 ProviderName [] = { 0x25, 0x8, 'N','i','n','t','e','n','d','o'};
// 0x200
u8 HIDDeviceReleaseNumber[] = { 0x09, 0x01, 0x00 };
// 0x201
u8 HIDParserVersion[] = { 0x09, 0x01, 0x11 };
// 0x202
u8 HIDDeviceSubclass[] = { 0x09, 0x00, 0x04 };
// 0x203
u8 HIDCountryCode[] = { 0x09, 0x00, 0x33 };
// 0x204
u8 HIDVirtualCable[] = { 0x09, 0x00, 0x00 };
// 0x205
u8 HIDReconnectInitiate[] = { 0x09, 0x00, 0x01 };
// 0x206
u8 HIDDescriptorList[] = { 0x35, 0xDF,
0x35, 0xDD,
0x08, 0x22, // Element 0
0x25, 0xD9,
// 0xD9 Bytes - Element 1
0x05, 0x01, 0x09, 0x05, 0xa1, 0x01, 0x85, 0x10,
0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95,
0x01, 0x06, 0x00, 0xff, 0x09, 0x01, 0x91, 0x00,
0x85, 0x11, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00,
0x85, 0x12, 0x95, 0x02, 0x09, 0x01, 0x91, 0x00,
0x85, 0x13, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00,
0x85, 0x14, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00,
0x85, 0x15, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00,
0x85, 0x16, 0x95, 0x15, 0x09, 0x01, 0x91, 0x00,
0x85, 0x17, 0x95, 0x06, 0x09, 0x01, 0x91, 0x00,
0x85, 0x18, 0x95, 0x15, 0x09, 0x01, 0x91, 0x00,
0x85, 0x19, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00,
0x85, 0x1a, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00,
0x85, 0x20, 0x95, 0x06, 0x09, 0x01, 0x81, 0x00,
0x85, 0x21, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
0x85, 0x22, 0x95, 0x04, 0x09, 0x01, 0x81, 0x00,
0x85, 0x30, 0x95, 0x02, 0x09, 0x01, 0x81, 0x00,
0x85, 0x31, 0x95, 0x05, 0x09, 0x01, 0x81, 0x00,
0x85, 0x32, 0x95, 0x0a, 0x09, 0x01, 0x81, 0x00,
0x85, 0x33, 0x95, 0x11, 0x09, 0x01, 0x81, 0x00,
0x85, 0x34, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
0x85, 0x35, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
0x85, 0x36, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
0x85, 0x37, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
0x85, 0x3d, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
0x85, 0x3e, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
0x85, 0x3f, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
0xc0 }; // end tag
// 0x207
u8 HIDLANGIDBaseList[] = { 0x35, 0x08,
0x35, 0x06,
0x09, 0x04, 0x09,
0x09, 0x01, 0x00 };
// 0x208
u8 HIDSDPDisable[] = { 0x28, 0x00 };
// 0x209
u8 HIDBatteryPower[] = { 0x28, 0x01 };
// 0x20a
u8 HIDRemoteWake[] = { 0x28, 0x01 };
// 0x20b
u8 HIDUnk_020B[] = { 0x09, 0x01, 0x00 };
// 0x20c
u8 HIDUnk_020C[] = { 0x09, 0x0c, 0x80 };
// 0x20d
u8 HIDUnk_020D[] = { 0x09, 0x00, 0x00 };
// 0x20e
u8 HIDBootDevice[] = { 0x28, 0x00 };
void InitAttribTable()
{
m_AttribTable.push_back(SAttrib(0x00, ServiceRecordHandle, sizeof(ServiceRecordHandle)));
m_AttribTable.push_back(SAttrib(0x01, SrvClassIDList, sizeof(SrvClassIDList)));
m_AttribTable.push_back(SAttrib(0x04, ProtocolDescriptorList, sizeof(ProtocolDescriptorList)));
m_AttribTable.push_back(SAttrib(0x05, BrowseGroupList, sizeof(BrowseGroupList)));
m_AttribTable.push_back(SAttrib(0x06, LanguageBaseAttributeIDList, sizeof(LanguageBaseAttributeIDList)));
m_AttribTable.push_back(SAttrib(0x09, BluetoothProfileDescriptorList, sizeof(BluetoothProfileDescriptorList)));
m_AttribTable.push_back(SAttrib(0x0D, AdditionalProtocolDescriptorLists, sizeof(AdditionalProtocolDescriptorLists)));
m_AttribTable.push_back(SAttrib(0x100, ServiceName, sizeof(ServiceName)));
m_AttribTable.push_back(SAttrib(0x101, ServiceDescription, sizeof(ServiceDescription)));
m_AttribTable.push_back(SAttrib(0x102, ProviderName, sizeof(ProviderName)));
m_AttribTable.push_back(SAttrib(0x200, HIDDeviceReleaseNumber, sizeof(HIDDeviceReleaseNumber)));
m_AttribTable.push_back(SAttrib(0x201, HIDParserVersion, sizeof(HIDParserVersion)));
m_AttribTable.push_back(SAttrib(0x202, HIDDeviceSubclass, sizeof(HIDDeviceSubclass)));
m_AttribTable.push_back(SAttrib(0x203, HIDCountryCode, sizeof(HIDCountryCode)));
m_AttribTable.push_back(SAttrib(0x204, HIDVirtualCable, sizeof(HIDVirtualCable)));
m_AttribTable.push_back(SAttrib(0x205, HIDReconnectInitiate, sizeof(HIDReconnectInitiate)));
m_AttribTable.push_back(SAttrib(0x206, HIDDescriptorList, sizeof(HIDDescriptorList)));
m_AttribTable.push_back(SAttrib(0x207, HIDLANGIDBaseList, sizeof(HIDLANGIDBaseList)));
m_AttribTable.push_back(SAttrib(0x208, HIDSDPDisable, sizeof(HIDSDPDisable)));
m_AttribTable.push_back(SAttrib(0x209, HIDBatteryPower, sizeof(HIDBatteryPower)));
m_AttribTable.push_back(SAttrib(0x20a, HIDRemoteWake, sizeof(HIDRemoteWake)));
m_AttribTable.push_back(SAttrib(0x20b, HIDUnk_020B, sizeof(HIDUnk_020B)));
m_AttribTable.push_back(SAttrib(0x20c, HIDUnk_020C, sizeof(HIDUnk_020C)));
m_AttribTable.push_back(SAttrib(0x20d, HIDUnk_020D, sizeof(HIDUnk_020D)));
m_AttribTable.push_back(SAttrib(0x20e, HIDBootDevice, sizeof(HIDBootDevice)));
}
const CAttribTable& GetAttribTable()
{
if (m_AttribTable.empty())
{
InitAttribTable();
}
return m_AttribTable;
}

View File

@ -0,0 +1,38 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef WIIMOTE_HID_ATTR_H_
#define WIIMOTE_HID_ATTR_H_
struct SAttrib
{
u16 ID;
u8* pData;
u16 size;
SAttrib(u16 _ID, u8* _Data, u16 _size)
: ID(_ID)
, pData(_Data)
, size(_size)
{ }
};
typedef std::vector<SAttrib> CAttribTable;
const CAttribTable& GetAttribTable();
#endif

View File

@ -2487,6 +2487,24 @@ struct SHCIEventConnectionComplete
u8 EncryptionEnabled; u8 EncryptionEnabled;
}; };
struct SHCIEventRoleChange
{
u8 EventType;
u8 PayloadLength;
u8 Status;
bdaddr_t bdaddr;
u8 NewRole;
};
struct SHCIEventNumberOfCompletedPackets
{
u8 EventType;
u8 PayloadLength;
u8 value;
u16 Connection_Handle;
u16 Number_Of_Completed_Packets;
};
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -1,168 +0,0 @@
#ifndef WIIMOTE_HID_H
#define WIIMOTE_HID_H
#include <CommonTypes.h>
#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_DATA_REPORTING 0x12
struct wm_data_reporting {
u8 rumble : 1;
u8 continuous : 1;
u8 : 6;
u8 mode;
};
#define WM_IR_PIXEL_CLOCK 0x13
#define WM_IR_LOGIC 0x1A
#define WM_REQUEST_STATUS 0x15
struct wm_request_status {
u8 rumble : 1;
u8 : 7;
};
#define WM_STATUS_REPORT 0x20
struct wm_status_report {
u8 padding1[2];
u8 unknown : 1;
u8 extension : 1;
u8 speaker : 1;
u8 ir : 1;
u8 leds : 4;
u8 padding2[2];
u8 battery;
};
#define WM_WRITE_DATA 0x16
struct wm_write_data {
u8 rumble : 1;
u8 space : 2; //see WM_SPACE_*
u8 : 5;
u8 address[3];
u8 size;
u8 data[16];
};
#define WM_WRITE_DATA_REPLY 0x22 //empty, afaik
#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
struct wm_core {
u8 left : 1;
u8 right : 1;
u8 down : 1;
u8 up : 1;
u8 plus : 1;
u8 : 3;
u8 two : 1;
u8 one : 1;
u8 b : 1;
u8 a : 1;
u8 minus : 1;
u8 : 2;
u8 home : 1;
};
struct wm_accel {
u8 x, y, z;
};
//filled with 0xFF if empty
struct wm_ir_extended {
u8 x;
u8 y;
u8 size : 4;
u8 xHi : 2;
u8 yHi : 2;
};
#define WM_REPORT_CORE 0x30
#define WM_REPORT_CORE_ACCEL 0x31
struct wm_report_core_accel {
wm_core c;
wm_accel a;
};
#define WM_REPORT_CORE_EXT8 0x32
#define WM_REPORT_CORE_ACCEL_IR12 0x33
struct wm_report_core_accel_ir12 {
wm_core c;
wm_accel a;
wm_ir_extended ir[4];
};
#define WM_REPORT_CORE_EXT19 0x34
#define WM_REPORT_CORE_ACCEL_EXT16 0x35
#define WM_REPORT_CORE_IR10_EXT9 0x36
#define WM_REPORT_CORE_ACCEL_IR10_EXT6 0x37
#define WM_REPORT_EXT21 0x3d
#define WM_REPORT_INTERLEAVE1 0x3e
#define WM_REPORT_INTERLEAVE2 0x3f
#if defined(_MSC_VER)
#pragma pack(pop)
#endif
#endif //WIIMOTE_HID_H

View File

@ -190,13 +190,45 @@ extern "C" void Wiimote_Output(const void* _pData, u32 _Size) {
hid_packet* hidp = (hid_packet*) data; hid_packet* hidp = (hid_packet*) data;
if(hidp->type == HID_TYPE_SET_REPORT && if ((hidp->param != HID_PARAM_INPUT) && (hidp->param != HID_PARAM_OUTPUT))
hidp->param == HID_PARAM_OUTPUT)
{ {
HidOutputReport((wm_report*)hidp->data); PanicAlert("hidp->param has a wrong parameter!!!");
} else {
PanicAlert("HidOutput: Unknown type 0x%02x", data[0]);
} }
switch(hidp->type)
{
case HID_TYPE_HANDSHAKE:
if (hidp->param == HID_PARAM_INPUT)
{
PanicAlert("HID_TYPE_HANDSHAKE - HID_PARAM_INPUT");
}
else
{
PanicAlert("HID_TYPE_HANDSHAKE - HID_PARAM_OUTPUT");
}
g_ReportingMode = 0x33;
break;
case HID_TYPE_SET_REPORT:
if (hidp->param == HID_PARAM_INPUT)
{
PanicAlert("HID_TYPE_SET_REPORT input");
}
else
{
HidOutputReport((wm_report*)hidp->data);
}
break;
case HID_TYPE_DATA:
PanicAlert("HID_TYPE_DATA %s", hidp->type, hidp->param == HID_PARAM_INPUT ? "input" : "output");
break;
default:
PanicAlert("HidOutput: Unknown type %x and param %x", hidp->type, hidp->param);
break;
}
} }
extern "C" void Wiimote_Update() { extern "C" void Wiimote_Update() {

View File

@ -16,10 +16,10 @@ struct hid_packet {
u8 data[0]; u8 data[0];
}; };
#define HID_TYPE_HANDSHAKE 0
#define HID_TYPE_SET_REPORT 5 #define HID_TYPE_SET_REPORT 5
#define HID_TYPE_DATA 0xA #define HID_TYPE_DATA 0xA
#define HID_TYPE_HANDSHAKE 0
#define HID_HANDSHAKE_SUCCESS 0 #define HID_HANDSHAKE_SUCCESS 0
#define HID_PARAM_INPUT 1 #define HID_PARAM_INPUT 1