1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Video4Linux2 generic ISP parameters and statistics support 4 * 5 * Copyright (C) 2025 Ideas On Board Oy 6 * Author: Jacopo Mondi <jacopo.mondi@ideasonboard.com> 7 */ 8 9 #include <media/v4l2-isp.h> 10 11 #include <linux/bitops.h> 12 #include <linux/device.h> 13 14 #include <media/videobuf2-core.h> 15 16 int v4l2_isp_params_validate_buffer_size(struct device *dev, 17 struct vb2_buffer *vb, 18 size_t max_size) 19 { 20 size_t header_size = offsetof(struct v4l2_isp_params_buffer, data); 21 size_t payload_size = vb2_get_plane_payload(vb, 0); 22 23 /* Payload size can't be greater than the destination buffer size */ 24 if (payload_size > max_size) { 25 dev_dbg(dev, "Payload size is too large: %zu\n", payload_size); 26 return -EINVAL; 27 } 28 29 /* Payload size can't be smaller than the header size */ 30 if (payload_size < header_size) { 31 dev_dbg(dev, "Payload size is too small: %zu\n", payload_size); 32 return -EINVAL; 33 } 34 35 return 0; 36 } 37 EXPORT_SYMBOL_GPL(v4l2_isp_params_validate_buffer_size); 38 39 int v4l2_isp_params_validate_buffer(struct device *dev, struct vb2_buffer *vb, 40 const struct v4l2_isp_params_buffer *buffer, 41 const struct v4l2_isp_params_block_info *info, 42 size_t num_blocks) 43 { 44 size_t header_size = offsetof(struct v4l2_isp_params_buffer, data); 45 size_t payload_size = vb2_get_plane_payload(vb, 0); 46 size_t block_offset = 0; 47 size_t buffer_size; 48 49 /* 50 * Currently only the first version of the V4L2 ISP parameters format is 51 * supported. We accept both V0 and V1 to support existing drivers 52 * compatible with V4L2 ISP that use either 0 or 1 as their "first 53 * version" identifiers. 54 */ 55 if (buffer->version != V4L2_ISP_PARAMS_VERSION_V0 && 56 buffer->version != V4L2_ISP_PARAMS_VERSION_V1) { 57 dev_dbg(dev, 58 "Unsupported V4L2 ISP parameters format version: %u\n", 59 buffer->version); 60 return -EINVAL; 61 } 62 63 /* Validate the size reported in the header */ 64 buffer_size = header_size + buffer->data_size; 65 if (buffer_size != payload_size) { 66 dev_dbg(dev, "Data size %zu and payload size %zu are different\n", 67 buffer_size, payload_size); 68 return -EINVAL; 69 } 70 71 /* Walk the list of ISP configuration blocks and validate them. */ 72 buffer_size = buffer->data_size; 73 while (buffer_size >= sizeof(struct v4l2_isp_params_block_header)) { 74 const struct v4l2_isp_params_block_info *block_info; 75 const struct v4l2_isp_params_block_header *block; 76 77 block = (const struct v4l2_isp_params_block_header *) 78 (buffer->data + block_offset); 79 80 if (block->type >= num_blocks) { 81 dev_dbg(dev, 82 "Invalid block type %u at offset %zu\n", 83 block->type, block_offset); 84 return -EINVAL; 85 } 86 87 if (block->size > buffer_size) { 88 dev_dbg(dev, "Premature end of parameters data\n"); 89 return -EINVAL; 90 } 91 92 /* It's invalid to specify both ENABLE and DISABLE. */ 93 if ((block->flags & (V4L2_ISP_PARAMS_FL_BLOCK_ENABLE | 94 V4L2_ISP_PARAMS_FL_BLOCK_DISABLE)) == 95 (V4L2_ISP_PARAMS_FL_BLOCK_ENABLE | 96 V4L2_ISP_PARAMS_FL_BLOCK_DISABLE)) { 97 dev_dbg(dev, "Invalid block flags %x at offset %zu\n", 98 block->flags, block_offset); 99 return -EINVAL; 100 } 101 102 /* 103 * Match the block reported size against the info provided 104 * one, but allow the block to only contain the header in 105 * case it is going to be disabled. 106 */ 107 block_info = &info[block->type]; 108 if (block->size != block_info->size && 109 (!(block->flags & V4L2_ISP_PARAMS_FL_BLOCK_DISABLE) || 110 block->size != sizeof(*block))) { 111 dev_dbg(dev, 112 "Invalid block size %u (expected %zu) at offset %zu\n", 113 block->size, block_info->size, block_offset); 114 return -EINVAL; 115 } 116 117 block_offset += block->size; 118 buffer_size -= block->size; 119 } 120 121 if (buffer_size) { 122 dev_dbg(dev, "Unexpected data after the parameters buffer end\n"); 123 return -EINVAL; 124 } 125 126 return 0; 127 } 128 EXPORT_SYMBOL_GPL(v4l2_isp_params_validate_buffer); 129 130 MODULE_LICENSE("GPL"); 131 MODULE_AUTHOR("Jacopo Mondi <jacopo.mondi@ideasonboard.com"); 132 MODULE_DESCRIPTION("V4L2 generic ISP parameters and statistics helpers"); 133