aboutsummaryrefslogtreecommitdiffstats
path: root/include/uapi
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2016-11-02 06:25:28 -0400
committerMauro Carvalho Chehab <mchehab@s-opensource.com>2016-11-16 12:40:20 -0500
commit0dbacebede1e4e44bf500f94d692fad05eb2c293 (patch)
tree633cbfbfed04251cbdb35fe158ad81ee8ed380ef /include/uapi
parenta69a168a1bd470cb8a8c5f2ff4b54463de615226 (diff)
[media] cec: move the CEC framework out of staging and to media
The last open issues have been addressed, so it is time to move this out of staging and into the mainline and to move the public cec headers to include/uapi/linux. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Diffstat (limited to 'include/uapi')
-rw-r--r--include/uapi/linux/Kbuild2
-rw-r--r--include/uapi/linux/cec-funcs.h1965
-rw-r--r--include/uapi/linux/cec.h1065
3 files changed, 3032 insertions, 0 deletions
diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild
index 6965d0909554..c49c448cff92 100644
--- a/include/uapi/linux/Kbuild
+++ b/include/uapi/linux/Kbuild
@@ -82,6 +82,8 @@ header-y += capi.h
82header-y += cciss_defs.h 82header-y += cciss_defs.h
83header-y += cciss_ioctl.h 83header-y += cciss_ioctl.h
84header-y += cdrom.h 84header-y += cdrom.h
85header-y += cec.h
86header-y += cec-funcs.h
85header-y += cgroupstats.h 87header-y += cgroupstats.h
86header-y += chio.h 88header-y += chio.h
87header-y += cm4000_cs.h 89header-y += cm4000_cs.h
diff --git a/include/uapi/linux/cec-funcs.h b/include/uapi/linux/cec-funcs.h
new file mode 100644
index 000000000000..1a1de2169f48
--- /dev/null
+++ b/include/uapi/linux/cec-funcs.h
@@ -0,0 +1,1965 @@
1/*
2 * cec - HDMI Consumer Electronics Control message functions
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 * Alternatively you can redistribute this file under the terms of the
11 * BSD license as stated below:
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in
20 * the documentation and/or other materials provided with the
21 * distribution.
22 * 3. The names of its contributors may not be used to endorse or promote
23 * products derived from this software without specific prior written
24 * permission.
25 *
26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
30 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
31 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
32 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33 * SOFTWARE.
34 */
35
36#ifndef _CEC_UAPI_FUNCS_H
37#define _CEC_UAPI_FUNCS_H
38
39#include <linux/cec.h>
40
41/* One Touch Play Feature */
42static inline void cec_msg_active_source(struct cec_msg *msg, __u16 phys_addr)
43{
44 msg->len = 4;
45 msg->msg[0] |= 0xf; /* broadcast */
46 msg->msg[1] = CEC_MSG_ACTIVE_SOURCE;
47 msg->msg[2] = phys_addr >> 8;
48 msg->msg[3] = phys_addr & 0xff;
49}
50
51static inline void cec_ops_active_source(const struct cec_msg *msg,
52 __u16 *phys_addr)
53{
54 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
55}
56
57static inline void cec_msg_image_view_on(struct cec_msg *msg)
58{
59 msg->len = 2;
60 msg->msg[1] = CEC_MSG_IMAGE_VIEW_ON;
61}
62
63static inline void cec_msg_text_view_on(struct cec_msg *msg)
64{
65 msg->len = 2;
66 msg->msg[1] = CEC_MSG_TEXT_VIEW_ON;
67}
68
69
70/* Routing Control Feature */
71static inline void cec_msg_inactive_source(struct cec_msg *msg,
72 __u16 phys_addr)
73{
74 msg->len = 4;
75 msg->msg[1] = CEC_MSG_INACTIVE_SOURCE;
76 msg->msg[2] = phys_addr >> 8;
77 msg->msg[3] = phys_addr & 0xff;
78}
79
80static inline void cec_ops_inactive_source(const struct cec_msg *msg,
81 __u16 *phys_addr)
82{
83 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
84}
85
86static inline void cec_msg_request_active_source(struct cec_msg *msg,
87 bool reply)
88{
89 msg->len = 2;
90 msg->msg[0] |= 0xf; /* broadcast */
91 msg->msg[1] = CEC_MSG_REQUEST_ACTIVE_SOURCE;
92 msg->reply = reply ? CEC_MSG_ACTIVE_SOURCE : 0;
93}
94
95static inline void cec_msg_routing_information(struct cec_msg *msg,
96 __u16 phys_addr)
97{
98 msg->len = 4;
99 msg->msg[0] |= 0xf; /* broadcast */
100 msg->msg[1] = CEC_MSG_ROUTING_INFORMATION;
101 msg->msg[2] = phys_addr >> 8;
102 msg->msg[3] = phys_addr & 0xff;
103}
104
105static inline void cec_ops_routing_information(const struct cec_msg *msg,
106 __u16 *phys_addr)
107{
108 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
109}
110
111static inline void cec_msg_routing_change(struct cec_msg *msg,
112 bool reply,
113 __u16 orig_phys_addr,
114 __u16 new_phys_addr)
115{
116 msg->len = 6;
117 msg->msg[0] |= 0xf; /* broadcast */
118 msg->msg[1] = CEC_MSG_ROUTING_CHANGE;
119 msg->msg[2] = orig_phys_addr >> 8;
120 msg->msg[3] = orig_phys_addr & 0xff;
121 msg->msg[4] = new_phys_addr >> 8;
122 msg->msg[5] = new_phys_addr & 0xff;
123 msg->reply = reply ? CEC_MSG_ROUTING_INFORMATION : 0;
124}
125
126static inline void cec_ops_routing_change(const struct cec_msg *msg,
127 __u16 *orig_phys_addr,
128 __u16 *new_phys_addr)
129{
130 *orig_phys_addr = (msg->msg[2] << 8) | msg->msg[3];
131 *new_phys_addr = (msg->msg[4] << 8) | msg->msg[5];
132}
133
134static inline void cec_msg_set_stream_path(struct cec_msg *msg, __u16 phys_addr)
135{
136 msg->len = 4;
137 msg->msg[0] |= 0xf; /* broadcast */
138 msg->msg[1] = CEC_MSG_SET_STREAM_PATH;
139 msg->msg[2] = phys_addr >> 8;
140 msg->msg[3] = phys_addr & 0xff;
141}
142
143static inline void cec_ops_set_stream_path(const struct cec_msg *msg,
144 __u16 *phys_addr)
145{
146 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
147}
148
149
150/* Standby Feature */
151static inline void cec_msg_standby(struct cec_msg *msg)
152{
153 msg->len = 2;
154 msg->msg[1] = CEC_MSG_STANDBY;
155}
156
157
158/* One Touch Record Feature */
159static inline void cec_msg_record_off(struct cec_msg *msg, bool reply)
160{
161 msg->len = 2;
162 msg->msg[1] = CEC_MSG_RECORD_OFF;
163 msg->reply = reply ? CEC_MSG_RECORD_STATUS : 0;
164}
165
166struct cec_op_arib_data {
167 __u16 transport_id;
168 __u16 service_id;
169 __u16 orig_network_id;
170};
171
172struct cec_op_atsc_data {
173 __u16 transport_id;
174 __u16 program_number;
175};
176
177struct cec_op_dvb_data {
178 __u16 transport_id;
179 __u16 service_id;
180 __u16 orig_network_id;
181};
182
183struct cec_op_channel_data {
184 __u8 channel_number_fmt;
185 __u16 major;
186 __u16 minor;
187};
188
189struct cec_op_digital_service_id {
190 __u8 service_id_method;
191 __u8 dig_bcast_system;
192 union {
193 struct cec_op_arib_data arib;
194 struct cec_op_atsc_data atsc;
195 struct cec_op_dvb_data dvb;
196 struct cec_op_channel_data channel;
197 };
198};
199
200struct cec_op_record_src {
201 __u8 type;
202 union {
203 struct cec_op_digital_service_id digital;
204 struct {
205 __u8 ana_bcast_type;
206 __u16 ana_freq;
207 __u8 bcast_system;
208 } analog;
209 struct {
210 __u8 plug;
211 } ext_plug;
212 struct {
213 __u16 phys_addr;
214 } ext_phys_addr;
215 };
216};
217
218static inline void cec_set_digital_service_id(__u8 *msg,
219 const struct cec_op_digital_service_id *digital)
220{
221 *msg++ = (digital->service_id_method << 7) | digital->dig_bcast_system;
222 if (digital->service_id_method == CEC_OP_SERVICE_ID_METHOD_BY_CHANNEL) {
223 *msg++ = (digital->channel.channel_number_fmt << 2) |
224 (digital->channel.major >> 8);
225 *msg++ = digital->channel.major & 0xff;
226 *msg++ = digital->channel.minor >> 8;
227 *msg++ = digital->channel.minor & 0xff;
228 *msg++ = 0;
229 *msg++ = 0;
230 return;
231 }
232 switch (digital->dig_bcast_system) {
233 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_GEN:
234 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_CABLE:
235 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_SAT:
236 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_T:
237 *msg++ = digital->atsc.transport_id >> 8;
238 *msg++ = digital->atsc.transport_id & 0xff;
239 *msg++ = digital->atsc.program_number >> 8;
240 *msg++ = digital->atsc.program_number & 0xff;
241 *msg++ = 0;
242 *msg++ = 0;
243 break;
244 default:
245 *msg++ = digital->dvb.transport_id >> 8;
246 *msg++ = digital->dvb.transport_id & 0xff;
247 *msg++ = digital->dvb.service_id >> 8;
248 *msg++ = digital->dvb.service_id & 0xff;
249 *msg++ = digital->dvb.orig_network_id >> 8;
250 *msg++ = digital->dvb.orig_network_id & 0xff;
251 break;
252 }
253}
254
255static inline void cec_get_digital_service_id(const __u8 *msg,
256 struct cec_op_digital_service_id *digital)
257{
258 digital->service_id_method = msg[0] >> 7;
259 digital->dig_bcast_system = msg[0] & 0x7f;
260 if (digital->service_id_method == CEC_OP_SERVICE_ID_METHOD_BY_CHANNEL) {
261 digital->channel.channel_number_fmt = msg[1] >> 2;
262 digital->channel.major = ((msg[1] & 3) << 6) | msg[2];
263 digital->channel.minor = (msg[3] << 8) | msg[4];
264 return;
265 }
266 digital->dvb.transport_id = (msg[1] << 8) | msg[2];
267 digital->dvb.service_id = (msg[3] << 8) | msg[4];
268 digital->dvb.orig_network_id = (msg[5] << 8) | msg[6];
269}
270
271static inline void cec_msg_record_on_own(struct cec_msg *msg)
272{
273 msg->len = 3;
274 msg->msg[1] = CEC_MSG_RECORD_ON;
275 msg->msg[2] = CEC_OP_RECORD_SRC_OWN;
276}
277
278static inline void cec_msg_record_on_digital(struct cec_msg *msg,
279 const struct cec_op_digital_service_id *digital)
280{
281 msg->len = 10;
282 msg->msg[1] = CEC_MSG_RECORD_ON;
283 msg->msg[2] = CEC_OP_RECORD_SRC_DIGITAL;
284 cec_set_digital_service_id(msg->msg + 3, digital);
285}
286
287static inline void cec_msg_record_on_analog(struct cec_msg *msg,
288 __u8 ana_bcast_type,
289 __u16 ana_freq,
290 __u8 bcast_system)
291{
292 msg->len = 7;
293 msg->msg[1] = CEC_MSG_RECORD_ON;
294 msg->msg[2] = CEC_OP_RECORD_SRC_ANALOG;
295 msg->msg[3] = ana_bcast_type;
296 msg->msg[4] = ana_freq >> 8;
297 msg->msg[5] = ana_freq & 0xff;
298 msg->msg[6] = bcast_system;
299}
300
301static inline void cec_msg_record_on_plug(struct cec_msg *msg,
302 __u8 plug)
303{
304 msg->len = 4;
305 msg->msg[1] = CEC_MSG_RECORD_ON;
306 msg->msg[2] = CEC_OP_RECORD_SRC_EXT_PLUG;
307 msg->msg[3] = plug;
308}
309
310static inline void cec_msg_record_on_phys_addr(struct cec_msg *msg,
311 __u16 phys_addr)
312{
313 msg->len = 5;
314 msg->msg[1] = CEC_MSG_RECORD_ON;
315 msg->msg[2] = CEC_OP_RECORD_SRC_EXT_PHYS_ADDR;
316 msg->msg[3] = phys_addr >> 8;
317 msg->msg[4] = phys_addr & 0xff;
318}
319
320static inline void cec_msg_record_on(struct cec_msg *msg,
321 bool reply,
322 const struct cec_op_record_src *rec_src)
323{
324 switch (rec_src->type) {
325 case CEC_OP_RECORD_SRC_OWN:
326 cec_msg_record_on_own(msg);
327 break;
328 case CEC_OP_RECORD_SRC_DIGITAL:
329 cec_msg_record_on_digital(msg, &rec_src->digital);
330 break;
331 case CEC_OP_RECORD_SRC_ANALOG:
332 cec_msg_record_on_analog(msg,
333 rec_src->analog.ana_bcast_type,
334 rec_src->analog.ana_freq,
335 rec_src->analog.bcast_system);
336 break;
337 case CEC_OP_RECORD_SRC_EXT_PLUG:
338 cec_msg_record_on_plug(msg, rec_src->ext_plug.plug);
339 break;
340 case CEC_OP_RECORD_SRC_EXT_PHYS_ADDR:
341 cec_msg_record_on_phys_addr(msg,
342 rec_src->ext_phys_addr.phys_addr);
343 break;
344 }
345 msg->reply = reply ? CEC_MSG_RECORD_STATUS : 0;
346}
347
348static inline void cec_ops_record_on(const struct cec_msg *msg,
349 struct cec_op_record_src *rec_src)
350{
351 rec_src->type = msg->msg[2];
352 switch (rec_src->type) {
353 case CEC_OP_RECORD_SRC_OWN:
354 break;
355 case CEC_OP_RECORD_SRC_DIGITAL:
356 cec_get_digital_service_id(msg->msg + 3, &rec_src->digital);
357 break;
358 case CEC_OP_RECORD_SRC_ANALOG:
359 rec_src->analog.ana_bcast_type = msg->msg[3];
360 rec_src->analog.ana_freq =
361 (msg->msg[4] << 8) | msg->msg[5];
362 rec_src->analog.bcast_system = msg->msg[6];
363 break;
364 case CEC_OP_RECORD_SRC_EXT_PLUG:
365 rec_src->ext_plug.plug = msg->msg[3];
366 break;
367 case CEC_OP_RECORD_SRC_EXT_PHYS_ADDR:
368 rec_src->ext_phys_addr.phys_addr =
369 (msg->msg[3] << 8) | msg->msg[4];
370 break;
371 }
372}
373
374static inline void cec_msg_record_status(struct cec_msg *msg, __u8 rec_status)
375{
376 msg->len = 3;
377 msg->msg[1] = CEC_MSG_RECORD_STATUS;
378 msg->msg[2] = rec_status;
379}
380
381static inline void cec_ops_record_status(const struct cec_msg *msg,
382 __u8 *rec_status)
383{
384 *rec_status = msg->msg[2];
385}
386
387static inline void cec_msg_record_tv_screen(struct cec_msg *msg,
388 bool reply)
389{
390 msg->len = 2;
391 msg->msg[1] = CEC_MSG_RECORD_TV_SCREEN;
392 msg->reply = reply ? CEC_MSG_RECORD_ON : 0;
393}
394
395
396/* Timer Programming Feature */
397static inline void cec_msg_timer_status(struct cec_msg *msg,
398 __u8 timer_overlap_warning,
399 __u8 media_info,
400 __u8 prog_info,
401 __u8 prog_error,
402 __u8 duration_hr,
403 __u8 duration_min)
404{
405 msg->len = 3;
406 msg->msg[1] = CEC_MSG_TIMER_STATUS;
407 msg->msg[2] = (timer_overlap_warning << 7) |
408 (media_info << 5) |
409 (prog_info ? 0x10 : 0) |
410 (prog_info ? prog_info : prog_error);
411 if (prog_info == CEC_OP_PROG_INFO_NOT_ENOUGH_SPACE ||
412 prog_info == CEC_OP_PROG_INFO_MIGHT_NOT_BE_ENOUGH_SPACE ||
413 prog_error == CEC_OP_PROG_ERROR_DUPLICATE) {
414 msg->len += 2;
415 msg->msg[3] = ((duration_hr / 10) << 4) | (duration_hr % 10);
416 msg->msg[4] = ((duration_min / 10) << 4) | (duration_min % 10);
417 }
418}
419
420static inline void cec_ops_timer_status(const struct cec_msg *msg,
421 __u8 *timer_overlap_warning,
422 __u8 *media_info,
423 __u8 *prog_info,
424 __u8 *prog_error,
425 __u8 *duration_hr,
426 __u8 *duration_min)
427{
428 *timer_overlap_warning = msg->msg[2] >> 7;
429 *media_info = (msg->msg[2] >> 5) & 3;
430 if (msg->msg[2] & 0x10) {
431 *prog_info = msg->msg[2] & 0xf;
432 *prog_error = 0;
433 } else {
434 *prog_info = 0;
435 *prog_error = msg->msg[2] & 0xf;
436 }
437 if (*prog_info == CEC_OP_PROG_INFO_NOT_ENOUGH_SPACE ||
438 *prog_info == CEC_OP_PROG_INFO_MIGHT_NOT_BE_ENOUGH_SPACE ||
439 *prog_error == CEC_OP_PROG_ERROR_DUPLICATE) {
440 *duration_hr = (msg->msg[3] >> 4) * 10 + (msg->msg[3] & 0xf);
441 *duration_min = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf);
442 } else {
443 *duration_hr = *duration_min = 0;
444 }
445}
446
447static inline void cec_msg_timer_cleared_status(struct cec_msg *msg,
448 __u8 timer_cleared_status)
449{
450 msg->len = 3;
451 msg->msg[1] = CEC_MSG_TIMER_CLEARED_STATUS;
452 msg->msg[2] = timer_cleared_status;
453}
454
455static inline void cec_ops_timer_cleared_status(const struct cec_msg *msg,
456 __u8 *timer_cleared_status)
457{
458 *timer_cleared_status = msg->msg[2];
459}
460
461static inline void cec_msg_clear_analogue_timer(struct cec_msg *msg,
462 bool reply,
463 __u8 day,
464 __u8 month,
465 __u8 start_hr,
466 __u8 start_min,
467 __u8 duration_hr,
468 __u8 duration_min,
469 __u8 recording_seq,
470 __u8 ana_bcast_type,
471 __u16 ana_freq,
472 __u8 bcast_system)
473{
474 msg->len = 13;
475 msg->msg[1] = CEC_MSG_CLEAR_ANALOGUE_TIMER;
476 msg->msg[2] = day;
477 msg->msg[3] = month;
478 /* Hours and minutes are in BCD format */
479 msg->msg[4] = ((start_hr / 10) << 4) | (start_hr % 10);
480 msg->msg[5] = ((start_min / 10) << 4) | (start_min % 10);
481 msg->msg[6] = ((duration_hr / 10) << 4) | (duration_hr % 10);
482 msg->msg[7] = ((duration_min / 10) << 4) | (duration_min % 10);
483 msg->msg[8] = recording_seq;
484 msg->msg[9] = ana_bcast_type;
485 msg->msg[10] = ana_freq >> 8;
486 msg->msg[11] = ana_freq & 0xff;
487 msg->msg[12] = bcast_system;
488 msg->reply = reply ? CEC_MSG_TIMER_CLEARED_STATUS : 0;
489}
490
491static inline void cec_ops_clear_analogue_timer(const struct cec_msg *msg,
492 __u8 *day,
493 __u8 *month,
494 __u8 *start_hr,
495 __u8 *start_min,
496 __u8 *duration_hr,
497 __u8 *duration_min,
498 __u8 *recording_seq,
499 __u8 *ana_bcast_type,
500 __u16 *ana_freq,
501 __u8 *bcast_system)
502{
503 *day = msg->msg[2];
504 *month = msg->msg[3];
505 /* Hours and minutes are in BCD format */
506 *start_hr = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf);
507 *start_min = (msg->msg[5] >> 4) * 10 + (msg->msg[5] & 0xf);
508 *duration_hr = (msg->msg[6] >> 4) * 10 + (msg->msg[6] & 0xf);
509 *duration_min = (msg->msg[7] >> 4) * 10 + (msg->msg[7] & 0xf);
510 *recording_seq = msg->msg[8];
511 *ana_bcast_type = msg->msg[9];
512 *ana_freq = (msg->msg[10] << 8) | msg->msg[11];
513 *bcast_system = msg->msg[12];
514}
515
516static inline void cec_msg_clear_digital_timer(struct cec_msg *msg,
517 bool reply,
518 __u8 day,
519 __u8 month,
520 __u8 start_hr,
521 __u8 start_min,
522 __u8 duration_hr,
523 __u8 duration_min,
524 __u8 recording_seq,
525 const struct cec_op_digital_service_id *digital)
526{
527 msg->len = 16;
528 msg->reply = reply ? CEC_MSG_TIMER_CLEARED_STATUS : 0;
529 msg->msg[1] = CEC_MSG_CLEAR_DIGITAL_TIMER;
530 msg->msg[2] = day;
531 msg->msg[3] = month;
532 /* Hours and minutes are in BCD format */
533 msg->msg[4] = ((start_hr / 10) << 4) | (start_hr % 10);
534 msg->msg[5] = ((start_min / 10) << 4) | (start_min % 10);
535 msg->msg[6] = ((duration_hr / 10) << 4) | (duration_hr % 10);
536 msg->msg[7] = ((duration_min / 10) << 4) | (duration_min % 10);
537 msg->msg[8] = recording_seq;
538 cec_set_digital_service_id(msg->msg + 9, digital);
539}
540
541static inline void cec_ops_clear_digital_timer(const struct cec_msg *msg,
542 __u8 *day,
543 __u8 *month,
544 __u8 *start_hr,
545 __u8 *start_min,
546 __u8 *duration_hr,
547 __u8 *duration_min,
548 __u8 *recording_seq,
549 struct cec_op_digital_service_id *digital)
550{
551 *day = msg->msg[2];
552 *month = msg->msg[3];
553 /* Hours and minutes are in BCD format */
554 *start_hr = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf);
555 *start_min = (msg->msg[5] >> 4) * 10 + (msg->msg[5] & 0xf);
556 *duration_hr = (msg->msg[6] >> 4) * 10 + (msg->msg[6] & 0xf);
557 *duration_min = (msg->msg[7] >> 4) * 10 + (msg->msg[7] & 0xf);
558 *recording_seq = msg->msg[8];
559 cec_get_digital_service_id(msg->msg + 9, digital);
560}
561
562static inline void cec_msg_clear_ext_timer(struct cec_msg *msg,
563 bool reply,
564 __u8 day,
565 __u8 month,
566 __u8 start_hr,
567 __u8 start_min,
568 __u8 duration_hr,
569 __u8 duration_min,
570 __u8 recording_seq,
571 __u8 ext_src_spec,
572 __u8 plug,
573 __u16 phys_addr)
574{
575 msg->len = 13;
576 msg->msg[1] = CEC_MSG_CLEAR_EXT_TIMER;
577 msg->msg[2] = day;
578 msg->msg[3] = month;
579 /* Hours and minutes are in BCD format */
580 msg->msg[4] = ((start_hr / 10) << 4) | (start_hr % 10);
581 msg->msg[5] = ((start_min / 10) << 4) | (start_min % 10);
582 msg->msg[6] = ((duration_hr / 10) << 4) | (duration_hr % 10);
583 msg->msg[7] = ((duration_min / 10) << 4) | (duration_min % 10);
584 msg->msg[8] = recording_seq;
585 msg->msg[9] = ext_src_spec;
586 msg->msg[10] = plug;
587 msg->msg[11] = phys_addr >> 8;
588 msg->msg[12] = phys_addr & 0xff;
589 msg->reply = reply ? CEC_MSG_TIMER_CLEARED_STATUS : 0;
590}
591
592static inline void cec_ops_clear_ext_timer(const struct cec_msg *msg,
593 __u8 *day,
594 __u8 *month,
595 __u8 *start_hr,
596 __u8 *start_min,
597 __u8 *duration_hr,
598 __u8 *duration_min,
599 __u8 *recording_seq,
600 __u8 *ext_src_spec,
601 __u8 *plug,
602 __u16 *phys_addr)
603{
604 *day = msg->msg[2];
605 *month = msg->msg[3];
606 /* Hours and minutes are in BCD format */
607 *start_hr = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf);
608 *start_min = (msg->msg[5] >> 4) * 10 + (msg->msg[5] & 0xf);
609 *duration_hr = (msg->msg[6] >> 4) * 10 + (msg->msg[6] & 0xf);
610 *duration_min = (msg->msg[7] >> 4) * 10 + (msg->msg[7] & 0xf);
611 *recording_seq = msg->msg[8];
612 *ext_src_spec = msg->msg[9];
613 *plug = msg->msg[10];
614 *phys_addr = (msg->msg[11] << 8) | msg->msg[12];
615}
616
617static inline void cec_msg_set_analogue_timer(struct cec_msg *msg,
618 bool reply,
619 __u8 day,
620 __u8 month,
621 __u8 start_hr,
622 __u8 start_min,
623 __u8 duration_hr,
624 __u8 duration_min,
625 __u8 recording_seq,
626 __u8 ana_bcast_type,
627 __u16 ana_freq,
628 __u8 bcast_system)
629{
630 msg->len = 13;
631 msg->msg[1] = CEC_MSG_SET_ANALOGUE_TIMER;
632 msg->msg[2] = day;
633 msg->msg[3] = month;
634 /* Hours and minutes are in BCD format */
635 msg->msg[4] = ((start_hr / 10) << 4) | (start_hr % 10);
636 msg->msg[5] = ((start_min / 10) << 4) | (start_min % 10);
637 msg->msg[6] = ((duration_hr / 10) << 4) | (duration_hr % 10);
638 msg->msg[7] = ((duration_min / 10) << 4) | (duration_min % 10);
639 msg->msg[8] = recording_seq;
640 msg->msg[9] = ana_bcast_type;
641 msg->msg[10] = ana_freq >> 8;
642 msg->msg[11] = ana_freq & 0xff;
643 msg->msg[12] = bcast_system;
644 msg->reply = reply ? CEC_MSG_TIMER_STATUS : 0;
645}
646
647static inline void cec_ops_set_analogue_timer(const struct cec_msg *msg,
648 __u8 *day,
649 __u8 *month,
650 __u8 *start_hr,
651 __u8 *start_min,
652 __u8 *duration_hr,
653 __u8 *duration_min,
654 __u8 *recording_seq,
655 __u8 *ana_bcast_type,
656 __u16 *ana_freq,
657 __u8 *bcast_system)
658{
659 *day = msg->msg[2];
660 *month = msg->msg[3];
661 /* Hours and minutes are in BCD format */
662 *start_hr = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf);
663 *start_min = (msg->msg[5] >> 4) * 10 + (msg->msg[5] & 0xf);
664 *duration_hr = (msg->msg[6] >> 4) * 10 + (msg->msg[6] & 0xf);
665 *duration_min = (msg->msg[7] >> 4) * 10 + (msg->msg[7] & 0xf);
666 *recording_seq = msg->msg[8];
667 *ana_bcast_type = msg->msg[9];
668 *ana_freq = (msg->msg[10] << 8) | msg->msg[11];
669 *bcast_system = msg->msg[12];
670}
671
672static inline void cec_msg_set_digital_timer(struct cec_msg *msg,
673 bool reply,
674 __u8 day,
675 __u8 month,
676 __u8 start_hr,
677 __u8 start_min,
678 __u8 duration_hr,
679 __u8 duration_min,
680 __u8 recording_seq,
681 const struct cec_op_digital_service_id *digital)
682{
683 msg->len = 16;
684 msg->reply = reply ? CEC_MSG_TIMER_STATUS : 0;
685 msg->msg[1] = CEC_MSG_SET_DIGITAL_TIMER;
686 msg->msg[2] = day;
687 msg->msg[3] = month;
688 /* Hours and minutes are in BCD format */
689 msg->msg[4] = ((start_hr / 10) << 4) | (start_hr % 10);
690 msg->msg[5] = ((start_min / 10) << 4) | (start_min % 10);
691 msg->msg[6] = ((duration_hr / 10) << 4) | (duration_hr % 10);
692 msg->msg[7] = ((duration_min / 10) << 4) | (duration_min % 10);
693 msg->msg[8] = recording_seq;
694 cec_set_digital_service_id(msg->msg + 9, digital);
695}
696
697static inline void cec_ops_set_digital_timer(const struct cec_msg *msg,
698 __u8 *day,
699 __u8 *month,
700 __u8 *start_hr,
701 __u8 *start_min,
702 __u8 *duration_hr,
703 __u8 *duration_min,
704 __u8 *recording_seq,
705 struct cec_op_digital_service_id *digital)
706{
707 *day = msg->msg[2];
708 *month = msg->msg[3];
709 /* Hours and minutes are in BCD format */
710 *start_hr = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf);
711 *start_min = (msg->msg[5] >> 4) * 10 + (msg->msg[5] & 0xf);
712 *duration_hr = (msg->msg[6] >> 4) * 10 + (msg->msg[6] & 0xf);
713 *duration_min = (msg->msg[7] >> 4) * 10 + (msg->msg[7] & 0xf);
714 *recording_seq = msg->msg[8];
715 cec_get_digital_service_id(msg->msg + 9, digital);
716}
717
718static inline void cec_msg_set_ext_timer(struct cec_msg *msg,
719 bool reply,
720 __u8 day,
721 __u8 month,
722 __u8 start_hr,
723 __u8 start_min,
724 __u8 duration_hr,
725 __u8 duration_min,
726 __u8 recording_seq,
727 __u8 ext_src_spec,
728 __u8 plug,
729 __u16 phys_addr)
730{
731 msg->len = 13;
732 msg->msg[1] = CEC_MSG_SET_EXT_TIMER;
733 msg->msg[2] = day;
734 msg->msg[3] = month;
735 /* Hours and minutes are in BCD format */
736 msg->msg[4] = ((start_hr / 10) << 4) | (start_hr % 10);
737 msg->msg[5] = ((start_min / 10) << 4) | (start_min % 10);
738 msg->msg[6] = ((duration_hr / 10) << 4) | (duration_hr % 10);
739 msg->msg[7] = ((duration_min / 10) << 4) | (duration_min % 10);
740 msg->msg[8] = recording_seq;
741 msg->msg[9] = ext_src_spec;
742 msg->msg[10] = plug;
743 msg->msg[11] = phys_addr >> 8;
744 msg->msg[12] = phys_addr & 0xff;
745 msg->reply = reply ? CEC_MSG_TIMER_STATUS : 0;
746}
747
748static inline void cec_ops_set_ext_timer(const struct cec_msg *msg,
749 __u8 *day,
750 __u8 *month,
751 __u8 *start_hr,
752 __u8 *start_min,
753 __u8 *duration_hr,
754 __u8 *duration_min,
755 __u8 *recording_seq,
756 __u8 *ext_src_spec,
757 __u8 *plug,
758 __u16 *phys_addr)
759{
760 *day = msg->msg[2];
761 *month = msg->msg[3];
762 /* Hours and minutes are in BCD format */
763 *start_hr = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf);
764 *start_min = (msg->msg[5] >> 4) * 10 + (msg->msg[5] & 0xf);
765 *duration_hr = (msg->msg[6] >> 4) * 10 + (msg->msg[6] & 0xf);
766 *duration_min = (msg->msg[7] >> 4) * 10 + (msg->msg[7] & 0xf);
767 *recording_seq = msg->msg[8];
768 *ext_src_spec = msg->msg[9];
769 *plug = msg->msg[10];
770 *phys_addr = (msg->msg[11] << 8) | msg->msg[12];
771}
772
773static inline void cec_msg_set_timer_program_title(struct cec_msg *msg,
774 const char *prog_title)
775{
776 unsigned int len = strlen(prog_title);
777
778 if (len > 14)
779 len = 14;
780 msg->len = 2 + len;
781 msg->msg[1] = CEC_MSG_SET_TIMER_PROGRAM_TITLE;
782 memcpy(msg->msg + 2, prog_title, len);
783}
784
785static inline void cec_ops_set_timer_program_title(const struct cec_msg *msg,
786 char *prog_title)
787{
788 unsigned int len = msg->len > 2 ? msg->len - 2 : 0;
789
790 if (len > 14)
791 len = 14;
792 memcpy(prog_title, msg->msg + 2, len);
793 prog_title[len] = '\0';
794}
795
796/* System Information Feature */
797static inline void cec_msg_cec_version(struct cec_msg *msg, __u8 cec_version)
798{
799 msg->len = 3;
800 msg->msg[1] = CEC_MSG_CEC_VERSION;
801 msg->msg[2] = cec_version;
802}
803
804static inline void cec_ops_cec_version(const struct cec_msg *msg,
805 __u8 *cec_version)
806{
807 *cec_version = msg->msg[2];
808}
809
810static inline void cec_msg_get_cec_version(struct cec_msg *msg,
811 bool reply)
812{
813 msg->len = 2;
814 msg->msg[1] = CEC_MSG_GET_CEC_VERSION;
815 msg->reply = reply ? CEC_MSG_CEC_VERSION : 0;
816}
817
818static inline void cec_msg_report_physical_addr(struct cec_msg *msg,
819 __u16 phys_addr, __u8 prim_devtype)
820{
821 msg->len = 5;
822 msg->msg[0] |= 0xf; /* broadcast */
823 msg->msg[1] = CEC_MSG_REPORT_PHYSICAL_ADDR;
824 msg->msg[2] = phys_addr >> 8;
825 msg->msg[3] = phys_addr & 0xff;
826 msg->msg[4] = prim_devtype;
827}
828
829static inline void cec_ops_report_physical_addr(const struct cec_msg *msg,
830 __u16 *phys_addr, __u8 *prim_devtype)
831{
832 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
833 *prim_devtype = msg->msg[4];
834}
835
836static inline void cec_msg_give_physical_addr(struct cec_msg *msg,
837 bool reply)
838{
839 msg->len = 2;
840 msg->msg[1] = CEC_MSG_GIVE_PHYSICAL_ADDR;
841 msg->reply = reply ? CEC_MSG_REPORT_PHYSICAL_ADDR : 0;
842}
843
844static inline void cec_msg_set_menu_language(struct cec_msg *msg,
845 const char *language)
846{
847 msg->len = 5;
848 msg->msg[0] |= 0xf; /* broadcast */
849 msg->msg[1] = CEC_MSG_SET_MENU_LANGUAGE;
850 memcpy(msg->msg + 2, language, 3);
851}
852
853static inline void cec_ops_set_menu_language(const struct cec_msg *msg,
854 char *language)
855{
856 memcpy(language, msg->msg + 2, 3);
857 language[3] = '\0';
858}
859
860static inline void cec_msg_get_menu_language(struct cec_msg *msg,
861 bool reply)
862{
863 msg->len = 2;
864 msg->msg[1] = CEC_MSG_GET_MENU_LANGUAGE;
865 msg->reply = reply ? CEC_MSG_SET_MENU_LANGUAGE : 0;
866}
867
868/*
869 * Assumes a single RC Profile byte and a single Device Features byte,
870 * i.e. no extended features are supported by this helper function.
871 *
872 * As of CEC 2.0 no extended features are defined, should those be added
873 * in the future, then this function needs to be adapted or a new function
874 * should be added.
875 */
876static inline void cec_msg_report_features(struct cec_msg *msg,
877 __u8 cec_version, __u8 all_device_types,
878 __u8 rc_profile, __u8 dev_features)
879{
880 msg->len = 6;
881 msg->msg[0] |= 0xf; /* broadcast */
882 msg->msg[1] = CEC_MSG_REPORT_FEATURES;
883 msg->msg[2] = cec_version;
884 msg->msg[3] = all_device_types;
885 msg->msg[4] = rc_profile;
886 msg->msg[5] = dev_features;
887}
888
889static inline void cec_ops_report_features(const struct cec_msg *msg,
890 __u8 *cec_version, __u8 *all_device_types,
891 const __u8 **rc_profile, const __u8 **dev_features)
892{
893 const __u8 *p = &msg->msg[4];
894
895 *cec_version = msg->msg[2];
896 *all_device_types = msg->msg[3];
897 *rc_profile = p;
898 while (p < &msg->msg[14] && (*p & CEC_OP_FEAT_EXT))
899 p++;
900 if (!(*p & CEC_OP_FEAT_EXT)) {
901 *dev_features = p + 1;
902 while (p < &msg->msg[15] && (*p & CEC_OP_FEAT_EXT))
903 p++;
904 }
905 if (*p & CEC_OP_FEAT_EXT)
906 *rc_profile = *dev_features = NULL;
907}
908
909static inline void cec_msg_give_features(struct cec_msg *msg,
910 bool reply)
911{
912 msg->len = 2;
913 msg->msg[1] = CEC_MSG_GIVE_FEATURES;
914 msg->reply = reply ? CEC_MSG_REPORT_FEATURES : 0;
915}
916
917/* Deck Control Feature */
918static inline void cec_msg_deck_control(struct cec_msg *msg,
919 __u8 deck_control_mode)
920{
921 msg->len = 3;
922 msg->msg[1] = CEC_MSG_DECK_CONTROL;
923 msg->msg[2] = deck_control_mode;
924}
925
926static inline void cec_ops_deck_control(const struct cec_msg *msg,
927 __u8 *deck_control_mode)
928{
929 *deck_control_mode = msg->msg[2];
930}
931
932static inline void cec_msg_deck_status(struct cec_msg *msg,
933 __u8 deck_info)
934{
935 msg->len = 3;
936 msg->msg[1] = CEC_MSG_DECK_STATUS;
937 msg->msg[2] = deck_info;
938}
939
940static inline void cec_ops_deck_status(const struct cec_msg *msg,
941 __u8 *deck_info)
942{
943 *deck_info = msg->msg[2];
944}
945
946static inline void cec_msg_give_deck_status(struct cec_msg *msg,
947 bool reply,
948 __u8 status_req)
949{
950 msg->len = 3;
951 msg->msg[1] = CEC_MSG_GIVE_DECK_STATUS;
952 msg->msg[2] = status_req;
953 msg->reply = reply ? CEC_MSG_DECK_STATUS : 0;
954}
955
956static inline void cec_ops_give_deck_status(const struct cec_msg *msg,
957 __u8 *status_req)
958{
959 *status_req = msg->msg[2];
960}
961
962static inline void cec_msg_play(struct cec_msg *msg,
963 __u8 play_mode)
964{
965 msg->len = 3;
966 msg->msg[1] = CEC_MSG_PLAY;
967 msg->msg[2] = play_mode;
968}
969
970static inline void cec_ops_play(const struct cec_msg *msg,
971 __u8 *play_mode)
972{
973 *play_mode = msg->msg[2];
974}
975
976
977/* Tuner Control Feature */
978struct cec_op_tuner_device_info {
979 __u8 rec_flag;
980 __u8 tuner_display_info;
981 bool is_analog;
982 union {
983 struct cec_op_digital_service_id digital;
984 struct {
985 __u8 ana_bcast_type;
986 __u16 ana_freq;
987 __u8 bcast_system;
988 } analog;
989 };
990};
991
992static inline void cec_msg_tuner_device_status_analog(struct cec_msg *msg,
993 __u8 rec_flag,
994 __u8 tuner_display_info,
995 __u8 ana_bcast_type,
996 __u16 ana_freq,
997 __u8 bcast_system)
998{
999 msg->len = 7;
1000 msg->msg[1] = CEC_MSG_TUNER_DEVICE_STATUS;
1001 msg->msg[2] = (rec_flag << 7) | tuner_display_info;
1002 msg->msg[3] = ana_bcast_type;
1003 msg->msg[4] = ana_freq >> 8;
1004 msg->msg[5] = ana_freq & 0xff;
1005 msg->msg[6] = bcast_system;
1006}
1007
1008static inline void cec_msg_tuner_device_status_digital(struct cec_msg *msg,
1009 __u8 rec_flag, __u8 tuner_display_info,
1010 const struct cec_op_digital_service_id *digital)
1011{
1012 msg->len = 10;
1013 msg->msg[1] = CEC_MSG_TUNER_DEVICE_STATUS;
1014 msg->msg[2] = (rec_flag << 7) | tuner_display_info;
1015 cec_set_digital_service_id(msg->msg + 3, digital);
1016}
1017
1018static inline void cec_msg_tuner_device_status(struct cec_msg *msg,
1019 const struct cec_op_tuner_device_info *tuner_dev_info)
1020{
1021 if (tuner_dev_info->is_analog)
1022 cec_msg_tuner_device_status_analog(msg,
1023 tuner_dev_info->rec_flag,
1024 tuner_dev_info->tuner_display_info,
1025 tuner_dev_info->analog.ana_bcast_type,
1026 tuner_dev_info->analog.ana_freq,
1027 tuner_dev_info->analog.bcast_system);
1028 else
1029 cec_msg_tuner_device_status_digital(msg,
1030 tuner_dev_info->rec_flag,
1031 tuner_dev_info->tuner_display_info,
1032 &tuner_dev_info->digital);
1033}
1034
1035static inline void cec_ops_tuner_device_status(const struct cec_msg *msg,
1036 struct cec_op_tuner_device_info *tuner_dev_info)
1037{
1038 tuner_dev_info->is_analog = msg->len < 10;
1039 tuner_dev_info->rec_flag = msg->msg[2] >> 7;
1040 tuner_dev_info->tuner_display_info = msg->msg[2] & 0x7f;
1041 if (tuner_dev_info->is_analog) {
1042 tuner_dev_info->analog.ana_bcast_type = msg->msg[3];
1043 tuner_dev_info->analog.ana_freq = (msg->msg[4] << 8) | msg->msg[5];
1044 tuner_dev_info->analog.bcast_system = msg->msg[6];
1045 return;
1046 }
1047 cec_get_digital_service_id(msg->msg + 3, &tuner_dev_info->digital);
1048}
1049
1050static inline void cec_msg_give_tuner_device_status(struct cec_msg *msg,
1051 bool reply,
1052 __u8 status_req)
1053{
1054 msg->len = 3;
1055 msg->msg[1] = CEC_MSG_GIVE_TUNER_DEVICE_STATUS;
1056 msg->msg[2] = status_req;
1057 msg->reply = reply ? CEC_MSG_TUNER_DEVICE_STATUS : 0;
1058}
1059
1060static inline void cec_ops_give_tuner_device_status(const struct cec_msg *msg,
1061 __u8 *status_req)
1062{
1063 *status_req = msg->msg[2];
1064}
1065
1066static inline void cec_msg_select_analogue_service(struct cec_msg *msg,
1067 __u8 ana_bcast_type,
1068 __u16 ana_freq,
1069 __u8 bcast_system)
1070{
1071 msg->len = 6;
1072 msg->msg[1] = CEC_MSG_SELECT_ANALOGUE_SERVICE;
1073 msg->msg[2] = ana_bcast_type;
1074 msg->msg[3] = ana_freq >> 8;
1075 msg->msg[4] = ana_freq & 0xff;
1076 msg->msg[5] = bcast_system;
1077}
1078
1079static inline void cec_ops_select_analogue_service(const struct cec_msg *msg,
1080 __u8 *ana_bcast_type,
1081 __u16 *ana_freq,
1082 __u8 *bcast_system)
1083{
1084 *ana_bcast_type = msg->msg[2];
1085 *ana_freq = (msg->msg[3] << 8) | msg->msg[4];
1086 *bcast_system = msg->msg[5];
1087}
1088
1089static inline void cec_msg_select_digital_service(struct cec_msg *msg,
1090 const struct cec_op_digital_service_id *digital)
1091{
1092 msg->len = 9;
1093 msg->msg[1] = CEC_MSG_SELECT_DIGITAL_SERVICE;
1094 cec_set_digital_service_id(msg->msg + 2, digital);
1095}
1096
1097static inline void cec_ops_select_digital_service(const struct cec_msg *msg,
1098 struct cec_op_digital_service_id *digital)
1099{
1100 cec_get_digital_service_id(msg->msg + 2, digital);
1101}
1102
1103static inline void cec_msg_tuner_step_decrement(struct cec_msg *msg)
1104{
1105 msg->len = 2;
1106 msg->msg[1] = CEC_MSG_TUNER_STEP_DECREMENT;
1107}
1108
1109static inline void cec_msg_tuner_step_increment(struct cec_msg *msg)
1110{
1111 msg->len = 2;
1112 msg->msg[1] = CEC_MSG_TUNER_STEP_INCREMENT;
1113}
1114
1115
1116/* Vendor Specific Commands Feature */
1117static inline void cec_msg_device_vendor_id(struct cec_msg *msg, __u32 vendor_id)
1118{
1119 msg->len = 5;
1120 msg->msg[0] |= 0xf; /* broadcast */
1121 msg->msg[1] = CEC_MSG_DEVICE_VENDOR_ID;
1122 msg->msg[2] = vendor_id >> 16;
1123 msg->msg[3] = (vendor_id >> 8) & 0xff;
1124 msg->msg[4] = vendor_id & 0xff;
1125}
1126
1127static inline void cec_ops_device_vendor_id(const struct cec_msg *msg,
1128 __u32 *vendor_id)
1129{
1130 *vendor_id = (msg->msg[2] << 16) | (msg->msg[3] << 8) | msg->msg[4];
1131}
1132
1133static inline void cec_msg_give_device_vendor_id(struct cec_msg *msg,
1134 bool reply)
1135{
1136 msg->len = 2;
1137 msg->msg[1] = CEC_MSG_GIVE_DEVICE_VENDOR_ID;
1138 msg->reply = reply ? CEC_MSG_DEVICE_VENDOR_ID : 0;
1139}
1140
1141static inline void cec_msg_vendor_command(struct cec_msg *msg,
1142 __u8 size, const __u8 *vendor_cmd)
1143{
1144 if (size > 14)
1145 size = 14;
1146 msg->len = 2 + size;
1147 msg->msg[1] = CEC_MSG_VENDOR_COMMAND;
1148 memcpy(msg->msg + 2, vendor_cmd, size);
1149}
1150
1151static inline void cec_ops_vendor_command(const struct cec_msg *msg,
1152 __u8 *size,
1153 const __u8 **vendor_cmd)
1154{
1155 *size = msg->len - 2;
1156
1157 if (*size > 14)
1158 *size = 14;
1159 *vendor_cmd = msg->msg + 2;
1160}
1161
1162static inline void cec_msg_vendor_command_with_id(struct cec_msg *msg,
1163 __u32 vendor_id, __u8 size,
1164 const __u8 *vendor_cmd)
1165{
1166 if (size > 11)
1167 size = 11;
1168 msg->len = 5 + size;
1169 msg->msg[1] = CEC_MSG_VENDOR_COMMAND_WITH_ID;
1170 msg->msg[2] = vendor_id >> 16;
1171 msg->msg[3] = (vendor_id >> 8) & 0xff;
1172 msg->msg[4] = vendor_id & 0xff;
1173 memcpy(msg->msg + 5, vendor_cmd, size);
1174}
1175
1176static inline void cec_ops_vendor_command_with_id(const struct cec_msg *msg,
1177 __u32 *vendor_id, __u8 *size,
1178 const __u8 **vendor_cmd)
1179{
1180 *size = msg->len - 5;
1181
1182 if (*size > 11)
1183 *size = 11;
1184 *vendor_id = (msg->msg[2] << 16) | (msg->msg[3] << 8) | msg->msg[4];
1185 *vendor_cmd = msg->msg + 5;
1186}
1187
1188static inline void cec_msg_vendor_remote_button_down(struct cec_msg *msg,
1189 __u8 size,
1190 const __u8 *rc_code)
1191{
1192 if (size > 14)
1193 size = 14;
1194 msg->len = 2 + size;
1195 msg->msg[1] = CEC_MSG_VENDOR_REMOTE_BUTTON_DOWN;
1196 memcpy(msg->msg + 2, rc_code, size);
1197}
1198
1199static inline void cec_ops_vendor_remote_button_down(const struct cec_msg *msg,
1200 __u8 *size,
1201 const __u8 **rc_code)
1202{
1203 *size = msg->len - 2;
1204
1205 if (*size > 14)
1206 *size = 14;
1207 *rc_code = msg->msg + 2;
1208}
1209
1210static inline void cec_msg_vendor_remote_button_up(struct cec_msg *msg)
1211{
1212 msg->len = 2;
1213 msg->msg[1] = CEC_MSG_VENDOR_REMOTE_BUTTON_UP;
1214}
1215
1216
1217/* OSD Display Feature */
1218static inline void cec_msg_set_osd_string(struct cec_msg *msg,
1219 __u8 disp_ctl,
1220 const char *osd)
1221{
1222 unsigned int len = strlen(osd);
1223
1224 if (len > 13)
1225 len = 13;
1226 msg->len = 3 + len;
1227 msg->msg[1] = CEC_MSG_SET_OSD_STRING;
1228 msg->msg[2] = disp_ctl;
1229 memcpy(msg->msg + 3, osd, len);
1230}
1231
1232static inline void cec_ops_set_osd_string(const struct cec_msg *msg,
1233 __u8 *disp_ctl,
1234 char *osd)
1235{
1236 unsigned int len = msg->len > 3 ? msg->len - 3 : 0;
1237
1238 *disp_ctl = msg->msg[2];
1239 if (len > 13)
1240 len = 13;
1241 memcpy(osd, msg->msg + 3, len);
1242 osd[len] = '\0';
1243}
1244
1245
1246/* Device OSD Transfer Feature */
1247static inline void cec_msg_set_osd_name(struct cec_msg *msg, const char *name)
1248{
1249 unsigned int len = strlen(name);
1250
1251 if (len > 14)
1252 len = 14;
1253 msg->len = 2 + len;
1254 msg->msg[1] = CEC_MSG_SET_OSD_NAME;
1255 memcpy(msg->msg + 2, name, len);
1256}
1257
1258static inline void cec_ops_set_osd_name(const struct cec_msg *msg,
1259 char *name)
1260{
1261 unsigned int len = msg->len > 2 ? msg->len - 2 : 0;
1262
1263 if (len > 14)
1264 len = 14;
1265 memcpy(name, msg->msg + 2, len);
1266 name[len] = '\0';
1267}
1268
1269static inline void cec_msg_give_osd_name(struct cec_msg *msg,
1270 bool reply)
1271{
1272 msg->len = 2;
1273 msg->msg[1] = CEC_MSG_GIVE_OSD_NAME;
1274 msg->reply = reply ? CEC_MSG_SET_OSD_NAME : 0;
1275}
1276
1277
1278/* Device Menu Control Feature */
1279static inline void cec_msg_menu_status(struct cec_msg *msg,
1280 __u8 menu_state)
1281{
1282 msg->len = 3;
1283 msg->msg[1] = CEC_MSG_MENU_STATUS;
1284 msg->msg[2] = menu_state;
1285}
1286
1287static inline void cec_ops_menu_status(const struct cec_msg *msg,
1288 __u8 *menu_state)
1289{
1290 *menu_state = msg->msg[2];
1291}
1292
1293static inline void cec_msg_menu_request(struct cec_msg *msg,
1294 bool reply,
1295 __u8 menu_req)
1296{
1297 msg->len = 3;
1298 msg->msg[1] = CEC_MSG_MENU_REQUEST;
1299 msg->msg[2] = menu_req;
1300 msg->reply = reply ? CEC_MSG_MENU_STATUS : 0;
1301}
1302
1303static inline void cec_ops_menu_request(const struct cec_msg *msg,
1304 __u8 *menu_req)
1305{
1306 *menu_req = msg->msg[2];
1307}
1308
1309struct cec_op_ui_command {
1310 __u8 ui_cmd;
1311 bool has_opt_arg;
1312 union {
1313 struct cec_op_channel_data channel_identifier;
1314 __u8 ui_broadcast_type;
1315 __u8 ui_sound_presentation_control;
1316 __u8 play_mode;
1317 __u8 ui_function_media;
1318 __u8 ui_function_select_av_input;
1319 __u8 ui_function_select_audio_input;
1320 };
1321};
1322
1323static inline void cec_msg_user_control_pressed(struct cec_msg *msg,
1324 const struct cec_op_ui_command *ui_cmd)
1325{
1326 msg->len = 3;
1327 msg->msg[1] = CEC_MSG_USER_CONTROL_PRESSED;
1328 msg->msg[2] = ui_cmd->ui_cmd;
1329 if (!ui_cmd->has_opt_arg)
1330 return;
1331 switch (ui_cmd->ui_cmd) {
1332 case 0x56:
1333 case 0x57:
1334 case 0x60:
1335 case 0x68:
1336 case 0x69:
1337 case 0x6a:
1338 /* The optional operand is one byte for all these ui commands */
1339 msg->len++;
1340 msg->msg[3] = ui_cmd->play_mode;
1341 break;
1342 case 0x67:
1343 msg->len += 4;
1344 msg->msg[3] = (ui_cmd->channel_identifier.channel_number_fmt << 2) |
1345 (ui_cmd->channel_identifier.major >> 8);
1346 msg->msg[4] = ui_cmd->channel_identifier.major & 0xff;
1347 msg->msg[5] = ui_cmd->channel_identifier.minor >> 8;
1348 msg->msg[6] = ui_cmd->channel_identifier.minor & 0xff;
1349 break;
1350 }
1351}
1352
1353static inline void cec_ops_user_control_pressed(const struct cec_msg *msg,
1354 struct cec_op_ui_command *ui_cmd)
1355{
1356 ui_cmd->ui_cmd = msg->msg[2];
1357 ui_cmd->has_opt_arg = false;
1358 if (msg->len == 3)
1359 return;
1360 switch (ui_cmd->ui_cmd) {
1361 case 0x56:
1362 case 0x57:
1363 case 0x60:
1364 case 0x68:
1365 case 0x69:
1366 case 0x6a:
1367 /* The optional operand is one byte for all these ui commands */
1368 ui_cmd->play_mode = msg->msg[3];
1369 ui_cmd->has_opt_arg = true;
1370 break;
1371 case 0x67:
1372 if (msg->len < 7)
1373 break;
1374 ui_cmd->has_opt_arg = true;
1375 ui_cmd->channel_identifier.channel_number_fmt = msg->msg[3] >> 2;
1376 ui_cmd->channel_identifier.major = ((msg->msg[3] & 3) << 6) | msg->msg[4];
1377 ui_cmd->channel_identifier.minor = (msg->msg[5] << 8) | msg->msg[6];
1378 break;
1379 }
1380}
1381
1382static inline void cec_msg_user_control_released(struct cec_msg *msg)
1383{
1384 msg->len = 2;
1385 msg->msg[1] = CEC_MSG_USER_CONTROL_RELEASED;
1386}
1387
1388/* Remote Control Passthrough Feature */
1389
1390/* Power Status Feature */
1391static inline void cec_msg_report_power_status(struct cec_msg *msg,
1392 __u8 pwr_state)
1393{
1394 msg->len = 3;
1395 msg->msg[1] = CEC_MSG_REPORT_POWER_STATUS;
1396 msg->msg[2] = pwr_state;
1397}
1398
1399static inline void cec_ops_report_power_status(const struct cec_msg *msg,
1400 __u8 *pwr_state)
1401{
1402 *pwr_state = msg->msg[2];
1403}
1404
1405static inline void cec_msg_give_device_power_status(struct cec_msg *msg,
1406 bool reply)
1407{
1408 msg->len = 2;
1409 msg->msg[1] = CEC_MSG_GIVE_DEVICE_POWER_STATUS;
1410 msg->reply = reply ? CEC_MSG_REPORT_POWER_STATUS : 0;
1411}
1412
1413/* General Protocol Messages */
1414static inline void cec_msg_feature_abort(struct cec_msg *msg,
1415 __u8 abort_msg, __u8 reason)
1416{
1417 msg->len = 4;
1418 msg->msg[1] = CEC_MSG_FEATURE_ABORT;
1419 msg->msg[2] = abort_msg;
1420 msg->msg[3] = reason;
1421}
1422
1423static inline void cec_ops_feature_abort(const struct cec_msg *msg,
1424 __u8 *abort_msg, __u8 *reason)
1425{
1426 *abort_msg = msg->msg[2];
1427 *reason = msg->msg[3];
1428}
1429
1430/* This changes the current message into a feature abort message */
1431static inline void cec_msg_reply_feature_abort(struct cec_msg *msg, __u8 reason)
1432{
1433 cec_msg_set_reply_to(msg, msg);
1434 msg->len = 4;
1435 msg->msg[2] = msg->msg[1];
1436 msg->msg[3] = reason;
1437 msg->msg[1] = CEC_MSG_FEATURE_ABORT;
1438}
1439
1440static inline void cec_msg_abort(struct cec_msg *msg)
1441{
1442 msg->len = 2;
1443 msg->msg[1] = CEC_MSG_ABORT;
1444}
1445
1446
1447/* System Audio Control Feature */
1448static inline void cec_msg_report_audio_status(struct cec_msg *msg,
1449 __u8 aud_mute_status,
1450 __u8 aud_vol_status)
1451{
1452 msg->len = 3;
1453 msg->msg[1] = CEC_MSG_REPORT_AUDIO_STATUS;
1454 msg->msg[2] = (aud_mute_status << 7) | (aud_vol_status & 0x7f);
1455}
1456
1457static inline void cec_ops_report_audio_status(const struct cec_msg *msg,
1458 __u8 *aud_mute_status,
1459 __u8 *aud_vol_status)
1460{
1461 *aud_mute_status = msg->msg[2] >> 7;
1462 *aud_vol_status = msg->msg[2] & 0x7f;
1463}
1464
1465static inline void cec_msg_give_audio_status(struct cec_msg *msg,
1466 bool reply)
1467{
1468 msg->len = 2;
1469 msg->msg[1] = CEC_MSG_GIVE_AUDIO_STATUS;
1470 msg->reply = reply ? CEC_MSG_REPORT_AUDIO_STATUS : 0;
1471}
1472
1473static inline void cec_msg_set_system_audio_mode(struct cec_msg *msg,
1474 __u8 sys_aud_status)
1475{
1476 msg->len = 3;
1477 msg->msg[1] = CEC_MSG_SET_SYSTEM_AUDIO_MODE;
1478 msg->msg[2] = sys_aud_status;
1479}
1480
1481static inline void cec_ops_set_system_audio_mode(const struct cec_msg *msg,
1482 __u8 *sys_aud_status)
1483{
1484 *sys_aud_status = msg->msg[2];
1485}
1486
1487static inline void cec_msg_system_audio_mode_request(struct cec_msg *msg,
1488 bool reply,
1489 __u16 phys_addr)
1490{
1491 msg->len = phys_addr == 0xffff ? 2 : 4;
1492 msg->msg[1] = CEC_MSG_SYSTEM_AUDIO_MODE_REQUEST;
1493 msg->msg[2] = phys_addr >> 8;
1494 msg->msg[3] = phys_addr & 0xff;
1495 msg->reply = reply ? CEC_MSG_SET_SYSTEM_AUDIO_MODE : 0;
1496
1497}
1498
1499static inline void cec_ops_system_audio_mode_request(const struct cec_msg *msg,
1500 __u16 *phys_addr)
1501{
1502 if (msg->len < 4)
1503 *phys_addr = 0xffff;
1504 else
1505 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1506}
1507
1508static inline void cec_msg_system_audio_mode_status(struct cec_msg *msg,
1509 __u8 sys_aud_status)
1510{
1511 msg->len = 3;
1512 msg->msg[1] = CEC_MSG_SYSTEM_AUDIO_MODE_STATUS;
1513 msg->msg[2] = sys_aud_status;
1514}
1515
1516static inline void cec_ops_system_audio_mode_status(const struct cec_msg *msg,
1517 __u8 *sys_aud_status)
1518{
1519 *sys_aud_status = msg->msg[2];
1520}
1521
1522static inline void cec_msg_give_system_audio_mode_status(struct cec_msg *msg,
1523 bool reply)
1524{
1525 msg->len = 2;
1526 msg->msg[1] = CEC_MSG_GIVE_SYSTEM_AUDIO_MODE_STATUS;
1527 msg->reply = reply ? CEC_MSG_SYSTEM_AUDIO_MODE_STATUS : 0;
1528}
1529
1530static inline void cec_msg_report_short_audio_descriptor(struct cec_msg *msg,
1531 __u8 num_descriptors,
1532 const __u32 *descriptors)
1533{
1534 unsigned int i;
1535
1536 if (num_descriptors > 4)
1537 num_descriptors = 4;
1538 msg->len = 2 + num_descriptors * 3;
1539 msg->msg[1] = CEC_MSG_REPORT_SHORT_AUDIO_DESCRIPTOR;
1540 for (i = 0; i < num_descriptors; i++) {
1541 msg->msg[2 + i * 3] = (descriptors[i] >> 16) & 0xff;
1542 msg->msg[3 + i * 3] = (descriptors[i] >> 8) & 0xff;
1543 msg->msg[4 + i * 3] = descriptors[i] & 0xff;
1544 }
1545}
1546
1547static inline void cec_ops_report_short_audio_descriptor(const struct cec_msg *msg,
1548 __u8 *num_descriptors,
1549 __u32 *descriptors)
1550{
1551 unsigned int i;
1552
1553 *num_descriptors = (msg->len - 2) / 3;
1554 if (*num_descriptors > 4)
1555 *num_descriptors = 4;
1556 for (i = 0; i < *num_descriptors; i++)
1557 descriptors[i] = (msg->msg[2 + i * 3] << 16) |
1558 (msg->msg[3 + i * 3] << 8) |
1559 msg->msg[4 + i * 3];
1560}
1561
1562static inline void cec_msg_request_short_audio_descriptor(struct cec_msg *msg,
1563 bool reply,
1564 __u8 num_descriptors,
1565 const __u8 *audio_format_id,
1566 const __u8 *audio_format_code)
1567{
1568 unsigned int i;
1569
1570 if (num_descriptors > 4)
1571 num_descriptors = 4;
1572 msg->len = 2 + num_descriptors;
1573 msg->msg[1] = CEC_MSG_REQUEST_SHORT_AUDIO_DESCRIPTOR;
1574 msg->reply = reply ? CEC_MSG_REPORT_SHORT_AUDIO_DESCRIPTOR : 0;
1575 for (i = 0; i < num_descriptors; i++)
1576 msg->msg[2 + i] = (audio_format_id[i] << 6) |
1577 (audio_format_code[i] & 0x3f);
1578}
1579
1580static inline void cec_ops_request_short_audio_descriptor(const struct cec_msg *msg,
1581 __u8 *num_descriptors,
1582 __u8 *audio_format_id,
1583 __u8 *audio_format_code)
1584{
1585 unsigned int i;
1586
1587 *num_descriptors = msg->len - 2;
1588 if (*num_descriptors > 4)
1589 *num_descriptors = 4;
1590 for (i = 0; i < *num_descriptors; i++) {
1591 audio_format_id[i] = msg->msg[2 + i] >> 6;
1592 audio_format_code[i] = msg->msg[2 + i] & 0x3f;
1593 }
1594}
1595
1596
1597/* Audio Rate Control Feature */
1598static inline void cec_msg_set_audio_rate(struct cec_msg *msg,
1599 __u8 audio_rate)
1600{
1601 msg->len = 3;
1602 msg->msg[1] = CEC_MSG_SET_AUDIO_RATE;
1603 msg->msg[2] = audio_rate;
1604}
1605
1606static inline void cec_ops_set_audio_rate(const struct cec_msg *msg,
1607 __u8 *audio_rate)
1608{
1609 *audio_rate = msg->msg[2];
1610}
1611
1612
1613/* Audio Return Channel Control Feature */
1614static inline void cec_msg_report_arc_initiated(struct cec_msg *msg)
1615{
1616 msg->len = 2;
1617 msg->msg[1] = CEC_MSG_REPORT_ARC_INITIATED;
1618}
1619
1620static inline void cec_msg_initiate_arc(struct cec_msg *msg,
1621 bool reply)
1622{
1623 msg->len = 2;
1624 msg->msg[1] = CEC_MSG_INITIATE_ARC;
1625 msg->reply = reply ? CEC_MSG_REPORT_ARC_INITIATED : 0;
1626}
1627
1628static inline void cec_msg_request_arc_initiation(struct cec_msg *msg,
1629 bool reply)
1630{
1631 msg->len = 2;
1632 msg->msg[1] = CEC_MSG_REQUEST_ARC_INITIATION;
1633 msg->reply = reply ? CEC_MSG_INITIATE_ARC : 0;
1634}
1635
1636static inline void cec_msg_report_arc_terminated(struct cec_msg *msg)
1637{
1638 msg->len = 2;
1639 msg->msg[1] = CEC_MSG_REPORT_ARC_TERMINATED;
1640}
1641
1642static inline void cec_msg_terminate_arc(struct cec_msg *msg,
1643 bool reply)
1644{
1645 msg->len = 2;
1646 msg->msg[1] = CEC_MSG_TERMINATE_ARC;
1647 msg->reply = reply ? CEC_MSG_REPORT_ARC_TERMINATED : 0;
1648}
1649
1650static inline void cec_msg_request_arc_termination(struct cec_msg *msg,
1651 bool reply)
1652{
1653 msg->len = 2;
1654 msg->msg[1] = CEC_MSG_REQUEST_ARC_TERMINATION;
1655 msg->reply = reply ? CEC_MSG_TERMINATE_ARC : 0;
1656}
1657
1658
1659/* Dynamic Audio Lipsync Feature */
1660/* Only for CEC 2.0 and up */
1661static inline void cec_msg_report_current_latency(struct cec_msg *msg,
1662 __u16 phys_addr,
1663 __u8 video_latency,
1664 __u8 low_latency_mode,
1665 __u8 audio_out_compensated,
1666 __u8 audio_out_delay)
1667{
1668 msg->len = 7;
1669 msg->msg[0] |= 0xf; /* broadcast */
1670 msg->msg[1] = CEC_MSG_REPORT_CURRENT_LATENCY;
1671 msg->msg[2] = phys_addr >> 8;
1672 msg->msg[3] = phys_addr & 0xff;
1673 msg->msg[4] = video_latency;
1674 msg->msg[5] = (low_latency_mode << 2) | audio_out_compensated;
1675 msg->msg[6] = audio_out_delay;
1676}
1677
1678static inline void cec_ops_report_current_latency(const struct cec_msg *msg,
1679 __u16 *phys_addr,
1680 __u8 *video_latency,
1681 __u8 *low_latency_mode,
1682 __u8 *audio_out_compensated,
1683 __u8 *audio_out_delay)
1684{
1685 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1686 *video_latency = msg->msg[4];
1687 *low_latency_mode = (msg->msg[5] >> 2) & 1;
1688 *audio_out_compensated = msg->msg[5] & 3;
1689 *audio_out_delay = msg->msg[6];
1690}
1691
1692static inline void cec_msg_request_current_latency(struct cec_msg *msg,
1693 bool reply,
1694 __u16 phys_addr)
1695{
1696 msg->len = 4;
1697 msg->msg[0] |= 0xf; /* broadcast */
1698 msg->msg[1] = CEC_MSG_REQUEST_CURRENT_LATENCY;
1699 msg->msg[2] = phys_addr >> 8;
1700 msg->msg[3] = phys_addr & 0xff;
1701 msg->reply = reply ? CEC_MSG_REPORT_CURRENT_LATENCY : 0;
1702}
1703
1704static inline void cec_ops_request_current_latency(const struct cec_msg *msg,
1705 __u16 *phys_addr)
1706{
1707 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1708}
1709
1710
1711/* Capability Discovery and Control Feature */
1712static inline void cec_msg_cdc_hec_inquire_state(struct cec_msg *msg,
1713 __u16 phys_addr1,
1714 __u16 phys_addr2)
1715{
1716 msg->len = 9;
1717 msg->msg[0] |= 0xf; /* broadcast */
1718 msg->msg[1] = CEC_MSG_CDC_MESSAGE;
1719 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1720 msg->msg[4] = CEC_MSG_CDC_HEC_INQUIRE_STATE;
1721 msg->msg[5] = phys_addr1 >> 8;
1722 msg->msg[6] = phys_addr1 & 0xff;
1723 msg->msg[7] = phys_addr2 >> 8;
1724 msg->msg[8] = phys_addr2 & 0xff;
1725}
1726
1727static inline void cec_ops_cdc_hec_inquire_state(const struct cec_msg *msg,
1728 __u16 *phys_addr,
1729 __u16 *phys_addr1,
1730 __u16 *phys_addr2)
1731{
1732 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1733 *phys_addr1 = (msg->msg[5] << 8) | msg->msg[6];
1734 *phys_addr2 = (msg->msg[7] << 8) | msg->msg[8];
1735}
1736
1737static inline void cec_msg_cdc_hec_report_state(struct cec_msg *msg,
1738 __u16 target_phys_addr,
1739 __u8 hec_func_state,
1740 __u8 host_func_state,
1741 __u8 enc_func_state,
1742 __u8 cdc_errcode,
1743 __u8 has_field,
1744 __u16 hec_field)
1745{
1746 msg->len = has_field ? 10 : 8;
1747 msg->msg[0] |= 0xf; /* broadcast */
1748 msg->msg[1] = CEC_MSG_CDC_MESSAGE;
1749 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1750 msg->msg[4] = CEC_MSG_CDC_HEC_REPORT_STATE;
1751 msg->msg[5] = target_phys_addr >> 8;
1752 msg->msg[6] = target_phys_addr & 0xff;
1753 msg->msg[7] = (hec_func_state << 6) |
1754 (host_func_state << 4) |
1755 (enc_func_state << 2) |
1756 cdc_errcode;
1757 if (has_field) {
1758 msg->msg[8] = hec_field >> 8;
1759 msg->msg[9] = hec_field & 0xff;
1760 }
1761}
1762
1763static inline void cec_ops_cdc_hec_report_state(const struct cec_msg *msg,
1764 __u16 *phys_addr,
1765 __u16 *target_phys_addr,
1766 __u8 *hec_func_state,
1767 __u8 *host_func_state,
1768 __u8 *enc_func_state,
1769 __u8 *cdc_errcode,
1770 __u8 *has_field,
1771 __u16 *hec_field)
1772{
1773 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1774 *target_phys_addr = (msg->msg[5] << 8) | msg->msg[6];
1775 *hec_func_state = msg->msg[7] >> 6;
1776 *host_func_state = (msg->msg[7] >> 4) & 3;
1777 *enc_func_state = (msg->msg[7] >> 4) & 3;
1778 *cdc_errcode = msg->msg[7] & 3;
1779 *has_field = msg->len >= 10;
1780 *hec_field = *has_field ? ((msg->msg[8] << 8) | msg->msg[9]) : 0;
1781}
1782
1783static inline void cec_msg_cdc_hec_set_state(struct cec_msg *msg,
1784 __u16 phys_addr1,
1785 __u16 phys_addr2,
1786 __u8 hec_set_state,
1787 __u16 phys_addr3,
1788 __u16 phys_addr4,
1789 __u16 phys_addr5)
1790{
1791 msg->len = 10;
1792 msg->msg[0] |= 0xf; /* broadcast */
1793 msg->msg[1] = CEC_MSG_CDC_MESSAGE;
1794 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1795 msg->msg[4] = CEC_MSG_CDC_HEC_INQUIRE_STATE;
1796 msg->msg[5] = phys_addr1 >> 8;
1797 msg->msg[6] = phys_addr1 & 0xff;
1798 msg->msg[7] = phys_addr2 >> 8;
1799 msg->msg[8] = phys_addr2 & 0xff;
1800 msg->msg[9] = hec_set_state;
1801 if (phys_addr3 != CEC_PHYS_ADDR_INVALID) {
1802 msg->msg[msg->len++] = phys_addr3 >> 8;
1803 msg->msg[msg->len++] = phys_addr3 & 0xff;
1804 if (phys_addr4 != CEC_PHYS_ADDR_INVALID) {
1805 msg->msg[msg->len++] = phys_addr4 >> 8;
1806 msg->msg[msg->len++] = phys_addr4 & 0xff;
1807 if (phys_addr5 != CEC_PHYS_ADDR_INVALID) {
1808 msg->msg[msg->len++] = phys_addr5 >> 8;
1809 msg->msg[msg->len++] = phys_addr5 & 0xff;
1810 }
1811 }
1812 }
1813}
1814
1815static inline void cec_ops_cdc_hec_set_state(const struct cec_msg *msg,
1816 __u16 *phys_addr,
1817 __u16 *phys_addr1,
1818 __u16 *phys_addr2,
1819 __u8 *hec_set_state,
1820 __u16 *phys_addr3,
1821 __u16 *phys_addr4,
1822 __u16 *phys_addr5)
1823{
1824 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1825 *phys_addr1 = (msg->msg[5] << 8) | msg->msg[6];
1826 *phys_addr2 = (msg->msg[7] << 8) | msg->msg[8];
1827 *hec_set_state = msg->msg[9];
1828 *phys_addr3 = *phys_addr4 = *phys_addr5 = CEC_PHYS_ADDR_INVALID;
1829 if (msg->len >= 12)
1830 *phys_addr3 = (msg->msg[10] << 8) | msg->msg[11];
1831 if (msg->len >= 14)
1832 *phys_addr4 = (msg->msg[12] << 8) | msg->msg[13];
1833 if (msg->len >= 16)
1834 *phys_addr5 = (msg->msg[14] << 8) | msg->msg[15];
1835}
1836
1837static inline void cec_msg_cdc_hec_set_state_adjacent(struct cec_msg *msg,
1838 __u16 phys_addr1,
1839 __u8 hec_set_state)
1840{
1841 msg->len = 8;
1842 msg->msg[0] |= 0xf; /* broadcast */
1843 msg->msg[1] = CEC_MSG_CDC_MESSAGE;
1844 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1845 msg->msg[4] = CEC_MSG_CDC_HEC_SET_STATE_ADJACENT;
1846 msg->msg[5] = phys_addr1 >> 8;
1847 msg->msg[6] = phys_addr1 & 0xff;
1848 msg->msg[7] = hec_set_state;
1849}
1850
1851static inline void cec_ops_cdc_hec_set_state_adjacent(const struct cec_msg *msg,
1852 __u16 *phys_addr,
1853 __u16 *phys_addr1,
1854 __u8 *hec_set_state)
1855{
1856 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1857 *phys_addr1 = (msg->msg[5] << 8) | msg->msg[6];
1858 *hec_set_state = msg->msg[7];
1859}
1860
1861static inline void cec_msg_cdc_hec_request_deactivation(struct cec_msg *msg,
1862 __u16 phys_addr1,
1863 __u16 phys_addr2,
1864 __u16 phys_addr3)
1865{
1866 msg->len = 11;
1867 msg->msg[0] |= 0xf; /* broadcast */
1868 msg->msg[1] = CEC_MSG_CDC_MESSAGE;
1869 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1870 msg->msg[4] = CEC_MSG_CDC_HEC_REQUEST_DEACTIVATION;
1871 msg->msg[5] = phys_addr1 >> 8;
1872 msg->msg[6] = phys_addr1 & 0xff;
1873 msg->msg[7] = phys_addr2 >> 8;
1874 msg->msg[8] = phys_addr2 & 0xff;
1875 msg->msg[9] = phys_addr3 >> 8;
1876 msg->msg[10] = phys_addr3 & 0xff;
1877}
1878
1879static inline void cec_ops_cdc_hec_request_deactivation(const struct cec_msg *msg,
1880 __u16 *phys_addr,
1881 __u16 *phys_addr1,
1882 __u16 *phys_addr2,
1883 __u16 *phys_addr3)
1884{
1885 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1886 *phys_addr1 = (msg->msg[5] << 8) | msg->msg[6];
1887 *phys_addr2 = (msg->msg[7] << 8) | msg->msg[8];
1888 *phys_addr3 = (msg->msg[9] << 8) | msg->msg[10];
1889}
1890
1891static inline void cec_msg_cdc_hec_notify_alive(struct cec_msg *msg)
1892{
1893 msg->len = 5;
1894 msg->msg[0] |= 0xf; /* broadcast */
1895 msg->msg[1] = CEC_MSG_CDC_MESSAGE;
1896 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1897 msg->msg[4] = CEC_MSG_CDC_HEC_NOTIFY_ALIVE;
1898}
1899
1900static inline void cec_ops_cdc_hec_notify_alive(const struct cec_msg *msg,
1901 __u16 *phys_addr)
1902{
1903 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1904}
1905
1906static inline void cec_msg_cdc_hec_discover(struct cec_msg *msg)
1907{
1908 msg->len = 5;
1909 msg->msg[0] |= 0xf; /* broadcast */
1910 msg->msg[1] = CEC_MSG_CDC_MESSAGE;
1911 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1912 msg->msg[4] = CEC_MSG_CDC_HEC_DISCOVER;
1913}
1914
1915static inline void cec_ops_cdc_hec_discover(const struct cec_msg *msg,
1916 __u16 *phys_addr)
1917{
1918 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1919}
1920
1921static inline void cec_msg_cdc_hpd_set_state(struct cec_msg *msg,
1922 __u8 input_port,
1923 __u8 hpd_state)
1924{
1925 msg->len = 6;
1926 msg->msg[0] |= 0xf; /* broadcast */
1927 msg->msg[1] = CEC_MSG_CDC_MESSAGE;
1928 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1929 msg->msg[4] = CEC_MSG_CDC_HPD_SET_STATE;
1930 msg->msg[5] = (input_port << 4) | hpd_state;
1931}
1932
1933static inline void cec_ops_cdc_hpd_set_state(const struct cec_msg *msg,
1934 __u16 *phys_addr,
1935 __u8 *input_port,
1936 __u8 *hpd_state)
1937{
1938 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1939 *input_port = msg->msg[5] >> 4;
1940 *hpd_state = msg->msg[5] & 0xf;
1941}
1942
1943static inline void cec_msg_cdc_hpd_report_state(struct cec_msg *msg,
1944 __u8 hpd_state,
1945 __u8 hpd_error)
1946{
1947 msg->len = 6;
1948 msg->msg[0] |= 0xf; /* broadcast */
1949 msg->msg[1] = CEC_MSG_CDC_MESSAGE;
1950 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1951 msg->msg[4] = CEC_MSG_CDC_HPD_REPORT_STATE;
1952 msg->msg[5] = (hpd_state << 4) | hpd_error;
1953}
1954
1955static inline void cec_ops_cdc_hpd_report_state(const struct cec_msg *msg,
1956 __u16 *phys_addr,
1957 __u8 *hpd_state,
1958 __u8 *hpd_error)
1959{
1960 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1961 *hpd_state = msg->msg[5] >> 4;
1962 *hpd_error = msg->msg[5] & 0xf;
1963}
1964
1965#endif
diff --git a/include/uapi/linux/cec.h b/include/uapi/linux/cec.h
new file mode 100644
index 000000000000..f4ec0af67707
--- /dev/null
+++ b/include/uapi/linux/cec.h
@@ -0,0 +1,1065 @@
1/*
2 * cec - HDMI Consumer Electronics Control public header
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 * Alternatively you can redistribute this file under the terms of the
11 * BSD license as stated below:
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in
20 * the documentation and/or other materials provided with the
21 * distribution.
22 * 3. The names of its contributors may not be used to endorse or promote
23 * products derived from this software without specific prior written
24 * permission.
25 *
26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
30 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
31 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
32 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33 * SOFTWARE.
34 */
35
36#ifndef _CEC_UAPI_H
37#define _CEC_UAPI_H
38
39#include <linux/types.h>
40
41#define CEC_MAX_MSG_SIZE 16
42
43/**
44 * struct cec_msg - CEC message structure.
45 * @tx_ts: Timestamp in nanoseconds using CLOCK_MONOTONIC. Set by the
46 * driver when the message transmission has finished.
47 * @rx_ts: Timestamp in nanoseconds using CLOCK_MONOTONIC. Set by the
48 * driver when the message was received.
49 * @len: Length in bytes of the message.
50 * @timeout: The timeout (in ms) that is used to timeout CEC_RECEIVE.
51 * Set to 0 if you want to wait forever. This timeout can also be
52 * used with CEC_TRANSMIT as the timeout for waiting for a reply.
53 * If 0, then it will use a 1 second timeout instead of waiting
54 * forever as is done with CEC_RECEIVE.
55 * @sequence: The framework assigns a sequence number to messages that are
56 * sent. This can be used to track replies to previously sent
57 * messages.
58 * @flags: Set to 0.
59 * @msg: The message payload.
60 * @reply: This field is ignored with CEC_RECEIVE and is only used by
61 * CEC_TRANSMIT. If non-zero, then wait for a reply with this
62 * opcode. Set to CEC_MSG_FEATURE_ABORT if you want to wait for
63 * a possible ABORT reply. If there was an error when sending the
64 * msg or FeatureAbort was returned, then reply is set to 0.
65 * If reply is non-zero upon return, then len/msg are set to
66 * the received message.
67 * If reply is zero upon return and status has the
68 * CEC_TX_STATUS_FEATURE_ABORT bit set, then len/msg are set to
69 * the received feature abort message.
70 * If reply is zero upon return and status has the
71 * CEC_TX_STATUS_MAX_RETRIES bit set, then no reply was seen at
72 * all. If reply is non-zero for CEC_TRANSMIT and the message is a
73 * broadcast, then -EINVAL is returned.
74 * if reply is non-zero, then timeout is set to 1000 (the required
75 * maximum response time).
76 * @rx_status: The message receive status bits. Set by the driver.
77 * @tx_status: The message transmit status bits. Set by the driver.
78 * @tx_arb_lost_cnt: The number of 'Arbitration Lost' events. Set by the driver.
79 * @tx_nack_cnt: The number of 'Not Acknowledged' events. Set by the driver.
80 * @tx_low_drive_cnt: The number of 'Low Drive Detected' events. Set by the
81 * driver.
82 * @tx_error_cnt: The number of 'Error' events. Set by the driver.
83 */
84struct cec_msg {
85 __u64 tx_ts;
86 __u64 rx_ts;
87 __u32 len;
88 __u32 timeout;
89 __u32 sequence;
90 __u32 flags;
91 __u8 msg[CEC_MAX_MSG_SIZE];
92 __u8 reply;
93 __u8 rx_status;
94 __u8 tx_status;
95 __u8 tx_arb_lost_cnt;
96 __u8 tx_nack_cnt;
97 __u8 tx_low_drive_cnt;
98 __u8 tx_error_cnt;
99};
100
101/**
102 * cec_msg_initiator - return the initiator's logical address.
103 * @msg: the message structure
104 */
105static inline __u8 cec_msg_initiator(const struct cec_msg *msg)
106{
107 return msg->msg[0] >> 4;
108}
109
110/**
111 * cec_msg_destination - return the destination's logical address.
112 * @msg: the message structure
113 */
114static inline __u8 cec_msg_destination(const struct cec_msg *msg)
115{
116 return msg->msg[0] & 0xf;
117}
118
119/**
120 * cec_msg_opcode - return the opcode of the message, -1 for poll
121 * @msg: the message structure
122 */
123static inline int cec_msg_opcode(const struct cec_msg *msg)
124{
125 return msg->len > 1 ? msg->msg[1] : -1;
126}
127
128/**
129 * cec_msg_is_broadcast - return true if this is a broadcast message.
130 * @msg: the message structure
131 */
132static inline bool cec_msg_is_broadcast(const struct cec_msg *msg)
133{
134 return (msg->msg[0] & 0xf) == 0xf;
135}
136
137/**
138 * cec_msg_init - initialize the message structure.
139 * @msg: the message structure
140 * @initiator: the logical address of the initiator
141 * @destination:the logical address of the destination (0xf for broadcast)
142 *
143 * The whole structure is zeroed, the len field is set to 1 (i.e. a poll
144 * message) and the initiator and destination are filled in.
145 */
146static inline void cec_msg_init(struct cec_msg *msg,
147 __u8 initiator, __u8 destination)
148{
149 memset(msg, 0, sizeof(*msg));
150 msg->msg[0] = (initiator << 4) | destination;
151 msg->len = 1;
152}
153
154/**
155 * cec_msg_set_reply_to - fill in destination/initiator in a reply message.
156 * @msg: the message structure for the reply
157 * @orig: the original message structure
158 *
159 * Set the msg destination to the orig initiator and the msg initiator to the
160 * orig destination. Note that msg and orig may be the same pointer, in which
161 * case the change is done in place.
162 */
163static inline void cec_msg_set_reply_to(struct cec_msg *msg,
164 struct cec_msg *orig)
165{
166 /* The destination becomes the initiator and vice versa */
167 msg->msg[0] = (cec_msg_destination(orig) << 4) |
168 cec_msg_initiator(orig);
169 msg->reply = msg->timeout = 0;
170}
171
172/* cec_msg flags field */
173#define CEC_MSG_FL_REPLY_TO_FOLLOWERS (1 << 0)
174
175/* cec_msg tx/rx_status field */
176#define CEC_TX_STATUS_OK (1 << 0)
177#define CEC_TX_STATUS_ARB_LOST (1 << 1)
178#define CEC_TX_STATUS_NACK (1 << 2)
179#define CEC_TX_STATUS_LOW_DRIVE (1 << 3)
180#define CEC_TX_STATUS_ERROR (1 << 4)
181#define CEC_TX_STATUS_MAX_RETRIES (1 << 5)
182
183#define CEC_RX_STATUS_OK (1 << 0)
184#define CEC_RX_STATUS_TIMEOUT (1 << 1)
185#define CEC_RX_STATUS_FEATURE_ABORT (1 << 2)
186
187static inline bool cec_msg_status_is_ok(const struct cec_msg *msg)
188{
189 if (msg->tx_status && !(msg->tx_status & CEC_TX_STATUS_OK))
190 return false;
191 if (msg->rx_status && !(msg->rx_status & CEC_RX_STATUS_OK))
192 return false;
193 if (!msg->tx_status && !msg->rx_status)
194 return false;
195 return !(msg->rx_status & CEC_RX_STATUS_FEATURE_ABORT);
196}
197
198#define CEC_LOG_ADDR_INVALID 0xff
199#define CEC_PHYS_ADDR_INVALID 0xffff
200
201/*
202 * The maximum number of logical addresses one device can be assigned to.
203 * The CEC 2.0 spec allows for only 2 logical addresses at the moment. The
204 * Analog Devices CEC hardware supports 3. So let's go wild and go for 4.
205 */
206#define CEC_MAX_LOG_ADDRS 4
207
208/* The logical addresses defined by CEC 2.0 */
209#define CEC_LOG_ADDR_TV 0
210#define CEC_LOG_ADDR_RECORD_1 1
211#define CEC_LOG_ADDR_RECORD_2 2
212#define CEC_LOG_ADDR_TUNER_1 3
213#define CEC_LOG_ADDR_PLAYBACK_1 4
214#define CEC_LOG_ADDR_AUDIOSYSTEM 5
215#define CEC_LOG_ADDR_TUNER_2 6
216#define CEC_LOG_ADDR_TUNER_3 7
217#define CEC_LOG_ADDR_PLAYBACK_2 8
218#define CEC_LOG_ADDR_RECORD_3 9
219#define CEC_LOG_ADDR_TUNER_4 10
220#define CEC_LOG_ADDR_PLAYBACK_3 11
221#define CEC_LOG_ADDR_BACKUP_1 12
222#define CEC_LOG_ADDR_BACKUP_2 13
223#define CEC_LOG_ADDR_SPECIFIC 14
224#define CEC_LOG_ADDR_UNREGISTERED 15 /* as initiator address */
225#define CEC_LOG_ADDR_BROADCAST 15 /* ad destination address */
226
227/* The logical address types that the CEC device wants to claim */
228#define CEC_LOG_ADDR_TYPE_TV 0
229#define CEC_LOG_ADDR_TYPE_RECORD 1
230#define CEC_LOG_ADDR_TYPE_TUNER 2
231#define CEC_LOG_ADDR_TYPE_PLAYBACK 3
232#define CEC_LOG_ADDR_TYPE_AUDIOSYSTEM 4
233#define CEC_LOG_ADDR_TYPE_SPECIFIC 5
234#define CEC_LOG_ADDR_TYPE_UNREGISTERED 6
235/*
236 * Switches should use UNREGISTERED.
237 * Processors should use SPECIFIC.
238 */
239
240#define CEC_LOG_ADDR_MASK_TV (1 << CEC_LOG_ADDR_TV)
241#define CEC_LOG_ADDR_MASK_RECORD ((1 << CEC_LOG_ADDR_RECORD_1) | \
242 (1 << CEC_LOG_ADDR_RECORD_2) | \
243 (1 << CEC_LOG_ADDR_RECORD_3))
244#define CEC_LOG_ADDR_MASK_TUNER ((1 << CEC_LOG_ADDR_TUNER_1) | \
245 (1 << CEC_LOG_ADDR_TUNER_2) | \
246 (1 << CEC_LOG_ADDR_TUNER_3) | \
247 (1 << CEC_LOG_ADDR_TUNER_4))
248#define CEC_LOG_ADDR_MASK_PLAYBACK ((1 << CEC_LOG_ADDR_PLAYBACK_1) | \
249 (1 << CEC_LOG_ADDR_PLAYBACK_2) | \
250 (1 << CEC_LOG_ADDR_PLAYBACK_3))
251#define CEC_LOG_ADDR_MASK_AUDIOSYSTEM (1 << CEC_LOG_ADDR_AUDIOSYSTEM)
252#define CEC_LOG_ADDR_MASK_BACKUP ((1 << CEC_LOG_ADDR_BACKUP_1) | \
253 (1 << CEC_LOG_ADDR_BACKUP_2))
254#define CEC_LOG_ADDR_MASK_SPECIFIC (1 << CEC_LOG_ADDR_SPECIFIC)
255#define CEC_LOG_ADDR_MASK_UNREGISTERED (1 << CEC_LOG_ADDR_UNREGISTERED)
256
257static inline bool cec_has_tv(__u16 log_addr_mask)
258{
259 return log_addr_mask & CEC_LOG_ADDR_MASK_TV;
260}
261
262static inline bool cec_has_record(__u16 log_addr_mask)
263{
264 return log_addr_mask & CEC_LOG_ADDR_MASK_RECORD;
265}
266
267static inline bool cec_has_tuner(__u16 log_addr_mask)
268{
269 return log_addr_mask & CEC_LOG_ADDR_MASK_TUNER;
270}
271
272static inline bool cec_has_playback(__u16 log_addr_mask)
273{
274 return log_addr_mask & CEC_LOG_ADDR_MASK_PLAYBACK;
275}
276
277static inline bool cec_has_audiosystem(__u16 log_addr_mask)
278{
279 return log_addr_mask & CEC_LOG_ADDR_MASK_AUDIOSYSTEM;
280}
281
282static inline bool cec_has_backup(__u16 log_addr_mask)
283{
284 return log_addr_mask & CEC_LOG_ADDR_MASK_BACKUP;
285}
286
287static inline bool cec_has_specific(__u16 log_addr_mask)
288{
289 return log_addr_mask & CEC_LOG_ADDR_MASK_SPECIFIC;
290}
291
292static inline bool cec_is_unregistered(__u16 log_addr_mask)
293{
294 return log_addr_mask & CEC_LOG_ADDR_MASK_UNREGISTERED;
295}
296
297static inline bool cec_is_unconfigured(__u16 log_addr_mask)
298{
299 return log_addr_mask == 0;
300}
301
302/*
303 * Use this if there is no vendor ID (CEC_G_VENDOR_ID) or if the vendor ID
304 * should be disabled (CEC_S_VENDOR_ID)
305 */
306#define CEC_VENDOR_ID_NONE 0xffffffff
307
308/* The message handling modes */
309/* Modes for initiator */
310#define CEC_MODE_NO_INITIATOR (0x0 << 0)
311#define CEC_MODE_INITIATOR (0x1 << 0)
312#define CEC_MODE_EXCL_INITIATOR (0x2 << 0)
313#define CEC_MODE_INITIATOR_MSK 0x0f
314
315/* Modes for follower */
316#define CEC_MODE_NO_FOLLOWER (0x0 << 4)
317#define CEC_MODE_FOLLOWER (0x1 << 4)
318#define CEC_MODE_EXCL_FOLLOWER (0x2 << 4)
319#define CEC_MODE_EXCL_FOLLOWER_PASSTHRU (0x3 << 4)
320#define CEC_MODE_MONITOR (0xe << 4)
321#define CEC_MODE_MONITOR_ALL (0xf << 4)
322#define CEC_MODE_FOLLOWER_MSK 0xf0
323
324/* Userspace has to configure the physical address */
325#define CEC_CAP_PHYS_ADDR (1 << 0)
326/* Userspace has to configure the logical addresses */
327#define CEC_CAP_LOG_ADDRS (1 << 1)
328/* Userspace can transmit messages (and thus become follower as well) */
329#define CEC_CAP_TRANSMIT (1 << 2)
330/*
331 * Passthrough all messages instead of processing them.
332 */
333#define CEC_CAP_PASSTHROUGH (1 << 3)
334/* Supports remote control */
335#define CEC_CAP_RC (1 << 4)
336/* Hardware can monitor all messages, not just directed and broadcast. */
337#define CEC_CAP_MONITOR_ALL (1 << 5)
338
339/**
340 * struct cec_caps - CEC capabilities structure.
341 * @driver: name of the CEC device driver.
342 * @name: name of the CEC device. @driver + @name must be unique.
343 * @available_log_addrs: number of available logical addresses.
344 * @capabilities: capabilities of the CEC adapter.
345 * @version: version of the CEC adapter framework.
346 */
347struct cec_caps {
348 char driver[32];
349 char name[32];
350 __u32 available_log_addrs;
351 __u32 capabilities;
352 __u32 version;
353};
354
355/**
356 * struct cec_log_addrs - CEC logical addresses structure.
357 * @log_addr: the claimed logical addresses. Set by the driver.
358 * @log_addr_mask: current logical address mask. Set by the driver.
359 * @cec_version: the CEC version that the adapter should implement. Set by the
360 * caller.
361 * @num_log_addrs: how many logical addresses should be claimed. Set by the
362 * caller.
363 * @vendor_id: the vendor ID of the device. Set by the caller.
364 * @flags: flags.
365 * @osd_name: the OSD name of the device. Set by the caller.
366 * @primary_device_type: the primary device type for each logical address.
367 * Set by the caller.
368 * @log_addr_type: the logical address types. Set by the caller.
369 * @all_device_types: CEC 2.0: all device types represented by the logical
370 * address. Set by the caller.
371 * @features: CEC 2.0: The logical address features. Set by the caller.
372 */
373struct cec_log_addrs {
374 __u8 log_addr[CEC_MAX_LOG_ADDRS];
375 __u16 log_addr_mask;
376 __u8 cec_version;
377 __u8 num_log_addrs;
378 __u32 vendor_id;
379 __u32 flags;
380 char osd_name[15];
381 __u8 primary_device_type[CEC_MAX_LOG_ADDRS];
382 __u8 log_addr_type[CEC_MAX_LOG_ADDRS];
383
384 /* CEC 2.0 */
385 __u8 all_device_types[CEC_MAX_LOG_ADDRS];
386 __u8 features[CEC_MAX_LOG_ADDRS][12];
387};
388
389/* Allow a fallback to unregistered */
390#define CEC_LOG_ADDRS_FL_ALLOW_UNREG_FALLBACK (1 << 0)
391/* Passthrough RC messages to the input subsystem */
392#define CEC_LOG_ADDRS_FL_ALLOW_RC_PASSTHRU (1 << 1)
393/* CDC-Only device: supports only CDC messages */
394#define CEC_LOG_ADDRS_FL_CDC_ONLY (1 << 2)
395
396/* Events */
397
398/* Event that occurs when the adapter state changes */
399#define CEC_EVENT_STATE_CHANGE 1
400/*
401 * This event is sent when messages are lost because the application
402 * didn't empty the message queue in time
403 */
404#define CEC_EVENT_LOST_MSGS 2
405
406#define CEC_EVENT_FL_INITIAL_STATE (1 << 0)
407
408/**
409 * struct cec_event_state_change - used when the CEC adapter changes state.
410 * @phys_addr: the current physical address
411 * @log_addr_mask: the current logical address mask
412 */
413struct cec_event_state_change {
414 __u16 phys_addr;
415 __u16 log_addr_mask;
416};
417
418/**
419 * struct cec_event_lost_msgs - tells you how many messages were lost due.
420 * @lost_msgs: how many messages were lost.
421 */
422struct cec_event_lost_msgs {
423 __u32 lost_msgs;
424};
425
426/**
427 * struct cec_event - CEC event structure
428 * @ts: the timestamp of when the event was sent.
429 * @event: the event.
430 * array.
431 * @state_change: the event payload for CEC_EVENT_STATE_CHANGE.
432 * @lost_msgs: the event payload for CEC_EVENT_LOST_MSGS.
433 * @raw: array to pad the union.
434 */
435struct cec_event {
436 __u64 ts;
437 __u32 event;
438 __u32 flags;
439 union {
440 struct cec_event_state_change state_change;
441 struct cec_event_lost_msgs lost_msgs;
442 __u32 raw[16];
443 };
444};
445
446/* ioctls */
447
448/* Adapter capabilities */
449#define CEC_ADAP_G_CAPS _IOWR('a', 0, struct cec_caps)
450
451/*
452 * phys_addr is either 0 (if this is the CEC root device)
453 * or a valid physical address obtained from the sink's EDID
454 * as read by this CEC device (if this is a source device)
455 * or a physical address obtained and modified from a sink
456 * EDID and used for a sink CEC device.
457 * If nothing is connected, then phys_addr is 0xffff.
458 * See HDMI 1.4b, section 8.7 (Physical Address).
459 *
460 * The CEC_ADAP_S_PHYS_ADDR ioctl may not be available if that is handled
461 * internally.
462 */
463#define CEC_ADAP_G_PHYS_ADDR _IOR('a', 1, __u16)
464#define CEC_ADAP_S_PHYS_ADDR _IOW('a', 2, __u16)
465
466/*
467 * Configure the CEC adapter. It sets the device type and which
468 * logical types it will try to claim. It will return which
469 * logical addresses it could actually claim.
470 * An error is returned if the adapter is disabled or if there
471 * is no physical address assigned.
472 */
473
474#define CEC_ADAP_G_LOG_ADDRS _IOR('a', 3, struct cec_log_addrs)
475#define CEC_ADAP_S_LOG_ADDRS _IOWR('a', 4, struct cec_log_addrs)
476
477/* Transmit/receive a CEC command */
478#define CEC_TRANSMIT _IOWR('a', 5, struct cec_msg)
479#define CEC_RECEIVE _IOWR('a', 6, struct cec_msg)
480
481/* Dequeue CEC events */
482#define CEC_DQEVENT _IOWR('a', 7, struct cec_event)
483
484/*
485 * Get and set the message handling mode for this filehandle.
486 */
487#define CEC_G_MODE _IOR('a', 8, __u32)
488#define CEC_S_MODE _IOW('a', 9, __u32)
489
490/*
491 * The remainder of this header defines all CEC messages and operands.
492 * The format matters since it the cec-ctl utility parses it to generate
493 * code for implementing all these messages.
494 *
495 * Comments ending with 'Feature' group messages for each feature.
496 * If messages are part of multiple features, then the "Has also"
497 * comment is used to list the previously defined messages that are
498 * supported by the feature.
499 *
500 * Before operands are defined a comment is added that gives the
501 * name of the operand and in brackets the variable name of the
502 * corresponding argument in the cec-funcs.h function.
503 */
504
505/* Messages */
506
507/* One Touch Play Feature */
508#define CEC_MSG_ACTIVE_SOURCE 0x82
509#define CEC_MSG_IMAGE_VIEW_ON 0x04
510#define CEC_MSG_TEXT_VIEW_ON 0x0d
511
512
513/* Routing Control Feature */
514
515/*
516 * Has also:
517 * CEC_MSG_ACTIVE_SOURCE
518 */
519
520#define CEC_MSG_INACTIVE_SOURCE 0x9d
521#define CEC_MSG_REQUEST_ACTIVE_SOURCE 0x85
522#define CEC_MSG_ROUTING_CHANGE 0x80
523#define CEC_MSG_ROUTING_INFORMATION 0x81
524#define CEC_MSG_SET_STREAM_PATH 0x86
525
526
527/* Standby Feature */
528#define CEC_MSG_STANDBY 0x36
529
530
531/* One Touch Record Feature */
532#define CEC_MSG_RECORD_OFF 0x0b
533#define CEC_MSG_RECORD_ON 0x09
534/* Record Source Type Operand (rec_src_type) */
535#define CEC_OP_RECORD_SRC_OWN 1
536#define CEC_OP_RECORD_SRC_DIGITAL 2
537#define CEC_OP_RECORD_SRC_ANALOG 3
538#define CEC_OP_RECORD_SRC_EXT_PLUG 4
539#define CEC_OP_RECORD_SRC_EXT_PHYS_ADDR 5
540/* Service Identification Method Operand (service_id_method) */
541#define CEC_OP_SERVICE_ID_METHOD_BY_DIG_ID 0
542#define CEC_OP_SERVICE_ID_METHOD_BY_CHANNEL 1
543/* Digital Service Broadcast System Operand (dig_bcast_system) */
544#define CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_GEN 0x00
545#define CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_GEN 0x01
546#define CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_GEN 0x02
547#define CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_BS 0x08
548#define CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_CS 0x09
549#define CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_T 0x0a
550#define CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_CABLE 0x10
551#define CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_SAT 0x11
552#define CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_T 0x12
553#define CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_C 0x18
554#define CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_S 0x19
555#define CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_S2 0x1a
556#define CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_T 0x1b
557/* Analogue Broadcast Type Operand (ana_bcast_type) */
558#define CEC_OP_ANA_BCAST_TYPE_CABLE 0
559#define CEC_OP_ANA_BCAST_TYPE_SATELLITE 1
560#define CEC_OP_ANA_BCAST_TYPE_TERRESTRIAL 2
561/* Broadcast System Operand (bcast_system) */
562#define CEC_OP_BCAST_SYSTEM_PAL_BG 0x00
563#define CEC_OP_BCAST_SYSTEM_SECAM_LQ 0x01 /* SECAM L' */
564#define CEC_OP_BCAST_SYSTEM_PAL_M 0x02
565#define CEC_OP_BCAST_SYSTEM_NTSC_M 0x03
566#define CEC_OP_BCAST_SYSTEM_PAL_I 0x04
567#define CEC_OP_BCAST_SYSTEM_SECAM_DK 0x05
568#define CEC_OP_BCAST_SYSTEM_SECAM_BG 0x06
569#define CEC_OP_BCAST_SYSTEM_SECAM_L 0x07
570#define CEC_OP_BCAST_SYSTEM_PAL_DK 0x08
571#define CEC_OP_BCAST_SYSTEM_OTHER 0x1f
572/* Channel Number Format Operand (channel_number_fmt) */
573#define CEC_OP_CHANNEL_NUMBER_FMT_1_PART 0x01
574#define CEC_OP_CHANNEL_NUMBER_FMT_2_PART 0x02
575
576#define CEC_MSG_RECORD_STATUS 0x0a
577/* Record Status Operand (rec_status) */
578#define CEC_OP_RECORD_STATUS_CUR_SRC 0x01
579#define CEC_OP_RECORD_STATUS_DIG_SERVICE 0x02
580#define CEC_OP_RECORD_STATUS_ANA_SERVICE 0x03
581#define CEC_OP_RECORD_STATUS_EXT_INPUT 0x04
582#define CEC_OP_RECORD_STATUS_NO_DIG_SERVICE 0x05
583#define CEC_OP_RECORD_STATUS_NO_ANA_SERVICE 0x06
584#define CEC_OP_RECORD_STATUS_NO_SERVICE 0x07
585#define CEC_OP_RECORD_STATUS_INVALID_EXT_PLUG 0x09
586#define CEC_OP_RECORD_STATUS_INVALID_EXT_PHYS_ADDR 0x0a
587#define CEC_OP_RECORD_STATUS_UNSUP_CA 0x0b
588#define CEC_OP_RECORD_STATUS_NO_CA_ENTITLEMENTS 0x0c
589#define CEC_OP_RECORD_STATUS_CANT_COPY_SRC 0x0d
590#define CEC_OP_RECORD_STATUS_NO_MORE_COPIES 0x0e
591#define CEC_OP_RECORD_STATUS_NO_MEDIA 0x10
592#define CEC_OP_RECORD_STATUS_PLAYING 0x11
593#define CEC_OP_RECORD_STATUS_ALREADY_RECORDING 0x12
594#define CEC_OP_RECORD_STATUS_MEDIA_PROT 0x13
595#define CEC_OP_RECORD_STATUS_NO_SIGNAL 0x14
596#define CEC_OP_RECORD_STATUS_MEDIA_PROBLEM 0x15
597#define CEC_OP_RECORD_STATUS_NO_SPACE 0x16
598#define CEC_OP_RECORD_STATUS_PARENTAL_LOCK 0x17
599#define CEC_OP_RECORD_STATUS_TERMINATED_OK 0x1a
600#define CEC_OP_RECORD_STATUS_ALREADY_TERM 0x1b
601#define CEC_OP_RECORD_STATUS_OTHER 0x1f
602
603#define CEC_MSG_RECORD_TV_SCREEN 0x0f
604
605
606/* Timer Programming Feature */
607#define CEC_MSG_CLEAR_ANALOGUE_TIMER 0x33
608/* Recording Sequence Operand (recording_seq) */
609#define CEC_OP_REC_SEQ_SUNDAY 0x01
610#define CEC_OP_REC_SEQ_MONDAY 0x02
611#define CEC_OP_REC_SEQ_TUESDAY 0x04
612#define CEC_OP_REC_SEQ_WEDNESDAY 0x08
613#define CEC_OP_REC_SEQ_THURSDAY 0x10
614#define CEC_OP_REC_SEQ_FRIDAY 0x20
615#define CEC_OP_REC_SEQ_SATERDAY 0x40
616#define CEC_OP_REC_SEQ_ONCE_ONLY 0x00
617
618#define CEC_MSG_CLEAR_DIGITAL_TIMER 0x99
619
620#define CEC_MSG_CLEAR_EXT_TIMER 0xa1
621/* External Source Specifier Operand (ext_src_spec) */
622#define CEC_OP_EXT_SRC_PLUG 0x04
623#define CEC_OP_EXT_SRC_PHYS_ADDR 0x05
624
625#define CEC_MSG_SET_ANALOGUE_TIMER 0x34
626#define CEC_MSG_SET_DIGITAL_TIMER 0x97
627#define CEC_MSG_SET_EXT_TIMER 0xa2
628
629#define CEC_MSG_SET_TIMER_PROGRAM_TITLE 0x67
630#define CEC_MSG_TIMER_CLEARED_STATUS 0x43
631/* Timer Cleared Status Data Operand (timer_cleared_status) */
632#define CEC_OP_TIMER_CLR_STAT_RECORDING 0x00
633#define CEC_OP_TIMER_CLR_STAT_NO_MATCHING 0x01
634#define CEC_OP_TIMER_CLR_STAT_NO_INFO 0x02
635#define CEC_OP_TIMER_CLR_STAT_CLEARED 0x80
636
637#define CEC_MSG_TIMER_STATUS 0x35
638/* Timer Overlap Warning Operand (timer_overlap_warning) */
639#define CEC_OP_TIMER_OVERLAP_WARNING_NO_OVERLAP 0
640#define CEC_OP_TIMER_OVERLAP_WARNING_OVERLAP 1
641/* Media Info Operand (media_info) */
642#define CEC_OP_MEDIA_INFO_UNPROT_MEDIA 0
643#define CEC_OP_MEDIA_INFO_PROT_MEDIA 1
644#define CEC_OP_MEDIA_INFO_NO_MEDIA 2
645/* Programmed Indicator Operand (prog_indicator) */
646#define CEC_OP_PROG_IND_NOT_PROGRAMMED 0
647#define CEC_OP_PROG_IND_PROGRAMMED 1
648/* Programmed Info Operand (prog_info) */
649#define CEC_OP_PROG_INFO_ENOUGH_SPACE 0x08
650#define CEC_OP_PROG_INFO_NOT_ENOUGH_SPACE 0x09
651#define CEC_OP_PROG_INFO_MIGHT_NOT_BE_ENOUGH_SPACE 0x0b
652#define CEC_OP_PROG_INFO_NONE_AVAILABLE 0x0a
653/* Not Programmed Error Info Operand (prog_error) */
654#define CEC_OP_PROG_ERROR_NO_FREE_TIMER 0x01
655#define CEC_OP_PROG_ERROR_DATE_OUT_OF_RANGE 0x02
656#define CEC_OP_PROG_ERROR_REC_SEQ_ERROR 0x03
657#define CEC_OP_PROG_ERROR_INV_EXT_PLUG 0x04
658#define CEC_OP_PROG_ERROR_INV_EXT_PHYS_ADDR 0x05
659#define CEC_OP_PROG_ERROR_CA_UNSUPP 0x06
660#define CEC_OP_PROG_ERROR_INSUF_CA_ENTITLEMENTS 0x07
661#define CEC_OP_PROG_ERROR_RESOLUTION_UNSUPP 0x08
662#define CEC_OP_PROG_ERROR_PARENTAL_LOCK 0x09
663#define CEC_OP_PROG_ERROR_CLOCK_FAILURE 0x0a
664#define CEC_OP_PROG_ERROR_DUPLICATE 0x0e
665
666
667/* System Information Feature */
668#define CEC_MSG_CEC_VERSION 0x9e
669/* CEC Version Operand (cec_version) */
670#define CEC_OP_CEC_VERSION_1_3A 4
671#define CEC_OP_CEC_VERSION_1_4 5
672#define CEC_OP_CEC_VERSION_2_0 6
673
674#define CEC_MSG_GET_CEC_VERSION 0x9f
675#define CEC_MSG_GIVE_PHYSICAL_ADDR 0x83
676#define CEC_MSG_GET_MENU_LANGUAGE 0x91
677#define CEC_MSG_REPORT_PHYSICAL_ADDR 0x84
678/* Primary Device Type Operand (prim_devtype) */
679#define CEC_OP_PRIM_DEVTYPE_TV 0
680#define CEC_OP_PRIM_DEVTYPE_RECORD 1
681#define CEC_OP_PRIM_DEVTYPE_TUNER 3
682#define CEC_OP_PRIM_DEVTYPE_PLAYBACK 4
683#define CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM 5
684#define CEC_OP_PRIM_DEVTYPE_SWITCH 6
685#define CEC_OP_PRIM_DEVTYPE_PROCESSOR 7
686
687#define CEC_MSG_SET_MENU_LANGUAGE 0x32
688#define CEC_MSG_REPORT_FEATURES 0xa6 /* HDMI 2.0 */
689/* All Device Types Operand (all_device_types) */
690#define CEC_OP_ALL_DEVTYPE_TV 0x80
691#define CEC_OP_ALL_DEVTYPE_RECORD 0x40
692#define CEC_OP_ALL_DEVTYPE_TUNER 0x20
693#define CEC_OP_ALL_DEVTYPE_PLAYBACK 0x10
694#define CEC_OP_ALL_DEVTYPE_AUDIOSYSTEM 0x08
695#define CEC_OP_ALL_DEVTYPE_SWITCH 0x04
696/*
697 * And if you wondering what happened to PROCESSOR devices: those should
698 * be mapped to a SWITCH.
699 */
700
701/* Valid for RC Profile and Device Feature operands */
702#define CEC_OP_FEAT_EXT 0x80 /* Extension bit */
703/* RC Profile Operand (rc_profile) */
704#define CEC_OP_FEAT_RC_TV_PROFILE_NONE 0x00
705#define CEC_OP_FEAT_RC_TV_PROFILE_1 0x02
706#define CEC_OP_FEAT_RC_TV_PROFILE_2 0x06
707#define CEC_OP_FEAT_RC_TV_PROFILE_3 0x0a
708#define CEC_OP_FEAT_RC_TV_PROFILE_4 0x0e
709#define CEC_OP_FEAT_RC_SRC_HAS_DEV_ROOT_MENU 0x50
710#define CEC_OP_FEAT_RC_SRC_HAS_DEV_SETUP_MENU 0x48
711#define CEC_OP_FEAT_RC_SRC_HAS_CONTENTS_MENU 0x44
712#define CEC_OP_FEAT_RC_SRC_HAS_MEDIA_TOP_MENU 0x42
713#define CEC_OP_FEAT_RC_SRC_HAS_MEDIA_CONTEXT_MENU 0x41
714/* Device Feature Operand (dev_features) */
715#define CEC_OP_FEAT_DEV_HAS_RECORD_TV_SCREEN 0x40
716#define CEC_OP_FEAT_DEV_HAS_SET_OSD_STRING 0x20
717#define CEC_OP_FEAT_DEV_HAS_DECK_CONTROL 0x10
718#define CEC_OP_FEAT_DEV_HAS_SET_AUDIO_RATE 0x08
719#define CEC_OP_FEAT_DEV_SINK_HAS_ARC_TX 0x04
720#define CEC_OP_FEAT_DEV_SOURCE_HAS_ARC_RX 0x02
721
722#define CEC_MSG_GIVE_FEATURES 0xa5 /* HDMI 2.0 */
723
724
725/* Deck Control Feature */
726#define CEC_MSG_DECK_CONTROL 0x42
727/* Deck Control Mode Operand (deck_control_mode) */
728#define CEC_OP_DECK_CTL_MODE_SKIP_FWD 1
729#define CEC_OP_DECK_CTL_MODE_SKIP_REV 2
730#define CEC_OP_DECK_CTL_MODE_STOP 3
731#define CEC_OP_DECK_CTL_MODE_EJECT 4
732
733#define CEC_MSG_DECK_STATUS 0x1b
734/* Deck Info Operand (deck_info) */
735#define CEC_OP_DECK_INFO_PLAY 0x11
736#define CEC_OP_DECK_INFO_RECORD 0x12
737#define CEC_OP_DECK_INFO_PLAY_REV 0x13
738#define CEC_OP_DECK_INFO_STILL 0x14
739#define CEC_OP_DECK_INFO_SLOW 0x15
740#define CEC_OP_DECK_INFO_SLOW_REV 0x16
741#define CEC_OP_DECK_INFO_FAST_FWD 0x17
742#define CEC_OP_DECK_INFO_FAST_REV 0x18
743#define CEC_OP_DECK_INFO_NO_MEDIA 0x19
744#define CEC_OP_DECK_INFO_STOP 0x1a
745#define CEC_OP_DECK_INFO_SKIP_FWD 0x1b
746#define CEC_OP_DECK_INFO_SKIP_REV 0x1c
747#define CEC_OP_DECK_INFO_INDEX_SEARCH_FWD 0x1d
748#define CEC_OP_DECK_INFO_INDEX_SEARCH_REV 0x1e
749#define CEC_OP_DECK_INFO_OTHER 0x1f
750
751#define CEC_MSG_GIVE_DECK_STATUS 0x1a
752/* Status Request Operand (status_req) */
753#define CEC_OP_STATUS_REQ_ON 1
754#define CEC_OP_STATUS_REQ_OFF 2
755#define CEC_OP_STATUS_REQ_ONCE 3
756
757#define CEC_MSG_PLAY 0x41
758/* Play Mode Operand (play_mode) */
759#define CEC_OP_PLAY_MODE_PLAY_FWD 0x24
760#define CEC_OP_PLAY_MODE_PLAY_REV 0x20
761#define CEC_OP_PLAY_MODE_PLAY_STILL 0x25
762#define CEC_OP_PLAY_MODE_PLAY_FAST_FWD_MIN 0x05
763#define CEC_OP_PLAY_MODE_PLAY_FAST_FWD_MED 0x06
764#define CEC_OP_PLAY_MODE_PLAY_FAST_FWD_MAX 0x07
765#define CEC_OP_PLAY_MODE_PLAY_FAST_REV_MIN 0x09
766#define CEC_OP_PLAY_MODE_PLAY_FAST_REV_MED 0x0a
767#define CEC_OP_PLAY_MODE_PLAY_FAST_REV_MAX 0x0b
768#define CEC_OP_PLAY_MODE_PLAY_SLOW_FWD_MIN 0x15
769#define CEC_OP_PLAY_MODE_PLAY_SLOW_FWD_MED 0x16
770#define CEC_OP_PLAY_MODE_PLAY_SLOW_FWD_MAX 0x17
771#define CEC_OP_PLAY_MODE_PLAY_SLOW_REV_MIN 0x19
772#define CEC_OP_PLAY_MODE_PLAY_SLOW_REV_MED 0x1a
773#define CEC_OP_PLAY_MODE_PLAY_SLOW_REV_MAX 0x1b
774
775
776/* Tuner Control Feature */
777#define CEC_MSG_GIVE_TUNER_DEVICE_STATUS 0x08
778#define CEC_MSG_SELECT_ANALOGUE_SERVICE 0x92
779#define CEC_MSG_SELECT_DIGITAL_SERVICE 0x93
780#define CEC_MSG_TUNER_DEVICE_STATUS 0x07
781/* Recording Flag Operand (rec_flag) */
782#define CEC_OP_REC_FLAG_USED 0
783#define CEC_OP_REC_FLAG_NOT_USED 1
784/* Tuner Display Info Operand (tuner_display_info) */
785#define CEC_OP_TUNER_DISPLAY_INFO_DIGITAL 0
786#define CEC_OP_TUNER_DISPLAY_INFO_NONE 1
787#define CEC_OP_TUNER_DISPLAY_INFO_ANALOGUE 2
788
789#define CEC_MSG_TUNER_STEP_DECREMENT 0x06
790#define CEC_MSG_TUNER_STEP_INCREMENT 0x05
791
792
793/* Vendor Specific Commands Feature */
794
795/*
796 * Has also:
797 * CEC_MSG_CEC_VERSION
798 * CEC_MSG_GET_CEC_VERSION
799 */
800#define CEC_MSG_DEVICE_VENDOR_ID 0x87
801#define CEC_MSG_GIVE_DEVICE_VENDOR_ID 0x8c
802#define CEC_MSG_VENDOR_COMMAND 0x89
803#define CEC_MSG_VENDOR_COMMAND_WITH_ID 0xa0
804#define CEC_MSG_VENDOR_REMOTE_BUTTON_DOWN 0x8a
805#define CEC_MSG_VENDOR_REMOTE_BUTTON_UP 0x8b
806
807
808/* OSD Display Feature */
809#define CEC_MSG_SET_OSD_STRING 0x64
810/* Display Control Operand (disp_ctl) */
811#define CEC_OP_DISP_CTL_DEFAULT 0x00
812#define CEC_OP_DISP_CTL_UNTIL_CLEARED 0x40
813#define CEC_OP_DISP_CTL_CLEAR 0x80
814
815
816/* Device OSD Transfer Feature */
817#define CEC_MSG_GIVE_OSD_NAME 0x46
818#define CEC_MSG_SET_OSD_NAME 0x47
819
820
821/* Device Menu Control Feature */
822#define CEC_MSG_MENU_REQUEST 0x8d
823/* Menu Request Type Operand (menu_req) */
824#define CEC_OP_MENU_REQUEST_ACTIVATE 0x00
825#define CEC_OP_MENU_REQUEST_DEACTIVATE 0x01
826#define CEC_OP_MENU_REQUEST_QUERY 0x02
827
828#define CEC_MSG_MENU_STATUS 0x8e
829/* Menu State Operand (menu_state) */
830#define CEC_OP_MENU_STATE_ACTIVATED 0x00
831#define CEC_OP_MENU_STATE_DEACTIVATED 0x01
832
833#define CEC_MSG_USER_CONTROL_PRESSED 0x44
834/* UI Broadcast Type Operand (ui_bcast_type) */
835#define CEC_OP_UI_BCAST_TYPE_TOGGLE_ALL 0x00
836#define CEC_OP_UI_BCAST_TYPE_TOGGLE_DIG_ANA 0x01
837#define CEC_OP_UI_BCAST_TYPE_ANALOGUE 0x10
838#define CEC_OP_UI_BCAST_TYPE_ANALOGUE_T 0x20
839#define CEC_OP_UI_BCAST_TYPE_ANALOGUE_CABLE 0x30
840#define CEC_OP_UI_BCAST_TYPE_ANALOGUE_SAT 0x40
841#define CEC_OP_UI_BCAST_TYPE_DIGITAL 0x50
842#define CEC_OP_UI_BCAST_TYPE_DIGITAL_T 0x60
843#define CEC_OP_UI_BCAST_TYPE_DIGITAL_CABLE 0x70
844#define CEC_OP_UI_BCAST_TYPE_DIGITAL_SAT 0x80
845#define CEC_OP_UI_BCAST_TYPE_DIGITAL_COM_SAT 0x90
846#define CEC_OP_UI_BCAST_TYPE_DIGITAL_COM_SAT2 0x91
847#define CEC_OP_UI_BCAST_TYPE_IP 0xa0
848/* UI Sound Presentation Control Operand (ui_snd_pres_ctl) */
849#define CEC_OP_UI_SND_PRES_CTL_DUAL_MONO 0x10
850#define CEC_OP_UI_SND_PRES_CTL_KARAOKE 0x20
851#define CEC_OP_UI_SND_PRES_CTL_DOWNMIX 0x80
852#define CEC_OP_UI_SND_PRES_CTL_REVERB 0x90
853#define CEC_OP_UI_SND_PRES_CTL_EQUALIZER 0xa0
854#define CEC_OP_UI_SND_PRES_CTL_BASS_UP 0xb1
855#define CEC_OP_UI_SND_PRES_CTL_BASS_NEUTRAL 0xb2
856#define CEC_OP_UI_SND_PRES_CTL_BASS_DOWN 0xb3
857#define CEC_OP_UI_SND_PRES_CTL_TREBLE_UP 0xc1
858#define CEC_OP_UI_SND_PRES_CTL_TREBLE_NEUTRAL 0xc2
859#define CEC_OP_UI_SND_PRES_CTL_TREBLE_DOWN 0xc3
860
861#define CEC_MSG_USER_CONTROL_RELEASED 0x45
862
863
864/* Remote Control Passthrough Feature */
865
866/*
867 * Has also:
868 * CEC_MSG_USER_CONTROL_PRESSED
869 * CEC_MSG_USER_CONTROL_RELEASED
870 */
871
872
873/* Power Status Feature */
874#define CEC_MSG_GIVE_DEVICE_POWER_STATUS 0x8f
875#define CEC_MSG_REPORT_POWER_STATUS 0x90
876/* Power Status Operand (pwr_state) */
877#define CEC_OP_POWER_STATUS_ON 0
878#define CEC_OP_POWER_STATUS_STANDBY 1
879#define CEC_OP_POWER_STATUS_TO_ON 2
880#define CEC_OP_POWER_STATUS_TO_STANDBY 3
881
882
883/* General Protocol Messages */
884#define CEC_MSG_FEATURE_ABORT 0x00
885/* Abort Reason Operand (reason) */
886#define CEC_OP_ABORT_UNRECOGNIZED_OP 0
887#define CEC_OP_ABORT_INCORRECT_MODE 1
888#define CEC_OP_ABORT_NO_SOURCE 2
889#define CEC_OP_ABORT_INVALID_OP 3
890#define CEC_OP_ABORT_REFUSED 4
891#define CEC_OP_ABORT_UNDETERMINED 5
892
893#define CEC_MSG_ABORT 0xff
894
895
896/* System Audio Control Feature */
897
898/*
899 * Has also:
900 * CEC_MSG_USER_CONTROL_PRESSED
901 * CEC_MSG_USER_CONTROL_RELEASED
902 */
903#define CEC_MSG_GIVE_AUDIO_STATUS 0x71
904#define CEC_MSG_GIVE_SYSTEM_AUDIO_MODE_STATUS 0x7d
905#define CEC_MSG_REPORT_AUDIO_STATUS 0x7a
906/* Audio Mute Status Operand (aud_mute_status) */
907#define CEC_OP_AUD_MUTE_STATUS_OFF 0
908#define CEC_OP_AUD_MUTE_STATUS_ON 1
909
910#define CEC_MSG_REPORT_SHORT_AUDIO_DESCRIPTOR 0xa3
911#define CEC_MSG_REQUEST_SHORT_AUDIO_DESCRIPTOR 0xa4
912#define CEC_MSG_SET_SYSTEM_AUDIO_MODE 0x72
913/* System Audio Status Operand (sys_aud_status) */
914#define CEC_OP_SYS_AUD_STATUS_OFF 0
915#define CEC_OP_SYS_AUD_STATUS_ON 1
916
917#define CEC_MSG_SYSTEM_AUDIO_MODE_REQUEST 0x70
918#define CEC_MSG_SYSTEM_AUDIO_MODE_STATUS 0x7e
919/* Audio Format ID Operand (audio_format_id) */
920#define CEC_OP_AUD_FMT_ID_CEA861 0
921#define CEC_OP_AUD_FMT_ID_CEA861_CXT 1
922
923
924/* Audio Rate Control Feature */
925#define CEC_MSG_SET_AUDIO_RATE 0x9a
926/* Audio Rate Operand (audio_rate) */
927#define CEC_OP_AUD_RATE_OFF 0
928#define CEC_OP_AUD_RATE_WIDE_STD 1
929#define CEC_OP_AUD_RATE_WIDE_FAST 2
930#define CEC_OP_AUD_RATE_WIDE_SLOW 3
931#define CEC_OP_AUD_RATE_NARROW_STD 4
932#define CEC_OP_AUD_RATE_NARROW_FAST 5
933#define CEC_OP_AUD_RATE_NARROW_SLOW 6
934
935
936/* Audio Return Channel Control Feature */
937#define CEC_MSG_INITIATE_ARC 0xc0
938#define CEC_MSG_REPORT_ARC_INITIATED 0xc1
939#define CEC_MSG_REPORT_ARC_TERMINATED 0xc2
940#define CEC_MSG_REQUEST_ARC_INITIATION 0xc3
941#define CEC_MSG_REQUEST_ARC_TERMINATION 0xc4
942#define CEC_MSG_TERMINATE_ARC 0xc5
943
944
945/* Dynamic Audio Lipsync Feature */
946/* Only for CEC 2.0 and up */
947#define CEC_MSG_REQUEST_CURRENT_LATENCY 0xa7
948#define CEC_MSG_REPORT_CURRENT_LATENCY 0xa8
949/* Low Latency Mode Operand (low_latency_mode) */
950#define CEC_OP_LOW_LATENCY_MODE_OFF 0
951#define CEC_OP_LOW_LATENCY_MODE_ON 1
952/* Audio Output Compensated Operand (audio_out_compensated) */
953#define CEC_OP_AUD_OUT_COMPENSATED_NA 0
954#define CEC_OP_AUD_OUT_COMPENSATED_DELAY 1
955#define CEC_OP_AUD_OUT_COMPENSATED_NO_DELAY 2
956#define CEC_OP_AUD_OUT_COMPENSATED_PARTIAL_DELAY 3
957
958
959/* Capability Discovery and Control Feature */
960#define CEC_MSG_CDC_MESSAGE 0xf8
961/* Ethernet-over-HDMI: nobody ever does this... */
962#define CEC_MSG_CDC_HEC_INQUIRE_STATE 0x00
963#define CEC_MSG_CDC_HEC_REPORT_STATE 0x01
964/* HEC Functionality State Operand (hec_func_state) */
965#define CEC_OP_HEC_FUNC_STATE_NOT_SUPPORTED 0
966#define CEC_OP_HEC_FUNC_STATE_INACTIVE 1
967#define CEC_OP_HEC_FUNC_STATE_ACTIVE 2
968#define CEC_OP_HEC_FUNC_STATE_ACTIVATION_FIELD 3
969/* Host Functionality State Operand (host_func_state) */
970#define CEC_OP_HOST_FUNC_STATE_NOT_SUPPORTED 0
971#define CEC_OP_HOST_FUNC_STATE_INACTIVE 1
972#define CEC_OP_HOST_FUNC_STATE_ACTIVE 2
973/* ENC Functionality State Operand (enc_func_state) */
974#define CEC_OP_ENC_FUNC_STATE_EXT_CON_NOT_SUPPORTED 0
975#define CEC_OP_ENC_FUNC_STATE_EXT_CON_INACTIVE 1
976#define CEC_OP_ENC_FUNC_STATE_EXT_CON_ACTIVE 2
977/* CDC Error Code Operand (cdc_errcode) */
978#define CEC_OP_CDC_ERROR_CODE_NONE 0
979#define CEC_OP_CDC_ERROR_CODE_CAP_UNSUPPORTED 1
980#define CEC_OP_CDC_ERROR_CODE_WRONG_STATE 2
981#define CEC_OP_CDC_ERROR_CODE_OTHER 3
982/* HEC Support Operand (hec_support) */
983#define CEC_OP_HEC_SUPPORT_NO 0
984#define CEC_OP_HEC_SUPPORT_YES 1
985/* HEC Activation Operand (hec_activation) */
986#define CEC_OP_HEC_ACTIVATION_ON 0
987#define CEC_OP_HEC_ACTIVATION_OFF 1
988
989#define CEC_MSG_CDC_HEC_SET_STATE_ADJACENT 0x02
990#define CEC_MSG_CDC_HEC_SET_STATE 0x03
991/* HEC Set State Operand (hec_set_state) */
992#define CEC_OP_HEC_SET_STATE_DEACTIVATE 0
993#define CEC_OP_HEC_SET_STATE_ACTIVATE 1
994
995#define CEC_MSG_CDC_HEC_REQUEST_DEACTIVATION 0x04
996#define CEC_MSG_CDC_HEC_NOTIFY_ALIVE 0x05
997#define CEC_MSG_CDC_HEC_DISCOVER 0x06
998/* Hotplug Detect messages */
999#define CEC_MSG_CDC_HPD_SET_STATE 0x10
1000/* HPD State Operand (hpd_state) */
1001#define CEC_OP_HPD_STATE_CP_EDID_DISABLE 0
1002#define CEC_OP_HPD_STATE_CP_EDID_ENABLE 1
1003#define CEC_OP_HPD_STATE_CP_EDID_DISABLE_ENABLE 2
1004#define CEC_OP_HPD_STATE_EDID_DISABLE 3
1005#define CEC_OP_HPD_STATE_EDID_ENABLE 4
1006#define CEC_OP_HPD_STATE_EDID_DISABLE_ENABLE 5
1007#define CEC_MSG_CDC_HPD_REPORT_STATE 0x11
1008/* HPD Error Code Operand (hpd_error) */
1009#define CEC_OP_HPD_ERROR_NONE 0
1010#define CEC_OP_HPD_ERROR_INITIATOR_NOT_CAPABLE 1
1011#define CEC_OP_HPD_ERROR_INITIATOR_WRONG_STATE 2
1012#define CEC_OP_HPD_ERROR_OTHER 3
1013#define CEC_OP_HPD_ERROR_NONE_NO_VIDEO 4
1014
1015/* End of Messages */
1016
1017/* Helper functions to identify the 'special' CEC devices */
1018
1019static inline bool cec_is_2nd_tv(const struct cec_log_addrs *las)
1020{
1021 /*
1022 * It is a second TV if the logical address is 14 or 15 and the
1023 * primary device type is a TV.
1024 */
1025 return las->num_log_addrs &&
1026 las->log_addr[0] >= CEC_LOG_ADDR_SPECIFIC &&
1027 las->primary_device_type[0] == CEC_OP_PRIM_DEVTYPE_TV;
1028}
1029
1030static inline bool cec_is_processor(const struct cec_log_addrs *las)
1031{
1032 /*
1033 * It is a processor if the logical address is 12-15 and the
1034 * primary device type is a Processor.
1035 */
1036 return las->num_log_addrs &&
1037 las->log_addr[0] >= CEC_LOG_ADDR_BACKUP_1 &&
1038 las->primary_device_type[0] == CEC_OP_PRIM_DEVTYPE_PROCESSOR;
1039}
1040
1041static inline bool cec_is_switch(const struct cec_log_addrs *las)
1042{
1043 /*
1044 * It is a switch if the logical address is 15 and the
1045 * primary device type is a Switch and the CDC-Only flag is not set.
1046 */
1047 return las->num_log_addrs == 1 &&
1048 las->log_addr[0] == CEC_LOG_ADDR_UNREGISTERED &&
1049 las->primary_device_type[0] == CEC_OP_PRIM_DEVTYPE_SWITCH &&
1050 !(las->flags & CEC_LOG_ADDRS_FL_CDC_ONLY);
1051}
1052
1053static inline bool cec_is_cdc_only(const struct cec_log_addrs *las)
1054{
1055 /*
1056 * It is a CDC-only device if the logical address is 15 and the
1057 * primary device type is a Switch and the CDC-Only flag is set.
1058 */
1059 return las->num_log_addrs == 1 &&
1060 las->log_addr[0] == CEC_LOG_ADDR_UNREGISTERED &&
1061 las->primary_device_type[0] == CEC_OP_PRIM_DEVTYPE_SWITCH &&
1062 (las->flags & CEC_LOG_ADDRS_FL_CDC_ONLY);
1063}
1064
1065#endif