summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac11
-rw-r--r--data/etc/sysactions.conf.in1
-rw-r--r--src/bin/Makefile.am6
-rw-r--r--src/bin/e_sys_l2ping.c101
-rw-r--r--src/bin/e_sys_main.c19
-rw-r--r--src/modules/bluez4/e_mod_main.c211
-rw-r--r--src/modules/bluez4/e_mod_main.h4
-rw-r--r--src/modules/bluez4/ebluez4.c8
8 files changed, 321 insertions, 40 deletions
diff --git a/configure.ac b/configure.ac
index 82c0a5bef..b3dbcec65 100644
--- a/configure.ac
+++ b/configure.ac
@@ -197,9 +197,13 @@ CPPFLAGS="${PCPPFLAGS}"
197AC_SUBST(cf_cflags) 197AC_SUBST(cf_cflags)
198AC_SUBST(cf_libs) 198AC_SUBST(cf_libs)
199 199
200AC_CHECK_HEADERS([bluetooth/bluetooth.h], 200PKG_CHECK_MODULES([BLUEZ], [bluez],
201 [have_bluetooth_h="yes"], 201 [have_bluetooth="yes"],
202 [have_bluetooth_h="no"]) 202 [have_bluetooth="no"])
203AM_CONDITIONAL([HAVE_BLUETOOTH], [test "x${have_bluetooth}"])
204if test "x${have_bluetooth}"; then
205 AC_DEFINE_UNQUOTED([HAVE_BLUETOOTH], [1], [Bluetooth is there])
206fi
203 207
204execinfo_libs="" 208execinfo_libs=""
205AC_CHECK_HEADERS([execinfo.h], [have_execinfo="yes"], [have_execinfo="no"]) 209AC_CHECK_HEADERS([execinfo.h], [have_execinfo="yes"], [have_execinfo="no"])
@@ -487,6 +491,7 @@ PKG_CHECK_MODULES(E_FM_OPEN, [
487 491
488PKG_CHECK_MODULES(E_SYS, [ 492PKG_CHECK_MODULES(E_SYS, [
489 eina >= ${efl_version} 493 eina >= ${efl_version}
494 ecore >= ${efl_version}
490]) 495])
491 496
492PKG_CHECK_MODULES(E_INIT, [ 497PKG_CHECK_MODULES(E_INIT, [
diff --git a/data/etc/sysactions.conf.in b/data/etc/sysactions.conf.in
index 6054a0423..b0dfab51c 100644
--- a/data/etc/sysactions.conf.in
+++ b/data/etc/sysactions.conf.in
@@ -51,6 +51,7 @@ action: /bin/mount /bin/mount
51action: /bin/umount /bin/umount 51action: /bin/umount /bin/umount
52action: /usr/bin/eject /usr/bin/eject 52action: /usr/bin/eject /usr/bin/eject
53action: gdb gdb 53action: gdb gdb
54action: l2ping l2ping
54 55
55# on FreeBSD use this instead of the above. 56# on FreeBSD use this instead of the above.
56#action suspend /usr/sbin/zzz 57#action suspend /usr/sbin/zzz
diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am
index fd930ef66..dfdb96b3b 100644
--- a/src/bin/Makefile.am
+++ b/src/bin/Makefile.am
@@ -422,10 +422,10 @@ e_fm_op.c
422enlightenment_fm_op_LDADD = @E_FM_OP_LIBS@ -lm 422enlightenment_fm_op_LDADD = @E_FM_OP_LIBS@ -lm
423 423
424enlightenment_sys_SOURCES = \ 424enlightenment_sys_SOURCES = \
425e_sys_main.c 425e_sys_main.c e_sys_l2ping.c
426 426
427enlightenment_sys_LDADD = @SUID_LDFLAGS@ @E_SYS_LIBS@ 427enlightenment_sys_LDADD = @SUID_LDFLAGS@ @E_SYS_LIBS@ @BLUEZ_LIBS@
428enlightenment_sys_CFLAGS = @SUID_CFLAGS@ @E_SYS_CFLAGS@ 428enlightenment_sys_CFLAGS = @SUID_CFLAGS@ @E_SYS_CFLAGS@ @BLUEZ_CFLAGS@
429 429
430if HAVE_EEZE 430if HAVE_EEZE
431enlightenment_backlight_SOURCES = \ 431enlightenment_backlight_SOURCES = \
diff --git a/src/bin/e_sys_l2ping.c b/src/bin/e_sys_l2ping.c
new file mode 100644
index 000000000..ac826ea72
--- /dev/null
+++ b/src/bin/e_sys_l2ping.c
@@ -0,0 +1,101 @@
1#include "config.h"
2
3#include <Ecore.h>
4
5#ifdef HAVE_BLUETOOTH
6#include <unistd.h>
7
8#include <bluetooth/bluetooth.h>
9#include <bluetooth/l2cap.h>
10#endif
11
12double
13e_sys_l2ping(const char *bluetooth_mac)
14{
15#ifdef HAVE_BLUETOOTH
16 char send_buf[L2CAP_CMD_HDR_SIZE + 1];
17 char recv_buf[L2CAP_CMD_HDR_SIZE + 1];
18 char tmp[18];
19 l2cap_cmd_hdr *send_cmd;
20 l2cap_cmd_hdr *recv_cmd;
21 struct sockaddr_l2 addr;
22 struct timeval tv;
23 socklen_t optlen;
24 fd_set rfds;
25 double start;
26 int fd;
27
28 /* Create socket */
29 fd = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_L2CAP);
30 if (fd < 0) {
31 perror("Can't create socket");
32 return -1;
33 }
34
35 /* Bind to local address */
36 memset(&addr, 0, sizeof(addr));
37 addr.l2_family = AF_BLUETOOTH;
38 bacpy(&addr.l2_bdaddr, BDADDR_ANY);
39
40 if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0)
41 {
42 perror("Can't bind socket");
43 return -1;
44 }
45
46 /* Connect to remote device */
47 memset(&addr, 0, sizeof(addr));
48 addr.l2_family = AF_BLUETOOTH;
49 str2ba(bluetooth_mac, &addr.l2_bdaddr);
50
51 if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0)
52 {
53 perror("Can't connect");
54 return -1;
55 }
56
57 start = ecore_time_get();
58
59 /* Get local address */
60 memset(&addr, 0, sizeof(addr));
61 optlen = sizeof(addr);
62
63 if (getsockname(fd, (struct sockaddr *) &addr, &optlen) < 0)
64 {
65 perror("Can't get local address");
66 return -1;
67 }
68
69 ba2str(&addr.l2_bdaddr, tmp);
70
71 send_cmd = (l2cap_cmd_hdr *) send_buf;
72 send_cmd->ident = 200;
73 send_cmd->len = htobs(1);
74 send_cmd->code = L2CAP_ECHO_REQ;
75 send_buf[L2CAP_CMD_HDR_SIZE] = 'A';
76
77 if (send(fd, send_buf, L2CAP_CMD_HDR_SIZE + 1, 0) <= 0)
78 {
79 perror("Send failed");
80 return -1;
81 }
82
83 if (recv(fd, recv_buf, L2CAP_CMD_HDR_SIZE + 1, 0) < 0)
84 {
85 perror("Recv failed");
86 return -1;
87 }
88
89 recv_cmd = (l2cap_cmd_hdr *) recv_buf;
90 recv_cmd->len = btohs(recv_cmd->len);
91 if (recv_cmd->ident != 200)
92 return -1; /* Wrong packet */
93
94 close(fd);
95
96 return ecore_time_get() - start;
97#else
98 fprintf(stderr, "e_sys_l2ping nop\n");
99 return -1;
100#endif
101}
diff --git a/src/bin/e_sys_main.c b/src/bin/e_sys_main.c
index 747836dca..180570670 100644
--- a/src/bin/e_sys_main.c
+++ b/src/bin/e_sys_main.c
@@ -16,6 +16,8 @@
16#endif 16#endif
17#include <Eina.h> 17#include <Eina.h>
18 18
19double e_sys_l2ping(const char *bluetooth_mac);
20
19/* local subsystem functions */ 21/* local subsystem functions */
20#ifdef HAVE_EEZE_MOUNT 22#ifdef HAVE_EEZE_MOUNT
21static Eina_Bool mountopts_check(const char *opts); 23static Eina_Bool mountopts_check(const char *opts);
@@ -88,6 +90,11 @@ main(int argc,
88 90
89 output = argv[3]; 91 output = argv[3];
90 } 92 }
93 else if (!strcmp(argv[1], "l2ping"))
94 {
95 action = argv[1];
96 output = argv[2];
97 }
91#ifdef HAVE_EEZE_MOUNT 98#ifdef HAVE_EEZE_MOUNT
92 else 99 else
93 { 100 {
@@ -173,6 +180,18 @@ main(int argc,
173 180
174 exit(WEXITSTATUS(r)); 181 exit(WEXITSTATUS(r));
175 } 182 }
183 else if (!test && !strcmp(action, "l2ping"))
184 {
185 char tmp[128];
186 double latency;
187
188 latency = e_sys_l2ping(output);
189
190 eina_convert_dtoa(latency, tmp);
191 fprintf(stdout, tmp);
192
193 return (latency < 0) ? 1 : 0;
194 }
176 if ((!test) 195 if ((!test)
177#ifdef HAVE_EEZE_MOUNT 196#ifdef HAVE_EEZE_MOUNT
178 && (!mnt) 197 && (!mnt)
diff --git a/src/modules/bluez4/e_mod_main.c b/src/modules/bluez4/e_mod_main.c
index f294ae9e9..594a3a0ee 100644
--- a/src/modules/bluez4/e_mod_main.c
+++ b/src/modules/bluez4/e_mod_main.c
@@ -4,6 +4,14 @@
4#include "ebluez4.h" 4#include "ebluez4.h"
5 5
6/* Local Variables */ 6/* Local Variables */
7static Ecore_Exe *autolock_exe = NULL;
8static Ecore_Poller *autolock_poller = NULL;
9static Ecore_Event_Handler *autolock_die = NULL;
10static Ecore_Event_Handler *autolock_out = NULL;
11static Ecore_Event_Handler *autolock_desklock = NULL;
12static Eina_Bool autolock_initted = EINA_FALSE;
13static Eina_Bool autolock_waiting = EINA_TRUE;
14
7static Eina_List *instances = NULL; 15static Eina_List *instances = NULL;
8static E_Module *mod = NULL; 16static E_Module *mod = NULL;
9static char tmpbuf[1024]; 17static char tmpbuf[1024];
@@ -15,6 +23,42 @@ Config *ebluez4_config = NULL;
15EAPI E_Module_Api e_modapi = {E_MODULE_API_VERSION, "Bluez4"}; 23EAPI E_Module_Api e_modapi = {E_MODULE_API_VERSION, "Bluez4"};
16 24
17/* Local Functions */ 25/* Local Functions */
26static Eina_Bool
27_ebluez_l2ping_poller(void *data EINA_UNUSED)
28{
29 Eina_Strbuf *buf;
30 const char *tmp = NULL;
31
32 autolock_poller = NULL;
33
34 buf = eina_strbuf_new();
35 if (e_desklock_state_get())
36 {
37 if (!autolock_waiting)
38 tmp = ebluez4_config->unlock_dev_addr;
39 else
40 tmp = ebluez4_config->lock_dev_addr;
41 }
42 else
43 {
44 if (!autolock_waiting)
45 tmp = ebluez4_config->lock_dev_addr;
46 else
47 tmp = ebluez4_config->unlock_dev_addr;
48 }
49
50 if (tmp)
51 {
52 eina_strbuf_append_printf(buf, "%s/enlightenment/utils/enlightenment_sys l2ping %s",
53 e_prefix_lib_get(), tmp);
54 autolock_exe = ecore_exe_run(eina_strbuf_string_get(buf), NULL);
55 }
56
57 eina_strbuf_free(buf);
58
59 return 0;
60}
61
18static void 62static void
19_ebluez4_search_dialog_del(Instance *inst) 63_ebluez4_search_dialog_del(Instance *inst)
20{ 64{
@@ -262,9 +306,15 @@ _ebluez4_cb_lock(void *data,
262 int tog; 306 int tog;
263 307
264 tog = e_menu_item_toggle_get(mi); 308 tog = e_menu_item_toggle_get(mi);
265 eina_stringshare_replace(&ebluez4_config->lock_dev_name, 309 eina_stringshare_replace(&ebluez4_config->lock_dev_addr,
266 tog ? dev->name : NULL); 310 tog ? dev->addr : NULL);
267 e_config_save_queue(); 311 e_config_save_queue();
312
313 if (autolock_exe)
314 ecore_exe_kill(autolock_exe);
315 autolock_exe = NULL;
316 if (!autolock_poller && (ebluez4_config->lock_dev_addr || ebluez4_config->unlock_dev_addr))
317 autolock_poller = ecore_poller_add(ECORE_POLLER_CORE, 32, _ebluez_l2ping_poller, NULL);
268} 318}
269 319
270static void 320static void
@@ -276,9 +326,15 @@ _ebluez4_cb_unlock(void *data,
276 int tog; 326 int tog;
277 327
278 tog = e_menu_item_toggle_get(mi); 328 tog = e_menu_item_toggle_get(mi);
279 eina_stringshare_replace(&ebluez4_config->unlock_dev_name, 329 eina_stringshare_replace(&ebluez4_config->unlock_dev_addr,
280 tog ? dev->name : NULL); 330 tog ? dev->addr : NULL);
281 e_config_save_queue(); 331 e_config_save_queue();
332
333 if (autolock_exe)
334 ecore_exe_kill(autolock_exe);
335 autolock_exe = NULL;
336 if (!autolock_poller && (ebluez4_config->lock_dev_addr || ebluez4_config->unlock_dev_addr))
337 autolock_poller = ecore_poller_add(ECORE_POLLER_CORE, 32, _ebluez_l2ping_poller, NULL);
282} 338}
283 339
284static void 340static void
@@ -348,22 +404,27 @@ _ebluez4_add_devices(Instance *inst)
348 e_menu_item_label_set(submi, "Forget"); 404 e_menu_item_label_set(submi, "Forget");
349 e_menu_item_callback_set(submi, _ebluez4_cb_forget, dev); 405 e_menu_item_callback_set(submi, _ebluez4_cb_forget, dev);
350 406
351 /* Auto lock when away */ 407#ifdef HAVE_BLUETOOTH
352 submi = e_menu_item_new(subm); 408 if (autolock_initted)
353 e_menu_item_check_set(submi, 1); 409 {
354 e_menu_item_label_set(submi, "Lock on disconnect"); 410 /* Auto lock when away */
355 e_menu_item_callback_set(submi, _ebluez4_cb_lock, dev); 411 submi = e_menu_item_new(subm);
356 chk = ebluez4_config->lock_dev_name && dev->name && 412 e_menu_item_check_set(submi, 1);
357 !strcmp(dev->name, ebluez4_config->lock_dev_name); 413 e_menu_item_label_set(submi, "Lock on disconnect");
358 e_menu_item_toggle_set(submi, !!chk); 414 e_menu_item_callback_set(submi, _ebluez4_cb_lock, dev);
359 415 chk = ebluez4_config->lock_dev_addr && dev->addr &&
360 submi = e_menu_item_new(subm); 416 !strcmp(dev->addr, ebluez4_config->lock_dev_addr);
361 e_menu_item_check_set(submi, 1); 417 e_menu_item_toggle_set(submi, !!chk);
362 e_menu_item_label_set(submi, "Unlock on disconnect"); 418
363 e_menu_item_callback_set(submi, _ebluez4_cb_unlock, dev); 419 submi = e_menu_item_new(subm);
364 chk = ebluez4_config->unlock_dev_name && dev->name && 420 e_menu_item_check_set(submi, 1);
365 !strcmp(dev->name, ebluez4_config->unlock_dev_name); 421 e_menu_item_label_set(submi, "Unlock on disconnect");
366 e_menu_item_toggle_set(submi, !!chk); 422 e_menu_item_callback_set(submi, _ebluez4_cb_unlock, dev);
423 chk = ebluez4_config->unlock_dev_addr && dev->addr &&
424 !strcmp(dev->addr, ebluez4_config->unlock_dev_addr);
425 e_menu_item_toggle_set(submi, !!chk);
426 }
427#endif
367 } 428 }
368 429
369 return ret; 430 return ret;
@@ -520,10 +581,93 @@ static const E_Gadcon_Client_Class _gc_class =
520 E_GADCON_CLIENT_STYLE_PLAIN 581 E_GADCON_CLIENT_STYLE_PLAIN
521}; 582};
522 583
584static Eina_Bool
585_ebluez_exe_die(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *event_info)
586{
587 Ecore_Exe_Event_Del *ev = event_info;
588
589 if (ev->exe != autolock_exe)
590 return ECORE_CALLBACK_PASS_ON;
591
592 if (!autolock_initted)
593 {
594 if (ev->exit_code == 0)
595 {
596 autolock_initted = EINA_TRUE;
597 }
598 }
599 else
600 {
601 if (e_desklock_state_get()) // Locked state ?
602 {
603 if (!autolock_waiting)
604 {
605 // Not waiting yet for the auto unlock device to appear before unlock
606 if (ev->exit_code == 0 && ebluez4_config->unlock_dev_addr)
607 {
608 e_desklock_hide();
609 }
610 }
611 else if (ev->exit_code == 1)
612 {
613 // The device just disapeared, now we can wait for it to disapear
614 autolock_waiting = EINA_FALSE;
615 }
616 }
617 else
618 {
619 if (!autolock_waiting)
620 {
621 // Not waiting yet for the auto lock device to disappear before locking
622 if (ev->exit_code == 1 && ebluez4_config->lock_dev_addr)
623 {
624 e_desklock_show(EINA_FALSE);
625 }
626 }
627 else if (ev->exit_code == 0)
628 {
629 // The device just appeared, now we can wait for it to disapear
630 autolock_waiting = EINA_FALSE;
631 }
632 }
633 }
634
635 if (autolock_initted)
636 autolock_poller = ecore_poller_add(ECORE_POLLER_CORE, 32, _ebluez_l2ping_poller, NULL);
637
638 autolock_exe = NULL;
639
640 return ECORE_CALLBACK_PASS_ON;
641}
642
643static Eina_Bool
644_ebluez_exe_out(void *data, int ev_type, void *ev)
645{
646 /* FIXME: Need experiment, but we should be able to use latency to somehow estimate distance, right ? */
647 return ECORE_CALLBACK_PASS_ON;
648}
649
650static Eina_Bool
651_ebluez_desklock(void *data, int ev_type, void *ev)
652{
653 if (autolock_exe)
654 ecore_exe_kill(autolock_exe);
655 autolock_exe = NULL;
656
657 if (!autolock_poller && autolock_initted && (ebluez4_config->lock_dev_addr || ebluez4_config->unlock_dev_addr))
658 autolock_poller = ecore_poller_add(ECORE_POLLER_CORE, 32, _ebluez_l2ping_poller, NULL);
659
660 autolock_waiting = EINA_TRUE;
661
662 return ECORE_CALLBACK_PASS_ON;
663}
664
523/* Module Functions */ 665/* Module Functions */
524EAPI void * 666EAPI void *
525e_modapi_init(E_Module *m) 667e_modapi_init(E_Module *m)
526{ 668{
669 Eina_Strbuf *buf;
670
527 mod = m; 671 mod = m;
528 672
529 conf_edd = E_CONFIG_DD_NEW("Config", Config); 673 conf_edd = E_CONFIG_DD_NEW("Config", Config);
@@ -531,8 +675,8 @@ e_modapi_init(E_Module *m)
531#undef D 675#undef D
532#define T Config 676#define T Config
533#define D conf_edd 677#define D conf_edd
534 E_CONFIG_VAL(D, T, lock_dev_name, STR); 678 E_CONFIG_VAL(D, T, lock_dev_addr, STR);
535 E_CONFIG_VAL(D, T, unlock_dev_name, STR); 679 E_CONFIG_VAL(D, T, unlock_dev_addr, STR);
536 680
537 ebluez4_config = e_config_domain_load("module.ebluez4", conf_edd); 681 ebluez4_config = e_config_domain_load("module.ebluez4", conf_edd);
538 if (!ebluez4_config) 682 if (!ebluez4_config)
@@ -542,6 +686,16 @@ e_modapi_init(E_Module *m)
542 686
543 e_gadcon_provider_register(&_gc_class); 687 e_gadcon_provider_register(&_gc_class);
544 688
689 autolock_die = ecore_event_handler_add(ECORE_EXE_EVENT_DEL, _ebluez_exe_die, NULL);
690 autolock_out = ecore_event_handler_add(ECORE_EXE_EVENT_DATA, _ebluez_exe_out, NULL);
691 autolock_desklock = ecore_event_handler_add(E_EVENT_DESKLOCK, _ebluez_desklock, NULL);
692
693 buf = eina_strbuf_new();
694 eina_strbuf_append_printf(buf, "%s/enlightenment/utils/enlightenment_sys -t l2ping",
695 e_prefix_lib_get());
696 autolock_exe = ecore_exe_run(eina_strbuf_string_get(buf), NULL);
697 eina_strbuf_free(buf);
698
545 return m; 699 return m;
546} 700}
547 701
@@ -550,8 +704,17 @@ e_modapi_shutdown(E_Module *m)
550{ 704{
551 E_CONFIG_DD_FREE(conf_edd); 705 E_CONFIG_DD_FREE(conf_edd);
552 706
553 eina_stringshare_del(ebluez4_config->lock_dev_name); 707 if (autolock_exe) ecore_exe_kill(autolock_exe);
554 eina_stringshare_del(ebluez4_config->unlock_dev_name); 708 autolock_exe = NULL;
709 if (autolock_poller) ecore_timer_del(autolock_poller);
710 autolock_poller = NULL;
711
712 ecore_event_handler_del(autolock_die);
713 ecore_event_handler_del(autolock_out);
714 ecore_event_handler_del(autolock_desklock);
715
716 eina_stringshare_del(ebluez4_config->lock_dev_addr);
717 eina_stringshare_del(ebluez4_config->unlock_dev_addr);
555 free(ebluez4_config); 718 free(ebluez4_config);
556 ebluez4_config = NULL; 719 ebluez4_config = NULL;
557 720
diff --git a/src/modules/bluez4/e_mod_main.h b/src/modules/bluez4/e_mod_main.h
index c8d713b60..dc48b3d2c 100644
--- a/src/modules/bluez4/e_mod_main.h
+++ b/src/modules/bluez4/e_mod_main.h
@@ -16,8 +16,8 @@ struct _Instance
16typedef struct _Config Config; 16typedef struct _Config Config;
17struct _Config 17struct _Config
18{ 18{
19 const char *lock_dev_name; 19 const char *lock_dev_addr;
20 const char *unlock_dev_name; 20 const char *unlock_dev_addr;
21}; 21};
22 22
23extern Config *ebluez4_config; 23extern Config *ebluez4_config;
diff --git a/src/modules/bluez4/ebluez4.c b/src/modules/bluez4/ebluez4.c
index 2347808d1..e10ccbe48 100644
--- a/src/modules/bluez4/ebluez4.c
+++ b/src/modules/bluez4/ebluez4.c
@@ -385,10 +385,6 @@ _on_removed(void *context, const EDBus_Message *msg)
385 fdev = eina_list_search_unsorted(ctxt->found_devices, _dev_addr_cmp, 385 fdev = eina_list_search_unsorted(ctxt->found_devices, _dev_addr_cmp,
386 dev->addr); 386 dev->addr);
387 387
388 if (dev->name && ebluez4_config->lock_dev_name &&
389 !strcmp(dev->name, ebluez4_config->lock_dev_name))
390 e_desklock_show(EINA_FALSE);
391
392 _unset_dev(dev, &ctxt->devices); 388 _unset_dev(dev, &ctxt->devices);
393 _unset_dev(fdev, &ctxt->found_devices); 389 _unset_dev(fdev, &ctxt->found_devices);
394} 390}
@@ -427,10 +423,6 @@ _on_device_found(void *context, const EDBus_Message *msg)
427 dev->paired = paired; 423 dev->paired = paired;
428 ctxt->found_devices = eina_list_append(ctxt->found_devices, dev); 424 ctxt->found_devices = eina_list_append(ctxt->found_devices, dev);
429 425
430 if (dev->name && ebluez4_config->unlock_dev_name &&
431 !strcmp(dev->name, ebluez4_config->unlock_dev_name))
432 e_desklock_hide();
433
434 ebluez4_update_instances(ctxt->found_devices); 426 ebluez4_update_instances(ctxt->found_devices);
435} 427}
436 428