]>
Commit | Line | Data |
---|---|---|
9881fe0c HV |
1 | /* |
2 | * cec-adap.c - HDMI Consumer Electronics Control framework - CEC adapter | |
3 | * | |
4 | * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved. | |
5 | * | |
6 | * This program is free software; you may redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License as published by | |
8 | * the Free Software Foundation; version 2 of the License. | |
9 | * | |
10 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
11 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
12 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
13 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |
14 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |
15 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |
16 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
17 | * SOFTWARE. | |
18 | */ | |
19 | ||
20 | #include <linux/errno.h> | |
21 | #include <linux/init.h> | |
22 | #include <linux/module.h> | |
23 | #include <linux/kernel.h> | |
24 | #include <linux/kmod.h> | |
25 | #include <linux/ktime.h> | |
26 | #include <linux/slab.h> | |
27 | #include <linux/mm.h> | |
28 | #include <linux/string.h> | |
29 | #include <linux/types.h> | |
30 | ||
23111ec3 HV |
31 | #include <drm/drm_edid.h> |
32 | ||
9881fe0c HV |
33 | #include "cec-priv.h" |
34 | ||
52bc30fd HV |
35 | static void cec_fill_msg_report_features(struct cec_adapter *adap, |
36 | struct cec_msg *msg, | |
37 | unsigned int la_idx); | |
9881fe0c HV |
38 | |
39 | /* | |
40 | * 400 ms is the time it takes for one 16 byte message to be | |
41 | * transferred and 5 is the maximum number of retries. Add | |
42 | * another 100 ms as a margin. So if the transmit doesn't | |
43 | * finish before that time something is really wrong and we | |
44 | * have to time out. | |
45 | * | |
46 | * This is a sign that something it really wrong and a warning | |
47 | * will be issued. | |
48 | */ | |
49 | #define CEC_XFER_TIMEOUT_MS (5 * 400 + 100) | |
50 | ||
51 | #define call_op(adap, op, arg...) \ | |
52 | (adap->ops->op ? adap->ops->op(adap, ## arg) : 0) | |
53 | ||
54 | #define call_void_op(adap, op, arg...) \ | |
55 | do { \ | |
56 | if (adap->ops->op) \ | |
57 | adap->ops->op(adap, ## arg); \ | |
58 | } while (0) | |
59 | ||
60 | static int cec_log_addr2idx(const struct cec_adapter *adap, u8 log_addr) | |
61 | { | |
62 | int i; | |
63 | ||
64 | for (i = 0; i < adap->log_addrs.num_log_addrs; i++) | |
65 | if (adap->log_addrs.log_addr[i] == log_addr) | |
66 | return i; | |
67 | return -1; | |
68 | } | |
69 | ||
70 | static unsigned int cec_log_addr2dev(const struct cec_adapter *adap, u8 log_addr) | |
71 | { | |
72 | int i = cec_log_addr2idx(adap, log_addr); | |
73 | ||
74 | return adap->log_addrs.primary_device_type[i < 0 ? 0 : i]; | |
75 | } | |
76 | ||
77 | /* | |
78 | * Queue a new event for this filehandle. If ts == 0, then set it | |
79 | * to the current time. | |
80 | * | |
81 | * The two events that are currently defined do not need to keep track | |
82 | * of intermediate events, so no actual queue of events is needed, | |
83 | * instead just store the latest state and the total number of lost | |
84 | * messages. | |
85 | * | |
86 | * Should new events be added in the future that require intermediate | |
87 | * results to be queued as well, then a proper queue data structure is | |
88 | * required. But until then, just keep it simple. | |
89 | */ | |
90 | void cec_queue_event_fh(struct cec_fh *fh, | |
91 | const struct cec_event *new_ev, u64 ts) | |
92 | { | |
93 | struct cec_event *ev = &fh->events[new_ev->event - 1]; | |
94 | ||
95 | if (ts == 0) | |
96 | ts = ktime_get_ns(); | |
97 | ||
98 | mutex_lock(&fh->lock); | |
99 | if (new_ev->event == CEC_EVENT_LOST_MSGS && | |
100 | fh->pending_events & (1 << new_ev->event)) { | |
101 | /* | |
102 | * If there is already a lost_msgs event, then just | |
103 | * update the lost_msgs count. This effectively | |
104 | * merges the old and new events into one. | |
105 | */ | |
106 | ev->lost_msgs.lost_msgs += new_ev->lost_msgs.lost_msgs; | |
107 | goto unlock; | |
108 | } | |
109 | ||
110 | /* | |
111 | * Intermediate states are not interesting, so just | |
112 | * overwrite any older event. | |
113 | */ | |
114 | *ev = *new_ev; | |
115 | ev->ts = ts; | |
116 | fh->pending_events |= 1 << new_ev->event; | |
117 | ||
118 | unlock: | |
119 | mutex_unlock(&fh->lock); | |
120 | wake_up_interruptible(&fh->wait); | |
121 | } | |
122 | ||
123 | /* Queue a new event for all open filehandles. */ | |
124 | static void cec_queue_event(struct cec_adapter *adap, | |
125 | const struct cec_event *ev) | |
126 | { | |
127 | u64 ts = ktime_get_ns(); | |
128 | struct cec_fh *fh; | |
129 | ||
62148f09 | 130 | mutex_lock(&adap->devnode.lock); |
9881fe0c HV |
131 | list_for_each_entry(fh, &adap->devnode.fhs, list) |
132 | cec_queue_event_fh(fh, ev, ts); | |
62148f09 | 133 | mutex_unlock(&adap->devnode.lock); |
9881fe0c HV |
134 | } |
135 | ||
136 | /* | |
137 | * Queue a new message for this filehandle. If there is no more room | |
138 | * in the queue, then send the LOST_MSGS event instead. | |
139 | */ | |
140 | static void cec_queue_msg_fh(struct cec_fh *fh, const struct cec_msg *msg) | |
141 | { | |
142 | static const struct cec_event ev_lost_msg = { | |
6a91d60a | 143 | .ts = 0, |
9881fe0c | 144 | .event = CEC_EVENT_LOST_MSGS, |
6a91d60a AM |
145 | .flags = 0, |
146 | { | |
147 | .lost_msgs.lost_msgs = 1, | |
148 | }, | |
9881fe0c HV |
149 | }; |
150 | struct cec_msg_entry *entry; | |
151 | ||
152 | mutex_lock(&fh->lock); | |
153 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); | |
154 | if (!entry) | |
155 | goto lost_msgs; | |
156 | ||
157 | entry->msg = *msg; | |
158 | /* Add new msg at the end of the queue */ | |
159 | list_add_tail(&entry->list, &fh->msgs); | |
160 | ||
161 | /* | |
11065f85 | 162 | * if the queue now has more than CEC_MAX_MSG_RX_QUEUE_SZ |
9881fe0c HV |
163 | * messages, drop the oldest one and send a lost message event. |
164 | */ | |
11065f85 | 165 | if (fh->queued_msgs == CEC_MAX_MSG_RX_QUEUE_SZ) { |
9881fe0c HV |
166 | list_del(&entry->list); |
167 | goto lost_msgs; | |
168 | } | |
169 | fh->queued_msgs++; | |
170 | mutex_unlock(&fh->lock); | |
171 | wake_up_interruptible(&fh->wait); | |
172 | return; | |
173 | ||
174 | lost_msgs: | |
175 | mutex_unlock(&fh->lock); | |
176 | cec_queue_event_fh(fh, &ev_lost_msg, 0); | |
177 | } | |
178 | ||
179 | /* | |
180 | * Queue the message for those filehandles that are in monitor mode. | |
181 | * If valid_la is true (this message is for us or was sent by us), | |
182 | * then pass it on to any monitoring filehandle. If this message | |
183 | * isn't for us or from us, then only give it to filehandles that | |
184 | * are in MONITOR_ALL mode. | |
185 | * | |
186 | * This can only happen if the CEC_CAP_MONITOR_ALL capability is | |
187 | * set and the CEC adapter was placed in 'monitor all' mode. | |
188 | */ | |
189 | static void cec_queue_msg_monitor(struct cec_adapter *adap, | |
190 | const struct cec_msg *msg, | |
191 | bool valid_la) | |
192 | { | |
193 | struct cec_fh *fh; | |
194 | u32 monitor_mode = valid_la ? CEC_MODE_MONITOR : | |
195 | CEC_MODE_MONITOR_ALL; | |
196 | ||
62148f09 | 197 | mutex_lock(&adap->devnode.lock); |
9881fe0c HV |
198 | list_for_each_entry(fh, &adap->devnode.fhs, list) { |
199 | if (fh->mode_follower >= monitor_mode) | |
200 | cec_queue_msg_fh(fh, msg); | |
201 | } | |
62148f09 | 202 | mutex_unlock(&adap->devnode.lock); |
9881fe0c HV |
203 | } |
204 | ||
205 | /* | |
206 | * Queue the message for follower filehandles. | |
207 | */ | |
208 | static void cec_queue_msg_followers(struct cec_adapter *adap, | |
209 | const struct cec_msg *msg) | |
210 | { | |
211 | struct cec_fh *fh; | |
212 | ||
62148f09 | 213 | mutex_lock(&adap->devnode.lock); |
9881fe0c HV |
214 | list_for_each_entry(fh, &adap->devnode.fhs, list) { |
215 | if (fh->mode_follower == CEC_MODE_FOLLOWER) | |
216 | cec_queue_msg_fh(fh, msg); | |
217 | } | |
62148f09 | 218 | mutex_unlock(&adap->devnode.lock); |
9881fe0c HV |
219 | } |
220 | ||
221 | /* Notify userspace of an adapter state change. */ | |
222 | static void cec_post_state_event(struct cec_adapter *adap) | |
223 | { | |
224 | struct cec_event ev = { | |
225 | .event = CEC_EVENT_STATE_CHANGE, | |
226 | }; | |
227 | ||
228 | ev.state_change.phys_addr = adap->phys_addr; | |
229 | ev.state_change.log_addr_mask = adap->log_addrs.log_addr_mask; | |
230 | cec_queue_event(adap, &ev); | |
231 | } | |
232 | ||
233 | /* | |
234 | * A CEC transmit (and a possible wait for reply) completed. | |
235 | * If this was in blocking mode, then complete it, otherwise | |
236 | * queue the message for userspace to dequeue later. | |
237 | * | |
238 | * This function is called with adap->lock held. | |
239 | */ | |
240 | static void cec_data_completed(struct cec_data *data) | |
241 | { | |
242 | /* | |
243 | * Delete this transmit from the filehandle's xfer_list since | |
244 | * we're done with it. | |
245 | * | |
246 | * Note that if the filehandle is closed before this transmit | |
247 | * finished, then the release() function will set data->fh to NULL. | |
248 | * Without that we would be referring to a closed filehandle. | |
249 | */ | |
250 | if (data->fh) | |
251 | list_del(&data->xfer_list); | |
252 | ||
253 | if (data->blocking) { | |
254 | /* | |
255 | * Someone is blocking so mark the message as completed | |
256 | * and call complete. | |
257 | */ | |
258 | data->completed = true; | |
259 | complete(&data->c); | |
260 | } else { | |
261 | /* | |
262 | * No blocking, so just queue the message if needed and | |
263 | * free the memory. | |
264 | */ | |
265 | if (data->fh) | |
266 | cec_queue_msg_fh(data->fh, &data->msg); | |
267 | kfree(data); | |
268 | } | |
269 | } | |
270 | ||
271 | /* | |
272 | * A pending CEC transmit needs to be cancelled, either because the CEC | |
273 | * adapter is disabled or the transmit takes an impossibly long time to | |
274 | * finish. | |
275 | * | |
276 | * This function is called with adap->lock held. | |
277 | */ | |
278 | static void cec_data_cancel(struct cec_data *data) | |
279 | { | |
280 | /* | |
281 | * It's either the current transmit, or it is a pending | |
282 | * transmit. Take the appropriate action to clear it. | |
283 | */ | |
11065f85 | 284 | if (data->adap->transmitting == data) { |
9881fe0c | 285 | data->adap->transmitting = NULL; |
11065f85 | 286 | } else { |
9881fe0c | 287 | list_del_init(&data->list); |
11065f85 HV |
288 | if (!(data->msg.tx_status & CEC_TX_STATUS_OK)) |
289 | data->adap->transmit_queue_sz--; | |
290 | } | |
9881fe0c HV |
291 | |
292 | /* Mark it as an error */ | |
980e0b36 | 293 | data->msg.tx_ts = ktime_get_ns(); |
12047612 HV |
294 | data->msg.tx_status |= CEC_TX_STATUS_ERROR | |
295 | CEC_TX_STATUS_MAX_RETRIES; | |
296 | data->msg.tx_error_cnt++; | |
9881fe0c | 297 | data->attempts = 0; |
9881fe0c HV |
298 | /* Queue transmitted message for monitoring purposes */ |
299 | cec_queue_msg_monitor(data->adap, &data->msg, 1); | |
300 | ||
301 | cec_data_completed(data); | |
302 | } | |
303 | ||
b39f93ef HV |
304 | /* |
305 | * Flush all pending transmits and cancel any pending timeout work. | |
306 | * | |
307 | * This function is called with adap->lock held. | |
308 | */ | |
309 | static void cec_flush(struct cec_adapter *adap) | |
310 | { | |
311 | struct cec_data *data, *n; | |
312 | ||
313 | /* | |
314 | * If the adapter is disabled, or we're asked to stop, | |
315 | * then cancel any pending transmits. | |
316 | */ | |
317 | while (!list_empty(&adap->transmit_queue)) { | |
318 | data = list_first_entry(&adap->transmit_queue, | |
319 | struct cec_data, list); | |
320 | cec_data_cancel(data); | |
321 | } | |
322 | if (adap->transmitting) | |
323 | cec_data_cancel(adap->transmitting); | |
324 | ||
325 | /* Cancel the pending timeout work. */ | |
326 | list_for_each_entry_safe(data, n, &adap->wait_queue, list) { | |
327 | if (cancel_delayed_work(&data->work)) | |
328 | cec_data_cancel(data); | |
329 | /* | |
330 | * If cancel_delayed_work returned false, then | |
331 | * the cec_wait_timeout function is running, | |
332 | * which will call cec_data_completed. So no | |
333 | * need to do anything special in that case. | |
334 | */ | |
335 | } | |
336 | } | |
337 | ||
9881fe0c HV |
338 | /* |
339 | * Main CEC state machine | |
340 | * | |
341 | * Wait until the thread should be stopped, or we are not transmitting and | |
342 | * a new transmit message is queued up, in which case we start transmitting | |
343 | * that message. When the adapter finished transmitting the message it will | |
344 | * call cec_transmit_done(). | |
345 | * | |
346 | * If the adapter is disabled, then remove all queued messages instead. | |
347 | * | |
348 | * If the current transmit times out, then cancel that transmit. | |
349 | */ | |
350 | int cec_thread_func(void *_adap) | |
351 | { | |
352 | struct cec_adapter *adap = _adap; | |
353 | ||
354 | for (;;) { | |
355 | unsigned int signal_free_time; | |
356 | struct cec_data *data; | |
357 | bool timeout = false; | |
358 | u8 attempts; | |
359 | ||
360 | if (adap->transmitting) { | |
361 | int err; | |
362 | ||
363 | /* | |
364 | * We are transmitting a message, so add a timeout | |
365 | * to prevent the state machine to get stuck waiting | |
366 | * for this message to finalize and add a check to | |
367 | * see if the adapter is disabled in which case the | |
368 | * transmit should be canceled. | |
369 | */ | |
370 | err = wait_event_interruptible_timeout(adap->kthread_waitq, | |
f902c1e9 HV |
371 | (adap->needs_hpd && |
372 | (!adap->is_configured && !adap->is_configuring)) || | |
9881fe0c | 373 | kthread_should_stop() || |
9881fe0c HV |
374 | (!adap->transmitting && |
375 | !list_empty(&adap->transmit_queue)), | |
376 | msecs_to_jiffies(CEC_XFER_TIMEOUT_MS)); | |
377 | timeout = err == 0; | |
378 | } else { | |
379 | /* Otherwise we just wait for something to happen. */ | |
380 | wait_event_interruptible(adap->kthread_waitq, | |
381 | kthread_should_stop() || | |
382 | (!adap->transmitting && | |
383 | !list_empty(&adap->transmit_queue))); | |
384 | } | |
385 | ||
386 | mutex_lock(&adap->lock); | |
387 | ||
f902c1e9 HV |
388 | if ((adap->needs_hpd && |
389 | (!adap->is_configured && !adap->is_configuring)) || | |
390 | kthread_should_stop()) { | |
b39f93ef | 391 | cec_flush(adap); |
9881fe0c HV |
392 | goto unlock; |
393 | } | |
394 | ||
395 | if (adap->transmitting && timeout) { | |
396 | /* | |
397 | * If we timeout, then log that. This really shouldn't | |
398 | * happen and is an indication of a faulty CEC adapter | |
399 | * driver, or the CEC bus is in some weird state. | |
400 | */ | |
a7a04b5b | 401 | dprintk(0, "%s: message %*ph timed out!\n", __func__, |
9881fe0c HV |
402 | adap->transmitting->msg.len, |
403 | adap->transmitting->msg.msg); | |
404 | /* Just give up on this. */ | |
405 | cec_data_cancel(adap->transmitting); | |
406 | goto unlock; | |
407 | } | |
408 | ||
409 | /* | |
410 | * If we are still transmitting, or there is nothing new to | |
411 | * transmit, then just continue waiting. | |
412 | */ | |
413 | if (adap->transmitting || list_empty(&adap->transmit_queue)) | |
414 | goto unlock; | |
415 | ||
416 | /* Get a new message to transmit */ | |
417 | data = list_first_entry(&adap->transmit_queue, | |
418 | struct cec_data, list); | |
419 | list_del_init(&data->list); | |
11065f85 | 420 | adap->transmit_queue_sz--; |
533a3f7b | 421 | |
9881fe0c HV |
422 | /* Make this the current transmitting message */ |
423 | adap->transmitting = data; | |
424 | ||
425 | /* | |
426 | * Suggested number of attempts as per the CEC 2.0 spec: | |
427 | * 4 attempts is the default, except for 'secondary poll | |
428 | * messages', i.e. poll messages not sent during the adapter | |
429 | * configuration phase when it allocates logical addresses. | |
430 | */ | |
431 | if (data->msg.len == 1 && adap->is_configured) | |
432 | attempts = 2; | |
433 | else | |
434 | attempts = 4; | |
435 | ||
436 | /* Set the suggested signal free time */ | |
437 | if (data->attempts) { | |
438 | /* should be >= 3 data bit periods for a retry */ | |
439 | signal_free_time = CEC_SIGNAL_FREE_TIME_RETRY; | |
440 | } else if (data->new_initiator) { | |
441 | /* should be >= 5 data bit periods for new initiator */ | |
442 | signal_free_time = CEC_SIGNAL_FREE_TIME_NEW_INITIATOR; | |
443 | } else { | |
444 | /* | |
445 | * should be >= 7 data bit periods for sending another | |
446 | * frame immediately after another. | |
447 | */ | |
448 | signal_free_time = CEC_SIGNAL_FREE_TIME_NEXT_XFER; | |
449 | } | |
450 | if (data->attempts == 0) | |
451 | data->attempts = attempts; | |
452 | ||
453 | /* Tell the adapter to transmit, cancel on error */ | |
454 | if (adap->ops->adap_transmit(adap, data->attempts, | |
455 | signal_free_time, &data->msg)) | |
456 | cec_data_cancel(data); | |
457 | ||
458 | unlock: | |
459 | mutex_unlock(&adap->lock); | |
460 | ||
461 | if (kthread_should_stop()) | |
462 | break; | |
463 | } | |
464 | return 0; | |
465 | } | |
466 | ||
467 | /* | |
468 | * Called by the CEC adapter if a transmit finished. | |
469 | */ | |
470 | void cec_transmit_done(struct cec_adapter *adap, u8 status, u8 arb_lost_cnt, | |
471 | u8 nack_cnt, u8 low_drive_cnt, u8 error_cnt) | |
472 | { | |
473 | struct cec_data *data; | |
474 | struct cec_msg *msg; | |
980e0b36 | 475 | u64 ts = ktime_get_ns(); |
9881fe0c | 476 | |
a7a04b5b | 477 | dprintk(2, "%s: status %02x\n", __func__, status); |
9881fe0c HV |
478 | mutex_lock(&adap->lock); |
479 | data = adap->transmitting; | |
480 | if (!data) { | |
481 | /* | |
482 | * This can happen if a transmit was issued and the cable is | |
483 | * unplugged while the transmit is ongoing. Ignore this | |
484 | * transmit in that case. | |
485 | */ | |
a7a04b5b HV |
486 | dprintk(1, "%s was called without an ongoing transmit!\n", |
487 | __func__); | |
9881fe0c HV |
488 | goto unlock; |
489 | } | |
490 | ||
491 | msg = &data->msg; | |
492 | ||
493 | /* Drivers must fill in the status! */ | |
494 | WARN_ON(status == 0); | |
980e0b36 | 495 | msg->tx_ts = ts; |
9881fe0c HV |
496 | msg->tx_status |= status; |
497 | msg->tx_arb_lost_cnt += arb_lost_cnt; | |
498 | msg->tx_nack_cnt += nack_cnt; | |
499 | msg->tx_low_drive_cnt += low_drive_cnt; | |
500 | msg->tx_error_cnt += error_cnt; | |
501 | ||
502 | /* Mark that we're done with this transmit */ | |
503 | adap->transmitting = NULL; | |
504 | ||
505 | /* | |
506 | * If there are still retry attempts left and there was an error and | |
507 | * the hardware didn't signal that it retried itself (by setting | |
508 | * CEC_TX_STATUS_MAX_RETRIES), then we will retry ourselves. | |
509 | */ | |
510 | if (data->attempts > 1 && | |
511 | !(status & (CEC_TX_STATUS_MAX_RETRIES | CEC_TX_STATUS_OK))) { | |
512 | /* Retry this message */ | |
513 | data->attempts--; | |
a7a04b5b HV |
514 | if (msg->timeout) |
515 | dprintk(2, "retransmit: %*ph (attempts: %d, wait for 0x%02x)\n", | |
516 | msg->len, msg->msg, data->attempts, msg->reply); | |
517 | else | |
518 | dprintk(2, "retransmit: %*ph (attempts: %d)\n", | |
519 | msg->len, msg->msg, data->attempts); | |
9881fe0c HV |
520 | /* Add the message in front of the transmit queue */ |
521 | list_add(&data->list, &adap->transmit_queue); | |
11065f85 | 522 | adap->transmit_queue_sz++; |
9881fe0c HV |
523 | goto wake_thread; |
524 | } | |
525 | ||
526 | data->attempts = 0; | |
527 | ||
528 | /* Always set CEC_TX_STATUS_MAX_RETRIES on error */ | |
529 | if (!(status & CEC_TX_STATUS_OK)) | |
530 | msg->tx_status |= CEC_TX_STATUS_MAX_RETRIES; | |
531 | ||
532 | /* Queue transmitted message for monitoring purposes */ | |
533 | cec_queue_msg_monitor(adap, msg, 1); | |
534 | ||
86e3577f HV |
535 | if ((status & CEC_TX_STATUS_OK) && adap->is_configured && |
536 | msg->timeout) { | |
9881fe0c HV |
537 | /* |
538 | * Queue the message into the wait queue if we want to wait | |
539 | * for a reply. | |
540 | */ | |
541 | list_add_tail(&data->list, &adap->wait_queue); | |
542 | schedule_delayed_work(&data->work, | |
543 | msecs_to_jiffies(msg->timeout)); | |
544 | } else { | |
545 | /* Otherwise we're done */ | |
546 | cec_data_completed(data); | |
547 | } | |
548 | ||
549 | wake_thread: | |
550 | /* | |
551 | * Wake up the main thread to see if another message is ready | |
552 | * for transmitting or to retry the current message. | |
553 | */ | |
554 | wake_up_interruptible(&adap->kthread_waitq); | |
555 | unlock: | |
556 | mutex_unlock(&adap->lock); | |
557 | } | |
558 | EXPORT_SYMBOL_GPL(cec_transmit_done); | |
559 | ||
c94cdc1e HV |
560 | void cec_transmit_attempt_done(struct cec_adapter *adap, u8 status) |
561 | { | |
562 | switch (status) { | |
563 | case CEC_TX_STATUS_OK: | |
564 | cec_transmit_done(adap, status, 0, 0, 0, 0); | |
565 | return; | |
566 | case CEC_TX_STATUS_ARB_LOST: | |
567 | cec_transmit_done(adap, status, 1, 0, 0, 0); | |
568 | return; | |
569 | case CEC_TX_STATUS_NACK: | |
570 | cec_transmit_done(adap, status, 0, 1, 0, 0); | |
571 | return; | |
572 | case CEC_TX_STATUS_LOW_DRIVE: | |
573 | cec_transmit_done(adap, status, 0, 0, 1, 0); | |
574 | return; | |
575 | case CEC_TX_STATUS_ERROR: | |
576 | cec_transmit_done(adap, status, 0, 0, 0, 1); | |
577 | return; | |
578 | default: | |
579 | /* Should never happen */ | |
580 | WARN(1, "cec-%s: invalid status 0x%02x\n", adap->name, status); | |
581 | return; | |
582 | } | |
583 | } | |
584 | EXPORT_SYMBOL_GPL(cec_transmit_attempt_done); | |
585 | ||
9881fe0c HV |
586 | /* |
587 | * Called when waiting for a reply times out. | |
588 | */ | |
589 | static void cec_wait_timeout(struct work_struct *work) | |
590 | { | |
591 | struct cec_data *data = container_of(work, struct cec_data, work.work); | |
592 | struct cec_adapter *adap = data->adap; | |
593 | ||
594 | mutex_lock(&adap->lock); | |
595 | /* | |
596 | * Sanity check in case the timeout and the arrival of the message | |
597 | * happened at the same time. | |
598 | */ | |
599 | if (list_empty(&data->list)) | |
600 | goto unlock; | |
601 | ||
602 | /* Mark the message as timed out */ | |
603 | list_del_init(&data->list); | |
980e0b36 | 604 | data->msg.rx_ts = ktime_get_ns(); |
9881fe0c HV |
605 | data->msg.rx_status = CEC_RX_STATUS_TIMEOUT; |
606 | cec_data_completed(data); | |
607 | unlock: | |
608 | mutex_unlock(&adap->lock); | |
609 | } | |
610 | ||
611 | /* | |
612 | * Transmit a message. The fh argument may be NULL if the transmit is not | |
613 | * associated with a specific filehandle. | |
614 | * | |
615 | * This function is called with adap->lock held. | |
616 | */ | |
617 | int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg, | |
618 | struct cec_fh *fh, bool block) | |
619 | { | |
620 | struct cec_data *data; | |
621 | u8 last_initiator = 0xff; | |
622 | unsigned int timeout; | |
623 | int res = 0; | |
624 | ||
40df3a7e HV |
625 | msg->rx_ts = 0; |
626 | msg->tx_ts = 0; | |
627 | msg->rx_status = 0; | |
628 | msg->tx_status = 0; | |
629 | msg->tx_arb_lost_cnt = 0; | |
630 | msg->tx_nack_cnt = 0; | |
631 | msg->tx_low_drive_cnt = 0; | |
632 | msg->tx_error_cnt = 0; | |
40df3a7e HV |
633 | msg->sequence = ++adap->sequence; |
634 | if (!msg->sequence) | |
635 | msg->sequence = ++adap->sequence; | |
636 | ||
9881fe0c HV |
637 | if (msg->reply && msg->timeout == 0) { |
638 | /* Make sure the timeout isn't 0. */ | |
639 | msg->timeout = 1000; | |
640 | } | |
7ae2a888 HV |
641 | if (msg->timeout) |
642 | msg->flags &= CEC_MSG_FL_REPLY_TO_FOLLOWERS; | |
643 | else | |
644 | msg->flags = 0; | |
9881fe0c HV |
645 | |
646 | /* Sanity checks */ | |
647 | if (msg->len == 0 || msg->len > CEC_MAX_MSG_SIZE) { | |
5a137df1 | 648 | dprintk(1, "%s: invalid length %d\n", __func__, msg->len); |
9881fe0c HV |
649 | return -EINVAL; |
650 | } | |
651 | if (msg->timeout && msg->len == 1) { | |
5a137df1 | 652 | dprintk(1, "%s: can't reply for poll msg\n", __func__); |
9881fe0c HV |
653 | return -EINVAL; |
654 | } | |
045344c3 | 655 | memset(msg->msg + msg->len, 0, sizeof(msg->msg) - msg->len); |
9881fe0c | 656 | if (msg->len == 1) { |
42980da2 | 657 | if (cec_msg_destination(msg) == 0xf) { |
5a137df1 | 658 | dprintk(1, "%s: invalid poll message\n", __func__); |
9881fe0c HV |
659 | return -EINVAL; |
660 | } | |
661 | if (cec_has_log_addr(adap, cec_msg_destination(msg))) { | |
662 | /* | |
663 | * If the destination is a logical address our adapter | |
664 | * has already claimed, then just NACK this. | |
665 | * It depends on the hardware what it will do with a | |
666 | * POLL to itself (some OK this), so it is just as | |
667 | * easy to handle it here so the behavior will be | |
668 | * consistent. | |
669 | */ | |
9a3f14ea | 670 | msg->tx_ts = ktime_get_ns(); |
9881fe0c HV |
671 | msg->tx_status = CEC_TX_STATUS_NACK | |
672 | CEC_TX_STATUS_MAX_RETRIES; | |
673 | msg->tx_nack_cnt = 1; | |
674 | return 0; | |
675 | } | |
676 | } | |
677 | if (msg->len > 1 && !cec_msg_is_broadcast(msg) && | |
678 | cec_has_log_addr(adap, cec_msg_destination(msg))) { | |
5a137df1 | 679 | dprintk(1, "%s: destination is the adapter itself\n", __func__); |
9881fe0c HV |
680 | return -EINVAL; |
681 | } | |
42980da2 | 682 | if (msg->len > 1 && adap->is_configured && |
9881fe0c | 683 | !cec_has_log_addr(adap, cec_msg_initiator(msg))) { |
5a137df1 HV |
684 | dprintk(1, "%s: initiator has unknown logical address %d\n", |
685 | __func__, cec_msg_initiator(msg)); | |
9881fe0c HV |
686 | return -EINVAL; |
687 | } | |
25c21078 | 688 | if (!adap->is_configured && !adap->is_configuring) { |
f902c1e9 | 689 | if (adap->needs_hpd || msg->msg[0] != 0xf0) { |
25c21078 HV |
690 | dprintk(1, "%s: adapter is unconfigured\n", __func__); |
691 | return -ENONET; | |
692 | } | |
693 | if (msg->reply) { | |
694 | dprintk(1, "%s: invalid msg->reply\n", __func__); | |
695 | return -EINVAL; | |
696 | } | |
697 | } | |
9881fe0c | 698 | |
25c21078 HV |
699 | if (adap->transmit_queue_sz >= CEC_MAX_MSG_TX_QUEUE_SZ) { |
700 | dprintk(1, "%s: transmit queue full\n", __func__); | |
11065f85 | 701 | return -EBUSY; |
25c21078 | 702 | } |
11065f85 | 703 | |
9881fe0c HV |
704 | data = kzalloc(sizeof(*data), GFP_KERNEL); |
705 | if (!data) | |
706 | return -ENOMEM; | |
707 | ||
708 | if (msg->len > 1 && msg->msg[1] == CEC_MSG_CDC_MESSAGE) { | |
709 | msg->msg[2] = adap->phys_addr >> 8; | |
710 | msg->msg[3] = adap->phys_addr & 0xff; | |
711 | } | |
712 | ||
713 | if (msg->timeout) | |
5a137df1 HV |
714 | dprintk(2, "%s: %*ph (wait for 0x%02x%s)\n", |
715 | __func__, msg->len, msg->msg, msg->reply, !block ? ", nb" : ""); | |
9881fe0c | 716 | else |
5a137df1 HV |
717 | dprintk(2, "%s: %*ph%s\n", |
718 | __func__, msg->len, msg->msg, !block ? " (nb)" : ""); | |
9881fe0c | 719 | |
9881fe0c HV |
720 | data->msg = *msg; |
721 | data->fh = fh; | |
722 | data->adap = adap; | |
723 | data->blocking = block; | |
724 | ||
725 | /* | |
726 | * Determine if this message follows a message from the same | |
727 | * initiator. Needed to determine the free signal time later on. | |
728 | */ | |
729 | if (msg->len > 1) { | |
730 | if (!(list_empty(&adap->transmit_queue))) { | |
731 | const struct cec_data *last; | |
732 | ||
733 | last = list_last_entry(&adap->transmit_queue, | |
734 | const struct cec_data, list); | |
735 | last_initiator = cec_msg_initiator(&last->msg); | |
736 | } else if (adap->transmitting) { | |
737 | last_initiator = | |
738 | cec_msg_initiator(&adap->transmitting->msg); | |
739 | } | |
740 | } | |
741 | data->new_initiator = last_initiator != cec_msg_initiator(msg); | |
742 | init_completion(&data->c); | |
743 | INIT_DELAYED_WORK(&data->work, cec_wait_timeout); | |
744 | ||
9881fe0c HV |
745 | if (fh) |
746 | list_add_tail(&data->xfer_list, &fh->xfer_list); | |
533a3f7b | 747 | |
9881fe0c | 748 | list_add_tail(&data->list, &adap->transmit_queue); |
11065f85 | 749 | adap->transmit_queue_sz++; |
9881fe0c HV |
750 | if (!adap->transmitting) |
751 | wake_up_interruptible(&adap->kthread_waitq); | |
752 | ||
753 | /* All done if we don't need to block waiting for completion */ | |
754 | if (!block) | |
755 | return 0; | |
756 | ||
757 | /* | |
758 | * If we don't get a completion before this time something is really | |
759 | * wrong and we time out. | |
760 | */ | |
761 | timeout = CEC_XFER_TIMEOUT_MS; | |
762 | /* Add the requested timeout if we have to wait for a reply as well */ | |
763 | if (msg->timeout) | |
764 | timeout += msg->timeout; | |
765 | ||
766 | /* | |
767 | * Release the lock and wait, retake the lock afterwards. | |
768 | */ | |
769 | mutex_unlock(&adap->lock); | |
770 | res = wait_for_completion_killable_timeout(&data->c, | |
771 | msecs_to_jiffies(timeout)); | |
772 | mutex_lock(&adap->lock); | |
773 | ||
774 | if (data->completed) { | |
775 | /* The transmit completed (possibly with an error) */ | |
776 | *msg = data->msg; | |
777 | kfree(data); | |
778 | return 0; | |
779 | } | |
780 | /* | |
781 | * The wait for completion timed out or was interrupted, so mark this | |
782 | * as non-blocking and disconnect from the filehandle since it is | |
783 | * still 'in flight'. When it finally completes it will just drop the | |
784 | * result silently. | |
785 | */ | |
786 | data->blocking = false; | |
787 | if (data->fh) | |
788 | list_del(&data->xfer_list); | |
789 | data->fh = NULL; | |
790 | ||
791 | if (res == 0) { /* timed out */ | |
792 | /* Check if the reply or the transmit failed */ | |
793 | if (msg->timeout && (msg->tx_status & CEC_TX_STATUS_OK)) | |
794 | msg->rx_status = CEC_RX_STATUS_TIMEOUT; | |
795 | else | |
796 | msg->tx_status = CEC_TX_STATUS_MAX_RETRIES; | |
797 | } | |
798 | return res > 0 ? 0 : res; | |
799 | } | |
800 | ||
801 | /* Helper function to be used by drivers and this framework. */ | |
802 | int cec_transmit_msg(struct cec_adapter *adap, struct cec_msg *msg, | |
803 | bool block) | |
804 | { | |
805 | int ret; | |
806 | ||
807 | mutex_lock(&adap->lock); | |
808 | ret = cec_transmit_msg_fh(adap, msg, NULL, block); | |
809 | mutex_unlock(&adap->lock); | |
810 | return ret; | |
811 | } | |
812 | EXPORT_SYMBOL_GPL(cec_transmit_msg); | |
813 | ||
814 | /* | |
815 | * I don't like forward references but without this the low-level | |
816 | * cec_received_msg() function would come after a bunch of high-level | |
817 | * CEC protocol handling functions. That was very confusing. | |
818 | */ | |
819 | static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg, | |
820 | bool is_reply); | |
821 | ||
3074fe4a HV |
822 | #define DIRECTED 0x80 |
823 | #define BCAST1_4 0x40 | |
824 | #define BCAST2_0 0x20 /* broadcast only allowed for >= 2.0 */ | |
825 | #define BCAST (BCAST1_4 | BCAST2_0) | |
826 | #define BOTH (BCAST | DIRECTED) | |
827 | ||
828 | /* | |
829 | * Specify minimum length and whether the message is directed, broadcast | |
830 | * or both. Messages that do not match the criteria are ignored as per | |
831 | * the CEC specification. | |
832 | */ | |
833 | static const u8 cec_msg_size[256] = { | |
834 | [CEC_MSG_ACTIVE_SOURCE] = 4 | BCAST, | |
835 | [CEC_MSG_IMAGE_VIEW_ON] = 2 | DIRECTED, | |
836 | [CEC_MSG_TEXT_VIEW_ON] = 2 | DIRECTED, | |
837 | [CEC_MSG_INACTIVE_SOURCE] = 4 | DIRECTED, | |
838 | [CEC_MSG_REQUEST_ACTIVE_SOURCE] = 2 | BCAST, | |
839 | [CEC_MSG_ROUTING_CHANGE] = 6 | BCAST, | |
840 | [CEC_MSG_ROUTING_INFORMATION] = 4 | BCAST, | |
841 | [CEC_MSG_SET_STREAM_PATH] = 4 | BCAST, | |
842 | [CEC_MSG_STANDBY] = 2 | BOTH, | |
843 | [CEC_MSG_RECORD_OFF] = 2 | DIRECTED, | |
844 | [CEC_MSG_RECORD_ON] = 3 | DIRECTED, | |
845 | [CEC_MSG_RECORD_STATUS] = 3 | DIRECTED, | |
846 | [CEC_MSG_RECORD_TV_SCREEN] = 2 | DIRECTED, | |
847 | [CEC_MSG_CLEAR_ANALOGUE_TIMER] = 13 | DIRECTED, | |
848 | [CEC_MSG_CLEAR_DIGITAL_TIMER] = 16 | DIRECTED, | |
849 | [CEC_MSG_CLEAR_EXT_TIMER] = 13 | DIRECTED, | |
850 | [CEC_MSG_SET_ANALOGUE_TIMER] = 13 | DIRECTED, | |
851 | [CEC_MSG_SET_DIGITAL_TIMER] = 16 | DIRECTED, | |
852 | [CEC_MSG_SET_EXT_TIMER] = 13 | DIRECTED, | |
853 | [CEC_MSG_SET_TIMER_PROGRAM_TITLE] = 2 | DIRECTED, | |
854 | [CEC_MSG_TIMER_CLEARED_STATUS] = 3 | DIRECTED, | |
855 | [CEC_MSG_TIMER_STATUS] = 3 | DIRECTED, | |
856 | [CEC_MSG_CEC_VERSION] = 3 | DIRECTED, | |
857 | [CEC_MSG_GET_CEC_VERSION] = 2 | DIRECTED, | |
858 | [CEC_MSG_GIVE_PHYSICAL_ADDR] = 2 | DIRECTED, | |
859 | [CEC_MSG_GET_MENU_LANGUAGE] = 2 | DIRECTED, | |
860 | [CEC_MSG_REPORT_PHYSICAL_ADDR] = 5 | BCAST, | |
861 | [CEC_MSG_SET_MENU_LANGUAGE] = 5 | BCAST, | |
862 | [CEC_MSG_REPORT_FEATURES] = 6 | BCAST, | |
863 | [CEC_MSG_GIVE_FEATURES] = 2 | DIRECTED, | |
864 | [CEC_MSG_DECK_CONTROL] = 3 | DIRECTED, | |
865 | [CEC_MSG_DECK_STATUS] = 3 | DIRECTED, | |
866 | [CEC_MSG_GIVE_DECK_STATUS] = 3 | DIRECTED, | |
867 | [CEC_MSG_PLAY] = 3 | DIRECTED, | |
868 | [CEC_MSG_GIVE_TUNER_DEVICE_STATUS] = 3 | DIRECTED, | |
869 | [CEC_MSG_SELECT_ANALOGUE_SERVICE] = 6 | DIRECTED, | |
870 | [CEC_MSG_SELECT_DIGITAL_SERVICE] = 9 | DIRECTED, | |
871 | [CEC_MSG_TUNER_DEVICE_STATUS] = 7 | DIRECTED, | |
872 | [CEC_MSG_TUNER_STEP_DECREMENT] = 2 | DIRECTED, | |
873 | [CEC_MSG_TUNER_STEP_INCREMENT] = 2 | DIRECTED, | |
874 | [CEC_MSG_DEVICE_VENDOR_ID] = 5 | BCAST, | |
875 | [CEC_MSG_GIVE_DEVICE_VENDOR_ID] = 2 | DIRECTED, | |
876 | [CEC_MSG_VENDOR_COMMAND] = 2 | DIRECTED, | |
877 | [CEC_MSG_VENDOR_COMMAND_WITH_ID] = 5 | BOTH, | |
878 | [CEC_MSG_VENDOR_REMOTE_BUTTON_DOWN] = 2 | BOTH, | |
879 | [CEC_MSG_VENDOR_REMOTE_BUTTON_UP] = 2 | BOTH, | |
880 | [CEC_MSG_SET_OSD_STRING] = 3 | DIRECTED, | |
881 | [CEC_MSG_GIVE_OSD_NAME] = 2 | DIRECTED, | |
882 | [CEC_MSG_SET_OSD_NAME] = 2 | DIRECTED, | |
883 | [CEC_MSG_MENU_REQUEST] = 3 | DIRECTED, | |
884 | [CEC_MSG_MENU_STATUS] = 3 | DIRECTED, | |
885 | [CEC_MSG_USER_CONTROL_PRESSED] = 3 | DIRECTED, | |
886 | [CEC_MSG_USER_CONTROL_RELEASED] = 2 | DIRECTED, | |
887 | [CEC_MSG_GIVE_DEVICE_POWER_STATUS] = 2 | DIRECTED, | |
888 | [CEC_MSG_REPORT_POWER_STATUS] = 3 | DIRECTED | BCAST2_0, | |
889 | [CEC_MSG_FEATURE_ABORT] = 4 | DIRECTED, | |
890 | [CEC_MSG_ABORT] = 2 | DIRECTED, | |
891 | [CEC_MSG_GIVE_AUDIO_STATUS] = 2 | DIRECTED, | |
892 | [CEC_MSG_GIVE_SYSTEM_AUDIO_MODE_STATUS] = 2 | DIRECTED, | |
893 | [CEC_MSG_REPORT_AUDIO_STATUS] = 3 | DIRECTED, | |
894 | [CEC_MSG_REPORT_SHORT_AUDIO_DESCRIPTOR] = 2 | DIRECTED, | |
895 | [CEC_MSG_REQUEST_SHORT_AUDIO_DESCRIPTOR] = 2 | DIRECTED, | |
896 | [CEC_MSG_SET_SYSTEM_AUDIO_MODE] = 3 | BOTH, | |
897 | [CEC_MSG_SYSTEM_AUDIO_MODE_REQUEST] = 2 | DIRECTED, | |
898 | [CEC_MSG_SYSTEM_AUDIO_MODE_STATUS] = 3 | DIRECTED, | |
899 | [CEC_MSG_SET_AUDIO_RATE] = 3 | DIRECTED, | |
900 | [CEC_MSG_INITIATE_ARC] = 2 | DIRECTED, | |
901 | [CEC_MSG_REPORT_ARC_INITIATED] = 2 | DIRECTED, | |
902 | [CEC_MSG_REPORT_ARC_TERMINATED] = 2 | DIRECTED, | |
903 | [CEC_MSG_REQUEST_ARC_INITIATION] = 2 | DIRECTED, | |
904 | [CEC_MSG_REQUEST_ARC_TERMINATION] = 2 | DIRECTED, | |
905 | [CEC_MSG_TERMINATE_ARC] = 2 | DIRECTED, | |
906 | [CEC_MSG_REQUEST_CURRENT_LATENCY] = 4 | BCAST, | |
f3854973 | 907 | [CEC_MSG_REPORT_CURRENT_LATENCY] = 6 | BCAST, |
3074fe4a HV |
908 | [CEC_MSG_CDC_MESSAGE] = 2 | BCAST, |
909 | }; | |
910 | ||
9881fe0c HV |
911 | /* Called by the CEC adapter if a message is received */ |
912 | void cec_received_msg(struct cec_adapter *adap, struct cec_msg *msg) | |
913 | { | |
914 | struct cec_data *data; | |
915 | u8 msg_init = cec_msg_initiator(msg); | |
916 | u8 msg_dest = cec_msg_destination(msg); | |
3074fe4a | 917 | u8 cmd = msg->msg[1]; |
9881fe0c HV |
918 | bool is_reply = false; |
919 | bool valid_la = true; | |
3074fe4a | 920 | u8 min_len = 0; |
9881fe0c | 921 | |
52d802d6 HV |
922 | if (WARN_ON(!msg->len || msg->len > CEC_MAX_MSG_SIZE)) |
923 | return; | |
924 | ||
3f98da96 HV |
925 | /* |
926 | * Some CEC adapters will receive the messages that they transmitted. | |
927 | * This test filters out those messages by checking if we are the | |
928 | * initiator, and just returning in that case. | |
929 | * | |
930 | * Note that this won't work if this is an Unregistered device. | |
931 | * | |
932 | * It is bad practice if the hardware receives the message that it | |
933 | * transmitted and luckily most CEC adapters behave correctly in this | |
934 | * respect. | |
935 | */ | |
936 | if (msg_init != CEC_LOG_ADDR_UNREGISTERED && | |
937 | cec_has_log_addr(adap, msg_init)) | |
938 | return; | |
939 | ||
980e0b36 | 940 | msg->rx_ts = ktime_get_ns(); |
9881fe0c | 941 | msg->rx_status = CEC_RX_STATUS_OK; |
9881fe0c | 942 | msg->sequence = msg->reply = msg->timeout = 0; |
980e0b36 HV |
943 | msg->tx_status = 0; |
944 | msg->tx_ts = 0; | |
8991a63d HV |
945 | msg->tx_arb_lost_cnt = 0; |
946 | msg->tx_nack_cnt = 0; | |
947 | msg->tx_low_drive_cnt = 0; | |
948 | msg->tx_error_cnt = 0; | |
9881fe0c | 949 | msg->flags = 0; |
045344c3 | 950 | memset(msg->msg + msg->len, 0, sizeof(msg->msg) - msg->len); |
9881fe0c | 951 | |
980e0b36 | 952 | mutex_lock(&adap->lock); |
a7a04b5b | 953 | dprintk(2, "%s: %*ph\n", __func__, msg->len, msg->msg); |
9881fe0c HV |
954 | |
955 | /* Check if this message was for us (directed or broadcast). */ | |
956 | if (!cec_msg_is_broadcast(msg)) | |
957 | valid_la = cec_has_log_addr(adap, msg_dest); | |
958 | ||
3074fe4a HV |
959 | /* |
960 | * Check if the length is not too short or if the message is a | |
961 | * broadcast message where a directed message was expected or | |
962 | * vice versa. If so, then the message has to be ignored (according | |
963 | * to section CEC 7.3 and CEC 12.2). | |
964 | */ | |
965 | if (valid_la && msg->len > 1 && cec_msg_size[cmd]) { | |
966 | u8 dir_fl = cec_msg_size[cmd] & BOTH; | |
967 | ||
968 | min_len = cec_msg_size[cmd] & 0x1f; | |
969 | if (msg->len < min_len) | |
970 | valid_la = false; | |
971 | else if (!cec_msg_is_broadcast(msg) && !(dir_fl & DIRECTED)) | |
972 | valid_la = false; | |
973 | else if (cec_msg_is_broadcast(msg) && !(dir_fl & BCAST1_4)) | |
974 | valid_la = false; | |
975 | else if (cec_msg_is_broadcast(msg) && | |
976 | adap->log_addrs.cec_version >= CEC_OP_CEC_VERSION_2_0 && | |
977 | !(dir_fl & BCAST2_0)) | |
978 | valid_la = false; | |
979 | } | |
980 | if (valid_la && min_len) { | |
981 | /* These messages have special length requirements */ | |
982 | switch (cmd) { | |
983 | case CEC_MSG_TIMER_STATUS: | |
984 | if (msg->msg[2] & 0x10) { | |
985 | switch (msg->msg[2] & 0xf) { | |
986 | case CEC_OP_PROG_INFO_NOT_ENOUGH_SPACE: | |
987 | case CEC_OP_PROG_INFO_MIGHT_NOT_BE_ENOUGH_SPACE: | |
988 | if (msg->len < 5) | |
989 | valid_la = false; | |
990 | break; | |
991 | } | |
992 | } else if ((msg->msg[2] & 0xf) == CEC_OP_PROG_ERROR_DUPLICATE) { | |
993 | if (msg->len < 5) | |
994 | valid_la = false; | |
995 | } | |
996 | break; | |
997 | case CEC_MSG_RECORD_ON: | |
998 | switch (msg->msg[2]) { | |
999 | case CEC_OP_RECORD_SRC_OWN: | |
1000 | break; | |
1001 | case CEC_OP_RECORD_SRC_DIGITAL: | |
1002 | if (msg->len < 10) | |
1003 | valid_la = false; | |
1004 | break; | |
1005 | case CEC_OP_RECORD_SRC_ANALOG: | |
1006 | if (msg->len < 7) | |
1007 | valid_la = false; | |
1008 | break; | |
1009 | case CEC_OP_RECORD_SRC_EXT_PLUG: | |
1010 | if (msg->len < 4) | |
1011 | valid_la = false; | |
1012 | break; | |
1013 | case CEC_OP_RECORD_SRC_EXT_PHYS_ADDR: | |
1014 | if (msg->len < 5) | |
1015 | valid_la = false; | |
1016 | break; | |
1017 | } | |
1018 | break; | |
1019 | } | |
1020 | } | |
1021 | ||
9881fe0c | 1022 | /* It's a valid message and not a poll or CDC message */ |
3074fe4a | 1023 | if (valid_la && msg->len > 1 && cmd != CEC_MSG_CDC_MESSAGE) { |
9881fe0c HV |
1024 | bool abort = cmd == CEC_MSG_FEATURE_ABORT; |
1025 | ||
1026 | /* The aborted command is in msg[2] */ | |
1027 | if (abort) | |
1028 | cmd = msg->msg[2]; | |
1029 | ||
1030 | /* | |
1031 | * Walk over all transmitted messages that are waiting for a | |
1032 | * reply. | |
1033 | */ | |
1034 | list_for_each_entry(data, &adap->wait_queue, list) { | |
1035 | struct cec_msg *dst = &data->msg; | |
9881fe0c | 1036 | |
f5580d8d HV |
1037 | /* |
1038 | * The *only* CEC message that has two possible replies | |
1039 | * is CEC_MSG_INITIATE_ARC. | |
1040 | * In this case allow either of the two replies. | |
1041 | */ | |
1042 | if (!abort && dst->msg[1] == CEC_MSG_INITIATE_ARC && | |
1043 | (cmd == CEC_MSG_REPORT_ARC_INITIATED || | |
1044 | cmd == CEC_MSG_REPORT_ARC_TERMINATED) && | |
1045 | (dst->reply == CEC_MSG_REPORT_ARC_INITIATED || | |
1046 | dst->reply == CEC_MSG_REPORT_ARC_TERMINATED)) | |
1047 | dst->reply = cmd; | |
1048 | ||
9881fe0c HV |
1049 | /* Does the command match? */ |
1050 | if ((abort && cmd != dst->msg[1]) || | |
1051 | (!abort && cmd != dst->reply)) | |
1052 | continue; | |
1053 | ||
1054 | /* Does the addressing match? */ | |
1055 | if (msg_init != cec_msg_destination(dst) && | |
1056 | !cec_msg_is_broadcast(dst)) | |
1057 | continue; | |
1058 | ||
1059 | /* We got a reply */ | |
980e0b36 HV |
1060 | memcpy(dst->msg, msg->msg, msg->len); |
1061 | dst->len = msg->len; | |
1062 | dst->rx_ts = msg->rx_ts; | |
1063 | dst->rx_status = msg->rx_status; | |
86e3577f | 1064 | if (abort) |
9881fe0c | 1065 | dst->rx_status |= CEC_RX_STATUS_FEATURE_ABORT; |
adc0c622 | 1066 | msg->flags = dst->flags; |
9881fe0c HV |
1067 | /* Remove it from the wait_queue */ |
1068 | list_del_init(&data->list); | |
1069 | ||
1070 | /* Cancel the pending timeout work */ | |
1071 | if (!cancel_delayed_work(&data->work)) { | |
1072 | mutex_unlock(&adap->lock); | |
1073 | flush_scheduled_work(); | |
1074 | mutex_lock(&adap->lock); | |
1075 | } | |
1076 | /* | |
1077 | * Mark this as a reply, provided someone is still | |
1078 | * waiting for the answer. | |
1079 | */ | |
1080 | if (data->fh) | |
1081 | is_reply = true; | |
1082 | cec_data_completed(data); | |
1083 | break; | |
1084 | } | |
1085 | } | |
1086 | mutex_unlock(&adap->lock); | |
1087 | ||
1088 | /* Pass the message on to any monitoring filehandles */ | |
1089 | cec_queue_msg_monitor(adap, msg, valid_la); | |
1090 | ||
1091 | /* We're done if it is not for us or a poll message */ | |
1092 | if (!valid_la || msg->len <= 1) | |
1093 | return; | |
1094 | ||
3e92d8b2 HV |
1095 | if (adap->log_addrs.log_addr_mask == 0) |
1096 | return; | |
1097 | ||
9881fe0c HV |
1098 | /* |
1099 | * Process the message on the protocol level. If is_reply is true, | |
1100 | * then cec_receive_notify() won't pass on the reply to the listener(s) | |
1101 | * since that was already done by cec_data_completed() above. | |
1102 | */ | |
1103 | cec_receive_notify(adap, msg, is_reply); | |
1104 | } | |
1105 | EXPORT_SYMBOL_GPL(cec_received_msg); | |
1106 | ||
1107 | /* Logical Address Handling */ | |
1108 | ||
1109 | /* | |
1110 | * Attempt to claim a specific logical address. | |
1111 | * | |
1112 | * This function is called with adap->lock held. | |
1113 | */ | |
1114 | static int cec_config_log_addr(struct cec_adapter *adap, | |
1115 | unsigned int idx, | |
1116 | unsigned int log_addr) | |
1117 | { | |
1118 | struct cec_log_addrs *las = &adap->log_addrs; | |
1119 | struct cec_msg msg = { }; | |
1120 | int err; | |
1121 | ||
1122 | if (cec_has_log_addr(adap, log_addr)) | |
1123 | return 0; | |
1124 | ||
1125 | /* Send poll message */ | |
1126 | msg.len = 1; | |
42980da2 | 1127 | msg.msg[0] = (log_addr << 4) | log_addr; |
9881fe0c HV |
1128 | err = cec_transmit_msg_fh(adap, &msg, NULL, true); |
1129 | ||
1130 | /* | |
1131 | * While trying to poll the physical address was reset | |
1132 | * and the adapter was unconfigured, so bail out. | |
1133 | */ | |
1134 | if (!adap->is_configuring) | |
1135 | return -EINTR; | |
1136 | ||
1137 | if (err) | |
1138 | return err; | |
1139 | ||
1140 | if (msg.tx_status & CEC_TX_STATUS_OK) | |
1141 | return 0; | |
1142 | ||
1143 | /* | |
1144 | * Message not acknowledged, so this logical | |
1145 | * address is free to use. | |
1146 | */ | |
1147 | err = adap->ops->adap_log_addr(adap, log_addr); | |
1148 | if (err) | |
1149 | return err; | |
1150 | ||
1151 | las->log_addr[idx] = log_addr; | |
1152 | las->log_addr_mask |= 1 << log_addr; | |
1153 | adap->phys_addrs[log_addr] = adap->phys_addr; | |
9881fe0c HV |
1154 | return 1; |
1155 | } | |
1156 | ||
1157 | /* | |
1158 | * Unconfigure the adapter: clear all logical addresses and send | |
1159 | * the state changed event. | |
1160 | * | |
1161 | * This function is called with adap->lock held. | |
1162 | */ | |
1163 | static void cec_adap_unconfigure(struct cec_adapter *adap) | |
1164 | { | |
f902c1e9 HV |
1165 | if (!adap->needs_hpd || |
1166 | adap->phys_addr != CEC_PHYS_ADDR_INVALID) | |
1167 | WARN_ON(adap->ops->adap_log_addr(adap, CEC_LOG_ADDR_INVALID)); | |
9881fe0c HV |
1168 | adap->log_addrs.log_addr_mask = 0; |
1169 | adap->is_configuring = false; | |
1170 | adap->is_configured = false; | |
1171 | memset(adap->phys_addrs, 0xff, sizeof(adap->phys_addrs)); | |
533a3f7b | 1172 | cec_flush(adap); |
9881fe0c HV |
1173 | wake_up_interruptible(&adap->kthread_waitq); |
1174 | cec_post_state_event(adap); | |
1175 | } | |
1176 | ||
1177 | /* | |
1178 | * Attempt to claim the required logical addresses. | |
1179 | */ | |
1180 | static int cec_config_thread_func(void *arg) | |
1181 | { | |
1182 | /* The various LAs for each type of device */ | |
1183 | static const u8 tv_log_addrs[] = { | |
1184 | CEC_LOG_ADDR_TV, CEC_LOG_ADDR_SPECIFIC, | |
1185 | CEC_LOG_ADDR_INVALID | |
1186 | }; | |
1187 | static const u8 record_log_addrs[] = { | |
1188 | CEC_LOG_ADDR_RECORD_1, CEC_LOG_ADDR_RECORD_2, | |
1189 | CEC_LOG_ADDR_RECORD_3, | |
1190 | CEC_LOG_ADDR_BACKUP_1, CEC_LOG_ADDR_BACKUP_2, | |
1191 | CEC_LOG_ADDR_INVALID | |
1192 | }; | |
1193 | static const u8 tuner_log_addrs[] = { | |
1194 | CEC_LOG_ADDR_TUNER_1, CEC_LOG_ADDR_TUNER_2, | |
1195 | CEC_LOG_ADDR_TUNER_3, CEC_LOG_ADDR_TUNER_4, | |
1196 | CEC_LOG_ADDR_BACKUP_1, CEC_LOG_ADDR_BACKUP_2, | |
1197 | CEC_LOG_ADDR_INVALID | |
1198 | }; | |
1199 | static const u8 playback_log_addrs[] = { | |
1200 | CEC_LOG_ADDR_PLAYBACK_1, CEC_LOG_ADDR_PLAYBACK_2, | |
1201 | CEC_LOG_ADDR_PLAYBACK_3, | |
1202 | CEC_LOG_ADDR_BACKUP_1, CEC_LOG_ADDR_BACKUP_2, | |
1203 | CEC_LOG_ADDR_INVALID | |
1204 | }; | |
1205 | static const u8 audiosystem_log_addrs[] = { | |
1206 | CEC_LOG_ADDR_AUDIOSYSTEM, | |
1207 | CEC_LOG_ADDR_INVALID | |
1208 | }; | |
1209 | static const u8 specific_use_log_addrs[] = { | |
1210 | CEC_LOG_ADDR_SPECIFIC, | |
1211 | CEC_LOG_ADDR_BACKUP_1, CEC_LOG_ADDR_BACKUP_2, | |
1212 | CEC_LOG_ADDR_INVALID | |
1213 | }; | |
1214 | static const u8 *type2addrs[6] = { | |
1215 | [CEC_LOG_ADDR_TYPE_TV] = tv_log_addrs, | |
1216 | [CEC_LOG_ADDR_TYPE_RECORD] = record_log_addrs, | |
1217 | [CEC_LOG_ADDR_TYPE_TUNER] = tuner_log_addrs, | |
1218 | [CEC_LOG_ADDR_TYPE_PLAYBACK] = playback_log_addrs, | |
1219 | [CEC_LOG_ADDR_TYPE_AUDIOSYSTEM] = audiosystem_log_addrs, | |
1220 | [CEC_LOG_ADDR_TYPE_SPECIFIC] = specific_use_log_addrs, | |
1221 | }; | |
1222 | static const u16 type2mask[] = { | |
1223 | [CEC_LOG_ADDR_TYPE_TV] = CEC_LOG_ADDR_MASK_TV, | |
1224 | [CEC_LOG_ADDR_TYPE_RECORD] = CEC_LOG_ADDR_MASK_RECORD, | |
1225 | [CEC_LOG_ADDR_TYPE_TUNER] = CEC_LOG_ADDR_MASK_TUNER, | |
1226 | [CEC_LOG_ADDR_TYPE_PLAYBACK] = CEC_LOG_ADDR_MASK_PLAYBACK, | |
1227 | [CEC_LOG_ADDR_TYPE_AUDIOSYSTEM] = CEC_LOG_ADDR_MASK_AUDIOSYSTEM, | |
1228 | [CEC_LOG_ADDR_TYPE_SPECIFIC] = CEC_LOG_ADDR_MASK_SPECIFIC, | |
1229 | }; | |
1230 | struct cec_adapter *adap = arg; | |
1231 | struct cec_log_addrs *las = &adap->log_addrs; | |
1232 | int err; | |
1233 | int i, j; | |
1234 | ||
1235 | mutex_lock(&adap->lock); | |
1236 | dprintk(1, "physical address: %x.%x.%x.%x, claim %d logical addresses\n", | |
1237 | cec_phys_addr_exp(adap->phys_addr), las->num_log_addrs); | |
1238 | las->log_addr_mask = 0; | |
1239 | ||
1240 | if (las->log_addr_type[0] == CEC_LOG_ADDR_TYPE_UNREGISTERED) | |
1241 | goto configured; | |
1242 | ||
1243 | for (i = 0; i < las->num_log_addrs; i++) { | |
1244 | unsigned int type = las->log_addr_type[i]; | |
1245 | const u8 *la_list; | |
1246 | u8 last_la; | |
1247 | ||
1248 | /* | |
1249 | * The TV functionality can only map to physical address 0. | |
1250 | * For any other address, try the Specific functionality | |
1251 | * instead as per the spec. | |
1252 | */ | |
1253 | if (adap->phys_addr && type == CEC_LOG_ADDR_TYPE_TV) | |
1254 | type = CEC_LOG_ADDR_TYPE_SPECIFIC; | |
1255 | ||
1256 | la_list = type2addrs[type]; | |
1257 | last_la = las->log_addr[i]; | |
1258 | las->log_addr[i] = CEC_LOG_ADDR_INVALID; | |
1259 | if (last_la == CEC_LOG_ADDR_INVALID || | |
1260 | last_la == CEC_LOG_ADDR_UNREGISTERED || | |
f9f96fc1 | 1261 | !((1 << last_la) & type2mask[type])) |
9881fe0c HV |
1262 | last_la = la_list[0]; |
1263 | ||
1264 | err = cec_config_log_addr(adap, i, last_la); | |
1265 | if (err > 0) /* Reused last LA */ | |
1266 | continue; | |
1267 | ||
1268 | if (err < 0) | |
1269 | goto unconfigure; | |
1270 | ||
1271 | for (j = 0; la_list[j] != CEC_LOG_ADDR_INVALID; j++) { | |
1272 | /* Tried this one already, skip it */ | |
1273 | if (la_list[j] == last_la) | |
1274 | continue; | |
1275 | /* The backup addresses are CEC 2.0 specific */ | |
1276 | if ((la_list[j] == CEC_LOG_ADDR_BACKUP_1 || | |
1277 | la_list[j] == CEC_LOG_ADDR_BACKUP_2) && | |
1278 | las->cec_version < CEC_OP_CEC_VERSION_2_0) | |
1279 | continue; | |
1280 | ||
1281 | err = cec_config_log_addr(adap, i, la_list[j]); | |
1282 | if (err == 0) /* LA is in use */ | |
1283 | continue; | |
1284 | if (err < 0) | |
1285 | goto unconfigure; | |
1286 | /* Done, claimed an LA */ | |
1287 | break; | |
1288 | } | |
1289 | ||
1290 | if (la_list[j] == CEC_LOG_ADDR_INVALID) | |
1291 | dprintk(1, "could not claim LA %d\n", i); | |
1292 | } | |
1293 | ||
dcceb1ea HV |
1294 | if (adap->log_addrs.log_addr_mask == 0 && |
1295 | !(las->flags & CEC_LOG_ADDRS_FL_ALLOW_UNREG_FALLBACK)) | |
1296 | goto unconfigure; | |
1297 | ||
9881fe0c HV |
1298 | configured: |
1299 | if (adap->log_addrs.log_addr_mask == 0) { | |
1300 | /* Fall back to unregistered */ | |
1301 | las->log_addr[0] = CEC_LOG_ADDR_UNREGISTERED; | |
1302 | las->log_addr_mask = 1 << las->log_addr[0]; | |
0c1d61b0 HV |
1303 | for (i = 1; i < las->num_log_addrs; i++) |
1304 | las->log_addr[i] = CEC_LOG_ADDR_INVALID; | |
9881fe0c | 1305 | } |
7af26f88 HV |
1306 | for (i = las->num_log_addrs; i < CEC_MAX_LOG_ADDRS; i++) |
1307 | las->log_addr[i] = CEC_LOG_ADDR_INVALID; | |
9881fe0c HV |
1308 | adap->is_configured = true; |
1309 | adap->is_configuring = false; | |
1310 | cec_post_state_event(adap); | |
9881fe0c | 1311 | |
f60f3560 HV |
1312 | /* |
1313 | * Now post the Report Features and Report Physical Address broadcast | |
1314 | * messages. Note that these are non-blocking transmits, meaning that | |
1315 | * they are just queued up and once adap->lock is unlocked the main | |
1316 | * thread will kick in and start transmitting these. | |
1317 | * | |
1318 | * If after this function is done (but before one or more of these | |
1319 | * messages are actually transmitted) the CEC adapter is unconfigured, | |
1320 | * then any remaining messages will be dropped by the main thread. | |
1321 | */ | |
9881fe0c | 1322 | for (i = 0; i < las->num_log_addrs; i++) { |
52bc30fd HV |
1323 | struct cec_msg msg = {}; |
1324 | ||
a69a168a HV |
1325 | if (las->log_addr[i] == CEC_LOG_ADDR_INVALID || |
1326 | (las->flags & CEC_LOG_ADDRS_FL_CDC_ONLY)) | |
9881fe0c HV |
1327 | continue; |
1328 | ||
52bc30fd HV |
1329 | msg.msg[0] = (las->log_addr[i] << 4) | 0x0f; |
1330 | ||
1331 | /* Report Features must come first according to CEC 2.0 */ | |
1332 | if (las->log_addr[i] != CEC_LOG_ADDR_UNREGISTERED && | |
1333 | adap->log_addrs.cec_version >= CEC_OP_CEC_VERSION_2_0) { | |
1334 | cec_fill_msg_report_features(adap, &msg, i); | |
f60f3560 | 1335 | cec_transmit_msg_fh(adap, &msg, NULL, false); |
52bc30fd HV |
1336 | } |
1337 | ||
d3d64bc7 HV |
1338 | /* Report Physical Address */ |
1339 | cec_msg_report_physical_addr(&msg, adap->phys_addr, | |
1340 | las->primary_device_type[i]); | |
a7a04b5b | 1341 | dprintk(1, "config: la %d pa %x.%x.%x.%x\n", |
d3d64bc7 HV |
1342 | las->log_addr[i], |
1343 | cec_phys_addr_exp(adap->phys_addr)); | |
f60f3560 | 1344 | cec_transmit_msg_fh(adap, &msg, NULL, false); |
9881fe0c | 1345 | } |
9881fe0c | 1346 | adap->kthread_config = NULL; |
9881fe0c | 1347 | complete(&adap->config_completion); |
f60f3560 | 1348 | mutex_unlock(&adap->lock); |
9881fe0c HV |
1349 | return 0; |
1350 | ||
1351 | unconfigure: | |
1352 | for (i = 0; i < las->num_log_addrs; i++) | |
1353 | las->log_addr[i] = CEC_LOG_ADDR_INVALID; | |
1354 | cec_adap_unconfigure(adap); | |
1355 | adap->kthread_config = NULL; | |
1356 | mutex_unlock(&adap->lock); | |
1357 | complete(&adap->config_completion); | |
1358 | return 0; | |
1359 | } | |
1360 | ||
1361 | /* | |
1362 | * Called from either __cec_s_phys_addr or __cec_s_log_addrs to claim the | |
1363 | * logical addresses. | |
1364 | * | |
1365 | * This function is called with adap->lock held. | |
1366 | */ | |
1367 | static void cec_claim_log_addrs(struct cec_adapter *adap, bool block) | |
1368 | { | |
1369 | if (WARN_ON(adap->is_configuring || adap->is_configured)) | |
1370 | return; | |
1371 | ||
1372 | init_completion(&adap->config_completion); | |
1373 | ||
1374 | /* Ready to kick off the thread */ | |
1375 | adap->is_configuring = true; | |
1376 | adap->kthread_config = kthread_run(cec_config_thread_func, adap, | |
1377 | "ceccfg-%s", adap->name); | |
1378 | if (IS_ERR(adap->kthread_config)) { | |
1379 | adap->kthread_config = NULL; | |
1380 | } else if (block) { | |
1381 | mutex_unlock(&adap->lock); | |
1382 | wait_for_completion(&adap->config_completion); | |
1383 | mutex_lock(&adap->lock); | |
1384 | } | |
1385 | } | |
1386 | ||
1387 | /* Set a new physical address and send an event notifying userspace of this. | |
1388 | * | |
1389 | * This function is called with adap->lock held. | |
1390 | */ | |
1391 | void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block) | |
1392 | { | |
c000e5da | 1393 | if (phys_addr == adap->phys_addr || adap->devnode.unregistered) |
9881fe0c HV |
1394 | return; |
1395 | ||
f902c1e9 HV |
1396 | dprintk(1, "new physical address %x.%x.%x.%x\n", |
1397 | cec_phys_addr_exp(phys_addr)); | |
9881fe0c HV |
1398 | if (phys_addr == CEC_PHYS_ADDR_INVALID || |
1399 | adap->phys_addr != CEC_PHYS_ADDR_INVALID) { | |
1400 | adap->phys_addr = CEC_PHYS_ADDR_INVALID; | |
1401 | cec_post_state_event(adap); | |
1402 | cec_adap_unconfigure(adap); | |
1403 | /* Disabling monitor all mode should always succeed */ | |
1404 | if (adap->monitor_all_cnt) | |
1405 | WARN_ON(call_op(adap, adap_monitor_all_enable, false)); | |
533a3f7b | 1406 | mutex_lock(&adap->devnode.lock); |
f902c1e9 | 1407 | if (adap->needs_hpd || list_empty(&adap->devnode.fhs)) |
533a3f7b HV |
1408 | WARN_ON(adap->ops->adap_enable(adap, false)); |
1409 | mutex_unlock(&adap->devnode.lock); | |
9881fe0c HV |
1410 | if (phys_addr == CEC_PHYS_ADDR_INVALID) |
1411 | return; | |
1412 | } | |
1413 | ||
533a3f7b | 1414 | mutex_lock(&adap->devnode.lock); |
f902c1e9 | 1415 | if ((adap->needs_hpd || list_empty(&adap->devnode.fhs)) && |
533a3f7b HV |
1416 | adap->ops->adap_enable(adap, true)) { |
1417 | mutex_unlock(&adap->devnode.lock); | |
9881fe0c | 1418 | return; |
533a3f7b | 1419 | } |
9881fe0c HV |
1420 | |
1421 | if (adap->monitor_all_cnt && | |
1422 | call_op(adap, adap_monitor_all_enable, true)) { | |
f902c1e9 | 1423 | if (adap->needs_hpd || list_empty(&adap->devnode.fhs)) |
533a3f7b HV |
1424 | WARN_ON(adap->ops->adap_enable(adap, false)); |
1425 | mutex_unlock(&adap->devnode.lock); | |
9881fe0c HV |
1426 | return; |
1427 | } | |
533a3f7b HV |
1428 | mutex_unlock(&adap->devnode.lock); |
1429 | ||
9881fe0c HV |
1430 | adap->phys_addr = phys_addr; |
1431 | cec_post_state_event(adap); | |
1432 | if (adap->log_addrs.num_log_addrs) | |
1433 | cec_claim_log_addrs(adap, block); | |
1434 | } | |
1435 | ||
1436 | void cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block) | |
1437 | { | |
1438 | if (IS_ERR_OR_NULL(adap)) | |
1439 | return; | |
1440 | ||
9881fe0c HV |
1441 | mutex_lock(&adap->lock); |
1442 | __cec_s_phys_addr(adap, phys_addr, block); | |
1443 | mutex_unlock(&adap->lock); | |
1444 | } | |
1445 | EXPORT_SYMBOL_GPL(cec_s_phys_addr); | |
1446 | ||
23111ec3 HV |
1447 | void cec_s_phys_addr_from_edid(struct cec_adapter *adap, |
1448 | const struct edid *edid) | |
1449 | { | |
1450 | u16 pa = CEC_PHYS_ADDR_INVALID; | |
1451 | ||
1452 | if (edid && edid->extensions) | |
1453 | pa = cec_get_edid_phys_addr((const u8 *)edid, | |
1454 | EDID_LENGTH * (edid->extensions + 1), NULL); | |
1455 | cec_s_phys_addr(adap, pa, false); | |
1456 | } | |
1457 | EXPORT_SYMBOL_GPL(cec_s_phys_addr_from_edid); | |
1458 | ||
9881fe0c HV |
1459 | /* |
1460 | * Called from either the ioctl or a driver to set the logical addresses. | |
1461 | * | |
1462 | * This function is called with adap->lock held. | |
1463 | */ | |
1464 | int __cec_s_log_addrs(struct cec_adapter *adap, | |
1465 | struct cec_log_addrs *log_addrs, bool block) | |
1466 | { | |
1467 | u16 type_mask = 0; | |
1468 | int i; | |
1469 | ||
c000e5da HV |
1470 | if (adap->devnode.unregistered) |
1471 | return -ENODEV; | |
1472 | ||
9881fe0c HV |
1473 | if (!log_addrs || log_addrs->num_log_addrs == 0) { |
1474 | adap->log_addrs.num_log_addrs = 0; | |
1475 | cec_adap_unconfigure(adap); | |
1476 | return 0; | |
1477 | } | |
1478 | ||
a69a168a HV |
1479 | if (log_addrs->flags & CEC_LOG_ADDRS_FL_CDC_ONLY) { |
1480 | /* | |
1481 | * Sanitize log_addrs fields if a CDC-Only device is | |
1482 | * requested. | |
1483 | */ | |
1484 | log_addrs->num_log_addrs = 1; | |
1485 | log_addrs->osd_name[0] = '\0'; | |
1486 | log_addrs->vendor_id = CEC_VENDOR_ID_NONE; | |
1487 | log_addrs->log_addr_type[0] = CEC_LOG_ADDR_TYPE_UNREGISTERED; | |
1488 | /* | |
1489 | * This is just an internal convention since a CDC-Only device | |
1490 | * doesn't have to be a switch. But switches already use | |
1491 | * unregistered, so it makes some kind of sense to pick this | |
1492 | * as the primary device. Since a CDC-Only device never sends | |
1493 | * any 'normal' CEC messages this primary device type is never | |
1494 | * sent over the CEC bus. | |
1495 | */ | |
1496 | log_addrs->primary_device_type[0] = CEC_OP_PRIM_DEVTYPE_SWITCH; | |
1497 | log_addrs->all_device_types[0] = 0; | |
1498 | log_addrs->features[0][0] = 0; | |
1499 | log_addrs->features[0][1] = 0; | |
1500 | } | |
1501 | ||
9881fe0c HV |
1502 | /* Ensure the osd name is 0-terminated */ |
1503 | log_addrs->osd_name[sizeof(log_addrs->osd_name) - 1] = '\0'; | |
1504 | ||
1505 | /* Sanity checks */ | |
1506 | if (log_addrs->num_log_addrs > adap->available_log_addrs) { | |
1507 | dprintk(1, "num_log_addrs > %d\n", adap->available_log_addrs); | |
1508 | return -EINVAL; | |
1509 | } | |
1510 | ||
1511 | /* | |
1512 | * Vendor ID is a 24 bit number, so check if the value is | |
1513 | * within the correct range. | |
1514 | */ | |
1515 | if (log_addrs->vendor_id != CEC_VENDOR_ID_NONE && | |
79cabaa3 HV |
1516 | (log_addrs->vendor_id & 0xff000000) != 0) { |
1517 | dprintk(1, "invalid vendor ID\n"); | |
9881fe0c | 1518 | return -EINVAL; |
79cabaa3 | 1519 | } |
9881fe0c HV |
1520 | |
1521 | if (log_addrs->cec_version != CEC_OP_CEC_VERSION_1_4 && | |
79cabaa3 HV |
1522 | log_addrs->cec_version != CEC_OP_CEC_VERSION_2_0) { |
1523 | dprintk(1, "invalid CEC version\n"); | |
9881fe0c | 1524 | return -EINVAL; |
79cabaa3 | 1525 | } |
9881fe0c HV |
1526 | |
1527 | if (log_addrs->num_log_addrs > 1) | |
1528 | for (i = 0; i < log_addrs->num_log_addrs; i++) | |
1529 | if (log_addrs->log_addr_type[i] == | |
1530 | CEC_LOG_ADDR_TYPE_UNREGISTERED) { | |
1531 | dprintk(1, "num_log_addrs > 1 can't be combined with unregistered LA\n"); | |
1532 | return -EINVAL; | |
1533 | } | |
1534 | ||
9881fe0c | 1535 | for (i = 0; i < log_addrs->num_log_addrs; i++) { |
009a6208 | 1536 | const u8 feature_sz = ARRAY_SIZE(log_addrs->features[0]); |
9881fe0c HV |
1537 | u8 *features = log_addrs->features[i]; |
1538 | bool op_is_dev_features = false; | |
a161bef0 | 1539 | unsigned j; |
9881fe0c HV |
1540 | |
1541 | log_addrs->log_addr[i] = CEC_LOG_ADDR_INVALID; | |
1542 | if (type_mask & (1 << log_addrs->log_addr_type[i])) { | |
1543 | dprintk(1, "duplicate logical address type\n"); | |
1544 | return -EINVAL; | |
1545 | } | |
1546 | type_mask |= 1 << log_addrs->log_addr_type[i]; | |
1547 | if ((type_mask & (1 << CEC_LOG_ADDR_TYPE_RECORD)) && | |
1548 | (type_mask & (1 << CEC_LOG_ADDR_TYPE_PLAYBACK))) { | |
1549 | /* Record already contains the playback functionality */ | |
1550 | dprintk(1, "invalid record + playback combination\n"); | |
1551 | return -EINVAL; | |
1552 | } | |
1553 | if (log_addrs->primary_device_type[i] > | |
1554 | CEC_OP_PRIM_DEVTYPE_PROCESSOR) { | |
1555 | dprintk(1, "unknown primary device type\n"); | |
1556 | return -EINVAL; | |
1557 | } | |
1558 | if (log_addrs->primary_device_type[i] == 2) { | |
1559 | dprintk(1, "invalid primary device type\n"); | |
1560 | return -EINVAL; | |
1561 | } | |
1562 | if (log_addrs->log_addr_type[i] > CEC_LOG_ADDR_TYPE_UNREGISTERED) { | |
1563 | dprintk(1, "unknown logical address type\n"); | |
1564 | return -EINVAL; | |
1565 | } | |
a161bef0 HV |
1566 | for (j = 0; j < feature_sz; j++) { |
1567 | if ((features[j] & 0x80) == 0) { | |
9881fe0c HV |
1568 | if (op_is_dev_features) |
1569 | break; | |
1570 | op_is_dev_features = true; | |
1571 | } | |
1572 | } | |
a161bef0 | 1573 | if (!op_is_dev_features || j == feature_sz) { |
9881fe0c HV |
1574 | dprintk(1, "malformed features\n"); |
1575 | return -EINVAL; | |
1576 | } | |
009a6208 | 1577 | /* Zero unused part of the feature array */ |
a161bef0 | 1578 | memset(features + j + 1, 0, feature_sz - j - 1); |
9881fe0c HV |
1579 | } |
1580 | ||
1581 | if (log_addrs->cec_version >= CEC_OP_CEC_VERSION_2_0) { | |
1582 | if (log_addrs->num_log_addrs > 2) { | |
1583 | dprintk(1, "CEC 2.0 allows no more than 2 logical addresses\n"); | |
1584 | return -EINVAL; | |
1585 | } | |
1586 | if (log_addrs->num_log_addrs == 2) { | |
1587 | if (!(type_mask & ((1 << CEC_LOG_ADDR_TYPE_AUDIOSYSTEM) | | |
1588 | (1 << CEC_LOG_ADDR_TYPE_TV)))) { | |
a7a04b5b | 1589 | dprintk(1, "two LAs is only allowed for audiosystem and TV\n"); |
9881fe0c HV |
1590 | return -EINVAL; |
1591 | } | |
1592 | if (!(type_mask & ((1 << CEC_LOG_ADDR_TYPE_PLAYBACK) | | |
1593 | (1 << CEC_LOG_ADDR_TYPE_RECORD)))) { | |
a7a04b5b | 1594 | dprintk(1, "an audiosystem/TV can only be combined with record or playback\n"); |
9881fe0c HV |
1595 | return -EINVAL; |
1596 | } | |
1597 | } | |
1598 | } | |
1599 | ||
009a6208 HV |
1600 | /* Zero unused LAs */ |
1601 | for (i = log_addrs->num_log_addrs; i < CEC_MAX_LOG_ADDRS; i++) { | |
1602 | log_addrs->primary_device_type[i] = 0; | |
1603 | log_addrs->log_addr_type[i] = 0; | |
1604 | log_addrs->all_device_types[i] = 0; | |
1605 | memset(log_addrs->features[i], 0, | |
1606 | sizeof(log_addrs->features[i])); | |
1607 | } | |
1608 | ||
9881fe0c HV |
1609 | log_addrs->log_addr_mask = adap->log_addrs.log_addr_mask; |
1610 | adap->log_addrs = *log_addrs; | |
1611 | if (adap->phys_addr != CEC_PHYS_ADDR_INVALID) | |
1612 | cec_claim_log_addrs(adap, block); | |
1613 | return 0; | |
1614 | } | |
1615 | ||
1616 | int cec_s_log_addrs(struct cec_adapter *adap, | |
1617 | struct cec_log_addrs *log_addrs, bool block) | |
1618 | { | |
1619 | int err; | |
1620 | ||
9881fe0c HV |
1621 | mutex_lock(&adap->lock); |
1622 | err = __cec_s_log_addrs(adap, log_addrs, block); | |
1623 | mutex_unlock(&adap->lock); | |
1624 | return err; | |
1625 | } | |
1626 | EXPORT_SYMBOL_GPL(cec_s_log_addrs); | |
1627 | ||
1628 | /* High-level core CEC message handling */ | |
1629 | ||
52bc30fd HV |
1630 | /* Fill in the Report Features message */ |
1631 | static void cec_fill_msg_report_features(struct cec_adapter *adap, | |
1632 | struct cec_msg *msg, | |
1633 | unsigned int la_idx) | |
9881fe0c | 1634 | { |
9881fe0c HV |
1635 | const struct cec_log_addrs *las = &adap->log_addrs; |
1636 | const u8 *features = las->features[la_idx]; | |
1637 | bool op_is_dev_features = false; | |
1638 | unsigned int idx; | |
1639 | ||
9881fe0c | 1640 | /* Report Features */ |
52bc30fd HV |
1641 | msg->msg[0] = (las->log_addr[la_idx] << 4) | 0x0f; |
1642 | msg->len = 4; | |
1643 | msg->msg[1] = CEC_MSG_REPORT_FEATURES; | |
1644 | msg->msg[2] = adap->log_addrs.cec_version; | |
1645 | msg->msg[3] = las->all_device_types[la_idx]; | |
9881fe0c HV |
1646 | |
1647 | /* Write RC Profiles first, then Device Features */ | |
1648 | for (idx = 0; idx < ARRAY_SIZE(las->features[0]); idx++) { | |
52bc30fd | 1649 | msg->msg[msg->len++] = features[idx]; |
9881fe0c HV |
1650 | if ((features[idx] & CEC_OP_FEAT_EXT) == 0) { |
1651 | if (op_is_dev_features) | |
1652 | break; | |
1653 | op_is_dev_features = true; | |
1654 | } | |
1655 | } | |
9881fe0c HV |
1656 | } |
1657 | ||
9881fe0c HV |
1658 | /* Transmit the Feature Abort message */ |
1659 | static int cec_feature_abort_reason(struct cec_adapter *adap, | |
1660 | struct cec_msg *msg, u8 reason) | |
1661 | { | |
1662 | struct cec_msg tx_msg = { }; | |
1663 | ||
1664 | /* | |
1665 | * Don't reply with CEC_MSG_FEATURE_ABORT to a CEC_MSG_FEATURE_ABORT | |
1666 | * message! | |
1667 | */ | |
1668 | if (msg->msg[1] == CEC_MSG_FEATURE_ABORT) | |
1669 | return 0; | |
a8e97e53 HV |
1670 | /* Don't Feature Abort messages from 'Unregistered' */ |
1671 | if (cec_msg_initiator(msg) == CEC_LOG_ADDR_UNREGISTERED) | |
1672 | return 0; | |
9881fe0c HV |
1673 | cec_msg_set_reply_to(&tx_msg, msg); |
1674 | cec_msg_feature_abort(&tx_msg, msg->msg[1], reason); | |
1675 | return cec_transmit_msg(adap, &tx_msg, false); | |
1676 | } | |
1677 | ||
1678 | static int cec_feature_abort(struct cec_adapter *adap, struct cec_msg *msg) | |
1679 | { | |
1680 | return cec_feature_abort_reason(adap, msg, | |
1681 | CEC_OP_ABORT_UNRECOGNIZED_OP); | |
1682 | } | |
1683 | ||
1684 | static int cec_feature_refused(struct cec_adapter *adap, struct cec_msg *msg) | |
1685 | { | |
1686 | return cec_feature_abort_reason(adap, msg, | |
1687 | CEC_OP_ABORT_REFUSED); | |
1688 | } | |
1689 | ||
1690 | /* | |
1691 | * Called when a CEC message is received. This function will do any | |
1692 | * necessary core processing. The is_reply bool is true if this message | |
1693 | * is a reply to an earlier transmit. | |
1694 | * | |
1695 | * The message is either a broadcast message or a valid directed message. | |
1696 | */ | |
1697 | static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg, | |
1698 | bool is_reply) | |
1699 | { | |
1700 | bool is_broadcast = cec_msg_is_broadcast(msg); | |
1701 | u8 dest_laddr = cec_msg_destination(msg); | |
1702 | u8 init_laddr = cec_msg_initiator(msg); | |
1703 | u8 devtype = cec_log_addr2dev(adap, dest_laddr); | |
1704 | int la_idx = cec_log_addr2idx(adap, dest_laddr); | |
9881fe0c HV |
1705 | bool from_unregistered = init_laddr == 0xf; |
1706 | struct cec_msg tx_cec_msg = { }; | |
1707 | ||
a7a04b5b | 1708 | dprintk(2, "%s: %*ph\n", __func__, msg->len, msg->msg); |
9881fe0c | 1709 | |
a69a168a HV |
1710 | /* If this is a CDC-Only device, then ignore any non-CDC messages */ |
1711 | if (cec_is_cdc_only(&adap->log_addrs) && | |
1712 | msg->msg[1] != CEC_MSG_CDC_MESSAGE) | |
1713 | return 0; | |
1714 | ||
9881fe0c HV |
1715 | if (adap->ops->received) { |
1716 | /* Allow drivers to process the message first */ | |
1717 | if (adap->ops->received(adap, msg) != -ENOMSG) | |
1718 | return 0; | |
1719 | } | |
1720 | ||
1721 | /* | |
1722 | * REPORT_PHYSICAL_ADDR, CEC_MSG_USER_CONTROL_PRESSED and | |
1723 | * CEC_MSG_USER_CONTROL_RELEASED messages always have to be | |
1724 | * handled by the CEC core, even if the passthrough mode is on. | |
1725 | * The others are just ignored if passthrough mode is on. | |
1726 | */ | |
1727 | switch (msg->msg[1]) { | |
1728 | case CEC_MSG_GET_CEC_VERSION: | |
1729 | case CEC_MSG_GIVE_DEVICE_VENDOR_ID: | |
1730 | case CEC_MSG_ABORT: | |
1731 | case CEC_MSG_GIVE_DEVICE_POWER_STATUS: | |
1732 | case CEC_MSG_GIVE_PHYSICAL_ADDR: | |
1733 | case CEC_MSG_GIVE_OSD_NAME: | |
1734 | case CEC_MSG_GIVE_FEATURES: | |
1735 | /* | |
1736 | * Skip processing these messages if the passthrough mode | |
1737 | * is on. | |
1738 | */ | |
1739 | if (adap->passthrough) | |
1740 | goto skip_processing; | |
1741 | /* Ignore if addressing is wrong */ | |
1742 | if (is_broadcast || from_unregistered) | |
1743 | return 0; | |
1744 | break; | |
1745 | ||
1746 | case CEC_MSG_USER_CONTROL_PRESSED: | |
1747 | case CEC_MSG_USER_CONTROL_RELEASED: | |
1748 | /* Wrong addressing mode: don't process */ | |
1749 | if (is_broadcast || from_unregistered) | |
1750 | goto skip_processing; | |
1751 | break; | |
1752 | ||
1753 | case CEC_MSG_REPORT_PHYSICAL_ADDR: | |
1754 | /* | |
1755 | * This message is always processed, regardless of the | |
1756 | * passthrough setting. | |
1757 | * | |
1758 | * Exception: don't process if wrong addressing mode. | |
1759 | */ | |
1760 | if (!is_broadcast) | |
1761 | goto skip_processing; | |
1762 | break; | |
1763 | ||
1764 | default: | |
1765 | break; | |
1766 | } | |
1767 | ||
1768 | cec_msg_set_reply_to(&tx_cec_msg, msg); | |
1769 | ||
1770 | switch (msg->msg[1]) { | |
1771 | /* The following messages are processed but still passed through */ | |
f8db65fe HV |
1772 | case CEC_MSG_REPORT_PHYSICAL_ADDR: { |
1773 | u16 pa = (msg->msg[2] << 8) | msg->msg[3]; | |
1774 | ||
1775 | if (!from_unregistered) | |
1776 | adap->phys_addrs[init_laddr] = pa; | |
a7a04b5b | 1777 | dprintk(1, "reported physical address %x.%x.%x.%x for logical address %d\n", |
f8db65fe | 1778 | cec_phys_addr_exp(pa), init_laddr); |
9881fe0c | 1779 | break; |
f8db65fe | 1780 | } |
9881fe0c HV |
1781 | |
1782 | case CEC_MSG_USER_CONTROL_PRESSED: | |
f4062625 HV |
1783 | if (!(adap->capabilities & CEC_CAP_RC) || |
1784 | !(adap->log_addrs.flags & CEC_LOG_ADDRS_FL_ALLOW_RC_PASSTHRU)) | |
9881fe0c HV |
1785 | break; |
1786 | ||
5f2c467c | 1787 | #ifdef CONFIG_MEDIA_CEC_RC |
9881fe0c HV |
1788 | switch (msg->msg[2]) { |
1789 | /* | |
1790 | * Play function, this message can have variable length | |
1791 | * depending on the specific play function that is used. | |
1792 | */ | |
1793 | case 0x60: | |
1794 | if (msg->len == 2) | |
1795 | rc_keydown(adap->rc, RC_TYPE_CEC, | |
1796 | msg->msg[2], 0); | |
1797 | else | |
1798 | rc_keydown(adap->rc, RC_TYPE_CEC, | |
1799 | msg->msg[2] << 8 | msg->msg[3], 0); | |
1800 | break; | |
1801 | /* | |
1802 | * Other function messages that are not handled. | |
1803 | * Currently the RC framework does not allow to supply an | |
1804 | * additional parameter to a keypress. These "keys" contain | |
1805 | * other information such as channel number, an input number | |
1806 | * etc. | |
1807 | * For the time being these messages are not processed by the | |
1808 | * framework and are simply forwarded to the user space. | |
1809 | */ | |
1810 | case 0x56: case 0x57: | |
1811 | case 0x67: case 0x68: case 0x69: case 0x6a: | |
1812 | break; | |
1813 | default: | |
1814 | rc_keydown(adap->rc, RC_TYPE_CEC, msg->msg[2], 0); | |
1815 | break; | |
1816 | } | |
1817 | #endif | |
1818 | break; | |
1819 | ||
1820 | case CEC_MSG_USER_CONTROL_RELEASED: | |
f4062625 HV |
1821 | if (!(adap->capabilities & CEC_CAP_RC) || |
1822 | !(adap->log_addrs.flags & CEC_LOG_ADDRS_FL_ALLOW_RC_PASSTHRU)) | |
9881fe0c | 1823 | break; |
5f2c467c | 1824 | #ifdef CONFIG_MEDIA_CEC_RC |
9881fe0c HV |
1825 | rc_keyup(adap->rc); |
1826 | #endif | |
1827 | break; | |
1828 | ||
1829 | /* | |
1830 | * The remaining messages are only processed if the passthrough mode | |
1831 | * is off. | |
1832 | */ | |
1833 | case CEC_MSG_GET_CEC_VERSION: | |
1834 | cec_msg_cec_version(&tx_cec_msg, adap->log_addrs.cec_version); | |
1835 | return cec_transmit_msg(adap, &tx_cec_msg, false); | |
1836 | ||
1837 | case CEC_MSG_GIVE_PHYSICAL_ADDR: | |
1838 | /* Do nothing for CEC switches using addr 15 */ | |
1839 | if (devtype == CEC_OP_PRIM_DEVTYPE_SWITCH && dest_laddr == 15) | |
1840 | return 0; | |
1841 | cec_msg_report_physical_addr(&tx_cec_msg, adap->phys_addr, devtype); | |
1842 | return cec_transmit_msg(adap, &tx_cec_msg, false); | |
1843 | ||
1844 | case CEC_MSG_GIVE_DEVICE_VENDOR_ID: | |
1845 | if (adap->log_addrs.vendor_id == CEC_VENDOR_ID_NONE) | |
1846 | return cec_feature_abort(adap, msg); | |
1847 | cec_msg_device_vendor_id(&tx_cec_msg, adap->log_addrs.vendor_id); | |
1848 | return cec_transmit_msg(adap, &tx_cec_msg, false); | |
1849 | ||
1850 | case CEC_MSG_ABORT: | |
1851 | /* Do nothing for CEC switches */ | |
1852 | if (devtype == CEC_OP_PRIM_DEVTYPE_SWITCH) | |
1853 | return 0; | |
1854 | return cec_feature_refused(adap, msg); | |
1855 | ||
1856 | case CEC_MSG_GIVE_OSD_NAME: { | |
1857 | if (adap->log_addrs.osd_name[0] == 0) | |
1858 | return cec_feature_abort(adap, msg); | |
1859 | cec_msg_set_osd_name(&tx_cec_msg, adap->log_addrs.osd_name); | |
1860 | return cec_transmit_msg(adap, &tx_cec_msg, false); | |
1861 | } | |
1862 | ||
1863 | case CEC_MSG_GIVE_FEATURES: | |
a24f56d4 HV |
1864 | if (adap->log_addrs.cec_version < CEC_OP_CEC_VERSION_2_0) |
1865 | return cec_feature_abort(adap, msg); | |
52bc30fd HV |
1866 | cec_fill_msg_report_features(adap, &tx_cec_msg, la_idx); |
1867 | return cec_transmit_msg(adap, &tx_cec_msg, false); | |
9881fe0c HV |
1868 | |
1869 | default: | |
1870 | /* | |
1871 | * Unprocessed messages are aborted if userspace isn't doing | |
1872 | * any processing either. | |
1873 | */ | |
a179b693 | 1874 | if (!is_broadcast && !is_reply && !adap->follower_cnt && |
9881fe0c HV |
1875 | !adap->cec_follower && msg->msg[1] != CEC_MSG_FEATURE_ABORT) |
1876 | return cec_feature_abort(adap, msg); | |
1877 | break; | |
1878 | } | |
1879 | ||
1880 | skip_processing: | |
adc0c622 HV |
1881 | /* If this was a reply, then we're done, unless otherwise specified */ |
1882 | if (is_reply && !(msg->flags & CEC_MSG_FL_REPLY_TO_FOLLOWERS)) | |
9881fe0c HV |
1883 | return 0; |
1884 | ||
1885 | /* | |
1886 | * Send to the exclusive follower if there is one, otherwise send | |
1887 | * to all followers. | |
1888 | */ | |
1889 | if (adap->cec_follower) | |
1890 | cec_queue_msg_fh(adap->cec_follower, msg); | |
1891 | else | |
1892 | cec_queue_msg_followers(adap, msg); | |
1893 | return 0; | |
1894 | } | |
1895 | ||
1896 | /* | |
1897 | * Helper functions to keep track of the 'monitor all' use count. | |
1898 | * | |
1899 | * These functions are called with adap->lock held. | |
1900 | */ | |
1901 | int cec_monitor_all_cnt_inc(struct cec_adapter *adap) | |
1902 | { | |
1903 | int ret = 0; | |
1904 | ||
1905 | if (adap->monitor_all_cnt == 0) | |
1906 | ret = call_op(adap, adap_monitor_all_enable, 1); | |
1907 | if (ret == 0) | |
1908 | adap->monitor_all_cnt++; | |
1909 | return ret; | |
1910 | } | |
1911 | ||
1912 | void cec_monitor_all_cnt_dec(struct cec_adapter *adap) | |
1913 | { | |
1914 | adap->monitor_all_cnt--; | |
1915 | if (adap->monitor_all_cnt == 0) | |
1916 | WARN_ON(call_op(adap, adap_monitor_all_enable, 0)); | |
1917 | } | |
1918 | ||
20249f84 | 1919 | #ifdef CONFIG_DEBUG_FS |
9881fe0c HV |
1920 | /* |
1921 | * Log the current state of the CEC adapter. | |
1922 | * Very useful for debugging. | |
1923 | */ | |
1924 | int cec_adap_status(struct seq_file *file, void *priv) | |
1925 | { | |
1926 | struct cec_adapter *adap = dev_get_drvdata(file->private); | |
1927 | struct cec_data *data; | |
1928 | ||
1929 | mutex_lock(&adap->lock); | |
1930 | seq_printf(file, "configured: %d\n", adap->is_configured); | |
1931 | seq_printf(file, "configuring: %d\n", adap->is_configuring); | |
1932 | seq_printf(file, "phys_addr: %x.%x.%x.%x\n", | |
1933 | cec_phys_addr_exp(adap->phys_addr)); | |
1934 | seq_printf(file, "number of LAs: %d\n", adap->log_addrs.num_log_addrs); | |
1935 | seq_printf(file, "LA mask: 0x%04x\n", adap->log_addrs.log_addr_mask); | |
1936 | if (adap->cec_follower) | |
1937 | seq_printf(file, "has CEC follower%s\n", | |
1938 | adap->passthrough ? " (in passthrough mode)" : ""); | |
1939 | if (adap->cec_initiator) | |
1940 | seq_puts(file, "has CEC initiator\n"); | |
1941 | if (adap->monitor_all_cnt) | |
1942 | seq_printf(file, "file handles in Monitor All mode: %u\n", | |
1943 | adap->monitor_all_cnt); | |
1944 | data = adap->transmitting; | |
1945 | if (data) | |
11065f85 HV |
1946 | seq_printf(file, "transmitting message: %*ph (reply: %02x, timeout: %ums)\n", |
1947 | data->msg.len, data->msg.msg, data->msg.reply, | |
1948 | data->msg.timeout); | |
1949 | seq_printf(file, "pending transmits: %u\n", adap->transmit_queue_sz); | |
9881fe0c | 1950 | list_for_each_entry(data, &adap->transmit_queue, list) { |
11065f85 HV |
1951 | seq_printf(file, "queued tx message: %*ph (reply: %02x, timeout: %ums)\n", |
1952 | data->msg.len, data->msg.msg, data->msg.reply, | |
1953 | data->msg.timeout); | |
9881fe0c HV |
1954 | } |
1955 | list_for_each_entry(data, &adap->wait_queue, list) { | |
11065f85 HV |
1956 | seq_printf(file, "message waiting for reply: %*ph (reply: %02x, timeout: %ums)\n", |
1957 | data->msg.len, data->msg.msg, data->msg.reply, | |
1958 | data->msg.timeout); | |
9881fe0c HV |
1959 | } |
1960 | ||
1961 | call_void_op(adap, adap_status, file); | |
1962 | mutex_unlock(&adap->lock); | |
1963 | return 0; | |
1964 | } | |
1965 | #endif |