linux copy_from_user/copy_to_user

copy_from_user/copy_to_user:用于在用户地址空间和内核地址空间之间进行整段数据的拷贝。


gpio_misc.c:

#include <linux/module.h>	//MODULE_AUTHOR,MODULE_LICENSE
#include <linux/init.h>		//module_init,module_exit
#include <linux/fs.h>		//file_operations
#include <linux/miscdevice.h>	//misdevice
#include <asm/io.h>		//ioread32,iowrite32
#include "mmp_err.h"
#include "mmpf_i2cm.h"
#include "mmpf_system.h"
#include "mmpf_pio.h"
#include <linux/irq.h>
#include <linux/uaccess.h>

/*设备名称*/
#define DEVICE_NAME "gpio_access"

typedef struct port_value_struct {
	int port;
	int value;
} PORT_VALUE;

static PioCallBackFunc *gPIO_CallBackFunc[PIO_MAX_PIN_SIZE];
extern MMP_ERR MMPF_PIO_SetData(MMPF_PIO_REG piopin, MMP_UBYTE outputValue);
extern MMP_ERR MMPF_PIO_GetData(MMPF_PIO_REG piopin, MMP_UBYTE * returnValue);
extern MMP_ERR MMPF_PIO_EnableOutputMode(MMPF_PIO_REG piopin, MMP_BOOL bEnable);
extern MMP_ERR MMPF_PIO_EnableGpioMode(MMPF_PIO_REG piopin, MMP_BOOL bEnable);
extern MMP_ERR MMPF_PIO_EnableInterrupt(MMPF_PIO_REG piopin, MMP_BOOL bEnable, MMP_ULONG boundingTime, PioCallBackFunc *CallBackFunc);

static int gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
//      printk("cmd=%d,arg=%d\n", cmd, arg);

	switch (cmd)
	  {
	  case 'r':		//read
		  {
			  /* MMP_UBYTE value;
			     MMPF_PIO_GetData((MMPF_PIO_REG)62, &value);
			     printk("charger value is %d\n", value);
			     put_user(value, (int __user *)arg); */
			  PORT_VALUE port_value ;
			  if (copy_from_user(&port_value, (PORT_VALUE *)arg, sizeof(PORT_VALUE)))
			    {
				    printk("copy_from_user failed.\n");
				    return -EFAULT;
			    }
			  MMPF_PIO_EnableGpioMode(port_value.port,1);
			  MMPF_PIO_EnableOutputMode((MMPF_PIO_REG)port_value.port,0);  
			  MMPF_PIO_GetData((MMPF_PIO_REG) port_value.port, &port_value.value);
			  printk("read: port=%d,value=%d\n", port_value.port, port_value.value);
			  //put_user(value, (int __user *)arg);
			  if (copy_to_user((PORT_VALUE *)arg, &port_value, sizeof(PORT_VALUE)))
			    {
				    printk("copy_to_user failed.\n");
				    return -EFAULT;
			    }

			  return 0;
		  }
	  case 'w':		//write
		  {
			  PORT_VALUE port_value;
			  if (copy_from_user(&port_value, (PORT_VALUE *)arg, sizeof(PORT_VALUE)))
			    {
				    printk("copy_from_user failed.\n");
				    return -EFAULT;
			    }

			  printk("write: port=%d,value=%d\n", port_value.port, port_value.value);
			  MMPF_PIO_EnableGpioMode(port_value.port,1);
			  MMPF_PIO_EnableOutputMode((MMPF_PIO_REG)port_value.port,1);  
			  MMPF_PIO_SetData((MMPF_PIO_REG) port_value.port, (MMP_BOOL) port_value.value);
		  }
		  return 0;
	 case 'i':
	 	{
		PORT_VALUE *port_value = arg; //the value should be 1(enable) or 0(disable)

		if(0 == port_value->value)
		MMPF_PIO_EnableOutputMode((MMPF_PIO_REG)port_value->port,0);  

		MMPF_PIO_EnableInterrupt(port_value->port, port_value->value, 0, 0);
		printk("port_value %d %d\n",port_value->port, port_value->value);
		return 0;
	 
	 	}

	  default:
		  return -EINVAL;
	  }
	return 0;
}

static struct file_operations dev_fops = {
	.owner = THIS_MODULE,
	.unlocked_ioctl = gpio_ioctl,	//定义的ioctl函数
};

static struct miscdevice misc = {
	.minor = MISC_DYNAMIC_MINOR,	//动态分配次设备号
	.name = DEVICE_NAME,	//设备名称
	.fops = &dev_fops,
};

/*模块初始化*/
static int __init dev_init(void)
{
	int ret;

	ret = misc_register(&misc);
	printk(DEVICE_NAME "\tinitialized.\n");

	return ret;
}

static void __exit dev_exit(void)
{
//卸载
	printk(DEVICE_NAME "\texit.\n");
	misc_deregister(&misc);
}

module_init(dev_init);
module_exit(dev_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("luke");


gpio_reg.c:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>

#define DEV_NAME "/dev/gpio_access"

typedef struct port_value_struct {
	int port;
	int value;
} PORT_VALUE;

void write_gpio(int port, int value)
{
	int fd;
	PORT_VALUE port_value;
	fd = open(DEV_NAME, O_RDONLY);
	if (fd < 0)
	  {
		  printf("gpio_access open fail\n");
		  return;
	  }

	port_value.port = port;
	port_value.value = value;

	printf("write_gpio():port=%d,value=%d\n", port, value);

	if (ioctl(fd, 'w', &port_value) < 0)
	  {
		  printf("ioctl w error\n");

	  }
	close(fd);
}

void interrupt_gpio(int port, int value)
{
	int fd;
	PORT_VALUE port_value;
	fd = open(DEV_NAME, O_RDONLY);
	if (fd < 0)
	  {
		  printf("gpio_access open fail\n");
		  return;
	  }

	port_value.port = port;
	port_value.value = value;

	printf("interrupt_gpio():port=%d,value=%d\n", port, value);

	if (ioctl(fd, 'i', &port_value) < 0)
	  {
		  printf("ioctl i error\n");

	  }
	close(fd);
}

void read_gpio(int port)
{
	int fd;
	PORT_VALUE port_value;
	port_value.port = port;
	fd = open(DEV_NAME, O_RDONLY);
	if (fd < 0)
	  {
		  printf("gpio_access open fail\n");
		  return;
	  }
	if (ioctl(fd, 'r', &port_value) < 0)
	  {
		  printf("ioctl r error\n");
		  close(fd);
		  return;
	  }

	printf("read_gpio():port=%d,value=%d\n", port, port_value.value);
	close(fd);
}

void usage(char *cmd)
{
	printf("*****luke gpio_reg V1.1*************\n");
	printf("Usage: %s r <port> - read value of the port\n", cmd);
	printf("       %s w <port> <value>- write value to the port\n", cmd);
	printf("       %s i <port> <value>- enable/disable interrupt of the port\n", cmd);
	printf("eg:ds1302_reg r 62\n");
	printf("   ds1302_reg w 62 1\n");
	printf("   ds1302_reg i 62 1\n");
	printf("\n");
}

void main(int argc, char *argv[])
{
//printf("argc=%d",argc);
	if (argc < 2)
	  {
		  usage(argv[0]);
		  return;
	  }

	if (argv[1][0] != 'r' && argv[1][0] != 'w' && argv[1][0] != 'i')
	  {
		  usage(argv[0]);
		  return;
	  }

	if ((argv[1][0] == 'r' && argc != 3))
	  {
		  usage(argv[0]);
		  return;
	  }

	if (argv[1][0] == 'w' && argc != 4)
	  {
		  usage(argv[0]);
		  return;
	  }

	if (argv[1][0] == 'i' && argc != 4)
	  {
		  usage(argv[0]);
		  return;
	  }

	switch (argv[1][0])
	  {
	  case 'r':
		  read_gpio(strtoul(argv[2], NULL, 10));
		  break;
	  case 'w':
		  write_gpio(strtoul(argv[2], NULL, 10), strtoul(argv[3], NULL, 10));
		  break;
	  case 'i':
		  interrupt_gpio(strtoul(argv[2], NULL, 10), strtoul(argv[3], NULL, 10));
		  break;
	  }

}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值