Chinaunix首页 | 论坛 | 博客
  • 博客访问: 310191
  • 博文数量: 78
  • 博客积分: 3635
  • 博客等级: 中校
  • 技术积分: 1115
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-28 09:35
文章分类

全部博文(78)

文章存档

2011年(13)

2010年(65)

我的朋友

分类: LINUX

2010-10-29 19:30:47

Linux Platform Device and Driver

http://blog.chinaunix.net/u2/60011/showart.php?id=1018502

http://blog.csdn.net/lanmanck/archive/2009/08/17/4455692.aspx

写的很精彩,尚观还是有两下子呵呵

原文地址:

(尚观-linux开发小组成员)
1.你的驱动只能挂一个设备.
2.无法用udev生成,因为没有class.(register_chrdev已经过时了).
3.如果你想单独写一驱动包括子系统层.
#include "hello.h"

#define HELLO_MAX_DEVS 6

static dev_t hello_base_id;
static int cur_dev_num = 0;
static struct class* hello_class;

typedef struct hello_dev {
struct cdev chrdev;
int dev_idx;
u8* dma_buf;
size_t cur_size;
}hello_dev_t;

static hello_dev_t* hi_dev[HELLO_MAX_DEVS];

static int __devinit hello_probe(struct platform_device *pdev);
static int __devexit hello_remove(struct platform_device *pdev);

static int hello_open(struct inode *inode, struct file *filp);
static int hello_close(struct inode *inode, struct file *filp);
static ssize_t hello_read(struct file *filp, char *buff, size_t count, loff_t *offp);
static ssize_t hello_write(struct file *filp, const char *buff, size_t count, loff_t *offp);


static int hello_open(struct inode *inode, struct file *filp)
{
hello_dev_t* hdev;
int idx;

idx = iminor(inode) - MINOR(hello_base_id);
hdev = hi_dev[idx];

sprintf(hdev->dma_buf, "hello%d from kernel!", idx);
hdev->cur_size = strlen(hdev->dma_buf);

filp->private_data = hdev;

return 0;
}

static int hello_close(struct inode *inode, struct file *filp)
{
hello_dev_t* hdev;
int idx;

idx = iminor(inode) - MINOR(hello_base_id);
hdev = hi_dev[idx];

filp->private_data = NULL;

printk("bye %d\n", hdev->dev_idx);

return 0;
}

static ssize_t hello_read(struct file *filp, char *buff, size_t count, loff_t *offp)
{
int ret;
size_t len;
hello_dev_t *hdev = filp->private_data;

len = (count > hdev->cur_size) ? hdev->cur_size : count;

ret = copy_to_user(buff, hdev->dma_buf, len);

return len;
}

static ssize_t hello_write(struct file *filp, const char *buff, size_t count, loff_t *offp)
{
int ret;
size_t len;
hello_dev_t *hdev = filp->private_data;

len = (count < MEM_LEN) ? count : MEM_LEN;

ret = copy_from_user(hdev->dma_buf, buff, len);

hdev->cur_size = len;

return len;
}


static struct platform_driver hello_driver = {
.probe = hello_probe,
.remove = hello_remove,
.driver = {
.name = HELLO_DEV_NAME,
.owner = THIS_MODULE,
},
};


static struct file_operations hello_fops = {
.owner = THIS_MODULE,
.open = hello_open,
.release = hello_close,
.read = hello_read,
.write = hello_write,

};

static int __devinit hello_probe(struct platform_device *pdev)
{
int ret;
dev_t dev_id;
struct class_device* cls_dev;
hello_dev_t *hdev;

printk("device %s-%d detected!\n", pdev->name, pdev->id);

hi_dev[cur_dev_num] = hdev = kzalloc(sizeof(hello_dev_t), GFP_KERNEL);

hdev->dma_buf = kmalloc(MEM_LEN, GFP_KERNEL);
hdev->dev_idx = cur_dev_num++;

dev_id = MKDEV(MAJOR(hello_base_id), MINOR(hello_base_id) + hdev->dev_idx);
pdev->dev.devt = dev_id;

cdev_init(&hdev->chrdev, &hello_fops);
hdev->chrdev.owner = THIS_MODULE;

ret = cdev_add(&hdev->chrdev, dev_id, 1);
if (ret)
{
printk("fail to register driver for " HELLO_DEV_NAME "%d!\n", pdev->id);
return ret;
}

platform_set_drvdata(pdev, hdev);


cls_dev = class_device_create(hello_class,
NULL,
dev_id,
&pdev->dev,
HELLO_DEV_NAME "%d", hdev->dev_idx
);
if (IS_ERR(cls_dev))
return PTR_ERR(cls_dev);


printk("driver for "HELLO_DEV_NAME".%d (%d,%d) registered\n", hdev->dev_idx, MAJOR(dev_id), MINOR(dev_id));

return ret;

}


static int __devexit hello_remove(struct platform_device *pdev)
{
hello_dev_t* hdev;

class_device_destroy(hello_class, pdev->dev.devt);

hdev = platform_get_drvdata(pdev);

if (hdev) cdev_del(&hdev->chrdev);

kfree(hdev->dma_buf);
kfree(hdev);

platform_set_drvdata(pdev, NULL);
pdev->dev.devt = 0;

cur_dev_num--;

printk(HELLO_DEV_NAME "%d removed!\n", pdev->id);

return 0;
}


static int __init hello_init(void)
{
int ret;

cur_dev_num = 0;

ret = alloc_chrdev_region(&hello_base_id,
10,
HELLO_MAX_DEVS,
HELLO_DEV_NAME
);

if (ret)
return ret;

hello_class = class_create(THIS_MODULE, HELLO_DEV_NAME);
if (IS_ERR(hello_class))
return PTR_ERR(hello_class);

ret = platform_driver_register(&hello_driver);

return ret;
}

static void __exit hello_exit(void)
{
platform_driver_unregister(&hello_driver);

class_destroy(hello_class);

unregister_chrdev_region(hello_base_id, HELLO_MAX_DEVS);

printk("unregister driver " HELLO_DEV_NAME "\n");
}


module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("GPL");

阅读(2164) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~