void HCI_task() { switch (hci_state) { case HCI_INIT_STATE: hci_counter++; if (hci_counter > 10) { // wait until we have looped 10 times to clear any old events WriteSerial("Init State"); hci_reset(); hci_state = HCI_RESET_STATE; hci_counter = 0; } break; case HCI_RESET_STATE: hci_counter++; if (hciflag(hci_event.HCI_FLAG_CMD_COMPLETE)) { WriteSerial("HCI Reset Complete"); hci_state = HCI_BDADDR_STATE; hci_read_bdaddr(); hci_counter = 0; } if (hci_counter > 100) { WriteSerial("No Response to HCI Reset - Try reconnecting the Bluetooth Dongle"); hci_state = HCI_INIT_STATE; hci_counter = 0; } break; case HCI_BDADDR_STATE: if (hciflag(hci_event.HCI_FLAG_CMD_COMPLETE)) { WriteSerial("Local Bluetooth Address: " + ByteToHex(my_bdaddr[5]).ToString() + ":" + ByteToHex(my_bdaddr[4]).ToString() + ":" + ByteToHex(my_bdaddr[3]).ToString() + ":" + ByteToHex(my_bdaddr[2]).ToString() + ":" + ByteToHex(my_bdaddr[1]).ToString() + ":" + ByteToHex(my_bdaddr[0]).ToString()); BDaddr[0] = my_bdaddr[5];//The commands are sent as LSB BDaddr[1] = my_bdaddr[4]; BDaddr[2] = my_bdaddr[3]; BDaddr[3] = my_bdaddr[2]; BDaddr[4] = my_bdaddr[1]; BDaddr[5] = my_bdaddr[0]; hci_state = HCI_SCANNING_STATE; } break; case HCI_SCANNING_STATE: WriteSerial("Wait For Incoming Connection Request"); hci_write_scan_enable(); hci_state = HCI_CONNECT_IN_STATE; break; case HCI_CONNECT_IN_STATE: if (hciflag(hci_event.HCI_FLAG_INCOMING_REQUEST)) { WriteSerial("Incoming Request"); hci_remote_name(0); hci_state = HCI_REMOTE_NAME; } break; case HCI_REMOTE_NAME: if (hciflag(hci_event.HCI_FLAG_REMOTE_NAME)) { WriteSerial("Remote Name:"); byte i; for (i = 0; i < 40; i++) { if (remote_name[i] == 0x00) break; } remote_name[i] = 13;// Carriage Return remote_name[i + 1] = 10;// Line Feed UART.Write(remote_name, 0, i + 2); hci_accept_connection(); hci_state = HCI_CONNECTED_STATE; } break; case HCI_CONNECTED_STATE: if (hciflag(hci_event.HCI_FLAG_CONN_COMPLETE)) { WriteSerial("Connected to Device: " + ByteToHex(disc_bdaddr[5]) + ":" + ByteToHex(disc_bdaddr[4]) + ":" + ByteToHex(disc_bdaddr[3]) + ":" + ByteToHex(disc_bdaddr[2]) + ":" + ByteToHex(disc_bdaddr[1]) + ":" + ByteToHex(disc_bdaddr[0])); hci_write_scan_disable();//Only allow one controller hci_state = HCI_DISABLE_SCAN; } break; case HCI_DISABLE_SCAN: if (hciflag(hci_event.HCI_FLAG_CMD_COMPLETE)) { WriteSerial("Scan Disabled"); l2cap_state = L2CAP_EV_CONTROL_SETUP; hci_state = HCI_DONE_STATE; } break; case HCI_DONE_STATE: if (hciflag(hci_event.HCI_FLAG_DISCONN_COMPLETE)) hci_state = HCI_DISCONNECT_STATE; break; case HCI_DISCONNECT_STATE: if (hciflag(hci_event.HCI_FLAG_DISCONN_COMPLETE)) { WriteSerial("Disconnected from Device: " + ByteToHex(disc_bdaddr[5]) + ":" + ByteToHex(disc_bdaddr[4]) + ":" + ByteToHex(disc_bdaddr[3]) + ":" + ByteToHex(disc_bdaddr[2]) + ":" + ByteToHex(disc_bdaddr[1]) + ":" + ByteToHex(disc_bdaddr[0])); l2cap_event_status = 0;//Clear all flags hci_event_flag = 0;//Clear all flags //Reset all buffers for (byte i = 0; i < IntInBuffer.Length; i++) IntInBuffer[i] = 0; for (byte i = 0; i < HCIBuffer.Length; i++) HCIBuffer[i] = 0; for (byte i = 0; i < BulkInBuffer.Length; i++) BulkInBuffer[i] = 0; for (byte i = 0; i < L2CAPBuffer.Length; i++) L2CAPBuffer[i] = 0; for (int i = 0; i < PS3Controller.OUTPUT_REPORT_BUFFER.Length; i++)//First two bytes reserved for report type and ID HIDBuffer[i + 2] = PS3Controller.OUTPUT_REPORT_BUFFER[i]; for (int i = 2; i < HIDMoveBuffer.Length; i++)//First two bytes reserved for DATA request and ID HIDMoveBuffer[i] = 0; l2cap_state = L2CAP_EV_WAIT; hci_state = HCI_SCANNING_STATE; } break; default: break; } }
void hci_remote_name(byte disc_device) { hci_event_flag &= ~(hci_event.HCI_FLAG_REMOTE_NAME);//Clear flag HCIBuffer[0] = 0x19; // HCI OCF = 19 HCIBuffer[1] = 0x01 << 2; // HCI OGF = 1 HCIBuffer[2] = 0x0A; // parameter length 10 HCIBuffer[3] = disc_bdaddr[0]; // 6 octet bdaddr HCIBuffer[4] = disc_bdaddr[1]; HCIBuffer[5] = disc_bdaddr[2]; HCIBuffer[6] = disc_bdaddr[3]; HCIBuffer[7] = disc_bdaddr[4]; HCIBuffer[8] = disc_bdaddr[5]; HCIBuffer[9] = 0x01;//Page Scan Repetition Mode HCIBuffer[10] = 0x00;//Reserved HCIBuffer[11] = 0x00;//Clock offset - low byte HCIBuffer[12] = 0x00;//Clock offset - high byte HCI_Command(HCIBuffer, 13); }
void hci_reset() { hci_event_flag = 0; // clear all flags HCIBuffer[0] = 0x03;// HCI OCF = 3 HCIBuffer[1] = 0x03 << 2; // HCI OGF = 3 HCIBuffer[2] = 0x00; // parameter length = 0 HCI_Command(HCIBuffer, 3); }
void hci_disconnect() { hci_event_flag &= ~(hci_event.HCI_FLAG_DISCONN_COMPLETE); HCIBuffer[0] = 0x06; // HCI OCF = 6 HCIBuffer[1] = 0x01 << 2; // HCI OGF = 1 HCIBuffer[2] = 0x03; // parameter length = 3 HCIBuffer[3] = (byte)(hci_handle & 0xFF);//connection handle - low byte HCIBuffer[4] = (byte)((hci_handle >> 8) & 0x0F);//connection handle - high byte HCIBuffer[5] = 0x13; // reason = Remote User Terminated Connection HCI_Command(HCIBuffer, 6); }
/************************************************************/ /* HCI Commands */ /************************************************************/ void HCI_Command(byte[] buf, int nbytes) { hci_command_packets--; hci_event_flag &= ~(hci_event.HCI_FLAG_CMD_COMPLETE); try { //Single FunctionPrimary Controller - Standard request raw.SendSetupTransfer(0x20, 0x00, 0x0000, 0x0000, buf, 0, nbytes); } catch { WriteSerial("HCI_Command failed"); } }
void hci_accept_connection() { hci_event_flag &= ~(hci_event.HCI_FLAG_INCOMING_REQUEST);//Clear flag HCIBuffer[0] = 0x09; // HCI OCF = 9 HCIBuffer[1] = 0x01 << 2; // HCI OGF = 1 HCIBuffer[2] = 0x07; // parameter length 7 HCIBuffer[3] = disc_bdaddr[0]; // 6 octet bdaddr HCIBuffer[4] = disc_bdaddr[1]; HCIBuffer[5] = disc_bdaddr[2]; HCIBuffer[6] = disc_bdaddr[3]; HCIBuffer[7] = disc_bdaddr[4]; HCIBuffer[8] = disc_bdaddr[5]; HCIBuffer[9] = 0x00; //switch role to master HCI_Command(HCIBuffer, 10); return; }
private bool hciflag(hci_event flag) { if ((hci_event_flag & flag) == flag) return true; else return false; }
private void IntReadingThread() { while (true) { //Read every bInterval Thread.Sleep(IntInPipe.PipeEndpoint.bInterval); { try { IntInPipe.TransferData(IntInBuffer, 0, IntInBuffer.Length); // uncomment for debugging /* int i = 0; WriteSerial( ByteToHex(IntInBuffer[i++]) + " " + ByteToHex(IntInBuffer[i++]) + " " + ByteToHex(IntInBuffer[i++]) + " " + ByteToHex(IntInBuffer[i++]) + " " + ByteToHex(IntInBuffer[i++]) + " " + ByteToHex(IntInBuffer[i++]) + " " + ByteToHex(IntInBuffer[i++]) + " " + ByteToHex(IntInBuffer[i++]) + " " + ByteToHex(IntInBuffer[i++]) + " " + ByteToHex(IntInBuffer[i++]) + " " + ByteToHex(IntInBuffer[i++]) + " " + ByteToHex(IntInBuffer[i++]) + " " + ByteToHex(IntInBuffer[i++]) + " " + ByteToHex(IntInBuffer[i++]) + " " + ByteToHex(IntInBuffer[i++]) + " " + ByteToHex(IntInBuffer[i++]) ); */ if (remote_name_bool) { for (byte i2 = 0; i2 < IntInBuffer.Length; i2++) { if (IntInBuffer[i2] == 0x00) { Debug.Print("Finished Reading Name"); remote_name_bool = false; hci_event_flag |= hci_event.HCI_FLAG_REMOTE_NAME; break; } if (IntInBuffer[0] == 0x54 || IntInBuffer[0] == 0x43 || IntInBuffer[0] == 0x69)// Second Line - 'T' in "PLAYSTATION(R)3 Controller" or 'C' in "Motion Controller" or 'i' in "Navigation Controller" remote_name[7 + i2] = IntInBuffer[i2]; else if (IntInBuffer[0] == 0x6C)// Third Line - "l" in "PLAYSTATION(R)3 Controller" remote_name[23 + i2] = IntInBuffer[i2]; else break; } } switch (IntInBuffer[0]) { /* buf[0] = Event Code */ /* buf[1] = Parameter Total Length */ /* buf[n] = Event Parameters based on each event */ case EV_REMOTE_NAME_COMPLETE: for (byte n = 0; n < remote_name.Length; n++)//Reset remote name remote_name[n] = 0; for (byte n = 9; n < IntInBuffer.Length; n++) remote_name[n - 9] = IntInBuffer[n]; remote_name_bool = true; break; case EV_COMMAND_COMPLETE: //Debug.Print("Command Complete"); hci_command_packets = IntInBuffer[2];//Update flow control if (IntInBuffer[5] != 0x00)// Check if success { hci_event_flag = ~hci_event.HCI_FLAG_CMD_COMPLETE;//Set flag WriteSerial("HCI Command Complete Failed - OGF: 0x" + (IntInBuffer[4] >> 2) + " OCF: 0x" + IntInBuffer[3]); return; } hci_event_flag |= hci_event.HCI_FLAG_CMD_COMPLETE;//Set flag // parameters from read local bluetooth address if ((IntInBuffer[3] == 0x09) && (IntInBuffer[4] == 0x10)) { for (byte n = 0; n < 6; n++) my_bdaddr[n] = IntInBuffer[6 + n]; //Debug.Print("Read Local Bluetooth Address: " + ByteToHex(my_bdaddr[5]).ToString() + ":" + ByteToHex(my_bdaddr[4]).ToString() + ":" + ByteToHex(my_bdaddr[3]).ToString() + ":" + ByteToHex(my_bdaddr[2]).ToString() + ":" + ByteToHex(my_bdaddr[1]).ToString() + ":" + ByteToHex(my_bdaddr[0]).ToString()); } break; case EV_COMMAND_STATUS: //Debug.Print("Command Status"); hci_command_packets = IntInBuffer[3];// update flow control hci_event_flag |= hci_event.HCI_FLAG_CMD_STATUS; if (IntInBuffer[2] == 0) Debug.Print("Command Status - Complete: 0x" + ByteToHex(IntInBuffer[5]) + ByteToHex(IntInBuffer[4])); else// show status on serial if not OK WriteSerial("HCI Command Failed - Error: 0x" + ByteToHex(IntInBuffer[2]) + " Command: 0x" + ByteToHex(IntInBuffer[5]) + ByteToHex(IntInBuffer[4])); break; case EV_CONNECT_COMPLETE: if (IntInBuffer[2] == 0)// check if connected OK { hci_handle = IntInBuffer[3] | IntInBuffer[4] << 8; //store the handle for the ACL connection Debug.Print("Connect Complete - HCI Handle: " + hci_handle); hci_event_flag |= hci_event.HCI_FLAG_CONN_COMPLETE; //set connection OK flag } break; case EV_DISCONNECT_COMPLETE: if (IntInBuffer[2] == 0)// check if disconnected OK { string reason = "Unknown Reason"; if (IntInBuffer[5] == 0x08) reason = "Connection Timeout"; else if (IntInBuffer[5] == 0x13) reason = "Remote User Terminated Connection"; else if (IntInBuffer[5] == 0x14) reason = "Remote Device Terminated Connection due to Low Resources"; else if (IntInBuffer[5] == 0x15) reason = "Remote Device Terminated Connection due to Power Off"; else if (IntInBuffer[5] == 0x16) reason = "Connection Terminated By Local Host"; Debug.Print("Disconnect Complete - Reason: " + reason); hci_event_flag |= hci_event.HCI_FLAG_DISCONN_COMPLETE; hci_event_flag &= ~(hci_event.HCI_FLAG_CONN_COMPLETE); //clear connection OK flag } break; case EV_NUM_COMPLETE_PKT: //Debug.Print("Number Of Completed Packets: " + (uint)(IntInBuffer[6] | IntInBuffer[7] << 8)); break; case EV_INCOMING_CONNECT: //Infact it also sends the class and link type, but it only stores the bluetooth address disc_bdaddr[0] = IntInBuffer[2]; disc_bdaddr[1] = IntInBuffer[3]; disc_bdaddr[2] = IntInBuffer[4]; disc_bdaddr[3] = IntInBuffer[5]; disc_bdaddr[4] = IntInBuffer[6]; disc_bdaddr[5] = IntInBuffer[7]; Debug.Print("Incoming Connection"); Debug.Print("Bluetooth Address: " + ByteToHex(disc_bdaddr[5]) + ":" + ByteToHex(disc_bdaddr[4]) + ":" + ByteToHex(disc_bdaddr[3]) + ":" + ByteToHex(disc_bdaddr[2]) + ":" + ByteToHex(disc_bdaddr[1]) + ":" + ByteToHex(disc_bdaddr[0])); hci_event_flag |= hci_event.HCI_FLAG_INCOMING_REQUEST; break; case EV_ROLE_CHANGED: Debug.Print("Role Changed"); dev_role = IntInBuffer[9]; break; default: if (IntInBuffer[0] != 0x00) Debug.Print("Unmanaged event: " + ByteToHex(IntInBuffer[0])); break; } HCI_task();//Start HCI_task } catch (Exception ex) { WriteSerial("Exception was thrown - try reconnecting the bluetooth dongle"); Debug.Print("=============================="); Debug.Print(DateTime.Now.ToString()); Debug.Print(ex.Message); Debug.Print(ex.StackTrace); if (ex.InnerException != null) { Debug.Print("Inner Exception: " + ex.InnerException.Message); } } } } }