mulit chrdev driver

本文详细介绍了一个基于Linux内核的字符设备驱动开发实例。通过创建两个字符设备,使用cdev结构体进行设备注册,并实现了设备的open、release、read等操作。此实例展示了如何在Linux环境下开发和注册字符设备,以及如何实现基本的文件操作。
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <asm/uaccess.h>

#define NAME "demo"
dev_t from;
int baseminor = 0 , count = 2;

struct mutil_dev{
    struct cdev dev;
    char string[64];
}dev1,dev2;   

int demo_open(struct inode *inode, struct file *file)
{
    //inode->cdev 
    //cdev -----> struct mutil_dev?--->
    //container_of
    struct mutil_dev *my_dev = container_of(inode->i_cdev,struct mutil_dev,dev);
    file->private_data = my_dev;
    
    printk("%s,%d\n",__func__,__LINE__);
    return 0;
}
int demo_release(struct inode *inode, struct file *file)
{
    printk("%s,%d\n",__func__,__LINE__);
    return 0;
}
ssize_t demo_read(struct file *file, char __user *user, size_t size, loff_t *loff)
{
    struct  mutil_dev *read_dev = file->private_data;

    if(copy_to_user(user,read_dev->string,sizeof(read_dev->string))){
        printk("%s,%d\n",__func__,__LINE__);
        return -EINVAL;
    }
    printk("%s,%d\n",__func__,__LINE__);
    return size;
}

ssize_t demo_write(struct file *file, const char __user *user, size_t size, loff_t *loff)
{
    printk("%s,%d\n",__func__,__LINE__);
    return size;
}

struct file_operations f_ops = {
    .owner = THIS_MODULE,//struct module
    .open = demo_open,
    .release = demo_release,
    .read = demo_read,
};

void mutil_dev_config(struct mutil_dev *dev ,dev_t from , int count)
{
    cdev_init(&dev->dev,&f_ops);
    cdev_add(&dev->dev,from,count);
}

static int __init demo_init(void)
{
    int ret;
    int major = 0,minor = 0;
    ret = alloc_chrdev_region(&from,baseminor,count,NAME);
    if(ret){
        printk("%s,%dalloc_chrdev_region\n",__func__,__LINE__);
        return -EINVAL;
    }
    
    major = MAJOR(from);
    minor = MINOR(from);
    
    strcpy(dev1.string , "from dev1");
    strcpy(dev2.string , "from dev2");
    
    mutil_dev_config(&dev1,MKDEV(major ,minor),1);//250 0
    mutil_dev_config(&dev2,MKDEV(major ,minor+1),1);//250 1
    printk("%s,%d\n",__func__,__LINE__);
    return 0;
}
static void  __exit demo_exit(void)
{
    cdev_del(&dev1.dev);
    cdev_del(&dev2.dev);
    unregister_chrdev_region(from,count);
    printk("%s,%d\n",__func__,__LINE__);
}

module_init(demo_init);
module_exit(demo_exit);
MODULE_LICENSE("GPL");

 

int mt_accdet_probe(struct platform_device dev) 1632 { 1633 int ret = 0; 1634 1635 #if DEBUG_THREAD 1636 struct platform_driver accdet_driver_hal = accdet_driver_func(); 1637 #endif 1638 1639 #if defined(CONFIG_TS3A225E_ACCDET) 1640 if (ts3a225e_i2c_client == NULL) { 1641 ACCDET_DEBUG(“[Accdet]ts3a225e_i2c_client is NULL!\n”); 1642 return -EPROBE_DEFER; 1643 } 1644 #endif 1645 1646 ACCDET_INFO(“[Accdet]accdet_probe begin!\n”); 1647 1648 /-------------------------------------------------------------------- 1649 // below register accdet as switch class 1650 //------------------------------------------------------------------/ 1651 #if JUST_INPUT_NO_SWITCH 1652 accdet_data.name = “h2w”; 1653 accdet_data.index = 0; 1654 accdet_data.state = NO_DEVICE; 1655 ret = switch_dev_register(&accdet_data); 1656 if (ret) { 1657 ACCDET_ERROR(“[Accdet]switch_dev_register returned:%d!\n”, ret); 1658 return 1; 1659 } 1660 #endif 1661 /---------------------------------------------------------------------- 1662 // Create normal device for auido use 1663 //--------------------------------------------------------------------/ 1664 ret = alloc_chrdev_region(&accdet_devno, 0, 1, ACCDET_DEVNAME); 1665 if (ret) 1666 ACCDET_ERROR(“[Accdet]alloc_chrdev_region: Get Major number error!\n”); 1667 1668 accdet_cdev = cdev_alloc(); 1669 accdet_cdev->owner = THIS_MODULE; 1670 accdet_cdev->ops = accdet_get_fops(); 1671 ret = cdev_add(accdet_cdev, accdet_devno, 1); 1672 if (ret) 1673 ACCDET_ERROR(“[Accdet]accdet error: cdev_add\n”); 1674 1675 accdet_class = class_create(THIS_MODULE, ACCDET_DEVNAME); 1676 1677 / if we want auto creat device node, we must call this*/ 1678 accdet_nor_device = device_create(accdet_class, NULL, accdet_devno, NULL, ACCDET_DEVNAME); 1679 1680 /-------------------------------------------------------------------- 1681 // Create input device 1682 //------------------------------------------------------------------/ 1683 kpd_accdet_dev = input_allocate_device(); 1684 if (!kpd_accdet_dev) { 1685 ACCDET_ERROR(“[Accdet]kpd_accdet_dev : fail!\n”); 1686 return -ENOMEM; 1687 } 1688 /INIT the timer to disable micbias./ 1689 timer_setup(&micbias_timer, disable_micbias, 0); 1690 micbias_timer.expires = jiffies + MICBIAS_DISABLE_TIMER; 1691 1692 /define multi-key keycode/ 1693 __set_bit(EV_KEY, kpd_accdet_dev->evbit); 1694 __set_bit(KEY_PLAYPAUSE, kpd_accdet_dev->keybit); 1695 __set_bit(KEY_VOLUMEDOWN, kpd_accdet_dev->keybit); 1696 __set_bit(KEY_VOLUMEUP, kpd_accdet_dev->keybit); 1697 __set_bit(KEY_VOICECOMMAND, kpd_accdet_dev->keybit); 1698 1699 __set_bit(EV_SW, kpd_accdet_dev->evbit); 1700 __set_bit(SW_HEADPHONE_INSERT, kpd_accdet_dev->swbit); 1701 __set_bit(SW_MICROPHONE_INSERT, kpd_accdet_dev->swbit); 1702 __set_bit(SW_JACK_PHYSICAL_INSERT, kpd_accdet_dev->swbit); 1703 __set_bit(SW_LINEOUT_INSERT, kpd_accdet_dev->swbit); 1704 1705 kpd_accdet_dev->id.bustype = BUS_HOST; 1706 kpd_accdet_dev->name = “ACCDET”; 1707 if (input_register_device(kpd_accdet_dev)) 1708 ACCDET_ERROR(“[Accdet]kpd_accdet_dev register : fail!\n”); 1709 /------------------------------------------------------------------ 1710 // Create workqueue 1711 //------------------------------------------------------------------ / 1712 accdet_workqueue = create_singlethread_workqueue(“accdet”); 1713 INIT_WORK(&accdet_work, accdet_work_callback); 1714 1715 /------------------------------------------------------------------ 1716 // wake lock 1717 //------------------------------------------------------------------/ 1718 accdet_suspend_lock = wakeup_source_register(NULL, “accdet_suspend_lock”); 1719 accdet_irq_lock = wakeup_source_register(NULL, “accdet_irq_lock”); 1720 accdet_key_lock = wakeup_source_register(NULL, “accdet_key_lock”); 1721 accdet_timer_lock = wakeup_source_register(NULL, “accdet_timer_lock”); 1722 #if DEBUG_THREAD 1723 ret = accdet_create_attr(&accdet_driver_hal.driver); 1724 if (ret != 0) 1725 ACCDET_ERROR(“create attribute err = %d\n”, ret); 1726 #endif 1727 pmic_register_interrupt_callback(12, accdet_int_handler); 1728 pmic_register_interrupt_callback(13, accdet_eint_int_handler); 1729 ACCDET_INFO(“[Accdet]accdet_probe : ACCDET_INIT\n”); 1730 if (g_accdet_first == 1) { 1731 eint_accdet_sync_flag = 1; 1732 #ifdef CONFIG_ACCDET_EINT_IRQ 1733 accdet_eint_workqueue = create_singlethread_workqueue(“accdet_eint”); 1734 INIT_WORK(&accdet_eint_work, accdet_eint_work_callback); 1735 accdet_disable_workqueue = create_singlethread_workqueue(“accdet_disable”); 1736 INIT_WORK(&accdet_disable_work, disable_micbias_callback); 1737 #endif 1738 /Accdet Hardware Init/ 1739 accdet_get_dts_data(); 1740 accdet_init(); 1741 accdet_pmic_Read_Efuse_HPOffset(); 1742 /schedule a work for the first detection/ 1743 queue_work(accdet_workqueue, &accdet_work); 1744 #ifdef CONFIG_ACCDET_EINT 1745 accdet_disable_workqueue = create_singlethread_workqueue(“accdet_disable”); 1746 INIT_WORK(&accdet_disable_work, disable_micbias_callback); 1747 accdet_eint_workqueue = create_singlethread_workqueue(“accdet_eint”); 1748 INIT_WORK(&accdet_eint_work, accdet_eint_work_callback); 1749 accdet_setup_eint(dev); 1750 #endif 1751 g_accdet_first = 0; 1752 } 1753 ACCDET_INFO(“[Accdet]accdet_probe done!\n”); 1754 return 0; 1755 }
最新发布
07-15
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值