前面我们讲解了字符设备驱动的一些写法,但是那样写出来的程序只能我们自己用或者自己公司用。因为你没有统一接口,别人不知道你的设备接口是什么,现在我们讲解几种常用的设设备模型。
第一:input输入子系统(键盘,鼠标,触摸屏等等)
static struct input_dev *s3c_ts_dev;//定义一个 input_dev结构体
s3c_ts_dev = input_allocate_device();//分配input_dev结构体
input_register_device(s3c_ts_dev);//注册 input_dev类型结构体
input_unregister_device(s3c_ts_dev);//卸载 input_dev类型结构体
input_free_device(s3c_ts_dev);//释放分配的input_dev结构体
其中用到的一设置事件的函数
/* 2.1 能产生哪类事件 */
set_bit(EV_KEY, s3c_ts_dev->evbit);
set_bit(EV_ABS, s3c_ts_dev->evbit);
/* 2.2 能产生这类事件里的哪些事件 */
set_bit(BTN_TOUCH, s3c_ts_dev->keybit);
input_set_abs_params(s3c_ts_dev, ABS_X, 0, 0x3FF, 0, 0);
input_set_abs_params(s3c_ts_dev, ABS_Y, 0, 0x3FF, 0, 0);
input_set_abs_params(s3c_ts_dev, ABS_PRESSURE, 0, 1, 0, 0);
unsigned long evbit[NBITS(EV_MAX)]; // 表示能产生哪类事件
unsigned long keybit[NBITS(KEY_MAX)]; // 表示能产生哪些按键
unsigned long relbit[NBITS(REL_MAX)]; // 表示能产生哪些相对位移事件, x,y,滚轮
unsigned long absbit[NBITS(ABS_MAX)]; // 表示能产生哪些绝对位移事件, x,y
platform_device_register(&led_dev);
static struct resource led_resource[] = {
platform_device_unregister(&led_dev);
static struct resource led_resource[] = {
[0] = {
.start = 0x56000010, //gpio_con gpio_dat两个寄存器占八个字节
.end = 0x56000010 + 8 - 1,//所以需要映射长八个字节
.flags = IORESOURCE_MEM,
},
[1] = {
.start = 8,
.end = 8,
.flags = IORESOURCE_IRQ,
}
};
static void led_release(struct device * dev)
{
}
static struct platform_device led_dev = {
.name = "myled",
.id = -1,
.num_resources = ARRAY_SIZE(led_resource),
.resource = led_resource,
.dev = {
.release = led_release,
},
};
drv:(稳定的部分)
struct platform_driver led_drv = {
.probe = led_probe,
.remove = led_remove,
.driver = {
.name = "myled",
}
};
platform_driver_register(&led_drv);
platform_driver_unregister(&led_drv);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);//这两个函数用开获取资源
第三:framebuffer结构
static struct fb_info *s3c_lcd;
s3c_lcd = framebuffer_alloc(0, NULL);
register_framebuffer(s3c_lcd);
unregister_framebuffer(s3c_lcd);
framebuffer_release(s3c_lcd);
第四:USB
//这里还是用了分离的概念,只是里面的一些函数接口不一样,其他的模型可以前的还是一样的。
static struct usb_driver usbmouse_as_key_driver = {
.name = "usbmouse_as_key_",
.probe = usbmouse_as_key_probe,
.disconnect = usbmouse_as_key_disconnect,
.id_table = usbmouse_as_key_id_table,
};
struct usb_device *dev = interface_to_usbdev(intf);
struct usb_host_interface *interface;
struct usb_endpoint_descriptor *endpoint;
input_allocate_device();
input_register_device(uk_dev);
usb_buf = usb_buffer_alloc(dev, len, GFP_ATOMIC, &usb_buf_phys);
usb_alloc_urb(0, GFP_KERNEL);
usb_submit_urb(uk_urb, GFP_KERNEL);
usb_kill_urb(uk_urb);
usb_free_urb(uk_urb);
usb_buffer_free(dev, len, usb_buf, usb_buf_phys);
input_unregister_device(uk_dev);
input_free_device(uk_dev);
第一:input输入子系统(键盘,鼠标,触摸屏等等)
static struct input_dev *s3c_ts_dev;//定义一个 input_dev结构体
s3c_ts_dev = input_allocate_device();//分配input_dev结构体
input_register_device(s3c_ts_dev);//注册 input_dev类型结构体
input_unregister_device(s3c_ts_dev);//卸载 input_dev类型结构体
input_free_device(s3c_ts_dev);//释放分配的input_dev结构体
其中用到的一设置事件的函数
/* 2.1 能产生哪类事件 */
set_bit(EV_KEY, s3c_ts_dev->evbit);
set_bit(EV_ABS, s3c_ts_dev->evbit);
/* 2.2 能产生这类事件里的哪些事件 */
set_bit(BTN_TOUCH, s3c_ts_dev->keybit);
input_set_abs_params(s3c_ts_dev, ABS_X, 0, 0x3FF, 0, 0);
input_set_abs_params(s3c_ts_dev, ABS_Y, 0, 0x3FF, 0, 0);
input_set_abs_params(s3c_ts_dev, ABS_PRESSURE, 0, 1, 0, 0);
unsigned long evbit[NBITS(EV_MAX)]; // 表示能产生哪类事件
unsigned long keybit[NBITS(KEY_MAX)]; // 表示能产生哪些按键
unsigned long relbit[NBITS(REL_MAX)]; // 表示能产生哪些相对位移事件, x,y,滚轮
unsigned long absbit[NBITS(ABS_MAX)]; // 表示能产生哪些绝对位移事件, x,y
第二:分离的概念,平台总线的引入。
dev:(属于不稳定的部分)platform_device_register(&led_dev);
static struct resource led_resource[] = {
platform_device_unregister(&led_dev);
static struct resource led_resource[] = {
[0] = {
.start = 0x56000010, //gpio_con gpio_dat两个寄存器占八个字节
.end = 0x56000010 + 8 - 1,//所以需要映射长八个字节
.flags = IORESOURCE_MEM,
},
[1] = {
.start = 8,
.end = 8,
.flags = IORESOURCE_IRQ,
}
};
static void led_release(struct device * dev)
{
}
static struct platform_device led_dev = {
.name = "myled",
.id = -1,
.num_resources = ARRAY_SIZE(led_resource),
.resource = led_resource,
.dev = {
.release = led_release,
},
};
drv:(稳定的部分)
struct platform_driver led_drv = {
.probe = led_probe,
.remove = led_remove,
.driver = {
.name = "myled",
}
};
platform_driver_register(&led_drv);
platform_driver_unregister(&led_drv);
platform_device_register(&led_dev);
platform_device_unregister(&led_dev);res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);//这两个函数用开获取资源
tips:在这里这个结构体里面的name必须和dev里面的name一致,只有相同的时候才会调用led_probe其他的跟写普通的字符设备驱动是不变的
第三:framebuffer结构
static struct fb_info *s3c_lcd;
s3c_lcd = framebuffer_alloc(0, NULL);
register_framebuffer(s3c_lcd);
unregister_framebuffer(s3c_lcd);
framebuffer_release(s3c_lcd);
第四:USB
//这里还是用了分离的概念,只是里面的一些函数接口不一样,其他的模型可以前的还是一样的。
static struct usb_driver usbmouse_as_key_driver = {
.name = "usbmouse_as_key_",
.probe = usbmouse_as_key_probe,
.disconnect = usbmouse_as_key_disconnect,
.id_table = usbmouse_as_key_id_table,
};
struct usb_device *dev = interface_to_usbdev(intf);
struct usb_host_interface *interface;
struct usb_endpoint_descriptor *endpoint;
input_allocate_device();
input_register_device(uk_dev);
usb_buf = usb_buffer_alloc(dev, len, GFP_ATOMIC, &usb_buf_phys);
usb_alloc_urb(0, GFP_KERNEL);
usb_submit_urb(uk_urb, GFP_KERNEL);
usb_kill_urb(uk_urb);
usb_free_urb(uk_urb);
usb_buffer_free(dev, len, usb_buf, usb_buf_phys);
input_unregister_device(uk_dev);
input_free_device(uk_dev);