43.封装驱动提供的api函数

应用工程师是不希望看到驱动的相关定义,比如#define TIMER_OPEN _IO('L',0),因此需要封装,提供相关的api函数。

timerlib.h

cpp 复制代码
#ifndef _TIMELIB_H_
#define _TIMELIB_H_
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
 
#define TIMER_OPEN _IO('L',0)
#define TIMER_CLOSE _IO('L',1)
#define TIMER_SET _IOW('L',2,int)
int dev_open();
int timer_open(int fd);
int timer_close(int fd);
int timer_set(int fd,int arg);
 
#endif

timeropen.c

cpp 复制代码
#include "timerlib.h"
int timer_open(int fd)
{
    int ret;
    ret = ioctl(fd,TIMER_OPEN);
    if(ret < 0){
        printf("ioctl open error \n");
        return -1;
    }
    return ret;
}

timerclose.c

cpp 复制代码
#include "timerlib.h"
int timer_close(int fd)
{
    int ret;
    ret = ioctl(fd,TIMER_CLOSE);
    if(ret < 0){
        printf("ioctl  close error \n");
        return -1;
    }
    return ret;
}

timerset.c

cpp 复制代码
#include "timerlib.h"
int timer_set(int fd,int arg)
{
    int ret;
    ret = ioctl(fd,TIMER_SET,arg);
    if(ret < 0){
        printf("ioctl error \n");
        return -1;
    }
    return ret;
}

dev_open.c

cpp 复制代码
#include "timerlib.h"
int dev_open()
{
    int fd;
    fd = open("/dev/test",O_RDWR,0777);
    if(fd < 0){
        printf("file open error \n");
    }
    return fd;
}

app.c

cpp 复制代码
#include "timerlib.h"
int main(int argc,char *argv[]){
    int fd;
    fd = dev_open();
    timer_set(fd,1000);
    timer_open(fd);
    sleep(3);
    timer_set(fd,3000);
    sleep(7);
    timer_close(fd);
    close(fd);
}

驱动ioctl_timer.c

cpp 复制代码
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/kdev_t.h>
#include <linux/uaccess.h>
#include <linux/timer.h>
#define TIMER_OPEN _IO('L',0)
#define TIMER_CLOSE _IO('L',1)
#define TIMER_SET _IOW('L',2,int)
 
struct device_test{
 
    dev_t dev_num;  //设备号
    int major ;  //主设备号
    int minor ;  //次设备号
    struct cdev cdev_test; // cdev
    struct class *class;   //类
    struct device *device; //设备
    int counter; 
};
static struct device_test dev1;
static void fnction_test(struct timer_list *t);//定义function_test定时功能函数
DEFINE_TIMER(timer_test,fnction_test);//定义一个定时器
void fnction_test(struct timer_list *t)
{
    printk("this is fnction_test\n");
    mod_timer(&timer_test,jiffies_64 + msecs_to_jiffies(dev1.counter));//使用mod_timer函数重新设置定时时间
}
static int cdev_test_open(struct inode *inode, struct file *file)
{
    file->private_data=&dev1;//设置私有数据
    return 0;
}
 
static int cdev_test_release(struct inode *inode, struct file *file)
{
    file->private_data=&dev1;//设置私有数据
 
    return 0;
}
 
static long cdev_test_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
    struct device_test *test_dev = (struct device_test *)file->private_data;//设置私有数据
    switch(cmd){
        case TIMER_OPEN:
            add_timer(&timer_test);//添加一个定时器
            break;
        case TIMER_CLOSE:
            del_timer(&timer_test);//删除一个定时器
            break;
        case TIMER_SET:
            test_dev->counter = arg;
            timer_test.expires = jiffies_64 + msecs_to_jiffies(test_dev->counter);//设置定时时间
            break;
 
    default:
            break;
    }
    return 0;
}
/*设备操作函数*/
struct file_operations cdev_test_fops = {
    .owner = THIS_MODULE, //将owner字段指向本模块,可以避免在模块的操作正在被使用时卸载该模块
    .open = cdev_test_open,
    .release = cdev_test_release,
    .unlocked_ioctl = cdev_test_ioctl,
};
static int __init timer_dev_init(void) //驱动入口函数
{
    /*注册字符设备驱动*/
    int ret;
    /*1 创建设备号*/
    ret = alloc_chrdev_region(&dev1.dev_num, 0, 1, "alloc_name"); //动态分配设备号
    if (ret < 0)
    {
       goto err_chrdev;
    }
    printk("alloc_chrdev_region is ok\n");
 
    dev1.major = MAJOR(dev1.dev_num); //获取主设备号
    dev1.minor = MINOR(dev1.dev_num); //获取次设备号
 
    printk("major is %d \r\n", dev1.major); //打印主设备号
    printk("minor is %d \r\n", dev1.minor); //打印次设备号
     /*2 初始化cdev*/
    dev1.cdev_test.owner = THIS_MODULE;
    cdev_init(&dev1.cdev_test, &cdev_test_fops);
 
    /*3 添加一个cdev,完成字符设备注册到内核*/
   ret =  cdev_add(&dev1.cdev_test, dev1.dev_num, 1);
    if(ret<0)
    {
        goto  err_chr_add;
    }
    /*4 创建类*/
 dev1. class = class_create(THIS_MODULE, "test");
if(IS_ERR(dev1.class))
{
        ret=PTR_ERR(dev1.class);
        goto err_class_create;
    }
    /*5  创建设备*/
    dev1.device = device_create(dev1.class, NULL, dev1.dev_num, NULL, "test");
    if(IS_ERR(dev1.device))
    {
        ret=PTR_ERR(dev1.device);
        goto err_device_create;
    }
 
return 0;
 
err_device_create:
        class_destroy(dev1.class);                 //删除类
 
err_class_create:
       cdev_del(&dev1.cdev_test);                 //删除cdev
 
err_chr_add:
        unregister_chrdev_region(dev1.dev_num, 1); //注销设备号
 
err_chrdev:
        return ret;
}
 
static void __exit timer_dev_exit(void) //驱动出口函数
{
    /*注销字符设备*/
    unregister_chrdev_region(dev1.dev_num, 1); //注销设备号
    cdev_del(&dev1.cdev_test);                 //删除cdev
    device_destroy(dev1.class, dev1.dev_num);       //删除设备
    class_destroy(dev1.class);                 //删除类
}
module_init(timer_dev_init);
module_exit(timer_dev_exit);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("quan");

Makefile

bash 复制代码
obj-m += ioctl_timer.o
KDIR:=/lib/modules/6.2.0-37-generic/build
PWD?=$(shell pwd)
all:
	make -C $(KDIR) M=$(PWD) modules
	echo $(PWD)
clean:
	rm -rf *.ko *.o *.mod *.mod.o *.mod.c *.symvers *.order

install:
	cp *.out *.ko ../../linux-kernel/linux-6.17.5/kmodules

编译及测试

bash 复制代码
gcc -c timer*  dev_open.c
ar rcs libtimer.a timer*.o dev_open.o
gcc app.c -L./ -ltimer
./a.out
dmesg

[114388.012997] this is fnction_test
[114389.037266] this is fnction_test
[114392.141121] this is fnction_test
[114395.213678] this is fnction_test
相关推荐
赖small强5 小时前
【Linux 驱动开发】Linux设备驱动框架与驱动模型深度解析
linux·驱动开发·kobject·设备驱动模型·总线-设备-驱动架构·probe
python百炼成钢16 小时前
55.Linux ADC框架(IIO续)
linux·运维·服务器·驱动开发
猫猫的小茶馆20 小时前
【PCB工艺】数模电及射频电路基础
驱动开发·stm32·单片机·嵌入式硬件·mcu·物联网·pcb工艺
dian2008-ic1 天前
Linux pcie【9】基于GIC-V3 ITS实现pcie msi中断
linux·arm开发·驱动开发·嵌入式硬件
技术摆渡人1 天前
Android 14系统深度分析
android·linux·驱动开发
DeeplyMind1 天前
TTM ttm_tt技术分析系列1:导读
linux·驱动开发·gpu·amd·gart
被遗忘的旋律.1 天前
Linux驱动开发笔记(二十二)——多点电容触摸屏
linux·驱动开发·笔记
PPS柴油1 天前
RK3568开发板gpio模拟LED呼吸灯
linux·驱动开发·嵌入式硬件
偶像你挑的噻2 天前
16-Linux驱动开发-多核通信中的并发控制
linux·驱动开发·stm32·嵌入式硬件