int btstack_main(int argc, const char * argv[]){ printf("Starting up..\n"); hci_set_class_of_device(0x200404); hci_disable_l2cap_timeout_check(); hci_ssp_set_io_capability(IO_CAPABILITY_NO_INPUT_NO_OUTPUT); gap_io_capabilities = "IO_CAPABILITY_NO_INPUT_NO_OUTPUT"; hci_ssp_set_authentication_requirement(0); hci_ssp_set_auto_accept(0); // gap_set_bondable_mode(0); l2cap_init(); l2cap_register_packet_handler(&packet_handler2); l2cap_register_fixed_channel(&packet_handler, L2CAP_CID_CONNECTIONLESS_CHANNEL); rfcomm_init(); rfcomm_register_packet_handler(packet_handler2); rfcomm_register_service_internal(NULL, RFCOMM_SERVER_CHANNEL, 150); // reserved channel, mtu=100 // init SDP, create record for SPP and register with SDP sdp_init(); memset(spp_service_buffer, 0, sizeof(spp_service_buffer)); sdp_create_spp_service((uint8_t*) spp_service_buffer, RFCOMM_SERVER_CHANNEL, "SPP Counter"); de_dump_data_element((uint8_t*) spp_service_buffer); printf("SDP service record size: %u\n\r", de_get_len((uint8_t*)spp_service_buffer)); sdp_register_service_internal(NULL, (uint8_t*)spp_service_buffer); memset(dummy_service_buffer, 0, sizeof(dummy_service_buffer)); sdp_create_dummy_service((uint8_t*)dummy_service_buffer, "UUID128 Test"); de_dump_data_element((uint8_t*)dummy_service_buffer); printf("Dummy service record size: %u\n\r", de_get_len((uint8_t*)dummy_service_buffer)); sdp_register_service_internal(NULL, (uint8_t*)dummy_service_buffer); sdp_query_rfcomm_register_callback(handle_query_rfcomm_event, NULL); hci_discoverable_control(0); hci_connectable_control(0); // turn on! hci_power_control(HCI_POWER_ON); btstack_stdin_setup(stdin_process); // set one-shot timer // timer_source_t heartbeat; // heartbeat.process = &heartbeat_handler; // run_loop_set_timer(&heartbeat, HEARTBEAT_PERIOD_MS); // run_loop_add_timer(&heartbeat); return 0; }
/* LISTING_START(HandleSDPQUeryResult): Handling query result chunks. */ static void handle_sdp_client_query_result(sdp_query_event_t * event){ sdp_query_attribute_value_event_t * ve; sdp_query_complete_event_t * ce; switch (event->type){ case SDP_QUERY_ATTRIBUTE_VALUE: ve = (sdp_query_attribute_value_event_t*) event; // handle new record if (ve->record_id != record_id){ record_id = ve->record_id; printf("\n---\nRecord nr. %u\n", record_id); } assertBuffer(ve->attribute_length); attribute_value[ve->data_offset] = ve->data; if ((uint16_t)(ve->data_offset+1) == ve->attribute_length){ printf("Attribute 0x%04x: ", ve->attribute_id); de_dump_data_element(attribute_value); } break; case SDP_QUERY_COMPLETE: ce = (sdp_query_complete_event_t*) event; printf("General query done with status %d.\n\n", ce->status); exit(0); break; } }
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); }