diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/video/fbmem.c | 141 |
1 files changed, 86 insertions, 55 deletions
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 217c5118ae9e..2a0f013dc37b 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c | |||
@@ -1002,101 +1002,132 @@ fb_blank(struct fb_info *info, int blank) | |||
1002 | return ret; | 1002 | return ret; |
1003 | } | 1003 | } |
1004 | 1004 | ||
1005 | static int | 1005 | static long |
1006 | fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 1006 | fb_ioctl(struct file *file, unsigned int cmd, |
1007 | unsigned long arg) | 1007 | unsigned long arg) |
1008 | { | 1008 | { |
1009 | struct inode *inode = file->f_path.dentry->d_inode; | ||
1009 | int fbidx = iminor(inode); | 1010 | int fbidx = iminor(inode); |
1010 | struct fb_info *info = registered_fb[fbidx]; | 1011 | struct fb_info *info; |
1011 | struct fb_ops *fb = info->fbops; | 1012 | struct fb_ops *fb; |
1012 | struct fb_var_screeninfo var; | 1013 | struct fb_var_screeninfo var; |
1013 | struct fb_fix_screeninfo fix; | 1014 | struct fb_fix_screeninfo fix; |
1014 | struct fb_con2fbmap con2fb; | 1015 | struct fb_con2fbmap con2fb; |
1015 | struct fb_cmap_user cmap; | 1016 | struct fb_cmap_user cmap; |
1016 | struct fb_event event; | 1017 | struct fb_event event; |
1017 | void __user *argp = (void __user *)arg; | 1018 | void __user *argp = (void __user *)arg; |
1018 | int i; | 1019 | long ret = 0; |
1019 | 1020 | ||
1020 | if (!fb) | 1021 | lock_kernel(); |
1022 | info = registered_fb[fbidx]; | ||
1023 | fb = info->fbops; | ||
1024 | |||
1025 | if (!fb) { | ||
1026 | unlock_kernel(); | ||
1021 | return -ENODEV; | 1027 | return -ENODEV; |
1028 | } | ||
1022 | switch (cmd) { | 1029 | switch (cmd) { |
1023 | case FBIOGET_VSCREENINFO: | 1030 | case FBIOGET_VSCREENINFO: |
1024 | return copy_to_user(argp, &info->var, | 1031 | ret = copy_to_user(argp, &info->var, |
1025 | sizeof(var)) ? -EFAULT : 0; | 1032 | sizeof(var)) ? -EFAULT : 0; |
1033 | break; | ||
1026 | case FBIOPUT_VSCREENINFO: | 1034 | case FBIOPUT_VSCREENINFO: |
1027 | if (copy_from_user(&var, argp, sizeof(var))) | 1035 | if (copy_from_user(&var, argp, sizeof(var))) { |
1028 | return -EFAULT; | 1036 | ret = -EFAULT; |
1037 | break; | ||
1038 | } | ||
1029 | acquire_console_sem(); | 1039 | acquire_console_sem(); |
1030 | info->flags |= FBINFO_MISC_USEREVENT; | 1040 | info->flags |= FBINFO_MISC_USEREVENT; |
1031 | i = fb_set_var(info, &var); | 1041 | ret = fb_set_var(info, &var); |
1032 | info->flags &= ~FBINFO_MISC_USEREVENT; | 1042 | info->flags &= ~FBINFO_MISC_USEREVENT; |
1033 | release_console_sem(); | 1043 | release_console_sem(); |
1034 | if (i) return i; | 1044 | if (ret == 0 && copy_to_user(argp, &var, sizeof(var))) |
1035 | if (copy_to_user(argp, &var, sizeof(var))) | 1045 | ret = -EFAULT; |
1036 | return -EFAULT; | 1046 | break; |
1037 | return 0; | ||
1038 | case FBIOGET_FSCREENINFO: | 1047 | case FBIOGET_FSCREENINFO: |
1039 | return copy_to_user(argp, &info->fix, | 1048 | ret = copy_to_user(argp, &info->fix, |
1040 | sizeof(fix)) ? -EFAULT : 0; | 1049 | sizeof(fix)) ? -EFAULT : 0; |
1050 | break; | ||
1041 | case FBIOPUTCMAP: | 1051 | case FBIOPUTCMAP: |
1042 | if (copy_from_user(&cmap, argp, sizeof(cmap))) | 1052 | if (copy_from_user(&cmap, argp, sizeof(cmap))) |
1043 | return -EFAULT; | 1053 | ret = -EFAULT; |
1044 | return (fb_set_user_cmap(&cmap, info)); | 1054 | else |
1055 | ret = fb_set_user_cmap(&cmap, info); | ||
1056 | break; | ||
1045 | case FBIOGETCMAP: | 1057 | case FBIOGETCMAP: |
1046 | if (copy_from_user(&cmap, argp, sizeof(cmap))) | 1058 | if (copy_from_user(&cmap, argp, sizeof(cmap))) |
1047 | return -EFAULT; | 1059 | ret = -EFAULT; |
1048 | return fb_cmap_to_user(&info->cmap, &cmap); | 1060 | else |
1061 | ret = fb_cmap_to_user(&info->cmap, &cmap); | ||
1062 | break; | ||
1049 | case FBIOPAN_DISPLAY: | 1063 | case FBIOPAN_DISPLAY: |
1050 | if (copy_from_user(&var, argp, sizeof(var))) | 1064 | if (copy_from_user(&var, argp, sizeof(var))) { |
1051 | return -EFAULT; | 1065 | ret = -EFAULT; |
1066 | break; | ||
1067 | } | ||
1052 | acquire_console_sem(); | 1068 | acquire_console_sem(); |
1053 | i = fb_pan_display(info, &var); | 1069 | ret = fb_pan_display(info, &var); |
1054 | release_console_sem(); | 1070 | release_console_sem(); |
1055 | if (i) | 1071 | if (ret == 0 && copy_to_user(argp, &var, sizeof(var))) |
1056 | return i; | 1072 | ret = -EFAULT; |
1057 | if (copy_to_user(argp, &var, sizeof(var))) | 1073 | break; |
1058 | return -EFAULT; | ||
1059 | return 0; | ||
1060 | case FBIO_CURSOR: | 1074 | case FBIO_CURSOR: |
1061 | return -EINVAL; | 1075 | ret = -EINVAL; |
1076 | break; | ||
1062 | case FBIOGET_CON2FBMAP: | 1077 | case FBIOGET_CON2FBMAP: |
1063 | if (copy_from_user(&con2fb, argp, sizeof(con2fb))) | 1078 | if (copy_from_user(&con2fb, argp, sizeof(con2fb))) |
1064 | return -EFAULT; | 1079 | ret = -EFAULT; |
1065 | if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) | 1080 | else if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) |
1066 | return -EINVAL; | 1081 | ret = -EINVAL; |
1067 | con2fb.framebuffer = -1; | 1082 | else { |
1068 | event.info = info; | 1083 | con2fb.framebuffer = -1; |
1069 | event.data = &con2fb; | 1084 | event.info = info; |
1070 | fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP, &event); | 1085 | event.data = &con2fb; |
1071 | return copy_to_user(argp, &con2fb, | 1086 | fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP, |
1087 | &event); | ||
1088 | ret = copy_to_user(argp, &con2fb, | ||
1072 | sizeof(con2fb)) ? -EFAULT : 0; | 1089 | sizeof(con2fb)) ? -EFAULT : 0; |
1090 | } | ||
1091 | break; | ||
1073 | case FBIOPUT_CON2FBMAP: | 1092 | case FBIOPUT_CON2FBMAP: |
1074 | if (copy_from_user(&con2fb, argp, sizeof(con2fb))) | 1093 | if (copy_from_user(&con2fb, argp, sizeof(con2fb))) { |
1075 | return - EFAULT; | 1094 | ret = -EFAULT; |
1076 | if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) | 1095 | break; |
1077 | return -EINVAL; | 1096 | } |
1078 | if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX) | 1097 | if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) { |
1079 | return -EINVAL; | 1098 | ret = -EINVAL; |
1080 | if (!registered_fb[con2fb.framebuffer]) | 1099 | break; |
1081 | request_module("fb%d", con2fb.framebuffer); | 1100 | } |
1101 | if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX) { | ||
1102 | ret = -EINVAL; | ||
1103 | break; | ||
1104 | } | ||
1082 | if (!registered_fb[con2fb.framebuffer]) | 1105 | if (!registered_fb[con2fb.framebuffer]) |
1083 | return -EINVAL; | 1106 | request_module("fb%d", con2fb.framebuffer); |
1107 | if (!registered_fb[con2fb.framebuffer]) { | ||
1108 | ret = -EINVAL; | ||
1109 | break; | ||
1110 | } | ||
1084 | event.info = info; | 1111 | event.info = info; |
1085 | event.data = &con2fb; | 1112 | event.data = &con2fb; |
1086 | return fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, | 1113 | ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, |
1087 | &event); | 1114 | &event); |
1115 | break; | ||
1088 | case FBIOBLANK: | 1116 | case FBIOBLANK: |
1089 | acquire_console_sem(); | 1117 | acquire_console_sem(); |
1090 | info->flags |= FBINFO_MISC_USEREVENT; | 1118 | info->flags |= FBINFO_MISC_USEREVENT; |
1091 | i = fb_blank(info, arg); | 1119 | ret = fb_blank(info, arg); |
1092 | info->flags &= ~FBINFO_MISC_USEREVENT; | 1120 | info->flags &= ~FBINFO_MISC_USEREVENT; |
1093 | release_console_sem(); | 1121 | release_console_sem(); |
1094 | return i; | 1122 | break;; |
1095 | default: | 1123 | default: |
1096 | if (fb->fb_ioctl == NULL) | 1124 | if (fb->fb_ioctl == NULL) |
1097 | return -EINVAL; | 1125 | ret = -ENOTTY; |
1098 | return fb->fb_ioctl(info, cmd, arg); | 1126 | else |
1127 | ret = fb->fb_ioctl(info, cmd, arg); | ||
1099 | } | 1128 | } |
1129 | unlock_kernel(); | ||
1130 | return ret; | ||
1100 | } | 1131 | } |
1101 | 1132 | ||
1102 | #ifdef CONFIG_COMPAT | 1133 | #ifdef CONFIG_COMPAT |
@@ -1150,7 +1181,7 @@ static int fb_getput_cmap(struct inode *inode, struct file *file, | |||
1150 | put_user(compat_ptr(data), &cmap->transp)) | 1181 | put_user(compat_ptr(data), &cmap->transp)) |
1151 | return -EFAULT; | 1182 | return -EFAULT; |
1152 | 1183 | ||
1153 | err = fb_ioctl(inode, file, cmd, (unsigned long) cmap); | 1184 | err = fb_ioctl(file, cmd, (unsigned long) cmap); |
1154 | 1185 | ||
1155 | if (!err) { | 1186 | if (!err) { |
1156 | if (copy_in_user(&cmap32->start, | 1187 | if (copy_in_user(&cmap32->start, |
@@ -1204,7 +1235,7 @@ static int fb_get_fscreeninfo(struct inode *inode, struct file *file, | |||
1204 | 1235 | ||
1205 | old_fs = get_fs(); | 1236 | old_fs = get_fs(); |
1206 | set_fs(KERNEL_DS); | 1237 | set_fs(KERNEL_DS); |
1207 | err = fb_ioctl(inode, file, cmd, (unsigned long) &fix); | 1238 | err = fb_ioctl(file, cmd, (unsigned long) &fix); |
1208 | set_fs(old_fs); | 1239 | set_fs(old_fs); |
1209 | 1240 | ||
1210 | if (!err) | 1241 | if (!err) |
@@ -1231,7 +1262,7 @@ fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
1231 | case FBIOPUT_CON2FBMAP: | 1262 | case FBIOPUT_CON2FBMAP: |
1232 | arg = (unsigned long) compat_ptr(arg); | 1263 | arg = (unsigned long) compat_ptr(arg); |
1233 | case FBIOBLANK: | 1264 | case FBIOBLANK: |
1234 | ret = fb_ioctl(inode, file, cmd, arg); | 1265 | ret = fb_ioctl(file, cmd, arg); |
1235 | break; | 1266 | break; |
1236 | 1267 | ||
1237 | case FBIOGET_FSCREENINFO: | 1268 | case FBIOGET_FSCREENINFO: |
@@ -1358,7 +1389,7 @@ static const struct file_operations fb_fops = { | |||
1358 | .owner = THIS_MODULE, | 1389 | .owner = THIS_MODULE, |
1359 | .read = fb_read, | 1390 | .read = fb_read, |
1360 | .write = fb_write, | 1391 | .write = fb_write, |
1361 | .ioctl = fb_ioctl, | 1392 | .unlocked_ioctl = fb_ioctl, |
1362 | #ifdef CONFIG_COMPAT | 1393 | #ifdef CONFIG_COMPAT |
1363 | .compat_ioctl = fb_compat_ioctl, | 1394 | .compat_ioctl = fb_compat_ioctl, |
1364 | #endif | 1395 | #endif |