void CWII_IPC_HLE_WiiMote::ReceiveL2capData(u16 scid, const void* _pData, u32 _Size) { // Allocate DataFrame u8 DataFrame[1024]; u32 Offset = 0; l2cap_hdr_t* pHeader = (l2cap_hdr_t*)DataFrame; Offset += sizeof(l2cap_hdr_t); // Check if we are already reporting on this channel _dbg_assert_(WII_IPC_WIIMOTE, DoesChannelExist(scid)); SChannel& rChannel = m_Channel[scid]; // Add an additional 4 byte header to the Wiimote report pHeader->dcid = rChannel.DCID; pHeader->length = _Size; // Copy the Wiimote report to DataFrame memcpy(DataFrame + Offset, _pData, _Size); // Update Offset to the final size of the report Offset += _Size; // Update the status bar Host_SetWiiMoteConnectionState(2); // Send the report m_pHost->SendACLPacket(GetConnectionHandle(), DataFrame, Offset); }
void CWII_IPC_HLE_WiiMote::ReceiveConnectionResponse(u8 _Ident, u8* _pData, u32 _Size) { l2cap_con_rsp_cp* rsp = (l2cap_con_rsp_cp*)_pData; _dbg_assert_(WII_IPC_WIIMOTE, _Size == sizeof(l2cap_con_rsp_cp)); INFO_LOG(WII_IPC_WIIMOTE, "[L2CAP] ReceiveConnectionResponse"); DEBUG_LOG(WII_IPC_WIIMOTE, " DCID: 0x%04x", rsp->dcid); DEBUG_LOG(WII_IPC_WIIMOTE, " SCID: 0x%04x", rsp->scid); DEBUG_LOG(WII_IPC_WIIMOTE, " Result: 0x%04x", rsp->result); DEBUG_LOG(WII_IPC_WIIMOTE, " Status: 0x%04x", rsp->status); _dbg_assert_(WII_IPC_WIIMOTE, rsp->result == L2CAP_SUCCESS); _dbg_assert_(WII_IPC_WIIMOTE, rsp->status == L2CAP_NO_INFO); _dbg_assert_(WII_IPC_WIIMOTE, DoesChannelExist(rsp->scid)); SChannel& rChannel = m_Channel[rsp->scid]; rChannel.DCID = rsp->dcid; // update state machine if (rChannel.PSM == L2CAP_PSM_HID_CNTL) m_HIDControlChannel_Connected = true; else if (rChannel.PSM == L2CAP_PSM_HID_INTR) m_HIDInterruptChannel_Connected = true; }
void CWII_IPC_HLE_WiiMote::SendConfigurationRequest(u16 scid, u16 MTU, u16 FlushTimeOut) { _dbg_assert_(WII_IPC_WIIMOTE, DoesChannelExist(scid)); SChannel& rChannel = m_Channel[scid]; u8 Buffer[1024]; int Offset = 0; l2cap_cfg_req_cp* cr = (l2cap_cfg_req_cp*)&Buffer[Offset]; cr->dcid = rChannel.DCID; cr->flags = 0; Offset += sizeof(l2cap_cfg_req_cp); DEBUG_LOG(WII_IPC_WIIMOTE, "[L2CAP] SendConfigurationRequest"); DEBUG_LOG(WII_IPC_WIIMOTE, " Dcid: 0x%04x", cr->dcid); DEBUG_LOG(WII_IPC_WIIMOTE, " Flags: 0x%04x", cr->flags); l2cap_cfg_opt_t* pOptions; // (shuffle2) currently we end up not appending options. this is because we don't // negotiate after trying to set MTU = 0 fails (stack will respond with // "configuration failed" msg...). This is still fine, we'll just use whatever the // Bluetooth stack defaults to. if (MTU || rChannel.MTU) { if (MTU == 0) MTU = rChannel.MTU; pOptions = (l2cap_cfg_opt_t*)&Buffer[Offset]; Offset += sizeof(l2cap_cfg_opt_t); pOptions->type = L2CAP_OPT_MTU; pOptions->length = L2CAP_OPT_MTU_SIZE; *(u16*)&Buffer[Offset] = MTU; Offset += L2CAP_OPT_MTU_SIZE; DEBUG_LOG(WII_IPC_WIIMOTE, " MTU: 0x%04x", MTU); } if (FlushTimeOut || rChannel.FlushTimeOut) { if (FlushTimeOut == 0) FlushTimeOut = rChannel.FlushTimeOut; pOptions = (l2cap_cfg_opt_t*)&Buffer[Offset]; Offset += sizeof(l2cap_cfg_opt_t); pOptions->type = L2CAP_OPT_FLUSH_TIMO; pOptions->length = L2CAP_OPT_FLUSH_TIMO_SIZE; *(u16*)&Buffer[Offset] = FlushTimeOut; Offset += L2CAP_OPT_FLUSH_TIMO_SIZE; DEBUG_LOG(WII_IPC_WIIMOTE, " FlushTimeOut: 0x%04x", FlushTimeOut); } SendCommandToACL(L2CAP_CONFIG_REQ, L2CAP_CONFIG_REQ, Offset, Buffer); }
void CWII_IPC_HLE_WiiMote::ReceiveConfigurationReq(u8 _Ident, u8* _pData, u32 _Size) { u32 Offset = 0; l2cap_cfg_req_cp* pCommandConfigReq = (l2cap_cfg_req_cp*)_pData; _dbg_assert_(WII_IPC_WIIMOTE, pCommandConfigReq->flags == 0x00); // 1 means that the options are send in multi-packets _dbg_assert_(WII_IPC_WIIMOTE, DoesChannelExist(pCommandConfigReq->dcid)); SChannel& rChannel = m_Channel[pCommandConfigReq->dcid]; INFO_LOG(WII_IPC_WIIMOTE, "[L2CAP] ReceiveConfigurationRequest"); DEBUG_LOG(WII_IPC_WIIMOTE, " Ident: 0x%02x", _Ident); DEBUG_LOG(WII_IPC_WIIMOTE, " DCID: 0x%04x", pCommandConfigReq->dcid); DEBUG_LOG(WII_IPC_WIIMOTE, " Flags: 0x%04x", pCommandConfigReq->flags); Offset += sizeof(l2cap_cfg_req_cp); u8 TempBuffer[1024]; u32 RespLen = 0; l2cap_cfg_rsp_cp* Rsp = (l2cap_cfg_rsp_cp*)TempBuffer; Rsp->scid = rChannel.DCID; Rsp->flags = 0x00; Rsp->result = L2CAP_SUCCESS; RespLen += sizeof(l2cap_cfg_rsp_cp); // read configuration options while (Offset < _Size) { l2cap_cfg_opt_t* pOptions = (l2cap_cfg_opt_t*)&_pData[Offset]; Offset += sizeof(l2cap_cfg_opt_t); switch (pOptions->type) { case L2CAP_OPT_MTU: { _dbg_assert_(WII_IPC_WIIMOTE, pOptions->length == L2CAP_OPT_MTU_SIZE); l2cap_cfg_opt_val_t* pMTU = (l2cap_cfg_opt_val_t*)&_pData[Offset]; rChannel.MTU = pMTU->mtu; DEBUG_LOG(WII_IPC_WIIMOTE, " MTU: 0x%04x", pMTU->mtu); } break; case L2CAP_OPT_FLUSH_TIMO: { _dbg_assert_(WII_IPC_WIIMOTE, pOptions->length == L2CAP_OPT_FLUSH_TIMO_SIZE); l2cap_cfg_opt_val_t* pFlushTimeOut = (l2cap_cfg_opt_val_t*)&_pData[Offset]; rChannel.FlushTimeOut = pFlushTimeOut->flush_timo; DEBUG_LOG(WII_IPC_WIIMOTE, " FlushTimeOut: 0x%04x", pFlushTimeOut->flush_timo); } break; default: _dbg_assert_msg_(WII_IPC_WIIMOTE, 0, "Unknown Option: 0x%02x", pOptions->type); break; } Offset += pOptions->length; u32 OptionSize = sizeof(l2cap_cfg_opt_t) + pOptions->length; memcpy(&TempBuffer[RespLen], pOptions, OptionSize); RespLen += OptionSize; } INFO_LOG(WII_IPC_WIIMOTE, "[L2CAP] SendConfigurationResponse"); SendCommandToACL(_Ident, L2CAP_CONFIG_RSP, RespLen, TempBuffer); // update state machine if (rChannel.PSM == L2CAP_PSM_HID_CNTL) m_HIDControlChannel_Connected = true; else if (rChannel.PSM == L2CAP_PSM_HID_INTR) m_HIDInterruptChannel_Connected = true; }
// This function receives L2CAP commands from the CPU void CWII_IPC_HLE_WiiMote::ExecuteL2capCmd(u8* _pData, u32 _Size) { // parse the command l2cap_hdr_t* pHeader = (l2cap_hdr_t*)_pData; u8* pData = _pData + sizeof(l2cap_hdr_t); u32 DataSize = _Size - sizeof(l2cap_hdr_t); INFO_LOG(WII_IPC_WIIMOTE, " CID 0x%04x, Len 0x%x, DataSize 0x%x", pHeader->dcid, pHeader->length, DataSize); if (pHeader->length != DataSize) { INFO_LOG(WII_IPC_WIIMOTE, "Faulty packet. It is dropped."); return; } switch (pHeader->dcid) { case L2CAP_SIGNAL_CID: SignalChannel(pData, DataSize); break; default: { _dbg_assert_msg_(WII_IPC_WIIMOTE, DoesChannelExist(pHeader->dcid), "L2CAP: SendACLPacket to unknown channel %i", pHeader->dcid); CChannelMap::iterator itr= m_Channel.find(pHeader->dcid); const int number = m_ConnectionHandle & 0xFF; if (itr != m_Channel.end()) { SChannel& rChannel = itr->second; switch (rChannel.PSM) { case L2CAP_PSM_SDP: HandleSDP(pHeader->dcid, pData, DataSize); break; case L2CAP_PSM_HID_CNTL: if (number < MAX_BBMOTES) Wiimote::ControlChannel(number, pHeader->dcid, pData, DataSize); break; case L2CAP_PSM_HID_INTR: { if (number < MAX_BBMOTES) { DEBUG_LOG(WIIMOTE, "Wiimote_InterruptChannel"); DEBUG_LOG(WIIMOTE, " Channel ID: %04x", pHeader->dcid); std::string Temp = ArrayToString((const u8*)pData, DataSize); DEBUG_LOG(WIIMOTE, " Data: %s", Temp.c_str()); Wiimote::InterruptChannel(number, pHeader->dcid, pData, DataSize); } } break; default: ERROR_LOG(WII_IPC_WIIMOTE, "Channel 0x04%x has unknown PSM %x", pHeader->dcid, rChannel.PSM); break; } } } break; } }