static void it_tasklet_func(unsigned long data);
static void ir_tasklet_func(unsigned long data);
+#ifdef CONFIG_COMPAT
+static long dv1394_compat_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg);
+#endif
+
/* GLOBAL DATA */
/* list of all video_cards */
static LIST_HEAD(dv1394_cards);
-static spinlock_t dv1394_cards_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(dv1394_cards_lock);
/* translate from a struct file* to the corresponding struct video_card* */
static int dv1394_fasync(int fd, struct file *file, int on)
{
/* I just copied this code verbatim from Alan Cox's mouse driver example
- (linux/Documentation/DocBook/) */
+ (Documentation/DocBook/) */
struct video_card *video = file_to_video_card(file);
return 0;
}
-static ssize_t dv1394_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
+static ssize_t dv1394_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
{
struct video_card *video = file_to_video_card(file);
DECLARE_WAITQUEUE(wait, current);
}
-static ssize_t dv1394_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
+static ssize_t dv1394_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
{
struct video_card *video = file_to_video_card(file);
DECLARE_WAITQUEUE(wait, current);
/*** DEVICE IOCTL INTERFACE ************************************************/
-/* I *think* the VFS serializes ioctl() for us, so we don't have to worry
- about situations like having two threads in here at once... */
-
-static int dv1394_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+static long dv1394_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
- struct video_card *video = file_to_video_card(file);
+ struct video_card *video;
unsigned long flags;
int ret = -EINVAL;
+ void __user *argp = (void __user *)arg;
DECLARE_WAITQUEUE(wait, current);
+ lock_kernel();
+ video = file_to_video_card(file);
+
/* serialize this to prevent multi-threaded mayhem */
if (file->f_flags & O_NONBLOCK) {
- if (down_trylock(&video->sem))
+ if (down_trylock(&video->sem)) {
+ unlock_kernel();
return -EAGAIN;
+ }
} else {
- if (down_interruptible(&video->sem))
+ if (down_interruptible(&video->sem)) {
+ unlock_kernel();
return -ERESTARTSYS;
+ }
}
switch(cmd)
case DV1394_IOC_INIT: {
struct dv1394_init init;
- if (arg == (unsigned long) NULL) {
+ if (!argp) {
ret = do_dv1394_init_default(video);
} else {
- if (copy_from_user(&init, (void*)arg, sizeof(init))) {
+ if (copy_from_user(&init, argp, sizeof(init))) {
ret = -EFAULT;
goto out;
}
spin_unlock_irqrestore(&video->spinlock, flags);
- if (copy_to_user((void*)arg, &status, sizeof(status))) {
+ if (copy_to_user(argp, &status, sizeof(status))) {
ret = -EFAULT;
goto out;
}
out:
up(&video->sem);
+ unlock_kernel();
return ret;
}
-
-
/*** DEVICE FILE INTERFACE CONTINUED ***************************************/
static int dv1394_open(struct inode *inode, struct file *file)
{
.owner = THIS_MODULE,
.poll = dv1394_poll,
- .ioctl = dv1394_ioctl,
+ .unlocked_ioctl = dv1394_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = dv1394_compat_ioctl,
+#endif
.mmap = dv1394_mmap,
.open = dv1394_open,
.write = dv1394_write,
u32 dropped_frames;
};
-static int handle_dv1394_init(unsigned int fd, unsigned int cmd, unsigned long arg,
- struct file *file)
+/* RED-PEN: this should use compat_alloc_userspace instead */
+
+static int handle_dv1394_init(struct file *file, unsigned int cmd, unsigned long arg)
{
struct dv1394_init32 dv32;
struct dv1394_init dv;
if (file->f_op->ioctl != dv1394_ioctl)
return -EFAULT;
- if (copy_from_user(&dv32, (void *)arg, sizeof(dv32)))
+ if (copy_from_user(&dv32, (void __user *)arg, sizeof(dv32)))
return -EFAULT;
dv.api_version = dv32.api_version;
old_fs = get_fs();
set_fs(KERNEL_DS);
- ret = dv1394_ioctl(file->f_dentry->d_inode, file,
+ ret = dv1394_ioctl(file,
DV1394_IOC_INIT, (unsigned long)&dv);
set_fs(old_fs);
return ret;
}
-static int handle_dv1394_get_status(unsigned int fd, unsigned int cmd, unsigned long arg,
- struct file *file)
+static int handle_dv1394_get_status(struct file *file, unsigned int cmd, unsigned long arg)
{
struct dv1394_status32 dv32;
struct dv1394_status dv;
old_fs = get_fs();
set_fs(KERNEL_DS);
- ret = dv1394_ioctl(file->f_dentry->d_inode, file,
+ ret = dv1394_ioctl(file,
DV1394_IOC_GET_STATUS, (unsigned long)&dv);
set_fs(old_fs);
dv32.n_clear_frames = dv.n_clear_frames;
dv32.dropped_frames = dv.dropped_frames;
- if (copy_to_user((struct dv1394_status32 *)arg, &dv32, sizeof(dv32)))
+ if (copy_to_user((struct dv1394_status32 __user *)arg, &dv32, sizeof(dv32)))
ret = -EFAULT;
}
return ret;
}
+
+
+
+static long dv1394_compat_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ int err;
+ switch (cmd) {
+ case DV1394_IOC_SHUTDOWN:
+ case DV1394_IOC_SUBMIT_FRAMES:
+ case DV1394_IOC_WAIT_FRAMES:
+ case DV1394_IOC_RECEIVE_FRAMES:
+ case DV1394_IOC_START_RECEIVE:
+ return dv1394_ioctl(file, cmd, arg);
+
+ case DV1394_IOC32_INIT:
+ return handle_dv1394_init(file, cmd, arg);
+ case DV1394_IOC32_GET_STATUS:
+ return handle_dv1394_get_status(file, cmd, arg);
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
#endif /* CONFIG_COMPAT */
static void __exit dv1394_exit_module(void)
{
-#ifdef CONFIG_COMPAT
- int ret;
-
- ret = unregister_ioctl32_conversion(DV1394_IOC_SHUTDOWN);
- ret |= unregister_ioctl32_conversion(DV1394_IOC_SUBMIT_FRAMES);
- ret |= unregister_ioctl32_conversion(DV1394_IOC_WAIT_FRAMES);
- ret |= unregister_ioctl32_conversion(DV1394_IOC_RECEIVE_FRAMES);
- ret |= unregister_ioctl32_conversion(DV1394_IOC_START_RECEIVE);
- ret |= unregister_ioctl32_conversion(DV1394_IOC32_INIT);
- ret |= unregister_ioctl32_conversion(DV1394_IOC32_GET_STATUS);
- if (ret)
- printk(KERN_ERR "dv1394: Error unregistering ioctl32 translations\n");
-#endif
-
hpsb_unregister_protocol(&dv1394_driver);
hpsb_unregister_highlevel(&dv1394_highlevel);
return ret;
}
-#ifdef CONFIG_COMPAT
- {
- /* First compatible ones */
- ret = register_ioctl32_conversion(DV1394_IOC_SHUTDOWN, NULL);
- ret |= register_ioctl32_conversion(DV1394_IOC_SUBMIT_FRAMES, NULL);
- ret |= register_ioctl32_conversion(DV1394_IOC_WAIT_FRAMES, NULL);
- ret |= register_ioctl32_conversion(DV1394_IOC_RECEIVE_FRAMES, NULL);
- ret |= register_ioctl32_conversion(DV1394_IOC_START_RECEIVE, NULL);
-
- /* These need to be handled by translation */
- ret |= register_ioctl32_conversion(DV1394_IOC32_INIT, handle_dv1394_init);
- ret |= register_ioctl32_conversion(DV1394_IOC32_GET_STATUS, handle_dv1394_get_status);
- if (ret)
- printk(KERN_ERR "dv1394: Error registering ioctl32 translations\n");
- }
-#endif
-
return 0;
}