예제 #1
1
파일: BTD.cpp 프로젝트: CaptFrank/GHID
/* Poll Bluetooth and print result */
void BTD::HCI_task() {
        switch(hci_state) {
                case HCI_INIT_STATE:
                        hci_counter++;
                        if(hci_counter > hci_num_reset_loops) { // wait until we have looped x times to clear any old events
                                hci_reset();
                                hci_state = HCI_RESET_STATE;
                                hci_counter = 0;
                        }
                        break;

                case HCI_RESET_STATE:
                        hci_counter++;
                        if(hci_check_flag(HCI_FLAG_CMD_COMPLETE)) {
                                hci_counter = 0;
#ifdef DEBUG_USB_HOST
                                Notify(PSTR("\r\nHCI Reset complete"), 0x80);
#endif
                                hci_state = HCI_CLASS_STATE;
                                hci_write_class_of_device();
                        } else if(hci_counter > hci_num_reset_loops) {
                                hci_num_reset_loops *= 10;
                                if(hci_num_reset_loops > 2000)
                                        hci_num_reset_loops = 2000;
#ifdef DEBUG_USB_HOST
                                Notify(PSTR("\r\nNo response to HCI Reset"), 0x80);
#endif
                                hci_state = HCI_INIT_STATE;
                                hci_counter = 0;
                        }
                        break;

                case HCI_CLASS_STATE:
                        if(hci_check_flag(HCI_FLAG_CMD_COMPLETE)) {
#ifdef DEBUG_USB_HOST
                                Notify(PSTR("\r\nWrite class of device"), 0x80);
#endif
                                hci_state = HCI_BDADDR_STATE;
                                hci_read_bdaddr();
                        }
                        break;

                case HCI_BDADDR_STATE:
                        if(hci_check_flag(HCI_FLAG_READ_BDADDR)) {
#ifdef DEBUG_USB_HOST
                                Notify(PSTR("\r\nLocal Bluetooth Address: "), 0x80);
                                for(int8_t i = 5; i > 0; i--) {
                                        D_PrintHex<uint8_t > (my_bdaddr[i], 0x80);
                                        Notify(PSTR(":"), 0x80);
                                }
                                D_PrintHex<uint8_t > (my_bdaddr[0], 0x80);
#endif
                                hci_read_local_version_information();
                                hci_state = HCI_LOCAL_VERSION_STATE;
                        }
                        break;

                case HCI_LOCAL_VERSION_STATE: // The local version is used by the PS3BT class
                        if(hci_check_flag(HCI_FLAG_READ_VERSION)) {
                                if(btdName != NULL) {
                                        hci_set_local_name(btdName);
                                        hci_state = HCI_SET_NAME_STATE;
                                } else
                                        hci_state = HCI_CHECK_DEVICE_SERVICE;
                        }
                        break;

                case HCI_SET_NAME_STATE:
                        if(hci_check_flag(HCI_FLAG_CMD_COMPLETE)) {
#ifdef DEBUG_USB_HOST
                                Notify(PSTR("\r\nThe name is set to: "), 0x80);
                                NotifyStr(btdName, 0x80);
#endif
                                hci_state = HCI_CHECK_DEVICE_SERVICE;
                        }
                        break;

                case HCI_CHECK_DEVICE_SERVICE:
                        if(pairWithHIDDevice || pairWithWii) { // Check if it should try to connect to a Wiimote
#ifdef DEBUG_USB_HOST
                                if(pairWithWii)
                                        Notify(PSTR("\r\nStarting inquiry\r\nPress 1 & 2 on the Wiimote\r\nOr press sync if you are using a Wii U Pro Controller"), 0x80);
                                else
                                        Notify(PSTR("\r\nPlease enable discovery of your device"), 0x80);
#endif
                                hci_inquiry();
                                hci_state = HCI_INQUIRY_STATE;
                        } else
                                hci_state = HCI_SCANNING_STATE; // Don't try to connect to a Wiimote
                        break;

                case HCI_INQUIRY_STATE:
                        if(hci_check_flag(HCI_FLAG_DEVICE_FOUND)) {
                                hci_inquiry_cancel(); // Stop inquiry
#ifdef DEBUG_USB_HOST
                                if(pairWithWii)
                                        Notify(PSTR("\r\nWiimote found"), 0x80);
                                else
                                        Notify(PSTR("\r\nHID device found"), 0x80);

                                Notify(PSTR("\r\nNow just create the instance like so:"), 0x80);
                                if(pairWithWii)
                                        Notify(PSTR("\r\nWII Wii(&Btd);"), 0x80);
                                else
                                        Notify(PSTR("\r\nBTHID hid(&Btd);"), 0x80);

                                Notify(PSTR("\r\nAnd then press any button on the "), 0x80);
                                if(pairWithWii)
                                        Notify(PSTR("Wiimote"), 0x80);
                                else
                                        Notify(PSTR("device"), 0x80);
#endif
                                if(motionPlusInside) {
                                        hci_remote_name(); // We need to know the name to distinguish between a Wiimote and a Wii U Pro Controller
                                        hci_state = HCI_REMOTE_NAME_STATE;
                                } else
                                        hci_state = HCI_CONNECT_DEVICE_STATE;
                        }
                        break;

                case HCI_CONNECT_DEVICE_STATE:
                        if(hci_check_flag(HCI_FLAG_CMD_COMPLETE)) {
#ifdef DEBUG_USB_HOST
                                if(pairWithWii)
                                        Notify(PSTR("\r\nConnecting to Wiimote"), 0x80);
                                else
                                        Notify(PSTR("\r\nConnecting to HID device"), 0x80);
#endif
                                hci_connect();
                                hci_state = HCI_CONNECTED_DEVICE_STATE;
                        }
                        break;

                case HCI_CONNECTED_DEVICE_STATE:
                        if(hci_check_flag(HCI_FLAG_CONNECT_EVENT)) {
                                if(hci_check_flag(HCI_FLAG_CONNECT_COMPLETE)) {
#ifdef DEBUG_USB_HOST
                                        if(pairWithWii)
                                                Notify(PSTR("\r\nConnected to Wiimote"), 0x80);
                                        else
                                                Notify(PSTR("\r\nConnected to HID device"), 0x80);
#endif
                                        hci_authentication_request(); // This will start the pairing with the Wiimote
                                        hci_state = HCI_SCANNING_STATE;
                                } else {
#ifdef DEBUG_USB_HOST
                                        Notify(PSTR("\r\nTrying to connect one more time..."), 0x80);
#endif
                                        hci_connect(); // Try to connect one more time
                                }
                        }
                        break;

                case HCI_SCANNING_STATE:
                        if(!connectToWii && !pairWithWii && !connectToHIDDevice && !pairWithHIDDevice) {
#ifdef DEBUG_USB_HOST
                                Notify(PSTR("\r\nWait For Incoming Connection Request"), 0x80);
#endif
                                hci_write_scan_enable();
                                watingForConnection = true;
                                hci_state = HCI_CONNECT_IN_STATE;
                        }
                        break;

                case HCI_CONNECT_IN_STATE:
                        if(hci_check_flag(HCI_FLAG_INCOMING_REQUEST)) {
                                watingForConnection = false;
#ifdef DEBUG_USB_HOST
                                Notify(PSTR("\r\nIncoming Connection Request"), 0x80);
#endif
                                hci_remote_name();
                                hci_state = HCI_REMOTE_NAME_STATE;
                        } else if(hci_check_flag(HCI_FLAG_DISCONNECT_COMPLETE))
                                hci_state = HCI_DISCONNECT_STATE;
                        break;

                case HCI_REMOTE_NAME_STATE:
                        if(hci_check_flag(HCI_FLAG_REMOTE_NAME_COMPLETE)) {
#ifdef DEBUG_USB_HOST
                                Notify(PSTR("\r\nRemote Name: "), 0x80);
                                for(uint8_t i = 0; i < strlen(remote_name); i++)
                                        Notifyc(remote_name[i], 0x80);
#endif
                                if(strncmp((const char*)remote_name, "Nintendo", 8) == 0) {
                                        incomingWii = true;
#ifdef DEBUG_USB_HOST
                                        Notify(PSTR("\r\nWiimote is connecting"), 0x80);
#endif
                                        if(strncmp((const char*)remote_name, "Nintendo RVL-CNT-01-TR", 22) == 0) {
#ifdef DEBUG_USB_HOST
                                                Notify(PSTR(" with Motion Plus Inside"), 0x80);
#endif
                                                motionPlusInside = true;
                                        } else if(strncmp((const char*)remote_name, "Nintendo RVL-CNT-01-UC", 22) == 0) {
#ifdef DEBUG_USB_HOST
                                                Notify(PSTR(" - Wii U Pro Controller"), 0x80);
#endif
                                                motionPlusInside = true;
                                                wiiUProController = true;
                                        } else {
                                                motionPlusInside = false;
                                                wiiUProController = false;
                                        }
                                }
                                if(classOfDevice[2] == 0 && classOfDevice[1] == 0x25 && classOfDevice[0] == 0x08 && strncmp((const char*)remote_name, "Wireless Controller", 19) == 0) {
#ifdef DEBUG_USB_HOST
                                        Notify(PSTR("\r\nPS4 controller is connecting"), 0x80);
#endif
                                        incomingPS4 = true;
                                }
                                if(pairWithWii && motionPlusInside)
                                        hci_state = HCI_CONNECT_DEVICE_STATE;
                                else {
                                        hci_accept_connection();
                                        hci_state = HCI_CONNECTED_STATE;
                                }
                        }
                        break;

                case HCI_CONNECTED_STATE:
                        if(hci_check_flag(HCI_FLAG_CONNECT_COMPLETE)) {
#ifdef DEBUG_USB_HOST
                                Notify(PSTR("\r\nConnected to Device: "), 0x80);
                                for(int8_t i = 5; i > 0; i--) {
                                        D_PrintHex<uint8_t > (disc_bdaddr[i], 0x80);
                                        Notify(PSTR(":"), 0x80);
                                }
                                D_PrintHex<uint8_t > (disc_bdaddr[0], 0x80);
#endif
                                if(incomingPS4)
                                        connectToHIDDevice = true; // We should always connect to the PS4 controller

                                // Clear these flags for a new connection
                                l2capConnectionClaimed = false;
                                sdpConnectionClaimed = false;
                                rfcommConnectionClaimed = false;

                                hci_event_flag = 0;
                                hci_state = HCI_DONE_STATE;
                        }
                        break;

                case HCI_DONE_STATE:
                        hci_counter++;
                        if(hci_counter > 1000) { // Wait until we have looped 1000 times to make sure that the L2CAP connection has been started
                                hci_counter = 0;
                                hci_state = HCI_SCANNING_STATE;
                        }
                        break;

                case HCI_DISCONNECT_STATE:
                        if(hci_check_flag(HCI_FLAG_DISCONNECT_COMPLETE)) {
#ifdef DEBUG_USB_HOST
                                Notify(PSTR("\r\nHCI Disconnected from Device"), 0x80);
#endif
                                hci_event_flag = 0; // Clear all flags

                                // Reset all buffers
                                memset(hcibuf, 0, BULK_MAXPKTSIZE);
                                memset(l2capinbuf, 0, BULK_MAXPKTSIZE);

                                connectToWii = incomingWii = pairWithWii = false;
                                connectToHIDDevice = incomingHIDDevice = pairWithHIDDevice = false;
                                incomingPS4 = false;

                                hci_state = HCI_SCANNING_STATE;
                        }
                        break;
                default:
                        break;
        }
}
예제 #2
0
/* Poll Bluetooth and print result */
void BTD::HCI_task() {
    switch (hci_state){
        case HCI_INIT_STATE:
            hci_counter++;
            if (hci_counter > hci_num_reset_loops) { // wait until we have looped x times to clear any old events
                hci_reset();
                hci_state = HCI_RESET_STATE;
                hci_counter = 0;
            }
            break;
            
        case HCI_RESET_STATE:
            hci_counter++;
            if (hci_cmd_complete) {
                hci_counter = 0;
#ifdef DEBUG
                Notify(PSTR("\r\nHCI Reset complete"));
#endif
                hci_state = HCI_CLASS_STATE;
                hci_write_class_of_device(); 
            }
            else if (hci_counter > hci_num_reset_loops) {
                hci_num_reset_loops *= 10;
                if(hci_num_reset_loops > 2000)
                    hci_num_reset_loops = 2000;
#ifdef DEBUG
                Notify(PSTR("\r\nNo response to HCI Reset"));
#endif
                hci_state = HCI_INIT_STATE;
                hci_counter = 0;
            }
            break;

        case HCI_CLASS_STATE:
            if(hci_cmd_complete) {
#ifdef DEBUG
                Notify(PSTR("\r\nWrite class of device"));
#endif
                hci_state = HCI_BDADDR_STATE;
                hci_read_bdaddr(); 
            }
            break;
            
        case HCI_BDADDR_STATE:
            if (hci_read_bdaddr_complete) {
#ifdef DEBUG
                Notify(PSTR("\r\nLocal Bluetooth Address: "));
                for(int8_t i = 5; i > 0;i--) {
                    PrintHex<uint8_t>(my_bdaddr[i]); 
                    Notify(PSTR(":"));
                }      
                PrintHex<uint8_t>(my_bdaddr[0]);
#endif
                hci_read_local_version_information();
                hci_state = HCI_LOCAL_VERSION_STATE;                
            }
            break;
            
        case HCI_LOCAL_VERSION_STATE: // The local version is used by the PS3BT class
            if (hci_read_version_complete) {
                if(btdName != NULL) {
                    hci_set_local_name(btdName);
                    hci_state = HCI_SET_NAME_STATE;
                } else
                    hci_state = HCI_CHECK_WII_SERVICE;                    
            }
            break;
            
        case HCI_SET_NAME_STATE:
            if (hci_cmd_complete) {
#ifdef DEBUG               
                Notify(PSTR("\r\nThe name is set to: "));
                Serial.print(btdName);
#endif
                hci_state = HCI_CHECK_WII_SERVICE;
            }
            break;
            
        case HCI_CHECK_WII_SERVICE:
            if(pairWithWii) { // Check if it should try to connect to a wiimote
#ifdef DEBUG
                Notify(PSTR("\r\nStarting inquiry\r\nPress 1 & 2 on the Wiimote\r\nOr press sync if you are using a Wii U Pro Controller"));
#endif
                hci_inquiry();
                hci_state = HCI_INQUIRY_STATE;
            }
            else
                hci_state = HCI_SCANNING_STATE; // Don't try to connect to a Wiimote
            break;
            
        case HCI_INQUIRY_STATE:
            if(hci_wii_found) {
                hci_inquiry_cancel(); // Stop inquiry
#ifdef DEBUG
                Notify(PSTR("\r\nWiimote found"));                
                Notify(PSTR("\r\nNow just create the instance like so:"));
                Notify(PSTR("\r\nWII Wii(&Btd);"));
                Notify(PSTR("\r\nAnd then press any button on the Wiimote"));                
#endif                                
                if(motionPlusInside) {
                    hci_remote_name(); // We need to know the name to distinguish between a Wiimote and a Wii U Pro Controller
                    hci_state = HCI_REMOTE_NAME_STATE;
                } else
                    hci_state = HCI_CONNECT_WII_STATE;
            }
            break;
            
        case HCI_CONNECT_WII_STATE:
            if(hci_cmd_complete) {
#ifdef DEBUG
                Notify(PSTR("\r\nConnecting to Wiimote"));
#endif            
                hci_connect();
                hci_state = HCI_CONNECTED_WII_STATE;
            }
            break;
            
        case HCI_CONNECTED_WII_STATE:
            if(hci_connect_event) {
                if(hci_connect_complete) {
#ifdef DEBUG
                    Notify(PSTR("\r\nConnected to Wiimote"));
#endif                    
                    hci_authentication_request(); // This will start the pairing with the wiimote
                    hci_state = HCI_SCANNING_STATE;
                } else {
#ifdef DEBUG
                    Notify(PSTR("\r\nTrying to connect one more time..."));
#endif
                    hci_connect(); // Try to connect one more time
                }
            }
            break;
            
        case HCI_SCANNING_STATE:
            if(!connectToWii && !pairWithWii) {
#ifdef DEBUG
                Notify(PSTR("\r\nWait For Incoming Connection Request"));
#endif            
                hci_write_scan_enable();
                watingForConnection = true;
                hci_state = HCI_CONNECT_IN_STATE;
            }
            break;
            
        case HCI_CONNECT_IN_STATE:
            if(hci_incoming_connect_request) {
                watingForConnection = false;
#ifdef DEBUG
                Notify(PSTR("\r\nIncoming Connection Request"));
#endif                
                hci_remote_name();
                hci_state = HCI_REMOTE_NAME_STATE;
            } else if (hci_disconnect_complete)
                hci_state = HCI_DISCONNECT_STATE;
            break;     
            
        case HCI_REMOTE_NAME_STATE:
            if(hci_remote_name_complete) {
#ifdef DEBUG
                Notify(PSTR("\r\nRemote Name: "));
                for (uint8_t i = 0; i < 30; i++) {
                    if(remote_name[i] == NULL)
                        break;
                    Serial.write(remote_name[i]);
                }
#endif
                if(strncmp((const char*)remote_name, "Nintendo", 8) == 0) {
#ifdef DEBUG
                    Notify(PSTR("\r\nWiimote is connecting"));
#endif
                    if(strncmp((const char*)remote_name, "Nintendo RVL-CNT-01-TR", 22) == 0) {
#ifdef DEBUG
                        Notify(PSTR(" with Motion Plus Inside"));
#endif
                        motionPlusInside = true;
                    }
                    else if(strncmp((const char*)remote_name, "Nintendo RVL-CNT-01-UC", 22) == 0) {
#ifdef DEBUG
                        Notify(PSTR(" - Wii U Pro Controller"));
#endif
                        motionPlusInside = true;
                        wiiUProController = true;
                    } else {
                        motionPlusInside = false;
                        wiiUProController = false;
                    }
                    incomingWii = true;
                }
                if(pairWithWii && motionPlusInside)
                    hci_state = HCI_CONNECT_WII_STATE;
                else {
                    hci_accept_connection();
                    hci_state = HCI_CONNECTED_STATE;
                }
            }      
            break;
            
        case HCI_CONNECTED_STATE:
            if (hci_connect_complete) {     
#ifdef DEBUG
                Notify(PSTR("\r\nConnected to Device: "));
                for(int8_t i = 5; i>0;i--) {
                    PrintHex<uint8_t>(disc_bdaddr[i]);
                    Notify(PSTR(":"));
                }      
                PrintHex<uint8_t>(disc_bdaddr[0]);
#endif
                // Clear these flags for a new connection
                l2capConnectionClaimed = false;
                sdpConnectionClaimed = false;
                rfcommConnectionClaimed = false;
                          
                hci_event_flag = 0;
                hci_state = HCI_DONE_STATE;
            }
            break;

        case HCI_DONE_STATE:
            hci_counter++;
            if (hci_counter > 1000) { // Wait until we have looped 1000 times to make sure that the L2CAP connection has been started
                hci_counter = 0;
                hci_state = HCI_SCANNING_STATE;                
            }            
            break;
            
        case HCI_DISCONNECT_STATE:
            if (hci_disconnect_complete) {
#ifdef DEBUG
                Notify(PSTR("\r\nHCI Disconnected from Device"));
#endif
                hci_event_flag = 0; // Clear all flags 
                
                // Reset all buffers                        
                for (uint8_t i = 0; i < BULK_MAXPKTSIZE; i++)
                    hcibuf[i] = 0;        
                for (uint8_t i = 0; i < BULK_MAXPKTSIZE; i++)
                    l2capinbuf[i] = 0;
                                                        
                hci_state = HCI_SCANNING_STATE;
            }
            break;
        default:
            break;
    }
}