1
0
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:
ioacademy-jikim 2015-08-19 19:26:23 +09:00
commit e92d98c6d0
62 changed files with 2573 additions and 0 deletions

10
01_day/Makefile Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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!= &current->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

Binary file not shown.

10
02_day/Makefile Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

Binary file not shown.

BIN
03_day/.mmap_dev.c.swp Normal file

Binary file not shown.

BIN
03_day/.my_memory.c.swp Normal file

Binary file not shown.

10
03_day/Makefile Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

Binary file not shown.

10
04_day/Makefile Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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>");