/* 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; } }
/* 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; } }