A59 -V1.1版本提交

This commit is contained in:
2024-10-10 17:41:53 +08:00
parent 16b6433a98
commit 5f032cd320
903 changed files with 171909 additions and 22876 deletions

21
.vscode/settings.json vendored
View File

@ -2,6 +2,23 @@
"files.associations": { "files.associations": {
"*.inc": "c", "*.inc": "c",
"navigator.h": "c", "navigator.h": "c",
"main_loop_simple.h": "c" "main_loop_simple.h": "c",
} "pwm.h": "c",
"sfud.h": "c",
"can_protocol.h": "c",
"awtk.h": "c",
"types_def.h": "c",
"gpio_protocol.h": "c",
"data_port.h": "c",
"serial.h": "c",
"ff_stdio.h": "c",
"ff_sfdisk.h": "c",
"universal.h": "c",
"data_communication_send.h": "c",
"object_date_time.h": "c",
"semphr.h": "c",
"user_data.h": "c",
"qr.h": "c"
},
"cmake.sourceDirectory": "G:/MXC_A58/lib/awtk/awtk/3rd/mbedtls/include"
} }

View File

@ -263,8 +263,8 @@
#ifdef WIFI_SUPPORT #ifdef WIFI_SUPPORT
#define CARLINK_EY 0 #define CARLINK_EY 0
#define CARLINK_EC 0 #define CARLINK_EC 1
#define CARLINK_CP 1 #define CARLINK_CP 0
#define CARLINK_AA 0 #define CARLINK_AA 0
#define WIFI_RESET_IO 12 #define WIFI_RESET_IO 12
@ -287,7 +287,7 @@
#error "Do not choose two car links" #error "Do not choose two car links"
#elif (CARLINK_EC && CARLINK_AA) #elif (CARLINK_EC && CARLINK_AA)
#error "Do not choose two car links" #error "Do not choose two car links"
#elif (CARLINK_CP && CARLINK_AA) // #elif (CARLINK_CP && CARLINK_AA)
#error "Do not choose two car links" #error "Do not choose two car links"
#endif #endif
@ -474,7 +474,7 @@
/*********************************************/ /*********************************************/
/********** update address configuration **********/ /********** update address configuration **********/
//#define OTA_UPDATE_SUPPORT #define OTA_UPDATE_SUPPORT
#ifdef OTA_UPDATE_SUPPORT #ifdef OTA_UPDATE_SUPPORT
//#define WIFI_UPDATE_SUPPORT //#define WIFI_UPDATE_SUPPORT
#if defined(WIFI_UPDATE_SUPPORT) && !defined(USB_SUPPORT) #if defined(WIFI_UPDATE_SUPPORT) && !defined(USB_SUPPORT)

View File

@ -19,7 +19,9 @@ typedef struct {
unsigned int image_offset; unsigned int image_offset;
unsigned int loader_offset; unsigned int loader_offset;
unsigned int loader_size; unsigned int loader_size;
unsigned int reserved[12]; unsigned int reserved[10];
unsigned int upgrade_flag;
unsigned int upgrade_appsize;
unsigned int checksum; unsigned int checksum;
} SysInfo; } SysInfo;

View File

@ -0,0 +1,656 @@
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "board.h"
#include "chip.h"
#include "sfud.h"
#include "updatefile.h"
#include "mfcapi.h"
#include "dwl.h"
#include "animation.h"
#if DEVICE_TYPE_SELECT == EMMC_FLASH
#include "mmcsd_core.h"
#endif
static TaskHandle_t animation_task = NULL;
static SemaphoreHandle_t animation_mutex;
#if ANIMATION_POLICY == ANIMATION_USE_SMALL_MEM
static BANIHEADER ani_header;
static BANIHEADER *aniheader = &ani_header;
#else
static BANIHEADER *aniheader;
#endif
static unsigned int anioffset;
static unsigned int anisize;
static int ani_playing = 0;
static int ani_replay = 0;
static int ani_stop = 0;
static int ani_frames = 0;
static int ani_display_index = 0;
static int ani_take_vdisbuf = 0;
static unsigned int ani_frame_addr;
static uint32_t first_show_done = 0;
#if 0
#include "ff_stdio.h"
static int get_h264_single_file_from_sd(void *buf, int *len)
{
#define READ_SIZE (LCD_WIDTH*LCD_HEIGHT*2)
char path_name[64] = "/sd/000.h264";
static int count = 0;
FF_FILE *fp;
int ret = -1;
sprintf(path_name, "/sd/%.3d.h264", count++);
*len = 0;
fp = ff_fopen(path_name, "rb");
if (fp) {
ret = ff_fread(buf, 1, READ_SIZE, fp);
if (ret <= 0) {
printf("read sdmmc file:%s failed, maybe read done\n", path_name);
return -1;
}
*len = ret;
} else {
printf("### open %s fail.\n", path_name);
count = 0;
return -1;
}
if(fp)
ff_fclose(fp);
//printf("###read %s len:%d.\n", path_name, *len);
return 0;
}
static void h264_decode_test_thread(void *param)
{
#define H264DEC_SEMIPLANAR_YUV420 0x020001
#define H264DEC_INBUF_SIZE (LCD_WIDTH*LCD_HEIGHT*2)
#define H264DEC_DISP_COUNTS 2
DWLLinearMem_t inBuf;
OutFrameBuffer outBuf = {0};
uint32_t h264SrcSize = 0;
MFCHandle *handle = NULL;
uint32_t display_addr[H264DEC_DISP_COUNTS] = {0};
uint32_t display_addr_index = 0;
uint32_t first_show_done = 0;
int ret;
int i;
void *h264SrcBuf = pvPortMalloc(H264DEC_INBUF_SIZE);
if(!h264SrcBuf) {
printf("%s, h264SrcBuf pvPortMalloc failed.\n", __func__);
return ;
}
for(i=0; i<H264DEC_DISP_COUNTS; i++) {
display_addr[i] = (uint32_t)pvPortMalloc(H264DEC_INBUF_SIZE);
if(!display_addr[i] ) {
printf("%s, display_addr[%d] pvPortMalloc failed.\n", __func__, i);
return ;
}
}
mmcsd_wait_cd_changed(portMAX_DELAY);
handle = mfc_init(RAW_STRM_TYPE_H264);
if(!handle) {
printf("%s, mfc_init failed.\n", __func__);
return ;
}
while(1) {
//memset(&outBuf, 0, sizeof(OutFrameBuffer));
//memset(h264SrcBuf, 0, H264DEC_INBUF_SIZE);
mdelay(30);
#if 1 //get h264 info form sdcard.
ret = get_h264_single_file_from_sd(h264SrcBuf, &h264SrcSize);
if(ret != 0) {
printf("%s, get_h264_single_file_from_sd failed.\n", __func__);
continue;
}
inBuf.busAddress = (u32)h264SrcBuf;
inBuf.virtualAddress = (u32 *)inBuf.busAddress;
inBuf.size = h264SrcSize;
CP15_clean_dcache_for_dma(inBuf.busAddress, inBuf.busAddress + inBuf.size);
#else
//1. copy your h264 data to h264SrcBuf;
//2. set your h264 data size to h264SrcSize;
inBuf.busAddress = (u32)h264SrcBuf;
inBuf.virtualAddress = (u32 *)inBuf.busAddress;
inBuf.size = h264SrcSize;
#endif
ret = mfc_decode(handle, &inBuf, &outBuf);
if (ret < 0) {
printf("animation decode fail.\n");
} else {
uint32_t align_width, align_height;
uint32_t yaddr, uaddr, vaddr;
for(i=0; i<outBuf.num; i++) {
align_width = outBuf.frameWidth;
align_height = outBuf.frameHeight;
if(1/*outBuf.outputFormat == H264DEC_SEMIPLANAR_YUV420*/ && align_width && align_height)
{
memcpy((void *)display_addr[display_addr_index], outBuf.buffer[i].pyVirAddress, align_width * align_height * 3 / 2);
// ret = dma_m2mcpy(display_addr[display_addr_index], (uint32_t)outBuf.buffer[i].yBusAddress, align_width * align_height * 3 / 2);
// if(ret) {
// printf("%s() dma_m2m_memcpy failed.\n", __func__);
// continue;
// }
yaddr = display_addr[display_addr_index];
uaddr = yaddr + align_width * align_height;
vaddr = yaddr + align_width * align_height * 5/4;
display_addr_index++;
if(display_addr_index >= H264DEC_DISP_COUNTS) {
display_addr_index = 0;
}
if(!first_show_done) {
ark_lcd_set_osd_size(LCD_VIDEO_LAYER, /*outBuf.codedWidth, outBuf.codedHeight*/LCD_WIDTH, LCD_HEIGHT);
ark_lcd_set_osd_format(LCD_VIDEO_LAYER, LCD_OSD_FORAMT_YUV420);
ark_lcd_set_osd_yuv420_mode(LCD_VIDEO_LAYER, LCD_OSD_Y_UV420);
ark_lcd_osd_enable(LCD_VIDEO_LAYER, 1);
ark_lcd_osd_enable(LCD_UI_LAYER, 0);
first_show_done = 1;
}
ark_lcd_set_osd_yaddr(LCD_VIDEO_LAYER, yaddr);
ark_lcd_set_osd_uaddr(LCD_VIDEO_LAYER, uaddr);
ark_lcd_set_osd_vaddr(LCD_VIDEO_LAYER, vaddr);
ark_lcd_set_osd_sync(LCD_VIDEO_LAYER);
ark_lcd_set_osd_sync(LCD_UI_LAYER);
ark_lcd_wait_for_vsync();
} else {
continue;
}
}
}
}
if(handle)
mfc_uninit(handle);
if(h264SrcBuf)
vPortFree(h264SrcBuf);
for(i=0; i<H264DEC_DISP_COUNTS; i++) {
if(!display_addr[i]) {
vPortFree((void *)display_addr[i]);
}
}
}
static int save_nv12_file_to_sd(void *buf, int len)
{
char path_name[64] = "/sd/000.bin";
static int count = 0;
FF_FILE *fp;
int ret = -1;
sprintf(path_name, "/sd/%.3d.bin", count++);
fp = ff_fopen(path_name, "w+");
if (fp) {
ret = ff_fwrite(buf, 1, len, fp);
if (ret != len) {
printf("read sdmmc file:%s failed.\n", path_name);
ff_fclose(fp);
return -1;
}
} else {
printf("### open %s fail.\n", path_name);
return -1;
}
ff_fclose(fp);
return 0;
}
static int get_file_from_sd(void *buf, int *len)
{
#define READ_SIZE (LCD_WIDTH*LCD_HEIGHT*2)
#if LCD_BPP == 32
char path_name[64] = "/sd/480x1280_rgb888.rgb";
#else
char path_name[64] = "/sd/480x1280_rgb565.rgb";
#endif
FF_FILE *fp;
int ret = -1;
*len = 0;
fp = ff_fopen(path_name, "rb");
if (fp) {
ret = ff_fread(buf, 1, READ_SIZE, fp);
if (ret <= 0) {
printf("read sdmmc file:%s failed.\n", path_name);
return -1;
}
*len = ret;
} else {
printf("### open %s fail.\n", path_name);
return -1;
}
if(fp)
ff_fclose(fp);
return 0;
}
void mipi_disp_test(void)
{
u32 len;
int ret;
u32 *disp_addr = (u32 *)pvPortMalloc(LCD_WIDTH*LCD_HEIGHT*2);
if(!disp_addr) {
printf("disp_addr pvPortMalloc failed.\n");
return ;
}
mmcsd_wait_cd_changed(portMAX_DELAY);
get_file_from_sd(disp_addr, &len);
if(!len) {
printf("get_file_from_sd failed.\n");
return ;
}
CP15_clean_dcache_for_dma((uint32_t)disp_addr, (uint32_t)disp_addr + LCD_WIDTH*LCD_HEIGHT*2);
u32 layer = LCD_OSD0;
u32 width = VIDEO_DISPLAY_WIDTH;
u32 height = VIDEO_DISPLAY_HEIGHT;
u32 format;
#if LCD_BPP == 32
format = LCD_OSD_FORAMT_ARGB888;
#else
format = LCD_OSD_FORAMT_RGB565;
#endif
while(1) {
ark_lcd_osd_enable(LCD_OSD0, 0);
ark_lcd_osd_enable(LCD_OSD1, 0);
ark_lcd_set_osd_sync(LCD_OSD0);
ark_lcd_set_osd_sync(LCD_OSD1);
ark_lcd_set_osd_size(layer, width, height);
ark_lcd_set_osd_format(layer, format);
ark_lcd_osd_enable(layer, 1);
ark_lcd_set_osd_yaddr(layer, (u32)disp_addr);
ark_lcd_set_osd_sync(layer);
ark_lcd_wait_for_vsync();
}
}
#endif
//#define PLAY_SHUTDOWN_ANIMATION
#ifdef PLAY_SHUTDOWN_ANIMATION
static int shutdown_anim = 0;
#endif
uint16_t animo_flag = 0;
static void animation_thread(void *param)
{
MFCHandle *mfc_handle = NULL;
#if DEVICE_TYPE_SELECT != EMMC_FLASH
sfud_flash *sflash;
#endif
uint32_t size;
uint32_t stick, etick, delaytick;
uint32_t display_addr;
uint32_t *tmp_addr = NULL;
uint8_t power=1;
anioffset = GetUpFileOffset(MKTAG('B', 'A', 'N', 'I'));
anisize = GetUpFileSize(MKTAG('B', 'A', 'N', 'I'));
#ifdef PLAY_SHUTDOWN_ANIMATION
if(shutdown_anim){
anioffset = GetUpFileOffset(MKTAG('S', 'A', 'N', 'I'));
anisize = GetUpFileSize(MKTAG('S', 'A', 'N', 'I'));
}
#endif
if (anisize > 0) {
void *anibuf = pvPortMalloc(anisize);
if (anibuf) {
#if DEVICE_TYPE_SELECT != EMMC_FLASH
sflash = sfud_get_device(0);
sfud_read(sflash, anioffset, anisize, anibuf);
#else
emmc_read(anioffset, anisize, anibuf);
#endif
aniheader = (BANIHEADER*)anibuf;
if (aniheader->magic != MKTAG('B', 'A', 'N', 'I')
#ifdef PLAY_SHUTDOWN_ANIMATION
&& aniheader->magic != MKTAG('S', 'A', 'N', 'I')
#endif
) {
printf("Read animation file error!\n");
vPortFree(anibuf);
vTaskDelete(NULL);
return;
}
CP15_clean_dcache_for_dma((uint32_t)anibuf, (uint32_t)anibuf + anisize);
} else {
printf("Error! No enough memory for animation file.\n");
vTaskDelete(NULL);
return;
}
} else {
printf("Warning! Not found animation in update file.\n");
vTaskDelete(NULL);
return;
}
ani_frame_addr = (uint32_t)aniheader + sizeof(BANIHEADER);
for (;;) {
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
xSemaphoreTake(animation_mutex, portMAX_DELAY);
if (ani_replay) {
ani_frame_addr = (uint32_t)aniheader + sizeof(BANIHEADER);
ani_frames = 0;
ani_replay = 0;
}
stick = xTaskGetTickCount();
ani_playing = 1;
size = *(uint32_t*)ani_frame_addr;
if (xVideoDisplayBufTake(pdMS_TO_TICKS(10)) == pdTRUE) {
if(!mfc_handle)
mfc_handle = mfc_init(RAW_STRM_TYPE_JPEG);
if(!mfc_handle) {
printf("%s, mfc_init failed.\n", __func__);
continue ;
}
display_addr = ulVideoDisplayBufGet();
JpegHeaderInfo jpegInfo = {0};
jpegInfo.handle = mfc_handle;
jpegInfo.jpg_addr = ani_frame_addr + 8;
jpegInfo.jpg_size = size;
jpegInfo.dec_addry = display_addr;
#if LCD_ROTATE_ANGLE != LCD_ROTATE_ANGLE_0
if(!tmp_addr) {
uint32_t tmp_size = ulVideoDisplayBufGetSize();
tmp_addr = (u32 *)pvPortMalloc(tmp_size);
if(!tmp_addr) {
printf("tmp_addr pvPortMalloc failed.\n");
}
}
if(tmp_addr) {
jpegInfo.dec_addry = VIRT_TO_PHY((u32)tmp_addr);
}
#endif
if (mfc_jpegdec(&jpegInfo) != 0) {
printf("animation decode %d frame fail.\n", ani_frames);
vVideoDisplayBufFree(display_addr);
} else {
if(!first_show_done) {
#if LCD_ROTATE_ANGLE == LCD_ROTATE_ANGLE_0
int align_width = (LCD_WIDTH + 0xF) & (~0xF);
int align_height = (LCD_HEIGHT + 0xF) & (~0xF);
if((align_width == jpegInfo.dec_width) && (align_height == jpegInfo.dec_height)) {
ark_lcd_set_osd_size(LCD_VIDEO_LAYER, LCD_WIDTH, LCD_HEIGHT);
} else {
ark_lcd_set_osd_size(LCD_VIDEO_LAYER, jpegInfo.dec_width, jpegInfo.dec_height);
}
ark_lcd_set_osd_format(LCD_VIDEO_LAYER, LCD_OSD_FORAMT_YUV420);
ark_lcd_set_osd_yuv420_mode(LCD_VIDEO_LAYER, LCD_OSD_Y_UV420);
#else
ark_lcd_set_osd_size(LCD_VIDEO_LAYER, LCD_WIDTH, LCD_HEIGHT);
ark_lcd_set_osd_format(LCD_VIDEO_LAYER, LCD_OSD_FORAMT_RGB565);
#endif
ark_lcd_osd_enable(LCD_VIDEO_LAYER, 1);
ark_lcd_osd_enable(LCD_UI_LAYER, 0);
first_show_done = 1;
}
animo_flag++;
if(animo_flag == 3){
BrightnessPowerOnSetting();
pwm_enable(2);
pwm_enable(3);
}
// printf("animo_flag------------ %d .\r\n",animo_flag);
#if LCD_ROTATE_ANGLE == LCD_ROTATE_ANGLE_0
ark_lcd_set_osd_yaddr(LCD_VIDEO_LAYER, jpegInfo.dec_addry);
ark_lcd_set_osd_uaddr(LCD_VIDEO_LAYER, jpegInfo.dec_addru);
ark_lcd_set_osd_vaddr(LCD_VIDEO_LAYER, jpegInfo.dec_addrv);
#else
pxp_scaler_rotate(jpegInfo.dec_addry, jpegInfo.dec_addru, jpegInfo.dec_addrv,
PXP_SRC_FMT_YUV2P420, jpegInfo.dec_width, jpegInfo.dec_height,
display_addr, 0, PXP_OUT_FMT_RGB565, LCD_WIDTH, LCD_HEIGHT, LCD_ROTATE_ANGLE);
ark_lcd_set_osd_yaddr(LCD_VIDEO_LAYER, display_addr);
#endif
ark_lcd_set_osd_sync(LCD_VIDEO_LAYER);
ark_lcd_set_osd_sync(LCD_UI_LAYER);
ark_lcd_wait_for_vsync();
vVideoDisplayBufRender(display_addr);
ani_take_vdisbuf = 1;
}
}
ani_frame_addr += size;
ani_display_index = !ani_display_index;
if (ani_stop || (++ani_frames >= aniheader->aniCount + aniheader->hasBootlogo ? 1 : 0)
#if ANIMATION_POLICY == ANIMATION_USE_SMALL_MEM
|| (ani_frame_addr > anioffset + anisize))
#else
|| (ani_frame_addr > (uint32_t)aniheader + anisize))
#endif
{
printf("animation end.\n");
extern void Set_sys_power_on_self_test(uint8_t value);
Set_sys_power_on_self_test(50);
ani_stop = 0;
if (aniheader->aniCount > 0)
vTaskDelay(aniheader->aniDelayHideTime);
else if (aniheader->hasBootlogo)
vTaskDelay(aniheader->bootlogoDisplayTime);
#ifdef PLAY_SHUTDOWN_ANIMATION
if(shutdown_anim)
ani_take_vdisbuf = 0;
#endif
if (ani_take_vdisbuf) {
ark_lcd_osd_enable(LCD_VIDEO_LAYER, 0);
ark_lcd_osd_enable(LCD_UI_LAYER, 1);
ark_lcd_set_osd_sync(LCD_UI_LAYER);
ark_lcd_set_osd_sync(LCD_VIDEO_LAYER);
}
vVideoDisplayBufFree(display_addr);
vVideoDisplayBufGive();
ani_playing = 0;
if (ani_replay)
xTaskNotifyGive(animation_task);
xSemaphoreGive(animation_mutex);
if(mfc_handle) {
mfc_uninit(mfc_handle);
mfc_handle = NULL;
}
if(tmp_addr) {
vPortFree(tmp_addr);
tmp_addr = NULL;
}
#ifdef PLAY_SHUTDOWN_ANIMATION
break;
#endif
continue;
}
vVideoDisplayBufGive();
xSemaphoreGive(animation_mutex);
etick = xTaskGetTickCount();
if (aniheader->hasBootlogo && ani_frames == 1)
delaytick = pdMS_TO_TICKS(aniheader->bootlogoDisplayTime) > (etick - stick) ?
pdMS_TO_TICKS(aniheader->bootlogoDisplayTime) - (etick - stick) : 0;
else
delaytick = pdMS_TO_TICKS(1000 / aniheader->aniFps) > (etick - stick) ?
pdMS_TO_TICKS(1000 / aniheader->aniFps) - (etick - stick) : 0;
if (delaytick)
vTaskDelay(delaytick);
xTaskNotifyGive(animation_task);
}
#ifdef PLAY_SHUTDOWN_ANIMATION
if(aniheader) {
vPortFree(aniheader);
aniheader = NULL;
}
animation_task = NULL;
vTaskDelete(NULL);
#endif
}
int animation_init(void)
{
if (animation_task) {
printf("animation is already inited.\n");
return 0;
}
animation_mutex = xSemaphoreCreateMutex();
/* Create a task to play animation */
//if (xTaskCreate(h264_decode_test_thread, "h264_decode_test", configMINIMAL_STACK_SIZE*2, NULL,
if (xTaskCreate(animation_thread, "animation", configMINIMAL_STACK_SIZE, NULL,
configMAX_PRIORITIES - 1, &animation_task) != pdPASS) {
printf("create animation task fail.\n");
animation_task = NULL;
return -1;
}
return 0;
}
void animation_start(void)
{
xSemaphoreTake(animation_mutex, portMAX_DELAY);
first_show_done=0;
if (ani_playing) {
printf("animation is already playing.\n");
xSemaphoreGive(animation_mutex);
return;
}
#if ANIMATION_POLICY == ANIMATION_USE_SMALL_MEM
ani_frame_addr = anioffset + sizeof(BANIHEADER);
#else
ani_frame_addr = (uint32_t)aniheader + sizeof(BANIHEADER);
#endif
ani_frames = 0;
if (animation_task)
xTaskNotifyGive(animation_task);
xSemaphoreGive(animation_mutex);
}
/* replay animation even if animation is already playing */
void animation_restart(void)
{
xSemaphoreTake(animation_mutex, portMAX_DELAY);
first_show_done=0;
ani_stop=0;
if (ani_playing) {
ani_replay = 1;
xSemaphoreGive(animation_mutex);
return;
}
#if ANIMATION_POLICY == ANIMATION_USE_SMALL_MEM
ani_frame_addr = anioffset + sizeof(BANIHEADER);
#else
ani_frame_addr = (uint32_t)aniheader + sizeof(BANIHEADER);
#endif
ani_frames = 0;
if (animation_task)
xTaskNotifyGive(animation_task);
xSemaphoreGive(animation_mutex);
}
#ifdef PLAY_SHUTDOWN_ANIMATION
int play_shutdown_animation(void)
{
#define TIMEOUT_SEC 10
uint32_t wait_tick;
if (animation_task) {
printf("%s, animation is already inited.\n", __func__);
return -1;
}
xSemaphoreTake(animation_mutex, portMAX_DELAY);
shutdown_anim = 1;
ani_frames = 0;
first_show_done = 0;
ani_stop = 0;
ani_take_vdisbuf = 0;
xSemaphoreGive(animation_mutex);
if (xTaskCreate(animation_thread, "animation", configMINIMAL_STACK_SIZE, NULL,
configMAX_PRIORITIES - 2, &animation_task) != pdPASS) {
printf("%s, create animation task fail.\n", __func__);
animation_task = NULL;
return -1;
}
xSemaphoreTake(animation_mutex, portMAX_DELAY);
if (ani_playing) {
printf("%s, animation is already playing.\n", __func__);
xSemaphoreGive(animation_mutex);
return -1;
}
if (animation_task)
xTaskNotifyGive(animation_task);
xSemaphoreGive(animation_mutex);
//wait for animation_thread exit.
wait_tick = xTaskGetTickCount();
while(xTaskGetTickCount() - wait_tick < configTICK_RATE_HZ * TIMEOUT_SEC) {
if(ani_stop)
break;
vTaskDelay(pdMS_TO_TICKS(100));
}
return 0;
}
#endif
void animation_stop(void)
{
xSemaphoreTake(animation_mutex, portMAX_DELAY);
ani_stop = 1;
xSemaphoreGive(animation_mutex);
}
int get_animation_status(void)
{
return ani_playing;
}

View File

@ -418,8 +418,8 @@ static void animation_thread(void *param)
#endif #endif
if(power){ if(power){
BrightnessPowerOnSetting(); BrightnessPowerOnSetting();
pwm_enable(2);//?<3F><>?<3F><>?-??<3F><>?<3F><>?<3F>̨<EFBFBD><CCA8><EFBFBD>???<3F><><EFBFBD><EFBFBD>?a??<3F><>31a pwm_enable(2);
pwm_enable(3);//?<3F><>?<3F><>?-??<3F><>?<3F><>?<3F>̨<EFBFBD><CCA8><EFBFBD>???<3F><><EFBFBD><EFBFBD>?a??<3F><>?1a pwm_enable(3);
} }
ark_lcd_osd_enable(LCD_VIDEO_LAYER, 1); ark_lcd_osd_enable(LCD_VIDEO_LAYER, 1);
ark_lcd_osd_enable(LCD_UI_LAYER, 0); ark_lcd_osd_enable(LCD_UI_LAYER, 0);
@ -536,7 +536,7 @@ int animation_init(void)
/* Create a task to play animation */ /* Create a task to play animation */
//if (xTaskCreate(h264_decode_test_thread, "h264_decode_test", configMINIMAL_STACK_SIZE*2, NULL, //if (xTaskCreate(h264_decode_test_thread, "h264_decode_test", configMINIMAL_STACK_SIZE*2, NULL,
if (xTaskCreate(animation_thread, "animation", configMINIMAL_STACK_SIZE, NULL, if (xTaskCreate(animation_thread, "animation", configMINIMAL_STACK_SIZE, NULL,
configMAX_PRIORITIES - 2, &animation_task) != pdPASS) { configMAX_PRIORITIES - 1, &animation_task) != pdPASS) {
printf("create animation task fail.\n"); printf("create animation task fail.\n");
animation_task = NULL; animation_task = NULL;
return -1; return -1;

View File

@ -31,6 +31,7 @@ typedef struct {
int width; int width;
int height; int height;
int format; int format;
int stride;
unsigned int yaddr; unsigned int yaddr;
unsigned int uaddr; unsigned int uaddr;
unsigned int vaddr; unsigned int vaddr;

View File

@ -31,6 +31,9 @@ typedef struct sfuddata_t{
char r_mac_address[9]; //物理地址 char r_mac_address[9]; //物理地址
uint32_t maintenance_mileage; //保养里程数max uint32_t maintenance_mileage; //保养里程数max
uint32_t mileage_flag; //设置时当前的总里程数 uint32_t mileage_flag; //设置时当前的总里程数
uint8_t display_mileage; // 里程显示类型
uint8_t tcs_on_off; //tcs类型
uint8_t mile_state; //保养里程状态
}SfudData_t; }SfudData_t;
typedef struct sfudmiledata_t{ typedef struct sfudmiledata_t{

View File

@ -5,7 +5,7 @@
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "chip.h" #include "chip.h"
//#define CAN_USE_TX_DEMO #define CAN_USE_TX_DEMO
#define CAN_RX_BUF_NUM 32 #define CAN_RX_BUF_NUM 32
#define CAN_TX_BUF_NUM 32 #define CAN_TX_BUF_NUM 32
@ -690,40 +690,66 @@ static void can_txdemo_thread(void *param)
{ {
CanPort_t *cap = param; CanPort_t *cap = param;
// CanMsg txmsg = {0};
// txmsg.IDE = CAN_Id_Standard;
// txmsg.DLC = 4;
// txmsg.Data[0] = 0x11;
// txmsg.Data[1] = 0x22;
// txmsg.Data[2] = 0x33;
// txmsg.Data[3] = 0x44;
CanMsg txmsg = {0}; CanMsg txmsg = {0};
txmsg.StdId = 0x200;
txmsg.IDE = CAN_Id_Standard; txmsg.IDE = CAN_Id_Standard;
txmsg.DLC = 4; txmsg.DLC = 8;
txmsg.Data[0] = 0x11; txmsg.Data[0] = Get_sys_tcs_on_off()?0x8:0x00;
txmsg.Data[1] = 0x22;
txmsg.Data[2] = 0x33;
txmsg.Data[3] = 0x44;
//uint32_t last_time = get_timer(0);
for (;;) { for (;;) {
txmsg.Data[0] = Get_sys_tcs_on_off()?0x8:0x00;
iCanWrite(cap, &txmsg, 1, 0); iCanWrite(cap, &txmsg, 1, 0);
vTaskDelay(pdMS_TO_TICKS(100));
//printf("%d us.\n", get_timer(last_time));
//last_time = get_timer(0);
vTaskDelay(pdMS_TO_TICKS(1000));
} }
} }
#endif #endif
uint8_t can101_flag = 0;
static void can_rxdemo_thread(void *param) static void can_rxdemo_thread(void *param)
{ {
CanPort_t *cap = param; CanPort_t *cap = param;
int tlv_data_value[8] = {0};
for (;;) { for (;;) {
CanMsg rxmsg[8] = {0}; CanMsg rxmsg[8] = {0};
int revlen; int revlen;
int i, j; int i, j;
if ((revlen = iCanRead(cap, rxmsg, 8, pdMS_TO_TICKS(200))) > 0) { if ((revlen = iCanRead(cap, rxmsg, 8, pdMS_TO_TICKS(10))) > 0 && (Get_sys_power_on_self_test() == 100)) {
printf("can receive %d messages:\n", revlen);
for (i = 0; i < revlen; i++) { for (i = 0; i < revlen; i++) {
for (j = 0; j < rxmsg[i].DLC; j++) for (j = 0; j < rxmsg[i].DLC; j++){
printf("%.2x, ", rxmsg[i].Data[j]); tlv_data_value[j] = rxmsg[i].Data[j];
printf("\n"); }
// printf("can>> Id = %03x",rxmsg[i].StdId);
switch(rxmsg[i].StdId){
case 0x37B:
tcsworking_event_handing(tlv_data_value);//TCS
break;
case 0x12B:
tcsswitch_event_handing(tlv_data_value);//tcs开关
break;
case 0x401:
break;
case 0x402://ECU故障码
break;
case 0xA5://ABS故障码
abs_dtc_event_handing(tlv_data_value);
break;
case 0xA3://ABS数据
break;
case 0x101://发送机数据
if(can101_flag != 10)
can101_flag = 10;
speed_event_handing(tlv_data_value);
break;
default:break;
}
} }
} }
} }
@ -739,13 +765,13 @@ int can_demo(void)
return -1; return -1;
} }
vCanInit(cap, CAN250kBaud, CAN_MODE_NORMAL); vCanInit(cap, CAN500kBaud, CAN_MODE_NORMAL);
#if 1 #if 1
CAN_FilterInitTypeDef canfilter = {0}; CAN_FilterInitTypeDef canfilter = {0};
/* 只接收ID的第0位为1的帧 */ /* 只接收ID的第0位为1的帧 */
canfilter.MODE = 1; /* 单滤波器模式 */ canfilter.MODE = 1; /* 单滤波器模式 */
canfilter.ID = 0x1; canfilter.ID = 0x37B;
canfilter.IDMASK = 0x7fe; canfilter.IDMASK = 0x7ff;
vCanSetFilter(cap, &canfilter); vCanSetFilter(cap, &canfilter);
#endif #endif

View File

@ -160,6 +160,7 @@ struct dw_spi {
void (*transfer_handler)(struct dw_spi *dws); void (*transfer_handler)(struct dw_spi *dws);
u32 current_freq; /* frequency in hz */ u32 current_freq; /* frequency in hz */
u32 current_qspi_freq; u32 current_qspi_freq;
int xfer_ret;
/* DMA info */ /* DMA info */
int dma_inited; int dma_inited;
@ -404,6 +405,7 @@ static void dma_transfer(struct dw_spi *dws)
dw_readl(dws, DW_SPI_ICR); dw_readl(dws, DW_SPI_ICR);
int_error_stop(dws, "dma_transfer: fifo overrun/underrun"); int_error_stop(dws, "dma_transfer: fifo overrun/underrun");
dws->xfer_ret = 1;
xQueueSendFromISR(dws->xfer_done, NULL, 0); xQueueSendFromISR(dws->xfer_done, NULL, 0);
return; return;
@ -626,6 +628,7 @@ xfer_continue:
if (ndf > 0xffff) ndf = 0xffff; if (ndf > 0xffff) ndf = 0xffff;
dws->dma_mapped = 1; dws->dma_mapped = 1;
dws->xfer_ret = 0;
dws->rx = (u8*)message->recv_buf + xfer_len; dws->rx = (u8*)message->recv_buf + xfer_len;
dws->len = (ndf + 1) * dws->n_bytes; dws->len = (ndf + 1) * dws->n_bytes;
dws->rx_end = (u8*)dws->rx + dws->len; dws->rx_end = (u8*)dws->rx + dws->len;
@ -721,11 +724,30 @@ xfer_continue:
goto end; goto end;
} }
if (dws->dma_mapped && dws->rx_dummy_buffer) { if (dws->xfer_ret) {
dws->xfer_ret = 0;
ret = -1;
if (dws->dma_mapped)
dma_stop_channel(dws->dma_rx);
goto end;
}
if (dws->dma_mapped) {
/* Invalidate cache after dma read, rx and len must align to cacheline(32bytes) */
portDISABLE_INTERRUPTS();
if (dws->rx_dummy_buffer)
CP15_invalidate_dcache_for_dma((uint32_t)dws->rx_dummy_buffer,
(uint32_t)dws->rx_dummy_buffer + dws->len);
else
CP15_invalidate_dcache_for_dma((uint32_t)dws->rx, (uint32_t)dws->rx + dws->len);
portENABLE_INTERRUPTS();
if (dws->rx_dummy_buffer) {
memcpy(dws->rx, dws->rx_dummy_buffer, dws->len); memcpy(dws->rx, dws->rx_dummy_buffer, dws->len);
vPortFree(dws->rx_dummy_buffer); vPortFree(dws->rx_dummy_buffer);
dws->rx_dummy_buffer = NULL; dws->rx_dummy_buffer = NULL;
} }
}
dma_stop_channel(dws->dma_rx); dma_stop_channel(dws->dma_rx);
@ -764,8 +786,7 @@ int dw_spi_setup(struct spi_slave *slave, struct spi_configuration *configuratio
chip->qspi_clk_div = (DIV_ROUND_UP(dws->max_freq, configuration->qspi_max_hz) + 1) & 0xfffe; chip->qspi_clk_div = (DIV_ROUND_UP(dws->max_freq, configuration->qspi_max_hz) + 1) & 0xfffe;
dws->current_freq = dws->max_freq / chip->clk_div; dws->current_freq = dws->max_freq / chip->clk_div;
dws->current_qspi_freq = dws->max_freq / chip->qspi_clk_div; dws->current_qspi_freq = dws->max_freq / chip->qspi_clk_div;
printf("spi max_freq %u, current freq %u, qspi_freq %u.\n", dws->max_freq, printf("spi max_freq %u, current freq %u, qspi_freq %u.\n", dws->max_freq, dws->current_freq, dws->current_qspi_freq);
dws->current_freq, dws->current_qspi_freq);
gpio_direction_output(dws->cs_gpio, gpio_direction_output(dws->cs_gpio,
!(dws->slave.mode & SPI_CS_HIGH)); !(dws->slave.mode & SPI_CS_HIGH));
@ -909,7 +930,7 @@ static int dw_spi_dma_transfer(struct dw_spi *dws, struct spi_message *message)
cfg.direction = DMA_DEV_TO_MEM; cfg.direction = DMA_DEV_TO_MEM;
cfg.src_addr = REGS_SPI0_BASE + DW_SPI_DR; cfg.src_addr = REGS_SPI0_BASE + DW_SPI_DR;
//if (((u32)dws->rx/* | dws->len*/) & (ARCH_DMA_MINALIGN - 1)) { //if (((u32)dws->rx/* | dws->len*/) & (ARCH_DMA_MINALIGN - 1)) {
if ((u32)dws->rx & 3) { if ((u32)dws->rx & 31) {
dws->rx_dummy_buffer = pvPortMalloc(dws->len); dws->rx_dummy_buffer = pvPortMalloc(dws->len);
if (!dws->rx_dummy_buffer) if (!dws->rx_dummy_buffer)
return -ENOMEM; return -ENOMEM;

View File

@ -147,7 +147,7 @@ static xPinGroup_t pin_groups[] = {
{.groupid = PGRP_I2C1, .pins_num = 2, .pins = {{50, 1}, {51, 1}}}, {.groupid = PGRP_I2C1, .pins_num = 2, .pins = {{50, 1}, {51, 1}}},
{.groupid = PGRP_LCD_TTL_CH0, .pins_num = 28, {.groupid = PGRP_LCD_TTL_CH0, .pins_num = 28,
/* de clk vynsc hsync */ /* de clk vynsc hsync */
.pins = {{88, 1}, {89, 1, PAD_DRIVE_2MA}, {90, 1}, {91, 1}, .pins = {{88, 1}, {89, 1, PAD_DRIVE_2MA}, {90, 0}, {91, 0},
{64, 1}, {65, 1}, {66, 1}, {67, 1}, {68, 1}, {69, 1}, {70, 1}, {71, 1}, /* B0-B7 */ {64, 1}, {65, 1}, {66, 1}, {67, 1}, {68, 1}, {69, 1}, {70, 1}, {71, 1}, /* B0-B7 */
{72, 1}, {73, 1}, {74, 1}, {75, 1}, {76, 1}, {77, 1}, {78, 1}, {79, 1}, /* G0-G7 */ {72, 1}, {73, 1}, {74, 1}, {75, 1}, {76, 1}, {77, 1}, {78, 1}, {79, 1}, /* G0-G7 */
{80, 1}, {81, 1}, {82, 1}, {83, 1}, {84, 1}, {85, 1}, {86, 1}, {87, 1},}}, /* R0-R7 */ {80, 1}, {81, 1}, {82, 1}, {83, 1}, {84, 1}, {85, 1}, {86, 1}, {87, 1},}}, /* R0-R7 */
@ -317,6 +317,7 @@ void vPinctrlSetup(void)
pinctrl_set_group(PGRP_ITU_CH1_INV); pinctrl_set_group(PGRP_ITU_CH1_INV);
pinctrl_set_group(PGRP_CAN0_CH0); pinctrl_set_group(PGRP_CAN0_CH0);
#ifdef AUDIO_REPLAY #ifdef AUDIO_REPLAY
#if (AUDIO_REPLAY_I2S == I2S_ID1) #if (AUDIO_REPLAY_I2S == I2S_ID1)
pinctrl_set_group(PGRP_I2S1_PLAY); pinctrl_set_group(PGRP_I2S1_PLAY);

View File

@ -12,13 +12,13 @@
#ifndef WITH_MVVM #ifndef WITH_MVVM
SfudData_t sfud_data_saved ={0}; SfudData_t sfud_data_saved ={0};
#define SFUD_DATA_FLASH_OFFSET 0xfff000 #define SFUD_DATA_FLASH_OFFSET 0x1fff000 //32Mflash
SfudMileData_t sfud_mile_data ={0}; SfudMileData_t sfud_mile_data ={0};
static uint32_t save_addr = 0; static uint32_t save_addr = 0;
static uint16_t User_data_index = 0; static uint16_t User_data_index = 0;
#define SFUD_MILE_DATA_FLASH_OFFSET 0xffe000//0xffe000 #define SFUD_MILE_DATA_FLASH_OFFSET 0xffe000//0xffe000
#define MILE_FLASH_OFFSET 0x1000 #define MILE_FLASH_OFFSET 0x1000
/*
void read_mileage(uint32_t trip_data,uint32_t total_data) void read_mileage(uint32_t trip_data,uint32_t total_data)
{ {
uint32_t i; uint32_t i;
@ -96,7 +96,7 @@ void SaveMileageData(uint32_t trip_data,uint32_t total_data){
} }
} }
*/
void Classify_SaveDataToFlash(SfudData_t user_data,uint8_t type){ void Classify_SaveDataToFlash(SfudData_t user_data,uint8_t type){
uint8_t buff[sizeof(SfudData_t)];//定义buff用于保存结构体 uint8_t buff[sizeof(SfudData_t)];//定义buff用于保存结构体
memset(buff,0,sizeof(buff));//将buff内存清零 memset(buff,0,sizeof(buff));//将buff内存清零
@ -137,20 +137,20 @@ void Classify_SaveDataToFlash(SfudData_t user_data,uint8_t type){
void SaveDataToFlash(SfudData_t user_data){ void SaveDataToFlash(SfudData_t user_data){
uint8_t buff[sizeof(SfudData_t)];//定义buff用于保存结构体 uint8_t buff[sizeof(SfudData_t)];//定义buff用于保存结构体
memset(buff,0,sizeof(buff));//将buff内存清零 memset(buff,0,sizeof(buff));//将buff内存清零
printf("**************save flash***********************\r\n"); // printf("**************save flash***********************\r\n");
// printf("user_data==> %d-%d-%d-%d-%d,%d",user_data.language,user_data.display_unit,user_data.theme // printf("user_data==> %d-%d-%d-%d-%d,%d",user_data.language,user_data.display_unit,user_data.theme
// ,user_data.theme_state,user_data.light_value,user_data.bt_on_off); // ,user_data.theme_state,user_data.light_value,user_data.bt_on_off);
printf("mac:%02X%02X%02X%02X%02X%02X , %02X%02X%02X%02X%02X%02X end\r\n",user_data.f_mac_address[0],user_data.f_mac_address[1],user_data.f_mac_address[2] // printf("mac:%02X%02X%02X%02X%02X%02X , %02X%02X%02X%02X%02X%02X end\r\n",user_data.f_mac_address[0],user_data.f_mac_address[1],user_data.f_mac_address[2]
,user_data.f_mac_address[3],user_data.f_mac_address[4],user_data.f_mac_address[5] // ,user_data.f_mac_address[3],user_data.f_mac_address[4],user_data.f_mac_address[5]
,user_data.r_mac_address[0],user_data.r_mac_address[1],user_data.r_mac_address[2] // ,user_data.r_mac_address[0],user_data.r_mac_address[1],user_data.r_mac_address[2]
,user_data.r_mac_address[3],user_data.r_mac_address[4],user_data.r_mac_address[5]); // ,user_data.r_mac_address[3],user_data.r_mac_address[4],user_data.r_mac_address[5]);
// printf("data:%02X %02X%02X , %02X %02X%02X end\r\n" // printf("data:%02X %02X%02X , %02X %02X%02X end\r\n"
// ,user_data.f_mac_address[6],user_data.f_mac_address[7],user_data.f_mac_address[8] // ,user_data.f_mac_address[6],user_data.f_mac_address[7],user_data.f_mac_address[8]
// ,user_data.r_mac_address[6],user_data.r_mac_address[7],user_data.r_mac_address[8]); // ,user_data.r_mac_address[6],user_data.r_mac_address[7],user_data.r_mac_address[8]);
// printf("*************************************\r\n"); // printf("*************************************\r\n");
// printf("mile data: %02X,%02X end\r\n" // printf("mile data: %02X,%02X end\r\n"
// ,user_data.maintenance_mileage,user_data.mileage_flag); // ,user_data.maintenance_mileage,user_data.mileage_flag);
printf("*************************************\r\n"); // printf("*************************************\r\n");
if(user_data.light_value==0) if(user_data.light_value==0)
user_data.light_value=1; user_data.light_value=1;
@ -169,6 +169,9 @@ void SaveDataToFlash(SfudData_t user_data){
strcpy(((SfudData_t *)buff)->r_mac_address,user_data.r_mac_address); strcpy(((SfudData_t *)buff)->r_mac_address,user_data.r_mac_address);
((SfudData_t *)buff)->maintenance_mileage = user_data.maintenance_mileage; ((SfudData_t *)buff)->maintenance_mileage = user_data.maintenance_mileage;
((SfudData_t *)buff)->mileage_flag = user_data.mileage_flag; ((SfudData_t *)buff)->mileage_flag = user_data.mileage_flag;
((SfudData_t *)buff)->display_mileage = user_data.display_mileage;
((SfudData_t *)buff)->tcs_on_off = user_data.tcs_on_off;
((SfudData_t *)buff)->mile_state = user_data.mile_state;
sfud_flash *sflash = sfud_get_device(0); sfud_flash *sflash = sfud_get_device(0);
if (sfud_erase_write(sflash,SFUD_DATA_FLASH_OFFSET,sizeof(buff),buff)!=SFUD_SUCCESS){ if (sfud_erase_write(sflash,SFUD_DATA_FLASH_OFFSET,sizeof(buff),buff)!=SFUD_SUCCESS){

View File

@ -833,7 +833,7 @@ static int uup_rx_data_len = 0;
#if DEVICE_TYPE_SELECT != EMMC_FLASH #if DEVICE_TYPE_SELECT != EMMC_FLASH
#include "ff_sfdisk.h" #include "ff_sfdisk.h"
#endif #endif
/*
typedef enum { typedef enum {
UART_FRAME_START, UART_FRAME_START,
UART_FRAME_FILEINFO, UART_FRAME_FILEINFO,
@ -855,8 +855,8 @@ typedef enum {
#define UUP_MAX_FILE_SIZE 0x1000000 #define UUP_MAX_FILE_SIZE 0x1000000
#define UUP_RX_FRAME_NUM 16 #define UUP_RX_FRAME_NUM 16
#define UUP_MAX_LOADER_SIZE STEPLDR_MAX_SIZE//0x10000 #define UUP_MAX_LOADER_SIZE STEPLDR_MAX_SIZE//0x10000
*/
static int uup_status = UUP_STATE_IDLE; // static int uup_status = UUP_STATE_IDLE;
static int uup_file_type = 0; static int uup_file_type = 0;
static int uup_file_size = 0; static int uup_file_size = 0;
static int uup_packet_num = 0; static int uup_packet_num = 0;
@ -877,7 +877,7 @@ static void uup_send_ack(UartPort_t *uap, int type, int ret)
iUartWrite(uap, buf, 7, pdMS_TO_TICKS(100)); iUartWrite(uap, buf, 7, pdMS_TO_TICKS(100));
} }
#if 0
void uup_ota_update(UartPort_t *uap, uint8_t *framebuf, size_t len) void uup_ota_update(UartPort_t *uap, uint8_t *framebuf, size_t len)
{ {
int frametype = framebuf[0]; int frametype = framebuf[0];
@ -1009,6 +1009,9 @@ void uup_ota_update(UartPort_t *uap, uint8_t *framebuf, size_t len)
break; break;
} }
} }
#endif
#else #else
static void uart_tx_demo_thread(void *param) static void uart_tx_demo_thread(void *param)
{ {

View File

@ -69,7 +69,7 @@ static void protocol_uart_tx_thread(void *param)
for (;;) for (;;)
{ {
if(uart_tx_flag){ if(uart_tx_flag){
if (uart_time_request[0] != 0 && uart_time_request[0] == 0xAA) if (uart_time_request[0] != 0 && (uart_time_request[0] == 0xAA || uart_time_request[0] == 0x27))
{ {
// printf("UART3 tx-->>> "); // printf("UART3 tx-->>> ");
for (uint8_t i = 0; i < 9; i++) for (uint8_t i = 0; i < 9; i++)
@ -126,7 +126,10 @@ static uint16_t calculate_cumulative_sum(uint8_t *buf)
return sum; return sum;
} }
extern uint8_t uart3_flag; uint8_t device_flag = 0;
uint8_t data_analysis_flag = 0;
uint8_t data_count_flag = 0;
uint8_t uart3_flag = 0;
static void protocol_uart_rx_thread(void *param) static void protocol_uart_rx_thread(void *param)
{ {
UartPort_t *uap = xUartOpen(UART_BT_PORT); UartPort_t *uap = xUartOpen(UART_BT_PORT);
@ -139,7 +142,7 @@ static void protocol_uart_rx_thread(void *param)
int i; int i;
uint8_t tlv_data_value[128] = {0}; uint8_t tlv_data_value[128] = {0};
unsigned char ota_request[8] = {0x7e,0x00,0x05,0x02,0x03,0x01,0x00,0x01}; // unsigned char ota_request[8] = {0x7e,0x00,0x05,0x02,0x03,0x01,0x00,0x01};
uint32_t sum = 0; uint32_t sum = 0;
uint8_t equipment_data = 0; uint8_t equipment_data = 0;
uint8_t mac_data = 0; uint8_t mac_data = 0;
@ -164,13 +167,9 @@ static void protocol_uart_rx_thread(void *param)
for (;;) for (;;)
{ {
len = iUartRead(uap, uartrx, BUFFER_LEN, pdMS_TO_TICKS(10)); len = iUartRead(uap, uartrx, BUFFER_LEN, pdMS_TO_TICKS(10));
if(uart3_flag){ if(Get_sys_power_on_self_test() != 150 ){
if(len==0) if(device_flag)
uart3_flag = 0; data_count_flag++;
else
printf("len!=0.\r\n");
}else if(Get_sys_power_on_self_test() != 150){
for(i=0;i<len;i++){ for(i=0;i<len;i++){
switch (upgrade_state) { switch (upgrade_state) {
case 0: case 0:
@ -214,26 +213,31 @@ static void protocol_uart_rx_thread(void *param)
if (uartrx[i] == 0x0a){ if (uartrx[i] == 0x0a){
sum = calculate_cumulative_sum(tlv_data_value); sum = calculate_cumulative_sum(tlv_data_value);
if(sum != tlv_data_value[str_len-1]){ if(sum != tlv_data_value[str_len-1]){
//printf("error.\r\n"); printf("error.\r\n");
}else{ }else{
if(equipment_data){ if(equipment_data){
device_data_analysis(tlv_data_value); device_data_analysis(tlv_data_value);
equipment_data = 0; equipment_data = 0;
if(!data_analysis_flag)
device_flag = 1;
}else if(mac_data){ }else if(mac_data){
tire_pressure_data_analysis(tlv_data_value); tire_pressure_data_analysis(tlv_data_value);
mac_data = 0; mac_data = 0;
}else }else{
data_analysis(tlv_data_value); data_analysis(tlv_data_value);
if(!data_analysis_flag)
data_analysis_flag = 1;
} }
// }else{ }
//DEBUG_PRINT("\nuartrx[i] = %x .\n",uartrx[i]); }else{
printf("\nuartrx[i] = %x .\n",uartrx[i]);
} }
upgrade_state=0; upgrade_state=0;
str_len = 0; str_len = 0;
data_len = 0; data_len = 0;
break; break;
} }
/*
switch (uup_rx_state) { switch (uup_rx_state) {
case 0: case 0:
if (uartrx[i] == 0x7e) if (uartrx[i] == 0x7e)
@ -272,22 +276,20 @@ static void protocol_uart_rx_thread(void *param)
case 6: case 6:
if (uartrx[i] == Get_sys_softwar_order()){ if (uartrx[i] == Get_sys_softwar_order()){
if(Get_sys_veer_velocity()){ if(Get_sys_veer_velocity()){
//DEBUG_PRINT("error ota sj. Speed present\n"); printf("error ota sj. Speed present\n");
ota_request[1] = 0x01; // ota_request[1] = 0x01;
ota_request[6] = Get_sys_softwar_host(); // ota_request[6] = Get_sys_softwar_host();
ota_request[7] = Get_sys_softwar_order(); // ota_request[7] = Get_sys_softwar_order();
TXCMD_Other_Set(ota_request,8); // TXCMD_Other_Set(ota_request,8);
Send_ota_state(1);
}else{ }else{
//DEBUG_PRINT("enter ota sj.\n"); printf("enter ota sj.\n");
Set_sys_power_on_self_test(150); Set_sys_power_on_self_test(150);
// extern uint8_t now_theme_state;
// now_theme_state = 5;
Set_sys_upgrade_Flag(1);//进入ota界面 Set_sys_upgrade_Flag(1);//进入ota界面
ota_request[6] = Get_sys_softwar_host(); // ota_request[6] = Get_sys_softwar_host();
ota_request[7] = Get_sys_softwar_order(); // ota_request[7] = Get_sys_softwar_order();
vTaskDelay(100); Send_ota_state(0);
TXCMD_Other_Set(ota_request,8);
if(timeout) if(timeout)
timeout=0; timeout=0;
@ -297,9 +299,20 @@ static void protocol_uart_rx_thread(void *param)
uup_rx_state = 0; uup_rx_state = 0;
break; break;
} }
} }
if((!data_analysis_flag) && data_count_flag == 50){
data_count_flag = 0;
if(uart3_flag){
printf("uart3 open .\r\n");
UART3_Type_regression();
uart3_flag = 0;
}else{
printf("uart3 close .\r\n");
UART3_Modification_Type();
uart3_flag = 1;
}
}
}else{//升级逻辑 }else{//升级逻辑
timeout ++; timeout ++;
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
@ -335,7 +348,7 @@ static void protocol_uart_rx_thread(void *param)
//uup_rx_data_len |= uartrx[i]; //uup_rx_data_len |= uartrx[i];
uup_rx_data_len = (uartrx[i]<<8) | uup_rx_data_len; uup_rx_data_len = (uartrx[i]<<8) | uup_rx_data_len;
if((uup_rx_data_len > UUP_PACKET_A27_SIZE + 2)) { //4096 + 2 if((uup_rx_data_len > UUP_PACKET_A27_SIZE + 2)) { //4096 + 2
//DEBUG_PRINT("Invalid uup_rx_data_len %d\n", uup_rx_data_len); printf("Invalid uup_rx_data_len %d\n", uup_rx_data_len);
uup_rx_state = 0; uup_rx_state = 0;
} else { } else {
uup_rx_state++; uup_rx_state++;
@ -365,27 +378,25 @@ static void protocol_uart_rx_thread(void *param)
len = buf[3]<<8 | len; len = buf[3]<<8 | len;
for (i = 0; i < len + 4; i++) for (i = 0; i < len + 4; i++)
checksum ^= buf[i]; checksum ^= buf[i];
////DEBUG_PRINT("checksum = 0x%x , buf[len + 4] = 0x%x\n",checksum,buf[len + 4]); //printf("checksum = 0x%x , buf[len + 4] = 0x%x\n",checksum,buf[len + 4]);
if (checksum == buf[len + 4]) { if (checksum == buf[len + 4]) {
timeout =0; timeout =0;
// uup_ota_update(uap, buf + 4, len); uup_ota_update(uap, buf + 4, len);
//DEBUG_PRINT("rev frame checksum err.\n"); } else {
printf("rev frame checksum err.\r\n");
} }
uup_rx_tail = (uup_rx_tail + 1) % UUP_RX_FRAME_NUM; uup_rx_tail = (uup_rx_tail + 1) % UUP_RX_FRAME_NUM;
} }
if(timeout >= 3000){//超时退出升级 大约40s if(timeout >= 3000){//超时退出升级 大约40s
//DEBUG_PRINT("exit ota sj.\n"); printf("exit ota sj.\n");
Set_sys_power_on_self_test(100); Set_sys_power_on_self_test(100);
Set_sys_upgrade_Flag(2); Set_sys_upgrade_Flag(2);
//DEBUG_PRINT("UART3_Type_regression .\n"); printf("UART3_Type_regression .\n");
extern void UART3_Type_regression(void); extern void UART3_Type_regression(void);
UART3_Type_regression(); UART3_Type_regression();
timeout = 0; timeout = 0;
} }
*/
}
} }
} }

View File

@ -67,7 +67,7 @@
// //
//#define configTOTAL_HEAP_SIZE ( ( size_t ) ( (18.8+32) * 1024 * 1024) ) // google拼音出现异常 //#define configTOTAL_HEAP_SIZE ( ( size_t ) ( (18.8+32) * 1024 * 1024) ) // google拼音出现异常
//#define configTOTAL_HEAP_SIZE ( ( size_t ) ( (8.5+32) * 1024 * 1024) ) // google拼音正常工作 //#define configTOTAL_HEAP_SIZE ( ( size_t ) ( (8.5+32) * 1024 * 1024) ) // google拼音正常工作
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( (3.5+32) * 1024 * 1024) ) // google拼音正常工作 #define configTOTAL_HEAP_SIZE ( ( size_t ) ( (3.5+30) * 1024 * 1024) ) // google拼音正常工作
#elif defined(REVERSE_TRACK) #elif defined(REVERSE_TRACK)
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( (22+32) * 1024 * 1024) ) #define configTOTAL_HEAP_SIZE ( ( size_t ) ( (22+32) * 1024 * 1024) )

View File

@ -89,8 +89,35 @@ struct IAACallbacks
void* cb_ctx; void* cb_ctx;
}; };
typedef struct __auto_cfg_info
{
short width;//pixel
short height;
short density;
short fps;
char* wifi_ssid;
char* wifi_passwd;
char wifi_channel;
bool disable_auto_audio;
bool video_auto_start;
} auto_cfg_info;
extern auto_cfg_info *g_auto_link_info;
int android_auto_init(struct IAACallbacks* cbs); int android_auto_init(struct IAACallbacks* cbs);
int android_auto_rfcomm_read_data_proc(char *buf, int len); int android_auto_rfcomm_read_data_proc(char *buf, int len);
void android_auto_start(); void android_auto_start();
void android_auto_set_rfcomm_info(const char * ssid, const char * passwd, const char * mac, int securityMode, const char * ip, int port); void android_auto_set_rfcomm_info(const char * ssid, const char * passwd, const char * mac, int securityMode, const char * ip, int port);
void android_auto_set_BT_paring_status(bool paired, const char *pinCode, int status);
void android_auto_send_touch_event(unsigned int x, unsigned int y, int action);
void android_auto_send_key_event(unsigned int keycode, int press);
void android_auto_send_knob_event(unsigned int keycode, int delta);
void android_auto_set_night_mode(bool night);
void android_auto_get_video_focus(int mode);
void android_auto_release_video_focus(int mode);
void android_auto_get_audio_focus(int mode);
void android_auto_release_audio_focus(int mode);
#endif #endif

Binary file not shown.

View File

@ -0,0 +1,302 @@
#include <stdio.h>
#include <stdint.h>
#include "carlink_video.h"
#include "carlink_common.h"
#include "AndroidAuto.h"
#include "board.h"
#if CARLINK_AA
struct AAHandle
{
struct ICalinkEventCallbacks carlinkEventCB;
struct IAACallbacks carlinkAACB;
bool mInitDone;
bool mBTConnected;
bool mRfcommReady;
char mLocalBTMac[6];
char mRemoteBTMac[6];
char mIp[32];
};
//extern int debug_buf_ref;
struct AAHandle gAACtx;
static bool g_aa_disable = false;
static void android_auto_notify_event(struct carlink_event *ev, enum CARLINK_EVENT_TYPE type, bool disable_filter)
{
ev->link_type = CARLINK_AUTO_WIRELESS;
ev->disable_filter = disable_filter;
ev->type = type;
carlink_notify_event(ev);
}
static void start_aa(struct AAHandle* pctx)
{
if (!pctx->mInitDone)
return;
//if (pctx->mBTConnected)
// return;
if (!pctx->mRfcommReady)
return;
if (g_aa_disable)
return;
printf("%s:%d\r\n", __func__, __LINE__);
g_auto_link_info->wifi_ssid = (char *)carlink_get_wifi_ssid();
g_auto_link_info->wifi_passwd = (char *)carlink_get_wifi_passwd;
android_auto_set_rfcomm_info((const char*)carlink_get_wifi_ssid(),
(const char*)carlink_get_wifi_passwd(), (const char*)carlink_get_wifi_mac(), 5, (const char*)pctx->mIp, 0);
android_auto_start();
}
static void onEventAA(void* ctx, const struct carlink_event *ev)
{
enum CARLINK_EVENT_TYPE type;
struct AAHandle* pctx = (struct AAHandle*)ctx;
if (NULL == ev)
return;
if (ev->link_type != CARLINK_AUTO_WIRELESS && !ev->disable_filter)// skip not aa event
return;
type = ev->type;
switch (type) {
case -1: {
break;
}
case CARLINK_EVENT_INIT_DONE:
pctx->mInitDone = true;
start_aa(pctx);
break;
case CARLINK_EVENT_BT_CONNECT: {
pctx->mBTConnected = true;
start_aa(pctx);
break;
}
case CARLINK_EVENT_BT_AA_RFCOMM_READY: {
pctx->mRfcommReady = true;
start_aa(pctx);
break;
}
case CARLINK_EVENT_BT_DISCONNECT: {
pctx->mBTConnected = false;
pctx->mRfcommReady = false;
break;
}
case CARLINK_EVENT_WIFI_CONNECT: {
break;
}
case CARLINK_EVENT_MSG_SESSION_CONNECT: {
break;
}
case CARLINK_EVENT_MSG_SESSION_STOP: {
printf("%s:%d\r\n", __func__, __LINE__);
start_aa(pctx);
break;
}
default:
break;
}
}
static void aa_rfcomm_data_read(void* ctx, const void* buf, int len)
{
struct AAHandle* pctx = (struct AAHandle*)ctx;
if (!pctx->mRfcommReady)
return;
android_auto_rfcomm_read_data_proc((char*)buf, len);
}
static int rf_write_transfer_cb(void* cb_ctx, char *buf, int len)
{
int ret = -1;
struct AAHandle* pctx = (struct AAHandle*)cb_ctx;
if (!pctx->mRfcommReady)
return -1;
ret = carlink_auto_rfcomm_data_write(buf, len);
return ret;
}
static void video_init_impl(void* cb_ctx, int w, int h, int x, int y)
{
struct AAHandle* pctx = (struct AAHandle*)cb_ctx;
printf("x:%d y:%d w:%d h:%d\r\n", x, y, w, h);
set_carlink_active_video_info(x, y);
h264_dec_ctx_init();
set_carlink_display_state(1);
//debug_buf_ref = 1;
}
static void video_uninit_impl(void* cb_ctx)
{
struct AAHandle* pctx = (struct AAHandle*)cb_ctx;
set_carlink_display_state(0);
set_carlink_active_video_info(0, 0);
}
int g_v_count;
static void video_play_impl(void* cb_ctx, char *buf, int len)
{
struct AAHandle* pctx = (struct AAHandle*)cb_ctx;
video_frame_s* frame = NULL;
get_retry:
frame = get_h264_frame_buf();
if (NULL == frame) {
//printf("h264 frame is empty\r\n");
vTaskDelay(pdMS_TO_TICKS(10));
goto get_retry;
//continue;
}
memcpy(frame->cur, buf, len);
frame->len = len;
notify_h264_frame_ready(&frame);
if (g_v_count++ > 50) {
//android_auto_get_video_focus(0);
}
}
static void audio_init_callback_impl(void* cb_ctx, int type, int sample, int ch, int bits)
{
struct AAHandle* pctx = (struct AAHandle*)cb_ctx;
}
static void audio_uninit_callback_impl(void* cb_ctx, int type)
{
struct AAHandle* pctx = (struct AAHandle*)cb_ctx;
}
static void audio_play_impl(void* cb_ctx, int type, char *buf, int len)
{
struct AAHandle* pctx = (struct AAHandle*)cb_ctx;
}
static void mic_init_callback_impl(void* cb_ctx, int sample, int ch, int bits)
{
struct AAHandle* pctx = (struct AAHandle*)cb_ctx;
}
static void mic_uninit_callback_impl(void* cb_ctx)
{
struct AAHandle* pctx = (struct AAHandle*)cb_ctx;
}
static void mic_capture_impl(void* cb_ctx, char *buf, int len)
{
struct AAHandle* pctx = (struct AAHandle*)cb_ctx;
}
static void bt_paring_request_callback_impl(void* cb_ctx, const char *phoneAddr, int pairingMethod)
{
struct AAHandle* pctx = (struct AAHandle*)cb_ctx;
}
static void status_notify_impl(void* cb_ctx, int status_type)
{
struct AAHandle* pctx = (struct AAHandle*)cb_ctx;
struct carlink_event ev = {0};
if (status_type == LINK_REMOVED) {
printf("%s:%d\r\n", __func__, __LINE__);
android_auto_notify_event(&ev, CARLINK_EVENT_MSG_SESSION_STOP, 0);
}
}
static void json_msg_notify_impl(void* cb_ctx, char *buf, int len)
{
struct AAHandle* pctx = (struct AAHandle*)cb_ctx;
}
int carlink_aa_init()
{
int ret = -1;
struct AAHandle* pctx = &gAACtx;
struct IAACallbacks* carlinkAACBPtr = NULL;
memset((void*)pctx, 0, sizeof(struct AAHandle));
g_auto_link_info->width = CARLINK_VIDEO_WIDTH;
g_auto_link_info->height = CARLINK_VIDEO_HEIGHT;
g_auto_link_info->fps = 30;
g_auto_link_info->density = 160;
g_auto_link_info->disable_auto_audio = 1;
g_auto_link_info->video_auto_start = 1;
set_carlink_display_info(0, 0, CARLINK_VIDEO_WIDTH, CARLINK_VIDEO_HEIGHT);
set_carlink_video_info(CARLINK_VIDEO_WIDTH, CARLINK_VIDEO_HEIGHT, 30);
ret = carlink_common_init();
pctx->carlinkEventCB.onEvent = onEventAA;
pctx->carlinkEventCB.rfcomm_data_read = aa_rfcomm_data_read;
pctx->carlinkEventCB.cb_ctx = (void*)pctx;
carlink_register_event_callbacks(&pctx->carlinkEventCB);
ret = carlink_bt_wifi_init();
carlinkAACBPtr = &pctx->carlinkAACB;
carlinkAACBPtr->video_init = video_init_impl;
carlinkAACBPtr->video_uninit = video_uninit_impl;
carlinkAACBPtr->video_play = video_play_impl;
carlinkAACBPtr->audio_init_callback = audio_init_callback_impl;
carlinkAACBPtr->audio_uninit_callback = audio_uninit_callback_impl;
carlinkAACBPtr->mic_init_callback = mic_init_callback_impl;
carlinkAACBPtr->mic_uninit_callback = mic_uninit_callback_impl;
carlinkAACBPtr->mic_capture = mic_capture_impl;
carlinkAACBPtr->bt_paring_request_callback = bt_paring_request_callback_impl;
carlinkAACBPtr->status_notify = status_notify_impl;
carlinkAACBPtr->json_msg_notify = json_msg_notify_impl;
carlinkAACBPtr->rf_read_transfer_cb = NULL;
carlinkAACBPtr->rf_write_transfer_cb = rf_write_transfer_cb;
carlinkAACBPtr->cb_ctx = (void*)pctx;
ret = android_auto_init(&pctx->carlinkAACB);
{
char ip[4] = {0};
carlink_get_ap_ip_addr(ip);
sprintf(pctx->mIp, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
}
{
struct carlink_event ev = {0};
android_auto_notify_event(&ev, CARLINK_EVENT_INIT_DONE, 0);
}
return 0;
}
void carlink_aa_enable(int enable)
{
if (enable) {
g_aa_disable = false;
} else {
g_aa_disable = true;
}
}
#else
int carlink_aa_init()
{
return 0;
}
void carlink_aa_enable(int enable)
{
(void)enable;
}
#endif

View File

@ -12,7 +12,6 @@ struct AAHandle
struct ICalinkEventCallbacks carlinkEventCB; struct ICalinkEventCallbacks carlinkEventCB;
struct IAACallbacks carlinkAACB; struct IAACallbacks carlinkAACB;
bool mInitDone; bool mInitDone;
bool mBTConnected; bool mBTConnected;
bool mRfcommReady; bool mRfcommReady;
@ -21,8 +20,11 @@ struct AAHandle
char mIp[32]; char mIp[32];
}; };
//extern int debug_buf_ref;
struct AAHandle gAACtx; struct AAHandle gAACtx;
static bool g_aa_disable = false;
static void android_auto_notify_event(struct carlink_event *ev, enum CARLINK_EVENT_TYPE type, bool disable_filter) static void android_auto_notify_event(struct carlink_event *ev, enum CARLINK_EVENT_TYPE type, bool disable_filter)
{ {
@ -40,7 +42,12 @@ static void start_aa(struct AAHandle* pctx)
// return; // return;
if (!pctx->mRfcommReady) if (!pctx->mRfcommReady)
return; return;
if (g_aa_disable)
return;
printf("%s:%d\r\n", __func__, __LINE__); printf("%s:%d\r\n", __func__, __LINE__);
g_auto_link_info->wifi_ssid = (char *)carlink_get_wifi_ssid();
g_auto_link_info->wifi_passwd = (char *)carlink_get_wifi_passwd;
android_auto_set_rfcomm_info((const char*)carlink_get_wifi_ssid(), android_auto_set_rfcomm_info((const char*)carlink_get_wifi_ssid(),
(const char*)carlink_get_wifi_passwd(), (const char*)carlink_get_wifi_mac(), 5, (const char*)pctx->mIp, 0); (const char*)carlink_get_wifi_passwd(), (const char*)carlink_get_wifi_mac(), 5, (const char*)pctx->mIp, 0);
android_auto_start(); android_auto_start();
@ -119,12 +126,17 @@ static int rf_write_transfer_cb(void* cb_ctx, char *buf, int len)
return ret; return ret;
} }
int g_v_count;
static void video_init_impl(void* cb_ctx, int w, int h, int x, int y) static void video_init_impl(void* cb_ctx, int w, int h, int x, int y)
{ {
struct AAHandle* pctx = (struct AAHandle*)cb_ctx; struct AAHandle* pctx = (struct AAHandle*)cb_ctx;
printf("x:%d y:%d w:%d h:%d\r\n", x, y, w, h);
set_carlink_active_video_info(x, y);
h264_dec_ctx_init(); h264_dec_ctx_init();
set_carlink_display_state(1); set_carlink_display_state(1);
//carlink_bt_close();
g_v_count = 0;
//debug_buf_ref = 1;
} }
static void video_uninit_impl(void* cb_ctx) static void video_uninit_impl(void* cb_ctx)
@ -132,6 +144,7 @@ static void video_uninit_impl(void* cb_ctx)
struct AAHandle* pctx = (struct AAHandle*)cb_ctx; struct AAHandle* pctx = (struct AAHandle*)cb_ctx;
set_carlink_display_state(0); set_carlink_display_state(0);
set_carlink_active_video_info(0, 0);
} }
static void video_play_impl(void* cb_ctx, char *buf, int len) static void video_play_impl(void* cb_ctx, char *buf, int len)
@ -153,6 +166,9 @@ get_retry:
frame->len = len; frame->len = len;
notify_h264_frame_ready(&frame); notify_h264_frame_ready(&frame);
if (g_v_count++ > 50) {//enable_malloc_debug = 1;
//android_auto_get_video_focus(0);
}
} }
static void audio_init_callback_impl(void* cb_ctx, int type, int sample, int ch, int bits) static void audio_init_callback_impl(void* cb_ctx, int type, int sample, int ch, int bits)
@ -204,7 +220,7 @@ static void json_msg_notify_impl(void* cb_ctx, char *buf, int len)
int carlink_aa_init() int _carlink_aa_init()
{ {
int ret = -1; int ret = -1;
struct AAHandle* pctx = &gAACtx; struct AAHandle* pctx = &gAACtx;
@ -212,6 +228,14 @@ int carlink_aa_init()
memset((void*)pctx, 0, sizeof(struct AAHandle)); memset((void*)pctx, 0, sizeof(struct AAHandle));
g_auto_link_info->width = CARLINK_VIDEO_WIDTH;
g_auto_link_info->height = CARLINK_VIDEO_HEIGHT;
g_auto_link_info->fps = 30;
g_auto_link_info->density = 160;
g_auto_link_info->disable_auto_audio = 1;
g_auto_link_info->video_auto_start = 1;
set_carlink_display_info(0, 0, CARLINK_VIDEO_WIDTH, CARLINK_VIDEO_HEIGHT); set_carlink_display_info(0, 0, CARLINK_VIDEO_WIDTH, CARLINK_VIDEO_HEIGHT);
set_carlink_video_info(CARLINK_VIDEO_WIDTH, CARLINK_VIDEO_HEIGHT, 30); set_carlink_video_info(CARLINK_VIDEO_WIDTH, CARLINK_VIDEO_HEIGHT, 30);
@ -255,10 +279,41 @@ int carlink_aa_init()
} }
return 0; return 0;
} }
static void taskInitCarlinkAA(void* param)
{
_carlink_aa_init();
vTaskDelete(NULL);
}
int carlink_aa_init()
{
xTaskCreate(taskInitCarlinkAA, "initThread", 2048 * 4, NULL, 1, NULL);
return 0;
}
void carlink_aa_enable(int enable)
{
if (enable) {
g_aa_disable = false;
} else {
g_aa_disable = true;
}
}
#else #else
int carlink_aa_init() int carlink_aa_init()
{ {
return 0; return 0;
} }
void carlink_aa_enable(int enable)
{
(void)enable;
}
#endif #endif

View File

@ -0,0 +1,133 @@
#ifndef MYCOMMON_H_H
#define MYCOMMON_H_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stdint.h>
#ifndef CAPLAY_LINK_TYPE
#define CAPLAY_LINK_TYPE
typedef enum
{
CARPLAY = 0x00,
CARLIFE,
ANDROID_CARLIFE,
ANDROID_MIRROR = 3,
IOS_CARLIFE,
ANDROID_AUTO = 5,
ECLINK = 0x06,
CARPLAY_WIRELESS
}Link_TYPE;
#endif
//general function
typedef enum __USB_MODE
{
UNDEFINED = 0,
HOST,
PERIPHERAL,
OTG
}USB_MODE;
#define LOGV(...) printf(__VA_ARGS__); printf("\r\n");
struct view_area
{
short w;
short h;
short x;
short y;
};
typedef struct __cfg_info
{
char *iap2_name;
char *iap2_modelIdentifier;
char *iap2_manfacturer;
char *iap2_serialnumber;
char *iap2_sw_ver;
char *iap2_hw_ver;
char *iap2_vehicleInfo_name;
char *iap2_product_uuid;
char *iap2_usb_serial_num;
char *manfacturer;
char *oem_icon_label;
char *oem_icon_path;
char *os_info;
char *iOSVersionMin;
char *limited_ui_elements;
char *guuid;
char *devid;
char link_type;
char btmac[6];
bool oem_icon_visible;
bool limited_ui;
bool right_hand_driver;
bool night_mode;
bool has_knob;
bool has_telbutton;
bool has_mediabutton;
bool has_proxsensor;
bool has_EnhancedReqCarUI;
bool has_ETCSupported;
bool HiFiTouch;
bool LoFiTouch;
unsigned short usb_country_code;
unsigned short tp_verndor_code;
unsigned short tp_product_code;
unsigned short tel_verndor_code;
unsigned short tel_product_code;
unsigned short knob_verndor_code;
unsigned short knob_product_code;
unsigned short proxsensor_verndor_code;
unsigned short proxsensor_product_code;
short width;//pixel
short height;
short fps;
short screen_width_phy;//mm
short screen_height_phy;
char encrypt_ic_i2c_bus_num;
char encrypt_ic_addr;
char usb_idx;
char need_sw_aec;
char aec_delay;
bool tvout_enable;
bool use_remote_audio;
char video_type;
short icurrent;
int duck_vol;
char enable_iap_carplay_sess;
char *keychain_path_dir;
char* wifi_ssid;
char* wifi_passwd;
char* public_key;
char* src_version;
char ip_v4_addr[4];
char wifi_channel;
short net_port;
char carplay_net_ready;
char disable_bonjour;
char iap_carplay_rej;
bool enable_enhanced_siri;
bool enable_single_ui;
bool is_old_carplay_ver;
struct view_area area[3];
char view_area_index;
}cfg_info;
extern cfg_info *g_link_info;
#ifdef __cplusplus
}
#endif
#endif

Binary file not shown.

View File

@ -36,6 +36,8 @@ struct carplay_ctx
}; };
struct carplay_ctx g_cp_handle; struct carplay_ctx g_cp_handle;
static bool g_cp_disable = false;
static void carplay_init_parameter(); static void carplay_init_parameter();
void start_mdnsd(); void start_mdnsd();
@ -56,9 +58,22 @@ static void iap2_link_status(void *ctx, IAP2_LINK_STATUS status){}
static int iap2_write_data(void *ctx, char *buf, int len) static int iap2_write_data(void *ctx, char *buf, int len)
{ {
(void)ctx; (void)ctx;
printf("iap2_write_data --------------------------\r\n");
return carlink_iap_data_write((unsigned char *)buf, len); return carlink_iap_data_write((unsigned char *)buf, len);
} }
static void iap2_msg_time_update(void *ctx, long long time, int zone_offset){} extern uint32_t tire_front_time;
extern uint32_t tire_rear_time;
extern uint32_t fml_stamp_to_time(uint32_t timep , uint32_t time[]);
static void iap2_msg_time_update(void *ctx, long long time, int zone_offset){
(void)ctx;
printf("iap2_msg_time_update time ======================================== %lld , %d\r\n",time,zone_offset);
uint32_t time_transfer[6];
uint32_t sum = (uint32_t)time;
tire_rear_time = sum;
tire_front_time = sum;
fml_stamp_to_time(sum,time_transfer);
}
static void iap2_msg_gps(void *ctx, unsigned char session, int start){} static void iap2_msg_gps(void *ctx, unsigned char session, int start){}
static void iap2_msg_gps_gprmc_data_status(void *ctx, int value_a, int value_v, int value_x){} static void iap2_msg_gps_gprmc_data_status(void *ctx, int value_a, int value_v, int value_x){}
static void iap2_msg_identify(void *ctx, int type, int ok) static void iap2_msg_identify(void *ctx, int type, int ok)
@ -163,6 +178,9 @@ static void start_cp(struct carplay_ctx* pctx)
if (pctx->mCarplayConnected) if (pctx->mCarplayConnected)
return; return;
if (g_cp_disable)
return;
g_link_info->enable_iap_carplay_sess = 1; g_link_info->enable_iap_carplay_sess = 1;
g_link_info->is_old_carplay_ver = 0; g_link_info->is_old_carplay_ver = 0;
g_link_info->wifi_passwd = (char *)carlink_get_wifi_passwd(); g_link_info->wifi_passwd = (char *)carlink_get_wifi_passwd();
@ -270,6 +288,7 @@ static void taskInitCarlinkCpProc(void* param)
(void)param; (void)param;
iap2_callbacks iap2_cbs; iap2_callbacks iap2_cbs;
memset((void *)&iap2_cbs, 0, sizeof(iap2_cbs)); memset((void *)&iap2_cbs, 0, sizeof(iap2_cbs));
iap2_cbs.iap2_link_status_cb = iap2_link_status; iap2_cbs.iap2_link_status_cb = iap2_link_status;
@ -388,8 +407,8 @@ static void carplay_init_parameter()
g_link_info->width = CARLINK_VIDEO_WIDTH;//pixel g_link_info->width = CARLINK_VIDEO_WIDTH;//pixel
g_link_info->height = CARLINK_VIDEO_HEIGHT; g_link_info->height = CARLINK_VIDEO_HEIGHT;
g_link_info->fps = 30; g_link_info->fps = 30;
g_link_info->screen_width_phy = PHYSICAL_WIDTH;//mm g_link_info->screen_width_phy = CARLINK_VIDEO_WIDTH;
g_link_info->screen_height_phy = PHYSICAL_HEIGHT; g_link_info->screen_height_phy = CARLINK_VIDEO_HEIGHT;
g_link_info->icurrent = 1000; g_link_info->icurrent = 1000;
g_link_info->enable_iap_carplay_sess = 1; g_link_info->enable_iap_carplay_sess = 1;
@ -424,6 +443,16 @@ int carlink_cp_init()
return 0; return 0;
} }
void carlink_cp_enable(int enable)
{
if (enable) {
g_cp_disable = false;
} else {
g_cp_disable = true;
}
}
//int mdnsd_task(); //int mdnsd_task();
static void taskMdnsdProc(void* param) static void taskMdnsdProc(void* param)
{ {
@ -442,5 +471,11 @@ int carlink_cp_init()
return 0; return 0;
} }
void carlink_cp_enable(int enable)
{
(void)enable;
}
#endif #endif

View File

@ -2,5 +2,6 @@
#define _CARLINK_CP_H_ #define _CARLINK_CP_H_
int carlink_cp_init(); int carlink_cp_init();
void carlink_cp_enable(int enable);
#endif #endif

View File

@ -0,0 +1,393 @@
//#include "os_adapt.h"
#include <FreeRTOS_POSIX.h>
#include <task.h>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdbool.h>
#include <stdio.h>
#include "board.h"
#include "timer.h"
#include "iot_wifi.h"
#include "mmcsd_core.h"
#include "carlink_utils.h"
#include "console.h"
#include "fsc_bt.h"
#include "iap.h"
#if !defined(USE_LWIP) || !USE_LWIP
#error "Carplay need lwip!"
#endif
#include "ethernet.h"
#include "tcpip.h"
#include "lwip/apps/lwiperf.h"
#include "dhcp.h"
#include "carlink_video.h"
#include "mycommon.h"
#include "wifi_conf.h"
#include "carlink_cp_priv.h"
//#define USE_WLAN_STA
static char g_cp_bt_mac[13] = {0};
static bool g_cp_bt_mac_ready = false;
static uint8_t cp_ap_ssid[64] = {"ap63011"};
static uint8_t cp_ap_passwd[16] = {"88888888"};
extern int wps_connect_done;
static const uint8_t ucIPAddress[4] = {192, 168, 13, 1};
static const uint8_t ucNetMask[4] = {255, 255, 255, 0};
static const uint8_t ucGatewayAddress[4] = {0, 0, 0, 0};
static int lwip_tcpip_init_done_flag = 0;
//static int g_bt_iap_ready = 0;
//static int g_dhcp_client_cp_ready = 0;
static struct netif gnetif[4];
extern int wifi_add_custom_ie(void *cus_ie, int ie_num);
int mmcsd_wait_sdio_ready(int32_t timeout);
static void cp_reset_wifi_ap_info(const char *prefex);
static void cp_start_wlan();
extern err_t dhcp_server_start(struct netif *netif, ip4_addr_t *start, ip4_addr_t *end);
extern err_t wlan_ethernetif_init(struct netif *netif);
#define lwip_ipv4_addr(addr) ((addr[0]) | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24))
static void tcpip_init_done(void *arg)
{
(void)arg;
//lwip_tcpip_init_done_flag = 1;
}
void lwiperf_report_cb_impl(void *arg, enum lwiperf_report_type report_type,
const ip_addr_t* local_addr, u16_t local_port, const ip_addr_t* remote_addr, u16_t remote_port,
u32_t bytes_transferred, u32_t ms_duration, u32_t bandwidth_kbitpsec)
{
(void)arg;
printf("lwiperf_report_cb_impl bytes:%d %d ms \r\n", bytes_transferred, ms_duration);
}
int cp_wlan_tcp_ip_is_ready()
{
return lwip_tcpip_init_done_flag;
}
//dd3000a0400000020022020961726B6D6963726F0003064C696E75780004030102030606ffffffffffff070666fadde250c0
static u8 carplay_vendor_ie[] = {
0xdd, 0x30, 0x00, 0xa0, 0x40, 0x00, 0x00, 0x02, 0x00, 0x22, 0x02, 0x09, 0x61, 0x72, 0x6B, 0x6D,
0x69, 0x63, 0x72, 0x6F, 0x00, 0x03, 0x06, 0x4C, 0x69, 0x6E, 0x75, 0x78, 0x00, 0x04, 0x03, 0x01,
0x02, 0x03, 0x06, 0x06, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x06, 0x66, 0xfa, 0xdd, 0xe2,
0x50, 0xc0
};
rtw_custom_ie_t carplay_ie[1] = {{carplay_vendor_ie, PROBE_RSP | BEACON}};
void carplay_add_vendor_ie()
{
wifi_add_custom_ie((void *)carplay_ie, 1);
}
void carplay_ie_replace_bt_mac(const char* btmac_str, int btmac_str_len)
{
char btmac[6] = {0};
string2hex((char *)btmac_str, btmac_str_len, btmac, 6);
memcpy((void*)g_link_info->btmac, (void*)btmac, 6);
//sscanf(btmac_str, "%02x%02x%02x%02x%02x%02x", btmac[0], btmac[1], btmac[2], btmac[3], btmac[4], btmac[5]);
carplay_vendor_ie[36] = btmac[0];
carplay_vendor_ie[37] = btmac[1];
carplay_vendor_ie[38] = btmac[2];
carplay_vendor_ie[39] = btmac[3];
carplay_vendor_ie[40] = btmac[4];
carplay_vendor_ie[41] = btmac[5];
//memcpy((void*)(carplay_vendor_ie + 36), (void*)btmac, 6);
{
int i;
for (i = 0; i < sizeof(carplay_vendor_ie); i++) {
printf("0x%02x, ", carplay_vendor_ie[i]);
}printf("\r\n");
}
}
#if defined(USE_WLAN_STA)
static void dump_ip_addr(const char *msg, const ip_addr_t *server_addr)
{
printf("%s %d.%d.%d.%d \r\n", msg,
ip4_addr1_16(ip_2_ip4(server_addr)), ip4_addr2_16(ip_2_ip4(server_addr)), ip4_addr3_16(ip_2_ip4(server_addr)), ip4_addr4_16(ip_2_ip4(server_addr)));
}
static void cp_dhcp_client_status_callback(struct netif *netif, int status, const ip_addr_t *server_addr)
{
if (&gnetif[0] == netif) {
dump_ip_addr("dhcp server ip :", (const ip_addr_t *)server_addr);
dump_ip_addr("dhcp client ip :", (const ip_addr_t *)&netif->ip_addr);
dump_ip_addr("dhcp client netmask:", (const ip_addr_t *)&netif->netmask);
dump_ip_addr("dhcp client gw :", (const ip_addr_t *)&netif->gw);
ip_addr_t *server_addr1 = (ip_addr_t *)&netif->ip_addr;
g_link_info->ip_v4_addr[0] = ip4_addr1_16(ip_2_ip4(server_addr1));
g_link_info->ip_v4_addr[1] = ip4_addr2_16(ip_2_ip4(server_addr1));
g_link_info->ip_v4_addr[2] = ip4_addr3_16(ip_2_ip4(server_addr1));
g_link_info->ip_v4_addr[3] = ip4_addr4_16(ip_2_ip4(server_addr1));
//g_dhcp_client_cp_ready = 1;
//if (g_bt_iap_ready)
//carplay_start();
}
}
#endif
void restart_bt_wifi()
{
cp_bt_close();
netif_set_down(&gnetif[0]);
WIFI_Off();
vTaskDelay(pdMS_TO_TICKS(2000));
cp_bt_open();
start_ap(36, (const char *)cp_ap_ssid, (const char *)cp_ap_passwd, 1);
carplay_add_vendor_ie();
netif_set_default(&gnetif[0]);
netif_set_up(&gnetif[0]);
}
static void cp_start_wlan()
{
char ap_prefix[5] = {0};
ip4_addr_t ip_addr;
ip4_addr_t netmask;
ip4_addr_t gw;
ip4_addr_t dhcp_addr_start;
ip4_addr_t dhcp_addr_end;
while(!g_cp_bt_mac_ready) {
vTaskDelay(pdMS_TO_TICKS(10));
}
memcpy(ap_prefix, g_cp_bt_mac + 8, 4);
cp_reset_wifi_ap_info(ap_prefix);
#if !defined(USE_WLAN_STA)
start_ap(36, (const char *)cp_ap_ssid, (const char *)cp_ap_passwd, 1);
#else
//start_sta((const char *)cp_ap_ssid, (const char *)cp_ap_passwd, 1);
dhcp_regisger_status_callback(cp_dhcp_client_status_callback);
#endif
ip_addr.addr = lwip_ipv4_addr(ucIPAddress);
netmask.addr = lwip_ipv4_addr(ucNetMask);
gw.addr = lwip_ipv4_addr(ucGatewayAddress);
tcpip_init(tcpip_init_done, NULL);
netif_add(&gnetif[0],
#if LWIP_IPV4
&ip_addr, &netmask, &gw,
#endif
NULL, wlan_ethernetif_init, tcpip_input);
netif_set_default(&gnetif[0]);
#if !defined(USE_WLAN_STA)
uint8_t addr_start[4] = {192, 168, 13, 20};
uint8_t addr_end[4] = {192, 168, 13, 30};
dhcp_addr_start.addr = lwip_ipv4_addr(addr_start);
dhcp_addr_end.addr = lwip_ipv4_addr(addr_end);
dhcp_server_start(&gnetif[0], &dhcp_addr_start, &dhcp_addr_end);
//g_dhcp_client_cp_ready = 1;
#endif
//netif_set_up(&gnetif[0]);
lwiperf_start_tcp_server_default(lwiperf_report_cb_impl, NULL);
lwip_tcpip_init_done_flag = 1;
carplay_add_vendor_ie();
}
void cp_wlan_start(void){
netif_set_up(&gnetif[0]);
}
static void cp_reset_wifi_ap_info(const char *prefex)
{
if (prefex) {
memset(cp_ap_ssid, 0, sizeof(cp_ap_ssid));
sprintf((char *)cp_ap_ssid, "AP630_CP_%s", prefex);
}
g_link_info->wifi_passwd = cp_ap_passwd;
g_link_info->wifi_ssid = cp_ap_ssid;
g_link_info->wifi_channel = 36;
g_link_info->ip_v4_addr[0] = ucIPAddress[0];
g_link_info->ip_v4_addr[1] = ucIPAddress[1];
g_link_info->ip_v4_addr[2] = ucIPAddress[2];
g_link_info->ip_v4_addr[3] = ucIPAddress[3];
}
static void cp_bt_callback(char * cAtStr)
{
char* cmd_para = NULL;
printf("\r\nfsc_bt_callback_ec %s %d\r\n", cAtStr, strlen(cAtStr));
struct cp_event ev;
memset((void*)&ev, 0, sizeof(ev));
ev.type = -1;
if (0) {
} else if (0 == strncmp(cAtStr, "+IAPDATA=", 9)) {
char ble_buf[256] = {0};
int data_len, i;
int data_str_len = (strlen(cAtStr) - 9);
cmd_para = cAtStr + 9;
data_len = data_str_len / 2;
string2hex(cmd_para, data_str_len, ble_buf, data_len);
for (i = 0; i < data_len; i++) {
printf("%02x ", ble_buf[i]);
}printf("\r\n");
iap2_read_data_proc(ble_buf, data_len);
} else if (0 == strncmp(cAtStr, "+GATTDATA=", 10)) {
} else if (0 == strncmp(cAtStr, "+GATTSTAT=1",11)) {
//ev.type = EC_EVENT_BT_DISCONNECT;
printf("TRACE[%s][%d]:EC_EVENT_BT_DISCONNECT\r\n",__func__ ,__LINE__);
ev.type = CP_EVENT_BT_DISCONNECT;
carlink_cp_notify_event(&ev);
} else if (0 == strncmp(cAtStr, "+GATTSTAT=3",11)) {
printf("TRACE[%s][%d]:EC_EVENT_BT_CONNECT\r\n",__func__ ,__LINE__);
ev.type = CP_EVENT_BT_CONNECT;
carlink_cp_notify_event(&ev);
} else if (0 == strncmp(cAtStr, "+ADDR=", 6)) {
char cmd_str[64] = {0};
sprintf(cmd_str, "AT+NAME=AP630_CP_%s\r\n", (cAtStr + 6 + 8));
printf("ADDR:%s\r\n", cAtStr + 6);
console_send_atcmd(cmd_str, strlen(cmd_str));//get mac addr
memset(cmd_str, 0, sizeof(cmd_str));
sprintf(cmd_str, "AT+LENAME=AP630_CP_%s\r\n", (cAtStr + 6 + 8));
console_send_atcmd(cmd_str, strlen(cmd_str));//get mac addr
memcpy(g_cp_bt_mac, (cAtStr + 6), 12);
carplay_ie_replace_bt_mac(cAtStr + 6, 12);
g_cp_bt_mac_ready = true;
} else if (0 == strncmp(cAtStr, "+VER", 4)) {
char* cmd = "AT+ADDR\r\n";
console_send_atcmd(cmd, strlen(cmd));//get mac addr
} else if (0 == strncmp(cAtStr, "+NAME=", 6)) {
char cmd_str[64] = {0};
sprintf(cmd_str, "AT+LEADDR\r\n");
console_send_atcmd(cmd_str, strlen(cmd_str));//get LE addr
} else if (0 == strncmp(cAtStr, "+LEADDR=", 6)) {
char hexMacAddr[6] = {0};
char m_tmp_buf[64] = {0};
string2hex(&cAtStr[8], 12, hexMacAddr, sizeof(hexMacAddr));
sprintf(m_tmp_buf, "AT+ADVDATA=%s\r\n", hexMacAddr);
console_send_atcmd(m_tmp_buf, 19);
} else if (0 == strncmp(cAtStr, "+GATTSENT=", 10)) {
return;
} else if (0 == strncmp(cAtStr, "+IAPSTAT=3", 10)) {
//g_bt_iap_ready = 1;
//if (g_dhcp_client_cp_ready)
//carplay_start();
ev.type = CP_EVENT_BT_IAP_READY;
carlink_cp_notify_event(&ev);
}
}
int iap_data_write(unsigned char *data, int len)
{
uint8_t *at_str = NULL, *at_str_ptr = NULL;
uint8_t *at_prefix = "AT+IAPSEND=";
int prefix_len = strlen((char *)at_prefix);
int cmd_len = (len * 2 + prefix_len + 2);
at_str = (uint8_t *)pvPortMalloc(cmd_len + 1);
memset(at_str, 0, cmd_len + 1);
if (NULL == at_str)
return -1;
at_str_ptr = at_str;
sprintf((char*)at_str_ptr, "%s", (char*)at_prefix);
at_str_ptr += prefix_len;
hex2str(data, len, (char *)at_str_ptr);
at_str_ptr += (len * 2);
*at_str_ptr++ = '\r';
*at_str_ptr++ = '\n';
console_send_atcmd((char *)at_str, cmd_len);
vPortFree(at_str);
return len;
}
void cp_bt_open()
{
char at_str[] = {"AT+BTEN=1\r\n"};
console_send_atcmd((char *)at_str, strlen(at_str));
}
void cp_bt_close()
{
char at_str[] = {"AT+BTEN=0\r\n"};
console_send_atcmd((char *)at_str, strlen(at_str));
}
static void cp_wifi_event_handler( WIFIEvent_t * xEvent )
{
WIFIEventType_t xEventType = xEvent->xEventType;
char mac_str[32] = {0};
char *mac = NULL;
if (xEvent) {
mac = xEvent->xInfo.xAPStationConnected.ucMac;
sprintf(mac_str, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}
wps_connect_done = 0;
if (0) {
} else if (eWiFiEventConnected == xEventType) {// meter is sta
printf("\r\n The meter is connected to ap \r\n");
} else if (eWiFiEventDisconnected == xEventType) {// meter is sta
printf("\r\n The meter is disconnected from ap \r\n");
} else if (eWiFiEventAPStationConnected == xEventType) {// meter is ap
printf("\r\n The meter in AP is connected by sta %s \r\n", mac_str);
} else if (eWiFiEventAPStationDisconnected == xEventType) {// meter is ap
printf("\r\n The sta %s is disconnected from the meter \r\n", mac_str);
}
}
static BaseType_t cp_wifi_init()
{
int status;
WIFI_Context_init();
WIFI_RegisterEvent(eWiFiEventMax, cp_wifi_event_handler);
for (;;) {
status = mmcsd_wait_sdio_ready((int32_t)portMAX_DELAY);
if (status == MMCSD_HOST_PLUGED) {
printf("detect sdio device\r\n");
break;
}
}
return 0;
}
static void bt_set_support_carplay()
{
char cmd_str[64] = {0};
sprintf(cmd_str, "AT+PROFILE=33962\r\n");
console_send_atcmd(cmd_str, strlen(cmd_str));
}
int carlink_cp_bt_wifi_init()
{
carlink_ey_video_init();
cp_wifi_init();
console_register_cb(NULL, cp_bt_callback);
fsc_bt_main();
bt_set_support_carplay();
cp_bt_open();
cp_start_wlan();
printf("bt wlan init is ok\r\n");
return 0;
}

View File

@ -0,0 +1,262 @@
#include "os_adapt.h"
#include <FreeRTOS_POSIX.h>
#include <task.h>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdbool.h>
#include <stdio.h>
#include "board.h"
#include "timer.h"
#include "iot_wifi.h"
#include "mmcsd_core.h"
#include "carlink_utils.h"
#include "console.h"
#include "fsc_bt.h"
#include "iap.h"
#if !defined(USE_LWIP) || !USE_LWIP
#error "Carplay in freertos must use lwip!"
#endif
#include "ethernet.h"
#include "tcpip.h"
#include "lwip/apps/lwiperf.h"
#include "dhcp.h"
#include "carlink_video.h"
#include "mycommon.h"
static char g_cp_bt_mac[13] = {0};
static bool g_cp_bt_mac_ready = false;
static uint8_t cp_ap_ssid[64] = {"ap63011"};
static uint8_t cp_ap_passwd[16] = {"88888888"};
extern int wps_connect_done;
static const uint8_t ucIPAddress[4] = {192, 168, 13, 1};
static const uint8_t ucNetMask[4] = {255, 255, 255, 0};
static const uint8_t ucGatewayAddress[4] = {0, 0, 0, 0};
static int lwip_tcpip_init_done_flag = 0;
static struct netif gnetif[4];
int mmcsd_wait_sdio_ready(int32_t timeout);
static void cp_reset_wifi_ap_info(const char *prefex);
static void cp_start_wlan();
extern err_t dhcp_server_start(struct netif *netif, ip4_addr_t *start, ip4_addr_t *end);
extern err_t wlan_ethernetif_init(struct netif *netif);
#define lwip_ipv4_addr(addr) ((addr[0]) | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24))
static void tcpip_init_done(void *arg)
{
(void)arg;
//lwip_tcpip_init_done_flag = 1;
}
void lwiperf_report_cb_impl(void *arg, enum lwiperf_report_type report_type,
const ip_addr_t* local_addr, u16_t local_port, const ip_addr_t* remote_addr, u16_t remote_port,
u32_t bytes_transferred, u32_t ms_duration, u32_t bandwidth_kbitpsec)
{
(void)arg;
printf("lwiperf_report_cb_impl bytes:%d %d ms \r\n", bytes_transferred, ms_duration);
}
int cp_wlan_tcp_ip_is_ready()
{
return lwip_tcpip_init_done_flag;
}
static void cp_start_wlan()
{
const char *customer = "ark630hv100";
char ap_prefix[5] = {0};
ip4_addr_t ip_addr;
ip4_addr_t netmask;
ip4_addr_t gw;
ip4_addr_t dhcp_addr_start;
ip4_addr_t dhcp_addr_end;
while(!g_cp_bt_mac_ready) {
vTaskDelay(pdMS_TO_TICKS(10));
}
memcpy(ap_prefix, g_cp_bt_mac + 8, 4);
cp_reset_wifi_ap_info(ap_prefix);
start_ap(36, (const char *)cp_ap_ssid, (const char *)cp_ap_passwd, 1);
ip_addr.addr = lwip_ipv4_addr(ucIPAddress);
netmask.addr = lwip_ipv4_addr(ucNetMask);
gw.addr = lwip_ipv4_addr(ucGatewayAddress);
tcpip_init(tcpip_init_done, NULL);
netif_add(&gnetif[0],
#if LWIP_IPV4
&ip_addr, &netmask, &gw,
#endif
NULL, wlan_ethernetif_init, tcpip_input);
netif_set_default(&gnetif[0]);
uint8_t addr_start[4] = {192, 168, 13, 20};
uint8_t addr_end[4] = {192, 168, 13, 30};
dhcp_addr_start.addr = lwip_ipv4_addr(addr_start);
dhcp_addr_end.addr = lwip_ipv4_addr(addr_end);
dhcp_server_start(&gnetif[0], &dhcp_addr_start, &dhcp_addr_end);
netif_set_up(&gnetif[0]);
lwiperf_start_tcp_server_default(lwiperf_report_cb_impl, NULL);
lwip_tcpip_init_done_flag = 1;
}
static void cp_reset_wifi_ap_info(const char *prefex)
{
memset(cp_ap_ssid, 0, sizeof(cp_ap_ssid));
sprintf((char *)cp_ap_ssid, "AP630_%s", prefex);
g_link_info->wifi_passwd = cp_ap_passwd;
g_link_info->wifi_ssid = cp_ap_ssid;
g_link_info->wifi_channel = 36;
g_link_info->ip_v4_addr[0] = ucIPAddress[0];
g_link_info->ip_v4_addr[1] = ucIPAddress[1];
g_link_info->ip_v4_addr[2] = ucIPAddress[2];
g_link_info->ip_v4_addr[3] = ucIPAddress[3];
}
static void cp_bt_callback(char * cAtStr)
{
char* cmd_para = NULL;
printf("\r\nfsc_bt_callback_ec %s %d\r\n", cAtStr, strlen(cAtStr));
if (0) {
} else if (0 == strncmp(cAtStr, "+IAPDATA=", 9)) {
char ble_buf[256] = {0};
int data_len, i;
int data_str_len = (strlen(cAtStr) - 9);
cmd_para = cAtStr + 9;
data_len = data_str_len / 2;
string2hex(cmd_para, data_str_len, ble_buf, data_len);
for (i = 0; i < data_len; i++) {
printf("%02x ", ble_buf[i]);
}printf("\r\n");
iap2_read_data_proc(ble_buf, data_len);
} else if (0 == strncmp(cAtStr, "+GATTDATA=", 10)) {
} else if (0 == strncmp(cAtStr, "+GATTSTAT=1",11)) {
//ev.type = EC_EVENT_BT_DISCONNECT;
printf("TRACE[%s][%d]:EC_EVENT_BT_DISCONNECT\r\n",__func__ ,__LINE__);
} else if (0 == strncmp(cAtStr, "+GATTSTAT=3",11)) {
printf("TRACE[%s][%d]:EC_EVENT_BT_CONNECT\r\n",__func__ ,__LINE__);
} else if (0 == strncmp(cAtStr, "+ADDR=", 6)) {
char cmd_str[64] = {0};
sprintf(cmd_str, "AT+NAME=EC_%s\r\n", (cAtStr + 6));
printf("ADDR:%s\r\n", cAtStr + 6);
console_send_atcmd(cmd_str, strlen(cmd_str));//get mac addr
memset(cmd_str, 0, sizeof(cmd_str));
sprintf(cmd_str, "AT+LENAME=EC_%s\r\n", (cAtStr + 6));
console_send_atcmd(cmd_str, strlen(cmd_str));//get mac addr
g_cp_bt_mac_ready = true;
memcpy(g_cp_bt_mac, (cAtStr + 6), 12);
} else if (0 == strncmp(cAtStr, "+VER", 4)) {
char* cmd = "AT+ADDR\r\n";
console_send_atcmd(cmd, strlen(cmd));//get mac addr
} else if (0 == strncmp(cAtStr, "+NAME=", 6)) {
char cmd_str[64] = {0};
sprintf(cmd_str, "AT+LEADDR\r\n");
console_send_atcmd(cmd_str, strlen(cmd_str));//get LE addr
} else if (0 == strncmp(cAtStr, "+LEADDR=", 6)) {
char hexMacAddr[6] = {0};
char m_tmp_buf[64] = {0};
string2hex(&cAtStr[8], 12, hexMacAddr, sizeof(hexMacAddr));
sprintf(m_tmp_buf, "AT+ADVDATA=%s\r\n", hexMacAddr);
console_send_atcmd(m_tmp_buf, 19);
} else if (0 == strncmp(cAtStr, "+GATTSENT=", 10)) {
return;
} else if (0 == strncmp(cAtStr, "+IAPSTAT=3", 10)) {
carplay_start();
}
}
int iap_data_write(unsigned char *data, int len)
{
uint8_t *at_str = NULL, *at_str_ptr = NULL;
uint8_t *at_prefix = "AT+IAPSEND=";
int prefix_len = strlen((char *)at_prefix);
int cmd_len = (len * 2 + prefix_len + 2);
at_str = (uint8_t *)pvPortMalloc(cmd_len + 1);
memset(at_str, 0, cmd_len + 1);
if (NULL == at_str)
return -1;
at_str_ptr = at_str;
sprintf((char*)at_str_ptr, "%s", (char*)at_prefix);
at_str_ptr += prefix_len;
hex2str(data, len, (char *)at_str_ptr);
at_str_ptr += (len * 2);
*at_str_ptr++ = '\r';
*at_str_ptr++ = '\n';
console_send_atcmd((char *)at_str, cmd_len);
vPortFree(at_str);
return len;
}
static void cp_wifi_event_handler( WIFIEvent_t * xEvent )
{
WIFIEventType_t xEventType = xEvent->xEventType;
wps_connect_done = 0;
if (0) {
} else if (eWiFiEventConnected == xEventType) {// meter is sta
printf("\r\n The meter is connected to ap \r\n");
} else if (eWiFiEventDisconnected == xEventType) {// meter is sta
printf("\r\n The meter is disconnected from ap \r\n");
} else if (eWiFiEventAPStationConnected == xEventType) {// meter is ap
printf("\r\n The meter in AP is connected by sta %s \r\n", xEvent->xInfo.xAPStationConnected.ucMac);
} else if (eWiFiEventAPStationDisconnected == xEventType) {// meter is ap
printf("\r\n The sta %s is disconnected from the meter \r\n", xEvent->xInfo.xAPStationDisconnected.ucMac);
}
}
static BaseType_t cp_wifi_init()
{
int status;
WIFI_Context_init();
WIFI_RegisterEvent(eWiFiEventMax, cp_wifi_event_handler);
for (;;) {
status = mmcsd_wait_sdio_ready((int32_t)portMAX_DELAY);
if (status == MMCSD_HOST_PLUGED) {
printf("detect sdio device\r\n");
break;
}
}
return 0;
}
static void bt_set_support_carplay()
{
char cmd_str[64] = {0};
sprintf(cmd_str, "AT+PROFILE=33962\r\n");
console_send_atcmd(cmd_str, strlen(cmd_str));
}
int carlink_cp_bt_wifi_init()
{
carlink_ey_video_init();
cp_wifi_init();
console_register_cb(NULL, cp_bt_callback);
fsc_bt_main();
bt_set_support_carplay();
cp_start_wlan();
printf("bt wlan init is ok\r\n");
return 0;
}

View File

@ -632,7 +632,7 @@ int32_t ec_ble_write(void * data, uint32_t len);
int32_t ec_ble_read(void * data, uint32_t len); int32_t ec_ble_read(void * data, uint32_t len);
int32_t ec_ble_open(); int32_t ec_ble_open();
void ec_ble_close(); void ec_ble_close();
extern char strQrText[100]; extern char strQrText[200];
void* initECTiny(void* param) void* initECTiny(void* param)
{ {
char uuid[32] = {0}; char uuid[32] = {0};

View File

@ -3,288 +3,259 @@
#include "ECTypes.h" #include "ECTypes.h"
#define ECSDK_VERSION "1.0.10" #define ECSDK_VERSION "1.0.13.1"
typedef struct { typedef struct {
/**
* @brief 互联连接状态回调函数
* @param status 互联连接状态
* @param type 互联连接类型
* @note 此函数是非常重要的回调函数。它会返回整个互联的状态。
* 有部分互联功能接口比如EC_startMirror()/EC_enableDownloadPhoneAppHud()/EC_enableDownloadPhoneAppHud() 等,
* 都需要 status为 EC_CONNECT_STATUS_CONNECT_SUCCEED 时,调用才能生效。
* 因为这些接口都是在互联成功之后(ECTiny与手机app建立了通讯)才能发指令给手机app对应功能才能开启。
*/
void (*onECConnectStatus)(ECConnectedStatus status, ECConnectedType type); void (*onECConnectStatus)(ECConnectedStatus status, ECConnectedType type);
void (*onMirrorStatus)(ECMirrorStatus status);
/** /**
* @brief Called when EasyConnected status changed. * @brief 投屏状态
* * @param status 互联投屏状态
* @param status The changed EasyConnected message. */
void (*onMirrorStatus)(ECMirrorStatus status);
/**
* @brief 互联状态变更通知
* @param status 变更的状态
*/ */
void (*onECStatusMessage)(ECStatusMessage status); void (*onECStatusMessage)(ECStatusMessage status);
/** /**
* @brief Called when the phone app sends down HUD information. * @brief 手机下发HUD信息时回调
* * @param data HUD信息
* @param data HUD information.
*/ */
void (*onPhoneAppHUD)(const ECNavigationHudInfo *data); void (*onPhoneAppHUD)(const ECNavigationHudInfo *data);
/** /**
* @brief Called when the phone app sends down HUD Road Junction Picture. * @brief 手机下发道路引导图时回调
* @param data * @param data
*/ */
void (*onPhoneAppHUDRoadJunctionPicture)(const ECHudRoadJunctionPictureInfo* data); void (*onPhoneAppHUDRoadJunctionPicture)(const ECHudRoadJunctionPictureInfo* data);
/* /**
* @brief Called when phone app tell the music info. * @brief 手机音乐信息变化时回调
* * @param data
* @param data The information of music.
*/ */
void (*onPhoneAppMusicInfo)(const ECAppMusicInfo *data); void (*onPhoneAppMusicInfo)(const ECAppMusicInfo *data);
/** /**
* @brief Called when the phone app sends down some information. * @brief 手机下发app信息时回调
* * @param data app信息
* @param data Buffer of app information. * @param length app信息长度
* * @note data 是json字符串, 包括手机类型、系统版本、ip地址等。
* @param length Buffer length. * ECTiny 与 手机app建立通讯后会回调此函数
*
* @note data is json string, the fields includes os, osVersion and ip.
* Called when ECSDK::openTransport succeed.
*/ */
void (*onPhoneAppInfo)(const void *data, uint32_t length); void (*onPhoneAppInfo)(const void *data, uint32_t length);
/** /**
* @brief Called when ECSDK wants car to do call operations(dial or hang up) via Bluetooth. * @brief 需要拨打或者挂断蓝牙电话时回调
* * @param type 操作类型
* @param type Operation type. * @param name 电话拨打的姓名
* * @param number 电话号码
* @param name The person's name of corresponding number. * @note 受限于Android/iOS系统的权限在车机上点击互联投屏的过来的拨打电话ECTiny无法完成电话的拨打和接听操作因此需要依赖于车机系统的蓝牙模块完成。
* * 车机的投屏界面上点击拨打蓝牙电话时,此回调函数会把拨打的用户姓名和电话号码传到车机上,由车机蓝牙模块完成电话的拨打
* @param number Phone numbers. * 1.需要车机端作为蓝牙免提设备Hand-Free-Device
* * 2.亿连的蓝牙电话功能需要在车机和手机的HFP保持连接后才可以正常启用。
* @note Phone app is not able to dial or hang up automatically due to the latest system access limitation,
* however, car is able to do it via Bluetooth. Therefore, ECSDK moves the call operations
* to car, which can dial or hang up when this method is called.
*/ */
void (*onCallAction)(ECCallType type, const char *name, const char *number); void (*onCallAction)(ECCallType type, const char *name, const char *number);
/** /**
* @brief Called when bulk data is received. * @brief 接收手机端发送的数据块
*
* @param data Buffer of bulk data. * @param data Buffer of bulk data.
*
* @param length Buffer length. * @param length Buffer length.
*
*/ */
void (*onBulkDataReceived)(const void *data, uint32_t length); void (*onBulkDataReceived)(const void *data, uint32_t length);
/** /**
* @brief onRealMirrorSizeChanged * @brief 投屏状态变更
* @param realWidth * @param ECVideoInfo 视屏参数
* @param realHeight * @note 投屏的实际宽高、横竖屏切换时回调此函数
*
* \note The actual size of the projection screen does not equal the size of the video stream in some cases.
* The surrounding area is filled with black. This message calls back the actual size of the projection screen
*/ */
void (*onMirrorInfoChanged)(const ECVideoInfo *info); void (*onMirrorInfoChanged)(const ECVideoInfo *info);
/** /**
* @brief Called when the license authorization failed. After this interface was called, * @brief 鉴权失败时回调此函数。ECTiny功能全部不可用
* all connections would be forced closed. * @param errCode 主要用于亿连后台进行排查的错误码,无需关心具体值。
* * @param errMsg 错误信息。
* @param errCode Error code. * @note 此回调函数需要处理,当出现激活失败时给与提示。
* * 该回调一般出现在互联建立过程中出现时ECTiny会在内部进行释放动作。
* @param errMsg Error message. * ECTiny使用者需要保证合法的激活校验流程之后重新初始化ECSDK方可使用。
*/ */
void (*onLicenseAuthFail)(int32_t errCode, const char *errMsg); void (*onLicenseAuthFail)(int32_t errCode, const char *errMsg);
/** /**
* @brief Called when the license authorization succeed. * @brief 鉴权成时回调此函数
* * @param code 正常错误码,无需关心具体值。
* @param code success code. The code can gain specific meaning by ECAuthSuccessCode. * @param msg 正常激活log信息。
* * @note 该接口回调一般出现在互联建立过程中在首次进行激活手机IME号备案激活回调会包含剩余数量等信息SDK使用者可根据具体的使用场景进行相关展示。
* @param msg success information.
*
* @param msg the description information.
*
*/ */
void (*onLicenseAuthSuccess)(int32_t code, const char *msg); void (*onLicenseAuthSuccess)(int32_t code, const char *msg);
/** /**
* @brief Called when registered command was triggered by VR. * @brief 当注册的控车指令被vr激活时回调
* * @param carCmd 触发的控车指令
* @param carCmd The triggered command. * @see EC_registerCarCmds()
*
* @note Voice control can be implemented with this method by VR.
*
* @see ECSDK::registerCarCmds
*/ */
void (*onCarCmdNotified)(const ECCarCmd *carCmd); void (*onCarCmdNotified)(const ECCarCmd *carCmd);
/** /**
* @brief Called when phone app request the HU to start input. * @brief 监听手机端文字输入
* * @param info 当前需要输入的文字信息包括输入类型文字、数字、电话号码等最大输入长度默认的文字最大行数以及Enter键默认的显示效果及动作。
* @param info relevant parameters about the input. * @note 监听手机端输入法的开始输入状态,并传递此次输入文字的相关信息。
*/ */
void (*onInputStart)(const ECInputInfo *info); void (*onInputStart)(const ECInputInfo *info);
/** /**
* @brief Called when phone app request the HU to cancel input. * @note 监听手机端输入法的结束或者取消的状态,此时车机端键盘也需要取消。
*/ */
void (*onInputCancel)(); void (*onInputCancel)();
/** /**
* @brief Called when phone app tell the selection of input. * @brief 监听手机端输入光标位置、选择状态信息
* @param start 光标开始的位置
* @param stop 光标结束的位置
* @note 监听手机端输入文字的选择状态,光标状态,车机端并做状态展示。仅对安卓手机有效,苹果手机互联无此回调。
*/ */
void (*onInputSelection)(int32_t start, int32_t stop); void (*onInputSelection)(int32_t start, int32_t stop);
/** /**
* @brief Called when phone app tell the text of input. * @brief 同步当前手机端的文字信息到车机
* @param text 当前手机端输入的文字信息。
* @note 如在手机端也对输入框内的文字进行输入,需要同步至车机端,保持车机端和手机端的状态同步。
*/ */
void (*onInputText)(const char *text); void (*onInputText)(const char *text);
/** /**
* @brief Called when phone app send the text of VR or TTS. * @brief 对识别内容进行展示
* @param info 手机端语音引擎识别后的文字内容信息。
*/ */
void (*onVRTextReceived)(const ECVRTextInfo *info); void (*onVRTextReceived)(const ECVRTextInfo *info);
/** /**
* @brief Called when phone app tell the page list. * @brief 获取快捷方式列表信息
* * @param pages 返回快捷方式的数组,参考 ECTypes.h 的 ECPageInfo 定义主要包含图标的编号、名称、icon的唯一标识信息
* @param pages Array of the struct ECPageInfo. * @param length pages数组长度
* * @note ECPageInfo::page 字段标识了每一个快捷方式的唯一标识,通过该标识,可以实现两个主要的功能:
* @param length The length of the array. * 1. 通过page编号可以通过调用 ECSDK::queryPageIcon 获取快捷方式的图标资源。
* 2. 通过page编号可以通过调用 ECSDK::openAppPage 实现快捷打开对应指定手机APP页面
*/ */
void (*onPageListReceived)(const ECPageInfo *pages, int32_t length); void (*onPageListReceived)(const ECPageInfo *pages, int32_t length);
/** /**
* @brief Called when phone app tell the icons. * @brief 手机app回调图标信息
* * @param icons 返回快捷方式图标资源的数组,参考 ECTypes.h 的 ECIconInfo 定义主要包含icon的编号、icon的格式、icon图像数据、icon的数据长度
* @param icons Array of the struct ECIconInfo. * @param length icons的数组长度。
*
* @param length The length of the array.
*/ */
void (*onPageIconReceived)(const ECIconInfo *icons, int32_t length); void (*onPageIconReceived)(const ECIconInfo *icons, int32_t length);
/** /**
* @brief Called when phone app tell weather. * @brief 回调天气信息
* * @param data 天气信息字符串
* @param data Buffer of weather information. * @param length 字符串长度
* * @note data 是一个固定格式的json字符串
* @param length Buffer length.
*
* @note data pointed to a json string buffer.
*/ */
void (*onWeatherReceived)(const char *data, int32_t length); void (*onWeatherReceived)(const char *data, int32_t length);
/** /**
* @brief Called when phone app tell vr tips. * @brief 请求VR提醒文字
* * @param data VR文字
* @param data Buffer of tips information. * @param length data长度
* * @note data是一个json字符串
* @param length Buffer length. * 在使用车机端本地语音助手时,一般需要有一些常驻提示类的使用帮助,这些文字主要通过手机端传输至车机端,由车机端系统完成展示。
*
* @note data pointed to a json string buffer.
*/ */
void (*onVRTipsReceived)(const char *data, int32_t length); void (*onVRTipsReceived)(const char *data, int32_t length);
/** /**
* @brief Called when the app requests networking * @brief 手机app发送到车机的请求组网
* * @param clientInfo 手机app的相关信息
* @param clientInfo Mobile phone related information * @note 此回调用于BLE组网
*
* @note
*/ */
void (*onRequestBuildNet)(const ECBTClientInfo *clientInfo); void (*onRequestBuildNet)(const ECBTClientInfo *clientInfo);
/** /**
* @brief Called when canceling networking * @brief 手机app取消组网时回调
* * @note 此回调用于BLE组网
* @note
*/ */
void (*onRequestBuildNetCancel)(); void (*onRequestBuildNetCancel)();
/** /**
* @brief Called when networking is completed * @brief 手机app组网完成时回调
* * @note 此回调用于BLE组网
* @note
*/ */
void (*onPhoneBuildNetFinish)(); void (*onPhoneBuildNetFinish)(const char* ip);
/** /**
* @brief Called when app sends AP information * @brief 手机app通知车机手机创建的ap信息
* * @param netDeviceInfo AP信息
* @param netDeviceInfo AP information * @note 此回调用于BLE组网
*
* @note
*/ */
void (*onPhoneAPInfo)(const ECBTNetInfo* netDeviceInfo); void (*onPhoneAPInfo)(const ECBTNetInfo* netDeviceInfo);
/** /**
* @brief Called when mobile phone has a notification message. * @brief 收到手机消息通知时回调
* @param notification * @param notification 消息通知
* @note 允许下发手机消息通知功能开启后,当收到短信、微信等消息时,此函数会回调消息到车机
* @see EC_requestPhoneNotification()
*/ */
void (*onPhoneNotification)(const ECPhoneNotification* notification); void (*onPhoneNotification)(const ECPhoneNotification* notification);
/** /**
* @brief Called when the phone app sends down HUD lane guidance Picture. * @brief HUD道路引导图
* @param notification * @param notification 引导图信息
* @note 下发HUD导航功能开启后导航时有道路引导图时此函数会回调
* @see EC_enableDownloadPhoneAppHud()
*/ */
void (*onPhoneAppHUDLaneGuidancePicture)(const ECHudLaneGuidancePictureInfo * data); void (*onPhoneAppHUDLaneGuidancePicture)(const ECHudLaneGuidancePictureInfo * data);
/** /**
* @brief Called when checkOTAUpdate was called, it will tell the result of checkOTAUpdate. * @brief 检测更新函数 EC_checkOTAUpdate()调用后, 此回调函数返回结果
* * @param downloadableSoftwares 可下载的软件包数组
* @param downloadableSoftwares It pointer to a array of ECOTAUpdateSoftware, which is downloadable software. * @param downloadableLength 可下载的软件包数组大小, 如果 downloadableLength < 0 标识出现错误, 错误码参考ECOTAUpdateErrorCode.
* * @param downloadedSoftwares 已下载的软件包数组
* @param downloadableLength The length of the downloadable array, if downloadableLength < 0, means check occur error, downloadableLength is error value of ECOTAUpdateErrorCode. * @param downloadedLength 已下载的软件包数组大小
*
* @param downloadedSoftwares It pointer to a array of ECOTAUpdateSoftware, which is downloaded software.
*
* @param downloadedLength The length of the downloaded array.
*/ */
void (*onOTAUpdateCheckResult)(const ECOTAUpdateSoftware* downloadableSoftwares, const int32_t downloadableLength, const ECOTAUpdateSoftware* downloadedSoftwares, const uint32_t downloadedLength); void (*onOTAUpdateCheckResult)(const ECOTAUpdateSoftware* downloadableSoftwares, const int32_t downloadableLength, const ECOTAUpdateSoftware* downloadedSoftwares, const uint32_t downloadedLength);
/** /**
* @brief Called when remote downloadable software has been downloaded to phone. * @brief 有软件包请求下载手机时回调
* * @param downloadableSoftwares 可下载的软件包数组
* @param downloadableSoftwares It pointer to a array of ECOTAUpdateSoftware, which has been in phone, can be downloaded from phone to HU. * @param downloadableLength 可下载软件包数组大小
* * @note 软件包已存在手机,请求下载到车机
* @param downloadableLength The length of the downloadable array.
*/ */
void (*onOTAUpdateRequestDownload)(const ECOTAUpdateSoftware* downloadableSoftwares, const uint32_t downloadableLength); void (*onOTAUpdateRequestDownload)(const ECOTAUpdateSoftware* downloadableSoftwares, const uint32_t downloadableLength);
/** /**
* @brief Called when startOTAUpdate is called, it will notify the progress of downloading. * @brief EC_startOTAUpdate()调用之后, 此回调函数会回调下载进度
* * @param downloadingSoftwareId 下载的软件ID
* @param downloadingSoftwareId The id of the downloading software. * @param progress 下载的进度
* * @param softwareLeftTime 剩余下载时间
* @param progress The progress of the downloading software,which is a percentage. * @param otaLeftTime OTA剩余时间
*
* @param softwareLeftTime The left time of the downloading software.
*
* @param otaLeftTime The left time of all the specified software by startOTAUpdate.
*/ */
void (*onOTAUpdateProgress)(const char* downloadingSoftwareId, float progress, uint32_t softwareLeftTime, uint32_t otaLeftTime); void (*onOTAUpdateProgress)(const char* downloadingSoftwareId, float progress, uint32_t softwareLeftTime, uint32_t otaLeftTime);
/** /**
* @brief Called when startOTAUpdate is called, it will notify software is downloaded. * @brief EC_startOTAUpdate()调用之后, 下载完成时回调此函数
* * @param downloadedSoftwareId 下载的软件ID
* @param downloadedSoftwareId The id of the downloaded software. * @param md5Path md5文件路径
* * @param packagePath 升级包路径
* @param md5Path The md5 file path. * @param iconPath 图标路径
* * @param leftSoftwareNum 剩余下载数量
* @param packagePath The software path.
*
* @param iconPath The icon path.
*
* @param leftSoftwareNum The amount of software remaining to be downloaded.
*/ */
void (*onOTAUpdateCompleted)(const char* downloadedSoftwareId, const char* md5Path, const char* packagePath, const char* iconPath, uint32_t leftSoftwareNum); void (*onOTAUpdateCompleted)(const char* downloadedSoftwareId, const char* md5Path, const char* packagePath, const char* iconPath, uint32_t leftSoftwareNum);
/** /**
* @brief Called when checkOTAUpdate or startOTAUpdate failed. * @brief EC_checkOTAUpdate() 或者 EC_startOTAUpdate() 调用过程出错回调此函数
* * @param errCode 错误码, 参考ECOTAUpdateErrorCode.
* @param errCode error code, see ECOTAUpdateErrorCode. * @param softwarId 软件id
*
* @param softwarId the id of software.
*/ */
void (*onOTAUpdateError)(int32_t errCode, const char* softwareId); void (*onOTAUpdateError)(int32_t errCode, const char* softwareId);
@ -350,67 +321,502 @@ ECConfigHandle EC_createECConfig();
void EC_destroyECConfig(ECConfigHandle config); void EC_destroyECConfig(ECConfigHandle config);
void EC_setBaseConfig(ECConfigHandle config,const char *uuid, const char *version,const char *writableDir); void EC_setBaseConfig(ECConfigHandle config,const char *uuid, const char *version,const char *writableDir);
void EC_setCommonConfig(ECConfigHandle config, const char *cfgName, const char *value); void EC_setCommonConfig(ECConfigHandle config, const char *cfgName, const char *value);
/**
* @brief 设置 ECTiny 连接的app版本
* @param type 0:国内版; 1:海外版
*/
void EC_setLinkPhoneApp(ECConfigHandle config,int32_t type);
void EC_setCommonConfig1(ECConfigHandle config, const char *cfgName, int32_t value); void EC_setCommonConfig1(ECConfigHandle config, const char *cfgName, int32_t value);
// This function must be called after the EC_start() function.
int32_t EC_resetECConfig(const char* config);
/**
* @brief ECTiny 初始化函数
* @param config 项目配置
* @param listener 回调接口
* @return EC_OK 为成功,其余值为失败。此返回值一般不处理
* @note 此接口为互联必调用的接口。
* 1.除了调用 EC_setBaseConfig() 设置基本的运行配置之外config 一般不需要额外配置。
* 2.listener 的生命周期大于 ECTiny 生命周期。即 listener 在 EC_initialize() 调用前就需要初始化EC_release()之后才可以释放。
*/
int32_t EC_initialize(ECConfigHandle config, IECCallBack *listener); int32_t EC_initialize(ECConfigHandle config, IECCallBack *listener);
/**
* @brief ECTiny 释放函数
* @return EC_OK 为成功,其余值为失败。此返回值一般不处理
* @note 此函数调用后,后面声明的函数调用都会失效。
* 没有互联时ECTiny线程处于block或者waiting状态占用系统资源不多所以ECTiny的一般使用场景不需要调用此函数。
*/
int32_t EC_release(); int32_t EC_release();
/**
* @brief 设置ECTiny日志
* @param level 日志级别。调试时设置成EC_LOG_LEVEL_ALL生产时设置成EC_LOG_LEVEL_ERROR或者其他高级别
* @param type 日志输出类型,设置成 EC_LOG_OUT_STD标准输出。其余类型暂不支持。
* @param logDirectory 日志保存位置,暂不支持
* @param module 日志模块通常设置成EC_LOG_MODULE_SDK | EC_LOG_MODULE_APP
* @return EC_OK 为成功,其余值为失败。此返回值一般不处理
* @note 此接口为互联必调用的接口。
*/
int32_t EC_setLogInfo(const ECLogLevel level,const ECLogOutputType type,const char *logDirectory, int32_t module); int32_t EC_setLogInfo(const ECLogLevel level,const ECLogOutputType type,const char *logDirectory, int32_t module);
/**
* @return 获取 ECTiny 版本号
*/
const char* EC_getVersion(); const char* EC_getVersion();
/**
* @return 获取 ECTiny 升级版本号
*/
int32_t EC_getVersionCode(); int32_t EC_getVersionCode();
/**
* @brief 开启互联服务
* @return EC_OK 为成功,其余值为失败。此返回值一般不处理
* @note 此接口为互联必调用的接口。
*/
int32_t EC_start(); int32_t EC_start();
/**
* @brief 停止互联服务
* @return EC_OK 为成功,其余值为失败。此返回值一般不处理
* @note 没有投屏的情况下, ECTiny线程出于阻塞状态占用的系统资源很少。
* 一般使用场景,调用 EC_start() 之后,不需要调用 EC_stop()。
*/
int32_t EC_stop(); int32_t EC_stop();
/**
* @brief 绑定文件读写设备
* @param handle 文件操作接口
* @return EC_OK 为成功,其余值为失败。此返回值一般不处理
* @note 对于某些 RTOS 系统,没有标准的文件操作接口,因此需要实现此接口,把基本文件操作的接口传给 ECTiny。
* ECTiny会使用此接口读写license和OTA。
*/
int32_t EC_bindAccessFile(IECAccessFile *handle); int32_t EC_bindAccessFile(IECAccessFile *handle);
/**
* @brief 绑定usb设备
* @param type 互联类型
* @param dev usb设备操作接口
* @return EC_OK 为成功,其余值为失败。此返回值一般不处理
* @note 绑定usb设备读写操作用于实现usb互联。
* @see EC_unbindDevice()
*/
int32_t EC_bindUSBDevice(ECTransportType type, IECAccessDevice *dev); int32_t EC_bindUSBDevice(ECTransportType type, IECAccessDevice *dev);
/**
* @brief 绑定wifi互联ip
* @param type 互联类型
* @param ip 对端ip地址
* @return EC_OK 为成功,其余值为失败。此返回值一般不处理
* @note 此函数调用之后, ECTiny会直接连接ip进行互联。
* @see EC_unbindDevice()
*/
int32_t EC_bindWIFIDevice(ECTransportType type, const char *ip); int32_t EC_bindWIFIDevice(ECTransportType type, const char *ip);
/**
* @brief 释放绑定的设备
* @param type 互联类型
* @return EC_OK 为成功,其余值为失败。此返回值一般不处理
* @note 此函数与 EC_bindUSBDevice()EC_bindWIFIDevice(),有绑定与解绑定关系。
*/
int32_t EC_unbindDevice(ECTransportType type); int32_t EC_unbindDevice(ECTransportType type);
/**
* @brief 绑定HID设备
* @param dev HID设备
* @return EC_OK 为成功,其余值为失败。此返回值一般不处理
* @see EC_unBindHidDevice()
*/
int32_t EC_bindHidDevice(IECHidAccessDev* dev); int32_t EC_bindHidDevice(IECHidAccessDev* dev);
/**
* @brief 解除HID设备绑定
* @return EC_OK 为成功,其余值为失败。此返回值一般不处理
* @see EC_bindHidDevice()
*/
int32_t EC_unBindHidDevice(); int32_t EC_unBindHidDevice();
/**
* @brief 绑定蓝牙ble设备操作接口
* @param ioHandle 蓝牙ble设备操作接口
* @return EC_OK 为成功,其余值为失败。此返回值一般不处理
* @note 此接口用于BLE组网方式的互联。
* @see EC_unBindBTDevice()
*/
int32_t EC_bindBTDevice( IECAccessDevice* ioHandle); int32_t EC_bindBTDevice( IECAccessDevice* ioHandle);
/**
* @brief 蓝牙ble设备解绑定
* @return EC_OK 为成功,其余值为失败。此返回值一般不处理
* @see EC_bindBTDevice()
*/
int32_t EC_unBindBTDevice(); int32_t EC_unBindBTDevice();
/**
* @brief 设置投屏参数
* @param mirrorCfg 投屏参数
* @return EC_OK 为成功,其余值为失败。此返回值一般不处理
* @note 此接口为互联必执行的接口。
*/
int32_t EC_setMirrorConfig(const ECMirrorConfig *mirrorCfg); int32_t EC_setMirrorConfig(const ECMirrorConfig *mirrorCfg);
/**
* @brief 设置解码显示设备
* @param video 解码显示器
* @return EC_OK 为成功,其余值为失败。此返回值一般不处理
* @note 解码显示器 IECVideoPlayer 通过此接口注册给 ECTiny之后由 ECTiny主动调用解码器的开始和停止。
*/
int32_t EC_setVideoPlayer(IECVideoPlayer* video); int32_t EC_setVideoPlayer(IECVideoPlayer* video);
/**
* @brief 设置音频播放器
* @param audio 音频播放器
* @return EC_OK 为成功,其余值为失败。此返回值一般不处理
* @note 声音数据走usb或者wifi时才需要设置此接口。一般项目声音都是走蓝牙a2dp不需要设置此接口。
*/
int32_t EC_setAudioPlayer(IECAudioPlayer* audio); int32_t EC_setAudioPlayer(IECAudioPlayer* audio);
/**
* @brief 设置录音设备
* @param audioRecorde 录音设备
* @return EC_OK 为成功,其余值为失败。此返回值一般不处理
* @note 需要手机app回声降噪的项目才需要设置此接口。
*/
int32_t EC_setAudioRecorder(IECAudioRecorder* audioRecorde); int32_t EC_setAudioRecorder(IECAudioRecorder* audioRecorde);
/**
* @brief 仪表wifi状态通知接口
* @param action 仪表wifi模式ap/sta。 目前此值不做要求,填写此枚举任意值即可
* @param netInfo 网络状态。ECNetWorkInfo::state 必须填写,其余字段不需要填。
* @return EC_OK 为成功,其余值为失败。此返回值一般不处理
* @note 仪表/车机wifi发生变化时通过此接口通知给 ECTiny。wifi连接此接口必调用
*/
int32_t EC_notifyWifiStateChanged(ECWifiStateAction action, const ECNetWorkInfo* netInfo); int32_t EC_notifyWifiStateChanged(ECWifiStateAction action, const ECNetWorkInfo* netInfo);
/**
* @brief 请求组网接口
* @param phoneID 手机id
* @param rly 组网信息
* @return EC_OK 为成功,其余值为失败。此返回值一般不处理
* @note 只有BLE组网的连接方式才用到此接口。
*/
int32_t EC_setRequestBuildNetRly(const char *phoneID, const ECBTRequestBuildNetRly *rly); int32_t EC_setRequestBuildNetRly(const char *phoneID, const ECBTRequestBuildNetRly *rly);
/**
* @brief 仪表ip地址上报给手机
* @param info 仪表网络信息
* @param num 仪表网络信息数量
* @return EC_OK 为成功,其余值为失败。此返回值一般不处理
* @note 只有BLE组网的连接方式才用到此接口。
*/
int32_t EC_setNetInterfaceInfo(const ECNetInterfaceInfo *info,const int32_t num); int32_t EC_setNetInterfaceInfo(const ECNetInterfaceInfo *info,const int32_t num);
/**
* @brief 开始投屏
* @return EC_OK 为成功,其余值为失败。此返回值一般不处理
* @note 此接口为互联必执行的接口。
* 此接口调用后手机app会把 H264 数据发送给 ECTiny。 ECTiny会自动调用 IECVideoPlayer 解码器解码显示。
* onECConnectStatus 回调函数status==EC_CONNECT_STATUS_CONNECT_SUCCEED 时才可以调用此接口,否则无效。
* @see EC_stopMirror()
*/
int32_t EC_startMirror(); int32_t EC_startMirror();
/**
* @brief 停止投屏
* @note 此接口为互联必执行的接口。
* @see EC_startMirror()
*/
void EC_stopMirror(); void EC_stopMirror();
/**
* @brief 暂停/开启 投屏
* @return EC_OK 为成功,其余值为失败。此返回值一般不处理
* @note 目前不调用。调用 EC_startMirror()/EC_stopMirror()
*/
int32_t EC_pauseMirror(); int32_t EC_pauseMirror();
int32_t EC_resumeMirror(); int32_t EC_resumeMirror();
int32_t EC_sendTouchEvent(const ECTouchEventData *touch, ECTouchEventType type);
int32_t EC_sendBtnEvent(int32_t btnCode, int32_t type);
int32_t EC_stopPhoneNavigation();
int32_t EC_stopPhoneVR();
int32_t EC_uploadNightModeStatus(uint32_t isNightModeOn);
int32_t EC_uploadDrivingStatus(ECDrivingStatus status);
int32_t EC_enableDownloadPhoneAppAudio(uint32_t supportType, uint32_t autoChangeToBT);
void EC_disableDownloadPhoneAppAudio();
int32_t EC_enableDownloadPhoneAppHud(uint32_t supportFunction);
void EC_disableDownloadPhoneAppHud();
int32_t EC_setConnectedBTAddress(const char *carBtMac, const char *phoneBtMac);
int32_t EC_sendCarBluetooth(const char *name, const char *adddress, const char *pin);
int32_t EC_openAppPage(int32_t page);
int32_t EC_queryGPS(uint32_t* status, ECGPSInfo* gps);
int32_t EC_queryTime(uint64_t *gmtTime, uint64_t *localTime, char *timeZone, uint32_t len, char* dateTime, uint32_t dateTimeLen);
int32_t EC_sendCarStatus(ECCarStatusType carStatus, ECCarStatusValue value);
int32_t EC_registerCarCmds(const ECCarCmd *carCmds, uint32_t length);
int32_t EC_playCarTTS(const char *text, uint32_t level);
int32_t EC_registerSimilarSoundingWords(const char *data, uint32_t length);
int32_t EC_sendInputText(const char* text);
int32_t EC_sendInputAction(int32_t actionId, int32_t keyCode);
int32_t EC_sendInputSelection(int32_t start, int32_t stop);
int32_t EC_queryPageList();
int32_t EC_queryPageIcon(int32_t* pages, int32_t length);
int32_t EC_queryWeather();
int32_t EC_queryVRTips();
const char* EC_generateQRCodeUrl(ECQRInfo* info);
int32_t EC_requestPhoneNotification(int32_t enable);
/**
* @brief 发送触控消息
* @param touch 触控数据
* @param type 触控类型
* @return EC_OK 为成功,其余值为失败。此返回值一般不处理
* @note 发送仪表/车机屏幕的触控消息给手机app互联程序会映射到手机的坐标让手机app做出响应。
*/
int32_t EC_sendTouchEvent(const ECTouchEventData *touch, ECTouchEventType type);
/**
* @brief 发送按键消息
* @param btnCode 按键键值取值于ECBtnCode
* @param type 按键类型取值与ECBtnEventType
* @return EC_OK 为成功,其余值为失败。此返回值一般不处理
* @note 发送按键消息给手机app让手机作出响应。
*/
int32_t EC_sendBtnEvent(int32_t btnCode, int32_t type);
/**
* @brief 结束手机导航
* @return EC_OK 为成功,其余值为失败。此返回值一般不处理
*/
int32_t EC_stopPhoneNavigation();
/**
* @brief 结束手机vr语音
* @return EC_OK 为成功,其余值为失败。此返回值一般不处理
*/
int32_t EC_stopPhoneVR();
/**
* @brief 上传汽车的夜间模式信息到手机
* @param isNightModeOn 1:夜间模式; 0: 非夜间模式
* @return EC_OK 为成功,其余值为失败。此返回值一般不处理
* @note 手机app的显示模式设置为自动时此接口才能让手机app响应
*/
int32_t EC_uploadNightModeStatus(uint32_t isNightModeOn);
/**
* @brief 上传汽车的驾驶信息到手机
* @param status 驾驶状态
* @return EC_OK 为成功,其余值为失败。此返回值一般不处理
*/
int32_t EC_uploadDrivingStatus(ECDrivingStatus status);
/**
* @brief 允许手机下发声音数据到仪表/车机
* @param supportType 下载的声音类型,取值于 ECAudioType 类型,可以通过或运算下载多种声音
* @param autoChangeToBT 是否启用蓝牙优先的策略,当蓝牙连接后,声音自动走蓝牙通道。
* 也可通过该接口控制手机端蓝牙连接提示框的弹出当该参数设置为false后手机端不再弹出连接蓝牙提示框。
* @return EC_OK 为成功,其余值为失败。此返回值一般不处理
* @note 只有在连接层成功建立后,接口调用才能成功。参考 onECConnectStatus()
* 该接口调用之后手机app才会下传相应声音停止音频下传接口为EC_disableDownloadPhoneAppAudio()
*/
int32_t EC_enableDownloadPhoneAppAudio(uint32_t supportType, uint32_t autoChangeToBT);
/**
* @brief 停止手机下发声音数据
*/
void EC_disableDownloadPhoneAppAudio();
/**
* @brief 允许手机下发HUD导航信息
* @param supportFunction hud导航功能取值于 ECAPPHUDSupportFunction 类型可以通过或运算开启多种hud功能
* @return EC_OK 为成功,其余值为失败。此返回值一般不处理
* @note 只有在连接层成功建立后,接口调用才能成功。参考 onECConnectStatus()
* 此接口调用一次即可生效
*/
int32_t EC_enableDownloadPhoneAppHud(uint32_t supportFunction);
/**
* @brief 停止手机下发HUD导航信息
*/
void EC_disableDownloadPhoneAppHud();
/**
* @brief 设置连接的蓝牙
* @param carBtMac 车机自己的蓝牙地址
* @param phoneBtMac 车机连接的蓝牙Mac地址
* @return EC_OK 为成功,其余值为失败。此返回值一般不处理
* @note 此接口的目的是用于对比手机和车机两者连接的蓝牙是不是对方。受限于手机系统限制,无法取得手机的蓝牙物理地址,目前此接口功能已经失效。
*/
int32_t EC_setConnectedBTAddress(const char *carBtMac, const char *phoneBtMac);
/**
* @brief 发送车机的蓝牙信息给手机
* @param name 蓝牙名称
* @param adddress 蓝牙地址
* @param pin 蓝牙pin码
* @return EC_OK 为成功,其余值为失败。此返回值一般不处理
*/
int32_t EC_sendCarBluetooth(const char *name, const char *adddress, const char *pin);
/**
* @brief 打开手机界面
* @param page 快速访问手机APP的相关界面或功能如导航、音乐、对讲等具体取值参考ECAppPage
* @return EC_OK 为成功,其余值为失败。
* @note 该接口主要用于如下场景,譬如车机端系统桌面集成快捷按钮,可直达互联的指定页面。
*/
int32_t EC_openAppPage(int32_t page);
/**
* @brief 查询GPS信息
* @param status 当前的请求结果是否有效0无效其余值有效
* @param gps GPS信息
* @return EC_OK 为成功,其余值为失败。
* @note 该接口主要用于车机需要使用到手机端GPS的场景请求网络当前位置。
*/
int32_t EC_queryGPS(uint32_t* status, ECGPSInfo* gps);
/**
* @brief 查询手机时间
* @param gmtTime 返回GMT(UTC)时间,单位毫秒。
* @param localTime 返回当前时区的时间,单位毫秒
* @param timeZone 返回当前的时区的字符串。
* @param len 当前时区字符串的长度
* @param dateTime 返回手机app当前时间字符串
* @param dateTimeLen 手机app当前时间字符串长度
* @return EC_OK 为成功,其余值为失败。
* @note 由于GMT时间涉及到系统函数和时区的计算建议直接使用后两个参数获取当前时间字符串然后解析字符串获取到时间
*/
int32_t EC_queryTime(uint64_t *gmtTime, uint64_t *localTime, char *timeZone, uint32_t len, char* dateTime, uint32_t dateTimeLen);
/**
* @brief 同步车机状态到手机
* @param carStatus 车机状态类型
* @param value 部分status需要携带状态值
* @return EC_OK 为成功,其余值为失败。
* @note 部分场景下需要将车机的部分状态信息通知到手机APP手机APP需要根据状态做互联的相关逻辑处理。
* 如手机APP可根据行车状态在不同的地区做不同的使用限制。该接口主要用于行车模式功能等功能。
*/
int32_t EC_sendCarStatus(ECCarStatusType carStatus, ECCarStatusValue value);
/**
* @brief 注册控车指令
* @param carCmds 控车指令
* .type : 指令类型,是一个全局指令或是一个和页面绑定的指令,见枚举 ECCarCmdEFFECTType 。
* .id : 指令id每个需要识别的指令都有一个唯一的标识。
* .cmd : 期望语音识别的指令,当时一个全局指令时,可以是正则表达式;如"(打开|开启)空调",等价于"打开空调" "开启空调";而当是一个和页面绑定的指令词,不支持正则表达式,仅支持明确的指令,如"放大地图"。
* .vrText : 当前成功匹配的语义,仅用于当 IECCallback::onCarCmdNotified 回调时,可根据匹配的内容处理相关的动作。
* .pauseMusic : 该参数仅用于 ECSDK::registerCarCmds ,告知手机如果触发语音识别时,是否需要暂停当前正在播放的音乐。
* .responser : 语音指令执行的结果是由车机端播报还是由手机端播报。0 车机端播报1手机端播报。
* .thresholdLevel : 可选项默认值为0由手机端指定默认的门限值 范围参考值 1~9999识别门限值值越大识别率越低误唤醒率越低开发者在使用语音识别功能时可在项目中调试设置合适的值。该参数仅在 type= EC_CAR_CMD_TYPE_EFFECTIVE_PAGE 生效;
* @param length 注册的指令列表的长度。
* @return EC_OK 为成功,其余值为失败。
* @note 当发起语音识别后通过手机端的VR引擎识别后会转化后具体的指令通过回调接口 IECCallback::onCarCmdNotified 响应,须在此进行相关处理。
*/
int32_t EC_registerCarCmds(const ECCarCmd *carCmds, uint32_t length);
/**
* @brief 播放指定的文字
* @param text 文字信息
* @param level 优先级0~10优先级越高被播放的优先级也越高。
* @return EC_OK 为成功,其余值为失败。
* @note 与手机的通讯建立成功后把需要播报的文字传输至手机APP。
* 如果车机端配置了 ECSDK::enableDownloadPhoneAppAudio 通过车机端播放手机APP音频此时音频将以TTS类型通过USB/wifi传输车机端。
*/
int32_t EC_playCarTTS(const char *text, uint32_t level);
/**
* @brief 注册近似指令
* @param data 需要注册的近音词组数据格式为JSON格式字符串
* {
* words:
* [
* ["词1", ..., "词m"], ///< 数据类型为string数组近音词集合数组中的第一个词为显示词。
* ...
* ["词a", ..., "词n"] ///< 数据类型为string数组近音词集合数组中的第一个词为显示词。
* ]
* }
* @param length 注册的指令Json字符串的长度。
* @return EC_OK 为成功,其余值为失败。
* @note 该接口主要是对 EC_registerCarCmds() 接口的补充,常见使用场景提高语音控车指令的准确度,如“上身车窗”、“上升车窗”可以正确的被识别为同一个含义。
*/
int32_t EC_registerSimilarSoundingWords(const char *data, uint32_t length);
/**
* @brief 发送给手机端当前已输入的文字
* @param text 当前输入的车机端文字
* @return EC_OK 为成功,其余值为失败。
* @note 此函数用于车机键盘输入功能
*/
int32_t EC_sendInputText(const char* text);
/**
* @brief 发送给手机端键盘按键事件
* @param actionId 当前输入的动作
* @param keyCode 键值
* @return EC_OK 为成功,其余值为失败。
* @note 如车机端输入法点击Enter键此时需把事件发送给手机端。所有keycode及ActionId对安卓手机都有效
* 苹果手机仅响应actionid=0 keycode=4苹果手机处理为隐藏手机端输入法并把输入状态置为inActive状态。
* 此函数用于车机键盘输入功能
*/
int32_t EC_sendInputAction(int32_t actionId, int32_t keyCode);
/**
* @brief 发送给手机端当前光标位置及选中状态
* @param start 光标开始的位置。
* @param stop 光标结束的位置。
* @return EC_OK 为成功,其余值为失败。
* @note 如果车机端的光标产生变化,需把对应状态发送至手机端同步。仅对安卓手机有效,苹果手机互联无此回调。
* 此函数用于车机键盘输入功能
*/
int32_t EC_sendInputSelection(int32_t start, int32_t stop);
/**
* @brief 获取快捷方式列表信息
* @return EC_OK 为成功,其余值为失败。
* @note ECTiny与手机app传输建立之后。通过 IECCallback::onPageListReceived 回调接口完快捷方式列表信息的接收。
*/
int32_t EC_queryPageList();
/**
* @brief 获取快捷方式图标资源
* @param pages 待请求的page编号的数组通过 EC_queryPageList 获取。
* @param length page编号的数组长度。
* @return EC_OK 为成功,其余值为失败。
* @note ECTiny与手机app传输建立之后。通过 IECCallback::onPageIconReceived 回调接口完快捷方式图标资源的的接收。
* 为了避免重复的请求占用带宽资源以及做到车机端的快捷方式快速显示车机端系统需要做好缓存策略对icon的资源信息做到增量更新
* 通过每次互联后 EC_queryPageList 获取最新的列表信息,然后比对车机端缓存的列表信息,仅对增量的资源进行请求更新;
*/
int32_t EC_queryPageIcon(int32_t* pages, int32_t length);
/**
* @brief 查询天气
* @return EC_OK 为成功,其余值为失败。
* @note 查询结果通过 IECCallback::onWeatherReceived 回调函数返回
*/
int32_t EC_queryWeather();
/**
* @brief 车机端语音提醒轮播
* @return EC_OK 为成功,其余值为失败。
* @note 在使用车机端本地语音助手时,一般需要有一些常驻提示类的使用帮助,这些文字主要通过手机端传输至车机端,由车机端系统完成展示。
*/
int32_t EC_queryVRTips();
/**
* @brief 生成二维码url
* @param info 二维码信息
* @return EC_OK 为成功,其余值为失败。
*/
const char* EC_generateQRCodeUrl(ECQRInfo* info);
/**
* @brief 允许手机下发手机消息
* @param enable 0禁止 1允许
* @return EC_OK 为成功,其余值为失败。
*/
int32_t EC_requestPhoneNotification(uint32_t enable);
/**
* @brief 检测OTA升级
* @param cfg ota配置
* @param language 语言
* @param mode ota升级模式
* @return EC_OK 为成功,其余值为失败。
*/
int32_t EC_checkOTAUpdate(const ECOTAConfig* cfg, const ECLanguage language, const ECOTAUpdateCheckMode mode); int32_t EC_checkOTAUpdate(const ECOTAConfig* cfg, const ECLanguage language, const ECOTAUpdateCheckMode mode);
/**
* @brief 开始OTA升级
* @param softwareIds 需要升级的软件id
* @param softwareNum 需要升级的软件id数量
* @return EC_OK 为成功,其余值为失败。
*/
int32_t EC_startOTAUpdate(const char** softwareIds, const int32_t softwareNum); int32_t EC_startOTAUpdate(const char** softwareIds, const int32_t softwareNum);
/**
* @brief 停止OTA升级
*/
void EC_stopOTAUpdate(); void EC_stopOTAUpdate();
/**
* @brief 开启iperf服务端
* @param ip
* @param port
* @return
* @note 简单实现的iperf功能。车机/仪表进行iperf测试时建议使用标准iperf
*/
int32_t EC_startIperfTcpServer(const char* ip, int port); int32_t EC_startIperfTcpServer(const char* ip, int port);
void EC_stopIperfTcpServer(); void EC_stopIperfTcpServer();
#endif #endif

View File

@ -194,6 +194,18 @@ enum ECProjectFlavor
}; };
typedef enum ECProjectFlavor ECProjectFlavor; typedef enum ECProjectFlavor ECProjectFlavor;
/**
* @enum ECAuthCheckMode
*
*/
enum ECAuthCheckMode {
EC_AUTH_CHECK_DEFAULT = 0, ///< default check auth on phone
EC_AUTH_CHECK_ON_CAR_NETWORK = 1, ///< check auth on car network
EC_AUTH_CHECK_SCAN_CODE_TO_ACTIVATE_FOR_SUDING = 2, ///< scan the code to activate the certificate for suding
EC_AUTH_CHECK_SCAN_CODE_TO_ACTIVATE = 4, ///< scan the code to activate the certificate
};
typedef enum ECAuthCheckMode ECAuthCheckMode;
/** /**
* @struct ECAuthentication * @struct ECAuthentication
* *
@ -205,7 +217,7 @@ struct ECAuthentication
char pwd[1024]; ///< the specific password for authentication powered by Carbit. char pwd[1024]; ///< the specific password for authentication powered by Carbit.
char versionName[1024]; ///< the version name of EasyConn. char versionName[1024]; ///< the version name of EasyConn.
uint32_t versionCode; ///< the version code of EasyConn. uint32_t versionCode; ///< the version code of EasyConn.
uint32_t autoAuthViaCar; ///< specify whether make automatic authentication via car's network. uint32_t authCheckMode; ///< the value of auth check model refer to ECAuthCheckMode.
ECProjectFlavor flavor; ///< specify the HU Project market for sale,SDK will carry a flavor by default.see enum ECProjectFlavor in ECTypes.h ECProjectFlavor flavor; ///< specify the HU Project market for sale,SDK will carry a flavor by default.see enum ECProjectFlavor in ECTypes.h
char reserve[256]; ///< reserve char reserve[256]; ///< reserve
}; };
@ -373,11 +385,22 @@ struct ECOptions
ECMirrorMode mirrorMode; ///< tell the app of connected phone which mirror mode would be used. ECMirrorMode mirrorMode; ///< tell the app of connected phone which mirror mode would be used.
uint32_t bluetoothPolicy; ///< the policy of A2DP message phone sent to the car. uint32_t bluetoothPolicy; ///< the policy of A2DP message phone sent to the car.
uint32_t disableShowCallInfo; ///< true:Don't show call info uint32_t disableShowCallInfo; ///< true:Don't show call info
uint32_t disablePageInRVMap; ///< Block display of some page
uint32_t socketTimeoutPeriod; ///< socket timeout period in seconds uint32_t socketTimeoutPeriod; ///< socket timeout period in seconds
char reserve[256]; ///< reserve char reserve[256]; ///< reserve
}; };
typedef struct ECOptions ECOptions; typedef struct ECOptions ECOptions;
/**
* @enum ECDisablePageInRVMap
*
*/
enum ECDisablePageInRVMap {
EC_DISABLE_PAGEINRVMAP_CALLPHONE = 0x0001, ///< Block call display
EC_DISABLE_PAGEINRVMAP_MUSIC = 0x0002, ///< Block music display
EC_DISABLE_PAGEINRVMAP_MESSAGE = 0x0004, ///< Block message display
};
/** /**
* @enum ECTransportType * @enum ECTransportType
* *

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -2,5 +2,7 @@
#define _CARLINK_EC_H_ #define _CARLINK_EC_H_
int carlink_ec_init(int argc,char ** argv); int carlink_ec_init(int argc,char ** argv);
void carlink_ec_enable(int enable);
#endif #endif

View File

@ -29,9 +29,12 @@
#include "wifi_conf.h" #include "wifi_conf.h"
#include "carlink_common.h" #include "carlink_common.h"
#define DEV_NAME_PREFIX "AP630_CARLINK"
static char g_cp_bt_mac[13] = {0}; static char g_cp_bt_mac[13] = {0};
static bool g_cp_bt_mac_ready = false; static bool g_cp_bt_mac_ready = false;
static uint8_t carlink_p2p_name[64] = {0};
static uint8_t carlink_ap_ssid[64] = {"ap63011"}; static uint8_t carlink_ap_ssid[64] = {"ap63011"};
static uint8_t carlink_ap_passwd[16] = {"88888888"}; static uint8_t carlink_ap_passwd[16] = {"88888888"};
static uint8_t carlink_wifi_mac[32] = {0}; static uint8_t carlink_wifi_mac[32] = {0};
@ -65,6 +68,17 @@ extern err_t dhcp_server_start(struct netif *netif, ip4_addr_t *start, ip4_addr_
extern err_t wlan_ethernetif_init(struct netif *netif); extern err_t wlan_ethernetif_init(struct netif *netif);
#define lwip_ipv4_addr(addr) ((addr[0]) | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24)) #define lwip_ipv4_addr(addr) ((addr[0]) | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24))
const char *carlink_get_bt_mac()
{
if (!g_cp_bt_mac_ready)
return NULL;
return (const char *)g_cp_bt_mac;
}
const char *carlink_get_wifi_p2p_name()
{
return (const char *)carlink_p2p_name;
}
const char *carlink_get_wifi_ssid() const char *carlink_get_wifi_ssid()
{ {
@ -74,7 +88,7 @@ const char *carlink_get_wifi_ssid()
const char *carlink_get_wifi_mac() const char *carlink_get_wifi_mac()
{ {
wifi_get_mac_address(carlink_wifi_mac); wifi_get_mac_address((char *)carlink_wifi_mac);
return (const char *)carlink_wifi_mac; return (const char *)carlink_wifi_mac;
} }
@ -173,7 +187,11 @@ static void carlink_start_wlan()
} }
memcpy(ap_prefix, g_cp_bt_mac + 8, 4); memcpy(ap_prefix, g_cp_bt_mac + 8, 4);
carlink_reset_wifi_ap_info(ap_prefix); carlink_reset_wifi_ap_info(ap_prefix);
#if (CARLINK_EC)
start_p2p((const char *)carlink_p2p_name, (const char *)carlink_ap_ssid, (const char *)carlink_ap_passwd);
#else
start_ap(36, (const char *)carlink_ap_ssid, (const char *)carlink_ap_passwd, 1); start_ap(36, (const char *)carlink_ap_ssid, (const char *)carlink_ap_passwd, 1);
#endif
ip_addr.addr = lwip_ipv4_addr(ucIPAddress); ip_addr.addr = lwip_ipv4_addr(ucIPAddress);
netmask.addr = lwip_ipv4_addr(ucNetMask); netmask.addr = lwip_ipv4_addr(ucNetMask);
@ -194,18 +212,113 @@ static void carlink_start_wlan()
dhcp_server_start(&gnetif[0], &dhcp_addr_start, &dhcp_addr_end); dhcp_server_start(&gnetif[0], &dhcp_addr_start, &dhcp_addr_end);
netif_set_up(&gnetif[0]); //netif_set_up(&gnetif[0]);
lwiperf_start_tcp_server_default(carlink_lwiperf_report_cb_impl, NULL); lwiperf_start_tcp_server_default(carlink_lwiperf_report_cb_impl, NULL);
lwip_tcpip_init_done_flag = 1; lwip_tcpip_init_done_flag = 1;
carlink_carplay_add_vendor_ie(); carlink_carplay_add_vendor_ie();
} }
void cp_wlan_start(void){
netif_set_up(&gnetif[0]);
}
static void dump_ip_addr(const char *msg, const ip_addr_t *server_addr)
{
printf("%s %d.%d.%d.%d \r\n", msg,
ip4_addr1_16(ip_2_ip4(server_addr)), ip4_addr2_16(ip_2_ip4(server_addr)), ip4_addr3_16(ip_2_ip4(server_addr)), ip4_addr4_16(ip_2_ip4(server_addr)));
}
static void dhcp_client_status_callback(struct netif *netif, int status, const ip_addr_t *server_addr)
{
if (&gnetif[0] == netif) {
dump_ip_addr("dhcp server ip :", (const ip_addr_t *)server_addr);
dump_ip_addr("dhcp client ip :", (const ip_addr_t *)&netif->ip_addr);
dump_ip_addr("dhcp client netmask:", (const ip_addr_t *)&netif->netmask);
dump_ip_addr("dhcp client gw :", (const ip_addr_t *)&netif->gw);
}
}
int start_sta_ext(const char* ssid, const char* passwd, char need_passwd)
{
int ret = -1;
ip4_addr_t ip_addr;
ip4_addr_t netmask;
ip4_addr_t gw;
ret = start_sta(ssid, passwd, need_passwd);
if (ret != 0) {
printf("start wifi sta failed\r\n");
return ret;
}
if (lwip_tcpip_init_done_flag) {
netif_remove(&gnetif[0]);
netif_add(&gnetif[0],
#if LWIP_IPV4
&ip_addr, &netmask, &gw,
#endif
NULL, wlan_ethernetif_init, tcpip_input);
netif_set_default(&gnetif[0]);
dhcp_regisger_status_callback(dhcp_client_status_callback);
netif_set_up(&gnetif[0]);
dhcp_start(&gnetif[0]);
}
return ret;
}
int __restart_p2p(const char *dev_name, const char *ssid, const char *passwd)
{
int ret = -1;
ip4_addr_t ip_addr;
ip4_addr_t netmask;
ip4_addr_t gw;
ip_addr.addr = lwip_ipv4_addr(ucIPAddress);
netmask.addr = lwip_ipv4_addr(ucNetMask);
gw.addr = lwip_ipv4_addr(ucGatewayAddress);
ret = start_p2p(dev_name, ssid, passwd);
if (ret != 0) {
printf("restart wifi p2p failed\r\n");
return ret;
}
if (!lwip_tcpip_init_done_flag) {
printf("lwip tcpip is not inited\r\n");
return ret;
}
dhcp_stop(&gnetif[0]);
netif_remove(&gnetif[0]);
netif_add(&gnetif[0],
#if LWIP_IPV4
&ip_addr, &netmask, &gw,
#endif
NULL, wlan_ethernetif_init, tcpip_input);
netif_set_up(&gnetif[0]);
ret = 0;
return ret;
}
int restart_p2p()
{
if (!g_cp_bt_mac_ready) {
printf("bt is not ready at %s", __func__);
return -1;
}
return __restart_p2p((const char *)carlink_p2p_name, (const char *)carlink_ap_ssid, (const char *)carlink_ap_passwd);
}
static void carlink_reset_wifi_ap_info(const char *prefex) static void carlink_reset_wifi_ap_info(const char *prefex)
{ {
if (prefex) { if (prefex) {
memset(carlink_ap_ssid, 0, sizeof(carlink_ap_ssid)); memset(carlink_ap_ssid, 0, sizeof(carlink_ap_ssid));
sprintf((char *)carlink_ap_ssid, "AP630_CARLINK_%s", prefex); sprintf((char *)carlink_ap_ssid, "%s_%s", DEV_NAME_PREFIX, prefex);
memset(carlink_p2p_name, 0, sizeof(carlink_p2p_name));
sprintf((char *)carlink_p2p_name, "DIRECT-%s_p2p_%s", DEV_NAME_PREFIX, prefex);//do not delete "DIRECT-" !!!
} }
} }
@ -256,11 +369,11 @@ static void carlink_bt_callback(char * cAtStr)
carlink_notify_event(&ev); carlink_notify_event(&ev);
} else if (0 == strncmp(cAtStr, "+ADDR=", 6)) { } else if (0 == strncmp(cAtStr, "+ADDR=", 6)) {
char cmd_str[64] = {0}; char cmd_str[64] = {0};
sprintf(cmd_str, "AT+NAME=AP630_CARLINK_%s\r\n", (cAtStr + 6 + 8)); sprintf(cmd_str, "AT+NAME=%s_%s\r\n", DEV_NAME_PREFIX, (cAtStr + 6 + 8));
printf("ADDR:%s\r\n", cAtStr + 6); printf("ADDR:%s\r\n", cAtStr + 6);
console_send_atcmd(cmd_str, strlen(cmd_str));//get mac addr console_send_atcmd(cmd_str, strlen(cmd_str));//get mac addr
memset(cmd_str, 0, sizeof(cmd_str)); memset(cmd_str, 0, sizeof(cmd_str));
sprintf(cmd_str, "AT+LENAME=AP630_CARLINK_%s\r\n", (cAtStr + 6 + 8)); sprintf(cmd_str, "AT+LENAME=%s_%s\r\n", DEV_NAME_PREFIX, (cAtStr + 6 + 8));
console_send_atcmd(cmd_str, strlen(cmd_str));//get mac addr console_send_atcmd(cmd_str, strlen(cmd_str));//get mac addr
memcpy(g_cp_bt_mac, (cAtStr + 6), 12); memcpy(g_cp_bt_mac, (cAtStr + 6), 12);
carlink_carplay_ie_replace_bt_mac(cAtStr + 6, 12); carlink_carplay_ie_replace_bt_mac(cAtStr + 6, 12);
@ -396,7 +509,7 @@ static void carlink_wifi_event_handler( WIFIEvent_t * xEvent )
char *mac = NULL; char *mac = NULL;
if (xEvent) { if (xEvent) {
mac = xEvent->xInfo.xAPStationConnected.ucMac; mac = (char *)xEvent->xInfo.xAPStationConnected.ucMac;
sprintf(mac_str, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); sprintf(mac_str, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
} }
@ -414,6 +527,40 @@ static void carlink_wifi_event_handler( WIFIEvent_t * xEvent )
} }
} }
#if ( ipconfigUSE_DHCP_HOOK != 0 )
eDHCPCallbackAnswer_t xApplicationDHCPHook( eDHCPCallbackPhase_t eDHCPPhase,
uint32_t ulIPAddress )
{
eDHCPCallbackAnswer_t eReturn;
char g_ip_str[32] = {0};
sprintf(g_ip_str, "%d.%d.%d.%d\r\n", (ulIPAddress >> 0) & 0xFF,
(ulIPAddress >> 8) & 0xFF, (ulIPAddress >> 16) & 0xFF, (ulIPAddress >> 24) & 0xFF);
printf("\r\n eDHCPPhase:%d ulIPAddress:%s state:%d \r\n", eDHCPPhase, g_ip_str, getDhcpClientState());
if (getDhcpClientState() == 0)
return eDHCPStopNoChanges;
switch( eDHCPPhase )
{
case eDHCPPhaseFinished:
eReturn = eDHCPContinue;
break;
case eDHCPPhasePreDiscover :
eReturn = eDHCPContinue;
break;
case eDHCPPhasePreRequest :
eReturn = eDHCPContinue;
break;
default :
eReturn = eDHCPContinue;
break;
}
return eReturn;
}
#endif
static BaseType_t carlink_wifi_init() static BaseType_t carlink_wifi_init()
{ {
int status; int status;

View File

@ -25,6 +25,7 @@ static pthread_mutex_t carlink_com_locker =
.xAttr = { .iType = 0 } .xAttr = { .iType = 0 }
}; };
void pthread_key_system_init();
void carlink_rfcomm_data_read_hook(void* buf, int len) void carlink_rfcomm_data_read_hook(void* buf, int len)
{ {
@ -41,7 +42,7 @@ void carlink_rfcomm_data_read_hook(void* buf, int len)
void carlink_notify_event(struct carlink_event *ev) void carlink_notify_event(struct carlink_event *ev)
{ {
if (-1 != ev->type && NULL != carlink_event_queue) { if (CARLINK_EVENT_NONE != ev->type && NULL != carlink_event_queue) {
xQueueSend(carlink_event_queue, ev, 0); xQueueSend(carlink_event_queue, ev, 0);
} }
} }

View File

@ -16,13 +16,14 @@ typedef enum
CARLINK_ANDROID_AUTO = 5, CARLINK_ANDROID_AUTO = 5,
CARLINK_ECLINK = 0x06, CARLINK_ECLINK = 0x06,
CARLINK_CARPLAY_WIRELESS, CARLINK_CARPLAY_WIRELESS,
CARLINK_AUTO_WIRELESS CARLINK_AUTO_WIRELESS,
CARLINK_ECLINK_WIRELESS,
}CARLink_TYPE; }CARLink_TYPE;
#define CARLINK_VIDEO_WIDTH 800 #define CARLINK_VIDEO_WIDTH 800
#define CARLINK_VIDEO_HEIGHT 480 #define CARLINK_VIDEO_HEIGHT 380
@ -72,6 +73,8 @@ int carlink_wlan_tcp_ip_is_ready();
void carlink_bt_open(); void carlink_bt_open();
void carlink_bt_close(); void carlink_bt_close();
void carlink_restart_bt_wifi(); void carlink_restart_bt_wifi();
const char *carlink_get_bt_mac();
const char *carlink_get_wifi_p2p_name();
const char *carlink_get_wifi_ssid(); const char *carlink_get_wifi_ssid();
const char *carlink_get_wifi_passwd(); const char *carlink_get_wifi_passwd();
const char *carlink_get_wifi_mac(); const char *carlink_get_wifi_mac();

View File

@ -25,6 +25,15 @@ static int g_disp_x = 0, g_disp_y = 0, g_disp_width = LCD_WIDTH, g_disp_height =
static int g_video_width = LCD_WIDTH, g_video_height = LCD_HEIGHT, g_video_fps = 30; static int g_video_width = LCD_WIDTH, g_video_height = LCD_HEIGHT, g_video_fps = 30;
static int g_hide_carlink_flag = 0; static int g_hide_carlink_flag = 0;
static int g_active_video_x = 0, g_active_video_y = 0;
void set_carlink_active_video_info(int x, int y)//for android auto
{
g_active_video_x = x;
g_active_video_y = y;
}
void set_carlink_video_info(int w, int h, int fps) void set_carlink_video_info(int w, int h, int fps)
{ {
g_video_width = w; g_video_width = w;
@ -145,7 +154,7 @@ void set_h264_frame_free(video_frame_s* frame)
} }
xSemaphoreGive(frame_list_mutex); xSemaphoreGive(frame_list_mutex);
} }
uint8_t map_flag = 0;
static void h264_decode_proc(void *pvParameters) static void h264_decode_proc(void *pvParameters)
{ {
MFCHandle *handle = NULL; MFCHandle *handle = NULL;
@ -197,6 +206,11 @@ static void h264_decode_proc(void *pvParameters)
} }
if (g_hide_carlink_flag == 0) { if (g_hide_carlink_flag == 0) {
if(map_flag)
map_flag = 0;
printf("Exit navigation =========\r\n ");
Set_sys_wifi(0);
//printf("start carplay or andrord auto .\r\n");
ark_lcd_osd_enable(LCD_VIDEO_LAYER, 0); ark_lcd_osd_enable(LCD_VIDEO_LAYER, 0);
ark_lcd_osd_enable(LCD_UI_LAYER, 1); ark_lcd_osd_enable(LCD_UI_LAYER, 1);
} }
@ -236,15 +250,16 @@ static void h264_decode_proc(void *pvParameters)
//continue; //continue;
for(i = 0; i < outBuf.num; i++) { for(i = 0; i < outBuf.num; i++) {
int active_offset = 0;
align_width = outBuf.frameWidth; align_width = outBuf.frameWidth;
align_height = outBuf.frameHeight; align_height = outBuf.frameHeight;
if(!(align_width && align_height)) if(!(align_width && align_height))
continue; continue;
active_offset = g_active_video_y * align_width;
yaddr = outBuf.buffer[i].yBusAddress; yaddr = outBuf.buffer[i].yBusAddress + active_offset + g_active_video_x;
uaddr = yaddr + align_width * align_height; uaddr = outBuf.buffer[i].yBusAddress + align_width * align_height + active_offset / 2 + g_active_video_x;
vaddr = yaddr + align_width * align_height * 5/4; vaddr = 0;//yaddr + align_width * align_height * 5/4;
if (carlink_lcd_take == 0) { if (carlink_lcd_take == 0) {
carlink_lcd_take = 1; carlink_lcd_take = 1;
@ -295,6 +310,8 @@ static void h264_decode_proc(void *pvParameters)
info.y = g_disp_y; info.y = g_disp_y;
info.width = g_disp_width; info.width = g_disp_width;
info.height = g_disp_height; info.height = g_disp_height;
if (g_active_video_x != 0)
info.stride = outBuf.frameWidth;
if (info.format == LCD_OSD_FORAMT_YUV420) if (info.format == LCD_OSD_FORAMT_YUV420)
ark_lcd_set_osd_yuv420_mode(LCD_VIDEO_LAYER, LCD_OSD_Y_UV420); ark_lcd_set_osd_yuv420_mode(LCD_VIDEO_LAYER, LCD_OSD_Y_UV420);
@ -306,7 +323,8 @@ static void h264_decode_proc(void *pvParameters)
ark_lcd_set_osd_info_atomic(LCD_VIDEO_LAYER, &info); ark_lcd_set_osd_info_atomic(LCD_VIDEO_LAYER, &info);
ark_lcd_osd_enable(LCD_VIDEO_LAYER, 1); ark_lcd_osd_enable(LCD_VIDEO_LAYER, 1);
ark_lcd_set_osd_sync(LCD_VIDEO_LAYER); ark_lcd_set_osd_sync(LCD_VIDEO_LAYER);
ark_lcd_osd_enable(LCD_UI_LAYER, 0); Set_sys_wifi(1);
// ark_lcd_osd_enable(LCD_UI_LAYER, 0);
ark_lcd_set_osd_sync(LCD_UI_LAYER); ark_lcd_set_osd_sync(LCD_UI_LAYER);
vVideoDisplayBufRender(dstaddr); vVideoDisplayBufRender(dstaddr);
if (outBuf.num > 1) {// for apple h264 if (outBuf.num > 1) {// for apple h264
@ -317,6 +335,13 @@ static void h264_decode_proc(void *pvParameters)
if (delta_ts > 0) if (delta_ts > 0)
vTaskDelay(pdMS_TO_TICKS(delta_ts)); vTaskDelay(pdMS_TO_TICKS(delta_ts));
} }
if(!map_flag){
// printf("###############################################.\r\n");
request_UI("maps:");
map_flag = 1;
// printf("###############################################.\r\n");
}
} }
} }
//printf("all use:%d ms dec:%ld ms all ts:%ld ms\r\n", (get_timer(0) - ts) / 1000, dec_ts, (get_timer(0) - all_ts) / 1000); //printf("all use:%d ms dec:%ld ms all ts:%ld ms\r\n", (get_timer(0) - ts) / 1000, dec_ts, (get_timer(0) - all_ts) / 1000);

View File

@ -29,7 +29,7 @@ int get_carlink_video_fps(void);
void set_carlink_video_info(int w, int h, int fps);//set h264 video stream info from phone void set_carlink_video_info(int w, int h, int fps);//set h264 video stream info from phone
void set_carlink_display_info(int x, int y, int w, int h);//set carlink show area in lcd void set_carlink_display_info(int x, int y, int w, int h);//set carlink show area in lcd
void set_carlink_display_state(int on); // on: 1.display carlink; 0. display native ui void set_carlink_display_state(int on); // on: 1.display carlink; 0. display native ui
void set_carlink_active_video_info(int x, int y);//for android auto
#define WRITE_BE32(ptr, val) \ #define WRITE_BE32(ptr, val) \
do { \ do { \

View File

@ -580,6 +580,33 @@ static void usb_read_thread(void *para)
status = usb_wait_stor_dev_pluged(portMAX_DELAY); status = usb_wait_stor_dev_pluged(portMAX_DELAY);
if (status == USB_DEV_PLUGED) { if (status == USB_DEV_PLUGED) {
printf("usb dev inserted.\n"); printf("usb dev inserted.\n");
FF_FILE *fp = ff_fopen("/usb/update.bin", "rb");
if (fp) {
UpFileHeader header;
SysInfo *sysinfo = GetSysInfo();
if (ff_fread(&header, 1, sizeof(header), fp) == sizeof(header)) {
if (header.magic != MKTAG('U', 'P', 'D', 'F')) {
printf("Wrong update file, don't update.\n");
} else {
if (header.checksum != sysinfo->app_checksum) {
printf("found different update file(0x%x-0x%x), update...\n",
header.checksum, sysinfo->app_checksum);
sysinfo->update_media_type = UPDATE_MEDIA_USB;
sysinfo->update_status = UPDATE_STATUS_START;
SaveSysInfo();
hub_usb_dev_reset();
vTaskDelay(500);
wdt_cpu_reboot();
} else {
printf("the update file version is same, don't update.\n");
}
}
};
ff_fclose(fp);
} else {
printf("open update.bin fail.\n");
}
/*printf("usb dev inserted.\n");
#ifdef OTA_UPDATE_SUPPORT #ifdef OTA_UPDATE_SUPPORT
FF_FILE *fp = ff_fopen("/usb/update.bin", "rb"); FF_FILE *fp = ff_fopen("/usb/update.bin", "rb");
if (fp) { if (fp) {
@ -635,7 +662,7 @@ static void usb_read_thread(void *para)
} else { } else {
printf("open update.bin fail.\n"); printf("open update.bin fail.\n");
} }
#endif #endif*/
} else if (status == USB_DEV_UNPLUGED) { } else if (status == USB_DEV_UNPLUGED) {
printf("usb removed.\n"); printf("usb removed.\n");
} }
@ -710,7 +737,7 @@ void awtk_thread(void *data)
/* can demo */ /* can demo */
//can_demo(); can_demo();
/* read sd card demo */ /* read sd card demo */
#ifdef SDMMC_SUPPORT #ifdef SDMMC_SUPPORT
@ -785,13 +812,15 @@ void awtk_thread(void *data)
extern int gui_app_start(int lcd_w, int lcd_h); extern int gui_app_start(int lcd_w, int lcd_h);
gui_app_start (OSD_WIDTH, OSD_HEIGHT); gui_app_start (OSD_WIDTH, OSD_HEIGHT);
#endif #endif
// float cell = 0;
// static float cell_value = 0;
// static uint8_t cell_count = 0;
while(1) { while(1) {
#ifdef TASK_STATUS_MONITOR #ifdef TASK_STATUS_MONITOR
static uint32_t idletick = 0; static uint32_t idletick = 0;
uint8_t CPU_RunInfo[1024]; uint8_t CPU_RunInfo[1024];
if (xTaskGetTickCount() - idletick > configTICK_RATE_HZ * 10) { if (xTaskGetTickCount() - idletick > configTICK_RATE_HZ * 10) {
memset(CPU_RunInfo,0,1024); memset(CPU_RunInfo,0,1024);
vTaskList((char *)&CPU_RunInfo); //获取任务运行时间信息 vTaskList((char *)&CPU_RunInfo); //获取任务运行时间信息
@ -807,6 +836,25 @@ void awtk_thread(void *data)
idletick = xTaskGetTickCount(); idletick = xTaskGetTickCount();
} }
#endif #endif
/*if ((xTaskGetTickCount() - idletick > configTICK_RATE_HZ*3) && (Get_sys_power_on_self_test() == 100)) {
adc_light = adc_get_channel_value(ADC_CH_AUX2);//光感
adc_voltage = adc_get_channel_value(ADC_CH_AUX3);//电压
// DEBUG_PRINT("adc_light = %d ,adc_voltage = %d . ",adc_light,adc_voltage);
idletick = xTaskGetTickCount();
cell = adc_voltage_calculation();
// DEBUG_PRINT("cell %lf .\r\n",cell);
// cell_value += cell;
// cell_count++;
// if(cell_count>=8){
// cell_value = cell_value/cell_count;
// Set_sys_voltage(cell_value);
// cell_value = 0;
// cell_count = 0;
// }
Set_sys_voltage(cell);
}*/
vTaskDelay(pdMS_TO_TICKS(10)); /*Just to let the system breath*/ vTaskDelay(pdMS_TO_TICKS(10)); /*Just to let the system breath*/
} }
} }

View File

@ -0,0 +1,162 @@
#include "awtk.h"
#include "conversation_protocol.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "chip.h"
#include "board.h"
#include "serial.h"
#include "sysinfo.h"
#include "user_data.h"
#include "data_port.h"
#include "universal.h"
#define MAX_ENTRIES 100 // 假设最大条目数为100
// 定义电话本条目结构体
typedef struct {
char name[50];
char phone[20];
} PhoneBookEntry;
PhoneBookEntry phoneBook[MAX_ENTRIES]; // 存储电话本信息的数组
int numEntries = 0; // 当前电话本条目数量
void Phone_book_analysis(void){
/*int numEntries = 0; // 当前电话本条目数量
// 模拟收到的电话本信息字符串
char data[] = "+PBDATA=1<FF>JACK<FF>12345678911";
// 解析字符串并提取姓名和电话号码
char *token = strtok(data, "<FF>"); // 使用<FF>作为分隔符
if (token != NULL) {
token = strtok(NULL, "<FF>"); // 跳过第一个分隔符
if (token != NULL) {
strcpy(phoneBook[numEntries].name, token);
token = strtok(NULL, "<FF>");
if (token != NULL) {
strcpy(phoneBook[numEntries].phone, token);
numEntries++;
printf("Phone book entry stored successfully.\n");
}
}
}*/
// 打印存储的电话本信息
for (int i = 0; i < numEntries; i++) {
printf("Entry %d: Name - %s, Phone - %s\n", i+1, phoneBook[i].name, phoneBook[i].phone);
}
}
void Call_analysis(){
}
void parseBtATCommand(char* cAtCmd,int cATLen) {
uint8_t str[64];
static uint8_t flag = 0;
uint8_t j=0;
uint32_t num = 0;
printf(">>");
for(uint16_t i =0;i<cATLen;i++){
printf("%c",cAtCmd[i]);
}
if(strlen(cAtCmd) > 8 && !memcmp(cAtCmd,"+A2DPDEV",8))//蓝牙连接设备信息 远端设备信息 蓝牙连接
{
Set_sys_bt_connect_state(1);
}else if(strlen(cAtCmd) > 8 && !memcmp(cAtCmd,"+A2DPDEV",8)){
}else if(strlen(cAtCmd) > 9 && !memcmp(cAtCmd,"+A2DPLOST",9)){//远距离断开 设备丢失
}else if(strlen(cAtCmd) > 12 && !memcmp(cAtCmd,"+AVRCPSTAT=1",12)){//AVRCP状态 1是配对状态 蓝牙断开
Set_sys_bt_connect_state(0);
}else if(strlen(cAtCmd) > 6 && !memcmp(cAtCmd,"+PBCNT",6)){//电话本数量
num = atoi(cAtCmd + 7); //从数字的起始位置开始转换为整数
printf("Extracted number from command: %d\n", num);
}else if(strlen(cAtCmd) > 7 && !memcmp(cAtCmd,"+PBDATA",7)){//电话号码
printf("----------------------------\r\n");
// 解析字符串并提取姓名和电话号码
// char *token = strtok(cAtCmd, "<FF>"); // 使用<FF>作为分隔符
/*char *token = strtok(cAtCmd, 0x3F); // 使用<FF>作为分隔符
printf("token1 > %s .\r\n",token);
if (token != NULL) {
// token = strtok(NULL, "<FF>"); // 跳过第一个分隔符
token = strtok(NULL, 0x3F); // 跳过第一个分隔符
printf("token2 > %s .\r\n",token);
if (token != NULL) {
strcpy(phoneBook[numEntries].name, token);
printf("token3 > %s .\r\n",token);
// token = strtok(NULL, "<FF>");
token = strtok(NULL, 0x3F); // 跳过第一个分隔符
if (token != NULL) {
strcpy(phoneBook[numEntries].phone, token);
printf("token4 > %s .\r\n",token);
numEntries++;
printf("Phone book entry stored successfully.\n");
}
}
}*/
printf(">>");
for(uint16_t i =0;i<cATLen;i++){
printf("%02X ",cAtCmd[i]);
}
char call_num[20];
char call_name[20];
uint16_t len1=0;
uint16_t len2=0;
for(uint16_t i=0;i<cATLen;i++){
if(cAtCmd[i] == 0xFF){
if(!len1)
len1 = i;
else
len2 = i;
}
}
printf("len1 = %d,len2 = %d.\r\n",len1,len2);
char *start;
char *start2;
char *start3;
char *start4 = cAtCmd + len2 +1;//call number
printf("start4 >%s.\r\n",start4);
strncpy(start2, (cAtCmd + len2), len2);//number
printf("start2 >%s.\r\n",start2);
strncpy(start, (cAtCmd + 10), len2-len1);//name
printf("start >%s, start2 >%s .\r\n",start,start2);
// char *start = cAtCmd + 10;
// char *start2;
// strncpy(start2, start, len1);
// char *start3 = start + len1;
// // char *end = strchr(start, 0x3F);
// // char *end2 = strchr(end, 0x3F);
// printf("start >%s, end >%s, end2 >%s .\r\n",start,start2,start3);
// if (end) {
// *end = '\0';
// strncpy(call_num, start, 19);
// call_num[19] = '\0'; // 确保字符串以null结尾
// printf("call_num > %s .\r\n",call_num);
// }
// if (end2) {
// *end2 = '\0';
// strncpy(call_name, end, 19);
// call_name[19] = '\0'; // 确保字符串以null结尾
// printf("call_name > %s .\r\n",call_name);
// }
}
}

View File

@ -0,0 +1,6 @@
#ifndef BT_INTERACTION_PROTOCOL_H
#define BT_INTERACTION_PROTOCOL_H
#endif

View File

@ -1,2 +1,69 @@
#include "awtk.h" #include "awtk.h"
#include "can_protocol.h" #include "can_protocol.h"
uint8_t tcs_twinkle = 0;
uint8_t tcs_switch = 0;
//37B
void tcsworking_event_handing(int *buf){
uint8_t data = 0;
*(buf++);
*(buf++);
data = *(buf++);
tcs_twinkle = getBitValue(data,7);//tcs闪烁控制指令 为1闪烁
}
//12B
void tcsswitch_event_handing(int *buf){
uint8_t data = 0;
uint8_t tcs_data = 0;
data = *(buf++);
tcs_data = getBit2Value(data,0);//tcs开关信号
if(tcs_data<=1)
tcs_switch = tcs_data;
}
//101
void speed_event_handing(int *buf){
uint16_t eng_temp = 0;
uint16_t data = 0;
double buf_value = 0;
*(buf++);
*(buf++);
*(buf++);
*(buf++);
data = *(buf++) &0xFF;
data = (*(buf++)&0xFF) | data<<8;
buf_value = data; //值为60-120
if(buf_value>5280)
buf_value = 255;
else if(buf_value>2730)
buf_value = ((buf_value*0.1)-273);
else
buf_value = 0;
eng_temp = (int)buf_value;
Set_sys_can_temp(eng_temp);
}
//0xA5
void abs_dtc_event_handing(int *buf){
char dtc[5] = {0};
dtc[4] = *(buf++)&0xFF;
dtc[3] = *(buf++)&0xFF;
dtc[2] = *(buf++)&0xFF;
dtc[1] = *(buf++)&0xFF;
dtc[0] = *(buf++)&0xFF;
Get_can_abs_dtc(dtc);
}
//0x402
void ecu_dtc_event_handing2(int *buf){
char dtc[5] = {0};
dtc[4] = *(buf++)&0xFF;
dtc[3] = *(buf++)&0xFF;
dtc[2] = *(buf++)&0xFF;
dtc[1] = *(buf++)&0xFF;
dtc[0] = *(buf++)&0xFF;
Get_can_abs_dtc(dtc);
}

View File

@ -70,29 +70,31 @@ void vbat_led_off(void){
void light_gpio_init(void){ void light_gpio_init(void){
// //灯光使能 //灯光使能
// gpio_direction_output(GPIO_LIGHT, TRUE); gpio_direction_output(47, TRUE);
//R_LED //R_LED
gpio_direction_output(GPIO_LIGHT_R_LED, TRUE); gpio_direction_output(GPIO_LIGHT_R_LED, TRUE);
//YG_LED //YG_LED
gpio_direction_output(GPIO_LIGHT_YG_LED, TRUE); gpio_direction_output(GPIO_LIGHT_YG_LED, TRUE);
//ABS_LED
gpio_direction_output(GPIO_LIGHT_ABS, TRUE);
//OIL_LED //OIL_LED
gpio_direction_output(GPIO_LIGHT_OIL, TRUE); gpio_direction_output(GPIO_LIGHT_OIL, TRUE);
//L_LED //L_LED
gpio_direction_output(GPIO_LIGHT_L_LED, TRUE); gpio_direction_output(GPIO_LIGHT_L_LED, TRUE);
//N_LED //N_LED
gpio_direction_output(GPIO_LIGHT_N_LED, TRUE); gpio_direction_output(GPIO_LIGHT_N_LED, TRUE);
//ENG_LED // #if (MOTO_WARE_HOSE == MOTO_ICMX_A580A)
gpio_direction_output(GPIO_LIGHT_ENG_LED, TRUE); // //ABS_LED
// gpio_direction_output(GPIO_LIGHT_ABS, TRUE);
// //ENG_LED
// gpio_direction_output(GPIO_LIGHT_ENG_LED, TRUE);
// #endif
//VBAT_LED //VBAT_LED
gpio_direction_output(GPIO_LIGHT_VBAT_LED, TRUE); gpio_direction_output(GPIO_LIGHT_VBAT_LED, TRUE);
gpio_direction_input(GPIO_LIGHT_SET); gpio_direction_input(GPIO_LIGHT_SET);
gpio_direction_input(GPIO_LIGHT_MODE); gpio_direction_input(GPIO_LIGHT_MODE);
gpio_timer(); gpio_timer();//按键 //左右灯光
} }
@ -101,16 +103,18 @@ void light_off(void){
gpio_direction_output(GPIO_LIGHT_R_LED, FALSE); gpio_direction_output(GPIO_LIGHT_R_LED, FALSE);
//YG_LED //YG_LED
gpio_direction_output(GPIO_LIGHT_YG_LED, FALSE); gpio_direction_output(GPIO_LIGHT_YG_LED, FALSE);
//ABS_LED
gpio_direction_output(GPIO_LIGHT_ABS, FALSE);
//OIL_LED //OIL_LED
gpio_direction_output(GPIO_LIGHT_OIL, FALSE); gpio_direction_output(GPIO_LIGHT_OIL, FALSE);
//L_LED //L_LED
gpio_direction_output(GPIO_LIGHT_L_LED, FALSE); gpio_direction_output(GPIO_LIGHT_L_LED, FALSE);
//N_LED //N_LED
gpio_direction_output(GPIO_LIGHT_N_LED, FALSE); gpio_direction_output(GPIO_LIGHT_N_LED, FALSE);
//ENG_LED // #if (MOTO_WARE_HOSE == MOTO_ICMX_A580A)
gpio_direction_output(GPIO_LIGHT_ENG_LED, FALSE); // //ABS_LED
// gpio_direction_output(GPIO_LIGHT_ABS, FALSE);
// //ENG_LED
// gpio_direction_output(GPIO_LIGHT_ENG_LED, FALSE);
// #endif
//VBAT_LED //VBAT_LED
gpio_direction_output(GPIO_LIGHT_VBAT_LED, FALSE); gpio_direction_output(GPIO_LIGHT_VBAT_LED, FALSE);

View File

@ -3,7 +3,7 @@
#include "tkc/types_def.h" #include "tkc/types_def.h"
#define GPIO_LIGHT 47
#define GPIO_LIGHT_R_LED_FLAG 11 #define GPIO_LIGHT_R_LED_FLAG 11
#define GPIO_LIGHT_L_LED_FLAG 10 #define GPIO_LIGHT_L_LED_FLAG 10

View File

@ -10,9 +10,10 @@ KEY_DAT gs_keyDat[KEY_NUMBERS]={0};
bool key_readKeyPin(uint8_t keyx) bool key_readKeyPin(uint8_t keyx)
{ {
bool status; bool status;
if(keyx==0) status = gpio_get_value(GPIO_LIGHT_MODE); if(keyx==0) status = gpio_get_value(GPIO_LIGHT_SET);
else if(keyx==1) status = gpio_get_value(GPIO_LIGHT_SET); else if(keyx==1) status = gpio_get_value(GPIO_LIGHT_MODE);
return status; // return (!status);//低有效
return (status);//高有效
} }
void key_Scan(void) void key_Scan(void)
@ -28,6 +29,9 @@ void key_Scan(void)
} }
} }
extern uint8_t map_flag;
static int step_about = 0;
static int step = 0;
void check_key(void) void check_key(void)
{ {
@ -44,7 +48,7 @@ void check_key(void)
gs_keyDat[1].flag_Reset=1; gs_keyDat[1].flag_Reset=1;
gs_keyDat[0].keyCnt=0; gs_keyDat[0].keyCnt=0;
gs_keyDat[1].keyCnt=0; gs_keyDat[1].keyCnt=0;
// printf("set mode key \r\n"); // printf("two long key ---------------------\r\n");
Key_Distinction(KEY_SHORT_ON,LV_KEY_OTHER1); Key_Distinction(KEY_SHORT_ON,LV_KEY_OTHER1);
} }
else if(gs_keyDat[i].keyCnt==KEY_LONGPRESS_COUNTER) else if(gs_keyDat[i].keyCnt==KEY_LONGPRESS_COUNTER)
@ -55,14 +59,14 @@ void check_key(void)
{ {
gs_keyDat[i].flag_Reset=1; gs_keyDat[i].flag_Reset=1;
gs_keyDat[i].keyCnt=0; gs_keyDat[i].keyCnt=0;
// printf("set key long key\r\n"); // printf("LV_KEY_OPTION key long key\r\n");
Key_Distinction(KEY_LONG_ON,LV_KEY_OPTION); Key_Distinction(KEY_LONG_ON,LV_KEY_OPTION);
} }
if(i==1 && gs_keyDat[0].flag_Pressed==KEY_OFF) if(i==1 && gs_keyDat[0].flag_Pressed==KEY_OFF)
{ {
gs_keyDat[i].flag_Reset=1; gs_keyDat[i].flag_Reset=1;
gs_keyDat[i].keyCnt=0; gs_keyDat[i].keyCnt=0;
// printf("mode key long key\r\n"); // printf("LV_KEY_SELECT key long key\r\n");
Key_Distinction(KEY_LONG_ON,LV_KEY_SELECT); Key_Distinction(KEY_LONG_ON,LV_KEY_SELECT);
} }
@ -76,12 +80,36 @@ void check_key(void)
{ {
if(i==0 && gs_keyDat[1].flag_Pressed==KEY_OFF) if(i==0 && gs_keyDat[1].flag_Pressed==KEY_OFF)
{ {
// printf("set key short key\r\n"); // printf("LV_KEY_OPTION-------------------------.\r\n");
// if(map_flag){
// // KnobUpdate(0,0,0,0,0,1);
// request_UI("maps:");
// }else
// if(Get_sys_wifi()){
// printf("option DOWN .\r\n");
// android_auto_send_key_event(20,1);
// android_auto_send_key_event(20,0);
// // android_auto_send_knob_event(19,1);
// // android_auto_send_knob_event(19,0);
// }else
Key_Distinction(KEY_SHORT_ON,LV_KEY_OPTION); Key_Distinction(KEY_SHORT_ON,LV_KEY_OPTION);
} }
else if(i==1 && gs_keyDat[0].flag_Pressed==KEY_OFF) else if(i==1 && gs_keyDat[0].flag_Pressed==KEY_OFF)
{ {
// printf("mode key short key\r\n"); // printf("LV_KEY_SELECT-------------------------.\r\n");
// if(map_flag){
// // KnobUpdate(0,0,0,0,0,-1);
// request_UI("maps:");
// }else
// if(Get_sys_wifi()){
// printf("select ENTER .\r\n");
// android_auto_send_key_event(66,1);
// android_auto_send_key_event(66,0);
// // android_auto_send_key_event(20,1);
// // android_auto_send_key_event(20,0);
// // android_auto_send_knob_event(20,1);
// // android_auto_send_knob_event(20,0);
// }else
Key_Distinction(KEY_SHORT_ON,LV_KEY_SELECT); Key_Distinction(KEY_SHORT_ON,LV_KEY_SELECT);
} }
} }
@ -143,7 +171,7 @@ static void gpio_handler(void *param)
int gpio_timer(void){ int gpio_timer(void){
// printf("gpio_timer .\r\n"); // printf("gpio_timer .\r\n");
if (xTaskCreate(gpio_handler, "gpio_handler", configMINIMAL_STACK_SIZE, NULL, if (xTaskCreate(gpio_handler, "gpio_handler", configMINIMAL_STACK_SIZE, NULL,
configMAX_PRIORITIES / 3, NULL) != pdPASS) { configMAX_PRIORITIES - 5, NULL) != pdPASS) {
printf("create uart rx demo task fail.\n"); printf("create uart rx demo task fail.\n");
return -1; return -1;
} }

View File

@ -0,0 +1,539 @@
#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include "FreeRTOS.h"
#include "chip.h"
#include "board.h"
#include "serial.h"
#include "sysinfo.h"
#include "conversation_protocol.h"
#include "sfud.h"
#include "ota_update.h"
#include "updatefile.h"
#include "romfile.h"
#include "animation.h"
#include "ff_stdio.h"
#include "awtk.h"
#include "ota_protocol.h"
int flash_copy_demo(void);
#if DEVICE_TYPE_SELECT != EMMC_FLASH
#include "ff_sfdisk.h"
#endif
typedef enum {
UART_FRAME_START,
UART_FRAME_FILEINFO,
UART_FRAME_FILEXFER,
UART_FRAME_FINISH,
} eUartFrameType;
typedef enum {
UUP_STATE_IDLE,
UUP_STATE_START,
UUP_STATE_GET_FILEINFO,
UUP_STATE_FILE_TFR,
UUP_STATE_END,
} eUartUpdateState;
#define UUP_ACK_OK 1
#define UUP_ACK_FAIL 0
#define UUP_MAX_FILE_SIZE 0x1000000
#define UUP_RX_FRAME_NUM 16
#define UUP_MAX_LOADER_SIZE STEPLDR_MAX_SIZE//0x10000
static int uup_status = UUP_STATE_IDLE;
static int uup_file_type = 0;
static int uup_file_size = 0;
static int uup_packet_num = 0;
static int uup_rev_packet = 0;
static int uup_rev_len = 0;
static char uup_filename[32];
static FF_FILE *uup_file = NULL;
#define UUP_PACKET_SIZE 128
#define UUP_MAX_FRAME_LEN (UUP_PACKET_SIZE + 16)
#define UUP_PACKET_A27_SIZE 4096
#define UUP_MAX_FRAME_A27_LEN (UUP_PACKET_A27_SIZE + 16)
#define UUP_RX_FRAME_NUM 16
#define BYTESPERPAGE 256
#define PAGESPERSECTORS 16
#define UUP_BUF_SIZE (BYTESPERPAGE * PAGESPERSECTORS)
#define IMAGE_RW_SIZE 0x10000
#define NEW_APPLDR_CHECKSUM_OFFSET 0x14
#define AMT630_BIN_OFFSET 0x41000
#define BOOTANIM_BIN_OFFSET 0x741000
#define ROM_BIN_OFFSET 0xb41000
#define NEW_APPFOOSET 0x17F0000
#define AMT630_BIN_MAX_SIZE 0x700000
/*
#define AMT630_BIN_OFFSET 0x41000
#define BOOTANIM_BIN_OFFSET 0x501000//0x341000
#define ROM_BIN_OFFSET 0x801000
#define NEW_APPFOOSET 0xb01000
#define AMT630_BIN_MAX_SIZE 0x4c0000
*/
static uint32_t uup_app_offset;
static uint32_t uup_burn_offset;
static unsigned char uup_buf[4096];
static unsigned int uup_buf_len = 0;
static unsigned int checksum = 0,calc_checksum = 0xffffffff;
static void uup_send_ack(UartPort_t *uap, int type, int ret)
{
/*unsigned char buf[7] = {0x55, 0x80, 0xc5, 0x02, 0x00, 0x00, 0x00};
int i;
buf[4] = type;
buf[5] = ret;
for (i = 1; i < 6; i++)
buf[6] ^= buf[i];
iUartWrite(uap, buf, 7, pdMS_TO_TICKS(100));*/
unsigned char buf[8] = {0x55, 0x80, 0xc5, 0x02, 0x00, 0x00, 0x00, 0x00};
int i;
buf[5] = type;
buf[6] = ret;
if(ret == 0){
Set_sys_power_on_self_test(100);
Set_sys_return_demo(2);
Set_sys_plan(0);
Set_sys_pace(0);
}
for (i = 1; i < 7; i++)
buf[7] ^= buf[i];
// printf("630->uart:");
// for(uint8_t j=0;j<8;j++){
// printf("%02x ",buf[j]);
// }
// printf("\n");
iUartWrite(uap, buf, 8, pdMS_TO_TICKS(100));
}
void uup_ota_update(UartPort_t *uap, uint8_t *framebuf, size_t len)
{
int frametype = framebuf[0];
uint8_t *buf = framebuf + 1;
unsigned int framelen;
unsigned int packetnum;
sfud_flash *sflash = sfud_get_device(0);
SysInfo *sysinfo = GetSysInfo();
//printf("uup_ota_update frametype =%d \n",frametype);
switch (frametype) {
case UART_FRAME_START:
printf("UART3_Modification_Type .\n");
UART3_Modification_Type();
vTaskDelay(10);
printf("start sfud erase flash .\n");
//擦除flash
uup_app_offset = NEW_APPFOOSET;
uup_burn_offset = uup_app_offset;
//uup_send_ack(uap, frametype, UUP_ACK_OK);
//Set_sys_power_on_self_test(150);
printf("erase add %X , size %X .\r\n",uup_app_offset,AMT630_BIN_MAX_SIZE);
if(sfud_erase(sflash, uup_app_offset, AMT630_BIN_MAX_SIZE)==SFUD_SUCCESS){
vTaskDelay(100);
printf("UART3_Type_regression .\n");
UART3_Type_regression();
vTaskDelay(100);
printf("UART_FRAME_START sfud erase ok.\n");
uup_send_ack(uap, frametype, UUP_ACK_OK);
}else{
vTaskDelay(100);
printf("UART3_Type_regression .\n");
UART3_Type_regression();
vTaskDelay(100);
printf("UART_FRAME_START sfud erase fail.\n");
uup_send_ack(uap, frametype, UUP_ACK_FAIL);
}
uup_status = UUP_STATE_START;
break;
case UART_FRAME_FILEINFO:
if (uup_status != UUP_STATE_START && uup_status != UUP_STATE_GET_FILEINFO) {
uup_send_ack(uap, frametype, UUP_ACK_FAIL);
break;
}
uup_file_type = buf[0];
if (uup_file_type > UPFILE_TYPE_LNCHEMMC) {
printf("Rev wrong file type %d.\n", uup_file_type);
uup_send_ack(uap, frametype, UUP_ACK_FAIL);
break;
}
uup_packet_num = (buf[1] << 16) | (buf[2] << 8) | buf[3];
uup_file_size = 128 * uup_packet_num;
if (uup_file_size > AMT630_BIN_MAX_SIZE) {
printf("Rev wrong file size.\n");
printf("uup_file_size = 0x%x ,uup_packet_num = 0x%x .\n",uup_file_size,uup_packet_num);
uup_send_ack(uap, frametype, UUP_ACK_FAIL);
break;
}
printf("uup_file_size = 0x%x .\n",uup_file_size);
uup_packet_num = uup_packet_num/32;
Set_sys_plan(uup_packet_num);
uup_rev_packet = 0;
uup_send_ack(uap, frametype, UUP_ACK_OK);
uup_status = UUP_STATE_GET_FILEINFO;
calc_checksum = 0xffffffff;
break;
case UART_FRAME_FILEXFER:
if (uup_status != UUP_STATE_GET_FILEINFO && uup_status != UUP_STATE_FILE_TFR) {
uup_send_ack(uap, frametype, UUP_ACK_FAIL);
break;
}
packetnum = buf[0];
if ((uup_rev_packet & 0xff) != packetnum) {
printf("Wrong packet number.\n");
//printf("buf 0 - 4 : 0x%x ,0x%x ,0x%x ,0x%x ,0x%x \n",buf[0],buf[1],buf[2],buf[3],buf[4],buf[5]);
//printf("packetnum = 0x%x,uup_rev_packet = 0x%x \n",packetnum,uup_rev_packet);
uup_send_ack(uap, frametype, UUP_ACK_FAIL);
break;
}
//printf("uup_rev_packet==0 ---------TURE\n");
//printf("uup_rev_packet %d.\n", uup_rev_packet);
if (uup_rev_packet==0) { //第一条数据保存其crc校验码
/*if (uup_file_type == UPFILE_TYPE_WHOLE) {
UpFileHeader *header = (UpFileHeader*)&buf[1];
if (header->magic != MKTAG('U', 'P', 'D', 'F')) {
printf("Wrong whole file magic.\n");
uup_send_ack(uap, frametype, UUP_ACK_FAIL);
break;
}
checksum = header->checksum;
sysinfo->app_size = header->files[0].size;
printf("sysinfo->appsize = 0x%x", sysinfo->app_size);
}else if (uup_file_type == UPFILE_TYPE_RESOURCE) {
RomHeader *header = (RomHeader *)&buf[1];
if (header->magic != MKTAG('R', 'O', 'M', 'A')) {
printf("Wrong resource file magic.\n");
uup_send_ack(uap, frametype, UUP_ACK_FAIL);
break;
}
checksum = header->checksum;
} else if (uup_file_type == UPFILE_TYPE_ANIMATION) {
BANIHEADER *header = (BANIHEADER *)&buf[1];
if (header->magic != MKTAG('B', 'A', 'N', 'I')) {
printf("Wrong animation file magic.\n");
uup_send_ack(uap, frametype, UUP_ACK_FAIL);
break;
}
checksum = header->checksum;
} else */
if (uup_file_type == UPFILE_TYPE_APP) {//代码文件
unsigned int magic = buf[1] | (buf[2] << 8) | (buf[3] << 16) | (buf[4] << 24);
if (magic != UPFILE_APP_MAGIC) {
printf("Wrong app file magic.\n");
uup_send_ack(uap, frametype, UUP_ACK_FAIL);
break;
}
unsigned char *tmp = buf + 1 + NEW_APPLDR_CHECKSUM_OFFSET;
checksum = tmp[0] | (tmp[1] <<8) | (tmp[2] << 16) | (tmp[3] << 24);
}else if (uup_file_type == UPFILE_TYPE_ANIMATION) {//动画文件
BANIHEADER *header = (BANIHEADER *)&buf[1];
if (header->magic != MKTAG('B', 'A', 'N', 'I')) {
printf("Wrong animation file magic.\n");
uup_send_ack(uap, frametype, UUP_ACK_FAIL);
break;
}
checksum = header->checksum;
}else if (uup_file_type == UPFILE_TYPE_RESOURCE) {//资源文件
RomHeader *header = (RomHeader *)&buf[1];
if (header->magic != MKTAG('R', 'O', 'M', 'A')) {
printf("Wrong resource file magic.\n");
uup_send_ack(uap, frametype, UUP_ACK_FAIL);
break;
}
checksum = header->checksum;
}
printf(" file_type = %d ,No1.checksum = 0x%x\n",uup_file_type,checksum);
}
framelen = len - 2;
//printf("framelen = %d ,uup_packet_num =%d ,uup_rev_packet = %d \n",framelen,uup_packet_num,uup_rev_packet);
/* only last frame size is less than UUP_PACKET_SIZE */
if (framelen > UUP_PACKET_A27_SIZE ||
(framelen < UUP_PACKET_A27_SIZE && uup_rev_packet != uup_packet_num)) { //UUP_PACKET_A27_SIZE
printf("Wrong packet len.\n");
printf("uup_rev_packet = %d, uup_packet_num = %d \n",uup_rev_packet,uup_packet_num);
uup_send_ack(uap, frametype, UUP_ACK_FAIL);
break;
}
memcpy(uup_buf + uup_buf_len, buf+1, framelen);
uup_buf_len += framelen;
uup_rev_packet++;
//uup_send_ack(uap, frametype, UUP_ACK_OK);
if (uup_buf_len == UUP_BUF_SIZE) {
printf("uup_rev_packet = %d , save_data.\n",uup_rev_packet);
uup_send_ack(uap, frametype, UUP_ACK_OK);
Set_sys_pace(uup_rev_packet);
//printf("addr=0x%x,size=%x\n",uup_burn_offset,framelen);
//sfud_erase_write(sflash, uup_burn_offset, UUP_BUF_SIZE, uup_buf);
sfud_write(sflash, uup_burn_offset, UUP_BUF_SIZE, uup_buf);
if (uup_rev_packet == 1){//UUP_BUF_SIZE/UUP_PACKET_SIZE) {
//printf("enter1 uup_rev_packet = %d \n",uup_rev_packet);
/*if (uup_file_type == UPFILE_TYPE_WHOLE) {
UpFileHeader *pheader = (UpFileHeader *)uup_buf;
pheader->checksum = 0;
} else if (uup_file_type == UPFILE_TYPE_RESOURCE) {
RomHeader *pheader = (RomHeader *)uup_buf;
pheader->checksum = 0;
} else if (uup_file_type == UPFILE_TYPE_ANIMATION) {
BANIHEADER *pheader = (BANIHEADER *)uup_buf;
pheader->checksum = 0;
} else if (uup_file_type == UPFILE_TYPE_APP) {*/
if (uup_file_type == UPFILE_TYPE_APP) {//代码文件
unsigned int *tmp = (unsigned int *)(uup_buf + NEW_APPLDR_CHECKSUM_OFFSET);
*tmp = 0;
}else if (uup_file_type == UPFILE_TYPE_ANIMATION) {//动画文件
BANIHEADER *pheader = (BANIHEADER *)uup_buf;
pheader->checksum = 0;
}else if (uup_file_type == UPFILE_TYPE_RESOURCE) {//资源文件
RomHeader *pheader = (RomHeader *)uup_buf;
pheader->checksum = 0;
}
//}
}
calc_checksum = xcrc32(uup_buf, UUP_BUF_SIZE, calc_checksum);//计算校验和
uup_buf_len =0;
uup_burn_offset += UUP_BUF_SIZE;
}else if (uup_buf_len > UUP_BUF_SIZE) {
printf("loader file is too large.\n");
uup_send_ack(uap, frametype, UUP_ACK_FAIL);
break;
}
/*memcpy(&uup_sysinfo, &buf[2], sizeof(SysInfo));
sfud_erase_write(sflash, uup_burn_offset, framelen, &buf[1]);//128字节写一次
uup_burn_offset += framelen;*/
uup_status = UUP_STATE_FILE_TFR;
break;
case UART_FRAME_FINISH:
if (uup_status != UUP_STATE_FILE_TFR && uup_status != UART_FRAME_FINISH) {
uup_send_ack(uap, frametype, UUP_ACK_FAIL);
break;
}
if (!buf[0]) {
printf("update end with error!\n");
uup_send_ack(uap, frametype, UUP_ACK_FAIL);
uup_status = UUP_STATE_END;
break;
}
framelen = len - 2;
//printf("finish calc_checksum =%x\n",calc_checksum);
if(uup_buf_len){//若最后一包数据不为0 则存数据并且继续计算校验和
//sfud_erase_write(sflash, uup_burn_offset, uup_buf_len, uup_buf);
sfud_write(sflash, uup_burn_offset, uup_buf_len, uup_buf);
//若数据为32 即首次的4k 那么将其置为0
if (uup_rev_packet <= 1){//< UUP_BUF_SIZE / UUP_PACKET_SIZE) {
printf("enter2 uup_rev_packet = %d \n",uup_rev_packet);
/*if (uup_file_type == UPFILE_TYPE_WHOLE) {
UpFileHeader *pheader = (UpFileHeader *)uup_buf;
pheader->checksum = 0;
} else if (uup_file_type == UPFILE_TYPE_RESOURCE) {
RomHeader *pheader = (RomHeader *)uup_buf;
pheader->checksum = 0;
} else if (uup_file_type == UPFILE_TYPE_ANIMATION) {
BANIHEADER *pheader = (BANIHEADER *)uup_buf;
pheader->checksum = 0;
} else if (uup_file_type == UPFILE_TYPE_APP) {*/
if (uup_file_type == UPFILE_TYPE_APP) {
unsigned int *checksum = (unsigned int *)(uup_buf + NEW_APPLDR_CHECKSUM_OFFSET);
*checksum = 0;
}else if (uup_file_type == UPFILE_TYPE_ANIMATION) {
BANIHEADER *pheader = (BANIHEADER *)uup_buf;
pheader->checksum = 0;
}else if (uup_file_type == UPFILE_TYPE_RESOURCE) {
RomHeader *pheader = (RomHeader *)uup_buf;
pheader->checksum = 0;
}
}
printf("enter2 uup_buf_len =%d calc_checksum================0x%x\n",uup_buf_len,calc_checksum);
calc_checksum = xcrc32(uup_buf, uup_buf_len, calc_checksum);
Set_sys_pace(0);
Set_sys_upgrade(1);
}
/*if (calc_checksum != checksum) {
printf("checksum error ! ! ! .\r\n");
}else{
printf("checksum ok .\r\n");
}*/
if (calc_checksum != checksum) {
printf("calc_checksum = 0x%02x,checksum = 0x%02x.\n",calc_checksum,checksum);
printf("whole crc check after burn fail!\n");
uup_send_ack(uap, frametype, UUP_ACK_FAIL);
uup_rev_packet = 0;
checksum = 0;
calc_checksum = 0xffffffff;
uup_buf_len = 0;
framelen = 0;
break;
} else {
uup_send_ack(uap, frametype, UUP_ACK_OK);
vTaskDelay(1000);
UART3_Modification_Type();
printf("uap close .\r\n");
printf("test amt630h update ok!\n");
sysinfo->image_offset=0x40000;
sysinfo->reserved[9] = uup_file_type;
sysinfo->upgrade_flag=uup_buf_len;
sysinfo->upgrade_appsize=uup_file_size;
SaveSysInfo();
vTaskDelay(500);
printf("TaskDelay 500ms SaveSysInfo .\n");
flash_copy_demo();
wdt_cpu_reboot();
}
uup_rev_packet = 0;
checksum = 0;
calc_checksum = 0xffffffff;
uup_buf_len = 0;
framelen = 0;
uup_status = UUP_STATE_END;
break;
}
}
int flash_copy_demo(void)
{
uint32_t calchecksum,appchecksum,imageoff,new_appoffset,new_appsize;
int i;
uint8_t *buf;
sfud_flash *sflash = sfud_get_device(0);
printf("enter copy flash .\n");
new_appsize=uup_file_size; //根据串口升级的协议获取
new_appoffset = NEW_APPFOOSET; //升级的程序可以固定写在这个地址预留3M
if(uup_file_type == UPFILE_TYPE_APP){
imageoff = AMT630_BIN_OFFSET; //固定的 运行区固定地址
}else if(uup_file_type == UPFILE_TYPE_ANIMATION){
imageoff = BOOTANIM_BIN_OFFSET; //固定的 运行区固定地址
}else if(uup_file_type == UPFILE_TYPE_RESOURCE){
imageoff = ROM_BIN_OFFSET;
}
//imageoff = AMT630_BIN_OFFSET; //固定的 运行区固定地址
printf("copy flash init ok.\n");
Set_sys_plan((new_appsize/IMAGE_RW_SIZE)+1);
printf("new_appsize = %x ,start flash copy .\n",new_appsize);
// sfud_qspi_fast_read_enable(sfud_get_device(0), 1);
// printf("sfud_qspi_fast_read_enable ok.\n");
buf = pvPortMalloc(IMAGE_RW_SIZE);
if (!buf) {
printf("%s %d malloc %d bytes fail.\n", __FUNCTION__, __LINE__, IMAGE_RW_SIZE);
return -1;
}
printf("start copy flash ok.\n");
for(i=0;i<new_appsize/IMAGE_RW_SIZE;i++)
{
printf("i = %d start read .\r\n",i);
sfud_read(sflash, new_appoffset+IMAGE_RW_SIZE*i, IMAGE_RW_SIZE, buf);
printf("start erase write .\r\n");
sfud_erase_write(sflash, imageoff+IMAGE_RW_SIZE*i, IMAGE_RW_SIZE, buf);
printf("start erase write ok.\r\n");
Set_sys_pace(i+1);
if(i==0)
{
if (uup_file_type == UPFILE_TYPE_APP) {//代码文件
unsigned int *tmp = (unsigned int *)(buf + NEW_APPLDR_CHECKSUM_OFFSET);
appchecksum = *tmp;
*tmp = 0;
}else if (uup_file_type == UPFILE_TYPE_ANIMATION) {//动画文件
BANIHEADER *pheader = (BANIHEADER *)buf;
appchecksum = pheader->checksum;
pheader->checksum = 0;
}else if (uup_file_type == UPFILE_TYPE_RESOURCE) {//资源文件
RomHeader *pheader = (RomHeader *)buf;
appchecksum = pheader->checksum;
pheader->checksum = 0;
}
printf("file_type = %d. %X\r\n",uup_file_type,appchecksum);
calchecksum = xcrc32(buf, IMAGE_RW_SIZE, 0xffffffff);
printf("i=0 calchecksum = 0x%X.\n",calchecksum);
}
else
{
calchecksum = xcrc32(buf, IMAGE_RW_SIZE, calchecksum);
printf("i=%d ,r_add = 0x%X ,w_add = 0x%X , calchecksum = 0x%X.\n",i,new_appoffset+IMAGE_RW_SIZE*i,imageoff+IMAGE_RW_SIZE*i,calchecksum);
}
}
if(new_appsize%IMAGE_RW_SIZE)
{
uint32_t red_add,wri_add,size,count;
int k;
count = (new_appsize%IMAGE_RW_SIZE )/0x1000;
red_add = new_appoffset+new_appsize- new_appsize%IMAGE_RW_SIZE;
wri_add = imageoff+new_appsize- new_appsize%IMAGE_RW_SIZE;
size = 0x1000;
printf("count = %d .\n",count);
for(k=0;k<count;k++){
sfud_read(sflash, red_add, size, buf);
sfud_erase_write(sflash, wri_add, size, buf);
calchecksum = xcrc32(buf, size, calchecksum);
printf("k=%d ,calchecksum = 0x%X.\n",k,calchecksum);
red_add +=size;
wri_add +=size;
}
if(uup_buf_len){//若最后一包数据不满0x1000 则存数据并且继续计算校验和
sfud_read(sflash, red_add, uup_buf_len, buf);
sfud_erase_write(sflash, wri_add, uup_buf_len, buf);
calchecksum = xcrc32(buf, uup_buf_len, calchecksum);
printf("end calchecksum = 0x%X.\n",calchecksum);
}
}
printf("end flash copy.\n");
vPortFree(buf);
printf("calchecksum is 0x%X\r\n",calchecksum);
printf("appchecksum is 0x%X\r\n",appchecksum);
if(calchecksum==appchecksum)
{
printf("crc32 OK\r\n");
SysInfo *sysinfo = GetSysInfo();
if(uup_file_type == UPFILE_TYPE_APP)
sysinfo->app_size = new_appsize;
sysinfo->image_offset=0x40000;
sysinfo->upgrade_flag = 0;
sysinfo->upgrade_appsize =0;
sysinfo->reserved[9] = 0;
SaveSysInfo();
vTaskDelay(500);
wdt_cpu_reboot();
return 0;
}
else
{
SysInfo *sysinfo = GetSysInfo();
sysinfo->image_offset=0x40000;
sysinfo->upgrade_flag = 0;
sysinfo->upgrade_appsize =0;
sysinfo->reserved[9] = 0;
SaveSysInfo();
vTaskDelay(500);
printf("crc32 ERROR\r\n");
return -1;
}
}

View File

@ -0,0 +1,6 @@
#ifndef OTA_PROTOCOL_H
#define OTA_PROTOCOL_H
#include "tkc/types_def.h"
#endif

View File

@ -79,7 +79,8 @@ void pressure_buffer_event_handing(Pressure_t pressure,char buffer[],uint8_t typ
pressure.temp = data; pressure.temp = data;
if(data>=70 && data<128){ if(data>=70 && data<128){
pressure.temp_state = 1; pressure.temp_state = 1;
} }else
pressure.temp_state = 0;
//DEBUG_PRINT("%x, ",data); //DEBUG_PRINT("%x, ",data);
//P //P
sum = 0; sum = 0;

View File

@ -11,7 +11,7 @@
#include "moto_adc.h" #include "moto_adc.h"
// uint8_t save_data = 0; uint8_t save_data = 0;
#define ADC_VPLTAGE_MIN 1666 #define ADC_VPLTAGE_MIN 1666
#define ADC_VPLTAGE_MAX 2486 #define ADC_VPLTAGE_MAX 2486
@ -20,7 +20,7 @@ int adc_light = 0;
int adc_voltage = 0; int adc_voltage = 0;
extern uint32_t fml_stamp_to_time(uint32_t timep , uint32_t time[]); extern uint32_t fml_stamp_to_time(uint32_t timep , uint32_t time[]);
extern uint16_t light_buffer[]; extern uint8_t light_buffer[];
extern double cell_buffer[]; extern double cell_buffer[];
extern uint8_t data_storage; extern uint8_t data_storage;
extern uint32_t tire_front_time; extern uint32_t tire_front_time;
@ -54,10 +54,10 @@ double adc_voltage_calculation(void){
value = 16.5; value = 16.5;
else else
value = (adc_voltage - ADC_VPLTAGE_MIN) * (16.5 - 11.0) / (ADC_VPLTAGE_MAX - ADC_VPLTAGE_MIN) + 11.0; value = (adc_voltage - ADC_VPLTAGE_MIN) * (16.5 - 11.0) / (ADC_VPLTAGE_MAX - ADC_VPLTAGE_MIN) + 11.0;
printf("adc_voltage = %d value = %lf.\r\n",adc_voltage,value); // printf("adc_voltage = %d value = %lf.\r\n",adc_voltage,value);
return value; return value;
} }
extern uint8_t device_flag;
//MOTO通讯 设备信息+时间戳解析协议 //MOTO通讯 设备信息+时间戳解析协议
void device_data_analysis(uint8_t *buf){ void device_data_analysis(uint8_t *buf){
DEBUG_PRINT("enter device_data_analysis .\r\n"); DEBUG_PRINT("enter device_data_analysis .\r\n");
@ -77,8 +77,7 @@ void device_data_analysis(uint8_t *buf){
// DEBUG_PRINT("0x47 -- %02x .\n",data); // DEBUG_PRINT("0x47 -- %02x .\n",data);
if(data!=0x47) if(data!=0x47)
return; return;
if(!device_flag)
device_flag = 1;
//设备相关信息 //设备相关信息
data = *(buf++);//0x01 data = *(buf++);//0x01
// DEBUG_PRINT("0x01 -- %02x .\n",data); // DEBUG_PRINT("0x01 -- %02x .\n",data);
@ -199,7 +198,7 @@ void device_data_analysis(uint8_t *buf){
Set_device_ability(data); Set_device_ability(data);
} }
int test_light = 0;
//MOTO通讯协议 //MOTO通讯协议
void data_analysis(uint8_t *buf){ void data_analysis(uint8_t *buf){
uint32_t data; uint32_t data;
@ -211,7 +210,8 @@ void data_analysis(uint8_t *buf){
uint8_t light = 0; uint8_t light = 0;
double cell = 0; double cell = 0;
uint8_t sys_state = 0; uint8_t sys_state = 0;
uint8_t save_data = 0; save_data = 0;
if(Get_sys_power_on_self_test()==100) if(Get_sys_power_on_self_test()==100)
sys_state=1; sys_state=1;
@ -279,11 +279,14 @@ void data_analysis(uint8_t *buf){
save_data = getBitValue(data,7); save_data = getBitValue(data,7);
if(sys_state){ if(sys_state){
// right_led_switch(getBitValue(data,0)); right_led_switch(getBitValue(data,0));
// left_led_switch(getBitValue(data,1)); left_led_switch(getBitValue(data,1));
yg_led_switch(getBitValue(data,2)); yg_led_switch(getBitValue(data,2));
// abs_led_switch(getBitValue(data,4)); #if (MOTO_WARE_HOSE == MOTO_ICMX_A580A)
// eng_led_switch(getBitValue(data,6)); abs_led_switch(getBitValue(data,4));
eng_led_switch(getBitValue(data,6));
#endif
} }
//档位 //档位
@ -343,7 +346,7 @@ void data_analysis(uint8_t *buf){
} }
if(save_data){ if(save_data){
DEBUG_PRINT("save_data.\r\n"); // DEBUG_PRINT("save_data.\r\n");
// printf("light = %d .\r\n",light); // printf("light = %d .\r\n",light);
Set_sys_gas(oil); Set_sys_gas(oil);
Set_sys_temp(temp); Set_sys_temp(temp);
@ -364,8 +367,11 @@ void data_analysis(uint8_t *buf){
//adc采样光感计算 //adc采样光感计算
int light_num = (adc_light/10); int light_num = (adc_light/10);
if(light_num>=100) test_light = light_num;
light_num = 100; if(light_num>=200)
light_num = 200;
if(Get_sys_power_on_self_test()<100)
light_num = 10;
light_buffer[data_storage] =light_num; light_buffer[data_storage] =light_num;
data_storage++; data_storage++;
if(data_storage>=SAVE_DATA_SIZE){//满足存储大小 计算均值 if(data_storage>=SAVE_DATA_SIZE){//满足存储大小 计算均值

View File

@ -3,4 +3,14 @@
#include "tkc/types_def.h" #include "tkc/types_def.h"
// 封装的函数,根据位位置获取对应的值
uint8_t getBitValue(uint8_t count, int bitPosition);
// 封装的函数获取2个bit组合成的值
uint8_t getBit2Value(uint8_t count, int bitPosition);
// 封装的函数获取3个bit组合成的值
uint8_t getBit3Value(uint8_t count, int bitPosition);
// 封装的函数获取4个bit组合成的值
uint8_t getBit4Value(uint8_t count, int bitPosition);
#endif #endif

21
lib/awtk/awtk-examples/.gitignore vendored Normal file
View File

@ -0,0 +1,21 @@
__docs__
__images__
bin/
*.o
*.a
*.so
*.swp
*.pdb
*.ilk
*.idb
*.obj
*.lib
*.exp
*.doc
*.docx
*.vsd
.sconsign.dblite
.vscode
build_web.py
Moto_A58/res/assets/
Moto_QH105/

Binary file not shown.

View File

@ -0,0 +1,115 @@
---
Language: Cpp
# BasedOnStyle: Google
AccessModifierOffset: -1
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Left
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: false
AllowShortIfStatementsOnASingleLine: true
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: true
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 100
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeCategories:
- Regex: '^<ext/.*\.h>'
Priority: 2
- Regex: '^<.*\.h>'
Priority: 1
- Regex: '^<.*'
Priority: 2
- Regex: '.*'
Priority: 3
IncludeIsMainRegex: '([-_](test|unittest))?$'
IndentCaseLabels: true
IndentPPDirectives: None
IndentWidth: 2
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: false
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 600
PenaltyBreakFirstLessLess: 100
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 200
PointerAlignment: Left
RawStringFormats:
- Language: TextProto
BasedOnStyle: google
ReflowComments: false
SortIncludes: false
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 2
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Auto
TabWidth: 2
UseTab: Never
...

View File

@ -0,0 +1,34 @@
*.o
*.a
*.so
*.swp
*.pdb
*.ilk
*.idb
*.obj
*.exe
*.os
*.pyc
/bin
/lib
.sconsign.dblite
lua/demo1
lua/lftk_run
tags
bin/demo1*
bin/demo_animator*
bin/demo_thread*
bin/demotr*
bin/demovg*
bin/fontgen*
bin/preview_ui*
bin/resgen*
bin/runLua*
bin/runTest*
bin/strgen*
bin/image*
bin/hello*
.vscode
.vs
*.os
res

View File

@ -0,0 +1,504 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random
Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

View File

@ -0,0 +1,143 @@
# awtk-widget-qr
qr 控件。用于显示二维码控件。
![](docs/images/ui.jpg)
* 本项目使用 [libqrencode](https://github.com/fukuchi/libqrencode) 生成二维码。
* 本项目使用 [awtk-widget-generator](https://github.com/zlgopen/awtk-widget-generator) 生成代码框架。
## 准备
1. 获取 awtk 并编译
```
git clone https://github.com/zlgopen/awtk.git
cd awtk; scons; cd -
```
2. 获取 awtk-widget-qr 并编译
```
git clone https://github.com/zlgopen/awtk-widget-qr.git
cd awtk-widget-qr; scons
```
## 运行
1. 生成示例代码的资源
```
python scripts/update_res.py all
```
> 也可以使用 Designer 打开项目,之后点击 “打包” 按钮进行生成;
> 如果资源发生修改,则需要重新生成资源。
如果 PIL 没有安装,执行上述脚本可能会出现如下错误:
```cmd
Traceback (most recent call last):
...
ModuleNotFoundError: No module named 'PIL'
```
请用 pip 安装:
```cmd
pip install Pillow
```
2. 编译
* 编译PC版本
```
scons
```
* 编译LINUX FB版本
```
scons LINUX_FB=true
```
> 完整编译选项请参考[编译选项](https://github.com/zlgopen/awtk-widget-generator/blob/master/docs/build_options.md)
3. 运行
```
./bin/demo
```
## 如何使用二维码控件
### 设置需要转成二维码的字符串
qr 控件 `value` 属性内容就是转成二维码的字符串内容。
在界面描述文件设置:
```xml
<window theme="main" name="main">
<qr name="qr" x="c" y="m" w="50%" h="50%" value="https://github.com/zlgopen/awtk"/>
</window>
```
或在代码中设置:
```c
widget_t* win = window_open("main");
widget_t* qr = widget_lookup(win, "qr", TRUE);
qr_set_value(qr, "https://github.com/zlgopen/awtk");
```
按照上述例子设置完成后,用手机扫该二维码就会打开[ https://github.com/zlgopen/awtk ](https://github.com/zlgopen/awtk)网址。
### 设置二维码中的颜色与图片
添加图片资源到项目中:
![](./design/default/images/x1/message.png)
在样式文件中设置 qr 控件样式在对应状态设置 `fg_color` `bg_color``bg_image` 属性:
```xml
<qr>
<style name="default">
<!-- fg_color 为二维码颜色bg_color 为二维码背景色 -->
<normal fg_color="black" bg_color="white" bg_image="message"/>
<!-- disable 状态用于模拟 被扫描 状态 -->
<!-- 不设置 bg_image 属性,则该状态二维码中间没有图片 -->
<disable fg_color="gray" bg_color="#f0f0f0"/>
</style>
</qr>
```
从上述例子得到的效果为:
正常状态:
![](./docs/images/normal_style.png)
被扫描状态:
![](./docs/images/scanned_style.png)
**注意**:图片大小不可以大于二维码的 `45%` ,否则图片将会被裁剪:
图片资源:
![](./design/default/images/x3/message.png)
得到的二维码:
![](./docs/images/clip_image.png)
qr 控件的属性名及作用如下表所示:
| 属性名 | 作用 |
| ------ | ---------------------- |
| value | 要转换为二维码的字符串 |
## 文档
[完善自定义控件](https://github.com/zlgopen/awtk-widget-generator/blob/master/docs/improve_generated_widget.md)

View File

@ -0,0 +1,8 @@
import os
import scripts.app_helper as app
helper = app.Helper(ARGUMENTS)
helper.set_dll_def('src/qr.def').set_libs(['qr']).call(DefaultEnvironment)
SConscriptFiles = ['src/SConscript']
SConscript(SConscriptFiles)

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -0,0 +1,459 @@
<window>
<style name="default">
<normal bg_color="#ffffff"/>
</style>
</window>
<dialog>
<style name="default" border_color="#c2c2c2">
<normal bg_color="#ffffff"/>
</style>
</dialog>
<popup>
<style name="default" border_color="#c2c2c2">
<normal bg_color="#ffffff"/>
</style>
</popup>
<overlay>
<style name="default" border_color="#c2c2c2">
<normal bg_color="#ffffff"/>
</style>
</overlay>
<system_bar>
<style name="default" border="bottom" border_color="#c2c2c2">
<normal bg_color="#ffffff"/>
</style>
</system_bar>
<system_bar_bottom>
<style name="default" border="top" border_color="#c2c2c2">
<normal bg_color="#ffffff"/>
</style>
</system_bar_bottom>
<keyboard>
<style name="default" border_color="#c2c2c2">
<normal bg_color="#e1e1e1"/>
</style>
</keyboard>
<button>
<style name="default" round_radius="4">
<normal text_color="#444444" bg_color="#f4f4f4" border_color="#c2c2c2"/>
<pressed text_color="#ffffff" bg_color="#1971dd" border_color="#1971dd"/>
<over text_color="#ffffff" bg_color="#338fff" border_color="#338fff"/>
<focused text_color="#444444" bg_color="#f4f4f4" border_color="#338fff" />
<disable text_color="#44444466" bg_color="#f4f4f466" border_color="#c2c2c266" />
</style>
<style name="combobox_down" border_color="#c2c2c2" bg_color="#f2f2f2">
<normal icon="arrow_down_n"/>
<pressed icon="arrow_down_p"/>
<over icon="arrow_down_o"/>
<disable icon="arrow_down_d" border_color="#c2c2c266" bg_color="#f2f2f266"/>
</style>
<style name="spinbox_down" border_color="#c2c2c2" bg_color="#f2f2f2">
<normal icon="arrow_down_n"/>
<pressed icon="arrow_down_p"/>
<over icon="arrow_down_o"/>
<disable icon="arrow_down_d" border_color="#c2c2c266" bg_color="#f2f2f266"/>
</style>
<style name="spinbox_up" border_color="#c2c2c2" bg_color="#f2f2f2">
<normal icon="arrow_up_n"/>
<pressed icon="arrow_up_p"/>
<over icon="arrow_up_o"/>
<disable icon="arrow_up_d" border_color="#c2c2c266" bg_color="#f2f2f266"/>
</style>
<style name="spinbox_left" border_color="#c2c2c2" bg_color="#f2f2f2">
<normal icon="arrow_left_n"/>
<pressed icon="arrow_left_p"/>
<over icon="arrow_left_o"/>
<disable icon="arrow_left_d" border_color="#c2c2c266" bg_color="#f2f2f266"/>
</style>
<style name="spinbox_right" border_color="#c2c2c2" bg_color="#f2f2f2">
<normal icon="arrow_right_n"/>
<pressed icon="arrow_right_p"/>
<over icon="arrow_right_o"/>
<disable icon="arrow_right_d" border_color="#c2c2c266" bg_color="#f2f2f266"/>
</style>
<style name="scroll_down" bg_color="#f2f2f2">
<normal icon="arrow_down_n"/>
<pressed icon="arrow_down_p"/>
<over icon="arrow_down_o"/>
<disable icon="arrow_down_d" border_color="#c2c2c266" bg_color="#f2f2f266"/>
</style>
<style name="scroll_up" bg_color="#f2f2f2">
<normal icon="arrow_up_n"/>
<pressed icon="arrow_up_p"/>
<over icon="arrow_up_o"/>
<disable icon="arrow_up_d" bg_color="#f2f2f266"/>
</style>
<style name="scroll_left" bg_color="#f2f2f2">
<normal icon="arrow_left_n"/>
<pressed icon="arrow_left_p"/>
<over icon="arrow_left_o"/>
<disable icon="arrow_left_d" bg_color="#f2f2f266"/>
</style>
<style name="scroll_right" bg_color="#f2f2f2">
<normal icon="arrow_right_n"/>
<pressed icon="arrow_right_p"/>
<over icon="arrow_right_o"/>
<disable icon="arrow_right_d" bg_color="#f2f2f266"/>
</style>
</button>
<edit selected_text_color="#010101" selected_bg_color="#b5d7fd">
<style name="default" bg_color="#f7f7f7" text_color="#444444" text_align_h="left">
<normal border_color="#c2c2c2"/>
<focused border_color="#338fff"/>
<disable bg_color="#f7f7f766" border_color="#c2c2c266" text_color="#44444466" />
<error border_color="#ff0000" />
<empty border_color="#c2c2c2" text_color="#959494"/>
<empty_focus border_color="#c2c2c2" text_color="#959494"/>
<over border_color="#338fff"/>
</style>
</edit>
<spin_box selected_text_color="#010101" selected_bg_color="#b5d7fd">
<style name="default" bg_color="#f7f7f7" text_color="#444444" text_align_h="left">
<normal border_color="#c2c2c2"/>
<focused border_color="#338fff"/>
<disable bg_color="#f7f7f766" border_color="#c2c2c266" text_color="#44444466"/>
<error border_color="#ff0000"/>
<empty border_color="#c2c2c2" text_color="#959494"/>
<empty_focus border_color="#c2c2c2" text_color="#959494"/>
<over border_color="#338fff"/>
<has_value has_value="1"/>
</style>
</spin_box>
<digit_clock>
<style name="default">
<normal text_color="#444444" />
</style>
</digit_clock>
<label>
<style name="default">
<normal text_color="#444444"/>
<disable text_color="#44444466"/>
</style>
</label>
<progress_bar>
<style name="default" round_radius="5">
<normal text_color="#444444" bg_color="#d8d8d8" fg_color="#338fff" border_color="#d8d8d8"/>
<disable text_color="#44444466" bg_color="#d8d8d866" fg_color="#338fff66" border_color="#d8d8d866"/>
</style>
</progress_bar>
<slider>
<style name="default" round_radius="5">
<normal bg_color="#d8d8d8" fg_color="#338fff" border_color="#bfbfbf"/>
<pressed bg_color="#d8d8d8" fg_color="#338fff" border_color="#1456d6"/>
<over bg_color="#d8d8d8" fg_color="#338fff" border_color="#54d8ff"/>
<focused bg_color="#d8d8d8" fg_color="#338fff" border_color="#54d8ff"/>
<disable bg_color="#d8d8d866" fg_color="#338fff66" border_color="#ececec"/>
</style>
</slider>
<check_button>
<style name="default" icon_at="left" text_color="#444444">
<normal icon="check_unchecked" />
<pressed icon="check_unchecked" />
<over icon="check_unchecked" />
<focused icon="check_unchecked" />
<disable icon="check_unchecked_d" text_color="#44444466"/>
<normal_of_checked icon="check_checked" />
<pressed_of_checked icon="check_checked" />
<over_of_checked icon="check_checked" />
<focused_of_checked icon="check_checked" />
<disable_of_checked icon="check_checked_d" text_color="#44444466"/>
</style>
</check_button>
<radio_button>
<style name="default" text_color="#444444" icon_at="left">
<normal icon="radio_unchecked" />
<pressed icon="radio_unchecked" />
<over icon="radio_unchecked" />
<focused icon="radio_unchecked" />
<disable icon="radio_unchecked_d" text_color="#44444466"/>
<normal_of_checked icon="radio_checked"/>
<pressed_of_checked icon="radio_checked"/>
<over_of_checked icon="radio_checked"/>
<focused_of_checked icon="radio_checked" />
<disable_of_checked icon="radio_checked_d" text_color="#44444466"/>
</style>
</radio_button>
<image>
<style name="default" text_color="#444444">
<normal />
</style>
</image>
<scroll_bar_m>
<style name="default">
<normal fg_color="#808080"/>
<disable fg_color="#80808066"/>
</style>
</scroll_bar_m>
<scroll_bar_d>
<style name="default" border_color="#bebebe">
<normal bg_color="#f0f0f0"/>
<over bg_color="#f0f0f0" />
<pressed bg_color="#f0f0f0" />
<disable bg_color="#f0f0f066" border_color="#bebebe66"/>
</style>
</scroll_bar_d>
<dragger>
<style name="default" bg_color="#9e9e9e">
<normal />
<pressed />
<over />
</style>
<style name="scroll_bar">
<normal bg_color="#d0d0d0" />
<pressed bg_color="#c0c0c0" />
<over bg_color="#c0c0c0" />
<disable bg_color="#c0c0c066" />
</style>
</dragger>
<list_item>
<style name="default" border_color="#e9e9e9" text_color="#444444">
<normal bg_color="#ffffff" />
<pressed bg_color="#338fff" text_color="#ffffff" />
<over bg_color="#ffffff" border_color="#338fff"/>
<disable border_color="#e9e9e966" text_color="#44444466"/>
</style>
</list_item>
<tab_button>
<style name="default" border_color="#c2c2c2" text_color="#444444">
<normal bg_color="#f4f4f4" />
<pressed bg_color="#cecdcd" />
<over bg_color="#ffffff" text_color="#1971dd"/>
<normal_of_active bg_color="#ffffff" border="top|left|right"/>
<pressed_of_active bg_color="#ffffff" text_color="#1971dd" border="top|left|right"/>
<over_of_active bg_color="#ffffff" text_color="#1971dd" border="top|left|right"/>
<disable_of_active border_color="#c2c2c266" bg_color="#f4f4f466" text_color="#44444466" border="top|left|right"/>
<disable border_color="#c2c2c266" bg_color="#f4f4f466" text_color="#44444466"/>
</style>
</tab_button>
<tab_button_group >
<style name="default">
<normal/>
</style>
<style name="scrollable" border_color="#a0a0a0" border="left|right">
<normal/>
</style>
</tab_button_group>
<combo_box selected_text_color="#010101" selected_bg_color="#b5d7fd">
<style name="default" bg_color="#f7f7f7" text_color="#444444" text_align_h="left" border_color="#c2c2c2">
<normal border_color="#c2c2c2"/>
<focused border_color="#338fff"/>
<disable bg_color="#f7f7f766" border_color="#c2c2c266" text_color="#44444466"/>
<error border_color="#ff0000"/>
<empty border_color="#c2c2c2" text_color="#959494"/>
<empty_focus border_color="#c2c2c2" text_color="#959494"/>
<over border_color="#338fff"/>
</style>
</combo_box>
<combo_box_ex selected_text_color="#010101" selected_bg_color="#b5d7fd">
<style name="default" bg_color="#f7f7f7" text_color="#444444" text_align_h="left" border_color="#c2c2c2">
<normal border_color="#c2c2c2"/>
<focused border_color="#338fff"/>
<disable bg_color="#f7f7f766" border_color="#c2c2c266" text_color="#44444466"/>
<error border_color="#ff0000"/>
<empty border_color="#c2c2c2" text_color="#959494"/>
<empty_focus border_color="#c2c2c2" text_color="#959494"/>
<over border_color="#338fff"/>
</style>
</combo_box_ex>
<combo_box_item>
<style name="default" icon_at="left" text_color="#444444" bg_color="#ffffff">
<normal />
<pressed bg_color="#338fff" text_color="#ffffff" />
<over bg_color="#1971dd" text_color="#ffffff" />
<focused bg_color="#1296db" text_color="#ffffff" />
<normal_of_checked bg_color="#338fff" text_color="#ffffff"/>
<focused_of_checked bg_color="#338fff" text_color="#ffffff"/>
<pressed_of_checked bg_color="#338fff" text_color="#ffffff" />
<over_of_checked bg_color="#1971dd" text_color="#ffffff" />
<disable_of_checked bg_color="#f4f4f466" text_color="#44444466" />
<disable bg_color="#f4f4f466" text_color="#44444466"/>
</style>
</combo_box_item>
<text_selector>
<style name="default" fg_color="#c2c2c2" text_color="#444444" text_align_h="center" bg_color="#ffffff">
<normal mask_color="#404040" border_color="#c2c2c2"/>
<disable mask_color="#c0c0c0" border_color="#c2c2c266" text_color="#44444466" />
</style>
</text_selector>
<switch>
<style name="default" margin="2" round_radius="11" fg_color="#ffffff">
<normal bg_color="#828282" selected_bg_color="#338fff"/>
<disable bg_color="#82828266" selected_bg_color="#338fff66"/>
</style>
</switch>
<slide_indicator>
<style name="default">
<normal fg_color="#338fff40" selected_fg_color="#338fff"/>
<disable fg_color="#338fff20" selected_fg_color="#338fff66"/>
</style>
</slide_indicator>
<slide_indicator_arc>
<style name="default">
<normal fg_color="#338fff40" selected_fg_color="#338fff"/>
<disable fg_color="#338fff20" selected_fg_color="#338fff66"/>
</style>
</slide_indicator_arc>
<progress_circle>
<style name="default">
<normal text_color="#444444" fg_color="#338fff"/>
<disable text_color="#44444466" fg_color="#338fff66"/>
</style>
</progress_circle>
<svg>
<style name="default" text_color="#444444">
<normal/>
</style>
</svg>
<gif>
<style name="default">
<normal/>
</style>
</gif>
<slide_menu>
<style name="default">
<normal/>
</style>
</slide_menu>
<mledit selected_fg_color="#020202" selected_text_color="#010101" selected_bg_color="#b5d7fd">
<style name="default" border_color="#a0a0a0" text_color="#444444" text_align_h="left">
<normal bg_color="#ffffff" />
<focused bg_color="#ffffff"/>
<disable bg_color="gray" text_color="#44444466" />
<error bg_color="#ffffff" text_color="red" />
<empty bg_color="#ffffff" text_color="#a0a0a0" />
<empty_focus bg_color="#ffffff" text_color="#a0a0a0"/>
</style>
</mledit>
<line_number>
<style name="default" text_align_h="center">
<normal text_color="#444444" bg_color="#d0d0d0"/>
<disable text_color="#44444466" bg_color="#d0d0d066"/>
</style>
</line_number>
<hscroll_label>
<style name="default" text_color="#444444">
<normal />
<disable text_color="#44444466"/>
</style>
</hscroll_label>
<color_tile>
<style name="default">
<normal border_color="#c2c2c2"/>
<focused border_color="#338fff"/>
<disable border_color="#c2c2c266"/>
</style>
</color_tile>
<view>
<style name="default">
<normal />
</style>
</view>
<tab_control>
<style name="default">
<normal />
</style>
</tab_control>
<scroll_view>
<style name="default">
<normal />
</style>
</scroll_view>
<list_view>
<style name="default" border_color="#c2c2c2" bg_color="#f4f4f4">
<normal />
<disable border_color="#c2c2c266" bg_color="#f4f4f466"/>
</style>
</list_view>
<list_view_h>
<style name="default" border_color="#c2c2c2" bg_color="#f4f4f4">
<normal />
<disable border_color="#c2c2c266" bg_color="#f4f4f466"/>
</style>
</list_view_h>
<pages>
<style name="default" border_color="#c2c2c2">
<normal />
</style>
</pages>
<slide_view>
<style name="default">
<normal />
</style>
</slide_view>
<color_picker>
<style name="default">
<normal />
</style>
</color_picker>
<color_component>
<style name="default" border_color="#c2c2c2">
<normal />
</style>
</color_component>
<candidates>
<style name="default" text_color="#444444" bg_color="#fafafa">
<normal />
</style>
</candidates>

View File

@ -0,0 +1,6 @@
<qr>
<style name="default" >
<normal fg_color="black" bg_color="white" bg_image="message"/>
<disable fg_color="gray" bg_color="#f0f0f0"/>
</style>
</qr>

View File

@ -0,0 +1,4 @@
<window theme="main">
<qr x="c" y="m" w="240" h="240" value="https://github.com/zlgopen/awtk"/>
<button x="c" y="b:30" w="80" h="30" name="close" text="Close"/>
</window>

View File

@ -0,0 +1,6 @@
### 2021/11/25
* 去除没有使用到的宏和变量(感谢兆坤提供补丁)
* 修复logo裁剪区域未还原导致的界面显示问题感谢兆坤提供补丁
### 2021/10/26
* 中间支持LOGO感谢兆坤提供补丁

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

View File

@ -0,0 +1,6 @@
find src -name \*.c -exec clang-format -i {} \;
find src -name \*.h -exec clang-format -i {} \;
find src -name \*.cc -exec clang-format -i {} \;
find src -name \*.cpp -exec clang-format -i {} \;
find src -name \*.inc -exec clang-format -i {} \;

View File

@ -0,0 +1,3 @@
node ../awtk/tools/idl_gen/index.js idl/idl.json src/
node ../awtk/tools/dll_def_gen/index.js idl/idl.json src/qr.def

View File

@ -0,0 +1,154 @@
[
{
"params": [],
"annotation": {
"global": true
},
"desc": "注册控件。",
"name": "qr_register",
"return": {
"type": "ret_t",
"desc": "返回RET_OK表示成功否则表示失败。"
},
"type": "method",
"header": "src/qr_register.h",
"level": 1
},
{
"params": [],
"annotation": {
"global": true
},
"desc": "获取支持的渲染模式。",
"name": "qr_supported_render_mode",
"return": {
"type": "const char*",
"desc": "返回渲染模式。"
},
"type": "method",
"header": "src/qr_register.h",
"level": 1
},
{
"type": "class",
"methods": [
{
"params": [
{
"type": "widget_t*",
"name": "parent",
"desc": "父控件"
},
{
"type": "xy_t",
"name": "x",
"desc": "x坐标"
},
{
"type": "xy_t",
"name": "y",
"desc": "y坐标"
},
{
"type": "wh_t",
"name": "w",
"desc": "宽度"
},
{
"type": "wh_t",
"name": "h",
"desc": "高度"
}
],
"annotation": {
"constructor": true,
"scriptable": true
},
"desc": "创建qr对象",
"name": "qr_create",
"return": {
"type": "widget_t*",
"desc": "qr对象。"
}
},
{
"params": [
{
"type": "widget_t*",
"name": "widget",
"desc": "qr对象。"
}
],
"annotation": {
"cast": true,
"scriptable": true
},
"desc": "转换为qr对象(供脚本语言使用)。",
"name": "qr_cast",
"return": {
"type": "widget_t*",
"desc": "qr对象。"
}
},
{
"params": [
{
"type": "widget_t*",
"name": "widget",
"desc": "widget对象。"
},
{
"type": "const char*",
"name": "value",
"desc": "格式字符串。"
}
],
"annotation": {
"scriptable": true
},
"desc": "设置要转成二维码的字符串。",
"name": "new_qr_set_value",
"return": {
"type": "ret_t",
"desc": "返回RET_OK表示成功否则表示失败。"
}
},
{
"params": [],
"annotation": {},
"desc": "获取 qr 虚表。",
"name": "qr_get_widget_vtable",
"return": {
"type": "const widget_vtable_t*",
"desc": "成功返回 qr 虚表。"
}
}
],
"events": [],
"properties": [
{
"name": "value",
"desc": "要转成二维码的字符串。值。",
"type": "char*",
"annotation": {
"set_prop": true,
"get_prop": true,
"readable": true,
"persitent": true,
"design": true,
"scriptable": true
}
}
],
"header": "qr/qr.h",
"desc": "显示二维码的控件\nqr\\_t是[widget\\_t](widget_t.md)的子类控件widget\\_t的函数均适用于qr\\_t控件。\n\n在xml中使用\"qr\"标签创建数值文本控件。如:\n\n```xml\n<!-- ui -->\n<qr x=\"c\" y=\"m\" w=\"240\" h=\"240\" value=\"https://github.com/zlgopen/awtk\"/>\n```\n在c代码中使用函数qr\\_create创建数值文本控件。如\n\n```c\nwidget_t* qr = qr_create(win, 10, 10, 128, 128);\n```\n可用通过style来设置控件的显示风格如字体的大小和颜色等等。如\n\n```xml\n<!-- style -->\n<qr>\n<style name=\"default\" >\n<normal fg_color=\"black\" bg_color=\"white\" bg_image=\"message\"/>\n<disable fg_color=\"gray\" bg_color=\"#f0f0f0\"/>\n</style>\n</qr>\n```",
"name": "qr_t",
"parent": "widget_t",
"annotation": {
"scriptable": true,
"design": true,
"widget": true
},
"level": 2
}
]

View File

@ -0,0 +1,46 @@
{
"name": "qr",
"version": "1.0.1",
"date": "2020-06-01",
"team": "AWTK Develop Team",
"author": "Li XianJing <xianjimli@hotmail.com>",
"desc": "显示二维码的控件",
"copyright": "Guangzhou ZHIYUAN Electronics Co.,Ltd.",
"type": "PROJECT_CUSTOM_WIDGET",
"entry": "main",
"assets": {
"activedTheme": "default",
"outputDir": "res",
"loadFrom": "any",
"const": "resource_data",
"screenDPR": "x1",
"defaultLanguage": "zh",
"defaultCountry": "CN",
"themes": {
"default": {
"activedSystemBar": "system_bar",
"activedBottomSystemBar": "system_bar_b",
"packaged": true,
"fonts": {
"default": {
"text": " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~,。?!确定取消"
}
},
"lcd": {
"width": "320",
"height": "480",
"colorDepth": "16bit",
"colorFormat": "BGR(A)"
}
}
}
},
"creator": {
"name": "AWTK Designer",
"version": "2.0.21"
},
"awtkRoot": "${AWTK_SDK_PATH}/awtk",
"dependencies": {
"awtk": ">=2112"
}
}

View File

@ -0,0 +1,2 @@
__pycache__
*.pyc

View File

@ -0,0 +1,7 @@
import os
import sys
APP_SCRIPTS_ROOT = os.path.abspath(os.path.dirname(__file__))
print('APP_SCRIPTS_ROOT:' + APP_SCRIPTS_ROOT)
sys.path.insert(0, APP_SCRIPTS_ROOT)

View File

@ -0,0 +1,7 @@
import awtk_locator as locator
def Helper(ARGUMENTS):
locator.init(ARGUMENTS)
from app_helper_base import AppHelperBase
return AppHelperBase(ARGUMENTS)

View File

@ -0,0 +1,62 @@
import os
import sys
AWTK_ROOT = ''
def getAwtkRoot():
return AWTK_ROOT
def getAwtkSDKPath():
env = os.environ
if 'AWTK_SDK_PATH' in env:
return env['AWTK_SDK_PATH']
else:
return ''
def getAwtkOrAwtkLinuxFbRoot(is_linux_fb):
if is_linux_fb:
return locateAWTK('awtk-linux-fb')
else:
return locateAWTK('awtk')
def locateAWTK(awtk):
awtk_root = ''
if not os.path.exists(awtk_root):
dirnames = ['../'+awtk, '../../'+awtk, '../../../'+awtk]
for dirname in dirnames:
if os.path.exists(dirname):
awtk_root = dirname
break
if not os.path.exists(awtk_root):
awtk_sdk_path = getAwtkSDKPath();
if os.path.exists(awtk_sdk_path):
awtk_root = awtk_sdk_path + '/' + awtk
return os.path.abspath(awtk_root)
def init(ARGUMENTS = None):
global AWTK_ROOT
global LINUX_FB
if ARGUMENTS:
AWTK_ROOT = ARGUMENTS.get('AWTK_ROOT', '')
LINUX_FB = ARGUMENTS.get('LINUX_FB', '')
else:
LINUX_FB = ''
if not os.path.exists(AWTK_ROOT):
AWTK_ROOT = getAwtkOrAwtkLinuxFbRoot(LINUX_FB != '')
elif os.path.exists(LINUX_FB):
print(' do not set LINUX_FB and AWTK_ROOT !!!')
sys.exit()
if LINUX_FB:
AWTK_SCRIPTS_ROOT = os.path.join(AWTK_ROOT, '../awtk/scripts')
else:
AWTK_SCRIPTS_ROOT = os.path.join(AWTK_ROOT, 'scripts')
sys.path.insert(0, AWTK_SCRIPTS_ROOT)
print('AWTK_ROOT: ' + AWTK_ROOT)
print('AWTK_SCRIPTS_ROOT: ' + AWTK_SCRIPTS_ROOT)

View File

@ -0,0 +1,41 @@
import sys
import awtk_locator as locator
LONGSOPTS = ['awtk_root=', 'AWTK_ROOT=']
def get_args(args, longsopts = []) :
list_opts = []
for arg in args:
if arg.startswith('--') :
tmp_opt = '';
for opt in longsopts:
if arg.find(opt) > 0 :
tmp_opt = opt;
break
if tmp_opt != '' :
list_opts.append(arg.split(tmp_opt)[1])
continue
else :
print(arg + " not find command, command :")
print(longsopts)
sys.exit()
return list_opts
def update_res(ARGUMENTS, is_new_usage):
locator.init(ARGUMENTS)
import update_res_app as updater
if is_new_usage and not hasattr(updater, "getopt") :
print(" must update awtk !!!")
sys.exit()
updater.run(locator.getAwtkRoot())
is_new_usage = False
opts = get_args(sys.argv[1:], LONGSOPTS)
ARGUMENTS = dict()
if len(opts) > 0 :
is_new_usage = True
ARGUMENTS['AWTK_ROOT'] = opts[0]
else :
ARGUMENTS['AWTK_ROOT'] = ''
update_res(ARGUMENTS, is_new_usage)

View File

@ -0,0 +1,22 @@
import os
import sys
import platform
OS_NAME = platform.system();
LIB_DIR=os.environ['LIB_DIR'];
BIN_DIR=os.environ['BIN_DIR'];
env=DefaultEnvironment().Clone()
SOURCES=Glob('qr/*.cpp') + Glob('qr/*.c') + Glob('*.c')
EXPORT_DEF=''
if OS_NAME == 'Windows' and os.environ['TOOLS_NAME'] == '':
EXPORT_DEF = ' /DEF:"src/qr.def" '
if 'BUILD_SHARED' in os.environ and os.environ['BUILD_SHARED'] == 'True':
LIBS=['awtk'];
LINKFLAGS=env['LINKFLAGS'] + EXPORT_DEF
env.SharedLibrary(os.path.join(BIN_DIR, 'qr'), SOURCES, LIBS=LIBS, LINKFLAGS=LINKFLAGS);
else:
env.Library(os.path.join(LIB_DIR, 'qr'), SOURCES);

View File

@ -0,0 +1,8 @@
LIBRARY qr
EXPORTS
qr_register
qr_supported_render_mode
qr_create
qr_cast
new_qr_set_value
qr_get_widget_vtable

View File

@ -0,0 +1,229 @@
/*
* qrencode - QR Code encoder
*
* Binary sequence class.
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
# include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bitstream.h"
#define DEFAULT_BUFSIZE (128)
BitStream *BitStream_new(void)
{
BitStream *bstream;
bstream = (BitStream *)TKMEM_ALLOC(sizeof(BitStream));
if(bstream == NULL) return NULL;
bstream->length = 0;
bstream->data = (unsigned char *)TKMEM_ALLOC(DEFAULT_BUFSIZE);
if(bstream->data == NULL) {
tk_free(bstream);
return NULL;
}
bstream->datasize = DEFAULT_BUFSIZE;
return bstream;
}
#ifdef WITH_TESTS
BitStream *BitStream_newWithBits(size_t size, unsigned char *bits)
{
BitStream *bstream;
if(size == 0) return BitStream_new();
bstream = (BitStream *)TKMEM_ALLOC(sizeof(BitStream));
if(bstream == NULL) return NULL;
bstream->data = (unsigned char *)TKMEM_ALLOC(size);
if(bstream->data == NULL) {
tk_free(bstream);
return NULL;
}
bstream->length = size;
bstream->datasize = size;
memcpy(bstream->data, bits, size);
return bstream;
}
#endif
static int BitStream_expand(BitStream *bstream)
{
unsigned char *data;
data = (unsigned char *)TKMEM_REALLOC(bstream->data, bstream->datasize * 2);
if(data == NULL) {
return -1;
}
bstream->data = data;
bstream->datasize *= 2;
return 0;
}
static void BitStream_writeNum(unsigned char *dest, size_t bits, unsigned int num)
{
unsigned int mask;
size_t i;
unsigned char *p;
p = dest;
mask = 1U << (bits - 1);
for(i = 0; i < bits; i++) {
if(num & mask) {
*p = 1;
} else {
*p = 0;
}
p++;
mask = mask >> 1;
}
}
static void BitStream_writeBytes(unsigned char *dest, size_t size, unsigned char *data)
{
unsigned char mask;
size_t i, j;
unsigned char *p;
p = dest;
for(i = 0; i < size; i++) {
mask = 0x80;
for(j = 0; j < 8; j++) {
if(data[i] & mask) {
*p = 1;
} else {
*p = 0;
}
p++;
mask = mask >> 1;
}
}
}
int BitStream_append(BitStream *bstream, BitStream *arg)
{
int ret;
if(arg == NULL) {
return -1;
}
if(arg->length == 0) {
return 0;
}
while(bstream->length + arg->length > bstream->datasize) {
ret = BitStream_expand(bstream);
if(ret < 0) return ret;
}
memcpy(bstream->data + bstream->length, arg->data, arg->length);
bstream->length += arg->length;
return 0;
}
int BitStream_appendNum(BitStream *bstream, size_t bits, unsigned int num)
{
int ret;
if(bits == 0) return 0;
while(bstream->datasize - bstream->length < bits) {
ret = BitStream_expand(bstream);
if(ret < 0) return ret;
}
BitStream_writeNum(bstream->data + bstream->length, bits, num);
bstream->length += bits;
return 0;
}
int BitStream_appendBytes(BitStream *bstream, size_t size, unsigned char *data)
{
int ret;
if(size == 0) return 0;
while(bstream->datasize - bstream->length < size * 8) {
ret = BitStream_expand(bstream);
if(ret < 0) return ret;
}
BitStream_writeBytes(bstream->data + bstream->length, size, data);
bstream->length += size * 8;
return 0;
}
unsigned char *BitStream_toByte(BitStream *bstream)
{
size_t i, j, size, bytes, oddbits;
unsigned char *data, v;
unsigned char *p;
size = BitStream_size(bstream);
if(size == 0) {
return NULL;
}
data = (unsigned char *)TKMEM_ALLOC((size + 7) / 8);
if(data == NULL) {
return NULL;
}
bytes = size / 8;
p = bstream->data;
for(i = 0; i < bytes; i++) {
v = 0;
for(j = 0; j < 8; j++) {
v = (unsigned char)(v << 1);
v |= *p;
p++;
}
data[i] = v;
}
oddbits = size & 7;
if(oddbits > 0) {
v = 0;
for(j = 0; j < oddbits; j++) {
v = (unsigned char)(v << 1);
v |= *p;
p++;
}
data[bytes] = (unsigned char)(v << (8 - oddbits));
}
return data;
}
void BitStream_free(BitStream *bstream)
{
if(bstream != NULL) {
tk_free(bstream->data);
tk_free(bstream);
}
}

View File

@ -0,0 +1,43 @@
/*
* qrencode - QR Code encoder
*
* Binary sequence class.
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef BITSTREAM_H
#define BITSTREAM_H
typedef struct {
size_t length;
size_t datasize;
unsigned char *data;
} BitStream;
extern BitStream *BitStream_new(void);
#ifdef WITH_TESTS
extern BitStream *BitStream_newWithBits(size_t size, unsigned char *bits);
#endif
extern int BitStream_append(BitStream *bstream, BitStream *arg);
extern int BitStream_appendNum(BitStream *bstream, size_t bits, unsigned int num);
extern int BitStream_appendBytes(BitStream *bstream, size_t size, unsigned char *data);
#define BitStream_size(__bstream__) (__bstream__->length)
#define BitStream_reset(__bstream__) (__bstream__->length = 0)
extern unsigned char *BitStream_toByte(BitStream *bstream);
extern void BitStream_free(BitStream *bstream);
#endif /* BITSTREAM_H */

View File

@ -0,0 +1,13 @@
#ifndef QRENCODER_CONFIG_H
#define QRENCODER_CONFIG_H
#include "awtk.h"
#include "tkc/mem.h"
#define STATIC_IN_RELEASE static
#define MAJOR_VERSION 4
#define MINOR_VERSION 1
#define MICRO_VERSION 0
#define VERSION "1.0"
#endif/*QRENCODER_CONFIG_H*/

View File

@ -0,0 +1,354 @@
/*
* qrencode - QR Code encoder
*
* Masking.
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
# include "config.h"
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <errno.h>
#include "qrencode.h"
#include "qrspec.h"
#include "mask.h"
STATIC_IN_RELEASE int Mask_writeFormatInformation(int width, unsigned char *frame, int mask, QRecLevel level)
{
unsigned int format;
unsigned char v;
int i;
int blacks = 0;
format = QRspec_getFormatInfo(mask, level);
for(i = 0; i < 8; i++) {
if(format & 1) {
blacks += 2;
v = 0x85;
} else {
v = 0x84;
}
frame[width * 8 + width - 1 - i] = v;
if(i < 6) {
frame[width * i + 8] = v;
} else {
frame[width * (i + 1) + 8] = v;
}
format= format >> 1;
}
for(i = 0; i < 7; i++) {
if(format & 1) {
blacks += 2;
v = 0x85;
} else {
v = 0x84;
}
frame[width * (width - 7 + i) + 8] = v;
if(i == 0) {
frame[width * 8 + 7] = v;
} else {
frame[width * 8 + 6 - i] = v;
}
format= format >> 1;
}
return blacks;
}
/**
* Demerit coefficients.
* See Section 8.8.2, pp.45, JIS X0510:2004.
*/
#define N1 (3)
#define N2 (3)
#define N3 (40)
#define N4 (10)
#define MASKMAKER(__exp__) \
int x, y;\
int b = 0;\
\
for(y = 0; y < width; y++) {\
for(x = 0; x < width; x++) {\
if(*s & 0x80) {\
*d = *s;\
} else {\
*d = *s ^ ((__exp__) == 0);\
}\
b += (int)(*d & 1);\
s++; d++;\
}\
}\
return b;
static int Mask_mask0(int width, const unsigned char *s, unsigned char *d)
{
MASKMAKER((x+y)&1)
}
static int Mask_mask1(int width, const unsigned char *s, unsigned char *d)
{
MASKMAKER(y&1)
}
static int Mask_mask2(int width, const unsigned char *s, unsigned char *d)
{
MASKMAKER(x%3)
}
static int Mask_mask3(int width, const unsigned char *s, unsigned char *d)
{
MASKMAKER((x+y)%3)
}
static int Mask_mask4(int width, const unsigned char *s, unsigned char *d)
{
MASKMAKER(((y/2)+(x/3))&1)
}
static int Mask_mask5(int width, const unsigned char *s, unsigned char *d)
{
MASKMAKER(((x*y)&1)+(x*y)%3)
}
static int Mask_mask6(int width, const unsigned char *s, unsigned char *d)
{
MASKMAKER((((x*y)&1)+(x*y)%3)&1)
}
static int Mask_mask7(int width, const unsigned char *s, unsigned char *d)
{
MASKMAKER((((x*y)%3)+((x+y)&1))&1)
}
#define maskNum (8)
typedef int MaskMaker(int, const unsigned char *, unsigned char *);
static MaskMaker *maskMakers[maskNum] = {
Mask_mask0, Mask_mask1, Mask_mask2, Mask_mask3,
Mask_mask4, Mask_mask5, Mask_mask6, Mask_mask7
};
#ifdef WITH_TESTS
unsigned char *Mask_makeMaskedFrame(int width, unsigned char *frame, int mask)
{
unsigned char *masked;
masked = (unsigned char *)TKMEM_ALLOC((size_t)(width * width));
if(masked == NULL) return NULL;
maskMakers[mask](width, frame, masked);
return masked;
}
#endif
unsigned char *Mask_makeMask(int width, unsigned char *frame, int mask, QRecLevel level)
{
unsigned char *masked;
if(mask < 0 || mask >= maskNum) {
return NULL;
}
masked = (unsigned char *)TKMEM_ALLOC((size_t)(width * width));
if(masked == NULL) return NULL;
maskMakers[mask](width, frame, masked);
Mask_writeFormatInformation(width, masked, mask, level);
return masked;
}
//static int n1;
//static int n2;
//static int n3;
//static int n4;
STATIC_IN_RELEASE int Mask_calcN1N3(int length, int *runLength)
{
int i;
int demerit = 0;
int fact;
for(i = 0; i < length; i++) {
if(runLength[i] >= 5) {
demerit += N1 + (runLength[i] - 5);
//n1 += N1 + (runLength[i] - 5);
}
if((i & 1)) {
if(i >= 3 && i < length-2 && (runLength[i] % 3) == 0) {
fact = runLength[i] / 3;
if(runLength[i-2] == fact &&
runLength[i-1] == fact &&
runLength[i+1] == fact &&
runLength[i+2] == fact) {
if(i == 3 || runLength[i-3] >= 4 * fact) {
demerit += N3;
//n3 += N3;
} else if(i+4 >= length || runLength[i+3] >= 4 * fact) {
demerit += N3;
//n3 += N3;
}
}
}
}
}
return demerit;
}
STATIC_IN_RELEASE int Mask_calcN2(int width, unsigned char *frame)
{
int x, y;
unsigned char *p;
unsigned char b22, w22;
int demerit = 0;
p = frame + width + 1;
for(y = 1; y < width; y++) {
for(x = 1; x < width; x++) {
b22 = p[0] & p[-1] & p[-width] & p [-width-1];
w22 = p[0] | p[-1] | p[-width] | p [-width-1];
if((b22 | (w22 ^ 1))&1) {
demerit += N2;
}
p++;
}
p++;
}
return demerit;
}
STATIC_IN_RELEASE int Mask_calcRunLengthH(int width, unsigned char *frame, int *runLength)
{
int head;
int i;
unsigned char prev;
if(frame[0] & 1) {
runLength[0] = -1;
head = 1;
} else {
head = 0;
}
runLength[head] = 1;
prev = frame[0];
for(i = 1; i < width; i++) {
if((frame[i] ^ prev) & 1) {
head++;
runLength[head] = 1;
prev = frame[i];
} else {
runLength[head]++;
}
}
return head + 1;
}
STATIC_IN_RELEASE int Mask_calcRunLengthV(int width, unsigned char *frame, int *runLength)
{
int head;
int i;
unsigned char prev;
if(frame[0] & 1) {
runLength[0] = -1;
head = 1;
} else {
head = 0;
}
runLength[head] = 1;
prev = frame[0];
for(i = 1; i < width; i++) {
if((frame[i * width] ^ prev) & 1) {
head++;
runLength[head] = 1;
prev = frame[i * width];
} else {
runLength[head]++;
}
}
return head + 1;
}
STATIC_IN_RELEASE int Mask_evaluateSymbol(int width, unsigned char *frame)
{
int x, y;
int demerit = 0;
int runLength[QRSPEC_WIDTH_MAX + 1];
int length;
demerit += Mask_calcN2(width, frame);
for(y = 0; y < width; y++) {
length = Mask_calcRunLengthH(width, frame + y * width, runLength);
demerit += Mask_calcN1N3(length, runLength);
}
for(x = 0; x < width; x++) {
length = Mask_calcRunLengthV(width, frame + x, runLength);
demerit += Mask_calcN1N3(length, runLength);
}
return demerit;
}
unsigned char *Mask_mask(int width, unsigned char *frame, QRecLevel level)
{
int i;
unsigned char *mask, *bestMask;
int minDemerit = INT_MAX;
int blacks;
int bratio;
int demerit;
int w2 = width * width;
mask = (unsigned char *)TKMEM_ALLOC((size_t)w2);
if(mask == NULL) return NULL;
bestMask = (unsigned char *)TKMEM_ALLOC((size_t)w2);
if(bestMask == NULL) {
tk_free(mask);
return NULL;
}
for(i = 0; i < maskNum; i++) {
// n1 = n2 = n3 = n4 = 0;
demerit = 0;
blacks = maskMakers[i](width, frame, mask);
blacks += Mask_writeFormatInformation(width, mask, i, level);
bratio = (200 * blacks + w2) / w2 / 2; /* (int)(100*blacks/w2+0.5) */
demerit = (abs(bratio - 50) / 5) * N4;
// n4 = demerit;
demerit += Mask_evaluateSymbol(width, mask);
// printf("(%d,%d,%d,%d)=%d\n", n1, n2, n3 ,n4, demerit);
if(demerit < minDemerit) {
minDemerit = demerit;
memcpy(bestMask, mask, (size_t)w2);
}
}
tk_free(mask);
return bestMask;
}

View File

@ -0,0 +1,38 @@
/*
* qrencode - QR Code encoder
*
* Masking.
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef MASK_H
#define MASK_H
extern unsigned char *Mask_makeMask(int width, unsigned char *frame, int mask, QRecLevel level);
extern unsigned char *Mask_mask(int width, unsigned char *frame, QRecLevel level);
#ifdef WITH_TESTS
extern int Mask_calcN2(int width, unsigned char *frame);
extern int Mask_calcN1N3(int length, int *runLength);
extern int Mask_calcRunLengthH(int width, unsigned char *frame, int *runLength);
extern int Mask_calcRunLengthV(int width, unsigned char *frame, int *runLength);
extern int Mask_evaluateSymbol(int width, unsigned char *frame);
extern int Mask_writeFormatInformation(int width, unsigned char *frame, int mask, QRecLevel level);
extern unsigned char *Mask_makeMaskedFrame(int width, unsigned char *frame, int mask);
#endif
#endif /* MASK_H */

View File

@ -0,0 +1,174 @@
/*
* qrencode - QR Code encoder
*
* Masking for Micro QR Code.
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
# include "config.h"
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <errno.h>
#include "qrencode.h"
#include "mqrspec.h"
#include "mmask.h"
STATIC_IN_RELEASE void MMask_writeFormatInformation(int version, int width, unsigned char *frame, int mask, QRecLevel level)
{
unsigned int format;
unsigned char v;
int i;
format = MQRspec_getFormatInfo(mask, version, level);
for(i = 0; i < 8; i++) {
v = 0x84 | (format & 1);
frame[width * (i + 1) + 8] = v;
format = format >> 1;
}
for(i = 0; i < 7; i++) {
v = 0x84 | (format & 1);
frame[width * 8 + 7 - i] = v;
format = format >> 1;
}
}
#define MASKMAKER(__exp__) \
int x, y;\
\
for(y = 0; y < width; y++) {\
for(x = 0; x < width; x++) {\
if(*s & 0x80) {\
*d = *s;\
} else {\
*d = *s ^ ((__exp__) == 0);\
}\
s++; d++;\
}\
}
static void Mask_mask0(int width, const unsigned char *s, unsigned char *d)
{
MASKMAKER(y&1)
}
static void Mask_mask1(int width, const unsigned char *s, unsigned char *d)
{
MASKMAKER(((y/2)+(x/3))&1)
}
static void Mask_mask2(int width, const unsigned char *s, unsigned char *d)
{
MASKMAKER((((x*y)&1)+(x*y)%3)&1)
}
static void Mask_mask3(int width, const unsigned char *s, unsigned char *d)
{
MASKMAKER((((x+y)&1)+((x*y)%3))&1)
}
#define maskNum (4)
typedef void MaskMaker(int, const unsigned char *, unsigned char *);
static MaskMaker *maskMakers[maskNum] = {
Mask_mask0, Mask_mask1, Mask_mask2, Mask_mask3
};
#ifdef WITH_TESTS
unsigned char *MMask_makeMaskedFrame(int width, unsigned char *frame, int mask)
{
unsigned char *masked;
masked = (unsigned char *)TKMEM_ALLOC((size_t)(width * width));
if(masked == NULL) return NULL;
maskMakers[mask](width, frame, masked);
return masked;
}
#endif
unsigned char *MMask_makeMask(int version, unsigned char *frame, int mask, QRecLevel level)
{
unsigned char *masked;
int width;
if(mask < 0 || mask >= maskNum) {
return NULL;
}
width = MQRspec_getWidth(version);
masked = (unsigned char *)TKMEM_ALLOC((size_t)(width * width));
if(masked == NULL) return NULL;
maskMakers[mask](width, frame, masked);
MMask_writeFormatInformation(version, width, masked, mask, level);
return masked;
}
STATIC_IN_RELEASE int MMask_evaluateSymbol(int width, unsigned char *frame)
{
int x, y;
unsigned char *p;
int sum1 = 0, sum2 = 0;
p = frame + width * (width - 1);
for(x = 1; x < width; x++) {
sum1 += (p[x] & 1);
}
p = frame + width * 2 - 1;
for(y = 1; y < width; y++) {
sum2 += (*p & 1);
p += width;
}
return (sum1 <= sum2)?(sum1 * 16 + sum2):(sum2 * 16 + sum1);
}
unsigned char *MMask_mask(int version, unsigned char *frame, QRecLevel level)
{
int i;
unsigned char *mask, *bestMask;
int maxScore = 0;
int score;
int width;
width = MQRspec_getWidth(version);
mask = (unsigned char *)TKMEM_ALLOC((size_t)(width * width));
if(mask == NULL) return NULL;
bestMask = NULL;
for(i = 0; i < maskNum; i++) {
score = 0;
maskMakers[i](width, frame, mask);
MMask_writeFormatInformation(version, width, mask, i, level);
score = MMask_evaluateSymbol(width, mask);
if(score > maxScore) {
maxScore = score;
tk_free(bestMask);
bestMask = mask;
mask = (unsigned char *)TKMEM_ALLOC((size_t)(width * width));
if(mask == NULL) break;
}
}
tk_free(mask);
return bestMask;
}

View File

@ -0,0 +1,34 @@
/*
* qrencode - QR Code encoder
*
* Masking for Micro QR Code.
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef MMASK_H
#define MMASK_H
extern unsigned char *MMask_makeMask(int version, unsigned char *frame, int mask, QRecLevel level);
extern unsigned char *MMask_mask(int version, unsigned char *frame, QRecLevel level);
#ifdef WITH_TESTS
extern int MMask_evaluateSymbol(int width, unsigned char *frame);
extern void MMask_writeFormatInformation(int version, int width, unsigned char *frame, int mask, QRecLevel level);
extern unsigned char *MMask_makeMaskedFrame(int width, unsigned char *frame, int mask);
#endif
#endif /* MMASK_H */

View File

@ -0,0 +1,230 @@
/*
* qrencode - QR Code encoder
*
* Micro QR Code specification in convenient format.
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* The following data / specifications are taken from
* "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
* or
* "Automatic identification and data capture techniques --
* QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
# include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "mqrspec.h"
/******************************************************************************
* Version and capacity
*****************************************************************************/
typedef struct {
int width; ///< Edge length of the symbol
int ec[4]; ///< Number of ECC code (bytes)
} MQRspec_Capacity;
/**
* Table of the capacity of symbols
* See Table 1 (pp.106) and Table 8 (pp.113) of Appendix 1, JIS X0510:2004.
*/
static const MQRspec_Capacity mqrspecCapacity[MQRSPEC_VERSION_MAX + 1] = {
{ 0, {0, 0, 0, 0}},
{ 11, {2, 0, 0, 0}},
{ 13, {5, 6, 0, 0}},
{ 15, {6, 8, 0, 0}},
{ 17, {8, 10, 14, 0}}
};
int MQRspec_getDataLengthBit(int version, QRecLevel level)
{
int w;
int ecc;
w = mqrspecCapacity[version].width - 1;
ecc = mqrspecCapacity[version].ec[level];
if(ecc == 0) return 0;
return w * w - 64 - ecc * 8;
}
int MQRspec_getDataLength(int version, QRecLevel level)
{
return (MQRspec_getDataLengthBit(version, level) + 4) / 8;
}
int MQRspec_getECCLength(int version, QRecLevel level)
{
return mqrspecCapacity[version].ec[level];
}
int MQRspec_getWidth(int version)
{
return mqrspecCapacity[version].width;
}
/******************************************************************************
* Length indicator
*****************************************************************************/
/**
* See Table 3 (pp.107) of Appendix 1, JIS X0510:2004.
*/
static const int lengthTableBits[4][4] = {
{ 3, 4, 5, 6},
{ 0, 3, 4, 5},
{ 0, 0, 4, 5},
{ 0, 0, 3, 4}
};
int MQRspec_lengthIndicator(QRencodeMode mode, int version)
{
return lengthTableBits[mode][version - 1];
}
int MQRspec_maximumWords(QRencodeMode mode, int version)
{
int bits;
int words;
bits = lengthTableBits[mode][version - 1];
words = (1 << bits) - 1;
if(mode == QR_MODE_KANJI) {
words *= 2; // the number of bytes is required
}
return words;
}
/******************************************************************************
* Format information
*****************************************************************************/
/* See calcFormatInfo in tests/test_mqrspec.c */
static const unsigned int formatInfo[4][8] = {
{0x4445, 0x55ae, 0x6793, 0x7678, 0x06de, 0x1735, 0x2508, 0x34e3},
{0x4172, 0x5099, 0x62a4, 0x734f, 0x03e9, 0x1202, 0x203f, 0x31d4},
{0x4e2b, 0x5fc0, 0x6dfd, 0x7c16, 0x0cb0, 0x1d5b, 0x2f66, 0x3e8d},
{0x4b1c, 0x5af7, 0x68ca, 0x7921, 0x0987, 0x186c, 0x2a51, 0x3bba}
};
/* See Table 10 of Appendix 1. (pp.115) */
static const int typeTable[MQRSPEC_VERSION_MAX + 1][3] = {
{-1, -1, -1},
{ 0, -1, -1},
{ 1, 2, -1},
{ 3, 4, -1},
{ 5, 6, 7}
};
unsigned int MQRspec_getFormatInfo(int mask, int version, QRecLevel level)
{
int type;
if(mask < 0 || mask > 3) return 0;
if(version <= 0 || version > MQRSPEC_VERSION_MAX) return 0;
if(level == QR_ECLEVEL_H) return 0;
type = typeTable[version][level];
if(type < 0) return 0;
return formatInfo[mask][type];
}
/******************************************************************************
* Frame
*****************************************************************************/
/**
* Put a finder pattern.
* @param frame
* @param width
* @param ox,oy upper-left coordinate of the pattern
*/
static void putFinderPattern(unsigned char *frame, int width, int ox, int oy)
{
static const unsigned char finder[] = {
0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1,
0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1,
0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1,
0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1,
0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1,
0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1,
0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1,
};
int x, y;
const unsigned char *s;
frame += oy * width + ox;
s = finder;
for(y = 0; y < 7; y++) {
for(x = 0; x < 7; x++) {
frame[x] = s[x];
}
frame += width;
s += 7;
}
}
static unsigned char *MQRspec_createFrame(int version)
{
unsigned char *frame, *p, *q;
int width;
int x, y;
width = mqrspecCapacity[version].width;
frame = (unsigned char *)TKMEM_ALLOC((size_t)(width * width));
if(frame == NULL) return NULL;
memset(frame, 0, (size_t)(width * width));
/* Finder pattern */
putFinderPattern(frame, width, 0, 0);
/* Separator */
p = frame;
for(y = 0; y < 7; y++) {
p[7] = 0xc0;
p += width;
}
memset(frame + width * 7, 0xc0, 8);
/* Mask format information area */
memset(frame + width * 8 + 1, 0x84, 8);
p = frame + width + 8;
for(y = 0; y < 7; y++) {
*p = 0x84;
p += width;
}
/* Timing pattern */
p = frame + 8;
q = frame + width * 8;
for(x = 1; x < width-7; x++) {
*p = 0x90 | (x & 1);
*q = 0x90 | (x & 1);
p++;
q += width;
}
return frame;
}
unsigned char *MQRspec_newFrame(int version)
{
if(version < 1 || version > MQRSPEC_VERSION_MAX) return NULL;
return MQRspec_createFrame(version);
}

View File

@ -0,0 +1,150 @@
/*
* qrencode - QR Code encoder
*
* Micro QR Code specification in convenient format.
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef MQRSPEC_H
#define MQRSPEC_H
#include "qrencode.h"
/******************************************************************************
* Version and capacity
*****************************************************************************/
/**
* Maximum width of a symbol
*/
#define MQRSPEC_WIDTH_MAX 17
/**
* Return maximum data code length (bits) for the version.
* @param version version of the symbol
* @param level error correction level
* @return maximum size (bits)
*/
extern int MQRspec_getDataLengthBit(int version, QRecLevel level);
/**
* Return maximum data code length (bytes) for the version.
* @param version version of the symbol
* @param level error correction level
* @return maximum size (bytes)
*/
extern int MQRspec_getDataLength(int version, QRecLevel level);
/**
* Return maximum error correction code length (bytes) for the version.
* @param version version of the symbol
* @param level error correction level
* @return ECC size (bytes)
*/
extern int MQRspec_getECCLength(int version, QRecLevel level);
/**
* Return a version number that satisfies the input code length.
* @param size input code length (byte)
* @param level error correction level
* @return version number
*/
extern int MQRspec_getMinimumVersion(int size, QRecLevel level);
/**
* Return the width of the symbol for the version.
* @param version version of the symbol
* @return width
*/
extern int MQRspec_getWidth(int version);
/**
* Return the numer of remainder bits.
* @param version version of the symbol
* @return number of remainder bits
*/
extern int MQRspec_getRemainder(int version);
/******************************************************************************
* Length indicator
*****************************************************************************/
/**
* Return the size of length indicator for the mode and version.
* @param mode encode mode
* @param version vesion of the symbol
* @return the size of the appropriate length indicator (bits).
*/
extern int MQRspec_lengthIndicator(QRencodeMode mode, int version);
/**
* Return the maximum length for the mode and version.
* @param mode encode mode
* @param version vesion of the symbol
* @return the maximum length (bytes)
*/
extern int MQRspec_maximumWords(QRencodeMode mode, int version);
/******************************************************************************
* Version information pattern
*****************************************************************************/
/**
* Return BCH encoded version information pattern that is used for the symbol
* of version 7 or greater. Use lower 18 bits.
* @param version vesion of the symbol
* @return BCH encoded version information pattern
*/
extern unsigned int MQRspec_getVersionPattern(int version);
/******************************************************************************
* Format information
*****************************************************************************/
/**
* Return BCH encoded format information pattern.
* @param mask mask number
* @param version version of the symbol
* @param level error correction level
* @return BCH encoded format information pattern
*/
extern unsigned int MQRspec_getFormatInfo(int mask, int version, QRecLevel level);
/******************************************************************************
* Frame
*****************************************************************************/
/**
* Return a copy of initialized frame.
* @param version version of the symbol
* @return Array of unsigned char. You can free it by free().
*/
extern unsigned char *MQRspec_newFrame(int version);
/******************************************************************************
* Mode indicator
*****************************************************************************/
/**
* Mode indicator. See Table 2 in Appendix 1 of JIS X0510:2004, pp.107.
*/
#define MQRSPEC_MODEID_NUM 0
#define MQRSPEC_MODEID_AN 1
#define MQRSPEC_MODEID_8 2
#define MQRSPEC_MODEID_KANJI 3
#endif /* MQRSPEC_H */

View File

@ -0,0 +1,214 @@
/**
* File: qr.c
* Author: AWTK Develop Team
* Brief: 显示二维码的控件
*
* Copyright (c) 2020 - 2020 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2020-06-01 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "tkc/mem.h"
#include "tkc/utils.h"
#include "base/widget_vtable.h"
#include "base/window_manager.h"
#include "qr.h"
#define IMAGE_QR_MAX_RATIO 0.45f /* 贴图的面积和二维码的面积最大比例 */
static ret_t qr_ensure_qrcode(widget_t* widget);
ret_t new_qr_set_value(widget_t* widget, const char* value) {
qr_t* qr = QR(widget);
return_value_if_fail(qr != NULL, RET_BAD_PARAMS);
if (tk_str_eq(qr->value, value)) { return RET_OK; }
qr->value = tk_str_copy(qr->value, value);
if (qr->qrcode != NULL) {
QRcode_free(qr->qrcode);
qr->qrcode = NULL;
}
ret_t ret = qr_ensure_qrcode(widget);
return (ret == RET_OK) ? widget_invalidate(widget, NULL) : RET_FAIL;
}
static ret_t qr_get_prop(widget_t* widget, const char* name, value_t* v) {
qr_t* qr = QR(widget);
return_value_if_fail(qr != NULL && name != NULL && v != NULL, RET_BAD_PARAMS);
if (tk_str_eq(WIDGET_PROP_VALUE, name) || tk_str_eq(WIDGET_PROP_TEXT, name)) {
value_set_str(v, qr->value);
return RET_OK;
}
return RET_NOT_FOUND;
}
static ret_t qr_set_prop(widget_t* widget, const char* name, const value_t* v) {
qr_t* qr = QR(widget);
return_value_if_fail(widget != NULL && name != NULL && v != NULL, RET_BAD_PARAMS);
if (tk_str_eq(WIDGET_PROP_VALUE, name) || tk_str_eq(WIDGET_PROP_TEXT, name)) {
new_qr_set_value(widget, value_str(v));
if (qr->qrcode != NULL) {
QRcode_free(qr->qrcode);
qr->qrcode = NULL;
}
return RET_OK;
}
return RET_NOT_FOUND;
}
static ret_t qr_on_destroy(widget_t* widget) {
qr_t* qr = QR(widget);
return_value_if_fail(widget != NULL && qr != NULL, RET_BAD_PARAMS);
TKMEM_FREE(qr->value);
if (qr->qrcode != NULL) {
QRcode_free(qr->qrcode);
qr->qrcode = NULL;
}
return RET_OK;
}
#define MIN_SIZE 21
static ret_t qr_ensure_qrcode(widget_t* widget) {
qr_t* qr = QR(widget);
int32_t size = tk_min(widget->w, widget->h) - 5;
if (size < MIN_SIZE) {
return RET_FAIL;
}
if (qr->qrcode != NULL) {
return RET_OK;
}
qr->qrcode = QRcode_encodeString(qr->value, 3, QR_ECLEVEL_H, QR_MODE_8, 1);
if (qr->qrcode != NULL) {
return RET_OK;
}
return RET_FAIL;
}
static ret_t qr_paint_logo(widget_t* widget, canvas_t* c) {
vgcanvas_t* vg = canvas_get_vgcanvas(c);
const char* logo_name = NULL;
bitmap_t logo = {0};
return_value_if_fail(widget != NULL && vg != NULL, RET_BAD_PARAMS);
logo_name = style_get_str(widget->astyle, STYLE_ID_BG_IMAGE, NULL);
if (logo_name != NULL && widget_load_image(widget, logo_name, &logo) == RET_OK) {
vgcanvas_translate(vg, c->ox + (widget->w - logo.w) / 2.0f,
c->oy + (widget->h - logo.h) / 2.0f);
vgcanvas_draw_image(vg, &logo, 0, 0, logo.w, logo.h, 0, 0, logo.w, logo.h);
}
return RET_OK;
}
static ret_t qr_on_paint_self(widget_t* widget, canvas_t* c) {
qr_t* qr = QR(widget);
style_t* style = widget->astyle;
if (style != NULL) {
color_t trans = color_init(0, 0, 0, 0);
uint32_t margin = style_get_int(style, STYLE_ID_MARGIN, 2);
color_t bg = style_get_color(style, STYLE_ID_BG_COLOR, trans);
color_t fg = style_get_color(style, STYLE_ID_FG_COLOR, trans);
if (qr_ensure_qrcode(widget) == RET_OK) {
rect_t r = { 0, 0, widget->w, widget->h };
uint32_t w = 0;
uint32_t h = 0;
uint32_t i = 0;
uint32_t j = 0;
uint8_t* p = qr->qrcode->data;
uint32_t size = qr->qrcode->width;
uint32_t pix_size = (tk_min(widget->w, widget->h) - 2 * margin) / size;
uint32_t x = (widget->w - pix_size * size) / 2;
uint32_t y = (widget->h - pix_size * size) / 2;
rect_t r_clip = rect_init(widget->x + ((1 - IMAGE_QR_MAX_RATIO) / 2.0f) * widget->w,
widget->y + ((1 - IMAGE_QR_MAX_RATIO) / 2.0f) * widget->h,
IMAGE_QR_MAX_RATIO * widget->w, IMAGE_QR_MAX_RATIO * widget->h);
return_value_if_fail(pix_size > 1, RET_BAD_PARAMS);
for (j = 0; j < size; j++) {
x = (widget->w - pix_size * size) / 2;
for (i = 0; i < size; i++) {
if (*p & 0x01) {
canvas_set_fill_color(c, fg);
} else {
canvas_set_fill_color(c, bg);
}
canvas_fill_rect(c, x, y, pix_size, pix_size);
p++;
x += pix_size;
}
y += pix_size;
}
widget_paint_with_clip(widget, &r_clip, c, qr_paint_logo);
}
}
return RET_OK;
}
static ret_t qr_on_event(widget_t* widget, event_t* e) {
qr_t* qr = QR(widget);
return_value_if_fail(widget != NULL && qr != NULL, RET_BAD_PARAMS);
(void)qr;
return RET_OK;
}
const char* s_qr_properties[] = {WIDGET_PROP_VALUE, NULL};
TK_DECL_VTABLE(qr) = {.size = sizeof(qr_t),
.type = WIDGET_TYPE_QR,
.clone_properties = s_qr_properties,
.persistent_properties = s_qr_properties,
.parent = TK_PARENT_VTABLE(widget),
.create = qr_create,
.on_paint_self = qr_on_paint_self,
.set_prop = qr_set_prop,
.get_prop = qr_get_prop,
.on_event = qr_on_event,
.on_destroy = qr_on_destroy};
widget_t* qr_create(widget_t* parent, xy_t x, xy_t y, wh_t w, wh_t h) {
widget_t* widget = widget_create(parent, TK_REF_VTABLE(qr), x, y, w, h);
qr_t* qr = QR(widget);
return_value_if_fail(qr != NULL, NULL);
return widget;
}
widget_t* qr_cast(widget_t* widget) {
return_value_if_fail(WIDGET_IS_INSTANCE_OF(widget, qr), NULL);
return widget;
}

View File

@ -0,0 +1,115 @@
/**
* File: qr.h
* Author: AWTK Develop Team
* Brief: 显示二维码的控件
*
* Copyright (c) 2020 - 2020 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2020-06-01 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_QR_H
#define TK_QR_H
#include "qrencode.h"
#include "base/widget.h"
BEGIN_C_DECLS
/**
* @class qr_t
* @parent widget_t
* @annotation ["scriptable","design","widget"]
* 显示二维码的控件
* qr\_t是[widget\_t](widget_t.md)的子类控件widget\_t的函数均适用于qr\_t控件。
*
* 在xml中使用"qr"标签创建数值文本控件。如:
*
* ```xml
* <!-- ui -->
* <qr x="c" y="m" w="240" h="240" value="https://github.com/zlgopen/awtk"/>
* ```
* 在c代码中使用函数qr\_create创建数值文本控件。如
*
* ```c
* widget_t* qr = qr_create(win, 10, 10, 128, 128);
* ```
* 可用通过style来设置控件的显示风格如字体的大小和颜色等等。如
*
* ```xml
* <!-- style -->
* <qr>
* <style name="default" >
* <normal fg_color="black" bg_color="white" bg_image="message"/>
* <disable fg_color="gray" bg_color="#f0f0f0"/>
* </style>
* </qr>
* ```
*/
typedef struct _qr_t {
widget_t widget;
/**
* @property {char*} value
* @annotation ["set_prop","get_prop","readable","persitent","design","scriptable"]
* 要转成二维码的字符串。值。
*/
char* value;
/*private*/
QRcode* qrcode;
} qr_t;
/**
* @method qr_create
* @annotation ["constructor", "scriptable"]
* 创建qr对象
* @param {widget_t*} parent 父控件
* @param {xy_t} x x坐标
* @param {xy_t} y y坐标
* @param {wh_t} w 宽度
* @param {wh_t} h 高度
*
* @return {widget_t*} qr对象。
*/
widget_t* qr_create(widget_t* parent, xy_t x, xy_t y, wh_t w, wh_t h);
/**
* @method qr_cast
* 转换为qr对象(供脚本语言使用)。
* @annotation ["cast", "scriptable"]
* @param {widget_t*} widget qr对象。
*
* @return {widget_t*} qr对象。
*/
widget_t* qr_cast(widget_t* widget);
/**
* @method new_qr_set_value
* 设置要转成二维码的字符串。
* @annotation ["scriptable"]
* @param {widget_t*} widget widget对象。
* @param {const char*} value 格式字符串。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t new_qr_set_value(widget_t* widget, const char* value);
#define WIDGET_TYPE_QR "qr"
#define QR(widget) ((qr_t*)(qr_cast(WIDGET(widget))))
/*public for subclass and runtime type check*/
TK_EXTERN_VTABLE(qr);
END_C_DECLS
#endif /*TK_QR_H*/

View File

@ -0,0 +1,891 @@
/*
* qrencode - QR Code encoder
*
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
# include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "qrencode.h"
#include "qrspec.h"
#include "mqrspec.h"
#include "bitstream.h"
#include "qrinput.h"
#include "rsecc.h"
#include "split.h"
#include "mask.h"
#include "mmask.h"
/******************************************************************************
* Raw code
*****************************************************************************/
typedef struct {
int dataLength;
int eccLength;
unsigned char *data;
unsigned char *ecc;
} RSblock;
typedef struct {
int version;
int dataLength;
int eccLength;
unsigned char *datacode;
unsigned char *ecccode;
int b1;
int blocks;
RSblock *rsblock;
int count;
} QRRawCode;
static void RSblock_initBlock(RSblock *block, int dl, unsigned char *data, int el, unsigned char *ecc)
{
block->dataLength = dl;
block->data = data;
block->eccLength = el;
block->ecc = ecc;
RSECC_encode((size_t)dl, (size_t)el, data, ecc);
}
static int RSblock_init(RSblock *blocks, int spec[5], unsigned char *data, unsigned char *ecc)
{
int i;
RSblock *block;
unsigned char *dp, *ep;
int el, dl;
dl = QRspec_rsDataCodes1(spec);
el = QRspec_rsEccCodes1(spec);
block = blocks;
dp = data;
ep = ecc;
for(i = 0; i < QRspec_rsBlockNum1(spec); i++) {
RSblock_initBlock(block, dl, dp, el, ep);
dp += dl;
ep += el;
block++;
}
if(QRspec_rsBlockNum2(spec) == 0) return 0;
dl = QRspec_rsDataCodes2(spec);
el = QRspec_rsEccCodes2(spec);
for(i = 0; i < QRspec_rsBlockNum2(spec); i++) {
RSblock_initBlock(block, dl, dp, el, ep);
dp += dl;
ep += el;
block++;
}
return 0;
}
STATIC_IN_RELEASE void QRraw_free(QRRawCode *raw);
STATIC_IN_RELEASE QRRawCode *QRraw_new(QRinput *input)
{
QRRawCode *raw;
int spec[5], ret;
raw = (QRRawCode *)TKMEM_ALLOC(sizeof(QRRawCode));
if(raw == NULL) return NULL;
raw->datacode = QRinput_getByteStream(input);
if(raw->datacode == NULL) {
tk_free(raw);
return NULL;
}
QRspec_getEccSpec(input->version, input->level, spec);
raw->version = input->version;
raw->b1 = QRspec_rsBlockNum1(spec);
raw->dataLength = QRspec_rsDataLength(spec);
raw->eccLength = QRspec_rsEccLength(spec);
raw->ecccode = (unsigned char *)TKMEM_ALLOC((size_t)raw->eccLength);
if(raw->ecccode == NULL) {
tk_free(raw->datacode);
tk_free(raw);
return NULL;
}
raw->blocks = QRspec_rsBlockNum(spec);
raw->rsblock = (RSblock *)TKMEM_CALLOC((size_t)(raw->blocks), sizeof(RSblock));
if(raw->rsblock == NULL) {
QRraw_free(raw);
return NULL;
}
ret = RSblock_init(raw->rsblock, spec, raw->datacode, raw->ecccode);
if(ret < 0) {
QRraw_free(raw);
return NULL;
}
raw->count = 0;
return raw;
}
/**
* Return a code (byte).
* This function can be called iteratively.
* @param raw raw code.
* @return code
*/
STATIC_IN_RELEASE unsigned char QRraw_getCode(QRRawCode *raw)
{
int col, row;
unsigned char ret;
if(raw->count < raw->dataLength) {
row = raw->count % raw->blocks;
col = raw->count / raw->blocks;
if(col >= raw->rsblock[0].dataLength) {
row += raw->b1;
}
ret = raw->rsblock[row].data[col];
} else if(raw->count < raw->dataLength + raw->eccLength) {
row = (raw->count - raw->dataLength) % raw->blocks;
col = (raw->count - raw->dataLength) / raw->blocks;
ret = raw->rsblock[row].ecc[col];
} else {
return 0;
}
raw->count++;
return ret;
}
STATIC_IN_RELEASE void QRraw_free(QRRawCode *raw)
{
if(raw != NULL) {
tk_free(raw->datacode);
tk_free(raw->ecccode);
tk_free(raw->rsblock);
tk_free(raw);
}
}
/******************************************************************************
* Raw code for Micro QR Code
*****************************************************************************/
typedef struct {
int version;
int dataLength;
int eccLength;
unsigned char *datacode;
unsigned char *ecccode;
RSblock *rsblock;
int oddbits;
int count;
} MQRRawCode;
STATIC_IN_RELEASE void MQRraw_free(MQRRawCode *raw);
STATIC_IN_RELEASE MQRRawCode *MQRraw_new(QRinput *input)
{
MQRRawCode *raw;
raw = (MQRRawCode *)TKMEM_ALLOC(sizeof(MQRRawCode));
if(raw == NULL) return NULL;
raw->version = input->version;
raw->dataLength = MQRspec_getDataLength(input->version, input->level);
raw->eccLength = MQRspec_getECCLength(input->version, input->level);
raw->oddbits = raw->dataLength * 8 - MQRspec_getDataLengthBit(input->version, input->level);
raw->datacode = QRinput_getByteStream(input);
if(raw->datacode == NULL) {
tk_free(raw);
return NULL;
}
raw->ecccode = (unsigned char *)TKMEM_ALLOC((size_t)raw->eccLength);
if(raw->ecccode == NULL) {
tk_free(raw->datacode);
tk_free(raw);
return NULL;
}
raw->rsblock = (RSblock *)TKMEM_CALLOC(1, sizeof(RSblock));
if(raw->rsblock == NULL) {
MQRraw_free(raw);
return NULL;
}
RSblock_initBlock(raw->rsblock, raw->dataLength, raw->datacode, raw->eccLength, raw->ecccode);
raw->count = 0;
return raw;
}
/**
* Return a code (byte).
* This function can be called iteratively.
* @param raw raw code.
* @return code
*/
STATIC_IN_RELEASE unsigned char MQRraw_getCode(MQRRawCode *raw)
{
unsigned char ret;
if(raw->count < raw->dataLength) {
ret = raw->datacode[raw->count];
} else if(raw->count < raw->dataLength + raw->eccLength) {
ret = raw->ecccode[raw->count - raw->dataLength];
} else {
return 0;
}
raw->count++;
return ret;
}
STATIC_IN_RELEASE void MQRraw_free(MQRRawCode *raw)
{
if(raw != NULL) {
tk_free(raw->datacode);
tk_free(raw->ecccode);
tk_free(raw->rsblock);
tk_free(raw);
}
}
/******************************************************************************
* Frame filling
*****************************************************************************/
typedef struct {
int width;
unsigned char *frame;
int x, y;
int dir;
int bit;
int mqr;
} FrameFiller;
static void FrameFiller_set(FrameFiller *filler, int width, unsigned char *frame, int mqr)
{
filler->width = width;
filler->frame = frame;
filler->x = width - 1;
filler->y = width - 1;
filler->dir = -1;
filler->bit = -1;
filler->mqr = mqr;
}
static unsigned char *FrameFiller_next(FrameFiller *filler)
{
unsigned char *p;
int x, y, w;
if(filler->bit == -1) {
filler->bit = 0;
return filler->frame + filler->y * filler->width + filler->x;
}
x = filler->x;
y = filler->y;
p = filler->frame;
w = filler->width;
if(filler->bit == 0) {
x--;
filler->bit++;
} else {
x++;
y += filler->dir;
filler->bit--;
}
if(filler->dir < 0) {
if(y < 0) {
y = 0;
x -= 2;
filler->dir = 1;
if(!filler->mqr && x == 6) {
x--;
y = 9;
}
}
} else if(y == w) {
y = w - 1;
x -= 2;
filler->dir = -1;
if(!filler->mqr && x == 6) {
x--;
y -= 8;
}
}
if(x < 0 || y < 0) return NULL;
filler->x = x;
filler->y = y;
if(p[y * w + x] & 0x80) {
// This tail recursion could be optimized.
return FrameFiller_next(filler);
}
return &p[y * w + x];
}
#ifdef WITH_TESTS
unsigned char *FrameFiller_test(int version)
{
int width;
unsigned char *frame, *p;
int i, length;
FrameFiller filler;
width = QRspec_getWidth(version);
frame = QRspec_newFrame(version);
if(frame == NULL) return NULL;
FrameFiller_set(&filler, width, frame, 0);
length = QRspec_getDataLength(version, QR_ECLEVEL_L) * 8
+ QRspec_getECCLength(version, QR_ECLEVEL_L) * 8
+ QRspec_getRemainder(version);
for(i = 0; i < length; i++) {
p = FrameFiller_next(&filler);
if(p == NULL) {
tk_free(frame);
return NULL;
}
*p = (unsigned char)(i & 0x7f) | 0x80;
}
return frame;
}
unsigned char *FrameFiller_testMQR(int version)
{
int width;
unsigned char *frame, *p;
int i, length;
FrameFiller filler;
width = MQRspec_getWidth(version);
frame = MQRspec_newFrame(version);
if(frame == NULL) return NULL;
FrameFiller_set(&filler, width, frame, 1);
length = MQRspec_getDataLengthBit(version, QR_ECLEVEL_L)
+ MQRspec_getECCLength(version, QR_ECLEVEL_L) * 8;
for(i = 0; i < length; i++) {
p = FrameFiller_next(&filler);
if(p == NULL) {
fprintf(stderr, "Frame filler run over the frame!\n");
return frame;
}
*p = (unsigned char)(i & 0x7f) | 0x80;
}
return frame;
}
#endif
/******************************************************************************
* QR-code encoding
*****************************************************************************/
STATIC_IN_RELEASE QRcode *QRcode_new(int version, int width, unsigned char *data)
{
QRcode *qrcode;
qrcode = (QRcode *)TKMEM_ALLOC(sizeof(QRcode));
if(qrcode == NULL) return NULL;
qrcode->version = version;
qrcode->width = width;
qrcode->data = data;
return qrcode;
}
void QRcode_free(QRcode *qrcode)
{
if(qrcode != NULL) {
tk_free(qrcode->data);
tk_free(qrcode);
}
}
STATIC_IN_RELEASE QRcode *QRcode_encodeMask(QRinput *input, int mask)
{
int width, version;
QRRawCode *raw;
unsigned char *frame, *masked, *p, code, bit;
int i, j;
QRcode *qrcode = NULL;
FrameFiller filler;
if(input->mqr) {
return NULL;
}
if(input->version < 0 || input->version > QRSPEC_VERSION_MAX) {
return NULL;
}
if(input->level > QR_ECLEVEL_H) {
return NULL;
}
raw = QRraw_new(input);
if(raw == NULL) return NULL;
version = raw->version;
width = QRspec_getWidth(version);
frame = QRspec_newFrame(version);
if(frame == NULL) {
QRraw_free(raw);
return NULL;
}
FrameFiller_set(&filler, width, frame, 0);
/* interleaved data and ecc codes */
for(i = 0; i < raw->dataLength; i++) {
code = QRraw_getCode(raw);
bit = 0x80;
for(j = 0; j < 8; j++) {
p = FrameFiller_next(&filler);
if(p == NULL) goto EXIT;
*p = ((bit & code) != 0);
bit = bit >> 1;
}
}
for(i = 0; i < raw->eccLength; i++) {
code = QRraw_getCode(raw);
bit = 0x80;
for(j = 0; j < 8; j++) {
p = FrameFiller_next(&filler);
if(p == NULL) goto EXIT;
*p = 0x02 | ((bit & code) != 0);
bit = bit >> 1;
}
}
QRraw_free(raw);
raw = NULL;
/* remainder bits */
j = QRspec_getRemainder(version);
for(i = 0; i < j; i++) {
p = FrameFiller_next(&filler);
if(p == NULL) goto EXIT;
*p = 0x02;
}
/* masking */
if(mask == -2) { // just for debug purpose
masked = (unsigned char *)TKMEM_ALLOC((size_t)(width * width));
memcpy(masked, frame, (size_t)(width * width));
} else if(mask < 0) {
masked = Mask_mask(width, frame, input->level);
} else {
masked = Mask_makeMask(width, frame, mask, input->level);
}
if(masked == NULL) {
goto EXIT;
}
qrcode = QRcode_new(version, width, masked);
if(qrcode == NULL) {
tk_free(masked);
}
EXIT:
QRraw_free(raw);
tk_free(frame);
return qrcode;
}
STATIC_IN_RELEASE QRcode *QRcode_encodeMaskMQR(QRinput *input, int mask)
{
int width, version;
MQRRawCode *raw;
unsigned char *frame, *masked, *p, code, bit;
int i, j, length;
QRcode *qrcode = NULL;
FrameFiller filler;
if(!input->mqr) {
return NULL;
}
if(input->version <= 0 || input->version > MQRSPEC_VERSION_MAX) {
return NULL;
}
if(input->level > QR_ECLEVEL_Q) {
return NULL;
}
raw = MQRraw_new(input);
if(raw == NULL) return NULL;
version = raw->version;
width = MQRspec_getWidth(version);
frame = MQRspec_newFrame(version);
if(frame == NULL) {
MQRraw_free(raw);
return NULL;
}
FrameFiller_set(&filler, width, frame, 1);
/* interleaved data and ecc codes */
for(i = 0; i < raw->dataLength; i++) {
code = MQRraw_getCode(raw);
bit = 0x80;
if(raw->oddbits && i == raw->dataLength - 1) {
length = raw->oddbits;
} else {
length = 8;
}
for(j = 0; j < length; j++) {
p = FrameFiller_next(&filler);
if(p == NULL) goto EXIT;
*p = ((bit & code) != 0);
bit = bit >> 1;
}
}
for(i = 0; i < raw->eccLength; i++) {
code = MQRraw_getCode(raw);
bit = 0x80;
length = 8;
for(j = 0; j < length; j++) {
p = FrameFiller_next(&filler);
if(p == NULL) goto EXIT;
*p = 0x02 | ((bit & code) != 0);
bit = bit >> 1;
}
}
MQRraw_free(raw);
raw = NULL;
/* masking */
if(mask == -2) { // just for debug purpose
masked = (unsigned char *)TKMEM_ALLOC((size_t)(width * width));
memcpy(masked, frame, (size_t)(width * width));
} else if(mask < 0) {
masked = MMask_mask(version, frame, input->level);
} else {
masked = MMask_makeMask(version, frame, mask, input->level);
}
if(masked == NULL) {
goto EXIT;
}
qrcode = QRcode_new(version, width, masked);
if(qrcode == NULL) {
tk_free(masked);
}
EXIT:
MQRraw_free(raw);
tk_free(frame);
return qrcode;
}
QRcode *QRcode_encodeInput(QRinput *input)
{
if(input->mqr) {
return QRcode_encodeMaskMQR(input, -1);
} else {
return QRcode_encodeMask(input, -1);
}
}
static QRcode *QRcode_encodeStringReal(const char *string, int version, QRecLevel level, int mqr, QRencodeMode hint, int casesensitive)
{
QRinput *input;
QRcode *code;
int ret;
if(string == NULL) {
return NULL;
}
if(hint != QR_MODE_8 && hint != QR_MODE_KANJI) {
return NULL;
}
if(mqr) {
input = QRinput_newMQR(version, level);
} else {
input = QRinput_new2(version, level);
}
if(input == NULL) return NULL;
ret = Split_splitStringToQRinput(string, input, hint, casesensitive);
if(ret < 0) {
QRinput_free(input);
return NULL;
}
code = QRcode_encodeInput(input);
QRinput_free(input);
return code;
}
QRcode *QRcode_encodeString(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive)
{
return QRcode_encodeStringReal(string, version, level, 0, hint, casesensitive);
}
QRcode *QRcode_encodeStringMQR(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive)
{
return QRcode_encodeStringReal(string, version, level, 1, hint, casesensitive);
}
static QRcode *QRcode_encodeDataReal(const unsigned char *data, int length, int version, QRecLevel level, int mqr)
{
QRinput *input;
QRcode *code;
int ret;
if(data == NULL || length == 0) {
return NULL;
}
if(mqr) {
input = QRinput_newMQR(version, level);
} else {
input = QRinput_new2(version, level);
}
if(input == NULL) return NULL;
ret = QRinput_append(input, QR_MODE_8, length, data);
if(ret < 0) {
QRinput_free(input);
return NULL;
}
code = QRcode_encodeInput(input);
QRinput_free(input);
return code;
}
QRcode *QRcode_encodeData(int size, const unsigned char *data, int version, QRecLevel level)
{
return QRcode_encodeDataReal(data, size, version, level, 0);
}
QRcode *QRcode_encodeString8bit(const char *string, int version, QRecLevel level)
{
if(string == NULL) {
return NULL;
}
return QRcode_encodeDataReal((unsigned char *)string, (int)strlen(string), version, level, 0);
}
QRcode *QRcode_encodeDataMQR(int size, const unsigned char *data, int version, QRecLevel level)
{
return QRcode_encodeDataReal(data, size, version, level, 1);
}
QRcode *QRcode_encodeString8bitMQR(const char *string, int version, QRecLevel level)
{
if(string == NULL) {
return NULL;
}
return QRcode_encodeDataReal((unsigned char *)string, (int)strlen(string), version, level, 1);
}
/******************************************************************************
* Structured QR-code encoding
*****************************************************************************/
static QRcode_List *QRcode_List_newEntry(void)
{
QRcode_List *entry;
entry = (QRcode_List *)TKMEM_ALLOC(sizeof(QRcode_List));
if(entry == NULL) return NULL;
entry->next = NULL;
entry->code = NULL;
return entry;
}
static void QRcode_List_freeEntry(QRcode_List *entry)
{
if(entry != NULL) {
QRcode_free(entry->code);
tk_free(entry);
}
}
void QRcode_List_free(QRcode_List *qrlist)
{
QRcode_List *list = qrlist, *next;
while(list != NULL) {
next = list->next;
QRcode_List_freeEntry(list);
list = next;
}
}
int QRcode_List_size(QRcode_List *qrlist)
{
QRcode_List *list = qrlist;
int size = 0;
while(list != NULL) {
size++;
list = list->next;
}
return size;
}
#if 0
static unsigned char QRcode_parity(const char *str, int size)
{
unsigned char parity = 0;
int i;
for(i = 0; i < size; i++) {
parity ^= str[i];
}
return parity;
}
#endif
QRcode_List *QRcode_encodeInputStructured(QRinput_Struct *s)
{
QRcode_List *head = NULL;
QRcode_List *tail = NULL;
QRcode_List *entry;
QRinput_InputList *list = s->head;
while(list != NULL) {
if(head == NULL) {
entry = QRcode_List_newEntry();
if(entry == NULL) goto ABORT;
head = entry;
tail = head;
} else {
entry = QRcode_List_newEntry();
if(entry == NULL) goto ABORT;
tail->next = entry;
tail = tail->next;
}
tail->code = QRcode_encodeInput(list->input);
if(tail->code == NULL) {
goto ABORT;
}
list = list->next;
}
return head;
ABORT:
QRcode_List_free(head);
return NULL;
}
static QRcode_List *QRcode_encodeInputToStructured(QRinput *input)
{
QRinput_Struct *s;
QRcode_List *codes;
s = QRinput_splitQRinputToStruct(input);
if(s == NULL) return NULL;
codes = QRcode_encodeInputStructured(s);
QRinput_Struct_free(s);
return codes;
}
static QRcode_List *QRcode_encodeDataStructuredReal(
int size, const unsigned char *data,
int version, QRecLevel level,
int eightbit, QRencodeMode hint, int casesensitive)
{
QRinput *input;
QRcode_List *codes;
int ret;
if(version <= 0) {
return NULL;
}
if(!eightbit && (hint != QR_MODE_8 && hint != QR_MODE_KANJI)) {
return NULL;
}
input = QRinput_new2(version, level);
if(input == NULL) return NULL;
if(eightbit) {
ret = QRinput_append(input, QR_MODE_8, size, data);
} else {
ret = Split_splitStringToQRinput((char *)data, input, hint, casesensitive);
}
if(ret < 0) {
QRinput_free(input);
return NULL;
}
codes = QRcode_encodeInputToStructured(input);
QRinput_free(input);
return codes;
}
QRcode_List *QRcode_encodeDataStructured(int size, const unsigned char *data, int version, QRecLevel level) {
return QRcode_encodeDataStructuredReal(size, data, version, level, 1, QR_MODE_NUL, 0);
}
QRcode_List *QRcode_encodeString8bitStructured(const char *string, int version, QRecLevel level) {
if(string == NULL) {
return NULL;
}
return QRcode_encodeDataStructured((int)strlen(string), (unsigned char *)string, version, level);
}
QRcode_List *QRcode_encodeStringStructured(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive)
{
if(string == NULL) {
return NULL;
}
return QRcode_encodeDataStructuredReal((int)strlen(string), (unsigned char *)string, version, level, 0, hint, casesensitive);
}
/******************************************************************************
* System utilities
*****************************************************************************/
void QRcode_APIVersion(int *major_version, int *minor_version, int *micro_version)
{
if(major_version != NULL) {
*major_version = MAJOR_VERSION;
}
if(minor_version != NULL) {
*minor_version = MINOR_VERSION;
}
if(micro_version != NULL) {
*micro_version = MICRO_VERSION;
}
}
char *QRcode_APIVersionString(void)
{
return VERSION;
}
void QRcode_clearCache(void)
{
return;
}

View File

@ -0,0 +1,568 @@
/**
* qrencode - QR Code encoder
*
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/** \mainpage
* Libqrencode is a library for encoding data in a QR Code symbol, a kind of 2D
* symbology.
*
* \section encoding Encoding
*
* There are two methods to encode data: <b>encoding a string/data</b> or
* <b>encoding a structured data</b>.
*
* \subsection encoding-string Encoding a string/data
* You can encode a string by calling QRcode_encodeString().
* The given string is parsed automatically and encoded. If you want to encode
* data that can be represented as a C string style (NUL terminated), you can
* simply use this way.
*
* If the input data contains Kanji (Shift-JIS) characters and you want to
* encode them as Kanji in QR Code, you should give QR_MODE_KANJI as a hint.
* Otherwise, all of non-alphanumeric characters are encoded as 8 bit data.
* If you want to encode a whole string in 8 bit mode, you can use
* QRcode_encodeString8bit() instead.
*
* Please note that a C string can not contain NUL characters. If your data
* contains NUL, you must use QRcode_encodeData().
*
* \subsection encoding-input Encoding a structured data
* You can construct a structured input data manually. If the structure of the
* input data is known, you can use this way.
* At first, create a ::QRinput object by QRinput_new(). Then add input data
* to the QRinput object by QRinput_append(). Finally call QRcode_encodeInput()
* to encode the QRinput data.
* You can reuse the QRinput data again to encode it in other symbols with
* different parameters.
*
* \section result Result
* The encoded symbol is resulted as a ::QRcode object. It will contain
* its version number, width of the symbol and an array represents the symbol.
* See ::QRcode for the details. You can free the object by QRcode_free().
*
* Please note that the version of the result may be larger than specified.
* In such cases, the input data would be too large to be encoded in a
* symbol of the specified version.
*
* \section structured Structured append
* Libqrencode can generate "Structured-appended" symbols that enables to split
* a large data set into mulitple QR codes. A QR code reader concatenates
* multiple QR code symbols into a string.
* Just like QRcode_encodeString(), you can use QRcode_encodeStringStructured()
* to generate structured-appended symbols. This functions returns an instance
* of ::QRcode_List. The returned list is a singly-linked list of QRcode: you
* can retrieve each QR code in this way:
*
* \code
* QRcode_List *qrcodes;
* QRcode_List *entry;
* QRcode *qrcode;
*
* qrcodes = QRcode_encodeStringStructured(...);
* entry = qrcodes;
* while(entry != NULL) {
* qrcode = entry->code;
* // do something
* entry = entry->next;
* }
* QRcode_List_free(entry);
* \endcode
*
* Instead of using auto-parsing functions, you can construct your own
* structured input. At first, instantiate an object of ::QRinput_Struct
* by calling QRinput_Struct_new(). This object can hold multiple ::QRinput,
* and one QR code is generated for a ::QRinput.
* QRinput_Struct_appendInput() appends a ::QRinput to a ::QRinput_Struct
* object. In order to generate structured-appended symbols, it is required to
* embed headers to each symbol. You can use
* QRinput_Struct_insertStructuredAppendHeaders() to insert appropriate
* headers to each symbol. You should call this function just once before
* encoding symbols.
*/
#ifndef QRENCODE_H
#define QRENCODE_H
#if defined(__cplusplus)
extern "C" {
#endif
/**
* Encoding mode.
*/
typedef enum {
QR_MODE_NUL = -1, ///< Terminator (NUL character). Internal use only
QR_MODE_NUM = 0, ///< Numeric mode
QR_MODE_AN, ///< Alphabet-numeric mode
QR_MODE_8, ///< 8-bit data mode
QR_MODE_KANJI, ///< Kanji (shift-jis) mode
QR_MODE_STRUCTURE, ///< Internal use only
QR_MODE_ECI, ///< ECI mode
QR_MODE_FNC1FIRST, ///< FNC1, first position
QR_MODE_FNC1SECOND, ///< FNC1, second position
} QRencodeMode;
/**
* Level of error correction.
*/
typedef enum {
QR_ECLEVEL_L = 0, ///< lowest
QR_ECLEVEL_M,
QR_ECLEVEL_Q,
QR_ECLEVEL_H ///< highest
} QRecLevel;
/**
* Maximum version (size) of QR-code symbol.
*/
#define QRSPEC_VERSION_MAX 40
/**
* Maximum version (size) of QR-code symbol.
*/
#define MQRSPEC_VERSION_MAX 4
/******************************************************************************
* Input data (qrinput.c)
*****************************************************************************/
/**
* Singly linked list to contain input strings. An instance of this class
* contains its version and error correction level too. It is required to
* set them by QRinput_setVersion() and QRinput_setErrorCorrectionLevel(),
* or use QRinput_new2() to instantiate an object.
*/
typedef struct _QRinput QRinput;
/**
* Instantiate an input data object. The version is set to 0 (auto-select)
* and the error correction level is set to QR_ECLEVEL_L.
* @return an input object (initialized). On error, NULL is returned and errno
* is set to indicate the error.
* @throw ENOMEM unable to allocate memory.
*/
extern QRinput *QRinput_new(void);
/**
* Instantiate an input data object.
* @param version version number.
* @param level Error correction level.
* @return an input object (initialized). On error, NULL is returned and errno
* is set to indicate the error.
* @throw ENOMEM unable to allocate memory for input objects.
* @throw EINVAL invalid arguments.
*/
extern QRinput *QRinput_new2(int version, QRecLevel level);
/**
* Instantiate an input data object. Object's Micro QR Code flag is set.
* Unlike with full-sized QR Code, version number must be specified (>0).
* @param version version number (1--4).
* @param level Error correction level.
* @return an input object (initialized). On error, NULL is returned and errno
* is set to indicate the error.
* @throw ENOMEM unable to allocate memory for input objects.
* @throw EINVAL invalid arguments.
*/
extern QRinput *QRinput_newMQR(int version, QRecLevel level);
/**
* Append data to an input object.
* The data is copied and appended to the input object.
* @param input input object.
* @param mode encoding mode.
* @param size size of data (byte).
* @param data a pointer to the memory area of the input data.
* @retval 0 success.
* @retval -1 an error occurred and errno is set to indeicate the error.
* See Execptions for the details.
* @throw ENOMEM unable to allocate memory.
* @throw EINVAL input data is invalid.
*
*/
extern int QRinput_append(QRinput *input, QRencodeMode mode, int size, const unsigned char *data);
/**
* Append ECI header.
* @param input input object.
* @param ecinum ECI indicator number (0 - 999999)
* @retval 0 success.
* @retval -1 an error occurred and errno is set to indeicate the error.
* See Execptions for the details.
* @throw ENOMEM unable to allocate memory.
* @throw EINVAL input data is invalid.
*
*/
extern int QRinput_appendECIheader(QRinput *input, unsigned int ecinum);
/**
* Get current version.
* @param input input object.
* @return current version.
*/
extern int QRinput_getVersion(QRinput *input);
/**
* Set version of the QR code that is to be encoded.
* This function cannot be applied to Micro QR Code.
* @param input input object.
* @param version version number (0 = auto)
* @retval 0 success.
* @retval -1 invalid argument.
*/
extern int QRinput_setVersion(QRinput *input, int version);
/**
* Get current error correction level.
* @param input input object.
* @return Current error correcntion level.
*/
extern QRecLevel QRinput_getErrorCorrectionLevel(QRinput *input);
/**
* Set error correction level of the QR code that is to be encoded.
* This function cannot be applied to Micro QR Code.
* @param input input object.
* @param level Error correction level.
* @retval 0 success.
* @retval -1 invalid argument.
*/
extern int QRinput_setErrorCorrectionLevel(QRinput *input, QRecLevel level);
/**
* Set version and error correction level of the QR code at once.
* This function is recommened for Micro QR Code.
* @param input input object.
* @param version version number (0 = auto)
* @param level Error correction level.
* @retval 0 success.
* @retval -1 invalid argument.
*/
extern int QRinput_setVersionAndErrorCorrectionLevel(QRinput *input, int version, QRecLevel level);
/**
* Free the input object.
* All of data chunks in the input object are freed too.
* @param input input object.
*/
extern void QRinput_free(QRinput *input);
/**
* Validate the input data.
* @param mode encoding mode.
* @param size size of data (byte).
* @param data a pointer to the memory area of the input data.
* @retval 0 success.
* @retval -1 invalid arguments.
*/
extern int QRinput_check(QRencodeMode mode, int size, const unsigned char *data);
/**
* Set of QRinput for structured symbols.
*/
typedef struct _QRinput_Struct QRinput_Struct;
/**
* Instantiate a set of input data object.
* @return an instance of QRinput_Struct. On error, NULL is returned and errno
* is set to indicate the error.
* @throw ENOMEM unable to allocate memory.
*/
extern QRinput_Struct *QRinput_Struct_new(void);
/**
* Set parity of structured symbols.
* @param s structured input object.
* @param parity parity of s.
*/
extern void QRinput_Struct_setParity(QRinput_Struct *s, unsigned char parity);
/**
* Append a QRinput object to the set. QRinput created by QRinput_newMQR()
* will be rejected.
* @warning never append the same QRinput object twice or more.
* @param s structured input object.
* @param input an input object.
* @retval >0 number of input objects in the structure.
* @retval -1 an error occurred. See Exceptions for the details.
* @throw ENOMEM unable to allocate memory.
* @throw EINVAL invalid arguments.
*/
extern int QRinput_Struct_appendInput(QRinput_Struct *s, QRinput *input);
/**
* Free all of QRinput in the set.
* @param s a structured input object.
*/
extern void QRinput_Struct_free(QRinput_Struct *s);
/**
* Split a QRinput to QRinput_Struct. It calculates a parity, set it, then
* insert structured-append headers. QRinput created by QRinput_newMQR() will
* be rejected.
* @param input input object. Version number and error correction level must be
* set.
* @return a set of input data. On error, NULL is returned, and errno is set
* to indicate the error. See Exceptions for the details.
* @throw ERANGE input data is too large.
* @throw EINVAL invalid input data.
* @throw ENOMEM unable to allocate memory.
*/
extern QRinput_Struct *QRinput_splitQRinputToStruct(QRinput *input);
/**
* Insert structured-append headers to the input structure. It calculates
* a parity and set it if the parity is not set yet.
* @param s input structure
* @retval 0 success.
* @retval -1 an error occurred and errno is set to indeicate the error.
* See Execptions for the details.
* @throw EINVAL invalid input object.
* @throw ENOMEM unable to allocate memory.
*/
extern int QRinput_Struct_insertStructuredAppendHeaders(QRinput_Struct *s);
/**
* Set FNC1-1st position flag.
*/
extern int QRinput_setFNC1First(QRinput *input);
/**
* Set FNC1-2nd position flag and application identifier.
*/
extern int QRinput_setFNC1Second(QRinput *input, unsigned char appid);
/******************************************************************************
* QRcode output (qrencode.c)
*****************************************************************************/
/**
* QRcode class.
* Symbol data is represented as an array contains width*width uchars.
* Each uchar represents a module (dot). If the less significant bit of
* the uchar is 1, the corresponding module is black. The other bits are
* meaningless for usual applications, but here its specification is described.
*
* @verbatim
MSB 76543210 LSB
|||||||`- 1=black/0=white
||||||`-- 1=ecc/0=data code area
|||||`--- format information
||||`---- version information
|||`----- timing pattern
||`------ alignment pattern
|`------- finder pattern and separator
`-------- non-data modules (format, timing, etc.)
@endverbatim
*/
typedef struct {
int version; ///< version of the symbol
int width; ///< width of the symbol
unsigned char *data; ///< symbol data
} QRcode;
/**
* Singly-linked list of QRcode. Used to represent a structured symbols.
* A list is terminated with NULL.
*/
typedef struct _QRcode_List {
QRcode *code;
struct _QRcode_List *next;
} QRcode_List;
/**
* Create a symbol from the input data.
* @warning This function is THREAD UNSAFE when pthread is disabled.
* @param input input data.
* @return an instance of QRcode class. The version of the result QRcode may
* be larger than the designated version. On error, NULL is returned,
* and errno is set to indicate the error. See Exceptions for the
* details.
* @throw EINVAL invalid input object.
* @throw ENOMEM unable to allocate memory for input objects.
*/
extern QRcode *QRcode_encodeInput(QRinput *input);
/**
* Create a symbol from the string. The library automatically parses the input
* string and encodes in a QR Code symbol.
* @warning This function is THREAD UNSAFE when pthread is disabled.
* @param string input string. It must be NUL terminated.
* @param version version of the symbol. If 0, the library chooses the minimum
* version for the given input data.
* @param level error correction level.
* @param hint tell the library how Japanese Kanji characters should be
* encoded. If QR_MODE_KANJI is given, the library assumes that the
* given string contains Shift-JIS characters and encodes them in
* Kanji-mode. If QR_MODE_8 is given, all of non-alphanumerical
* characters will be encoded as is. If you want to embed UTF-8
* string, choose this. Other mode will cause EINVAL error.
* @param casesensitive case-sensitive(1) or not(0).
* @return an instance of QRcode class. The version of the result QRcode may
* be larger than the designated version. On error, NULL is returned,
* and errno is set to indicate the error. See Exceptions for the
* details.
* @throw EINVAL invalid input object.
* @throw ENOMEM unable to allocate memory for input objects.
* @throw ERANGE input data is too large.
*/
extern QRcode *QRcode_encodeString(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive);
/**
* Same to QRcode_encodeString(), but encode whole data in 8-bit mode.
* @warning This function is THREAD UNSAFE when pthread is disabled.
*/
extern QRcode *QRcode_encodeString8bit(const char *string, int version, QRecLevel level);
/**
* Micro QR Code version of QRcode_encodeString().
* @warning This function is THREAD UNSAFE when pthread is disabled.
*/
extern QRcode *QRcode_encodeStringMQR(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive);
/**
* Micro QR Code version of QRcode_encodeString8bit().
* @warning This function is THREAD UNSAFE when pthread is disabled.
*/
extern QRcode *QRcode_encodeString8bitMQR(const char *string, int version, QRecLevel level);
/**
* Encode byte stream (may include '\0') in 8-bit mode.
* @warning This function is THREAD UNSAFE when pthread is disabled.
* @param size size of the input data.
* @param data input data.
* @param version version of the symbol. If 0, the library chooses the minimum
* version for the given input data.
* @param level error correction level.
* @throw EINVAL invalid input object.
* @throw ENOMEM unable to allocate memory for input objects.
* @throw ERANGE input data is too large.
*/
extern QRcode *QRcode_encodeData(int size, const unsigned char *data, int version, QRecLevel level);
/**
* Micro QR Code version of QRcode_encodeData().
* @warning This function is THREAD UNSAFE when pthread is disabled.
*/
extern QRcode *QRcode_encodeDataMQR(int size, const unsigned char *data, int version, QRecLevel level);
/**
* Free the instance of QRcode class.
* @param qrcode an instance of QRcode class.
*/
extern void QRcode_free(QRcode *qrcode);
/**
* Create structured symbols from the input data.
* @warning This function is THREAD UNSAFE when pthread is disabled.
* @param s input data, structured.
* @return a singly-linked list of QRcode.
*/
extern QRcode_List *QRcode_encodeInputStructured(QRinput_Struct *s);
/**
* Create structured symbols from the string. The library automatically parses
* the input string and encodes in a QR Code symbol.
* @warning This function is THREAD UNSAFE when pthread is disabled.
* @param string input string. It must be NUL terminated.
* @param version version of the symbol.
* @param level error correction level.
* @param hint tell the library how Japanese Kanji characters should be
* encoded. If QR_MODE_KANJI is given, the library assumes that the
* given string contains Shift-JIS characters and encodes them in
* Kanji-mode. If QR_MODE_8 is given, all of non-alphanumerical
* characters will be encoded as is. If you want to embed UTF-8
* string, choose this. Other mode will cause EINVAL error.
* @param casesensitive case-sensitive(1) or not(0).
* @return a singly-linked list of QRcode. On error, NULL is returned, and
* errno is set to indicate the error. See Exceptions for the details.
* @throw EINVAL invalid input object.
* @throw ENOMEM unable to allocate memory for input objects.
*/
extern QRcode_List *QRcode_encodeStringStructured(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive);
/**
* Same to QRcode_encodeStringStructured(), but encode whole data in 8-bit mode.
* @warning This function is THREAD UNSAFE when pthread is disabled.
*/
extern QRcode_List *QRcode_encodeString8bitStructured(const char *string, int version, QRecLevel level);
/**
* Create structured symbols from byte stream (may include '\0'). Wholde data
* are encoded in 8-bit mode.
* @warning This function is THREAD UNSAFE when pthread is disabled.
* @param size size of the input data.
* @param data input dat.
* @param version version of the symbol.
* @param level error correction level.
* @return a singly-linked list of QRcode. On error, NULL is returned, and
* errno is set to indicate the error. See Exceptions for the details.
* @throw EINVAL invalid input object.
* @throw ENOMEM unable to allocate memory for input objects.
*/
extern QRcode_List *QRcode_encodeDataStructured(int size, const unsigned char *data, int version, QRecLevel level);
/**
* Return the number of symbols included in a QRcode_List.
* @param qrlist a head entry of a QRcode_List.
* @return number of symbols in the list.
*/
extern int QRcode_List_size(QRcode_List *qrlist);
/**
* Free the QRcode_List.
* @param qrlist a head entry of a QRcode_List.
*/
extern void QRcode_List_free(QRcode_List *qrlist);
/******************************************************************************
* System utilities
*****************************************************************************/
/**
* Return a string that identifies the library version.
* @param major_version major version number
* @param minor_version minor version number
* @param micro_version micro version number
*/
extern void QRcode_APIVersion(int *major_version, int *minor_version, int *micro_version);
/**
* Return a string that identifies the library version.
* @return a string identifies the library version. The string is held by the
* library. Do NOT free it.
*/
extern char *QRcode_APIVersionString(void);
/**
* @deprecated
*/
#ifndef _MSC_VER
extern void QRcode_clearCache(void) __attribute__ ((deprecated));
#else
extern void QRcode_clearCache(void);
#endif
#if defined(__cplusplus)
}
#endif
#endif /* QRENCODE_H */

View File

@ -0,0 +1,88 @@
/**
* qrencode - QR Code encoder
*
* Header for test use
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef QRENCODE_INNER_H
#define QRENCODE_INNER_H
/**
* This header file includes definitions for test use.
*/
/******************************************************************************
* Raw code
*****************************************************************************/
typedef struct {
int dataLength;
int eccLength;
unsigned char *data;
unsigned char *ecc;
} RSblock;
typedef struct {
int version;
int dataLength;
int eccLength;
unsigned char *datacode;
unsigned char *ecccode;
int b1;
int blocks;
RSblock *rsblock;
int count;
} QRRawCode;
extern QRRawCode *QRraw_new(QRinput *input);
extern unsigned char QRraw_getCode(QRRawCode *raw);
extern void QRraw_free(QRRawCode *raw);
/******************************************************************************
* Raw code for Micro QR Code
*****************************************************************************/
typedef struct {
int version;
int dataLength;
int eccLength;
unsigned char *datacode;
unsigned char *ecccode;
RSblock *rsblock;
int oddbits;
int count;
} MQRRawCode;
extern MQRRawCode *MQRraw_new(QRinput *input);
extern unsigned char MQRraw_getCode(MQRRawCode *raw);
extern void MQRraw_free(MQRRawCode *raw);
/******************************************************************************
* Frame filling
*****************************************************************************/
extern unsigned char *FrameFiller_test(int version);
extern unsigned char *FrameFiller_testMQR(int version);
/******************************************************************************
* QR-code encoding
*****************************************************************************/
extern QRcode *QRcode_encodeMask(QRinput *input, int mask);
extern QRcode *QRcode_encodeMaskMQR(QRinput *input, int mask);
extern QRcode *QRcode_new(int version, int width, unsigned char *data);
#endif /* QRENCODE_INNER_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,123 @@
/*
* qrencode - QR Code encoder
*
* Input data chunk class
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef QRINPUT_H
#define QRINPUT_H
#include "qrencode.h"
#include "bitstream.h"
int QRinput_isSplittableMode(QRencodeMode mode);
/******************************************************************************
* Entry of input data
*****************************************************************************/
typedef struct _QRinput_List QRinput_List;
struct _QRinput_List {
QRencodeMode mode;
int size; ///< Size of data chunk (byte).
unsigned char *data; ///< Data chunk.
BitStream *bstream;
QRinput_List *next;
};
/******************************************************************************
* Input Data
*****************************************************************************/
struct _QRinput {
int version;
QRecLevel level;
QRinput_List *head;
QRinput_List *tail;
int mqr;
int fnc1;
unsigned char appid;
};
/******************************************************************************
* Structured append input data
*****************************************************************************/
typedef struct _QRinput_InputList QRinput_InputList;
struct _QRinput_InputList {
QRinput *input;
QRinput_InputList *next;
};
struct _QRinput_Struct {
int size; ///< number of structured symbols
int parity;
QRinput_InputList *head;
QRinput_InputList *tail;
};
/**
* Pack all bit streams padding bits into a byte array.
* @param input input data.
* @return padded merged byte stream
*/
extern unsigned char *QRinput_getByteStream(QRinput *input);
extern int QRinput_estimateBitsModeNum(int size);
extern int QRinput_estimateBitsModeAn(int size);
extern int QRinput_estimateBitsMode8(int size);
extern int QRinput_estimateBitsModeKanji(int size);
extern QRinput *QRinput_dup(QRinput *input);
extern const signed char QRinput_anTable[128];
/**
* Look up the alphabet-numeric convesion table (see JIS X0510:2004, pp.19).
* @param __c__ character
* @return value
*/
#define QRinput_lookAnTable(__c__) \
((__c__ & 0x80)?-1:QRinput_anTable[(int)__c__])
/**
* Length of a standard mode indicator in bits.
*/
#define MODE_INDICATOR_SIZE 4
/**
* Length of a segment of structured-append header.
*/
#define STRUCTURE_HEADER_SIZE 20
/**
* Maximum number of symbols in a set of structured-appended symbols.
*/
#define MAX_STRUCTURED_SYMBOLS 16
#ifdef WITH_TESTS
extern int QRinput_mergeBitStream(QRinput *input, BitStream *bstream);
extern int QRinput_getBitStream(QRinput *input, BitStream *bstream);
extern int QRinput_estimateBitStreamSize(QRinput *input, int version);
extern int QRinput_splitEntry(QRinput_List *entry, int bytes);
extern int QRinput_lengthOfCode(QRencodeMode mode, int version, int bits);
extern int QRinput_insertStructuredAppendHeader(QRinput *input, int size, int index, unsigned char parity);
#endif
#endif /* QRINPUT_H */

Some files were not shown because too many files have changed in this diff Show More