您的位置:首页 > 其它

字符设备驱动之LED-混杂设备驱动(misc)

2011-09-17 20:13 411 查看
misc_led.c

#include <linux/fs.h>

#include <linux/module.h>

#include <linux/errno.h>

#include <linux/kernel.h>

#include <linux/init.h>

#include <linux/cdev.h>

#include <linux/ioport.h>

#include <linux/pci.h>

#include <asm/uaccess.h>

#include <asm/io.h>

#include <linux/miscdevice.h>

static volatile unsigned long * gpfcon; // = (volatile unsigned long *)0x56000050;

static volatile unsigned long * gpfdat; // = (volatile unsigned long *)0x56000054;

int led_open(struct inode *inode, struct file *file)

{

/* 配置GPIO为输出引脚 */

*gpfcon &= ~0xff00;

*gpfcon |= 0x5500;

return 0;

}

ssize_t led_write(struct file *file, const char __user *buf, size_t size, loff_t *offset)

{

char ker_buf[2];

/* 根据buf传入的值点/灭灯 */

/* buf[0] - 哪个灯, 0 - 第1个灯 */

/* buf[1] - 亮/灭 , 0 - 亮, 1 - 灭 */

if (size != 2)

{

return -EINVAL;

}

copy_from_user(ker_buf, buf, 2);

if (ker_buf[0] < 0 || ker_buf[0] > 3)

return -EINVAL;

if ((ker_buf[1] != 0) && (ker_buf[1] != 1))

return -EINVAL;

if (ker_buf[1])

{

// 灭灯

*gpfdat |= (1<<(ker_buf[0] + 4));

}

else

{

*gpfdat &= ~(1<<(ker_buf[0] + 4));

}

return 2;

}

/* buf[0] - led1,0亮, 1灭 */

/* buf[1] - led2,0亮, 1灭 */

/* buf[2] - led3,0亮, 1灭 */

/* buf[3] - led4,0亮, 1灭 */

ssize_t led_read(struct file *file, char __user *buf, size_t size, loff_t *offset)

{

char ker_buf[4];

unsigned long val;

if (size != 4)

return -EINVAL;

val = *gpfdat;

ker_buf[0] = (val & (1<<4)) ? 1 : 0;

ker_buf[1] = (val & (1<<5)) ? 1 : 0;

ker_buf[2] = (val & (1<<6)) ? 1 : 0;

ker_buf[3] = (val & (1<<7)) ? 1 : 0;

copy_to_user(buf, ker_buf, 4);

return 4;

}

static const struct file_operations led_fops = {

.owner = THIS_MODULE,

.write = led_write,

.read = led_read,

.open = led_open

};

static struct miscdevice led_misc = {

.minor = 140,

.name = "led",

.fops = &led_fops,

};

int led_init(void)

{

misc_register(&led_misc);

gpfcon = ioremap(0x56000050, 8); /* 得到虚拟地址 */

gpfdat = gpfcon + 1;

return 0;

}

void led_exit(void)

{

misc_deregister(&led_misc);

iounmap(gpfcon);

}

module_init(led_init);

module_exit(led_exit);

MODULE_LICENSE("GPL");

test.c

#include <stdio.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <unistd.h>

/* led_test <which> <on|off>

* led_test r

*/

void print_usage(char *str)

{

printf("Usage:\n");

printf("%s r : read status\n", str);

printf("%s <which> <on|off>\n", str);

printf("which = 0,1,2,3\n");

}

int main(int argc, char **argv)

{

int fd;

char buf[4];

int ret;

int i;

if (argc != 3 && 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 (argc == 3)

{

buf[0] = strtoul(argv[1], NULL, 0);

if (strcmp(argv[2], "on") == 0)

{

buf[1] = 0;

}

else

{

buf[1] = 1;

}

ret = write(fd, buf, 2);

if (ret != 2)

{

printf("error!\n");

return -1;

}

}

else

{

if (strcmp(argv[1], "r") == 0)

{

ret = read(fd, buf, 4);

for (i = 0; i < 4; i++)

{

printf("led%d %s\n", i+1, buf[i] ? "off" : "on");

}

}

}

return 0;

}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: