weixin_44508514 2022-06-17 10:41
浏览 60
已结题

USB红外测温摄像头内核驱动,video_device注册失败

在写USB红外测温摄像头内核驱动时,video_register_device(myuvc_vdev, VFL_TYPE_VIDEO, -1) 老是返回-22,失败。
dmesg 有下面内容(列举),不知道有没有用:
[ 7226.486925] WARNING: CPU: 0 PID: 24262 at drivers/media/v4l2-core/v4l2-dev.c:898 __video_register_device+0x621/0x7a0 [videodev]
[ 7226.486958] RIP: 0010:__video_register_device+0x621/0x7a0 [videodev]

#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/usb.h>
#include <linux/videodev2.h>
#include <linux/vmalloc.h>
#include <linux/wait.h>
#include <asm/atomic.h>
#include <asm/unaligned.h>

#include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h>

static struct video_device *myuvc_vdev;

/* A2 */
static int myuvc_vidioc_querycap(struct file *file, void  *priv,
                    struct v4l2_capability *cap)
{
    return 0;
}

/* A3 列举支持哪种格式 */
static int myuvc_vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
                    struct v4l2_fmtdesc *f)
{
    return 0;
}

/* A4 返回当前所使用的格式 */
static int myuvc_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
                    struct v4l2_format *f)
{
    return (0);
}

/* A5 测试驱动程序是否支持某种格式 */
static int myuvc_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
            struct v4l2_format *f)
{
    return 0;
}

/* A6 */
static int myuvc_vidioc_s_fmt_vid_cap(struct file *file, void *priv,
                    struct v4l2_format *f)
{
    return 0;
}

/* A7 APP调用该ioctl让驱动程序分配若干个缓存, APP将从这些缓存中读到视频数据 */
static int myuvc_vidioc_reqbufs(struct file *file, void *priv,
              struct v4l2_requestbuffers *p)
{
    return 0;
}

/* A8 查询缓存状态, 比如地址信息(APP可以用mmap进行映射) */
static int myuvc_vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
{
    return 0;
}

/* A10 把缓冲区放入队列, 底层的硬件操作函数将会把数据放入这个队列的缓存 */
static int myuvc_vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
{
    return 0;
}

/* A11 启动传输 */
static int myuvc_vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
{
    return 0;
}

/* A13 APP通过poll/select确定有数据后, 把缓存从队列中取出来
 */
static int myuvc_vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
{
    return 0;
}

/*
 * A14 之前已经通过mmap映射了缓存, APP可以直接读数据
 * A15 再次调用myuvc_vidioc_qbuf把缓存放入队列
 * A16 poll...
 */

/* A17 停止 */
static int myuvc_vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
{
    return 0;
}



static const struct v4l2_ioctl_ops myuvc_ioctl_ops = {
        // 表示它是一个摄像头设备
        .vidioc_querycap      = myuvc_vidioc_querycap,

        /* 用于列举、获得、测试、设置摄像头的数据的格式 */
        .vidioc_enum_fmt_vid_cap  = myuvc_vidioc_enum_fmt_vid_cap,
        .vidioc_g_fmt_vid_cap     = myuvc_vidioc_g_fmt_vid_cap,
        .vidioc_try_fmt_vid_cap   = myuvc_vidioc_try_fmt_vid_cap,
        .vidioc_s_fmt_vid_cap     = myuvc_vidioc_s_fmt_vid_cap,
        
        /* 缓冲区操作: 申请/查询/放入队列/取出队列 */
        .vidioc_reqbufs       = myuvc_vidioc_reqbufs,
        .vidioc_querybuf      = myuvc_vidioc_querybuf,
        .vidioc_qbuf          = myuvc_vidioc_qbuf,
        .vidioc_dqbuf         = myuvc_vidioc_dqbuf,
        
        // 启动/停止
        .vidioc_streamon      = myuvc_vidioc_streamon,
        .vidioc_streamoff     = myuvc_vidioc_streamoff,   
};

/* A1 */
static int myuvc_open(struct file *file)
{
    return 0;
}


/* A9 把缓存映射到APP的空间,以后APP就可以直接操作这块缓存 */
static int myuvc_mmap(struct file *file, struct vm_area_struct *vma)
{
    return 0;
}

/* A12 APP调用POLL/select来确定缓存是否就绪(有数据) */
static unsigned int myuvc_poll(struct file *file, struct poll_table_struct *wait)
{
    return 0;
}

/* A18 关闭 */
static int myuvc_close(struct file *file)
{
    
    return 0;
}

static const struct v4l2_file_operations myuvc_fops = {
    .owner         = THIS_MODULE,
    .open            = myuvc_open,
    .release           = myuvc_close,
    .mmap               = myuvc_mmap,
    .unlocked_ioctl      = video_ioctl2, /* V4L2 ioctl handler */
    .poll            = myuvc_poll,
};

static void myuvc_release(struct video_device *vdev)
{
}


static int myuvc_probe(struct usb_interface *intf,
             const struct usb_device_id *id)
{
    static int cnt = 0;
    struct usb_device *dev = interface_to_usbdev(intf);
    struct usb_device_descriptor *descriptor = &dev->descriptor;
    struct usb_host_config *hostconfig;
    struct usb_config_descriptor *config;
    struct usb_interface_assoc_descriptor *assoc_desc;
    struct usb_interface_descriptor    *interface;
    struct usb_endpoint_descriptor  *endpoint;
    int i, j, k, l, m;
    unsigned char *buffer;
    int buflen;
    int desc_len;
    int desc_cnt;
    int ret;

    printk("myuvc_probe : cnt = %d\n", cnt++);

    if (cnt == 1)
    {
        /* 1. 分配一个video_device结构体 */
        myuvc_vdev = video_device_alloc();

        /* 2. 设置 */
        /* 2.1 */
        myuvc_vdev->release = myuvc_release;
        
        /* 2.2 */
        myuvc_vdev->fops    = &myuvc_fops;
        
        /* 2.3 */
        myuvc_vdev->ioctl_ops = &myuvc_ioctl_ops;

        /* 3. 注册 */
        ret = video_register_device(myuvc_vdev, VFL_TYPE_VIDEO, -1);
    printk("ret = %d\n",ret);
    }
    
    
    return 0;
}

static void myuvc_disconnect(struct usb_interface *intf)
{
    static int cnt = 0;
    printk("myuvc_disconnect : cnt = %d\n", cnt++);

    if (cnt == 1)
    {
        video_unregister_device(myuvc_vdev);
        video_device_release(myuvc_vdev);
    }
    
}

static struct usb_device_id myuvc_ids[] = {
    {
        USB_DEVICE(0x4206, 0x3702),    /*靠縄D靠縄D */
    },
    {}
};

/* 1. 分配usb_driver */
/* 2. 设置 */
static struct usb_driver myuvc_driver = {
    .name       = "myuvc",
    .probe      = myuvc_probe,
    .disconnect = myuvc_disconnect,
    .id_table   = myuvc_ids,
};

static int myuvc_init(void)
{
    /* 3. 注册 */
    usb_register(&myuvc_driver);
    return 0;
}

static void myuvc_exit(void)
{
    usb_deregister(&myuvc_driver);
}

module_init(myuvc_init);
module_exit(myuvc_exit);

MODULE_LICENSE("GPL");





  • 写回答

0条回答 默认 最新

    报告相同问题?

    问题事件

    • 系统已结题 6月25日
    • 创建了问题 6月17日

    悬赏问题

    • ¥20 指导如何跑通以下两个Github代码
    • ¥15 大家知道这个后备文件怎么删吗,为啥这些文件我只看到一份,没有后备呀
    • ¥15 C++为什么这个代码没报错运行不出来啊
    • ¥15 一道ban了很多东西的pyjail题
    • ¥15 关于#r语言#的问题:如何将生成的四幅图排在一起,且对变量的赋值进行更改,让组合的图漂亮、美观@(相关搜索:森林图)
    • ¥15 C++识别堆叠物体异常
    • ¥15 微软硬件驱动认证账号申请
    • ¥15 GPT写作提示指令词
    • ¥20 根据动态演化博弈支付矩阵完成复制动态方程求解和演化相图分析等
    • ¥15 华为超融合部署环境下RedHat虚拟机分区扩容问题