예제 #1
0
int  stdin_process(struct data_source *ds){
    char buffer;
    read(ds->fd, &buffer, 1);

    // passkey input
    if (ui_digits_for_passkey){
        if (buffer < '0' || buffer > '9') return 0;
        printf("%c", buffer);
        fflush(stdout);
        ui_passkey = ui_passkey * 10 + buffer - '0';
        ui_digits_for_passkey--;
        if (ui_digits_for_passkey == 0){
            printf("\nSending Passkey '%06x'\n", ui_passkey);
            sm_passkey_input(master_addr_type, master_address, ui_passkey);
        }
        return 0;
    }

    switch (buffer){
        case 'a':
            gap_advertisements = 0;
            update_advertisements();
            show_usage();
            break;
        case 'A':
            gap_advertisements = 1;
            update_advertisements();
            show_usage();
            break;
        case 'b':
            gap_bondable = 0;
            sm_set_authentication_requirements(SM_AUTHREQ_NO_BONDING);
            show_usage();
            break;
        case 'B':
            gap_bondable = 1;
            sm_set_authentication_requirements(SM_AUTHREQ_BONDING);
            show_usage();
            break;
        case 'c':
            gap_connectable = 0;
            update_advertisements();
            break;
        case 'C':
            gap_connectable = 1;
            update_advertisements();
            break;
        case 'd':
            gap_discoverable = 0;
            update_advertisements();
            break;
        case 'D':
            gap_discoverable = 1;
            update_advertisements();
            break;
        case 'r':
            gap_random = 0;
            update_advertisements();
            break;
        case 'R':
            gap_random = 1;
            update_advertisements();
            break;
        case 'x':
            gap_directed_connectable = 0;
            update_advertisements();
            break;
        case 'X':
            gap_directed_connectable = 1;
            update_advertisements();
            break;
        case 'y':
            gap_scannable = 0;
            update_advertisements();
            break;
        case 'Y':
            gap_scannable = 1;
            update_advertisements();
            break;
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9':
        case '0':
            advertisement_index = buffer - '0';
            update_advertisements();
            break;
        case '+':
            advertisement_index = 10;
            update_advertisements();
            break;
        case '-':
            advertisement_index = 11;
            update_advertisements();
            break;
        case '&':
            advertisement_index = 12;
            update_advertisements();
            break;
        case '=':
            advertisement_index = 13;
            update_advertisements();
            break;
        case '/':
            advertisement_index = 14;
            update_advertisements();
            break;
        case '#':
            advertisement_index = 15;
            update_advertisements();
            break;
        case 's':
            printf("SM: sending security request\n");
            sm_send_security_request();
            break;
        case 'e':
            sm_io_capabilities = "IO_CAPABILITY_DISPLAY_ONLY";
            sm_set_io_capabilities(IO_CAPABILITY_DISPLAY_ONLY);
            show_usage();
            break;
        case 'f':
            sm_io_capabilities = "IO_CAPABILITY_DISPLAY_YES_NO";
            sm_set_io_capabilities(IO_CAPABILITY_DISPLAY_YES_NO);
            show_usage();
            break;
        case 'g':
            sm_io_capabilities = "IO_CAPABILITY_NO_INPUT_NO_OUTPUT";
            sm_set_io_capabilities(IO_CAPABILITY_NO_INPUT_NO_OUTPUT);
            show_usage();
            break;
        case 'h':
            sm_io_capabilities = "IO_CAPABILITY_KEYBOARD_ONLY";
            sm_set_io_capabilities(IO_CAPABILITY_KEYBOARD_ONLY);
            show_usage();
            break;
        case 'i':
            sm_io_capabilities = "IO_CAPABILITY_KEYBOARD_DISPLAY";
            sm_set_io_capabilities(IO_CAPABILITY_KEYBOARD_DISPLAY);
            show_usage();
            break;
        case 't':
            printf("Terminating connection\n");
            hci_send_cmd(&hci_disconnect, handle, 0x13);
            break;
        case 'z':
            printf("Sending l2cap connection update parameter request\n");
            l2cap_le_request_connection_parameter_update(handle, 50, 120, 0, 550);
            break;
        case 'l':
            att_default_value_long = 0;
            show_usage();
            break;
        case 'L':
            att_default_value_long = 1;
            show_usage();
            break;
        case 'p':
            gap_privacy = 0;
            show_usage();
            break;
        case 'P':
            gap_privacy = 1;
            show_usage();
            break;
        case 'o':
            sm_have_oob_data = 0;
            show_usage();
            break;
        case 'O':
            sm_have_oob_data = 1;
            show_usage();
            break;
        case 'k':
            sm_min_key_size = 7;
            sm_set_encryption_key_size_range(7, 16);
            show_usage();
            break;
        case 'K':
            sm_min_key_size = 16;
            sm_set_encryption_key_size_range(16, 16);
            show_usage();
            break;
        case 'm':
            sm_mitm_protection = 0;
            update_auth_req();
            show_usage();
            break;
        case 'M':
            sm_mitm_protection = 1;
            update_auth_req();
            show_usage();
            break;
        case 'j':
            printf("Create L2CAP Connection to %s\n", bd_addr_to_str(tester_address));
            hci_send_cmd(&hci_le_create_connection, 
                1000,      // scan interval: 625 ms
                1000,      // scan interval: 625 ms
                0,         // don't use whitelist
                0,         // peer address type: public
                tester_address,      // remote bd addr
                tester_address_type, // random or public
                80,        // conn interval min
                80,        // conn interval max (3200 * 0.625)
                0,         // conn latency
                2000,      // supervision timeout
                0,         // min ce length
                1000       // max ce length
                );
            break;
        default:
            show_usage();
            break;

    }
    return 0;
}
예제 #2
0
static void handle_gatt_client_event(le_event_t * event) {

    uint8_t * packet = (uint8_t*) event;
    int connection_encrypted;

    // handle connect / disconncet events first
    switch (packet[0]) {
    case HCI_EVENT_LE_META:
        switch (packet[2]) {
        case HCI_SUBEVENT_LE_CONNECTION_COMPLETE:
            gc_handle = READ_BT_16(packet, 4);
            printf("Connection handle 0x%04x, request encryption\n", gc_handle);

            // we need to be paired to enable notifications
            tc_state = TC_W4_ENCRYPTED_CONNECTION;
            sm_send_security_request(gc_handle);
            break;
        default:
            break;
        }
        return;

    case HCI_EVENT_ENCRYPTION_CHANGE:
        if (gc_handle != READ_BT_16(packet, 3)) return;
        connection_encrypted = packet[5];
        log_info("Encryption state change: %u", connection_encrypted);
        if (!connection_encrypted) return;
        if (tc_state != TC_W4_ENCRYPTED_CONNECTION) return;

        // let's start
        printf("\nANCS Client - CONNECTED, discover ANCS service\n");
        tc_state = TC_W4_SERVICE_RESULT;
        gatt_client_discover_primary_services_by_uuid128(gc_id, gc_handle, ancs_service_uuid);
        return;

    case HCI_EVENT_DISCONNECTION_COMPLETE:
        notify_client(ANCS_CLIENT_DISCONNECTED);
        return;

    default:
        break;
    }

    le_characteristic_t characteristic;
    le_characteristic_value_event_t * value_event;
    switch(tc_state) {
    case TC_W4_SERVICE_RESULT:
        switch(event->type) {
        case GATT_SERVICE_QUERY_RESULT:
            ancs_service = ((le_service_event_t *) event)->service;
            ancs_service_found = 1;
            break;
        case GATT_QUERY_COMPLETE:
            if (!ancs_service_found) {
                printf("ANCS Service not found");
                tc_state = TC_IDLE;
                break;
            }
            tc_state = TC_W4_CHARACTERISTIC_RESULT;
            printf("ANCS Client - Discover characteristics for ANCS SERVICE \n");
            gatt_client_discover_characteristics_for_service(gc_id, gc_handle, &ancs_service);
            break;
        default:
            break;
        }
        break;

    case TC_W4_CHARACTERISTIC_RESULT:
        switch(event->type) {
        case GATT_CHARACTERISTIC_QUERY_RESULT:
            characteristic = ((le_characteristic_event_t *) event)->characteristic;
            if (memcmp(characteristic.uuid128, ancs_notification_source_uuid, 16) == 0) {
                printf("ANCS Notification Source Characterisic found\n");
                ancs_notification_source_characteristic = characteristic;
                ancs_characteristcs++;
                break;
            }
            if (memcmp(characteristic.uuid128, ancs_control_point_uuid, 16) == 0) {
                printf("ANCS Control Point found\n");
                ancs_control_point_characteristic = characteristic;
                ancs_characteristcs++;
                break;
            }
            if (memcmp(characteristic.uuid128, ancs_data_source_uuid, 16) == 0) {
                printf("ANCS Data Source Characterisic found\n");
                ancs_data_source_characteristic = characteristic;
                ancs_characteristcs++;
                break;
            }
            break;
        case GATT_QUERY_COMPLETE:
            printf("ANCS Characteristcs count %u\n", ancs_characteristcs);
            tc_state = TC_W4_NOTIFICATION_SOURCE_SUBSCRIBED;
            gatt_client_write_client_characteristic_configuration(gc_id, gc_handle, &ancs_notification_source_characteristic,
                    GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION);
            break;
        default:
            break;
        }
        break;
    case TC_W4_NOTIFICATION_SOURCE_SUBSCRIBED:
        switch(event->type) {
        case GATT_QUERY_COMPLETE:
            printf("ANCS Notification Source subscribed\n");
            tc_state = TC_W4_DATA_SOURCE_SUBSCRIBED;
            gatt_client_write_client_characteristic_configuration(gc_id, gc_handle, &ancs_data_source_characteristic,
                    GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION);
            break;
        default:
            break;
        }
        break;
    case TC_W4_DATA_SOURCE_SUBSCRIBED:
        switch(event->type) {
        case GATT_QUERY_COMPLETE:
            printf("ANCS Data Source subscribed\n");
            tc_state = TC_SUBSCRIBED;
            notify_client(ANCS_CLIENT_CONNECTED);
            break;
        default:
            break;
        }
        break;
    case TC_SUBSCRIBED:
        if ( event->type != GATT_NOTIFICATION && event->type != GATT_INDICATION ) break;
        value_event = (le_characteristic_value_event_t *) event;
        if (value_event->value_handle == ancs_data_source_characteristic.value_handle) {
            int i;
            for (i=0; i<value_event->blob_length; i++) {
                ancs_chunk_parser_handle_byte(value_event->blob[i]);
            }
        } else if (value_event->value_handle == ancs_notification_source_characteristic.value_handle) {
            ancs_notification_uid = READ_BT_32(value_event->blob, 4);
            printf("Notification received: EventID %02x, EventFlags %02x, CategoryID %02x, CategoryCount %u, UID %04x\n",
                   value_event->blob[0], value_event->blob[1], value_event->blob[2], value_event->blob[3], (int) ancs_notification_uid);
            static uint8_t get_notification_attributes[] = {0, 0,0,0,0,  0,  1,32,0,  2,32,0, 3,32,0, 4, 5};
            bt_store_32(get_notification_attributes, 1, ancs_notification_uid);
            ancs_notification_uid = 0;
            ancs_chunk_parser_init();
            gatt_client_write_value_of_characteristic(gc_id, gc_handle, ancs_control_point_characteristic.value_handle,
                    sizeof(get_notification_attributes), get_notification_attributes);
        } else {
            printf("Unknown Source: ");
            printf_hexdump(value_event->blob , value_event->blob_length);
        }
        break;
    default:
        break;
    }
    // app_run();
}
예제 #3
0
static void handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){

    UNUSED(packet_type);
    UNUSED(channel);
    UNUSED(size);

    int connection_encrypted;

    // handle connect / disconncet events first
    switch (hci_event_packet_get_type(packet)) {
        case HCI_EVENT_LE_META:
            switch (packet[2]) {
                case HCI_SUBEVENT_LE_CONNECTION_COMPLETE:
                    gc_handle = little_endian_read_16(packet, 4);
                    log_info("Connection handle 0x%04x, request encryption", gc_handle);

                    // we need to be paired to enable notifications
                    tc_state = TC_W4_ENCRYPTED_CONNECTION;
                    sm_send_security_request(gc_handle);
                    break;
                default:
                    break;
            }
            return;

        case HCI_EVENT_ENCRYPTION_CHANGE: 
            if (gc_handle != little_endian_read_16(packet, 3)) return;
            connection_encrypted = packet[5];
            log_info("Encryption state change: %u", connection_encrypted);
            if (!connection_encrypted) return;
            if (tc_state != TC_W4_ENCRYPTED_CONNECTION) return;

            // let's start
            log_info("\nANCS Client - CONNECTED, discover ANCS service");
            tc_state = TC_W4_SERVICE_RESULT;
            gatt_client_discover_primary_services_by_uuid128(handle_hci_event, gc_handle, ancs_service_uuid);
            return;
            
        case HCI_EVENT_DISCONNECTION_COMPLETE:
            if (hci_event_disconnection_complete_get_connection_handle(packet) != gc_handle) break;
            if (tc_state == TC_SUBSCRIBED){
                notify_client_simple(ANCS_SUBEVENT_CLIENT_DISCONNECTED);
            }
            tc_state = TC_IDLE;
            gc_handle = 0;
            return;

        default:
            break;
    }

    gatt_client_characteristic_t characteristic;
    uint8_t *           value;
    uint16_t            value_handle;
    uint16_t            value_length;

    switch(tc_state){
        case TC_W4_SERVICE_RESULT:
            switch(hci_event_packet_get_type(packet)){
                case GATT_EVENT_SERVICE_QUERY_RESULT:
                    gatt_event_service_query_result_get_service(packet, &ancs_service);
                    ancs_service_found = 1;
                    break;
                case GATT_EVENT_QUERY_COMPLETE:
                    if (!ancs_service_found){
                        log_info("ANCS Service not found");
                        tc_state = TC_IDLE;
                        break;
                    }
                    tc_state = TC_W4_CHARACTERISTIC_RESULT;
                    log_info("ANCS Client - Discover characteristics for ANCS SERVICE ");
                    gatt_client_discover_characteristics_for_service(handle_hci_event, gc_handle, &ancs_service);
                    break;
                default:
                    break;
            }
            break;
            
        case TC_W4_CHARACTERISTIC_RESULT:
            switch(hci_event_packet_get_type(packet)){
                case GATT_EVENT_CHARACTERISTIC_QUERY_RESULT:
                    gatt_event_characteristic_query_result_get_characteristic(packet, &characteristic);
                    if (memcmp(characteristic.uuid128, ancs_notification_source_uuid, 16) == 0){
                        log_info("ANCS Notification Source found, attribute handle %u", characteristic.value_handle);
                        ancs_notification_source_characteristic = characteristic;
                        ancs_characteristcs++;
                        break;                        
                    }
                    if (memcmp(characteristic.uuid128, ancs_control_point_uuid, 16) == 0){
                        log_info("ANCS Control Point found, attribute handle %u", characteristic.value_handle);
                        ancs_control_point_characteristic = characteristic;
                        ancs_characteristcs++;
                        break;                        
                    }
                    if (memcmp(characteristic.uuid128, ancs_data_source_uuid, 16) == 0){
                        log_info("ANCS Data Source found, attribute handle %u", characteristic.value_handle);
                        ancs_data_source_characteristic = characteristic;
                        ancs_characteristcs++;
                        break;                        
                    }
                    break;
                case GATT_EVENT_QUERY_COMPLETE:
                    log_info("ANCS Characteristcs count %u", ancs_characteristcs);
                    tc_state = TC_W4_NOTIFICATION_SOURCE_SUBSCRIBED;
                    gatt_client_listen_for_characteristic_value_updates(&ancs_notification_source_notification, &handle_hci_event, gc_handle, &ancs_notification_source_characteristic);
                    gatt_client_write_client_characteristic_configuration(handle_hci_event, gc_handle, &ancs_notification_source_characteristic,
                        GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION);
                    break;
                default:
                    break;
            }
            break;
        case TC_W4_NOTIFICATION_SOURCE_SUBSCRIBED:
            switch(hci_event_packet_get_type(packet)){
                case GATT_EVENT_QUERY_COMPLETE:
                    log_info("ANCS Notification Source subscribed");
                    tc_state = TC_W4_DATA_SOURCE_SUBSCRIBED;
                    gatt_client_listen_for_characteristic_value_updates(&ancs_data_source_notification, &handle_hci_event, gc_handle, &ancs_data_source_characteristic);
                    gatt_client_write_client_characteristic_configuration(handle_hci_event, gc_handle, &ancs_data_source_characteristic,
                        GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION);
                    break;
                default:
                    break;
            }
            break;
        case TC_W4_DATA_SOURCE_SUBSCRIBED:
            switch(hci_event_packet_get_type(packet)){
                case GATT_EVENT_QUERY_COMPLETE:
                    log_info("ANCS Data Source subscribed");
                    tc_state = TC_SUBSCRIBED;
                    notify_client_simple(ANCS_SUBEVENT_CLIENT_CONNECTED);
                    break;
                default:
                    break;
            }
            break;
        case TC_SUBSCRIBED:
            if (hci_event_packet_get_type(packet) != GATT_EVENT_NOTIFICATION && hci_event_packet_get_type(packet) != GATT_EVENT_INDICATION ) break;

            value_handle = little_endian_read_16(packet, 4);
            value_length = little_endian_read_16(packet, 6);
            value = &packet[8];

            log_info("ANCS Notification, value handle %u", value_handle);

            if (value_handle == ancs_data_source_characteristic.value_handle){
                int i;
                for (i=0;i<value_length;i++) {
                    ancs_chunk_parser_handle_byte(value[i]);
                }
            } else if (value_handle == ancs_notification_source_characteristic.value_handle){
                ancs_notification_uid = little_endian_read_32(value, 4);
                log_info("Notification received: EventID %02x, EventFlags %02x, CategoryID %02x, CategoryCount %u, UID %04x",
                    value[0], value[1], value[2], value[3], (int) ancs_notification_uid);
                static uint8_t get_notification_attributes[] = {0, 0,0,0,0,  0,  1,32,0,  2,32,0, 3,32,0, 4, 5};
                little_endian_store_32(get_notification_attributes, 1, ancs_notification_uid);
                ancs_notification_uid = 0;
                ancs_chunk_parser_init();
                gatt_client_write_value_of_characteristic(handle_hci_event, gc_handle, ancs_control_point_characteristic.value_handle, 
                    sizeof(get_notification_attributes), get_notification_attributes);
            } else {
                log_info("Unknown Source: ");
                log_info_hexdump(value , value_length);
            }
            break;
        default:
            break;
    }    
    // app_run();
}