1. 程式人生 > >Linux系統ioctl使用示例 ioctl實驗

Linux系統ioctl使用示例 ioctl實驗

    本文是我在andoid實驗的ioctl的功能,如雙向傳遞引數。貼出來希望對學習ioctl的人很有幫助。
    linux的ioctl功能是很強大的,android顯示模組還有camera模組都離不開ioctl讓上層和核心互動。

這個實驗對初學者很有幫助的。


board中新增platform_devce
static struct ioctl_test_platform_data ioctl_pdata = {
        static struct ioctl_test_platform_data ioctl_pdata = {
        .gpio=17,
};

static struct platform_device msm_device_ioctl = {
    .name    = "gpio_test",
    .id        = -1,
    .dev    = {
        .platform_data = &ioctl_pdata,
    },
};


標頭檔案:
ioctl_test.h

#ifndef IOCTL_TEST_H
#define IOCTL_TEST_H


/* platform data from board file */
struct ioctl_test_platform_data{
    u16 gpio;
};

struct gpio_priv_t {
    
    int gpio;
    int state0;
    int state1;
    int state2;
    int state3;
    
};

#define GPIO_TEST_IOC_MAGIC          0x92

#define GPIO_TEST_SET_HIGH          _IO(GPIO_TEST_IOC_MAGIC, 1)
#define GPIO_TEST_SET_LOW           _IO(GPIO_TEST_IOC_MAGIC, 2)

#define GPIO_TEST_WRITE_STRUCT           _IOW(GPIO_TEST_IOC_MAGIC, 3,struct gpio_priv_t *)
#define GPIO_TEST_WRITE_INT         _IOW(GPIO_TEST_IOC_MAGIC, 4,unsigned int *)

#define GPIO_TEST_READ_STRUCT          _IOR(GPIO_TEST_IOC_MAGIC, 5,struct gpio_priv_t *)
#define GPIO_TEST_READ_INT          _IOR(GPIO_TEST_IOC_MAGIC, 6,unsigned int *)




#endif




driver:
生成裝置節點:/dev/gpio_test
ioctl_test.c

#define pr_fmt(fmt) "%s: " fmt, __func__

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/uaccess.h>
#include <linux/regulator/consumer.h>
#include <linux/platform_device.h>
#include <linux/mutex.h>
#include <mach/gpio.h>
#include<linux/ioctl_test.h>


static struct gpio_priv_t *gpio_priv;


static int gpio_test_open(struct inode *inode, struct file *filp)
{
    if (gpio_priv == NULL)
        return -ENODEV;

    filp->private_data = gpio_priv;

    return 0;
}

static int gpio_test_release(struct inode *inode, struct file *filp)
{

    filp->private_data = NULL;

    return 0;
}


static long
gpio_test_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
    int err = 0;
    void __user *argp = (void __user *)arg;
    int value0;
    int value1 ;
    

    /* Verify user arguments. */
    if (_IOC_TYPE(cmd) != GPIO_TEST_IOC_MAGIC)
        return -ENOTTY;

    switch (cmd) {
    case GPIO_TEST_SET_HIGH:
        printk("GPIO_TEST_SET_HIGH\n");
        if (arg == 0) {
            pr_err("user space arg not supplied\n");
            err = -EFAULT;
            break;
        }
        gpio_set_value(17,1);

        break;

    case GPIO_TEST_SET_LOW:
        printk("GPIO_TEST_SET_LOW\n");
        if (arg == 0) {
            pr_err("user space arg not supplied\n");
            err = -EFAULT;
            break;
        }
        gpio_set_value(17,0);

        break;

    case GPIO_TEST_WRITE_STRUCT:
        printk("GPIO_TEST_WRITE\n");
        if (copy_from_user(gpio_priv, argp, sizeof(struct gpio_priv_t)))
            return -EFAULT;
        printk("gpio_priv->state0=%d\n",gpio_priv->state0);
        printk("gpio_priv->state1=%d\n",gpio_priv->state1);
        printk("gpio_priv->state2=%d\n",gpio_priv->state2);

        break;

    case GPIO_TEST_READ_STRUCT:
        printk("GPIO_TEST_READ\n");
        gpio_priv->state0=1;
        gpio_priv->state1=2;
        gpio_priv->state2=3;
        if (copy_to_user(argp, gpio_priv, sizeof(struct gpio_priv_t)))
            return -EFAULT;

        break;
        
    case GPIO_TEST_WRITE_INT:
        printk("GPIO_TEST_WRITE_INT\n");
        if(copy_from_user(&value0,argp,sizeof(int)))
            return -EFAULT;
        printk("value0 = %d\n",value0);
        break;

    case GPIO_TEST_READ_INT:
        printk("GPIO_TEST_READ_INT\n");
        value1=101;
        if (copy_to_user(argp, &value1, sizeof(int)))
            return -EFAULT;
        break;
        
    default:
        pr_err("Invalid ioctl command.\n");
        return -ENOTTY;
    }

    return err;
}

static const struct file_operations gpio_test_fops = {
    .owner = THIS_MODULE,
    .unlocked_ioctl = gpio_test_ioctl,
    .open = gpio_test_open,
    .release = gpio_test_release
};

static struct miscdevice gpio_test_dev = {
    .minor = MISC_DYNAMIC_MINOR,
    .name = "gpio_test",
    .fops = &gpio_test_fops
};


static int gpio_test_probe(struct platform_device *pdev)
{
    int ret = 0;

    printk("gpio_test_probe 0\n");
    
    /* Initialize */
    gpio_priv = kzalloc(sizeof(struct gpio_priv_t), GFP_KERNEL);

    if (gpio_priv == NULL) {
        pr_alert("Not enough memory to initialize device\n");
        return -ENOMEM;
    }

    ret = misc_register(&gpio_test_dev);
    
    if (ret < 0)
        goto err;
    return 0;

err:
    printk("gpio_test register failed\n");
    

    kfree(gpio_priv);
    gpio_priv = NULL;

    return ret;

}

static int __devexit gpio_test_remove(struct platform_device *plat)
{

    kfree(gpio_priv);
    gpio_priv = NULL;

    misc_deregister(&gpio_test_dev);
    printk("gpio_test remove\n");
    return 0;
}

static struct platform_driver gpio_test_driver = {
    .probe = gpio_test_probe,
    .remove = gpio_test_remove,
    .driver = {
        .name = "gpio_test",
        .owner = THIS_MODULE,
    },
};

static int __init gpio_test_init(void)
    
{
    printk("gpio_test_init  \n");
    return platform_driver_register(&gpio_test_driver);
}

static void __exit gpio_test_exit(void)
{
    platform_driver_unregister(&gpio_test_driver);
}



module_init(gpio_test_init);
module_exit(gpio_test_exit);

應用層:

ioctl_test_app.c

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <time.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>


struct gpio_priv_t {
    
    int gpio;
    int state0;
    int state1;
    int state2;
    int state3;
    
};

#define GPIO_TEST_IOC_MAGIC          0x92

#define GPIO_TEST_IOC_MAGIC          0x92

#define GPIO_TEST_SET_HIGH          _IO(GPIO_TEST_IOC_MAGIC, 1)
#define GPIO_TEST_SET_LOW           _IO(GPIO_TEST_IOC_MAGIC, 2)

#define GPIO_TEST_WRITE_STRUCT           _IOW(GPIO_TEST_IOC_MAGIC, 3,struct gpio_priv_t *)
#define GPIO_TEST_WRITE_INT         _IOW(GPIO_TEST_IOC_MAGIC, 4,unsigned int *)

#define GPIO_TEST_READ_STRUCT          _IOR(GPIO_TEST_IOC_MAGIC, 5,struct gpio_priv_t *)
#define GPIO_TEST_READ_INT          _IOR(GPIO_TEST_IOC_MAGIC, 6,unsigned int *)




static struct gpio_priv_t my_gpio;

int main(int argc, char *argv[])
{

    int ret = 0;
    
    int fp = 0;
    int prama;
    int prama0;
    prama=100;
    my_gpio.state0=4;
    my_gpio.state1=5;
    my_gpio.state2=6;

    printf("ioctl  test... ...\n");
    
    //open module
    if ((ret = (fp = open("/dev/gpio_test", O_RDWR))) < 0)
    {
        printf("ioctl test error retcode = %d\n", ret);
        exit(0);
    }

    
    ioctl(fp, GPIO_TEST_SET_LOW,1);
    ioctl(fp, GPIO_TEST_SET_HIGH,1);
    ioctl(fp, GPIO_TEST_SET_LOW,1);
    ioctl(fp, GPIO_TEST_WRITE_INT,&prama);
    ioctl(fp, GPIO_TEST_READ_INT,&prama0);
    printf("prama0=%d\n",prama0);
    ioctl(fp, GPIO_TEST_WRITE_STRUCT,&my_gpio);
    ioctl(fp, GPIO_TEST_READ_STRUCT,&my_gpio);
    printf("my_gpio.state0=%d\n",my_gpio.state0);
    printf("my_gpio.state1=%d\n",my_gpio.state1);
    printf("my_gpio.state2=%d\n",my_gpio.state2);
    return ret;

}

在android上實驗的
android.mk
#Android.mk //TODO:Here is makefile reference
LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)
LOCAL_SRC_FILES:= ioctl_test_app.c

LOCAL_MODULE_TAGS := eng optional

LOCAL_MODULE:= ioctl_app

include $(BUILD_EXECUTABLE)


編譯make ioctl_app -j4
adb remount
adb push ioctl_app /system/bin
adb shell
ioctl_app
msg:

使用者空間:
ioctl  test... ...
prama0=101
my_gpio.state0=1
my_gpio.state1=2
my_gpio.state2=3
核心:
<4>[   37.787128] GPIO_TEST_SET_LOW
<4>[   37.787908] GPIO_TEST_SET_HIGH
<4>[   37.787976] GPIO_TEST_SET_LOW
<4>[   37.788404] GPIO_TEST_WRITE_INT
<4>[   37.788469] value0 = 100
<4>[   37.788519] GPIO_TEST_READ_INT
<4>[   37.789478] GPIO_TEST_WRITE
<4>[   37.790193] gpio_priv->state0=4
<4>[   37.790256] gpio_priv->state1=5
<4>[   37.790668] gpio_priv->state2=6
<4>[   37.790733] GPIO_TEST_READ