linux的类总线设备驱动,linux设备驱动模型之平台总线实践环节(四)

//通过led_classdev类型的指针得到s5pv210_led_pladata类型的指针,这个s5pv210_led_pladata类型结构体是我们自己定义的设备数据部分。

static inline struct s5pv210_gpio_led *to_gpio(struct led_classdev *led_cdev)

{

return container_of(led_cdev, struct s5pv210_gpio_led, cdev);

}

#define X210_LED_OFF 1

#define X210_LED_ON 0

//从platform_device的指针得到s5pv210_gpio_led的指针

static inline struct s5pv210_gpio_led *pdev_to_gpio(struct platform_device *dev)

{

return platform_get_drvdata(dev);

}

//定义一个大的结构体框架,包含led_classdev和设备的数据部分的结构体

struct s5pv210_gpio_led {

struct led_classdev cdev;

struct s5pv210_led_platdata*pdata;

};

//为了让这个操作led的驱动方法具有一般性,所以函数可以通过参数struct led_classdev类型的指针反推得到s5pv210_gpio_led的指针

//从而通过这个指针知道s5pv210_led_platdata这个成员,这个类型的成员是我们自己定义的设备的数据部分。

static void whyx210_led_set(struct led_classdev *led_cdev, enum led_brightness value)

{

printk(KERN_INFO "whyx210_led_set\n");

struct s5pv210_gpio_led *p = to_gpio(led_cdev);    //从led_classdev指针反推得到s5pv210_gpio_led的指针

if (value == LED_OFF) { //用户输入0时灭       对应用户输入的是echo 0 > brightness

//writel(readl(GPJ0DAT) | (1 <

gpio_set_value(p->pdata->gpio, X210_LED_OFF);    //通过s5pv210_gpio_led中的pdata来知道gpio号是多少,pdata是设备数据部分,我们写

//platform_device时已经填充好

}else if (value == LED_FULL){   //用户输入255时亮     对应用户输入的是echo 255 > brightness

//writel(readl(GPJ0DAT) & ~(1 <

gpio_set_value(p->pdata->gpio, X210_LED_ON);

}

}

static int why_led_probe(struct platform_device *dev)

{

int ret = -1;

struct s5pv210_led_platdata *pdata = dev->platform_data;    //得到匹配上的设备的数据部分

struct s5pv210_gpio_led *led; //上一章博客中说道brightness绑定的函数不能写死,所以使用这种设计逻辑,这个结构体中包含了led_classdev结构体

//同时也包含了我们定义的设备的数据部分的结构体

led = kzalloc(sizeof(struct s3c24xx_gpio_led), GFP_KERNEL);

if (led == NULL) {

dev_err(&dev->dev, "No memory for device\n");

return -ENOMEM;

}

platform_set_drvdata(dev, led);//这个函数的功能是将led这个含有led_classdev和设备数据部分的结构体变量的指针让其driver中的数据部分的指针指

//向,就是将led结构体被driver中能指向任意类型的指针指向,将led这个代表设备数据部分的东西传递给驱动。

//填充我们要注册的struct led_classdev类型的结构体

//myled.name = pdata->name; //当前匹配上的led设备的名字

//myled.brightness = 255;

//myled.brightness_set = whyx210_led1_set;//这个myled的brightness_set方法绑定的其实就不能是固定的whyx210_led1_set这个方法了,因为我们

//的驱动和设备的匹配不是固定是led1的,有可能led2的设备也和这个驱动匹配上了,总不能led2的

//操作方法使用的还是led1的方法吧

//因为led中包含了led_classdev,所以上面的代码改变如下,用这样的方法将设备的数据填充到led中,同时因为led已经在上面被drvier成员中的指针

//指向,所以等于为driver填充数据。

led->cdev.name = pdata->name;    //led中的成员cdev就是上面的myled

led->cdev.brightness = 255;

led->cdev.brightness_set = whyx210_led_set;    //这个set函数就不能写死了,要根据实际设备硬件数据的变化来去进行操作led灯的亮灭。所以

//从新写这个函数,名字改为why210_led_set,用一个框架更大的思路去操作led,通过实时获取设

//备硬件数据的方法,来操作led,这样这个操作led的驱动方法就具有一般性,以后只需要改动设

//备的数据,就可以达到控制不同的led。

//去调用led驱动框架中为我们提供的led注册函数led_classdev_register去注册驱动

//在led-class.c中int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)

ret = led_classdev_register(&dev->dev, &led->cdev);

led->pdata = pdata;    //将从设备中得到数据部分,填充到这个led结构体中的pdata成员,led因为前面已经被driver成员中的指针指向,所以等于将

//数据传递到驱动中

if (ret 

printk(KERN_ERR "led_classdev_register errro\n");

return ret;

}

return 0;

}

static int why_led_remove(struct platform_device *dev)

{

struct s5pv210_gpio_led *led = pdev_to_gpio(dev);    //从platform_device类型的指针反推得到s5pv210_gpio_led的指针

led_classdev_unregister(&led->cdev);    //注销这个设备

kfree(led);

return 0;

}

static struct platform_driver why_led_driver = {

.probe      = why_led_probe,

.remove     = why_led_remove,

.driver     = {

.name       = "why_led",

.owner      = THIS_MODULE,

},

};

static int __init whyx210_led_init(void)

{

return platform_driver_register(&why_led_driver);

}

static void __init whyx210_led_exit(void)

{

platform_driver_unregister(&why_led_driver);

}

module_init(whyx210_led_init);

module_exit(whyx210_led_exit);

MODULE_AUTHOR("why <417842990@qq.com>");

MODULE_DESCRIPTION("whyx210 LED driver");

MODULE_LICENSE("GPL");

MODULE_ALIAS("whyx210_led"

将具有一般性的驱动代码实现完毕后,进行make编译,加载到系统中后,设备和驱动是可以匹配上的,内核代码中写了几个led的设备,那么驱动就会匹配上几个led设备,echo 0或1 到/sys/class/leds/ledx/brightness文件也能控制led的亮灭,证明驱动是工作了。

想要在class目录下的leds目录中出现led设备文件并使用,就需要利用led_classdev_register函数将led设备和驱动数据结构体进行注册。

想要实时获取设备的数据部分传递给驱动,并且能给让驱动操作led的操作方法具有一般性,就需要使用上面的s5pv210_gpio_led这个结构体创造框架进行实现。

这个代码是通过三星内核中的/driver/leds/leds-s3c24xx.c代码进行仿造来完成的,几乎是一样的.

代码中有一些细节部分,没有做处理,只为框架思路上作下记录,使自己对platform总线理解的能够更深入些。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值