mirror of
https://github.com/ioacademy-jikim/device_driver.git
synced 2026-08-11 16:32:54 +00:00
first sample
This commit is contained in:
Binary file not shown.
@@ -0,0 +1,10 @@
|
||||
obj-m = my_timer.o
|
||||
|
||||
KDIR = /usr/src/tegra
|
||||
PWD = $(shell pwd)
|
||||
|
||||
default:
|
||||
make -C $(KDIR) SUBDIRS=$(PWD) modules
|
||||
|
||||
clean:
|
||||
make -C $(KDIR) SUBDIRS=$(PWD) clean
|
||||
@@ -0,0 +1,77 @@
|
||||
#include <stdio.h>
|
||||
#define BITS_PER_LONG 64
|
||||
#define ffz(x) __ffs(~(x))
|
||||
#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
|
||||
#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
|
||||
static __always_inline unsigned long __ffs(unsigned long word)
|
||||
{
|
||||
int num = 0;
|
||||
|
||||
#if BITS_PER_LONG == 64
|
||||
if ((word & 0xffffffff) == 0) {
|
||||
num += 32;
|
||||
word >>= 32;
|
||||
}
|
||||
#endif
|
||||
if ((word & 0xffff) == 0) {
|
||||
num += 16;
|
||||
word >>= 16;
|
||||
}
|
||||
if ((word & 0xff) == 0) {
|
||||
num += 8;
|
||||
word >>= 8;
|
||||
}
|
||||
if ((word & 0xf) == 0) {
|
||||
num += 4;
|
||||
word >>= 4;
|
||||
}
|
||||
if ((word & 0x3) == 0) {
|
||||
num += 2;
|
||||
word >>= 2;
|
||||
}
|
||||
if ((word & 0x1) == 0)
|
||||
num += 1;
|
||||
return num;
|
||||
}
|
||||
static inline void set_bit(int nr, volatile unsigned long *addr)
|
||||
{
|
||||
unsigned long mask = BIT_MASK(nr);
|
||||
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
|
||||
unsigned long flags;
|
||||
|
||||
*p |= mask;
|
||||
}
|
||||
|
||||
unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size)
|
||||
{
|
||||
const unsigned long *p = addr;
|
||||
unsigned long result = 0;
|
||||
unsigned long tmp;
|
||||
|
||||
while (size & ~(BITS_PER_LONG-1)) {
|
||||
if (~(tmp = *(p++)))
|
||||
goto found;
|
||||
result += BITS_PER_LONG;
|
||||
size -= BITS_PER_LONG;
|
||||
}
|
||||
if (!size)
|
||||
return result;
|
||||
|
||||
tmp = (*p) | (~0UL << size);
|
||||
if (tmp == ~0UL) /* Are any bits zero? */
|
||||
return result + size; /* Nope. */
|
||||
found:
|
||||
return result + ffz(tmp);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
unsigned long a[1] = {0x0UL};
|
||||
unsigned long index;
|
||||
index = find_first_zero_bit(a, 64);
|
||||
printf("%lu\n", 64-index-1 );
|
||||
set_bit( 0, a );
|
||||
index = find_first_zero_bit(a, 64);
|
||||
printf("%lu\n", 64-index-1 );
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
int my_open (struct inode *inode, struct file *filp)
|
||||
{
|
||||
printk("my_open()\n");
|
||||
return 0;
|
||||
}
|
||||
int my_close(struct inode *inode, struct file *filp)
|
||||
{
|
||||
printk("my_close()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct file_operations fops =
|
||||
{
|
||||
.open = my_open,
|
||||
.release = my_close,
|
||||
};
|
||||
|
||||
static dev_t devt;
|
||||
static struct class *my_class;
|
||||
int my_init(void)
|
||||
{
|
||||
devt = MKDEV(200, 0);
|
||||
my_class = class_create(THIS_MODULE, "mydev");
|
||||
register_chrdev(200, "mydev", &fops );
|
||||
device_create(my_class, 0, devt, &fops, "%s", "mydev");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void my_exit(void)
|
||||
{
|
||||
device_destroy(my_class, devt);
|
||||
unregister_chrdev( 200, "mydev" );
|
||||
class_destroy(my_class);
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
module_init( my_init );
|
||||
module_exit( my_exit );
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/miscdevice.h> //misc_register
|
||||
|
||||
int my_open (struct inode *inode, struct file *filp)
|
||||
{
|
||||
printk("my_open()\n");
|
||||
return 0;
|
||||
}
|
||||
int my_close(struct inode *inode, struct file *filp)
|
||||
{
|
||||
printk("my_close()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
long my_ioctl (struct file *filp, unsigned int cmd, unsigned long opt)
|
||||
{
|
||||
_IOC_SIZE(cmd)
|
||||
printk("my_ioctl()\n");
|
||||
switch( cmd )
|
||||
{
|
||||
case 1: printk("LED_ON"); break;
|
||||
case 2: printk("LED_OFF"); break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct file_operations fops =
|
||||
{
|
||||
.open = my_open,
|
||||
.release = my_close,
|
||||
.unlocked_ioctl = my_ioctl,
|
||||
.compat_ioctl = my_ioctl,
|
||||
};
|
||||
|
||||
static struct miscdevice misc =
|
||||
{
|
||||
.minor = MISC_DYNAMIC_MINOR,
|
||||
.name = "mydev",
|
||||
.fops = &fops,
|
||||
};
|
||||
|
||||
int my_init(void)
|
||||
{
|
||||
misc_register( &misc );
|
||||
return 0;
|
||||
}
|
||||
|
||||
void my_exit(void)
|
||||
{
|
||||
misc_deregister( &misc );
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
module_init( my_init );
|
||||
module_exit( my_exit );
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_CFLAGS := -fPIE
|
||||
LOCAL_LDFLAGS := -fPIE -pie
|
||||
LOCAL_MODULE := myapp
|
||||
LOCAL_SRC_FILES := rdwr_app.c
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
#include <fcntl.h>
|
||||
int main()
|
||||
{
|
||||
int fd;
|
||||
fd = open( "/sys/devices/virtual/misc/mydev/uevent", O_WRONLY );
|
||||
write( fd, "add\n", 4 );
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
int main()
|
||||
{
|
||||
int fd, ret;
|
||||
char buff[10];
|
||||
fd = open( "/dev/mydev", O_RDONLY );
|
||||
ret = read( fd, buff, sizeof buff );
|
||||
buff[ret] = 0;
|
||||
printf( "buff[%s], ret=%d\n", buff, ret );
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
int main()
|
||||
{
|
||||
int fd, ret;
|
||||
int temp;
|
||||
fd = open( "/dev/mydev", O_RDONLY );
|
||||
ret = read( fd, &temp, sizeof temp );
|
||||
printf( "temp=%d, ret=%d\n", temp, ret );
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
int main()
|
||||
{
|
||||
int fd, ret;
|
||||
char buff[] = "LED_ON";
|
||||
fd = open( "/dev/mydev", O_WRONLY );
|
||||
ret = write( fd, buff, strlen(buff) );
|
||||
printf( "ret=%d\n", ret );
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
/*
|
||||
#include <fcntl.h>
|
||||
int main()
|
||||
{
|
||||
int fd;
|
||||
int flag=128;
|
||||
fd = open( "/dev/mydev", O_WRONLY );
|
||||
write( fd, &flag, sizeof flag );
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
@@ -0,0 +1,67 @@
|
||||
#include <stdio.h>
|
||||
struct list_head {
|
||||
struct list_head *next, *prev;
|
||||
};
|
||||
|
||||
struct miscdevice {
|
||||
int minor;
|
||||
const char *name;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
|
||||
static inline void __list_add(struct list_head *new,
|
||||
struct list_head *prev,
|
||||
struct list_head *next)
|
||||
{
|
||||
next->prev = new;
|
||||
new->next = next;
|
||||
new->prev = prev;
|
||||
prev->next = new;
|
||||
}
|
||||
|
||||
static inline void list_add(struct list_head *new, struct list_head *head)
|
||||
{
|
||||
__list_add(new, head, head->next);
|
||||
}
|
||||
|
||||
#define LIST_HEAD_INIT(name) { &(name), &(name) }
|
||||
|
||||
#define LIST_HEAD(name) \
|
||||
struct list_head name = LIST_HEAD_INIT(name)
|
||||
|
||||
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
|
||||
|
||||
#define container_of(ptr, type, member) ({ \
|
||||
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
|
||||
(type *)( (char *)__mptr - offsetof(type,member) );})
|
||||
|
||||
#define list_entry(ptr, type, member) \
|
||||
container_of(ptr, type, member)
|
||||
|
||||
#define list_for_each_entry(pos, head, member) \
|
||||
for (pos = list_entry((head)->next, typeof(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = list_entry(pos->member.next, typeof(*pos), member))
|
||||
|
||||
static LIST_HEAD(misc_list);
|
||||
static struct miscdevice misc = {
|
||||
.minor = 24,
|
||||
.name = "mydev",
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
struct miscdevice *c;
|
||||
list_add(&misc.list, &misc_list);
|
||||
|
||||
list_for_each_entry(c, &misc_list, list) {
|
||||
printf("minor=%d, name=%s\n", c->minor, c->name );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
#define __must_check __attribute__((warn_unused_result))
|
||||
int __must_check foo(void)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int ret;
|
||||
ret = foo();
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/miscdevice.h> //misc_register
|
||||
|
||||
int my_open (struct inode *inode, struct file *filp)
|
||||
{
|
||||
printk("my_open()\n");
|
||||
return 0;
|
||||
}
|
||||
int my_close(struct inode *inode, struct file *filp)
|
||||
{
|
||||
printk("my_close()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct file_operations fops =
|
||||
{
|
||||
.open = my_open,
|
||||
.release = my_close,
|
||||
};
|
||||
|
||||
static struct miscdevice misc =
|
||||
{
|
||||
.minor = MISC_DYNAMIC_MINOR,
|
||||
.name = "mydev",
|
||||
.fops = &fops,
|
||||
};
|
||||
|
||||
int my_init(void)
|
||||
{
|
||||
misc_register( &misc );
|
||||
return 0;
|
||||
}
|
||||
|
||||
void my_exit(void)
|
||||
{
|
||||
misc_deregister( &misc );
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
module_init( my_init );
|
||||
module_exit( my_exit );
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
mknod("mydev", S_IFCHR | 0666, (200<<8) | 0 );
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
#if 1
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/timer.h>
|
||||
|
||||
static struct timer_list timer;
|
||||
void my_function(unsigned long data)
|
||||
{
|
||||
printk("my_function(%lu)\n", data );
|
||||
timer.data = data+1;
|
||||
mod_timer( &timer, jiffies + HZ);
|
||||
}
|
||||
int my_init(void)
|
||||
{
|
||||
printk("init_module()\n");
|
||||
init_timer( &timer );
|
||||
timer.expires = jiffies + HZ;
|
||||
timer.function = my_function;
|
||||
timer.data = 0;
|
||||
add_timer( &timer );
|
||||
return 0;
|
||||
}
|
||||
|
||||
void my_exit(void)
|
||||
{
|
||||
del_timer( &timer );
|
||||
printk("cleanup_module()\n");
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
module_init( my_init );
|
||||
module_exit( my_exit );
|
||||
#endif
|
||||
#if 0
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/timer.h>
|
||||
|
||||
static struct timer_list timer;
|
||||
void my_function(unsigned long data)
|
||||
{
|
||||
printk("my_function(%lu)\n", data );
|
||||
}
|
||||
int my_init(void)
|
||||
{
|
||||
printk("init_module()\n");
|
||||
init_timer( &timer );
|
||||
timer.expires = jiffies + 3*HZ;
|
||||
timer.function = my_function;
|
||||
timer.data = 0;
|
||||
add_timer( &timer );
|
||||
return 0;
|
||||
}
|
||||
|
||||
void my_exit(void)
|
||||
{
|
||||
del_timer( &timer );
|
||||
printk("cleanup_module()\n");
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
module_init( my_init );
|
||||
module_exit( my_exit );
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/miscdevice.h> //misc_register
|
||||
#include <asm/uaccess.h> //get_user, put_user
|
||||
|
||||
int my_open (struct inode *inode, struct file *filp)
|
||||
{
|
||||
printk("my_open()\n");
|
||||
return 0;
|
||||
}
|
||||
int my_close(struct inode *inode, struct file *filp)
|
||||
{
|
||||
printk("my_close()\n");
|
||||
return 0;
|
||||
}
|
||||
ssize_t my_write (struct file *filp, const char __user *buff,
|
||||
size_t size, loff_t *off)
|
||||
{
|
||||
int ret, len;
|
||||
char k_buff[5];
|
||||
printk("my_write()\n");
|
||||
len = (size>sizeof(k_buff)-1)? sizeof(k_buff)-1 : size;
|
||||
|
||||
ret = copy_from_user( k_buff, buff, len );
|
||||
k_buff[len] = 0;
|
||||
printk("%s\n", k_buff);
|
||||
return len;
|
||||
}
|
||||
/*
|
||||
ssize_t my_write (struct file *filp, const char __user *buff,
|
||||
size_t size, loff_t *off)
|
||||
{
|
||||
int i, len;
|
||||
char k_buff[5];
|
||||
printk("my_write()\n");
|
||||
len = sizeof(k_buff)-1;
|
||||
|
||||
for(i=0; i<size; i++ )
|
||||
{
|
||||
if( i >= len )
|
||||
break;
|
||||
get_user( k_buff[i], buff+i); // k_buff[i] = *(buff+i);
|
||||
}
|
||||
k_buff[i] = 0;
|
||||
printk("%s\n", k_buff);
|
||||
return i;
|
||||
}
|
||||
*/
|
||||
/*
|
||||
ssize_t my_write (struct file *filp, const char __user *buff,
|
||||
size_t size, loff_t *off)
|
||||
{
|
||||
int k_buff;
|
||||
printk("my_write()\n");
|
||||
get_user( k_buff, (int*)buff ); // k_buff = *(int*)buff;
|
||||
printk("%d\n", k_buff);
|
||||
return sizeof(int);
|
||||
}
|
||||
*/
|
||||
ssize_t my_read (struct file *filp, char __user *buff,
|
||||
size_t size, loff_t * off)
|
||||
{
|
||||
char k_buff[] = "Hello user!!";
|
||||
int len = strlen(k_buff);
|
||||
int ret;
|
||||
|
||||
len = (size-1>len)? len: size-1;
|
||||
printk("my_read()\n");
|
||||
ret = copy_to_user( buff, k_buff, len ); // *(buff+i) = k_buff[i];
|
||||
return len;
|
||||
}
|
||||
/*
|
||||
ssize_t my_read (struct file *filp, char __user *buff,
|
||||
size_t size, loff_t * off)
|
||||
{
|
||||
char k_buff[] = "Hello user!!";
|
||||
int i;
|
||||
printk("my_read()\n");
|
||||
for(i=0; k_buff[i]; i++)
|
||||
{
|
||||
if( i >= size-1 )
|
||||
break;
|
||||
put_user( k_buff[i], buff+i ); // *(buff+i) = k_buff[i];
|
||||
}
|
||||
return i;
|
||||
}
|
||||
*/
|
||||
/*
|
||||
ssize_t my_read (struct file *filp, char __user *buff,
|
||||
size_t size, loff_t * off)
|
||||
{
|
||||
int temp=28;
|
||||
printk("my_read()\n");
|
||||
put_user( temp, (int*)buff ); // *(int*)buff = temp;
|
||||
return sizeof temp;
|
||||
}
|
||||
*/
|
||||
static struct file_operations fops =
|
||||
{
|
||||
.open = my_open,
|
||||
.release = my_close,
|
||||
.write = my_write,
|
||||
.read = my_read,
|
||||
};
|
||||
|
||||
static struct miscdevice misc =
|
||||
{
|
||||
.minor = MISC_DYNAMIC_MINOR,
|
||||
.name = "mydev",
|
||||
.fops = &fops,
|
||||
};
|
||||
|
||||
int my_init(void)
|
||||
{
|
||||
misc_register( &misc );
|
||||
return 0;
|
||||
}
|
||||
|
||||
void my_exit(void)
|
||||
{
|
||||
misc_deregister( &misc );
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
module_init( my_init );
|
||||
module_exit( my_exit );
|
||||
|
||||
Reference in New Issue
Block a user