| .. | .. |
|---|
| 39 | 39 | #include <linux/isdn/capiutil.h> |
|---|
| 40 | 40 | #include <linux/isdn/capicmd.h> |
|---|
| 41 | 41 | |
|---|
| 42 | | -MODULE_DESCRIPTION("CAPI4Linux: Userspace /dev/capi20 interface"); |
|---|
| 42 | +#include "kcapi.h" |
|---|
| 43 | + |
|---|
| 44 | +MODULE_DESCRIPTION("CAPI4Linux: kernel CAPI layer and /dev/capi20 interface"); |
|---|
| 43 | 45 | MODULE_AUTHOR("Carsten Paeth"); |
|---|
| 44 | 46 | MODULE_LICENSE("GPL"); |
|---|
| 45 | 47 | |
|---|
| .. | .. |
|---|
| 950 | 952 | return ret; |
|---|
| 951 | 953 | } |
|---|
| 952 | 954 | |
|---|
| 955 | +#ifdef CONFIG_COMPAT |
|---|
| 956 | +static long |
|---|
| 957 | +capi_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
|---|
| 958 | +{ |
|---|
| 959 | + int ret; |
|---|
| 960 | + |
|---|
| 961 | + if (cmd == CAPI_MANUFACTURER_CMD) { |
|---|
| 962 | + struct { |
|---|
| 963 | + compat_ulong_t cmd; |
|---|
| 964 | + compat_uptr_t data; |
|---|
| 965 | + } mcmd32; |
|---|
| 966 | + |
|---|
| 967 | + if (!capable(CAP_SYS_ADMIN)) |
|---|
| 968 | + return -EPERM; |
|---|
| 969 | + if (copy_from_user(&mcmd32, compat_ptr(arg), sizeof(mcmd32))) |
|---|
| 970 | + return -EFAULT; |
|---|
| 971 | + |
|---|
| 972 | + mutex_lock(&capi_mutex); |
|---|
| 973 | + ret = capi20_manufacturer(mcmd32.cmd, compat_ptr(mcmd32.data)); |
|---|
| 974 | + mutex_unlock(&capi_mutex); |
|---|
| 975 | + |
|---|
| 976 | + return ret; |
|---|
| 977 | + } |
|---|
| 978 | + |
|---|
| 979 | + return capi_unlocked_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); |
|---|
| 980 | +} |
|---|
| 981 | +#endif |
|---|
| 982 | + |
|---|
| 953 | 983 | static int capi_open(struct inode *inode, struct file *file) |
|---|
| 954 | 984 | { |
|---|
| 955 | 985 | struct capidev *cdev; |
|---|
| .. | .. |
|---|
| 968 | 998 | list_add_tail(&cdev->list, &capidev_list); |
|---|
| 969 | 999 | mutex_unlock(&capidev_list_lock); |
|---|
| 970 | 1000 | |
|---|
| 971 | | - return nonseekable_open(inode, file); |
|---|
| 1001 | + return stream_open(inode, file); |
|---|
| 972 | 1002 | } |
|---|
| 973 | 1003 | |
|---|
| 974 | 1004 | static int capi_release(struct inode *inode, struct file *file) |
|---|
| .. | .. |
|---|
| 996 | 1026 | .write = capi_write, |
|---|
| 997 | 1027 | .poll = capi_poll, |
|---|
| 998 | 1028 | .unlocked_ioctl = capi_unlocked_ioctl, |
|---|
| 1029 | +#ifdef CONFIG_COMPAT |
|---|
| 1030 | + .compat_ioctl = capi_compat_ioctl, |
|---|
| 1031 | +#endif |
|---|
| 999 | 1032 | .open = capi_open, |
|---|
| 1000 | 1033 | .release = capi_release, |
|---|
| 1001 | 1034 | }; |
|---|
| .. | .. |
|---|
| 1163 | 1196 | return mp->outbytes; |
|---|
| 1164 | 1197 | } |
|---|
| 1165 | 1198 | |
|---|
| 1166 | | -static int capinc_tty_ioctl(struct tty_struct *tty, |
|---|
| 1167 | | - unsigned int cmd, unsigned long arg) |
|---|
| 1168 | | -{ |
|---|
| 1169 | | - return -ENOIOCTLCMD; |
|---|
| 1170 | | -} |
|---|
| 1171 | | - |
|---|
| 1172 | 1199 | static void capinc_tty_set_termios(struct tty_struct *tty, struct ktermios *old) |
|---|
| 1173 | 1200 | { |
|---|
| 1174 | 1201 | pr_debug("capinc_tty_set_termios\n"); |
|---|
| .. | .. |
|---|
| 1244 | 1271 | .flush_chars = capinc_tty_flush_chars, |
|---|
| 1245 | 1272 | .write_room = capinc_tty_write_room, |
|---|
| 1246 | 1273 | .chars_in_buffer = capinc_tty_chars_in_buffer, |
|---|
| 1247 | | - .ioctl = capinc_tty_ioctl, |
|---|
| 1248 | 1274 | .set_termios = capinc_tty_set_termios, |
|---|
| 1249 | 1275 | .throttle = capinc_tty_throttle, |
|---|
| 1250 | 1276 | .unthrottle = capinc_tty_unthrottle, |
|---|
| .. | .. |
|---|
| 1388 | 1414 | { |
|---|
| 1389 | 1415 | const char *compileinfo; |
|---|
| 1390 | 1416 | int major_ret; |
|---|
| 1417 | + int ret; |
|---|
| 1418 | + |
|---|
| 1419 | + ret = kcapi_init(); |
|---|
| 1420 | + if (ret) |
|---|
| 1421 | + return ret; |
|---|
| 1391 | 1422 | |
|---|
| 1392 | 1423 | major_ret = register_chrdev(capi_major, "capi20", &capi_fops); |
|---|
| 1393 | 1424 | if (major_ret < 0) { |
|---|
| 1394 | 1425 | printk(KERN_ERR "capi20: unable to get major %d\n", capi_major); |
|---|
| 1426 | + kcapi_exit(); |
|---|
| 1395 | 1427 | return major_ret; |
|---|
| 1396 | 1428 | } |
|---|
| 1397 | 1429 | capi_class = class_create(THIS_MODULE, "capi"); |
|---|
| 1398 | 1430 | if (IS_ERR(capi_class)) { |
|---|
| 1399 | 1431 | unregister_chrdev(capi_major, "capi20"); |
|---|
| 1432 | + kcapi_exit(); |
|---|
| 1400 | 1433 | return PTR_ERR(capi_class); |
|---|
| 1401 | 1434 | } |
|---|
| 1402 | 1435 | |
|---|
| .. | .. |
|---|
| 1406 | 1439 | device_destroy(capi_class, MKDEV(capi_major, 0)); |
|---|
| 1407 | 1440 | class_destroy(capi_class); |
|---|
| 1408 | 1441 | unregister_chrdev(capi_major, "capi20"); |
|---|
| 1442 | + kcapi_exit(); |
|---|
| 1409 | 1443 | return -ENOMEM; |
|---|
| 1410 | 1444 | } |
|---|
| 1411 | 1445 | |
|---|
| .. | .. |
|---|
| 1431 | 1465 | unregister_chrdev(capi_major, "capi20"); |
|---|
| 1432 | 1466 | |
|---|
| 1433 | 1467 | capinc_tty_exit(); |
|---|
| 1468 | + |
|---|
| 1469 | + kcapi_exit(); |
|---|
| 1434 | 1470 | } |
|---|
| 1435 | 1471 | |
|---|
| 1436 | 1472 | module_init(capi_init); |
|---|