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
uint8_t BTD::Poll() { if(!bPollEnable) return 0; if(qNextPollTime <= millis()) { // Don't poll if shorter than polling interval qNextPollTime = millis() + pollInterval; // Set new poll time HCI_event_task(); // Poll the HCI event pipe HCI_task(); // HCI state machine ACL_event_task(); // Poll the ACL input pipe too } return 0; }
void BTD::HCI_event_task() { /* check the event pipe*/ uint16_t MAX_BUFFER_SIZE = BULK_MAXPKTSIZE; // Request more than 16 bytes anyway, the inTransfer routine will take care of this uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[ BTD_EVENT_PIPE ].epAddr, &MAX_BUFFER_SIZE, hcibuf); // input on endpoint 1 if(!rcode || rcode == hrNAK) // Check for errors { switch (hcibuf[0]) //switch on event type { case EV_COMMAND_COMPLETE: if (!hcibuf[5]) { // Check if command succeeded hci_event_flag |= HCI_FLAG_CMD_COMPLETE; // set command complete flag if((hcibuf[3] == 0x01) && (hcibuf[4] == 0x10)) { // parameters from read local version information hci_version = hcibuf[6]; // Used to check if it supports 2.0+EDR - see http://www.bluetooth.org/Technical/AssignedNumbers/hci.htm hci_event_flag |= HCI_FLAG_READ_VERSION; } else if((hcibuf[3] == 0x09) && (hcibuf[4] == 0x10)) { // parameters from read local bluetooth address for (uint8_t i = 0; i < 6; i++) my_bdaddr[i] = hcibuf[6 + i]; hci_event_flag |= HCI_FLAG_READ_BDADDR; } } break; case EV_COMMAND_STATUS: if(hcibuf[2]) { // show status on serial if not OK #ifdef DEBUG Notify(PSTR("\r\nHCI Command Failed: ")); PrintHex<uint8_t>(hcibuf[2]); Notify(PSTR(" ")); PrintHex<uint8_t>(hcibuf[4]); Notify(PSTR(" ")); PrintHex<uint8_t>(hcibuf[5]); #endif } break; case EV_INQUIRY_COMPLETE: if(inquiry_counter >= 5) { inquiry_counter = 0; #ifdef DEBUG Notify(PSTR("\r\nCouldn't find Wiimote")); #endif connectToWii = false; pairWithWii = false; hci_state = HCI_SCANNING_STATE; } inquiry_counter++; break; case EV_INQUIRY_RESULT: if (hcibuf[2]) { // Check that there is more than zero responses #ifdef EXTRADEBUG Notify(PSTR("\r\nNumber of responses: ")); Serial.print(hcibuf[2]); #endif for(uint8_t i = 0; i < hcibuf[2]; i++) { if((hcibuf[4+8*hcibuf[2]+3*i] == 0x04 && hcibuf[5+8*hcibuf[2]+3*i] == 0x25 && hcibuf[6+8*hcibuf[2]+3*i] == 0x00) || (hcibuf[4+8*hcibuf[2]+3*i] == 0x08 && hcibuf[5+8*hcibuf[2]+3*i] == 0x05 && hcibuf[6+8*hcibuf[2]+3*i] == 0x00)) { // See http://bluetooth-pentest.narod.ru/software/bluetooth_class_of_device-service_generator.html and http://wiibrew.org/wiki/Wiimote#SDP_information if(hcibuf[4+8*hcibuf[2]+3*i] == 0x08) // Check if it's the new Wiimote with motion plus inside that was detected motionPlusInside = true; else motionPlusInside = false; disc_bdaddr[0] = hcibuf[3+6*i]; disc_bdaddr[1] = hcibuf[4+6*i]; disc_bdaddr[2] = hcibuf[5+6*i]; disc_bdaddr[3] = hcibuf[6+6*i]; disc_bdaddr[4] = hcibuf[7+6*i]; disc_bdaddr[5] = hcibuf[8+6*i]; hci_event_flag |= HCI_FLAG_WII_FOUND; break; } #ifdef EXTRADEBUG else { Notify(PSTR("\r\nClass of device: ")); PrintHex<uint8_t>(hcibuf[6+8*hcibuf[2]+3*i]); Notify(PSTR(" ")); PrintHex<uint8_t>(hcibuf[5+8*hcibuf[2]+3*i]); Notify(PSTR(" ")); PrintHex<uint8_t>(hcibuf[4+8*hcibuf[2]+3*i]); } #endif } } break; case EV_CONNECT_COMPLETE: hci_event_flag |= HCI_FLAG_CONNECT_EVENT; if (!hcibuf[2]) { // check if connected OK hci_handle = hcibuf[3] | ((hcibuf[4] & 0x0F) << 8); // store the handle for the ACL connection hci_event_flag |= HCI_FLAG_CONN_COMPLETE; // set connection complete flag } #ifdef EXTRADEBUG else { Notify(PSTR("\r\nConnection Failed")); } #endif break; case EV_DISCONNECT_COMPLETE: if (!hcibuf[2]) { // check if disconnected OK hci_event_flag |= HCI_FLAG_DISCONN_COMPLETE; // set disconnect command complete flag hci_event_flag &= ~HCI_FLAG_CONN_COMPLETE; // clear connection complete flag } break; case EV_REMOTE_NAME_COMPLETE: if (!hcibuf[2]) { // check if reading is OK for (uint8_t i = 0; i < 30; i++) remote_name[i] = hcibuf[9 + i]; //store first 30 bytes hci_event_flag |= HCI_FLAG_REMOTE_NAME_COMPLETE; } break; case EV_INCOMING_CONNECT: disc_bdaddr[0] = hcibuf[2]; disc_bdaddr[1] = hcibuf[3]; disc_bdaddr[2] = hcibuf[4]; disc_bdaddr[3] = hcibuf[5]; disc_bdaddr[4] = hcibuf[6]; disc_bdaddr[5] = hcibuf[7]; hci_event_flag |= HCI_FLAG_INCOMING_REQUEST; break; case EV_PIN_CODE_REQUEST: if(pairWithWii) { #ifdef DEBUG Notify(PSTR("\r\nPairing with wiimote")); #endif hci_pin_code_request_reply(); } else if(btdPin != NULL) { #ifdef DEBUG Notify(PSTR("\r\nBluetooth pin is set too: ")); Serial.print(btdPin); #endif hci_pin_code_request_reply(); } else { #ifdef DEBUG Notify(PSTR("\r\nNo pin was set")); #endif hci_pin_code_negative_request_reply(); } break; case EV_LINK_KEY_REQUEST: #ifdef DEBUG Notify(PSTR("\r\nReceived Key Request")); #endif hci_link_key_request_negative_reply(); break; case EV_AUTHENTICATION_COMPLETE: if(pairWithWii && !connectToWii) { #ifdef DEBUG Notify(PSTR("\r\nPairing successful")); #endif connectToWii = true; // Only send the ACL data to the Wii service } break; /* We will just ignore the following events */ case EV_NUM_COMPLETE_PKT: case EV_ROLE_CHANGED: case EV_PAGE_SCAN_REP_MODE: case EV_LOOPBACK_COMMAND: case EV_DATA_BUFFER_OVERFLOW: case EV_CHANGE_CONNECTION_LINK: case EV_MAX_SLOTS_CHANGE: case EV_QOS_SETUP_COMPLETE: case EV_LINK_KEY_NOTIFICATION: case EV_ENCRYPTION_CHANGE: case EV_READ_REMOTE_VERSION_INFORMATION_COMPLETE: break; #ifdef EXTRADEBUG default: if(hcibuf[0] != 0x00) { Notify(PSTR("\r\nUnmanaged HCI Event: ")); PrintHex<uint8_t>(hcibuf[0]); } break; #endif } // switch HCI_task(); } #ifdef EXTRADEBUG else { Notify(PSTR("\r\nHCI event error: ")); PrintHex<uint8_t>(rcode); } #endif }