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
Exemple #2
0
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
}