private void BulkReadingThread() { while (true) { //Read every bInterval Thread.Sleep(BulkInPipe.PipeEndpoint.bInterval); { try { BulkInPipe.TransferData(BulkInBuffer, 0, BulkInBuffer.Length); // uncomment for debugging /* int i = 0; WriteSerial( ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) + " " + ByteToHex(BulkInBuffer[i++]) ); */ if (((BulkInBuffer[0] | (BulkInBuffer[1] << 8)) == (hci_handle | 0x2000)))//acl_handle_ok { if ((BulkInBuffer[6] | (BulkInBuffer[7] << 8)) == 0x0001)//l2cap_control - Channel ID for ACL-U { if (BulkInBuffer[8] != 0x00) Debug.Print("L2CAP Signaling Command - 0x" + ByteToHex(BulkInBuffer[8])); if (BulkInBuffer[8] == L2CAP_CMD_COMMAND_REJECT) Debug.Print("L2CAP Command Reject - Reason: " + ByteToHex(BulkInBuffer[13]) + ByteToHex(BulkInBuffer[12]) + " Data: " + ByteToHex(BulkInBuffer[17]) + " " + ByteToHex(BulkInBuffer[16]) + " " + ByteToHex(BulkInBuffer[15]) + " " + ByteToHex(BulkInBuffer[14])); else if (BulkInBuffer[8] == L2CAP_CMD_CONNECTION_REQUEST) { //Debug.Print("Code: 0x" + ByteToHex(BulkInBuffer[8]) + " Identifier: 0x" + ByteToHex(BulkInBuffer[9]) + " Length: 0x" + ByteToHex(BulkInBuffer[11]) + ByteToHex(BulkInBuffer[10]) + " PSM: 0x" + ByteToHex(BulkInBuffer[13]) + ByteToHex(BulkInBuffer[12]) + " SCID: 0x" + ByteToHex(BulkInBuffer[15]) + ByteToHex(BulkInBuffer[14])); Debug.Print("L2CAP Connection Request - Source CID: 0x" + ByteToHex(BulkInBuffer[15]) + ByteToHex(BulkInBuffer[14]) + " PSM: 0x" + ByteToHex(BulkInBuffer[13]) + ByteToHex(BulkInBuffer[12])); if ((BulkInBuffer[13] | BulkInBuffer[12]) == L2CAP_PSM_HID_CTRL) { identifier = BulkInBuffer[9]; control_scid[0] = BulkInBuffer[14]; control_scid[1] = BulkInBuffer[15]; l2cap_event_status |= l2cap_event.L2CAP_EV_CONTROL_CONNECTION_REQUEST; } else if ((BulkInBuffer[13] | BulkInBuffer[12]) == L2CAP_PSM_HID_INTR) { identifier = BulkInBuffer[9]; interrupt_scid[0] = BulkInBuffer[14]; interrupt_scid[1] = BulkInBuffer[15]; l2cap_event_status |= l2cap_event.L2CAP_EV_INTERRUPT_CONNECTION_REQUEST; } } else if (BulkInBuffer[8] == L2CAP_CMD_CONFIG_RESPONSE) { if (BulkInBuffer[12] == control_dcid[0] && BulkInBuffer[13] == control_dcid[1]) { if ((BulkInBuffer[16] | (BulkInBuffer[17] << 8)) == 0x0000)//Success { Debug.Print("HID Control Configuration Complete"); l2cap_event_status |= l2cap_event.L2CAP_EV_CONTROL_CONFIG_SUCCESS; } } else if (BulkInBuffer[12] == interrupt_dcid[0] && BulkInBuffer[13] == interrupt_dcid[1]) { if ((BulkInBuffer[16] | (BulkInBuffer[17] << 8)) == 0x0000)//Success { Debug.Print("HID Interrupt Configuration Complete"); l2cap_event_status |= l2cap_event.L2CAP_EV_INTERRUPT_CONFIG_SUCCESS; } } } else if (BulkInBuffer[8] == L2CAP_CMD_CONFIG_REQUEST) { if (BulkInBuffer[12] == control_dcid[0] && BulkInBuffer[13] == control_dcid[1]) { Debug.Print("HID Control Configuration Request"); identifier = BulkInBuffer[9]; l2cap_event_status |= l2cap_event.L2CAP_EV_CONTROL_CONFIG_REQUEST; } else if (BulkInBuffer[12] == interrupt_dcid[0] && BulkInBuffer[13] == interrupt_dcid[1]) { Debug.Print("HID Interrupt Configuration Request"); identifier = BulkInBuffer[9]; l2cap_event_status |= l2cap_event.L2CAP_EV_INTERRUPT_CONFIG_REQUEST; } } else if (BulkInBuffer[8] == L2CAP_CMD_DISCONNECT_REQUEST) { if (BulkInBuffer[12] == control_dcid[0] && BulkInBuffer[13] == control_dcid[1]) Debug.Print("Disconnected Request: Disconnected Control"); else if (BulkInBuffer[12] == interrupt_dcid[0] && BulkInBuffer[13] == interrupt_dcid[1]) Debug.Print("Disconnected Request: Disconnected Interrupt"); } else if (BulkInBuffer[8] == L2CAP_CMD_DISCONNECT_RESPONSE) { if (BulkInBuffer[12] == control_scid[0] && BulkInBuffer[13] == control_scid[1]) { Debug.Print("Disconnected Response: Disconnected Control"); identifier = BulkInBuffer[9]; l2cap_event_status |= l2cap_event.L2CAP_EV_CONTROL_DISCONNECT_RESPONSE; } else if (BulkInBuffer[12] == interrupt_scid[0] && BulkInBuffer[13] == interrupt_scid[1]) { Debug.Print("Disconnected Response: Disconnected Interrupt"); identifier = BulkInBuffer[9]; l2cap_event_status |= l2cap_event.L2CAP_EV_INTERRUPT_DISCONNECT_RESPONSE; } } } else if (BulkInBuffer[6] == interrupt_dcid[0] && BulkInBuffer[7] == interrupt_dcid[1])//l2cap_interrupt { //Debug.Print("L2CAP Interrupt"); //readReport();//Uncomment for debugging } L2CAP_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); } } } } }
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; } }
private bool l2capflag(l2cap_event flag) { if ((l2cap_event_status & flag) == flag) return true; else return false; }