周立功zlg600a 模块linux驱动

1.设备树中添加设备信息
nfc_reader:zlg600a@59 {
compatible = “nfc,zlg600a”;
reg = <0x59>;
interrupt-parent = <&gpio2>;
interrupts = <17 0>;
status = “disabled”;
};
2.驱动代码框架,具体细节不方便列出。

#include <linux/module.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/gpio_keys.h>
#include <linux/irq.h>
#include <linux/i2c.h>
#include <linux/fs.h>
#include <linux/delay.h>
#include <linux/miscdevice.h>
#include <asm-generic/errno.h>
#include <linux/slab.h>

#define __FRAME_LEN 0 /< \brief 帧长度 */
#define __FRAME_CMD_TYPE 1 /
< \brief 命令类型(高4位为包号) /
#define __FRAME_CMD 2 /**< \brief 命令
/
#define __FRAME_STATUS 2 /< \brief 响应状态 */
#define __FRAME_DATA_LEN 3 /
< \brief 数据长度 */
#define __FRAME_DATA 4 /< \brief 数据起始位置 */
#define __FRAME_PRTC_LEN 6 /
< \brief 协议字符长度 */

#define __CMD_TYPE_DEV_CTRL 0x01 /< \brief 设备控制类命令 */
#define __CMD_TYPE_MFIARE 0x02 /
< \brief TypeA(包括Mifare卡)类命令 */
#define __CMD_TYPE_ISO7816 0x05 /< \brief ISO7816类命令 */
#define __CMD_TYPE_PICC 0x06 /
< \brief ISO14443(PICC)卡类命令 */
#define __CMD_TYPE_PLUS_CPU 0x07 /**< \brief PLUS CPU卡(不包括Mifare卡)类命令 */
#define __ACK_LENGTH_DEV_INFO 0x1A /返回设备信息时的数据总长度/
#define __ACK_LENGTH_AUTO_DETECT 0x1F /返回设备信息时的数据总长度/

static struct i2c_client *zlg600_client;
static int request_id = 0;
wait_queue_head_t read_data_wq; //定义一个等待工作队列
static volatile int irq_come_in = 0;
static volatile int g_cmd_seq = 0x00;

static int nfc_zlg_open(struct inode *inode, struct file *file)
{
//open的时候要进行初始化,初始化模块进入自动工作模式
printk(“Open Device: Initial Auto Work Mode\n”);
return 1;
}

static ssize_t nfc_zlg_read(struct file *filp, char __user *buf,
size_t count, loff_t *offset)
{

int ret;
if (filp->f_flags & O_NONBLOCK) {
		ret = -EAGAIN;
		goto FAIL;
	}
	
ret = wait_event_interruptible(read_data_wq, (irq_come_in==1));	

FAIL:
return ret;

}

static const struct file_operations nfc_zlg_fops = {
.owner = THIS_MODULE,
.open = nfc_zlg_open,
.read = nfc_zlg_read,
};

static struct miscdevice nfc_zlg_miscdev = {
.minor = MISC_DYNAMIC_MINOR,
.name = “zlg600a”,
.fops = &nfc_zlg_fops,
};

uint8_t g_send_buf[100]; /< \brief 发送缓冲区 */
uint8_t g_recv_buf[100]; /
< \brief 接收缓冲区 */

static uint8_t nfc_drive_bcc_cacl (const uint8_t *p_buf)
{
int i;
uint8_t bcc = 0x00;

for (i = 0; i < (p_buf[0] - 2); i++) {
    bcc ^= p_buf[i];
}
return (~bcc);

}

static int nfc_set_cmd(uint8_t cmd_type,
uint8_t cmd,
uint8_t *p_info,
uint8_t info_nbytes)
{
int bcc;
int bcc_site;
int ret,i=0;

memset(g_send_buf, 0, sizeof(g_send_buf));
memset(g_recv_buf, 0, sizeof(g_recv_buf));

g_send_buf[__FRAME_CMD_TYPE] = cmd_type | g_cmd_seq;
g_cmd_seq += 0x10;
g_send_buf[__FRAME_CMD]      = cmd;
g_send_buf[__FRAME_DATA_LEN] = info_nbytes;
g_send_buf[__FRAME_LEN]      = 0x06 + info_nbytes;

memcpy(&g_send_buf[__FRAME_DATA], p_info, info_nbytes);

bcc_site = __FRAME_DATA + info_nbytes;
bcc      = nfc_drive_bcc_cacl(g_send_buf);

g_send_buf[bcc_site]     = bcc; 
g_send_buf[bcc_site + 1] = 0x03;
printk("\n");
for(i=0; i< g_send_buf[__FRAME_LEN]; i++)
{
	printk("%02X",g_send_buf[i]);
}
printk("\n");
msleep(500);
ret = i2c_master_send(zlg600_client, g_send_buf, g_send_buf[__FRAME_LEN]);
msleep(500);
ret = i2c_master_recv(zlg600_client, g_recv_buf, sizeof(g_recv_buf));
printk("Recv Data Size:%02X\n", g_recv_buf[0]);

return ret;

}

static int nfc_zlg_get_dev_info (uint8_t cmd_type,
uint8_t cmd,
uint8_t *p_info,
uint8_t info_nbytes)
{
int bcc;
int bcc_site;
int ret,i=0;

memset(g_send_buf, 0, sizeof(g_send_buf));
memset(g_recv_buf, 0, sizeof(g_recv_buf));

g_send_buf[__FRAME_CMD_TYPE] = cmd_type | g_cmd_seq;
g_cmd_seq += 0x10;
g_send_buf[__FRAME_CMD]      = cmd;
g_send_buf[__FRAME_DATA_LEN] = info_nbytes;
g_send_buf[__FRAME_LEN]      = 0x06 + info_nbytes;

memcpy(&g_send_buf[__FRAME_DATA], p_info, info_nbytes);

bcc_site = __FRAME_DATA + info_nbytes;
bcc      = nfc_drive_bcc_cacl(g_send_buf);

g_send_buf[bcc_site]     = bcc; 
g_send_buf[bcc_site + 1] = 0x03;
	
msleep(500);
for( i=0; i < 3; i++)
{
	ret = i2c_master_send(zlg600_client, g_send_buf, g_send_buf[__FRAME_LEN]);
	//printk("Send Data By Smbus size=%d;\n", ret);
	msleep(500);
	ret = i2c_master_recv(zlg600_client , g_recv_buf , __ACK_LENGTH_DEV_INFO);
	if(g_recv_buf[__FRAME_LEN] == __ACK_LENGTH_DEV_INFO)
	{
		break;
	}
}
//__FRAME_DATA
//取出设备信息  数据的4 -- 14

uint8_t *info =  kzalloc(g_recv_buf[__FRAME_DATA_LEN], GFP_KERNEL);;
for(i=4; i < 19; i++)
{
	memcpy(info, &g_recv_buf[__FRAME_DATA], g_recv_buf[__FRAME_DATA_LEN]);
}
printk("Detect Nfc zlg600a: %s\n", info);

return ret;

}

//外部中断的处理函数
static irqreturn_t nfc_zlg600a_interrupt(int irq, void *dev_id)
{
printk(“zlg600a interrupt now, card data report\n”);
irq_come_in = 1;
//当发生中断时,唤醒工作队列,读取数据
wake_up(&read_data_wq);

return IRQ_HANDLED;

}

static int nfc_zlg_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int error;

zlg600_client = client;
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_I2C_BLOCK)) {
	dev_err(&adapter->dev, "doesn't support required functionality\n");
	error = -EIO;
}
msleep(500);

//动态初始化等待工作队列
init_waitqueue_head(&read_data_wq);

//申请中断
request_id = client->irq;
printk("Client Address:%02X,%d\n", zlg600_client->addr, request_id);
error = request_irq(request_id, nfc_zlg600a_interrupt, IRQF_TRIGGER_FALLING, "zlg600a_int", NULL);
if (error < 0) {
    dev_err(&client->dev, "ZLG NFC Module: request irq failed %s:%d \n ",__FILE__,__LINE__);
	goto exit_irq_request_failed;
}
//获取设备信息
nfc_zlg_get_dev_info(__CMD_TYPE_DEV_CTRL, 'A', NULL, 0);
	
// 设置Mifare 自动检测
// uint8_t check_buf[1];
// check_buf[0] = 0x01;
// nfc_zlg_set_auto_detect(__CMD_TYPE_MFIARE, 'O', check_buf, sizeof(check_buf));


//设置天线范围内的所有A类卡请求
uint8_t check_buf[1];
check_buf[0] = 0x52;	 
int i = 0;
for( i=0; i < 4; i++)
{
	nfc_set_cmd(__CMD_TYPE_MFIARE, 'A', check_buf, sizeof(check_buf));
}


int ret = misc_register(&nfc_zlg_miscdev);
if (ret < 0)
{
	printk("ZLG600A Misc Register Failed:%d\n",ret);
	return ret;
}

exit_irq_request_failed:

return 0;

}

static int nfc_zlg_remove(struct i2c_client *client)
{
free_irq(request_id, NULL);
misc_deregister(&nfc_zlg_miscdev);
return 0;
}

static int nfc_zlg_detect(struct i2c_client *client,
struct i2c_board_info *info)
{
return 0;
}

static const struct i2c_device_id nfc_zlg_id[] = {
{ “zlg600a”, 0 },
{}
};

MODULE_DEVICE_TABLE(i2c, nfc_zlg_id);

#ifdef CONFIG_OF
static const struct of_device_id nfc_zlg_ids[] = {
{ .compatible = “nfc,zlg600a”, },
{ /* sentinel / }
};
MODULE_DEVICE_TABLE(of, nfc_zlg_ids);
#endif
/
1. 分配/设置i2c_driver */
static struct i2c_driver nfc_zlg_driver = {
.driver = {
.owner = THIS_MODULE,
.name = “zlg600a”,
.of_match_table = of_match_ptr(nfc_zlg_ids),
},
.probe = nfc_zlg_probe,
.id_table = nfc_zlg_id,
.remove = nfc_zlg_remove,
.detect = nfc_zlg_detect,
};

static int nfc_zlg_module_init(void)
{
i2c_add_driver(&nfc_zlg_driver);
return 0;
}

static void nfc_zlg_module_exit(void)
{
i2c_del_driver(&nfc_zlg_driver);
}

module_init(nfc_zlg_module_init);
module_exit(nfc_zlg_module_exit);
MODULE_LICENSE(“GPL”);

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于Python ZLG驱动的使用,你可以按照以下步骤进行操作: 1. 首先,你需要下载ZLG驱动的Python库文件、接口文档和上位机例程。确保将这些文件与你的主程序(main.py)放在同一个目录下。同时,你还需要将zlgcan.py中调用dll文件的路径修改为当前路径。 2. 接下来,你可以使用import语句导入zlgcan.py中的函数,以便在你的主程序中使用这些函数。如果你觉得zlgcan.py中的原始函数使用起来不够方便,你可以考虑编写一个zlg_driver.py文件,对zlgcan.py进行二次封装,以提高代码的可读性。 3. 在使用ZLG驱动之前,确保你已经安装了ZLG USBCAN-I驱动和Microsoft Visual C++运行库。这些驱动和运行库的安装可以参考ZLG官方网站提供的资料。 4. 最后,根据你的需求,使用ZLG驱动提供的函数来读取和处理周立功USBCAN-I设备的信息。 希望以上信息对你有所帮助!\[1\]\[2\]\[3\] #### 引用[.reference_title] - *1* *3* [python-GUI:利用pyqt5设计一个bootloader上位机页面(ZLG驱动)及打包报错faild to execute script pyi_rth_...](https://blog.csdn.net/qq_42274565/article/details/122300995)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [64位Python读取周立功USBCAN-I信息](https://blog.csdn.net/qq_41690864/article/details/118164093)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值