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