#define BLUEZ_PREFIX "org.bluez"
#define BLUEZ_SERVICE BLUEZ_PREFIX
-#define BLUEZ_MANAGER_IFACE BLUEZ_PREFIX ".Manager"
-#define BLUEZ_ADAPTER_IFACE BLUEZ_PREFIX ".Adapter"
-#define BLUEZ_DEVICE_IFACE BLUEZ_PREFIX ".Device"
-#define BLUEZ_AGENT_IFACE BLUEZ_PREFIX ".Agent"
+#define BLUEZ_ADAPTER_IFACE BLUEZ_PREFIX ".Adapter1"
+#define BLUEZ_DEVICE_IFACE BLUEZ_PREFIX ".Device1"
+#define BLUEZ_AGENT_IFACE BLUEZ_PREFIX ".Agent1"
-#define AGENT_PATH "/org/bluez/agent_poc"
+#define AGENT_PATH "/org/bluez/poc_agent"
#define AGENT_CAPABILITIES "KeyboardDisplay"
#define AGENT_PASSKEY 123456
#define AGENT_PINCODE "123456"
-#define AGENT_INTERFACE_XML \
- "<node>" \
- " <interface name='org.bluez.Agent'>" \
- " <method name='Release'>" \
- " </method>" \
- " <method name='Authorize'>" \
- " <arg type='o' name='device' direction='in'/>" \
- " <arg type='s' name='uuid' direction='in'/>" \
- " </method>" \
- " <method name='RequestPinCode'>" \
- " <arg type='o' name='device' direction='in'/>" \
- " <arg type='s' name='pincode' direction='out'/>" \
- " </method>" \
- " <method name='RequestPasskey'>" \
- " <arg type='o' name='device' direction='in'/>" \
- " <arg type='u' name='passkey' direction='out'/>" \
- " </method>" \
- " <method name='DisplayPasskey'>" \
- " <arg type='o' name='device' direction='in'/>" \
- " <arg type='u' name='passkey' direction='in'/>" \
- " </method>" \
- " <method name='DisplayPinCode'>" \
- " <arg type='o' name='device' direction='in'/>" \
- " <arg type='s' name='pincode' direction='in'/>" \
- " </method>" \
- " <method name='RequestConfirmation'>" \
- " <arg type='o' name='device' direction='in'/>" \
- " <arg type='u' name='passkey' direction='in'/>" \
- " </method>" \
- " <method name='ConfirmModeChange'>" \
- " <arg type='s' name='mode' direction='in'/>" \
- " </method>" \
- " <method name='Cancel'>" \
- " </method>" \
- " </interface>" \
- "</node>"
-
/* NOTE:
* "Release" ... does nothing
* "Authorize" ... automatically authorized
}
memset(&mAgentIfaceVTable, 0, sizeof(mAgentIfaceVTable));
- // subscribe for AdapterAdded/AdapterRemoved to get notification about the change
- Utils::setSignalListener(G_BUS_TYPE_SYSTEM, BLUEZ_SERVICE, BLUEZ_MANAGER_IFACE,
- "/", "AdapterAdded", Bluez::handleSignal,
+ // subscribe for InterfacesAdded/InterfacesRemoved to get notification about the change
+ Utils::setSignalListener(G_BUS_TYPE_SYSTEM, BLUEZ_SERVICE, "org.freedesktop.DBus.ObjectManager",
+ "/", "InterfacesAdded", Bluez::handleSignal,
this);
- Utils::setSignalListener(G_BUS_TYPE_SYSTEM, BLUEZ_SERVICE, BLUEZ_MANAGER_IFACE,
- "/", "AdapterRemoved", Bluez::handleSignal,
+ Utils::setSignalListener(G_BUS_TYPE_SYSTEM, BLUEZ_SERVICE, "org.freedesktop.DBus.ObjectManager",
+ "/", "InterfacesRemoved", Bluez::handleSignal,
this);
if(mAdapterPath) {
gchar* Bluez::getDefaultAdapter()
{
- GError *err = NULL;
- GVariant *reply = NULL;
- reply = g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL),
- BLUEZ_SERVICE,
- "/",
- BLUEZ_MANAGER_IFACE,
- "DefaultAdapter",
- NULL,
- NULL,
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- NULL,
- &err);
- if(err || !reply) {
- if(err) {
- LoggerE("Failed to get default adapter: " << err->message);
- g_error_free(err);
- }
- if(!reply)
- LoggerE("Reply from 'DefaultAdapter' is null");
- return NULL;
- }
-
- char *adapter = NULL;
- g_variant_get(reply, "(o)", &adapter);
- LoggerD("DefaultAdapter: " << adapter);
-
- // make a copy of adapter, 'cause it will be destroyed when 'reply' is un-refed
- char *result = adapter?strdup(adapter):NULL;
-
- g_variant_unref(reply);
-
- return result;
+ char *result;
+
+ GError * error = nullptr;
+ GDBusProxy * managerProxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, NULL,
+ "org.bluez",
+ "/",
+ "org.freedesktop.DBus.ObjectManager",
+ nullptr,&error);
+ if(error)
+ {
+ LoggerE("could not create ObjManager proxy");
+ // DebugOut(DebugOut::Error)<<"Could not create ObjectManager proxy for Bluez: "<<error->message<<endl;
+ g_error_free(error);
+ return "";
+ }
+
+ GVariant * objectMap = g_dbus_proxy_call_sync(managerProxy, "GetManagedObjects",nullptr, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
+
+ if(error)
+ {
+ LoggerE("failed to get GetManagedObj");
+ //DebugOut(DebugOut::Error)<<"Failed call to GetManagedObjects: "<<error->message<<endl;
+ g_object_unref(managerProxy);
+ g_error_free(error);
+ return "";
+ }
+
+ GVariantIter* iter;
+ char* objPath;
+ GVariantIter* level2Dict;
+
+ g_variant_get(objectMap, "(a{oa{sa{sv}}})",&iter);
+ while(g_variant_iter_next(iter, "{oa{sa{sv}}}",&objPath, &level2Dict))
+ {
+ char * interfaceName;
+ GVariantIter* innerDict;
+ while(g_variant_iter_next(level2Dict, "{sa{sv}}", &interfaceName, &innerDict))
+ {
+ if(!strcmp(interfaceName, "org.bluez.Adapter1"))
+ {
+ result = objPath?strdup(objPath):NULL;
+ }
+ g_free(interfaceName);
+ g_variant_iter_free(innerDict);
+ }
+ g_free(objPath);
+ g_variant_iter_free(level2Dict);
+ }
+ g_variant_iter_free(iter);
+
+ return result;
}
bool Bluez::setAdapterPowered(bool value) {
if(mAdapterPath) {
GError *err = NULL;
- g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL,NULL),
- BLUEZ_SERVICE,
- mAdapterPath,
- BLUEZ_ADAPTER_IFACE,
- "SetProperty",
- g_variant_new ("(sv)", // floating parameters are consumed, no cleanup/unref needed
- "Powered",
- g_variant_new("b", &value) // floating parameters are consumed, no cleanup/unref needed
- ),
- NULL,
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- NULL,
- &err);
+
+ g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL,NULL),
+ BLUEZ_SERVICE,
+ mAdapterPath,
+ "org.freedesktop.DBus.Properties",
+ "Set",
+ g_variant_new("(ssv)", "org.bluez.Adapter1", "Powered", g_variant_new_boolean(value)),
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &err);
if(err) {
LoggerE("Failed to call \"SetProperty\" DBUS method: " << err->message);
return;
}
- if(!strcmp(interface_name, BLUEZ_MANAGER_IFACE)) {
- if(!strcmp(signal_name, "AdapterAdded")) {
- const char *adapter = NULL;
- g_variant_get(parameters, "(o)", &adapter);
- if(adapter) {
- LoggerD("Adapter added: " << adapter);
- if(!ctx->mAdapterPath) {
- // make added adapter as default
- ctx->mAdapterPath = strdup(adapter);
- //ctx->setupAgent();
- ctx->registerAgent();
- ctx->defaultAdapterAdded();
- }
- }
+ if(!strcmp(interface_name, "org.freedesktop.DBus.ObjectManager")) {
+ if(!strcmp(signal_name, "InterfacesAdded"))
+ {
+ char *objPath = NULL;
+ GVariantIter* iter;
+
+ g_variant_get(parameters, "(oa{sa{sv}})", &objPath, &iter);
+
+ if(objPath)
+ {
+ GVariantIter* iter2;
+ char *interface = NULL;
+
+ while(g_variant_iter_next(iter, "{sa{sv}}",&interface, &iter2))
+ {
+
+ if(!strcmp(interface, "org.bluez.Adapter1"))
+ {
+ LoggerD("Adapter added: " << objPath);
+ if(!ctx->mAdapterPath) {
+ // make added adapter as default
+ ctx->mAdapterPath = strdup(objPath);
+ //ctx->setupAgent();
+ //ctx->registerAgent();
+ ctx->defaultAdapterAdded();
+ }
+ }
+ }
}
- else if(!strcmp(signal_name, "AdapterRemoved")) {
- const char *adapter = NULL;
- g_variant_get(parameters, "(o)", &adapter);
- if(adapter) {
- LoggerD("Adapter removed: " << adapter);
- if(ctx->mAdapterPath && !strcmp(ctx->mAdapterPath, adapter)) {
- // removed the default adapter
- free(ctx->mAdapterPath);
- ctx->mAdapterPath = NULL;
- ctx->defaultAdapterRemoved();
- }
+ }
+ else if(!strcmp(signal_name, "InterfacesRemoved")) {
+ char *objPath = NULL;
+ GVariantIter* iter;
+
+ g_variant_get(parameters, "(oa{sa{sv}})", &objPath, &iter);
+
+ if(objPath)
+ {
+ GVariantIter* iter2;
+ char *interface = NULL;
+
+ while(g_variant_iter_next(iter, "{sa{sv}}",&interface, &iter2))
+ {
+
+ if(!strcmp(interface, "org.bluez.Adapter1"))
+ {
+ LoggerD("Adapter removed: " << objPath);
+ if(ctx->mAdapterPath && !strcmp(ctx->mAdapterPath, objPath)) {
+ // removed the default adapter
+ free(ctx->mAdapterPath);
+ ctx->mAdapterPath = NULL;
+ ctx->defaultAdapterRemoved();
+ }
+ }
}
}
}
+}
else if(!strcmp(interface_name, BLUEZ_ADAPTER_IFACE)) {
if(!strcmp(signal_name, "DeviceCreated")) {
const char *device;
return;
}
- if(!strcmp(method_name, "Authorize")) {
+ if(!strcmp(method_name, "AuthorizeService")) {
g_dbus_method_invocation_return_value(invocation, NULL);
}
else if(!strcmp(method_name, "RequestPinCode")) {
}
}
+gchar* Bluez::getDeviceFromAddress(std::string &address)
+{
+ char *result = NULL;
+ bool done = false;
+
+ GError * error = nullptr;
+ GDBusProxy * managerProxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, NULL,
+ "org.bluez",
+ "/",
+ "org.freedesktop.DBus.ObjectManager",
+ nullptr,&error);
+ if(error)
+ {
+ LoggerE("could not create ObjManager proxy");
+ // DebugOut(DebugOut::Error)<<"Could not create ObjectManager proxy for Bluez: "<<error->message<<endl;
+ g_error_free(error);
+ return "";
+ }
+
+ GVariant * objectMap = g_dbus_proxy_call_sync(managerProxy, "GetManagedObjects",nullptr, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
+
+ if(error)
+ {
+ LoggerE("failed to get GetManagedObj");
+ //DebugOut(DebugOut::Error)<<"Failed call to GetManagedObjects: "<<error->message<<endl;
+ g_object_unref(managerProxy);
+ g_error_free(error);
+ return "";
+ }
+
+ GVariantIter* iter;
+ char* objPath;
+ GVariantIter* level2Dict;
+
+ g_variant_get(objectMap, "(a{oa{sa{sv}}})",&iter);
+ while(g_variant_iter_next(iter, "{oa{sa{sv}}}",&objPath, &level2Dict))
+ {
+ char * interfaceName;
+ GVariantIter* innerDict;
+ while(g_variant_iter_next(level2Dict, "{sa{sv}}", &interfaceName, &innerDict))
+ {
+ if(!strcmp(interfaceName, "org.bluez.Device1"))
+ {
+ char* propertyName;
+ GVariant* value;
+
+ while(done == false && g_variant_iter_next(innerDict,"{sv}", &propertyName, &value))
+ {
+ if(!strcmp(propertyName, "Address"))
+ {
+ char* addr;
+ g_variant_get(value,"s",&addr);
+ if(addr && std::string(addr) == address)
+ {
+
+ result = objPath?strdup(objPath):NULL;
+ done = true;
+ LoggerD("getDeviceFromAddress found : " << result);
+ }
+
+ g_free(addr);
+ }
+ g_free(propertyName);
+ g_variant_unref(value);
+ }
+ }
+ g_free(interfaceName);
+ g_variant_iter_free(innerDict);
+ }
+ g_free(objPath);
+ g_variant_iter_free(level2Dict);
+ }
+ g_variant_iter_free(iter);
+
+ return result;
+}
+
bool Bluez::isDevicePaired(const char *bt_addr) {
bool paired = false;
+ std::string addrStr = std::string(bt_addr);
+ gchar* device = getDeviceFromAddress(addrStr);
if(!mAdapterPath)
return paired;
GError *err = NULL;
GVariant *reply = NULL;
- reply = g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL),
- BLUEZ_SERVICE,
- mAdapterPath,
- BLUEZ_ADAPTER_IFACE,
- "FindDevice",
- g_variant_new("(s)", bt_addr),
- NULL,
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- NULL,
- &err);
+ reply = g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL),
+ BLUEZ_SERVICE,
+ device,
+ "org.freedesktop.DBus.Properties",
+ "Get",
+ g_variant_new("(ss)", "org.bluez.Device1", "Paired"),
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &err);
if(err || !reply) {
if(err)
return paired;
}
- const char *tmp = NULL;
- g_variant_get(reply, "(o)", &tmp);
- if(!tmp) {
- g_variant_unref(reply);
- return paired;
- }
-
- char *device = strdup(tmp);
- g_variant_unref(reply);
-
- // get device properties and check if the device is Paired
- reply = g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL),
- BLUEZ_SERVICE,
- device,
- BLUEZ_DEVICE_IFACE,
- "GetProperties",
- NULL,
- NULL,
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- NULL,
- &err);
- if(err || !reply) {
- if(err)
- g_error_free(err);
- free(device);
- return paired;
- }
-
- GVariantIter *iter;
- g_variant_get(reply, "(a{sv})", &iter);
- const char *key;
- GVariant *value;
- while(g_variant_iter_next(iter, "{sv}", &key, &value)) {
- if(!strcmp(key, "Paired")) {
- paired = g_variant_get_boolean(value);
- break;
- }
- }
+ GVariant *value;
+ g_variant_get(reply, "(v)", &value);
+ paired = g_variant_get_boolean(value);
- free(device);
- g_variant_unref(reply);
+ g_variant_unref(reply);
return paired;
}
*/
mAgentIfaceVTable.method_call = Bluez::agentHandleMethodCall;
- mAgentIntrospectionData = g_dbus_node_info_new_for_xml(AGENT_INTERFACE_XML, NULL);
+ //mAgentIntrospectionData = g_dbus_node_info_new_for_xml(AGENT_INTERFACE_XML, NULL);
if (mAgentIntrospectionData == NULL) {
LoggerD("failed to create introspection data.");
#define OBEX_PREFIX "org.bluez.obex"
-#define OBEX_CLIENT_SERVICE OBEX_PREFIX ".client"
-#define OBEX_CLIENT_IFACE OBEX_PREFIX ".Client"
-#define OBEX_PHONEBOOK_IFACE OBEX_PREFIX ".PhonebookAccess"
-#define OBEX_TRANSFER_IFACE OBEX_PREFIX ".Transfer"
+#define OBEX_CLIENT_IFACE OBEX_PREFIX ".Client1"
+#define OBEX_PHONEBOOK_IFACE OBEX_PREFIX ".PhonebookAccess1"
+#define OBEX_TRANSFER_IFACE OBEX_PREFIX ".Transfer1"
// check for stalled active transfer (in seconds)
#define CHECK_STALLED_TRANSFER_TIMEOUT 120
GVariant *parameters = g_variant_builder_end(builder);
g_dbus_connection_call( g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL),
- OBEX_CLIENT_SERVICE,
- "/",
+ OBEX_PREFIX,
+ "/org/bluez/obex",
OBEX_CLIENT_IFACE,
"CreateSession",
parameters,
GError *err = NULL;
g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL),
- OBEX_CLIENT_SERVICE,
+ OBEX_PREFIX,
mSession,
OBEX_PHONEBOOK_IFACE,
"Select",
GError *err = NULL;
g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL),
- OBEX_CLIENT_SERVICE,
- "/",
+ OBEX_PREFIX,
+ "/org/bluez/obex",
OBEX_CLIENT_IFACE,
"RemoveSession",
g_variant_new("(o)", mSession), // floating variants are consumed
if(mActiveTransfer) {
GError *err = NULL;
g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL),
- OBEX_CLIENT_SERVICE,
+ OBEX_PREFIX,
mActiveTransfer,
OBEX_TRANSFER_IFACE,
"Cancel",
GVariant *parameters = g_variant_builder_end(builder);
reply = g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL),
- OBEX_CLIENT_SERVICE,
+ OBEX_PREFIX,
mSession,
OBEX_PHONEBOOK_IFACE,
"PullAll",
const char *transfer = NULL;
GVariantIter *iter;
- g_variant_get(reply, "((oa{sv}))", &transfer, &iter);
+ g_variant_get(reply, "(oa{sv})", &transfer, &iter);
LoggerD("transfer path = " << transfer);
mActiveTransfer = strdup(transfer);
g_timeout_add(CHECK_STALLED_TRANSFER_TIMEOUT*1000,
// let's abuse 'cb' field from CtxCbData to store selected remote device's MAC
CtxCbData *data = new CtxCbData(this, strdup(mSelectedRemoteDevice.c_str()), NULL, (void*)type);
- // we can set signal listener for "Error" from here,
- // since we don't need to know file path of stored transfer data
- Utils::setSignalListener(G_BUS_TYPE_SESSION, OBEX_CLIENT_SERVICE,
- OBEX_TRANSFER_IFACE, transfer, "Error",
- Obex::handleSignal, data); //TODO: think of using 'error' callback here,
- // or if error occurs, returns empty NULL string
const char *key;
GVariant *value;
// !!! what if signal comes before we subscribe for it? ... CAN IT? ... signals from DBUS
// should be executed in the thread the registration was made from, ie. this method has to
// to be completed first
- data->data1 = strdup(fileName);
- Utils::setSignalListener(G_BUS_TYPE_SESSION, OBEX_CLIENT_SERVICE,
- OBEX_TRANSFER_IFACE, transfer, "Complete",
+ data->data1 = strdup(fileName);
+ Utils::setSignalListener(G_BUS_TYPE_SESSION, OBEX_PREFIX,
+ "org.freedesktop.DBus.Properties", transfer, "PropertiesChanged",
Obex::handleSignal, data);
}
}
return;
}
- if(!strcmp(interface_name, OBEX_TRANSFER_IFACE)) {
- if(!strcmp(signal_name, "Complete") || !strcmp(signal_name, "Error")) {
- Utils::removeSignalListener(G_BUS_TYPE_SESSION, OBEX_CLIENT_SERVICE,
- OBEX_TRANSFER_IFACE, object_path,
- "Complete");
- Utils::removeSignalListener(G_BUS_TYPE_SESSION, OBEX_CLIENT_SERVICE,
- OBEX_TRANSFER_IFACE, object_path,
- "Error");
- if(ctx->mActiveTransfer) {
- free(ctx->mActiveTransfer);
- ctx->mActiveTransfer = NULL;
- }
-
- if(!strcmp(signal_name, "Complete")) {
- const char *path = static_cast<const char *>(data->data1);
- const char *type = static_cast<const char *>(data->data2);
- const char *origin = static_cast<const char *>(data->cb);
- ctx->processVCards(path, type, origin);
- }
- else if(!strcmp(signal_name, "Error")) {
- // dont' have to do anything
- }
- if(data->data1) free(data->data1); // path - to the file containing received VCards
- if(data->cb) free(data->cb); // origin - MAC address of selected remote device
- delete data;
- ctx->initiateNextSyncRequest();
- }
+ if(!strcmp(signal_name, "PropertiesChanged"))
+ {
+ char *objPath = NULL;
+ GVariantIter* iter, iter2;
+
+ g_variant_get(parameters, "(sa{sv}as)", &objPath, &iter, &iter2);
+
+ if(objPath)
+ {
+ GVariant* var;
+ char *prop = NULL;
+
+ while(g_variant_iter_next(iter, "{sv}", &prop, &var))
+ {
+ if(!strcmp(prop, "Status"))
+ {
+ char *status_str=0;
+ g_variant_get(var, "s", &status_str);
+ //LoggerD("Status is: " << status_str);
+
+ if(!strcmp(status_str, "complete"))
+ {
+ const char *path = static_cast<const char *>(data->data1);
+ const char *type = static_cast<const char *>(data->data2);
+ const char *origin = static_cast<const char *>(data->cb);
+ ctx->processVCards(path, type, origin);
+
+
+ if(data->data1) free(data->data1); // path - to the file containing received VCards
+ if(data->cb) free(data->cb); // origin - MAC address of selected remote device
+ delete data;
+ ctx->initiateNextSyncRequest();
+ }
+ }
+ }
+ }
+ else
+ {
+ LoggerD("No objectPath found. Exiting.");
+ }
}
}