msm8909 模块android 驱动编写

sc20_gpio.c

```
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/types.h>
#include <asm/gpio.h>
#include <mach/gpio.h>
#include <linux/slab.h>
#include <linux/miscdevice.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include<linux/delay.h>
#include <asm/errno.h>
#include <asm-generic/gpio.h>           /* cansleep wrappers */
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/sched.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
#include <linux/platform_device.h>
#include <linux/workqueue.h>
#include <linux/of_platform.h>
#include <linux/of_gpio.h>
#include <linux/spinlock.h>
#include <linux/pinctrl/consumer.h>


#define DEVICE_NAME "sc20_gpio"
#define USE_MSG_LEV KERN_ERR
#define IOCTL_WR  _IO(10, 0)
#define IOCTL_RD  _IO(10, 1)


typedef struct 
{
    u32 pin;
    u32 val;

}USER_DATA;



int gpio_data=0;
static long sc20_gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{

    USER_DATA usr_data;
    if(copy_from_user(&usr_data,(void __user *)arg,sizeof(USER_DATA))==0)
    {
        if(cmd == IOCTL_WR) //write
        {   

        gpio_set_value(gpio_data, usr_data.val);
        printk(USE_MSG_LEV "gpio write:%d \n",usr_data.val);

        }
        else if(cmd == IOCTL_RD) //read
        {
            usr_data.val = gpio_get_value(gpio_data);
            if(copy_to_user(&arg,&usr_data,sizeof(USER_DATA))==0)
            {
              printk(USE_MSG_LEV "gpio read:%d \n",usr_data.val);
            }
            else
            {
                printk(USE_MSG_LEV "copy_to_user eror \n");
            }
        }
        else
        {
            printk(USE_MSG_LEV "in kgpio illegal cmd\n");
        }
    }
    else
    {
        printk(USE_MSG_LEV "copy_from_user eror \n");
    }
    return 0;
}

static ssize_t sc20_gpio_read(struct file *filp, char *buf, size_t count, loff_t *f_pos)
{
    return 0;
}

static ssize_t sc20_gpio_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
    return 0;
}

static int sc20_gpio_release(struct inode *inode, struct file *filp)
{
    return 0;
}

/*文件操作结构体*/
static struct file_operations sc20_gpio_fops = {
    .owner = THIS_MODULE,
    .unlocked_ioctl = sc20_gpio_ioctl,
    .write = sc20_gpio_write,
    .read =  sc20_gpio_read,
    .release = sc20_gpio_release,
    //.open = sc20_gpio_open,
};

/*misc设备结构体初始化*/
static struct miscdevice misc = {
    .minor = MISC_DYNAMIC_MINOR,
    .name = DEVICE_NAME,
    .fops = &sc20_gpio_fops,
};







int gpio_intit(struct platform_device *pdev)
{
    struct device *dev = &pdev->dev;
    struct device_node *node=dev->of_node;
    int error=0;
    enum of_gpio_flags flags;
    const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev);
    if (!pdata) 
    {
        gpio_data = of_get_gpio_flags(node, 0, &flags);
        if (gpio_is_valid(gpio_data)) 
        {
            error = gpio_request_one(gpio_data, GPIOF_OUT_INIT_HIGH, "net_led");
            if (error < 0)
            {
                dev_err(dev, "Failed to request GPIO %d, error %d\n",gpio_data, error);
                return error;
            }
        }
        gpio_set_value(gpio_data,1);
    }
    return error;
}



static int sc20_gpio_probe(struct platform_device *pdev)
{
    int ret;
    gpio_intit(pdev);
    ret = misc_register(&misc);
    if(ret)
    {
         printk(USE_MSG_LEV "%s register fail\n", DEVICE_NAME);
         //goto err_free_gpios;
    }   
    printk(USE_MSG_LEV "%s register success\n", DEVICE_NAME);
    return ret;
}

static int sc20_gpio_remove(struct platform_device *pdev)
{
    misc_deregister(&misc);
    return 0;

}


static struct of_device_id sc20_gpio_of_match[] = 
{
    { .compatible = "gpio-outs", },
    { },
};


MODULE_DEVICE_TABLE(of, sc20_gpio_of_match);


static struct platform_driver gpio_keys_device_driver = {
    .probe      = sc20_gpio_probe,
    .remove     = sc20_gpio_remove,
    .driver     = {
        .name   = "gpio-outs",
        .owner  = THIS_MODULE,
        //.pm   = &sc20_gpio_pm_ops,
        .of_match_table = of_match_ptr(sc20_gpio_of_match),
    }
};

#if 0
 void test_for_pin(void)
{
    struct device_node *node,*pp;
    int nbuttons;
    int code;
    const char *desc;
    int gpio;
    node=of_find_compatible_node(NULL,NULL, "gpio-keys");//找到dts中compatible为 "gpio-keys"的节点返回
    printk(KERN_INFO"%d",of_device_is_compatible(node,"gpio-keys"));
    nbuttons = of_get_child_count(node);//算出此节点下面共有多少节点
    printk(KERN_INFO"of_get_child_count: %d\n",nbuttons);

    for_each_child_of_node(node, pp) //遍历每个子节点
    {

        enum of_gpio_flags flags;

        if (!of_find_property(pp, "gpios", NULL)) //子节点里是否包含"gpios" 属性
        {
        printk(KERN_INFO"Found button without gpios\n");
        continue;
        }

        gpio = of_get_gpio_flags(pp, 0, &flags);
        printk(KERN_INFO"of_get_gpio_flags(pp, 0, &flags): %d\n",gpio);

        of_property_read_u32(pp, "linux,code", &code); //读取属性名为"linux,code"属性的节点整形值
        printk(KERN_INFO"of_property_read_u32(pp, \"linux,code\", &code);%d\n",code);

        desc = of_get_property(pp, "label", NULL);//读取属性名为"label"
        printk(KERN_INFO"of_get_property(pp, \"label\", NULL);%s\n",desc);


    }
}
 #endif
static int __init sc20_gpio_init(void)
{
     printk(USE_MSG_LEV "%s sc20_gpio_init\r\n", DEVICE_NAME);
     //test_for_pin();

     return platform_driver_register(&gpio_keys_device_driver);
}

static void __exit sc20_gpio_exit(void)
{
    platform_driver_unregister(&gpio_keys_device_driver);
}

module_init(sc20_gpio_init);
module_exit(sc20_gpio_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("xuliang");

makefile

project=test
curren_dir=$(shell pwd)
build_dir=/code/android/out/target/product/msm8909/obj/KERNEL_OBJ

obj-m+=sc20_gpio.o
VERSION = 3
PATCHLEVEL = 10
SUBLEVEL = 49
EXTRAVERSION =""
CFLAGS_MODULE=-fno-pic


all:
    $(MAKE) -C $(build_dir) M=$(curren_dir) modules ARCH=arm CROSS_COMPILE=arm-linux-androidkernel-
    perl /code/android/kernel/scripts/sign-file sha512 $(build_dir)/signing_key.priv $(build_dir)/signing_key.x509 /code/driver_debug/sc20_gpio/sc20_gpio.ko 
    echo ok
clean:
    rm *.o *.ko 

设备树中添加

    gpio-outs {
        compatible = "gpio-outs";
        input-name = "gpio-outs";       
        gpios = <&msm_gpio 99 0x0>;
        debounce-interval = <15>;
    };

说明:
CFLAGS_MODULE=-fno-pic 解决insmod 时 Exec format error,由于andriod引入了数字签名所似生成ko后要手动加入签名
perl /code/android/kernel/scripts/sign-file sha512 (builddir)/signingkey.priv ( b u i l d d i r ) / s i g n i n g k e y . p r i v (build_dir)/signing_key.x509 /code/driver_debug/sc20_gpio/sc20_gpio.ko ,执行hexdump -C hello.ko | tail查看签名
JNI调用源码

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值