/
mce-sensorfw.c
3425 lines (2737 loc) · 94.2 KB
/
mce-sensorfw.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/**
* @file mce-sensorfw.c
*
* Mode Control Entity - Interprocess communication with sensord
*
* <p>
*
* Copyright (C) 2013-2014 Jolla Ltd.
*
* <p>
*
* @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
*
* mce is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* mce is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with mce. If not, see <http://www.gnu.org/licenses/>.
*/
#include "mce-sensorfw.h"
#include "mce.h"
#include "mce-log.h"
#include "mce-dbus.h"
#include "libwakelock.h"
#include <linux/input.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <inttypes.h>
/* ========================================================================= *
*
* Internal Layering - Top-Down
*
* ========================================================================= *
*
* SENSORFW_MODULE:
* - implements internal mce interface defined in mce-sensorfw.h
*
* SENSORFW_SERVICE:
* - state machine that tracks availablity of sensord on system bus
* - availalibility changes trigger activity in SENSORFW_PLUGIN
*
* SENSORFW_PLUGIN:
* - state machine that takes care of sensord plugin loading ipc
* - one instance / sensor
* - finishing plugin loading triggers activity in SENSORFW_SESSION
*
* SENSORFW_SESSION:
* - state machine that takes care of data session start ipc
* - one instance / sensor
* - acquiring a session id triggers activity in SENSORFW_CONNECTION
*
* SENSORFW_CONNECTION:
* - state machine that takes care of data connection with sensord
* - one instance / sensor
* - establishing a connection triggers activity in SENSORFW_OVERRIDE
* and SENSORFW_REPORTING
*
* SENSORFW_OVERRIDE:
* - state machine that takes care of standby override ipc
* - one instance / sensor
*
*
* SENSORFW_REPORTING:
* - state machine that takes care of sensor start/stop ipc
* - one instance / sensor
* - value changes reported via sensor specific SENSORFW_BACKEND
*
* SENSORFW_BACKEND:
* - contains all sensor specific constants and logic
*
* SENSORFW_NOTIFY:
* - manages cached sensor state
* - provides default values used when sensord is not available
* - feeds sensor data to upper level logic when state changes
* and/or listening callbacks are registered
*
* Error handling:
* - The layer where error occurred makes transition to ERROR state
* and all layers below that are reset to IDLE state and sensor
* states are reverted to sensord-is-not-available defaults.
* - At least initially sensord restart is needed for full recovery.
*
* State transitions:
* - state transition diagram can be generated from mce-sensorfw.dot
* via installing graphviz package and running from command line
* dot -Tpng mce-sensorfw.dot -o mce-sensorfw.png
*
* ========================================================================= *
*
* Rough Data/Control Flow Diagram - Error Handling and EVDEV Input Excluded
*
* ========================================================================= *
*
* .--------------------. .--------------------.
* | MCE INIT/EXIT | | MCE SENSOR LOGIC |
* `--------------------' `--------------------'
* | |
* | init/quit enable/disable |
* | |
* v v
* .--------------------------------------------.
* | SENSORFW_MODULE |
* `--------------------------------------------'
* | |
* | probe/reset enable/disable |
* | |
* v v
* .--------------------------------------------.
* | SENSORFW_SERVICE |
* `--------------------------------------------'
* | | |
* | load/reset set/unset | |
* | | | start/stop
* v | |
* .------------------------------. | |
* | SENSORFW_PLUGIN | | |
* `------------------------------' | |
* | | |
* | start/reset | |
* | | |
* v | |
* .------------------------------. | |
* | SENSORFW_SESSION | | |
* `------------------------------' | |
* | | |
* | connect/reset | |
* | | |
* v | |
* .------------------------------. | |
* | SENSORFW_CONNECTION | | |
* `------------------------------' | |
* | | | |
* | rethink/reset | | |
* | | | |
* | rethink/reset | | |
* | | | |
* | v v |
* | .--------------------------------. |
* | | SENSORFW_OVERRIDE | |
* | `--------------------------------' |
* v v
* .--------------------------------------------.
* | SENSORFW_REPORTING |
* `--------------------------------------------'
* |
* | initial/change/reset
* |
* v
* .--------------------------------------------.
* | SENSORFW_BACKEND |
* `--------------------------------------------'
* |
* | sensor state
* |
* v
* .--------------------------------------------.
* | SENSORFW_NOTIFY |
* `--------------------------------------------'
* |
* | sensor state
* |
* v
* .--------------------------------------------.
* | MCE SENSOR LOGIC |
* `--------------------------------------------'
*
* ========================================================================= */
/* ========================================================================= *
* D-BUS CONSTANTS FOR D-BUS DAEMON
* ========================================================================= */
/** org.freedesktop.DBus.NameOwnerChanged D-Bus signal */
#define DBUS_SIGNAL_NAME_OWNER_CHANGED "NameOwnerChanged"
#define DBUS_METHOD_GET_NAME_OWNER "GetNameOwner"
/* ========================================================================= *
* D-BUS CONSTANTS FOR SENSORD SERVICE
* ========================================================================= */
/** D-Bus name of the sensord service */
#define SENSORFW_SERVICE "com.nokia.SensorService"
// ----------------------------------------------------------------
/** D-Bus object path for sensord sensor manager */
#define SENSORFW_MANAGER_OBJECT "/SensorManager"
/** D-Bus interface used by sensor manager */
#define SENSORFW_MANAGER_INTEFCACE "local.SensorManager"
/** D-Bus method for loading sensor plugin */
#define SENSORFW_MANAGER_METHOD_LOAD_PLUGIN "loadPlugin"
/** D-Bus method for starting sensor session */
#define SENSORFW_MANAGER_METHOD_START_SESSION "requestSensor"
// ----------------------------------------------------------------
/* Note: Every sensor has unique object path & interface */
/** D-Bus interface used by proximity sensor plugin */
#define SENSORFW_SENSOR_INTERFACE_PS "local.ProximitySensor"
/** D-Bus interface used by ambient light sensor plugin */
#define SENSORFW_SENSOR_INTERFACE_ALS "local.ALSSensor"
/** D-Bus interface used by orientation sensor plugin */
#define SENSORFW_SENSOR_INTERFACE_ORIENT "local.OrientationSensor"
/* Common methods supported by all sensor interfaces */
/** D-Bus method for enabling sensor */
#define SENSORFW_SENSOR_METHOD_START "start"
/** D-Bus method for disabling sensor */
#define SENSORFW_SENSOR_METHOD_STOP "stop"
/** D-Bus method for changing sensor standby override */
#define SENSORFW_SENSOR_METHOD_SET_OVERRIDE "setStandbyOverride"
/* Note: The sensor specific methods for reading current state
* differ only by method name, so common logic can stll be
* used for making the queries and processing the replies. */
/** D-Bus method for reading intial proximity state */
#define SENSORFW_SENSOR_METHOD_READ_PS "proximity"
/** D-Bus method for reading intial ambient light state */
#define SENSORFW_SENSOR_METHOD_READ_ALS "lux"
/** D-Bus method for reading intial orientation state */
#define SENSORFW_SENSOR_METHOD_READ_ORIENT "orientation"
// ----------------------------------------------------------------
/** Connect path to sensord data unix domain socket */
#define SENSORFW_DATA_SOCKET "/var/run/sensord.sock"
// ----------------------------------------------------------------
/** Name of proximity sensor */
#define SENSORFW_SENSOR_NAME_PS "proximitysensor"
/** Name of ambient light sensor */
#define SENSORFW_SENSOR_NAME_ALS "alssensor"
/** Name of orientation sensor */
#define SENSORFW_SENSOR_NAME_ORIENT "orientationsensor"
/* ========================================================================= *
* FORWARD_DECLARATIONS
* ========================================================================= */
typedef struct sfw_service_t sfw_service_t;
typedef struct sfw_plugin_t sfw_plugin_t;
typedef struct sfw_session_t sfw_session_t;
typedef struct sfw_connection_t sfw_connection_t;
typedef struct sfw_override_t sfw_override_t;
typedef struct sfw_reporting_t sfw_reporting_t;
typedef struct sfw_backend_t sfw_backend_t;
typedef struct sfw_sample_als_t sfw_sample_als_t;
typedef struct sfw_sample_ps_t sfw_sample_ps_t;
typedef struct sfw_sample_orient_t sfw_sample_orient_t;
/* ========================================================================= *
* SENSORD_DATA_TYPES
* ========================================================================= */
/** ALS data block as sensord sends them */
struct sfw_sample_als_t
{
/** microseconds, monotonic */
uint64_t als_timestamp;
/** amount of light [lux] */
uint32_t als_value;
};
/** PS data block as sensord sends them */
struct sfw_sample_ps_t
{
/** microseconds, monotonic */
uint64_t ps_timestamp;
/** distance of blocking object [cm] */
uint32_t ps_value;
/** sensor covered [bool]
*
* This should be the size of a C++ bool on the same platform.
* Unfortunately there's no way to find out in a C program
*/
uint8_t ps_withinProximity;
};
/** Orientation data block as sensord sends them */
struct sfw_sample_orient_t
{
/* microseconds, monotonic */
uint64_t orient_timestamp;
/* orientation [enum orientation_state_t] */
int32_t orient_state;
};
/* ========================================================================= *
* SENSORFW_BACKEND
* ========================================================================= */
/** Callback function type: initial value reporting */
typedef void (*sfw_value_fn)(sfw_plugin_t *plugin, unsigned value);
/** Callback function type: value change reporting */
typedef void (*sfw_sample_fn)(sfw_plugin_t *plugin, const void *sample);
/** Callback function type: value reset reporting */
typedef void (*sfw_reset_fn)(sfw_plugin_t *plugin);
/** Sensor specific data and callbacks */
struct sfw_backend_t
{
/** Name of the sensor as expected by sensord */
const char *be_sensor_name;
/** D-Bus object path for the sensor, or NULL to construct default one */
const char *be_sensor_object;
/** D-Bus interface for the sensor */
const char *be_sensor_interface;
/** Size of sensor data blobs sensord will be sending */
size_t be_sample_size;
/** Callback for handling sensor data blob */
sfw_sample_fn be_sample_cb;
/** D-Bus method name for querying the initial sensor value */
const char *be_value_method;
/** Callback for handling received initial sensor value */
sfw_value_fn be_value_cb;
/** Callback for resetting sensor value back to default */
sfw_reset_fn be_reset_cb;
};
/* ========================================================================= *
* SENSORFW_HELPERS
* ========================================================================= */
static bool sfw_socket_set_blocking (int fd, bool blocking);
static int sfw_socket_open (void);
static guint sfw_socket_add_notify (int fd, bool close_on_unref, GIOCondition cnd, GIOFunc io_cb, gpointer aptr);
/* ========================================================================= *
* SENSORFW_REPORTING
* ========================================================================= */
typedef enum
{
/** Sensord is not available */
REPORTING_IDLE,
/** Choose between start() and stop() */
REPORTING_RETHINK,
/** Waiting a reply to start() */
REPORTING_ENABLING,
/** Sensor started succesfully */
REPORTING_ENABLED,
/** Waiting a reply to stop() */
REPORTING_DISABLING,
/** Sensor stopped succesfully */
REPORTING_DISABLED,
/** Something went wrong */
REPORTING_ERROR,
REPORTING_NUMSTATES
} sfw_reporting_state_t;
/** State machine for handling sensor start/stop */
struct sfw_reporting_t
{
/** Pointer to containing plugin object */
sfw_plugin_t *rep_plugin;
/** Current reporting state */
sfw_reporting_state_t rep_state;
/** Pending start/stop dbus method call */
DBusPendingCall *rep_change_pc;
/** Pending initial value dbus method call */
DBusPendingCall *rep_value_pc;
/** Flag for: MCE wants sensor to be enabled */
bool rep_target;
};
static const char *sfw_reporting_state_name (sfw_reporting_state_t state);
static sfw_reporting_t *sfw_reporting_create (sfw_plugin_t *plugin);
static void sfw_reporting_delete (sfw_reporting_t *self);
static void sfw_reporting_cancel_change (sfw_reporting_t *self);
static void sfw_reporting_cancel_value (sfw_reporting_t *self);
static void sfw_reporting_trans (sfw_reporting_t *self, sfw_reporting_state_t state);
static void sfw_reporting_change_cb (DBusPendingCall *pc, void *aptr);
static void sfw_reporting_value_cb (DBusPendingCall *pc, void *aptr);
static void sfw_reporting_do_rethink (sfw_reporting_t *self);
static void sfw_reporting_do_start (sfw_reporting_t *self);
static void sfw_reporting_do_reset (sfw_reporting_t *self);
static void sfw_reporting_set_target (sfw_reporting_t *self, bool enable);
/* ========================================================================= *
* SENSORFW_OVERRIDE
* ========================================================================= */
typedef enum {
/** Sensord is not available */
OVERRIDE_IDLE,
/** Choose between standby override set/unset */
OVERRIDE_RETHINK,
/** Waiting for a reply to set standby override */
OVERRIDE_ENABLING,
/** Standby override succesfully set */
OVERRIDE_ENABLED,
/** Waiting for a reply to unset standby override */
OVERRIDE_DISABLING,
/** Standby override succesfully unset */
OVERRIDE_DISABLED,
/** Something went wrong */
OVERRIDE_ERROR,
OVERRIDE_NUMSTATES
} sfw_override_state_t;
/** State machine for handling sensor standby override */
struct sfw_override_t
{
/** Pointer to containing plugin object */
sfw_plugin_t *ovr_plugin;
/** Current override state */
sfw_override_state_t ovr_state;
/** Pending standby override set/unset method call */
DBusPendingCall *ovr_start_pc;
/** Flag for: MCE wants standby override to be set */
bool ovr_target;
};
static const char *sfw_override_state_name (sfw_override_state_t state);
static sfw_override_t *sfw_override_create (sfw_plugin_t *plugin);
static void sfw_override_delete (sfw_override_t *self);
static void sfw_override_cancel_start (sfw_override_t *self);
static void sfw_override_trans (sfw_override_t *self, sfw_override_state_t state);
static void sfw_override_start_cb (DBusPendingCall *pc, void *aptr);
static void sfw_override_do_rethink (sfw_override_t *self);
static void sfw_override_do_start (sfw_override_t *self);
static void sfw_override_do_reset (sfw_override_t *self);
static void sfw_override_set_target (sfw_override_t *self, bool enable);
/* ========================================================================= *
* SENSORFW_CONNECTION
* ========================================================================= */
typedef enum
{
/** Sensord is not available */
CONNECTION_IDLE,
/** Waiting for data socket to come writable */
CONNECTION_CONNECTING,
/** Waiting for handshake reply */
CONNECTION_REGISTERING,
/** Waiting for sensor data */
CONNECTION_CONNECTED,
/** Something went wrong */
CONNECTION_ERROR,
CONNECTION_NUMSTATES
} sfw_connection_state_t;
/** State machine for handling sensor data connection */
struct sfw_connection_t
{
/** Pointer to containing plugin object */
sfw_plugin_t *con_plugin;
/** Current connection state */
sfw_connection_state_t con_state;
/** File descriptor for data socket */
int con_fd;
/** I/O watch id id for: ready to write */
guint con_rx_id;
/** I/O watch id id for: data available */
guint con_tx_id;
};
static const char *sfw_connection_state_name (sfw_connection_state_t state);
static sfw_connection_t *sfw_connection_create (sfw_plugin_t *plugin);
static void sfw_connection_delete (sfw_connection_t *self);
static bool sfw_connection_handle_samples (sfw_connection_t *self, char *data, size_t size);
static int sfw_connection_get_session_id (const sfw_connection_t *self);
static bool sfw_connection_tx_req (sfw_connection_t *self);
static bool sfw_connection_rx_ack (sfw_connection_t *self);
static bool sfw_connection_rx_dta (sfw_connection_t *self);
static gboolean sfw_connection_tx_cb (GIOChannel *chn, GIOCondition cnd, gpointer aptr);
static gboolean sfw_connection_rx_cb (GIOChannel *chn, GIOCondition cnd, gpointer aptr);
static void sfw_connection_remove_tx_notify(sfw_connection_t *self);
static void sfw_connection_remove_rx_notify(sfw_connection_t *self);
static void sfw_connection_close_socket (sfw_connection_t *self);
static bool sfw_connection_open_socket (sfw_connection_t *self);
static void sfw_connection_trans (sfw_connection_t *self, sfw_connection_state_t state);
static void sfw_connection_do_start (sfw_connection_t *self);
static void sfw_connection_do_reset (sfw_connection_t *self);
/* ========================================================================= *
* SENSORFW_SESSION
* ========================================================================= */
typedef enum
{
/** Sensord is not available */
SESSION_IDLE,
/** Waiting for session id reply */
SESSION_REQUESTING,
/** Have a session id */
SESSION_ACTIVE,
/** Something went wrong */
SESSION_ERROR,
SESSION_NUMSTATES
} sfw_session_state_t;
/** State machine for handling sensor data session */
struct sfw_session_t
{
/** Pointer to containing plugin object */
sfw_plugin_t *ses_plugin;
/** Current session state */
sfw_session_state_t ses_state;
/** Pending session start dbus method call */
DBusPendingCall *ses_start_pc;
/** Session ID received from sensord */
dbus_int32_t ses_id;
};
static const char *sfw_session_state_name (sfw_session_state_t state);
static sfw_session_t *sfw_session_create (sfw_plugin_t *plugin);
static void sfw_session_delete (sfw_session_t *self);
static int sfw_session_get_id (const sfw_session_t *self);
static void sfw_session_cancel_start (sfw_session_t *self);
static void sfw_session_trans (sfw_session_t *self, sfw_session_state_t state);
static void sfw_session_start_cb (DBusPendingCall *pc, void *aptr);
static void sfw_session_do_start (sfw_session_t *self);
static void sfw_session_do_reset (sfw_session_t *self);
/* ========================================================================= *
* SENSORFW_PLUGIN
* ========================================================================= */
typedef enum
{
/** Sensord is not available */
PLUGIN_IDLE,
/** Waiting for a reply to plugin load method call */
PLUGIN_LOADING,
/** Sensor plugin is loaded */
PLUGIN_LOADED,
/** Something went wrong */
PLUGIN_ERROR,
PLUGIN_NUMSTATES
} sfw_plugin_state_t;
/** State machine for handling sensor plugin loading */
struct sfw_plugin_t
{
/** Sensor specific backend data & callbacks */
const sfw_backend_t *plg_backend;
/** Default sensor specific D-BUs object path
*
* Constructed if backend does not define one explicitly */
char *plg_sensor_object;
/** Current plugin state */
sfw_plugin_state_t plg_state;
/** Pending plugin load dbus method call */
DBusPendingCall *plg_load_pc;
/** Session state machine object */
sfw_session_t *plg_session;
/** Connection state machine object */
sfw_connection_t *plg_connection;
/** Standby override state machine object */
sfw_override_t *plg_override;
/** Sensor reporting state machine object */
sfw_reporting_t *plg_reporting;
};
static const char *sfw_plugin_state_name (sfw_plugin_state_t state);
static sfw_plugin_t *sfw_plugin_create (const sfw_backend_t *backend);
static void sfw_plugin_delete (sfw_plugin_t *self);
static const char *sfw_plugin_get_sensor_name (const sfw_plugin_t *self);
static const char *sfw_plugin_get_sensor_object (const sfw_plugin_t *self);
static const char *sfw_plugin_get_sensor_interface(const sfw_plugin_t *self);
static int sfw_plugin_get_session_id (const sfw_plugin_t *self);
static const char *sfw_plugin_get_value_method (const sfw_plugin_t *self);
static size_t sfw_plugin_get_sample_size (const sfw_plugin_t *self);
static void sfw_plugin_handle_sample (sfw_plugin_t *self, const void *sample);
static void sfw_plugin_handle_value (sfw_plugin_t *self, unsigned value);
static void sfw_plugin_reset_value (sfw_plugin_t *self);
static void sfw_plugin_cancel_load (sfw_plugin_t *self);
static void sfw_plugin_trans (sfw_plugin_t *self, sfw_plugin_state_t state);
static void sfw_plugin_load_cb (DBusPendingCall *pc, void *aptr);
static void sfw_plugin_do_load (sfw_plugin_t *self);
static void sfw_plugin_do_reset (sfw_plugin_t *self);
static void sfw_plugin_do_session_start (sfw_plugin_t *self);
static void sfw_plugin_do_session_reset (sfw_plugin_t *self);
static void sfw_plugin_do_connection_start (sfw_plugin_t *self);
static void sfw_plugin_do_connection_reset (sfw_plugin_t *self);
static void sfw_plugin_do_override_start (sfw_plugin_t *self);
static void sfw_plugin_do_override_reset (sfw_plugin_t *self);
static void sfw_plugin_do_reporting_start (sfw_plugin_t *self);
static void sfw_plugin_do_reporting_reset (sfw_plugin_t *self);
/* ========================================================================= *
* SENSORFW_SERVICE
* ========================================================================= */
typedef enum
{
/** Sensord availability is not known */
SERVICE_IDLE,
/** Waiting for a reply to name owner query */
SERVICE_QUERYING,
/** Sensord service is available */
SERVICE_RUNNING,
/** Sensord service is not available */
SERVICE_STOPPED,
SERVICE_NUMSTATES
} sfw_service_state_t;
/** State machine for handling sensord service availability tracking */
struct sfw_service_t
{
/** Sensord service tracking state */
sfw_service_state_t srv_state;
/** Pending name owner dbus method call */
DBusPendingCall *srv_query_pc;
/** State machine object for proximity sensor */
sfw_plugin_t *srv_ps;
/** State machine object for ambient light sensor */
sfw_plugin_t *srv_als;
/** State machine object for orientation sensor */
sfw_plugin_t *srv_orient;
};
static const char *sfw_service_state_name (sfw_service_state_t state);
static sfw_service_t *sfw_service_create (void);
static void sfw_service_delete (sfw_service_t *self);
static void sfw_service_cancel_query (sfw_service_t *self);
static void sfw_service_query_cb (DBusPendingCall *pc, void *aptr);
static void sfw_service_trans (sfw_service_t *self, sfw_service_state_t state);
static void sfw_service_do_start (sfw_service_t *self);
static void sfw_service_do_stop (sfw_service_t *self);
static void sfw_service_do_query (sfw_service_t *self);
static void sfw_service_set_ps (sfw_service_t *self, bool enable);
static void sfw_service_set_als (sfw_service_t *self, bool enable);
static void sfw_service_set_orient (sfw_service_t *self, bool enable);
/* ========================================================================= *
* SENSORFW_NOTIFY
* ========================================================================= */
/** Proximity state to use when sensor can't be enabled */
#define SWF_NOTIFY_DEFAULT_PS false
/** Ambient light level [lux] to use when sensor can't be enabled */
#define SWF_NOTIFY_DEFAULT_ALS 400
/** Orientation state to use when sensor can't be enabled */
#define SWF_NOTIFY_DEFAULT_ORIENT MCE_ORIENTATION_FACE_UP
/** Dummy sensor value to use when re-sending cached state data */
#define SWF_NOTIFY_DUMMY 0
typedef enum
{
/** Cached sensor state should be reset to default value */
NOTIFY_RESET,
/** Cached sensor state should be sent again */
NOTIFY_REPEAT,
/** Sensor state was received from evdev source */
NOTIFY_EVDEV,
/** Sensor state was received from sensord */
NOTIFY_SENSORD,
NOTIFY_NUMTYPES
} sfw_notify_t;
static gboolean sfw_name_owner_changed_cb (DBusMessage *const msg);
static void sfw_notify_ps (sfw_notify_t type, bool covered);
static void sfw_notify_als (sfw_notify_t type, unsigned lux);
static void sfw_notify_orient (sfw_notify_t type, int state);
/* ========================================================================= *
* SENSORFW_MODULE
* ========================================================================= */
// (exported API defined in "mce-sensorfw.h")
/* ========================================================================= *
* SENSORFW_BACKEND
* ========================================================================= */
/** Callback for handling ambient light events from sensord */
static void
sfw_backend_als_sample_cb(sfw_plugin_t *plugin, const void *sample)
{
(void)plugin;
const sfw_sample_als_t *self = sample;
mce_log(LL_DEBUG, "ALS: time=%"PRIu64" light=%"PRIu32"",
self->als_timestamp, self->als_value);
sfw_notify_als(NOTIFY_SENSORD, self->als_value);
}
/** Callback for handling proximity events from sensord */
static void
sfw_backend_ps_sample_cb(sfw_plugin_t *plugin, const void *sample)
{
(void)plugin;
const sfw_sample_ps_t *self = sample;
mce_log(LL_DEBUG, "PS: time=%"PRIu64" distance=%"PRIu32" proximity=%s",
self->ps_timestamp, self->ps_value,
self->ps_withinProximity ? "true" : "false");
sfw_notify_ps(NOTIFY_SENSORD, self->ps_withinProximity);
}
/** Callback for handling orientation events from sensord */
static void
sfw_backend_orient_sample_cb(sfw_plugin_t *plugin, const void *sample)
{
(void)plugin;
const sfw_sample_orient_t *self = sample;
mce_log(LL_DEBUG, "ORIENT: time=%"PRIu64" state=%"PRId32"",
self->orient_timestamp, self->orient_state);
sfw_notify_orient(NOTIFY_SENSORD, self->orient_state);
}
// ----------------------------------------------------------------
/** Callback for handling reply to ambient light query from sensord */
static void
sfw_backend_als_value_cb(sfw_plugin_t *plugin, unsigned value)
{
(void)plugin;
mce_log(LL_DEBUG, "ALS: initial light=%u", value);
sfw_notify_als(NOTIFY_SENSORD, value);
}
/** Callback for handling reply to proximity query from sensord */
static void
sfw_backend_ps_value_cb(sfw_plugin_t *plugin, unsigned value)
{
(void)plugin;
bool covered = (value < 1);
mce_log(LL_DEBUG, "PS: initial distance=%u proximity=%s",
value, covered ? "true" : "false");
sfw_notify_ps(NOTIFY_SENSORD, covered);
}
/** Callback for handling reply to orientation query from sensord */
static void
sfw_backend_orient_value_cb(sfw_plugin_t *plugin, unsigned value)
{
(void)plugin;
mce_log(LL_DEBUG, "ORIENT: initial state=%u", value);
sfw_notify_orient(NOTIFY_SENSORD, value);
}
// ----------------------------------------------------------------
/** Callback for resetting ambient light state to default */
static void
sfw_backend_als_reset_cb(sfw_plugin_t *plugin)
{
(void)plugin;
mce_log(LL_DEBUG, "ALS: light=reset-to-default");
sfw_notify_als(NOTIFY_RESET, SWF_NOTIFY_DUMMY);
}
/** Callback for resetting proximity state to default */
static void
sfw_backend_ps_reset_cb(sfw_plugin_t *plugin)
{
(void)plugin;
mce_log(LL_DEBUG, "PS: covered=reset-to-default");
sfw_notify_ps(NOTIFY_RESET, SWF_NOTIFY_DUMMY);
}
/** Callback for resetting orientation state to default */
static void
sfw_backend_orient_reset_cb(sfw_plugin_t *plugin)
{
(void)plugin;
mce_log(LL_DEBUG, "ORIENT: state=reset-to-default");
sfw_notify_orient(NOTIFY_RESET, SWF_NOTIFY_DUMMY);
}
// ----------------------------------------------------------------
/** Data and callbacks for proximity sensor */
static const sfw_backend_t sfw_backend_ps =
{
.be_sensor_name = SENSORFW_SENSOR_NAME_PS,
.be_sensor_object = 0,
.be_sensor_interface = SENSORFW_SENSOR_INTERFACE_PS,
.be_sample_size = sizeof(sfw_sample_ps_t),
.be_sample_cb = sfw_backend_ps_sample_cb,
.be_value_method = SENSORFW_SENSOR_METHOD_READ_PS,
.be_value_cb = sfw_backend_ps_value_cb,
.be_reset_cb = sfw_backend_ps_reset_cb,
};
/** Data and callbacks for ambient light sensor */
static const sfw_backend_t sfw_backend_als =
{
.be_sensor_name = SENSORFW_SENSOR_NAME_ALS,
.be_sensor_object = 0,
.be_sensor_interface = SENSORFW_SENSOR_INTERFACE_ALS,
.be_sample_size = sizeof(sfw_sample_als_t),
.be_sample_cb = sfw_backend_als_sample_cb,
.be_value_method = SENSORFW_SENSOR_METHOD_READ_ALS,
.be_value_cb = sfw_backend_als_value_cb,
.be_reset_cb = sfw_backend_als_reset_cb,
};
/** Data and callbacks for orientation sensor */
static const sfw_backend_t sfw_backend_orient =
{
.be_sensor_name = SENSORFW_SENSOR_NAME_ORIENT,
.be_sensor_object = 0,
.be_sensor_interface = SENSORFW_SENSOR_INTERFACE_ORIENT,
.be_sample_size = sizeof(sfw_sample_orient_t),
.be_sample_cb = sfw_backend_orient_sample_cb,
.be_value_method = SENSORFW_SENSOR_METHOD_READ_ORIENT,
.be_value_cb = sfw_backend_orient_value_cb,
.be_reset_cb = sfw_backend_orient_reset_cb,
};
/* ========================================================================= *
* SENSORFW_HELPERS
* ========================================================================= */
/* Set file descriptor to blocking/unblocking state
*/
static bool
sfw_socket_set_blocking(int fd, bool blocking)
{
bool ok = false;
int flags = 0;