.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * uvc_ctrl.c -- USB Video Class driver - Controls |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2005-2010 |
---|
5 | 6 | * Laurent Pinchart (laurent.pinchart@ideasonboard.com) |
---|
6 | | - * |
---|
7 | | - * This program is free software; you can redistribute it and/or modify |
---|
8 | | - * it under the terms of the GNU General Public License as published by |
---|
9 | | - * the Free Software Foundation; either version 2 of the License, or |
---|
10 | | - * (at your option) any later version. |
---|
11 | | - * |
---|
12 | 7 | */ |
---|
13 | 8 | |
---|
| 9 | +#include <asm/barrier.h> |
---|
14 | 10 | #include <linux/kernel.h> |
---|
15 | 11 | #include <linux/list.h> |
---|
16 | 12 | #include <linux/module.h> |
---|
.. | .. |
---|
38 | 34 | * Controls |
---|
39 | 35 | */ |
---|
40 | 36 | |
---|
41 | | -static struct uvc_control_info uvc_ctrls[] = { |
---|
| 37 | +static const struct uvc_control_info uvc_ctrls[] = { |
---|
42 | 38 | { |
---|
43 | 39 | .entity = UVC_GUID_UVC_PROCESSING, |
---|
44 | 40 | .selector = UVC_PU_BRIGHTNESS_CONTROL, |
---|
.. | .. |
---|
354 | 350 | }, |
---|
355 | 351 | }; |
---|
356 | 352 | |
---|
357 | | -static struct uvc_menu_info power_line_frequency_controls[] = { |
---|
| 353 | +static const struct uvc_menu_info power_line_frequency_controls[] = { |
---|
358 | 354 | { 0, "Disabled" }, |
---|
359 | 355 | { 1, "50 Hz" }, |
---|
360 | 356 | { 2, "60 Hz" }, |
---|
361 | 357 | }; |
---|
362 | 358 | |
---|
363 | | -static struct uvc_menu_info exposure_auto_controls[] = { |
---|
| 359 | +static const struct uvc_menu_info exposure_auto_controls[] = { |
---|
364 | 360 | { 2, "Auto Mode" }, |
---|
365 | 361 | { 1, "Manual Mode" }, |
---|
366 | 362 | { 4, "Shutter Priority Mode" }, |
---|
.. | .. |
---|
421 | 417 | data[first+1] = min_t(int, abs(value), 0xff); |
---|
422 | 418 | } |
---|
423 | 419 | |
---|
424 | | -static struct uvc_control_mapping uvc_ctrl_mappings[] = { |
---|
| 420 | +static const struct uvc_control_mapping uvc_ctrl_mappings[] = { |
---|
425 | 421 | { |
---|
426 | 422 | .id = V4L2_CID_BRIGHTNESS, |
---|
427 | 423 | .name = "Brightness", |
---|
.. | .. |
---|
982 | 978 | s32 value = mapping->get(mapping, UVC_GET_CUR, data); |
---|
983 | 979 | |
---|
984 | 980 | if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) { |
---|
985 | | - struct uvc_menu_info *menu = mapping->menu_info; |
---|
| 981 | + const struct uvc_menu_info *menu = mapping->menu_info; |
---|
986 | 982 | unsigned int i; |
---|
987 | 983 | |
---|
988 | 984 | for (i = 0; i < mapping->menu_count; ++i, ++menu) { |
---|
.. | .. |
---|
1029 | 1025 | { |
---|
1030 | 1026 | struct uvc_control_mapping *master_map = NULL; |
---|
1031 | 1027 | struct uvc_control *master_ctrl = NULL; |
---|
1032 | | - struct uvc_menu_info *menu; |
---|
| 1028 | + const struct uvc_menu_info *menu; |
---|
1033 | 1029 | unsigned int i; |
---|
1034 | 1030 | |
---|
1035 | 1031 | memset(v4l2_ctrl, 0, sizeof(*v4l2_ctrl)); |
---|
1036 | 1032 | v4l2_ctrl->id = mapping->id; |
---|
1037 | 1033 | v4l2_ctrl->type = mapping->v4l2_type; |
---|
1038 | | - strlcpy(v4l2_ctrl->name, mapping->name, sizeof(v4l2_ctrl->name)); |
---|
| 1034 | + strscpy(v4l2_ctrl->name, mapping->name, sizeof(v4l2_ctrl->name)); |
---|
1039 | 1035 | v4l2_ctrl->flags = 0; |
---|
1040 | 1036 | |
---|
1041 | 1037 | if (!(ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR)) |
---|
.. | .. |
---|
1149 | 1145 | int uvc_query_v4l2_menu(struct uvc_video_chain *chain, |
---|
1150 | 1146 | struct v4l2_querymenu *query_menu) |
---|
1151 | 1147 | { |
---|
1152 | | - struct uvc_menu_info *menu_info; |
---|
| 1148 | + const struct uvc_menu_info *menu_info; |
---|
1153 | 1149 | struct uvc_control_mapping *mapping; |
---|
1154 | 1150 | struct uvc_control *ctrl; |
---|
1155 | 1151 | u32 index = query_menu->index; |
---|
.. | .. |
---|
1195 | 1191 | } |
---|
1196 | 1192 | } |
---|
1197 | 1193 | |
---|
1198 | | - strlcpy(query_menu->name, menu_info->name, sizeof(query_menu->name)); |
---|
| 1194 | + strscpy(query_menu->name, menu_info->name, sizeof(query_menu->name)); |
---|
1199 | 1195 | |
---|
1200 | 1196 | done: |
---|
1201 | 1197 | mutex_unlock(&chain->ctrl_mutex); |
---|
.. | .. |
---|
1280 | 1276 | uvc_ctrl_send_event(chain, handle, ctrl, mapping, val, changes); |
---|
1281 | 1277 | } |
---|
1282 | 1278 | |
---|
1283 | | -static void uvc_ctrl_status_event_work(struct work_struct *work) |
---|
| 1279 | +void uvc_ctrl_status_event(struct uvc_video_chain *chain, |
---|
| 1280 | + struct uvc_control *ctrl, const u8 *data) |
---|
1284 | 1281 | { |
---|
1285 | | - struct uvc_device *dev = container_of(work, struct uvc_device, |
---|
1286 | | - async_ctrl.work); |
---|
1287 | | - struct uvc_ctrl_work *w = &dev->async_ctrl; |
---|
1288 | | - struct uvc_video_chain *chain = w->chain; |
---|
1289 | 1282 | struct uvc_control_mapping *mapping; |
---|
1290 | | - struct uvc_control *ctrl = w->ctrl; |
---|
1291 | 1283 | struct uvc_fh *handle; |
---|
1292 | 1284 | unsigned int i; |
---|
1293 | | - int ret; |
---|
1294 | 1285 | |
---|
1295 | 1286 | mutex_lock(&chain->ctrl_mutex); |
---|
1296 | 1287 | |
---|
.. | .. |
---|
1298 | 1289 | ctrl->handle = NULL; |
---|
1299 | 1290 | |
---|
1300 | 1291 | list_for_each_entry(mapping, &ctrl->info.mappings, list) { |
---|
1301 | | - s32 value = __uvc_ctrl_get_value(mapping, w->data); |
---|
| 1292 | + s32 value = __uvc_ctrl_get_value(mapping, data); |
---|
1302 | 1293 | |
---|
1303 | 1294 | /* |
---|
1304 | 1295 | * handle may be NULL here if the device sends auto-update |
---|
.. | .. |
---|
1317 | 1308 | } |
---|
1318 | 1309 | |
---|
1319 | 1310 | mutex_unlock(&chain->ctrl_mutex); |
---|
| 1311 | +} |
---|
| 1312 | + |
---|
| 1313 | +static void uvc_ctrl_status_event_work(struct work_struct *work) |
---|
| 1314 | +{ |
---|
| 1315 | + struct uvc_device *dev = container_of(work, struct uvc_device, |
---|
| 1316 | + async_ctrl.work); |
---|
| 1317 | + struct uvc_ctrl_work *w = &dev->async_ctrl; |
---|
| 1318 | + int ret; |
---|
| 1319 | + |
---|
| 1320 | + uvc_ctrl_status_event(w->chain, w->ctrl, w->data); |
---|
| 1321 | + |
---|
| 1322 | + /* The barrier is needed to synchronize with uvc_status_stop(). */ |
---|
| 1323 | + if (smp_load_acquire(&dev->flush_status)) |
---|
| 1324 | + return; |
---|
1320 | 1325 | |
---|
1321 | 1326 | /* Resubmit the URB. */ |
---|
1322 | 1327 | w->urb->interval = dev->int_ep->desc.bInterval; |
---|
.. | .. |
---|
1326 | 1331 | ret); |
---|
1327 | 1332 | } |
---|
1328 | 1333 | |
---|
1329 | | -bool uvc_ctrl_status_event(struct urb *urb, struct uvc_video_chain *chain, |
---|
1330 | | - struct uvc_control *ctrl, const u8 *data) |
---|
| 1334 | +bool uvc_ctrl_status_event_async(struct urb *urb, struct uvc_video_chain *chain, |
---|
| 1335 | + struct uvc_control *ctrl, const u8 *data) |
---|
1331 | 1336 | { |
---|
1332 | 1337 | struct uvc_device *dev = chain->dev; |
---|
1333 | 1338 | struct uvc_ctrl_work *w = &dev->async_ctrl; |
---|
.. | .. |
---|
2025 | 2030 | static int uvc_ctrl_add_info(struct uvc_device *dev, struct uvc_control *ctrl, |
---|
2026 | 2031 | const struct uvc_control_info *info) |
---|
2027 | 2032 | { |
---|
2028 | | - int ret = 0; |
---|
2029 | | - |
---|
2030 | 2033 | ctrl->info = *info; |
---|
2031 | 2034 | INIT_LIST_HEAD(&ctrl->info.mappings); |
---|
2032 | 2035 | |
---|
2033 | 2036 | /* Allocate an array to save control values (cur, def, max, etc.) */ |
---|
2034 | 2037 | ctrl->uvc_data = kzalloc(ctrl->info.size * UVC_CTRL_DATA_LAST + 1, |
---|
2035 | 2038 | GFP_KERNEL); |
---|
2036 | | - if (ctrl->uvc_data == NULL) { |
---|
2037 | | - ret = -ENOMEM; |
---|
2038 | | - goto done; |
---|
2039 | | - } |
---|
| 2039 | + if (!ctrl->uvc_data) |
---|
| 2040 | + return -ENOMEM; |
---|
2040 | 2041 | |
---|
2041 | 2042 | ctrl->initialized = 1; |
---|
2042 | 2043 | |
---|
.. | .. |
---|
2044 | 2045 | "entity %u\n", ctrl->info.entity, ctrl->info.selector, |
---|
2045 | 2046 | dev->udev->devpath, ctrl->entity->id); |
---|
2046 | 2047 | |
---|
2047 | | -done: |
---|
2048 | | - if (ret < 0) |
---|
2049 | | - kfree(ctrl->uvc_data); |
---|
2050 | | - return ret; |
---|
| 2048 | + return 0; |
---|
2051 | 2049 | } |
---|
2052 | 2050 | |
---|
2053 | 2051 | /* |
---|