既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新
有些时候需要对驱动的所有设备进行迭代,这种情况通常发生在多个设备驱动使用同一个硬件设备的情况下,比如 ivtvfb 驱动就是个 framebuffer 驱动,它用到了 ivtv 这个硬件设备。可以使用以下方法来迭代所有的已注册设备:
static int callback(struct device \*dev, void \*p)
{
struct v4l2\_device \*v4l2_dev = dev\_get\_drvdata(dev);
/\* test if this device was inited \*/
if (v4l2_dev == NULL)
return 0;
...
return 0;
}
int iterate(void \*p)
{
struct device\_driver \*drv;
int err;
/\* Find driver 'ivtv' on the PCI bus.
\* pci\_bus\_type is a global. For USB busses use usb\_bus\_type.
\*/
drv = driver\_find("ivtv", &pci_bus_type);
/\* iterate over all ivtv device instances \*/
err = driver\_for\_each\_device(drv, NULL, p, callback);
put\_driver(drv);
return err;
}
有时候需要对设备实例进行计数以将设备实例映射到模块的全局数组里面,可以使用以下步骤来完成计数操作:
static atomic\_t drv_instance = ATOMIC\_INIT(0);
static int drv\_probe(struct pci\_dev \*pdev, const struct pci\_device\_id \*pci_id)
{
...
state->instance = atomic\_inc\_return(&drv_instance) - 1;
}
如果一个热拔插设备有很多个设备节点(比如一个USB摄像头可以产生多路视频输出,虽然它的视频源是一个),那么很难知道在什么时候才能够安全地卸载 v4l2_device
设备。基于以上问题, v4l2_device
引入了引用计数机制,当 video_register_device
函数被调用的时候,引用计数会加一,当 video_device
被释放的时候,引用计数会减一,直到 v4l2_device
的引用计数到0的时候,v4l2_device
的 release
回调函数就会被调用,可以在该回调函数里面做一些清理工作。当其它的设备(alsa,因为这个不属于 video 设备,所以也就不能使用上面的 video 函数进行计数的加减操作)节点被创建的时候,可以人为调用以下函数对引用计数进行增减操作:
void v4l2_device_get(struct v4l2_device *v4l2_dev);
int v4l2_device_put(struct v4l2_device *v4l2_dev);
需要注意的是,
v4l2_device_register
函数将引用计数初始化为1,所以需要在remove
或者disconnect
回调方法里面调用v4l2_device_put
来减少引用计数,否则引用计数将永远不会达到0。
v4l2_subdev
结构体
很多设备都需要与子设备进行交互,通常情况下子设备用于音视频的编解码以及混合处理,对于网络摄像机来说子设备就是 sensors 和 camera 控制器。通常情况下它们都是 I2C 设备,但也有例外。v4l2_subdev
结构体被用于子设备管理。
每一个子设备驱动都必须有一个 v4l2_subdev
结构体,这个结构体可以作为独立的简单子设备存在,也可以嵌入到更大的结构体(自定义的子设备结构体)里面。通常会有一个由内核设置的低层次结构体(i2c_client
,也就是上面说的 i2c 设备),它包含了一些设备数据,要调用 v4l2_set_subdevdata
来设置子设备私有数据指针指向它,这样的话就可以很方便的从 subdev
找到相关的 I2C 设备数据(这个要编程实现的时候才能够了解它的用意)。另外也需要设置低级别结构的私有数据指针指向 v4l2_subdev
结构体,方便从低级别的结构体访问 v4l2_subdev
结构体,达到双向访问的目的,对于 i2c_client
来说,可