2 * Copyright (C) 2012 Jolla Ltd.
3 * Author: Philippe De Swert <philippe.deswert@jollamobile.com>
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
28 #include <android/hardware/gps.h>
30 const GpsInterface
* Gps
= NULL
;
31 const AGpsInterface
* AGps
= NULL
;
32 const AGpsRilInterface
* AGpsRil
= NULL
;
33 const GpsNiInterface
*GpsNi
= NULL
;
34 const GpsXtraInterface
*GpsExtra
= NULL
;
36 const UlpNetworkInterface
*UlpNetwork
= NULL
;
37 const UlpPhoneContextInterface
*UlpPhoneContext
= NULL
;
41 static const GpsInterface
* get_gps_interface()
45 const GpsInterface
* interface
= NULL
;
46 struct gps_device_t
*device
;
48 error
= hw_get_module(GPS_HARDWARE_MODULE_ID
, (hw_module_t
const**)&module
);
52 error
= module
->methods
->open(module
, GPS_HARDWARE_MODULE_ID
, (struct hw_device_t
**) &device
);
53 fprintf(stdout
, "*** device info\n id = %s\n name = %s\n author = %s\n",
54 module
->id
, module
->name
, module
->author
);
58 interface
= device
->get_gps_interface(device
);
63 fprintf(stdout
, "*** GPS interface not found :\(\n Bye! \n");
70 static const AGpsInterface
* get_agps_interface(const GpsInterface
*gps
)
72 const AGpsInterface
* interface
= NULL
;
76 interface
= (const AGpsInterface
*)gps
->get_extension(AGPS_INTERFACE
);
81 static const AGpsRilInterface
* get_agps_ril_interface(const GpsInterface
*gps
)
83 const AGpsRilInterface
* interface
= NULL
;
87 interface
= (const AGpsRilInterface
*)gps
->get_extension(AGPS_RIL_INTERFACE
);
92 static const GpsNiInterface
* get_gps_ni_interface(const GpsInterface
*gps
)
94 const GpsNiInterface
* interface
= NULL
;
98 interface
= (const GpsNiInterface
*)gps
->get_extension(GPS_NI_INTERFACE
);
103 static const GpsDebugInterface
* get_gps_debug_interface(const GpsInterface
*gps
)
105 const GpsDebugInterface
* interface
= NULL
;
109 interface
= (const GpsDebugInterface
*)gps
->get_extension(GPS_DEBUG_INTERFACE
);
114 static const GpsXtraInterface
* get_gps_extra_interface(const GpsInterface
*gps
)
116 const GpsXtraInterface
* interface
= NULL
;
120 interface
= (const GpsXtraInterface
*)gps
->get_extension(GPS_XTRA_INTERFACE
);
126 static const UlpNetworkInterface
* get_ulp_network_interface(const GpsInterface
*gps
)
128 const UlpNetworkInterface
* interface
= NULL
;
132 interface
= (const UlpNetworkInterface
*)gps
->get_extension(ULP_NETWORK_INTERFACE
);
137 static const UlpPhoneContextInterface
* get_ulp_phone_context_interface(const GpsInterface
*gps
)
139 const UlpPhoneContextInterface
* interface
= NULL
;
143 interface
= (const UlpPhoneContextInterface
*)gps
->get_extension(ULP_PHONE_CONTEXT_INTERFACE
);
147 #endif /* HAVE_ULP */
149 static void location_callback(GpsLocation
* location
)
151 fprintf(stdout
, "*** location callback\n");
152 fprintf(stdout
, "flags:\t%d\n", location
->flags
);
153 fprintf(stdout
, "latitude: \t%lf\n", location
->latitude
);
154 fprintf(stdout
, "longtide: \t%lf\n", location
->longitude
);
155 fprintf(stdout
, "accuracy:\t%f\n", location
->accuracy
);
156 fprintf(stdout
, "utc: \t%ld\n", (long)location
->timestamp
);
159 static void status_callback(GpsStatus
* status
)
161 fprintf(stdout
, "*** status callback\n");
163 switch (status
->status
)
165 case GPS_STATUS_NONE
:
166 fprintf(stdout
, "*** no gps\n");
168 case GPS_STATUS_SESSION_BEGIN
:
169 fprintf(stdout
, "*** session begin\n");
171 case GPS_STATUS_SESSION_END
:
172 fprintf(stdout
, "*** session end\n");
174 case GPS_STATUS_ENGINE_ON
:
175 fprintf(stdout
, "*** engine on\n");
177 case GPS_STATUS_ENGINE_OFF
:
178 fprintf(stdout
, "*** engine off\n");
181 fprintf(stdout
, "*** unknown status\n");
185 static void sv_status_callback(GpsSvStatus
* sv_info
)
189 fprintf(stdout
, "*** sv status\n");
190 fprintf(stdout
, "sv_size:\t%zu\n", sv_info
->size
);
191 fprintf(stdout
, "num_svs:\t%d\n", sv_info
->num_svs
);
192 for(i
=0; i
< sv_info
->num_svs
; i
++)
194 fprintf(stdout
, "\t azimuth:\t%f\n", sv_info
->sv_list
[i
].azimuth
);
195 fprintf(stdout
, "\t elevation:\t%f\n", sv_info
->sv_list
[i
].elevation
);
196 /* if prn > 65 and <= 88 this is a glonass sattelite */
197 fprintf(stdout
, "\t prn:\t%d\n", sv_info
->sv_list
[i
].prn
);
198 fprintf(stdout
, "\t size:\t%zu\n", sv_info
->sv_list
[i
].size
);
199 fprintf(stdout
, "\t snr:\t%f\n", sv_info
->sv_list
[i
].snr
);
204 static void nmea_callback(GpsUtcTime timestamp
, const char* nmea
, int length
)
207 fprintf(stdout
, "*** nmea info\n");
208 fprintf(stdout
, "timestamp:\t%ld\n", (long)timestamp
);
209 /* NMEA sentences can only be between 11 ($TTFFF*CC\r\n) and 82 characters long */
210 if (length
> 10 && length
< 83) {
211 strncpy(buf
, nmea
, length
);
213 fprintf(stdout
, "nmea (%d): \t%s\n", length
, buf
);
215 fprintf(stdout
, "Invalid nmea data\n");
219 static void set_capabilities_callback(uint32_t capabilities
)
221 fprintf(stdout
, "*** set capabilities\n");
222 fprintf(stdout
, "capability is %.8x\n", capabilities
);
226 static void acquire_wakelock_callback()
228 fprintf(stdout
, "*** acquire wakelock\n");
232 static void release_wakelock_callback()
234 fprintf(stdout
, "*** release wakelock\n");
238 struct ThreadWrapperContext
{
239 void (*func
)(void *);
243 static void *thread_wrapper_context_main_func(void *user_data
)
245 struct ThreadWrapperContext
*ctx
= (struct ThreadWrapperContext
*)user_data
;
247 fprintf(stderr
, " **** Thread wrapper start (start=%p, arg=%p) ****\n",
248 ctx
->func
, ctx
->user_data
);
249 ctx
->func(ctx
->user_data
);
250 fprintf(stderr
, " **** Thread wrapper end (start=%p, arg=%p) ****\n",
251 ctx
->func
, ctx
->user_data
);
258 static pthread_t
create_thread_callback(const char* name
, void (*start
)(void *), void* arg
)
263 /* Wrap thread function, so we can return void * to pthread and log start/end of thread */
264 struct ThreadWrapperContext
*ctx
= calloc(1, sizeof(struct ThreadWrapperContext
));
266 ctx
->user_data
= arg
;
268 fprintf(stderr
, " ** Creating thread: '%s' (start=%p, arg=%p)\n", name
, start
, arg
);
269 /* Do not use a pthread_attr_t (we'd have to take care of bionic/glibc differences) */
270 error
= pthread_create(&thread_id
, NULL
, thread_wrapper_context_main_func
, ctx
);
271 fprintf(stderr
, " ** After thread_create: '%s', error=%d (start=%p, arg=%p)\n", name
, error
, start
, arg
);
279 static void agps_handle_status_callback(AGpsStatus
*status
)
283 fprintf(stdout
, "*** gps type %d\n", status
->type
);
285 switch (status
->status
)
287 case GPS_REQUEST_AGPS_DATA_CONN
:
288 fprintf(stdout
, "*** data_conn_open\n");
289 #ifndef HAS_ANDROID_4_2_0
290 AGps
->data_conn_open(AGPS_TYPE_SUPL
, apn
, AGPS_APN_BEARER_IPV4
);
292 AGps
->data_conn_open(apn
);
295 case GPS_RELEASE_AGPS_DATA_CONN
:
296 fprintf(stdout
, "*** data_conn_closed\n");
297 #ifndef HAS_ANDROID_4_2_0
298 AGps
->data_conn_closed(AGPS_TYPE_SUPL
);
300 AGps
->data_conn_closed();
303 case GPS_AGPS_DATA_CONNECTED
:
304 fprintf(stdout
, "*** data_conn_established\n");
306 case GPS_AGPS_DATA_CONN_DONE
:
307 fprintf(stdout
, "*** data_conn_done\n");
309 case GPS_AGPS_DATA_CONN_FAILED
:
310 fprintf(stdout
, "*** data_conn_FAILED\n");
315 static void agps_ril_set_id_callback(uint32_t flags
)
317 fprintf(stdout
, "*** set_id_cb\n");
318 AGpsRil
->set_set_id(AGPS_SETID_TYPE_IMSI
, "000000000000000");
321 static void agps_ril_refloc_callback(uint32_t flags
)
323 fprintf(stdout
, "*** refloc_cb\n");
324 /* TODO : find out how to fill in location
325 AGpsRefLocation location;
326 AGpsRil->set_ref_location(&location, sizeof(location));
330 static void ni_notify_callback (GpsNiNotification
*notification
)
332 fprintf(stdout
, "*** ni notification callback\n");
335 static void download_xtra_request_callback (void)
337 fprintf(stdout
, "*** xtra download request to client\n");
341 static void ulp_network_location_request_callback(UlpNetworkRequestPos
*req
)
343 fprintf(stdout
, "*** ulp network location request (request_type=%#x, interval_ms=%d, desired_position_source=%#x)\n",
344 req
->request_type
, req
->interval_ms
, req
->desired_position_source
);
347 static void ulp_request_phone_context_callback(UlpPhoneContextRequest
*req
)
349 fprintf(stdout
, "*** ulp phone context request (context_type=%#x, request_type=%#x, interval_ms=%d)\n",
350 req
->context_type
, req
->request_type
, req
->interval_ms
);
352 if (UlpPhoneContext
) {
353 fprintf(stdout
, "*** sending ulp phone context reply\n");
354 UlpPhoneContextSettings settings
;
355 settings
.context_type
= req
->context_type
;
356 settings
.is_gps_enabled
= 1;
357 settings
.is_agps_enabled
= 1;
358 settings
.is_network_position_available
= 1;
359 settings
.is_wifi_setting_enabled
= 1;
360 settings
.is_battery_charging
= 0;
361 settings
.is_enh_location_services_enabled
= 1;
362 UlpPhoneContext
->ulp_phone_context_settings_update(&settings
);
365 #endif /* HAVE_ULP */
367 GpsCallbacks callbacks
= {
368 sizeof(GpsCallbacks
),
373 set_capabilities_callback
,
374 acquire_wakelock_callback
,
375 release_wakelock_callback
,
376 create_thread_callback
,
379 AGpsCallbacks callbacks2
= {
380 agps_handle_status_callback
,
381 create_thread_callback
,
384 AGpsRilCallbacks callbacks3
= {
385 agps_ril_set_id_callback
,
386 agps_ril_refloc_callback
,
387 create_thread_callback
,
390 GpsNiCallbacks callbacks4
= {
392 create_thread_callback
,
395 GpsXtraCallbacks callbacks5
= {
396 download_xtra_request_callback
,
397 create_thread_callback
,
401 UlpNetworkLocationCallbacks callbacks6
= {
402 ulp_network_location_request_callback
,
405 UlpPhoneContextCallbacks callbacks7
= {
406 ulp_request_phone_context_callback
,
408 #endif /* HAVE_ULP */
410 void sigint_handler(int signum
)
412 fprintf(stdout
, "*** cleanup\n");
415 #ifndef HAS_ANDROID_4_2_0
416 AGps
->data_conn_closed(AGPS_TYPE_SUPL
);
418 AGps
->data_conn_closed();
429 int main(int argc
, char *argv
[])
431 int sleeptime
= 6000, opt
, initok
= 0;
432 int coldstart
= 0, extra
= 0, ulp
= 0;
434 int agps
= 0, agpsril
= 0, injecttime
= 0, injectlocation
= 0;
435 char *location
= 0, *longitude
, *latitude
;
436 float accuracy
= 100; /* Use 100m as location accuracy by default */
438 while ((opt
= getopt(argc
, argv
, "acl:p:rtux")) != -1)
443 fprintf(stdout
, "*** Using agps\n");
447 fprintf(stdout
, "*** Using cold start\n");
452 fprintf(stdout
, "*** Location info %s will be injected\n", location
);
456 fprintf(stdout
, "*** Using agpsril\n");
460 fprintf(stdout
, "*** Timing info will be injected\n");
470 fprintf(stdout
, "*** Allowing for Xtra downloads\n");
473 fprintf(stderr
, "\n Usage: %s \n \
475 \t-c for coldstarting the gps,\n \
476 \t-p <apn name> to specify an apn name,\n \
477 \t-r for agpsril,\n \
478 \t-t to inject time,\n \
479 \t-u to use ULP (if available,\n \
480 \t-x deal with Xtra gps data.\n \
481 \tnone for standalone gps\n",
489 apn
= strdup("Internet");
492 fprintf(stdout
, "*** setup signal handler\n");
493 signal(SIGINT
, sigint_handler
);
495 fprintf(stdout
, "*** get gps interface\n");
496 Gps
= get_gps_interface();
498 fprintf(stdout
, "*** init gps interface\n");
499 initok
= Gps
->init(&callbacks
);
500 fprintf(stdout
, "*** setting positioning mode\n");
501 /* need to be done before starting gps or no info will come out */
502 if((agps
||agpsril
) && !initok
)
503 Gps
->set_position_mode(GPS_POSITION_MODE_MS_BASED
, GPS_POSITION_RECURRENCE_PERIODIC
, 1000, 0, 0);
505 Gps
->set_position_mode(GPS_POSITION_MODE_STANDALONE
, GPS_POSITION_RECURRENCE_PERIODIC
, 1000, 0, 0);
507 if (Gps
&& !initok
&& (agps
||agpsril
))
509 fprintf(stdout
, "*** get agps interface\n");
510 AGps
= get_agps_interface(Gps
);
513 fprintf(stdout
, "*** set up agps interface\n");
514 AGps
->init(&callbacks2
);
515 fprintf(stdout
, "*** set up agps server\n");
516 AGps
->set_server(AGPS_TYPE_SUPL
, "supl.google.com", 7276);
521 fprintf(stdout
, "*** get agps ril interface\n");
523 AGpsRil
= get_agps_ril_interface(Gps
);
526 AGpsRil
->init(&callbacks3
);
529 /* if coldstart is requested, delete all location info */
532 fprintf(stdout
, "*** delete aiding data\n");
533 Gps
->delete_aiding_data(GPS_DELETE_ALL
);
538 fprintf(stdout
, "*** xtra aiding data init\n");
539 GpsExtra
= get_gps_extra_interface(Gps
);
541 GpsExtra
->init(&callbacks5
);
544 fprintf(stdout
, "*** setting up network notification handling\n");
545 GpsNi
= get_gps_ni_interface(Gps
);
548 GpsNi
->init(&callbacks4
);
554 UlpNetwork
= get_ulp_network_interface(Gps
);
556 fprintf(stdout
, "*** got ulp network interface\n");
557 if (UlpNetwork
->init(&callbacks6
) != 0) {
558 fprintf(stdout
, "*** FAILED to init ulp network interface\n");
563 fprintf(stdout
, "*** ULP failed!\n");
565 UlpPhoneContext
= get_ulp_phone_context_interface(Gps
);
566 if (UlpPhoneContext
) {
567 fprintf(stdout
, "*** got ulp phone context interface\n");
568 UlpPhoneContext
->init(&callbacks7
);
571 #endif /* HAVE_ULP */
575 fprintf(stdout
, "*** aiding gps by injecting time information\n");
576 gettimeofday(&tv
, NULL
);
577 Gps
->inject_time(tv
.tv_sec
, tv
.tv_sec
, 0);
582 fprintf(stdout
, "*** aiding gps by injecting location information\n");
583 //Gps->inject_location(double latitude, double longitude, float accuracy);
584 latitude
= strtok(location
, ",");
585 longitude
= strtok(NULL
, ",");
586 Gps
->inject_location(strtod(latitude
, NULL
), strtod(longitude
, NULL
), accuracy
);
589 fprintf(stdout
, "*** start gps track\n");
592 fprintf(stdout
, "*** gps tracking started\n");
596 fprintf(stdout
, "*** tracking.... \n");
598 sleeptime
= sleeptime
- 100;
602 AGps
->data_conn_closed(AGPS_TYPE_SUPL
);
603 fprintf(stdout
, "*** stop tracking\n");
605 fprintf(stdout
, "*** cleaning up\n");