switch (cfg->codec) { case CODEC_SBC: break; #ifdef HAVE_FFMPEG case CODEC_AAC: break; #endif default: break; } return (bt_close(pbe)); } static const uint32_t bt_attrs[] = { SDP_ATTR_RANGE(SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST), }; #define BT_NUM_VALUES 32 #define BT_BUF_SIZE 32 static int bt_find_psm(const uint8_t *start, const uint8_t *end) { uint32_t type; uint32_t len; int protover = 0; int psm = -1; if ((end - start) < 2) return (-1);
* $Id: search.c,v 1.2 2003/09/08 17:35:15 max Exp $ * $FreeBSD: release/9.0.0/usr.sbin/bluetooth/sdpcontrol/search.c 173335 2007-11-04 21:24:33Z emax $ */ #include <netinet/in.h> #include <bluetooth.h> #include <ctype.h> #include <sdp.h> #include <stdio.h> #include <stdlib.h> #include "sdpcontrol.h" /* List of the attributes we are looking for */ static uint32_t attrs[] = { SDP_ATTR_RANGE( SDP_ATTR_SERVICE_RECORD_HANDLE, SDP_ATTR_SERVICE_RECORD_HANDLE), SDP_ATTR_RANGE( SDP_ATTR_SERVICE_CLASS_ID_LIST, SDP_ATTR_SERVICE_CLASS_ID_LIST), SDP_ATTR_RANGE( SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST), SDP_ATTR_RANGE( SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST, SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST) }; #define attrs_len (sizeof(attrs)/sizeof(attrs[0])) /* Buffer for the attributes */ #define NRECS 25 /* request this much records from the SDP server */ #define BSIZE 256 /* one attribute buffer size */ static uint8_t buffer[NRECS * attrs_len][BSIZE]; /* SDP attributes */
static int find_service_channel(bdaddr_t *adapter, bdaddr_t *device, int only_gnapplet, uint16_t svclass_id) { int i, channel = -1; char name[64]; void *ss = NULL; uint32_t attrs[] = { SDP_ATTR_RANGE( SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST), SDP_ATTR_RANGE( SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_SERVICE_NAME_OFFSET, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_SERVICE_NAME_OFFSET), }; /* Buffer for the attributes */ static uint8_t buffer[NRECS * attrs_len][BSIZE]; /* SDP attributes */ static sdp_attr_t values[NRECS * attrs_len]; /* Initialize attribute values array */ for (i = 0; i < values_len; i ++) { values[i].flags = SDP_ATTR_INVALID; values[i].attr = 0; values[i].vlen = BSIZE; values[i].value = buffer[i]; } if ((ss = sdp_open(adapter, device)) == NULL) return -1; if (sdp_error(ss) != 0) goto end; if (sdp_search(ss, 1, &svclass_id, attrs_len, attrs, values_len, values) != 0) goto end; for (i = 0; i < values_len; i++) { union { uint8_t uint8; uint16_t uint16; uint32_t uint32; uint64_t uint64; int128_t int128; } value; uint8_t *start, *end; uint32_t type, len; if (values[i].flags != SDP_ATTR_OK) break; start = values[i].value; end = values[i].value + values[i].vlen; switch (values[i].attr) { case SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST: SDP_GET8(type, start); switch (type) { case SDP_DATA_SEQ8: SDP_GET8(len, start); break; case SDP_DATA_SEQ16: SDP_GET16(len, start); break; case SDP_DATA_SEQ32: SDP_GET32(len, start); break; default: goto end; break; } SDP_GET8(type, start); switch (type) { case SDP_DATA_SEQ8: SDP_GET8(len, start); break; case SDP_DATA_SEQ16: SDP_GET16(len, start); break; case SDP_DATA_SEQ32: SDP_GET32(len, start); break; default: goto end; } while (start < end) { SDP_GET8(type, start); switch (type) { case SDP_DATA_UUID16: SDP_GET16(value.uint16, start); break; case SDP_DATA_UUID32: SDP_GET32(value.uint32, start); break; case SDP_DATA_UUID128: SDP_GET_UUID128(&value.int128, start); break; default: goto end; } if (value.uint16 == 3) { SDP_GET8(type, start); switch (type) { case SDP_DATA_UINT8: case SDP_DATA_INT8: SDP_GET8(value.uint8, start); channel = value.uint8; break; case SDP_DATA_UINT16: case SDP_DATA_INT16: SDP_GET16(value.uint16, start); channel = value.uint16; break; case SDP_DATA_UINT32: case SDP_DATA_INT32: SDP_GET32(value.uint32, start); channel = value.uint32; break; default: goto end; } } else { SDP_GET8(type, start); switch (type) { case SDP_DATA_SEQ8: case SDP_DATA_UINT8: case SDP_DATA_INT8: case SDP_DATA_BOOL: SDP_GET8(value.uint8, start); break; case SDP_DATA_SEQ16: case SDP_DATA_UINT16: case SDP_DATA_INT16: case SDP_DATA_UUID16: SDP_GET16(value.uint16, start); break; case SDP_DATA_SEQ32: case SDP_DATA_UINT32: case SDP_DATA_INT32: case SDP_DATA_UUID32: SDP_GET32(value.uint32, start); break; case SDP_DATA_UINT64: case SDP_DATA_INT64: SDP_GET64(value.uint64, start); break; case SDP_DATA_UINT128: case SDP_DATA_INT128: SDP_GET128(&value.int128, start); break; default: goto end; } } } start += len; break; case SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_SERVICE_NAME_OFFSET: if (channel == -1) break; SDP_GET8(type, start); switch (type) { case SDP_DATA_STR8: case SDP_DATA_URL8: SDP_GET8(len, start); snprintf(name, sizeof(name), "%*.*s", len, len, (char *) start); start += len; break; case SDP_DATA_STR16: case SDP_DATA_URL16: SDP_GET16(len, start); snprintf(name, sizeof(name), "%*.*s", len, len, (char *) start); start += len; break; case SDP_DATA_STR32: case SDP_DATA_URL32: SDP_GET32(len, start); snprintf(name, sizeof(name), "%*.*s", len, len, (char *) start); start += len; break; default: goto end; } if (name == NULL) break; if (only_gnapplet != 0) { if (strcmp(name, "gnapplet") == 0) goto end; else { channel = -1; break; } } if (strstr(name, "Nokia PC Suite") != NULL) { channel = -1; break; } if (strstr(name, "Bluetooth Serial Port") != NULL) { channel = -1; break; } if (strstr(name, "m-Router Connectivity") != NULL) { channel = -1; break; } goto end; } } end: sdp_close(ss); return channel; }
static void client_query(void) { uint8_t buffer[512]; sdp_attr_t attr; uint32_t range; void *ss; int rv; uint8_t *seq0, *seq1; attr.flags = SDP_ATTR_INVALID; attr.attr = 0; attr.vlen = sizeof(buffer); attr.value = buffer; range = SDP_ATTR_RANGE(SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST); ss = sdp_open(&local_bdaddr, &remote_bdaddr); if (ss == NULL || (errno = sdp_error(ss)) != 0) { log_err("%s: %m", service_name); exit(EXIT_FAILURE); } log_info("Searching for %s service at %s", service_name, bt_ntoa(&remote_bdaddr, NULL)); rv = sdp_search(ss, 1, &service_class, 1, &range, 1, &attr); if (rv != 0) { log_err("%s: %s", service_name, strerror(sdp_error(ss))); exit(EXIT_FAILURE); } sdp_close(ss); if (attr.flags != SDP_ATTR_OK || attr.attr != SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST) { log_err("%s service not found", service_name); exit(EXIT_FAILURE); } /* * we expect the following protocol descriptor list * * seq len * seq len * uuid value == L2CAP * uint16 value16 => PSM * seq len * uuid value == BNEP */ if (_sdp_get_seq(&attr.value, attr.value + attr.vlen, &seq0) && _sdp_get_seq(&seq0, attr.value, &seq1) && _sdp_match_uuid16(&seq1, seq0, SDP_UUID_PROTOCOL_L2CAP) && _sdp_get_uint16(&seq1, seq0, &l2cap_psm) && _sdp_get_seq(&seq0, attr.value, &seq1) && _sdp_match_uuid16(&seq1, seq0, SDP_UUID_PROTOCOL_BNEP)) { log_info("Found PSM %d for service %s", l2cap_psm, service_name); return; } log_err("%s query failed", service_name); exit(EXIT_FAILURE); }
int rfcomm_channel_lookup(bdaddr_t const *local, bdaddr_t const *remote, int service, int *channel, int *error) { uint8_t buffer[PROTOCOL_DESCRIPTOR_LIST_BUFFER_SIZE]; void *ss = NULL; uint16_t serv = (uint16_t) service; uint32_t attr = SDP_ATTR_RANGE( SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST); sdp_attr_t proto = { SDP_ATTR_INVALID,0,sizeof(buffer),buffer }; uint32_t type, len; if (local == NULL) local = NG_HCI_BDADDR_ANY; if (remote == NULL || channel == NULL) rfcomm_channel_lookup_exit(EINVAL); if ((ss = sdp_open(local, remote)) == NULL) rfcomm_channel_lookup_exit(ENOMEM); if (sdp_error(ss) != 0) rfcomm_channel_lookup_exit(sdp_error(ss)); if (sdp_search(ss, 1, &serv, 1, &attr, 1, &proto) != 0) rfcomm_channel_lookup_exit(sdp_error(ss)); if (proto.flags != SDP_ATTR_OK) rfcomm_channel_lookup_exit(ENOATTR); sdp_close(ss); ss = NULL; /* * If it is possible for more than one kind of protocol stack to be * used to gain access to the service, the ProtocolDescriptorList * takes the form of a data element alternative. We always use the * first protocol stack. * * A minimal Protocol Descriptor List for RFCOMM based service would * look like * * seq8 len8 - 2 bytes * seq8 len8 - 2 bytes * uuid16 value16 - 3 bytes L2CAP * seq8 len8 - 2 bytes * uuid16 value16 - 3 bytes RFCOMM * uint8 value8 - 2 bytes RFCOMM param #1 * ========= * 14 bytes * * Lets not count first [seq8 len8] wrapper, so the minimal size of * the Protocol Descriptor List (the data we are actually interested * in) for RFCOMM based service would be 12 bytes. */ if (proto.vlen < PROTOCOL_DESCRIPTOR_LIST_MINIMAL_SIZE) rfcomm_channel_lookup_exit(EINVAL); SDP_GET8(type, proto.value); if (type == SDP_DATA_ALT8) { SDP_GET8(len, proto.value); } else if (type == SDP_DATA_ALT16) { SDP_GET16(len, proto.value); } else if (type == SDP_DATA_ALT32) { SDP_GET32(len, proto.value); } else len = 0; if (len > 0) SDP_GET8(type, proto.value); switch (type) { case SDP_DATA_SEQ8: SDP_GET8(len, proto.value); break; case SDP_DATA_SEQ16: SDP_GET16(len, proto.value); break; case SDP_DATA_SEQ32: SDP_GET32(len, proto.value); break; default: rfcomm_channel_lookup_exit(ENOATTR); /* NOT REACHED */ } if (len < PROTOCOL_DESCRIPTOR_LIST_MINIMAL_SIZE) rfcomm_channel_lookup_exit(EINVAL); return (rfcomm_proto_list_parse(proto.value, buffer + proto.vlen, channel, error)); }
#include <sdp.h> #include <stdio.h> #include <string.h> #include <usbhid.h> #include "bthid_config.h" #include "bthidcontrol.h" static int32_t hid_sdp_query (bdaddr_t const *local, struct hid_device *hd, int32_t *error); static int32_t hid_sdp_parse_protocol_descriptor_list (sdp_attr_p a); static int32_t hid_sdp_parse_hid_descriptor (sdp_attr_p a); static int32_t hid_sdp_parse_boolean (sdp_attr_p a); static uint16_t service = SDP_SERVICE_CLASS_HUMAN_INTERFACE_DEVICE; static uint32_t attrs[] = { SDP_ATTR_RANGE( SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST), SDP_ATTR_RANGE (SDP_ATTR_ADDITIONAL_PROTOCOL_DESCRIPTOR_LISTS, SDP_ATTR_ADDITIONAL_PROTOCOL_DESCRIPTOR_LISTS), SDP_ATTR_RANGE( 0x0205, /* HIDReconnectInitiate */ 0x0205), SDP_ATTR_RANGE( 0x0206, /* HIDDescriptorList */ 0x0206), SDP_ATTR_RANGE( 0x0209, /* HIDBatteryPower */ 0x0209), SDP_ATTR_RANGE( 0x020d, /* HIDNormallyConnectable */ 0x020d) }; #define nattrs (sizeof(attrs)/sizeof(attrs[0])) static sdp_attr_t values[8]; #define nvalues (sizeof(values)/sizeof(values[0]))