/* * Copyright (c) 2025 Wingcool Technology Co., Ltd * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include #include #include //#include LOG_MODULE_REGISTER(uart2_rec, LOG_LEVEL_INF); #define CONFIG_UART2_REC_DEV_NAME "uart2_rec" #define UART2_REC_DEV_NAME CONFIG_UART_2_NAME #define UART_FIFO_MAX 256 #define REC_DATA_BUFFER_SIZE 256 #define PRODUCT_INFO_SIZE 64 #define WRITE_KEY_SIZE 160 // 定义命令 #define DEVICE_ID_CMD 0xB1 #define PROJECT_ID_CMD 0xB2 #define WRITE_KEY_CMD 0xB3 #define IS_KEY_INSIDE_CMD 0xB4 #define SET_TIME_CMD 0xC1 // 定义帧头和帧尾 #define FRAME_HEADER1 0xAA #define FRAME_HEADER2 0x55 #define FRAME_TAIL1 0x55 #define FRAME_TAIL2 0xAA struct uart2_rec_data { const struct device *uart_gpio_dev; uint8_t rec_data[REC_DATA_BUFFER_SIZE]; //gps_notify_t notify; }; static struct uart2_rec_data uart2_rec_data; uint8_t bySetTimeStep = 0; extern uint8_t bySetHour; extern uint8_t bySetMinute; extern uint8_t bySetWeekday; extern uint16_t wSetYear; extern uint8_t bySetMonth; extern uint8_t bySetDay; extern void uart2_poll_out_ch(int c); // UART2发送一个字节 extern bool aem_read_aem_key_record(aem_key_w_record_t *record); // 读取AEM KEY记录 extern bool aem_defender_factory_write_key(uint8_t * data, uint16_t len); // 写入KEY extern uint16_t aem_factory_get_product_info(uint8_t *data, uint16_t in_len); // 获取产品信息 // 计算累加和校验值 //1 字节,对命令码、数据长度和数据内容的所有字节进行累加求和,取低8位作为校验值,用于检测数据在传输过程中是否出错 uint8_t calculate_checksum(uint8_t cmd, uint8_t *data, uint8_t data_len) { uint8_t checksum = cmd + data_len; for (uint8_t i = 0; i < data_len; i++) { checksum += data[i]; } return checksum; } // 发送一帧数据 void send_frame(uint8_t cmd, uint8_t *data, uint8_t data_len) { uint8_t checksum = calculate_checksum(cmd, data, data_len); // 发送帧头 uart2_poll_out_ch(FRAME_HEADER1); uart2_poll_out_ch(FRAME_HEADER2); // 发送命令码 uart2_poll_out_ch(cmd); // 发送数据长度 uart2_poll_out_ch(data_len); // 发送数据内容 for (uint8_t i = 0; i < data_len; i++) { uart2_poll_out_ch(data[i]); } // 发送累加和校验值 uart2_poll_out_ch(checksum); // 发送帧尾 uart2_poll_out_ch(FRAME_TAIL1); uart2_poll_out_ch(FRAME_TAIL2); } // 检查一帧数据是否正确 bool check_receive_frame(uint8_t *data) { uint8_t calculated_checksum; uint8_t data_len = data[3]; // 帧头 if (data[0] != FRAME_HEADER1) { return false; // 帧头错误 } if (data[1] != FRAME_HEADER2) { return false; // 帧头错误 } // 计算本地累加和校验值 calculated_checksum = calculate_checksum(data[2], data + 4, data_len); if (data[data_len + 4] != calculated_checksum) { return false; // 累加和校验错误 } // 读取帧尾 if (data[data_len + 5] != FRAME_TAIL1 || data[data_len + 6] != FRAME_TAIL2) { return false; // 帧尾错误 } return true; // 接收成功 } static uint8_t byAACnt = 2; static bool bReceiveFrameDone = false; static void uart_fifo_callback(const struct device *dev, void *user_data) { uint8_t rx_buff[UART_FIFO_MAX]; uint8_t tx_buff[UART_FIFO_MAX]; int read_size; static uint8_t cnt; aem_key_w_record_t *key_record = NULL; printk("uart_fifo_callback start\n"); uart_irq_update(dev); if (uart_irq_rx_ready(dev)) { read_size = uart_fifo_read(dev, rx_buff, UART_FIFO_MAX); printk("read_size: %d\n", read_size); if (read_size == UART_FIFO_MAX) printk("uart fifo buffer overflow\n"); for (int i = 0; i < read_size; i++) { switch (rx_buff[i]) { case FRAME_HEADER1: byAACnt++; if (byAACnt > 2) { byAACnt = 1; cnt = 0; bReceiveFrameDone = false; } else if (byAACnt == 2) { bReceiveFrameDone = true; } uart2_rec_data.rec_data[cnt++] = rx_buff[i]; break; default: uart2_rec_data.rec_data[cnt++] = rx_buff[i]; /* protection data cannot exceed boundary */ if (cnt >= REC_DATA_BUFFER_SIZE) cnt--; break; } } if (bReceiveFrameDone && check_receive_frame(uart2_rec_data.rec_data)) { printk("receive frame success\n"); switch (uart2_rec_data.rec_data[2]) { case DEVICE_ID_CMD: aem_factory_get_product_info(tx_buff, PRODUCT_INFO_SIZE); send_frame(PROJECT_ID_CMD, tx_buff, PRODUCT_INFO_SIZE); break; case PROJECT_ID_CMD: tx_buff[0] = 0x0F; tx_buff[1] = 0x6B; tx_buff[2] = 0x3B; tx_buff[3] = 0xD8; send_frame(PROJECT_ID_CMD, tx_buff, 4); break; case WRITE_KEY_CMD: //uart_fifo_fill(dev,rx_buff,read_size); tx_buff[0] = 0; if (aem_defender_factory_write_key(uart2_rec_data.rec_data, WRITE_KEY_SIZE)) { tx_buff[0] = 0xAA; } send_frame(WRITE_KEY_CMD, tx_buff, 1); break; case IS_KEY_INSIDE_CMD: tx_buff[0] = 0; aem_read_aem_key_record(key_record); if (key_record != NULL) { if (key_record->is_pass) tx_buff[0] = 0xAA; } send_frame(IS_KEY_INSIDE_CMD, tx_buff, 1); break; case SET_TIME_CMD: bySetMinute = uart2_rec_data.rec_data[4]; bySetHour = uart2_rec_data.rec_data[5]; bySetDay = uart2_rec_data.rec_data[6]; bySetWeekday = uart2_rec_data.rec_data[7]; bySetMonth = uart2_rec_data.rec_data[8]; wSetYear = uart2_rec_data.rec_data[9]; bySetTimeStep = 1; send_frame(SET_TIME_CMD, tx_buff, 0); break; default: break; } } } } /* static void uart2_rec_enable(const struct device *dev) { struct uart2_rec_data *data = (struct uart2_rec_data *)dev->data; printk("uart2_rec_enable\n"); uart_irq_rx_enable(data->uart_gpio_dev); } static void uart2_rec_disable(const struct device *dev) { struct uart2_rec_data *data = (struct uart2_rec_data *)dev->data; printk("uart2_rec_disable\n"); uart_irq_rx_disable(data->uart_gpio_dev); } static void uart2_rec_register_notify(const struct device *dev, gps_notify_t notify) { printk("uart2_rec_register_notify\n"); struct uart2_rec_data *data = (struct uart2_rec_data *)dev->data; data->notify = notify; } static void uart2_rec_unregister_notify(const struct device *dev, gps_notify_t notify) { struct uart2_rec_data *data = (struct uart2_rec_data *)dev->data; data->notify = NULL; } static const struct gps_dev_driver_api uart2_rec_api = { .enable = uart2_rec_enable, .disable = uart2_rec_disable, .inquiry = NULL, .register_notify = uart2_rec_register_notify, .unregister_notify = uart2_rec_unregister_notify, }; */ static int uart2_rec_init(const struct device *dev) { struct uart2_rec_data *data = (struct uart2_rec_data *)dev->data; printk("uart2_rec_init\n"); data->uart_gpio_dev = device_get_binding(UART2_REC_DEV_NAME); if (data->uart_gpio_dev == NULL) { printk("Couldn't find uart2\n"); return -ENODEV; } uart_irq_callback_set(data->uart_gpio_dev, uart_fifo_callback); uart_irq_rx_enable(data->uart_gpio_dev); return 0; } #if IS_ENABLED(CONFIG_UART_ACTS) DEVICE_DEFINE(uart2_rec, CONFIG_UART2_REC_DEV_NAME, &uart2_rec_init, NULL, &uart2_rec_data, NULL, POST_KERNEL, 60, NULL); #endif