aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/media/pwc/pwc-ctrl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/media/pwc/pwc-ctrl.c')
-rw-r--r--drivers/usb/media/pwc/pwc-ctrl.c264
1 files changed, 89 insertions, 175 deletions
diff --git a/drivers/usb/media/pwc/pwc-ctrl.c b/drivers/usb/media/pwc/pwc-ctrl.c
index 359c4b2df735..3ebb6e9cdf92 100644
--- a/drivers/usb/media/pwc/pwc-ctrl.c
+++ b/drivers/usb/media/pwc/pwc-ctrl.c
@@ -1152,45 +1152,6 @@ int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
1152 /* End of Add-Ons */ 1152 /* End of Add-Ons */
1153 /* ************************************************* */ 1153 /* ************************************************* */
1154 1154
1155/* Linux 2.5.something and 2.6 pass direct pointers to arguments of
1156 ioctl() calls. With 2.4, you have to do tedious copy_from_user()
1157 and copy_to_user() calls. With these macros we circumvent this,
1158 and let me maintain only one source file. The functionality is
1159 exactly the same otherwise.
1160 */
1161
1162#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
1163
1164/* define local variable for arg */
1165#define ARG_DEF(ARG_type, ARG_name)\
1166 ARG_type *ARG_name = arg;
1167/* copy arg to local variable */
1168#define ARG_IN(ARG_name) /* nothing */
1169/* argument itself (referenced) */
1170#define ARGR(ARG_name) (*ARG_name)
1171/* argument address */
1172#define ARGA(ARG_name) ARG_name
1173/* copy local variable to arg */
1174#define ARG_OUT(ARG_name) /* nothing */
1175
1176#else
1177
1178#define ARG_DEF(ARG_type, ARG_name)\
1179 ARG_type ARG_name;
1180#define ARG_IN(ARG_name)\
1181 if (copy_from_user(&ARG_name, arg, sizeof(ARG_name))) {\
1182 ret = -EFAULT;\
1183 break;\
1184 }
1185#define ARGR(ARG_name) ARG_name
1186#define ARGA(ARG_name) &ARG_name
1187#define ARG_OUT(ARG_name)\
1188 if (copy_to_user(arg, &ARG_name, sizeof(ARG_name))) {\
1189 ret = -EFAULT;\
1190 break;\
1191 }
1192
1193#endif
1194 1155
1195int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) 1156int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
1196{ 1157{
@@ -1220,243 +1181,206 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
1220 1181
1221 case VIDIOCPWCSCQUAL: 1182 case VIDIOCPWCSCQUAL:
1222 { 1183 {
1223 ARG_DEF(int, qual) 1184 int *qual = arg;
1224 1185
1225 ARG_IN(qual) 1186 if (*qual < 0 || *qual > 3)
1226 if (ARGR(qual) < 0 || ARGR(qual) > 3)
1227 ret = -EINVAL; 1187 ret = -EINVAL;
1228 else 1188 else
1229 ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, ARGR(qual), pdev->vsnapshot); 1189 ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, *qual, pdev->vsnapshot);
1230 if (ret >= 0) 1190 if (ret >= 0)
1231 pdev->vcompression = ARGR(qual); 1191 pdev->vcompression = *qual;
1232 break; 1192 break;
1233 } 1193 }
1234 1194
1235 case VIDIOCPWCGCQUAL: 1195 case VIDIOCPWCGCQUAL:
1236 { 1196 {
1237 ARG_DEF(int, qual) 1197 int *qual = arg;
1238 1198 *qual = pdev->vcompression;
1239 ARGR(qual) = pdev->vcompression;
1240 ARG_OUT(qual)
1241 break; 1199 break;
1242 } 1200 }
1243 1201
1244 case VIDIOCPWCPROBE: 1202 case VIDIOCPWCPROBE:
1245 { 1203 {
1246 ARG_DEF(struct pwc_probe, probe) 1204 struct pwc_probe *probe = arg;
1247 1205 strcpy(probe->name, pdev->vdev->name);
1248 strcpy(ARGR(probe).name, pdev->vdev->name); 1206 probe->type = pdev->type;
1249 ARGR(probe).type = pdev->type;
1250 ARG_OUT(probe)
1251 break; 1207 break;
1252 } 1208 }
1253 1209
1254 case VIDIOCPWCGSERIAL: 1210 case VIDIOCPWCGSERIAL:
1255 { 1211 {
1256 ARG_DEF(struct pwc_serial, serial) 1212 struct pwc_serial *serial = arg;
1257 1213 strcpy(serial->serial, pdev->serial);
1258 strcpy(ARGR(serial).serial, pdev->serial);
1259 ARG_OUT(serial)
1260 break; 1214 break;
1261 } 1215 }
1262 1216
1263 case VIDIOCPWCSAGC: 1217 case VIDIOCPWCSAGC:
1264 { 1218 {
1265 ARG_DEF(int, agc) 1219 int *agc = arg;
1266 1220 if (pwc_set_agc(pdev, *agc < 0 ? 1 : 0, *agc))
1267 ARG_IN(agc)
1268 if (pwc_set_agc(pdev, ARGR(agc) < 0 ? 1 : 0, ARGR(agc)))
1269 ret = -EINVAL; 1221 ret = -EINVAL;
1270 break; 1222 break;
1271 } 1223 }
1272 1224
1273 case VIDIOCPWCGAGC: 1225 case VIDIOCPWCGAGC:
1274 { 1226 {
1275 ARG_DEF(int, agc) 1227 int *agc = arg;
1276 1228
1277 if (pwc_get_agc(pdev, ARGA(agc))) 1229 if (pwc_get_agc(pdev, agc))
1278 ret = -EINVAL; 1230 ret = -EINVAL;
1279 ARG_OUT(agc)
1280 break; 1231 break;
1281 } 1232 }
1282 1233
1283 case VIDIOCPWCSSHUTTER: 1234 case VIDIOCPWCSSHUTTER:
1284 { 1235 {
1285 ARG_DEF(int, shutter_speed) 1236 int *shutter_speed = arg;
1286 1237 ret = pwc_set_shutter_speed(pdev, *shutter_speed < 0 ? 1 : 0, *shutter_speed);
1287 ARG_IN(shutter_speed)
1288 ret = pwc_set_shutter_speed(pdev, ARGR(shutter_speed) < 0 ? 1 : 0, ARGR(shutter_speed));
1289 break; 1238 break;
1290 } 1239 }
1291 1240
1292 case VIDIOCPWCSAWB: 1241 case VIDIOCPWCSAWB:
1293 { 1242 {
1294 ARG_DEF(struct pwc_whitebalance, wb) 1243 struct pwc_whitebalance *wb = arg;
1295 1244
1296 ARG_IN(wb) 1245 ret = pwc_set_awb(pdev, wb->mode);
1297 ret = pwc_set_awb(pdev, ARGR(wb).mode); 1246 if (ret >= 0 && wb->mode == PWC_WB_MANUAL) {
1298 if (ret >= 0 && ARGR(wb).mode == PWC_WB_MANUAL) { 1247 pwc_set_red_gain(pdev, wb->manual_red);
1299 pwc_set_red_gain(pdev, ARGR(wb).manual_red); 1248 pwc_set_blue_gain(pdev, wb->manual_blue);
1300 pwc_set_blue_gain(pdev, ARGR(wb).manual_blue);
1301 } 1249 }
1302 break; 1250 break;
1303 } 1251 }
1304 1252
1305 case VIDIOCPWCGAWB: 1253 case VIDIOCPWCGAWB:
1306 { 1254 {
1307 ARG_DEF(struct pwc_whitebalance, wb) 1255 struct pwc_whitebalance *wb = arg;
1308 1256
1309 memset(ARGA(wb), 0, sizeof(struct pwc_whitebalance)); 1257 memset(wb, 0, sizeof(struct pwc_whitebalance));
1310 ARGR(wb).mode = pwc_get_awb(pdev); 1258 wb->mode = pwc_get_awb(pdev);
1311 if (ARGR(wb).mode < 0) 1259 if (wb->mode < 0)
1312 ret = -EINVAL; 1260 ret = -EINVAL;
1313 else { 1261 else {
1314 if (ARGR(wb).mode == PWC_WB_MANUAL) { 1262 if (wb->mode == PWC_WB_MANUAL) {
1315 ret = pwc_get_red_gain(pdev, &ARGR(wb).manual_red); 1263 ret = pwc_get_red_gain(pdev, &wb->manual_red);
1316 if (ret < 0) 1264 if (ret < 0)
1317 break; 1265 break;
1318 ret = pwc_get_blue_gain(pdev, &ARGR(wb).manual_blue); 1266 ret = pwc_get_blue_gain(pdev, &wb->manual_blue);
1319 if (ret < 0) 1267 if (ret < 0)
1320 break; 1268 break;
1321 } 1269 }
1322 if (ARGR(wb).mode == PWC_WB_AUTO) { 1270 if (wb->mode == PWC_WB_AUTO) {
1323 ret = pwc_read_red_gain(pdev, &ARGR(wb).read_red); 1271 ret = pwc_read_red_gain(pdev, &wb->read_red);
1324 if (ret < 0) 1272 if (ret < 0)
1325 break; 1273 break;
1326 ret =pwc_read_blue_gain(pdev, &ARGR(wb).read_blue); 1274 ret = pwc_read_blue_gain(pdev, &wb->read_blue);
1327 if (ret < 0) 1275 if (ret < 0)
1328 break; 1276 break;
1329 } 1277 }
1330 } 1278 }
1331 ARG_OUT(wb)
1332 break; 1279 break;
1333 } 1280 }
1334 1281
1335 case VIDIOCPWCSAWBSPEED: 1282 case VIDIOCPWCSAWBSPEED:
1336 { 1283 {
1337 ARG_DEF(struct pwc_wb_speed, wbs) 1284 struct pwc_wb_speed *wbs = arg;
1338 1285
1339 if (ARGR(wbs).control_speed > 0) { 1286 if (wbs->control_speed > 0) {
1340 ret = pwc_set_wb_speed(pdev, ARGR(wbs).control_speed); 1287 ret = pwc_set_wb_speed(pdev, wbs->control_speed);
1341 } 1288 }
1342 if (ARGR(wbs).control_delay > 0) { 1289 if (wbs->control_delay > 0) {
1343 ret = pwc_set_wb_delay(pdev, ARGR(wbs).control_delay); 1290 ret = pwc_set_wb_delay(pdev, wbs->control_delay);
1344 } 1291 }
1345 break; 1292 break;
1346 } 1293 }
1347 1294
1348 case VIDIOCPWCGAWBSPEED: 1295 case VIDIOCPWCGAWBSPEED:
1349 { 1296 {
1350 ARG_DEF(struct pwc_wb_speed, wbs) 1297 struct pwc_wb_speed *wbs = arg;
1351 1298
1352 ret = pwc_get_wb_speed(pdev, &ARGR(wbs).control_speed); 1299 ret = pwc_get_wb_speed(pdev, &wbs->control_speed);
1353 if (ret < 0) 1300 if (ret < 0)
1354 break; 1301 break;
1355 ret = pwc_get_wb_delay(pdev, &ARGR(wbs).control_delay); 1302 ret = pwc_get_wb_delay(pdev, &wbs->control_delay);
1356 if (ret < 0) 1303 if (ret < 0)
1357 break; 1304 break;
1358 ARG_OUT(wbs)
1359 break; 1305 break;
1360 } 1306 }
1361 1307
1362 case VIDIOCPWCSLED: 1308 case VIDIOCPWCSLED:
1363 { 1309 {
1364 ARG_DEF(struct pwc_leds, leds) 1310 struct pwc_leds *leds = arg;
1365 1311 ret = pwc_set_leds(pdev, leds->led_on, leds->led_off);
1366 ARG_IN(leds)
1367 ret = pwc_set_leds(pdev, ARGR(leds).led_on, ARGR(leds).led_off);
1368 break; 1312 break;
1369 } 1313 }
1370 1314
1371 1315
1372 case VIDIOCPWCGLED: 1316 case VIDIOCPWCGLED:
1373 { 1317 {
1374 ARG_DEF(struct pwc_leds, leds) 1318 struct pwc_leds *leds = arg;
1375 1319 ret = pwc_get_leds(pdev, &leds->led_on, &leds->led_off);
1376 ret = pwc_get_leds(pdev, &ARGR(leds).led_on, &ARGR(leds).led_off);
1377 ARG_OUT(leds)
1378 break; 1320 break;
1379 } 1321 }
1380 1322
1381 case VIDIOCPWCSCONTOUR: 1323 case VIDIOCPWCSCONTOUR:
1382 { 1324 {
1383 ARG_DEF(int, contour) 1325 int *contour = arg;
1384 1326 ret = pwc_set_contour(pdev, *contour);
1385 ARG_IN(contour)
1386 ret = pwc_set_contour(pdev, ARGR(contour));
1387 break; 1327 break;
1388 } 1328 }
1389 1329
1390 case VIDIOCPWCGCONTOUR: 1330 case VIDIOCPWCGCONTOUR:
1391 { 1331 {
1392 ARG_DEF(int, contour) 1332 int *contour = arg;
1393 1333 ret = pwc_get_contour(pdev, contour);
1394 ret = pwc_get_contour(pdev, ARGA(contour));
1395 ARG_OUT(contour)
1396 break; 1334 break;
1397 } 1335 }
1398 1336
1399 case VIDIOCPWCSBACKLIGHT: 1337 case VIDIOCPWCSBACKLIGHT:
1400 { 1338 {
1401 ARG_DEF(int, backlight) 1339 int *backlight = arg;
1402 1340 ret = pwc_set_backlight(pdev, *backlight);
1403 ARG_IN(backlight)
1404 ret = pwc_set_backlight(pdev, ARGR(backlight));
1405 break; 1341 break;
1406 } 1342 }
1407 1343
1408 case VIDIOCPWCGBACKLIGHT: 1344 case VIDIOCPWCGBACKLIGHT:
1409 { 1345 {
1410 ARG_DEF(int, backlight) 1346 int *backlight = arg;
1411 1347 ret = pwc_get_backlight(pdev, backlight);
1412 ret = pwc_get_backlight(pdev, ARGA(backlight));
1413 ARG_OUT(backlight)
1414 break; 1348 break;
1415 } 1349 }
1416 1350
1417 case VIDIOCPWCSFLICKER: 1351 case VIDIOCPWCSFLICKER:
1418 { 1352 {
1419 ARG_DEF(int, flicker) 1353 int *flicker = arg;
1420 1354 ret = pwc_set_flicker(pdev, *flicker);
1421 ARG_IN(flicker)
1422 ret = pwc_set_flicker(pdev, ARGR(flicker));
1423 break; 1355 break;
1424 } 1356 }
1425 1357
1426 case VIDIOCPWCGFLICKER: 1358 case VIDIOCPWCGFLICKER:
1427 { 1359 {
1428 ARG_DEF(int, flicker) 1360 int *flicker = arg;
1429 1361 ret = pwc_get_flicker(pdev, flicker);
1430 ret = pwc_get_flicker(pdev, ARGA(flicker));
1431 ARG_OUT(flicker)
1432 break; 1362 break;
1433 } 1363 }
1434 1364
1435 case VIDIOCPWCSDYNNOISE: 1365 case VIDIOCPWCSDYNNOISE:
1436 { 1366 {
1437 ARG_DEF(int, dynnoise) 1367 int *dynnoise = arg;
1438 1368 ret = pwc_set_dynamic_noise(pdev, *dynnoise);
1439 ARG_IN(dynnoise)
1440 ret = pwc_set_dynamic_noise(pdev, ARGR(dynnoise));
1441 break; 1369 break;
1442 } 1370 }
1443 1371
1444 case VIDIOCPWCGDYNNOISE: 1372 case VIDIOCPWCGDYNNOISE:
1445 { 1373 {
1446 ARG_DEF(int, dynnoise) 1374 int *dynnoise = arg;
1447 1375 ret = pwc_get_dynamic_noise(pdev, dynnoise);
1448 ret = pwc_get_dynamic_noise(pdev, ARGA(dynnoise));
1449 ARG_OUT(dynnoise);
1450 break; 1376 break;
1451 } 1377 }
1452 1378
1453 case VIDIOCPWCGREALSIZE: 1379 case VIDIOCPWCGREALSIZE:
1454 { 1380 {
1455 ARG_DEF(struct pwc_imagesize, size) 1381 struct pwc_imagesize *size = arg;
1456 1382 size->width = pdev->image.x;
1457 ARGR(size).width = pdev->image.x; 1383 size->height = pdev->image.y;
1458 ARGR(size).height = pdev->image.y;
1459 ARG_OUT(size)
1460 break; 1384 break;
1461 } 1385 }
1462 1386
@@ -1464,10 +1388,9 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
1464 { 1388 {
1465 if (pdev->features & FEATURE_MOTOR_PANTILT) 1389 if (pdev->features & FEATURE_MOTOR_PANTILT)
1466 { 1390 {
1467 ARG_DEF(int, flags) 1391 int *flags = arg;
1468 1392
1469 ARG_IN(flags) 1393 ret = pwc_mpt_reset(pdev, *flags);
1470 ret = pwc_mpt_reset(pdev, ARGR(flags));
1471 if (ret >= 0) 1394 if (ret >= 0)
1472 { 1395 {
1473 pdev->pan_angle = 0; 1396 pdev->pan_angle = 0;
@@ -1485,10 +1408,8 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
1485 { 1408 {
1486 if (pdev->features & FEATURE_MOTOR_PANTILT) 1409 if (pdev->features & FEATURE_MOTOR_PANTILT)
1487 { 1410 {
1488 ARG_DEF(struct pwc_mpt_range, range) 1411 struct pwc_mpt_range *range = arg;
1489 1412 *range = pdev->angle_range;
1490 ARGR(range) = pdev->angle_range;
1491 ARG_OUT(range)
1492 } 1413 }
1493 else 1414 else
1494 { 1415 {
@@ -1503,21 +1424,19 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
1503 1424
1504 if (pdev->features & FEATURE_MOTOR_PANTILT) 1425 if (pdev->features & FEATURE_MOTOR_PANTILT)
1505 { 1426 {
1506 ARG_DEF(struct pwc_mpt_angles, angles) 1427 struct pwc_mpt_angles *angles = arg;
1507
1508 ARG_IN(angles)
1509 /* The camera can only set relative angles, so 1428 /* The camera can only set relative angles, so
1510 do some calculations when getting an absolute angle . 1429 do some calculations when getting an absolute angle .
1511 */ 1430 */
1512 if (ARGR(angles).absolute) 1431 if (angles->absolute)
1513 { 1432 {
1514 new_pan = ARGR(angles).pan; 1433 new_pan = angles->pan;
1515 new_tilt = ARGR(angles).tilt; 1434 new_tilt = angles->tilt;
1516 } 1435 }
1517 else 1436 else
1518 { 1437 {
1519 new_pan = pdev->pan_angle + ARGR(angles).pan; 1438 new_pan = pdev->pan_angle + angles->pan;
1520 new_tilt = pdev->tilt_angle + ARGR(angles).tilt; 1439 new_tilt = pdev->tilt_angle + angles->tilt;
1521 } 1440 }
1522 /* check absolute ranges */ 1441 /* check absolute ranges */
1523 if (new_pan < pdev->angle_range.pan_min || 1442 if (new_pan < pdev->angle_range.pan_min ||
@@ -1560,12 +1479,11 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
1560 1479
1561 if (pdev->features & FEATURE_MOTOR_PANTILT) 1480 if (pdev->features & FEATURE_MOTOR_PANTILT)
1562 { 1481 {
1563 ARG_DEF(struct pwc_mpt_angles, angles) 1482 struct pwc_mpt_angles *angles = arg;
1564 1483
1565 ARGR(angles).absolute = 1; 1484 angles->absolute = 1;
1566 ARGR(angles).pan = pdev->pan_angle; 1485 angles->pan = pdev->pan_angle;
1567 ARGR(angles).tilt = pdev->tilt_angle; 1486 angles->tilt = pdev->tilt_angle;
1568 ARG_OUT(angles)
1569 } 1487 }
1570 else 1488 else
1571 { 1489 {
@@ -1578,10 +1496,8 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
1578 { 1496 {
1579 if (pdev->features & FEATURE_MOTOR_PANTILT) 1497 if (pdev->features & FEATURE_MOTOR_PANTILT)
1580 { 1498 {
1581 ARG_DEF(struct pwc_mpt_status, status) 1499 struct pwc_mpt_status *status = arg;
1582 1500 ret = pwc_mpt_get_status(pdev, status);
1583 ret = pwc_mpt_get_status(pdev, ARGA(status));
1584 ARG_OUT(status)
1585 } 1501 }
1586 else 1502 else
1587 { 1503 {
@@ -1592,24 +1508,22 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
1592 1508
1593 case VIDIOCPWCGVIDCMD: 1509 case VIDIOCPWCGVIDCMD:
1594 { 1510 {
1595 ARG_DEF(struct pwc_video_command, cmd); 1511 struct pwc_video_command *cmd = arg;
1596 1512
1597 ARGR(cmd).type = pdev->type; 1513 cmd->type = pdev->type;
1598 ARGR(cmd).release = pdev->release; 1514 cmd->release = pdev->release;
1599 ARGR(cmd).command_len = pdev->cmd_len; 1515 cmd->command_len = pdev->cmd_len;
1600 memcpy(&ARGR(cmd).command_buf, pdev->cmd_buf, pdev->cmd_len); 1516 memcpy(&cmd->command_buf, pdev->cmd_buf, pdev->cmd_len);
1601 ARGR(cmd).bandlength = pdev->vbandlength; 1517 cmd->bandlength = pdev->vbandlength;
1602 ARGR(cmd).frame_size = pdev->frame_size; 1518 cmd->frame_size = pdev->frame_size;
1603 ARG_OUT(cmd)
1604 break; 1519 break;
1605 } 1520 }
1606 /* 1521 /*
1607 case VIDIOCPWCGVIDTABLE: 1522 case VIDIOCPWCGVIDTABLE:
1608 { 1523 {
1609 ARG_DEF(struct pwc_table_init_buffer, table); 1524 struct pwc_table_init_buffer *table = arg;
1610 ARGR(table).len = pdev->cmd_len; 1525 table->len = pdev->cmd_len;
1611 memcpy(&ARGR(table).buffer, pdev->decompress_data, pdev->decompressor->table_size); 1526 memcpy(&table->buffer, pdev->decompress_data, pdev->decompressor->table_size);
1612 ARG_OUT(table)
1613 break; 1527 break;
1614 } 1528 }
1615 */ 1529 */