drm/radeon/kms: enable use of unmappable VRAM V2
[pandora-kernel.git] / drivers / macintosh / mac_hid.c
1 /*
2  * drivers/macintosh/mac_hid.c
3  *
4  * HID support stuff for Macintosh computers.
5  *
6  * Copyright (C) 2000 Franz Sirl.
7  *
8  * This file will soon be removed in favor of an uinput userspace tool.
9  */
10
11 #include <linux/init.h>
12 #include <linux/proc_fs.h>
13 #include <linux/sysctl.h>
14 #include <linux/input.h>
15 #include <linux/module.h>
16
17 MODULE_LICENSE("GPL");
18
19 static int mouse_emulate_buttons;
20 static int mouse_button2_keycode = KEY_RIGHTCTRL;       /* right control key */
21 static int mouse_button3_keycode = KEY_RIGHTALT;        /* right option key */
22
23 static struct input_dev *mac_hid_emumouse_dev;
24
25 static int mac_hid_create_emumouse(void)
26 {
27         static struct lock_class_key mac_hid_emumouse_dev_event_class;
28         static struct lock_class_key mac_hid_emumouse_dev_mutex_class;
29         int err;
30
31         mac_hid_emumouse_dev = input_allocate_device();
32         if (!mac_hid_emumouse_dev)
33                 return -ENOMEM;
34
35         lockdep_set_class(&mac_hid_emumouse_dev->event_lock,
36                           &mac_hid_emumouse_dev_event_class);
37         lockdep_set_class(&mac_hid_emumouse_dev->mutex,
38                           &mac_hid_emumouse_dev_mutex_class);
39
40         mac_hid_emumouse_dev->name = "Macintosh mouse button emulation";
41         mac_hid_emumouse_dev->id.bustype = BUS_ADB;
42         mac_hid_emumouse_dev->id.vendor = 0x0001;
43         mac_hid_emumouse_dev->id.product = 0x0001;
44         mac_hid_emumouse_dev->id.version = 0x0100;
45
46         mac_hid_emumouse_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
47         mac_hid_emumouse_dev->keybit[BIT_WORD(BTN_MOUSE)] =
48                 BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
49         mac_hid_emumouse_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
50
51         err = input_register_device(mac_hid_emumouse_dev);
52         if (err) {
53                 input_free_device(mac_hid_emumouse_dev);
54                 mac_hid_emumouse_dev = NULL;
55                 return err;
56         }
57
58         return 0;
59 }
60
61 static void mac_hid_destroy_emumouse(void)
62 {
63         input_unregister_device(mac_hid_emumouse_dev);
64         mac_hid_emumouse_dev = NULL;
65 }
66
67 static bool mac_hid_emumouse_filter(struct input_handle *handle,
68                                     unsigned int type, unsigned int code,
69                                     int value)
70 {
71         unsigned int btn;
72
73         if (type != EV_KEY)
74                 return false;
75
76         if (code == mouse_button2_keycode)
77                 btn = BTN_MIDDLE;
78         else if (code == mouse_button3_keycode)
79                 btn = BTN_RIGHT;
80         else
81                 return false;
82
83         input_report_key(mac_hid_emumouse_dev, btn, value);
84         input_sync(mac_hid_emumouse_dev);
85
86         return true;
87 }
88
89 static int mac_hid_emumouse_connect(struct input_handler *handler,
90                                     struct input_dev *dev,
91                                     const struct input_device_id *id)
92 {
93         struct input_handle *handle;
94         int error;
95
96         /* Don't bind to ourselves */
97         if (dev == mac_hid_emumouse_dev)
98                 return -ENODEV;
99
100         handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
101         if (!handle)
102                 return -ENOMEM;
103
104         handle->dev = dev;
105         handle->handler = handler;
106         handle->name = "mac-button-emul";
107
108         error = input_register_handle(handle);
109         if (error) {
110                 printk(KERN_ERR
111                         "mac_hid: Failed to register button emulation handle, "
112                         "error %d\n", error);
113                 goto err_free;
114         }
115
116         error = input_open_device(handle);
117         if (error) {
118                 printk(KERN_ERR
119                         "mac_hid: Failed to open input device, error %d\n",
120                         error);
121                 goto err_unregister;
122         }
123
124         return 0;
125
126  err_unregister:
127         input_unregister_handle(handle);
128  err_free:
129         kfree(handle);
130         return error;
131 }
132
133 static void mac_hid_emumouse_disconnect(struct input_handle *handle)
134 {
135         input_close_device(handle);
136         input_unregister_handle(handle);
137         kfree(handle);
138 }
139
140 static const struct input_device_id mac_hid_emumouse_ids[] = {
141         {
142                 .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
143                 .evbit = { BIT_MASK(EV_KEY) },
144         },
145         { },
146 };
147
148 MODULE_DEVICE_TABLE(input, mac_hid_emumouse_ids);
149
150 static struct input_handler mac_hid_emumouse_handler = {
151         .filter         = mac_hid_emumouse_filter,
152         .connect        = mac_hid_emumouse_connect,
153         .disconnect     = mac_hid_emumouse_disconnect,
154         .name           = "mac-button-emul",
155         .id_table       = mac_hid_emumouse_ids,
156 };
157
158 static int mac_hid_start_emulation(void)
159 {
160         int err;
161
162         err = mac_hid_create_emumouse();
163         if (err)
164                 return err;
165
166         err = input_register_handler(&mac_hid_emumouse_handler);
167         if (err) {
168                 mac_hid_destroy_emumouse();
169                 return err;
170         }
171
172         return 0;
173 }
174
175 static void mac_hid_stop_emulation(void)
176 {
177         input_unregister_handler(&mac_hid_emumouse_handler);
178         mac_hid_destroy_emumouse();
179 }
180
181 static int mac_hid_toggle_emumouse(ctl_table *table, int write,
182                                    void __user *buffer, size_t *lenp,
183                                    loff_t *ppos)
184 {
185         int *valp = table->data;
186         int old_val = *valp;
187         int rc;
188
189         rc = proc_dointvec(table, write, buffer, lenp, ppos);
190
191         if (rc == 0 && write && *valp != old_val) {
192                 if (*valp == 1)
193                         rc = mac_hid_start_emulation();
194                 else if (*valp == 0)
195                         mac_hid_stop_emulation();
196                 else
197                         rc = -EINVAL;
198         }
199
200         /* Restore the old value in case of error */
201         if (rc)
202                 *valp = old_val;
203
204         return rc;
205 }
206
207 /* file(s) in /proc/sys/dev/mac_hid */
208 static ctl_table mac_hid_files[] = {
209         {
210                 .procname       = "mouse_button_emulation",
211                 .data           = &mouse_emulate_buttons,
212                 .maxlen         = sizeof(int),
213                 .mode           = 0644,
214                 .proc_handler   = mac_hid_toggle_emumouse,
215         },
216         {
217                 .procname       = "mouse_button2_keycode",
218                 .data           = &mouse_button2_keycode,
219                 .maxlen         = sizeof(int),
220                 .mode           = 0644,
221                 .proc_handler   = proc_dointvec,
222         },
223         {
224                 .procname       = "mouse_button3_keycode",
225                 .data           = &mouse_button3_keycode,
226                 .maxlen         = sizeof(int),
227                 .mode           = 0644,
228                 .proc_handler   = proc_dointvec,
229         },
230         { }
231 };
232
233 /* dir in /proc/sys/dev */
234 static ctl_table mac_hid_dir[] = {
235         {
236                 .procname       = "mac_hid",
237                 .maxlen         = 0,
238                 .mode           = 0555,
239                 .child          = mac_hid_files,
240         },
241         { }
242 };
243
244 /* /proc/sys/dev itself, in case that is not there yet */
245 static ctl_table mac_hid_root_dir[] = {
246         {
247                 .procname       = "dev",
248                 .maxlen         = 0,
249                 .mode           = 0555,
250                 .child          = mac_hid_dir,
251         },
252         { }
253 };
254
255 static struct ctl_table_header *mac_hid_sysctl_header;
256
257 static int __init mac_hid_init(void)
258 {
259         mac_hid_sysctl_header = register_sysctl_table(mac_hid_root_dir);
260         if (!mac_hid_sysctl_header)
261                 return -ENOMEM;
262
263         return 0;
264 }
265 module_init(mac_hid_init);
266
267 static void __exit mac_hid_exit(void)
268 {
269         unregister_sysctl_table(mac_hid_sysctl_header);
270
271         if (mouse_emulate_buttons)
272                 mac_hid_stop_emulation();
273 }
274 module_exit(mac_hid_exit);