forked from enlightenment/enlightenment
e: add automatic desktop lock/unlock when a bluetooth device disapear.
This use a custom implementation of l2ping to ping known device and do proper action when they go away. I don't recommend to use the auto unlonck, but it is there if someone need it.
This commit is contained in:
parent
1a472d475e
commit
2f6fcf4228
11
configure.ac
11
configure.ac
|
@ -197,9 +197,13 @@ CPPFLAGS="${PCPPFLAGS}"
|
|||
AC_SUBST(cf_cflags)
|
||||
AC_SUBST(cf_libs)
|
||||
|
||||
AC_CHECK_HEADERS([bluetooth/bluetooth.h],
|
||||
[have_bluetooth_h="yes"],
|
||||
[have_bluetooth_h="no"])
|
||||
PKG_CHECK_MODULES([BLUEZ], [bluez],
|
||||
[have_bluetooth="yes"],
|
||||
[have_bluetooth="no"])
|
||||
AM_CONDITIONAL([HAVE_BLUETOOTH], [test "x${have_bluetooth}"])
|
||||
if test "x${have_bluetooth}"; then
|
||||
AC_DEFINE_UNQUOTED([HAVE_BLUETOOTH], [1], [Bluetooth is there])
|
||||
fi
|
||||
|
||||
execinfo_libs=""
|
||||
AC_CHECK_HEADERS([execinfo.h], [have_execinfo="yes"], [have_execinfo="no"])
|
||||
|
@ -487,6 +491,7 @@ PKG_CHECK_MODULES(E_FM_OPEN, [
|
|||
|
||||
PKG_CHECK_MODULES(E_SYS, [
|
||||
eina >= ${efl_version}
|
||||
ecore >= ${efl_version}
|
||||
])
|
||||
|
||||
PKG_CHECK_MODULES(E_INIT, [
|
||||
|
|
|
@ -51,6 +51,7 @@ action: /bin/mount /bin/mount
|
|||
action: /bin/umount /bin/umount
|
||||
action: /usr/bin/eject /usr/bin/eject
|
||||
action: gdb gdb
|
||||
action: l2ping l2ping
|
||||
|
||||
# on FreeBSD use this instead of the above.
|
||||
#action suspend /usr/sbin/zzz
|
||||
|
|
|
@ -422,10 +422,10 @@ e_fm_op.c
|
|||
enlightenment_fm_op_LDADD = @E_FM_OP_LIBS@ -lm
|
||||
|
||||
enlightenment_sys_SOURCES = \
|
||||
e_sys_main.c
|
||||
e_sys_main.c e_sys_l2ping.c
|
||||
|
||||
enlightenment_sys_LDADD = @SUID_LDFLAGS@ @E_SYS_LIBS@
|
||||
enlightenment_sys_CFLAGS = @SUID_CFLAGS@ @E_SYS_CFLAGS@
|
||||
enlightenment_sys_LDADD = @SUID_LDFLAGS@ @E_SYS_LIBS@ @BLUEZ_LIBS@
|
||||
enlightenment_sys_CFLAGS = @SUID_CFLAGS@ @E_SYS_CFLAGS@ @BLUEZ_CFLAGS@
|
||||
|
||||
if HAVE_EEZE
|
||||
enlightenment_backlight_SOURCES = \
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
#include "config.h"
|
||||
|
||||
#include <Ecore.h>
|
||||
|
||||
#ifdef HAVE_BLUETOOTH
|
||||
#include <unistd.h>
|
||||
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/l2cap.h>
|
||||
#endif
|
||||
|
||||
double
|
||||
e_sys_l2ping(const char *bluetooth_mac)
|
||||
{
|
||||
#ifdef HAVE_BLUETOOTH
|
||||
char send_buf[L2CAP_CMD_HDR_SIZE + 1];
|
||||
char recv_buf[L2CAP_CMD_HDR_SIZE + 1];
|
||||
char tmp[18];
|
||||
l2cap_cmd_hdr *send_cmd;
|
||||
l2cap_cmd_hdr *recv_cmd;
|
||||
struct sockaddr_l2 addr;
|
||||
struct timeval tv;
|
||||
socklen_t optlen;
|
||||
fd_set rfds;
|
||||
double start;
|
||||
int fd;
|
||||
|
||||
/* Create socket */
|
||||
fd = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_L2CAP);
|
||||
if (fd < 0) {
|
||||
perror("Can't create socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Bind to local address */
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.l2_family = AF_BLUETOOTH;
|
||||
bacpy(&addr.l2_bdaddr, BDADDR_ANY);
|
||||
|
||||
if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0)
|
||||
{
|
||||
perror("Can't bind socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Connect to remote device */
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.l2_family = AF_BLUETOOTH;
|
||||
str2ba(bluetooth_mac, &addr.l2_bdaddr);
|
||||
|
||||
if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0)
|
||||
{
|
||||
perror("Can't connect");
|
||||
return -1;
|
||||
}
|
||||
|
||||
start = ecore_time_get();
|
||||
|
||||
/* Get local address */
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
optlen = sizeof(addr);
|
||||
|
||||
if (getsockname(fd, (struct sockaddr *) &addr, &optlen) < 0)
|
||||
{
|
||||
perror("Can't get local address");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ba2str(&addr.l2_bdaddr, tmp);
|
||||
|
||||
send_cmd = (l2cap_cmd_hdr *) send_buf;
|
||||
send_cmd->ident = 200;
|
||||
send_cmd->len = htobs(1);
|
||||
send_cmd->code = L2CAP_ECHO_REQ;
|
||||
send_buf[L2CAP_CMD_HDR_SIZE] = 'A';
|
||||
|
||||
if (send(fd, send_buf, L2CAP_CMD_HDR_SIZE + 1, 0) <= 0)
|
||||
{
|
||||
perror("Send failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (recv(fd, recv_buf, L2CAP_CMD_HDR_SIZE + 1, 0) < 0)
|
||||
{
|
||||
perror("Recv failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
recv_cmd = (l2cap_cmd_hdr *) recv_buf;
|
||||
recv_cmd->len = btohs(recv_cmd->len);
|
||||
if (recv_cmd->ident != 200)
|
||||
return -1; /* Wrong packet */
|
||||
|
||||
close(fd);
|
||||
|
||||
return ecore_time_get() - start;
|
||||
#else
|
||||
fprintf(stderr, "e_sys_l2ping nop\n");
|
||||
return -1;
|
||||
#endif
|
||||
}
|
|
@ -16,6 +16,8 @@
|
|||
#endif
|
||||
#include <Eina.h>
|
||||
|
||||
double e_sys_l2ping(const char *bluetooth_mac);
|
||||
|
||||
/* local subsystem functions */
|
||||
#ifdef HAVE_EEZE_MOUNT
|
||||
static Eina_Bool mountopts_check(const char *opts);
|
||||
|
@ -88,6 +90,11 @@ main(int argc,
|
|||
|
||||
output = argv[3];
|
||||
}
|
||||
else if (!strcmp(argv[1], "l2ping"))
|
||||
{
|
||||
action = argv[1];
|
||||
output = argv[2];
|
||||
}
|
||||
#ifdef HAVE_EEZE_MOUNT
|
||||
else
|
||||
{
|
||||
|
@ -173,6 +180,18 @@ main(int argc,
|
|||
|
||||
exit(WEXITSTATUS(r));
|
||||
}
|
||||
else if (!test && !strcmp(action, "l2ping"))
|
||||
{
|
||||
char tmp[128];
|
||||
double latency;
|
||||
|
||||
latency = e_sys_l2ping(output);
|
||||
|
||||
eina_convert_dtoa(latency, tmp);
|
||||
fprintf(stdout, tmp);
|
||||
|
||||
return (latency < 0) ? 1 : 0;
|
||||
}
|
||||
if ((!test)
|
||||
#ifdef HAVE_EEZE_MOUNT
|
||||
&& (!mnt)
|
||||
|
|
|
@ -4,6 +4,14 @@
|
|||
#include "ebluez4.h"
|
||||
|
||||
/* Local Variables */
|
||||
static Ecore_Exe *autolock_exe = NULL;
|
||||
static Ecore_Poller *autolock_poller = NULL;
|
||||
static Ecore_Event_Handler *autolock_die = NULL;
|
||||
static Ecore_Event_Handler *autolock_out = NULL;
|
||||
static Ecore_Event_Handler *autolock_desklock = NULL;
|
||||
static Eina_Bool autolock_initted = EINA_FALSE;
|
||||
static Eina_Bool autolock_waiting = EINA_TRUE;
|
||||
|
||||
static Eina_List *instances = NULL;
|
||||
static E_Module *mod = NULL;
|
||||
static char tmpbuf[1024];
|
||||
|
@ -15,6 +23,42 @@ Config *ebluez4_config = NULL;
|
|||
EAPI E_Module_Api e_modapi = {E_MODULE_API_VERSION, "Bluez4"};
|
||||
|
||||
/* Local Functions */
|
||||
static Eina_Bool
|
||||
_ebluez_l2ping_poller(void *data EINA_UNUSED)
|
||||
{
|
||||
Eina_Strbuf *buf;
|
||||
const char *tmp = NULL;
|
||||
|
||||
autolock_poller = NULL;
|
||||
|
||||
buf = eina_strbuf_new();
|
||||
if (e_desklock_state_get())
|
||||
{
|
||||
if (!autolock_waiting)
|
||||
tmp = ebluez4_config->unlock_dev_addr;
|
||||
else
|
||||
tmp = ebluez4_config->lock_dev_addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!autolock_waiting)
|
||||
tmp = ebluez4_config->lock_dev_addr;
|
||||
else
|
||||
tmp = ebluez4_config->unlock_dev_addr;
|
||||
}
|
||||
|
||||
if (tmp)
|
||||
{
|
||||
eina_strbuf_append_printf(buf, "%s/enlightenment/utils/enlightenment_sys l2ping %s",
|
||||
e_prefix_lib_get(), tmp);
|
||||
autolock_exe = ecore_exe_run(eina_strbuf_string_get(buf), NULL);
|
||||
}
|
||||
|
||||
eina_strbuf_free(buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
_ebluez4_search_dialog_del(Instance *inst)
|
||||
{
|
||||
|
@ -262,9 +306,15 @@ _ebluez4_cb_lock(void *data,
|
|||
int tog;
|
||||
|
||||
tog = e_menu_item_toggle_get(mi);
|
||||
eina_stringshare_replace(&ebluez4_config->lock_dev_name,
|
||||
tog ? dev->name : NULL);
|
||||
eina_stringshare_replace(&ebluez4_config->lock_dev_addr,
|
||||
tog ? dev->addr : NULL);
|
||||
e_config_save_queue();
|
||||
|
||||
if (autolock_exe)
|
||||
ecore_exe_kill(autolock_exe);
|
||||
autolock_exe = NULL;
|
||||
if (!autolock_poller && (ebluez4_config->lock_dev_addr || ebluez4_config->unlock_dev_addr))
|
||||
autolock_poller = ecore_poller_add(ECORE_POLLER_CORE, 32, _ebluez_l2ping_poller, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -276,9 +326,15 @@ _ebluez4_cb_unlock(void *data,
|
|||
int tog;
|
||||
|
||||
tog = e_menu_item_toggle_get(mi);
|
||||
eina_stringshare_replace(&ebluez4_config->unlock_dev_name,
|
||||
tog ? dev->name : NULL);
|
||||
eina_stringshare_replace(&ebluez4_config->unlock_dev_addr,
|
||||
tog ? dev->addr : NULL);
|
||||
e_config_save_queue();
|
||||
|
||||
if (autolock_exe)
|
||||
ecore_exe_kill(autolock_exe);
|
||||
autolock_exe = NULL;
|
||||
if (!autolock_poller && (ebluez4_config->lock_dev_addr || ebluez4_config->unlock_dev_addr))
|
||||
autolock_poller = ecore_poller_add(ECORE_POLLER_CORE, 32, _ebluez_l2ping_poller, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -348,23 +404,28 @@ _ebluez4_add_devices(Instance *inst)
|
|||
e_menu_item_label_set(submi, "Forget");
|
||||
e_menu_item_callback_set(submi, _ebluez4_cb_forget, dev);
|
||||
|
||||
#ifdef HAVE_BLUETOOTH
|
||||
if (autolock_initted)
|
||||
{
|
||||
/* Auto lock when away */
|
||||
submi = e_menu_item_new(subm);
|
||||
e_menu_item_check_set(submi, 1);
|
||||
e_menu_item_label_set(submi, "Lock on disconnect");
|
||||
e_menu_item_callback_set(submi, _ebluez4_cb_lock, dev);
|
||||
chk = ebluez4_config->lock_dev_name && dev->name &&
|
||||
!strcmp(dev->name, ebluez4_config->lock_dev_name);
|
||||
chk = ebluez4_config->lock_dev_addr && dev->addr &&
|
||||
!strcmp(dev->addr, ebluez4_config->lock_dev_addr);
|
||||
e_menu_item_toggle_set(submi, !!chk);
|
||||
|
||||
submi = e_menu_item_new(subm);
|
||||
e_menu_item_check_set(submi, 1);
|
||||
e_menu_item_label_set(submi, "Unlock on disconnect");
|
||||
e_menu_item_callback_set(submi, _ebluez4_cb_unlock, dev);
|
||||
chk = ebluez4_config->unlock_dev_name && dev->name &&
|
||||
!strcmp(dev->name, ebluez4_config->unlock_dev_name);
|
||||
chk = ebluez4_config->unlock_dev_addr && dev->addr &&
|
||||
!strcmp(dev->addr, ebluez4_config->unlock_dev_addr);
|
||||
e_menu_item_toggle_set(submi, !!chk);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -520,10 +581,93 @@ static const E_Gadcon_Client_Class _gc_class =
|
|||
E_GADCON_CLIENT_STYLE_PLAIN
|
||||
};
|
||||
|
||||
static Eina_Bool
|
||||
_ebluez_exe_die(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *event_info)
|
||||
{
|
||||
Ecore_Exe_Event_Del *ev = event_info;
|
||||
|
||||
if (ev->exe != autolock_exe)
|
||||
return ECORE_CALLBACK_PASS_ON;
|
||||
|
||||
if (!autolock_initted)
|
||||
{
|
||||
if (ev->exit_code == 0)
|
||||
{
|
||||
autolock_initted = EINA_TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (e_desklock_state_get()) // Locked state ?
|
||||
{
|
||||
if (!autolock_waiting)
|
||||
{
|
||||
// Not waiting yet for the auto unlock device to appear before unlock
|
||||
if (ev->exit_code == 0 && ebluez4_config->unlock_dev_addr)
|
||||
{
|
||||
e_desklock_hide();
|
||||
}
|
||||
}
|
||||
else if (ev->exit_code == 1)
|
||||
{
|
||||
// The device just disapeared, now we can wait for it to disapear
|
||||
autolock_waiting = EINA_FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!autolock_waiting)
|
||||
{
|
||||
// Not waiting yet for the auto lock device to disappear before locking
|
||||
if (ev->exit_code == 1 && ebluez4_config->lock_dev_addr)
|
||||
{
|
||||
e_desklock_show(EINA_FALSE);
|
||||
}
|
||||
}
|
||||
else if (ev->exit_code == 0)
|
||||
{
|
||||
// The device just appeared, now we can wait for it to disapear
|
||||
autolock_waiting = EINA_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (autolock_initted)
|
||||
autolock_poller = ecore_poller_add(ECORE_POLLER_CORE, 32, _ebluez_l2ping_poller, NULL);
|
||||
|
||||
autolock_exe = NULL;
|
||||
|
||||
return ECORE_CALLBACK_PASS_ON;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_ebluez_exe_out(void *data, int ev_type, void *ev)
|
||||
{
|
||||
/* FIXME: Need experiment, but we should be able to use latency to somehow estimate distance, right ? */
|
||||
return ECORE_CALLBACK_PASS_ON;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_ebluez_desklock(void *data, int ev_type, void *ev)
|
||||
{
|
||||
if (autolock_exe)
|
||||
ecore_exe_kill(autolock_exe);
|
||||
autolock_exe = NULL;
|
||||
|
||||
if (!autolock_poller && autolock_initted && (ebluez4_config->lock_dev_addr || ebluez4_config->unlock_dev_addr))
|
||||
autolock_poller = ecore_poller_add(ECORE_POLLER_CORE, 32, _ebluez_l2ping_poller, NULL);
|
||||
|
||||
autolock_waiting = EINA_TRUE;
|
||||
|
||||
return ECORE_CALLBACK_PASS_ON;
|
||||
}
|
||||
|
||||
/* Module Functions */
|
||||
EAPI void *
|
||||
e_modapi_init(E_Module *m)
|
||||
{
|
||||
Eina_Strbuf *buf;
|
||||
|
||||
mod = m;
|
||||
|
||||
conf_edd = E_CONFIG_DD_NEW("Config", Config);
|
||||
|
@ -531,8 +675,8 @@ e_modapi_init(E_Module *m)
|
|||
#undef D
|
||||
#define T Config
|
||||
#define D conf_edd
|
||||
E_CONFIG_VAL(D, T, lock_dev_name, STR);
|
||||
E_CONFIG_VAL(D, T, unlock_dev_name, STR);
|
||||
E_CONFIG_VAL(D, T, lock_dev_addr, STR);
|
||||
E_CONFIG_VAL(D, T, unlock_dev_addr, STR);
|
||||
|
||||
ebluez4_config = e_config_domain_load("module.ebluez4", conf_edd);
|
||||
if (!ebluez4_config)
|
||||
|
@ -542,6 +686,16 @@ e_modapi_init(E_Module *m)
|
|||
|
||||
e_gadcon_provider_register(&_gc_class);
|
||||
|
||||
autolock_die = ecore_event_handler_add(ECORE_EXE_EVENT_DEL, _ebluez_exe_die, NULL);
|
||||
autolock_out = ecore_event_handler_add(ECORE_EXE_EVENT_DATA, _ebluez_exe_out, NULL);
|
||||
autolock_desklock = ecore_event_handler_add(E_EVENT_DESKLOCK, _ebluez_desklock, NULL);
|
||||
|
||||
buf = eina_strbuf_new();
|
||||
eina_strbuf_append_printf(buf, "%s/enlightenment/utils/enlightenment_sys -t l2ping",
|
||||
e_prefix_lib_get());
|
||||
autolock_exe = ecore_exe_run(eina_strbuf_string_get(buf), NULL);
|
||||
eina_strbuf_free(buf);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
|
@ -550,8 +704,17 @@ e_modapi_shutdown(E_Module *m)
|
|||
{
|
||||
E_CONFIG_DD_FREE(conf_edd);
|
||||
|
||||
eina_stringshare_del(ebluez4_config->lock_dev_name);
|
||||
eina_stringshare_del(ebluez4_config->unlock_dev_name);
|
||||
if (autolock_exe) ecore_exe_kill(autolock_exe);
|
||||
autolock_exe = NULL;
|
||||
if (autolock_poller) ecore_timer_del(autolock_poller);
|
||||
autolock_poller = NULL;
|
||||
|
||||
ecore_event_handler_del(autolock_die);
|
||||
ecore_event_handler_del(autolock_out);
|
||||
ecore_event_handler_del(autolock_desklock);
|
||||
|
||||
eina_stringshare_del(ebluez4_config->lock_dev_addr);
|
||||
eina_stringshare_del(ebluez4_config->unlock_dev_addr);
|
||||
free(ebluez4_config);
|
||||
ebluez4_config = NULL;
|
||||
|
||||
|
|
|
@ -16,8 +16,8 @@ struct _Instance
|
|||
typedef struct _Config Config;
|
||||
struct _Config
|
||||
{
|
||||
const char *lock_dev_name;
|
||||
const char *unlock_dev_name;
|
||||
const char *lock_dev_addr;
|
||||
const char *unlock_dev_addr;
|
||||
};
|
||||
|
||||
extern Config *ebluez4_config;
|
||||
|
|
|
@ -385,10 +385,6 @@ _on_removed(void *context, const EDBus_Message *msg)
|
|||
fdev = eina_list_search_unsorted(ctxt->found_devices, _dev_addr_cmp,
|
||||
dev->addr);
|
||||
|
||||
if (dev->name && ebluez4_config->lock_dev_name &&
|
||||
!strcmp(dev->name, ebluez4_config->lock_dev_name))
|
||||
e_desklock_show(EINA_FALSE);
|
||||
|
||||
_unset_dev(dev, &ctxt->devices);
|
||||
_unset_dev(fdev, &ctxt->found_devices);
|
||||
}
|
||||
|
@ -427,10 +423,6 @@ _on_device_found(void *context, const EDBus_Message *msg)
|
|||
dev->paired = paired;
|
||||
ctxt->found_devices = eina_list_append(ctxt->found_devices, dev);
|
||||
|
||||
if (dev->name && ebluez4_config->unlock_dev_name &&
|
||||
!strcmp(dev->name, ebluez4_config->unlock_dev_name))
|
||||
e_desklock_hide();
|
||||
|
||||
ebluez4_update_instances(ctxt->found_devices);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue