VALUE method_stop_advertising(VALUE klass, VALUE rb_device_id) { int device_id = FIX2INT(rb_device_id); int device_handle = hci_open_dev(device_id); hci_le_set_advertise_enable(device_handle, 0x00, 1000); hci_close_dev(device_handle); return Qnil; }
int main(int argc, const char* argv[]) { char *hciDeviceIdOverride = NULL; int hciDeviceId = 0; int hciSocket; struct hci_dev_info hciDevInfo; char address[18]; int previousAdapterState = -1; int currentAdapterState; const char* adapterState = NULL; fd_set rfds; struct timeval tv; int selectRetval; char stdinBuf[256 * 2 + 1]; char advertisementDataBuf[256]; int advertisementDataLen = 0; char scanDataBuf[256]; int scanDataLen = 0; int len; int i; memset(&hciDevInfo, 0x00, sizeof(hciDevInfo)); // remove buffering setbuf(stdin, NULL); setbuf(stdout, NULL); setbuf(stderr, NULL); // setup signal handlers signal(SIGINT, signalHandler); signal(SIGKILL, signalHandler); signal(SIGHUP, signalHandler); signal(SIGUSR1, signalHandler); prctl(PR_SET_PDEATHSIG, SIGKILL); hciDeviceIdOverride = getenv("BLENO_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); hciDevInfo.dev_id = hciDeviceId; if (hciSocket == -1) { printf("adapterState unsupported\n"); return -1; } while(1) { FD_ZERO(&rfds); FD_SET(0, &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 { hci_le_set_advertise_enable(hciSocket, 0, 1000); hci_le_set_advertise_enable(hciSocket, 1, 1000); if (hci_le_set_advertise_enable(hciSocket, 0, 1000) == -1) { if (EPERM == errno) { adapterState = "unauthorized"; } else if (EIO == errno) { adapterState = "unsupported"; } else { printf("%d\n", errno); adapterState = "unknown"; } } else { adapterState = "poweredOn"; } } ba2str(&hciDevInfo.bdaddr, address); printf("address %s\n", address); 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 (SIGHUP == lastSignal) { // stop advertising hci_le_set_advertise_enable(hciSocket, 0, 1000); } else if (SIGUSR1 == lastSignal) { // stop advertising hci_le_set_advertise_enable(hciSocket, 0, 1000); // set scan data hci_le_set_scan_response_data(hciSocket, (uint8_t*)&scanDataBuf, scanDataLen, 1000); // set advertisement data hci_le_set_advertising_data(hciSocket, (uint8_t*)&advertisementDataBuf, advertisementDataLen, 1000); // set advertisement parameters, mostly to set the advertising interval to 100ms hci_le_set_advertising_parameters(hciSocket, 1000); // start advertising hci_le_set_advertise_enable(hciSocket, 1, 1000); // set scan data hci_le_set_scan_response_data(hciSocket, (uint8_t*)&scanDataBuf, scanDataLen, 1000); // set advertisement data hci_le_set_advertising_data(hciSocket, (uint8_t*)&advertisementDataBuf, advertisementDataLen, 1000); } } else if (selectRetval) { if (FD_ISSET(0, &rfds)) { len = readLine(0, stdinBuf, sizeof(stdinBuf)); if (len <= 0) { break; } i = 0; advertisementDataLen = 0; while(i < len && stdinBuf[i] != ' ') { unsigned int data = 0; sscanf(&stdinBuf[i], "%02x", &data); advertisementDataBuf[advertisementDataLen] = data; advertisementDataLen++; i += 2; } i++; scanDataLen = 0; while(i < len && stdinBuf[i] != '\n') { unsigned int data = 0; sscanf(&stdinBuf[i], "%02x", &data); scanDataBuf[scanDataLen] = data; scanDataLen++; i += 2; } // stop advertising hci_le_set_advertise_enable(hciSocket, 0, 1000); // set scan data hci_le_set_scan_response_data(hciSocket, (uint8_t*)&scanDataBuf, scanDataLen, 1000); // set advertisement data hci_le_set_advertising_data(hciSocket, (uint8_t*)&advertisementDataBuf, advertisementDataLen, 1000); // set advertisement parameters, mostly to set the advertising interval to 100ms hci_le_set_advertising_parameters(hciSocket, 1000); // start advertising hci_le_set_advertise_enable(hciSocket, 1, 1000); // set scan data hci_le_set_scan_response_data(hciSocket, (uint8_t*)&scanDataBuf, scanDataLen, 1000); // set advertisement data hci_le_set_advertising_data(hciSocket, (uint8_t*)&advertisementDataBuf, advertisementDataLen, 1000); } } } // stop advertising hci_le_set_advertise_enable(hciSocket, 0, 1000); close(hciSocket); return 0; }
VALUE method_start_advertising(VALUE klass, VALUE rb_device_id, VALUE random_address) { struct hci_request rq; le_set_advertising_parameters_cp adv_params_cp; uint8_t status; int device_handle; uint16_t interval_100ms = htobs(0x00A0); // 0xA0 * 0.625ms = 100ms // open connection to the device int device_id = FIX2INT(rb_device_id); if (device_id < 0) { rb_raise(rb_eException, "Could not find device"); } device_handle = hci_open_dev(device_id); if (device_handle < 0) { rb_raise(rb_eException, "Could not open device"); } // set advertising data memset(&rq, 0, sizeof(rq)); rq.ogf = OGF_LE_CTL; rq.ocf = OCF_LE_SET_ADVERTISING_DATA; rq.cparam = &advertisements[device_id]; rq.clen = sizeof(Advertisement); rq.rparam = &status; rq.rlen = 1; hci_send_req(device_handle, &rq, 1000); // set advertising params memset(&adv_params_cp, 0, sizeof(adv_params_cp)); adv_params_cp.min_interval = interval_100ms; adv_params_cp.max_interval = interval_100ms; adv_params_cp.advtype = 0x03; // non-connectable undirected advertising adv_params_cp.chan_map = 0x07;// all 3 channels if (random_address != Qnil) { adv_params_cp.own_bdaddr_type = LE_RANDOM_ADDRESS; } memset(&rq, 0, sizeof(rq)); rq.ogf = OGF_LE_CTL; rq.ocf = OCF_LE_SET_ADVERTISING_PARAMETERS; rq.cparam = &adv_params_cp; rq.clen = LE_SET_ADVERTISING_PARAMETERS_CP_SIZE; rq.rparam = &status; rq.rlen = 1; hci_send_req(device_handle, &rq, 1000); if (random_address != Qnil) { // set random address le_set_random_address_cp random_addr_cp; str2ba(StringValuePtr(random_address), &random_addr_cp.bdaddr); memset(&rq, 0, sizeof(rq)); rq.ogf = OGF_LE_CTL; rq.ocf = OCF_LE_SET_RANDOM_ADDRESS; rq.cparam = &random_addr_cp; rq.clen = LE_SET_RANDOM_ADDRESS_CP_SIZE; rq.rparam = &status; rq.rlen = 1; hci_send_req(device_handle, &rq, 1000); } // turn on advertising hci_le_set_advertise_enable(device_handle, 0x01, 1000); // and close the connection hci_close_dev(device_handle); return Qnil; }
int main(int argc, const char* argv[]) { const char *hciDeviceIdOverride = NULL; int hciDeviceId = 0; int hciSocket; struct hci_dev_info hciDevInfo; int previousAdapterState = -1; int currentAdapterState; const char* adapterState = NULL; fd_set rfds; struct timeval tv; int selectRetval; char stdinBuf[256 * 2 + 1]; char advertisementDataBuf[256]; int advertisementDataLen = 0; char scanDataBuf[256]; int scanDataLen = 0; int len; int i; memset(&hciDevInfo, 0x00, sizeof(hciDevInfo)); // remove buffering setbuf(stdin, NULL); setbuf(stdout, NULL); setbuf(stderr, NULL); // setup signal handlers signal(SIGINT, signalHandler); signal(SIGKILL, signalHandler); signal(SIGHUP, signalHandler); signal(SIGUSR1, signalHandler); prctl(PR_SET_PDEATHSIG, SIGINT); if (argc > 1 && strlen(argv[1]) > 0) { hciDeviceIdOverride = argv[1]; } 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 } printf("hciDeviceId %d\n", hciDeviceId); // setup HCI socket hciSocket = hci_open_dev(hciDeviceId); hciDevInfo.dev_id = hciDeviceId; if (hciSocket == -1) { printf("adapterState unsupported\n"); return -1; } while(1) { FD_ZERO(&rfds); FD_SET(0, &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 { hci_le_set_advertise_enable(hciSocket, 0, 1000); hci_le_set_advertise_enable(hciSocket, 1, 1000); if (hci_le_set_advertise_enable(hciSocket, 0, 1000) == -1) { switch errno { case EPERM: adapterState = "unauthorized"; break; case EIO: adapterState = "unsupported"; break; case ETIMEDOUT: adapterState = "timedout"; break; default: printf("advertiseErrno %d\n", errno); adapterState = "unknown"; break; } } else { adapterState = "poweredOn"; } } printf("adapterState %s\n", adapterState); }