static int write_inquiry_mode(int dev_id, int sock) { struct hci_filter flt; write_inquiry_mode_cp cp; hci_filter_clear(&flt); hci_filter_set_ptype(HCI_EVENT_PKT, &flt); hci_filter_set_event(EVT_INQUIRY_RESULT, &flt); hci_filter_set_event(EVT_INQUIRY_RESULT_WITH_RSSI, &flt); hci_filter_set_event(EVT_INQUIRY_COMPLETE, &flt); if (setsockopt(sock, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) { perror("Can't set HCI filter"); return 1; } memset(&cp, 0, sizeof(cp)); cp.mode = 0x01; //cp.mode = 0x00; if (hci_send_cmd(sock, OGF_HOST_CTL, OCF_WRITE_INQUIRY_MODE,WRITE_INQUIRY_MODE_RP_SIZE, &cp) < 0) { perror("Can't set write inquiry mode"); return 1; } return 0; }
/** * Set up the socket so that we get the message that we are interested in, and * put the device into periodic inquiry mode. */ static int start_scan(int dev_sd, int scan_length) { int opt; struct hci_filter flt; periodic_inquiry_cp info_data; periodic_inquiry_cp *info = &info_data; opt = 1; if (setsockopt(dev_sd, SOL_HCI, HCI_TIME_STAMP, &opt, sizeof(opt)) < 0) { syslog(LOG_ERR, "failed to request data timestamps: %m"); return EXIT_FAILURE; } hci_filter_clear(&flt); hci_filter_set_ptype(HCI_EVENT_PKT, &flt); hci_filter_set_event(EVT_INQUIRY_RESULT, &flt); hci_filter_set_event(EVT_INQUIRY_RESULT_WITH_RSSI, &flt); hci_filter_set_event(EVT_INQUIRY_COMPLETE, &flt); if (setsockopt(dev_sd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) { syslog(LOG_ERR, "failed to set hci filter: %m"); return EXIT_FAILURE; } /* no limit on number of responses per scan */ info->num_rsp = 0x00; /* use the global inquiry access code (GIAC), which has 0x338b9e as its lower * address part (LAP) */ info->lap[0] = 0x33; info->lap[1] = 0x8b; info->lap[2] = 0x9e; /* note: according to [BTSPEC, volume 2, section 7.1.3], we must have * max_period > min_period > length * so we set these values to give us the shortest random delay between scans * that is permitted by the specification */ info->length = scan_length; info->min_period = info->length + 1; info->max_period = info->min_period + 1; if (hci_send_cmd(dev_sd, OGF_LINK_CTL, OCF_PERIODIC_INQUIRY, PERIODIC_INQUIRY_CP_SIZE, info) < 0) { syslog(LOG_ERR, "failed to request periodic inquiry: %m"); return EXIT_FAILURE; } return EXIT_SUCCESS; }
/* * Returns true if \a event was successfully enabled */ bool HciManager::monitorEvent(HciManager::HciEvent event) { if (!isValid()) return false; // this event is already enabled // TODO runningEvents does not seem to be used if (runningEvents.contains(event)) return true; hci_filter filter; socklen_t length = sizeof(hci_filter); if (getsockopt(hciSocket, SOL_HCI, HCI_FILTER, &filter, &length) < 0) { qCWarning(QT_BT_BLUEZ) << "Cannot retrieve HCI filter settings"; return false; } hci_filter_set_ptype(HCI_EVENT_PKT, &filter); hci_filter_set_event(event, &filter); //hci_filter_all_events(&filter); if (setsockopt(hciSocket, SOL_HCI, HCI_FILTER, &filter, sizeof(hci_filter)) < 0) { qCWarning(QT_BT_BLUEZ) << "Could not set HCI socket options:" << strerror(errno); return false; } return true; }
VALUE method_scan(int argc, VALUE *argv, VALUE klass) { VALUE rb_device_id; int device_id; int device_handle; uint8_t scan_type = 0x01; //passive uint8_t own_type = 0x00; // I think this specifies not to use a random MAC uint8_t filter_dups = 0x00; uint8_t filter_policy = 0x00; // ? uint16_t interval = htobs(0x0005); uint16_t window = htobs(0x0005); struct hci_filter new_filter; socklen_t filter_size; // which device was specified? rb_scan_args(argc, argv, "01", &rb_device_id); if (rb_device_id == Qnil) { device_id = hci_get_route(NULL); } else { device_id = NUM2INT(rb_device_id); } // open the device if ( (device_handle = hci_open_dev(device_id)) < 0) { rb_raise(rb_eException, "Could not open device"); } device_handles[device_id] = device_handle; // save the old filter so we can restore it later filter_size = sizeof(stored_filters[0]); if (getsockopt(device_handle, SOL_HCI, HCI_FILTER, &stored_filters[device_id], &filter_size) < 0) { rb_raise(rb_eException, "Could not get socket options"); } // new filter to only look for event packets hci_filter_clear(&new_filter); hci_filter_set_ptype(HCI_EVENT_PKT, &new_filter); hci_filter_set_event(EVT_LE_META_EVENT, &new_filter); if (setsockopt(device_handle, SOL_HCI, HCI_FILTER, &new_filter, sizeof(new_filter)) < 0) { rb_raise(rb_eException, "Could not set socket options"); } // set the params hci_le_set_scan_parameters(device_handle, scan_type, interval, window, own_type, filter_policy, 1000); hci_le_set_scan_enable(device_handle, 0x01, filter_dups, 1000); // perform the scan and make sure device gets put back into a proper state // even in the case of being interrupted by a ruby exception rb_ensure(perform_scan, INT2FIX(device_id), stop_scan, INT2FIX(device_id)); return Qnil; }
static int open_stack_internal(void) { struct sockaddr_hci addr; struct hci_filter flt; int fd, opt = 1; fd = socket(AF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC, BTPROTO_HCI); if (fd < 0) { perror("Failed to open channel"); return -1; } /* Setup filter */ hci_filter_clear(&flt); hci_filter_set_ptype(HCI_EVENT_PKT, &flt); hci_filter_set_event(EVT_STACK_INTERNAL, &flt); if (setsockopt(fd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) { perror("Failed to set HCI filter"); close(fd); return -1; } if (setsockopt(fd, SOL_HCI, HCI_TIME_STAMP, &opt, sizeof(opt)) < 0) { perror("Failed to enable HCI time stamps"); close(fd); return -1; } memset(&addr, 0, sizeof(addr)); addr.hci_family = AF_BLUETOOTH; addr.hci_dev = HCI_DEV_NONE; addr.hci_channel = HCI_CHANNEL_RAW; if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { perror("Failed to bind channel"); close(fd); return -1; } device_list(fd, HCI_MAX_DEV); return fd; }
CBlueZStack::CBlueZStack(): CGenericBluetoothStack(), m_fd(-1) { if (g_devId < 0) { // retrieve local bluetooth address from environment variable const char *addr = getenv("JSR82BTADDR"); if (addr != NULL) { g_devId = hci_devid(addr); } else { g_devId = hci_get_route(NULL); } if (g_devId < 0) { return; } hci_dev_info di; hci_devinfo(g_devId, &di); } m_fd = hci_open_dev(g_devId); if (m_fd < 0) { return; } fcntl(m_fd, F_SETFL, O_NONBLOCK); hci_filter flt; hci_filter_clear(&flt); hci_filter_set_ptype(HCI_EVENT_PKT, &flt); hci_filter_set_event(EVT_CMD_COMPLETE, &flt); hci_filter_set_event(EVT_CMD_STATUS, &flt); hci_filter_set_event(EVT_INQUIRY_COMPLETE, &flt); hci_filter_set_event(EVT_INQUIRY_RESULT, &flt); hci_filter_set_event(EVT_INQUIRY_RESULT, &flt); hci_filter_set_event(EVT_REMOTE_NAME_REQ_COMPLETE, &flt); hci_filter_set_event(EVT_AUTH_COMPLETE, &flt); hci_filter_set_event(EVT_ENCRYPT_CHANGE, &flt); if (setsockopt(m_fd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) { return; } m_poll.fd = m_fd; m_poll.events = POLLIN | POLLHUP | POLLERR; m_poll.revents = 0; m_bInitialized = true; }
void start_hci_scan(struct hci_state current_hci_state) { if(hci_le_set_scan_parameters(current_hci_state.device_handle, 0x01, htobs(0x0010), htobs(0x0010), 0x00, 0x00, 1000) < 0) { current_hci_state.has_error = TRUE; snprintf(current_hci_state.error_message, sizeof(current_hci_state.error_message), "Failed to set scan parameters: %s", strerror(errno)); return; } if(hci_le_set_scan_enable(current_hci_state.device_handle, 0x01, 1, 1000) < 0) { current_hci_state.has_error = TRUE; snprintf(current_hci_state.error_message, sizeof(current_hci_state.error_message), "Failed to enable scan: %s", strerror(errno)); return; } current_hci_state.state = HCI_STATE_SCANNING; // Save the current HCI filter socklen_t olen = sizeof(current_hci_state.original_filter); if(getsockopt(current_hci_state.device_handle, SOL_HCI, HCI_FILTER, ¤t_hci_state.original_filter, &olen) < 0) { current_hci_state.has_error = TRUE; snprintf(current_hci_state.error_message, sizeof(current_hci_state.error_message), "Could not get socket options: %s", strerror(errno)); return; } // Create and set the new filter struct hci_filter new_filter; hci_filter_clear(&new_filter); hci_filter_set_ptype(HCI_EVENT_PKT, &new_filter); hci_filter_set_event(EVT_LE_META_EVENT, &new_filter); if(setsockopt(current_hci_state.device_handle, SOL_HCI, HCI_FILTER, &new_filter, sizeof(new_filter)) < 0) { current_hci_state.has_error = TRUE; snprintf(current_hci_state.error_message, sizeof(current_hci_state.error_message), "Could not set socket options: %s", strerror(errno)); return; } current_hci_state.state = HCI_STATE_FILTERING; }
static int print_advertising_devices(int dd, uint8_t filter_type) { unsigned char buf[HCI_MAX_EVENT_SIZE], *ptr; struct hci_filter nf, of; struct sigaction sa; socklen_t olen; int len; int8_t rssi; olen = sizeof(of); if (getsockopt(dd, SOL_HCI, HCI_FILTER, &of, &olen) < 0) { printf("Could not get socket options\n"); return -1; } hci_filter_clear(&nf); hci_filter_set_ptype(HCI_EVENT_PKT, &nf); hci_filter_set_event(EVT_LE_META_EVENT, &nf); if (setsockopt(dd, SOL_HCI, HCI_FILTER, &nf, sizeof(nf)) < 0) { printf("Could not set socket options\n"); return -1; } memset(&sa, 0, sizeof(sa)); sa.sa_flags = SA_NOCLDSTOP; sa.sa_handler = sigint_handler; sigaction(SIGINT, &sa, NULL); while (1) { evt_le_meta_event *meta; le_advertising_info *info; char addr[18]; while ((len = read(dd, buf, sizeof(buf))) < 0) { if (errno == EINTR && signal_received == SIGINT) { len = 0; goto done; } if (errno == EAGAIN || errno == EINTR) continue; goto done; } ptr = buf + (1 + HCI_EVENT_HDR_SIZE); len -= (1 + HCI_EVENT_HDR_SIZE); meta = (void *) ptr; if (meta->subevent != 0x02) goto done; /* Ignoring multiple reports */ info = (le_advertising_info *) (meta->data + 1); if (check_report_filter(filter_type, info)) { // Jeff's comment // typedef struct { // uint8_t evt_type; // uint8_t bdaddr_type; // bdaddr_t bdaddr; // uint8_t length; // uint8_t data[0]; // } __attribute__ ((packed)) le_advertising_info; char name[30]; memset(name, 0, sizeof(name)); ba2str(&info->bdaddr, addr); eir_parse_name(info->data, info->length, name, sizeof(name) - 1); rssi = *(info->data + info->length); printf("%s %s %d\n", addr, name, rssi); fflush(stdout); // see: http://stackoverflow.com/questions/20503671/python-c-program-subprocess-hangs-at-for-line-in-iter } } done: setsockopt(dd, SOL_HCI, HCI_FILTER, &of, sizeof(of)); if (len < 0) return -1; return 0; }
static int hciops_setup(void) { struct sockaddr_hci addr; struct hci_filter flt; GIOChannel *ctl_io, *child_io; int sock, err; if (child_pipe[0] != -1) return -EALREADY; if (pipe(child_pipe) < 0) { err = errno; error("pipe(): %s (%d)", strerror(err), err); return -err; } child_io = g_io_channel_unix_new(child_pipe[0]); g_io_channel_set_close_on_unref(child_io, TRUE); child_io_id = g_io_add_watch(child_io, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, child_exit, NULL); g_io_channel_unref(child_io); /* Create and bind HCI socket */ sock = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); if (sock < 0) { err = errno; error("Can't open HCI socket: %s (%d)", strerror(err), err); return -err; } /* Set filter */ hci_filter_clear(&flt); hci_filter_set_ptype(HCI_EVENT_PKT, &flt); hci_filter_set_event(EVT_STACK_INTERNAL, &flt); if (setsockopt(sock, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) { err = errno; error("Can't set filter: %s (%d)", strerror(err), err); return -err; } memset(&addr, 0, sizeof(addr)); addr.hci_family = AF_BLUETOOTH; addr.hci_dev = HCI_DEV_NONE; if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { err = errno; error("Can't bind HCI socket: %s (%d)", strerror(err), err); return -err; } ctl_io = g_io_channel_unix_new(sock); g_io_channel_set_close_on_unref(ctl_io, TRUE); ctl_io_id = g_io_add_watch(ctl_io, G_IO_IN, io_stack_event, NULL); g_io_channel_unref(ctl_io); /* Initialize already connected devices */ return init_known_adapters(sock); }
int main(int argc, const char* argv[]) { char *hciDeviceIdOverride = NULL; int hciDeviceId = 0; int hciSocket; struct hci_dev_info hciDevInfo; struct hci_filter oldHciFilter; struct hci_filter newHciFilter; socklen_t oldHciFilterLen; int previousAdapterState = -1; int currentAdapterState; const char* adapterState = NULL; fd_set rfds; struct timeval tv; int selectRetval; unsigned char hciEventBuf[HCI_MAX_EVENT_SIZE]; int hciEventLen; evt_le_meta_event *leMetaEvent; le_advertising_info *leAdvertisingInfo; char btAddress[18]; int i; int scanning = 0; int8_t rssi; memset(&hciDevInfo, 0x00, sizeof(hciDevInfo)); // setup signal handlers signal(SIGINT, signalHandler); signal(SIGKILL, signalHandler); signal(SIGUSR1, signalHandler); signal(SIGUSR2, signalHandler); signal(SIGHUP, signalHandler); prctl(PR_SET_PDEATHSIG, SIGKILL); // remove buffering setbuf(stdin, NULL); setbuf(stdout, NULL); setbuf(stderr, NULL); hciDeviceIdOverride = getenv("NOBLE_HCI_DEVICE_ID"); if (hciDeviceIdOverride != NULL) { hciDeviceId = atoi(hciDeviceIdOverride); } else { // if no env variable given, use the first available device hciDeviceId = hci_get_route(NULL); } if (hciDeviceId < 0) { hciDeviceId = 0; // use device 0, if device id is invalid } // setup HCI socket hciSocket = hci_open_dev(hciDeviceId); if (hciSocket == -1) { printf("adapterState unsupported\n"); return -1; } hciDevInfo.dev_id = hciDeviceId; // get old HCI filter oldHciFilterLen = sizeof(oldHciFilter); getsockopt(hciSocket, SOL_HCI, HCI_FILTER, &oldHciFilter, &oldHciFilterLen); // setup new HCI filter hci_filter_clear(&newHciFilter); hci_filter_set_ptype(HCI_EVENT_PKT, &newHciFilter); hci_filter_set_event(EVT_LE_META_EVENT, &newHciFilter); setsockopt(hciSocket, SOL_HCI, HCI_FILTER, &newHciFilter, sizeof(newHciFilter)); while(1) { FD_ZERO(&rfds); FD_SET(hciSocket, &rfds); tv.tv_sec = 1; tv.tv_usec = 0; // get HCI dev info for adapter state ioctl(hciSocket, HCIGETDEVINFO, (void *)&hciDevInfo); currentAdapterState = hci_test_bit(HCI_UP, &hciDevInfo.flags); if (previousAdapterState != currentAdapterState) { previousAdapterState = currentAdapterState; if (!currentAdapterState) { adapterState = "poweredOff"; } else if (hci_le_set_scan_parameters(hciSocket, 0x01, htobs(0x0010), htobs(0x0010), 0x00, 0, 1000) < 0) { if (EPERM == errno) { adapterState = "unauthorized"; } else if (EIO == errno) { adapterState = "unsupported"; } else { adapterState = "unknown"; } } else { adapterState = "poweredOn"; } printf("adapterState %s\n", adapterState); } selectRetval = select(hciSocket + 1, &rfds, NULL, NULL, &tv); if (-1 == selectRetval) { if (SIGINT == lastSignal || SIGKILL == lastSignal) { // done break; } else if (SIGUSR1 == lastSignal) { // start scan, filter scanning = 1; hci_le_set_scan_enable(hciSocket, 0x00, 1, 1000); hci_le_set_scan_enable(hciSocket, 0x01, 1, 1000); } else if (SIGUSR2 == lastSignal) { // start scan, no filter scanning = 1; hci_le_set_scan_enable(hciSocket, 0x00, 0, 1000); hci_le_set_scan_enable(hciSocket, 0x01, 0, 1000); } else if (SIGHUP == lastSignal) { // stop scan scanning = 0; hci_le_set_scan_enable(hciSocket, 0x00, 0, 1000); } } else if (selectRetval) { // read event hciEventLen = read(hciSocket, hciEventBuf, sizeof(hciEventBuf)); leMetaEvent = (evt_le_meta_event *)(hciEventBuf + (1 + HCI_EVENT_HDR_SIZE)); hciEventLen -= (1 + HCI_EVENT_HDR_SIZE); if (!scanning) { // ignore, not scanning continue; } if (leMetaEvent->subevent != 0x02) { continue; } leAdvertisingInfo = (le_advertising_info *)(leMetaEvent->data + 1); ba2str(&leAdvertisingInfo->bdaddr, btAddress); printf("event %s,%s,", btAddress, (leAdvertisingInfo->bdaddr_type == LE_PUBLIC_ADDRESS) ? "public" : "random"); for (i = 0; i < leAdvertisingInfo->length; i++) { printf("%02x", leAdvertisingInfo->data[i]); } rssi = *(leAdvertisingInfo->data + leAdvertisingInfo->length); printf(",%d\n", rssi); } } // restore original filter setsockopt(hciSocket, SOL_HCI, HCI_FILTER, &oldHciFilter, sizeof(oldHciFilter)); // disable LE scan hci_le_set_scan_enable(hciSocket, 0x00, 0, 1000); close(hciSocket); return 0; }
int main(int argc, char *argv[]) { struct sigaction sa; struct hci_dev_info di; struct hci_version ver; struct hci_filter flt; bdaddr_t bdaddr, master, slave; int need_raw; int dd, opt, dev = 0; bacpy(&slave, BDADDR_ANY); while ((opt=getopt_long(argc, argv, "+i:h", main_options, NULL)) != -1) { switch (opt) { case 'i': dev = hci_devid(optarg); if (dev < 0) { perror("Invalid device"); exit(1); } break; case 'h': default: usage(); exit(0); } } argc -= optind; argv += optind; optind = 0; if (argc < 1) { usage(); exit(1); } str2ba(argv[0], &master); if (argc > 1) str2ba(argv[1], &slave); dd = hci_open_dev(dev); if (dd < 0) { fprintf(stderr, "Can't open device hci%d: %s (%d)\n", dev, strerror(errno), errno); exit(1); } if (hci_devinfo(dev, &di) < 0) { fprintf(stderr, "Can't get device info for hci%d: %s (%d)\n", dev, strerror(errno), errno); hci_close_dev(dd); exit(1); } if (hci_read_local_version(dd, &ver, 1000) < 0) { fprintf(stderr, "Can't read version for hci%d: %s (%d)\n", dev, strerror(errno), errno); hci_close_dev(dd); exit(1); } if (ver.manufacturer != 10 || id2ver(ver.hci_rev) < 0) { fprintf(stderr, "Can't find sniffer at hci%d: %s (%d)\n", dev, strerror(ENOSYS), ENOSYS); hci_close_dev(dd); exit(1); } if (!bacmp(&di.bdaddr, BDADDR_ANY)) { if (hci_read_bd_addr(dd, &bdaddr, 1000) < 0) { fprintf(stderr, "Can't read address for hci%d: %s (%d)\n", dev, strerror(errno), errno); hci_close_dev(dd); exit(1); } } else bacpy(&bdaddr, &di.bdaddr); need_raw = !hci_test_bit(HCI_RAW, &di.flags); hci_filter_clear(&flt); hci_filter_set_ptype(HCI_ACLDATA_PKT, &flt); hci_filter_set_ptype(HCI_EVENT_PKT, &flt); hci_filter_set_event(EVT_VENDOR, &flt); if (setsockopt(dd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) { fprintf(stderr, "Can't set filter for hci%d: %s (%d)\n", dev, strerror(errno), errno); hci_close_dev(dd); exit(1); } memset(&sa, 0, sizeof(sa)); sa.sa_flags = SA_NOCLDSTOP; sa.sa_handler = SIG_IGN; sigaction(SIGCHLD, &sa, NULL); sigaction(SIGPIPE, &sa, NULL); sa.sa_handler = sig_term; sigaction(SIGTERM, &sa, NULL); sigaction(SIGINT, &sa, NULL); sa.sa_handler = sig_hup; sigaction(SIGHUP, &sa, NULL); if (need_raw) { if (ioctl(dd, HCISETRAW, 1) < 0) { fprintf(stderr, "Can't set raw mode on hci%d: %s (%d)\n", dev, strerror(errno), errno); hci_close_dev(dd); exit(1); } } printf("CSR sniffer - Bluetooth packet analyzer ver %s\n", VERSION); if (need_raw) { if (ioctl(dd, HCISETRAW, 0) < 0) fprintf(stderr, "Can't clear raw mode on hci%d: %s (%d)\n", dev, strerror(errno), errno); } hci_close_dev(dd); return 0; }
static int ble_scan(int device_desc, ble_discovered_device_t discovered_device_cb, int timeout) { struct hci_filter old_options; socklen_t slen = sizeof(old_options); struct hci_filter new_options; int len; unsigned char buffer[HCI_MAX_EVENT_SIZE]; evt_le_meta_event* meta = (evt_le_meta_event*)(buffer + HCI_EVENT_HDR_SIZE + 1); le_advertising_info* info; struct timeval wait; fd_set read_set; char addr[18]; if (getsockopt(device_desc, SOL_HCI, HCI_FILTER, &old_options, &slen) < 0) { fprintf(stderr, "ERROR: Could not get socket options.\n"); return 1; } hci_filter_clear(&new_options); hci_filter_set_ptype(HCI_EVENT_PKT, &new_options); hci_filter_set_event(EVT_LE_META_EVENT, &new_options); if (setsockopt(device_desc, SOL_HCI, HCI_FILTER, &new_options, sizeof(new_options)) < 0) { fprintf(stderr, "ERROR: Could not set socket options.\n"); return 1; } wait.tv_sec = timeout; int ts = time(NULL); while(1) { FD_ZERO(&read_set); FD_SET(device_desc, &read_set); int err = select(FD_SETSIZE, &read_set, NULL, NULL, &wait); if (err <= 0) break; len = read(device_desc, buffer, sizeof(buffer)); if (meta->subevent != 0x02 || (uint8_t)buffer[BLE_EVENT_TYPE] != BLE_SCAN_RESPONSE) continue; info = (le_advertising_info*) (meta->data + 1); ba2str(&info->bdaddr, addr); char* name = parse_name(info->data, info->length); discovered_device_cb(addr, name); if (name) { free(name); } int elapsed = time(NULL) - ts; if (elapsed >= timeout) break; wait.tv_sec = timeout - elapsed; } setsockopt(device_desc, SOL_HCI, HCI_FILTER, &old_options, sizeof(old_options)); return 0; }
static int print_advertising_devices(int dd, uint8_t filter_type) { unsigned char buf[HCI_MAX_EVENT_SIZE], *ptr; struct hci_filter nf, of; struct sigaction sa; socklen_t olen; int len; olen = sizeof(of); if (getsockopt(dd, SOL_HCI, HCI_FILTER, &of, &olen) < 0) { printf("Could not get socket options\n"); return -1; } hci_filter_clear(&nf); hci_filter_set_ptype(HCI_EVENT_PKT, &nf); hci_filter_set_event(EVT_LE_META_EVENT, &nf); if (setsockopt(dd, SOL_HCI, HCI_FILTER, &nf, sizeof(nf)) < 0) { printf("Could not set socket options\n"); return -1; } memset(&sa, 0, sizeof(sa)); sa.sa_flags = SA_NOCLDSTOP; sa.sa_handler = sigint_handler; sigaction(SIGINT, &sa, NULL); while (1) { evt_le_meta_event *meta; le_advertising_info *info; char addr[18]; while ((len = read(dd, buf, sizeof(buf))) < 0) { if (errno == EINTR && signal_received == SIGINT) { len = 0; goto done; } if (errno == EAGAIN || errno == EINTR) continue; goto done; } ptr = buf + (1 + HCI_EVENT_HDR_SIZE); len -= (1 + HCI_EVENT_HDR_SIZE); meta = (void *) ptr; if (meta->subevent != 0x02) goto done; /* Ignoring multiple reports */ info = (le_advertising_info *) (meta->data + 1); if (check_report_filter(filter_type, info)) { char name[30]; char uuid[16*2 + 1]; memset(name, 0, sizeof(name)); ba2str(&info->bdaddr, addr); eir_parse_name(info->data, info->length, name, sizeof(name) - 1); eir_parse_uuid(info->data, info->length, uuid, sizeof(uuid) - 1); printf("%s %s %s\n", addr, name, uuid); } } done: setsockopt(dd, SOL_HCI, HCI_FILTER, &of, sizeof(of)); if (len < 0) return -1; return 0; }
static int cmd_lescan(int dev_id) { int hci_dev = 0; int err = 0, opt = 0, dd = 0; uint8_t own_type = 0x00; uint8_t scan_type = 0x01; uint8_t filter_type = 0; uint8_t filter_policy = 0x00; uint8_t filter_dup = 1; uint16_t interval = htobs(0x0010); uint16_t window = htobs(0x0010); if (dev_id < 0) { dev_id = hci_get_route(NULL); } if (dev_id < 0) { return -1; } if((hci_dev = hci_open_dev(dev_id)) < 0) { printf("Opening hci device failed\n"); return -2; } err = hci_le_set_scan_parameters(hci_dev, scan_type, interval, window, own_type, filter_policy, 2000); if (err < 0) { printf("Setting scan parameters failed %d\n", err); return -3; } err = hci_le_set_scan_enable(hci_dev, 0x01, filter_dup, 1000); if (err < 0) { printf("Enabling the scan failed\n"); return -4; } struct sigaction sa; sa.sa_flags = SA_NOCLDSTOP; sa.sa_handler = signal_handler; sigaction(SIGINT, &sa, NULL); unsigned char buf[HCI_MAX_EVENT_SIZE], *ptr; int len, sl_no = 0; socklen_t olen = sizeof(old_filter); if (getsockopt(hci_dev, SOL_HCI, HCI_FILTER, &old_filter, &olen) < 0) { printf("getsockopt failed\n"); btcmd_stop_scanning(hci_dev); return -5; } struct hci_filter filter; hci_filter_clear(&filter); hci_filter_set_ptype(HCI_EVENT_PKT, &filter); hci_filter_set_event(EVT_LE_META_EVENT, &filter); if (setsockopt(hci_dev, SOL_HCI, HCI_FILTER, &filter, sizeof(filter)) < 0) { printf("setsockopt failed\n"); btcmd_stop_scanning(hci_dev); return -6; } finish_scanning = 0; while(1) { le_advertising_info *info; evt_le_meta_event *meta; char addr[20]; while ((len = read(hci_dev, buf, sizeof(buf))) < 0) { set_state(STATE_SCANNING); if (errno == EINTR && finish_scanning) { len = 0; goto done; } if (errno == EAGAIN) { continue; } /* anything else, just end the loop */ goto done; } ptr = buf + (1 + HCI_EVENT_HDR_SIZE); len -= (1 + HCI_EVENT_HDR_SIZE); meta = (void *) ptr; if (meta->subevent != 0x02) { goto done; } info = (le_advertising_info *) (meta->data + 1); memset(addr, 0, sizeof(addr)); address2string(&info->bdaddr, addr); /* Socket gives same BT address twice, and we need to eliminate * duplicate entries */ static int duplicate = 0; if (duplicate == 0) { printf("%s\n", addr); duplicate = 1; } else if (duplicate) { duplicate = 0; } } /* while (1) */ done: btcmd_stop_scanning(hci_dev); set_state(STATE_DISCONNECTED); return 0; }