Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

staging/easycap: Eliminate BKL

No locking is required for normal operation of the driver, but locking
is needed to prevent an Oops during some hot-unplugging scenarios. The
BKL is replaced here by mutex locks together with traps to detect null
pointers following asynchronous device disconnection.

Signed-off-by: Mike Thomas <rmthomas@sciolus.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by

Mike Thomas and committed by
Greg Kroah-Hartman
ae59dad4 2a87a0b9

+697 -194
-1
drivers/staging/easycap/Kconfig
··· 1 1 config EASYCAP 2 2 tristate "EasyCAP USB ID 05e1:0408 support" 3 3 depends on USB && VIDEO_DEV 4 - depends on BKL # please fix 5 4 6 5 ---help--- 7 6 This is an integrated audio/video driver for EasyCAP cards with
+1
drivers/staging/easycap/Makefile
··· 10 10 ccflags-y += -DEASYCAP_IS_VIDEODEV_CLIENT 11 11 ccflags-y += -DEASYCAP_NEEDS_V4L2_DEVICE_H 12 12 ccflags-y += -DEASYCAP_NEEDS_V4L2_FOPS 13 + ccflags-y += -DEASYCAP_NEEDS_UNLOCKED_IOCTL 13 14
+14 -2
drivers/staging/easycap/easycap.h
··· 251 251 * STRUCTURE DEFINITIONS 252 252 */ 253 253 /*---------------------------------------------------------------------------*/ 254 + struct easycap_dongle { 255 + struct easycap *peasycap; 256 + struct mutex mutex_video; 257 + struct mutex mutex_audio; 258 + }; 259 + /*---------------------------------------------------------------------------*/ 254 260 struct data_buffer { 255 261 struct list_head list_head; 256 262 void *pgo; ··· 497 491 void easycap_complete(struct urb *); 498 492 int easycap_open(struct inode *, struct file *); 499 493 int easycap_release(struct inode *, struct file *); 500 - long easycap_ioctl(struct file *, unsigned int, unsigned long); 494 + long easycap_ioctl_noinode(struct file *, unsigned int, \ 495 + unsigned long); 496 + int easycap_ioctl(struct inode *, struct file *, unsigned int, \ 497 + unsigned long); 501 498 502 499 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ 503 500 #if defined(EASYCAP_IS_VIDEODEV_CLIENT) ··· 547 538 ssize_t easysnd_read(struct file *, char __user *, size_t, loff_t *); 548 539 int easysnd_open(struct inode *, struct file *); 549 540 int easysnd_release(struct inode *, struct file *); 550 - long easysnd_ioctl(struct file *, unsigned int, unsigned long); 541 + long easysnd_ioctl_noinode(struct file *, unsigned int, \ 542 + unsigned long); 543 + int easysnd_ioctl(struct inode *, struct file *, unsigned int, \ 544 + unsigned long); 551 545 unsigned int easysnd_poll(struct file *, poll_table *); 552 546 void easysnd_delete(struct kref *); 553 547 int submit_audio_urbs(struct easycap *);
+1
drivers/staging/easycap/easycap_debug.h
··· 26 26 /*****************************************************************************/ 27 27 extern int debug; 28 28 extern int gain; 29 + extern struct easycap_dongle easycap_dongle[];
+338 -88
drivers/staging/easycap/easycap_ioctl.c
··· 953 953 return -ENOENT; 954 954 } 955 955 /*****************************************************************************/ 956 - static int easycap_ioctl_bkl(struct inode *inode, struct file *file, 957 - unsigned int cmd, unsigned long arg) 956 + /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ 957 + #if ((defined(EASYCAP_IS_VIDEODEV_CLIENT)) || \ 958 + (defined(EASYCAP_NEEDS_UNLOCKED_IOCTL))) 959 + long 960 + easycap_ioctl_noinode(struct file *file, unsigned int cmd, unsigned long arg) { 961 + return (long)easycap_ioctl((struct inode *)NULL, file, cmd, arg); 962 + } 963 + #endif /*EASYCAP_IS_VIDEODEV_CLIENT||EASYCAP_NEEDS_UNLOCKED_IOCTL*/ 964 + /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ 965 + /*---------------------------------------------------------------------------*/ 966 + int 967 + easycap_ioctl(struct inode *inode, struct file *file, 968 + unsigned int cmd, unsigned long arg) 958 969 { 959 970 struct easycap *peasycap; 960 971 struct usb_device *p; 972 + int kd; 961 973 962 974 if (NULL == file) { 963 975 SAY("ERROR: file is NULL\n"); ··· 985 973 SAM("ERROR: peasycap->pusb_device is NULL\n"); 986 974 return -EFAULT; 987 975 } 976 + kd = isdongle(peasycap); 977 + if (0 <= kd && DONGLE_MANY > kd) { 978 + if (mutex_lock_interruptible(&easycap_dongle[kd].mutex_video)) { 979 + SAY("ERROR: cannot lock easycap_dongle[%i].mutex_video\n", kd); 980 + return -ERESTARTSYS; 981 + } 982 + JOM(4, "locked easycap_dongle[%i].mutex_video\n", kd); 983 + /*---------------------------------------------------------------------------*/ 984 + /* 985 + * MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap, 986 + * IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL. 987 + * IF NECESSARY, BAIL OUT. 988 + */ 989 + /*---------------------------------------------------------------------------*/ 990 + if (kd != isdongle(peasycap)) 991 + return -ERESTARTSYS; 992 + if (NULL == file) { 993 + SAY("ERROR: file is NULL\n"); 994 + mutex_unlock(&easycap_dongle[kd].mutex_video); 995 + return -ERESTARTSYS; 996 + } 997 + peasycap = file->private_data; 998 + if (NULL == peasycap) { 999 + SAY("ERROR: peasycap is NULL\n"); 1000 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1001 + return -ERESTARTSYS; 1002 + } 1003 + p = peasycap->pusb_device; 1004 + if (NULL == peasycap->pusb_device) { 1005 + SAM("ERROR: peasycap->pusb_device is NULL\n"); 1006 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1007 + return -ERESTARTSYS; 1008 + } 1009 + } else { 1010 + /*---------------------------------------------------------------------------*/ 1011 + /* 1012 + * IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap BEFORE THE 1013 + * ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL HAVE FAILED. BAIL OUT. 1014 + */ 1015 + /*---------------------------------------------------------------------------*/ 1016 + return -ERESTARTSYS; 1017 + } 988 1018 /*---------------------------------------------------------------------------*/ 989 1019 switch (cmd) { 990 1020 case VIDIOC_QUERYCAP: { ··· 1038 984 JOM(8, "VIDIOC_QUERYCAP\n"); 1039 985 1040 986 if (16 <= strlen(EASYCAP_DRIVER_VERSION)) { 1041 - SAM("ERROR: bad driver version string\n"); return -EINVAL; 987 + SAM("ERROR: bad driver version string\n"); 988 + mutex_unlock(&easycap_dongle[kd].mutex_video); 989 + return -EINVAL; 1042 990 } 1043 991 strcpy(&version[0], EASYCAP_DRIVER_VERSION); 1044 992 for (i = 0; i < 3; i++) ··· 1057 1001 if (0 != rc) { 1058 1002 SAM("ERROR: %i=strict_strtol(%s,.,,)\n", \ 1059 1003 rc, p1); 1004 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1060 1005 return -EINVAL; 1061 1006 } 1062 1007 k[i] = (int)lng; ··· 1087 1030 &v4l2_capability.bus_info[0]); 1088 1031 } 1089 1032 if (0 != copy_to_user((void __user *)arg, &v4l2_capability, \ 1090 - sizeof(struct v4l2_capability))) 1033 + sizeof(struct v4l2_capability))) { 1034 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1091 1035 return -EFAULT; 1036 + } 1092 1037 break; 1093 1038 } 1094 1039 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ··· 1101 1042 JOM(8, "VIDIOC_ENUMINPUT\n"); 1102 1043 1103 1044 if (0 != copy_from_user(&v4l2_input, (void __user *)arg, \ 1104 - sizeof(struct v4l2_input))) 1045 + sizeof(struct v4l2_input))) { 1046 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1105 1047 return -EFAULT; 1048 + } 1106 1049 1107 1050 index = v4l2_input.index; 1108 1051 memset(&v4l2_input, 0, sizeof(struct v4l2_input)); ··· 1184 1123 } 1185 1124 default: { 1186 1125 JOM(8, "%i=index: exhausts inputs\n", index); 1126 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1187 1127 return -EINVAL; 1188 1128 } 1189 1129 } 1190 1130 1191 1131 if (0 != copy_to_user((void __user *)arg, &v4l2_input, \ 1192 - sizeof(struct v4l2_input))) 1132 + sizeof(struct v4l2_input))) { 1133 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1193 1134 return -EFAULT; 1135 + } 1194 1136 break; 1195 1137 } 1196 1138 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ··· 1203 1139 JOM(8, "VIDIOC_G_INPUT\n"); 1204 1140 index = (__u32)peasycap->input; 1205 1141 JOM(8, "user is told: %i\n", index); 1206 - if (0 != copy_to_user((void __user *)arg, &index, sizeof(__u32))) 1142 + if (0 != copy_to_user((void __user *)arg, &index, sizeof(__u32))) { 1143 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1207 1144 return -EFAULT; 1145 + } 1208 1146 break; 1209 1147 } 1210 1148 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ··· 1217 1151 1218 1152 JOM(8, "VIDIOC_S_INPUT\n"); 1219 1153 1220 - if (0 != copy_from_user(&index, (void __user *)arg, sizeof(__u32))) 1154 + if (0 != copy_from_user(&index, (void __user *)arg, sizeof(__u32))) { 1155 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1221 1156 return -EFAULT; 1157 + } 1222 1158 1223 1159 JOM(8, "user requests input %i\n", index); 1224 1160 ··· 1231 1163 1232 1164 if ((0 > index) || (INPUT_MANY <= index)) { 1233 1165 JOM(8, "ERROR: bad requested input: %i\n", index); 1166 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1234 1167 return -EINVAL; 1235 1168 } 1236 1169 ··· 1240 1171 JOM(8, "newinput(.,%i) OK\n", (int)index); 1241 1172 } else { 1242 1173 SAM("ERROR: newinput(.,%i) returned %i\n", (int)index, rc); 1174 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1243 1175 return -EFAULT; 1244 1176 } 1245 1177 break; ··· 1248 1178 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1249 1179 case VIDIOC_ENUMAUDIO: { 1250 1180 JOM(8, "VIDIOC_ENUMAUDIO\n"); 1181 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1251 1182 return -EINVAL; 1252 1183 } 1253 1184 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ··· 1258 1187 JOM(8, "VIDIOC_ENUMAUDOUT\n"); 1259 1188 1260 1189 if (0 != copy_from_user(&v4l2_audioout, (void __user *)arg, \ 1261 - sizeof(struct v4l2_audioout))) 1190 + sizeof(struct v4l2_audioout))) { 1191 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1262 1192 return -EFAULT; 1193 + } 1263 1194 1264 - if (0 != v4l2_audioout.index) 1195 + if (0 != v4l2_audioout.index) { 1196 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1265 1197 return -EINVAL; 1198 + } 1266 1199 memset(&v4l2_audioout, 0, sizeof(struct v4l2_audioout)); 1267 1200 v4l2_audioout.index = 0; 1268 1201 strcpy(&v4l2_audioout.name[0], "Soundtrack"); 1269 1202 1270 1203 if (0 != copy_to_user((void __user *)arg, &v4l2_audioout, \ 1271 - sizeof(struct v4l2_audioout))) 1204 + sizeof(struct v4l2_audioout))) { 1205 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1272 1206 return -EFAULT; 1207 + } 1273 1208 break; 1274 1209 } 1275 1210 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ··· 1286 1209 JOM(8, "VIDIOC_QUERYCTRL\n"); 1287 1210 1288 1211 if (0 != copy_from_user(&v4l2_queryctrl, (void __user *)arg, \ 1289 - sizeof(struct v4l2_queryctrl))) 1212 + sizeof(struct v4l2_queryctrl))) { 1213 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1290 1214 return -EFAULT; 1215 + } 1291 1216 1292 1217 i1 = 0; 1293 1218 while (0xFFFFFFFF != easycap_control[i1].id) { ··· 1304 1225 } 1305 1226 if (0xFFFFFFFF == easycap_control[i1].id) { 1306 1227 JOM(8, "%i=index: exhausts controls\n", i1); 1228 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1307 1229 return -EINVAL; 1308 1230 } 1309 1231 if (0 != copy_to_user((void __user *)arg, &v4l2_queryctrl, \ 1310 - sizeof(struct v4l2_queryctrl))) 1232 + sizeof(struct v4l2_queryctrl))) { 1233 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1311 1234 return -EFAULT; 1235 + } 1312 1236 break; 1313 1237 } 1314 1238 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1315 1239 case VIDIOC_QUERYMENU: { 1316 1240 JOM(8, "VIDIOC_QUERYMENU unsupported\n"); 1241 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1317 1242 return -EINVAL; 1318 - break; 1319 1243 } 1320 1244 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1321 1245 case VIDIOC_G_CTRL: { ··· 1328 1246 pv4l2_control = kzalloc(sizeof(struct v4l2_control), GFP_KERNEL); 1329 1247 if (!pv4l2_control) { 1330 1248 SAM("ERROR: out of memory\n"); 1249 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1331 1250 return -ENOMEM; 1332 1251 } 1333 1252 if (0 != copy_from_user(pv4l2_control, (void __user *)arg, \ 1334 1253 sizeof(struct v4l2_control))) { 1335 1254 kfree(pv4l2_control); 1255 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1336 1256 return -EFAULT; 1337 1257 } 1338 1258 ··· 1376 1292 SAM("ERROR: unknown V4L2 control: 0x%08X=id\n", \ 1377 1293 pv4l2_control->id); 1378 1294 kfree(pv4l2_control); 1295 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1379 1296 return -EINVAL; 1380 1297 } 1381 1298 } 1382 1299 if (0 != copy_to_user((void __user *)arg, pv4l2_control, \ 1383 1300 sizeof(struct v4l2_control))) { 1384 1301 kfree(pv4l2_control); 1302 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1385 1303 return -EFAULT; 1386 1304 } 1387 1305 kfree(pv4l2_control); ··· 1402 1316 JOM(8, "VIDIOC_S_CTRL\n"); 1403 1317 1404 1318 if (0 != copy_from_user(&v4l2_control, (void __user *)arg, \ 1405 - sizeof(struct v4l2_control))) 1319 + sizeof(struct v4l2_control))) { 1320 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1406 1321 return -EFAULT; 1322 + } 1407 1323 1408 1324 switch (v4l2_control.id) { 1409 1325 case V4L2_CID_BRIGHTNESS: { ··· 1454 1366 default: { 1455 1367 SAM("ERROR: unknown V4L2 control: 0x%08X=id\n", \ 1456 1368 v4l2_control.id); 1369 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1457 1370 return -EINVAL; 1458 - } 1371 + } 1459 1372 } 1460 1373 break; 1461 1374 } 1462 1375 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1463 1376 case VIDIOC_S_EXT_CTRLS: { 1464 1377 JOM(8, "VIDIOC_S_EXT_CTRLS unsupported\n"); 1378 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1465 1379 return -EINVAL; 1466 1380 } 1467 1381 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ··· 1474 1384 JOM(8, "VIDIOC_ENUM_FMT\n"); 1475 1385 1476 1386 if (0 != copy_from_user(&v4l2_fmtdesc, (void __user *)arg, \ 1477 - sizeof(struct v4l2_fmtdesc))) 1387 + sizeof(struct v4l2_fmtdesc))) { 1388 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1478 1389 return -EFAULT; 1390 + } 1479 1391 1480 1392 index = v4l2_fmtdesc.index; 1481 1393 memset(&v4l2_fmtdesc, 0, sizeof(struct v4l2_fmtdesc)); ··· 1530 1438 } 1531 1439 default: { 1532 1440 JOM(8, "%i=index: exhausts formats\n", index); 1441 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1533 1442 return -EINVAL; 1534 1443 } 1535 1444 } 1536 1445 if (0 != copy_to_user((void __user *)arg, &v4l2_fmtdesc, \ 1537 - sizeof(struct v4l2_fmtdesc))) 1446 + sizeof(struct v4l2_fmtdesc))) { 1447 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1538 1448 return -EFAULT; 1449 + } 1539 1450 break; 1540 1451 } 1541 1452 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ··· 1554 1459 JOM(8, "VIDIOC_ENUM_FRAMESIZES\n"); 1555 1460 1556 1461 if (0 != copy_from_user(&v4l2_frmsizeenum, (void __user *)arg, \ 1557 - sizeof(struct v4l2_frmsizeenum))) 1462 + sizeof(struct v4l2_frmsizeenum))) { 1463 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1558 1464 return -EFAULT; 1465 + } 1559 1466 1560 1467 index = v4l2_frmsizeenum.index; 1561 1468 ··· 1607 1510 } 1608 1511 default: { 1609 1512 JOM(8, "%i=index: exhausts framesizes\n", index); 1513 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1610 1514 return -EINVAL; 1611 1515 } 1612 1516 } ··· 1665 1567 } 1666 1568 default: { 1667 1569 JOM(8, "%i=index: exhausts framesizes\n", index); 1570 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1668 1571 return -EINVAL; 1669 1572 } 1670 1573 } 1671 1574 } 1672 1575 if (0 != copy_to_user((void __user *)arg, &v4l2_frmsizeenum, \ 1673 - sizeof(struct v4l2_frmsizeenum))) 1576 + sizeof(struct v4l2_frmsizeenum))) { 1577 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1674 1578 return -EFAULT; 1579 + } 1675 1580 break; 1676 1581 } 1677 1582 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ··· 1701 1600 1702 1601 if (0 != copy_from_user(&v4l2_frmivalenum, (void __user *)arg, \ 1703 1602 sizeof(struct v4l2_frmivalenum))) { 1603 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1704 1604 return -EFAULT; 1705 1605 } 1706 1606 ··· 1728 1626 } 1729 1627 default: { 1730 1628 JOM(8, "%i=index: exhausts frameintervals\n", index); 1629 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1731 1630 return -EINVAL; 1732 1631 } 1733 1632 } 1734 1633 if (0 != copy_to_user((void __user *)arg, &v4l2_frmivalenum, \ 1735 - sizeof(struct v4l2_frmivalenum))) 1634 + sizeof(struct v4l2_frmivalenum))) { 1635 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1736 1636 return -EFAULT; 1637 + } 1737 1638 break; 1738 1639 } 1739 1640 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ··· 1748 1643 pv4l2_format = kzalloc(sizeof(struct v4l2_format), GFP_KERNEL); 1749 1644 if (!pv4l2_format) { 1750 1645 SAM("ERROR: out of memory\n"); 1751 - return -ENOMEM; 1646 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1647 + return -ENOMEM; 1752 1648 } 1753 1649 pv4l2_pix_format = kzalloc(sizeof(struct v4l2_pix_format), GFP_KERNEL); 1754 1650 if (!pv4l2_pix_format) { 1755 1651 SAM("ERROR: out of memory\n"); 1756 1652 kfree(pv4l2_format); 1653 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1757 1654 return -ENOMEM; 1758 1655 } 1759 1656 if (0 != copy_from_user(pv4l2_format, (void __user *)arg, \ 1760 1657 sizeof(struct v4l2_format))) { 1761 1658 kfree(pv4l2_format); 1762 1659 kfree(pv4l2_pix_format); 1660 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1763 1661 return -EFAULT; 1764 1662 } 1765 1663 1766 1664 if (pv4l2_format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { 1767 1665 kfree(pv4l2_format); 1768 1666 kfree(pv4l2_pix_format); 1667 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1769 1668 return -EINVAL; 1770 1669 } 1771 1670 ··· 1785 1676 sizeof(struct v4l2_format))) { 1786 1677 kfree(pv4l2_format); 1787 1678 kfree(pv4l2_pix_format); 1679 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1788 1680 return -EFAULT; 1789 1681 } 1790 1682 kfree(pv4l2_format); ··· 1809 1699 } 1810 1700 1811 1701 if (0 != copy_from_user(&v4l2_format, (void __user *)arg, \ 1812 - sizeof(struct v4l2_format))) 1702 + sizeof(struct v4l2_format))) { 1703 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1813 1704 return -EFAULT; 1705 + } 1814 1706 1815 1707 best_format = adjust_format(peasycap, \ 1816 1708 v4l2_format.fmt.pix.width, \ ··· 1821 1709 v4l2_format.fmt.pix.field, \ 1822 1710 try); 1823 1711 if (0 > best_format) { 1824 - if (-EBUSY == best_format) 1712 + if (-EBUSY == best_format) { 1713 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1825 1714 return -EBUSY; 1715 + } 1826 1716 JOM(8, "WARNING: adjust_format() returned %i\n", best_format); 1717 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1827 1718 return -ENOENT; 1828 1719 } 1829 1720 /*...........................................................................*/ ··· 1838 1723 JOM(8, "user is told: %s\n", &easycap_format[best_format].name[0]); 1839 1724 1840 1725 if (0 != copy_to_user((void __user *)arg, &v4l2_format, \ 1841 - sizeof(struct v4l2_format))) 1726 + sizeof(struct v4l2_format))) { 1727 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1842 1728 return -EFAULT; 1729 + } 1843 1730 break; 1844 1731 } 1845 1732 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ··· 1851 1734 JOM(8, "VIDIOC_CROPCAP\n"); 1852 1735 1853 1736 if (0 != copy_from_user(&v4l2_cropcap, (void __user *)arg, \ 1854 - sizeof(struct v4l2_cropcap))) 1737 + sizeof(struct v4l2_cropcap))) { 1738 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1855 1739 return -EFAULT; 1740 + } 1856 1741 1857 1742 if (v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 1858 1743 JOM(8, "v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE\n"); ··· 1875 1756 JOM(8, "user is told: %ix%i\n", peasycap->width, peasycap->height); 1876 1757 1877 1758 if (0 != copy_to_user((void __user *)arg, &v4l2_cropcap, \ 1878 - sizeof(struct v4l2_cropcap))) 1759 + sizeof(struct v4l2_cropcap))) { 1760 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1879 1761 return -EFAULT; 1762 + } 1880 1763 break; 1881 1764 } 1882 1765 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1883 1766 case VIDIOC_G_CROP: 1884 1767 case VIDIOC_S_CROP: { 1885 1768 JOM(8, "VIDIOC_G_CROP|VIDIOC_S_CROP unsupported\n"); 1769 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1886 1770 return -EINVAL; 1887 1771 } 1888 1772 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1889 1773 case VIDIOC_QUERYSTD: { 1890 1774 JOM(8, "VIDIOC_QUERYSTD: " \ 1891 1775 "EasyCAP is incapable of detecting standard\n"); 1776 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1892 1777 return -EINVAL; 1893 1778 break; 1894 1779 } ··· 1913 1790 JOM(8, "VIDIOC_ENUMSTD\n"); 1914 1791 1915 1792 if (0 != copy_from_user(&v4l2_standard, (void __user *)arg, \ 1916 - sizeof(struct v4l2_standard))) 1793 + sizeof(struct v4l2_standard))) { 1794 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1917 1795 return -EFAULT; 1796 + } 1918 1797 index = v4l2_standard.index; 1919 1798 1920 1799 last3 = last2; last2 = last1; last1 = last0; last0 = index; ··· 1936 1811 } 1937 1812 if (0xFFFF == peasycap_standard->mask) { 1938 1813 JOM(8, "%i=index: exhausts standards\n", index); 1814 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1939 1815 return -EINVAL; 1940 1816 } 1941 1817 JOM(8, "%i=index: %s\n", index, \ ··· 1947 1821 v4l2_standard.index = index; 1948 1822 1949 1823 if (0 != copy_to_user((void __user *)arg, &v4l2_standard, \ 1950 - sizeof(struct v4l2_standard))) 1824 + sizeof(struct v4l2_standard))) { 1825 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1951 1826 return -EFAULT; 1827 + } 1952 1828 break; 1953 1829 } 1954 1830 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ··· 1963 1835 if (0 > peasycap->standard_offset) { 1964 1836 JOM(8, "%i=peasycap->standard_offset\n", \ 1965 1837 peasycap->standard_offset); 1838 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1966 1839 return -EBUSY; 1967 1840 } 1968 1841 1969 1842 if (0 != copy_from_user(&std_id, (void __user *)arg, \ 1970 - sizeof(v4l2_std_id))) 1843 + sizeof(v4l2_std_id))) { 1844 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1971 1845 return -EFAULT; 1846 + } 1972 1847 1973 1848 peasycap_standard = &easycap_standard[peasycap->standard_offset]; 1974 1849 std_id = peasycap_standard->v4l2_standard.id; ··· 1980 1849 &peasycap_standard->v4l2_standard.name[0]); 1981 1850 1982 1851 if (0 != copy_to_user((void __user *)arg, &std_id, \ 1983 - sizeof(v4l2_std_id))) 1852 + sizeof(v4l2_std_id))) { 1853 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1984 1854 return -EFAULT; 1855 + } 1985 1856 break; 1986 1857 } 1987 1858 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ··· 1994 1861 JOM(8, "VIDIOC_S_STD\n"); 1995 1862 1996 1863 if (0 != copy_from_user(&std_id, (void __user *)arg, \ 1997 - sizeof(v4l2_std_id))) 1864 + sizeof(v4l2_std_id))) { 1865 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1998 1866 return -EFAULT; 1867 + } 1999 1868 2000 1869 JOM(8, "User requests standard: 0x%08X%08X\n", \ 2001 1870 (int)((std_id & (((v4l2_std_id)0xFFFFFFFF) << 32)) >> 32), \ ··· 2006 1871 rc = adjust_standard(peasycap, std_id); 2007 1872 if (0 > rc) { 2008 1873 JOM(8, "WARNING: adjust_standard() returned %i\n", rc); 1874 + mutex_unlock(&easycap_dongle[kd].mutex_video); 2009 1875 return -ENOENT; 2010 1876 } 2011 1877 break; ··· 2019 1883 JOM(8, "VIDIOC_REQBUFS\n"); 2020 1884 2021 1885 if (0 != copy_from_user(&v4l2_requestbuffers, (void __user *)arg, \ 2022 - sizeof(struct v4l2_requestbuffers))) 1886 + sizeof(struct v4l2_requestbuffers))) { 1887 + mutex_unlock(&easycap_dongle[kd].mutex_video); 2023 1888 return -EFAULT; 1889 + } 2024 1890 2025 - if (v4l2_requestbuffers.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 1891 + if (v4l2_requestbuffers.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { 1892 + mutex_unlock(&easycap_dongle[kd].mutex_video); 2026 1893 return -EINVAL; 2027 - if (v4l2_requestbuffers.memory != V4L2_MEMORY_MMAP) 1894 + } 1895 + if (v4l2_requestbuffers.memory != V4L2_MEMORY_MMAP) { 1896 + mutex_unlock(&easycap_dongle[kd].mutex_video); 2028 1897 return -EINVAL; 1898 + } 2029 1899 nbuffers = v4l2_requestbuffers.count; 2030 1900 JOM(8, " User requests %i buffers ...\n", nbuffers); 2031 1901 if (nbuffers < 2) ··· 2049 1907 peasycap->frame_buffer_many = nbuffers; 2050 1908 2051 1909 if (0 != copy_to_user((void __user *)arg, &v4l2_requestbuffers, \ 2052 - sizeof(struct v4l2_requestbuffers))) 1910 + sizeof(struct v4l2_requestbuffers))) { 1911 + mutex_unlock(&easycap_dongle[kd].mutex_video); 2053 1912 return -EFAULT; 1913 + } 2054 1914 break; 2055 1915 } 2056 1916 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ··· 2065 1921 if (peasycap->video_eof) { 2066 1922 JOM(8, "returning -EIO because %i=video_eof\n", \ 2067 1923 peasycap->video_eof); 1924 + mutex_unlock(&easycap_dongle[kd].mutex_video); 2068 1925 return -EIO; 2069 1926 } 2070 1927 2071 1928 if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \ 2072 - sizeof(struct v4l2_buffer))) 1929 + sizeof(struct v4l2_buffer))) { 1930 + mutex_unlock(&easycap_dongle[kd].mutex_video); 2073 1931 return -EFAULT; 1932 + } 2074 1933 2075 - if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 1934 + if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { 1935 + mutex_unlock(&easycap_dongle[kd].mutex_video); 2076 1936 return -EINVAL; 1937 + } 2077 1938 index = v4l2_buffer.index; 2078 1939 if (index < 0 || index >= peasycap->frame_buffer_many) 2079 1940 return -EINVAL; ··· 2107 1958 JOM(16, " %10i=length\n", v4l2_buffer.length); 2108 1959 2109 1960 if (0 != copy_to_user((void __user *)arg, &v4l2_buffer, \ 2110 - sizeof(struct v4l2_buffer))) 1961 + sizeof(struct v4l2_buffer))) { 1962 + mutex_unlock(&easycap_dongle[kd].mutex_video); 2111 1963 return -EFAULT; 1964 + } 2112 1965 break; 2113 1966 } 2114 1967 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ··· 2120 1969 JOM(8, "VIDIOC_QBUF\n"); 2121 1970 2122 1971 if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \ 2123 - sizeof(struct v4l2_buffer))) 1972 + sizeof(struct v4l2_buffer))) { 1973 + mutex_unlock(&easycap_dongle[kd].mutex_video); 2124 1974 return -EFAULT; 1975 + } 2125 1976 2126 - if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 1977 + if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { 1978 + mutex_unlock(&easycap_dongle[kd].mutex_video); 2127 1979 return -EINVAL; 2128 - if (v4l2_buffer.memory != V4L2_MEMORY_MMAP) 1980 + } 1981 + if (v4l2_buffer.memory != V4L2_MEMORY_MMAP) { 1982 + mutex_unlock(&easycap_dongle[kd].mutex_video); 2129 1983 return -EINVAL; 1984 + } 2130 1985 if (v4l2_buffer.index < 0 || \ 2131 - (v4l2_buffer.index >= peasycap->frame_buffer_many)) 1986 + (v4l2_buffer.index >= peasycap->frame_buffer_many)) { 1987 + mutex_unlock(&easycap_dongle[kd].mutex_video); 2132 1988 return -EINVAL; 1989 + } 2133 1990 v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED; 2134 1991 2135 1992 peasycap->done[v4l2_buffer.index] = 0; 2136 1993 peasycap->queued[v4l2_buffer.index] = V4L2_BUF_FLAG_QUEUED; 2137 1994 2138 1995 if (0 != copy_to_user((void __user *)arg, &v4l2_buffer, \ 2139 - sizeof(struct v4l2_buffer))) 1996 + sizeof(struct v4l2_buffer))) { 1997 + mutex_unlock(&easycap_dongle[kd].mutex_video); 2140 1998 return -EFAULT; 1999 + } 2141 2000 2142 2001 JOM(8, "..... user queueing frame buffer %i\n", \ 2143 2002 (int)v4l2_buffer.index); ··· 2178 2017 JOM(8, "returning -EIO because " \ 2179 2018 "%i=video_idle %i=video_eof\n", \ 2180 2019 peasycap->video_idle, peasycap->video_eof); 2020 + mutex_unlock(&easycap_dongle[kd].mutex_video); 2181 2021 return -EIO; 2182 2022 } 2183 2023 2184 2024 if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \ 2185 - sizeof(struct v4l2_buffer))) 2025 + sizeof(struct v4l2_buffer))) { 2026 + mutex_unlock(&easycap_dongle[kd].mutex_video); 2186 2027 return -EFAULT; 2028 + } 2187 2029 2188 - if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 2030 + if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { 2031 + mutex_unlock(&easycap_dongle[kd].mutex_video); 2189 2032 return -EINVAL; 2033 + } 2190 2034 2191 2035 if (true == peasycap->offerfields) { 2192 2036 /*-----------------------------------------------------------*/ ··· 2213 2047 2214 2048 if (!peasycap->video_isoc_streaming) { 2215 2049 JOM(16, "returning -EIO because video urbs not streaming\n"); 2050 + mutex_unlock(&easycap_dongle[kd].mutex_video); 2216 2051 return -EIO; 2217 2052 } 2218 2053 /*---------------------------------------------------------------------------*/ ··· 2230 2063 if (-EIO == rcdq) { 2231 2064 JOM(8, "returning -EIO because " \ 2232 2065 "dqbuf() returned -EIO\n"); 2066 + mutex_unlock(&easycap_dongle[kd].mutex_video); 2233 2067 return -EIO; 2234 2068 } 2235 2069 } while (0 != rcdq); 2236 2070 } else { 2237 - if (peasycap->video_eof) 2071 + if (peasycap->video_eof) { 2072 + mutex_unlock(&easycap_dongle[kd].mutex_video); 2238 2073 return -EIO; 2074 + } 2239 2075 } 2240 2076 if (V4L2_BUF_FLAG_DONE != peasycap->done[peasycap->frame_read]) { 2241 2077 SAM("ERROR: V4L2_BUF_FLAG_DONE != 0x%08X\n", \ ··· 2325 2155 JOM(16, " %10i=length\n", v4l2_buffer.length); 2326 2156 2327 2157 if (0 != copy_to_user((void __user *)arg, &v4l2_buffer, \ 2328 - sizeof(struct v4l2_buffer))) 2158 + sizeof(struct v4l2_buffer))) { 2159 + mutex_unlock(&easycap_dongle[kd].mutex_video); 2329 2160 return -EFAULT; 2161 + } 2330 2162 2331 2163 input = peasycap->frame_buffer[peasycap->frame_read][0].input; 2332 2164 if (0x08 & input) { ··· 2359 2187 peasycap->merit[i] = 0; 2360 2188 if ((struct usb_device *)NULL == peasycap->pusb_device) { 2361 2189 SAM("ERROR: peasycap->pusb_device is NULL\n"); 2190 + mutex_unlock(&easycap_dongle[kd].mutex_video); 2362 2191 return -EFAULT; 2363 2192 } 2364 2193 submit_video_urbs(peasycap); ··· 2375 2202 2376 2203 if ((struct usb_device *)NULL == peasycap->pusb_device) { 2377 2204 SAM("ERROR: peasycap->pusb_device is NULL\n"); 2205 + mutex_unlock(&easycap_dongle[kd].mutex_video); 2378 2206 return -EFAULT; 2379 2207 } 2380 2208 ··· 2401 2227 pv4l2_streamparm = kzalloc(sizeof(struct v4l2_streamparm), GFP_KERNEL); 2402 2228 if (!pv4l2_streamparm) { 2403 2229 SAM("ERROR: out of memory\n"); 2230 + mutex_unlock(&easycap_dongle[kd].mutex_video); 2404 2231 return -ENOMEM; 2405 2232 } 2406 2233 if (0 != copy_from_user(pv4l2_streamparm, (void __user *)arg, \ 2407 2234 sizeof(struct v4l2_streamparm))) { 2408 2235 kfree(pv4l2_streamparm); 2236 + mutex_unlock(&easycap_dongle[kd].mutex_video); 2409 2237 return -EFAULT; 2410 2238 } 2411 2239 2412 2240 if (pv4l2_streamparm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { 2413 2241 kfree(pv4l2_streamparm); 2242 + mutex_unlock(&easycap_dongle[kd].mutex_video); 2414 2243 return -EINVAL; 2415 2244 } 2416 2245 pv4l2_streamparm->parm.capture.capability = 0; ··· 2439 2262 if (0 != copy_to_user((void __user *)arg, pv4l2_streamparm, \ 2440 2263 sizeof(struct v4l2_streamparm))) { 2441 2264 kfree(pv4l2_streamparm); 2265 + mutex_unlock(&easycap_dongle[kd].mutex_video); 2442 2266 return -EFAULT; 2443 2267 } 2444 2268 kfree(pv4l2_streamparm); ··· 2448 2270 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 2449 2271 case VIDIOC_S_PARM: { 2450 2272 JOM(8, "VIDIOC_S_PARM unsupported\n"); 2273 + mutex_unlock(&easycap_dongle[kd].mutex_video); 2451 2274 return -EINVAL; 2452 2275 } 2453 2276 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 2454 2277 case VIDIOC_G_AUDIO: { 2455 2278 JOM(8, "VIDIOC_G_AUDIO unsupported\n"); 2279 + mutex_unlock(&easycap_dongle[kd].mutex_video); 2456 2280 return -EINVAL; 2457 2281 } 2458 2282 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 2459 2283 case VIDIOC_S_AUDIO: { 2460 2284 JOM(8, "VIDIOC_S_AUDIO unsupported\n"); 2285 + mutex_unlock(&easycap_dongle[kd].mutex_video); 2461 2286 return -EINVAL; 2462 2287 } 2463 2288 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 2464 2289 case VIDIOC_S_TUNER: { 2465 2290 JOM(8, "VIDIOC_S_TUNER unsupported\n"); 2291 + mutex_unlock(&easycap_dongle[kd].mutex_video); 2466 2292 return -EINVAL; 2467 2293 } 2468 2294 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ··· 2474 2292 case VIDIOC_S_FBUF: 2475 2293 case VIDIOC_OVERLAY: { 2476 2294 JOM(8, "VIDIOC_G_FBUF|VIDIOC_S_FBUF|VIDIOC_OVERLAY unsupported\n"); 2295 + mutex_unlock(&easycap_dongle[kd].mutex_video); 2477 2296 return -EINVAL; 2478 2297 } 2479 2298 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 2480 2299 case VIDIOC_G_TUNER: { 2481 2300 JOM(8, "VIDIOC_G_TUNER unsupported\n"); 2301 + mutex_unlock(&easycap_dongle[kd].mutex_video); 2482 2302 return -EINVAL; 2483 2303 } 2484 2304 case VIDIOC_G_FREQUENCY: 2485 2305 case VIDIOC_S_FREQUENCY: { 2486 2306 JOM(8, "VIDIOC_G_FREQUENCY|VIDIOC_S_FREQUENCY unsupported\n"); 2307 + mutex_unlock(&easycap_dongle[kd].mutex_video); 2487 2308 return -EINVAL; 2488 2309 } 2489 2310 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 2490 2311 default: { 2491 2312 JOM(8, "ERROR: unrecognized V4L2 IOCTL command: 0x%08X\n", cmd); 2313 + mutex_unlock(&easycap_dongle[kd].mutex_video); 2492 2314 return -ENOIOCTLCMD; 2493 2315 } 2494 2316 } 2317 + mutex_unlock(&easycap_dongle[kd].mutex_video); 2318 + JOM(4, "unlocked easycap_dongle[%i].mutex_video\n", kd); 2495 2319 return 0; 2496 2320 } 2497 - 2498 - long easycap_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 2499 - { 2500 - struct inode *inode = file->f_dentry->d_inode; 2501 - long ret; 2502 - 2503 - lock_kernel(); 2504 - ret = easycap_ioctl_bkl(inode, file, cmd, arg); 2505 - unlock_kernel(); 2506 - 2507 - return ret; 2508 - } 2509 2321 /*****************************************************************************/ 2510 - static int easysnd_ioctl_bkl(struct inode *inode, struct file *file, 2511 - unsigned int cmd, unsigned long arg) 2322 + /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ 2323 + #if ((defined(EASYCAP_IS_VIDEODEV_CLIENT)) || \ 2324 + (defined(EASYCAP_NEEDS_UNLOCKED_IOCTL))) 2325 + long 2326 + easysnd_ioctl_noinode(struct file *file, unsigned int cmd, unsigned long arg) { 2327 + return (long)easysnd_ioctl((struct inode *)NULL, file, cmd, arg); 2328 + } 2329 + #endif /*EASYCAP_IS_VIDEODEV_CLIENT||EASYCAP_NEEDS_UNLOCKED_IOCTL*/ 2330 + /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ 2331 + /*---------------------------------------------------------------------------*/ 2332 + int 2333 + easysnd_ioctl(struct inode *inode, struct file *file, 2334 + unsigned int cmd, unsigned long arg) 2512 2335 { 2513 2336 struct easycap *peasycap; 2514 2337 struct usb_device *p; 2338 + int kd; 2515 2339 2516 2340 if (NULL == file) { 2517 2341 SAY("ERROR: file is NULL\n"); ··· 2532 2344 if (NULL == p) { 2533 2345 SAM("ERROR: peasycap->pusb_device is NULL\n"); 2534 2346 return -EFAULT; 2347 + } 2348 + kd = isdongle(peasycap); 2349 + if (0 <= kd && DONGLE_MANY > kd) { 2350 + if (mutex_lock_interruptible(&easycap_dongle[kd].mutex_audio)) { 2351 + SAY("ERROR: cannot lock easycap_dongle[%i].mutex_audio\n", kd); 2352 + return -ERESTARTSYS; 2353 + } 2354 + JOM(4, "locked easycap_dongle[%i].mutex_audio\n", kd); 2355 + /*---------------------------------------------------------------------------*/ 2356 + /* 2357 + * MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap, 2358 + * IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL. 2359 + * IF NECESSARY, BAIL OUT. 2360 + */ 2361 + /*---------------------------------------------------------------------------*/ 2362 + if (kd != isdongle(peasycap)) 2363 + return -ERESTARTSYS; 2364 + if (NULL == file) { 2365 + SAY("ERROR: file is NULL\n"); 2366 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 2367 + return -ERESTARTSYS; 2368 + } 2369 + peasycap = file->private_data; 2370 + if (NULL == peasycap) { 2371 + SAY("ERROR: peasycap is NULL\n"); 2372 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 2373 + return -ERESTARTSYS; 2374 + } 2375 + p = peasycap->pusb_device; 2376 + if (NULL == peasycap->pusb_device) { 2377 + SAM("ERROR: peasycap->pusb_device is NULL\n"); 2378 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 2379 + return -ERESTARTSYS; 2380 + } 2381 + } else { 2382 + /*---------------------------------------------------------------------------*/ 2383 + /* 2384 + * IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap BEFORE THE 2385 + * ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL HAVE FAILED. BAIL OUT. 2386 + */ 2387 + /*---------------------------------------------------------------------------*/ 2388 + return -ERESTARTSYS; 2535 2389 } 2536 2390 /*---------------------------------------------------------------------------*/ 2537 2391 switch (cmd) { ··· 2593 2363 caps = 0x04400000; 2594 2364 #endif /*UPSAMPLE*/ 2595 2365 2596 - if (0 != copy_to_user((void __user *)arg, &caps, sizeof(int))) 2366 + if (0 != copy_to_user((void __user *)arg, &caps, sizeof(int))) { 2367 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 2597 2368 return -EFAULT; 2369 + } 2598 2370 break; 2599 2371 } 2600 2372 case SNDCTL_DSP_GETFMTS: { ··· 2615 2383 incoming = AFMT_S16_LE; 2616 2384 #endif /*UPSAMPLE*/ 2617 2385 2618 - if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) 2386 + if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) { 2387 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 2619 2388 return -EFAULT; 2389 + } 2620 2390 break; 2621 2391 } 2622 2392 case SNDCTL_DSP_SETFMT: { 2623 2393 int incoming, outgoing; 2624 2394 JOM(8, "SNDCTL_DSP_SETFMT\n"); 2625 - if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) 2395 + if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) { 2396 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 2626 2397 return -EFAULT; 2398 + } 2627 2399 JOM(8, "........... %i=incoming\n", incoming); 2628 2400 2629 2401 #if defined(UPSAMPLE) ··· 2647 2411 JOM(8, " cf. %i=AFMT_S16_LE\n", AFMT_S16_LE); 2648 2412 JOM(8, " cf. %i=AFMT_U8\n", AFMT_U8); 2649 2413 if (0 != copy_to_user((void __user *)arg, &outgoing, \ 2650 - sizeof(int))) 2414 + sizeof(int))) { 2415 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 2651 2416 return -EFAULT; 2417 + } 2418 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 2652 2419 return -EINVAL ; 2653 2420 } 2654 2421 break; ··· 2659 2420 case SNDCTL_DSP_STEREO: { 2660 2421 int incoming; 2661 2422 JOM(8, "SNDCTL_DSP_STEREO\n"); 2662 - if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) 2423 + if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) { 2424 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 2663 2425 return -EFAULT; 2426 + } 2664 2427 JOM(8, "........... %i=incoming\n", incoming); 2665 2428 2666 2429 #if defined(UPSAMPLE) ··· 2677 2436 incoming = 1; 2678 2437 #endif /*UPSAMPLE*/ 2679 2438 2680 - if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) 2439 + if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) { 2440 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 2681 2441 return -EFAULT; 2442 + } 2682 2443 break; 2683 2444 } 2684 2445 case SNDCTL_DSP_SPEED: { 2685 2446 int incoming; 2686 2447 JOM(8, "SNDCTL_DSP_SPEED\n"); 2687 - if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) 2448 + if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) { 2449 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 2688 2450 return -EFAULT; 2451 + } 2689 2452 JOM(8, "........... %i=incoming\n", incoming); 2690 2453 2691 2454 #if defined(UPSAMPLE) ··· 2704 2459 incoming = 48000; 2705 2460 #endif /*UPSAMPLE*/ 2706 2461 2707 - if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) 2462 + if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) { 2463 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 2708 2464 return -EFAULT; 2465 + } 2709 2466 break; 2710 2467 } 2711 2468 case SNDCTL_DSP_GETTRIGGER: { 2712 2469 int incoming; 2713 2470 JOM(8, "SNDCTL_DSP_GETTRIGGER\n"); 2714 - if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) 2471 + if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) { 2472 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 2715 2473 return -EFAULT; 2474 + } 2716 2475 JOM(8, "........... %i=incoming\n", incoming); 2717 2476 2718 2477 incoming = PCM_ENABLE_INPUT; 2719 - if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) 2478 + if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) { 2479 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 2720 2480 return -EFAULT; 2481 + } 2721 2482 break; 2722 2483 } 2723 2484 case SNDCTL_DSP_SETTRIGGER: { 2724 2485 int incoming; 2725 2486 JOM(8, "SNDCTL_DSP_SETTRIGGER\n"); 2726 - if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) 2487 + if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) { 2488 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 2727 2489 return -EFAULT; 2490 + } 2728 2491 JOM(8, "........... %i=incoming\n", incoming); 2729 2492 JOM(8, "........... cf 0x%x=PCM_ENABLE_INPUT " \ 2730 2493 "0x%x=PCM_ENABLE_OUTPUT\n", \ ··· 2746 2493 case SNDCTL_DSP_GETBLKSIZE: { 2747 2494 int incoming; 2748 2495 JOM(8, "SNDCTL_DSP_GETBLKSIZE\n"); 2749 - if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) 2496 + if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) { 2497 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 2750 2498 return -EFAULT; 2499 + } 2751 2500 JOM(8, "........... %i=incoming\n", incoming); 2752 2501 incoming = peasycap->audio_bytes_per_fragment; 2753 - if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) 2502 + if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) { 2503 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 2754 2504 return -EFAULT; 2505 + } 2755 2506 break; 2756 2507 } 2757 2508 case SNDCTL_DSP_GETISPACE: { ··· 2769 2512 audio_buf_info.fragstotal = 0; 2770 2513 2771 2514 if (0 != copy_to_user((void __user *)arg, &audio_buf_info, \ 2772 - sizeof(int))) 2515 + sizeof(int))) { 2516 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 2773 2517 return -EFAULT; 2518 + } 2774 2519 break; 2775 2520 } 2776 2521 case 0x00005401: ··· 2782 2523 case 0x00005405: 2783 2524 case 0x00005406: { 2784 2525 JOM(8, "SNDCTL_TMR_...: 0x%08X unsupported\n", cmd); 2526 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 2785 2527 return -ENOIOCTLCMD; 2786 2528 } 2787 2529 default: { 2788 2530 JOM(8, "ERROR: unrecognized DSP IOCTL command: 0x%08X\n", cmd); 2531 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 2789 2532 return -ENOIOCTLCMD; 2790 2533 } 2791 2534 } 2535 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 2792 2536 return 0; 2793 - } 2794 - 2795 - long easysnd_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 2796 - { 2797 - struct inode *inode = file->f_dentry->d_inode; 2798 - long ret; 2799 - 2800 - lock_kernel(); 2801 - ret = easysnd_ioctl_bkl(inode, file, cmd, arg); 2802 - unlock_kernel(); 2803 - 2804 - return ret; 2805 2537 } 2806 2538 /*****************************************************************************/
+49 -6
drivers/staging/easycap/easycap_low.c
··· 38 38 */ 39 39 /****************************************************************************/ 40 40 41 - #include "easycap_debug.h" 42 41 #include "easycap.h" 42 + #include "easycap_debug.h" 43 43 44 44 /*--------------------------------------------------------------------------*/ 45 45 const struct stk1160config { int reg; int set; } stk1160configPAL[256] = { ··· 248 248 confirm_resolution(struct usb_device *p) 249 249 { 250 250 __u8 get0, get1, get2, get3, get4, get5, get6, get7; 251 + 252 + if (NULL == p) 253 + return -ENODEV; 251 254 GET(p, 0x0110, &get0); 252 255 GET(p, 0x0111, &get1); 253 256 GET(p, 0x0112, &get2); ··· 291 288 __u16 get2; 292 289 __u8 igot; 293 290 291 + if (NULL == p) 292 + return -ENODEV; 294 293 GET(p, 0x0100, &igot); get2 = 0x80 & igot; 295 294 if (0x80 == get2) 296 295 JOT(8, "confirm_stream: OK\n"); ··· 306 301 { 307 302 int i0; 308 303 304 + if (NULL == p) 305 + return -ENODEV; 309 306 i0 = 0; 310 307 if (true == ntsc) { 311 308 while (0xFFF != stk1160configNTSC[i0].reg) { ··· 331 324 { 332 325 int i0, ir; 333 326 327 + if (NULL == p) 328 + return -ENODEV; 334 329 i0 = 0; 335 330 if (true == ntsc) { 336 331 while (0xFF != saa7113configNTSC[i0].reg) { ··· 355 346 { 356 347 __u8 igot0, igot2; 357 348 349 + if (NULL == p) 350 + return -ENODEV; 358 351 GET(p, 0x0002, &igot2); 359 352 GET(p, 0x0000, &igot0); 360 353 SET(p, 0x0002, set2); ··· 367 356 int 368 357 write_saa(struct usb_device *p, __u16 reg0, __u16 set0) 369 358 { 359 + if (NULL == p) 360 + return -ENODEV; 370 361 SET(p, 0x200, 0x00); 371 362 SET(p, 0x204, reg0); 372 363 SET(p, 0x205, set0); ··· 392 379 __u16 got502, got503; 393 380 __u16 set502, set503; 394 381 382 + if (NULL == p) 383 + return -ENODEV; 395 384 SET(p, 0x0504, reg0); 396 385 SET(p, 0x0500, 0x008B); 397 386 ··· 429 414 __u8 igot; 430 415 __u16 got502, got503; 431 416 417 + if (NULL == p) 418 + return -ENODEV; 432 419 SET(p, 0x0504, reg0); 433 420 SET(p, 0x0500, 0x008B); 434 421 ··· 450 433 int 451 434 write_300(struct usb_device *p) 452 435 { 436 + if (NULL == p) 437 + return -ENODEV; 453 438 SET(p, 0x300, 0x0012); 454 439 SET(p, 0x350, 0x002D); 455 440 SET(p, 0x351, 0x0001); ··· 472 453 { 473 454 int i0, ir, rc; 474 455 456 + if (NULL == p) 457 + return -ENODEV; 475 458 i0 = 0; 476 459 rc = 0; 477 460 if (true == ntsc) { ··· 522 501 { 523 502 int rc; 524 503 504 + if (NULL == p) 505 + return -ENODEV; 525 506 rc = read_saa(p, 0x1F); 526 507 if ((0 > rc) || (0x02 & rc)) 527 508 return 1 ; ··· 544 521 * 3 FOR NON-INTERLACED 60 Hz 545 522 */ 546 523 /*--------------------------------------------------------------------------*/ 524 + if (NULL == p) 525 + return -ENODEV; 547 526 j = 0; 548 527 while (max > j) { 549 528 rc = read_saa(p, 0x1F); ··· 590 565 { 591 566 int i0, ir; 592 567 568 + if (NULL == p) 569 + return -ENODEV; 593 570 i0 = 0; 594 571 if (true == ntsc) { 595 572 while (0xFFF != stk1160configNTSC[i0].reg) { ··· 664 637 { 665 638 __u8 igot; 666 639 640 + if (NULL == p) 641 + return -ENODEV; 667 642 SET(p, 0x208, reg0); 668 643 SET(p, 0x200, 0x20); 669 644 if (0 != wait_i2c(p)) ··· 680 651 { 681 652 __u8 igot; 682 653 654 + if (NULL == p) 655 + return -ENODEV; 683 656 igot = 0; 684 657 GET(p, reg0, &igot); 685 658 return igot; ··· 710 679 { 711 680 int ir; 712 681 682 + if (NULL == p) 683 + return -ENODEV; 713 684 stop_100(p); 714 685 switch (input) { 715 686 case 0: ··· 814 781 { 815 782 __u16 u0x0111, u0x0113, u0x0115, u0x0117; 816 783 784 + if (NULL == p) 785 + return -ENODEV; 817 786 u0x0111 = ((0xFF00 & set0) >> 8); 818 787 u0x0113 = ((0xFF00 & set1) >> 8); 819 788 u0x0115 = ((0xFF00 & set2) >> 8); ··· 839 804 __u16 get116, get117, get0; 840 805 __u8 igot116, igot117, igot; 841 806 807 + if (NULL == p) 808 + return -ENODEV; 842 809 GET(p, 0x0116, &igot116); 843 810 get116 = igot116; 844 811 GET(p, 0x0117, &igot117); ··· 864 827 __u16 get0; 865 828 __u8 igot; 866 829 830 + if (NULL == p) 831 + return -ENODEV; 867 832 GET(p, 0x0100, &igot); 868 833 get0 = igot; 869 834 SET(p, 0x0100, (0x7F & get0)); ··· 885 846 const int max = 2; 886 847 int k; 887 848 849 + if (NULL == p) 850 + return -ENODEV; 888 851 for (k = 0; k < max; k++) { 889 852 GET(p, 0x0201, &igot); get0 = igot; 890 853 switch (get0) { ··· 913 872 int rc0, rc1; 914 873 915 874 if (!pusb_device) 916 - return -EFAULT; 917 - 875 + return -ENODEV; 918 876 rc1 = 0; igot = 0; 919 877 rc0 = usb_control_msg(pusb_device, usb_sndctrlpipe(pusb_device, 0), \ 920 878 (__u8)0x01, \ ··· 976 936 int ir; 977 937 978 938 if (!pusb_device) 979 - return -EFAULT; 980 - 939 + return -ENODEV; 981 940 ir = usb_control_msg(pusb_device, usb_rcvctrlpipe(pusb_device, 0), \ 982 941 (__u8)0x00, \ 983 942 (__u8)(USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE), \ ··· 991 952 int 992 953 wakeup_device(struct usb_device *pusb_device) 993 954 { 955 + if (!pusb_device) 956 + return -ENODEV; 994 957 return usb_control_msg(pusb_device, usb_sndctrlpipe(pusb_device, 0), \ 995 958 (__u8)USB_REQ_SET_FEATURE, \ 996 959 (__u8)(USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE), \ ··· 1097 1056 { 1098 1057 int igot; 1099 1058 1059 + if (!pusb_device) 1060 + return -ENODEV; 1100 1061 igot = read_vt(pusb_device, 0x0002); 1101 1062 if (0 > igot) 1102 1063 SAY("ERROR: failed to read VT1612A register 0x02\n"); ··· 1171 1128 __u8 u8; 1172 1129 __u16 mute; 1173 1130 1174 - if ((struct usb_device *)NULL == pusb_device) 1131 + if (NULL == pusb_device) 1175 1132 return -ENODEV; 1176 1133 if (0 > loud) 1177 1134 loud = 0;
+221 -94
drivers/staging/easycap/easycap_main.c
··· 45 45 * IS CALLED SUCCESSIVELY FOR INTERFACES 0, 1, 2 AND THE POINTER peasycap 46 46 * ALLOCATED DURING THE PROBING OF INTERFACE 0 MUST BE REMEMBERED WHEN 47 47 * PROBING INTERFACES 1 AND 2. 48 + * 49 + * IOCTL LOCKING IS DONE AT MODULE LEVEL, NOT DEVICE LEVEL. 48 50 */ 49 51 /*---------------------------------------------------------------------------*/ 50 52 51 - struct easycap *peasycap_dongle[DONGLE_MANY]; 53 + struct easycap_dongle easycap_dongle[DONGLE_MANY]; 52 54 static int dongle_this; 55 + static int dongle_done; 53 56 54 57 /*---------------------------------------------------------------------------*/ 55 58 /* ··· 83 80 .owner = THIS_MODULE, 84 81 .open = easycap_open, 85 82 .release = easycap_release, 86 - .unlocked_ioctl = easycap_ioctl, 83 + #if defined(EASYCAP_NEEDS_UNLOCKED_IOCTL) 84 + .unlocked_ioctl = easycap_ioctl_noinode, 85 + #else 86 + .ioctl = easycap_ioctl, 87 + #endif /*EASYCAP_NEEDS_UNLOCKED_IOCTL*/ 87 88 .poll = easycap_poll, 88 89 .mmap = easycap_mmap, 89 90 .llseek = no_llseek, ··· 110 103 .owner = THIS_MODULE, 111 104 .open = easycap_open_noinode, 112 105 .release = easycap_release_noinode, 113 - .unlocked_ioctl = easycap_ioctl, 106 + #if defined(EASYCAP_NEEDS_UNLOCKED_IOCTL) 107 + .unlocked_ioctl = easycap_ioctl_noinode, 108 + #else 109 + .ioctl = easycap_ioctl, 110 + #endif /*EASYCAP_NEEDS_UNLOCKED_IOCTL*/ 114 111 .poll = easycap_poll, 115 112 .mmap = easycap_mmap, 116 113 }; ··· 131 120 .owner = THIS_MODULE, 132 121 .open = easysnd_open, 133 122 .release = easysnd_release, 134 - .unlocked_ioctl = easysnd_ioctl, 123 + #if defined(EASYCAP_NEEDS_UNLOCKED_IOCTL) 124 + .unlocked_ioctl = easysnd_ioctl_noinode, 125 + #else 126 + .ioctl = easysnd_ioctl, 127 + #endif /*EASYCAP_NEEDS_UNLOCKED_IOCTL*/ 135 128 .read = easysnd_read, 136 129 .llseek = no_llseek, 137 130 }; ··· 154 139 isdongle(struct easycap *peasycap) 155 140 { 156 141 int k; 157 - if ((struct easycap *)NULL == peasycap) 142 + if (NULL == peasycap) 158 143 return -2; 159 144 for (k = 0; k < DONGLE_MANY; k++) { 160 - if (peasycap_dongle[k] == peasycap) { 145 + if (easycap_dongle[k].peasycap == peasycap) { 161 146 peasycap->isdongle = k; 162 147 return k; 163 148 } ··· 211 196 peasycap = (struct easycap *)video_get_drvdata(pvideo_device); 212 197 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ 213 198 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ 214 - if ((struct easycap *)NULL == peasycap) { 199 + if (NULL == peasycap) { 215 200 SAY("ERROR: peasycap is NULL\n"); 216 201 return -EFAULT; 217 202 } 218 - file->private_data = peasycap; 219 203 if (NULL == peasycap->pusb_device) { 220 204 SAM("ERROR: peasycap->pusb_device is NULL\n"); 221 205 return -EFAULT; ··· 222 208 JOM(16, "0x%08lX=peasycap->pusb_device\n", \ 223 209 (long int)peasycap->pusb_device); 224 210 } 211 + file->private_data = peasycap; 225 212 rc = wakeup_device(peasycap->pusb_device); 226 213 if (0 == rc) 227 214 JOM(8, "wakeup_device() OK\n"); ··· 258 243 int i, rc, input, rate; 259 244 bool ntsc, other; 260 245 261 - if ((struct easycap *)NULL == peasycap) { 246 + if (NULL == peasycap) { 262 247 SAY("ERROR: peasycap is NULL\n"); 263 248 return -EFAULT; 264 249 } ··· 266 251 267 252 /*---------------------------------------------------------------------------*/ 268 253 /* 269 - * IF THE SAA7113H HAS ALREADY ACQUIRED LOCK, USE ITS HARDWARE-DETECTED 254 + * IF THE SAA7113H HAS ALREADY ACQUIRED SYNC, USE ITS HARDWARE-DETECTED 270 255 * FIELD FREQUENCY TO DISTINGUISH NTSC FROM PAL. THIS IS ESSENTIAL FOR 271 256 * gstreamer AND OTHER USERSPACE PROGRAMS WHICH MAY NOT ATTEMPT TO INITIATE 272 257 * A SWITCH BETWEEN PAL AND NTSC. ··· 462 447 } 463 448 JOM(8, "%i=input sought\n", input); 464 449 465 - if ((0 > input) &&(INPUT_MANY <= input)) 450 + if (0 > input && INPUT_MANY <= input) 466 451 return -ENOENT; 467 452 inputnow = peasycap->input; 468 453 if (input == inputnow) ··· 596 581 return -ENOENT; 597 582 } 598 583 /*---------------------------------------------------------------------------*/ 599 - if ((struct usb_device *)NULL == peasycap->pusb_device) { 584 + if (NULL == peasycap->pusb_device) { 600 585 SAM("ERROR: peasycap->pusb_device is NULL\n"); 601 586 return -ENODEV; 602 587 } ··· 632 617 int j, isbad, nospc, m, rc; 633 618 int isbuf; 634 619 635 - if ((struct easycap *)NULL == peasycap) { 620 + if (NULL == peasycap) { 636 621 SAY("ERROR: peasycap is NULL\n"); 637 622 return -EFAULT; 638 623 } 639 624 640 - if ((struct list_head *)NULL == peasycap->purb_video_head) { 625 + if (NULL == peasycap->purb_video_head) { 641 626 SAY("ERROR: peasycap->urb_video_head uninitialized\n"); 642 627 return -EFAULT; 643 628 } 644 - if ((struct usb_device *)NULL == peasycap->pusb_device) { 629 + if (NULL == peasycap->pusb_device) { 645 630 SAY("ERROR: peasycap->pusb_device is NULL\n"); 646 631 return -ENODEV; 647 632 } ··· 783 768 struct list_head *plist_head; 784 769 struct data_urb *pdata_urb; 785 770 786 - if ((struct easycap *)NULL == peasycap) { 771 + if (NULL == peasycap) { 787 772 SAY("ERROR: peasycap is NULL\n"); 788 773 return -EFAULT; 789 774 } ··· 795 780 list_for_each(plist_head, (peasycap->purb_video_head)) { 796 781 pdata_urb = list_entry(plist_head, struct data_urb, \ 797 782 list_head); 798 - if ((struct data_urb *)NULL != pdata_urb) { 799 - if ((struct urb *)NULL != pdata_urb->purb) { 783 + if (NULL != pdata_urb) { 784 + if (NULL != pdata_urb->purb) { 800 785 usb_kill_urb(pdata_urb->purb); 801 786 m++; 802 787 } ··· 879 864 /*****************************************************************************/ 880 865 /*--------------------------------------------------------------------------*/ 881 866 /* 882 - * THIS FUNCTION IS CALLED FROM WITHIN easycap_usb_disconnect(). 883 - * BY THIS STAGE THE DEVICE HAS ALREADY BEEN PHYSICALLY UNPLUGGED. 884 - * peasycap->pusb_device IS NO LONGER VALID AND SHOULD HAVE BEEN SET TO NULL. 867 + * THIS FUNCTION IS CALLED FROM WITHIN easycap_usb_disconnect() AND IS 868 + * PROTECTED BY SEMAPHORES SET AND CLEARED BY easycap_usb_disconnect(). 869 + * 870 + * BY THIS STAGE THE DEVICE HAS ALREADY BEEN PHYSICALLY UNPLUGGED, SO 871 + * peasycap->pusb_device IS NO LONGER VALID. 885 872 */ 886 873 /*---------------------------------------------------------------------------*/ 887 874 void 888 875 easycap_delete(struct kref *pkref) 889 876 { 890 - int k, m, gone; 877 + int k, m, gone, kd; 891 878 int allocation_video_urb, allocation_video_page, allocation_video_struct; 892 879 int allocation_audio_urb, allocation_audio_page, allocation_audio_struct; 893 880 int registered_video, registered_audio; ··· 900 883 JOT(4, "\n"); 901 884 902 885 peasycap = container_of(pkref, struct easycap, kref); 903 - if ((struct easycap *)NULL == peasycap) { 886 + if (NULL == peasycap) { 904 887 SAM("ERROR: peasycap is NULL: cannot perform deletions\n"); 905 888 return; 906 889 } 890 + kd = isdongle(peasycap); 907 891 /*---------------------------------------------------------------------------*/ 908 892 /* 909 893 * FREE VIDEO. ··· 943 925 JOM(4, "%i video data_urb structures freed\n", m); 944 926 JOM(4, "setting peasycap->purb_video_head=NULL\n"); 945 927 peasycap->purb_video_head = (struct list_head *)NULL; 946 - } else { 947 - JOM(4, "peasycap->purb_video_head is NULL\n"); 948 928 } 949 929 /*---------------------------------------------------------------------------*/ 950 930 JOM(4, "freeing video isoc buffers.\n"); ··· 1067 1051 allocation_audio_page = peasycap->allocation_audio_page; 1068 1052 allocation_audio_struct = peasycap->allocation_audio_struct; 1069 1053 registered_audio = peasycap->registered_audio; 1070 - m = 0; 1071 - if ((struct easycap *)NULL != peasycap) { 1072 - kfree(peasycap); peasycap = (struct easycap *)NULL; 1073 - allocation_video_struct -= sizeof(struct easycap); 1074 - m++; 1075 - } 1076 - JOT(4, "%i easycap structure freed\n", m); 1077 - /*---------------------------------------------------------------------------*/ 1078 1054 1055 + kfree(peasycap); 1056 + if (0 <= kd && DONGLE_MANY > kd) { 1057 + easycap_dongle[kd].peasycap = (struct easycap *)NULL; 1058 + JOT(4, " null-->easycap_dongle[%i].peasycap\n", kd); 1059 + allocation_video_struct -= sizeof(struct easycap); 1060 + } else { 1061 + SAY("ERROR: cannot purge easycap_dongle[].peasycap"); 1062 + } 1063 + /*---------------------------------------------------------------------------*/ 1079 1064 SAY("%8i= video urbs after all deletions\n", allocation_video_urb); 1080 1065 SAY("%8i= video pages after all deletions\n", allocation_video_page); 1081 1066 SAY("%8i= video structs after all deletions\n", allocation_video_struct); ··· 1093 1076 unsigned int easycap_poll(struct file *file, poll_table *wait) 1094 1077 { 1095 1078 struct easycap *peasycap; 1079 + int rc, kd; 1096 1080 1097 1081 JOT(8, "\n"); 1098 1082 1099 1083 if (NULL == ((poll_table *)wait)) 1100 1084 JOT(8, "WARNING: poll table pointer is NULL ... continuing\n"); 1101 - if (NULL == ((struct file *)file)) { 1085 + if ((struct file *)NULL == file) { 1102 1086 SAY("ERROR: file pointer is NULL\n"); 1103 - return -EFAULT; 1087 + return -ERESTARTSYS; 1104 1088 } 1105 1089 peasycap = file->private_data; 1106 1090 if (NULL == peasycap) { 1107 1091 SAY("ERROR: peasycap is NULL\n"); 1108 1092 return -EFAULT; 1109 1093 } 1094 + if (NULL == peasycap->pusb_device) { 1095 + SAY("ERROR: peasycap->pusb_device is NULL\n"); 1096 + return -EFAULT; 1097 + } 1098 + /*---------------------------------------------------------------------------*/ 1099 + kd = isdongle(peasycap); 1100 + if (0 <= kd && DONGLE_MANY > kd) { 1101 + if (mutex_lock_interruptible(&easycap_dongle[kd].mutex_video)) { 1102 + SAY("ERROR: cannot down easycap_dongle[%i].mutex_video\n", kd); 1103 + return -ERESTARTSYS; 1104 + } 1105 + JOM(4, "locked easycap_dongle[%i].mutex_video\n", kd); 1106 + /*-------------------------------------------------------------------*/ 1107 + /* 1108 + * MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER 1109 + * peasycap, IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL. 1110 + * IF NECESSARY, BAIL OUT. 1111 + */ 1112 + /*-------------------------------------------------------------------*/ 1113 + if (kd != isdongle(peasycap)) 1114 + return -ERESTARTSYS; 1115 + if (NULL == file) { 1116 + SAY("ERROR: file is NULL\n"); 1117 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1118 + return -ERESTARTSYS; 1119 + } 1120 + peasycap = file->private_data; 1121 + if (NULL == peasycap) { 1122 + SAY("ERROR: peasycap is NULL\n"); 1123 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1124 + return -ERESTARTSYS; 1125 + } 1126 + if (NULL == peasycap->pusb_device) { 1127 + SAM("ERROR: peasycap->pusb_device is NULL\n"); 1128 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1129 + return -ERESTARTSYS; 1130 + } 1131 + } else 1132 + /*-------------------------------------------------------------------*/ 1133 + /* 1134 + * IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap 1135 + * BEFORE THE ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL 1136 + * HAVE FAILED. BAIL OUT. 1137 + */ 1138 + /*-------------------------------------------------------------------*/ 1139 + return -ERESTARTSYS; 1140 + /*---------------------------------------------------------------------------*/ 1141 + rc = easycap_dqbuf(peasycap, 0); 1110 1142 peasycap->polled = 1; 1111 - 1112 - if (0 == easycap_dqbuf(peasycap, 0)) 1143 + mutex_unlock(&easycap_dongle[kd].mutex_video); 1144 + if (0 == rc) 1113 1145 return POLLIN | POLLRDNORM; 1114 1146 else 1115 1147 return POLLERR; 1116 - 1117 1148 } 1118 1149 /*****************************************************************************/ 1119 1150 /*---------------------------------------------------------------------------*/ ··· 1180 1115 SAY("ERROR: peasycap is NULL\n"); 1181 1116 return -EFAULT; 1182 1117 } 1118 + if (NULL == peasycap->pusb_device) { 1119 + SAY("ERROR: peasycap->pusb_device is NULL\n"); 1120 + return -EFAULT; 1121 + } 1183 1122 ifield = 0; 1184 1123 JOM(8, "%i=ifield\n", ifield); 1185 1124 /*---------------------------------------------------------------------------*/ ··· 1191 1122 * CHECK FOR LOST INPUT SIGNAL. 1192 1123 * 1193 1124 * FOR THE FOUR-CVBS EasyCAP, THIS DOES NOT WORK AS EXPECTED. 1194 - * IF INPUT 0 IS PRESENT AND LOCKED, UNPLUGGING INPUT 4 DOES NOT RESULT IN 1195 - * SETTING BIT 0x40 ON REGISTER 0x1F, PRESUMABLY BECAUSE THERE IS FLYWHEELING 1196 - * ON INPUT 0. THE UPSHOT IS: 1125 + * IF INPUT 0 IS PRESENT AND SYNC ACQUIRED, UNPLUGGING INPUT 4 DOES NOT 1126 + * RESULT IN SETTING BIT 0x40 ON REGISTER 0x1F, PRESUMABLY BECAUSE THERE 1127 + * IS FLYWHEELING ON INPUT 0. THE UPSHOT IS: 1197 1128 * 1198 1129 * INPUT 0 PLUGGED, INPUT 4 PLUGGED => SCREEN 0 OK, SCREEN 4 OK 1199 1130 * INPUT 0 PLUGGED, INPUT 4 UNPLUGGED => SCREEN 0 OK, SCREEN 4 BLACK ··· 1411 1342 __u8 mask, margin; 1412 1343 bool odd, isuy, decimatepixel, offerfields, badinput; 1413 1344 1414 - if ((struct easycap *)NULL == peasycap) { 1345 + if (NULL == peasycap) { 1415 1346 SAY("ERROR: peasycap is NULL\n"); 1416 1347 return -EFAULT; 1417 1348 } ··· 1516 1447 much) / 2; 1517 1448 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1518 1449 if (1 < bytesperpixel) { 1519 - if ((rad * \ 1520 - 2) < (much * \ 1521 - bytesperpixel)) { 1450 + if (rad * 2 < much * bytesperpixel) { 1522 1451 /* 1523 1452 ** INJUDICIOUS ALTERATION OF THIS 1524 - ** BLOCK WILL CAUSE BREAKAGE. 1525 - ** BEWARE. 1453 + ** STATEMENT BLOCK WILL CAUSE 1454 + ** BREAKAGE. BEWARE. 1526 1455 **/ 1527 1456 rad2 = rad + bytesperpixel - 1; 1528 1457 much = ((((2 * \ ··· 1550 1483 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1551 1484 if (rump) 1552 1485 caches++; 1553 - 1554 1486 if (true == badinput) { 1555 1487 JOM(8, "ERROR: 0x%02X=->field_buffer" \ 1556 1488 "[%i][%i].input, " \ ··· 1558 1492 [kex][mex].input, kex, mex, \ 1559 1493 (0x08|peasycap->input)); 1560 1494 } 1561 - 1562 1495 rc = redaub(peasycap, pad, pex, much, more, \ 1563 1496 mask, margin, isuy); 1564 1497 if (0 > rc) { ··· 1640 1575 much) / 4; 1641 1576 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1642 1577 if (1 < bytesperpixel) { 1643 - if ((rad * 4) < (much * \ 1644 - bytesperpixel)) { 1578 + if (rad * 4 < much * bytesperpixel) { 1645 1579 /* 1646 1580 ** INJUDICIOUS ALTERATION OF THIS 1647 - ** BLOCK WILL CAUSE BREAKAGE. 1648 - ** BEWARE. 1581 + ** STATEMENT BLOCK WILL CAUSE 1582 + ** BREAKAGE. BEWARE. 1649 1583 **/ 1650 1584 rad2 = rad + bytesperpixel - 1; 1651 1585 much = ((((2 * rad2)/bytesperpixel)/2)\ ··· 1684 1620 [kex][mex].input, kex, mex, \ 1685 1621 (0x08|peasycap->input)); 1686 1622 } 1687 - 1688 1623 rc = redaub(peasycap, pad, pex, much, more, \ 1689 1624 mask, margin, isuy); 1690 1625 if (0 > rc) { ··· 3360 3297 * FIXME 3361 3298 * 3362 3299 * 3363 - * THIS FUNCTION ASSUMES THAT, ON EACH AND EVERY OCCASION THAT THE DEVICE IS 3364 - * PHYSICALLY PLUGGED IN, INTERFACE 0 IS PROBED FIRST. 3300 + * THIS FUNCTION ASSUMES THAT, ON EACH AND EVERY OCCASION THAT THE EasyCAP 3301 + * IS PHYSICALLY PLUGGED IN, INTERFACE 0 IS PROBED FIRST. 3365 3302 * IF THIS IS NOT TRUE, THERE IS THE POSSIBILITY OF AN Oops. 3366 3303 * 3367 3304 * THIS HAS NEVER BEEN A PROBLEM IN PRACTICE, BUT SOMETHING SEEMS WRONG HERE. ··· 3401 3338 struct easycap_format *peasycap_format; 3402 3339 3403 3340 JOT(4, "\n"); 3341 + 3342 + if (!dongle_done) { 3343 + dongle_done = 1; 3344 + for (k = 0; k < DONGLE_MANY; k++) { 3345 + easycap_dongle[k].peasycap = (struct easycap *)NULL; 3346 + mutex_init(&easycap_dongle[k].mutex_video); 3347 + mutex_init(&easycap_dongle[k].mutex_audio); 3348 + } 3349 + } 3350 + 3404 3351 peasycap = (struct easycap *)NULL; 3405 3352 3406 3353 if ((struct usb_interface *)NULL == pusb_interface) { ··· 3554 3481 init_waitqueue_head(&peasycap->wq_audio); 3555 3482 3556 3483 for (dongle_this = 0; dongle_this < DONGLE_MANY; dongle_this++) { 3557 - if ((struct easycap *)NULL == peasycap_dongle[dongle_this]) { 3558 - peasycap_dongle[dongle_this] = peasycap; 3559 - JOM(8, "intf[%i]: peasycap-->easycap" \ 3484 + if (NULL == easycap_dongle[dongle_this].peasycap) { 3485 + if (0 == mutex_is_locked(&easycap_dongle\ 3486 + [dongle_this].mutex_video)) { 3487 + if (0 == mutex_is_locked(&easycap_dongle\ 3488 + [dongle_this].mutex_audio)) { 3489 + easycap_dongle\ 3490 + [dongle_this].peasycap = \ 3491 + peasycap; 3492 + JOM(8, "intf[%i]: peasycap-->easycap" \ 3560 3493 "_dongle[%i].peasycap\n", \ 3561 3494 bInterfaceNumber, dongle_this); 3562 - break; 3495 + break; 3496 + } 3497 + } 3563 3498 } 3564 3499 } 3565 3500 if (DONGLE_MANY <= dongle_this) { ··· 3746 3665 * FOR INTERFACES 1 AND 2 THE POINTER peasycap IS OBTAINED BY ASSUMING 3747 3666 * THAT dongle_this HAS NOT CHANGED SINCE INTERFACE 0 WAS PROBED. IF 3748 3667 * THIS IS NOT THE CASE, FOR EXAMPLE WHEN TWO EASYCAPs ARE PLUGGED IN 3749 - * SIMULTANEOUSLY, THERE WILL BE VERY SERIOUS TROUBLE. 3668 + * SIMULTANEOUSLY, THERE WILL BE SERIOUS TROUBLE. 3750 3669 */ 3751 3670 /*---------------------------------------------------------------------------*/ 3752 3671 if ((0 > dongle_this) || (DONGLE_MANY <= dongle_this)) { 3753 3672 SAY("ERROR: bad dongle count\n"); 3754 3673 return -EFAULT; 3755 3674 } 3756 - peasycap = peasycap_dongle[dongle_this]; 3757 - JOT(8, "intf[%i]: peasycap_dongle[%i]-->peasycap\n", \ 3675 + peasycap = easycap_dongle[dongle_this].peasycap; 3676 + JOT(8, "intf[%i]: easycap_dongle[%i].peasycap-->peasycap\n", \ 3758 3677 bInterfaceNumber, dongle_this); 3759 3678 3760 3679 if ((struct easycap *)NULL == peasycap) { ··· 3802 3721 */ 3803 3722 /*---------------------------------------------------------------------------*/ 3804 3723 isokalt = 0; 3724 + 3805 3725 for (i = 0; i < pusb_interface->num_altsetting; i++) { 3806 3726 pusb_host_interface = &(pusb_interface->altsetting[i]); 3807 3727 if ((struct usb_host_interface *)NULL == pusb_host_interface) { ··· 4327 4245 } 4328 4246 /*---------------------------------------------------------------------------*/ 4329 4247 /* 4248 + * FIXME 4249 + * 4250 + * 4330 4251 * THIS IS BELIEVED TO BE HARMLESS, BUT MAY WELL BE UNNECESSARY OR WRONG: 4331 4252 */ 4332 4253 /*---------------------------------------------------------------------------*/ ··· 4672 4587 /*****************************************************************************/ 4673 4588 /*---------------------------------------------------------------------------*/ 4674 4589 /* 4675 - * WHEN THIS FUNCTION IS CALLED THE DEVICE HAS ALREADY BEEN PHYSICALLY 4676 - * UNPLUGGED. 4677 - * HENCE peasycap->pusb_device IS NO LONGER VALID AND MUST BE SET TO NULL. 4590 + * WHEN THIS FUNCTION IS CALLED THE EasyCAP HAS ALREADY BEEN PHYSICALLY 4591 + * UNPLUGGED. HENCE peasycap->pusb_device IS NO LONGER VALID. 4678 4592 */ 4679 4593 /*---------------------------------------------------------------------------*/ 4680 4594 void ··· 4686 4602 4687 4603 struct list_head *plist_head; 4688 4604 struct data_urb *pdata_urb; 4689 - int minor, m; 4605 + int minor, m, kd; 4690 4606 4691 4607 JOT(4, "\n"); 4692 4608 ··· 4775 4691 /*--------------------------------------------------------------------------*/ 4776 4692 /* 4777 4693 * DEREGISTER 4694 + * 4695 + * THIS PROCEDURE WILL BLOCK UNTIL easycap_poll(), VIDEO IOCTL AND AUDIO 4696 + * IOCTL ARE ALL UNLOCKED. IF THIS IS NOT DONE AN Oops CAN OCCUR WHEN 4697 + * AN EasyCAP IS UNPLUGGED WHILE THE URBS ARE RUNNING. BEWARE. 4778 4698 */ 4779 4699 /*--------------------------------------------------------------------------*/ 4700 + kd = isdongle(peasycap); 4780 4701 switch (bInterfaceNumber) { 4781 4702 case 0: { 4703 + if (0 <= kd && DONGLE_MANY > kd) { 4704 + wake_up_interruptible(&peasycap->wq_video); 4705 + JOM(4, "about to lock easycap_dongle[%i].mutex_video\n", kd); 4706 + if (mutex_lock_interruptible(&easycap_dongle[kd].\ 4707 + mutex_video)) { 4708 + SAY("ERROR: cannot lock easycap_dongle[%i]." \ 4709 + "mutex_video\n", kd); 4710 + return; 4711 + } 4712 + JOM(4, "locked easycap_dongle[%i].mutex_video\n", kd); 4713 + } else 4714 + SAY("ERROR: %i=kd is bad: cannot lock dongle\n", kd); 4715 + /*---------------------------------------------------------------------------*/ 4782 4716 #if (!defined(EASYCAP_IS_VIDEODEV_CLIENT)) 4783 4717 if ((struct easycap *)NULL == peasycap) { 4784 4718 SAM("ERROR: peasycap has become NULL\n"); 4785 4719 } else { 4786 - lock_kernel(); 4787 4720 usb_deregister_dev(pusb_interface, &easycap_class); 4788 4721 (peasycap->registered_video)--; 4789 - 4790 4722 JOM(4, "intf[%i]: usb_deregister_dev()\n", bInterfaceNumber); 4791 - unlock_kernel(); 4792 4723 SAM("easycap detached from minor #%d\n", minor); 4793 4724 } 4794 4725 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ 4795 4726 #else 4796 - if ((struct easycap *)NULL == peasycap) 4797 - SAM("ERROR: peasycap has become NULL\n"); 4798 - else { 4799 - lock_kernel(); 4800 - video_unregister_device(&peasycap->video_device); 4801 - (peasycap->registered_video)--; 4802 - unlock_kernel(); 4803 - JOM(4, "unregistered with videodev: %i=minor\n", \ 4727 + video_unregister_device(&peasycap->video_device); 4728 + JOM(4, "unregistered with videodev: %i=minor\n", \ 4804 4729 peasycap->video_device.minor); 4805 - } 4730 + (peasycap->registered_video)--; 4806 4731 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ 4807 4732 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ 4733 + if (0 <= kd && DONGLE_MANY > kd) { 4734 + mutex_unlock(&easycap_dongle[kd].mutex_video); 4735 + JOM(4, "unlocked easycap_dongle[%i].mutex_video\n", kd); 4736 + } 4808 4737 break; 4809 4738 } 4810 4739 case 2: { 4811 - lock_kernel(); 4740 + if (0 <= kd && DONGLE_MANY > kd) { 4741 + wake_up_interruptible(&peasycap->wq_audio); 4742 + JOM(4, "about to lock easycap_dongle[%i].mutex_audio\n", kd); 4743 + if (mutex_lock_interruptible(&easycap_dongle[kd].\ 4744 + mutex_audio)) { 4745 + SAY("ERROR: cannot lock easycap_dongle[%i]." \ 4746 + "mutex_audio\n", kd); 4747 + return; 4748 + } 4749 + JOM(4, "locked easycap_dongle[%i].mutex_audio\n", kd); 4750 + } else 4751 + SAY("ERROR: %i=kd is bad: cannot lock dongle\n", kd); 4812 4752 4813 4753 usb_deregister_dev(pusb_interface, &easysnd_class); 4814 - if ((struct easycap *)NULL != peasycap) 4815 - (peasycap->registered_audio)--; 4754 + (peasycap->registered_audio)--; 4816 4755 4817 4756 JOM(4, "intf[%i]: usb_deregister_dev()\n", bInterfaceNumber); 4818 - unlock_kernel(); 4819 - 4820 4757 SAM("easysnd detached from minor #%d\n", minor); 4758 + 4759 + if (0 <= kd && DONGLE_MANY > kd) { 4760 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 4761 + JOM(4, "unlocked easycap_dongle[%i].mutex_audio\n", kd); 4762 + } 4821 4763 break; 4822 4764 } 4823 4765 default: ··· 4854 4744 * CALL easycap_delete() IF NO REMAINING REFERENCES TO peasycap 4855 4745 */ 4856 4746 /*---------------------------------------------------------------------------*/ 4857 - if ((struct easycap *)NULL == peasycap) { 4858 - SAM("ERROR: peasycap has become NULL\n"); 4859 - SAM("cannot call kref_put()\n"); 4860 - SAM("ending unsuccessfully: may cause memory leak\n"); 4861 - return; 4862 - } 4863 4747 if (!peasycap->kref.refcount.counter) { 4864 - SAM("ERROR: peasycap->kref.refcount.counter is zero " \ 4748 + SAM("ERROR: peasycap->kref.refcount.counter is zero " 4865 4749 "so cannot call kref_put()\n"); 4866 4750 SAM("ending unsuccessfully: may cause memory leak\n"); 4867 4751 return; 4868 4752 } 4869 - JOM(4, "intf[%i]: kref_put() with %i=peasycap->kref.refcount.counter\n", \ 4753 + if (0 <= kd && DONGLE_MANY > kd) { 4754 + JOM(4, "about to lock easycap_dongle[%i].mutex_video\n", kd); 4755 + if (mutex_lock_interruptible(&easycap_dongle[kd].mutex_video)) { 4756 + SAY("ERROR: cannot down easycap_dongle[%i].mutex_video\n", kd); 4757 + SAM("ending unsuccessfully: may cause memory leak\n"); 4758 + return; 4759 + } 4760 + JOM(4, "locked easycap_dongle[%i].mutex_video\n", kd); 4761 + JOM(4, "about to lock easycap_dongle[%i].mutex_audio\n", kd); 4762 + if (mutex_lock_interruptible(&easycap_dongle[kd].mutex_audio)) { 4763 + SAY("ERROR: cannot down easycap_dongle[%i].mutex_audio\n", kd); 4764 + mutex_unlock(&(easycap_dongle[kd].mutex_video)); 4765 + JOM(4, "unlocked easycap_dongle[%i].mutex_video\n", kd); 4766 + SAM("ending unsuccessfully: may cause memory leak\n"); 4767 + return; 4768 + } 4769 + JOM(4, "locked easycap_dongle[%i].mutex_audio\n", kd); 4770 + } 4771 + JOM(4, "intf[%i]: %i=peasycap->kref.refcount.counter\n", \ 4870 4772 bInterfaceNumber, (int)peasycap->kref.refcount.counter); 4871 4773 kref_put(&peasycap->kref, easycap_delete); 4872 - JOM(4, "intf[%i]: kref_put() done.\n", bInterfaceNumber); 4774 + JOT(4, "intf[%i]: kref_put() done.\n", bInterfaceNumber); 4775 + if (0 <= kd && DONGLE_MANY > kd) { 4776 + mutex_unlock(&(easycap_dongle[kd].mutex_audio)); 4777 + JOT(4, "unlocked easycap_dongle[%i].mutex_audio\n", kd); 4778 + mutex_unlock(&easycap_dongle[kd].mutex_video); 4779 + JOT(4, "unlocked easycap_dongle[%i].mutex_video\n", kd); 4780 + } 4873 4781 /*---------------------------------------------------------------------------*/ 4874 - 4875 4782 JOM(4, "ends\n"); 4876 4783 return; 4877 4784 }
+73 -3
drivers/staging/easycap/easycap_sound.c
··· 636 636 637 637 if ((struct usb_device *)NULL == peasycap->pusb_device) { 638 638 SAM("ERROR: peasycap->pusb_device has become NULL\n"); 639 - return -EFAULT; 639 + return -ENODEV; 640 640 } 641 641 /*---------------------------------------------------------------------------*/ 642 642 if ((struct usb_device *)NULL == peasycap->pusb_device) { ··· 695 695 struct signed_div_result sdr; 696 696 unsigned char *p0; 697 697 long int kount1, more, rc, l0, lm; 698 - int fragment; 698 + int fragment, kd; 699 699 struct easycap *peasycap; 700 700 struct data_buffer *pdata_buffer; 701 701 size_t szret; ··· 713 713 714 714 JOT(8, "===== easysnd_read(): kount=%i, *poff=%i\n", (int)kount, (int)(*poff)); 715 715 716 - peasycap = (struct easycap *)(file->private_data); 716 + if (NULL == file) { 717 + SAY("ERROR: file is NULL\n"); 718 + return -ERESTARTSYS; 719 + } 720 + peasycap = file->private_data; 717 721 if (NULL == peasycap) { 718 722 SAY("ERROR in easysnd_read(): peasycap is NULL\n"); 719 723 return -EFAULT; 720 724 } 725 + if (NULL == peasycap->pusb_device) { 726 + SAY("ERROR in easysnd_read(): peasycap->pusb_device is NULL\n"); 727 + return -EFAULT; 728 + } 729 + kd = isdongle(peasycap); 730 + if (0 <= kd && DONGLE_MANY > kd) { 731 + if (mutex_lock_interruptible(&(easycap_dongle[kd].mutex_audio))) { 732 + SAY("ERROR: cannot lock easycap_dongle[%i].mutex_audio\n", kd); 733 + return -ERESTARTSYS; 734 + } 735 + JOM(4, "locked easycap_dongle[%i].mutex_audio\n", kd); 721 736 /*---------------------------------------------------------------------------*/ 737 + /* 738 + * MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap, 739 + * IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL. 740 + * IF NECESSARY, BAIL OUT. 741 + */ 742 + /*---------------------------------------------------------------------------*/ 743 + if (kd != isdongle(peasycap)) 744 + return -ERESTARTSYS; 745 + if (NULL == file) { 746 + SAY("ERROR: file is NULL\n"); 747 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 748 + return -ERESTARTSYS; 749 + } 750 + peasycap = file->private_data; 751 + if (NULL == peasycap) { 752 + SAY("ERROR: peasycap is NULL\n"); 753 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 754 + return -ERESTARTSYS; 755 + } 756 + if (NULL == peasycap->pusb_device) { 757 + SAM("ERROR: peasycap->pusb_device is NULL\n"); 758 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 759 + return -ERESTARTSYS; 760 + } 761 + } else { 762 + /*---------------------------------------------------------------------------*/ 763 + /* 764 + * IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap BEFORE THE 765 + * ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL HAVE FAILED. BAIL OUT. 766 + */ 767 + /*---------------------------------------------------------------------------*/ 768 + return -ERESTARTSYS; 769 + } 770 + /*---------------------------------------------------------------------------*/ 771 + if (file->f_flags & O_NONBLOCK) 772 + JOT(16, "NONBLOCK kount=%i, *poff=%i\n", (int)kount, (int)(*poff)); 773 + else 774 + JOT(8, "BLOCKING kount=%i, *poff=%i\n", (int)kount, (int)(*poff)); 775 + 722 776 if ((0 > peasycap->audio_read) || \ 723 777 (peasycap->audio_buffer_page_many <= peasycap->audio_read)) { 724 778 SAM("ERROR: peasycap->audio_read out of range\n"); 779 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 725 780 return -EFAULT; 726 781 } 727 782 pdata_buffer = &peasycap->audio_buffer[peasycap->audio_read]; 728 783 if ((struct data_buffer *)NULL == pdata_buffer) { 729 784 SAM("ERROR: pdata_buffer is NULL\n"); 785 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 730 786 return -EFAULT; 731 787 } 732 788 JOM(12, "before wait, %i=frag read %i=frag fill\n", \ ··· 794 738 (0 == (PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo)))) { 795 739 if (file->f_flags & O_NONBLOCK) { 796 740 JOM(16, "returning -EAGAIN as instructed\n"); 741 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 797 742 return -EAGAIN; 798 743 } 799 744 rc = wait_event_interruptible(peasycap->wq_audio, \ ··· 804 747 (0 < (PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo)))))); 805 748 if (0 != rc) { 806 749 SAM("aborted by signal\n"); 750 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 807 751 return -ERESTARTSYS; 808 752 } 809 753 if (peasycap->audio_eof) { 810 754 JOM(8, "returning 0 because %i=audio_eof\n", \ 811 755 peasycap->audio_eof); 812 756 kill_audio_urbs(peasycap); 757 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 813 758 return 0; 814 759 } 815 760 if (peasycap->audio_idle) { 816 761 JOM(16, "returning 0 because %i=audio_idle\n", \ 817 762 peasycap->audio_idle); 763 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 818 764 return 0; 819 765 } 820 766 if (!peasycap->audio_isoc_streaming) { 821 767 JOM(16, "returning 0 because audio urbs not streaming\n"); 768 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 822 769 return 0; 823 770 } 824 771 } ··· 834 773 peasycap->audio_pages_per_fragment)) { 835 774 if (NULL == pdata_buffer->pgo) { 836 775 SAM("ERROR: pdata_buffer->pgo is NULL\n"); 776 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 837 777 return -EFAULT; 838 778 } 839 779 if (NULL == pdata_buffer->pto) { 840 780 SAM("ERROR: pdata_buffer->pto is NULL\n"); 781 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 841 782 return -EFAULT; 842 783 } 843 784 kount1 = PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo); 844 785 if (0 > kount1) { 845 786 SAM("easysnd_read: MISTAKE: kount1 is negative\n"); 787 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 846 788 return -ERESTARTSYS; 847 789 } 848 790 if (!kount1) { ··· 863 799 (peasycap->audio_buffer_page_many <= \ 864 800 peasycap->audio_read)) { 865 801 SAM("ERROR: peasycap->audio_read out of range\n"); 802 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 866 803 return -EFAULT; 867 804 } 868 805 pdata_buffer = &peasycap->audio_buffer[peasycap->audio_read]; 869 806 if ((struct data_buffer *)NULL == pdata_buffer) { 870 807 SAM("ERROR: pdata_buffer is NULL\n"); 808 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 871 809 return -EFAULT; 872 810 } 873 811 if (NULL == pdata_buffer->pgo) { 874 812 SAM("ERROR: pdata_buffer->pgo is NULL\n"); 813 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 875 814 return -EFAULT; 876 815 } 877 816 if (NULL == pdata_buffer->pto) { 878 817 SAM("ERROR: pdata_buffer->pto is NULL\n"); 818 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 879 819 return -EFAULT; 880 820 } 881 821 kount1 = PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo); ··· 908 840 rc = copy_to_user(puserspacebuffer, pdata_buffer->pto, more); 909 841 if (0 != rc) { 910 842 SAM("ERROR: copy_to_user() returned %li\n", rc); 843 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 911 844 return -EFAULT; 912 845 } 913 846 *poff += (loff_t)more; ··· 971 902 peasycap->dnbydt = sdr.quotient; 972 903 973 904 JOM(8, "returning %li\n", (long int)szret); 905 + mutex_unlock(&easycap_dongle[kd].mutex_audio); 974 906 return szret; 975 907 } 976 908 /*****************************************************************************/