驱动层
long led_ ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
/*fp 文件指针,cmd 命令,arg 数据
cmd 命令是一个 32 位数
从上层应用传过来的 arg 可能是数据也可能是指针
如果是应用层是指针,读的时候需要先转换成 数据 *((int *)arg)
*/
cmd | bit |
---|---|
0-7 | nr 功能码 |
8-15 | type 命令类型,模数 幻数 |
16-29 | size 数据尺寸 |
30-31 | dir 方向 |
{
int i=0;
if(_IOC_TYPE(cmd) != 'x') //_IOC_TYPE 取命令类型
return -EINVAL;
switch (_IOC_DIR(cmd)) //_IOC_DIR 取命令方向
{
case _IOC_READ:
for(i=0;i<MYLED_NUM;i++)
{
led_status[i] =! (rGPM4DAT&(0x1<<i));
}
if(copy_to_user((long*)arg,led_status,4))
return -EINVAL;
break;
case _IOC_WRITE:
if(_IOC_NR(cmd)==0) //_IOC_NR 取命令功能码
rGPM4DAT |= (0x1<<arg);
else if(_IOC_NR(cmd) == 1)
rGPM4DAT &= ~(0x1<<arg);
else
return -EINVAL;
break;
case (_IOC_WRITE|_IOC_READ):
{
for(i=0;i<MYLED_NUM;i++)
led_status[i]=! (rGPM4DAT&(0x1<<i));
switch (_IOC_NR(cmd))
{
case 0:
rGPM4DAT |= (0x1<<*((int *)arg));
break;
case 1:
rGPM4DAT &= ~(0x1<<*((int *)arg));
break;
default :
return -EINVAL;
break;
}
if(copy_to_user((long*)arg,led_status,MYLED_NUM))
return -EINVAL;
break;
}
case _IOC_NONE:
break;
default:
break;
}
return 0;
}
应用层
主要函数
static long ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include <sys/ioctl.h>
#define LED_ON _IOW('x',1,sizeof(long)) //_IOW(x,y,z) 合成一个驱动函数用的 cmd 命令,x:模数,幻数,命令类型 y:命令功能码 z:数据尺寸
//_IOW(x,y,z) write
//_IOR(x,y,z) read
#define LED_OFF _IOW('x',0,sizeof(long))
#define LED_R _IOR('x',0,sizeof(long))
#define LED_RW_OFF _IOWR('x',0,sizeof(long))
#define LED_RW_ON _IOWR('x',1,sizeof(long))
char led_status[4]={-1,-1,-1,-1};
void print(int fd)
{
int i=0;
read(fd,led_status,4);
for(i=0;i<4;i++)
{
printf("led[%d]:%s\n",i,led_status[i]?"on":"off");
}
lseek(fd,0,SEEK_SET);
}
int main(int argc,char *argv[])
{
int i;
int fd = open(argv[1],O_RDWR);
if(fd == -1)
{
printf("打开失败\n");
return 0;
}
print(fd);
lseek(fd,0,SEEK_SET);
for(i=0;i<4;i++)
{
ioctl(fd,LED_ON,i);
print(fd);
ioctl(fd,LED_R,&arg); //ioctl 读数据时,读入的形参使用指针
printf("ths value is %d \n",arg);
sleep(1);
ioctl(fd,LED_OFF,i);
print(fd);
sleep(1);
}
i=3;
ioctl(fd,LED_RW_ON,&i);
print(fd);
printf("the value is %d \n",i);
sleep(1);
i=3;
ioctl(fd,LED_RW_OFF,&i);
print(fd);
printf("the value is %d \n",i);
sleep(1);
read(fd,led_status,4);
print(fd);
close(fd);
return 0;
}