blob: 0bb7c5a4a8d97ad1a710e95465b8a250231d021e [file] [log] [blame]
yq.wang99db6f52024-09-12 01:58:48 -07001#include <string.h>
2#include <stdio.h>
3#include <stdlib.h>
4#include <math.h>
5#include <stdint.h>
6#include <errno.h>
7#include <fcntl.h>
8#include <string.h>
9#include <unistd.h>
10
11
12#include "8122_agnss.h"
13#include "mbtk_log.h"
14
15#define BUFFER_SIZE 1024
16
17#define INJECT_RESULT_SUCCESS 0
18#define INJECT_RESULT_FAIL -1
19
20static int hd_fd = -1;
21static hd_eph_inject_status_type eph_inject_status = HD_EPH_INJECT_STATUS_SUCCESS;
22
23static void hd_agnss_delay(uint32_t nms)
24{
25 usleep(nms * 1000);
26}
27
28static int hd_agnss_uart_write(uint8_t *buf, uint32_t len)
29{
b.liu9e8584b2024-11-06 19:21:28 +080030 int TxLen = -1;
yq.wang99db6f52024-09-12 01:58:48 -070031 if(hd_fd > 0)
32 {
33 TxLen = write(hd_fd,buf,len);
34 if(TxLen != (int)len)
35 {
36 LOGE("hd_agnss_uart_write fail.ret = [%d], len = [%d]", TxLen, len);
37 return INJECT_RESULT_FAIL;
38 }
39 }
40 else
41 {
42 LOGE("8122 agps fd error.");
43 }
44 return TxLen;
45}
46
47static int32_t message_package(uint8_t *dst, uint8_t *src, int32_t src_len)
48{
49 int32_t i = 0;
50 int8_t checksum1 = 0;
51 int8_t checksum2 = 0;
52
53 /* message header */
54 for (i = 0; i < 4; i++)
55 {
56 dst[i] = *(src + i);
57 }
58
59 /* message len */
60 dst[4] = src_len;
61 dst[5] = 0;
62
63 /* payload */
64 for( i = 0 ; i < src_len; i++)
65 {
66 dst[6 + i] = *(src + 4) ;
67 src++;
68 }
69
70 /* check sum */
71 for(i = 2; i < (6 + dst[4]); i++)
72 {
73 checksum1 += dst[i];
74 checksum2 += checksum1;
75 }
76
77 dst[src_len + 6] = checksum1;
78 dst[src_len + 7] = checksum2;
79
80 return src_len + 8;
81}
82
b.liu9e8584b2024-11-06 19:21:28 +080083/************************************time inject*************************************/
yq.wang99db6f52024-09-12 01:58:48 -070084static int gnss_inject_time(HD_AGNSS_UTC_TIME_TYPE *time)
85{
86 uint8_t cmd[24] = {0}; /* packet head+payload */
87 uint8_t message[30] = {0}; /* payload : 20, packet pad : 8 */
88 int32_t len = 0;
89
90 memset(cmd, 0, sizeof(cmd));
91
92 cmd[0] = 0xF1;
93 cmd[1] = 0xD9;
94 cmd[2] = 0x0B;
95 cmd[3] = 0x11;
96
97 cmd[4] = 0x00; /* UTC */
98 cmd[5] = 0x00; /* reserved */
99 cmd[6] = 0x12; /* leap cnt, hd8030 not used */
100
101 cmd[7] = time->year & 0xFF;
102 cmd[8] = ((time->year >> 8) & 0xFF); /* year */
103 cmd[9] = time->month; /* month */
104 cmd[10] = time->day; /* day */
105 cmd[11] = time->hour; /* hour */
106 cmd[12] = time->min; /* minu */
107 cmd[13] = time->second; /* sec */
108
109 cmd[18] = 0x00;
110 cmd[19] = 0x00;
111 for (int i = 0; i < 4; i++)
112 {
113 cmd[20 + i] = 0x00;
114 }
115
116 len = message_package(message, cmd, sizeof(cmd) - 4);
117
118 LOGE("%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X",
119 message[0],message[1],message[2],message[3],message[4],message[5],message[6],message[7],
120 message[8],message[9],message[10],message[11],message[12],message[13],message[14],
121 message[15],message[16],message[17],message[18],message[19],message[20],
122 message[21],message[22],message[23],message[24],message[25],message[26],
123 message[27],message[28],message[29]);
124
125 hd_agnss_uart_write(message, len);
126 hd_agnss_delay(3); // just example, use wait 3ms instead of ACK
127
128 return 0;
129}
130
131/************************************location inject*************************************/
132static int gnss_inject_location(int32_t latitude, int32_t longitude, float altitude, float accuracy)
133{
134 uint8_t cmd[21] = { 0 }; /* packet head+payload */
135 uint32_t acc = (uint32_t)(fabs(accuracy));
136 uint32_t alti = (uint32_t)(altitude * 100); // m--->cm
137 uint32_t i = 0;
138 uint8_t message[25] = {0}; /* payload:17 + packet pad:8 */
139
140 memset(cmd, 0, sizeof(cmd));
141 cmd[0] = 0xF1;
142 cmd[1] = 0xD9;
143 cmd[2] = 0x0B;
144 cmd[3] = 0x10;
145
146 /* LLA : 1 */
147 cmd[4] = 0x01;
148
149 /* lat : 4 */
150 for (i = 0; i < 4; i++)
151 {
152 cmd[5 + i] = (latitude >> (i * 8)) & 0xff;
153 }
154
155 /* long : 4 */
156 for (i = 0; i < 4; i++)
157 {
158 cmd[9 + i] = (longitude >> (i * 8)) & 0xff;
159 }
160
161 /* alti : 4 */
162 for (i = 0; i < 4; i++)
163 {
164 cmd[13 + i] = (alti >> (i * 8)) & 0xff;
165 }
166
167 /* accuracy : 4 */
168 for (i = 0; i < 4; i++)
169 {
170 cmd[17 + i] = (acc >> (i * 8)) & 0xff;
171 }
172
173
174 int32_t len = message_package(message, cmd, sizeof(cmd) - 4);
175
176 LOGE("%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X",
177 message[0],message[1],message[2],message[3],message[4],message[5],message[6],message[7],
178 message[8],message[9],message[10],message[11],message[12],message[13],message[14],
179 message[15],message[16],message[17],message[18],message[19],message[20],
180 message[21],message[22],message[23],message[24]);
181
182 hd_agnss_uart_write(message, len);
183 hd_agnss_delay(3); // just example, use wait 3ms instead of ACK
184
185 return 0;
186}
187
b.liu9e8584b2024-11-06 19:21:28 +0800188/************************************eph data inject*************************************/
yq.wang99db6f52024-09-12 01:58:48 -0700189/**
190* @brief get the eph frame and send to HD80xx
191* @param data: the pointer of the eph data file
192* @param len : the total length of eph data file(eg:the length of HD_GPS_BD.hdb )
193* @retval 0: successs -1 error
194*/
195static int gnss_eph_inject_data(const char *eph_file_path)
196{
197 int packet_length;
198 int eph_file_fd = -1;
199 int size = 0;
200 int left_size = 0;
201 int total_size = 0;
202 int write_size = 0;
yq.wang9dd771b2024-09-13 23:38:40 -0700203 //int wait_time = 0;
yq.wang99db6f52024-09-12 01:58:48 -0700204 uint8_t *databuf = (uint8_t *)malloc(BUFFER_SIZE);
205 if(databuf == NULL)
206 {
207 LOGE("malloc fail");
208 return INJECT_RESULT_FAIL;
209 }
b.liu9e8584b2024-11-06 19:21:28 +0800210
yq.wang99db6f52024-09-12 01:58:48 -0700211 eph_file_fd = open(eph_file_path, O_RDWR);
212 if (eph_file_fd <= 0)
213 {
214 LOGE("%s open file FAIL. errno:%d\n", __FUNCTION__, errno);
b.liu9e8584b2024-11-06 19:21:28 +0800215 goto error;
yq.wang99db6f52024-09-12 01:58:48 -0700216 }
217 while(0 < (size = read(eph_file_fd, (databuf + left_size), BUFFER_SIZE)))
218 {
219 total_size = size + left_size;
220 left_size = 0;
221 for(int i=0; i < total_size;)
222 {
223 if((databuf[i] == 0xF1) && (databuf[i + 1] == 0xD9))
224 {
225 packet_length = (databuf[i + 4] | (databuf[i + 5] << 8));
226 if (i + packet_length + 8 <= total_size)
227 {
yq.wang9dd771b2024-09-13 23:38:40 -0700228 //hd_set_eph_inject_status(HD_EPH_INJECT_STATUS_WAIT_RETURN);
yq.wang99db6f52024-09-12 01:58:48 -0700229 write_size = hd_agnss_uart_write(databuf + i, packet_length + 8);
230 if(write_size < 0)
231 {
232 LOGE("hd_agnss_uart_write fail");
b.liu9e8584b2024-11-06 19:21:28 +0800233 goto error;
yq.wang99db6f52024-09-12 01:58:48 -0700234 }
235 LOGD("%s Write[%d]\r\n", __FUNCTION__, write_size);
yq.wang9dd771b2024-09-13 23:38:40 -0700236 hd_agnss_delay(50);
237#if 0
yq.wang99db6f52024-09-12 01:58:48 -0700238 wait_time = 0;
239 while(1)
240 {
241 wait_time += 100;
242 hd_agnss_delay(wait_time);
243 if(wait_time < 1000)
244 {
245 if(hd_get_eph_inject_status() == HD_EPH_INJECT_STATUS_SUCCESS)
246 {
247 break;
248 }
249 else if(hd_get_eph_inject_status() == HD_EPH_INJECT_STATUS_FAIL)
250 {
251 LOGE("8122 return fail");
252 goto error;
253 }
254 else
255 {
256 LOGE("eph inject wait 8122 return");
257 }
258 }
259 else
260 {
261 LOGE("8122 wait 1s return timeout");
262 goto error;
263 }
264 }
yq.wang9dd771b2024-09-13 23:38:40 -0700265#endif
yq.wang99db6f52024-09-12 01:58:48 -0700266 i = i + packet_length + 8;
267 }
268 else
269 {
270 left_size = total_size - i;
271 uint8_t *tmp = databuf;
272 databuf = (uint8_t *)malloc(BUFFER_SIZE + left_size);
273 memcpy(databuf, tmp + i ,left_size);
274 free(tmp);
275 break;
276 }
277 }
278 else
279 {
280 i++;
281 }
282 }
283 }
b.liu9e8584b2024-11-06 19:21:28 +0800284
yq.wang99db6f52024-09-12 01:58:48 -0700285 if(databuf)
286 {
287 free(databuf);
288 databuf = NULL;
289 }
290 if(eph_file_fd > 0)
291 {
292 close(eph_file_fd);
293 eph_file_fd = -1;
294 }
295 hd_set_eph_inject_status(HD_EPH_INJECT_STATUS_SUCCESS);
296 return INJECT_RESULT_SUCCESS;
297error:
298 if(databuf)
299 {
300 free(databuf);
301 databuf = NULL;
302 }
303 if(eph_file_fd > 0)
304 {
305 close(eph_file_fd);
306 eph_file_fd = -1;
307 }
308 hd_set_eph_inject_status(HD_EPH_INJECT_STATUS_SUCCESS);
309 return INJECT_RESULT_FAIL;
310}
311
312/************************************choice func inject*************************************/
313/**
314 * @brief AGNSS星历注入、位置注入、时间注入。星历、位置、时间可选择性注入。
315 * @param eph_file_path:从服务器下载的星历数据文件路径;若无则填NULL
316
317 latitude:纬度,乘以10^7;若无则填0
318 longitude:经度,乘以10^7;若无则填0
319 altitude:高程,浮点,单位为m;若无则填0
320 accuracy:精度;若无则填0
321
322 UTC_time:UTC时间;若无则填NULL
323 * @retval VOID
324**/
325int hd_agnss_inject(const char *eph_file_path, int32_t latitude, int32_t longitude, float altitude, float accuracy, /****latitude和longitude由double型乘以10^7得到*****/
326 HD_AGNSS_UTC_TIME_TYPE *UTC_time)
327{
328 int ret = INJECT_RESULT_SUCCESS;
b.liu9e8584b2024-11-06 19:21:28 +0800329 if (UTC_time != NULL)
yq.wang99db6f52024-09-12 01:58:48 -0700330 {
331 gnss_inject_time(UTC_time);
332 }
333
b.liu9e8584b2024-11-06 19:21:28 +0800334 if ((latitude != 0) && (longitude != 0))
yq.wang99db6f52024-09-12 01:58:48 -0700335 {
336 gnss_inject_location(latitude, longitude, altitude, accuracy);
337 }
338
b.liu9e8584b2024-11-06 19:21:28 +0800339 if (eph_file_path != NULL)
yq.wang99db6f52024-09-12 01:58:48 -0700340 {
341 ret = gnss_eph_inject_data(eph_file_path);
342 if(ret < 0)
343 {
344 LOGE("gnss_eph_inject_data fail");
345 return INJECT_RESULT_FAIL;
346 }
347 }
348 return INJECT_RESULT_SUCCESS;
349}
350
351
352/************************************set fd*************************************/
353void hd_set_gnss_dev_fd(int fd)
354{
355 hd_fd = fd;
356}
357
358/************************************check return*************************************/
359//gps f1 d9 05 01 02 00 0b 32 46 74
360//bds f1 d9 05 01 02 00 0b 33 46 74
361//glo f1 d9 05 01 02 00 0b 34 46 74
362
363int hd_eph_inject_result_check(const uint8_t *pack, int pack_len)
364{
365 if(pack_len == 0 || pack_len % 10)
366 {
367 LOGE("pack_len(%d) error.", pack_len);
368 return -1;
369 }
370 int count = pack_len / 10;
371 int i = 0;
372 while(i < count)
373 {
374 const uint8_t *ptr = pack + i * 10;
375 if(ptr[0] != 0xf1 || ptr[1] != 0xd9)
376 {
377 LOGE("Pack head error : %02x %02x", ptr[0], ptr[1]);
378 return INJECT_RESULT_FAIL;
379 }
380
381 if(ptr[2] != 0x05)
382 {
383 LOGE("Type not 0x05 : %02x", ptr[2]);
384 return INJECT_RESULT_FAIL;
385 }
386
387 if(ptr[6] != 0x0b || (ptr[7] < 0x32 && ptr[7] > 0x36))
388 {
389 LOGE("Unknown gid - %d, sid - %d", ptr[6], ptr[7]);
390 return INJECT_RESULT_FAIL;
391 }
392
393 if(ptr[3] == 0x01)
394 {
395 return INJECT_RESULT_SUCCESS;
396 }
397 else if(ptr[3] == 0x00)
398 {
399 return INJECT_RESULT_FAIL;
400 }
401 else
402 {
403 LOGE("ID not 0x00 or 0x01 : %02x", ptr[3]);
404 return INJECT_RESULT_FAIL;
405 }
406 i++;
407 }
408
409 return INJECT_RESULT_SUCCESS;
410}
411/************************************get or set status*************************************/
412void hd_set_eph_inject_status(hd_eph_inject_status_type status)
413{
414 eph_inject_status = status;
415}
416
417hd_eph_inject_status_type hd_get_eph_inject_status(void)
418{
419 return eph_inject_status;
420}
421