1 /*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "android/sensors-port.h"
18 #include "android/hw-sensors.h"
19
20 #define E(...) derror(__VA_ARGS__)
21 #define W(...) dwarning(__VA_ARGS__)
22 #define D(...) VERBOSE_PRINT(sensors_port,__VA_ARGS__)
23 #define D_ACTIVE VERBOSE_CHECK(sensors_port)
24
25 /* Maximum number of sensors supported. */
26 #define ASP_MAX_SENSOR 12
27
28 /* Maximum length of a sensor message. */
29 #define ASP_MAX_SENSOR_MSG 1024
30
31 /* Maximum length of a sensor event. */
32 #define ASP_MAX_SENSOR_EVENT 256
33
34 /* Query timeout in milliseconds. */
35 #define ASP_QUERY_TIMEOUT 3000
36
37 /* Sensors port descriptor. */
38 struct AndroidSensorsPort {
39 /* Caller identifier. */
40 void* opaque;
41 /* Connected android device. */
42 AndroidDevice* device;
43 /* String containing list of all available sensors. */
44 char sensors[ASP_MAX_SENSOR * 64];
45 /* Array of available sensor names. Note that each string in this array
46 * points inside the 'sensors' buffer. */
47 const char* sensor_list[ASP_MAX_SENSOR];
48 /* Number of available sensors. */
49 int sensors_num;
50 /* Connection status: 1 connected, 0 - disconnected. */
51 int is_connected;
52 /* Buffer where to receive sensor messages. */
53 char sensor_msg[ASP_MAX_SENSOR_MSG];
54 /* Buffer where to receive sensor events. */
55 char events[ASP_MAX_SENSOR_EVENT];
56 };
57
58 /* Destroys and frees the descriptor. */
59 static void
_sensors_port_free(AndroidSensorsPort * asp)60 _sensors_port_free(AndroidSensorsPort* asp)
61 {
62 if (asp != NULL) {
63 if (asp->device != NULL) {
64 android_device_destroy(asp->device);
65 }
66 AFREE(asp);
67 }
68 }
69
70 /********************************************************************************
71 * Sensors port callbacks
72 *******************************************************************************/
73
74 /* A callback that invoked on sensor events.
75 * Param:
76 * opaque - AndroidSensorsPort instance.
77 * ad - Android device used by this sensors port.
78 * msg, msgsize - Sensor event message
79 * failure - Message receiving status.
80 */
81 static void
_on_sensor_received(void * opaque,AndroidDevice * ad,char * msg,int msgsize)82 _on_sensor_received(void* opaque, AndroidDevice* ad, char* msg, int msgsize)
83 {
84 float fvalues[3] = {0, 0, 0};
85 char sensor[ASP_MAX_SENSOR_MSG];
86 char* value;
87 int id;
88 AndroidSensorsPort* asp = (AndroidSensorsPort*)opaque;
89
90 if (errno) {
91 D("Sensors notification has failed on sensors port: %s", strerror(errno));
92 return;
93 }
94
95 /* Parse notification, separating sensor name from parameters. */
96 memcpy(sensor, msg, msgsize);
97 value = strchr(sensor, ':');
98 if (value == NULL) {
99 W("Bad format for sensor notification: %s", msg);
100 return;
101 }
102 sensor[value-sensor] = '\0';
103 value++;
104
105 id = android_sensors_get_id_from_name(sensor);
106 if (id >= 0) {
107 /* Parse the value part to get the sensor values(a, b, c) */
108 int i;
109 char* pnext;
110 char* pend = value + strlen(value);
111 for (i = 0; i < 3; i++, value = pnext + 1) {
112 pnext=strchr( value, ':' );
113 if (pnext) {
114 *pnext = 0;
115 } else {
116 pnext = pend;
117 }
118
119 if (pnext > value) {
120 if (1 != sscanf( value,"%g", &fvalues[i] )) {
121 W("Bad parameters in sensor notification %s", msg);
122 return;
123 }
124 }
125 }
126 android_sensors_set(id, fvalues[0], fvalues[1], fvalues[2]);
127 } else {
128 W("Unknown sensor name '%s' in '%s'", sensor, msg);
129 }
130
131 /* Listen to the next event. */
132 android_device_listen(ad, asp->events, sizeof(asp->events), _on_sensor_received);
133 }
134
135 /* A callback that is invoked when android device is connected (i.e. both, command
136 * and event channels have been stablished.
137 * Param:
138 * opaque - AndroidSensorsPort instance.
139 * ad - Android device used by this sensors port.
140 * failure - Connections status.
141 */
142 static void
_on_device_connected(void * opaque,AndroidDevice * ad,int failure)143 _on_device_connected(void* opaque, AndroidDevice* ad, int failure)
144 {
145 if (!failure) {
146 AndroidSensorsPort* asp = (AndroidSensorsPort*)opaque;
147 asp->is_connected = 1;
148 D("Sensor emulation has started");
149 /* Initialize sensors on device. */
150 sensors_port_init_sensors(asp);
151 }
152 }
153
154 /* Invoked when an I/O failure occurs on a socket.
155 * Note that this callback will not be invoked on connection failures.
156 * Param:
157 * opaque - AndroidSensorsPort instance.
158 * ad - Android device instance
159 * ads - Connection socket where failure has occured.
160 * failure - Contains 'errno' indicating the reason for failure.
161 */
162 static void
_on_io_failure(void * opaque,AndroidDevice * ad,int failure)163 _on_io_failure(void* opaque, AndroidDevice* ad, int failure)
164 {
165 AndroidSensorsPort* asp = (AndroidSensorsPort*)opaque;
166 E("Sensors port got disconnected: %s", strerror(failure));
167 asp->is_connected = false;
168 android_device_disconnect(ad);
169 android_device_connect_async(ad, _on_device_connected);
170 }
171
172 /********************************************************************************
173 * Sensors port API
174 *******************************************************************************/
175
176 #include "android/sdk-controller-socket.h"
177
178 static AsyncIOAction
_on_sdkctl_connection(void * client_opaque,SDKCtlSocket * sdkctl,AsyncIOState status)179 _on_sdkctl_connection(void* client_opaque, SDKCtlSocket* sdkctl, AsyncIOState status)
180 {
181 if (status == ASIO_STATE_FAILED) {
182 sdkctl_socket_reconnect(sdkctl, 1970, 20);
183 }
184 return ASIO_ACTION_DONE;
185 }
186
on_sdkctl_handshake(void * client_opaque,SDKCtlSocket * sdkctl,void * handshake,uint32_t handshake_size,AsyncIOState status)187 void on_sdkctl_handshake(void* client_opaque,
188 SDKCtlSocket* sdkctl,
189 void* handshake,
190 uint32_t handshake_size,
191 AsyncIOState status)
192 {
193 if (status == ASIO_STATE_SUCCEEDED) {
194 printf("---------- Handshake %d bytes received.\n", handshake_size);
195 } else {
196 printf("!!!!!!!!!! Handshake failed with status %d: %d -> %s\n",
197 status, errno, strerror(errno));
198 sdkctl_socket_reconnect(sdkctl, 1970, 20);
199 }
200 }
201
on_sdkctl_message(void * client_opaque,SDKCtlSocket * sdkctl,SDKCtlPacket * message,int msg_type,void * msg_data,int msg_size)202 void on_sdkctl_message(void* client_opaque,
203 SDKCtlSocket* sdkctl,
204 SDKCtlPacket* message,
205 int msg_type,
206 void* msg_data,
207 int msg_size)
208 {
209 printf("########################################################\n");
210 }
211
212 AndroidSensorsPort*
sensors_port_create(void * opaque)213 sensors_port_create(void* opaque)
214 {
215 AndroidSensorsPort* asp;
216 char* wrk;
217 int res;
218
219 SDKCtlSocket* sdkctl = sdkctl_socket_new(20, "test", _on_sdkctl_connection,
220 on_sdkctl_handshake, on_sdkctl_message,
221 NULL);
222 // sdkctl_init_recycler(sdkctl, 64, 8);
223 sdkctl_socket_connect(sdkctl, 1970, 20);
224
225 ANEW0(asp);
226 asp->opaque = opaque;
227 asp->is_connected = 0;
228
229 asp->device = android_device_init(asp, AD_SENSOR_PORT, _on_io_failure);
230 if (asp->device == NULL) {
231 _sensors_port_free(asp);
232 return NULL;
233 }
234
235 res = android_device_connect_sync(asp->device, ASP_QUERY_TIMEOUT);
236 if (res != 0) {
237 sensors_port_destroy(asp);
238 return NULL;
239 }
240
241 res = android_device_query(asp->device, "list",
242 asp->sensors, sizeof(asp->sensors),
243 ASP_QUERY_TIMEOUT);
244 if (res != 0) {
245 sensors_port_destroy(asp);
246 return NULL;
247 }
248
249 /* Parse sensor list. */
250 asp->sensors_num = 0;
251 wrk = asp->sensors;
252
253 while (wrk != NULL && *wrk != '\0' && *wrk != '\n') {
254 asp->sensor_list[asp->sensors_num] = wrk;
255 asp->sensors_num++;
256 wrk = strchr(wrk, '\n');
257 if (wrk != NULL) {
258 *wrk = '\0'; wrk++;
259 }
260 }
261
262 android_device_listen(asp->device, asp->events, sizeof(asp->events),
263 _on_sensor_received);
264 return asp;
265 }
266
267 int
sensors_port_init_sensors(AndroidSensorsPort * asp)268 sensors_port_init_sensors(AndroidSensorsPort* asp)
269 {
270 int res, id;
271
272 /* Disable all sensors for now. Reenable only those that are emulated. */
273 res = sensors_port_disable_sensor(asp, "all");
274 if (res) {
275 return res;
276 }
277
278 /* Start listening on sensor events. */
279 res = android_device_listen(asp->device, asp->events, sizeof(asp->events),
280 _on_sensor_received);
281 if (res) {
282 return res;
283 }
284
285 /* Walk throuh the list of enabled sensors enabling them on the device. */
286 for (id = 0; id < MAX_SENSORS; id++) {
287 if (android_sensors_get_sensor_status(id) == 1) {
288 res = sensors_port_enable_sensor(asp, android_sensors_get_name_from_id(id));
289 if (res == 0) {
290 D("Sensor '%s' is enabled on the device.",
291 android_sensors_get_name_from_id(id));
292 }
293 }
294 }
295
296 /* Start sensor events. */
297 return sensors_port_start(asp);
298 }
299
300 void
sensors_port_destroy(AndroidSensorsPort * asp)301 sensors_port_destroy(AndroidSensorsPort* asp)
302 {
303 _sensors_port_free(asp);
304 }
305
306 int
sensors_port_is_connected(AndroidSensorsPort * asp)307 sensors_port_is_connected(AndroidSensorsPort* asp)
308 {
309 return asp->is_connected;
310 }
311
312 int
sensors_port_enable_sensor(AndroidSensorsPort * asp,const char * name)313 sensors_port_enable_sensor(AndroidSensorsPort* asp, const char* name)
314 {
315 char query[1024];
316 char qresp[1024];
317 snprintf(query, sizeof(query), "enable:%s", name);
318 const int res =
319 android_device_query(asp->device, query, qresp, sizeof(qresp),
320 ASP_QUERY_TIMEOUT);
321 if (res) {
322 if (errno) {
323 D("Query '%s' failed on I/O: %s", query, strerror(errno));
324 } else {
325 D("Query '%s' failed on device: %s", query, qresp);
326 }
327 }
328 return res;
329 }
330
331 int
sensors_port_disable_sensor(AndroidSensorsPort * asp,const char * name)332 sensors_port_disable_sensor(AndroidSensorsPort* asp, const char* name)
333 {
334 char query[1024];
335 char qresp[1024];
336 snprintf(query, sizeof(query), "disable:%s", name);
337 const int res =
338 android_device_query(asp->device, query, qresp, sizeof(qresp),
339 ASP_QUERY_TIMEOUT);
340 if (res) {
341 if (errno) {
342 D("Query '%s' failed on I/O: %s", query, strerror(errno));
343 } else {
344 D("Query '%s' failed on device: %s", query, qresp);
345 }
346 }
347 return res;
348 }
349
350 int
sensors_port_start(AndroidSensorsPort * asp)351 sensors_port_start(AndroidSensorsPort* asp)
352 {
353 char qresp[ASP_MAX_SENSOR_MSG];
354 const int res =
355 android_device_query(asp->device, "start", qresp, sizeof(qresp),
356 ASP_QUERY_TIMEOUT);
357 if (res) {
358 if (errno) {
359 D("Query 'start' failed on I/O: %s", strerror(errno));
360 } else {
361 D("Query 'start' failed on device: %s", qresp);
362 }
363 }
364 return res;
365 }
366
367 int
sensors_port_stop(AndroidSensorsPort * asp)368 sensors_port_stop(AndroidSensorsPort* asp)
369 {
370 char qresp[ASP_MAX_SENSOR_MSG];
371 const int res =
372 android_device_query(asp->device, "stop", qresp, sizeof(qresp),
373 ASP_QUERY_TIMEOUT);
374 if (res) {
375 if (errno) {
376 D("Query 'stop' failed on I/O: %s", strerror(errno));
377 } else {
378 D("Query 'stop' failed on device: %s", qresp);
379 }
380 }
381
382 return res;
383 }
384