串口mcu:重新编写的ldisc

 * 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);

 


 

 

你可能感兴趣的:(电路与硬件的通信协议,uart,ldisc)