Example #1
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
}
Example #2
0
/*
 * pin_req():
 *
 * Called by HCI when a request for a PIN code has been received. A PIN code
 * is required to create a new link key.
 * Replys to the request with the given PIN code
 */
err_t pin_req(void *arg, struct bd_addr *bdaddr)
{
	u8_t pin[] = "1234";
	LWIP_DEBUGF(BT_SPP_DEBUG, ("pin_req\n"));
	return hci_pin_code_request_reply(bdaddr, 4, pin);
}
Example #3
0
void BTD::HCI_event_task() {
        uint16_t length = BULK_MAXPKTSIZE; // Request more than 16 bytes anyway, the inTransfer routine will take care of this
        char reading_buffer[length];

        serial_port->readBytes(reading_buffer, length);
        memcpy((void*)hcibuf, (void*)reading_buffer, sizeof(BULK_MAXPKTSIZE));

        if(1) { // Check for errors
                switch(hcibuf[0]) { // Switch on event type
                        case EV_COMMAND_COMPLETE:
                                if(!hcibuf[5]) { // Check if command succeeded
                                        hci_set_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_set_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_set_flag(HCI_FLAG_READ_BDADDR);
                                        }
                                }
                                break;

                        case EV_COMMAND_STATUS:
                                if(hcibuf[2]) { // Show status on serial if not OK
#ifdef DEBUG_USB_HOST
                                        Notify(PSTR("\r\nHCI Command Failed: "), 0x80);
                                        D_PrintHex<uint8_t > (hcibuf[2], 0x80);
#endif
                                }
                                break;

                        case EV_INQUIRY_COMPLETE:
                                if(inquiry_counter >= 5 && (pairWithWii || pairWithHIDDevice)) {
                                        inquiry_counter = 0;
#ifdef DEBUG_USB_HOST
                                        if(pairWithWii)
                                                Notify(PSTR("\r\nCouldn't find Wiimote"), 0x80);
                                        else
                                                Notify(PSTR("\r\nCouldn't find HID device"), 0x80);
#endif
                                        connectToWii = false;
                                        pairWithWii = false;
                                        connectToHIDDevice = false;
                                        pairWithHIDDevice = 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: "), 0x80);
                                        Notify(hcibuf[2], 0x80);
#endif
                                        for(uint8_t i = 0; i < hcibuf[2]; i++) {
                                                uint8_t offset = 8 * hcibuf[2] + 3 * i;

                                                for(uint8_t j = 0; j < 3; j++)
                                                        classOfDevice[j] = hcibuf[j + 4 + offset];

                                                if(pairWithWii && classOfDevice[2] == 0x00 && (classOfDevice[1] & 0x05) && (classOfDevice[0] & 0x0C)) { // See http://wiibrew.org/wiki/Wiimote#SDP_information
                                                        if(classOfDevice[0] & 0x08) // Check if it's the new Wiimote with motion plus inside that was detected
                                                                motionPlusInside = true;
                                                        else
                                                                motionPlusInside = false;

                                                        for(uint8_t j = 0; j < 6; j++)
                                                                disc_bdaddr[j] = hcibuf[j + 3 + 6 * i];

                                                        hci_set_flag(HCI_FLAG_DEVICE_FOUND);
                                                        break;
                                                } else if(pairWithHIDDevice && (classOfDevice[1] & 0x05) && (classOfDevice[0] & 0xC8)) { // Check if it is a mouse, keyboard or a gamepad - see: http://bluetooth-pentest.narod.ru/software/bluetooth_class_of_device-service_generator.html
#ifdef DEBUG_USB_HOST
                                                        if(classOfDevice[0] & 0x80)
                                                                Notify(PSTR("\r\nMouse found"), 0x80);
                                                        if(classOfDevice[0] & 0x40)
                                                                Notify(PSTR("\r\nKeyboard found"), 0x80);
                                                        if(classOfDevice[0] & 0x08)
                                                                Notify(PSTR("\r\nGamepad found"), 0x80);
#endif

                                                        for(uint8_t j = 0; j < 6; j++)
                                                                disc_bdaddr[j] = hcibuf[j + 3 + 6 * i];

                                                        hci_set_flag(HCI_FLAG_DEVICE_FOUND);
                                                }
#ifdef EXTRADEBUG
                                                else {
                                                        Notify(PSTR("\r\nClass of device: "), 0x80);
                                                        D_PrintHex<uint8_t > (classOfDevice[2], 0x80);
                                                        Notify(PSTR(" "), 0x80);
                                                        D_PrintHex<uint8_t > (classOfDevice[1], 0x80);
                                                        Notify(PSTR(" "), 0x80);
                                                        D_PrintHex<uint8_t > (classOfDevice[0], 0x80);
                                                }
#endif
                                        }
                                }
                                break;

                        case EV_CONNECT_COMPLETE:
                                hci_set_flag(HCI_FLAG_CONNECT_EVENT);
                                if(!hcibuf[2]) { // Check if connected OK
#ifdef EXTRADEBUG
                                        Notify(PSTR("\r\nConnection established"), 0x80);
#endif
                                        hci_handle = hcibuf[3] | ((hcibuf[4] & 0x0F) << 8); // Store the handle for the ACL connection
                                        hci_set_flag(HCI_FLAG_CONNECT_COMPLETE); // Set connection complete flag
                                } else {
                                        hci_state = HCI_CHECK_DEVICE_SERVICE;
#ifdef DEBUG_USB_HOST
                                        Notify(PSTR("\r\nConnection Failed: "), 0x80);
                                        D_PrintHex<uint8_t > (hcibuf[2], 0x80);
#endif
                                }
                                break;

                        case EV_DISCONNECT_COMPLETE:
                                if(!hcibuf[2]) { // Check if disconnected OK
                                        hci_set_flag(HCI_FLAG_DISCONNECT_COMPLETE); // Set disconnect command complete flag
                                        hci_clear_flag(HCI_FLAG_CONNECT_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 < min(sizeof (remote_name), sizeof (hcibuf) - 9); i++) {
                                                remote_name[i] = hcibuf[9 + i];
                                                if(remote_name[i] == '\0') // End of string
                                                        break;
                                        }
                                        hci_set_flag(HCI_FLAG_REMOTE_NAME_COMPLETE);
                                }
                                break;

                        case EV_INCOMING_CONNECT:
                                for(uint8_t i = 0; i < 6; i++)
                                        disc_bdaddr[i] = hcibuf[i + 2];

                                for(uint8_t i = 0; i < 3; i++)
                                        classOfDevice[i] = hcibuf[i + 8];

                                if((classOfDevice[1] & 0x05) && (classOfDevice[0] & 0xC8)) { // Check if it is a mouse, keyboard or a gamepad
#ifdef DEBUG_USB_HOST
                                        if(classOfDevice[0] & 0x80)
                                                Notify(PSTR("\r\nMouse is connecting"), 0x80);
                                        if(classOfDevice[0] & 0x40)
                                                Notify(PSTR("\r\nKeyboard is connecting"), 0x80);
                                        if(classOfDevice[0] & 0x08)
                                                Notify(PSTR("\r\nGamepad is connecting"), 0x80);
#endif
                                        incomingHIDDevice = true;
                                }

#ifdef EXTRADEBUG
                                Notify(PSTR("\r\nClass of device: "), 0x80);
                                D_PrintHex<uint8_t > (classOfDevice[2], 0x80);
                                Notify(PSTR(" "), 0x80);
                                D_PrintHex<uint8_t > (classOfDevice[1], 0x80);
                                Notify(PSTR(" "), 0x80);
                                D_PrintHex<uint8_t > (classOfDevice[0], 0x80);
#endif
                                hci_set_flag(HCI_FLAG_INCOMING_REQUEST);
                                break;

                        case EV_PIN_CODE_REQUEST:
                                if(pairWithWii) {
#ifdef DEBUG_USB_HOST
                                        Notify(PSTR("\r\nPairing with wiimote"), 0x80);
#endif
                                        hci_pin_code_request_reply();
                                } else if(btdPin != NULL) {
#ifdef DEBUG_USB_HOST
                                        Notify(PSTR("\r\nBluetooth pin is set too: "), 0x80);
                                        NotifyStr(btdPin, 0x80);
#endif
                                        hci_pin_code_request_reply();
                                } else {
#ifdef DEBUG_USB_HOST
                                        Notify(PSTR("\r\nNo pin was set"), 0x80);
#endif
                                        hci_pin_code_negative_request_reply();
                                }
                                break;

                        case EV_LINK_KEY_REQUEST:
#ifdef DEBUG_USB_HOST
                                Notify(PSTR("\r\nReceived Key Request"), 0x80);
#endif
                                hci_link_key_request_negative_reply();
                                break;

                        case EV_AUTHENTICATION_COMPLETE:
                                if(pairWithWii && !connectToWii) {
#ifdef DEBUG_USB_HOST
                                        Notify(PSTR("\r\nPairing successful with Wiimote"), 0x80);
#endif
                                        connectToWii = true; // Used to indicate to the Wii service, that it should connect to this device
                                } else if(pairWithHIDDevice && !connectToHIDDevice) {
#ifdef DEBUG_USB_HOST
                                        Notify(PSTR("\r\nPairing successful with HID device"), 0x80);
#endif
                                        connectToHIDDevice = true; // Used to indicate to the BTHID service, that it should connect to this device
                                }
                                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: "), 0x80);
                                        D_PrintHex<uint8_t > (hcibuf[0], 0x80);
                                }
                                break;
#endif
                } // Switch
        }
#ifdef EXTRADEBUG
        else {
                Notify(PSTR("\r\nHCI event error: "), 0x80);
                D_PrintHex<uint8_t > (rcode, 0x80);
        }
#endif
}