#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <time.h>
#include <execinfo.h>
#include <signal.h>
static int g_exit =0;
static pthread_t tid1;
static pthread_t tid2;
static pthread_t tid3;
typedef void *Ptr;
/* MCU字符驱动的"魔数" */
#define MCU_IOC_MAGIC 'M'
/* 按键状态 */
#define MCU_KEY_STATE _IOWR( MCU_IOC_MAGIC, 0x1, Ptr)
/* 裸读MCU */
#define MCU_RAW_READ _IOWR( MCU_IOC_MAGIC, 0x2, Ptr)
/* 裸写MCU */
#define MCU_RAW_WRITE _IOWR( MCU_IOC_MAGIC, 0x3, Ptr)
/* 开始升级 */
#define MCU_UPGRADE_START _IOWR( MCU_IOC_MAGIC, 0x4, Ptr)
/* 结束升级 */
#define MCU_UPGRADE_END _IOWR( MCU_IOC_MAGIC, 0x5, Ptr)
/*获得MCU的能力*/
#define MCU_GET_CAPS _IOWR( MCU_IOC_MAGIC, 0x6, Ptr)
/* 复位MCU */
#define MCU_RESET
_IOWR( MCU_IOC_MAGIC, 0x7, Ptr)
/* 读取卡信息*/
#define MCU_READCARD
_IOWR( MCU_IOC_MAGIC, 0x8, Ptr)
typedef struct {
int fd;
int cmd;
}para;
void *read_thread(void *p)
{
int i=0;
int ret = -1;
char buf[7]={0x00};
para *pa = p;
printf("read_thread!\n" );
do
{
ret = ioctl(pa->fd,pa->cmd,&buf);
printf("read_thread ret=%d \n",ret );
if(ret > 0)
{
for(i=0 ; i< 7;i++)
{
printf("buf[%d] = %x \n",i,buf[i]);
buf[i] = 0x00;//清除
}
}
}while(!g_exit);
return;
}
void *read_thread_card(void *p)
{
int i=0;
int ret = -1;
char buf[15]={0x00};
para *pa = p;
printf("read_thread card :\n" );
do
{
ret = ioctl(pa->fd,pa->cmd,&buf);
printf("read_thread card ret=%d \n",ret );
if(ret > 0)
{
for(i=0 ; i< 15;i++)
{
printf("buf[%d] = %x \n",i,buf[i]);
buf[i] = 0;
}
}
}while(!g_exit);
return;
}
char update_buf_request[7] = {0xA6,0x00,0x7,0x60, 0x00,0x0D,0x1A};
typedef struct UpData
// 升级数据下发
{
//命令区//0xA6000763 or 0xA6000764
char cmd_h;
//0xa6
char slave_addr;
//0x00
char cmd_g;
//0x07
char cmd_code;
//0x63
//数据区
char dwIndex_h;
// 数据 index (第几包) 2个字节
char dwIndex_l;
char
btDataSize;
// 数据长度1个字节
char btBuffer[1];
// 长度为 btDataSize;
}TUpData,*LpUpData;
char caculate_check_sum(TUpData *outbuf,char * buf)
{
char res=0x00;
unsigned int sum=0x00;
int i =0;
//命令部分
sum = (outbuf->cmd_h) + (outbuf->slave_addr) + (outbuf->cmd_g)+ (outbuf->cmd_code);
printf("sum cmd= 0x%x \n",sum);
//数据部分
sum += (outbuf->dwIndex_h +outbuf->dwIndex_l +outbuf->btDataSize);
printf("sum data= 0x%x \n",sum);
for(i=0; i < outbuf->btDataSize ;i++)
sum += *(buf+i);
//只取low 8bit
res =0xFF& sum;
printf("check res = %x sum =0x%x\n",res,sum);
return res;
}
void *update_thread(void *p)
{
int i=0;
int ret = -1;
char dw_resp_buf[10]={0x00};
FILE *fo;
char * inBuf=NULL;
TUpData * outBuf=NULL;
char len= 128;//默认根据协议每包128字节,控制读取文件的长度
char lastlen=0;//最后一包数据的长度
int loop;//
int file_len =0;
int readed_len;
para *pa = p;
printf("update_thread!\n" );
//握手过程
//ret = ioctl(pa->fd, MCU_UPGRADE_START,&buf);
ret = 0;//
printf("hand shake = %x \n",ret);
if(ret < 0)
{
goto EXIT_THREAD;
}
// 打开文件
if( NULL == (fo = fopen("/mnt/misc/buf2", "rb")))
{
printf("Open output file invalid\n");
goto EXIT_THREAD;
}
else
{
printf("open /mnt/misc/sg succeed\n");
}
//获取升级文件的大小
fseek(fo, 0, SEEK_END);//文件流位置是末尾
file_len = ftell(fo);//获取大小
fseek(fo, 0, SEEK_SET);//设置文件流为起始位置
if(file_len <128)
{
printf("file_len is small than 128 bytes");
goto EXIT_THREAD;
}
lastlen = file_len%128;
if(lastlen ==0)//整除128个字节
{
loop = file_len/128;
lastlen = 128;
}
else
{
loop = file_len/128+1;}
printf("file len=%d loop=%d lastlen =%d \n",file_len,loop,lastlen);
//申请buf缓存读出的文件
if(NULL == (inBuf = malloc(len+1)))//+1byte校验和
{
printf("malloc failed \n");
goto EXIT_THREAD;
}
//申请封装数据包的内存
if(NULL == (outBuf=malloc(sizeof(TUpData)+len+1)))//128+1byte校验和
{
printf("malloc outBuf failed \n");
goto EXIT_THREAD;
}
//开始升级数据
while ((--loop) >= 0)
{
readed_len = (unsigned int)fread(inBuf,1,len,fo) ;
if(readed_len <= 0 )
{
printf("***** read err %d\n",readed_len);
goto EXIT_THREAD;
}
//封装数据
if(loop >0 )
{
len = 128;
outBuf->cmd_h
= 0xA6;//0xa6000763;
outBuf->slave_addr
=0x00;
outBuf->cmd_g
=0x07;
outBuf->cmd_code
=0x63;
outBuf->dwIndex_h =dw_resp_buf[6];//第一包是0
outBuf->dwIndex_h =dw_resp_buf[7];
outBuf->btDataSize = len;
*(inBuf+len)
= caculate_check_sum(outBuf,inBuf);
memcpy(outBuf->btBuffer,inBuf,outBuf->btDataSize+1);
printf("the loop =%d packet len=%d \n",loop,len);
}//最后一包
else{
outBuf->cmd_h
= 0xA6;//0xa6000764;
outBuf->slave_addr
=0x00;
outBuf->cmd_g
=0x07;
outBuf->cmd_code
=0x64;
outBuf->dwIndex_h =dw_resp_buf[6];
outBuf->dwIndex_h =dw_resp_buf[7];
outBuf->btDataSize = len;
*(inBuf+len)
= caculate_check_sum(outBuf,inBuf);
memcpy(outBuf->btBuffer,inBuf,outBuf->btDataSize+1);
printf("the last packet \n");
}
//写入一包数据,阻塞5s
printf("start to write the [%d] packet len=%d checksum=0x%x \n",loop,len,*(outBuf->btBuffer+len));
//ret = write(pa->fd,outBuf,sizeof(outBuf));//
if(0)//ret < 0 )
{
printf("write packet err =%d \n");
goto
FAILED;
}
//设置最后一包的长度
if(loop == 1 )
len = lastlen;
printf(" write packet done and wait for next resp %d \n",ret);
//等待应答,阻塞访问3s后超时
//ret = ioctl(pa->fd, MCU_RAW_READ,&dw_resp_buf);
if(1)//ret > 0)
{
for(i=0 ; i< 10;i++)
{
//printf("buf[%d] = %x \n",i,dw_resp_buf[i]);
}
}
else
{
printf("respond err =%d \n",ret);
goto
FAILED;
}
};
FAILED:
free(inBuf);
free(outBuf);
EXIT_THREAD:
//升级线程退出
printf(" update FW thread exit !!! \n");
pthread_join(tid3,NULL);
return;
}
static void sigprocess(int inSigno)
{
printf("need to exit the Demo!\n" );
if(tid1)
{
pthread_join(tid1,NULL);}//等待线程退出
if(tid2)
{
pthread_join(tid2,NULL);}//等待线程退出
if(tid3)
{
pthread_join(tid3,NULL);}//等待线程退出
g_exit = 1;
}
//最后一位是检验和,取前面所有数据和的低8位
char buf_led[7]=
{0xA6,0x00,0x07,0x40,0x01,0x01,0xEF};
char buf_keepalive[7]= {0xA6,0x00,0x07,0x30,0x01,0x02,0xE0};
int main ( int argc, char *argv[] )
{
int ret =0;
int fd = 0;
para para_t;
para para_t_card;
char buf[15]={0};
int i;
signal(SIGSEGV, sigprocess);
signal(SIGINT, sigprocess);
signal(SIGTERM, sigprocess);
//打开mcu
fd = open("/dev/ mcu", O_RDWR);
if (!fd)
{
printf("Error: cannot open mcu device.\n");
exit(1);
}
//测试写接口
ret = write(fd,&buf_led,sizeof(buf_led));
ret = write(fd,&buf_keepalive,sizeof(buf_keepalive));
do{
//测试polling接口和读接口的交互,同步
fd_set fds;
struct timeval tv;
int r;
FD_ZERO(&fds);
FD_SET(fd, &fds);
tv.tv_sec = 3;
tv.tv_usec = 0;
ret = select(fd + 1, &fds, NULL, NULL, &tv);
if (0 == ret) {
fprintf(stderr, "select timeout\n");
continue;
}
//有数据可以读
ret = read(fd,&buf,sizeof(buf));
printf("receive MCU data = %x \n",ret);
for(i=0 ; i< sizeof(buf);i++)
{
printf("buf[%d] = %x \n",i,buf[i]);
buf[i] = 0x00;//清除
}
break;
}while(!g_exit);
//end
printf("write buf done! ret = %d \n ",ret);
#if 1
//update线程
para_t.fd = fd;
para_t.cmd = MCU_UPGRADE_START;
ret = pthread_create(&tid1, NULL, (void *)update_thread, ¶_t);
if (ret < 0)
{
printf("create thread error\r\n");
pthread_exit(NULL);
}
#endif
//测试读接口
para_t.fd = fd;
para_t.cmd = MCU_KEY_STATE;
ret = pthread_create(&tid2, NULL, (void *)read_thread, ¶_t);
if (ret < 0)
{
printf("create thread error\r\n");
pthread_exit(NULL);
}
para_t_card.fd = fd;
para_t_card.cmd = MCU_READCARD;
ret = pthread_create(&tid3, NULL, (void *)read_thread_card, ¶_t_card);
if (ret < 0)
{
printf("create thread error\r\n");
pthread_exit(NULL);
}
while(!g_exit)
sleep(2);
printf("exit the Demo!\n" );
close(fd);
exit(1);
return 0;
}