本篇主要讲在Android系统中的linux下控制GPIO的方法,android 通过jni控制GPIO可基于本篇内容继续开展;
linux控制GPIO基本上有两种方法,一是通过pinctrl体系,直接使用/sys下的文件进行控制,另一种就是编写驱动,在驱动中进行控制,下面分别进行介绍:
一、是用sys文件系统控制(更深入的介绍请移步:
http://blog.chinaunix.net/uid-27717694-id-3701921.html);
二、编写驱动(rk3128为例,转载自:
http://developer.t-firefly.com/forum.php?mod=viewthread&tid=2436&highlight=gpio)
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
static struct UserData{
int gpio;
int state;
};
static struct of_device_id luobogpio_of_match[] = {
{ .compatible = "luobogpio" },
{ }
};
MODULE_DEVICE_TABLE(of, luobogpio_of_match);
static int luobogpio_open(struct inode *inode, struct file *filp)
{
printk("luobogpio_open\n");
return 0;
}
static ssize_t luobogpio_read(struct file *filp, char __user *ptr, size_t size, loff_t *pos)
{
if (ptr == NULL)
printk("%s: user space address is NULL\n", __func__);
return sizeof(int);
}
static long luobogpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
long ret = 0;
struct UserData userdata;
unsigned char label[10];
printk("luobogpio_ioctl: cmd = %d arg = %ld\n",cmd, arg);
switch (cmd){
case 0:
printk("gpio_request\n");
if (copy_from_user((void*)&userdata,(void __user *)arg, sizeof(struct UserData)))
return -EFAULT;
printk("copy_from_user gpio=%d ,state=%d\n",userdata.gpio,userdata.state);
sprintf(label,"gpio-%d",userdata.gpio);
printk("----->%s\n",label);
ret = gpio_request(userdata.gpio, label);
if (ret) {
printk("failed to request GPIO%d for you ret:%d\n",userdata.gpio,ret);
}
break;
case 1:
printk("gpio_direction_output\n");
if (copy_from_user((void*)&userdata,(void __user *)arg, sizeof(struct UserData)))
return -EFAULT;
printk("copy_from_user gpio=%d ,state=%d\n",userdata.gpio,userdata.state);
ret=gpio_direction_output(userdata.gpio, userdata.state);
if (ret) {
printk("failed to gpio_direction_output for you ret:%d\n",userdata.gpio);
}
break;
case 5:
printk("gpio_free\n");
if (copy_from_user((void*)&userdata,(void __user *)arg, sizeof(struct UserData)))
return -EFAULT;
printk("copy_from_user gpio=%d ,state=%d\n",userdata.gpio,userdata.state);
gpio_free(userdata.gpio);
break;
default:
printk("unknown ioctl cmd!\n");
ret = -EINVAL;
break;
}
return ret;
}
static int luobogpio_release(struct inode *inode, struct file *filp)
{
printk("luobogpio_release\n");
return 0;
}
static struct file_operations luobogpio_fops = {
.owner = THIS_MODULE,
.open = luobogpio_open,
.read = luobogpio_read,
.unlocked_ioctl = luobogpio_ioctl,
.release = luobogpio_release,
};
static struct miscdevice luobogpio_dev =
{
.minor = MISC_DYNAMIC_MINOR,
.name = "luobogpio",
.fops = &luobogpio_fops,
};
static int luobogpio_probe(struct platform_device *pdev)
{
int ret=-1;
ret = misc_register(&luobogpio_dev);
if (ret < 0){
printk("ac_usb_switch register err!\n");
return ret;
}
printk("func: %s\n", __func__);
return 0;
}
static int luobogpio_remove(struct platform_device *pdev)
{
//printk("func: %s\n", __func__);
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int luobogpio_suspend(struct device *dev)
{
//printk("func: %s\n", __func__);
return 0;
}
static int luobogpio_resume(struct device *dev)
{
//printk("func: %s\n", __func__);
return 0;
}
#endif
static const struct dev_pm_ops luobogpio_pm_ops = {
#ifdef CONFIG_PM_SLEEP
.suspend = luobogpio_suspend,
.resume = luobogpio_resume,
.poweroff = luobogpio_suspend,
.restore = luobogpio_resume,
#endif
};
static struct platform_driver luogpio_driver = {
.driver = {
.name = "luobogpio",
.owner = THIS_MODULE,
.pm = &luobogpio_pm_ops,
.of_match_table = of_match_ptr(luobogpio_of_match),
},
.probe = luobogpio_probe,
.remove = luobogpio_remove,
};
module_platform_driver(luogpio_driver);
MODULE_DESCRIPTION("luobogpio Driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:luobogpio");