blob: 4acbe3348e6c69d1eb59fd085a8fe4bf77106c23 [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{
30 int TxLen;
31 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
83/************************************time inject*************************************/
84static 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
188/************************************eph data inject*************************************/
189/**
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;
203 int wait_time = 0;
204 uint8_t *databuf = (uint8_t *)malloc(BUFFER_SIZE);
205 if(databuf == NULL)
206 {
207 LOGE("malloc fail");
208 return INJECT_RESULT_FAIL;
209 }
210
211 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);
215 goto error;
216 }
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 {
228 hd_set_eph_inject_status(HD_EPH_INJECT_STATUS_WAIT_RETURN);
229 write_size = hd_agnss_uart_write(databuf + i, packet_length + 8);
230 if(write_size < 0)
231 {
232 LOGE("hd_agnss_uart_write fail");
233 goto error;
234 }
235 LOGD("%s Write[%d]\r\n", __FUNCTION__, write_size);
236 wait_time = 0;
237 while(1)
238 {
239 wait_time += 100;
240 hd_agnss_delay(wait_time);
241 if(wait_time < 1000)
242 {
243 if(hd_get_eph_inject_status() == HD_EPH_INJECT_STATUS_SUCCESS)
244 {
245 break;
246 }
247 else if(hd_get_eph_inject_status() == HD_EPH_INJECT_STATUS_FAIL)
248 {
249 LOGE("8122 return fail");
250 goto error;
251 }
252 else
253 {
254 LOGE("eph inject wait 8122 return");
255 }
256 }
257 else
258 {
259 LOGE("8122 wait 1s return timeout");
260 goto error;
261 }
262 }
263 i = i + packet_length + 8;
264 }
265 else
266 {
267 left_size = total_size - i;
268 uint8_t *tmp = databuf;
269 databuf = (uint8_t *)malloc(BUFFER_SIZE + left_size);
270 memcpy(databuf, tmp + i ,left_size);
271 free(tmp);
272 break;
273 }
274 }
275 else
276 {
277 i++;
278 }
279 }
280 }
281
282 if(databuf)
283 {
284 free(databuf);
285 databuf = NULL;
286 }
287 if(eph_file_fd > 0)
288 {
289 close(eph_file_fd);
290 eph_file_fd = -1;
291 }
292 hd_set_eph_inject_status(HD_EPH_INJECT_STATUS_SUCCESS);
293 return INJECT_RESULT_SUCCESS;
294error:
295 if(databuf)
296 {
297 free(databuf);
298 databuf = NULL;
299 }
300 if(eph_file_fd > 0)
301 {
302 close(eph_file_fd);
303 eph_file_fd = -1;
304 }
305 hd_set_eph_inject_status(HD_EPH_INJECT_STATUS_SUCCESS);
306 return INJECT_RESULT_FAIL;
307}
308
309/************************************choice func inject*************************************/
310/**
311 * @brief AGNSS星历注入、位置注入、时间注入。星历、位置、时间可选择性注入。
312 * @param eph_file_path:从服务器下载的星历数据文件路径;若无则填NULL
313
314 latitude:纬度,乘以10^7;若无则填0
315 longitude:经度,乘以10^7;若无则填0
316 altitude:高程,浮点,单位为m;若无则填0
317 accuracy:精度;若无则填0
318
319 UTC_time:UTC时间;若无则填NULL
320 * @retval VOID
321**/
322int hd_agnss_inject(const char *eph_file_path, int32_t latitude, int32_t longitude, float altitude, float accuracy, /****latitude和longitude由double型乘以10^7得到*****/
323 HD_AGNSS_UTC_TIME_TYPE *UTC_time)
324{
325 int ret = INJECT_RESULT_SUCCESS;
326 if (UTC_time != NULL)
327 {
328 gnss_inject_time(UTC_time);
329 }
330
331 if ((latitude != 0) && (longitude != 0))
332 {
333 gnss_inject_location(latitude, longitude, altitude, accuracy);
334 }
335
336 if (eph_file_path != NULL)
337 {
338 ret = gnss_eph_inject_data(eph_file_path);
339 if(ret < 0)
340 {
341 LOGE("gnss_eph_inject_data fail");
342 return INJECT_RESULT_FAIL;
343 }
344 }
345 return INJECT_RESULT_SUCCESS;
346}
347
348
349/************************************set fd*************************************/
350void hd_set_gnss_dev_fd(int fd)
351{
352 hd_fd = fd;
353}
354
355/************************************check return*************************************/
356//gps f1 d9 05 01 02 00 0b 32 46 74
357//bds f1 d9 05 01 02 00 0b 33 46 74
358//glo f1 d9 05 01 02 00 0b 34 46 74
359
360int hd_eph_inject_result_check(const uint8_t *pack, int pack_len)
361{
362 if(pack_len == 0 || pack_len % 10)
363 {
364 LOGE("pack_len(%d) error.", pack_len);
365 return -1;
366 }
367 int count = pack_len / 10;
368 int i = 0;
369 while(i < count)
370 {
371 const uint8_t *ptr = pack + i * 10;
372 if(ptr[0] != 0xf1 || ptr[1] != 0xd9)
373 {
374 LOGE("Pack head error : %02x %02x", ptr[0], ptr[1]);
375 return INJECT_RESULT_FAIL;
376 }
377
378 if(ptr[2] != 0x05)
379 {
380 LOGE("Type not 0x05 : %02x", ptr[2]);
381 return INJECT_RESULT_FAIL;
382 }
383
384 if(ptr[6] != 0x0b || (ptr[7] < 0x32 && ptr[7] > 0x36))
385 {
386 LOGE("Unknown gid - %d, sid - %d", ptr[6], ptr[7]);
387 return INJECT_RESULT_FAIL;
388 }
389
390 if(ptr[3] == 0x01)
391 {
392 return INJECT_RESULT_SUCCESS;
393 }
394 else if(ptr[3] == 0x00)
395 {
396 return INJECT_RESULT_FAIL;
397 }
398 else
399 {
400 LOGE("ID not 0x00 or 0x01 : %02x", ptr[3]);
401 return INJECT_RESULT_FAIL;
402 }
403 i++;
404 }
405
406 return INJECT_RESULT_SUCCESS;
407}
408/************************************get or set status*************************************/
409void hd_set_eph_inject_status(hd_eph_inject_status_type status)
410{
411 eph_inject_status = status;
412}
413
414hd_eph_inject_status_type hd_get_eph_inject_status(void)
415{
416 return eph_inject_status;
417}
418