• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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