blob: 17ecda16e98b4b6805f0ed05e3ba9d08fda0e2bc [file] [log] [blame]
b.liu8f231a12024-05-31 17:55:06 +08001#include <stdio.h>
2#include <stdlib.h>
3#include <unistd.h>
4#include <errno.h>
5#include <fcntl.h>
6#include <termios.h>
7#include <fcntl.h>
8#include <string.h>
b.liu778645e2024-06-21 16:47:42 +08009#include <pthread.h>
b.liu8f231a12024-05-31 17:55:06 +080010
11#include "gnss_6228.h"
12#include "gnss_utils.h"
13#include "mbtk_str.h"
14#include "mbtk_log.h"
15#include "mbtk_utils.h"
16
17typedef enum {
18 GNSS_6228_STATE_NON,
19 GNSS_6228_STATE_WAIT_YC,
20 GNSS_6228_STATE_BL_DL,
21 GNSS_6228_STATE_FW_DL,
22 GNSS_6228_STATE_SETTING
23} gnss_6228_state_enum;
24
25typedef enum {
26 XMODEM_STATE_C_NAK_WAIT,
27 XMODEM_STATE_DATA_SENDING,
28 XMODEM_STATE_EOT_SENDING,
29 XMODEM_STATE_C_NAK_GET,
30 XMODEM_STATE_DATA_ACK_GET,
31 XMODEM_STATE_DATA_NAK_GET,
32 XMODEM_STATE_EOT_ACK_GET,
33 XMODEM_STATE_EOT_NAK_GET,
34 XMODEM_STATE_CAN_GET,
35} xmodem_state_enum;
36
37#define VMIN 6
38#define GPS_DEV "/sys/devices/soc.0/d4000000.apb/mbtk-dev-op/gps_power"
39#define GNSS_6228_BOOTLOADER "/etc/mbtk/bootloader_r3.0.0_build6773_uartboot_921600.pkg"
40#define GNSS_6228_FIRMWARE "/etc/mbtk/UC6228CI-R3.5.2.19Build4370_mfg.pkg"
41
42#define GNSS_SET_TIMEOUT 3000 // 3s
43
44#define UART_BITRATE_DL_BL 230400
45#define UART_BITRATE_DL_FW 921600
46#define UART_BITRATE_NMEA_DEF_FW 9600 // Default bitrate.
47#define UART_BITRATE_NMEA 460800
48
49#define GNSS_6228_WAIT_YC_COUNT 40
50
51#define XMODEM_SOH 0x01
52#define XMODEM_STX 0x02
53#define XMODEM_EOT 0x04
54#define XMODEM_ACK 0x06
55#define XMODEM_NAK 0x15
56#define XMODEM_CAN 0x18
57#define XMODEM_CRC_CHR 'C'
58#define XMODEM_CRC_SIZE 2 /* Crc_High Byte + Crc_Low Byte */
59#define XMODEM_FRAME_ID_SIZE 2 /* Frame_Id + 255-Frame_Id */
60#define XMODEM_DATA_SIZE_SOH 128 /* for Xmodem protocol */
61#define XMODEM_DATA_SIZE_STX 1024 /* for 1K xmodem protocol */
62#define USE_1K_XMODEM 1 /* 1 for use 1k_xmodem 0 for xmodem */
63#define TIMEOUT_USEC 0
64#define TIMEOUT_SEC 10
65
66#if (USE_1K_XMODEM)
67#define XMODEM_DATA_SIZE XMODEM_DATA_SIZE_STX
68#define XMODEM_HEAD XMODEM_STX
69#else
70#define XMODEM_DATA_SIZE XMODEM_DATA_SIZE_SOH
71#define XMODEM_HEAD XMODEM_SOH
72#endif
73#define XMODEM_PACK_SIZE (XMODEM_DATA_SIZE + XMODEM_CRC_SIZE + XMODEM_FRAME_ID_SIZE + 1)
74
75
76
77
78// Default bitrate.
79static gnss_6228_state_enum gnss_state = GNSS_6228_STATE_WAIT_YC;
80static xmodem_state_enum xmodem_state = XMODEM_STATE_C_NAK_WAIT;
81static pthread_cond_t read_cond;
82static pthread_mutex_t read_mutex;
83static char xmodem_pack_buff[XMODEM_PACK_SIZE];
84static int xmodem_pack_index = 0;
85static void *gnss_set_rsp_ptr = NULL;
86static gnss_err_enum gnss_set_result = GNSS_ERR_OK;
87
88
89int gnss_write(int fd, const void *data, int data_len);
90
91static void gnss_set_timer_cb(int signo)
92{
93 if(gnss_state == GNSS_6228_STATE_SETTING) {
94 pthread_mutex_lock(&read_mutex);
95 pthread_cond_signal(&read_cond);
96 pthread_mutex_unlock(&read_mutex);
97 gnss_set_result = GNSS_ERR_TIMEOUT;
98 }
99 return;
100}
101
102int gnss_init_config(int fd)
103{
104 char *send_buf = "$ANTSTAT,1\r\n";
105 gnss_write(fd, send_buf, strlen(send_buf));
106 send_buf = "$ANTSTAT1\r\n";
107 gnss_write(fd, send_buf, strlen(send_buf));
108 send_buf = "$PDTINFO\r\n";
109 gnss_write(fd, send_buf, strlen(send_buf));
110 send_buf = "$CFGNMEA\r\n";
111 gnss_write(fd, send_buf, strlen(send_buf));
112 send_buf = "$CFGPRT,1\r\n";
113 gnss_write(fd, send_buf, strlen(send_buf));
114 send_buf = "$CFGAID,0\r\n";
115 gnss_write(fd, send_buf, strlen(send_buf));
116 return 0;
117}
118
119static void gnss_cmd_rsp_process(const void *data, int data_len) {
120 const char *ptr = (const char*)data;
121 LOGD("Setting RSP : %s", ptr);
122 if(memcmp(ptr, "$PDTINFO,", 9) == 0) {
b.liud0ba7152024-06-19 14:47:21 +0800123 if(gnss_set_rsp_ptr) {
124 gnss_6228_dev_info_t *dev_info = (gnss_6228_dev_info_t*)gnss_set_rsp_ptr;
125 if(6 == gnss_nmea_sscanf(ptr + 9, dev_info->pdtName, dev_info->Config,
126 dev_info->hwVer, dev_info->fwVer, dev_info->PN, dev_info->SN)) {
127 LOGD("$PDTINFO : %s,%s,%s,%s,%s,%s", dev_info->pdtName, dev_info->Config,
128 dev_info->hwVer, dev_info->fwVer, dev_info->PN, dev_info->SN);
129 } else {
130 LOGW("Parse $PDTINFO error.");
131 }
b.liu8f231a12024-05-31 17:55:06 +0800132 }
133 }
134
135
136 else if(memcmp(ptr, "$OK", 3) == 0 || memcmp(ptr, "$Fail", 5) == 0)
137 {
138 // $Fail,0*3E
139 if(memcmp(ptr, "$Fail", 5) == 0) {
140 int code = atoi(ptr + 6);
141 if(code == 1) {
142 gnss_set_result = GNSS_ERR_CHECKSUM;
143 } else if(code == 0) {
144 gnss_set_result = GNSS_ERR_ARG;
145 } else {
146 gnss_set_result = GNSS_ERR_UNKNOWN;
147 }
148 }
149
150 mbtk_timer_clear();
151
152 pthread_mutex_lock(&read_mutex);
153 pthread_cond_signal(&read_cond);
154 pthread_mutex_unlock(&read_mutex);
155 }
156}
157
158int gnss_6228_dev_open()
159{
160 int fd, ret;
161 fd = open(GPS_DEV, O_RDWR | O_TRUNC, 0644);
162 if(fd < 0)
163 {
164 LOGE("[%s] file [%s] open error\n", __FUNCTION__, GPS_DEV);
165 return -1;
166 }
167 ret = write(fd, "on", 2);
168 if (ret < 0)
169 {
170 LOGE("%s: error writing to file!\n", __FUNCTION__);
171 close(fd);
172 return -2;
173 }
174
175 close(fd);
176 return 0;
177}
178
b.liu978f5432024-07-01 18:04:18 +0800179int gnss_6228_dev_close(int uart_fd)
b.liu8f231a12024-05-31 17:55:06 +0800180{
181 int fd, ret;
182 fd = open(GPS_DEV, O_RDWR | O_TRUNC, 0644);
183 if(fd < 0)
184 {
185 LOGE("[%s] file [%s] open error\n", __FUNCTION__, GPS_DEV);
186 return -1;
187 }
188 ret = write(fd, "off", 3);
189 if (ret < 0)
190 {
191 LOGE("%s: error writing to file!\n", __FUNCTION__);
192 close(fd);
193 return -2;
194 }
195
196 close(fd);
197 return 0;
198}
199
200int gnss_6228_open(const char *dev)
201{
202 pthread_mutex_init(&read_mutex, NULL);
203 pthread_cond_init(&read_cond, NULL);
204 return gnss_port_open(dev, O_RDWR | O_NONBLOCK | O_NOCTTY, UART_BITRATE_NMEA_DEF_FW, TRUE);
205}
206
207int gnss_6228_close(int fd)
208{
209 pthread_mutex_destroy(&read_mutex);
210 pthread_cond_destroy(&read_cond);
211 return gnss_port_close(fd);
212}
213
214static void xmodem_state_change(const void *data, int data_len)
215{
216 // log_hex("XModem-RECV", data, data_len);
217
218 pthread_mutex_lock(&read_mutex);
219 const char *ptr = (const char*)data;
220 if(ptr[0] == XMODEM_CAN) {
221 LOGD("GET CAN message.");
222 xmodem_state = XMODEM_STATE_CAN_GET;
223 pthread_cond_signal(&read_cond);
224 pthread_mutex_unlock(&read_mutex);
225 return;
226 }
227
228 switch(xmodem_state) {
229 case XMODEM_STATE_C_NAK_WAIT:
230 {
231#if 0
232 if(ptr[0] == XMODEM_CRC_CHR || ptr[0] == XMODEM_NAK) {
233 LOGD("GET C/NAK(X-Modem start...)");
234 xmodem_state = XMODEM_STATE_C_NAK_GET;
235 pthread_cond_signal(&read_cond);
236 }
237#else
238 if(ptr[0] == XMODEM_CRC_CHR) {
239 LOGD("GET C (X-Modem start...)");
240 xmodem_state = XMODEM_STATE_C_NAK_GET;
241 pthread_cond_signal(&read_cond);
242 }
243#endif
244 break;
245 }
246 case XMODEM_STATE_DATA_SENDING:
247 {
248 if(ptr[0] == XMODEM_NAK) {
249 xmodem_state = XMODEM_STATE_DATA_NAK_GET;
250 pthread_cond_signal(&read_cond);
251 } else if(ptr[0] == XMODEM_ACK) {
252 xmodem_state = XMODEM_STATE_DATA_ACK_GET;
253 pthread_cond_signal(&read_cond);
254 }
255 break;
256 }
257 case XMODEM_STATE_EOT_SENDING:
258 {
259 if(ptr[0] == XMODEM_NAK) {
260 xmodem_state = XMODEM_STATE_EOT_NAK_GET;
261 pthread_cond_signal(&read_cond);
262 } else if(ptr[0] == XMODEM_ACK) {
263 xmodem_state = XMODEM_STATE_EOT_ACK_GET;
264 pthread_cond_signal(&read_cond);
265 }
266 break;
267 }
268 default:
269 {
270 break;
271 }
272 }
273 pthread_mutex_unlock(&read_mutex);
274}
275
276void gnss_6228_dl_read_cb(const void *data, int data_len)
277{
b.liu9e8584b2024-11-06 19:21:28 +0800278// const char *buff = (const char*)data;
279// int index = 0;
b.liu8f231a12024-05-31 17:55:06 +0800280 switch(gnss_state) {
281 case GNSS_6228_STATE_WAIT_YC:
282 {
283#if 0
284 static bool found_y = FALSE;
285 while(index < data_len) {
286 if(found_y) {
287 if(buff[index] == 'C') { // Found "YC"
288 gnss_state = GNSS_6228_STATE_BL_DL;
289 bool found_y = FALSE; // Should reset.
290 LOGD("Get YC");
291 break;
292 } else {
293 found_y = FALSE; // Is "Yxxx" and not "YC".
294 }
295 } else {
296 if(buff[index] == 'Y') { // Only found "Y"
297 found_y = TRUE;
298 }
299 }
300 index++;
301 }
302#else
303 if(strstr(data, "YC")) {
304 gnss_state = GNSS_6228_STATE_BL_DL;
305 LOGD("Get YC");
306 }
307#endif
308 break;
309 }
310 case GNSS_6228_STATE_BL_DL:
311 case GNSS_6228_STATE_FW_DL:
312 {
313 xmodem_state_change(data, data_len);
314 break;
315 }
316 default:
317 {
318 LOGW("Unknown 6228 state:%d", gnss_state);
319 break;
320 }
321 }
322}
323
324void gnss_6228_set_cb(const void *data, int data_len)
325{
b.liu9e8584b2024-11-06 19:21:28 +0800326// const char *buff = (const char*)data;
b.liu8f231a12024-05-31 17:55:06 +0800327 switch(gnss_state) {
328 case GNSS_6228_STATE_SETTING:
329 {
330 gnss_cmd_rsp_process(data, data_len);
331 break;
332 }
333 default:
334 {
335 break;
336 }
337 }
338}
339
340
341static int gnss_xmodem_pack_send(int uart_fd, int pack_index, char *data, int data_len)
342{
343 if(data_len > XMODEM_DATA_SIZE) {
344 LOGE("X-Modem data lenght error:%d", data_len);
345 return -1;
346 }
347
348 if(pack_index != xmodem_pack_index) {
349 memset(xmodem_pack_buff, 0x1A, XMODEM_PACK_SIZE);
350 xmodem_pack_buff[0] = XMODEM_HEAD; // 帧开始字符
351 xmodem_pack_buff[1] = (char)pack_index; // 信息包序号
352 xmodem_pack_buff[2] = (char)(255 - xmodem_pack_buff[1]); // 信息包序号的补码
353
354 memcpy(xmodem_pack_buff + 3, data, data_len);
355
356 uint16 crc_value = get_crc16(xmodem_pack_buff + 3, XMODEM_DATA_SIZE); // 16位crc校验
357 xmodem_pack_buff[XMODEM_DATA_SIZE+3] = (unsigned char)(crc_value >> 8);// 高八位数据
358 xmodem_pack_buff[XMODEM_DATA_SIZE+4] = (unsigned char)(crc_value); //低八位数据
359 xmodem_pack_index = pack_index;
360 }
361
362 return gnss_write(uart_fd, xmodem_pack_buff, XMODEM_PACK_SIZE);
363}
364
365static int gnss_xmodem_send(int fd, char *file_name)
366{
367 xmodem_state = XMODEM_STATE_C_NAK_WAIT;
368
369 bool running = TRUE;
370 int result = 0;
371 xmodem_pack_index = 0;
372 int pack_index = 1;
373 int file_fd = open(file_name, O_RDONLY);
374 if(file_fd <= 0) {
375 LOGE("Can't open (%s) or not exist!(errno=%d)", file_name, errno);
376 return -1;
377 }
378 char buff[XMODEM_DATA_SIZE];
379 int len = 0;
380
381 pthread_mutex_lock(&read_mutex);
382 while(running) {
383 //LOGD("Waitting...");
384 pthread_cond_wait(&read_cond, &read_mutex);
385 //LOGD("Continue : %d", xmodem_state);
386 switch(xmodem_state)
387 {
388 case XMODEM_STATE_C_NAK_GET:
389 case XMODEM_STATE_DATA_ACK_GET:
390 {
391 len = read(file_fd, buff, XMODEM_DATA_SIZE);
392 if(len > 0) {
393 if(XMODEM_PACK_SIZE != gnss_xmodem_pack_send(fd, pack_index, buff, len)) {
394 LOGE( "Send xmodem package fail.");
395 running = FALSE;
396 result = -1;
397 }
398 xmodem_state = XMODEM_STATE_DATA_SENDING;
399 } else {
400 LOGW("Read file complete[len = %d, errno = %d]", len, errno);
401 //running = FALSE;
402 char end_cmd = XMODEM_EOT;
403 if(gnss_write(fd, &end_cmd, 1) != 1) {
404 LOGE("Send EOT fail.");
405 //running = FALSE;
406 } else {
407 xmodem_state = XMODEM_STATE_EOT_SENDING;
408 }
409 }
410 pack_index++;
411 break;
412 }
413 case XMODEM_STATE_DATA_NAK_GET:
414 {
415 // Retry
416 if(XMODEM_PACK_SIZE != gnss_xmodem_pack_send(fd, pack_index - 1, NULL, XMODEM_DATA_SIZE)) {
417 LOGE( "Retry send xmodem package fail.");
418 running = FALSE;
419 result = -1;
420 }
421 xmodem_state = XMODEM_STATE_DATA_SENDING;
422 break;
423 }
424
425 case XMODEM_STATE_EOT_ACK_GET:
426 {
427 LOGD("Send EOT success.");
428 running = FALSE;
429 break;
430 }
431 case XMODEM_STATE_EOT_NAK_GET:
432 {
433 LOGW("Send EOT fail, retry...");
434 char end_cmd = XMODEM_EOT;
435 if(gnss_write(fd, &end_cmd, 1) != 1) {
436 LOGE("Send EOT fail.");
437 //running = FALSE;
438 } else {
439 xmodem_state = XMODEM_STATE_EOT_SENDING;
440 }
441 break;
442 }
443 case XMODEM_STATE_CAN_GET:
444 {
445 LOGD("Recv CAN message.");
446 running = FALSE;
447 break;
448 }
449 default:
450 {
451 LOGE("Unknown X-Modem state : %d", xmodem_state);
452 running = FALSE;
453 result = -1;
454 break;
455 }
456 }
457 }
458 pthread_mutex_unlock(&read_mutex);
459
460 if(file_fd > 0) {
461 close(file_fd);
462 }
463 return result;
464}
465
b.liudbc3f4b2024-06-25 18:22:24 +0800466int gnss_6228_fw_dl(int fd, const char *fw_name, const char *dev)
b.liu8f231a12024-05-31 17:55:06 +0800467{
468 // Set bootloader baudrate.
469 gnss_set_baudrate(fd, uart_baud_get(UART_BITRATE_DL_BL));
470
471 gnss_state = GNSS_6228_STATE_WAIT_YC;
472 int wait_yc_num = 0;
473 while(gnss_state == GNSS_6228_STATE_WAIT_YC && wait_yc_num < GNSS_6228_WAIT_YC_COUNT) {
b.liu9e8584b2024-11-06 19:21:28 +0800474 mbtk_write(fd, "M!T", 3);
b.liu8f231a12024-05-31 17:55:06 +0800475 usleep(500);
476 wait_yc_num++;
477 }
478
479 if(wait_yc_num >= GNSS_6228_WAIT_YC_COUNT) {
480 LOGE("Wait YC timeout : %d / %d", wait_yc_num, GNSS_6228_WAIT_YC_COUNT);
481 return -1;
482 }
483
484 // Start download bootloader.
485 LOGD("Start download bootloader : %s", GNSS_6228_BOOTLOADER);
486 gnss_state = GNSS_6228_STATE_BL_DL;
487 if(gnss_xmodem_send(fd, GNSS_6228_BOOTLOADER)) {
488 LOGE("Download bootloader fail.");
489 return -1;
490 }
491 LOGD("Bootloader download success.");
492
493 // Set firmware baudrate.
494 gnss_set_baudrate(fd, uart_baud_get(UART_BITRATE_DL_FW));
495
496 // Start download firmware.
497 LOGD("Start download firmware : %s", GNSS_6228_FIRMWARE);
498 gnss_state = GNSS_6228_STATE_FW_DL;
499 if(gnss_xmodem_send(fd, GNSS_6228_FIRMWARE)) {
500 LOGE("Download firmware fail.");
501 return -1;
502 }
503 LOGD("Firmware download success.");
504
505 // Set NMEA baudrate.
506 gnss_set_baudrate(fd, uart_baud_get(UART_BITRATE_NMEA));
507
508 return 0;
509}
510
511gnss_err_enum gnss_6228_set(int fd, const char *cmd, void *cmd_rsp, int cmd_rsp_len)
512{
513 gnss_state = GNSS_6228_STATE_SETTING;
514 gnss_set_rsp_ptr = cmd_rsp;
515 gnss_set_result = GNSS_ERR_OK;
516 mbtk_timer_set(gnss_set_timer_cb, GNSS_SET_TIMEOUT);
517
518 char cmd_tmp[128] = {0};
519 snprintf(cmd_tmp, sizeof(cmd_tmp), "%s\r\n", cmd);
520 gnss_write(fd, cmd_tmp, strlen(cmd_tmp));
521
522 pthread_mutex_lock(&read_mutex);
523 pthread_cond_wait(&read_cond, &read_mutex);
524 pthread_mutex_unlock(&read_mutex);
525
526 gnss_state = GNSS_6228_STATE_NON;
527 return gnss_set_result;
528}
529