Android IOCtrl使用[Driver + Jni]

1.驱动H结构体以及IOCTL接口定义

    #define XXX_IOCTL_MAGIC   	's'
    #define XXX_MAGIC			0xD0
    
    typedef struct _REG_CMD {
    	unsigned char addr;
    	unsigned char data;
    } REG_CMD;
    
    struct xxx_wreg_handle {
    	REG_CMD *regcmd;
    	int len;
    };
    
    struct xxx_wcram_handle{
    	int    dsp;
    	int    addr;
    	unsigned char *cram;
    	int    len;
    };
    
    #define XXX_IOCTL_SETSTATUS		_IOW(XXX_MAGIC, 0x10, int)
    #define XXX_IOCTL_SETMIR		_IOW(XXX_MAGIC, 0x12, int)
    #define XXX_IOCTL_GETMIR		_IOR(XXX_MAGIC, 0x13, unsigned long)
    #define XXX_IOCTL_WRITEREG		_IOW(XXX_MAGIC, 0x14, struct xxx_wreg_handle)
    #define XXX_IOCTL_WRITECRAM		_IOW(XXX_MAGIC, 0x15, struct xxx_wcram_handle)

2. 驱动C接口注册

 #include 
    #include 
    #include 
    
    struct _xxx_pd_handler {
    	int ref_count;
    	struct mutex lock;
    	struct xxx_priv *data;
    } xxx_pd_handler = {
    	.ref_count = -1,
    	.data = NULL,
    };
    
    static long xxx_ioctl(struct file *file, unsigned int cmd, unsigned long args)
    {
    	struct xxx_priv *xxx = (struct xxx_priv*)file->private_data;
    	struct xxx_wreg_handle xxx_wreg;
    	struct xxx_wcram_handle  xxx_wcram;
    	void __user *data = (void __user *)args;
    	int *val = (int *)args;
    	int i;
    	unsigned long dwMIRData;
    	int ret = 0;
    	REG_CMD      regcmd[MAX_WREG];
    	unsigned char cram_data[MAX_WCRAM];
    	switch(cmd) {
    	case XXX_IOCTL_WRITECRAM:
    		if (copy_from_user(&xxx_wcram, data, sizeof(struct xxx_wcram_handle)))
    			return -EFAULT;
    		if ( (  xxx_wcram.len % 3 ) != 0 ) {
    			printk(KERN_ERR "[xxx] %s CRAM len error\n",__FUNCTION__);
    			return -EFAULT;
    		}
    		if ( ( xxx_wcram.len < 3 ) || ( xxx_wcram.len > MAX_WCRAM ) ) {
    			printk(KERN_ERR "[xxx] %s CRAM len error2\n",__FUNCTION__);
    			return -EFAULT;
    		}
    		for ( i = 0 ; i < xxx_wcram.len ; i ++ ) {
    			cram_data[i] = xxx_wcram.cram[i];
    		}
    		ret = xxx_write_cram(xxx->codec, xxx_wcram.dsp, xxx_wcram.addr, xxx_wcram.len, cram_data);
    		break;
    	case XXX_IOCTL_WRITEREG:
    		if (copy_from_user(&xxx_wreg, data, sizeof(struct xxx_wreg_handle)))
    			return -EFAULT;
    		if ( ( xxx_wreg.len < 1 ) || ( xxx_wreg.len > MAX_WREG ) ) {
    			printk(KERN_ERR "MAXREG ERROR %d\n", xxx_wreg.len );
    			return -EFAULT;
    		}
    		for ( i = 0 ; i < xxx_wreg.len; i ++ ) {
    			regcmd[i].addr = xxx_wreg.regcmd[i].addr;
    			regcmd[i].data = xxx_wreg.regcmd[i].data;
    		}
    		xxx_reg_cmd(xxx->codec, regcmd, xxx_wreg.len);
    		break;	
    	case XXX_IOCTL_SETSTATUS:
    		ret = xxx_set_status(xxx->codec, val[0]);
    		if (ret < 0) {
    			printk(KERN_ERR "xxx: set_status error: \n");
    			return ret;
    		}
    		break;
    	case XXX_IOCTL_SETMIR:
    		xxx->MIRNo = val[0];
    		if (ret < 0) {
    			printk(KERN_ERR "xxx: set MIR error\n");
    			return -EFAULT;
    		}
    		break;
    	case XXX_IOCTL_GETMIR:
    		XXX_readMIR(xxx->codec, (xxx->MIRNo/16), (0xF & (xxx->MIRNo)), &dwMIRData);
    		ret = copy_to_user(data, (const void*)&dwMIRData, (unsigned long)4);
    		if (ret < 0) {
    			printk(KERN_ERR "xxx: get status error\n");
    			return -EFAULT;
    		}
    		break;
    		break;
    	default:
    		printk(KERN_ERR "Unknown command required: %d\n", cmd);
    		return -EINVAL;
    	}
    
    	return ret;
    }
    
    static int init_xxx_pd(struct xxx_priv *data)
    {
    	struct _xxx_pd_handler *xxx = &xxx_pd_handler;
    
    	if (data == NULL)
    		return -EFAULT;
    
    	mutex_init(&xxx->lock);
    
    	mutex_lock(&xxx->lock);
    	xxx->data = data;
    	mutex_unlock(&xxx->lock);
    
    	printk("data:%p, xxx->data:%p\n", data, xxx->data);
    
    	return 0;
    }
    
    static struct xxx_priv* get_xxx_pd(void)
    {
    	struct _xxx_pd_handler *xxx = &xxx_pd_handler;
    
    	if (xxx->data == NULL)
    		return NULL;
    
    	mutex_lock(&xxx->lock);
    	xxx->ref_count++;
    	mutex_unlock(&xxx->lock);
    
    	return xxx->data;
    }
    
    static int rel_xxx_pd(struct xxx_priv *data)
    {
    	struct _xxx_pd_handler *xxx = &xxx_pd_handler;
    
    	if (xxx->data == NULL)
    		return -EFAULT;
    
    	mutex_lock(&xxx->lock);
    	xxx->ref_count--;
    	mutex_unlock(&xxx->lock);
    
    	data = NULL;
    
    	return 0;
    }
    
    /* xxx Misc driver interfaces */
    static int xxx_open(struct inode *inode, struct file *file)
    {
    	struct xxx_priv *xxx;
    
    	xxx = get_xxx_pd();
    	file->private_data = xxx;
    
    	return 0;
    }
    
    static int xxx_close(struct inode *inode, struct file *file)
    {
    	struct xxx_priv *xxx = (struct xxx_priv*)file->private_data;
    
    	rel_xxx_pd(xxx);
    
    	return 0;
    }
    
    /*dev设备文件操作*/
    static const struct file_operations xxx_fops = {
    	.owner = THIS_MODULE,
    	.open = xxx_open,
    	.release = xxx_close,
    	.unlocked_ioctl = xxx_ioctl,
    };
    
    static struct miscdevice xxx_misc = {
    	.minor = MISC_DYNAMIC_MINOR,
    	.name = "xxx-ioctrl",
    	.fops = &xxx_fops,
    };
    
    static int __init xxx_modinit(void)
    {
    	int ret = 0;
    	/*注册dev ioctrl设备节点*/
    	ret = misc_register(&xxx_misc);
    	if (ret < 0) {
    		printk(KERN_ERR "Failed to register XXX MISC driver: %d\n",  ret);
    	}
    }
    static void __exit xxx_exit(void)
    {
    	misc_deregister(&xxx_misc);
    }

3. JNI API接口.

 #include 
    #include 
    #include 
    
    #include 
    #include 
    #include 
    
    #define XXX_IOCTL_MAGIC   	's'
    #define XXX_MAGIC			0xD0
    
    typedef struct _REG_CMD {
    	unsigned char addr;
    	unsigned char data;
    } REG_CMD;
    
    struct xxx_wreg_handle {
    	REG_CMD *regcmd;
    	int len;
    };
    
    struct xxx_wcram_handle{
    	int    dsp;
    	int    addr;
    	unsigned char *cram;
    	int    len;
    };
    
    #define XXX_IOCTL_SETSTATUS		_IOW(XXX_MAGIC, 0x10, int)
    #define XXX_IOCTL_SETMIR		_IOW(XXX_MAGIC, 0x12, int)
    #define XXX_IOCTL_GETMIR		_IOR(XXX_MAGIC, 0x13, unsigned long)
    #define XXX_IOCTL_WRITEREG		_IOW(XXX_MAGIC, 0x14, struct xxx_wreg_handle)
    #define XXX_IOCTL_WRITECRAM		_IOW(XXX_MAGIC, 0x15, struct xxx_wcram_handle)
    
    /*Open打开dev接口*/
    static int open_dev(void)
    {
    	char fname[] = "/dev/xxx-ioctrl";
    	int fd = open(fname, O_RDWR);
    	return fd;
    }
    
    /*Close关闭dev ioControl接口*/
    static void close_dev(int fd)
    {
    	close(fd);
    }
    
    /*IOCTRL 传送结构体数据*/
    static int do_writereg(int addr, int value)
    {
    	int fd;
    	struct xxx_wreg_handle hd;
    
    	hd.len = 1;
    	regcmd[0].addr = addr;
    	regcmd[0].data = value;
    	hd.regcmd = regcmd;
    
    	fd = open_dev();
    	ioctl(fd, XXX_IOCTL_WRITEREG, &hd);
    	close_dev(fd);
    
    	return(0);
    
    }
    /*IOCTRL 传送int类型数据*/
    static void do_sets(int nStatus)
    {
    	int fd;
    	int status;
    
    	fd = open_dev();
    	ioctl(fd, XXX_IOCTL_SETSTATUS, &nStatus);
    	close_dev(fd);
    
    	printf("XXX Get Status = %d\n", status);
    
    }

 

你可能感兴趣的:(Android驱动开发)