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 <linux/ioctl.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
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 <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#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);
}