$NetBSD: patch-aj,v 1.2 2009/07/20 05:56:03 hasso Exp $ --- apps/bt_discovery.c.orig 2006-01-11 17:27:35.000000000 +0000 +++ apps/bt_discovery.c @@ -10,6 +10,205 @@ #include #include +#if defined(__NetBSD__) || defined(__DragonFly__) +#include +#include +#include +#include + +#include "bt_discovery.h" + +/* + * Parse protocol descriptor list for the RFCOMM channel + * + * seq8 len8 2 + * seq8 len8 2 + * uuid16 value16 3 L2CAP + * seq8 len8 2 + * uuid16 value16 3 RFCOMM + * uint8 value8 2 channel + * === + * 14 + */ + +static int32_t +parse_rfcomm_channel(sdp_attr_t *a) +{ + uint8_t *ptr = a->value; + uint8_t *end = a->value + a->vlen; + int32_t type, len, uuid, channel; + + if (end - ptr < 14) + return (-1); + + SDP_GET8(type, ptr); + switch (type) { + case SDP_DATA_SEQ8: + SDP_GET8(len, ptr); + break; + + case SDP_DATA_SEQ16: + SDP_GET16(len, ptr); + break; + + case SDP_DATA_SEQ32: + SDP_GET32(len, ptr); + break; + + default: + return (-1); + } + if (ptr + len > end) + return (-1); + + /* Protocol */ + SDP_GET8(type, ptr); + switch (type) { + case SDP_DATA_SEQ8: + SDP_GET8(len, ptr); + break; + + case SDP_DATA_SEQ16: + SDP_GET16(len, ptr); + break; + + case SDP_DATA_SEQ32: + SDP_GET32(len, ptr); + break; + + default: + return (-1); + } + if (ptr + len > end) + return (-1); + + /* UUID */ + if (ptr + 3 > end) + return (-1); + SDP_GET8(type, ptr); + switch (type) { + case SDP_DATA_UUID16: + SDP_GET16(uuid, ptr); + if (uuid != SDP_UUID_PROTOCOL_L2CAP) + return (-1); + break; + + case SDP_DATA_UUID32: /* XXX FIXME can we have 32-bit UUID */ + case SDP_DATA_UUID128: /* XXX FIXME can we have 128-bit UUID */ + default: + return (-1); + } + + /* Protocol */ + SDP_GET8(type, ptr); + switch (type) { + case SDP_DATA_SEQ8: + SDP_GET8(len, ptr); + break; + + case SDP_DATA_SEQ16: + SDP_GET16(len, ptr); + break; + + case SDP_DATA_SEQ32: + SDP_GET32(len, ptr); + break; + + default: + return (-1); + } + if (ptr + len > end) + return (-1); + + /* UUID */ + if (ptr + 3 > end) + return (-1); + SDP_GET8(type, ptr); + switch (type) { + case SDP_DATA_UUID16: + SDP_GET16(uuid, ptr); + if (uuid != SDP_UUID_PROTOCOL_RFCOMM) + return (-1); + break; + + case SDP_DATA_UUID32: /* XXX FIXME can we have 32-bit UUID */ + case SDP_DATA_UUID128: /* XXX FIXME can we have 128-bit UUID */ + default: + return (-1); + } + + /* channel */ + if (ptr + 2 > end) + return (-1); + + SDP_GET8(type, ptr); + if (type != SDP_DATA_UINT8) + return (-1); + + SDP_GET8(channel, ptr); + + return (channel); +} + +int +discover_bt(char *addr, char **res_bdaddr, int *res_channel) +{ + bdaddr_t laddr, raddr; + uint8_t buffer[256]; + sdp_attr_t proto = { SDP_ATTR_INVALID, 0, sizeof(buffer), buffer }; + uint16_t serv = SDP_SERVICE_CLASS_OBEX_FILE_TRANSFER; + uint32_t attr = SDP_ATTR_RANGE(SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST, + SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST); + void *ss; + + /* + * Convert given address to bdaddr. If not bdaddr, + * look it up in hosts database. + * + * XXX original does an inquiry if no name is given, + * XXX and matches against the name given or uses + * XXX the first device found. Consider that. + */ + if (addr == NULL) + errx(1, "must have address"); + + if (!bt_aton(addr, &raddr)) { + struct hostent *he = NULL; + + if ((he = bt_gethostbyname(addr)) == NULL) + errx(1, "%s: %s", + addr, hstrerror(h_errno)); + + bdaddr_copy(&raddr, (bdaddr_t *)he->h_addr); + } + + *res_bdaddr = strdup(bt_ntoa(&raddr, NULL)); + fprintf(stderr, "Browsing %s ...\n", *res_bdaddr); + + /* + * Connect to remote SDP server to find the channel + * number to use for the OBEX_FILE_TRANSFER service + */ + bdaddr_copy(&laddr, BDADDR_ANY); + ss = sdp_open(&laddr, &raddr); + if (ss == NULL || (errno = sdp_error(ss)) != 0) + err(1, "%s", addr); + + if (sdp_search(ss, 1, &serv, 1, &attr, 1, &proto) != 0) + errx(1, "sdp_search", strerror(sdp_error(ss))); + + if (proto.flags != SDP_ATTR_OK) + errx(1, "sdp_search: File Transfer not available"); + + sdp_close(ss); + + *res_channel = parse_rfcomm_channel(&proto); + if (*res_channel == -1) + errx(1, "sdp_search: No Channel #"); + + return 0; +} +#else #include #include #include @@ -146,6 +345,7 @@ int discover_bt(char *addr, char **res_b return 0; } +#endif #else #include "bt_discovery.h"