static void test_attribute_value_event(const uint8_t * event){
    static int recordId = 0;
    static int attributeId = 0;
    static int attributeOffset = 0;
    static int attributeLength = 0;

    CHECK_EQUAL(event[0], SDP_EVENT_QUERY_ATTRIBUTE_VALUE);

    // record ids are sequential
   // printf("sdp_event_query_attribute_byte_get_record_id(event) %d",sdp_event_query_attribute_byte_get_record_id(event));

    if (sdp_event_query_attribute_byte_get_record_id(event) != recordId){
        recordId++;
    }
    CHECK_EQUAL(sdp_event_query_attribute_byte_get_record_id(event), recordId);
    
    // is attribute value complete
    if (sdp_event_query_attribute_byte_get_attribute_id(event) != attributeId ){
        if (attributeLength > 0){
            CHECK_EQUAL(attributeLength, attributeOffset+1);
        }
        attributeId = sdp_event_query_attribute_byte_get_attribute_id(event);
        attributeOffset = 0;
    }

    // count attribute value bytes
    if (sdp_event_query_attribute_byte_get_data_offset(event) != attributeOffset){
        attributeOffset++;
    }
    attributeLength = sdp_event_query_attribute_byte_get_attribute_length(event);

    CHECK_EQUAL(sdp_event_query_attribute_byte_get_data_offset(event), attributeOffset);
}
Exemplo n.º 2
0
static void handle_sdp_client_query_result(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {

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

    des_iterator_t attribute_list_it;
    des_iterator_t additional_des_it;
    des_iterator_t prot_it;
    uint8_t       *des_element;
    uint8_t       *element;
    uint32_t       uuid;
    uint8_t        status;

    switch (hci_event_packet_get_type(packet)){
        case SDP_EVENT_QUERY_ATTRIBUTE_VALUE:
            if (sdp_event_query_attribute_byte_get_attribute_length(packet) <= attribute_value_buffer_size) {
                attribute_value[sdp_event_query_attribute_byte_get_data_offset(packet)] = sdp_event_query_attribute_byte_get_data(packet);
                if ((uint16_t)(sdp_event_query_attribute_byte_get_data_offset(packet)+1) == sdp_event_query_attribute_byte_get_attribute_length(packet)) {
                    switch(sdp_event_query_attribute_byte_get_attribute_id(packet)) {
                        case BLUETOOTH_ATTRIBUTE_PROTOCOL_DESCRIPTOR_LIST:
                            for (des_iterator_init(&attribute_list_it, attribute_value); des_iterator_has_more(&attribute_list_it); des_iterator_next(&attribute_list_it)) {                                    
                                if (des_iterator_get_type(&attribute_list_it) != DE_DES) continue;
                                des_element = des_iterator_get_element(&attribute_list_it);
                                des_iterator_init(&prot_it, des_element);
                                element = des_iterator_get_element(&prot_it);
                                if (de_get_element_type(element) != DE_UUID) continue;
                                uuid = de_get_uuid32(element);
                                switch (uuid){
                                    case BLUETOOTH_PROTOCOL_L2CAP:
                                        if (!des_iterator_has_more(&prot_it)) continue;
                                        des_iterator_next(&prot_it);
                                        de_element_get_uint16(des_iterator_get_element(&prot_it), &hid_control_psm);
                                        printf("HID Control PSM: 0x%04x\n", (int) hid_control_psm);
                                        break;
                                    default:
                                        break;
                                }
                            }
                            break;
                        case BLUETOOTH_ATTRIBUTE_ADDITIONAL_PROTOCOL_DESCRIPTOR_LISTS:
                            for (des_iterator_init(&attribute_list_it, attribute_value); des_iterator_has_more(&attribute_list_it); des_iterator_next(&attribute_list_it)) {                                    
                                if (des_iterator_get_type(&attribute_list_it) != DE_DES) continue;
                                des_element = des_iterator_get_element(&attribute_list_it);
                                for (des_iterator_init(&additional_des_it, des_element); des_iterator_has_more(&additional_des_it); des_iterator_next(&additional_des_it)) {                                    
                                    if (des_iterator_get_type(&additional_des_it) != DE_DES) continue;
                                    des_element = des_iterator_get_element(&additional_des_it);
                                    des_iterator_init(&prot_it, des_element);
                                    element = des_iterator_get_element(&prot_it);
                                    if (de_get_element_type(element) != DE_UUID) continue;
                                    uuid = de_get_uuid32(element);
                                    switch (uuid){
                                        case BLUETOOTH_PROTOCOL_L2CAP:
                                            if (!des_iterator_has_more(&prot_it)) continue;
                                            des_iterator_next(&prot_it);
                                            de_element_get_uint16(des_iterator_get_element(&prot_it), &hid_interrupt_psm);
                                            printf("HID Interrupt PSM: 0x%04x\n", (int) hid_interrupt_psm);
                                            break;
                                        default:
                                            break;
                                    }
                                }
                            }
                            break;
                        case BLUETOOTH_ATTRIBUTE_HID_DESCRIPTOR_LIST:
                            for (des_iterator_init(&attribute_list_it, attribute_value); des_iterator_has_more(&attribute_list_it); des_iterator_next(&attribute_list_it)) {
                                if (des_iterator_get_type(&attribute_list_it) != DE_DES) continue;
                                des_element = des_iterator_get_element(&attribute_list_it);
                                for (des_iterator_init(&additional_des_it, des_element); des_iterator_has_more(&additional_des_it); des_iterator_next(&additional_des_it)) {                                    
                                    if (des_iterator_get_type(&additional_des_it) != DE_STRING) continue;
                                    element = des_iterator_get_element(&additional_des_it);
                                    const uint8_t * descriptor = de_get_string(element);
                                    hid_descriptor_len = de_get_data_size(element);
                                    memcpy(hid_descriptor, descriptor, hid_descriptor_len);
                                    printf("HID Descriptor:\n");
                                    printf_hexdump(hid_descriptor, hid_descriptor_len);
                                }
                            }                        
                            break;
                        default:
                            break;
                    }
                }
            } else {
                fprintf(stderr, "SDP attribute value buffer size exceeded: available %d, required %d\n", attribute_value_buffer_size, sdp_event_query_attribute_byte_get_attribute_length(packet));
            }
            break;
            
        case SDP_EVENT_QUERY_COMPLETE:
            if (!hid_control_psm) {
                printf("HID Control PSM missing\n");
                break;
            }
            if (!hid_interrupt_psm) {
                printf("HID Interrupt PSM missing\n");
                break;
            }
            printf("Setup HID\n");
            status = l2cap_create_channel(packet_handler, remote_addr, hid_control_psm, 48, &l2cap_hid_control_cid);
            if (status){
                printf("Connecting to HID Control failed: 0x%02x\n", status);
            }
            break;
    }
}
Exemplo n.º 3
0
/* LISTING_START(HandleSDPQUeryResult): Extracting BNEP Protcol UUID and L2CAP PSM */
static void handle_sdp_client_query_result(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
    /* LISTING_PAUSE */
    des_iterator_t des_list_it;
    des_iterator_t prot_it;
    char *str;

    switch (hci_event_packet_get_type(packet)){
        case SDP_EVENT_QUERY_ATTRIBUTE_VALUE:
            // handle new record
            if (sdp_event_query_attribute_byte_get_record_id(packet) != record_id){
                record_id = sdp_event_query_attribute_byte_get_record_id(packet);
                printf("\n---\nRecord nr. %u\n", record_id);
            }

            assertBuffer(sdp_event_query_attribute_byte_get_attribute_length(packet));

            attribute_value[sdp_event_query_attribute_byte_get_data_offset(packet)] = sdp_event_query_attribute_byte_get_data(packet);
            if ((uint16_t)(sdp_event_query_attribute_byte_get_data_offset(packet)+1) == sdp_event_query_attribute_byte_get_attribute_length(packet)){

                /* LISTING_RESUME */
                /* @text The Service Class ID List is a Data Element Sequence (DES) of UUIDs. 
                 * The BNEP PAN protocol UUID is within this list.
                 */

                switch(sdp_event_query_attribute_byte_get_attribute_id(packet)){
                    // 0x0001 "Service Class ID List"
                    case SDP_ServiceClassIDList:
                        if (de_get_element_type(attribute_value) != DE_DES) break;
                        for (des_iterator_init(&des_list_it, attribute_value); des_iterator_has_more(&des_list_it); des_iterator_next(&des_list_it)){
                            uint8_t * element = des_iterator_get_element(&des_list_it);
                            if (de_get_element_type(element) != DE_UUID) continue;
                            uint32_t uuid = de_get_uuid32(element);
                            switch (uuid){
                                case PANU_UUID:
                                case NAP_UUID:
                                case GN_UUID:
                                    printf(" ** Attribute 0x%04x: BNEP PAN protocol UUID: %04x\n", sdp_event_query_attribute_byte_get_attribute_id(packet), uuid);
                                    break;
                                default:
                                    break;
                            }
                        }
                        break;
                    /* LISTING_PAUSE */
                    // 0x0100 "Service Name"
                    case 0x0100:
                    // 0x0101 "Service Description"
                    case 0x0101:
                        str = get_string_from_data_element(attribute_value);
                        printf(" ** Attribute 0x%04x: %s\n", sdp_event_query_attribute_byte_get_attribute_id(packet), str);
                        free(str);
                        break;
                    
                    /* LISTING_RESUME */
                    /* @text The Protocol Descriptor List is DES 
                     * which contains one DES for each protocol. For PAN serivces, it contains
                     * a DES with the L2CAP Protocol UUID and a PSM,
                     * and another DES with the BNEP UUID and the the BNEP version.
                     */
                    case SDP_ProtocolDescriptorList:{
                            printf(" ** Attribute 0x%04x: ", sdp_event_query_attribute_byte_get_attribute_id(packet));
                            
                            uint16_t l2cap_psm = 0;
                            uint16_t bnep_version = 0;
                            for (des_iterator_init(&des_list_it, attribute_value); des_iterator_has_more(&des_list_it); des_iterator_next(&des_list_it)){
                                if (des_iterator_get_type(&des_list_it) != DE_DES) continue;
                                uint8_t * des_element = des_iterator_get_element(&des_list_it);
                                des_iterator_init(&prot_it, des_element);
                                uint8_t * element = des_iterator_get_element(&prot_it);
                                
                                if (de_get_element_type(element) != DE_UUID) continue;
                                uint32_t uuid = de_get_uuid32(element);
                                switch (uuid){
                                    case SDP_L2CAPProtocol:
                                        if (!des_iterator_has_more(&prot_it)) continue;
                                        des_iterator_next(&prot_it);
                                        de_element_get_uint16(des_iterator_get_element(&prot_it), &l2cap_psm);
                                        break;
                                    case SDP_BNEPProtocol:
                                        if (!des_iterator_has_more(&prot_it)) continue;
                                        des_iterator_next(&prot_it);
                                        de_element_get_uint16(des_iterator_get_element(&prot_it), &bnep_version);
                                        break;
                                    default:
                                        break;
                                }
                            }
                            printf("l2cap_psm 0x%04x, bnep_version 0x%04x\n", l2cap_psm, bnep_version);
                        }
                        break;
                    /* LISTING_PAUSE */
                    default:
                        break;
                }
            }
            break;
        case SDP_EVENT_QUERY_COMPLETE:
            printf("General query done with status %d.\n\n", sdp_event_query_complete_get_status(packet));
            break;
    }
    /* LISTING_RESUME */
}