说明
由于车机gps是外挂的,所以需要原厂提供gps库替换系统的gps.default.so库。
流程
1.在vendor/fibo/common/目录添加gnsshal文件夹,将Android.mk和gps_zkw.c文件放入该目录。
Android.mk文件:
#include $(all-subdir-makefiles)
LOCAL_PATH := $(call my-dir)
#ifeq ($(BOARD_GPS_LIBRARIES), libgps)
#ifneq ($(TARGET_PRODUCT),sim)
# HAL module implemenation, not prelinked and stored in
# # hw/<GPS_HARDWARE_MODULE_ID>.<ro.hardware>.so
include $(CLEAR_VARS)
LOCAL_PRELINK_MODULE := false
#LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
LOCAL_MULTILIB := both
LOCAL_MODULE_RELATIVE_PATH := hw
#LOCAL_MULTILIB := TARGET_PREFER_64_BIT
LOCAL_CFLAGS := -DHAVE_GPS_HARDWARE
LOCAL_SHARED_LIBRARIES := liblog libcutils libhardware libc libutils
LOCAL_SRC_FILES := gps_zkw.c
#LOCAL_MODULE := gps.$(TARGET_BOARD_PLATFORM)
LOCAL_MODULE := gps.default
LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY)
#endif
#adb push $(TARGET_OUT_SHARED_LIBRARIES)/hw/gps.default /system/lib/hw/
#endif
gps_zkw.c内容:
#include <errno.h>
#include <pthread.h>
#include <fcntl.h>
#include <sys/epoll.h>
#include <math.h>
#include <time.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <cutils/properties.h>
#define LOCATION_NLP_FIX "/data/misc/gps/LOCATION.DAT"
#define C_INVALID_FD -1
#define LOG_TAG "gps_zkw"
#include <cutils/log.h>
#include <cutils/sockets.h>
#include <cutils/properties.h>
#ifdef HAVE_LIBC_SYSTEM_PROPERTIES
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
#include <sys/_system_properties.h>
#endif
//#include <hardware/gps7.h>
#include <hardware/gps.h>
/* the name of the controlled socket */
#define GPS_CHANNEL_NAME "/dev/ttyHSL1"
#define TTY_BAUD B9600 // B115200
#define BDS_POWER_ON "/sys/class/gpio/gpio0/value"
#define GPS_DEBUG 1
#define NEMA_DEBUG 1 /*the flag works if GPS_DEBUG is defined*/
#if GPS_DEBUG
#define TRC(f) ALOGD("%s", __func__)
#define ERR(f, ...) ALOGE("%s: line = %d, " f, __func__, __LINE__, ##__VA_ARGS__)
#define WAN(f, ...) ALOGW("%s: line = %d, " f, __func__, __LINE__, ##__VA_ARGS__)
#define DBG(f, ...) ALOGD("%s: line = %d, " f, __func__, __LINE__, ##__VA_ARGS__)
#define VER(f, ...) ((void)0) // ((void)0) //
#else
# define DBG(...) ((void)0)
# define VER(...) ((void)0)
# define ERR(...) ((void)0)
#endif
static int flag_unlock = 0;
GpsStatus gps_status;
const char* gps_native_thread = "GPS NATIVE THREAD";
static GpsCallbacks callback_backup;
static float report_time_interval = 0;
static int started = 0;
/*****************************************************************************/
/*****************************************************************/
/*****************************************************************/
/***** *****/
/***** C O N N E C T I O N S T A T E *****/
/***** *****/
/*****************************************************************/
/*****************************************************************/
/* commands sent to the gps thread */
enum {
CMD_QUIT = 0,
CMD_START = 1,
CMD_STOP = 2,
CMD_RESTART = 3,
CMD_DOWNLOAD = 4,
CMD_TEST_START = 10,
CMD_TEST_STOP = 11,
CMD_TEST_SMS_NO_RESULT = 12,
};
static int gps_nmea_end_tag = 0;
/*****************************************************************/
/*****************************************************************/
/***** *****/
/***** N M E A T O K E N I Z E R *****/
/***** *****/
/*****************************************************************/
/*****************************************************************/
typedef struct {
const char* p;
const char* end;
} Token;
#define MAX_NMEA_TOKENS 24
typedef struct {
int count;
Token tokens[ MAX_NMEA_TOKENS ];
} NmeaTokenizer;
static int
nmea_tokenizer_init(NmeaTokenizer* t, const char* p, const char* end)
{
int count = 0;
char* q;
// the initial '$' is optional
if (p < end && p[0] == '$')
p += 1;
// remove trailing newline
if (end > p && (*(end-1) == '\n')) {
end -= 1;
if (end > p && (*(end-1) == '\r'))
end -= 1;
}
// get rid of checksum at the end of the sentecne
if (end >= p+3 && (*(end-3) == '*')) {
end -= 3;
}
while (p < end) {
const char* q = p;
q = memchr(p, ',', end-p);
if (q == NULL)
q = end;
if (q >= p) {
if (count < MAX_NMEA_TOKENS) {
t->tokens[count].p = p;
t->tokens[count].end = q;
count += 1;
}
}
if (q < end)
q += 1;
p = q;
}
t->count = count;
return count;
}
static Token
nmea_tokenizer_get(NmeaTokenizer* t, int index)
{
Token tok;
static const char* dummy = "";
if (index < 0 || index >= t->count) {
tok.p = tok.end = dummy;
} else
tok = t->tokens[index];
return tok;
}
static int
str2int(const char* p, const char* end)
{
int result = 0;
int len = end - p;
int sign = 1;
if (*p == '-')
{
sign = -1;
p++;
len = end - p;
}
for (; len > 0; len--, p++)
{
int c;
if (p >= end)
goto Fail;
c = *p - '0';
if ((unsigned)c >= 10)
goto Fail;
result = result*10 + c;
}
return sign*result;
Fail:
return -1;
}
static double
str2float(const char* p, const char* end)
{
int result = 0;
int len = end - p;
char temp[16];
if (len >= (int)sizeof(temp))
return 0.;
memcpy(temp, p, len);
temp[len] = 0;
return strtod(temp, NULL);
}
/*****************************************************************/
/*****************************************************************/
/***** *****/
/***** N M E A P A R S E R *****/
/***** *****/
/*****************************************************************/
/*****************************************************************/
static void gps_dev_power(int state)
{
int fd;
char cmd = '0';
int ret;
do {
fd = open( BDS_POWER_ON, O_RDWR );
} while (fd < 0 && errno == EINTR);
if (fd < 0) {
ALOGE("could not open gps power interfcae: %s", BDS_POWER_ON );
return;
}
if (state) {
cmd = '1';
} else {
cmd = '0';
}
do {
ret = write( fd, &cmd, 1 );
} while (ret < 0 && errno == EINTR);
close(fd);
ALOGE("gps power state = %c", cmd);
return;
}
// #define NMEA_MAX_SIZE 83
#define NMEA_MAX_SIZE 128
/*maximum number of SV information in GPGSV*/
#define NMEA_MAX_SV_INFO 4
#define LOC_FIXED(pNmeaReader) ((pNmeaReader->fix_mode == 2) || (pNmeaReader->fix_mode ==3))
typedef struct {
int pos;
int overflow;
int utc_year;
int utc_mon;
int utc_day;
int utc_diff;
GpsLocation fix;
/*
* The fix flag extracted from GPGSA setence: 1: No fix; 2 = 2D; 3 = 3D
* if the fix mode is 0, no location will be reported via callback
* otherwise, the location will be reported via callback
*/
int fix_mode;
/*
* Indicate that the status of callback handling.
* The flag is used to report GPS_STATUS_SESSION_BEGIN or GPS_STATUS_SESSION_END:
* (0) The flag will be set as true when callback setting is changed via nmea_reader_set_callback
* (1) GPS_STATUS_SESSION_BEGIN: receive location fix + flag set + callback is set
* (2) GPS_STATUS_SESSION_END: receive location fix + flag set + callback is null
*/
int cb_status_changed;
int sv_count; /*used to count the number of received SV information*/
GpsSvStatus sv_status_gps;
GnssSvStatus sv_status_gnss;
GpsCallbacks callbacks;
char in[ NMEA_MAX_SIZE+1 ];
int sv_status_can_report;
int location_can_report;
int sv_used_in_fix[256];
} NmeaReader;
static void
nmea_reader_update_utc_diff(NmeaReader* const r)
{
time_t now = time(NULL);
struct tm tm_local;
struct tm tm_utc;
unsigned long time_local, time_utc;
gmtime_r(&now, &tm_utc);
localtime_r(&now, &tm_local);
time_local = mktime(&tm_local);
time_utc = mktime(&tm_utc);
r->utc_diff = time_utc - time_local;
}
static void
nmea_reader_init(NmeaReader* const r)
{
memset(r, 0, sizeof(*r));
r->pos = 0;
r->overflow = 0;
r->utc_year = -1;
r->utc_mon = -1;
r->utc_day = -1;
r->utc_diff = 0;
r->callbacks.location_cb= NULL;
r->callbacks.status_cb= NULL;
r->callbacks.sv_status_cb= NULL;
r->sv_count = 0;
r->fix_mode = 0; /*no fix*/
r->cb_status_changed = 0;
memset((void*)&r->sv_status_gps, 0x00, sizeof(r->sv_status_gps));
memset((void*)&r->sv_status_gnss, 0x00, sizeof(r->sv_status_gnss));
memset((void*)&r->in, 0x00, sizeof(r->in));
nmea_reader_update_utc_diff(r);
}
static vo