diff options
Diffstat (limited to 'src/hci.c')
-rw-r--r-- | src/hci.c | 116 |
1 files changed, 88 insertions, 28 deletions
@@ -354,6 +354,59 @@ char *lmp_featurestostr(uint8_t *features, char *pref, int width) /* HCI functions that do not require open device */ +int hci_for_each_dev(int flag, int(*func)(int s, int dev_id, long arg), long arg) +{ + struct hci_dev_list_req *dl; + struct hci_dev_req *dr; + int dev_id = -1; + int s, i; + + s = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); + if (s < 0) + return -1; + + dl = malloc(HCI_MAX_DEV * sizeof(struct hci_dev_req) + sizeof(uint16_t)); + if (!dl) { + close(s); + return -1; + } + + dl->dev_num = HCI_MAX_DEV; + dr = dl->dev_req; + + if (ioctl(s, HCIGETDEVLIST, (void *)dl)) + goto done; + + for (i=0; i < dl->dev_num; i++, dr++) { + if (hci_test_bit(flag, &dr->dev_opt)) + if (!func || func(s, dr->dev_id, arg)) { + dev_id = dr->dev_id; + break; + } + } + +done: + close(s); + free(dl); + return dev_id; +} + +static int __other_bdaddr(int s, int dev_id, long arg) +{ + struct hci_dev_info di = {dev_id: dev_id}; + if (ioctl(s, HCIGETDEVINFO, (void*) &di)) + return 0; + return bacmp((bdaddr_t *)arg, &di.bdaddr); +} + +int hci_get_route(bdaddr_t *bdaddr) +{ + if (bdaddr) + return hci_for_each_dev(HCI_UP, __other_bdaddr, (long) bdaddr); + else + return hci_for_each_dev(HCI_UP, NULL, 0); +} + int hci_devinfo(int dev_id, struct hci_dev_info *di) { int s, err; @@ -385,22 +438,33 @@ int hci_devba(int dev_id, bdaddr_t *ba) return 0; } -inquiry_info *hci_inquiry(int dev_id, int len, int *num_rsp, uint8_t *lap, long flags) +int hci_inquiry(int dev_id, int len, int nrsp, uint8_t *lap, inquiry_info **ii, long flags) { struct hci_inquiry_req *ir; - char *buf, *ptr; - int s, err, size; + void *buf; + int s, err; - if (!*num_rsp) - *num_rsp = 200; // enough ? + if (nrsp <= 0) + nrsp = 200; // enough ? - size = sizeof(*ir) + (sizeof(inquiry_info) * (*num_rsp)); - if (!(buf = malloc(size))) - return NULL; + if (dev_id < 0 && (dev_id = hci_get_route(NULL)) < 0) { + errno = ENODEV; + return -1; + } + + s = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); + if (s < 0) + return -1; + + buf = malloc(sizeof(*ir) + (sizeof(inquiry_info) * (nrsp))); + if (!buf) { + close(s); + return -1; + } - ir = (void *)buf; + ir = buf; ir->dev_id = dev_id; - ir->num_rsp = *num_rsp; + ir->num_rsp = nrsp; ir->length = len; ir->flags = flags; @@ -412,28 +476,23 @@ inquiry_info *hci_inquiry(int dev_id, int len, int *num_rsp, uint8_t *lap, long ir->lap[2] = 0x9e; } - if ((s = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI)) < 0) - goto failed; - if (ioctl(s, HCIINQUIRY, (unsigned long)buf) < 0) - goto failed; - - size = sizeof(inquiry_info) * ir->num_rsp; - if (!(ptr = malloc(size))) - goto failed; + err = ioctl(s, HCIINQUIRY, (unsigned long) buf); + close(s); - memcpy(ptr, buf + sizeof(*ir), size); - *num_rsp = ir->num_rsp; + if (!err) { + int size = sizeof(inquiry_info) * ir->num_rsp; - free(buf); - close(s); - return (void *) ptr; + if (!*ii) + *ii = (void *) malloc(size); -failed: - err = errno; + if (*ii) { + memcpy((void *) *ii, buf + sizeof(*ir), size); + err = ir->num_rsp; + } else + err = -1; + } free(buf); - close(s); - errno = err; - return NULL; + return err; } /* Open HCI device. @@ -838,3 +897,4 @@ int hci_class_of_dev(int dd, uint8_t *class, int to) memcpy(class, rp.dev_class, 3); return 0; } + |