从底层驱动 到上层APP的流程(1)

2019-04-14 22:00发布



1. 如何在底层添加一个设备节点,并封装到JNI 供APP调用(framework servermanager&NDK) 以驱Camera旋转马达为例,Camera旋转马达的GPIO的拉高拉低与camera的上电下电一致,所以添加到camera的驱动下
暴露出接口给其他设备调用
EXPORT_SYMBOL(kdCISModulePowerOn);,驱动给出)
under path:      alps/kernel-3.10/drivers/misc/mediatek/mach/mt6735/land6735_65u_l1/camera/camera/kd_camera_hw.c



2. 接下我们要创建一个设备节点来访问这个旋转马达       2.1 仿照vibrator(振动马达)的驱动,新建一个camera_vibrator under path:  $: alps/kernel-3.10/drivers/misc/mediatek $:  makedir camera_vibrator
     2.2  添加一个camera_vibrator 的驱动文件 和一个make文件:           camera_vibrator.c 和 Makefile (copy vibrator下的文件并进行修改)  
camera_vibrator.c


/******************************************************************************
 * mt6575_vibrator.c - MT6575 Android Linux Vibrator Device Driver
 *
 * Copyright 2009-2010 MediaTek Co.,Ltd.
 *
 * DESCRIPTION:
 *     This file provid the other drivers vibrator relative functions
 *
 ******************************************************************************/

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define VERSION                            "v 0.1"
#define VIB_DEVICE                "camera_vibrator"

/******************************************************************************
Error Code No.
******************************************************************************/
#define RSUCCESS        0


//打开设备节点
static int cameravibrator_open(struct inode *inode, struct file *filp)
{
    printk("luobogpio_open ");
    return 0;
}
//读取设备节点
static ssize_t cameravibrator_read(struct file *filp, char __user *ptr, size_t size, loff_t *pos)
{
    if (ptr == NULL)
        printk("%s: user space address is NULL ", __func__);
    return sizeof(int);
}

// I/O口控制,执行具体操作
static long cameravibrator_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
    long ret = 0;    
    printk("luobogpio_ioctl: cmd = %d arg = %ld ",cmd, arg);
    switch (cmd){
    case 0:
        printk("gpio_request ");
        break;
     case 1:
         printk("gpio_direction_output ");
             break;
      case 3:
         printk("gpio_free ");
          break;
      default:
        printk("unknown ioctl cmd! ");
        ret = -EINVAL;
        break;
    }
    return ret;
}

#ifdef CONFIG_COMPAT
static long  cameravibrator_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg){
            return cameravibrator_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));           } #else
#define spidev_compat_ioctl NULL
#endif /* CONFIG_COMPAT */

//关闭,释放资源
static int cameravibrator_release(struct inode *inode, struct file *filp)
{
    printk("luobogpio_release ");
    return 0;
}

//注册设备点的操作(类似java里的上下文传递)
static const struct file_operations cameravibrator_fops = {
    .owner   = THIS_MODULE,
    .open    = cameravibrator_open,
    .read    = cameravibrator_read,
    .unlocked_ioctl   = cameravibrator_ioctl,
    .compat_ioctl = cameravibrator_compat_ioctl,
    .release = cameravibrator_release,
};

//注册设备节点
static struct miscdevice cameravibrator_dev = 
{
    .minor = MISC_DYNAMIC_MINOR,
    .name = "cameravibrator",
    .fops = &cameravibrator_fops,
};

static int vib_probe(struct platform_device *pdev)
{
    int ret=-1;
    ret = misc_register(&cameravibrator_dev);
    if (ret < 0){
        printk("ac_usb_switch register err! ");
        return ret;  }
        printk("func: %s ", __func__); 
        return 0;
}

static int vib_remove(struct platform_device *pdev)
{
   printk("[ vib_remove] vib_mod_init ");
    return 0;
}

static void vib_shutdown(struct platform_device *pdev)
{
   printk("[vib_shutdown] vib_mod_init ");
}
/******************************************************************************
Device driver structure
*****************************************************************************/ //注册设备
static struct platform_driver vibrator_driver = {
    .probe = vib_probe,
    .remove = vib_remove,
    .shutdown = vib_shutdown,
    .driver = {  .name = VIB_DEVICE,  .owner = THIS_MODULE, },
};

//注册驱动
static struct platform_device vibrator_device = {
    .name = VIB_DEVICE,
    .id = -1,
};

//初始化
static int cameravibrator_mod_init(void)
{
    s32 ret;
    printk("[camera vibrator] vib_mod_init ");
    ret = platform_device_register(&vibrator_device);
    if (ret != 0) {
      printk("[vibrator]Unable to register vibrator device (%d) ", ret);
      eturn ret;  }
    ret = platform_driver_register(&vibrator_driver);
    if (ret) {
      printk("[vibrator]Unable to register vibrator driver (%d) ", ret);
      return ret; }
    return RSUCCESS;
}

/******************************************************************************
 * vib_mod_exit  * DESCRIPTION:                PARAMETERS:    RETURNS:     NOTES:
 * Free the device driver !   None                  None            None  ******************************************************************************/

static void cameravibrator_mod_exit(void)
{
    printk("[vibrator]vib_mod_exit Done ");
}

module_init(cameravibrator_mod_init);
module_exit(cameravibrator_mod_exit);
MODULE_AUTHOR("MediaTek Inc.");
MODULE_DESCRIPTION("MTK Vibrator Driver (VIB)");
MODULE_LICENSE("GPL"); Makefile 文件如下

include $(srctree)/drivers/misc/mediatek/Makefile.custom
obj-y += camera_vibrator.o #obj-$(CONFIG_MTK_VIBRATOR) := camera_vibrator.o #obj-y += $(subst ",,$(CONFIG_MTK_PLATFORM))/(屏蔽)


3. 在当前目录下这个对Makefile.mt6735 、Makefile.custom、Makefile修改 添加 camera_vibrort
  Makefile.mt6735 :
 Makefile:
   4.编译    编译内核    $: make -j8 kernel 2>&1 | tee kernel.log(生成log,出错可以查看),为了检测是否生成对应的camera_vibrator.o        文件,你可以定位到out目录,执行 find -name camera_vibrator.o,或者到对应的目录下查看        under path:alps/out/target/product/land6735_65u_l1/obj/KERNEL_OBJ/drivers/misc/mediatek        打包bootimage       $:  make bootimage
  5.烧录bootimage      
  6. Boot Device 查看设备节点是否创建                cameravibrator设备节点已经创建,权限属于Root权限,在下一篇介绍如何得到全部权限



  1. 如何在底层添加一个设备节点,并封装到JNI 供APP调用(framework servermanager&NDK) 以驱Camera旋转马达为例,Camera旋转马达的GPIO的拉高拉低与camera的上电下电一致,所以添加到camera的驱动下
暴露出接口给其他设备调用
EXPORT_SYMBOL(kdCISModulePowerOn);,驱动给出)
under path:      alps/kernel-3.10/drivers/misc/mediatek/mach/mt6735/land6735_65u_l1/camera/camera/kd_camera_hw.c



2. 接下我们要创建一个设备节点来访问这个旋转马达       2.1 仿照vibrator(振动马达)的驱动,新建一个camera_vibrator under path:  $: alps/kernel-3.10/drivers/misc/mediatek $:  makedir camera_vibrator
     2.2  添加一个camera_vibrator 的驱动文件 和一个make文件:           camera_vibrator.c 和 Makefile (copy vibrator下的文件并进行修改)  
camera_vibrator.c


/******************************************************************************
 * mt6575_vibrator.c - MT6575 Android Linux Vibrator Device Driver
 *
 * Copyright 2009-2010 MediaTek Co.,Ltd.
 *
 * DESCRIPTION:
 *     This file provid the other drivers vibrator relative functions
 *
 ******************************************************************************/

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define VERSION                            "v 0.1"
#define VIB_DEVICE                "camera_vibrator"

/******************************************************************************
Error Code No.
******************************************************************************/
#define RSUCCESS        0


//打开设备节点
static int cameravibrator_open(struct inode *inode, struct file *filp)
{
    printk("luobogpio_open ");
    return 0;
}
//读取设备节点
static ssize_t cameravibrator_read(struct file *filp, char __user *ptr, size_t size, loff_t *pos)
{
    if (ptr == NULL)
        printk("%s: user space address is NULL ", __func__);
    return sizeof(int);
}

// I/O口控制,执行具体操作
static long cameravibrator_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
    long ret = 0;    
    printk("luobogpio_ioctl: cmd = %d arg = %ld ",cmd, arg);
    switch (cmd){
    case 0:
        printk("gpio_request ");
        break;
     case 1:
         printk("gpio_direction_output ");
             break;
      case 3:
         printk("gpio_free ");
          break;
      default:
        printk("unknown ioctl cmd! ");
        ret = -EINVAL;
        break;
    }
    return ret;
}

#ifdef CONFIG_COMPAT
static long  cameravibrator_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg){
            return cameravibrator_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));           } #else
#define spidev_compat_ioctl NULL
#endif /* CONFIG_COMPAT */

//关闭,释放资源
static int cameravibrator_release(struct inode *inode, struct file *filp)
{
    printk("luobogpio_release ");
    return 0;
}

//注册设备点的操作(类似java里的上下文传递)
static const struct file_operations cameravibrator_fops = {
    .owner   = THIS_MODULE,
    .open    = cameravibrator_open,
    .read    = cameravibrator_read,
    .unlocked_ioctl   = cameravibrator_ioctl,
    .compat_ioctl = cameravibrator_compat_ioctl,
    .release = cameravibrator_release,
};

//注册设备节点
static struct miscdevice cameravibrator_dev = 
{
    .minor = MISC_DYNAMIC_MINOR,
    .name = "cameravibrator",
    .fops = &cameravibrator_fops,
};

static int vib_probe(struct platform_device *pdev)
{
    int ret=-1;
    ret = misc_register(&cameravibrator_dev);
    if (ret < 0){
        printk("ac_usb_switch register err! ");
        return ret;  }
        printk("func: %s ", __func__); 
        return 0;
}

static int vib_remove(struct platform_device *pdev)
{
   printk("[ vib_remove] vib_mod_init ");
    return 0;
}

static void vib_shutdown(struct platform_device *pdev)
{
   printk("[vib_shutdown] vib_mod_init ");
}
/******************************************************************************
Device driver structure
*****************************************************************************/ //注册设备
static struct platform_driver vibrator_driver = {
    .probe = vib_probe,
    .remove = vib_remove,
    .shutdown = vib_shutdown,
    .driver = {  .name = VIB_DEVICE,  .owner = THIS_MODULE, },
};

//注册驱动
static struct platform_device vibrator_device = {
    .name = VIB_DEVICE,
    .id = -1,
};

//初始化
static int cameravibrator_mod_init(void)
{
    s32 ret;
    printk("[camera vibrator] vib_mod_init ");
    ret = platform_device_register(&vibrator_device);
    if (ret != 0) {
      printk("[vibrator]Unable to register vibrator device (%d) ", ret);
      eturn ret;  }
    ret = platform_driver_register(&vibrator_driver);
    if (ret) {
      printk("[vibrator]Unable to register vibrator driver (%d) ", ret);
      return ret; }
    return RSUCCESS;
}

/******************************************************************************
 * vib_mod_exit  * DESCRIPTION:                PARAMETERS:    RETURNS:     NOTES:
 * Free the device driver !   None                  None            None  ******************************************************************************/

static void cameravibrator_mod_exit(void)
{
    printk("[vibrator]vib_mod_exit Done ");
}

module_init(cameravibrator_mod_init);
module_exit(cameravibrator_mod_exit);
MODULE_AUTHOR("MediaTek Inc.");
MODULE_DESCRIPTION("MTK Vibrator Driver (VIB)");
MODULE_LICENSE("GPL"); Makefile 文件如下

include $(srctree)/drivers/misc/mediatek/Makefile.custom
obj-y += camera_vibrator.o #obj-$(CONFIG_MTK_VIBRATOR) := camera_vibrator.o #obj-y += $(subst ",,$(CONFIG_MTK_PLATFORM))/(屏蔽)


3. 在当前目录下这个对Makefile.mt6735 、Makefile.custom、Makefile修改 添加 camera_vibrort
  Makefile.mt6735 :
 Makefile:
   4.编译    编译内核    $: make -j8 kernel 2>&1 | tee kernel.log(生成log,出错可以查看),为了检测是否生成对应的camera_vibrator.o        文件,你可以定位到out目录,执行 find -name camera_vibrator.o,或者到对应的目录下查看        under path:alps/out/target/product/land6735_65u_l1/obj/KERNEL_OBJ/drivers/misc/mediatek        打包bootimage       $:  make bootimage
  5.烧录bootimage      
  6. Boot Device 查看设备节点是否创建                cameravibrator设备节点已经创建,权限属于Root权限,在下一篇介绍如何得到全部权限