blob: 2cd86a4c1d3620e6b1da5dfaeffa7d2239aac249 [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) {
122 gnss_6228_dev_info_t *dev_info = (gnss_6228_dev_info_t*)gnss_set_rsp_ptr;
123 if(6 == gnss_nmea_sscanf(ptr + 9, dev_info->pdtName, dev_info->Config,
124 dev_info->hwVer, dev_info->fwVer, dev_info->PN, dev_info->SN)) {
125 LOGD("$PDTINFO : %s,%s,%s,%s,%s,%s", dev_info->pdtName, dev_info->Config,
126 dev_info->hwVer, dev_info->fwVer, dev_info->PN, dev_info->SN);
127 } else {
128 LOGW("Parse $PDTINFO error.");
129 }
130 }
131
132
133 else if(memcmp(ptr, "$OK", 3) == 0 || memcmp(ptr, "$Fail", 5) == 0)
134 {
135 // $Fail,0*3E
136 if(memcmp(ptr, "$Fail", 5) == 0) {
137 int code = atoi(ptr + 6);
138 if(code == 1) {
139 gnss_set_result = GNSS_ERR_CHECKSUM;
140 } else if(code == 0) {
141 gnss_set_result = GNSS_ERR_ARG;
142 } else {
143 gnss_set_result = GNSS_ERR_UNKNOWN;
144 }
145 }
146
147 mbtk_timer_clear();
148
149 pthread_mutex_lock(&read_mutex);
150 pthread_cond_signal(&read_cond);
151 pthread_mutex_unlock(&read_mutex);
152 }
153}
154
155int gnss_6228_dev_open()
156{
157 int fd, ret;
158 fd = open(GPS_DEV, O_RDWR | O_TRUNC, 0644);
159 if(fd < 0)
160 {
161 LOGE("[%s] file [%s] open error\n", __FUNCTION__, GPS_DEV);
162 return -1;
163 }
164 ret = write(fd, "on", 2);
165 if (ret < 0)
166 {
167 LOGE("%s: error writing to file!\n", __FUNCTION__);
168 close(fd);
169 return -2;
170 }
171
172 close(fd);
173 return 0;
174}
175
176int gnss_6228_dev_close()
177{
178 int fd, ret;
179 fd = open(GPS_DEV, O_RDWR | O_TRUNC, 0644);
180 if(fd < 0)
181 {
182 LOGE("[%s] file [%s] open error\n", __FUNCTION__, GPS_DEV);
183 return -1;
184 }
185 ret = write(fd, "off", 3);
186 if (ret < 0)
187 {
188 LOGE("%s: error writing to file!\n", __FUNCTION__);
189 close(fd);
190 return -2;
191 }
192
193 close(fd);
194 return 0;
195}
196
197int gnss_6228_open(const char *dev)
198{
199 pthread_mutex_init(&read_mutex, NULL);
200 pthread_cond_init(&read_cond, NULL);
201 return gnss_port_open(dev, O_RDWR | O_NONBLOCK | O_NOCTTY, UART_BITRATE_NMEA_DEF_FW, TRUE);
202}
203
204int gnss_6228_close(int fd)
205{
206 pthread_mutex_destroy(&read_mutex);
207 pthread_cond_destroy(&read_cond);
208 return gnss_port_close(fd);
209}
210
211static void xmodem_state_change(const void *data, int data_len)
212{
213 // log_hex("XModem-RECV", data, data_len);
214
215 pthread_mutex_lock(&read_mutex);
216 const char *ptr = (const char*)data;
217 if(ptr[0] == XMODEM_CAN) {
218 LOGD("GET CAN message.");
219 xmodem_state = XMODEM_STATE_CAN_GET;
220 pthread_cond_signal(&read_cond);
221 pthread_mutex_unlock(&read_mutex);
222 return;
223 }
224
225 switch(xmodem_state) {
226 case XMODEM_STATE_C_NAK_WAIT:
227 {
228#if 0
229 if(ptr[0] == XMODEM_CRC_CHR || ptr[0] == XMODEM_NAK) {
230 LOGD("GET C/NAK(X-Modem start...)");
231 xmodem_state = XMODEM_STATE_C_NAK_GET;
232 pthread_cond_signal(&read_cond);
233 }
234#else
235 if(ptr[0] == XMODEM_CRC_CHR) {
236 LOGD("GET C (X-Modem start...)");
237 xmodem_state = XMODEM_STATE_C_NAK_GET;
238 pthread_cond_signal(&read_cond);
239 }
240#endif
241 break;
242 }
243 case XMODEM_STATE_DATA_SENDING:
244 {
245 if(ptr[0] == XMODEM_NAK) {
246 xmodem_state = XMODEM_STATE_DATA_NAK_GET;
247 pthread_cond_signal(&read_cond);
248 } else if(ptr[0] == XMODEM_ACK) {
249 xmodem_state = XMODEM_STATE_DATA_ACK_GET;
250 pthread_cond_signal(&read_cond);
251 }
252 break;
253 }
254 case XMODEM_STATE_EOT_SENDING:
255 {
256 if(ptr[0] == XMODEM_NAK) {
257 xmodem_state = XMODEM_STATE_EOT_NAK_GET;
258 pthread_cond_signal(&read_cond);
259 } else if(ptr[0] == XMODEM_ACK) {
260 xmodem_state = XMODEM_STATE_EOT_ACK_GET;
261 pthread_cond_signal(&read_cond);
262 }
263 break;
264 }
265 default:
266 {
267 break;
268 }
269 }
270 pthread_mutex_unlock(&read_mutex);
271}
272
273void gnss_6228_dl_read_cb(const void *data, int data_len)
274{
275 const char *buff = (const char*)data;
276 int index = 0;
277 switch(gnss_state) {
278 case GNSS_6228_STATE_WAIT_YC:
279 {
280#if 0
281 static bool found_y = FALSE;
282 while(index < data_len) {
283 if(found_y) {
284 if(buff[index] == 'C') { // Found "YC"
285 gnss_state = GNSS_6228_STATE_BL_DL;
286 bool found_y = FALSE; // Should reset.
287 LOGD("Get YC");
288 break;
289 } else {
290 found_y = FALSE; // Is "Yxxx" and not "YC".
291 }
292 } else {
293 if(buff[index] == 'Y') { // Only found "Y"
294 found_y = TRUE;
295 }
296 }
297 index++;
298 }
299#else
300 if(strstr(data, "YC")) {
301 gnss_state = GNSS_6228_STATE_BL_DL;
302 LOGD("Get YC");
303 }
304#endif
305 break;
306 }
307 case GNSS_6228_STATE_BL_DL:
308 case GNSS_6228_STATE_FW_DL:
309 {
310 xmodem_state_change(data, data_len);
311 break;
312 }
313 default:
314 {
315 LOGW("Unknown 6228 state:%d", gnss_state);
316 break;
317 }
318 }
319}
320
321void gnss_6228_set_cb(const void *data, int data_len)
322{
323 const char *buff = (const char*)data;
324 switch(gnss_state) {
325 case GNSS_6228_STATE_SETTING:
326 {
327 gnss_cmd_rsp_process(data, data_len);
328 break;
329 }
330 default:
331 {
332 break;
333 }
334 }
335}
336
337
338static int gnss_xmodem_pack_send(int uart_fd, int pack_index, char *data, int data_len)
339{
340 if(data_len > XMODEM_DATA_SIZE) {
341 LOGE("X-Modem data lenght error:%d", data_len);
342 return -1;
343 }
344
345 if(pack_index != xmodem_pack_index) {
346 memset(xmodem_pack_buff, 0x1A, XMODEM_PACK_SIZE);
347 xmodem_pack_buff[0] = XMODEM_HEAD; // 帧开始字符
348 xmodem_pack_buff[1] = (char)pack_index; // 信息包序号
349 xmodem_pack_buff[2] = (char)(255 - xmodem_pack_buff[1]); // 信息包序号的补码
350
351 memcpy(xmodem_pack_buff + 3, data, data_len);
352
353 uint16 crc_value = get_crc16(xmodem_pack_buff + 3, XMODEM_DATA_SIZE); // 16位crc校验
354 xmodem_pack_buff[XMODEM_DATA_SIZE+3] = (unsigned char)(crc_value >> 8);// 高八位数据
355 xmodem_pack_buff[XMODEM_DATA_SIZE+4] = (unsigned char)(crc_value); //低八位数据
356 xmodem_pack_index = pack_index;
357 }
358
359 return gnss_write(uart_fd, xmodem_pack_buff, XMODEM_PACK_SIZE);
360}
361
362static int gnss_xmodem_send(int fd, char *file_name)
363{
364 xmodem_state = XMODEM_STATE_C_NAK_WAIT;
365
366 bool running = TRUE;
367 int result = 0;
368 xmodem_pack_index = 0;
369 int pack_index = 1;
370 int file_fd = open(file_name, O_RDONLY);
371 if(file_fd <= 0) {
372 LOGE("Can't open (%s) or not exist!(errno=%d)", file_name, errno);
373 return -1;
374 }
375 char buff[XMODEM_DATA_SIZE];
376 int len = 0;
377
378 pthread_mutex_lock(&read_mutex);
379 while(running) {
380 //LOGD("Waitting...");
381 pthread_cond_wait(&read_cond, &read_mutex);
382 //LOGD("Continue : %d", xmodem_state);
383 switch(xmodem_state)
384 {
385 case XMODEM_STATE_C_NAK_GET:
386 case XMODEM_STATE_DATA_ACK_GET:
387 {
388 len = read(file_fd, buff, XMODEM_DATA_SIZE);
389 if(len > 0) {
390 if(XMODEM_PACK_SIZE != gnss_xmodem_pack_send(fd, pack_index, buff, len)) {
391 LOGE( "Send xmodem package fail.");
392 running = FALSE;
393 result = -1;
394 }
395 xmodem_state = XMODEM_STATE_DATA_SENDING;
396 } else {
397 LOGW("Read file complete[len = %d, errno = %d]", len, errno);
398 //running = FALSE;
399 char end_cmd = XMODEM_EOT;
400 if(gnss_write(fd, &end_cmd, 1) != 1) {
401 LOGE("Send EOT fail.");
402 //running = FALSE;
403 } else {
404 xmodem_state = XMODEM_STATE_EOT_SENDING;
405 }
406 }
407 pack_index++;
408 break;
409 }
410 case XMODEM_STATE_DATA_NAK_GET:
411 {
412 // Retry
413 if(XMODEM_PACK_SIZE != gnss_xmodem_pack_send(fd, pack_index - 1, NULL, XMODEM_DATA_SIZE)) {
414 LOGE( "Retry send xmodem package fail.");
415 running = FALSE;
416 result = -1;
417 }
418 xmodem_state = XMODEM_STATE_DATA_SENDING;
419 break;
420 }
421
422 case XMODEM_STATE_EOT_ACK_GET:
423 {
424 LOGD("Send EOT success.");
425 running = FALSE;
426 break;
427 }
428 case XMODEM_STATE_EOT_NAK_GET:
429 {
430 LOGW("Send EOT fail, retry...");
431 char end_cmd = XMODEM_EOT;
432 if(gnss_write(fd, &end_cmd, 1) != 1) {
433 LOGE("Send EOT fail.");
434 //running = FALSE;
435 } else {
436 xmodem_state = XMODEM_STATE_EOT_SENDING;
437 }
438 break;
439 }
440 case XMODEM_STATE_CAN_GET:
441 {
442 LOGD("Recv CAN message.");
443 running = FALSE;
444 break;
445 }
446 default:
447 {
448 LOGE("Unknown X-Modem state : %d", xmodem_state);
449 running = FALSE;
450 result = -1;
451 break;
452 }
453 }
454 }
455 pthread_mutex_unlock(&read_mutex);
456
457 if(file_fd > 0) {
458 close(file_fd);
459 }
460 return result;
461}
462
463int gnss_6228_fw_dl(int fd)
464{
465 // Set bootloader baudrate.
466 gnss_set_baudrate(fd, uart_baud_get(UART_BITRATE_DL_BL));
467
468 gnss_state = GNSS_6228_STATE_WAIT_YC;
469 int wait_yc_num = 0;
470 while(gnss_state == GNSS_6228_STATE_WAIT_YC && wait_yc_num < GNSS_6228_WAIT_YC_COUNT) {
471 write(fd, "M!T", 3);
472 usleep(500);
473 wait_yc_num++;
474 }
475
476 if(wait_yc_num >= GNSS_6228_WAIT_YC_COUNT) {
477 LOGE("Wait YC timeout : %d / %d", wait_yc_num, GNSS_6228_WAIT_YC_COUNT);
478 return -1;
479 }
480
481 // Start download bootloader.
482 LOGD("Start download bootloader : %s", GNSS_6228_BOOTLOADER);
483 gnss_state = GNSS_6228_STATE_BL_DL;
484 if(gnss_xmodem_send(fd, GNSS_6228_BOOTLOADER)) {
485 LOGE("Download bootloader fail.");
486 return -1;
487 }
488 LOGD("Bootloader download success.");
489
490 // Set firmware baudrate.
491 gnss_set_baudrate(fd, uart_baud_get(UART_BITRATE_DL_FW));
492
493 // Start download firmware.
494 LOGD("Start download firmware : %s", GNSS_6228_FIRMWARE);
495 gnss_state = GNSS_6228_STATE_FW_DL;
496 if(gnss_xmodem_send(fd, GNSS_6228_FIRMWARE)) {
497 LOGE("Download firmware fail.");
498 return -1;
499 }
500 LOGD("Firmware download success.");
501
502 // Set NMEA baudrate.
503 gnss_set_baudrate(fd, uart_baud_get(UART_BITRATE_NMEA));
504
505 return 0;
506}
507
508gnss_err_enum gnss_6228_set(int fd, const char *cmd, void *cmd_rsp, int cmd_rsp_len)
509{
510 gnss_state = GNSS_6228_STATE_SETTING;
511 gnss_set_rsp_ptr = cmd_rsp;
512 gnss_set_result = GNSS_ERR_OK;
513 mbtk_timer_set(gnss_set_timer_cb, GNSS_SET_TIMEOUT);
514
515 char cmd_tmp[128] = {0};
516 snprintf(cmd_tmp, sizeof(cmd_tmp), "%s\r\n", cmd);
517 gnss_write(fd, cmd_tmp, strlen(cmd_tmp));
518
519 pthread_mutex_lock(&read_mutex);
520 pthread_cond_wait(&read_cond, &read_mutex);
521 pthread_mutex_unlock(&read_mutex);
522
523 gnss_state = GNSS_6228_STATE_NON;
524 return gnss_set_result;
525}
526