#include <linux/atomic.h> #include <linux/kernel.h> #include <linux/list.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/usb.h> #include <linux/videodev2.h> #include <linux/vmalloc.h> #include <linux/wait.h> #include <linux/version.h> #include <asm/unaligned.h> #include <media/v4l2-common.h> #include <media/v4l2-ioctl.h> #include <media/videobuf-core.h> #include "uvcvideo.h" static struct usb_device *myuvc_udev; static int myuvc_control_intf; static int myuvc_streaming_intf; static struct video_device *myuvc_vdev; /* A2 参考 uvc_v4l2_do_ioctl */ static int my_vivid_vidioc_querycap(struct file *file, void *fh,struct v4l2_capability *cap) { memset(cap, 0, sizeof *cap); strcpy(cap->driver, "myuvc"); strcpy(cap->card, "myuvc"); cap->version=1; cap->capabilities=V4L2_CAP_VIDEO_CAPTURE|V4L2_CAP_STREAMING; return 0; } /* A3 列举支持哪种格式 * 参考: uvc_fmts 数组 */ /* A1 */ static int myuvc_v4l2_open(struct file *file) { return 0; } const struct v4l2_file_operations myuvc_fops = { .owner = THIS_MODULE, // .open = myuvc_v4l2_open, // .release = uvc_v4l2_release, // .unlocked_ioctl = video_ioctl2, // .mmap = uvc_v4l2_mmap, // .poll = uvc_v4l2_poll, }; const struct v4l2_ioctl_ops myuvc_ioctl_ops = { // // 表示它是一个摄像头设备 // .vidioc_querycap = my_vivid_vidioc_querycap, // /* 用于列举、获得、测试、设置摄像头的数据的格式 */ // .vidioc_enum_fmt_vid_cap = my_vivid_vidioc_enum_fmt_vid_cap, // .vidioc_g_fmt_vid_cap = my_vivid_vidioc_g_fmt_vid_cap, // .vidioc_try_fmt_vid_cap = my_vivid_vidioc_try_fmt_vid_cap, // .vidioc_s_fmt_vid_cap = my_vivid_vidioc_s_fmt_vid_cap, // /* 缓冲区操作: 申请/查询/放入队列/取出队列 */ // .vidioc_reqbufs = my_vivid_vidioc_reqbufs, // .vidioc_querybuf = my_vivid_vidioc_querybuf, // .vidioc_qbuf = my_vivid_vidioc_qbuf, // .vidioc_dqbuf = my_vivid_vidioc_dqbuf, // // 启动/停止 // .vidioc_streamon = my_vivid_vidioc_streamon, // .vidioc_streamoff = my_vivid_vidioc_streamoff, }; static void myuvc_release(struct video_device *vdev) { } /* ------------------------------------------------------------------------ * USB probe, disconnect, suspend and resume * printk("%s %s %d\n",__FILE__,__FUNCTION__,__LINE__); */ static int myuvc_probe(struct usb_interface *intf,const struct usb_device_id *id){ static int cnt = 0; static struct usb_device *dev; printk("myuvc_probe : cnt = %d\n", cnt++); dev=interface_to_usbdev(intf); myuvc_udev=dev; if(cnt==1){ myuvc_control_intf=intf->cur_altsetting->desc.bInterfaceNumber; } else if(cnt==2){ myuvc_streaming_intf=intf->cur_altsetting->desc.bInterfaceNumber; } if(cnt==2){ //1.分配一个video_device结构体 myuvc_vdev=video_device_alloc(); //2.设置 //2.1 myuvc_vdev->release = myuvc_release; myuvc_vdev->fops = &myuvc_fops; myuvc_vdev->ioctl_ops = &myuvc_ioctl_ops; //3.注册 video_register_device(myuvc_vdev, VFL_TYPE_GRABBER, -1); } return 0; } static void myuvc_disconnect(struct usb_interface *intf) { static int cnt = 0; printk("myuvc_disconnect : cnt = %d\n", cnt++); if (cnt == 2) { //video_unregister_device(myuvc_vdev); //video_device_release(myuvc_vdev); } } static struct usb_device_id myuvc_ids[] = { /* Generic USB Video Class */ { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) },/* VideoControl Interface */ { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 2, 0) },/* VideoStreaming Interface */ {} }; /* 1. 分配usb_driver */ /* 2. 设置 */ struct usb_driver myuvc_driver={ .name = "myuvc", .probe = myuvc_probe, .disconnect = myuvc_disconnect, .id_table = myuvc_ids, }; static int __init myuvc_init(void) { /* 3. 注册 */ usb_register(&myuvc_driver); return 0; } static void __exit myuvc_cleanup(void) { usb_deregister(&myuvc_driver); } module_init(myuvc_init); module_exit(myuvc_cleanup); MODULE_LICENSE("GPL"); MODULE_AUTHOR("JWT");
< [ 3247.170065] myuvc_probe : cnt = 0
< [ 3247.170105] myuvc_probe : cnt = 1
< [ 3247.170107] ------------[ cut here ]------------
< [ 3247.170126] WARNING: CPU: 3 PID: 11348 at /build/linux-hwe-SPgdUD/linux-hwe-4.15.0/drivers/media/v4l2-core/v4l2-dev.c:841 __video_register_device+0x609/0x700 [videodev]
< [ 3247.170126] Modules linked in: myuvc(OE+) rfcomm vmw_vsock_vmci_transport vsock bnep crct10dif_pclmul crc32_pclmul ghash_clmulni_intel pcbc snd_ens1371 snd_ac97_codec gameport ac97_bus aesni_intel snd_pcm videobuf2_vmalloc videobuf2_memops videobuf2_v4l2 videobuf2_core snd_seq_midi snd_seq_midi_event videodev snd_rawmidi media aes_x86_64 crypto_simd glue_helper cryptd snd_seq snd_seq_device vmw_balloon btusb btrtl btbcm btintel intel_rapl_perf snd_timer snd bluetooth joydev input_leds serio_raw ecdh_generic soundcore vmw_vmci i2c_piix4 shpchp mac_hid nfsd auth_rpcgss nfs_acl lockd grace sunrpc parport_pc ppdev lp parport autofs4 hid_generic usbhid hid vmwgfx ttm drm_kms_helper syscopyarea sysfillrect psmouse sysimgblt fb_sys_fops e1000 ahci mptspi libahci mptscsih drm mptbase scsi_transport_spi pata_acpi
< [ 3247.170146] [last unloaded: uvcvideo]
< [ 3247.170147] CPU: 3 PID: 11348 Comm: insmod Tainted: G W OE 4.15.0-136-generic #140~16.04.1-Ubuntu
< [ 3247.170148] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 07/29/2019
< [ 3247.170151] RIP: 0010:__video_register_device+0x609/0x700 [videodev]
< [ 3247.170152] RSP: 0018:ffffae3d43163aa0 EFLAGS: 00010286
< [ 3247.170153] RAX: 0000000000000024 RBX: ffff9de9ee850898 RCX: 0000000000000006
< [ 3247.170153] RDX: 0000000000000000 RSI: 0000000000000082 RDI: ffff9de9f56d6490
< [ 3247.170154] RBP: ffffae3d43163ad0 R08: 000000000002705c R09: ffff9de9ffec8000
< [ 3247.170154] R10: ffff9de9f13c4800 R11: 0000000000000735 R12: 00000000ffffffff
< [ 3247.170155] R13: ffffffffc084e068 R14: ffff9de9f13c4800 R15: ffffffffc084e120
< [ 3247.170156] FS: 00007f30e6d4a700(0000) GS:ffff9de9f56c0000(0000) knlGS:0000000000000000
< [ 3247.170156] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
< [ 3247.170157] CR2: 00007f30e68eb781 CR3: 00000001eaae2003 CR4: 00000000003606e0
< [ 3247.170173] Call Trace:
< [ 3247.170177] myuvc_probe+0x72/0x76 [myuvc]
< [ 3247.170181] usb_probe_interface+0x158/0x2f0
< [ 3247.170183] driver_probe_device+0x3c7/0x4a0
< [ 3247.170184] __driver_attach+0xef/0x100
< [ 3247.170186] ? driver_probe_device+0x4a0/0x4a0
< [ 3247.170187] bus_for_each_dev+0x72/0xc0
< [ 3247.170188] driver_attach+0x1e/0x20
< [ 3247.170189] bus_add_driver+0x1f4/0x270
< [ 3247.170191] driver_register+0x60/0xe0
< [ 3247.170192] usb_register_driver+0x84/0x140
< [ 3247.170192] ? 0xffffffffc0851000
< [ 3247.170194] myuvc_init+0x23/0x1000 [myuvc]
< [ 3247.170196] do_one_initcall+0x55/0x1ac
< [ 3247.170197] ? _cond_resched+0x1a/0x50
< [ 3247.170200] ? kmem_cache_alloc_trace+0x165/0x1c0
< [ 3247.170202] do_init_module+0x5f/0x223
< [ 3247.170203] load_module+0x188c/0x1ea0
< [ 3247.170206] ? ima_post_read_file+0x83/0xa0
< [ 3247.170207] SYSC_finit_module+0xe5/0x120
< [ 3247.170209] ? SYSC_finit_module+0xe5/0x120
< [ 3247.170210] SyS_finit_module+0xe/0x10
< [ 3247.170212] do_syscall_64+0x73/0x130
< [ 3247.170213] entry_SYSCALL_64_after_hwframe+0x41/0xa6
< [ 3247.170213] RIP: 0033:0x7f30e6875599
< [ 3247.170214] RSP: 002b:00007fff08a5c138 EFLAGS: 00000202 ORIG_RAX: 0000000000000139
< [ 3247.170215] RAX: ffffffffffffffda RBX: 00005624169361f0 RCX: 00007f30e6875599
< [ 3247.170215] RDX: 0000000000000000 RSI: 0000562415fc926b RDI: 0000000000000003
< [ 3247.170216] RBP: 0000562415fc926b R08: 0000000000000000 R09: 00007f30e6b3aea0
< [ 3247.170216] R10: 0000000000000003 R11: 0000000000000202 R12: 0000000000000000
< [ 3247.170216] R13: 0000562416935130 R14: 0000000000000000 R15: 0000000000000000
< [ 3247.170217] Code: c0 4b 78 c0 e8 49 a7 58 d9 0f 0b 48 83 c4 08 b8 ea ff ff ff 5b 41 5c 41 5d 41 5e 41 5f 5d c3 48 c7 c7 c0 4b 78 c0 e8 27 a7 58 d9 <0f> 0b b8 ea ff ff ff e9 97 fa ff ff bb 03 02 00 00 e9 be fd ff
< [ 3247.170226] ---[ end trace e8f67ae589c6c4e1 ]---
< [ 3247.170253] usbcore: registered new interface driver myuvc