STRUCT VB2_OPS(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

πŸ’– STRUCT VB2_OPS(9) πŸ’–

okay bestie, so this is a page from the Kernel API Manual and it's about struct vb2_ops β€” the videobuf2 callback table. yes it's kernel-internals-core. yes it's iconic. no cap, this is the whole vibe of "driver, do your thing when the core asks you to." πŸ¦‹


✨ NAME ✨

struct vb2_ops β€” driver-specific callbacks. literally it's the menu of functions your driver hands over and the vb2 core calls back into. periodt πŸ’…


πŸŽ€ SYNOPSIS πŸŽ€

struct vb2_ops {
    int (*queue_setup)(struct vb2_queue *q, unsigned int *num_buffers,
unsigned int *num_planes, unsigned int sizes[], struct device
*alloc_devs[]);
    int (*buf_out_validate)(struct vb2_buffer *vb);
    int (*buf_init)(struct vb2_buffer *vb);
    int (*buf_prepare)(struct vb2_buffer *vb);
    void (*buf_finish)(struct vb2_buffer *vb);
    void (*buf_cleanup)(struct vb2_buffer *vb);
    int (*prepare_streaming)(struct vb2_queue *q);
    int (*start_streaming)(struct vb2_queue *q, unsigned int count);
    void (*stop_streaming)(struct vb2_queue *q);
    void (*unprepare_streaming)(struct vb2_queue *q);
    void (*buf_queue)(struct vb2_buffer *vb);
    void (*buf_request_complete)(struct vb2_buffer *vb);
 };

like, that's the whole function-pointer lineup. twelve slots. every one of them a little moment. 🌸


🌈 MEMBERS 🌈

  • queue_setup β€” called from the VIDIOC_REQBUFS and VIDIOC_CREATE_BUFS handlers before memory allocation. and listen, it can be called twice: if the original number of requested buffers couldn't be allocated, it gets called a second time with the actually allocated number of buffers to verify if that is OK. sneaky but valid. 🫢

the driver should return the required number of buffers in um_buffers, the required number of planes per buffer in um_planes, the size of each plane should be set in the sizes array, and optional per-plane allocator specific device in the alloc_devs array.

  • when called from VIDIOC_REQBUFS: um_planes == 0, the driver has to use the currently configured format to determine the plane sizes, and um_buffers is the total number of buffers that are being allocated.
  • when called from VIDIOC_CREATE_BUFS: um_planes != 0 and it describes the requested number of planes, and sizes contains the requested plane sizes. in this case um_buffers are being allocated additionally to the buffers already allocated.
if either um_planes or the requested sizes are invalid, the callback must return -EINVAL. no negotiating. 🚨
  • buf_out_validate β€” called when the output buffer is prepared or queued to a request; drivers can use this to validate userspace-provided information; this is required only for OUTPUT queues. so if you're not OUTPUT, you can lowkey ignore it. ✨
  • buf_init β€” called once after allocating a buffer (in the MMAP case) or after acquiring a new USERPTR buffer; drivers may perform additional buffer-related initialization; initialization failure (return != 0) will prevent queue setup from completing successfully; optional. one shot. make it count. πŸ’…
  • buf_prepare β€” called every time the buffer is queued from userspace and from the VIDIOC_PREPARE_BUF ioctl; drivers may perform any initialization required before each hardware operation in this callback; drivers can access/modify the buffer here as it is still synced for the CPU; drivers that support VIDIOC_CREATE_BUFS must also validate the buffer size; if an error is returned, the buffer will not be queued in the driver; optional. this is the main-character callback ngl πŸ‘‘
  • buf_finish β€” called before every dequeue of the buffer back to userspace; the buffer is synced for the CPU, so drivers can access/modify the buffer contents; drivers may perform any operations required before userspace accesses the buffer; optional. πŸ”₯

the buffer state can be one of the following: DONE and ERROR occur while streaming is in progress, and the PREPARED state occurs when the queue has been canceled and all pending buffers are being returned to their default DEQUEUED state.

typically you only have to do something if the state is VB2_BUF_STATE_DONE, since in all other cases the buffer contents will be ignored anyway. so don't do extra work for no reason bestie 😌
  • buf_cleanup β€” called once before the buffer is freed; drivers may perform any additional cleanup; optional. the goodbye kiss πŸŽ€
  • prepare_streaming β€” called once to prepare for the 'streaming' state; this is where validation can be done to verify everything is okay and streaming resources can be claimed. it is called when the VIDIOC_STREAMON ioctl is called. the actual streaming starts when start_streaming is called. optional. it's giving "pre-game" energy ✨
  • start_streaming β€” called once to enter the 'streaming' state; the driver may receive buffers with the buf_queue callback before start_streaming is called; the driver gets the number of already queued buffers in the count parameter; the driver can return an error if the hardware fails, in that case all buffers that have been already given by the buf_queue callback are to be returned by the driver by calling vb2_buffer_done with VB2_BUF_STATE_QUEUED. 🚨

if you need a minimum number of buffers before you can start streaming, then set vb2_queue->min_queued_buffers. if that is non-zero then start_streaming won't be called until at least that many buffers have been queued up by userspace. gatekeeping, but make it hardware πŸ’€

  • stop_streaming β€” called when the 'streaming' state must be disabled; the driver should stop any DMA transactions or wait until they finish, and give back all buffers it got from the buf_queue callback by calling vb2_buffer_done with either VB2_BUF_STATE_DONE or VB2_BUF_STATE_ERROR; may use the vb2_wait_for_all_buffers function. cleanup era 🧹
  • unprepare_streaming β€” called as counterpart to prepare_streaming; any claimed streaming resources can be released here. it is called when the VIDIOC_STREAMOFF ioctls is called or when the streaming filehandle is closed. optional. the outro track 🎡
  • buf_queue β€” passes buffer vb to the driver; the driver may start a hardware operation on this buffer; the driver should give the buffer back by calling the vb2_buffer_done function; it is always called after calling the VIDIOC_STREAMON ioctl; might be called before the start_streaming callback if the user pre-queued buffers before calling VIDIOC_STREAMON. okay work it πŸ’ƒ
  • buf_request_complete β€” a buffer that was never queued to the driver but is associated with a queued request was canceled. the driver will have to mark associated objects in the request as completed; required if requests are supported. no skipping this one if you're doing requests fr fr 🫑

🌸 DESCRIPTION 🌸

these operations are not called from interrupt context β€” except where mentioned specifically. so like, mostly you're in a nice normal context, not the panic-y one. πŸ™ˆ


⭐ SEE ALSO ⭐

kernel file ./include/media/videobuf2-core.h β€” and the whole squad of related pages, all here, none skipped, i would never:

enum vb2_memory(9), struct vb2_mem_ops(9), struct vb2_plane(9), enum vb2_io_modes(9), enum vb2_buffer_state(9), struct vb2_buffer(9), struct vb2_buf_ops(9), struct vb2_queue(9), vb2_queue_allows_cache_hints(9), vb2_plane_vaddr(9), vb2_plane_cookie(9), vb2_buffer_done(9), vb2_discard_done(9), vb2_wait_for_all_buffers(9), vb2_core_querybuf(9), vb2_core_reqbufs(9), vb2_core_create_bufs(9), vb2_core_prepare_buf(9), vb2_core_remove_bufs(9), vb2_core_qbuf(9), vb2_core_dqbuf(9), vb2_core_streamon(9), vb2_core_streamoff(9), vb2_core_expbuf(9), vb2_core_queue_init(9), vb2_core_queue_release(9), vb2_queue_error(9), vb2_mmap(9), vb2_get_unmapped_area(9), vb2_core_poll(9), vb2_read(9), vb2_write(9), vb2_thread_fnc(9), vb2_thread_start(9), vb2_thread_stop(9), vb2_is_streaming(9), vb2_fileio_is_active(9), vb2_get_num_buffers(9), vb2_is_busy(9), vb2_get_drv_priv(9), vb2_set_plane_payload(9), vb2_get_plane_payload(9), vb2_plane_size(9), vb2_start_streaming_called(9), vb2_clear_last_buffer_dequeued(9), vb2_get_buffer(9), vb2_buffer_in_use(9), vb2_verify_memory_type(9), vb2_request_object_is_buffer(9), vb2_request_buffer_cnt(9)


that's the whole thing bestie, you ate it πŸ’…βœ¨

sign-off from the ./include/media corner of the tree, dated October 2026 β€” go forth and callback responsibly πŸ¦‹πŸ’œ

πŸ“¦ where this page comes from