mirror of
https://github.com/ioacademy-jikim/device_driver
synced 2025-06-06 15:36:39 +00:00
first sample
This commit is contained in:
commit
e92d98c6d0
10
01_day/Makefile
Normal file
10
01_day/Makefile
Normal file
@ -0,0 +1,10 @@
|
||||
obj-m = misc_dev.o
|
||||
|
||||
KDIR = /usr/src/tegra
|
||||
PWD = $(shell pwd)
|
||||
|
||||
default:
|
||||
make -C $(KDIR) SUBDIRS=$(PWD) modules
|
||||
|
||||
clean:
|
||||
make -C $(KDIR) SUBDIRS=$(PWD) clean
|
21
01_day/for_each_process.c
Normal file
21
01_day/for_each_process.c
Normal file
@ -0,0 +1,21 @@
|
||||
#include <linux/module.h> // my_init
|
||||
#include <linux/kernel.h> // printk
|
||||
#include <linux/sched.h> // task_struct
|
||||
|
||||
int my_init(void)
|
||||
{
|
||||
struct task_struct *p;
|
||||
for_each_process(p)
|
||||
printk("pid=%d , comm=%s\n", p->pid, p->comm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void my_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
module_init( my_init );
|
||||
module_exit( my_exit );
|
||||
|
8
01_day/jni/Android.mk
Normal file
8
01_day/jni/Android.mk
Normal file
@ -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 := myapp.c
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
9
01_day/jni/myapp.c
Normal file
9
01_day/jni/myapp.c
Normal file
@ -0,0 +1,9 @@
|
||||
#include <fcntl.h>
|
||||
int main()
|
||||
{
|
||||
int fd;
|
||||
fd = open( "/dev/mydev", O_RDONLY );
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
155
01_day/macro.c
Normal file
155
01_day/macro.c
Normal file
@ -0,0 +1,155 @@
|
||||
#if 1
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef MODULE
|
||||
#define module_init( fn ) \
|
||||
int init_module(void) __attribute__((alias(#fn)))
|
||||
#else
|
||||
#define module_init( fn ) __initcall(x);
|
||||
#endif
|
||||
|
||||
int my_init(void)
|
||||
{
|
||||
printf("init_module()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
module_init( my_init );
|
||||
|
||||
int main()
|
||||
{
|
||||
init_module();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
#include <stdio.h>
|
||||
|
||||
void bar(void)
|
||||
{
|
||||
printf("bar()\n");
|
||||
}
|
||||
|
||||
void foo(void) __attribute__((alias("bar")));
|
||||
|
||||
int main()
|
||||
{
|
||||
foo();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
#include <stdio.h>
|
||||
|
||||
#define ___PASTE(a,b) a##b
|
||||
#define __PASTE(a,b) ___PASTE(a,b)
|
||||
#define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__)
|
||||
|
||||
#define __MODULE_LICENSE( license, info ) \
|
||||
static const char __UNIQUE_ID(license)[] = "license" "=" info
|
||||
|
||||
|
||||
__MODULE_LICENSE(license, "GPL"); __MODULE_LICENSE(license, "BSD");
|
||||
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
#include <stdio.h>
|
||||
|
||||
#define __FOO(a,b) a##b
|
||||
#define FOO( a,b ) __FOO(a,b)
|
||||
#define __MODULE_LICENSE( license, info ) \
|
||||
static const char FOO(license,__LINE__)[] = "license" "=" info
|
||||
|
||||
|
||||
__MODULE_LICENSE(license, "GPL"); __MODULE_LICENSE(license, "BSD");
|
||||
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
#include <stdio.h>
|
||||
|
||||
#define BAR hello
|
||||
|
||||
int main()
|
||||
{
|
||||
//printf("%s\n", "license" "=" "GPL" );
|
||||
printf("%s\n", "license=GPL" );
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
#include <stdio.h>
|
||||
|
||||
#define __FOO(x) #x
|
||||
#define FOO(x) __FOO(x)
|
||||
#define BAR hello
|
||||
|
||||
int main()
|
||||
{
|
||||
printf("%s\n", FOO(BAR) );
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
#include <stdio.h>
|
||||
|
||||
#define FOO(x) #x
|
||||
#define BAR hello
|
||||
|
||||
int main()
|
||||
{
|
||||
printf("%s\n", FOO(BAR) );
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
#include <stdio.h>
|
||||
|
||||
//#define __stringify_1(x...) #x
|
||||
//#define __stringify(x...) __stringify_1(x)
|
||||
|
||||
#define __stringify(x...) #x
|
||||
int main()
|
||||
{
|
||||
printf("%s\n", __stringify(license));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
#include <stdio.h>
|
||||
|
||||
# define __used __attribute__((__used__))
|
||||
int main()
|
||||
{
|
||||
int __used __attribute__((unused)) glob;
|
||||
|
||||
//printf("glob=%d\n", glob );
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
static const char a[]
|
||||
__attribute__((section(".modinfo")))
|
||||
= "hello";
|
||||
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
static const char a[] = "hello";
|
||||
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
44
01_day/misc_dev.c
Normal file
44
01_day/misc_dev.c
Normal file
@ -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 );
|
||||
|
15
01_day/module1.c
Normal file
15
01_day/module1.c
Normal file
@ -0,0 +1,15 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
int init_module(void)
|
||||
{
|
||||
printk("init_module()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cleanup_module(void)
|
||||
{
|
||||
printk("cleanup_module()\n");
|
||||
}
|
||||
|
||||
|
16
01_day/module2.c
Normal file
16
01_day/module2.c
Normal file
@ -0,0 +1,16 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
int init_module(void)
|
||||
{
|
||||
printk("init_module()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cleanup_module(void)
|
||||
{
|
||||
printk("cleanup_module()\n");
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
18
01_day/module3.c
Normal file
18
01_day/module3.c
Normal file
@ -0,0 +1,18 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
int my_init(void)
|
||||
{
|
||||
printk("init_module()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void my_exit(void)
|
||||
{
|
||||
printk("cleanup_module()\n");
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
module_init( my_init );
|
||||
module_exit( my_exit );
|
||||
|
36
01_day/my_dev.c
Normal file
36
01_day/my_dev.c
Normal file
@ -0,0 +1,36 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.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,
|
||||
};
|
||||
|
||||
int my_init(void)
|
||||
{
|
||||
register_chrdev(200, "mydev", &fops );
|
||||
return 0;
|
||||
}
|
||||
|
||||
void my_exit(void)
|
||||
{
|
||||
unregister_chrdev( 200, "mydev" );
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
module_init( my_init );
|
||||
module_exit( my_exit );
|
||||
|
19
01_day/my_process.c
Normal file
19
01_day/my_process.c
Normal file
@ -0,0 +1,19 @@
|
||||
#include <linux/module.h> // my_init
|
||||
#include <linux/kernel.h> // printk
|
||||
#include <linux/sched.h> // task_struct
|
||||
|
||||
int my_init(void)
|
||||
{
|
||||
struct task_struct *p = current;
|
||||
printk("pid=%d, comm=%s\n", p->pid, p->comm );
|
||||
return 0;
|
||||
}
|
||||
|
||||
void my_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
module_init( my_init );
|
||||
module_exit( my_exit );
|
||||
|
31
01_day/my_process_list.c
Normal file
31
01_day/my_process_list.c
Normal file
@ -0,0 +1,31 @@
|
||||
#include <linux/module.h> // my_init
|
||||
#include <linux/kernel.h> // printk
|
||||
#include <linux/sched.h> // task_struct
|
||||
#include <linux/list.h> // kernel list
|
||||
|
||||
int my_init(void)
|
||||
{
|
||||
struct task_struct *p;
|
||||
struct list_head *temp;
|
||||
|
||||
for( temp = current->tasks.next;
|
||||
temp!= ¤t->tasks;
|
||||
temp = temp->next )
|
||||
{
|
||||
p = list_entry( temp, struct task_struct, tasks );
|
||||
printk("pid=%d , comm=%s\n", p->pid, p->comm);
|
||||
}
|
||||
p = list_entry( temp, struct task_struct, tasks );
|
||||
printk("pid=%d , comm=%s\n", p->pid, p->comm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void my_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
module_init( my_init );
|
||||
module_exit( my_exit );
|
||||
|
BIN
02_day/.gen_dev.c.swp
Normal file
BIN
02_day/.gen_dev.c.swp
Normal file
Binary file not shown.
10
02_day/Makefile
Normal file
10
02_day/Makefile
Normal file
@ -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
|
77
02_day/bit.c
Normal file
77
02_day/bit.c
Normal file
@ -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;
|
||||
}
|
45
02_day/gen_dev.c
Normal file
45
02_day/gen_dev.c
Normal file
@ -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 );
|
||||
|
58
02_day/ioctl_dev.c
Normal file
58
02_day/ioctl_dev.c
Normal file
@ -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 );
|
||||
|
8
02_day/jni/Android.mk
Normal file
8
02_day/jni/Android.mk
Normal file
@ -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)
|
||||
|
10
02_day/jni/myapp.c
Normal file
10
02_day/jni/myapp.c
Normal file
@ -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;
|
||||
}
|
||||
|
57
02_day/jni/rdwr_app.c
Normal file
57
02_day/jni/rdwr_app.c
Normal file
@ -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;
|
||||
}
|
||||
*/
|
67
02_day/list.c
Normal file
67
02_day/list.c
Normal file
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
12
02_day/macro.c
Normal file
12
02_day/macro.c
Normal file
@ -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;
|
||||
}
|
44
02_day/misc_dev.c
Normal file
44
02_day/misc_dev.c
Normal file
@ -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 );
|
||||
|
10
02_day/mknod.c
Normal file
10
02_day/mknod.c
Normal file
@ -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;
|
||||
}
|
65
02_day/my_timer.c
Normal file
65
02_day/my_timer.c
Normal file
@ -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
|
||||
|
128
02_day/rdwr_dev.c
Normal file
128
02_day/rdwr_dev.c
Normal file
@ -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 );
|
||||
|
BIN
03_day/.kernel_file.c.swp
Normal file
BIN
03_day/.kernel_file.c.swp
Normal file
Binary file not shown.
BIN
03_day/.mmap_dev.c.swp
Normal file
BIN
03_day/.mmap_dev.c.swp
Normal file
Binary file not shown.
BIN
03_day/.my_memory.c.swp
Normal file
BIN
03_day/.my_memory.c.swp
Normal file
Binary file not shown.
10
03_day/Makefile
Normal file
10
03_day/Makefile
Normal file
@ -0,0 +1,10 @@
|
||||
obj-m = blocking_dev.o
|
||||
|
||||
KDIR = /usr/src/tegra
|
||||
PWD = $(shell pwd)
|
||||
|
||||
default:
|
||||
make -C $(KDIR) SUBDIRS=$(PWD) modules
|
||||
|
||||
clean:
|
||||
make -C $(KDIR) SUBDIRS=$(PWD) clean
|
75
03_day/blocking_dev.c
Normal file
75
03_day/blocking_dev.c
Normal file
@ -0,0 +1,75 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/miscdevice.h> //misc_register
|
||||
#include <linux/wait.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
static int temp;
|
||||
static DECLARE_WAIT_QUEUE_HEAD(my_wait);
|
||||
|
||||
int my_open (struct inode *inode, struct file *filp)
|
||||
{
|
||||
temp = -999;
|
||||
printk("my_open()\n");
|
||||
return 0;
|
||||
}
|
||||
int my_close(struct inode *inode, struct file *filp)
|
||||
{
|
||||
printk("my_close()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
irqreturn_t my_handler(int irq, void *id)
|
||||
{
|
||||
printk("my_handler()\n");
|
||||
temp=23;
|
||||
wake_up_interruptible(&my_wait);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
ssize_t my_read (struct file *filp, char __user *buff, size_t size,
|
||||
loff_t *off)
|
||||
{
|
||||
printk("my_read()\n");
|
||||
if( temp == -999 )
|
||||
interruptible_sleep_on(&my_wait);
|
||||
put_user( temp, (int*)buff );
|
||||
return 4;
|
||||
}
|
||||
|
||||
static struct file_operations fops =
|
||||
{
|
||||
.open = my_open,
|
||||
.release = my_close,
|
||||
.read = my_read,
|
||||
};
|
||||
|
||||
static struct miscdevice misc =
|
||||
{
|
||||
.minor = MISC_DYNAMIC_MINOR,
|
||||
.name = "mydev",
|
||||
.fops = &fops,
|
||||
};
|
||||
|
||||
int my_init(void)
|
||||
{
|
||||
int ret;
|
||||
unsigned long flags=IRQF_SHARED;
|
||||
misc_register( &misc );
|
||||
flags |= IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
|
||||
ret = request_irq(342, my_handler, flags, "MY_INT", my_handler);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void my_exit(void)
|
||||
{
|
||||
free_irq( 342, my_handler);
|
||||
misc_deregister( &misc );
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
module_init( my_init );
|
||||
module_exit( my_exit );
|
||||
|
99
03_day/ioctl_dev.c
Normal file
99
03_day/ioctl_dev.c
Normal file
@ -0,0 +1,99 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/miscdevice.h> //misc_register
|
||||
#include <asm/ioctl.h>
|
||||
#include <asm/uaccess.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;
|
||||
}
|
||||
//#define BINDER_WRITE_READ _IOWR('b', 1, struct binder_write_read)
|
||||
#define LED_RATIO _IOW( 'm', 1, int )
|
||||
|
||||
static int ratio;
|
||||
|
||||
long my_ioctl(struct file *filp, unsigned int cmd, unsigned long opt)
|
||||
{
|
||||
unsigned int size;
|
||||
int ret;
|
||||
printk("my_ioctl()\n");
|
||||
|
||||
size = _IOC_SIZE(cmd);
|
||||
|
||||
switch( cmd )
|
||||
{
|
||||
case LED_RATIO:
|
||||
if( size != sizeof(int))
|
||||
return -EINVAL;
|
||||
|
||||
ret = copy_from_user( &ratio, (void*)opt, size);
|
||||
printk("LED_RATIO, ratio=%d\n", ratio );
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
//#define BINDER_WRITE_READ _IOWR('b', 1, struct binder_write_read)
|
||||
#define LED_RATIO _IO( 'm', 1 )
|
||||
static int ratio;
|
||||
|
||||
long my_ioctl(struct file *filp, unsigned int cmd, unsigned long opt)
|
||||
{
|
||||
printk("my_ioctl()\n");
|
||||
|
||||
if( _IOC_TYPE(cmd) != 'm' )
|
||||
return -EINVAL;
|
||||
|
||||
if( _IOC_NR(cmd) != 1 )
|
||||
return -EINVAL;
|
||||
|
||||
switch( cmd )
|
||||
{
|
||||
case LED_RATIO: ratio = 128;
|
||||
printk("LED_RATIO, ratio=%d\n", ratio );
|
||||
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 );
|
||||
|
8
03_day/jni/Android.mk
Normal file
8
03_day/jni/Android.mk
Normal file
@ -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 := blocking_app.c
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
52
03_day/jni/ioctl_app.c
Normal file
52
03_day/jni/ioctl_app.c
Normal file
@ -0,0 +1,52 @@
|
||||
#if 1
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define LED_RATIO _IOW( 'm', 1 , int)
|
||||
|
||||
int main()
|
||||
{
|
||||
int fd, ret;
|
||||
int ratio;
|
||||
char buff[10];
|
||||
printf("밝기 입력( 0-255 ) : ");
|
||||
scanf("%d", &ratio );
|
||||
fd = open( "/dev/mydev", O_RDONLY );
|
||||
ret = ioctl(fd, LED_RATIO, &ratio);
|
||||
if( ret < 0 )
|
||||
{
|
||||
printf("ret=%d, errno=%d\n", ret, errno );
|
||||
return 0;
|
||||
}
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define LED_RATIO _IO( 'm', 1 )
|
||||
|
||||
int main()
|
||||
{
|
||||
int fd, ret;
|
||||
char buff[10];
|
||||
fd = open( "/dev/mydev", O_RDONLY );
|
||||
ret = ioctl(fd, LED_RATIO);
|
||||
if( ret < 0 )
|
||||
{
|
||||
printf("ret=%d, errno=%d\n", ret, errno );
|
||||
return 0;
|
||||
}
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
21
03_day/jni/mmap_app.c
Normal file
21
03_day/jni/mmap_app.c
Normal file
@ -0,0 +1,21 @@
|
||||
#if 1
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
int fd;
|
||||
char *p;
|
||||
fd = open("/dev/mydev", O_RDWR );
|
||||
p = mmap(0, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
strcpy( p , "hello world\n");
|
||||
printf("%s\n", p );
|
||||
munmap(p, 4096);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
10
03_day/jni/myapp.c
Normal file
10
03_day/jni/myapp.c
Normal file
@ -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;
|
||||
}
|
||||
|
59
03_day/jni/poll_app.c
Normal file
59
03_day/jni/poll_app.c
Normal file
@ -0,0 +1,59 @@
|
||||
#if 1
|
||||
#include <stdio.h>
|
||||
#include <poll.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
int fd, ret;
|
||||
int temp;
|
||||
char buff[1024];
|
||||
struct pollfd fds[2];
|
||||
fd = open( "/dev/mydev", O_RDONLY );
|
||||
fds[0].fd = 0 ;
|
||||
fds[0].events = POLLIN;
|
||||
fds[1].fd = fd ;
|
||||
fds[1].events = POLLIN;
|
||||
|
||||
poll( fds, 2, -1 );
|
||||
|
||||
if( fds[0].revents & POLLIN )
|
||||
{
|
||||
read( 0, buff, sizeof buff );
|
||||
buff[ret-1] = 0;
|
||||
printf("buff=%s\n", buff );
|
||||
}
|
||||
if( fds[1].revents & POLLIN )
|
||||
{
|
||||
read( fd, &temp, sizeof temp );
|
||||
printf("temp=%d\n", temp );
|
||||
}
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define LED_RATIO _IO( 'm', 1 )
|
||||
|
||||
int main()
|
||||
{
|
||||
int fd, ret;
|
||||
char buff[10];
|
||||
fd = open( "/dev/mydev", O_RDONLY );
|
||||
ret = ioctl(fd, LED_RATIO);
|
||||
if( ret < 0 )
|
||||
{
|
||||
printf("ret=%d, errno=%d\n", ret, errno );
|
||||
return 0;
|
||||
}
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
57
03_day/jni/rdwr_app.c
Normal file
57
03_day/jni/rdwr_app.c
Normal file
@ -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;
|
||||
}
|
||||
*/
|
29
03_day/kernel_file.c
Normal file
29
03_day/kernel_file.c
Normal file
@ -0,0 +1,29 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/gfp.h>
|
||||
// /data/aaa
|
||||
int my_init(void) {
|
||||
char *buff;
|
||||
struct file *filp;
|
||||
int ret;
|
||||
filp = filp_open( "/data/bbb", O_WRONLY|O_TRUNC|O_CREAT, 0666 );
|
||||
if( filp == 0 )
|
||||
return 0;
|
||||
buff = (char*)__get_free_pages( GFP_KERNEL, 0 );
|
||||
strcpy(buff, "hello world");
|
||||
ret = kernel_write( filp, buff, strlen(buff), 0 );
|
||||
printk("ret=%d\n", ret );
|
||||
free_pages( (unsigned long)buff, 0 );
|
||||
filp_close( filp, 0 );
|
||||
return 0;
|
||||
}
|
||||
|
||||
void my_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
module_init( my_init );
|
||||
module_exit( my_exit );
|
||||
|
34
03_day/mmap.c
Normal file
34
03_day/mmap.c
Normal file
@ -0,0 +1,34 @@
|
||||
#if 1
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
int main()
|
||||
{
|
||||
int fd;
|
||||
char *p;
|
||||
printf("main=%p\n", main);
|
||||
fd = open("aaa", O_RDWR | O_TRUNC | O_CREAT , 0666 );
|
||||
ftruncate(fd, 1024);
|
||||
p = mmap(0, 1024, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
strcpy( p , "hello world\n");
|
||||
//printf("%s\n", p );
|
||||
munmap(p, 1024);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#include <fcntl.h>
|
||||
int main()
|
||||
{
|
||||
//mmap();
|
||||
|
||||
int fd;
|
||||
fd = open("aaa", O_WRONLY | O_TRUNC | O_CREAT , 0666 );
|
||||
write( fd, "hello world", 11 );
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
60
03_day/mmap_dev.c
Normal file
60
03_day/mmap_dev.c
Normal file
@ -0,0 +1,60 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/miscdevice.h> //misc_register
|
||||
#include <linux/mm_types.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/mm.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;
|
||||
}
|
||||
|
||||
int my_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
{
|
||||
unsigned long pfn;
|
||||
unsigned long page;
|
||||
printk("my_mmap()\n");
|
||||
page = __get_free_pages( GFP_KERNEL, 0 );
|
||||
pfn = __pa( page );
|
||||
remap_pfn_range(vma, vma->vm_start,
|
||||
pfn>>12, 1<<12, vma->vm_page_prot);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct file_operations fops =
|
||||
{
|
||||
.open = my_open,
|
||||
.release = my_close,
|
||||
.mmap = my_mmap,
|
||||
};
|
||||
|
||||
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 );
|
||||
|
28
03_day/my_int.c
Normal file
28
03_day/my_int.c
Normal file
@ -0,0 +1,28 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
irqreturn_t my_handler(int irq, void *id)
|
||||
{
|
||||
printk("my_handler()\n");
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
int my_init(void)
|
||||
{
|
||||
int ret;
|
||||
unsigned long flags=IRQF_SHARED;
|
||||
flags |= IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
|
||||
ret = request_irq(342, my_handler, flags, "MY_INT", my_handler);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void my_exit(void)
|
||||
{
|
||||
free_irq( 342, my_handler);
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
module_init( my_init );
|
||||
module_exit( my_exit );
|
||||
|
56
03_day/my_memory.c
Normal file
56
03_day/my_memory.c
Normal file
@ -0,0 +1,56 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
|
||||
struct my_struct
|
||||
{
|
||||
char name[20];
|
||||
int id;
|
||||
};
|
||||
|
||||
int my_init(void)
|
||||
{
|
||||
char *p;
|
||||
struct my_struct *task;
|
||||
struct kmem_cache *my_struct_cachep;
|
||||
p = (char*)__get_free_pages( GFP_KERNEL, 0 );
|
||||
p[4095] = 'x';
|
||||
printk("%c\n", p[4095]);
|
||||
free_pages((unsigned long)p, 0);
|
||||
|
||||
p = (char*)kmalloc( 64, GFP_KERNEL);
|
||||
p[63] = 'x';
|
||||
printk("%c\n", p[63]);
|
||||
kfree(p);
|
||||
|
||||
#define L1_CACHE_SHIFT 6
|
||||
#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
|
||||
#define ARCH_MIN_TASKALIGN L1_CACHE_BYTES
|
||||
|
||||
my_struct_cachep =
|
||||
kmem_cache_create("my_struct", sizeof(struct my_struct),
|
||||
ARCH_MIN_TASKALIGN, SLAB_PANIC | SLAB_NOTRACK, NULL);
|
||||
task = kmem_cache_alloc( my_struct_cachep, GFP_KERNEL);
|
||||
strcpy( task->name, "kji");
|
||||
task->id = 1234;
|
||||
printk("%s, %d\n", task->name, task->id);
|
||||
kmem_cache_free( my_struct_cachep, task);
|
||||
kmem_cache_destroy( my_struct_cachep );
|
||||
|
||||
p = vmalloc( 8192 * 1024 );
|
||||
p[8192 * 1024-1] = 'x';
|
||||
printk("%c\n", p[8192 * 1024-1] );
|
||||
vfree( p );
|
||||
return 0;
|
||||
}
|
||||
|
||||
void my_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
module_init( my_init );
|
||||
module_exit( my_exit );
|
||||
|
74
03_day/poll_1.c
Normal file
74
03_day/poll_1.c
Normal file
@ -0,0 +1,74 @@
|
||||
#if 1
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <poll.h>
|
||||
int main()
|
||||
{
|
||||
char buff[1024];
|
||||
int ret;
|
||||
int fd;
|
||||
struct pollfd fds[2];
|
||||
// mkfifo myfifo
|
||||
fd = open("myfifo", O_RDWR );
|
||||
while(1)
|
||||
{
|
||||
fds[0].fd = 0;
|
||||
fds[0].events = POLLIN;
|
||||
fds[1].fd = fd;
|
||||
fds[1].events = POLLIN;
|
||||
poll( fds, 2, -1);
|
||||
if( fds[0].revents & POLLIN )
|
||||
{
|
||||
ret = read(0, buff, sizeof buff );
|
||||
buff[ret-1] = 0;
|
||||
printf("키보드 [%s]\n", buff );
|
||||
}
|
||||
|
||||
if( fds[1].revents & POLLIN )
|
||||
{
|
||||
ret = read(fd, buff, sizeof buff );
|
||||
buff[ret-1] = 0;
|
||||
printf("myfifo [%s]\n", buff );
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
int main()
|
||||
{
|
||||
char buff[1024];
|
||||
int ret;
|
||||
int fd;
|
||||
// mkfifo myfifo
|
||||
fd = open("myfifo", O_RDWR );
|
||||
while(1)
|
||||
{
|
||||
ret = read(0, buff, sizeof buff );
|
||||
buff[ret-1] = 0;
|
||||
printf("키보드 [%s]\n", buff );
|
||||
|
||||
ret = read(fd, buff, sizeof buff );
|
||||
buff[ret-1] = 0;
|
||||
printf("myfifo [%s]\n", buff );
|
||||
}
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if 0
|
||||
#include <fcntl.h>
|
||||
int main()
|
||||
{
|
||||
char buff[1024];
|
||||
int ret;
|
||||
ret = read(0, buff, sizeof buff );
|
||||
write( 1, buff, ret );
|
||||
return 0;
|
||||
}
|
||||
#endif
|
87
03_day/poll_dev.c
Normal file
87
03_day/poll_dev.c
Normal file
@ -0,0 +1,87 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/miscdevice.h> //misc_register
|
||||
#include <linux/wait.h>
|
||||
#include <linux/timer.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/poll.h>
|
||||
|
||||
static int temp;
|
||||
static DECLARE_WAIT_QUEUE_HEAD(my_wait);
|
||||
static struct timer_list timer;
|
||||
|
||||
void my_function(unsigned long data)
|
||||
{
|
||||
printk("my_function(%lu)\n", data );
|
||||
temp = 28;
|
||||
wake_up_interruptible( &my_wait );
|
||||
}
|
||||
int my_open (struct inode *inode, struct file *filp)
|
||||
{
|
||||
init_timer( &timer );
|
||||
timer.expires = jiffies + 3*HZ;
|
||||
timer.function = my_function;
|
||||
timer.data = 0;
|
||||
add_timer( &timer );
|
||||
temp = -999;
|
||||
printk("my_open()\n");
|
||||
return 0;
|
||||
}
|
||||
int my_close(struct inode *inode, struct file *filp)
|
||||
{
|
||||
printk("my_close()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
unsigned int my_poll(struct file *filp, struct poll_table_struct *table)
|
||||
{
|
||||
unsigned int mask=0;
|
||||
printk("my_poll()\n");
|
||||
|
||||
poll_wait(filp, &my_wait, table);
|
||||
if( temp != -999 )
|
||||
mask = POLLIN;
|
||||
return mask;
|
||||
}
|
||||
|
||||
ssize_t my_read (struct file *filp, char __user *buff, size_t size,
|
||||
loff_t *off)
|
||||
{
|
||||
printk("my_read()\n");
|
||||
put_user( temp, (int*)buff );
|
||||
return 4;
|
||||
}
|
||||
|
||||
static struct file_operations fops =
|
||||
{
|
||||
.open = my_open,
|
||||
.release = my_close,
|
||||
.poll = my_poll,
|
||||
.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)
|
||||
{
|
||||
del_timer( &timer );
|
||||
misc_deregister( &misc );
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
module_init( my_init );
|
||||
module_exit( my_exit );
|
||||
|
10
03_day/type.c
Normal file
10
03_day/type.c
Normal file
@ -0,0 +1,10 @@
|
||||
#include <stdio.h>
|
||||
int main()
|
||||
{
|
||||
int a[4];
|
||||
int *p = a;
|
||||
printf("sizeof(a) =%lu\n", sizeof(a));
|
||||
printf("sizeof(int[4])=%lu\n", sizeof(int[4]));
|
||||
printf("sizeof(p) =%lu\n", sizeof(p));
|
||||
printf("sizeof(int*) =%lu\n", sizeof(int*));
|
||||
}
|
BIN
04_day/.input_dev.c.swp
Normal file
BIN
04_day/.input_dev.c.swp
Normal file
Binary file not shown.
10
04_day/Makefile
Normal file
10
04_day/Makefile
Normal file
@ -0,0 +1,10 @@
|
||||
obj-m = my_work.o
|
||||
|
||||
KDIR = /usr/src/tegra
|
||||
PWD = $(shell pwd)
|
||||
|
||||
default:
|
||||
make -C $(KDIR) SUBDIRS=$(PWD) modules
|
||||
|
||||
clean:
|
||||
make -C $(KDIR) SUBDIRS=$(PWD) clean
|
34
04_day/flex.c
Normal file
34
04_day/flex.c
Normal file
@ -0,0 +1,34 @@
|
||||
#if 1
|
||||
#include <stdio.h>
|
||||
struct aaa
|
||||
{
|
||||
int count;
|
||||
int flag;
|
||||
int data[];
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
struct aaa *p;
|
||||
p = malloc( sizeof(struct aaa) + sizeof(int)*100 );
|
||||
p->count = 0;
|
||||
p->data[0] = 10;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#include <stdio.h>
|
||||
struct aaa
|
||||
{
|
||||
int a;
|
||||
int b[];
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
struct aaa a;
|
||||
printf("sizeof(a)=%lu\n", sizeof a );
|
||||
return 0;
|
||||
}
|
||||
#endif
|
52
04_day/input_dev.c
Normal file
52
04_day/input_dev.c
Normal file
@ -0,0 +1,52 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/miscdevice.h> //misc_register
|
||||
#include <linux/wait.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/input.h>
|
||||
|
||||
static struct input_dev *my_input;
|
||||
|
||||
irqreturn_t my_handler_up(int irq, void *id)
|
||||
{
|
||||
printk("my_handler_up()\n");
|
||||
input_sync(my_input);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
irqreturn_t my_handler_down(int irq, void *id)
|
||||
{
|
||||
static int value=0;
|
||||
printk("my_handler_down()\n");
|
||||
input_report_key(my_input, KEY_VOLUMEDOWN, value^=1);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
int my_init(void)
|
||||
{
|
||||
int ret;
|
||||
unsigned long flags=IRQF_SHARED;
|
||||
my_input = input_allocate_device();
|
||||
__set_bit( EV_KEY, my_input->evbit);
|
||||
__set_bit( KEY_VOLUMEDOWN, my_input->keybit);
|
||||
__set_bit( KEY_VOLUMEUP, my_input->keybit);
|
||||
|
||||
ret = input_register_device(my_input);
|
||||
flags |= IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
|
||||
ret = request_irq(342, my_handler_down, flags, "MY_INT_DOWN", my_handler_down);
|
||||
ret = request_irq(379, my_handler_up, flags, "MY_INT_UP", my_handler_up);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void my_exit(void)
|
||||
{
|
||||
free_irq( 342, my_handler_down);
|
||||
free_irq( 379, my_handler_up);
|
||||
input_unregister_device(my_input);
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
module_init( my_init );
|
||||
module_exit( my_exit );
|
||||
|
8
04_day/jni/Android.mk
Normal file
8
04_day/jni/Android.mk
Normal file
@ -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 := input_app.c
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
23
04_day/jni/input_app.c
Normal file
23
04_day/jni/input_app.c
Normal file
@ -0,0 +1,23 @@
|
||||
#if 1
|
||||
#include <stdio.h>
|
||||
#include <poll.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/input.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
int i;
|
||||
int fd, ret;
|
||||
struct input_event events[64];
|
||||
fd = open( "/dev/input/event4", O_RDONLY );
|
||||
while (ret = read( fd, events, sizeof events ))
|
||||
{
|
||||
for( i=0 ; i<(ret/(int)sizeof(struct input_event)); i++ )
|
||||
printf("type=%d, code=%d, value=%d\n",
|
||||
events[i].type, events[i].code, events[i].value);
|
||||
}
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
21
04_day/jni/queue_app.c
Normal file
21
04_day/jni/queue_app.c
Normal file
@ -0,0 +1,21 @@
|
||||
#if 1
|
||||
#include <stdio.h>
|
||||
#include <poll.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
int i;
|
||||
int fd, ret;
|
||||
int temp[64];
|
||||
fd = open( "/dev/mydev", O_RDONLY );
|
||||
while (ret = read( fd, temp, sizeof temp ))
|
||||
{
|
||||
for( i=0 ; i<(ret/(int)sizeof(int)); i++ )
|
||||
printf("temp[%d] = %d\n", i, temp[i] );
|
||||
}
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
37
04_day/my_work.c
Normal file
37
04_day/my_work.c
Normal file
@ -0,0 +1,37 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
static struct work_struct work;
|
||||
|
||||
irqreturn_t my_handler(int irq, void *id)
|
||||
{
|
||||
printk("my_handler()\n");
|
||||
schedule_work( &work );
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
void my_work_handler(struct work_struct *work)
|
||||
{
|
||||
printk("my_work_handler()\n");
|
||||
}
|
||||
|
||||
int my_init(void)
|
||||
{
|
||||
int ret;
|
||||
unsigned long flags=IRQF_SHARED;
|
||||
flags |= IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
|
||||
ret = request_irq(342, my_handler, flags, "MY_INT", my_handler);
|
||||
INIT_WORK(&work, my_work_handler);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void my_exit(void)
|
||||
{
|
||||
free_irq( 342, my_handler);
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
module_init( my_init );
|
||||
module_exit( my_exit );
|
||||
|
48
04_day/queue.c
Normal file
48
04_day/queue.c
Normal file
@ -0,0 +1,48 @@
|
||||
#include <stdio.h>
|
||||
typedef struct
|
||||
{
|
||||
int queue[64];
|
||||
int head;
|
||||
int tail;
|
||||
int count;
|
||||
} QUEUE;
|
||||
|
||||
void init( QUEUE *q )
|
||||
{
|
||||
q->head = 0;
|
||||
q->tail = 0;
|
||||
q->count = 0;
|
||||
}
|
||||
void put( QUEUE *q, int data )
|
||||
{
|
||||
q->queue[q->head] = data;
|
||||
q->head = (q->head+1)%64;
|
||||
q->count++;
|
||||
}
|
||||
int get( QUEUE *q )
|
||||
{
|
||||
int temp;
|
||||
temp = q->queue[q->tail];
|
||||
q->tail = (q->tail+1)%64;
|
||||
q->count--;
|
||||
return temp;
|
||||
}
|
||||
int is_empty( QUEUE *q )
|
||||
{
|
||||
return q->count == 0 ;
|
||||
}
|
||||
int main()
|
||||
{
|
||||
QUEUE q;
|
||||
init( &q );
|
||||
put( &q, 1 );
|
||||
put( &q, 2 );
|
||||
put( &q, 3 );
|
||||
while( !is_empty( &q ) )
|
||||
printf("%d\n", get(&q) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
120
04_day/queue_dev.c
Normal file
120
04_day/queue_dev.c
Normal file
@ -0,0 +1,120 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/miscdevice.h> //misc_register
|
||||
#include <linux/wait.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/input.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int queue[64];
|
||||
int head;
|
||||
int tail;
|
||||
int count;
|
||||
} QUEUE;
|
||||
static QUEUE queue;
|
||||
static DECLARE_WAIT_QUEUE_HEAD(my_wait);
|
||||
|
||||
|
||||
void init( QUEUE *q )
|
||||
{
|
||||
q->head = 0;
|
||||
q->tail = 0;
|
||||
q->count = 0;
|
||||
}
|
||||
void put( QUEUE *q, int data )
|
||||
{
|
||||
q->queue[q->head] = data;
|
||||
q->head = (q->head+1)%64;
|
||||
q->count++;
|
||||
}
|
||||
int get( QUEUE *q )
|
||||
{
|
||||
int temp;
|
||||
temp = q->queue[q->tail];
|
||||
q->tail = (q->tail+1)%64;
|
||||
q->count--;
|
||||
return temp;
|
||||
}
|
||||
int is_empty( QUEUE *q )
|
||||
{
|
||||
return q->count == 0 ;
|
||||
}
|
||||
|
||||
int my_open (struct inode *inode, struct file *filp)
|
||||
{
|
||||
init(&queue);
|
||||
printk("my_open()\n");
|
||||
return 0;
|
||||
}
|
||||
int my_close(struct inode *inode, struct file *filp)
|
||||
{
|
||||
printk("my_close()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
irqreturn_t my_handler_up(int irq, void *id)
|
||||
{
|
||||
printk("my_handler_up()\n");
|
||||
wake_up_interruptible(&my_wait);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
irqreturn_t my_handler_down(int irq, void *id)
|
||||
{
|
||||
printk("my_handler_down()\n");
|
||||
put( &queue, KEY_VOLUMEDOWN );
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
ssize_t my_read (struct file *filp, char __user *buff, size_t size,
|
||||
loff_t *off)
|
||||
{
|
||||
int i;
|
||||
int *p = (int*)buff;
|
||||
printk("my_read()\n");
|
||||
if( is_empty(&queue) )
|
||||
interruptible_sleep_on(&my_wait);
|
||||
|
||||
for(i=0; !is_empty(&queue); i++ )
|
||||
put_user( get(&queue) , p+i);
|
||||
return 4*i;
|
||||
}
|
||||
|
||||
static struct file_operations fops =
|
||||
{
|
||||
.open = my_open,
|
||||
.release = my_close,
|
||||
.read = my_read,
|
||||
};
|
||||
|
||||
static struct miscdevice misc =
|
||||
{
|
||||
.minor = MISC_DYNAMIC_MINOR,
|
||||
.name = "mydev",
|
||||
.fops = &fops,
|
||||
};
|
||||
|
||||
int my_init(void)
|
||||
{
|
||||
int ret;
|
||||
unsigned long flags=IRQF_SHARED;
|
||||
misc_register( &misc );
|
||||
flags |= IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
|
||||
ret = request_irq(342, my_handler_down, flags, "MY_INT_DOWN", my_handler_down);
|
||||
ret = request_irq(379, my_handler_up, flags, "MY_INT_UP", my_handler_up);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void my_exit(void)
|
||||
{
|
||||
free_irq( 342, my_handler_down);
|
||||
free_irq( 379, my_handler_up);
|
||||
misc_deregister( &misc );
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
module_init( my_init );
|
||||
module_exit( my_exit );
|
||||
|
10
05_day/Makefile
Normal file
10
05_day/Makefile
Normal file
@ -0,0 +1,10 @@
|
||||
obj-m = kobject-example.o
|
||||
|
||||
KDIR = /usr/src/tegra
|
||||
PWD = $(shell pwd)
|
||||
|
||||
default:
|
||||
make -C $(KDIR) SUBDIRS=$(PWD) modules
|
||||
|
||||
clean:
|
||||
make -C $(KDIR) SUBDIRS=$(PWD) clean
|
8
05_day/jni/Android.mk
Normal file
8
05_day/jni/Android.mk
Normal file
@ -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 := input_app.c
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
23
05_day/jni/input_app.c
Normal file
23
05_day/jni/input_app.c
Normal file
@ -0,0 +1,23 @@
|
||||
#if 1
|
||||
#include <stdio.h>
|
||||
#include <poll.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/input.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
int i;
|
||||
int fd, ret;
|
||||
struct input_event events[64];
|
||||
fd = open( "/dev/input/event4", O_RDONLY );
|
||||
while (ret = read( fd, events, sizeof events ))
|
||||
{
|
||||
for( i=0 ; i<(ret/(int)sizeof(struct input_event)); i++ )
|
||||
printf("type=%d, code=%d, value=%d\n",
|
||||
events[i].type, events[i].code, events[i].value);
|
||||
}
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
21
05_day/jni/queue_app.c
Normal file
21
05_day/jni/queue_app.c
Normal file
@ -0,0 +1,21 @@
|
||||
#if 1
|
||||
#include <stdio.h>
|
||||
#include <poll.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
int i;
|
||||
int fd, ret;
|
||||
int temp[64];
|
||||
fd = open( "/dev/mydev", O_RDONLY );
|
||||
while (ret = read( fd, temp, sizeof temp ))
|
||||
{
|
||||
for( i=0 ; i<(ret/(int)sizeof(int)); i++ )
|
||||
printf("temp[%d] = %d\n", i, temp[i] );
|
||||
}
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
137
05_day/kobject-example.c
Normal file
137
05_day/kobject-example.c
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Sample kobject implementation
|
||||
*
|
||||
* Copyright (C) 2004-2007 Greg Kroah-Hartman <greg@kroah.com>
|
||||
* Copyright (C) 2007 Novell Inc.
|
||||
*
|
||||
* Released under the GPL version 2 only.
|
||||
*
|
||||
*/
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
/*
|
||||
* This module shows how to create a simple subdirectory in sysfs called
|
||||
* /sys/kernel/kobject-example In that directory, 3 files are created:
|
||||
* "foo", "baz", and "bar". If an integer is written to these files, it can be
|
||||
* later read out of it.
|
||||
*/
|
||||
|
||||
static int foo;
|
||||
static int baz;
|
||||
static int bar;
|
||||
|
||||
/*
|
||||
* The "foo" file where a static variable is read from and written to.
|
||||
*/
|
||||
static ssize_t foo_show(struct kobject *kobj, struct kobj_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return sprintf(buf, "%d\n", foo);
|
||||
}
|
||||
|
||||
static ssize_t foo_store(struct kobject *kobj, struct kobj_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
sscanf(buf, "%du", &foo);
|
||||
return count;
|
||||
}
|
||||
|
||||
static struct kobj_attribute foo_attribute =
|
||||
__ATTR(foo, 0666, foo_show, foo_store);
|
||||
|
||||
/*
|
||||
* More complex function where we determine which variable is being accessed by
|
||||
* looking at the attribute for the "baz" and "bar" files.
|
||||
*/
|
||||
static ssize_t b_show(struct kobject *kobj, struct kobj_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
int var;
|
||||
|
||||
if (strcmp(attr->attr.name, "baz") == 0)
|
||||
var = baz;
|
||||
else
|
||||
var = bar;
|
||||
return sprintf(buf, "%d\n", var);
|
||||
}
|
||||
|
||||
static ssize_t b_store(struct kobject *kobj, struct kobj_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int var;
|
||||
|
||||
sscanf(buf, "%du", &var);
|
||||
if (strcmp(attr->attr.name, "baz") == 0)
|
||||
baz = var;
|
||||
else
|
||||
bar = var;
|
||||
return count;
|
||||
}
|
||||
|
||||
static struct kobj_attribute baz_attribute =
|
||||
__ATTR(baz, 0666, b_show, b_store);
|
||||
static struct kobj_attribute bar_attribute =
|
||||
__ATTR(bar, 0666, b_show, b_store);
|
||||
|
||||
|
||||
/*
|
||||
* Create a group of attributes so that we can create and destroy them all
|
||||
* at once.
|
||||
*/
|
||||
static struct attribute *attrs[] = {
|
||||
&foo_attribute.attr,
|
||||
&baz_attribute.attr,
|
||||
&bar_attribute.attr,
|
||||
NULL, /* need to NULL terminate the list of attributes */
|
||||
};
|
||||
|
||||
/*
|
||||
* An unnamed attribute group will put all of the attributes directly in
|
||||
* the kobject directory. If we specify a name, a subdirectory will be
|
||||
* created for the attributes with the directory being the name of the
|
||||
* attribute group.
|
||||
*/
|
||||
static struct attribute_group attr_group = {
|
||||
.attrs = attrs,
|
||||
};
|
||||
|
||||
static struct kobject *example_kobj;
|
||||
|
||||
static int __init example_init(void)
|
||||
{
|
||||
int retval;
|
||||
|
||||
/*
|
||||
* Create a simple kobject with the name of "kobject_example",
|
||||
* located under /sys/kernel/
|
||||
*
|
||||
* As this is a simple directory, no uevent will be sent to
|
||||
* userspace. That is why this function should not be used for
|
||||
* any type of dynamic kobjects, where the name and number are
|
||||
* not known ahead of time.
|
||||
*/
|
||||
example_kobj = kobject_create_and_add("kobject_example", kernel_kobj);
|
||||
if (!example_kobj)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Create the files associated with this kobject */
|
||||
retval = sysfs_create_group(example_kobj, &attr_group);
|
||||
if (retval)
|
||||
kobject_put(example_kobj);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void __exit example_exit(void)
|
||||
{
|
||||
kobject_put(example_kobj);
|
||||
}
|
||||
|
||||
module_init(example_init);
|
||||
module_exit(example_exit);
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Greg Kroah-Hartman <greg@kroah.com>");
|
279
05_day/kset-example.c
Normal file
279
05_day/kset-example.c
Normal file
@ -0,0 +1,279 @@
|
||||
/*
|
||||
* Sample kset and ktype implementation
|
||||
*
|
||||
* Copyright (C) 2004-2007 Greg Kroah-Hartman <greg@kroah.com>
|
||||
* Copyright (C) 2007 Novell Inc.
|
||||
*
|
||||
* Released under the GPL version 2 only.
|
||||
*
|
||||
*/
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
/*
|
||||
* This module shows how to create a kset in sysfs called
|
||||
* /sys/kernel/kset-example
|
||||
* Then tree kobjects are created and assigned to this kset, "foo", "baz",
|
||||
* and "bar". In those kobjects, attributes of the same name are also
|
||||
* created and if an integer is written to these files, it can be later
|
||||
* read out of it.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* This is our "object" that we will create a few of and register them with
|
||||
* sysfs.
|
||||
*/
|
||||
struct foo_obj {
|
||||
struct kobject kobj;
|
||||
int foo;
|
||||
int baz;
|
||||
int bar;
|
||||
};
|
||||
#define to_foo_obj(x) container_of(x, struct foo_obj, kobj)
|
||||
|
||||
/* a custom attribute that works just for a struct foo_obj. */
|
||||
struct foo_attribute {
|
||||
struct attribute attr;
|
||||
ssize_t (*show)(struct foo_obj *foo, struct foo_attribute *attr, char *buf);
|
||||
ssize_t (*store)(struct foo_obj *foo, struct foo_attribute *attr, const char *buf, size_t count);
|
||||
};
|
||||
#define to_foo_attr(x) container_of(x, struct foo_attribute, attr)
|
||||
|
||||
/*
|
||||
* The default show function that must be passed to sysfs. This will be
|
||||
* called by sysfs for whenever a show function is called by the user on a
|
||||
* sysfs file associated with the kobjects we have registered. We need to
|
||||
* transpose back from a "default" kobject to our custom struct foo_obj and
|
||||
* then call the show function for that specific object.
|
||||
*/
|
||||
static ssize_t foo_attr_show(struct kobject *kobj,
|
||||
struct attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct foo_attribute *attribute;
|
||||
struct foo_obj *foo;
|
||||
|
||||
attribute = to_foo_attr(attr);
|
||||
foo = to_foo_obj(kobj);
|
||||
|
||||
if (!attribute->show)
|
||||
return -EIO;
|
||||
|
||||
return attribute->show(foo, attribute, buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Just like the default show function above, but this one is for when the
|
||||
* sysfs "store" is requested (when a value is written to a file.)
|
||||
*/
|
||||
static ssize_t foo_attr_store(struct kobject *kobj,
|
||||
struct attribute *attr,
|
||||
const char *buf, size_t len)
|
||||
{
|
||||
struct foo_attribute *attribute;
|
||||
struct foo_obj *foo;
|
||||
|
||||
attribute = to_foo_attr(attr);
|
||||
foo = to_foo_obj(kobj);
|
||||
|
||||
if (!attribute->store)
|
||||
return -EIO;
|
||||
|
||||
return attribute->store(foo, attribute, buf, len);
|
||||
}
|
||||
|
||||
/* Our custom sysfs_ops that we will associate with our ktype later on */
|
||||
static const struct sysfs_ops foo_sysfs_ops = {
|
||||
.show = foo_attr_show,
|
||||
.store = foo_attr_store,
|
||||
};
|
||||
|
||||
/*
|
||||
* The release function for our object. This is REQUIRED by the kernel to
|
||||
* have. We free the memory held in our object here.
|
||||
*
|
||||
* NEVER try to get away with just a "blank" release function to try to be
|
||||
* smarter than the kernel. Turns out, no one ever is...
|
||||
*/
|
||||
static void foo_release(struct kobject *kobj)
|
||||
{
|
||||
struct foo_obj *foo;
|
||||
|
||||
foo = to_foo_obj(kobj);
|
||||
kfree(foo);
|
||||
}
|
||||
|
||||
/*
|
||||
* The "foo" file where the .foo variable is read from and written to.
|
||||
*/
|
||||
static ssize_t foo_show(struct foo_obj *foo_obj, struct foo_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return sprintf(buf, "%d\n", foo_obj->foo);
|
||||
}
|
||||
|
||||
static ssize_t foo_store(struct foo_obj *foo_obj, struct foo_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
sscanf(buf, "%du", &foo_obj->foo);
|
||||
return count;
|
||||
}
|
||||
|
||||
static struct foo_attribute foo_attribute =
|
||||
__ATTR(foo, 0666, foo_show, foo_store);
|
||||
|
||||
/*
|
||||
* More complex function where we determine which variable is being accessed by
|
||||
* looking at the attribute for the "baz" and "bar" files.
|
||||
*/
|
||||
static ssize_t b_show(struct foo_obj *foo_obj, struct foo_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
int var;
|
||||
|
||||
if (strcmp(attr->attr.name, "baz") == 0)
|
||||
var = foo_obj->baz;
|
||||
else
|
||||
var = foo_obj->bar;
|
||||
return sprintf(buf, "%d\n", var);
|
||||
}
|
||||
|
||||
static ssize_t b_store(struct foo_obj *foo_obj, struct foo_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int var;
|
||||
|
||||
sscanf(buf, "%du", &var);
|
||||
if (strcmp(attr->attr.name, "baz") == 0)
|
||||
foo_obj->baz = var;
|
||||
else
|
||||
foo_obj->bar = var;
|
||||
return count;
|
||||
}
|
||||
|
||||
static struct foo_attribute baz_attribute =
|
||||
__ATTR(baz, 0666, b_show, b_store);
|
||||
static struct foo_attribute bar_attribute =
|
||||
__ATTR(bar, 0666, b_show, b_store);
|
||||
|
||||
/*
|
||||
* Create a group of attributes so that we can create and destroy them all
|
||||
* at once.
|
||||
*/
|
||||
static struct attribute *foo_default_attrs[] = {
|
||||
&foo_attribute.attr,
|
||||
&baz_attribute.attr,
|
||||
&bar_attribute.attr,
|
||||
NULL, /* need to NULL terminate the list of attributes */
|
||||
};
|
||||
|
||||
/*
|
||||
* Our own ktype for our kobjects. Here we specify our sysfs ops, the
|
||||
* release function, and the set of default attributes we want created
|
||||
* whenever a kobject of this type is registered with the kernel.
|
||||
*/
|
||||
static struct kobj_type foo_ktype = {
|
||||
.sysfs_ops = &foo_sysfs_ops,
|
||||
.release = foo_release,
|
||||
.default_attrs = foo_default_attrs,
|
||||
};
|
||||
|
||||
static struct kset *example_kset;
|
||||
static struct foo_obj *foo_obj;
|
||||
static struct foo_obj *bar_obj;
|
||||
static struct foo_obj *baz_obj;
|
||||
|
||||
static struct foo_obj *create_foo_obj(const char *name)
|
||||
{
|
||||
struct foo_obj *foo;
|
||||
int retval;
|
||||
|
||||
/* allocate the memory for the whole object */
|
||||
foo = kzalloc(sizeof(*foo), GFP_KERNEL);
|
||||
if (!foo)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* As we have a kset for this kobject, we need to set it before calling
|
||||
* the kobject core.
|
||||
*/
|
||||
foo->kobj.kset = example_kset;
|
||||
|
||||
/*
|
||||
* Initialize and add the kobject to the kernel. All the default files
|
||||
* will be created here. As we have already specified a kset for this
|
||||
* kobject, we don't have to set a parent for the kobject, the kobject
|
||||
* will be placed beneath that kset automatically.
|
||||
*/
|
||||
retval = kobject_init_and_add(&foo->kobj, &foo_ktype, NULL, "%s", name);
|
||||
if (retval) {
|
||||
kobject_put(&foo->kobj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* We are always responsible for sending the uevent that the kobject
|
||||
* was added to the system.
|
||||
*/
|
||||
kobject_uevent(&foo->kobj, KOBJ_ADD);
|
||||
|
||||
return foo;
|
||||
}
|
||||
|
||||
static void destroy_foo_obj(struct foo_obj *foo)
|
||||
{
|
||||
kobject_put(&foo->kobj);
|
||||
}
|
||||
|
||||
static int __init example_init(void)
|
||||
{
|
||||
/*
|
||||
* Create a kset with the name of "kset_example",
|
||||
* located under /sys/kernel/
|
||||
*/
|
||||
example_kset = kset_create_and_add("kset_example", NULL, kernel_kobj);
|
||||
if (!example_kset)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* Create three objects and register them with our kset
|
||||
*/
|
||||
foo_obj = create_foo_obj("foo");
|
||||
if (!foo_obj)
|
||||
goto foo_error;
|
||||
|
||||
bar_obj = create_foo_obj("bar");
|
||||
if (!bar_obj)
|
||||
goto bar_error;
|
||||
|
||||
baz_obj = create_foo_obj("baz");
|
||||
if (!baz_obj)
|
||||
goto baz_error;
|
||||
|
||||
return 0;
|
||||
|
||||
baz_error:
|
||||
destroy_foo_obj(bar_obj);
|
||||
bar_error:
|
||||
destroy_foo_obj(foo_obj);
|
||||
foo_error:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void __exit example_exit(void)
|
||||
{
|
||||
destroy_foo_obj(baz_obj);
|
||||
destroy_foo_obj(bar_obj);
|
||||
destroy_foo_obj(foo_obj);
|
||||
kset_unregister(example_kset);
|
||||
}
|
||||
|
||||
module_init(example_init);
|
||||
module_exit(example_exit);
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Greg Kroah-Hartman <greg@kroah.com>");
|
Loading…
x
Reference in New Issue
Block a user