1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * cec-core.c - HDMI Consumer Electronics Control framework - Core |
4 | * |
5 | * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved. |
6 | */ |
7 | |
8 | #include <linux/errno.h> |
9 | #include <linux/init.h> |
10 | #include <linux/module.h> |
11 | #include <linux/kernel.h> |
12 | #include <linux/kmod.h> |
13 | #include <linux/slab.h> |
14 | #include <linux/mm.h> |
15 | #include <linux/string.h> |
16 | #include <linux/types.h> |
17 | |
18 | #include "cec-priv.h" |
19 | |
20 | #define CEC_NUM_DEVICES 256 |
21 | #define CEC_NAME "cec" |
22 | |
23 | /* |
24 | * 400 ms is the time it takes for one 16 byte message to be |
25 | * transferred and 5 is the maximum number of retries. Add |
26 | * another 100 ms as a margin. So if the transmit doesn't |
27 | * finish before that time something is really wrong and we |
28 | * have to time out. |
29 | * |
30 | * This is a sign that something it really wrong and a warning |
31 | * will be issued. |
32 | */ |
33 | #define CEC_XFER_TIMEOUT_MS (5 * 400 + 100) |
34 | |
35 | int cec_debug; |
36 | module_param_named(debug, cec_debug, int, 0644); |
37 | MODULE_PARM_DESC(debug, "debug level (0-2)" ); |
38 | |
39 | static bool debug_phys_addr; |
40 | module_param(debug_phys_addr, bool, 0644); |
41 | MODULE_PARM_DESC(debug_phys_addr, "add CEC_CAP_PHYS_ADDR if set" ); |
42 | |
43 | static dev_t cec_dev_t; |
44 | |
45 | /* Active devices */ |
46 | static DEFINE_MUTEX(cec_devnode_lock); |
47 | static DECLARE_BITMAP(cec_devnode_nums, CEC_NUM_DEVICES); |
48 | |
49 | static struct dentry *top_cec_dir; |
50 | |
51 | /* dev to cec_devnode */ |
52 | #define to_cec_devnode(cd) container_of(cd, struct cec_devnode, dev) |
53 | |
54 | int cec_get_device(struct cec_devnode *devnode) |
55 | { |
56 | /* |
57 | * Check if the cec device is available. This needs to be done with |
58 | * the devnode->lock held to prevent an open/unregister race: |
59 | * without the lock, the device could be unregistered and freed between |
60 | * the devnode->registered check and get_device() calls, leading to |
61 | * a crash. |
62 | */ |
63 | mutex_lock(&devnode->lock); |
64 | /* |
65 | * return ENXIO if the cec device has been removed |
66 | * already or if it is not registered anymore. |
67 | */ |
68 | if (!devnode->registered) { |
69 | mutex_unlock(lock: &devnode->lock); |
70 | return -ENXIO; |
71 | } |
72 | /* and increase the device refcount */ |
73 | get_device(dev: &devnode->dev); |
74 | mutex_unlock(lock: &devnode->lock); |
75 | return 0; |
76 | } |
77 | |
78 | void cec_put_device(struct cec_devnode *devnode) |
79 | { |
80 | put_device(dev: &devnode->dev); |
81 | } |
82 | |
83 | /* Called when the last user of the cec device exits. */ |
84 | static void cec_devnode_release(struct device *cd) |
85 | { |
86 | struct cec_devnode *devnode = to_cec_devnode(cd); |
87 | |
88 | mutex_lock(&cec_devnode_lock); |
89 | /* Mark device node number as free */ |
90 | clear_bit(nr: devnode->minor, addr: cec_devnode_nums); |
91 | mutex_unlock(lock: &cec_devnode_lock); |
92 | |
93 | cec_delete_adapter(to_cec_adapter(devnode)); |
94 | } |
95 | |
96 | static const struct bus_type cec_bus_type = { |
97 | .name = CEC_NAME, |
98 | }; |
99 | |
100 | /* |
101 | * Register a cec device node |
102 | * |
103 | * The registration code assigns minor numbers and registers the new device node |
104 | * with the kernel. An error is returned if no free minor number can be found, |
105 | * or if the registration of the device node fails. |
106 | * |
107 | * Zero is returned on success. |
108 | * |
109 | * Note that if the cec_devnode_register call fails, the release() callback of |
110 | * the cec_devnode structure is *not* called, so the caller is responsible for |
111 | * freeing any data. |
112 | */ |
113 | static int __must_check cec_devnode_register(struct cec_devnode *devnode, |
114 | struct module *owner) |
115 | { |
116 | int minor; |
117 | int ret; |
118 | |
119 | /* Part 1: Find a free minor number */ |
120 | mutex_lock(&cec_devnode_lock); |
121 | minor = find_first_zero_bit(addr: cec_devnode_nums, CEC_NUM_DEVICES); |
122 | if (minor == CEC_NUM_DEVICES) { |
123 | mutex_unlock(lock: &cec_devnode_lock); |
124 | pr_err("could not get a free minor\n" ); |
125 | return -ENFILE; |
126 | } |
127 | |
128 | set_bit(nr: minor, addr: cec_devnode_nums); |
129 | mutex_unlock(lock: &cec_devnode_lock); |
130 | |
131 | devnode->minor = minor; |
132 | devnode->dev.bus = &cec_bus_type; |
133 | devnode->dev.devt = MKDEV(MAJOR(cec_dev_t), minor); |
134 | devnode->dev.release = cec_devnode_release; |
135 | dev_set_name(dev: &devnode->dev, name: "cec%d" , devnode->minor); |
136 | device_initialize(dev: &devnode->dev); |
137 | |
138 | /* Part 2: Initialize and register the character device */ |
139 | cdev_init(&devnode->cdev, &cec_devnode_fops); |
140 | devnode->cdev.owner = owner; |
141 | kobject_set_name(kobj: &devnode->cdev.kobj, name: "cec%d" , devnode->minor); |
142 | |
143 | devnode->registered = true; |
144 | ret = cdev_device_add(cdev: &devnode->cdev, dev: &devnode->dev); |
145 | if (ret) { |
146 | devnode->registered = false; |
147 | pr_err("%s: cdev_device_add failed\n" , __func__); |
148 | goto clr_bit; |
149 | } |
150 | |
151 | return 0; |
152 | |
153 | clr_bit: |
154 | mutex_lock(&cec_devnode_lock); |
155 | clear_bit(nr: devnode->minor, addr: cec_devnode_nums); |
156 | mutex_unlock(lock: &cec_devnode_lock); |
157 | return ret; |
158 | } |
159 | |
160 | /* |
161 | * Unregister a cec device node |
162 | * |
163 | * This unregisters the passed device. Future open calls will be met with |
164 | * errors. |
165 | * |
166 | * This function can safely be called if the device node has never been |
167 | * registered or has already been unregistered. |
168 | */ |
169 | static void cec_devnode_unregister(struct cec_adapter *adap) |
170 | { |
171 | struct cec_devnode *devnode = &adap->devnode; |
172 | struct cec_fh *fh; |
173 | |
174 | mutex_lock(&devnode->lock); |
175 | |
176 | /* Check if devnode was never registered or already unregistered */ |
177 | if (!devnode->registered || devnode->unregistered) { |
178 | mutex_unlock(lock: &devnode->lock); |
179 | return; |
180 | } |
181 | devnode->registered = false; |
182 | devnode->unregistered = true; |
183 | |
184 | mutex_lock(&devnode->lock_fhs); |
185 | list_for_each_entry(fh, &devnode->fhs, list) |
186 | wake_up_interruptible(&fh->wait); |
187 | mutex_unlock(lock: &devnode->lock_fhs); |
188 | |
189 | mutex_unlock(lock: &devnode->lock); |
190 | |
191 | mutex_lock(&adap->lock); |
192 | __cec_s_phys_addr(adap, CEC_PHYS_ADDR_INVALID, block: false); |
193 | __cec_s_log_addrs(adap, NULL, block: false); |
194 | // Disable the adapter (since adap->devnode.unregistered is true) |
195 | cec_adap_enable(adap); |
196 | mutex_unlock(lock: &adap->lock); |
197 | |
198 | cdev_device_del(cdev: &devnode->cdev, dev: &devnode->dev); |
199 | put_device(dev: &devnode->dev); |
200 | } |
201 | |
202 | #ifdef CONFIG_DEBUG_FS |
203 | static ssize_t cec_error_inj_write(struct file *file, |
204 | const char __user *ubuf, size_t count, loff_t *ppos) |
205 | { |
206 | struct seq_file *sf = file->private_data; |
207 | struct cec_adapter *adap = sf->private; |
208 | char *buf; |
209 | char *line; |
210 | char *p; |
211 | |
212 | buf = memdup_user_nul(ubuf, min_t(size_t, PAGE_SIZE, count)); |
213 | if (IS_ERR(ptr: buf)) |
214 | return PTR_ERR(ptr: buf); |
215 | p = buf; |
216 | while (p && *p) { |
217 | p = skip_spaces(p); |
218 | line = strsep(&p, "\n" ); |
219 | if (!*line || *line == '#') |
220 | continue; |
221 | if (!call_op(adap, error_inj_parse_line, line)) { |
222 | kfree(objp: buf); |
223 | return -EINVAL; |
224 | } |
225 | } |
226 | kfree(objp: buf); |
227 | return count; |
228 | } |
229 | |
230 | static int cec_error_inj_show(struct seq_file *sf, void *unused) |
231 | { |
232 | struct cec_adapter *adap = sf->private; |
233 | |
234 | return call_op(adap, error_inj_show, sf); |
235 | } |
236 | |
237 | static int cec_error_inj_open(struct inode *inode, struct file *file) |
238 | { |
239 | return single_open(file, cec_error_inj_show, inode->i_private); |
240 | } |
241 | |
242 | static const struct file_operations cec_error_inj_fops = { |
243 | .open = cec_error_inj_open, |
244 | .write = cec_error_inj_write, |
245 | .read = seq_read, |
246 | .llseek = seq_lseek, |
247 | .release = single_release, |
248 | }; |
249 | #endif |
250 | |
251 | struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, |
252 | void *priv, const char *name, u32 caps, |
253 | u8 available_las) |
254 | { |
255 | struct cec_adapter *adap; |
256 | int res; |
257 | |
258 | #ifndef CONFIG_MEDIA_CEC_RC |
259 | caps &= ~CEC_CAP_RC; |
260 | #endif |
261 | |
262 | if (WARN_ON(!caps)) |
263 | return ERR_PTR(error: -EINVAL); |
264 | if (WARN_ON(!ops)) |
265 | return ERR_PTR(error: -EINVAL); |
266 | if (WARN_ON(!available_las || available_las > CEC_MAX_LOG_ADDRS)) |
267 | return ERR_PTR(error: -EINVAL); |
268 | adap = kzalloc(size: sizeof(*adap), GFP_KERNEL); |
269 | if (!adap) |
270 | return ERR_PTR(error: -ENOMEM); |
271 | strscpy(adap->name, name, sizeof(adap->name)); |
272 | adap->phys_addr = CEC_PHYS_ADDR_INVALID; |
273 | adap->cec_pin_is_high = true; |
274 | adap->log_addrs.cec_version = CEC_OP_CEC_VERSION_2_0; |
275 | adap->log_addrs.vendor_id = CEC_VENDOR_ID_NONE; |
276 | adap->capabilities = caps; |
277 | if (debug_phys_addr) |
278 | adap->capabilities |= CEC_CAP_PHYS_ADDR; |
279 | adap->needs_hpd = caps & CEC_CAP_NEEDS_HPD; |
280 | adap->available_log_addrs = available_las; |
281 | adap->sequence = 0; |
282 | adap->ops = ops; |
283 | adap->priv = priv; |
284 | mutex_init(&adap->lock); |
285 | INIT_LIST_HEAD(list: &adap->transmit_queue); |
286 | INIT_LIST_HEAD(list: &adap->wait_queue); |
287 | init_waitqueue_head(&adap->kthread_waitq); |
288 | |
289 | /* adap->devnode initialization */ |
290 | INIT_LIST_HEAD(list: &adap->devnode.fhs); |
291 | mutex_init(&adap->devnode.lock_fhs); |
292 | mutex_init(&adap->devnode.lock); |
293 | |
294 | adap->kthread = kthread_run(cec_thread_func, adap, "cec-%s" , name); |
295 | if (IS_ERR(ptr: adap->kthread)) { |
296 | pr_err("cec-%s: kernel_thread() failed\n" , name); |
297 | res = PTR_ERR(ptr: adap->kthread); |
298 | kfree(objp: adap); |
299 | return ERR_PTR(error: res); |
300 | } |
301 | |
302 | #ifdef CONFIG_MEDIA_CEC_RC |
303 | if (!(caps & CEC_CAP_RC)) |
304 | return adap; |
305 | |
306 | /* Prepare the RC input device */ |
307 | adap->rc = rc_allocate_device(RC_DRIVER_SCANCODE); |
308 | if (!adap->rc) { |
309 | pr_err("cec-%s: failed to allocate memory for rc_dev\n" , |
310 | name); |
311 | kthread_stop(k: adap->kthread); |
312 | kfree(objp: adap); |
313 | return ERR_PTR(error: -ENOMEM); |
314 | } |
315 | |
316 | snprintf(buf: adap->input_phys, size: sizeof(adap->input_phys), |
317 | fmt: "%s/input0" , adap->name); |
318 | |
319 | adap->rc->device_name = adap->name; |
320 | adap->rc->input_phys = adap->input_phys; |
321 | adap->rc->input_id.bustype = BUS_CEC; |
322 | adap->rc->input_id.vendor = 0; |
323 | adap->rc->input_id.product = 0; |
324 | adap->rc->input_id.version = 1; |
325 | adap->rc->driver_name = CEC_NAME; |
326 | adap->rc->allowed_protocols = RC_PROTO_BIT_CEC; |
327 | adap->rc->priv = adap; |
328 | adap->rc->map_name = RC_MAP_CEC; |
329 | adap->rc->timeout = MS_TO_US(550); |
330 | #endif |
331 | return adap; |
332 | } |
333 | EXPORT_SYMBOL_GPL(cec_allocate_adapter); |
334 | |
335 | int cec_register_adapter(struct cec_adapter *adap, |
336 | struct device *parent) |
337 | { |
338 | int res; |
339 | |
340 | if (IS_ERR_OR_NULL(ptr: adap)) |
341 | return 0; |
342 | |
343 | if (WARN_ON(!parent)) |
344 | return -EINVAL; |
345 | |
346 | adap->owner = parent->driver->owner; |
347 | adap->devnode.dev.parent = parent; |
348 | if (!adap->xfer_timeout_ms) |
349 | adap->xfer_timeout_ms = CEC_XFER_TIMEOUT_MS; |
350 | |
351 | #ifdef CONFIG_MEDIA_CEC_RC |
352 | if (adap->capabilities & CEC_CAP_RC) { |
353 | adap->rc->dev.parent = parent; |
354 | res = rc_register_device(dev: adap->rc); |
355 | |
356 | if (res) { |
357 | pr_err("cec-%s: failed to prepare input device\n" , |
358 | adap->name); |
359 | rc_free_device(dev: adap->rc); |
360 | adap->rc = NULL; |
361 | return res; |
362 | } |
363 | } |
364 | #endif |
365 | |
366 | res = cec_devnode_register(devnode: &adap->devnode, owner: adap->owner); |
367 | if (res) { |
368 | #ifdef CONFIG_MEDIA_CEC_RC |
369 | /* Note: rc_unregister also calls rc_free */ |
370 | rc_unregister_device(dev: adap->rc); |
371 | adap->rc = NULL; |
372 | #endif |
373 | return res; |
374 | } |
375 | |
376 | dev_set_drvdata(dev: &adap->devnode.dev, data: adap); |
377 | #ifdef CONFIG_DEBUG_FS |
378 | if (!top_cec_dir) |
379 | return 0; |
380 | |
381 | adap->cec_dir = debugfs_create_dir(name: dev_name(dev: &adap->devnode.dev), |
382 | parent: top_cec_dir); |
383 | |
384 | debugfs_create_devm_seqfile(dev: &adap->devnode.dev, name: "status" , parent: adap->cec_dir, |
385 | read_fn: cec_adap_status); |
386 | |
387 | if (!adap->ops->error_inj_show || !adap->ops->error_inj_parse_line) |
388 | return 0; |
389 | debugfs_create_file(name: "error-inj" , mode: 0644, parent: adap->cec_dir, data: adap, |
390 | fops: &cec_error_inj_fops); |
391 | #endif |
392 | return 0; |
393 | } |
394 | EXPORT_SYMBOL_GPL(cec_register_adapter); |
395 | |
396 | void cec_unregister_adapter(struct cec_adapter *adap) |
397 | { |
398 | if (IS_ERR_OR_NULL(ptr: adap)) |
399 | return; |
400 | |
401 | #ifdef CONFIG_MEDIA_CEC_RC |
402 | /* Note: rc_unregister also calls rc_free */ |
403 | rc_unregister_device(dev: adap->rc); |
404 | adap->rc = NULL; |
405 | #endif |
406 | debugfs_remove_recursive(dentry: adap->cec_dir); |
407 | #ifdef CONFIG_CEC_NOTIFIER |
408 | cec_notifier_cec_adap_unregister(n: adap->notifier, adap); |
409 | #endif |
410 | cec_devnode_unregister(adap); |
411 | } |
412 | EXPORT_SYMBOL_GPL(cec_unregister_adapter); |
413 | |
414 | void cec_delete_adapter(struct cec_adapter *adap) |
415 | { |
416 | if (IS_ERR_OR_NULL(ptr: adap)) |
417 | return; |
418 | if (adap->kthread_config) |
419 | kthread_stop(k: adap->kthread_config); |
420 | kthread_stop(k: adap->kthread); |
421 | if (adap->ops->adap_free) |
422 | adap->ops->adap_free(adap); |
423 | #ifdef CONFIG_MEDIA_CEC_RC |
424 | rc_free_device(dev: adap->rc); |
425 | #endif |
426 | kfree(objp: adap); |
427 | } |
428 | EXPORT_SYMBOL_GPL(cec_delete_adapter); |
429 | |
430 | /* |
431 | * Initialise cec for linux |
432 | */ |
433 | static int __init cec_devnode_init(void) |
434 | { |
435 | int ret = alloc_chrdev_region(&cec_dev_t, 0, CEC_NUM_DEVICES, CEC_NAME); |
436 | |
437 | if (ret < 0) { |
438 | pr_warn("cec: unable to allocate major\n" ); |
439 | return ret; |
440 | } |
441 | |
442 | #ifdef CONFIG_DEBUG_FS |
443 | top_cec_dir = debugfs_create_dir(name: "cec" , NULL); |
444 | if (IS_ERR_OR_NULL(ptr: top_cec_dir)) { |
445 | pr_warn("cec: Failed to create debugfs cec dir\n" ); |
446 | top_cec_dir = NULL; |
447 | } |
448 | #endif |
449 | |
450 | ret = bus_register(bus: &cec_bus_type); |
451 | if (ret < 0) { |
452 | unregister_chrdev_region(cec_dev_t, CEC_NUM_DEVICES); |
453 | pr_warn("cec: bus_register failed\n" ); |
454 | return -EIO; |
455 | } |
456 | |
457 | return 0; |
458 | } |
459 | |
460 | static void __exit cec_devnode_exit(void) |
461 | { |
462 | debugfs_remove_recursive(dentry: top_cec_dir); |
463 | bus_unregister(bus: &cec_bus_type); |
464 | unregister_chrdev_region(cec_dev_t, CEC_NUM_DEVICES); |
465 | } |
466 | |
467 | subsys_initcall(cec_devnode_init); |
468 | module_exit(cec_devnode_exit) |
469 | |
470 | MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>" ); |
471 | MODULE_DESCRIPTION("Device node registration for cec drivers" ); |
472 | MODULE_LICENSE("GPL" ); |
473 | |