kernel_thread로 디바이스 접근 가능한가요?
글쓴이: jeon9075 / 작성시간: 토, 2008/08/23 - 2:45오전
kernel_thread를 사용하여 fnd device에 불을 키려고 합니다.
가능한 방법이 있는지 알고 싶습니다.
제가 시도한 방법으로는 되질 않네요~
*** device driver code ***
fnd.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <asm/fcntl.h>
#include <linux/ioport.h>
#include <asm/processor.h>
#include <asm/ioctl.h>
#include <asm/hardware.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#define DRIVER_AUTHOR "hanback"
#define DRIVER_DESC "fnd test"
#define FND_MODULE_VERSION "FND PORT V0.1"
#define FND_NAME "FND"
#define FND_MAJOR_NUMBER 0
#define FND_ADDRESS_GRID 0x08800000
#define FND_ADDRESS_DATA 0x08801000
#define FND_ADDRESS_RANGE 0x1000
//Global variable
static unsigned int fnd_usage = 0;
static unsigned int fnd_major = 0;
static unsigned char *fnd_data;
static unsigned char *fnd_grid;
static char data[6];
static unsigned char digit[6]={0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
int fnd_open (struct inode *inode, struct file *filp)
{
if(fnd_usage != 0) return -EBUSY;
fnd_grid = ioremap(FND_ADDRESS_GRID, FND_ADDRESS_RANGE);
fnd_data = ioremap(FND_ADDRESS_DATA, FND_ADDRESS_RANGE);
if(!check_region(fnd_data,FND_ADDRESS_RANGE) && !check_region(fnd_grid, FND_ADDRESS_RANGE))
{
request_region(fnd_grid, FND_ADDRESS_RANGE, FND_NAME);
request_region(fnd_data, FND_ADDRESS_RANGE, FND_NAME);
}
else printk("driver : unable to register this!\n");
fnd_usage = 1;
return 0;
}
int fnd_release (struct inode *inode, struct file *filp)
{
iounmap(fnd_grid);
iounmap(fnd_data);
release_region(fnd_data, FND_ADDRESS_RANGE);
release_region(fnd_grid, FND_ADDRESS_RANGE);
fnd_usage = 0;
return 0;
}
unsigned char Getfndcode (char x)
{
unsigned char code;
switch (x) {
case 0x0 : code = 0x3f; break;
case 0x1 : code = 0x06; break;
case 0x2 : code = 0x5b; break;
case 0x3 : code = 0x4f; break;
case 0x4 : code = 0x66; break;
case 0x5 : code = 0x6d; break;
case 0x6 : code = 0x7d; break;
case 0x7 : code = 0x07; break;
case 0x8 : code = 0x7f; break;
case 0x9 : code = 0x6f; break;
case 0xA : code = 0x77; break;
case 0xB : code = 0x7c; break;
case 0xC : code = 0x39; break;
case 0xD : code = 0x5e; break;
case 0xE : code = 0x79; break;
case 0xF : code = 0x71; break;
default : code = 0; break;
}
return code;
}
int myfunc (void *unused)
{
unsigned int i,k;
for (;;)
{
for(i=0;i<6;i++) {
// *fnd_grid = ~digit[i];
// *fnd_data = data[i];
for(k=0;k<65536;k++);
//schedule_timeout(1000);
}
}
}
ssize_t fnd_write (struct file *inode, const char *gdata, size_t length, loff_t *off_what)
{
unsigned int num;
copy_from_user(&num,gdata,4);
data[5]=Getfndcode (num & 0x0f);
data[4]=Getfndcode (0xE); // 'S' strike
data[3]=Getfndcode (num & 0xf0);
data[2]=Getfndcode (0xB); // 'B' ball
data[1]=Getfndcode (0);
data[0]=Getfndcode (0);
}
struct file_operations fnd_fops =
{
.owner = THIS_MODULE,
.open = fnd_open,
.write = fnd_write,
.release = fnd_release,
};
int fnd_init(void)
{
int result;
kernel_thread(myfunc, NULL, 0);
result = register_chrdev(FND_MAJOR_NUMBER, FND_NAME, &fnd_fops);
if (result < 0) {
printk(KERN_WARNING"Can't get any major\n");
return result;
}
fnd_major = result;
printk("init module, fnd major number : %d\n", result);
return 0;
}
void fnd_exit(void)
{
if(unregister_chrdev(fnd_major,FND_NAME))
printk("driver: %s DRIVER EXIT FAILED\n", FND_NAME);
else
printk("driver: %s DRIVER EXIT\n", FND_NAME);
}
module_init(fnd_init);
module_exit(fnd_exit);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("Dual BSD/GPL");
*********** test.c code ********************
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
int baseball[3], userball[3];
int baserand() {
srand((unsigned int)time(NULL));
return (rand()%9);
}
void initgame(int baseball[]) {
baseball[0] = baserand();
baseball[1] = baserand();
while (baseball[0] == baseball[1])
baseball[1]=baserand();
baseball[2] = baserand();
while ((baseball[0] == baseball[2]) || (baseball[1] == baseball[2]))
baseball[2]=baserand();
}
void inputball(int userball[], int tmp) {
int i;
for(i=2; i>=0; i--) {
userball [i] = tmp % 10;
tmp /= 10;
}
}
void cmpball(int *baseball, int *userball, int *strike, int *ball) {
int i, j;
for(i=0; i<3; i++){
for(j=0; j<3; j++){
if((i==j) && (baseball[i] == userball[j]))
*strike = *strike+1;
else if(baseball[i] == userball[j])
*ball = *ball+1;
else
;
}
}
}
int main(void) {
int fd;
int value;
int strike, ball;
int cnt, tmp;
int call;
printf("===Baseball Game===\n\n");
if((fd=open("/dev/fnd",O_RDWR|O_SYNC)) < 0) {
printf("FND open fail\n");
exit(1);
}
initgame (baseball);
for (cnt=0; cnt<3; cnt++)
printf("baseball[%d] = %d\n",cnt,baseball[cnt]);
printf("\n");
cnt = 1;
while(1){
printf("\n%dth Input 3 Numbers ?", cnt);
scanf("%d",&tmp);
strike=0 , ball=0;
inputball(userball, tmp);
cmpball (baseball, userball, &strike, &ball);
printf("\n%d Strike! %d Ball!!\n",strike, ball);
ball = ball << 4;
call = ball | strike;
write(fd,&call,4);
if(strike == 3)
break;
cnt++;
}
printf("\n==========!!Congraturation!!==========\n\n");
printf("\nYou find %dth count.\n",cnt);
close(fd);
return 0;
}
****************** Makefile *************************************
# 7-segment Device Driver Makefile
CC = arm-linux-gcc
obj-m := fnd.o
KDIR := /working/linux-2.6.12-sm2
PWD := $(shell pwd)
TEST_TARGET = test
TEST_SRCS = test.c
default:$(TEST_TARGET)
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
$(CC) $(TEST_SRCS) -o $@
rm -f default
clean:
rm -f fnd
rm -f *.ko
rm -f *.o
rm -f *.mod.*
rm -f .*.cmd
rm -f $(TEST_TARGET)Forums:


댓글 달기