Example #1
0
static void parse_service_attribute_response(uint8_t* packet){
    uint16_t offset = 3;
    uint16_t parameterLength = READ_NET_16(packet,offset);
    offset+=2;

    // AttributeListByteCount <= mtu
    uint16_t attributeListByteCount = READ_NET_16(packet,offset);
    offset+=2;

    if (attributeListByteCount > mtu){
        log_error("Error parsing ServiceSearchAttributeResponse: Number of bytes in found attribute list is larger then the MaximumAttributeByteCount.");
        return;
    }

    // AttributeLists
    parse_attribute_lists(packet+offset, attributeListByteCount);
    offset+=attributeListByteCount;

    continuationStateLen = packet[offset];
    offset++;

    if (continuationStateLen > 16){
        log_error("Error parsing ServiceAttributeResponse: Number of bytes in continuation state exceedes 16.");
        return;
    }
    memcpy(continuationState, packet+offset, continuationStateLen);
    offset+=continuationStateLen;

    if (parameterLength != offset - 5){
        log_error("Error parsing ServiceAttributeResponse: wrong size of parameters, number of expected bytes%u, actual number %u.", parameterLength, offset);
    }
}
Example #2
0
static void parse_service_search_response(uint8_t* packet){
    uint16_t offset = 3;
    uint16_t parameterLength = READ_NET_16(packet,offset);
    offset+=2;

    uint16_t totalServiceRecordCount = READ_NET_16(packet,offset);
    offset+=2;

    uint16_t currentServiceRecordCount = READ_NET_16(packet,offset);
    offset+=2;
    if (currentServiceRecordCount > totalServiceRecordCount){
        log_error("CurrentServiceRecordCount is larger then TotalServiceRecordCount.");
        return;
    }
    
    parse_service_record_handle_list(packet+offset, totalServiceRecordCount, currentServiceRecordCount);
    offset+=(currentServiceRecordCount * 4);

    continuationStateLen = packet[offset];
    offset++;
    if (continuationStateLen > 16){
        log_error("Error parsing ServiceSearchResponse: Number of bytes in continuation state exceedes 16.");
        return;
    }
    memcpy(continuationState, packet+offset, continuationStateLen);
    offset+=continuationStateLen;

    if (parameterLength != offset - 5){
        log_error("Error parsing ServiceSearchResponse: wrong size of parameters, number of expected bytes%u, actual number %u.", parameterLength, offset);
    }
}
Example #3
0
File: sdp.c Project: ajsb85/ioio
static void dump_service_search_response(void){
    uint16_t nr_services = READ_NET_16(sdp_response_buffer, 7);
    int i;
    printf("Nr service handles: %u\n", nr_services);
    for (i=0; i<nr_services;i++){
        printf("  ServiceHandle %x\n", READ_NET_32(sdp_response_buffer, 9+i*4));
    }
    if (sdp_response_buffer[9 + nr_services * 4]){
        printf("  Continuation index %u\n", READ_NET_16(sdp_response_buffer, 9+nr_services*4+1));
    } else {
        printf("  Continuation: NO\n");
    }
}
Example #4
0
static void handle_gps_data(stlv_packet pack, element_handle handle)
{
    char type_buf[MAX_ELEMENT_TYPE_BUFSIZE];

    uint16_t gps_spd = 0xffff;
    uint16_t gps_alt = 0xffff;
    uint32_t gps_dis = 0;

    element_handle element = get_first_sub_element(pack, handle);
    while (IS_VALID_STLV_HANDLE(element))
    {
        int type_len = get_element_type(pack, element, type_buf, sizeof(type_buf));
        switch (type_buf[0])
        {
            case SUB_TYPE_ACTIVITY_ALT:
                {
                    uint8_t* data = get_element_data_buffer(pack, element, type_buf, type_len);
                    uint8_t  data_size = get_element_data_size(pack, element, type_buf, type_len);
                    log_info("gps.alt=%d:%02x %02x\n", data_size, data[0], data[1]);
                    //gps_alt = *((uint16_t*)data);
                    //gps_alt = htons(gps_alt);
                    gps_alt = READ_NET_16(data, 0);
                }
                break;

            case SUB_TYPE_ACTIVITY_SPD:
                {
                    uint8_t* data = get_element_data_buffer(pack, element, type_buf, type_len);
                    uint8_t  data_size = get_element_data_size(pack, element, type_buf, type_len);
                    log_info("gps.spd=%d:%02x %02x\n", data_size, data[0], data[1]);
                    //gps_spd = *((uint16_t*)data);
                    //gps_spd = htons(gps_spd);
                    gps_spd = READ_NET_16(data, 0);
                }
                break;

            case SUB_TYPE_ACTIVITY_DIS:
                {
                    uint8_t* data = get_element_data_buffer(pack, element, type_buf, type_len);
                    uint8_t  data_size = get_element_data_size(pack, element, type_buf, type_len);
                    log_info("gps.dis=%d:%02x %02x %02x %02x\n", data_size, data[0], data[1], data[2], data[3]);
                    gps_dis = READ_NET_32(data, 0);
                }
               break;
        }
        element = get_next_sub_element(pack, handle, element);
    }

    handle_gps_info(gps_spd, gps_alt, gps_dis);

}
Example #5
0
void handle_set_watch_config(ui_config* new_config)
{
    //TODO: help check this




    ui_config* config = window_readconfig();
    if (config != NULL)
    {
        memcpy(config, new_config, sizeof(ui_config));

        //adjust values: big endian to little endian
        uint8_t* p = (uint8_t*)new_config;
        config->signature     = READ_NET_32(p, 0);
        config->goal_steps    = READ_NET_16(p, 4);
        config->goal_distance = READ_NET_16(p, 6);
        config->goal_calories = READ_NET_16(p, 8);
        config->lap_length    = READ_NET_16(p, 10);

        if (config->weight < 20) config->weight = 20;
        if (config->height < 60) config->height = 60;

        log_info("set_watch_config:\n");
        log_info("  signature     = %x\n", config->signature);
        log_info("  default_clock = %d\n", config->default_clock); // 0 - analog, 1 - digit
        log_info("  analog_clock  = %d\n", config->analog_clock);  // num : which lock face
        log_info("  digit_clock   = %d\n", config->digit_clock);   // num : which clock face
        log_info("  sports_grid   = %d\n", config->sports_grid);   // 0 - 3 grid, 1 - 4 grid, 2 - 5 grid
        log_info("  sports_grids  = %d, %d, %d, %d, %d\n",
                config->sports_grid_data[0],
                config->sports_grid_data[1],
                config->sports_grid_data[2],
                config->sports_grid_data[3],
                config->sports_grid_data[4]);
        log_info("  is_ukuint     = %02x\n", config->is_ukuint);
        log_info("  goal_steps    = %d\n", config->goal_steps);
        log_info("  goal_distance = %d\n", config->goal_distance);
        log_info("  goal_calories = %d\n", config->goal_calories);
        log_info("  weight        = %d\n", config->weight); // in kg
        log_info("  height        = %d\n", config->height); // in cm
        log_info("  circumference = %d\n", config->circumference);
        log_info("  lap_len       = %d\n", config->lap_length);


        window_writeconfig();
        window_loadconfig();
    }
}
Example #6
0
/*************** PANU client routines *********************/
static void packet_handler (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size)
{
    uint8_t   event;
    bd_addr_t event_addr;
    bd_addr_t src_addr;
    bd_addr_t dst_addr;
    uint16_t  uuid_source;
    uint16_t  uuid_dest;
    uint16_t  mtu;    
    uint16_t  network_type;
    uint8_t   protocol_type;
    uint8_t   icmp_type;
    int       ihl;
    int       payload_offset;

    switch (packet_type) {
		case HCI_EVENT_PACKET:
            event = packet[0];
            switch (event) {            
                case BTSTACK_EVENT_STATE:
                    /* BT Stack activated, get started */ 
                    if (packet[2] == HCI_STATE_WORKING) {
                        printf("BNEP Test ready\n");
                        show_usage();
                    }
                    break;

                case HCI_EVENT_COMMAND_COMPLETE:
					if (COMMAND_COMPLETE_EVENT(packet, hci_read_bd_addr)){
                        bt_flip_addr(local_addr, &packet[6]);
                        printf("BD-ADDR: %s\n", bd_addr_to_str(local_addr));
                        break;
                    }
                    break;

                case HCI_EVENT_USER_CONFIRMATION_REQUEST:
                    // inform about user confirmation request
                    printf("SSP User Confirmation Request with numeric value '%06u'\n", READ_BT_32(packet, 8));
                    printf("SSP User Confirmation Auto accept\n");
                    break;
					
				case BNEP_EVENT_OPEN_CHANNEL_COMPLETE:
                    if (packet[2]) {
                        printf("BNEP channel open failed, status %02x\n", packet[2]);
                    } else {
                        // data: event(8), len(8), status (8), bnep source uuid (16), bnep destination uuid (16), remote_address (48)
                        uuid_source = READ_BT_16(packet, 3);
                        uuid_dest   = READ_BT_16(packet, 5);
                        mtu         = READ_BT_16(packet, 7);
                        bnep_cid    = channel;
                        //bt_flip_addr(event_addr, &packet[9]); 
                        memcpy(&event_addr, &packet[9], sizeof(bd_addr_t));
                        printf("BNEP connection open succeeded to %s source UUID 0x%04x dest UUID: 0x%04x, max frame size %u\n", bd_addr_to_str(event_addr), uuid_source, uuid_dest, mtu);
                    }
					break;
                    
                case BNEP_EVENT_CHANNEL_TIMEOUT:
                    printf("BNEP channel timeout! Channel will be closed\n");
                    break;
                    
                case BNEP_EVENT_CHANNEL_CLOSED:
                    printf("BNEP channel closed\n");
                    break;

                case BNEP_EVENT_READY_TO_SEND:
                    /* Check for parked network packets and send it out now */
                    if (network_buffer_len > 0) {
                        bnep_send(bnep_cid, network_buffer, network_buffer_len);
                        network_buffer_len = 0;
                    }
                    break;
                    
                default:
                    break;
            }
            break;
        case BNEP_DATA_PACKET:
            // show received packet on console

            // TODO: fix BNEP to return BD ADDR in little endian, to use these lines
            // bt_flip_addr(dst_addr, &packet[0]);
            // bt_flip_addr(src_addr, &packet[6]);
            // instead of these
            memcpy(dst_addr, &packet[0], 6);
            memcpy(src_addr, &packet[6], 6);
            // END TOOD

            network_type = READ_NET_16(packet, 12);
            printf("BNEP packet received\n");
            printf("Dst Addr: %s\n", bd_addr_to_str(dst_addr));
            printf("Src Addr: %s\n", bd_addr_to_str(src_addr));
            printf("Net Type: %04x\n", network_type);
            // ignore the next 60 bytes
            // hexdumpf(&packet[74], size - 74);
            switch (network_type){
                case NETWORK_TYPE_IPv4:
                    ihl = packet[14] & 0x0f;
                    payload_offset = 14 + (ihl << 2);
                    // protocol
                    protocol_type = packet[14 + 9]; // offset 9 into IPv4
                    switch (protocol_type){
                        case 0x01:  // ICMP
                            icmp_type = packet[payload_offset];
                            hexdumpf(&packet[payload_offset], size - payload_offset);
                            printf("ICMP packet of type %x\n", icmp_type);
                            switch (icmp_type){
                                case ICMP_V4_TYPE_PING_REQUEST:
                                    printf("IPv4 Ping Request received, sending pong\n");
                                    send_ping_response_ipv4();
                                    break;
                                break;
                            }
                        case 0x11:  // UDP
                            printf("UDP IPv4 packet\n");                        
                            hexdumpf(&packet[payload_offset], size - payload_offset);
                            break;
                        default:
                            printf("Unknown IPv4 protocol type %x", protocol_type);
                            break;
                    }
                    break;
                case NETWORK_TYPE_IPv6:
                    protocol_type = packet[6];
                    switch(protocol_type){
                        case 0x11: // UDP
                            printf("UDP IPv6 packet\n");
                            payload_offset = 40;    // fixed
                            hexdumpf(&packet[payload_offset], size - payload_offset);

                            // send response

                            break;
                        default:
                            printf("IPv6 packet of protocol 0x%02x\n", protocol_type);
                            hexdumpf(&packet[14], size - 14);
                            break;
                    }
                    break;
                default:
                    printf("Unknown network type %x", network_type);
                    break;
            }

            break;            
            
        default:
            break;
    }
}
Example #7
0
// we assume that we don't get two requests in a row
static void sdp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
    uint16_t transaction_id;
    SDP_PDU_ID_t pdu_id;
    uint16_t remote_mtu;
    // uint16_t param_len;

    switch (packet_type) {

    case L2CAP_DATA_PACKET:
        pdu_id = (SDP_PDU_ID_t) packet[0];
        transaction_id = READ_NET_16(packet, 1);
        // param_len = READ_NET_16(packet, 3);
        remote_mtu = l2cap_get_remote_mtu_for_local_cid(channel);
        // account for our buffer
        if (remote_mtu > SDP_RESPONSE_BUFFER_SIZE) {
            remote_mtu = SDP_RESPONSE_BUFFER_SIZE;
        }

        // log_info("SDP Request: type %u, transaction id %u, len %u, mtu %u", pdu_id, transaction_id, param_len, remote_mtu);
        switch (pdu_id) {

        case SDP_ServiceSearchRequest:
            sdp_response_size = sdp_handle_service_search_request(packet, remote_mtu);
            break;

        case SDP_ServiceAttributeRequest:
            sdp_response_size = sdp_handle_service_attribute_request(packet, remote_mtu);
            break;

        case SDP_ServiceSearchAttributeRequest:
            sdp_response_size = sdp_handle_service_search_attribute_request(packet, remote_mtu);
            break;

        default:
            sdp_response_size = sdp_create_error_response(transaction_id, 0x0003); // invalid syntax
            break;
        }

        sdp_try_respond();

        break;

    case HCI_EVENT_PACKET:

        switch (packet[0]) {

        case L2CAP_EVENT_INCOMING_CONNECTION:
            if (l2cap_cid) {
                // CONNECTION REJECTED DUE TO LIMITED RESOURCES
                l2cap_decline_connection_internal(channel, 0x04);
                break;
            }
            // accept
            l2cap_cid = channel;
            sdp_response_size = 0;
            l2cap_accept_connection_internal(channel);
            break;

        case L2CAP_EVENT_CHANNEL_OPENED:
            if (packet[2]) {
                // open failed -> reset
                l2cap_cid = 0;
            }
            break;

        case L2CAP_EVENT_CREDITS:
        case DAEMON_EVENT_HCI_PACKET_SENT:
            sdp_try_respond();
            break;

        case L2CAP_EVENT_CHANNEL_CLOSED:
            if (channel == l2cap_cid) {
                // reset
                l2cap_cid = 0;
            }
            break;

        default:
            // other event
            break;
        }
        break;

    default:
        // other packet type
        break;
    }
}
Example #8
0
int sdp_handle_service_search_attribute_request(uint8_t * packet, uint16_t remote_mtu) {

    // SDP header before attribute sevice list: 7
    // Continuation, worst case: 5

    // get request details
    uint16_t  transaction_id = READ_NET_16(packet, 1);
    // not used yet - uint16_t  param_len = READ_NET_16(packet, 3);
    uint8_t * serviceSearchPattern = &packet[5];
    uint16_t  serviceSearchPatternLen = de_get_len(serviceSearchPattern);
    uint16_t  maximumAttributeByteCount = READ_NET_16(packet, 5 + serviceSearchPatternLen);
    uint8_t * attributeIDList = &packet[5+serviceSearchPatternLen+2];
    uint16_t  attributeIDListLen = de_get_len(attributeIDList);
    uint8_t * continuationState = &packet[5+serviceSearchPatternLen+2+attributeIDListLen];

    // calc maximumAttributeByteCount based on remote MTU, SDP header and reserved Continuation block
    uint16_t maximumAttributeByteCount2 = remote_mtu - 12;
    if (maximumAttributeByteCount2 < maximumAttributeByteCount) {
        maximumAttributeByteCount = maximumAttributeByteCount2;
    }

    // continuation state contains: index of next service record to examine
    // continuation state contains: byte offset into this service record
    uint16_t continuation_service_index = 0;
    uint16_t continuation_offset = 0;
    if (continuationState[0] == 4) {
        continuation_service_index = READ_NET_16(continuationState, 1);
        continuation_offset = READ_NET_16(continuationState, 3);
    }

    // log_info("--> sdp_handle_service_search_attribute_request, cont %u/%u, max %u", continuation_service_index, continuation_offset, maximumAttributeByteCount);

    // AttributeLists - starts at offset 7
    uint16_t pos = 7;

    // add DES with total size for first request
    if (continuation_service_index == 0 && continuation_offset == 0) {
        uint16_t total_response_size = sdp_get_size_for_service_search_attribute_response(serviceSearchPattern, attributeIDList);
        de_store_descriptor_with_len(&sdp_response_buffer[pos], DE_DES, DE_SIZE_VAR_16, total_response_size);
        // log_info("total response size %u", total_response_size);
        pos += 3;
        maximumAttributeByteCount -= 3;
    }

    // create attribute list
    int      first_answer = 1;
    int      continuation = 0;
    uint16_t current_service_index = 0;
    linked_item_t *it = (linked_item_t *) sdp_service_records;
    for ( ; it ; it = it->next, ++current_service_index) {
        service_record_item_t * item = (service_record_item_t *) it;

        if (current_service_index < continuation_service_index ) continue;
        if (!sdp_record_matches_service_search_pattern(item->service_record, serviceSearchPattern)) continue;

        if (continuation_offset == 0) {

            // get size of this record
            uint16_t filtered_attributes_size = spd_get_filtered_size(item->service_record, attributeIDList);

            // stop if complete record doesn't fits into response but we already have a partial response
            if ((filtered_attributes_size + 3 > maximumAttributeByteCount) && !first_answer) {
                continuation = 1;
                break;
            }

            // store DES
            de_store_descriptor_with_len(&sdp_response_buffer[pos], DE_DES, DE_SIZE_VAR_16, filtered_attributes_size);
            pos += 3;
            maximumAttributeByteCount -= 3;
        }

        first_answer = 0;

        // copy maximumAttributeByteCount from record
        uint16_t bytes_used;
        int complete = sdp_filter_attributes_in_attributeIDList(item->service_record, attributeIDList, continuation_offset, maximumAttributeByteCount, &bytes_used, &sdp_response_buffer[pos]);
        pos += bytes_used;
        maximumAttributeByteCount -= bytes_used;

        if (complete) {
            continuation_offset = 0;
            continue;
        }

        continuation = 1;
        continuation_offset += bytes_used;
        break;
    }

    uint16_t attributeListsByteCount = pos - 7;

    // Continuation State
    if (continuation) {
        sdp_response_buffer[pos++] = 4;
        net_store_16(sdp_response_buffer, pos, (uint16_t) current_service_index);
        pos += 2;
        net_store_16(sdp_response_buffer, pos, continuation_offset);
        pos += 2;
    } else {
        // complete
        sdp_response_buffer[pos++] = 0;
    }

    // create SDP header
    sdp_response_buffer[0] = SDP_ServiceSearchAttributeResponse;
    net_store_16(sdp_response_buffer, 1, transaction_id);
    net_store_16(sdp_response_buffer, 3, pos - 5);  // size of variable payload
    net_store_16(sdp_response_buffer, 5, attributeListsByteCount);

    return pos;
}
Example #9
0
int sdp_handle_service_attribute_request(uint8_t * packet, uint16_t remote_mtu) {

    // get request details
    uint16_t  transaction_id = READ_NET_16(packet, 1);
    // not used yet - uint16_t  param_len = READ_NET_16(packet, 3);
    uint32_t  serviceRecordHandle = READ_NET_32(packet, 5);
    uint16_t  maximumAttributeByteCount = READ_NET_16(packet, 9);
    uint8_t * attributeIDList = &packet[11];
    uint16_t  attributeIDListLen = de_get_len(attributeIDList);
    uint8_t * continuationState = &packet[11+attributeIDListLen];

    // calc maximumAttributeByteCount based on remote MTU
    uint16_t maximumAttributeByteCount2 = remote_mtu - (7+3);
    if (maximumAttributeByteCount2 < maximumAttributeByteCount) {
        maximumAttributeByteCount = maximumAttributeByteCount2;
    }

    // continuation state contains the offset into the complete response
    uint16_t continuation_offset = 0;
    if (continuationState[0] == 2) {
        continuation_offset = READ_NET_16(continuationState, 1);
    }

    // get service record
    service_record_item_t * item = sdp_get_record_for_handle(serviceRecordHandle);
    if (!item) {
        // service record handle doesn't exist
        return sdp_create_error_response(transaction_id, 0x0002); /// invalid Service Record Handle
    }


    // AttributeList - starts at offset 7
    uint16_t pos = 7;

    if (continuation_offset == 0) {

        // get size of this record
        uint16_t filtered_attributes_size = spd_get_filtered_size(item->service_record, attributeIDList);

        // store DES
        de_store_descriptor_with_len(&sdp_response_buffer[pos], DE_DES, DE_SIZE_VAR_16, filtered_attributes_size);
        maximumAttributeByteCount -= 3;
        pos += 3;
    }

    // copy maximumAttributeByteCount from record
    uint16_t bytes_used;
    int complete = sdp_filter_attributes_in_attributeIDList(item->service_record, attributeIDList, continuation_offset, maximumAttributeByteCount, &bytes_used, &sdp_response_buffer[pos]);
    pos += bytes_used;

    uint16_t attributeListByteCount = pos - 7;

    if (complete) {
        sdp_response_buffer[pos++] = 0;
    } else {
        continuation_offset += bytes_used;
        sdp_response_buffer[pos++] = 2;
        net_store_16(sdp_response_buffer, pos, continuation_offset);
        pos += 2;
    }

    // header
    sdp_response_buffer[0] = SDP_ServiceAttributeResponse;
    net_store_16(sdp_response_buffer, 1, transaction_id);
    net_store_16(sdp_response_buffer, 3, pos - 5);  // size of variable payload
    net_store_16(sdp_response_buffer, 5, attributeListByteCount);

    return pos;
}
Example #10
0
int sdp_handle_service_search_request(uint8_t * packet, uint16_t remote_mtu) {

    // get request details
    uint16_t  transaction_id = READ_NET_16(packet, 1);
    // not used yet - uint16_t  param_len = READ_NET_16(packet, 3);
    uint8_t * serviceSearchPattern = &packet[5];
    uint16_t  serviceSearchPatternLen = de_get_len(serviceSearchPattern);
    uint16_t  maximumServiceRecordCount = READ_NET_16(packet, 5 + serviceSearchPatternLen);
    uint8_t * continuationState = &packet[5+serviceSearchPatternLen+2];

    // calc maxumumServiceRecordCount based on remote MTU
    uint16_t maxNrServiceRecordsPerResponse = (remote_mtu - (9+3))/4;

    // continuation state contains index of next service record to examine
    int      continuation = 0;
    uint16_t continuation_index = 0;
    if (continuationState[0] == 2) {
        continuation_index = READ_NET_16(continuationState, 1);
    }

    // get and limit total count
    linked_item_t *it;
    uint16_t total_service_count   = 0;
    for (it = (linked_item_t *) sdp_service_records; it ; it = it->next) {
        service_record_item_t * item = (service_record_item_t *) it;
        if (!sdp_record_matches_service_search_pattern(item->service_record, serviceSearchPattern)) continue;
        total_service_count++;
    }
    if (total_service_count > maximumServiceRecordCount) {
        total_service_count = maximumServiceRecordCount;
    }

    // ServiceRecordHandleList at 9
    uint16_t pos = 9;
    uint16_t current_service_count  = 0;
    uint16_t current_service_index  = 0;
    uint16_t matching_service_count = 0;
    for (it = (linked_item_t *) sdp_service_records; it ; it = it->next, ++current_service_index) {
        service_record_item_t * item = (service_record_item_t *) it;

        if (!sdp_record_matches_service_search_pattern(item->service_record, serviceSearchPattern)) continue;
        matching_service_count++;

        if (current_service_index < continuation_index) continue;

        net_store_32(sdp_response_buffer, pos, item->service_record_handle);
        pos += 4;
        current_service_count++;

        if (matching_service_count >= total_service_count) break;

        if (current_service_count >= maxNrServiceRecordsPerResponse) {
            continuation = 1;
            continuation_index = current_service_index + 1;
            break;
        }
    }

    // Store continuation state
    if (continuation) {
        sdp_response_buffer[pos++] = 2;
        net_store_16(sdp_response_buffer, pos, continuation_index);
        pos += 2;
    } else {
        sdp_response_buffer[pos++] = 0;
    }

    // header
    sdp_response_buffer[0] = SDP_ServiceSearchResponse;
    net_store_16(sdp_response_buffer, 1, transaction_id);
    net_store_16(sdp_response_buffer, 3, pos - 5); // size of variable payload
    net_store_16(sdp_response_buffer, 5, total_service_count);
    net_store_16(sdp_response_buffer, 7, current_service_count);

    return pos;
}
Example #11
0
/*
parse the sdp record:
type   DES (6), element len 26
    type   DES (6), element len 24
        type  UINT (1), element len  3 , value: 0x00000004
        type   DES (6), element len 19
            type   DES (6), element len  5
                type  UUID (3), element len  3 , value: 0x00000100
            type   DES (6), element len  7
                type  UUID (3), element len  3 , value: 0x00000003
                type  UINT (1), element len  2 , value: 0x00000002
            type   DES (6), element len  5
                type  UUID (3), element len  3 , value: 0x00000008
*/
static void sdpc_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size)
{
  if (packet_type == HCI_EVENT_PACKET)
  {
    switch(packet[0]){
    case L2CAP_EVENT_CHANNEL_OPENED:
      {
        if (packet[2]) {
          log_info("Connection failed\n");
          return;
        }
        log_info("Connected\n");
        state = SENDING;
        current_server = 0;
        l2cap_cid = READ_BT_16(packet, 13);
        sdpc_trysend();
        break;
      }
    case DAEMON_EVENT_HCI_PACKET_SENT:
    case L2CAP_EVENT_CREDITS:
      {
        sdpc_trysend();
        break;
      }
    case L2CAP_EVENT_CHANNEL_CLOSED:
      if (channel == l2cap_cid){
        // reset
        l2cap_cid = 0;
      }
      break;
    }
  }

  if (packet_type == L2CAP_DATA_PACKET){
    log_info("SDP Respone %d \n", READ_NET_16(packet, 5));
    //de_dump_data_element(&packet[7]);

    //check if valid answer returns
    if (READ_NET_16(packet, 5) > 2)
    {
      switch(current_server)
      {
      case 0:
        {
        hfp_port = sdp_get_parameters_for_uuid(&packet[7], 0x0003);;
        log_info("hfp port: %d\n", hfp_port);
        break;
        }
      case 1:
        break;
      case 2:
        {
        mas_port = sdp_get_parameters_for_uuid(&packet[7], 0x0003);;
        log_info("MAP port: %d\n", mas_port );
        break;
        }
      }
    }

    current_server++;
    if (current_server == 3)
    {
      state = DONE;
      l2cap_close_connection(&current_server);
      if (hfp_port != 0)
        hfp_open(&addr, hfp_port);
//      if (mas_port != 0)
//        mas_open(&addr, mas_port);
    }
    else
    {
      state = SENDING;
      sdpc_trysend();
    }
  }
}
Example #12
0
void sdp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
    // uint16_t handle;
    if (packet_type == L2CAP_DATA_PACKET){
        uint16_t responseTransactionID = READ_NET_16(packet,1);
        if ( responseTransactionID != transactionID){
            log_error("Missmatching transaction ID, expected %u, found %u.", transactionID, responseTransactionID);
            return;
        } 
        
        if (packet[0] != SDP_ServiceSearchAttributeResponse 
            && packet[0] != SDP_ServiceSearchResponse
            && packet[0] != SDP_ServiceAttributeResponse){
            log_error("Not a valid PDU ID, expected %u, %u or %u, found %u.", SDP_ServiceSearchResponse, 
                                    SDP_ServiceAttributeResponse, SDP_ServiceSearchAttributeResponse, packet[0]);
            return;
        }

        PDU_ID = packet[0];
        log_info("SDP Client :: PDU ID. %u ,%u", PDU_ID, packet[0]);
        switch (PDU_ID){
#ifdef HAVE_SDP_EXTRA_QUERIES
            case SDP_ServiceSearchResponse:
                parse_service_search_response(packet);
                break;
            case SDP_ServiceAttributeResponse:
                parse_service_attribute_response(packet);
                break;
#endif
            case SDP_ServiceSearchAttributeResponse:
                parse_service_search_attribute_response(packet);
                break;
            default:
                log_error("SDP Client :: PDU ID invalid. %u ,%u", PDU_ID, packet[0]);
                return;
        }

        // continuation set or DONE?
        if (continuationStateLen == 0){
            log_info("SDP Client Query DONE! ");
            sdp_client_state = QUERY_COMPLETE;
            l2cap_disconnect_internal(sdp_cid, 0);
            // sdp_parser_handle_done(0);
            return;
        }
        // prepare next request and send
        sdp_client_state = W2_SEND;
        if (can_send_now(sdp_cid)) send_request(sdp_cid);
        return;
    }
    
    if (packet_type != HCI_EVENT_PACKET) return;
    
    switch(packet[0]){
        case L2CAP_EVENT_TIMEOUT_CHECK:
            log_info("sdp client: L2CAP_EVENT_TIMEOUT_CHECK");
            break;
        case L2CAP_EVENT_CHANNEL_OPENED:
            if (sdp_client_state != W4_CONNECT) break;
            // data: event (8), len(8), status (8), address(48), handle (16), psm (16), local_cid(16), remote_cid (16), local_mtu(16), remote_mtu(16) 
            if (packet[2]) {
                log_error("SDP Client Connection failed.");
                sdp_parser_handle_done(packet[2]);
                break;
            }
            sdp_cid = channel;
            mtu = READ_BT_16(packet, 17);
            // handle = READ_BT_16(packet, 9);
            log_info("SDP Client Connected, cid %x, mtu %u.", sdp_cid, mtu);

            sdp_client_state = W2_SEND;
            if (can_send_now(sdp_cid)) send_request(sdp_cid);
        
            break;
        case L2CAP_EVENT_CREDITS:
        case DAEMON_EVENT_HCI_PACKET_SENT:
            if (can_send_now(sdp_cid)) send_request(sdp_cid);
            break;
        case L2CAP_EVENT_CHANNEL_CLOSED: {
            if (sdp_cid != READ_BT_16(packet, 2)) {
                // log_info("Received L2CAP_EVENT_CHANNEL_CLOSED for cid %x, current cid %x\n",  READ_BT_16(packet, 2),sdp_cid);
                break;
            }
            log_info("SDP Client disconnected.");
            uint8_t status = sdp_client_state == QUERY_COMPLETE ? 0 : SDP_QUERY_INCOMPLETE;
            sdp_client_state = INIT;
            sdp_parser_handle_done(status);
            break;
        }
        default:
            break;
    }
}
Example #13
0
File: sdp.c Project: ajsb85/ioio
void sdp_test(){
    
    const uint16_t remote_mtu = 48;
    uint8_t allAttributeIDs[20];  //
    
    // create an attribute list
    de_create_sequence(allAttributeIDs);
    de_add_number(allAttributeIDs, DE_UINT, DE_SIZE_32, 0x0000ffff);
        
    // create two records with 2 attributes each
    de_create_sequence(record);
    de_add_number(record, DE_UINT, DE_SIZE_16, SDP_ServiceRecordHandle); 
    de_add_number(record, DE_UINT, DE_SIZE_32, 0x10001);
    de_add_number(record, DE_UINT, DE_SIZE_16, SDP_ServiceClassIDList);
    de_add_number(record, DE_UUID, DE_SIZE_16, 0x0001);
    de_add_number(record, DE_UINT, DE_SIZE_16, SDP_BrowseGroupList);
    de_add_number(record, DE_UUID, DE_SIZE_16, 0x0001);
    uint32_t handle_1 = sdp_register_service_internal(NULL, record);
    de_dump_data_element(record);
    
    de_create_sequence(record);
    de_add_number(record, DE_UINT, DE_SIZE_16, SDP_ServiceRecordHandle);
    de_add_number(record, DE_UINT, DE_SIZE_32, 0x10002);
    de_add_number(record, DE_UINT, DE_SIZE_16, SDP_ServiceClassIDList);
    de_add_number(record, DE_UUID, DE_SIZE_16, 0x0002);
    de_add_number(record, DE_UINT, DE_SIZE_16, SDP_BrowseGroupList);
    de_add_number(record, DE_UUID, DE_SIZE_16, 0x0001);
    sdp_register_service_internal(NULL, record);
    de_dump_data_element(record);

    uint16_t size = spd_get_filtered_size(record, allAttributeIDs);
    printf("Attribute size %u\n", size);
    
    uint16_t transactionID = 1;
    uint8_t * attributeIDList;
    uint16_t attributeIDListLen;
    uint16_t response_pos;
    uint8_t * serviceSearchPattern;
    uint16_t serviceSearchPatternLen;
    
#if 1
    // sdp_handle_service_search_request
    uint16_t nr_services = 1;
    request[0] = SDP_ServiceSearchRequest;
    net_store_16(request, 1, transactionID++); // transaction ID
    serviceSearchPattern = &request[5];
    de_create_sequence(serviceSearchPattern);
    {
        de_add_number(serviceSearchPattern, DE_UUID, DE_SIZE_16, 0x0001);
    }
    serviceSearchPatternLen = de_get_len(serviceSearchPattern);
    net_store_16(request, 5 + serviceSearchPatternLen, 2);  // max 
    request[5 + serviceSearchPatternLen + 2] = 0;   // cont
    sdp_handle_service_search_request(request, 16);
    dump_service_search_response();
    memcpy(request + 5 + serviceSearchPatternLen + 2, sdp_response_buffer + 9 + nr_services*4, 3); 
    sdp_handle_service_search_request(request, remote_mtu);
    dump_service_search_response();
#endif
    
#if 1
    // sdp_handle_service_attribute_request
    request[0] = SDP_ServiceAttributeRequest;
    net_store_16(request, 1, transactionID++); // transaction ID
    net_store_32(request, 5, handle_1); // record handle
    net_store_16(request, 9, 11); // max bytes
    attributeIDList = request + 11;
    de_create_sequence(attributeIDList);
    de_add_number(attributeIDList, DE_UINT, DE_SIZE_32, 0x0000ffff);
    attributeIDListLen = de_get_len(attributeIDList);
    request[11+attributeIDListLen] = 0;
    response_pos = 0;
    while(1) {
        sdp_handle_service_attribute_request(request, remote_mtu);

        uint16_t attributeListByteCount = READ_NET_16(sdp_response_buffer, 5);
        memcpy( &response[response_pos], &sdp_response_buffer[7], attributeListByteCount);
        response_pos += attributeListByteCount;
        
        printf("attributeListByteCount %u\n", attributeListByteCount);
        printf("Continuation %u\n", sdp_response_buffer[7+attributeListByteCount]);
        if (sdp_response_buffer[7+attributeListByteCount] == 0) break;
        printf("Continuation {%u}\n", READ_NET_16(sdp_response_buffer, 7+attributeListByteCount+1));
        memcpy(request+11+attributeIDListLen, sdp_response_buffer+7+attributeListByteCount, 3);
    }
    de_dump_data_element(response);
#endif
    
#if 1
    // sdp_handle_service_search_attribute_request
    request[0] = SDP_ServiceSearchAttributeRequest;
    net_store_16(request, 1, transactionID++); // transaction ID
    serviceSearchPattern = &request[5];
    de_create_sequence(serviceSearchPattern);
    {
        de_add_number(serviceSearchPattern, DE_UUID, DE_SIZE_16, 0x0001);
    }
    serviceSearchPatternLen = de_get_len(serviceSearchPattern);
    net_store_16(request, 5 + serviceSearchPatternLen, 11); // MaximumAttributeByteCount:
    attributeIDList = request + 5 + serviceSearchPatternLen + 2;
    de_create_sequence(attributeIDList);
    de_add_number(attributeIDList, DE_UINT, DE_SIZE_32, 0x0000ffff);
    attributeIDListLen = de_get_len(attributeIDList);
    request[5 + serviceSearchPatternLen + 2 + attributeIDListLen] = 0;
    response_pos = 0;
    while (1) {
        sdp_handle_service_search_attribute_request(request, remote_mtu);
        uint16_t attributeListByteCount = READ_NET_16(sdp_response_buffer, 5);
        memcpy( &response[response_pos], &sdp_response_buffer[7], attributeListByteCount);
        response_pos += attributeListByteCount;
        
        printf("attributeListByteCount %u\n", attributeListByteCount);
        printf("Continuation %u\n", sdp_response_buffer[7+attributeListByteCount]);
        if (sdp_response_buffer[7+attributeListByteCount] == 0) break;
        printf("Continuation {%u,%u}\n", READ_NET_16(sdp_response_buffer, 7+attributeListByteCount+1),
               READ_NET_16(sdp_response_buffer, 7+attributeListByteCount+3));
        memcpy(request+5 + serviceSearchPatternLen + 2 + attributeIDListLen, sdp_response_buffer+7+attributeListByteCount, 5);
    }
    de_dump_data_element(response);
#endif
    exit(0);
}