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)
-
驱动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);
} -
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 0xD0typedef 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);
}