《Linux驱动》分层分离

led_drv

#include <linux/module.h>
#include <linux/compat.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/smp_lock.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/mman.h>
#include <linux/vt.h>
#include <linux/init.h>
#include <linux/linux_logo.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/console.h>
#include <linux/kmod.h>
#include <linux/err.h>
#include <linux/device.h>
#include <asm/uaccess.h>
#include <asm/io.h>

#include <linux/platform_device.h>

static int major  = 0;
static volatile unsigned long *gpxcon;
static volatile unsigned long *gpxdat;
static int pin;
static struct class *cls;

static int led_open(struct inode *inode, struct file *file)
{
    *gpxcon &= ~(0xf << (pin * 4));
    *gpxcon |= (0x1 << (pin * 4));
    return 0;
}

static ssize_t led_write(struct file *file, const char __user *buf, size_t count, loff_t *offset)
{
    char val;
    copy_from_user(&val, buf, 1);
    if (val == 0)
    {
        /* 开灯 */
        *gpxdat &= ~(1<<pin);
    }
    else
    {
        *gpxdat |= (1<<pin);
    }
    return 1;   
}

static struct file_operations led_fops = {
    .owner    = THIS_MODULE,
    .open     = led_open,
    .write    = led_write,
};


static int led_probe(struct platform_device *dev)
{
    struct resource *res;

    res = platform_get_resource(dev, IORESOURCE_MEM, 0);
    gpxcon = ioremap(res->start, res->end - res->start + 1);
    gpxdat = gpxcon + 1;

    res = platform_get_resource(dev, IORESOURCE_IRQ, 0);
    pin = res->start;

    major = register_chrdev(0, "led", &led_fops);
    cls = class_create(THIS_MODULE, "led"); /* sysfs */
    device_create(cls, NULL, MKDEV(major, 0), NULL, "led");

    return 0;
}

static int led_remove(struct platform_device *dev)
{
    device_destroy(cls, MKDEV(major, 0));
    class_destroy(cls);
    unregister_chrdev(major, "led");
    iounmap(gpxcon);
    return 0;
}

/* 1. 分配一个platform_driver */
/* 2. 设置 */
static struct platform_driver led_drv = {
    .probe      = led_probe,
    .remove     = __devexit_p(led_remove),
    .driver     = {
        .name   = "up6410_led",
        .owner  = THIS_MODULE,
    },
};

/* 3. 注册 */

static int led_drv_init(void)
{
    platform_driver_register(&led_drv);
    return 0;
}

static void led_drv_exit(void)
{
    platform_driver_unregister(&led_drv);
}

module_init(led_drv_init);
module_exit(led_drv_exit);
MODULE_LICENSE("GPL");

led_dev

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/platform_device.h>


/* 1. 分配一个platform_device */
/* 2. 设置 */
static struct resource led_resoures[] = {
    [0] = {
        .start  = 0x7F008820,  /* GPMCON */
        .end    = 0x7F008827,
        .flags  = IORESOURCE_MEM,
    },

    [1] = {
        .start  = 1,
        .end    = 1,
        .flags  = IORESOURCE_IRQ,
    },
};

static void led_release(struct device *dev)
{
}

static struct platform_device led_dev = {
    .name           = "up6410_led",
    .id             = 0,
    .num_resources  = 2,
    .resource       = led_resoures,
    .dev            = {
            .release = led_release,
    },
};

/* 3. 注册 */

static int led_dev_init(void)
{
    platform_device_register(&led_dev);
    return 0;
}

static void led_dev_exit(void)
{
    platform_device_del(&led_dev);
}

module_init(led_dev_init);
module_exit(led_dev_exit);
MODULE_LICENSE("GPL");

led_test.c

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void print_usage(char *file)
{
    printf("Usage:\n");
    printf("%s <on|off>\n", file);
}

int main(int argc, char **argv)
{
    int fd;
    char val;

    if (argc != 2)
    {
        print_usage(argv[0]);
        return -1;
    }

    fd = open("/dev/led", O_RDWR);
    if (fd < 0)
    {
        printf("can't open /dev/led\n");
        return -1;
    }


    if (strcmp(argv[1], "on") == 0)
    {
        val = 0;
    }
    else
    {
        val = 1;
    }

    write(fd, &val, 1);

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值