Advertisement
Guest User

bluez dbus

a guest
Jul 12th, 2016
1,888
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.41 KB | None | 0 0
  1. #include <iostream>
  2. #include <chrono>
  3. #include <thread>
  4. #include <unistd.h>
  5.  
  6. #include <bluetooth/hci.h>
  7. #include <bluetooth/hci_lib.h>
  8. #include <bluetooth/bluetooth.h>
  9.  
  10. #include <glib.h>
  11. #include <gio/gio.h>
  12.  
  13. using namespace std;
  14.  
  15. const u_char LE_ADV_REPORT = 0x02;
  16.  
  17. //based on hcitool lescan
  18. bool receiveAdv(int dd, std::chrono::seconds timeout)
  19. {
  20.     u_char buff[HCI_MAX_EVENT_SIZE];
  21.     u_char *ptr;
  22.     hci_filter filter;
  23.  
  24.     hci_filter_clear(&filter);
  25.     hci_filter_set_ptype(HCI_EVENT_PKT, &filter);
  26.     hci_filter_set_event(EVT_LE_META_EVENT, &filter);
  27.  
  28.     if (setsockopt(dd, SOL_HCI, HCI_FILTER, &filter, sizeof(filter)) < 0) {
  29.         printf("Could not set socket options\n");
  30.         return false;
  31.     }
  32.  
  33.     using namespace std::chrono;
  34.     time_point<steady_clock> start = steady_clock::now();
  35.     while (steady_clock::now() - start < timeout) {
  36.         if (read(dd, buff, sizeof(buff)) < 0) {
  37.             std::this_thread::sleep_for(milliseconds(20));
  38.             continue;
  39.         }
  40.  
  41.         ptr = buff + (1 + HCI_EVENT_HDR_SIZE);
  42.         evt_le_meta_event *meta = reinterpret_cast<evt_le_meta_event *>(ptr);
  43.  
  44.         if (meta->subevent != LE_ADV_REPORT)
  45.             continue;
  46.  
  47.         le_advertising_info *info = reinterpret_cast<le_advertising_info *>(meta->data + 1);
  48.         char addr[18];
  49.         ba2str(&info->bdaddr, addr);
  50.         int rssi = info->data[info->length]; //intentional, isn't out of bounds
  51.         cout << "Detected device: " << addr << " " << rssi << endl;
  52.     }
  53.  
  54.     return true;
  55. }
  56.  
  57. bool scan(unsigned timeout)
  58. {
  59.     int devId = hci_get_route(nullptr);
  60.     int dd = hci_open_dev(devId);
  61.     if (devId < 0 || dd < 0) {
  62.         cerr << "Could not open device\n";
  63.         return false;
  64.     }
  65.  
  66.     uint8_t localAddr = LE_PUBLIC_ADDRESS; //LE_PUBLIC_ADDRESS to use public on local device, LE_RANDOM_ADDRESS to use random
  67.     uint8_t scanType = 0x01; //0x01 = active, 0x00 = passive
  68.     uint8_t filterPolicy = 0x00; //0x00 = don't use whitelist, 0x01 = use whitelist
  69.     uint16_t interval = htobs(0x0010); //no idea, default for all except 'g' or 'l' filters that use htobs(0x0012)
  70.     uint16_t window = htobs(0x0010); //no idea, default for all except 'g' or 'l' filters that use htobs(0x0012)
  71.     uint8_t filterDup = 0x00; // 0x01 = filter duplicates, 0x00 = receive duplicates
  72.     int hciTimeout = 10000; // this is timeout for communication with the local adapter, not scanning
  73.  
  74.     if (hci_le_set_scan_parameters(dd, scanType, interval, window, localAddr, filterPolicy, hciTimeout) < 0) {
  75.         cerr << "Set scan parameters failed\n";
  76.         hci_close_dev(dd);
  77.         return false;
  78.     }
  79.  
  80.     uint8_t scanEnable = 0x01;
  81.     if (hci_le_set_scan_enable(dd, scanEnable, filterDup, hciTimeout) < 0) {
  82.         cerr << "Enable scan failed\n";
  83.         hci_close_dev(dd);
  84.         return false;
  85.     }
  86.  
  87.     if (receiveAdv(dd, std::chrono::seconds(timeout)) < 0) {
  88.         cerr << "Could not receive advertising events\n";
  89.         hci_close_dev(dd);
  90.         return false;
  91.     }
  92.  
  93.     hci_close_dev(dd);
  94.     return true;
  95. }
  96.  
  97. GDBusProxy *connect(const char *addr)
  98. {
  99.     GError *err = nullptr;
  100.     char objPath[sizeof("/org/bluez/hci0/dev_DA_06_9E_3A_E2_5C")] = "/org/bluez/hci0/dev_DA_06_9E_3A_E2_5C";
  101.     GDBusProxy *devProxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, nullptr, "org.bluez", objPath, "org.bluez.Device1", nullptr, &err);
  102.  
  103.     if (!devProxy) {
  104.         cerr << "Device " << addr << " not available:" << err->message << endl;
  105.         g_clear_error(&err);
  106.         return nullptr;
  107.     }
  108.     if (!g_dbus_proxy_call_sync(devProxy, "Connect", nullptr, G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &err)) {
  109.         cerr << "Failed to connect: " << err->message << "(" << err->code << ")\n";
  110.         g_clear_error(&err);
  111.         if (!g_dbus_proxy_call_sync(devProxy, "Pair", nullptr, G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &err)) {
  112.             cerr << "Failed to connect: " << err->message << "(" << err->code << ")\n";
  113.             g_clear_error(&err);
  114.             return nullptr;
  115.         }
  116.     }
  117.     return devProxy;
  118. }
  119.  
  120. bool disconnect(GDBusProxy *devProxy)
  121. {
  122.     GError *err = nullptr;
  123.     if (!g_dbus_proxy_call_sync(devProxy, "Disconnect", nullptr, G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &err)) {
  124.         cerr << "Failed to disconnect - " << err->message << "(" << err->code << ")\n";
  125.         g_clear_error(&err);
  126.         return false;
  127.     }
  128.     return true;
  129. }
  130.  
  131. GVariant *read()
  132. {
  133.     const char *objPath("/org/bluez/hci0/dev_DA_06_9E_3A_E2_5C/service0013/char0014");
  134.  
  135.     GVariantBuilder *b = g_variant_builder_new(G_VARIANT_TYPE("({sv})"));
  136.     g_variant_builder_add (b, "{sv}", "offset", g_variant_new_uint16(0));
  137.     GVariant *args = g_variant_builder_end(b);
  138.  
  139.     GError *err = nullptr;
  140.     GDBusProxy *charProxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, nullptr, "org.bluez", objPath, "org.bluez.GattCharacteristic1", nullptr, &err);
  141.     GVariant *ret = g_dbus_proxy_call_sync(charProxy, "ReadValue", args, G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &err);
  142.     if (ret == FALSE) {
  143.         cerr << "Failed to read - " << err->message << "(" << err->code << ")\n";
  144.         g_clear_error(&err);
  145.         return nullptr;
  146.     }
  147.  
  148.     return ret;
  149. }
  150.  
  151. int main()
  152. {
  153.     scan(3);
  154.     GDBusProxy *proxy = connect("DA:06:9E:3A:E2:5C");
  155.     GVariant *ret = read();
  156.     disconnect(proxy);
  157.     return 0;
  158. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement