2
* Copyright (C) 2013 Canonical Ltd
4
* This program is free software: you can redistribute it and/or modify
5
* it under the terms of the GNU Lesser General Public License version 3 as
6
* published by the Free Software Foundation.
8
* This program is distributed in the hope that it will be useful,
9
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
* GNU Lesser General Public License for more details.
13
* You should have received a copy of the GNU Lesser General Public License
14
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16
* Authored by: Martin Pitt <martin.pitti@ubuntu.com>
19
#include <ubuntu/application/sensors/ubuntu_application_sensors.h>
20
#include <ubuntu/application/sensors/accelerometer.h>
21
#include <ubuntu/application/sensors/proximity.h>
22
#include <ubuntu/application/sensors/light.h>
39
// necessary for functions that return float
40
// pcs attribute (calling convention) is only defined on ARM, avoid warning on
43
#define __SF_FN_ATTR __attribute__((pcs("aapcs")))
49
/***************************************
51
* test sensor implementation
53
***************************************/
55
// this is only internal API, so we make everything public
58
TestSensor(ubuntu_sensor_type _type, float _min_value, float _max_value, float _resolution) :
61
resolution(_resolution),
63
min_value(_min_value),
64
max_value(_max_value),
66
event_cb_context(NULL),
70
distance((UASProximityDistance) 0), // LP#1256969
74
ubuntu_sensor_type type;
78
float min_value, max_value;
79
void (*on_event_cb)(void*, void*);
80
void* event_cb_context;
82
/* current value; note that we do not track separate Event objects/pointers
83
* at all, and just always deliver the current value */
85
UASProximityDistance distance;
89
/* Singleton which reads the sensor data file and maintains the TestSensor
91
class SensorController
94
// Ensure that controller is initialized, and return singleton
95
static SensorController& instance()
97
static SensorController _inst;
101
// Return TestSensor of given type, or NULL if it doesn't exist
102
TestSensor* get(ubuntu_sensor_type type)
105
return sensors.at(type).get();
106
} catch (const out_of_range&) {
114
bool process_create_command();
115
void process_event_command();
116
void setup_timer(unsigned delay_ms);
117
static void on_timer(union sigval sval);
119
static ubuntu_sensor_type type_from_name(const string& type)
122
return ubuntu_sensor_type_light;
123
if (type == "proximity")
124
return ubuntu_sensor_type_proximity;
126
return ubuntu_sensor_type_accelerometer;
128
cerr << "TestSensor ERROR: unknown sensor type " << type << endl;
132
map<ubuntu_sensor_type, shared_ptr<TestSensor>> sensors;
135
// current command/event
136
string current_command;
137
TestSensor* event_sensor;
138
float event_x, event_y, event_z;
139
UASProximityDistance event_distance;
142
SensorController::SensorController()
144
const char* path = getenv("UBUNTU_PLATFORM_API_SENSOR_TEST");
147
cerr << "TestSensor ERROR: Need $UBUNTU_PLATFORM_API_SENSOR_TEST to point to a data file\n";
151
//cout << "SensorController ctor: opening " << path << endl;
154
if (!data.is_open()) {
155
cerr << "TestSensor ERROR: Failed to open data file " << path << ": " << strerror(errno) << endl;
159
// process all "create" commands
160
while (next_command()) {
161
if (!process_create_command())
165
// start event processing
167
process_event_command();
171
SensorController::next_command()
173
while (getline(data, current_command)) {
174
// trim leading and trailing space
175
current_command.erase(0, current_command.find_first_not_of(" \t"));
176
current_command.erase(current_command.find_last_not_of(" \t") + 1);
177
// ignore empty or comment lines
178
if (current_command.size() == 0 || current_command[0] == '#')
186
SensorController::process_create_command()
188
stringstream ss(current_command, ios_base::in);
191
// we only process "create" commands here; if we have something else, stop
193
if (token != "create")
197
ubuntu_sensor_type type = type_from_name(token);
199
if (get(type) != NULL) {
200
cerr << "TestSensor ERROR: duplicate creation of sensor type " << token << endl;
204
float min = 0, max = 0, resolution = 0;
206
if (type != ubuntu_sensor_type_proximity) {
207
// read min, max, resolution
208
ss >> min >> max >> resolution;
211
cerr << "TestSensor ERROR: max_value must be >= min_value in " << current_command << endl;
214
if (resolution <= 0) {
215
cerr << "TestSensor ERROR: resolution must be > 0 in " << current_command << endl;
220
//cout << "SensorController::process_create_command: type " << type << " min " << min << " max " << max << " res " << resolution << endl;
222
sensors[type] = make_shared<TestSensor>(type, min, max, resolution);
227
SensorController::process_event_command()
229
stringstream ss(current_command, ios_base::in);
232
//cout << "TestSensor: processing event " << current_command << endl;
237
cerr << "TestSensor ERROR: delay must be positive in command " << current_command << endl;
244
ubuntu_sensor_type type = type_from_name(token);
245
event_sensor = get(type);
246
if (event_sensor == NULL) {
247
cerr << "TestSensor ERROR: sensor does not exist, you need to create it: " << token << endl;
252
case ubuntu_sensor_type_light:
254
//cout << "got event: sensor type " << type << " (light), delay "
255
// << delay << " ms, value " << event_x << endl;
258
case ubuntu_sensor_type_accelerometer:
259
ss >> event_x >> event_y >> event_z;
260
//cout << "got event: sensor type " << type << " (accel), delay "
261
// << delay << " ms, value " << event_x << "/" << event_y << "/" << event_z << endl;
264
case ubuntu_sensor_type_proximity:
266
if (token == "unknown")
267
event_distance = (UASProximityDistance) 0; // LP#1256969
268
else if (token == "near")
269
event_distance = U_PROXIMITY_NEAR;
270
else if (token == "far")
271
event_distance = U_PROXIMITY_FAR;
273
cerr << "TestSensor ERROR: unknown proximity value " << token << endl;
276
//cout << "got event: sensor type " << type << " (proximity), delay "
277
// << delay << " ms, value " << int(event_distance) << endl;
281
cerr << "TestSensor ERROR: unhandled sensor type " << token << endl;
285
// wake up after given delay for committing the change and processing the
287
setup_timer(unsigned(delay));
291
SensorController::setup_timer(unsigned delay_ms)
293
static timer_t timerid; // we keep a pointer to that until on_timer
295
struct itimerspec its { {0, 0}, // interval
296
{time_t(delay_ms / 1000),
297
long((delay_ms % 1000) * 1000000L) % 1000000000L } };
299
sev.sigev_notify = SIGEV_THREAD;
300
sev.sigev_notify_function = SensorController::on_timer;
301
sev.sigev_notify_attributes = NULL;
302
sev.sigev_value.sival_ptr = &timerid;
304
if (timer_create(CLOCK_MONOTONIC, &sev, &timerid) < 0) {
305
perror("TestSensor ERROR: Failed to create timer");
308
if (timer_settime(timerid, 0, &its, NULL) < 0) {
309
perror("TestSensor ERROR: Failed to set up timer");
315
SensorController::on_timer(union sigval sval)
317
timer_t* timerid = static_cast<timer_t*>(sval.sival_ptr);
318
//cout << "on_timer called\n";
319
timer_delete(*timerid);
321
SensorController& sc = SensorController::instance();
323
// update sensor values, call callback
324
if (sc.event_sensor && sc.event_sensor->enabled) {
325
sc.event_sensor->x = sc.event_x;
326
sc.event_sensor->y = sc.event_y;
327
sc.event_sensor->z = sc.event_z;
328
sc.event_sensor->distance = sc.event_distance;
329
sc.event_sensor->timestamp = chrono::duration_cast<chrono::nanoseconds>(
330
chrono::system_clock::now().time_since_epoch()).count();
331
if (sc.event_sensor->on_event_cb != NULL) {
332
//cout << "TestSensor: calling sensor callback for type " << sc.event_sensor->type << endl;
333
sc.event_sensor->on_event_cb(sc.event_sensor, sc.event_sensor->event_cb_context);
335
//cout << "TestSensor: sensor type " << sc.event_sensor->type << "has no callback\n";
338
//cout << "TestSensor: sensor type " << sc.event_sensor->type << "disabled, not processing event\n";
341
// read/process next event
342
if (sc.next_command())
343
sc.process_event_command();
345
//cout << "TestSensor: script ended, no further commands\n";
350
/***************************************
354
***************************************/
356
UASensorsAccelerometer* ua_sensors_accelerometer_new()
358
return SensorController::instance().get(ubuntu_sensor_type_accelerometer);
361
UStatus ua_sensors_accelerometer_enable(UASensorsAccelerometer* s)
363
static_cast<TestSensor*>(s)->enabled = true;
367
UStatus ua_sensors_accelerometer_disable(UASensorsAccelerometer* s)
369
static_cast<TestSensor*>(s)->enabled = false;
373
uint32_t ua_sensors_accelerometer_get_min_delay(UASensorsAccelerometer* s)
375
return static_cast<TestSensor*>(s)->min_delay;
378
float ua_sensors_accelerometer_get_min_value(UASensorsAccelerometer* s) __SF_FN_ATTR;
379
float ua_sensors_accelerometer_get_min_value(UASensorsAccelerometer* s)
381
return static_cast<TestSensor*>(s)->min_value;
384
float ua_sensors_accelerometer_get_max_value(UASensorsAccelerometer* s) __SF_FN_ATTR;
385
float ua_sensors_accelerometer_get_max_value(UASensorsAccelerometer* s)
387
return static_cast<TestSensor*>(s)->max_value;
390
float ua_sensors_accelerometer_get_resolution(UASensorsAccelerometer* s) __SF_FN_ATTR;
391
float ua_sensors_accelerometer_get_resolution(UASensorsAccelerometer* s)
393
return static_cast<TestSensor*>(s)->resolution;
396
void ua_sensors_accelerometer_set_reading_cb(UASensorsAccelerometer* s, on_accelerometer_event_cb cb, void* ctx)
398
TestSensor* sensor = static_cast<TestSensor*>(s);
399
sensor->on_event_cb = cb;
400
sensor->event_cb_context = ctx;
403
uint64_t uas_accelerometer_event_get_timestamp(UASAccelerometerEvent* e)
405
return static_cast<TestSensor*>(e)->timestamp;
408
float uas_accelerometer_event_get_acceleration_x(UASAccelerometerEvent* e) __SF_FN_ATTR;
409
float uas_accelerometer_event_get_acceleration_x(UASAccelerometerEvent* e)
411
return static_cast<TestSensor*>(e)->x;
414
float uas_accelerometer_event_get_acceleration_y(UASAccelerometerEvent* e) __SF_FN_ATTR;
415
float uas_accelerometer_event_get_acceleration_y(UASAccelerometerEvent* e)
417
return static_cast<TestSensor*>(e)->y;
420
float uas_accelerometer_event_get_acceleration_z(UASAccelerometerEvent* e) __SF_FN_ATTR;
421
float uas_accelerometer_event_get_acceleration_z(UASAccelerometerEvent* e)
423
return static_cast<TestSensor*>(e)->z;
426
/***************************************
430
***************************************/
432
UASensorsProximity* ua_sensors_proximity_new()
434
return SensorController::instance().get(ubuntu_sensor_type_proximity);
437
UStatus ua_sensors_proximity_enable(UASensorsProximity* s)
439
static_cast<TestSensor*>(s)->enabled = true;
443
UStatus ua_sensors_proximity_disable(UASensorsProximity* s)
445
static_cast<TestSensor*>(s)->enabled = false;
449
uint32_t ua_sensors_proximity_get_min_delay(UASensorsProximity* s)
451
return static_cast<TestSensor*>(s)->min_delay;
454
// the next three function make no sense in the API, just return zero
455
float ua_sensors_proximity_get_min_value(UASensorsProximity*) __SF_FN_ATTR;
456
float ua_sensors_proximity_get_min_value(UASensorsProximity*)
461
float ua_sensors_proximity_get_max_value(UASensorsProximity*) __SF_FN_ATTR;
462
float ua_sensors_proximity_get_max_value(UASensorsProximity*)
467
float ua_sensors_proximity_get_resolution(UASensorsProximity*) __SF_FN_ATTR;
468
float ua_sensors_proximity_get_resolution(UASensorsProximity*)
473
void ua_sensors_proximity_set_reading_cb(UASensorsProximity* s, on_proximity_event_cb cb, void* ctx)
475
TestSensor* sensor = static_cast<TestSensor*>(s);
476
sensor->on_event_cb = cb;
477
sensor->event_cb_context = ctx;
480
uint64_t uas_proximity_event_get_timestamp(UASProximityEvent* e)
482
return static_cast<TestSensor*>(e)->timestamp;
485
UASProximityDistance uas_proximity_event_get_distance(UASProximityEvent* e)
487
return static_cast<TestSensor*>(e)->distance;
491
/***************************************
495
***************************************/
497
UASensorsLight* ua_sensors_light_new()
499
return SensorController::instance().get(ubuntu_sensor_type_light);
502
UStatus ua_sensors_light_enable(UASensorsLight* s)
504
static_cast<TestSensor*>(s)->enabled = true;
508
UStatus ua_sensors_light_disable(UASensorsLight* s)
510
static_cast<TestSensor*>(s)->enabled = false;
514
uint32_t ua_sensors_light_get_min_delay(UASensorsLight* s)
516
return static_cast<TestSensor*>(s)->min_delay;
519
float ua_sensors_light_get_min_value(UASensorsLight* s) __SF_FN_ATTR;
520
float ua_sensors_light_get_min_value(UASensorsLight* s)
522
return static_cast<TestSensor*>(s)->min_value;
525
float ua_sensors_light_get_max_value(UASensorsLight* s) __SF_FN_ATTR;
526
float ua_sensors_light_get_max_value(UASensorsLight* s)
528
return static_cast<TestSensor*>(s)->max_value;
531
float ua_sensors_light_get_resolution(UASensorsLight* s) __SF_FN_ATTR;
532
float ua_sensors_light_get_resolution(UASensorsLight* s)
534
return static_cast<TestSensor*>(s)->resolution;
537
void ua_sensors_light_set_reading_cb(UASensorsLight* s, on_light_event_cb cb, void* ctx)
539
TestSensor* sensor = static_cast<TestSensor*>(s);
540
sensor->on_event_cb = cb;
541
sensor->event_cb_context = ctx;
544
uint64_t uas_light_event_get_timestamp(UASLightEvent* e)
546
return static_cast<TestSensor*>(e)->timestamp;
549
float uas_light_event_get_light(UASLightEvent* e) __SF_FN_ATTR;
550
float uas_light_event_get_light(UASLightEvent* e)
552
return static_cast<TestSensor*>(e)->x;