* Modification:
* - Data : 2015年9月12日
* - Revision: 初稿
* - Author : chen_guangjian
* - Contents: 创建文件
*
*-------------------------------------------------------------------------------------------------------------------*/
/*----------------------------------------------*
* 包含头文件 *
*----------------------------------------------*/
/**内核依赖的头文件**/
#include "drvbox_c.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/*本地头文件*/
#include "mcu_common.h"
#include "mcuinfo_resource.h"
#include "mcu_if_uart.h"
//static int L_FD = -1;
static struct file *gfilp=NULL;
/************************************************************************
* 外部函数实现 *
************************************************************************/
int32_t Mcu_IF_Uart_Open(McuInfoRes_t * mcuRes)
{
int err =-1;
int i_ld = N_UART;
//打开串口
#if 0 //sys_open's 方式,内核模块找不到符号表
struct ktermios option;
//L_FD = sys_open(mcuRes->UART_Res.Res.Name,0,0);
if (L_FD >= 0) {
//初始化uart配置信息
//底层驱动注册的时候已经有默认的设置tty_std_termios{}
err = sys_ioctl(L_FD,TCGETS,(long)&option);//先获取回来,
/*
option.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
option.c_iflag = ICRNL | IXON;
option.c_oflag = OPOST | ONLCR;
option.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK |ECHOCTL | ECHOKE | IEXTEN;
option.c_cc = INIT_C_CC;
*/
//设置波特率
option.c_ispeed = option.c_ospeed = mcuRes->UART_Res.baudrate;
err = sys_ioctl(L_FD,TCSETSF,(long)&option);//--->set_termios /*TCSETSF:TCSETSW*/
//设置线路规则
err = sys_ioctl(L_FD, TIOCSETD, (long)&i_ld);
}
else
{
OSA_ERROR("mcu_if_uart_open error");
}
OSA_INFO("mcu_if_uart_open end err = %d \n",err);
#endif
#if 1//filp _open 的方法
struct termios settings;
mm_segment_t oldfs;
OSA_printf(KERN_INFO"type =%d \n",mcuRes->UART_Res.Res);
OSA_printf(KERN_INFO"name= %s \n",mcuRes->UART_Res.Res.Name);
gfilp = filp_open(mcuRes->UART_Res.Res.Name,O_RDWR,0);
if (IS_ERR(gfilp)) {
printk(" open dev error = %ld\n",PTR_ERR(gfilp));
}
else
{
//linux 3.0内核的tty_ops是unlocked_ioctl()
if(!(gfilp->f_op)||!(gfilp->f_op->unlocked_ioctl)||!(gfilp->f_op->write) )
{
OSA_ERROR("file f_op %s gfilp=%x cann't readable or writable?\n",mcuRes->UART_Res.Res.Name,gfilp);
return -1;
}
/*系统调用在内核空间会检查地址是否是__user,所以改变非用户空间地址的限制,
否则内核空间使用的系统调用的参数地址会出错*/
oldfs = get_fs();
set_fs(KERNEL_DS);
//初始化uart配置信息
//底层驱动注册的时候已经有默认的设置tty_std_termios{}
err = gfilp->f_op->unlocked_ioctl(gfilp, TCGETS, (unsigned long)&settings);
if(mcuRes->UART_Res.baudrate == 9600)
settings.c_cflag = B9600;
err = gfilp->f_op->unlocked_ioctl( gfilp, TCSETS, (unsigned long)&settings);
//设置线路规
err = gfilp->f_op->unlocked_ioctl(gfilp, TIOCSETD, (long)&i_ld);
set_fs(oldfs);
}
OSA_INFO("mcu_if_uart_open end err = %d \n",err);
#endif
return err;
}
int32_t Mcu_IF_Uart_Close(McuInfoRes_t * mcuRes)
{
int err =-1 ;
if(gfilp)
err = filp_close(gfilp,0);
gfilp = NULL;
return err;
}
/**
*读取一些杂项的数据,比如韦根应答包,升级应答包....
**/
int32_t Mcu_IF_ReadRaw(Char *pReadBuf,uint32_t size)
{
int ret = -1 ;
//if(gfilp)
// ret = gfilp->f_op->unlocked_ioctl(gfilp, MCU_UART_RAW_READ, (unsigned long)pReadBuf);
if(gfilp)
{
gfilp->f_pos = 0;
ret = gfilp->f_op->read(gfilp, pReadBuf, size, &gfilp->f_pos);
}
OSA_INFO("Mcu_IF_ReadRaw end ret = %d \n",ret);
return ret;
}
int32_t Mcu_IF_WriteRaw(const Char *pWriteBuf, Uint32 size)
{
int ret = -1 ;
if(gfilp)
{
gfilp->f_pos = 0;
ret = gfilp->f_op->write(gfilp, pWriteBuf, size, &gfilp->f_pos);
}
return ret;
}
/*
*读取按键信息的buf
*buf地址来自用户空间
*/
int32_t Mcu_IF_GetKey(Uint8 *pBuf)
{
int ret = -1 ;
if(gfilp)
ret = gfilp->f_op->unlocked_ioctl(gfilp, MCU_UART_READKEY, (unsigned long)pBuf);
OSA_INFO("Mcu_IF_GetKey end ret = %d \n",ret);
return ret;
}
/*
*读取iccard的信息
*/
int32_t Mcu_IF_ReadCard(Uint8 *pBuf)
{
int ret = -1 ;
if(gfilp)
ret = gfilp->f_op->unlocked_ioctl(gfilp, MCU_UART_READCARD, (unsigned long)pBuf);
OSA_INFO("Mcu_IF_GetKey end ret = %d \n",ret);
return ret;
}
int32_t Mcu_IF_Uart_PollEvent(poll_table *wait)
{
int ret =-1;
if(gfilp)
ret = gfilp->f_op->poll(gfilp, wait);
OSA_INFO("Mcu_IF_Uart_PollEvent end mask = 0x%x \n",ret);
return ret;
}/*******************************************************************************
* 描 述 : 开始升级,完成升级过程的握手,而updaet的数据,
通过RawWrite发送下来
* 输 入 : 无。
* 输 出 : 无。
* 返回值 : OSA_EFAIL: 失败
* OSA_SOK : 成功
*******************************************************************************/
int32_t Mcu_IF_Uart_UpgradeStart(void)
{
int ret = -1;
const Char update_buf_req[6] = {0xA6,0x00,0x07,0x60,0x00,0x0D};/*定义请求升级命令*/
Char pReadBuf[13] ={0};
uint32_t resp= 0x00;
if(!gfilp)
return OSA_EFAIL;
////发送请求升级命令
ret = gfilp->f_op->write(gfilp, update_buf_req, sizeof(update_buf_req), &gfilp->f_pos);
OSA_INFO("write update FW cmd ret = %x \n",ret);
if(ret < 0)
return OSA_EFAIL;
///等待升级命令的应答包
ret = gfilp->f_op->read(gfilp, pReadBuf, sizeof(pReadBuf), &gfilp->f_pos);
OSA_INFO("wait respond = %x \n",ret);
resp = pReadBuf[0] <<24 | pReadBuf[1]<<16 | pReadBuf[2]<<8 | pReadBuf[3];
if(ret < 0 )
{
OSA_INFO("UpgradeStart not respond \n");
return OSA_EFAIL;
}
//是否获取到正确的响应包,且允许升级pReadBuf[5] =1
if(( resp != MCU_UART_CMD_UPDATE_RESP )||(pReadBuf[5] !=1) )
{
return OSA_EFAIL;
}
// 获得单片机请求升级数据的第0包
ret = gfilp->f_op->read(gfilp, pReadBuf, sizeof(pReadBuf), &gfilp->f_pos);
OSA_INFO("wait respond first request packet= %x \n",ret);
if(ret < 0 )
{
OSA_INFO("UpgradeStart not respond \n");
return OSA_EFAIL;
}
//是否获取到正确的响应包
if(resp != MCU_UART_CMD_UPDATE_REQUEST )
{
return OSA_EFAIL;
}
OSA_INFO("Mcu_IF_Uart_UpgradeStart end \n");
return OSA_SOK;
}
Mcu_If_Driver_t Mcu_IF_Uart_Driver =
{
.pUsrArgs = NULL,
.OpOpen = Mcu_IF_Uart_Open,
.OpClose = Mcu_IF_Uart_Close,
.RawRead = Mcu_IF_ReadRaw,
.RawWrite = Mcu_IF_WriteRaw,
.UpgradeStart = Mcu_IF_Uart_UpgradeStart,
.UpgradeEnd = NULL,
.PollEvent = Mcu_IF_Uart_PollEvent,
.GetEvent = NULL,
.GetKey = Mcu_IF_GetKey,
.GetSoftwareVer = NULL,
.ReadCard = Mcu_IF_ReadCard,
.ResetMcu =NULL,
};
/*******************************************************************
* 内部函数实现***********************************************
*******************************************************************/
/* 调试log设置 */
#define DEBUG_LEVEL_INFO 1
static int debuglevel;
/*
* DH uart ldisc的buffer管理函数
*/
static void Uart_Ldisc_buf_list_init(struct Uart_Ldisc_buf_list *list);
static void Uart_Ldisc_buf_put(struct Uart_Ldisc_buf_list *list,struct Uart_Ldisc_buf *buf);
static struct Uart_Ldisc_buf *Uart_Ldisc_buf_get(struct Uart_Ldisc_buf_list *list);
static struct Uart_Ldisc *Uart_Ldisc_alloc (void);
/* 收发数据的buf定义*/
#define DEFAULT_RX_BUF_COUNT 3
#define DEFAULT_TX_BUF_COUNT 3
static int max_rx_buf_frame = 15;
static int max_tx_buf_frame = 130;
#define RX_BUF_SIZE(sizeof(struct Uart_Ldisc_buf) + max_rx_buf_frame)
#define TX_BUF_SIZE(sizeof(struct Uart_Ldisc_buf) + max_tx_buf_frame)
/* TTY ldisc的回调函数 */
static ssize_t Uart_Ldisc_tty_read(struct tty_struct *tty, struct file *file,
__u8 __user *buf, size_t nr);
static ssize_t Uart_Ldisc_tty_write(struct tty_struct *tty, struct file *file,
const unsigned char *buf, size_t nr);
static int Uart_Ldisc_tty_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg);
static unsigned int Uart_Ldisc_tty_poll(struct tty_struct *tty, struct file *filp,
poll_table *wait);
static int Uart_Ldisc_tty_open(struct tty_struct *tty);
static void Uart_Ldisc_tty_close(struct tty_struct *tty);
static void Uart_Ldisc_tty_receive(struct tty_struct *tty, const __u8 *cp,
char *fp, int count);
static void Uart_Ldisc_tty_wakeup(struct tty_struct *tty);
/*定义tty 与ldisc之间的结构体获取*/
#define tty2Uart_Ldisc(tty) ((struct Uart_Ldisc *) ((tty)->disc_data))
#define Uart_Ldisc2tty(Uart_Ldisc) ((Uart_Ldisc)->tty)
.....
int Uart_Ldisc_init(void)
{
int status=0;
debuglevel = 2;//调试等级设置
//注册ldisc,用于处理uart口收到的单片机数据。
status = tty_register_ldisc(N_UART, &Uart_Ldisc_ldisc);
if (!status)
OSA_INFO("Uart_Ldisc_init ok \n");
else
OSA_ERROR("Uart_Ldisc_init falied %d \n", status);
return status;
}
void Uart_Ldisc_exit(void)
{
int status = tty_unregister_ldisc(N_UART);
if (status)
OSA_ERROR("Uart_Ldisc_exit failed %d \n", status);
else
OSA_INFO("Uart_Ldisc_exit ok !");
}
头文件
* - 使用说明: mcu_if_uart.h 作为uart接口的mcu与主机直接协议解析的驱动
*
* - 局限性说明:
*
* - 其他说明:
*
*
* Modification:
* - Data : 2015年9月12日
* - Revision: 初稿
* - Author : chen_guangjian
* - Contents: 创建文件
*
*-------------------------------------------------------------------------------------------------------------------*/
/*----------------------------------------------*
* 包含头文件 *
*----------------------------------------------*/
#include "mcu_common.h"
#include
/*----------------------------------------------*
* 宏定义 *
*----------------------------------------------*/
#define MCU_UART_IOC_MAGIC 'M'
/* 按键状态 */
#define MCU_UART_READKEY _IOWR(MCU_IOC_MAGIC, 0x1, int)
/* 裸读MCU */
#define MCU_UART_RAW_READ _IOWR(MCU_IOC_MAGIC, 0x2, int)
/* 读取卡信息*/
#define MCU_UART_READCARD _IOWR(MCU_IOC_MAGIC, 0x3, int)
/**参考内核头文件tty.h**/
#define N_UART 19
#define LDISC_MAGIC 0xFFFF
/*----------------------------------------------*
* 数据结构
*----------------------------------------------*/
/*
*这里定义的是单片机与主机之间协议解析的头部命令
*
*/
#define MCU_UART_CMD_HEAD_LEN 4//前4个字节
#define MCU_UART_CMD_CARD 0xA6000710
#define MCU_UART_CMD_KEY0xA6000720
#define MCU_UART_CMD_KEEPALIVE0xA6000730
#define MCU_UART_CMD_KEEPALIVE_RESP0xA6000731
#define MCU_UART_CMD_SETLED 0xA6000740
#define MCU_UART_CMD_SETWEIGEN0xA6000750
#define MCU_UART_CMD_WEIGEN_RESP0xA6000751
#define MCU_UART_CMD_SETID0xA6000752
#define MCU_UART_CMD_UPDATE_START0xA6000760
#define MCU_UART_CMD_UPDATE_RESP0xA6000761
#define MCU_UART_CMD_UPDATE_REQUEST0xA6000762
#define MCU_UART_CMD_UPDATE_DATA0xA6000763
#define MCU_UART_CMD_UPDATE_END0xA6000764
#define MCU_UART_CMD_UPDATE_END_RESP0xA6000765
#define MCU_UART_CMD_UNKNONW0xFFFFFFFF
struct Uart_Ldisc_buf {
struct Uart_Ldisc_buf *link;
int count;
char buf[1];
};
struct Uart_Ldisc_buf_list {
struct Uart_Ldisc_buf *head;
struct Uart_Ldisc_buf *tail;
int count;
spinlock_t spinlock;
};
struct Uart_Ldisc {
int magic;
__u32 flags;
struct tty_struct*tty;
//传输控制标志
int tbusy;
int woke_up;
struct Uart_Ldisc_buf*tbuf; //当前正在发送的buf项
struct Uart_Ldisc_buf_listtx_buf_list; //用于发送的buf链表
struct Uart_Ldisc_buf_listtx_free_buf_list; //用于缓存应用发下来的buf链表
struct Uart_Ldisc_buf_listrx_card_buf_list; //用于发送给用户的card buf 链表
struct Uart_Ldisc_buf_listrx_free_card_buf_list; //用于缓存ldisc收到的card buf链表
struct Uart_Ldisc_buf_listrx_key_buf_list; //用于发送给用户的key buf 链表
struct Uart_Ldisc_buf_listrx_free_key_buf_list; //用于缓存ldisc收到的key buf链?struct Uart_Ldisc_buf_list rx_misc_buf_list;//用于发送给用户的杂项 buf 链表
struct Uart_Ldisc_buf_listrx_free_misc_buf_list; //用于缓存ldisc收到的杂项buf链?};
extern int Uart_Ldisc_init(void);
extern void Uart_Ldisc_exit(void);