static void sdpc_trysend() { uint8_t buf[128]; if (state != SENDING) return; if (!l2cap_cid) return; if (!l2cap_can_send_packet_now(l2cap_cid)) return; buf[0] = SDP_ServiceSearchAttributeRequest; net_store_16(buf, 1, transitionid++); uint8_t *param = &buf[5]; de_create_sequence(param); de_add_number(param, DE_UUID, DE_SIZE_16, serviceids[current_server]); uint16_t size = de_get_len(param); net_store_16(param, size, 30); // max length is 30 bytes size+=2; de_create_sequence(param + size); //de_add_number(param + size, DE_UINT, DE_SIZE_16, SDP_ServiceClassIDList); de_add_number(param + size, DE_UINT, DE_SIZE_16, SDP_ProtocolDescriptorList); size += de_get_len(param + size); param[size++] = 0; net_store_16(buf, 3, size); hexdump(buf, size + 5); int err = l2cap_send_internal(l2cap_cid, buf, size + 5); if (!err) { state = RECV; log_info("sdp request sent.\n"); } else { log_info("sdpc_trysend l2cap_send_internal error: %d\n", err); } }
static void sdp_create_did_service(uint8_t *service){ uint8_t* attribute; de_create_sequence(service); // 0x0000 "Service Record Handle" de_add_number(service, DE_UINT, DE_SIZE_16, SDP_ServiceRecordHandle); de_add_number(service, DE_UINT, DE_SIZE_32, 0x10009); de_add_number(service, DE_UINT, DE_SIZE_16, SDP_ServiceClassIDList); attribute = de_push_sequence(service); { de_add_number(attribute, DE_UUID, DE_SIZE_16, 0x1200 ); } de_pop_sequence(service, attribute); de_add_number(service, DE_UINT, DE_SIZE_16, SDP_SpecificationID); attribute = de_push_sequence(service); { de_add_number(attribute, DE_UINT, DE_SIZE_16, 0x0103 ); } de_pop_sequence(service, attribute); de_add_number(service, DE_UINT, DE_SIZE_16, SDP_VendorID); attribute = de_push_sequence(service); { de_add_number(attribute, DE_UINT, DE_SIZE_16, 0xFFFF ); } de_pop_sequence(service, attribute); de_add_number(service, DE_UINT, DE_SIZE_16, SDP_ProductID); attribute = de_push_sequence(service); { de_add_number(attribute, DE_UINT, DE_SIZE_16, 0x0001 ); } de_pop_sequence(service, attribute); de_add_number(service, DE_UINT, DE_SIZE_16, SDP_Version); attribute = de_push_sequence(service); { de_add_number(attribute, DE_UINT, DE_SIZE_16, 0x0001); } de_pop_sequence(service, attribute); de_add_number(service, DE_UINT, DE_SIZE_16, SDP_PrimaryRecord); attribute = de_push_sequence(service); { de_add_number(attribute, DE_BOOL, DE_SIZE_8, 1); } de_pop_sequence(service, attribute); de_add_number(service, DE_UINT, DE_SIZE_16, SDP_VendorIDSource); attribute = de_push_sequence(service); { de_add_number(attribute, DE_UINT, DE_SIZE_16, 0x0001); } de_pop_sequence(service, attribute); }
void a2dp_source_create_sdp_record(uint8_t * service, uint32_t service_record_handle, uint16_t supported_features, const char * service_name, const char * service_provider_name){ uint8_t* attribute; de_create_sequence(service); // 0x0000 "Service Record Handle" de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_SERVICE_RECORD_HANDLE); de_add_number(service, DE_UINT, DE_SIZE_32, service_record_handle); // 0x0001 "Service Class ID List" de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_SERVICE_CLASS_ID_LIST); attribute = de_push_sequence(service); { de_add_number(attribute, DE_UUID, DE_SIZE_16, BLUETOOTH_SERVICE_CLASS_AUDIO_SOURCE); } de_pop_sequence(service, attribute); // 0x0004 "Protocol Descriptor List" de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_PROTOCOL_DESCRIPTOR_LIST); attribute = de_push_sequence(service); { uint8_t* l2cpProtocol = de_push_sequence(attribute); { de_add_number(l2cpProtocol, DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_L2CAP); de_add_number(l2cpProtocol, DE_UINT, DE_SIZE_16, BLUETOOTH_PROTOCOL_AVDTP); } de_pop_sequence(attribute, l2cpProtocol); uint8_t* avProtocol = de_push_sequence(attribute); { de_add_number(avProtocol, DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_AVDTP); // avProtocol_service de_add_number(avProtocol, DE_UINT, DE_SIZE_16, 0x0103); // version } de_pop_sequence(attribute, avProtocol); } de_pop_sequence(service, attribute); // 0x0005 "Public Browse Group" de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_BROWSE_GROUP_LIST); // public browse group attribute = de_push_sequence(service); { de_add_number(attribute, DE_UUID, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_PUBLIC_BROWSE_ROOT); } de_pop_sequence(service, attribute); // 0x0009 "Bluetooth Profile Descriptor List" de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_BLUETOOTH_PROFILE_DESCRIPTOR_LIST); attribute = de_push_sequence(service); { uint8_t *a2dProfile = de_push_sequence(attribute); { de_add_number(a2dProfile, DE_UUID, DE_SIZE_16, BLUETOOTH_SERVICE_CLASS_ADVANCED_AUDIO_DISTRIBUTION); de_add_number(a2dProfile, DE_UINT, DE_SIZE_16, 0x0103); } de_pop_sequence(attribute, a2dProfile); } de_pop_sequence(service, attribute); // 0x0100 "Service Name" de_add_number(service, DE_UINT, DE_SIZE_16, 0x0100); if (service_name){ de_add_data(service, DE_STRING, strlen(service_name), (uint8_t *) service_name); } else { de_add_data(service, DE_STRING, strlen(default_a2dp_source_service_name), (uint8_t *) default_a2dp_source_service_name); } // 0x0100 "Provider Name" de_add_number(service, DE_UINT, DE_SIZE_16, 0x0102); if (service_provider_name){ de_add_data(service, DE_STRING, strlen(service_provider_name), (uint8_t *) service_provider_name); } else { de_add_data(service, DE_STRING, strlen(default_a2dp_source_service_provider_name), (uint8_t *) default_a2dp_source_service_provider_name); } // 0x0311 "Supported Features" de_add_number(service, DE_UINT, DE_SIZE_16, 0x0311); de_add_number(service, DE_UINT, DE_SIZE_16, supported_features); }
void create_serial_port_service(uint8_t* service){ uint8_t * attribute; // create HID service de_create_sequence(service); de_add_number(service, DE_UINT, DE_SIZE_16, SDP_ServiceClassIDList); attribute = de_push_sequence(service); { de_add_number(attribute, DE_UUID, DE_SIZE_16, 0x1101); } de_pop_sequence(service, attribute); de_add_number(service, DE_UINT, DE_SIZE_16, SDP_ProtocolDescriptorList); uint8_t * protocolStack = de_push_sequence(service); { uint8_t * l2cpProtocol = de_push_sequence(protocolStack); { de_add_number(l2cpProtocol, DE_UUID, DE_SIZE_16, 0x0100); } de_pop_sequence(protocolStack, l2cpProtocol); uint8_t * rfcommChannel = de_push_sequence(protocolStack); { de_add_number(rfcommChannel, DE_UUID, DE_SIZE_16, 0x0003); de_add_number(rfcommChannel, DE_UINT, DE_SIZE_8, 0x0001); } de_pop_sequence(protocolStack, rfcommChannel); } de_pop_sequence(service, protocolStack); de_add_number(service, DE_UINT, DE_SIZE_16, SDP_BrowseGroupList); attribute = de_push_sequence(service); { de_add_number(attribute, DE_UUID, DE_SIZE_16, 0x1002); } de_pop_sequence(service, attribute); de_add_number(service, DE_UINT, DE_SIZE_16, SDP_LanguageBaseAttributeIDList); attribute = de_push_sequence(service); { de_add_number(attribute, DE_UINT, DE_SIZE_16, 0x656e); de_add_number(attribute, DE_UINT, DE_SIZE_16, 0x006a); de_add_number(attribute, DE_UINT, DE_SIZE_16, 0x0100); } de_pop_sequence(service, attribute); de_add_number(service, DE_UINT, DE_SIZE_16, SDP_BluetoothProfileDescriptorList); uint8_t * profileDescriptors = de_push_sequence(service); { uint8_t * hidProtocol = de_push_sequence(profileDescriptors); { de_add_number(hidProtocol, DE_UUID, DE_SIZE_16, 0x1124); de_add_number(hidProtocol, DE_UINT, DE_SIZE_16, 0x0100); } de_pop_sequence(profileDescriptors, hidProtocol); } de_pop_sequence(service, profileDescriptors); de_add_number(service, DE_UINT, DE_SIZE_16, 0x0100); de_add_data(service, DE_STRING, 16, (uint8_t *) "RFCOMM"); }
void create_sap_service(uint8_t* service){ uint8_t * attribute; uint8_t * protocolStack; uint8_t * l2cpProtocol; uint8_t * rfcommChannel; de_create_sequence(service); de_add_number(service, DE_UINT, DE_SIZE_16, SDP_ServiceClassIDList); attribute = de_push_sequence(service); { de_add_number(attribute, DE_UUID, DE_SIZE_16, 0x112d); de_add_number(attribute, DE_UUID, DE_SIZE_16, 0x1204); } de_pop_sequence(service, attribute); de_add_number(service, DE_UINT, DE_SIZE_16, SDP_ProtocolDescriptorList); protocolStack = de_push_sequence(service); { l2cpProtocol = de_push_sequence(protocolStack); { de_add_number(l2cpProtocol, DE_UUID, DE_SIZE_16, 0x0100); } de_pop_sequence(protocolStack, l2cpProtocol); rfcommChannel = de_push_sequence(protocolStack); { de_add_number(rfcommChannel, DE_UUID, DE_SIZE_16, 0x0003); de_add_number(rfcommChannel, DE_UINT, DE_SIZE_8, RFCOMM_CHANNEL_ID); } de_pop_sequence(protocolStack, rfcommChannel); } de_pop_sequence(service, protocolStack); de_add_number(service, DE_UINT, DE_SIZE_16, SDP_BrowseGroupList); attribute = de_push_sequence(service); { de_add_number(attribute, DE_UUID, DE_SIZE_16, 0x1002); } de_pop_sequence(service, attribute); de_add_number(service, DE_UINT, DE_SIZE_16, SDP_LanguageBaseAttributeIDList); attribute = de_push_sequence(service); { de_add_number(attribute, DE_UINT, DE_SIZE_16, 0x656e); de_add_number(attribute, DE_UINT, DE_SIZE_16, 0x006a); de_add_number(attribute, DE_UINT, DE_SIZE_16, 0x0100); } de_pop_sequence(service, attribute); uint8_t * profileDescriptors; uint8_t * hidProtocol; de_add_number(service, DE_UINT, DE_SIZE_16, SDP_BluetoothProfileDescriptorList); profileDescriptors = de_push_sequence(service); { hidProtocol = de_push_sequence(profileDescriptors); { de_add_number(hidProtocol, DE_UUID, DE_SIZE_16, 0x112d); de_add_number(hidProtocol, DE_UINT, DE_SIZE_16, 0x0102); } de_pop_sequence(profileDescriptors, hidProtocol); } de_pop_sequence(service, profileDescriptors); de_add_number(service, DE_UINT, DE_SIZE_16, 0x0100); de_add_data(service, DE_STRING, 16, (uint8_t *) "SIM Access"); }
// register service record internally - the normal version creates a copy of the record // pre: AttributeIDs are in ascending order => ServiceRecordHandle is first attribute if present // @returns ServiceRecordHandle or 0 if registration failed uint32_t sdp_register_service_internal(void *connection, uint8_t * record) { // dump for now // log_info("Register service record"); // de_dump_data_element(record); // get user record handle uint32_t record_handle = sdp_get_service_record_handle(record); // validate service record handle is not in reserved range if (record_handle <= maxReservedServiceRecordHandle) record_handle = 0; // check if already in use if (record_handle) { if (sdp_get_record_for_handle(record_handle)) { record_handle = 0; } } // create new handle if needed if (!record_handle) { record_handle = sdp_create_service_record_handle(); } // calculate size of new service record: DES (2 byte len) // + ServiceRecordHandle attribute (UINT16 UINT32) + size of existing attributes uint16_t recordSize = 3 + (3 + 5) + de_get_data_size(record); // alloc memory for new service_record_item service_record_item_t * newRecordItem = (service_record_item_t *) malloc(recordSize + sizeof(service_record_item_t)); if (!newRecordItem) { sdp_emit_service_registered(connection, 0, BTSTACK_MEMORY_ALLOC_FAILED); return 0; } // link new service item to client connection newRecordItem->connection = connection; // set new handle newRecordItem->service_record_handle = record_handle; // create updated service record uint8_t * newRecord = (uint8_t *) &(newRecordItem->service_record); // create DES for new record de_create_sequence(newRecord); // set service record handle de_add_number(newRecord, DE_UINT, DE_SIZE_16, 0); de_add_number(newRecord, DE_UINT, DE_SIZE_32, record_handle); // add other attributes sdp_append_attributes_in_attributeIDList(record, (uint8_t *) removeServiceRecordHandleAttributeIDList, 0, recordSize, newRecord); // dump for now // de_dump_data_element(newRecord); // log_info("reserved size %u, actual size %u", recordSize, de_get_len(newRecord)); // add to linked list linked_list_add(&sdp_service_records, (linked_item_t *) newRecordItem); sdp_emit_service_registered(connection, 0, newRecordItem->service_record_handle); return record_handle; }
void hsp_hs_create_sdp_record(uint8_t * service, int rfcomm_channel_nr, const char * name, uint8_t have_remote_audio_control){ uint8_t* attribute; de_create_sequence(service); // 0x0000 "Service Record Handle" de_add_number(service, DE_UINT, DE_SIZE_16, SDP_ServiceRecordHandle); de_add_number(service, DE_UINT, DE_SIZE_32, 0x10001); // 0x0001 "Service Class ID List" de_add_number(service, DE_UINT, DE_SIZE_16, SDP_ServiceClassIDList); attribute = de_push_sequence(service); { // see Bluetooth Erratum #3507 de_add_number(attribute, DE_UUID, DE_SIZE_16, SDP_HSP); // 0x1108 de_add_number(attribute, DE_UUID, DE_SIZE_16, SDP_Headset_HS); // 0x1131 de_add_number(attribute, DE_UUID, DE_SIZE_16, SDP_GenericAudio); // 0x1203 } de_pop_sequence(service, attribute); // 0x0004 "Protocol Descriptor List" de_add_number(service, DE_UINT, DE_SIZE_16, SDP_ProtocolDescriptorList); attribute = de_push_sequence(service); { uint8_t* l2cpProtocol = de_push_sequence(attribute); { de_add_number(l2cpProtocol, DE_UUID, DE_SIZE_16, SDP_L2CAPProtocol); } de_pop_sequence(attribute, l2cpProtocol); uint8_t* rfcomm = de_push_sequence(attribute); { de_add_number(rfcomm, DE_UUID, DE_SIZE_16, SDP_RFCOMMProtocol); // rfcomm_service de_add_number(rfcomm, DE_UINT, DE_SIZE_8, rfcomm_channel_nr); // rfcomm channel } de_pop_sequence(attribute, rfcomm); } de_pop_sequence(service, attribute); // 0x0005 "Public Browse Group" de_add_number(service, DE_UINT, DE_SIZE_16, SDP_BrowseGroupList); // public browse group attribute = de_push_sequence(service); { de_add_number(attribute, DE_UUID, DE_SIZE_16, SDP_PublicBrowseGroup); } de_pop_sequence(service, attribute); // 0x0009 "Bluetooth Profile Descriptor List" de_add_number(service, DE_UINT, DE_SIZE_16, SDP_BluetoothProfileDescriptorList); attribute = de_push_sequence(service); { uint8_t *hsp_profile = de_push_sequence(attribute); { de_add_number(hsp_profile, DE_UUID, DE_SIZE_16, SDP_HSP); de_add_number(hsp_profile, DE_UINT, DE_SIZE_16, 0x0102); // Verision 1.2 } de_pop_sequence(attribute, hsp_profile); } de_pop_sequence(service, attribute); // 0x0100 "Service Name" de_add_number(service, DE_UINT, DE_SIZE_16, 0x0100); if (name){ de_add_data(service, DE_STRING, strlen(name), (uint8_t *) name); } else { de_add_data(service, DE_STRING, strlen(default_hsp_hs_service_name), (uint8_t *) default_hsp_hs_service_name); } // Remote audio volume control de_add_number(service, DE_UINT, DE_SIZE_16, 0x030C); de_add_number(service, DE_BOOL, DE_SIZE_8, have_remote_audio_control); }
void hfp_create_sdp_record(uint8_t * service, uint16_t service_uuid, int rfcomm_channel_nr, const char * name, uint16_t supported_features){ uint8_t* attribute; de_create_sequence(service); // 0x0000 "Service Record Handle" de_add_number(service, DE_UINT, DE_SIZE_16, SDP_ServiceRecordHandle); de_add_number(service, DE_UINT, DE_SIZE_32, 0x10001); // 0x0001 "Service Class ID List" de_add_number(service, DE_UINT, DE_SIZE_16, SDP_ServiceClassIDList); attribute = de_push_sequence(service); { // "UUID for Service" de_add_number(attribute, DE_UUID, DE_SIZE_16, service_uuid); de_add_number(attribute, DE_UUID, DE_SIZE_16, SDP_GenericAudio); } de_pop_sequence(service, attribute); // 0x0004 "Protocol Descriptor List" de_add_number(service, DE_UINT, DE_SIZE_16, SDP_ProtocolDescriptorList); attribute = de_push_sequence(service); { uint8_t* l2cpProtocol = de_push_sequence(attribute); { de_add_number(l2cpProtocol, DE_UUID, DE_SIZE_16, SDP_L2CAPProtocol); } de_pop_sequence(attribute, l2cpProtocol); uint8_t* rfcomm = de_push_sequence(attribute); { de_add_number(rfcomm, DE_UUID, DE_SIZE_16, SDP_RFCOMMProtocol); // rfcomm_service de_add_number(rfcomm, DE_UINT, DE_SIZE_8, rfcomm_channel_nr); // rfcomm channel } de_pop_sequence(attribute, rfcomm); } de_pop_sequence(service, attribute); // 0x0005 "Public Browse Group" de_add_number(service, DE_UINT, DE_SIZE_16, SDP_BrowseGroupList); // public browse group attribute = de_push_sequence(service); { de_add_number(attribute, DE_UUID, DE_SIZE_16, SDP_PublicBrowseGroup); } de_pop_sequence(service, attribute); // 0x0009 "Bluetooth Profile Descriptor List" de_add_number(service, DE_UINT, DE_SIZE_16, SDP_BluetoothProfileDescriptorList); attribute = de_push_sequence(service); { uint8_t *sppProfile = de_push_sequence(attribute); { de_add_number(sppProfile, DE_UUID, DE_SIZE_16, SDP_Handsfree); de_add_number(sppProfile, DE_UINT, DE_SIZE_16, 0x0107); // Verision 1.7 } de_pop_sequence(attribute, sppProfile); } de_pop_sequence(service, attribute); // 0x0100 "Service Name" de_add_number(service, DE_UINT, DE_SIZE_16, 0x0100); de_add_data(service, DE_STRING, strlen(name), (uint8_t *) name); de_add_number(service, DE_UINT, DE_SIZE_16, supported_features); }
void create_spp_service(uint8_t *service, int service_id){ uint8_t* attribute; de_create_sequence(service); // 0x0001 "Service Class ID List" de_add_number(service, DE_UINT, DE_SIZE_16, 0x0001); attribute = de_push_sequence(service); { de_add_number(attribute, DE_UUID, DE_SIZE_16, 0x1101 ); } de_pop_sequence(service, attribute); // 0x0004 "Protocol Descriptor List" de_add_number(service, DE_UINT, DE_SIZE_16, 0x0004); attribute = de_push_sequence(service); { uint8_t* l2cpProtocol = de_push_sequence(attribute); { de_add_number(l2cpProtocol, DE_UUID, DE_SIZE_16, 0x0100); } de_pop_sequence(attribute, l2cpProtocol); uint8_t* rfcomm = de_push_sequence(attribute); { de_add_number(rfcomm, DE_UUID, DE_SIZE_16, 0x0003); // rfcomm_service de_add_number(rfcomm, DE_UINT, DE_SIZE_8, service_id); // rfcomm channel } de_pop_sequence(attribute, rfcomm); } de_pop_sequence(service, attribute); // 0x0005 "Public Browse Group" de_add_number(service, DE_UINT, DE_SIZE_16, 0x0005); // public browse group attribute = de_push_sequence(service); { de_add_number(attribute, DE_UUID, DE_SIZE_16, 0x1002 ); } de_pop_sequence(service, attribute); // 0x0006 de_add_number(service, DE_UINT, DE_SIZE_16, SDP_LanguageBaseAttributeIDList); attribute = de_push_sequence(service); { de_add_number(attribute, DE_UINT, DE_SIZE_16, 0x656e); de_add_number(attribute, DE_UINT, DE_SIZE_16, 0x006a); de_add_number(attribute, DE_UINT, DE_SIZE_16, 0x0100); } de_pop_sequence(service, attribute); // 0x0009 "Bluetooth Profile Descriptor List" de_add_number(service, DE_UINT, DE_SIZE_16, 0x0009); attribute = de_push_sequence(service); { uint8_t *sppProfile = de_push_sequence(attribute); { de_add_number(sppProfile, DE_UUID, DE_SIZE_16, 0x1101); de_add_number(sppProfile, DE_UINT, DE_SIZE_16, 0x0100); } de_pop_sequence(attribute, sppProfile); } de_pop_sequence(service, attribute); // 0x0100 "ServiceName" de_add_number(service, DE_UINT, DE_SIZE_16, 0x0100); de_add_data(service, DE_STRING, 8, (uint8_t *) "SPP ECHO"); }
void pan_create_service(uint8_t *service, uint32_t service_uuid, uint16_t * network_packet_types, const char *name, const char *descriptor, security_description_t security_desc, net_access_type_t net_access_type, uint32_t max_net_access_rate, const char *IPv4Subnet, const char *IPv6Subnet){ uint8_t* attribute; de_create_sequence(service); // 0x0000 "Service Record Handle" de_add_number(service, DE_UINT, DE_SIZE_16, SDP_ServiceRecordHandle); de_add_number(service, DE_UINT, DE_SIZE_32, 0x10001); // 0x0001 "Service Class ID List" de_add_number(service, DE_UINT, DE_SIZE_16, SDP_ServiceClassIDList); attribute = de_push_sequence(service); { // "UUID for PAN Service" de_add_number(attribute, DE_UUID, DE_SIZE_32, service_uuid); } de_pop_sequence(service, attribute); // 0x0004 "Protocol Descriptor List" de_add_number(service, DE_UINT, DE_SIZE_16, SDP_ProtocolDescriptorList); attribute = de_push_sequence(service); { uint8_t* l2cpProtocol = de_push_sequence(attribute); { de_add_number(l2cpProtocol, DE_UUID, DE_SIZE_16, SDP_L2CAPProtocol); de_add_number(l2cpProtocol, DE_UINT, DE_SIZE_16, PSM_BNEP); // l2cap psm } de_pop_sequence(attribute, l2cpProtocol); uint8_t* bnep = de_push_sequence(attribute); { de_add_number(bnep, DE_UUID, DE_SIZE_16, SDP_BNEPProtocol); de_add_number(bnep, DE_UINT, DE_SIZE_16, 0x0100); // version uint8_t * net_packet_type_list = de_push_sequence(bnep); { if (network_packet_types){ while (*network_packet_types){ de_add_number(net_packet_type_list, DE_UINT, DE_SIZE_16, *network_packet_types++); } } } de_pop_sequence(bnep, net_packet_type_list); } de_pop_sequence(attribute, bnep); } de_pop_sequence(service, attribute); // 0x0005 "Public Browse Group" de_add_number(service, DE_UINT, DE_SIZE_16, SDP_BrowseGroupList); // public browse group attribute = de_push_sequence(service); { de_add_number(attribute, DE_UUID, DE_SIZE_16, SDP_PublicBrowseGroup); } de_pop_sequence(service, attribute); // 0x0006 "LanguageBaseAttributeIDList" de_add_number(service, DE_UINT, DE_SIZE_16, SDP_LanguageBaseAttributeIDList); attribute = de_push_sequence(service); { de_add_number(attribute, DE_UINT, DE_SIZE_16, 0x656e); de_add_number(attribute, DE_UINT, DE_SIZE_16, 0x006a); de_add_number(attribute, DE_UINT, DE_SIZE_16, 0x0100); // Base for Service Name and Service Description } de_pop_sequence(service, attribute); // 0x0008 "Service Availability", optional // de_add_number(service, DE_UINT, DE_SIZE_16, 0x0008); // de_add_number(service, DE_UINT, DE_SIZE_8, service_availability); // 0x0009 "Bluetooth Profile Descriptor List" de_add_number(service, DE_UINT, DE_SIZE_16, SDP_BluetoothProfileDescriptorList); attribute = de_push_sequence(service); { uint8_t *sppProfile = de_push_sequence(attribute); { de_add_number(sppProfile, DE_UUID, DE_SIZE_16, service_uuid); de_add_number(sppProfile, DE_UINT, DE_SIZE_16, 0x0100); // Verision 1.0 } de_pop_sequence(attribute, sppProfile); } de_pop_sequence(service, attribute); // 0x0100 "Service Name" de_add_number(service, DE_UINT, DE_SIZE_16, 0x0100); if (name){ de_add_data(service, DE_STRING, strlen(name), (uint8_t *) name); } else { switch (service_uuid){ case SDP_PANU: de_add_data(service, DE_STRING, strlen(default_panu_service_name), (uint8_t *) default_panu_service_name); break; case SDP_NAP: de_add_data(service, DE_STRING, strlen(default_nap_service_name), (uint8_t *) default_nap_service_name); break; case SDP_GN: de_add_data(service, DE_STRING, strlen(default_gn_service_name), (uint8_t *) default_gn_service_name); break; default: break; } } // 0x0101 "Service Description" de_add_number(service, DE_UINT, DE_SIZE_16, 0x0101); if (descriptor){ de_add_data(service, DE_STRING, strlen(descriptor), (uint8_t *) descriptor); } else { switch (service_uuid){ case SDP_PANU: de_add_data(service, DE_STRING, strlen(default_panu_service_desc), (uint8_t *) default_panu_service_desc); break; case SDP_NAP: de_add_data(service, DE_STRING, strlen(default_nap_service_desc), (uint8_t *) default_nap_service_desc); break; case SDP_GN: de_add_data(service, DE_STRING, strlen(default_gn_service_desc), (uint8_t *) default_gn_service_desc); break; default: break; } } // 0x030A "Security Description" de_add_number(service, DE_UINT, DE_SIZE_16, 0x030A); de_add_number(service, DE_UINT, DE_SIZE_16, security_desc); if (service_uuid == SDP_PANU) return; if (IPv4Subnet){ // 0x030D "IPv4Subnet", optional de_add_number(service, DE_UINT, DE_SIZE_16, 0x030D); de_add_data(service, DE_STRING, strlen(IPv4Subnet), (uint8_t *) IPv4Subnet); } if (IPv6Subnet){ // 0x030E "IPv6Subnet", optional de_add_number(service, DE_UINT, DE_SIZE_16, 0x030E); de_add_data(service, DE_STRING, strlen(IPv6Subnet), (uint8_t *) IPv6Subnet); } if (service_uuid == SDP_GN) return; // 0x030B "NetAccessType" de_add_number(service, DE_UINT, DE_SIZE_16, 0x030B); de_add_number(service, DE_UINT, DE_SIZE_16, net_access_type); // 0x030C "MaxNetAccessRate" de_add_number(service, DE_UINT, DE_SIZE_16, 0x030C); de_add_number(service, DE_UINT, DE_SIZE_32, max_net_access_rate); }
void hsp_ag_create_sdp_record(uint8_t * service, int rfcomm_channel_nr, const char * name){ uint8_t* attribute; de_create_sequence(service); // 0x0000 "Service Record Handle" de_add_number(service, DE_UINT, DE_SIZE_16, SDP_ServiceRecordHandle); de_add_number(service, DE_UINT, DE_SIZE_32, 0x10001); // 0x0001 "Service Class ID List" de_add_number(service, DE_UINT, DE_SIZE_16, SDP_ServiceClassIDList); attribute = de_push_sequence(service); { // "UUID for PAN Service" de_add_number(attribute, DE_UUID, DE_SIZE_16, SDP_Headset_AG); de_add_number(attribute, DE_UUID, DE_SIZE_16, SDP_GenericAudio); } de_pop_sequence(service, attribute); // 0x0004 "Protocol Descriptor List" de_add_number(service, DE_UINT, DE_SIZE_16, SDP_ProtocolDescriptorList); attribute = de_push_sequence(service); { uint8_t* l2cpProtocol = de_push_sequence(attribute); { de_add_number(l2cpProtocol, DE_UUID, DE_SIZE_16, SDP_L2CAPProtocol); } de_pop_sequence(attribute, l2cpProtocol); uint8_t* rfcomm = de_push_sequence(attribute); { de_add_number(rfcomm, DE_UUID, DE_SIZE_16, SDP_RFCOMMProtocol); // rfcomm_service de_add_number(rfcomm, DE_UINT, DE_SIZE_8, rfcomm_channel_nr); // rfcomm channel } de_pop_sequence(attribute, rfcomm); } de_pop_sequence(service, attribute); // 0x0005 "Public Browse Group" de_add_number(service, DE_UINT, DE_SIZE_16, SDP_BrowseGroupList); // public browse group attribute = de_push_sequence(service); { de_add_number(attribute, DE_UUID, DE_SIZE_16, SDP_PublicBrowseGroup); } de_pop_sequence(service, attribute); // 0x0009 "Bluetooth Profile Descriptor List" de_add_number(service, DE_UINT, DE_SIZE_16, SDP_BluetoothProfileDescriptorList); attribute = de_push_sequence(service); { uint8_t *sppProfile = de_push_sequence(attribute); { de_add_number(sppProfile, DE_UUID, DE_SIZE_16, SDP_HSP); de_add_number(sppProfile, DE_UINT, DE_SIZE_16, 0x0102); // Verision 1.2 } de_pop_sequence(attribute, sppProfile); } de_pop_sequence(service, attribute); // 0x0100 "Service Name" de_add_number(service, DE_UINT, DE_SIZE_16, 0x0100); if (name){ de_add_data(service, DE_STRING, strlen(name), (uint8_t *) name); } else { de_add_data(service, DE_STRING, strlen(default_hsp_ag_service_name), (uint8_t *) default_hsp_ag_service_name); } }
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); }
void hsp_hs_create_sdp_record(uint8_t * service, uint32_t service_record_handle, int rfcomm_channel_nr, const char * name, uint8_t have_remote_audio_control){ uint8_t* attribute; de_create_sequence(service); // 0x0000 "Service Record Handle" de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_SERVICE_RECORD_HANDLE); de_add_number(service, DE_UINT, DE_SIZE_32, service_record_handle); // 0x0001 "Service Class ID List" de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_SERVICE_CLASS_ID_LIST); attribute = de_push_sequence(service); { // see Bluetooth Erratum #3507 de_add_number(attribute, DE_UUID, DE_SIZE_16, BLUETOOTH_SERVICE_CLASS_HEADSET); // 0x1108 de_add_number(attribute, DE_UUID, DE_SIZE_16, BLUETOOTH_SERVICE_CLASS_HEADSET_HS); // 0x1131 de_add_number(attribute, DE_UUID, DE_SIZE_16, BLUETOOTH_SERVICE_CLASS_GENERIC_AUDIO); // 0x1203 } de_pop_sequence(service, attribute); // 0x0004 "Protocol Descriptor List" de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_PROTOCOL_DESCRIPTOR_LIST); attribute = de_push_sequence(service); { uint8_t* l2cpProtocol = de_push_sequence(attribute); { de_add_number(l2cpProtocol, DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_L2CAP); } de_pop_sequence(attribute, l2cpProtocol); uint8_t* rfcomm = de_push_sequence(attribute); { de_add_number(rfcomm, DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_RFCOMM); // rfcomm_service de_add_number(rfcomm, DE_UINT, DE_SIZE_8, rfcomm_channel_nr); // rfcomm channel } de_pop_sequence(attribute, rfcomm); } de_pop_sequence(service, attribute); // 0x0005 "Public Browse Group" de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_BROWSE_GROUP_LIST); // public browse group attribute = de_push_sequence(service); { de_add_number(attribute, DE_UUID, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_PUBLIC_BROWSE_ROOT); } de_pop_sequence(service, attribute); // 0x0009 "Bluetooth Profile Descriptor List" de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_BLUETOOTH_PROFILE_DESCRIPTOR_LIST); attribute = de_push_sequence(service); { uint8_t *hsp_profile = de_push_sequence(attribute); { de_add_number(hsp_profile, DE_UUID, DE_SIZE_16, BLUETOOTH_SERVICE_CLASS_HEADSET); de_add_number(hsp_profile, DE_UINT, DE_SIZE_16, 0x0102); // Verision 1.2 } de_pop_sequence(attribute, hsp_profile); } de_pop_sequence(service, attribute); // 0x0100 "Service Name" de_add_number(service, DE_UINT, DE_SIZE_16, 0x0100); if (name){ de_add_data(service, DE_STRING, strlen(name), (uint8_t *) name); } else { de_add_data(service, DE_STRING, strlen(default_hsp_hs_service_name), (uint8_t *) default_hsp_hs_service_name); } // Remote audio volume control de_add_number(service, DE_UINT, DE_SIZE_16, 0x030C); de_add_number(service, DE_BOOL, DE_SIZE_8, have_remote_audio_control); }
void sdp_create_dummy_service(uint8_t *service, const char *name){ uint8_t* attribute; de_create_sequence(service); // 0x0000 "Service Record Handle" de_add_number(service, DE_UINT, DE_SIZE_16, SDP_ServiceRecordHandle); de_add_number(service, DE_UINT, DE_SIZE_32, 0x10002); // 0x0001 "Service Class ID List" de_add_number(service, DE_UINT, DE_SIZE_16, SDP_ServiceClassIDList); attribute = de_push_sequence(service); { de_add_uuid128(attribute, &dummy_uuid128[0] ); } de_pop_sequence(service, attribute); // 0x0004 "Protocol Descriptor List" de_add_number(service, DE_UINT, DE_SIZE_16, SDP_ProtocolDescriptorList); attribute = de_push_sequence(service); { uint8_t* l2cpProtocol = de_push_sequence(attribute); { de_add_number(l2cpProtocol, DE_UUID, DE_SIZE_16, 0x0100); } de_pop_sequence(attribute, l2cpProtocol); } de_pop_sequence(service, attribute); // 0x0005 "Public Browse Group" de_add_number(service, DE_UINT, DE_SIZE_16, SDP_BrowseGroupList); // public browse group attribute = de_push_sequence(service); { de_add_number(attribute, DE_UUID, DE_SIZE_16, SDP_PublicBrowseGroup); } de_pop_sequence(service, attribute); // 0x0006 de_add_number(service, DE_UINT, DE_SIZE_16, SDP_LanguageBaseAttributeIDList); attribute = de_push_sequence(service); { de_add_number(attribute, DE_UINT, DE_SIZE_16, 0x656e); de_add_number(attribute, DE_UINT, DE_SIZE_16, 0x006a); de_add_number(attribute, DE_UINT, DE_SIZE_16, 0x0100); } de_pop_sequence(service, attribute); // 0x0009 "Bluetooth Profile Descriptor List" de_add_number(service, DE_UINT, DE_SIZE_16, SDP_BluetoothProfileDescriptorList); attribute = de_push_sequence(service); { uint8_t *sppProfile = de_push_sequence(attribute); { de_add_number(sppProfile, DE_UINT, DE_SIZE_16, 0x0100); } de_pop_sequence(attribute, sppProfile); } de_pop_sequence(service, attribute); // 0x0100 "ServiceName" de_add_number(service, DE_UINT, DE_SIZE_16, 0x0100); de_add_data(service, DE_STRING, strlen(name), (uint8_t *) name); }