initial import
[ps3linux_kernel_patches_314.git] / 0060-ps3avmgr-char-device.patch
blob4c4ec200d7059f92dbebd51dedb43e6d130346e9
1 --- a/drivers/ps3/ps3av.c 2013-03-07 22:13:51.309374686 +0100
2 +++ b/drivers/ps3/ps3av.c 2013-03-07 22:14:15.449376092 +0100
3 @@ -25,6 +25,8 @@
4 #include <linux/ioctl.h>
5 #include <linux/fb.h>
6 #include <linux/slab.h>
7 +#include <linux/uaccess.h>
8 +#include <linux/miscdevice.h>
10 #include <asm/firmware.h>
11 #include <asm/ps3av.h>
12 @@ -35,6 +37,8 @@
13 #define BUFSIZE 4096 /* vuart buf size */
14 #define PS3AV_BUF_SIZE 512 /* max packet size */
16 +#define DEVICE_NAME "ps3avmngr"
18 static int safe_mode;
20 static int timeout = 5000; /* in msec ( 5 sec ) */
21 @@ -60,6 +64,8 @@
22 struct ps3av_reply_hdr reply_hdr;
23 u8 raw[PS3AV_BUF_SIZE];
24 } recv_buf;
25 + struct miscdevice misc;
26 + int misc_ok;
27 } *ps3av;
29 /* color space */
30 @@ -932,6 +938,68 @@
32 EXPORT_SYMBOL_GPL(ps3av_audio_mute);
34 +static ssize_t ps3av_misc_read(struct file *file, char __user *usrbuf,
35 + size_t count, loff_t *pos)
37 + char *buf;
38 + int result;
40 + buf = kmalloc(count, GFP_KERNEL);
41 + if (!buf)
42 + return -ENOMEM;
44 + result = ps3_vuart_read(ps3av->dev, buf, count);
45 + if (result)
46 + goto out;
48 + if (copy_to_user(usrbuf, buf, count)) {
49 + result = -EFAULT;
50 + goto out;
51 + }
53 + result = count;
55 +out:
57 + kfree(buf);
59 + return result;
62 +static ssize_t ps3av_misc_write(struct file *file, const char __user *usrbuf,
63 + size_t count, loff_t *pos)
65 + char *buf;
66 + int result;
68 + buf = kmalloc(count, GFP_KERNEL);
69 + if (!buf)
70 + return -ENOMEM;
72 + if (copy_from_user(buf, usrbuf, count)) {
73 + result = -EFAULT;
74 + goto out;
75 + }
77 + result = ps3_vuart_write(ps3av->dev, buf, count);
78 + if (result)
79 + goto out;
81 + result = count;
83 +out:
85 + kfree(buf);
87 + return result;
90 +static const struct file_operations ps3av_misc_fops = {
91 + .owner = THIS_MODULE,
92 + .read = ps3av_misc_read,
93 + .write = ps3av_misc_write,
94 +};
96 static int ps3av_probe(struct ps3_system_bus_device *dev)
98 int res;
99 @@ -1003,11 +1071,34 @@
100 ps3av->ps3av_mode = id;
101 mutex_unlock(&ps3av->mutex);
103 + ps3av->misc.parent = &dev->core;
104 + ps3av->misc.minor = MISC_DYNAMIC_MINOR,
105 + ps3av->misc.name = DEVICE_NAME,
106 + ps3av->misc.fops = &ps3av_misc_fops,
108 + res = misc_register(&ps3av->misc);
109 + if (res) {
110 + dev_err(&dev->core, "%s:%u: misc_register failed %d\n",
111 + __func__, __LINE__, res);
112 + goto skip_misc;
115 + ps3av->misc_ok = 1;
117 + dev_info(&dev->core, "%s:%u: registered misc device %d\n",
118 + __func__, __LINE__, ps3av->misc.minor);
120 +skip_misc:
122 dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
124 return 0;
126 fail:
128 + if (ps3av->misc_ok)
129 + misc_deregister(&ps3av->misc);
131 kfree(ps3av);
132 ps3av = NULL;
133 return res;
134 @@ -1017,6 +1108,9 @@
136 dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
137 if (ps3av) {
138 + if (ps3av->misc_ok)
139 + misc_deregister(&ps3av->misc);
141 ps3av_cmd_fin();
142 if (ps3av->wq)
143 destroy_workqueue(ps3av->wq);