Ядро Android: Как создать /dev/video0 до запуска демона ueventd?

Я хочу получить доступ к /dev/video0 из модуля ядра после инициализации камеры. Для этого я хочу создать узел /dev/video0 до запуска демона ueventd.

1 ответ

При более глубоком рассмотрении обработки ядром узла /dev/video0 всякий раз, когда приложение пытается открыть этот файл, оно получает указатель FILE *fp, виртуальная файловая система ядра Linux проверяет, является ли это обычным файлом или файлом устройства, и если это В файле устройства он проверяет свой основной номер, чтобы отследить драйвер, который его зарегистрировал, и сохраняет младший номер в поле i_rdev struct inode *inode, которое снова внедряется в struct file *fp и передается этому драйверу.

Таким образом, для каждого FILE *fp, открытого приложением, в зарегистрированном драйвере есть struct file *fp, т.е. в нашем случае драйвер v4l2. Этот указатель файла передается в ядро ​​ioctl API v4l2_ioctl.

Теперь внутренний драйвер v4l2 поддерживает массив указателей на все зарегистрированные видеоустройства, как показано ниже:static struct video_device * video_device [VIDEO_NUM_DEVICES];

Теперь, если мы увидим реализацию основного вызова ioctl.

static long v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
        struct video_device *vdev = video_devdata(filp);
    ...
}

Эта структура видеоустройства извлекается из файлового указателя, который является ключом, с помощью которого мы можем управлять видеоустройством, т.е. нашей камерой, изнутри ядра, поскольку оно содержит функциональные указатели на все зарегистрированные ioctl v4l2. Поэтому наша цель - получить доступ к структуре видеоустройства из ядра.

Теперь снова посмотрим, как ядро ​​обращается к видеоустройству, когда оно получает запрос от приложения.

struct video_device *video_devdata(struct file *file)

{
        return video_device[iminor(file->f_path.dentry->d_inode)];
}
EXPORT_SYMBOL(video_devdata);

static inline unsigned iminor(const struct inode *inode)
{
        return MINOR(inode->i_rdev);
}

Как видно выше, он использует поле i_rdev для получения младшего номера, передаваемого из struct file *fp через VFS.

Подводя итог, если мы хотим получить доступ к ioctl из ядра, нам нужно заполнить фиктивный указатель файла * fp, содержащий младший номер в поле file->f_path.dentry->d_inode.i_rdev, подсистема v4l2 получит структуру video_device, используя это поле, и будет уметь дальше управлять операциями ioctl из структуры video_device, используя поле video_device->ioctl_ops, как показано ниже.

struct video_device                                                             
{                                                                               
#if defined(CONFIG_MEDIA_CONTROLLER)                                            
        struct media_entity entity;                                             
#endif                                                                          
        /* device ops */                                                        
        const struct v4l2_file_operations *fops; 
    const struct v4l2_ioctl_ops *ioctl_ops;
    ...
}

Чтобы установить file->f_path.dentry->d_inode.i_rdev, нам нужно добавить ссылки на структуру inode и dentry внутри структуры файла, как показано ниже псевдокода:

static int enumerate_camera()           
{                                                                                 

                        inode.i_rdev = cam_minor_number ;// Saved when camera device registered;        
                        dentry.d_inode = inode;        
                        file.f_path.dentry = dentry;   
                        file.f_dentry->d_inode = inode;
....                
  }                                                                       
Другие вопросы по тегам