blob: a1c65a2cafd93b938f0a00831f8277081bc780b2 [file] [log] [blame]
b.liu68a94c92025-05-24 12:53:41 +08001#include <stdio.h>
2#include <string.h>
3#include <strings.h>
4#include <stdlib.h>
5#include <errno.h>
6#include <fcntl.h>
7#include <signal.h>
8#include <sys/types.h>
9#include <unistd.h>
10#include <pthread.h>
11#include <termios.h>
12#include <time.h>
13#include <sys/ioctl.h>
14#include <dlfcn.h>
15#include <stdint.h>
16#include <stdbool.h>
17
zw.wang581aab12025-05-28 19:43:53 +080018#include "gsw_gnss_interface.h"
19
20#define MBTK_GNSS_IND_LOCATION (1) // 1
21#define MBTK_GNSS_IND_NMEA (1 << 1) // 2
22#define QSER_GNSS_TIMEOUT 5
b.liu68a94c92025-05-24 12:53:41 +080023
zw.wangbd342b92025-07-21 11:24:16 +080024#include "gsw_log_interface.h"
l.yang6a42e4d2025-05-28 01:04:20 -070025#define GSW_GNSS "[HAL][GSW_GNSS]"
26
b.liu68a94c92025-05-24 12:53:41 +080027#define MOPEN_GNSS_NMEA_MAX_LENGTH 255 /** NMEA string maximum length. */
28static gsw_gnss_cb *gsw_cb = NULL;
29static bool inited = false;
30static bool strated = false;
31
32typedef void (*mbtk_gnss_callback_func)(uint32_t ind_type, const void* data, uint32_t data_len);
b.liu68a94c92025-05-24 12:53:41 +080033
34int (*mbtk_gnss_init)(mbtk_gnss_callback_func cb);
35int (*mbtk_gnss_deinit)();
36
37int (*mbtk_gnss_ind_set)(uint32_t ,int);
38int (*mbtk_gnss_open)(int, int);
39int (*mbtk_gnss_close)(int);
40int (*mbtk_gnss_setting)(const char *setting_cmd, int);
41
42int (*mbtk_gnss_eph_download)(int);
43int (*mbtk_gnss_eph_inject)(int);
44
45int gnss_freq = -1;
46GSW_GNSS_MODE_CONFIGURATION gnss_startmode = -1;
zw.wang581aab12025-05-28 19:43:53 +080047GSW_CONF_SWITCH gnss_switch_op = -1;
b.liu68a94c92025-05-24 12:53:41 +080048void *dlHandle_gnss;
49char *lynqLib_gnss = "/lib/libmbtk_lib.so";
50
51typedef enum
52{
53 E_MT_LOC_MSG_ID_LOCATION_INFO = 1, /**< pv_data = & mopen_location_info_t */
54 E_MT_LOC_MSG_ID_NMEA_INFO = 3, /**< pv_data = & mopen_gnss_nmea_info_t */
55} e_msg_id_t;
56
57typedef struct
58{
59 int64_t timestamp; /**< System Timestamp, marked for when got the nmea data */
60 int length; /**< NMEA string length. */
61 char nmea[MOPEN_GNSS_NMEA_MAX_LENGTH + 1]; /**< NMEA string.*/
62}mopen_gnss_nmea_info_t; /* Message */
63
64typedef struct
65{
66 uint32_t size; /**< Set to the size of mcm_gps_location_t. */
67 int flags; /**< Contains GPS location flags bits. */
68 int position_source; /**< Provider indicator for HYBRID or GPS. */ //功能暂未实现,可不用添加进结构体
69 double latitude; /**< Latitude in degrees. */
70 double longitude; /**< Longitude in degrees. */
71 double altitude; /**< Altitude in meters above the WGS 84 reference ellipsoid. */
72 float speed; /**< Speed in meters per second. */
73 float bearing; /**< Heading in degrees. */ //功能暂未实现,可不用添加进结构体
74 float accuracy; /**< Expected accuracy in meters. */ //功能暂未实现,可不用添加进结构体
75 int64_t timestamp; /**< Timestamp for the location fix in UTC million-second base. */
76 int32_t is_indoor; /**< Location is indoors. */ //功能暂未实现,可不用添加进结构体
77 float floor_number; /**< Indicates the floor number. */
78}mopen_location_info_t;//功能暂未实现,可不用添加进结构体
79
80
81typedef struct {
82 uint32_t flags;
83 double latitude; /**< Latitude in degrees. */
84 double longitude; /**< Longitude in degrees. */
85 double altitude; /**< Altitude in meters above the WGS 84 reference ellipsoid. */
86 float speed; /**< Speed in meters per second. */
87 float bearing; /**< Heading in degrees. */
88 int64_t timestamp; /**< Timestamp for the location fix in UTC million-second base. */
89} mbtk_gnss_location_info_t;
90
zw.wang581aab12025-05-28 19:43:53 +080091typedef struct{
92 GSW_GNSS_MODE_CONFIGURATION start_mode;
93 gnss_freq_type freq;
94 gsw_gnss_cb callback;
95}gsw_gnss_init_configure_t;
96
b.liu68a94c92025-05-24 12:53:41 +080097typedef enum{
98 MODE_GPS = 1, /**< GPS only */
99 MODE_BEIDOU, /**< BEIDOU only*/
100 MODE_GPS_BEIDOU, /**< GPS+BEIDOU */
101 MODE_GLONASS, /**< GLONASS only */
102 MODE_GPS_GLONASS, /**< GPS+GLONASS */
103 MODE_GLONASS_BEIDOU, /**< GLONASS+BEIDOU */ /* The type does not support this type */
104 MODE_GPS_GLONASS_BEIDOU, /**< GPS+GLONASS+BEIDOU */ /* The type does not support this type */
105 MODE_GALILEO, /**< GALILEO only */
106 MODE_GPS_GALILEO, /**< GPS+GALILEO */
107 MODE_BEIDOU_GALILEO, /**< BEIDOU+GALILEO */
108 MODE_GPS_BEIDOU_GALILEO, /**< GPS+BEIDOU+GALILEO */
109 MODE_GLONASS_GALILEO, /**< GLONASS+GALILEO */
110 MODE_GPS_GLONASS_GALILEO, /**< GPS+GLONASS+GALILEO */
111 MODE_BEIDOU_GLONASS_GALILEO, /**< BEIDOU+GLONASS+GALILEO */ /* The type does not support this type */
112 MODE_END = -1, /**< init value */
113}GSW_GNSS_MODE_CONFIGURATION_HD;
114
zw.wangbe05b922025-07-14 18:37:51 +0800115typedef enum{
116 NO_DEVICE = 0,
117 HD8122,
118 HD8040D,
119}GSW_DEVICE;
b.liu68a94c92025-05-24 12:53:41 +0800120
zw.wangbe05b922025-07-14 18:37:51 +0800121typedef struct {
122 int fd;
123 GSW_DEVICE got_hd8;
124} rx_ctx;
125
126static GSW_DEVICE gsw_device = NO_DEVICE;
b.liu68a94c92025-05-24 12:53:41 +0800127GSW_GNSS_MODE_CONFIGURATION_HD map_gnss_mode(GSW_GNSS_MODE_CONFIGURATION mode)
128{
129 switch (mode)
130 {
131 case GSW_MODE_GPS_GLONASS:
132 return MODE_GPS_GLONASS;
133 case GSW_MODE_GPS_BEIDOU:
134 return MODE_GPS_BEIDOU;
135 case GSW_MODE_GPS_GLONASS_BEIDOU:
136 return MODE_END;
137 case GSW_MODE_GPS:
138 return MODE_GPS;
139 case GSW_MODE_BEIDOU:
140 return MODE_BEIDOU;
141 case GSW_MODE_GLONASS:
142 return MODE_GLONASS;
143 case GSW_MODE_GPS_GLONASS_BEIDOU_GALILEO:
144 return MODE_END;
145 case GSW_MODE_GPS_GALILEO:
146 return MODE_GPS_GALILEO;
147 case GSW_MODE_GPS_GLONASS_GALILEO:
148 return MODE_GPS_GLONASS_GALILEO;
149 case GSW_MODE_GPS_GALILEO_ONLY:
150 return MODE_GALILEO;
151 case GSW_MODE_GPS_GLONASS_BEIDOU_GALILEO_NAVIC:
152 return MODE_END;
153 case GSW_MODE_GNSS_END:
154 return MODE_END;
155 default:
156 return MODE_END;
157 }
158}
159
zw.wangbe05b922025-07-14 18:37:51 +0800160static void *rx_thread(void *arg)
161{
162 rx_ctx *c = (rx_ctx *)arg;
163 char buf[128];
164 ssize_t n;
165 time_t end = time(NULL) + 1; /* 1 秒超时 */
166
167 while (time(NULL) < end) {
168 n = read(c->fd, buf, sizeof(buf));
169 if (n > 0 && memmem(buf, n, "HD8040D", 7)) {
170 c->got_hd8 = 2;
171 break;
172 }
173 else if (n > 0 && memmem(buf, n, "HD812", 5)) {
174 c->got_hd8 = 1;
175 break;
176 }
177 }
178 return NULL;
179}
180
181static int send_and_wait(int fd)
182{
183 int ret;
184 pthread_t tid;
185 rx_ctx ctx = { .fd = fd, .got_hd8 = NO_DEVICE };
186
187 pthread_create(&tid, NULL, rx_thread, &ctx);
188
189 unsigned char tx[8] = {0xF1,0xD9,0x0A,0x04,0x00,0x00,0x0E,0x34};
190 ret = write(fd, tx, sizeof(tx));
191 if(ret < 0)
192 {
zw.wangbd342b92025-07-21 11:24:16 +0800193 LOGE(GSW_GNSS,"[GSW_gnss] send_and_wait write fail.ret = [%d]", ret);
zw.wangbe05b922025-07-14 18:37:51 +0800194 }
195 pthread_join(tid, NULL);
196 return ctx.got_hd8;
197}
198
199static int get_gnss_device_version(void)
200{
201 int fd = open("/dev/ttyS3", O_RDWR | O_NOCTTY);
202 if (fd < 0) { perror("open"); return 1; }
203 gsw_device = send_and_wait(fd);
204 close(fd);
205 return gsw_device;
206}
207
b.liu68a94c92025-05-24 12:53:41 +0800208int mbtk_gnss_set_VTG()
209{
210 int ret;
zw.wang57f3a9f2025-07-10 14:26:52 +0800211 ret = system("/usr/sbin/gnss_gpio.sh VTG > /dev/null 2>&1");
b.liu68a94c92025-05-24 12:53:41 +0800212 if(ret != 0)
213 {
zw.wangbd342b92025-07-21 11:24:16 +0800214 LOGE(GSW_GNSS,"[GSW_gnss] mbtk_gnss_set_VTG on fail.ret = [%d]", ret);
hong.liud2417072025-06-27 07:10:37 -0700215 return GSW_HAL_NORMAL_FAIL;
b.liu68a94c92025-05-24 12:53:41 +0800216 }
217 return GSW_HAL_SUCCESS;
218}
219
zw.wangbe05b922025-07-14 18:37:51 +0800220static int HD8040D_gsw_gnss_set_freq(int freq)
221{
222 int ret;
223 char cmd[64] = {0};
224 switch (freq)
225 {
226 case 1:
227 snprintf(cmd, sizeof(cmd), "/usr/sbin/gnss_gpio.sh %s > /dev/null 2>&1", "1HZ");
228 break;
229 case 5:
230 snprintf(cmd, sizeof(cmd), "/usr/sbin/gnss_gpio.sh %s > /dev/null 2>&1", "5HZ");
231 break;
232 case 10:
233 snprintf(cmd, sizeof(cmd), "/usr/sbin/gnss_gpio.sh %s > /dev/null 2>&1", "10HZ");
234 break;
235 default:
236 return GSW_HAL_NORMAL_FAIL;
237 break;
238 }
239 ret = system(cmd);
240 if(ret != 0)
241 {
zw.wangbd342b92025-07-21 11:24:16 +0800242 LOGE(GSW_GNSS,"[GSW_gnss] gnss_gpio.sh GSW_HD8040D mode fail.ret = [%d]", ret);
zw.wangbe05b922025-07-14 18:37:51 +0800243 return GSW_HAL_NORMAL_FAIL;
244 }
245 return ret;
246}
b.liu68a94c92025-05-24 12:53:41 +0800247/**
248 * @brief SDK interface to set gnss sampling frequency, support 1Hz、2Hz、5Hz
249 * @param [in] freq
250 * @retval 0: success
251 * @retval other: fail
252 */
253int gsw_gnss_set_freq(int freq)
254{
zw.wangbc534c02025-06-26 09:31:44 +0800255 if(!inited)
hong.liud2417072025-06-27 07:10:37 -0700256 return GSW_HAL_NORMAL_FAIL;
zw.wangbc534c02025-06-26 09:31:44 +0800257
b.liu68a94c92025-05-24 12:53:41 +0800258 int ret;
259 if (!strated)
260 {
261 gnss_freq = freq;
262 return GSW_HAL_SUCCESS;
263 }
zw.wangbe05b922025-07-14 18:37:51 +0800264 if(gsw_device == NO_DEVICE)
265 {
266 ret = get_gnss_device_version();
zw.wangbd342b92025-07-21 11:24:16 +0800267 LOGD(GSW_GNSS,"[GSW_gnss] get_gnss_device_version ret = [%d]", ret);
zw.wangbe05b922025-07-14 18:37:51 +0800268 }
269 if(gsw_device == HD8040D)
270 {
271 ret = HD8040D_gsw_gnss_set_freq(freq);
272 return ret;
273 }
b.liu68a94c92025-05-24 12:53:41 +0800274 char param_buf[32] = {0};
275 snprintf(param_buf, 32, "$FREQCFG,%d", freq);
276 mbtk_gnss_setting=(int(*)(const char *setting_cmd, int))dlsym(dlHandle_gnss, "mbtk_gnss_setting");
277 ret = mbtk_gnss_setting(param_buf, QSER_GNSS_TIMEOUT);
278 if(ret != 0)
279 {
zw.wangbd342b92025-07-21 11:24:16 +0800280 LOGE(GSW_GNSS,"[qser_gnss] mbtk_gnss_setting fail.ret = [%d]", ret);
hong.liud2417072025-06-27 07:10:37 -0700281 return GSW_HAL_NORMAL_FAIL;
b.liu68a94c92025-05-24 12:53:41 +0800282 }
283 return GSW_HAL_SUCCESS;
284}
285
zw.wangbe05b922025-07-14 18:37:51 +0800286static int32_t HD8040D_gsw_gnss_set_start_mode(GSW_GNSS_MODE_CONFIGURATION start_mode)
287{
288 int ret;
289 char cmd[64] = {0};
290 switch (start_mode)
291 {
292 case GSW_MODE_GPS_GLONASS:
293 return GSW_HAL_NORMAL_FAIL;
294 break;
295 case GSW_MODE_GPS_BEIDOU:
296 snprintf(cmd, sizeof(cmd), "/usr/sbin/gnss_gpio.sh %s > /dev/null 2>&1", "GSW_GPS_BD_DUAL");
297 break;
298 case GSW_MODE_GPS_GLONASS_BEIDOU:
299 return GSW_HAL_NORMAL_FAIL;
300 break;
301 case GSW_MODE_GPS:
302 snprintf(cmd, sizeof(cmd), "/usr/sbin/gnss_gpio.sh %s > /dev/null 2>&1", "GSW_GPS_L1L5");
303 break;
304 case GSW_MODE_BEIDOU:
305 snprintf(cmd, sizeof(cmd), "/usr/sbin/gnss_gpio.sh %s > /dev/null 2>&1", "GSW_BD_B1I_B1C_B2A");
306 break;
307 case GSW_MODE_GLONASS:
308 snprintf(cmd, sizeof(cmd), "/usr/sbin/gnss_gpio.sh %s > /dev/null 2>&1", "GSW_GALILEO_E1_E5A");
309 break;
310 case GSW_MODE_GPS_GLONASS_BEIDOU_GALILEO:
311 return GSW_HAL_NORMAL_FAIL;
312 break;
313 case GSW_MODE_GPS_GALILEO:
314 return GSW_HAL_NORMAL_FAIL;
315 break;
316 case GSW_MODE_GPS_GLONASS_GALILEO:
317 return GSW_HAL_NORMAL_FAIL;
318 break;
319 case GSW_MODE_GPS_GALILEO_ONLY:
320 return GSW_HAL_NORMAL_FAIL;
321 break;
322 case GSW_MODE_GPS_GLONASS_BEIDOU_GALILEO_NAVIC:
323 return GSW_HAL_NORMAL_FAIL;
324 break;
325 case GSW_MODE_GNSS_END:
326 return GSW_HAL_NORMAL_FAIL;
327 break;
328 default:
329 return GSW_HAL_NORMAL_FAIL;
330 break;
331 }
332 ret = system(cmd);
333 if(ret != 0)
334 {
zw.wangbd342b92025-07-21 11:24:16 +0800335 LOGE(GSW_GNSS,"[GSW_gnss] gnss_gpio.sh GSW_HD8040D mode fail.ret = [%d]", ret);
zw.wangbe05b922025-07-14 18:37:51 +0800336 return GSW_HAL_NORMAL_FAIL;
337 }
338 return ret;
339}
340
b.liu68a94c92025-05-24 12:53:41 +0800341/**
342 * @brief SDK interface to set gnss start mode,specific mode refreence GSW_HAL_GNSS_MODE_CONFIGURATION
343 * @param [in] start_mode
344 * @retval 0: success
345 * @retval other: fail
346 */
hong.liud2417072025-06-27 07:10:37 -0700347int32_t gsw_gnss_set_start_mode(GSW_GNSS_MODE_CONFIGURATION start_mode)
b.liu68a94c92025-05-24 12:53:41 +0800348{
zw.wangbc534c02025-06-26 09:31:44 +0800349 if(!inited)
hong.liud2417072025-06-27 07:10:37 -0700350 return GSW_HAL_NORMAL_FAIL;
b.liu68a94c92025-05-24 12:53:41 +0800351 int ret;
352 if (!strated)
353 {
354 gnss_startmode = start_mode;
355 return GSW_HAL_SUCCESS;
356 }
zw.wangbe05b922025-07-14 18:37:51 +0800357 if(gsw_device == NO_DEVICE)
358 {
359 ret = get_gnss_device_version();
zw.wangbd342b92025-07-21 11:24:16 +0800360 LOGD(GSW_GNSS,"[GSW_gnss] get_gnss_device_version ret = [%d]", ret);
zw.wangbe05b922025-07-14 18:37:51 +0800361 }
362 if(gsw_device == HD8040D)
363 {
364 ret = HD8040D_gsw_gnss_set_start_mode(start_mode);
365 return ret;
366 }
b.liu68a94c92025-05-24 12:53:41 +0800367 char param_buf[32] = {0};
368 snprintf(param_buf, 32, "$SYSCFG,%d", map_gnss_mode(start_mode));
369 if(map_gnss_mode(start_mode) == -1)
370 {
zw.wangbd342b92025-07-21 11:24:16 +0800371 LOGE(GSW_GNSS,"[qser_gnss] mbtk_gnss_start_mode con't support");
hong.liud2417072025-06-27 07:10:37 -0700372 return GSW_HAL_NORMAL_FAIL;
b.liu68a94c92025-05-24 12:53:41 +0800373 }
374 mbtk_gnss_setting=(int(*)(const char *setting_cmd, int))dlsym(dlHandle_gnss, "mbtk_gnss_setting");
375 ret = mbtk_gnss_setting(param_buf, QSER_GNSS_TIMEOUT);
376 if(ret != 0)
377 {
zw.wangbd342b92025-07-21 11:24:16 +0800378 LOGE(GSW_GNSS,"[qser_gnss] mbtk_gnss_setting fail.ret = [%d]", ret);
hong.liud2417072025-06-27 07:10:37 -0700379 return GSW_HAL_NORMAL_FAIL;
b.liu68a94c92025-05-24 12:53:41 +0800380 }
381 return GSW_HAL_SUCCESS;
382}
383
384/**
385 * @brief SDK interface to set EPO switch if open or close
386 * @param [in] switch_op
387 * @retval 0: success
388 * @retval other: fail
389 */
hong.liud2417072025-06-27 07:10:37 -0700390int32_t gsw_gnss_epo_switch(GSW_CONF_SWITCH switch_op)
b.liu68a94c92025-05-24 12:53:41 +0800391{
zw.wangbc534c02025-06-26 09:31:44 +0800392 if(!inited)
hong.liud2417072025-06-27 07:10:37 -0700393 return GSW_HAL_NORMAL_FAIL;
b.liu68a94c92025-05-24 12:53:41 +0800394 int ret;
395 if (!strated)
396 {
397 gnss_switch_op = switch_op;
398 return GSW_HAL_SUCCESS;
399 }
400
401 if(switch_op)
402 {
403 mbtk_gnss_eph_download=(int(*)(int))dlsym(dlHandle_gnss, "mbtk_gnss_eph_download");
404 ret = mbtk_gnss_eph_download(QSER_GNSS_TIMEOUT);
405 if(ret != 0)
406 {
zw.wangbd342b92025-07-21 11:24:16 +0800407 LOGE(GSW_GNSS,"[qser_gnss] mbtk_gnss_eph_download fail.ret = [%d]", ret);
hong.liud2417072025-06-27 07:10:37 -0700408 return GSW_HAL_NORMAL_FAIL;
b.liu68a94c92025-05-24 12:53:41 +0800409 }
410 mbtk_gnss_eph_inject=(int(*)(int))dlsym(dlHandle_gnss, "mbtk_gnss_eph_inject");
411 ret = mbtk_gnss_eph_inject(QSER_GNSS_TIMEOUT);
412 if(ret != 0)
413 {
zw.wangbd342b92025-07-21 11:24:16 +0800414 LOGE(GSW_GNSS,"[qser_gnss] mbtk_gnss_eph_inject fail.ret = [%d]", ret);
hong.liud2417072025-06-27 07:10:37 -0700415 return GSW_HAL_NORMAL_FAIL;
b.liu68a94c92025-05-24 12:53:41 +0800416 }
417 }
418 return GSW_HAL_SUCCESS;
419}
420
421static void gnss_callback(uint32_t ind_type, const void* data, uint32_t data_len)
422{
423 if(data == NULL || data_len <= 0)
424 {
zw.wangbd342b92025-07-21 11:24:16 +0800425 LOGE(GSW_GNSS,"[GSW_gnss] data is NULL.");
b.liu68a94c92025-05-24 12:53:41 +0800426 return;
427 }
428
429 if(gsw_cb == NULL)
430 {
zw.wangbd342b92025-07-21 11:24:16 +0800431 //LOGE(GSW_GNSS,"[qser_gnss] qser_gnss_callback is NULL.");
b.liu68a94c92025-05-24 12:53:41 +0800432 return;
433 }
434
zw.wanga5250d62025-06-13 16:01:34 +0800435 if(ind_type == MBTK_GNSS_IND_LOCATION && gsw_cb->gsw_location_cb != NULL) {
b.liu68a94c92025-05-24 12:53:41 +0800436 if(data_len != sizeof(mbtk_gnss_location_info_t))
437 {
zw.wangbd342b92025-07-21 11:24:16 +0800438 LOGE(GSW_GNSS,"[GSW_gnss] data size error");
b.liu68a94c92025-05-24 12:53:41 +0800439 return;
440 }
441 GSW_GNSS_LOCATION_EXT_T gsw_location;
hong.liud2417072025-06-27 07:10:37 -0700442 GSW_GNSS_LOCATION_T gsw_location_t = {0};
b.liu68a94c92025-05-24 12:53:41 +0800443 mbtk_gnss_location_info_t *locl_info = (mbtk_gnss_location_info_t *)data;
444 gsw_location_t.altitude = locl_info->altitude;
445 gsw_location_t.latitude = locl_info->latitude;
446 gsw_location_t.longitude = locl_info->longitude;
447 gsw_location_t.speed = locl_info->speed;
448 gsw_location_t.bearing = locl_info->bearing;
449 gsw_location_t.timestamp = locl_info->timestamp;
zw.wanga5250d62025-06-13 16:01:34 +0800450 gsw_location_t.flags = locl_info->flags;
b.liu68a94c92025-05-24 12:53:41 +0800451 gsw_location.legacyLocation = gsw_location_t;
452 gsw_cb->gsw_location_cb(&gsw_location);
zw.wanga5250d62025-06-13 16:01:34 +0800453 } else if(ind_type == MBTK_GNSS_IND_NMEA && gsw_cb->gsw_nmea_cb != NULL) {
b.liu68a94c92025-05-24 12:53:41 +0800454 mopen_gnss_nmea_info_t qser_nmea = {0};
455 memset(&qser_nmea, 0x0, sizeof(mopen_gnss_nmea_info_t));
456 qser_nmea.length = data_len;
457 memcpy(qser_nmea.nmea, (char *)data, data_len);
458 //qser_nmea.timestamp = qser_get_gnss_time_sec(data, data_len);
459 gsw_cb->gsw_nmea_cb(data,data_len);
460 } else {
zw.wangbd342b92025-07-21 11:24:16 +0800461 LOGD(GSW_GNSS,"Unknown IND : %d\n", ind_type);
b.liu68a94c92025-05-24 12:53:41 +0800462 }
463}
464
hong.liud2417072025-06-27 07:10:37 -0700465int32_t gsw_gnss_init(void)
b.liu68a94c92025-05-24 12:53:41 +0800466{
lichengzhanga7089172025-07-01 20:41:46 +0800467 int ret;
b.liu68a94c92025-05-24 12:53:41 +0800468 if(!inited)
469 {
lichengzhanga7089172025-07-01 20:41:46 +0800470 ret = system("serial_atcmd AT*IMLCONFIG=13");
471 if(ret != 0)
472 {
zw.wangbd342b92025-07-21 11:24:16 +0800473 LOGE(GSW_GNSS,"serial_atcmd fail\n");
lichengzhanga7089172025-07-01 20:41:46 +0800474 return GSW_HAL_NORMAL_FAIL;
475 }
zw.wang1907e8f2025-07-01 16:26:39 +0800476 if(dlHandle_gnss == NULL)
zw.wangbd342b92025-07-21 11:24:16 +0800477 dlHandle_gnss = dlopen(lynqLib_gnss, RTLD_NOW);;
478 if(dlHandle_gnss == NULL)
b.liu68a94c92025-05-24 12:53:41 +0800479 {
hong.liud2417072025-06-27 07:10:37 -0700480 return GSW_HAL_NORMAL_FAIL;
b.liu68a94c92025-05-24 12:53:41 +0800481 }
482 mbtk_gnss_init=(int(*)(mbtk_gnss_callback_func))dlsym(dlHandle_gnss, "mbtk_gnss_init");
483 ret = mbtk_gnss_init(gnss_callback);
484 if(ret == 0)
485 {
486 mbtk_gnss_ind_set=(int(*)(uint32_t ,int))dlsym(dlHandle_gnss, "mbtk_gnss_ind_set");
zw.wanga5250d62025-06-13 16:01:34 +0800487 ret = mbtk_gnss_ind_set(MBTK_GNSS_IND_NMEA |MBTK_GNSS_IND_LOCATION, QSER_GNSS_TIMEOUT);
b.liu68a94c92025-05-24 12:53:41 +0800488 if(ret == 0)
489 {
490 inited = true;
491 }
492 else
493 {
zw.wangbd342b92025-07-21 11:24:16 +0800494 LOGE(GSW_GNSS,"[GSW_gnss] init mbtk_gnss_ind_set() fail.ret = [%d]", ret);
hong.liud2417072025-06-27 07:10:37 -0700495 return GSW_HAL_NORMAL_FAIL;
b.liu68a94c92025-05-24 12:53:41 +0800496 }
497 }
498 else
499 {
zw.wangbd342b92025-07-21 11:24:16 +0800500 LOGE(GSW_GNSS,"[GSW_gnss] mbtk_gnss_init() fail.ret = [%d]", ret);
hong.liud2417072025-06-27 07:10:37 -0700501 return GSW_HAL_NORMAL_FAIL;
b.liu68a94c92025-05-24 12:53:41 +0800502 }
503 }
504
505 return GSW_HAL_SUCCESS;
506}
507
508/**
509 * @brief SDK interface to registered callback function
510 * @param [in] callback
511 * @retval 0: success
512 * @retval other: fail
513 */
hong.liud2417072025-06-27 07:10:37 -0700514int32_t gsw_gnss_reg_cb_group(gsw_gnss_cb callback)
b.liu68a94c92025-05-24 12:53:41 +0800515{
zw.wangbc534c02025-06-26 09:31:44 +0800516 if(!inited)
hong.liud2417072025-06-27 07:10:37 -0700517 return GSW_HAL_NORMAL_FAIL;
b.liu68a94c92025-05-24 12:53:41 +0800518 if(callback.gsw_location_cb == NULL && callback.gsw_nmea_cb == NULL)
519 {
zw.wangbd342b92025-07-21 11:24:16 +0800520 LOGE(GSW_GNSS,"[GSW_gnss] handler_ptr is NULL.");
hong.liud2417072025-06-27 07:10:37 -0700521 return GSW_HAL_NORMAL_FAIL;
b.liu68a94c92025-05-24 12:53:41 +0800522 }
523 if (gsw_cb == NULL)
524 {
525 gsw_cb = (gsw_gnss_cb *)malloc(sizeof(gsw_gnss_cb));
526 if (gsw_cb == NULL)
527 {
zw.wangbd342b92025-07-21 11:24:16 +0800528 LOGE(GSW_GNSS,"[GSW_gnss] Memory allocation failed.");
hong.liud2417072025-06-27 07:10:37 -0700529 return GSW_HAL_NORMAL_FAIL;
b.liu68a94c92025-05-24 12:53:41 +0800530 }
531 }
532 gsw_cb->gsw_location_cb = callback.gsw_location_cb;
533 gsw_cb->gsw_nmea_cb = callback.gsw_nmea_cb;
534 return GSW_HAL_SUCCESS;
535}
536/**
537 * @brief SDK interface to start gnss
538 * @param
539 * @retval 0: success
540 * @retval other: fail
541 */
hong.liud2417072025-06-27 07:10:37 -0700542int32_t gsw_gnss_start(void)
b.liu68a94c92025-05-24 12:53:41 +0800543{
544 int ret;
zw.wangbc534c02025-06-26 09:31:44 +0800545 if(!inited)
hong.liud2417072025-06-27 07:10:37 -0700546 return GSW_HAL_NORMAL_FAIL;
zw.wangbc534c02025-06-26 09:31:44 +0800547 ret = system("/usr/sbin/gnss_gpio.sh on > /dev/null 2>&1");
548 if(ret != 0)
549 {
zw.wangbd342b92025-07-21 11:24:16 +0800550 LOGE(GSW_GNSS,"[GSW_gnss] gnss_gpio.sh on fail.ret = [%d]", ret);
hong.liud2417072025-06-27 07:10:37 -0700551 return GSW_HAL_NORMAL_FAIL;
zw.wangbc534c02025-06-26 09:31:44 +0800552 }
zw.wang57f3a9f2025-07-10 14:26:52 +0800553 // 记录mbtk_gnss_open前的时间戳
554 struct timespec start_time;
555 if (clock_gettime(CLOCK_MONOTONIC, &start_time) != 0) {
zw.wangbd342b92025-07-21 11:24:16 +0800556 LOGE(GSW_GNSS,"[GSW_gnss] Failed to get start time");
zw.wang57f3a9f2025-07-10 14:26:52 +0800557 return GSW_HAL_NORMAL_FAIL;
558 }
559
b.liu68a94c92025-05-24 12:53:41 +0800560 mbtk_gnss_open=(int(*)(int,int))dlsym(dlHandle_gnss, "mbtk_gnss_open");
561 ret = mbtk_gnss_open(255, QSER_GNSS_TIMEOUT);
562 if(ret != 0)
563 {
zw.wangbd342b92025-07-21 11:24:16 +0800564 LOGE(GSW_GNSS,"[GSW_gnss] mbtk_gnss_open is error.ret = [%d]", ret);
hong.liud2417072025-06-27 07:10:37 -0700565 return GSW_HAL_NORMAL_FAIL;
b.liu68a94c92025-05-24 12:53:41 +0800566 }
zw.wang89c18242025-06-24 19:07:10 +0800567
b.liu68a94c92025-05-24 12:53:41 +0800568 strated = true;
zw.wang7aa34062025-06-27 17:54:55 +0800569 /*
b.liu68a94c92025-05-24 12:53:41 +0800570 if (gnss_freq > 0)
571 gsw_gnss_set_freq(gnss_freq);
572 if (gnss_startmode >= 0)
573 gsw_gnss_set_start_mode(gnss_startmode);
574 if (gnss_switch_op > 0)
575 gsw_gnss_epo_switch(gnss_switch_op);
zw.wang7aa34062025-06-27 17:54:55 +0800576 */
zw.wang57f3a9f2025-07-10 14:26:52 +0800577
578 // 记录mbtk_gnss_set_VTG前的时间戳并计算等待时间
579 struct timespec end_time;
580 if (clock_gettime(CLOCK_MONOTONIC, &end_time) != 0) {
zw.wangbd342b92025-07-21 11:24:16 +0800581 LOGE(GSW_GNSS,"[GSW_gnss] Failed to get end time");
zw.wang57f3a9f2025-07-10 14:26:52 +0800582 return GSW_HAL_NORMAL_FAIL;
583 }
584 long start_ms = start_time.tv_sec * 1000 + start_time.tv_nsec / 1000000;
585 long end_ms = end_time.tv_sec * 1000 + end_time.tv_nsec / 1000000;
586 long diff_ms = end_ms - start_ms;
587 if (diff_ms < 700) {
588 long wait_ms = 700 - diff_ms;
589 usleep(wait_ms * 1000); // 转换为微秒等待
590 }
591
b.liu68a94c92025-05-24 12:53:41 +0800592 mbtk_gnss_set_VTG();
593
594 return GSW_HAL_SUCCESS;
595}
596
zw.wang57f3a9f2025-07-10 14:26:52 +0800597
b.liu68a94c92025-05-24 12:53:41 +0800598/**
599 * @brief SDK interface to stop gnss
600 * @param
601 * @retval 0: success
602 * @retval other: fail
603 */
hong.liud2417072025-06-27 07:10:37 -0700604int32_t gsw_gnss_stop(void)
b.liu68a94c92025-05-24 12:53:41 +0800605{
606 int ret;
zw.wangbc534c02025-06-26 09:31:44 +0800607 if(!inited)
hong.liud2417072025-06-27 07:10:37 -0700608 return GSW_HAL_NORMAL_FAIL;
b.liu68a94c92025-05-24 12:53:41 +0800609 mbtk_gnss_close=(int(*)(int))dlsym(dlHandle_gnss, "mbtk_gnss_close");
610 ret = mbtk_gnss_close(QSER_GNSS_TIMEOUT);
611 if(ret != 0)
612 {
zw.wangbd342b92025-07-21 11:24:16 +0800613 LOGE(GSW_GNSS,"[GSW_gnss] mbtk_gnss_close is error.ret = [%d]", ret);
hong.liud2417072025-06-27 07:10:37 -0700614 return GSW_HAL_NORMAL_FAIL;
b.liu68a94c92025-05-24 12:53:41 +0800615 }
zw.wangbc534c02025-06-26 09:31:44 +0800616 ret = system("/usr/sbin/gnss_gpio.sh off > /dev/null 2>&1");
617 if(ret != 0)
618 {
zw.wangbd342b92025-07-21 11:24:16 +0800619 LOGE(GSW_GNSS,"[GSW_gnss] gnss_gpio.sh off fail.ret = [%d]", ret);
hong.liud2417072025-06-27 07:10:37 -0700620 return GSW_HAL_NORMAL_FAIL;
zw.wangbc534c02025-06-26 09:31:44 +0800621 }
b.liu68a94c92025-05-24 12:53:41 +0800622 strated = false;
623 return GSW_HAL_SUCCESS;
624}
625
626/**
627 * @brief SDK interface to de initialization gnss
628 * @param
629 * @retval 0: success
630 * @retval other: fail
631 */
hong.liud2417072025-06-27 07:10:37 -0700632int32_t gsw_gnss_deinit(void)
b.liu68a94c92025-05-24 12:53:41 +0800633{
634 int ret;
zw.wangbc534c02025-06-26 09:31:44 +0800635 if(!inited)
hong.liud2417072025-06-27 07:10:37 -0700636 return GSW_HAL_NORMAL_FAIL;
b.liu68a94c92025-05-24 12:53:41 +0800637 if(inited)
638 {
lichengzhanga7089172025-07-01 20:41:46 +0800639 ret = system("serial_atcmd AT*IMLCONFIG=12");
640 if(ret != 0)
641 {
zw.wangbd342b92025-07-21 11:24:16 +0800642 LOGE(GSW_GNSS,"serial_atcmd fail\n");
lichengzhanga7089172025-07-01 20:41:46 +0800643 return GSW_HAL_NORMAL_FAIL;
644 }
b.liu68a94c92025-05-24 12:53:41 +0800645 mbtk_gnss_deinit=(int(*)())dlsym(dlHandle_gnss, "mbtk_gnss_deinit");
646 ret = mbtk_gnss_deinit();
647 if(ret == 0)
648 {
649 inited = false;
650 }
651 else
652 {
zw.wangbd342b92025-07-21 11:24:16 +0800653 LOGE(GSW_GNSS,"[GSW_gnss] mbtk_gnss_deinit() fail.ret = [%d]", ret);
zw.wang1907e8f2025-07-01 16:26:39 +0800654 /*
b.liu68a94c92025-05-24 12:53:41 +0800655 dlclose(dlHandle_gnss);
656 dlHandle_gnss = NULL;
zw.wang1907e8f2025-07-01 16:26:39 +0800657 */
hong.liud2417072025-06-27 07:10:37 -0700658 return GSW_HAL_NORMAL_FAIL;
b.liu68a94c92025-05-24 12:53:41 +0800659 }
660 }
661
zw.wang1907e8f2025-07-01 16:26:39 +0800662 /*
b.liu68a94c92025-05-24 12:53:41 +0800663 dlclose(dlHandle_gnss);
664 dlHandle_gnss = NULL;
zw.wang1907e8f2025-07-01 16:26:39 +0800665 */
b.liu68a94c92025-05-24 12:53:41 +0800666 gnss_freq = -1;
667 gnss_startmode = -1;
668 gnss_switch_op = -1;
669 return GSW_HAL_SUCCESS;
670}
671
zw.wang75e98ea2025-05-29 17:57:38 +0800672int gsw_gnss_add_lib(void)
673{
674 return GSW_HAL_SUCCESS;
675}
b.liu68a94c92025-05-24 12:53:41 +0800676
677/**
678 * @brief SDK interface to enable XTRA switch
679 * @param [in] state
680 * @retval 0: success
681 * @retval other: fail
682 */
hong.liud2417072025-06-27 07:10:37 -0700683int32_t gsw_gnss_xtra_is_enable(gsw_xtra_state_e state)
b.liu68a94c92025-05-24 12:53:41 +0800684{
685 return GSW_HAL_SUCCESS;
686}
687
688/**
689 * @brief SDK interface to delete aiding data,delete aiding data for cold start(1-H,2-W,3-C)
690 * @param [in] switch_op
691 * @retval 0: success
692 * @retval other: fail
693 */
hong.liud2417072025-06-27 07:10:37 -0700694int32_t gsw_gnss_delete_aiding_data(unsigned int flags) /*1-don`t delete == hot_start ; 2-delete EPH == warm start ; 3-delete all == cold start*/
b.liu68a94c92025-05-24 12:53:41 +0800695{
zw.wangbc534c02025-06-26 09:31:44 +0800696 if(!inited)
hong.liud2417072025-06-27 07:10:37 -0700697 return GSW_HAL_NORMAL_FAIL;
b.liu68a94c92025-05-24 12:53:41 +0800698 int ret;
699 char param_buf[32] = {0};
700 snprintf(param_buf, 32, "$RESET,%u", flags);
701 mbtk_gnss_setting=(int(*)(const char *setting_cmd, int))dlsym(dlHandle_gnss, "mbtk_gnss_setting");
702 ret = mbtk_gnss_setting(param_buf, QSER_GNSS_TIMEOUT);
703 if(ret != 0)
704 {
zw.wangbd342b92025-07-21 11:24:16 +0800705 LOGE(GSW_GNSS,"[qser_gnss] mbtk_gnss_setting fail.ret = [%d]", ret);
hong.liud2417072025-06-27 07:10:37 -0700706 return GSW_HAL_NORMAL_FAIL;
b.liu68a94c92025-05-24 12:53:41 +0800707 }
708 return GSW_HAL_SUCCESS;
709}
710
711/**
712 * @brief init and configure gps
713 * @param [in] init_configure
714 * @retval 0: success
715 * @retval other: fail
716 */
hong.liud2417072025-06-27 07:10:37 -0700717int32_t gsw_gnss_init_configure_gps(gsw_gnss_init_configure_t init_configure)
b.liu68a94c92025-05-24 12:53:41 +0800718{
719 return GSW_HAL_SUCCESS;
720}
hong.liud2417072025-06-27 07:10:37 -0700721
722int gsw_gnss_get_tail_nmea_type(char *tail_type, int len)
723{
724 if(NULL == tail_type){
zw.wangbd342b92025-07-21 11:24:16 +0800725 LOGE(GSW_GNSS,"get_tail_nmea_type fail, tail_type is NULL");
hong.liud2417072025-06-27 07:10:37 -0700726 return GSW_HAL_ERROR_GNSS_FAIL;
727 }
728
729 if(len >= 3){
730 strcpy(tail_type, "RMC");
731 return GSW_HAL_GNSS_SUCCESS;
732 }else{
zw.wangbd342b92025-07-21 11:24:16 +0800733 LOGE(GSW_GNSS,"get_tail_nmea_type fail, len[%d] is too short", len);
hong.liud2417072025-06-27 07:10:37 -0700734 return GSW_HAL_ERROR_GNSS_FAIL;
735 }
736}