enlightenment/src/modules/bluez4/agent.c

252 lines
8.0 KiB
C

#include <inttypes.h>
#include "e.h"
#include "ebluez4.h"
#include "agent.h"
#define AGENT_INTERFACE "org.bluez.Agent"
#define BLUEZ_ERROR_FAILED "org.bluez.Error.Failed"
#define GET_ERROR_MSG "edbus_message_arguments_get() error"
#define BLUEZ_ERROR_REJECTED "org.bluez.Error.Rejected"
#define REJECTED_MSG "Request was rejected"
static EDBus_Connection *bluez_conn;
static char buf[1024];
/* Local Functions */
static void
_reply(EDBus_Message *message, EDBus_Message *reply)
{
edbus_connection_send(bluez_conn, reply, NULL, NULL, -1);
edbus_message_unref(message);
}
static void
_pincode_ok(void *data, char *text)
{
EDBus_Message *message = data;
EDBus_Message *reply = edbus_message_method_return_new(message);
edbus_message_arguments_append(reply, "s", text);
_reply(message, reply);
}
static void
_passkey_ok(void *data, char *text)
{
EDBus_Message *message = data;
uint32_t passkey = (uint32_t)atoi(text);
EDBus_Message *reply = edbus_message_method_return_new(message);
edbus_message_arguments_append(reply, "u", passkey);
_reply(message, reply);
}
static void
_cancel(void *data)
{
EDBus_Message *message = data;
EDBus_Message *reply = edbus_message_error_new(message,
BLUEZ_ERROR_REJECTED, REJECTED_MSG);
_reply(message, reply);
}
static E_Dialog *
_create_dialog(const char *title, const char *msg,
const char *icon, const char *class)
{
E_Container *con;
E_Dialog *dialog;
con = e_container_current_get(e_manager_current_get());
dialog = e_dialog_new(con, title, class);
e_dialog_title_set(dialog, title);
e_dialog_icon_set(dialog, icon, 64);
e_dialog_text_set(dialog, msg);
return dialog;
}
static void
_display_msg(const char *title, const char *msg)
{
E_Dialog *dialog = _create_dialog(title, msg, "view-hidden-files",
"display");
e_dialog_button_add(dialog, "OK", NULL, NULL, NULL);
e_dialog_show(dialog);
}
static void
_reply_and_del_dialog(EDBus_Message *reply, E_Dialog *dialog)
{
EDBus_Message *message = dialog->data;
_reply(message, reply);
if (!dialog) return;
e_object_del(E_OBJECT(dialog));
}
static void
_reject(void *data, E_Dialog *dialog)
{
const EDBus_Message *msg = dialog->data;
EDBus_Message *reply = edbus_message_error_new(msg, BLUEZ_ERROR_REJECTED,
REJECTED_MSG);
_reply_and_del_dialog(reply, dialog);
}
static void
_ok(void *data, E_Dialog *dialog)
{
const EDBus_Message *msg = dialog->data;
EDBus_Message *reply = edbus_message_method_return_new(msg);
_reply_and_del_dialog(reply, dialog);
}
static void
_close(E_Win *win)
{
E_Dialog *dialog = win->data;
_reject(NULL, dialog);
}
static void
_ask(const char *title, const char *ask_msg, const char *ok_label,
EDBus_Message *edbus_message)
{
E_Dialog *dialog = _create_dialog(title, ask_msg, "dialog-ask", "ask");
dialog->data = edbus_message;
e_win_delete_callback_set(dialog->win, _close);
e_dialog_button_add(dialog, ok_label, NULL, _ok, NULL);
e_dialog_button_add(dialog, "Reject", NULL, _reject, NULL);
e_dialog_show(dialog);
}
/* Implementation of agent API */
static EDBus_Message *
_agent_release(const EDBus_Service_Interface *iface, const EDBus_Message *message)
{
DBG("Agent Released.");
return edbus_message_method_return_new(message);
}
static EDBus_Message *
_agent_request_pin_code(const EDBus_Service_Interface *iface, const EDBus_Message *message)
{
EDBus_Message *msg = (EDBus_Message *)message;
edbus_message_ref(msg);
e_entry_dialog_show("Pin Code Requested", NULL,
"Enter the PinCode above. It should have 1-16 "
"characters and can be alphanumeric.", "0000",
"OK", "Cancel", _pincode_ok, _cancel, msg);
return NULL;
}
static EDBus_Message *
_agent_request_passkey(const EDBus_Service_Interface *iface, const EDBus_Message *message)
{
EDBus_Message *msg = (EDBus_Message *)message;
edbus_message_ref(msg);
e_entry_dialog_show("Passkey Requested", NULL, "Enter the Passkey above. "
"It should be a numeric value between 0-999999.",
"0", "OK", "Cancel", _passkey_ok, _cancel, msg);
return NULL;
}
static EDBus_Message *
_agent_display_passkey(const EDBus_Service_Interface *iface, const EDBus_Message *message)
{
const char *device;
uint32_t passkey;
uint16_t entered;
Device *dev;
if(!edbus_message_arguments_get(message, "ouq", &device, &passkey, &entered))
return edbus_message_error_new(message, BLUEZ_ERROR_FAILED, GET_ERROR_MSG);
dev = eina_list_search_unsorted(ctxt->devices, ebluez4_dev_path_cmp, device);
snprintf(buf, sizeof(buf), "%d keys were typed on %s. Passkey is %06d",
entered, dev->name, passkey);
_display_msg("Display Passkey", buf);
return edbus_message_method_return_new(message);
}
static EDBus_Message *
_agent_display_pin_code(const EDBus_Service_Interface *iface, const EDBus_Message *message)
{
const char *device, *pincode;
Device *dev;
if(!edbus_message_arguments_get(message, "os", &device, &pincode))
return edbus_message_error_new(message, BLUEZ_ERROR_FAILED, GET_ERROR_MSG);
dev = eina_list_search_unsorted(ctxt->devices, ebluez4_dev_path_cmp, device);
snprintf(buf, sizeof(buf), "Pincode for %s is %s", dev->name, pincode);
_display_msg("Display Pincode", buf);
return edbus_message_method_return_new(message);
}
static EDBus_Message *
_agent_request_confirmation(const EDBus_Service_Interface *iface, const EDBus_Message *message)
{
const char *device;
uint32_t passkey;
Device *dev;
if(!edbus_message_arguments_get(message, "ou", &device, &passkey))
return edbus_message_error_new(message, BLUEZ_ERROR_FAILED, GET_ERROR_MSG);
dev = eina_list_search_unsorted(ctxt->devices, ebluez4_dev_path_cmp, device);
snprintf(buf, sizeof(buf), "%06d is the passkey presented in %s?",
passkey, dev->name);
edbus_message_ref((EDBus_Message *)message);
_ask("Confirm Request", buf, "Confirm", (EDBus_Message *)message);
return NULL;
}
static EDBus_Message *
_agent_authorize(const EDBus_Service_Interface *iface, const EDBus_Message *message)
{
const char *device, *uuid;
Device *dev;
if(!edbus_message_arguments_get(message, "os", &device, &uuid))
return edbus_message_error_new(message, BLUEZ_ERROR_FAILED, GET_ERROR_MSG);
dev = eina_list_search_unsorted(ctxt->devices, ebluez4_dev_path_cmp, device);
snprintf(buf, sizeof(buf), "Grant permission for %s to connect?",
dev->name);
edbus_message_ref((EDBus_Message *)message);
_ask("Authorize Connection", buf, "Grant", (EDBus_Message *)message);
return NULL;
}
static EDBus_Message *
_agent_cancel(const EDBus_Service_Interface *iface, const EDBus_Message *message)
{
DBG("Request canceled.");
return edbus_message_method_return_new(message);
}
static const EDBus_Method agent_methods[] = {
{ "Release", NULL, NULL, _agent_release },
{ "RequestPinCode", EDBUS_ARGS({"o", "device"}),
EDBUS_ARGS({"s", "pincode"}), _agent_request_pin_code },
{ "RequestPasskey", EDBUS_ARGS({"o", "device"}),
EDBUS_ARGS({"u", "passkey"}), _agent_request_passkey },
{ "DisplayPasskey",
EDBUS_ARGS({"o", "device"},{"u", "passkey"},{"q", "entered"}),
NULL, _agent_display_passkey },
{ "DisplayPinCode", EDBUS_ARGS({"o", "device"},{"s", "pincode"}),
NULL, _agent_display_pin_code },
{ "RequestConfirmation", EDBUS_ARGS({"o", "device"},{"u", "passkey"}),
NULL, _agent_request_confirmation },
{ "Authorize", EDBUS_ARGS({"o", "device"},{"s", "uuid"}),
NULL, _agent_authorize },
{ "Cancel", NULL, NULL, _agent_cancel },
{ }
};
static const EDBus_Service_Interface_Desc agent_iface = {
AGENT_INTERFACE, agent_methods
};
/* Public Functions */
void ebluez4_register_agent_interfaces(EDBus_Connection *conn)
{
bluez_conn = conn;
edbus_service_interface_register(conn, AGENT_PATH, &agent_iface);
edbus_service_interface_register(conn, REMOTE_AGENT_PATH, &agent_iface);
}