aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/uvc
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2010-09-29 15:03:03 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-10-20 23:18:24 -0400
commit52c58ad6f95ff60343bf0c517182d5f649ca0403 (patch)
treeba5e136941f806d340bee2d0fe2b76deed4cb01c /drivers/media/video/uvc
parent071c8bb827c80a68510a1cdb7e8bebbda1a494d6 (diff)
[media] uvcvideo: Delay initialization of XU controls
XU controls initialization requires querying the device for control information. As some buggy UVC devices will crash when queried repeatedly in a tight loop, delay XU controls initialization until first use. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/uvc')
-rw-r--r--drivers/media/video/uvc/uvc_ctrl.c194
1 files changed, 107 insertions, 87 deletions
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c
index 97a2395671b5..a0c9d580ca9d 100644
--- a/drivers/media/video/uvc/uvc_ctrl.c
+++ b/drivers/media/video/uvc/uvc_ctrl.c
@@ -1164,6 +1164,90 @@ int uvc_ctrl_set(struct uvc_video_chain *chain,
1164 * Dynamic controls 1164 * Dynamic controls
1165 */ 1165 */
1166 1166
1167/*
1168 * Query control information (size and flags) for XU controls.
1169 */
1170static int uvc_ctrl_fill_xu_info(struct uvc_device *dev,
1171 const struct uvc_control *ctrl, struct uvc_control_info *info)
1172{
1173 u8 *data;
1174 int ret;
1175
1176 data = kmalloc(2, GFP_KERNEL);
1177 if (data == NULL)
1178 return -ENOMEM;
1179
1180 memcpy(info->entity, ctrl->entity->extension.guidExtensionCode,
1181 sizeof(info->entity));
1182 info->index = ctrl->index;
1183 info->selector = ctrl->index + 1;
1184
1185 /* Query and verify the control length (GET_LEN) */
1186 ret = uvc_query_ctrl(dev, UVC_GET_LEN, ctrl->entity->id, dev->intfnum,
1187 info->selector, data, 2);
1188 if (ret < 0) {
1189 uvc_trace(UVC_TRACE_CONTROL,
1190 "GET_LEN failed on control %pUl/%u (%d).\n",
1191 info->entity, info->selector, ret);
1192 goto done;
1193 }
1194
1195 info->size = le16_to_cpup((__le16 *)data);
1196
1197 /* Query the control information (GET_INFO) */
1198 ret = uvc_query_ctrl(dev, UVC_GET_INFO, ctrl->entity->id, dev->intfnum,
1199 info->selector, data, 1);
1200 if (ret < 0) {
1201 uvc_trace(UVC_TRACE_CONTROL,
1202 "GET_INFO failed on control %pUl/%u (%d).\n",
1203 info->entity, info->selector, ret);
1204 goto done;
1205 }
1206
1207 info->flags = UVC_CONTROL_GET_MIN | UVC_CONTROL_GET_MAX
1208 | UVC_CONTROL_GET_RES | UVC_CONTROL_GET_DEF
1209 | (data[0] & UVC_CONTROL_CAP_GET ? UVC_CONTROL_GET_CUR : 0)
1210 | (data[0] & UVC_CONTROL_CAP_SET ? UVC_CONTROL_SET_CUR : 0)
1211 | (data[0] & UVC_CONTROL_CAP_AUTOUPDATE ?
1212 UVC_CONTROL_AUTO_UPDATE : 0);
1213
1214 uvc_trace(UVC_TRACE_CONTROL, "XU control %pUl/%u queried: len %u, "
1215 "flags { get %u set %u auto %u }.\n",
1216 info->entity, info->selector, info->size,
1217 (info->flags & UVC_CONTROL_GET_CUR) ? 1 : 0,
1218 (info->flags & UVC_CONTROL_SET_CUR) ? 1 : 0,
1219 (info->flags & UVC_CONTROL_AUTO_UPDATE) ? 1 : 0);
1220
1221done:
1222 kfree(data);
1223 return ret;
1224}
1225
1226static int uvc_ctrl_add_info(struct uvc_device *dev, struct uvc_control *ctrl,
1227 const struct uvc_control_info *info);
1228
1229static int uvc_ctrl_init_xu_ctrl(struct uvc_device *dev,
1230 struct uvc_control *ctrl)
1231{
1232 struct uvc_control_info info;
1233 int ret;
1234
1235 if (ctrl->initialized)
1236 return 0;
1237
1238 ret = uvc_ctrl_fill_xu_info(dev, ctrl, &info);
1239 if (ret < 0)
1240 return ret;
1241
1242 ret = uvc_ctrl_add_info(dev, ctrl, &info);
1243 if (ret < 0)
1244 uvc_trace(UVC_TRACE_CONTROL, "Failed to initialize control "
1245 "%pUl/%u on device %s entity %u\n", info.entity,
1246 info.selector, dev->udev->devpath, ctrl->entity->id);
1247
1248 return ret;
1249}
1250
1167int uvc_xu_ctrl_query(struct uvc_video_chain *chain, 1251int uvc_xu_ctrl_query(struct uvc_video_chain *chain,
1168 struct uvc_xu_control *xctrl, int set) 1252 struct uvc_xu_control *xctrl, int set)
1169{ 1253{
@@ -1186,13 +1270,10 @@ int uvc_xu_ctrl_query(struct uvc_video_chain *chain,
1186 return -EINVAL; 1270 return -EINVAL;
1187 } 1271 }
1188 1272
1189 /* Find the control. */ 1273 /* Find the control and perform delayed initialization if needed. */
1190 for (i = 0; i < entity->ncontrols; ++i) { 1274 for (i = 0; i < entity->ncontrols; ++i) {
1191 ctrl = &entity->controls[i]; 1275 ctrl = &entity->controls[i];
1192 if (!ctrl->initialized) 1276 if (ctrl->index == xctrl->selector - 1) {
1193 continue;
1194
1195 if (ctrl->info.selector == xctrl->selector) {
1196 found = 1; 1277 found = 1;
1197 break; 1278 break;
1198 } 1279 }
@@ -1204,6 +1285,10 @@ int uvc_xu_ctrl_query(struct uvc_video_chain *chain,
1204 return -EINVAL; 1285 return -EINVAL;
1205 } 1286 }
1206 1287
1288 ret = uvc_ctrl_init_xu_ctrl(chain->dev, ctrl);
1289 if (ret < 0)
1290 return -ENOENT;
1291
1207 /* Validate control data size. */ 1292 /* Validate control data size. */
1208 if (ctrl->info.size != xctrl->size) 1293 if (ctrl->info.size != xctrl->size)
1209 return -EINVAL; 1294 return -EINVAL;
@@ -1295,65 +1380,6 @@ int uvc_ctrl_resume_device(struct uvc_device *dev)
1295 */ 1380 */
1296 1381
1297/* 1382/*
1298 * Query control information (size and flags) for XU controls.
1299 */
1300static int uvc_ctrl_fill_xu_info(struct uvc_device *dev,
1301 const struct uvc_control *ctrl, struct uvc_control_info *info)
1302{
1303 u8 *data;
1304 int ret;
1305
1306 data = kmalloc(2, GFP_KERNEL);
1307 if (data == NULL)
1308 return -ENOMEM;
1309
1310 memcpy(info->entity, ctrl->entity->extension.guidExtensionCode,
1311 sizeof(info->entity));
1312 info->index = ctrl->index;
1313 info->selector = ctrl->index + 1;
1314
1315 /* Query and verify the control length (GET_LEN) */
1316 ret = uvc_query_ctrl(dev, UVC_GET_LEN, ctrl->entity->id, dev->intfnum,
1317 info->selector, data, 2);
1318 if (ret < 0) {
1319 uvc_trace(UVC_TRACE_CONTROL,
1320 "GET_LEN failed on control %pUl/%u (%d).\n",
1321 info->entity, info->selector, ret);
1322 goto done;
1323 }
1324
1325 info->size = le16_to_cpup((__le16 *)data);
1326
1327 /* Query the control information (GET_INFO) */
1328 ret = uvc_query_ctrl(dev, UVC_GET_INFO, ctrl->entity->id, dev->intfnum,
1329 info->selector, data, 1);
1330 if (ret < 0) {
1331 uvc_trace(UVC_TRACE_CONTROL,
1332 "GET_INFO failed on control %pUl/%u (%d).\n",
1333 info->entity, info->selector, ret);
1334 goto done;
1335 }
1336
1337 info->flags = UVC_CONTROL_GET_MIN | UVC_CONTROL_GET_MAX
1338 | UVC_CONTROL_GET_RES | UVC_CONTROL_GET_DEF
1339 | (data[0] & UVC_CONTROL_CAP_GET ? UVC_CONTROL_GET_CUR : 0)
1340 | (data[0] & UVC_CONTROL_CAP_SET ? UVC_CONTROL_SET_CUR : 0)
1341 | (data[0] & UVC_CONTROL_CAP_AUTOUPDATE ?
1342 UVC_CONTROL_AUTO_UPDATE : 0);
1343
1344 uvc_trace(UVC_TRACE_CONTROL, "XU control %pUl/%u queried: len %u, "
1345 "flags { get %u set %u auto %u }.\n",
1346 info->entity, info->selector, info->size,
1347 (info->flags & UVC_CONTROL_GET_CUR) ? 1 : 0,
1348 (info->flags & UVC_CONTROL_SET_CUR) ? 1 : 0,
1349 (info->flags & UVC_CONTROL_AUTO_UPDATE) ? 1 : 0);
1350
1351done:
1352 kfree(data);
1353 return ret;
1354}
1355
1356/*
1357 * Add control information to a given control. 1383 * Add control information to a given control.
1358 */ 1384 */
1359static int uvc_ctrl_add_info(struct uvc_device *dev, struct uvc_control *ctrl, 1385static int uvc_ctrl_add_info(struct uvc_device *dev, struct uvc_control *ctrl,
@@ -1434,7 +1460,7 @@ int uvc_ctrl_add_mapping(struct uvc_video_chain *chain,
1434 1460
1435 if (mapping->id & ~V4L2_CTRL_ID_MASK) { 1461 if (mapping->id & ~V4L2_CTRL_ID_MASK) {
1436 uvc_trace(UVC_TRACE_CONTROL, "Can't add mapping '%s', control " 1462 uvc_trace(UVC_TRACE_CONTROL, "Can't add mapping '%s', control "
1437 "control id 0x%08x is invalid.\n", mapping->name, 1463 "id 0x%08x is invalid.\n", mapping->name,
1438 mapping->id); 1464 mapping->id);
1439 return -EINVAL; 1465 return -EINVAL;
1440 } 1466 }
@@ -1443,13 +1469,13 @@ int uvc_ctrl_add_mapping(struct uvc_video_chain *chain,
1443 list_for_each_entry(entity, &dev->entities, list) { 1469 list_for_each_entry(entity, &dev->entities, list) {
1444 unsigned int i; 1470 unsigned int i;
1445 1471
1446 if (!uvc_entity_match_guid(entity, mapping->entity)) 1472 if (UVC_ENTITY_TYPE(entity) != UVC_VC_EXTENSION_UNIT ||
1473 !uvc_entity_match_guid(entity, mapping->entity))
1447 continue; 1474 continue;
1448 1475
1449 for (i = 0; i < entity->ncontrols; ++i) { 1476 for (i = 0; i < entity->ncontrols; ++i) {
1450 ctrl = &entity->controls[i]; 1477 ctrl = &entity->controls[i];
1451 if (ctrl->initialized && 1478 if (ctrl->index == mapping->selector - 1) {
1452 ctrl->info.selector == mapping->selector) {
1453 found = 1; 1479 found = 1;
1454 break; 1480 break;
1455 } 1481 }
@@ -1464,6 +1490,13 @@ int uvc_ctrl_add_mapping(struct uvc_video_chain *chain,
1464 if (mutex_lock_interruptible(&chain->ctrl_mutex)) 1490 if (mutex_lock_interruptible(&chain->ctrl_mutex))
1465 return -ERESTARTSYS; 1491 return -ERESTARTSYS;
1466 1492
1493 /* Perform delayed initialization of XU controls */
1494 ret = uvc_ctrl_init_xu_ctrl(dev, ctrl);
1495 if (ret < 0) {
1496 ret = -ENOENT;
1497 goto done;
1498 }
1499
1467 list_for_each_entry(map, &ctrl->info.mappings, list) { 1500 list_for_each_entry(map, &ctrl->info.mappings, list) {
1468 if (mapping->id == map->id) { 1501 if (mapping->id == map->id) {
1469 uvc_trace(UVC_TRACE_CONTROL, "Can't add mapping '%s', " 1502 uvc_trace(UVC_TRACE_CONTROL, "Can't add mapping '%s', "
@@ -1567,26 +1600,13 @@ static void uvc_ctrl_init_ctrl(struct uvc_device *dev, struct uvc_control *ctrl)
1567 const struct uvc_control_mapping *mend = 1600 const struct uvc_control_mapping *mend =
1568 mapping + ARRAY_SIZE(uvc_ctrl_mappings); 1601 mapping + ARRAY_SIZE(uvc_ctrl_mappings);
1569 1602
1570 /* Query XU controls for control information */ 1603 /* XU controls initialization requires querying the device for control
1571 if (UVC_ENTITY_TYPE(ctrl->entity) == UVC_VC_EXTENSION_UNIT) { 1604 * information. As some buggy UVC devices will crash when queried
1572 struct uvc_control_info info; 1605 * repeatedly in a tight loop, delay XU controls initialization until
1573 int ret; 1606 * first use.
1574 1607 */
1575 ret = uvc_ctrl_fill_xu_info(dev, ctrl, &info); 1608 if (UVC_ENTITY_TYPE(ctrl->entity) == UVC_VC_EXTENSION_UNIT)
1576 if (ret < 0)
1577 return;
1578
1579 ret = uvc_ctrl_add_info(dev, ctrl, &info);
1580 if (ret < 0) {
1581 /* Skip the control */
1582 uvc_trace(UVC_TRACE_CONTROL, "Failed to initialize "
1583 "control %pUl/%u on device %s entity %u\n",
1584 info.entity, info.selector, dev->udev->devpath,
1585 ctrl->entity->id);
1586 memset(ctrl, 0, sizeof(*ctrl));
1587 }
1588 return; 1609 return;
1589 }
1590 1610
1591 for (; info < iend; ++info) { 1611 for (; info < iend; ++info) {
1592 if (uvc_entity_match_guid(ctrl->entity, info->entity) && 1612 if (uvc_entity_match_guid(ctrl->entity, info->entity) &&