1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (C) 2015-2016 Red Hat |
4 | * Copyright (C) 2015 Lyude Paul <thatslyude@gmail.com> |
5 | */ |
6 | |
7 | #include <linux/kernel.h> |
8 | #include <linux/slab.h> |
9 | #include <linux/serio.h> |
10 | #include <linux/notifier.h> |
11 | #include "rmi_driver.h" |
12 | |
13 | #define RMI_F03_RX_DATA_OFB 0x01 |
14 | #define RMI_F03_OB_SIZE 2 |
15 | |
16 | #define RMI_F03_OB_OFFSET 2 |
17 | #define RMI_F03_OB_DATA_OFFSET 1 |
18 | #define RMI_F03_OB_FLAG_TIMEOUT BIT(6) |
19 | #define RMI_F03_OB_FLAG_PARITY BIT(7) |
20 | |
21 | #define RMI_F03_DEVICE_COUNT 0x07 |
22 | #define RMI_F03_BYTES_PER_DEVICE 0x07 |
23 | #define RMI_F03_BYTES_PER_DEVICE_SHIFT 4 |
24 | #define RMI_F03_QUEUE_LENGTH 0x0F |
25 | |
26 | #define 0x01 |
27 | |
28 | struct f03_data { |
29 | struct rmi_function *fn; |
30 | |
31 | struct serio *serio; |
32 | bool serio_registered; |
33 | |
34 | unsigned int overwrite_buttons; |
35 | |
36 | u8 device_count; |
37 | u8 rx_queue_length; |
38 | }; |
39 | |
40 | int rmi_f03_overwrite_button(struct rmi_function *fn, unsigned int button, |
41 | int value) |
42 | { |
43 | struct f03_data *f03 = dev_get_drvdata(dev: &fn->dev); |
44 | unsigned int bit; |
45 | |
46 | if (button < BTN_LEFT || button > BTN_MIDDLE) |
47 | return -EINVAL; |
48 | |
49 | bit = BIT(button - BTN_LEFT); |
50 | |
51 | if (value) |
52 | f03->overwrite_buttons |= bit; |
53 | else |
54 | f03->overwrite_buttons &= ~bit; |
55 | |
56 | return 0; |
57 | } |
58 | |
59 | void rmi_f03_commit_buttons(struct rmi_function *fn) |
60 | { |
61 | struct f03_data *f03 = dev_get_drvdata(dev: &fn->dev); |
62 | struct serio *serio = f03->serio; |
63 | |
64 | serio_pause_rx(serio); |
65 | if (serio->drv) { |
66 | serio->drv->interrupt(serio, PSMOUSE_OOB_EXTRA_BTNS, |
67 | SERIO_OOB_DATA); |
68 | serio->drv->interrupt(serio, f03->overwrite_buttons, |
69 | SERIO_OOB_DATA); |
70 | } |
71 | serio_continue_rx(serio); |
72 | } |
73 | |
74 | static int rmi_f03_pt_write(struct serio *id, unsigned char val) |
75 | { |
76 | struct f03_data *f03 = id->port_data; |
77 | int error; |
78 | |
79 | rmi_dbg(RMI_DEBUG_FN, dev: &f03->fn->dev, |
80 | fmt: "%s: Wrote %.2hhx to PS/2 passthrough address" , |
81 | __func__, val); |
82 | |
83 | error = rmi_write(d: f03->fn->rmi_dev, addr: f03->fn->fd.data_base_addr, data: val); |
84 | if (error) { |
85 | dev_err(&f03->fn->dev, |
86 | "%s: Failed to write to F03 TX register (%d).\n" , |
87 | __func__, error); |
88 | return error; |
89 | } |
90 | |
91 | return 0; |
92 | } |
93 | |
94 | static int rmi_f03_initialize(struct f03_data *f03) |
95 | { |
96 | struct rmi_function *fn = f03->fn; |
97 | struct device *dev = &fn->dev; |
98 | int error; |
99 | u8 bytes_per_device; |
100 | u8 query1; |
101 | u8 query2[RMI_F03_DEVICE_COUNT * RMI_F03_BYTES_PER_DEVICE]; |
102 | size_t query2_len; |
103 | |
104 | error = rmi_read(d: fn->rmi_dev, addr: fn->fd.query_base_addr, buf: &query1); |
105 | if (error) { |
106 | dev_err(dev, "Failed to read query register (%d).\n" , error); |
107 | return error; |
108 | } |
109 | |
110 | f03->device_count = query1 & RMI_F03_DEVICE_COUNT; |
111 | bytes_per_device = (query1 >> RMI_F03_BYTES_PER_DEVICE_SHIFT) & |
112 | RMI_F03_BYTES_PER_DEVICE; |
113 | |
114 | query2_len = f03->device_count * bytes_per_device; |
115 | |
116 | /* |
117 | * The first generation of image sensors don't have a second part to |
118 | * their f03 query, as such we have to set some of these values manually |
119 | */ |
120 | if (query2_len < 1) { |
121 | f03->device_count = 1; |
122 | f03->rx_queue_length = 7; |
123 | } else { |
124 | error = rmi_read_block(d: fn->rmi_dev, addr: fn->fd.query_base_addr + 1, |
125 | buf: query2, len: query2_len); |
126 | if (error) { |
127 | dev_err(dev, |
128 | "Failed to read second set of query registers (%d).\n" , |
129 | error); |
130 | return error; |
131 | } |
132 | |
133 | f03->rx_queue_length = query2[0] & RMI_F03_QUEUE_LENGTH; |
134 | } |
135 | |
136 | return 0; |
137 | } |
138 | |
139 | static int rmi_f03_pt_open(struct serio *serio) |
140 | { |
141 | struct f03_data *f03 = serio->port_data; |
142 | struct rmi_function *fn = f03->fn; |
143 | const u8 ob_len = f03->rx_queue_length * RMI_F03_OB_SIZE; |
144 | const u16 data_addr = fn->fd.data_base_addr + RMI_F03_OB_OFFSET; |
145 | u8 obs[RMI_F03_QUEUE_LENGTH * RMI_F03_OB_SIZE]; |
146 | int error; |
147 | |
148 | /* |
149 | * Consume any pending data. Some devices like to spam with |
150 | * 0xaa 0x00 announcements which may confuse us as we try to |
151 | * probe the device. |
152 | */ |
153 | error = rmi_read_block(d: fn->rmi_dev, addr: data_addr, buf: &obs, len: ob_len); |
154 | if (!error) |
155 | rmi_dbg(RMI_DEBUG_FN, dev: &fn->dev, |
156 | fmt: "%s: Consumed %*ph (%d) from PS2 guest\n" , |
157 | __func__, ob_len, obs, ob_len); |
158 | |
159 | return fn->rmi_dev->driver->set_irq_bits(fn->rmi_dev, fn->irq_mask); |
160 | } |
161 | |
162 | static void rmi_f03_pt_close(struct serio *serio) |
163 | { |
164 | struct f03_data *f03 = serio->port_data; |
165 | struct rmi_function *fn = f03->fn; |
166 | |
167 | fn->rmi_dev->driver->clear_irq_bits(fn->rmi_dev, fn->irq_mask); |
168 | } |
169 | |
170 | static int rmi_f03_register_pt(struct f03_data *f03) |
171 | { |
172 | struct serio *serio; |
173 | |
174 | serio = kzalloc(size: sizeof(struct serio), GFP_KERNEL); |
175 | if (!serio) |
176 | return -ENOMEM; |
177 | |
178 | serio->id.type = SERIO_PS_PSTHRU; |
179 | serio->write = rmi_f03_pt_write; |
180 | serio->open = rmi_f03_pt_open; |
181 | serio->close = rmi_f03_pt_close; |
182 | serio->port_data = f03; |
183 | |
184 | strscpy(p: serio->name, q: "RMI4 PS/2 pass-through" , size: sizeof(serio->name)); |
185 | snprintf(buf: serio->phys, size: sizeof(serio->phys), fmt: "%s/serio0" , |
186 | dev_name(dev: &f03->fn->dev)); |
187 | serio->dev.parent = &f03->fn->dev; |
188 | |
189 | f03->serio = serio; |
190 | |
191 | printk(KERN_INFO "serio: %s port at %s\n" , |
192 | serio->name, dev_name(&f03->fn->dev)); |
193 | serio_register_port(serio); |
194 | |
195 | return 0; |
196 | } |
197 | |
198 | static int rmi_f03_probe(struct rmi_function *fn) |
199 | { |
200 | struct device *dev = &fn->dev; |
201 | struct f03_data *f03; |
202 | int error; |
203 | |
204 | f03 = devm_kzalloc(dev, size: sizeof(struct f03_data), GFP_KERNEL); |
205 | if (!f03) |
206 | return -ENOMEM; |
207 | |
208 | f03->fn = fn; |
209 | |
210 | error = rmi_f03_initialize(f03); |
211 | if (error < 0) |
212 | return error; |
213 | |
214 | if (f03->device_count != 1) |
215 | dev_warn(dev, "found %d devices on PS/2 passthrough" , |
216 | f03->device_count); |
217 | |
218 | dev_set_drvdata(dev, data: f03); |
219 | return 0; |
220 | } |
221 | |
222 | static int rmi_f03_config(struct rmi_function *fn) |
223 | { |
224 | struct f03_data *f03 = dev_get_drvdata(dev: &fn->dev); |
225 | int error; |
226 | |
227 | if (!f03->serio_registered) { |
228 | error = rmi_f03_register_pt(f03); |
229 | if (error) |
230 | return error; |
231 | |
232 | f03->serio_registered = true; |
233 | } else { |
234 | /* |
235 | * We must be re-configuring the sensor, just enable |
236 | * interrupts for this function. |
237 | */ |
238 | fn->rmi_dev->driver->set_irq_bits(fn->rmi_dev, fn->irq_mask); |
239 | } |
240 | |
241 | return 0; |
242 | } |
243 | |
244 | static irqreturn_t rmi_f03_attention(int irq, void *ctx) |
245 | { |
246 | struct rmi_function *fn = ctx; |
247 | struct rmi_device *rmi_dev = fn->rmi_dev; |
248 | struct rmi_driver_data *drvdata = dev_get_drvdata(dev: &rmi_dev->dev); |
249 | struct f03_data *f03 = dev_get_drvdata(dev: &fn->dev); |
250 | const u16 data_addr = fn->fd.data_base_addr + RMI_F03_OB_OFFSET; |
251 | const u8 ob_len = f03->rx_queue_length * RMI_F03_OB_SIZE; |
252 | u8 obs[RMI_F03_QUEUE_LENGTH * RMI_F03_OB_SIZE]; |
253 | u8 ob_status; |
254 | u8 ob_data; |
255 | unsigned int serio_flags; |
256 | int i; |
257 | int error; |
258 | |
259 | if (drvdata->attn_data.data) { |
260 | /* First grab the data passed by the transport device */ |
261 | if (drvdata->attn_data.size < ob_len) { |
262 | dev_warn(&fn->dev, "F03 interrupted, but data is missing!\n" ); |
263 | return IRQ_HANDLED; |
264 | } |
265 | |
266 | memcpy(obs, drvdata->attn_data.data, ob_len); |
267 | |
268 | drvdata->attn_data.data += ob_len; |
269 | drvdata->attn_data.size -= ob_len; |
270 | } else { |
271 | /* Grab all of the data registers, and check them for data */ |
272 | error = rmi_read_block(d: fn->rmi_dev, addr: data_addr, buf: &obs, len: ob_len); |
273 | if (error) { |
274 | dev_err(&fn->dev, |
275 | "%s: Failed to read F03 output buffers: %d\n" , |
276 | __func__, error); |
277 | serio_interrupt(serio: f03->serio, data: 0, SERIO_TIMEOUT); |
278 | return IRQ_RETVAL(error); |
279 | } |
280 | } |
281 | |
282 | for (i = 0; i < ob_len; i += RMI_F03_OB_SIZE) { |
283 | ob_status = obs[i]; |
284 | ob_data = obs[i + RMI_F03_OB_DATA_OFFSET]; |
285 | serio_flags = 0; |
286 | |
287 | if (!(ob_status & RMI_F03_RX_DATA_OFB)) |
288 | continue; |
289 | |
290 | if (ob_status & RMI_F03_OB_FLAG_TIMEOUT) |
291 | serio_flags |= SERIO_TIMEOUT; |
292 | if (ob_status & RMI_F03_OB_FLAG_PARITY) |
293 | serio_flags |= SERIO_PARITY; |
294 | |
295 | rmi_dbg(RMI_DEBUG_FN, dev: &fn->dev, |
296 | fmt: "%s: Received %.2hhx from PS2 guest T: %c P: %c\n" , |
297 | __func__, ob_data, |
298 | serio_flags & SERIO_TIMEOUT ? 'Y' : 'N', |
299 | serio_flags & SERIO_PARITY ? 'Y' : 'N'); |
300 | |
301 | serio_interrupt(serio: f03->serio, data: ob_data, flags: serio_flags); |
302 | } |
303 | |
304 | return IRQ_HANDLED; |
305 | } |
306 | |
307 | static void rmi_f03_remove(struct rmi_function *fn) |
308 | { |
309 | struct f03_data *f03 = dev_get_drvdata(dev: &fn->dev); |
310 | |
311 | if (f03->serio_registered) |
312 | serio_unregister_port(serio: f03->serio); |
313 | } |
314 | |
315 | struct rmi_function_handler rmi_f03_handler = { |
316 | .driver = { |
317 | .name = "rmi4_f03" , |
318 | }, |
319 | .func = 0x03, |
320 | .probe = rmi_f03_probe, |
321 | .config = rmi_f03_config, |
322 | .attention = rmi_f03_attention, |
323 | .remove = rmi_f03_remove, |
324 | }; |
325 | |
326 | MODULE_AUTHOR("Lyude Paul <thatslyude@gmail.com>" ); |
327 | MODULE_DESCRIPTION("RMI F03 module" ); |
328 | MODULE_LICENSE("GPL" ); |
329 | |