fnd 나 부저 같은 간단한 디바이스를 제어하기 위한 드라이버를 만들때 각각 만들어 구분해도 상관 없으나, 하나의 드라이버로 만들어 메이저 번호를 공통으로 하고 마이너 번호로 이들을 구분해 각각 따로 open 이 가능 한 형태로 사용 할 수도 있습니다.


fnd 제어 드라이버와 buzzer 드라이버를 하나의  메이저 아래 두개의 마이너로 구분해 사용 하는 방법을 알아보겠습니다.


1. 메이저 번호는 dev.h 파일에 아래와 같이 선언해 줍니다.

-----------------------------------------------------------------------

#define DEV_DRIVER_MAJOR 203

-----------------------------------------------------------------------



2. 먼저 minor 로 open 하기위해 아래와 같은 구조체가 필요합니다.

-----------------------------------------------------------------------


struct file_operations minor_fops=

{

.owner THIS_MODULE,

.open minor_open,

};


-----------------------------------------------------------------------


3. dev_init 함수에서 장치 파일등록

장치 파일을 등록 할때 _init int dev_init(void)  함수에서 아래와 같이 등록 합니다.

-----------------------------------------------------------------------

static __init int dev_init(void)

{

// 장치파일 등록

major &= 0xff;

register_chrdev( DEV_DRIVER_MAJOR, DEV_NAME, &minor_fops );


 ~ 생략 ~ 

}


4. 이제 minor_open 함수가 있어야 합니다.

실제 이 minor_open 함수에서 어플리케이션 으로부터 받은 마이너 번호에 따라 해당 디바이스의 드라이버를 open 하게 됩니다.

아래 minor_open 함수의 filp->f_op 값이 바로 어플리케이션 에서 넘어온 minor 번호가 됩니다.

-----------------------------------------------------------------------

int minor_open( struct inode *inode, struct file *filp)

{

switch(MINOR(inode->i_rdev))

{

case 1: filp->f_op = &minor_fnd_fops;break;

case 2: filp->f_op = &minor_buzzer_fops;break;

default : return -ENXIO;

}

if (filp->f_op && filp->f_op->open)

return filp->f_op->open(inode,filp);

return 0;

}

-----------------------------------------------------------------------


5. 드라이버 등록 구조체 선언

두 드라이버는 마이너 번호로 완젼 분리 되기 떄문에 각각 다른 드라이버 등록 구조체를 갖게 되며 따라서 따로 구조체를 선언

해 주어야 합니다. 

------------------------------------------------------------------------

//------------------------------------------------------------------------------

// FND 드라이버 등록 구조체

//------------------------------------------------------------------------------

static struct file_operations minor_fnd_fops =

{

.owner = THIS_MODULE,

.open    = fnd_open, 

// .release = fnd_release, 

// .read    = fnd_read,

// .write   = fnd_write,

.ioctl  = fnd_ioctl,

// .poll    = fnd_poll,

};


//------------------------------------------------------------------------------

// BUZZER 드라이버 등록 구조체

//------------------------------------------------------------------------------

static struct file_operations minor_buzzer_fops =

{

.owner = THIS_MODULE,

.open    = buzzer_open, 

// .release = buzzer_release, 

// .read    = buzzer_read,

// .write   = buzzer_write,

.ioctl   = buzzer_ioctl,

// .poll    = buzzer_poll,

};

---------------------------------------------------------------------------------


6. 이제 각각의 드라이버 등록 구조체에 선언된 함수들을 구현 해 주면 됩니다.

이중에서 open,release,read,write,poll 은 사용 하지 않으므로 그냥 주석처리 해도 동작에 문제는 없습니다.

따라서 iotcl 함수만 각각 구현해 주면 됩니다.


//------------------------------------------------------------------------------

// BUZZER 드라이버 ioctl

//------------------------------------------------------------------------------

static int buzzer_ioctl( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg )

{

unsigned char u8val;


switch(cmd)

{

case IOCTL_BZR_OUT :  

if(copy_from_user( &u8val, (void *)arg, sizeof(unsigned char) ))printk("copy_from_user error ! \n");

bzr_out(u8val );

return 0;

}


return -EINVAL;

}


7. 어플리케이션에서 open 하기

어플리케이션 에서는 마이너 번호로 open 할 것이기 때문에 두개의 드라이버 파일 포인터가 필요합니다.

--------------------------------------------------------------------------

int  fnd_dev_fd;

int  buzzer_dev_fd;

--------------------------------------------------------------------------


그리고 , open 할때 아래와 같이 마지막에 마이넌 번호를 넣어 주어야 합니다.

이 번호가 위에서 설명한  filp->f_op 값으로 넘어 가므로 해당 디바이스의 마이너 번호를 잘 확인해야 합니다.

-------------------------------------------------------------------------------------

fnd_dev_fd = dev_open( FND_DEVICE_FILENAME, DEV_DRIVER_MAJOR,1);

buzzer_dev_fd = dev_open( BUZZER_DEVICE_FILENAME, DEV_DRIVER_MAJOR,2);

-------------------------------------------------------------------------------------

실제 드라이버를 open 하는 함수(dev_open)는 아래와 같으며, 자세히 보면 마이너 번호 mknod 로 마이너 번호의

디바이스를 따로 생성해 주는 것을 볼 수 있습니다.

fnd_dev_fd = dev_open( FND_DEVICE_FILENAME, DEV_DRIVER_MAJOR,1); 이런식으로 하지 않고 아래 함수를

직접 풀어서 사용해도 무방하나 사용상 편의를 위해 dev_open 함수를 별도로 만들어 사용 합니다.

-----------------------------------------------------------------------------------------------------

int dev_open( char *fname, unsigned char major, unsigned char minor )

{

int dev;

dev = open( fname, O_RDWR|O_NDELAY );

if (dev < 0 )

{

if( access( fname, F_OK ) == 0 ) 

{

unlink( fname );

}

mknod( fname, (S_IRWXU|S_IRWXG|S_IFCHR), MKDEV(major,minor) );

dev = open( fname, O_RDWR|O_NDELAY );

if (dev < 0 )

{

printf( " Device OPEN FAIL %s\n", fname );

return -1;

}

}

        

return dev;

}

----------------------------------------------------------------------------------------------------



8. 어플리케이션 에서 사용하기

이제 하나의 메이저아래 두개의 마이너번호로 등록된 두개의 드라이버를 각각 따로 사용 할 수 있습니다.

-----------------------------------------------------------------------------------------------------


ioctl( fnd_dev_fd, IOCTL_FND_OUT, &param );

ioctl( buzzer_dev_fd, IOCTL_BZR_OUT, &command );


-----------------------------------------------------------------------------------------------------


물론 이 드라이버는 구분이 되기 때문에 fnd 와 buzzer 를 각각 따로 open 해서 사용 할 수 있습니다.


실제 타겟 보드에서 이 드라이버를 확인해보면 아래와 같습니다.

-----------------------------------------------------------------------------------

[root@falinux driver]$ cd /dev

[root@falinux dev]$ ll

crwxr-x---    1 root     root     203,   1 Jan  1 07:13 fnd

crwxr-x---    1 root     root     203,   2 Jan  1 07:07 buzzer

------------------------------------------------------------------------------------

이처럼 203 이라는 메이저번호에 1,2 번으로 마이너 번호를 갖는 두개의 드라이버가 올려진 것을 확인 할 수 있습니다.