How to Learn about camera driver in Linux: (2) how to analyze camera driver by Using Virtual Drive vivi, linuxvivi
1. Run the "strace-o xawtv. log xawtv" command to obtain the following call information:
// 1 ~ 7 is called in v4l2_open
1. open
2. ioctl (4, VIDIOC_QUERYCAP
// 3 ~ 7 is called in get_device_capabilities
3. ()
Ioctl (4, VIDIOC_ENUMINPUT // lists the input sources. VIDIOC_ENUMINPUT/VIDIOC_G_INPUT/VIDIOC_S_INPUT is not required.
4. ()
Ioctl (4, VIDIOC_ENUMSTD // list standard (standard), not required
5. ()
Ioctl (4, VIDIOC_ENUM_FMT // List format
6. ioctl (4, VIDIOC_G_PARM
7. ()
Ioctl (4, VIDIOC_QUERYCTRL // query attributes (such as the Minimum brightness value, maximum value, and default value)
// 8 ~ 10 is called through v4l2_read_attr.
8. ioctl (4, VIDIOC_G_STD // obtain the currently used standard (standard), not required
9. ioctl (4, VIDIOC_G_INPUT
10. ioctl (4, VIDIOC_G_CTRL // obtain the current attribute, such as the brightness
11. ioctl (4, VIDIOC_TRY_FMT // try to see if some format is supported
12. ioctl (4, VIDIOC_S_FMT // set the camera to use a certain format
// 13 ~ 16 In v4l2_start_streaming
13. ioctl (4, VIDIOC_REQBUFS // request the system to allocate a buffer
14. ()
Ioctl (4, VIDIOC_QUERYBUF // query the allocated buffer
Mmap
15. ()
Ioctl (4, VIDIOC_QBUF // put the buffer into the queue
16. ioctl (4, VIDIOC_STREAMON // start the camera
// 17 is called through v4l2_write_attr.
17. ()
Ioctl (4, VIDIOC_S_CTRL // set attributes
Ioctl (4, VIDIOC_S_INPUT // sets the Input Source
Ioctl (4, VIDIOC_S_STD // set standard (standard), not required
// V4l2_nextframe> v4l2_waiton
18. v4l2_queue_all // put all into the buffer
V4l2_waiton
For ()
{
Select (5, [4], NULL, NULL, {5, 0}) = 1 (in [4], left {4, 985979 })
Ioctl (4, VIDIOC_DQBUF // de-queue, fetch the buffer from the queue
// Processing. You can directly access the data by obtaining the buffer address through mmap.
Ioctl (4, VIDIOC_QBUF // put the buffer into the queue
}
Several Functions of xawtv:
1. v4l2_open
2. v4l2_read_attr/v4l2_write_attr // read/write attributes
3. v4l2_start_streaming // apply for a buffer
4. v4l2_nextframe/v4l2_waiton
2. 11 ioctl required by the camera driver:/drivers/media/video/vivi. c-> vivi_ioctl_ops (struct). The modification test shows that:
. Vidioc_querycap = vidioc_querycap, // indicates that it is a camera device.
/* Used to list, obtain, test, and set the format of the camera data */
. Vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
. Vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
. Vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
. Vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
/* Buffer operation: Apply for/query/put in queue/retrieve queue */
. Vidioc_reqbufs = vidioc_reqbufs,
. Vidioc_querybuf = vidioc_querybuf,
. Vidioc_qbuf = vidioc_qbuf,
. Vidioc_dqbuf = vidioc_dqbuf,
// Start/stop
. Vidioc_streamon = vidioc_streamon,
. Vidioc_streamoff = vidioc_streamoff,
Continue to analyze the data acquisition process:
1. Request allocation Buffer: ioctl (4, VIDIOC_REQBUFS // request system allocation Buffer
Videobuf_reqbufs (queue, v4l2_requestbuffers) // The queue is initialized using videobuf_queue_vmalloc_init in the open function.
// Note: This IOCTL only allocates the header information of the buffer, and the real cache has not been allocated.
2. query the ing Buffer:
Ioctl (4, VIDIOC_QUERYBUF // query the allocated buffer
Videobuf_querybuf // obtain the data format, size, length, and height of the buffer.
Mmap (the parameter contains "size") // cache is allocated here
V4l2_mmap
Vivi_mmap
Videobuf_mmap_mapper
_ Videobuf_mmap_mapper in the videobuf-vmalloc.c
Mem-> vmalloc = vmalloc_user (pages); // The buffer space is allocated here.
3. Put the buffer into the queue:
Ioctl (4, VIDIOC_QBUF // put the buffer into the queue
Videobuf_qbuf
Q-> ops-> buf_prepare (q, buf, field); // call the functions provided by the driver for preprocessing.
List_add_tail (& buf-> stream, & q-> stream); // put the buffer zone at the end of the queue
Q-> ops-> buf_queue (q, buf); // call the "inbound queue function" provided by the driver"
4. Start the camera
Ioctl (4, VIDIOC_STREAMON
Videobuf_streamon
Q-> streaming = 1;
5. use select to query data: select (5, [4], NULL, NULL, {5, 0}) = 1 (in [4], left {4, 985979 })
// The driver must include: generate data and wake up the process.
V4l2_poll
Vdev-> fops-> poll
Vivi_poll
Videobuf_poll_stream
// Obtain the buffer from the queue Header
Buf = list_entry (q-> stream. next, struct videobuf_buffer, stream );
// Sleep if no data exists
Poll_wait (file, & buf-> done, wait );
Who will generate data and who will wake it up?
The kernel thread vivi_thread is executed every 30 ms, and it calls
Vivi_thread_tick
Vivi_fillbuff (fh, buf); // construct data
Wake_up (& buf-> vb. done); // wake up the process
6. Fetch the buffer from the queue after data is available
// With so many buffers, how does the APP know which buffer zone has data? Call VIDIOC_DQBUF
Ioctl (4, VIDIOC_DQBUF
Vidioc_dqbuf
// Obtain a buffer with data in the queue
Retval = stream_next_buffer (q, & buf, nonblocking );
// Delete it from the queue
List_del (& buf-> stream );
// Return the status of the buffer to the APP
Videobuf_status (q, B, buf, q-> type );
7. The application obtains the buffer status based on VIDIOC_DQBUF and knows which buffer has data.
Read the corresponding address (the address comes from the previous mmap ).
==> Vivi. c buffer operation process: ① VIDIOC_REQBUFS (allocating header information)-> ② VIDIOC_QUERYBUF (returning attribute)/mmap (ing address, allocating actual space)->
③ VIDIOC_QBUF (put the buffer in the queue)-> ④ VIDIOC_STREAMON (start the camera)-> ⑤ use select to query whether data exists: operate on the first buf of the queue->
⑥ VIDIOC_DQBUF (return the buf of the queue header and delete it from the queue)-> 7 VIDIOC_DQBUF (put it back to the queue again-③)
How to write the camera driver:
1. assign a struct: video_device: video_device_alloc
2. Set
. Fops
. Ioctl_ops (11 items need to be set in it)
If you want to use the buffer operation function provided by the kernel, you also need to construct a videobuf_queue_ops
3. Register: video_register_device