Exemplo n.º 1
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;
    }
}
Exemplo n.º 2
0
void sdp_client_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
    UNUSED(size);
    
    // uint16_t handle;
    if (packet_type == L2CAP_DATA_PACKET){
        uint16_t responseTransactionID = big_endian_read_16(packet,1);
        if (responseTransactionID != transactionID){
            log_error("Mismatching transaction ID, expected %u, found %u.", transactionID, responseTransactionID);
            return;
        } 
        
        if (packet[0] == SDP_ErrorResponse){
            log_error("Received error response with code %u, disconnecting", packet[2]);
            l2cap_disconnect(sdp_cid, 0);
            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 = (SDP_PDU_ID_t)packet[0];
        log_debug("SDP Client :: PDU ID. %u ,%u", PDU_ID, packet[0]);
        switch (PDU_ID){
#ifdef ENABLE_SDP_EXTRA_QUERIES
            case SDP_ServiceSearchResponse:
                sdp_client_parse_service_search_response(packet);
                break;
            case SDP_ServiceAttributeResponse:
                sdp_client_parse_service_attribute_response(packet);
                break;
#endif
            case SDP_ServiceSearchAttributeResponse:
                sdp_client_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_debug("SDP Client Query DONE! ");
            sdp_client_state = QUERY_COMPLETE;
            l2cap_disconnect(sdp_cid, 0);
            return;
        }
        // prepare next request and send
        sdp_client_state = W2_SEND;
        l2cap_request_can_send_now_event(sdp_cid);
        return;
    }
    
    if (packet_type != HCI_EVENT_PACKET) return;
    
    switch(hci_event_packet_get_type(packet)){
        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_info("SDP Client Connection failed, status 0x%02x.", packet[2]);
                sdp_client_state = INIT;
                sdp_parser_handle_done(packet[2]);
                break;
            }
            sdp_cid = channel;
            mtu = little_endian_read_16(packet, 17);
            // handle = little_endian_read_16(packet, 9);
            log_debug("SDP Client Connected, cid %x, mtu %u.", sdp_cid, mtu);

            sdp_client_state = W2_SEND;
            l2cap_request_can_send_now_event(sdp_cid);
            break;

        case L2CAP_EVENT_CAN_SEND_NOW:
            if(l2cap_event_can_send_now_get_local_cid(packet) == sdp_cid){
                sdp_client_send_request(sdp_cid);
            }
            break;
        case L2CAP_EVENT_CHANNEL_CLOSED: {
            if (sdp_cid != little_endian_read_16(packet, 2)) {
                // log_info("Received L2CAP_EVENT_CHANNEL_CLOSED for cid %x, current cid %x\n",  little_endian_read_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;
    }
}