[media] uvcvideo: Set error_idx properly for extended controls API failures
When one of the requested controls doesn't exist the error_idx field must reflect that situation. For G_EXT_CTRLS and S_EXT_CTRLS, error_idx must be set to the control count. For TRY_EXT_CTRLS, it must be set to the index of the unexisting control. This issue was found by the v4l2-compliance tool. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Acked-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
		
					parent
					
						
							
								e9de051666
							
						
					
				
			
			
				commit
				
					
						f0ed2ce840
					
				
			
		
					 2 changed files with 22 additions and 14 deletions
				
			
		|  | @ -1061,7 +1061,7 @@ int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, | ||||||
| 
 | 
 | ||||||
| 	ctrl = uvc_find_control(chain, v4l2_ctrl->id, &mapping); | 	ctrl = uvc_find_control(chain, v4l2_ctrl->id, &mapping); | ||||||
| 	if (ctrl == NULL) { | 	if (ctrl == NULL) { | ||||||
| 		ret = -EINVAL; | 		ret = -ENOENT; | ||||||
| 		goto done; | 		goto done; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -1099,12 +1099,13 @@ int uvc_query_v4l2_menu(struct uvc_video_chain *chain, | ||||||
| 		return -ERESTARTSYS; | 		return -ERESTARTSYS; | ||||||
| 
 | 
 | ||||||
| 	ctrl = uvc_find_control(chain, query_menu->id, &mapping); | 	ctrl = uvc_find_control(chain, query_menu->id, &mapping); | ||||||
| 	if (ctrl == NULL || mapping->v4l2_type != V4L2_CTRL_TYPE_MENU) { | 	if (ctrl == NULL) { | ||||||
| 		ret = -EINVAL; | 		ret = -ENOENT; | ||||||
| 		goto done; | 		goto done; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (query_menu->index >= mapping->menu_count) { | 	if (mapping->v4l2_type != V4L2_CTRL_TYPE_MENU || | ||||||
|  | 	    query_menu->index >= mapping->menu_count) { | ||||||
| 		ret = -EINVAL; | 		ret = -EINVAL; | ||||||
| 		goto done; | 		goto done; | ||||||
| 	} | 	} | ||||||
|  | @ -1263,7 +1264,7 @@ static int uvc_ctrl_add_event(struct v4l2_subscribed_event *sev, unsigned elems) | ||||||
| 
 | 
 | ||||||
| 	ctrl = uvc_find_control(handle->chain, sev->id, &mapping); | 	ctrl = uvc_find_control(handle->chain, sev->id, &mapping); | ||||||
| 	if (ctrl == NULL) { | 	if (ctrl == NULL) { | ||||||
| 		ret = -EINVAL; | 		ret = -ENOENT; | ||||||
| 		goto done; | 		goto done; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -1414,7 +1415,7 @@ int uvc_ctrl_get(struct uvc_video_chain *chain, | ||||||
| 
 | 
 | ||||||
| 	ctrl = uvc_find_control(chain, xctrl->id, &mapping); | 	ctrl = uvc_find_control(chain, xctrl->id, &mapping); | ||||||
| 	if (ctrl == NULL) | 	if (ctrl == NULL) | ||||||
| 		return -EINVAL; | 		return -ENOENT; | ||||||
| 
 | 
 | ||||||
| 	return __uvc_ctrl_get(chain, ctrl, mapping, &xctrl->value); | 	return __uvc_ctrl_get(chain, ctrl, mapping, &xctrl->value); | ||||||
| } | } | ||||||
|  | @ -1431,7 +1432,9 @@ int uvc_ctrl_set(struct uvc_video_chain *chain, | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	ctrl = uvc_find_control(chain, xctrl->id, &mapping); | 	ctrl = uvc_find_control(chain, xctrl->id, &mapping); | ||||||
| 	if (ctrl == NULL || (ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR) == 0) | 	if (ctrl == NULL) | ||||||
|  | 		return -ENOENT; | ||||||
|  | 	if (!(ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR)) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 
 | 
 | ||||||
| 	/* Clamp out of range values. */ | 	/* Clamp out of range values. */ | ||||||
|  |  | ||||||
|  | @ -591,8 +591,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) | ||||||
| 
 | 
 | ||||||
| 		ret = uvc_ctrl_get(chain, &xctrl); | 		ret = uvc_ctrl_get(chain, &xctrl); | ||||||
| 		uvc_ctrl_rollback(handle); | 		uvc_ctrl_rollback(handle); | ||||||
| 		if (ret >= 0) | 		if (ret < 0) | ||||||
| 			ctrl->value = xctrl.value; | 			return ret == -ENOENT ? -EINVAL : ret; | ||||||
|  | 
 | ||||||
|  | 		ctrl->value = xctrl.value; | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -612,7 +614,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) | ||||||
| 		ret = uvc_ctrl_set(chain, &xctrl); | 		ret = uvc_ctrl_set(chain, &xctrl); | ||||||
| 		if (ret < 0) { | 		if (ret < 0) { | ||||||
| 			uvc_ctrl_rollback(handle); | 			uvc_ctrl_rollback(handle); | ||||||
| 			return ret; | 			return ret == -ENOENT ? -EINVAL : ret; | ||||||
| 		} | 		} | ||||||
| 		ret = uvc_ctrl_commit(handle, &xctrl, 1); | 		ret = uvc_ctrl_commit(handle, &xctrl, 1); | ||||||
| 		if (ret == 0) | 		if (ret == 0) | ||||||
|  | @ -637,8 +639,9 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) | ||||||
| 			ret = uvc_ctrl_get(chain, ctrl); | 			ret = uvc_ctrl_get(chain, ctrl); | ||||||
| 			if (ret < 0) { | 			if (ret < 0) { | ||||||
| 				uvc_ctrl_rollback(handle); | 				uvc_ctrl_rollback(handle); | ||||||
| 				ctrls->error_idx = i; | 				ctrls->error_idx = ret == -ENOENT | ||||||
| 				return ret; | 						 ? ctrls->count : i; | ||||||
|  | 				return ret == -ENOENT ? -EINVAL : ret; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		ctrls->error_idx = 0; | 		ctrls->error_idx = 0; | ||||||
|  | @ -661,8 +664,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) | ||||||
| 			ret = uvc_ctrl_set(chain, ctrl); | 			ret = uvc_ctrl_set(chain, ctrl); | ||||||
| 			if (ret < 0) { | 			if (ret < 0) { | ||||||
| 				uvc_ctrl_rollback(handle); | 				uvc_ctrl_rollback(handle); | ||||||
| 				ctrls->error_idx = i; | 				ctrls->error_idx = (ret == -ENOENT && | ||||||
| 				return ret; | 						    cmd == VIDIOC_S_EXT_CTRLS) | ||||||
|  | 						 ? ctrls->count : i; | ||||||
|  | 				return ret == -ENOENT ? -EINVAL : ret; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Laurent Pinchart
				Laurent Pinchart