void WiiRemote::task(void (*pFunc)(void)) { Max.Task(); Usb.Task(); delay(1); // re-initialize if (Usb.getUsbTaskState() == USB_DETACHED_SUBSTATE_INITIALIZE) { /* TODO */ wiiremote_status_ = 0; } // wait for addressing state if (Usb.getUsbTaskState() == USB_STATE_CONFIGURING) { initBTController(); if (wiiremote_status_ & WIIREMOTE_STATE_USB_CONFIGURED) { hci_state_ = HCI_INIT_STATE; hci_counter_ = 10; l2cap_state_ = L2CAP_DOWN_STATE; Usb.setUsbTaskState(USB_STATE_RUNNING); } } if (Usb.getUsbTaskState() == USB_STATE_RUNNING) { HCI_task(); // poll the HCI event pipe L2CAP_task(); // start polling the ACL input pipe too, though discard // data until connected } //if (l2cap_state_ == L2CAP_READY_STATE) { if (wiiremote_status_ & WIIREMOTE_STATE_RUNNING) { if (pFunc) { pFunc(); } } } // task
void BTHID::ACLData(uint8_t* l2capinbuf) { if(!pBtd->l2capConnectionClaimed && pBtd->incomingHIDDevice && !connected && !activeConnection) { if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) { pBtd->incomingHIDDevice = false; pBtd->l2capConnectionClaimed = true; // Claim that the incoming connection belongs to this service activeConnection = true; hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection l2cap_state = L2CAP_WAIT; } } } //if((l2capinbuf[0] | (uint16_t)l2capinbuf[1] << 8) == (hci_handle | 0x2000U)) { // acl_handle_ok or it's a new connection if(UHS_ACL_HANDLE_OK(l2capinbuf, hci_handle)) { // acl_handle_ok or it's a new connection if((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001U) { // l2cap_control - Channel ID for ACL-U if(l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) { #ifdef DEBUG_USB_HOST Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80); D_PrintHex<uint8_t > (l2capinbuf[13], 0x80); Notify(PSTR(" "), 0x80); D_PrintHex<uint8_t > (l2capinbuf[12], 0x80); Notify(PSTR(" "), 0x80); D_PrintHex<uint8_t > (l2capinbuf[17], 0x80); Notify(PSTR(" "), 0x80); D_PrintHex<uint8_t > (l2capinbuf[16], 0x80); Notify(PSTR(" "), 0x80); D_PrintHex<uint8_t > (l2capinbuf[15], 0x80); Notify(PSTR(" "), 0x80); D_PrintHex<uint8_t > (l2capinbuf[14], 0x80); #endif } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_RESPONSE) { if(((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) && ((l2capinbuf[18] | (l2capinbuf[19] << 8)) == SUCCESSFUL)) { // Success if(l2capinbuf[14] == control_dcid[0] && l2capinbuf[15] == control_dcid[1]) { //Notify(PSTR("\r\nHID Control Connection Complete"), 0x80); identifier = l2capinbuf[9]; control_scid[0] = l2capinbuf[12]; control_scid[1] = l2capinbuf[13]; l2cap_set_flag(L2CAP_FLAG_CONTROL_CONNECTED); } else if(l2capinbuf[14] == interrupt_dcid[0] && l2capinbuf[15] == interrupt_dcid[1]) { //Notify(PSTR("\r\nHID Interrupt Connection Complete"), 0x80); identifier = l2capinbuf[9]; interrupt_scid[0] = l2capinbuf[12]; interrupt_scid[1] = l2capinbuf[13]; l2cap_set_flag(L2CAP_FLAG_INTERRUPT_CONNECTED); } } } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { #ifdef EXTRADEBUG Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80); D_PrintHex<uint8_t > (l2capinbuf[13], 0x80); Notify(PSTR(" "), 0x80); D_PrintHex<uint8_t > (l2capinbuf[12], 0x80); Notify(PSTR(" SCID: "), 0x80); D_PrintHex<uint8_t > (l2capinbuf[15], 0x80); Notify(PSTR(" "), 0x80); D_PrintHex<uint8_t > (l2capinbuf[14], 0x80); Notify(PSTR(" Identifier: "), 0x80); D_PrintHex<uint8_t > (l2capinbuf[9], 0x80); #endif if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) { identifier = l2capinbuf[9]; control_scid[0] = l2capinbuf[14]; control_scid[1] = l2capinbuf[15]; l2cap_set_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST); } else if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_INTR_PSM) { identifier = l2capinbuf[9]; interrupt_scid[0] = l2capinbuf[14]; interrupt_scid[1] = l2capinbuf[15]; l2cap_set_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST); } } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) { if((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { //Notify(PSTR("\r\nHID Control Configuration Complete"), 0x80); identifier = l2capinbuf[9]; l2cap_set_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS); } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { //Notify(PSTR("\r\nHID Interrupt Configuration Complete"), 0x80); identifier = l2capinbuf[9]; l2cap_set_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS); } } } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) { if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { //Notify(PSTR("\r\nHID Control Configuration Request"), 0x80); pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], control_scid); } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { //Notify(PSTR("\r\nHID Interrupt Configuration Request"), 0x80); pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], interrupt_scid); } } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) { if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { #ifdef DEBUG_USB_HOST Notify(PSTR("\r\nDisconnect Request: Control Channel"), 0x80); #endif identifier = l2capinbuf[9]; pBtd->l2cap_disconnection_response(hci_handle, identifier, control_dcid, control_scid); Reset(); } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { #ifdef DEBUG_USB_HOST Notify(PSTR("\r\nDisconnect Request: Interrupt Channel"), 0x80); #endif identifier = l2capinbuf[9]; pBtd->l2cap_disconnection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid); Reset(); } } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) { if(l2capinbuf[12] == control_scid[0] && l2capinbuf[13] == control_scid[1]) { //Notify(PSTR("\r\nDisconnect Response: Control Channel"), 0x80); identifier = l2capinbuf[9]; l2cap_set_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE); } else if(l2capinbuf[12] == interrupt_scid[0] && l2capinbuf[13] == interrupt_scid[1]) { //Notify(PSTR("\r\nDisconnect Response: Interrupt Channel"), 0x80); identifier = l2capinbuf[9]; l2cap_set_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE); } } #ifdef EXTRADEBUG else { identifier = l2capinbuf[9]; Notify(PSTR("\r\nL2CAP Unknown Signaling Command: "), 0x80); D_PrintHex<uint8_t > (l2capinbuf[8], 0x80); } #endif } else if(l2capinbuf[6] == interrupt_dcid[0] && l2capinbuf[7] == interrupt_dcid[1]) { // l2cap_interrupt #ifdef PRINTREPORT Notify(PSTR("\r\nL2CAP Interrupt: "), 0x80); for(uint16_t i = 0; i < ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); i++) { D_PrintHex<uint8_t > (l2capinbuf[i + 8], 0x80); Notify(PSTR(" "), 0x80); } #endif if(l2capinbuf[8] == 0xA1) { // HID_THDR_DATA_INPUT uint16_t length = ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); ParseBTHID(this, (uint8_t)(length - 1), &l2capinbuf[9]); switch(l2capinbuf[9]) { case 0x01: // Keyboard or Joystick events if(pRptParser[KEYBOARD_PARSER_ID]) pRptParser[KEYBOARD_PARSER_ID]->Parse(reinterpret_cast<HID *>(this), 0, (uint8_t)(length - 2), &l2capinbuf[10]); // Use reinterpret_cast again to extract the instance break; case 0x02: // Mouse events if(pRptParser[MOUSE_PARSER_ID]) pRptParser[MOUSE_PARSER_ID]->Parse(reinterpret_cast<HID *>(this), 0, (uint8_t)(length - 2), &l2capinbuf[10]); // Use reinterpret_cast again to extract the instance break; #ifdef EXTRADEBUG default: Notify(PSTR("\r\nUnknown Report type: "), 0x80); D_PrintHex<uint8_t > (l2capinbuf[9], 0x80); break; #endif } } } else if(l2capinbuf[6] == control_dcid[0] && l2capinbuf[7] == control_dcid[1]) { // l2cap_control #ifdef PRINTREPORT Notify(PSTR("\r\nL2CAP Control: "), 0x80); for(uint16_t i = 0; i < ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); i++) { D_PrintHex<uint8_t > (l2capinbuf[i + 8], 0x80); Notify(PSTR(" "), 0x80); } #endif } #ifdef EXTRADEBUG else { Notify(PSTR("\r\nUnsupported L2CAP Data - Channel ID: "), 0x80); D_PrintHex<uint8_t > (l2capinbuf[7], 0x80); Notify(PSTR(" "), 0x80); D_PrintHex<uint8_t > (l2capinbuf[6], 0x80); Notify(PSTR("\r\nData: "), 0x80); Notify(PSTR("\r\n"), 0x80); for(uint16_t i = 0; i < ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); i++) { D_PrintHex<uint8_t > (l2capinbuf[i + 8], 0x80); Notify(PSTR(" "), 0x80); } } #endif L2CAP_task(); } }