1 /* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
3 * cec - HDMI Consumer Electronics Control message functions
5 * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
8 #ifndef _CEC_UAPI_FUNCS_H
9 #define _CEC_UAPI_FUNCS_H
11 #include <linux/cec.h>
13 /* One Touch Play Feature */
14 static inline void cec_msg_active_source(struct cec_msg
*msg
, __u16 phys_addr
)
17 msg
->msg
[0] |= 0xf; /* broadcast */
18 msg
->msg
[1] = CEC_MSG_ACTIVE_SOURCE
;
19 msg
->msg
[2] = phys_addr
>> 8;
20 msg
->msg
[3] = phys_addr
& 0xff;
23 static inline void cec_ops_active_source(const struct cec_msg
*msg
,
26 *phys_addr
= (msg
->msg
[2] << 8) | msg
->msg
[3];
29 static inline void cec_msg_image_view_on(struct cec_msg
*msg
)
32 msg
->msg
[1] = CEC_MSG_IMAGE_VIEW_ON
;
35 static inline void cec_msg_text_view_on(struct cec_msg
*msg
)
38 msg
->msg
[1] = CEC_MSG_TEXT_VIEW_ON
;
42 /* Routing Control Feature */
43 static inline void cec_msg_inactive_source(struct cec_msg
*msg
,
47 msg
->msg
[1] = CEC_MSG_INACTIVE_SOURCE
;
48 msg
->msg
[2] = phys_addr
>> 8;
49 msg
->msg
[3] = phys_addr
& 0xff;
52 static inline void cec_ops_inactive_source(const struct cec_msg
*msg
,
55 *phys_addr
= (msg
->msg
[2] << 8) | msg
->msg
[3];
58 static inline void cec_msg_request_active_source(struct cec_msg
*msg
,
62 msg
->msg
[0] |= 0xf; /* broadcast */
63 msg
->msg
[1] = CEC_MSG_REQUEST_ACTIVE_SOURCE
;
64 msg
->reply
= reply
? CEC_MSG_ACTIVE_SOURCE
: 0;
67 static inline void cec_msg_routing_information(struct cec_msg
*msg
,
71 msg
->msg
[0] |= 0xf; /* broadcast */
72 msg
->msg
[1] = CEC_MSG_ROUTING_INFORMATION
;
73 msg
->msg
[2] = phys_addr
>> 8;
74 msg
->msg
[3] = phys_addr
& 0xff;
77 static inline void cec_ops_routing_information(const struct cec_msg
*msg
,
80 *phys_addr
= (msg
->msg
[2] << 8) | msg
->msg
[3];
83 static inline void cec_msg_routing_change(struct cec_msg
*msg
,
89 msg
->msg
[0] |= 0xf; /* broadcast */
90 msg
->msg
[1] = CEC_MSG_ROUTING_CHANGE
;
91 msg
->msg
[2] = orig_phys_addr
>> 8;
92 msg
->msg
[3] = orig_phys_addr
& 0xff;
93 msg
->msg
[4] = new_phys_addr
>> 8;
94 msg
->msg
[5] = new_phys_addr
& 0xff;
95 msg
->reply
= reply
? CEC_MSG_ROUTING_INFORMATION
: 0;
98 static inline void cec_ops_routing_change(const struct cec_msg
*msg
,
99 __u16
*orig_phys_addr
,
100 __u16
*new_phys_addr
)
102 *orig_phys_addr
= (msg
->msg
[2] << 8) | msg
->msg
[3];
103 *new_phys_addr
= (msg
->msg
[4] << 8) | msg
->msg
[5];
106 static inline void cec_msg_set_stream_path(struct cec_msg
*msg
, __u16 phys_addr
)
109 msg
->msg
[0] |= 0xf; /* broadcast */
110 msg
->msg
[1] = CEC_MSG_SET_STREAM_PATH
;
111 msg
->msg
[2] = phys_addr
>> 8;
112 msg
->msg
[3] = phys_addr
& 0xff;
115 static inline void cec_ops_set_stream_path(const struct cec_msg
*msg
,
118 *phys_addr
= (msg
->msg
[2] << 8) | msg
->msg
[3];
122 /* Standby Feature */
123 static inline void cec_msg_standby(struct cec_msg
*msg
)
126 msg
->msg
[1] = CEC_MSG_STANDBY
;
130 /* One Touch Record Feature */
131 static inline void cec_msg_record_off(struct cec_msg
*msg
, int reply
)
134 msg
->msg
[1] = CEC_MSG_RECORD_OFF
;
135 msg
->reply
= reply
? CEC_MSG_RECORD_STATUS
: 0;
138 struct cec_op_arib_data
{
141 __u16 orig_network_id
;
144 struct cec_op_atsc_data
{
146 __u16 program_number
;
149 struct cec_op_dvb_data
{
152 __u16 orig_network_id
;
155 struct cec_op_channel_data
{
156 __u8 channel_number_fmt
;
161 struct cec_op_digital_service_id
{
162 __u8 service_id_method
;
163 __u8 dig_bcast_system
;
165 struct cec_op_arib_data arib
;
166 struct cec_op_atsc_data atsc
;
167 struct cec_op_dvb_data dvb
;
168 struct cec_op_channel_data channel
;
172 struct cec_op_record_src
{
175 struct cec_op_digital_service_id digital
;
190 static inline void cec_set_digital_service_id(__u8
*msg
,
191 const struct cec_op_digital_service_id
*digital
)
193 *msg
++ = (digital
->service_id_method
<< 7) | digital
->dig_bcast_system
;
194 if (digital
->service_id_method
== CEC_OP_SERVICE_ID_METHOD_BY_CHANNEL
) {
195 *msg
++ = (digital
->channel
.channel_number_fmt
<< 2) |
196 (digital
->channel
.major
>> 8);
197 *msg
++ = digital
->channel
.major
& 0xff;
198 *msg
++ = digital
->channel
.minor
>> 8;
199 *msg
++ = digital
->channel
.minor
& 0xff;
204 switch (digital
->dig_bcast_system
) {
205 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_GEN
:
206 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_CABLE
:
207 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_SAT
:
208 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_T
:
209 *msg
++ = digital
->atsc
.transport_id
>> 8;
210 *msg
++ = digital
->atsc
.transport_id
& 0xff;
211 *msg
++ = digital
->atsc
.program_number
>> 8;
212 *msg
++ = digital
->atsc
.program_number
& 0xff;
217 *msg
++ = digital
->dvb
.transport_id
>> 8;
218 *msg
++ = digital
->dvb
.transport_id
& 0xff;
219 *msg
++ = digital
->dvb
.service_id
>> 8;
220 *msg
++ = digital
->dvb
.service_id
& 0xff;
221 *msg
++ = digital
->dvb
.orig_network_id
>> 8;
222 *msg
++ = digital
->dvb
.orig_network_id
& 0xff;
227 static inline void cec_get_digital_service_id(const __u8
*msg
,
228 struct cec_op_digital_service_id
*digital
)
230 digital
->service_id_method
= msg
[0] >> 7;
231 digital
->dig_bcast_system
= msg
[0] & 0x7f;
232 if (digital
->service_id_method
== CEC_OP_SERVICE_ID_METHOD_BY_CHANNEL
) {
233 digital
->channel
.channel_number_fmt
= msg
[1] >> 2;
234 digital
->channel
.major
= ((msg
[1] & 3) << 6) | msg
[2];
235 digital
->channel
.minor
= (msg
[3] << 8) | msg
[4];
238 digital
->dvb
.transport_id
= (msg
[1] << 8) | msg
[2];
239 digital
->dvb
.service_id
= (msg
[3] << 8) | msg
[4];
240 digital
->dvb
.orig_network_id
= (msg
[5] << 8) | msg
[6];
243 static inline void cec_msg_record_on_own(struct cec_msg
*msg
)
246 msg
->msg
[1] = CEC_MSG_RECORD_ON
;
247 msg
->msg
[2] = CEC_OP_RECORD_SRC_OWN
;
250 static inline void cec_msg_record_on_digital(struct cec_msg
*msg
,
251 const struct cec_op_digital_service_id
*digital
)
254 msg
->msg
[1] = CEC_MSG_RECORD_ON
;
255 msg
->msg
[2] = CEC_OP_RECORD_SRC_DIGITAL
;
256 cec_set_digital_service_id(msg
->msg
+ 3, digital
);
259 static inline void cec_msg_record_on_analog(struct cec_msg
*msg
,
265 msg
->msg
[1] = CEC_MSG_RECORD_ON
;
266 msg
->msg
[2] = CEC_OP_RECORD_SRC_ANALOG
;
267 msg
->msg
[3] = ana_bcast_type
;
268 msg
->msg
[4] = ana_freq
>> 8;
269 msg
->msg
[5] = ana_freq
& 0xff;
270 msg
->msg
[6] = bcast_system
;
273 static inline void cec_msg_record_on_plug(struct cec_msg
*msg
,
277 msg
->msg
[1] = CEC_MSG_RECORD_ON
;
278 msg
->msg
[2] = CEC_OP_RECORD_SRC_EXT_PLUG
;
282 static inline void cec_msg_record_on_phys_addr(struct cec_msg
*msg
,
286 msg
->msg
[1] = CEC_MSG_RECORD_ON
;
287 msg
->msg
[2] = CEC_OP_RECORD_SRC_EXT_PHYS_ADDR
;
288 msg
->msg
[3] = phys_addr
>> 8;
289 msg
->msg
[4] = phys_addr
& 0xff;
292 static inline void cec_msg_record_on(struct cec_msg
*msg
,
294 const struct cec_op_record_src
*rec_src
)
296 switch (rec_src
->type
) {
297 case CEC_OP_RECORD_SRC_OWN
:
298 cec_msg_record_on_own(msg
);
300 case CEC_OP_RECORD_SRC_DIGITAL
:
301 cec_msg_record_on_digital(msg
, &rec_src
->digital
);
303 case CEC_OP_RECORD_SRC_ANALOG
:
304 cec_msg_record_on_analog(msg
,
305 rec_src
->analog
.ana_bcast_type
,
306 rec_src
->analog
.ana_freq
,
307 rec_src
->analog
.bcast_system
);
309 case CEC_OP_RECORD_SRC_EXT_PLUG
:
310 cec_msg_record_on_plug(msg
, rec_src
->ext_plug
.plug
);
312 case CEC_OP_RECORD_SRC_EXT_PHYS_ADDR
:
313 cec_msg_record_on_phys_addr(msg
,
314 rec_src
->ext_phys_addr
.phys_addr
);
317 msg
->reply
= reply
? CEC_MSG_RECORD_STATUS
: 0;
320 static inline void cec_ops_record_on(const struct cec_msg
*msg
,
321 struct cec_op_record_src
*rec_src
)
323 rec_src
->type
= msg
->msg
[2];
324 switch (rec_src
->type
) {
325 case CEC_OP_RECORD_SRC_OWN
:
327 case CEC_OP_RECORD_SRC_DIGITAL
:
328 cec_get_digital_service_id(msg
->msg
+ 3, &rec_src
->digital
);
330 case CEC_OP_RECORD_SRC_ANALOG
:
331 rec_src
->analog
.ana_bcast_type
= msg
->msg
[3];
332 rec_src
->analog
.ana_freq
=
333 (msg
->msg
[4] << 8) | msg
->msg
[5];
334 rec_src
->analog
.bcast_system
= msg
->msg
[6];
336 case CEC_OP_RECORD_SRC_EXT_PLUG
:
337 rec_src
->ext_plug
.plug
= msg
->msg
[3];
339 case CEC_OP_RECORD_SRC_EXT_PHYS_ADDR
:
340 rec_src
->ext_phys_addr
.phys_addr
=
341 (msg
->msg
[3] << 8) | msg
->msg
[4];
346 static inline void cec_msg_record_status(struct cec_msg
*msg
, __u8 rec_status
)
349 msg
->msg
[1] = CEC_MSG_RECORD_STATUS
;
350 msg
->msg
[2] = rec_status
;
353 static inline void cec_ops_record_status(const struct cec_msg
*msg
,
356 *rec_status
= msg
->msg
[2];
359 static inline void cec_msg_record_tv_screen(struct cec_msg
*msg
,
363 msg
->msg
[1] = CEC_MSG_RECORD_TV_SCREEN
;
364 msg
->reply
= reply
? CEC_MSG_RECORD_ON
: 0;
368 /* Timer Programming Feature */
369 static inline void cec_msg_timer_status(struct cec_msg
*msg
,
370 __u8 timer_overlap_warning
,
378 msg
->msg
[1] = CEC_MSG_TIMER_STATUS
;
379 msg
->msg
[2] = (timer_overlap_warning
<< 7) |
381 (prog_info
? 0x10 : 0) |
382 (prog_info
? prog_info
: prog_error
);
383 if (prog_info
== CEC_OP_PROG_INFO_NOT_ENOUGH_SPACE
||
384 prog_info
== CEC_OP_PROG_INFO_MIGHT_NOT_BE_ENOUGH_SPACE
||
385 prog_error
== CEC_OP_PROG_ERROR_DUPLICATE
) {
387 msg
->msg
[3] = ((duration_hr
/ 10) << 4) | (duration_hr
% 10);
388 msg
->msg
[4] = ((duration_min
/ 10) << 4) | (duration_min
% 10);
392 static inline void cec_ops_timer_status(const struct cec_msg
*msg
,
393 __u8
*timer_overlap_warning
,
400 *timer_overlap_warning
= msg
->msg
[2] >> 7;
401 *media_info
= (msg
->msg
[2] >> 5) & 3;
402 if (msg
->msg
[2] & 0x10) {
403 *prog_info
= msg
->msg
[2] & 0xf;
407 *prog_error
= msg
->msg
[2] & 0xf;
409 if (*prog_info
== CEC_OP_PROG_INFO_NOT_ENOUGH_SPACE
||
410 *prog_info
== CEC_OP_PROG_INFO_MIGHT_NOT_BE_ENOUGH_SPACE
||
411 *prog_error
== CEC_OP_PROG_ERROR_DUPLICATE
) {
412 *duration_hr
= (msg
->msg
[3] >> 4) * 10 + (msg
->msg
[3] & 0xf);
413 *duration_min
= (msg
->msg
[4] >> 4) * 10 + (msg
->msg
[4] & 0xf);
415 *duration_hr
= *duration_min
= 0;
419 static inline void cec_msg_timer_cleared_status(struct cec_msg
*msg
,
420 __u8 timer_cleared_status
)
423 msg
->msg
[1] = CEC_MSG_TIMER_CLEARED_STATUS
;
424 msg
->msg
[2] = timer_cleared_status
;
427 static inline void cec_ops_timer_cleared_status(const struct cec_msg
*msg
,
428 __u8
*timer_cleared_status
)
430 *timer_cleared_status
= msg
->msg
[2];
433 static inline void cec_msg_clear_analogue_timer(struct cec_msg
*msg
,
447 msg
->msg
[1] = CEC_MSG_CLEAR_ANALOGUE_TIMER
;
450 /* Hours and minutes are in BCD format */
451 msg
->msg
[4] = ((start_hr
/ 10) << 4) | (start_hr
% 10);
452 msg
->msg
[5] = ((start_min
/ 10) << 4) | (start_min
% 10);
453 msg
->msg
[6] = ((duration_hr
/ 10) << 4) | (duration_hr
% 10);
454 msg
->msg
[7] = ((duration_min
/ 10) << 4) | (duration_min
% 10);
455 msg
->msg
[8] = recording_seq
;
456 msg
->msg
[9] = ana_bcast_type
;
457 msg
->msg
[10] = ana_freq
>> 8;
458 msg
->msg
[11] = ana_freq
& 0xff;
459 msg
->msg
[12] = bcast_system
;
460 msg
->reply
= reply
? CEC_MSG_TIMER_CLEARED_STATUS
: 0;
463 static inline void cec_ops_clear_analogue_timer(const struct cec_msg
*msg
,
471 __u8
*ana_bcast_type
,
476 *month
= msg
->msg
[3];
477 /* Hours and minutes are in BCD format */
478 *start_hr
= (msg
->msg
[4] >> 4) * 10 + (msg
->msg
[4] & 0xf);
479 *start_min
= (msg
->msg
[5] >> 4) * 10 + (msg
->msg
[5] & 0xf);
480 *duration_hr
= (msg
->msg
[6] >> 4) * 10 + (msg
->msg
[6] & 0xf);
481 *duration_min
= (msg
->msg
[7] >> 4) * 10 + (msg
->msg
[7] & 0xf);
482 *recording_seq
= msg
->msg
[8];
483 *ana_bcast_type
= msg
->msg
[9];
484 *ana_freq
= (msg
->msg
[10] << 8) | msg
->msg
[11];
485 *bcast_system
= msg
->msg
[12];
488 static inline void cec_msg_clear_digital_timer(struct cec_msg
*msg
,
497 const struct cec_op_digital_service_id
*digital
)
500 msg
->reply
= reply
? CEC_MSG_TIMER_CLEARED_STATUS
: 0;
501 msg
->msg
[1] = CEC_MSG_CLEAR_DIGITAL_TIMER
;
504 /* Hours and minutes are in BCD format */
505 msg
->msg
[4] = ((start_hr
/ 10) << 4) | (start_hr
% 10);
506 msg
->msg
[5] = ((start_min
/ 10) << 4) | (start_min
% 10);
507 msg
->msg
[6] = ((duration_hr
/ 10) << 4) | (duration_hr
% 10);
508 msg
->msg
[7] = ((duration_min
/ 10) << 4) | (duration_min
% 10);
509 msg
->msg
[8] = recording_seq
;
510 cec_set_digital_service_id(msg
->msg
+ 9, digital
);
513 static inline void cec_ops_clear_digital_timer(const struct cec_msg
*msg
,
521 struct cec_op_digital_service_id
*digital
)
524 *month
= msg
->msg
[3];
525 /* Hours and minutes are in BCD format */
526 *start_hr
= (msg
->msg
[4] >> 4) * 10 + (msg
->msg
[4] & 0xf);
527 *start_min
= (msg
->msg
[5] >> 4) * 10 + (msg
->msg
[5] & 0xf);
528 *duration_hr
= (msg
->msg
[6] >> 4) * 10 + (msg
->msg
[6] & 0xf);
529 *duration_min
= (msg
->msg
[7] >> 4) * 10 + (msg
->msg
[7] & 0xf);
530 *recording_seq
= msg
->msg
[8];
531 cec_get_digital_service_id(msg
->msg
+ 9, digital
);
534 static inline void cec_msg_clear_ext_timer(struct cec_msg
*msg
,
548 msg
->msg
[1] = CEC_MSG_CLEAR_EXT_TIMER
;
551 /* Hours and minutes are in BCD format */
552 msg
->msg
[4] = ((start_hr
/ 10) << 4) | (start_hr
% 10);
553 msg
->msg
[5] = ((start_min
/ 10) << 4) | (start_min
% 10);
554 msg
->msg
[6] = ((duration_hr
/ 10) << 4) | (duration_hr
% 10);
555 msg
->msg
[7] = ((duration_min
/ 10) << 4) | (duration_min
% 10);
556 msg
->msg
[8] = recording_seq
;
557 msg
->msg
[9] = ext_src_spec
;
559 msg
->msg
[11] = phys_addr
>> 8;
560 msg
->msg
[12] = phys_addr
& 0xff;
561 msg
->reply
= reply
? CEC_MSG_TIMER_CLEARED_STATUS
: 0;
564 static inline void cec_ops_clear_ext_timer(const struct cec_msg
*msg
,
577 *month
= msg
->msg
[3];
578 /* Hours and minutes are in BCD format */
579 *start_hr
= (msg
->msg
[4] >> 4) * 10 + (msg
->msg
[4] & 0xf);
580 *start_min
= (msg
->msg
[5] >> 4) * 10 + (msg
->msg
[5] & 0xf);
581 *duration_hr
= (msg
->msg
[6] >> 4) * 10 + (msg
->msg
[6] & 0xf);
582 *duration_min
= (msg
->msg
[7] >> 4) * 10 + (msg
->msg
[7] & 0xf);
583 *recording_seq
= msg
->msg
[8];
584 *ext_src_spec
= msg
->msg
[9];
585 *plug
= msg
->msg
[10];
586 *phys_addr
= (msg
->msg
[11] << 8) | msg
->msg
[12];
589 static inline void cec_msg_set_analogue_timer(struct cec_msg
*msg
,
603 msg
->msg
[1] = CEC_MSG_SET_ANALOGUE_TIMER
;
606 /* Hours and minutes are in BCD format */
607 msg
->msg
[4] = ((start_hr
/ 10) << 4) | (start_hr
% 10);
608 msg
->msg
[5] = ((start_min
/ 10) << 4) | (start_min
% 10);
609 msg
->msg
[6] = ((duration_hr
/ 10) << 4) | (duration_hr
% 10);
610 msg
->msg
[7] = ((duration_min
/ 10) << 4) | (duration_min
% 10);
611 msg
->msg
[8] = recording_seq
;
612 msg
->msg
[9] = ana_bcast_type
;
613 msg
->msg
[10] = ana_freq
>> 8;
614 msg
->msg
[11] = ana_freq
& 0xff;
615 msg
->msg
[12] = bcast_system
;
616 msg
->reply
= reply
? CEC_MSG_TIMER_STATUS
: 0;
619 static inline void cec_ops_set_analogue_timer(const struct cec_msg
*msg
,
627 __u8
*ana_bcast_type
,
632 *month
= msg
->msg
[3];
633 /* Hours and minutes are in BCD format */
634 *start_hr
= (msg
->msg
[4] >> 4) * 10 + (msg
->msg
[4] & 0xf);
635 *start_min
= (msg
->msg
[5] >> 4) * 10 + (msg
->msg
[5] & 0xf);
636 *duration_hr
= (msg
->msg
[6] >> 4) * 10 + (msg
->msg
[6] & 0xf);
637 *duration_min
= (msg
->msg
[7] >> 4) * 10 + (msg
->msg
[7] & 0xf);
638 *recording_seq
= msg
->msg
[8];
639 *ana_bcast_type
= msg
->msg
[9];
640 *ana_freq
= (msg
->msg
[10] << 8) | msg
->msg
[11];
641 *bcast_system
= msg
->msg
[12];
644 static inline void cec_msg_set_digital_timer(struct cec_msg
*msg
,
653 const struct cec_op_digital_service_id
*digital
)
656 msg
->reply
= reply
? CEC_MSG_TIMER_STATUS
: 0;
657 msg
->msg
[1] = CEC_MSG_SET_DIGITAL_TIMER
;
660 /* Hours and minutes are in BCD format */
661 msg
->msg
[4] = ((start_hr
/ 10) << 4) | (start_hr
% 10);
662 msg
->msg
[5] = ((start_min
/ 10) << 4) | (start_min
% 10);
663 msg
->msg
[6] = ((duration_hr
/ 10) << 4) | (duration_hr
% 10);
664 msg
->msg
[7] = ((duration_min
/ 10) << 4) | (duration_min
% 10);
665 msg
->msg
[8] = recording_seq
;
666 cec_set_digital_service_id(msg
->msg
+ 9, digital
);
669 static inline void cec_ops_set_digital_timer(const struct cec_msg
*msg
,
677 struct cec_op_digital_service_id
*digital
)
680 *month
= msg
->msg
[3];
681 /* Hours and minutes are in BCD format */
682 *start_hr
= (msg
->msg
[4] >> 4) * 10 + (msg
->msg
[4] & 0xf);
683 *start_min
= (msg
->msg
[5] >> 4) * 10 + (msg
->msg
[5] & 0xf);
684 *duration_hr
= (msg
->msg
[6] >> 4) * 10 + (msg
->msg
[6] & 0xf);
685 *duration_min
= (msg
->msg
[7] >> 4) * 10 + (msg
->msg
[7] & 0xf);
686 *recording_seq
= msg
->msg
[8];
687 cec_get_digital_service_id(msg
->msg
+ 9, digital
);
690 static inline void cec_msg_set_ext_timer(struct cec_msg
*msg
,
704 msg
->msg
[1] = CEC_MSG_SET_EXT_TIMER
;
707 /* Hours and minutes are in BCD format */
708 msg
->msg
[4] = ((start_hr
/ 10) << 4) | (start_hr
% 10);
709 msg
->msg
[5] = ((start_min
/ 10) << 4) | (start_min
% 10);
710 msg
->msg
[6] = ((duration_hr
/ 10) << 4) | (duration_hr
% 10);
711 msg
->msg
[7] = ((duration_min
/ 10) << 4) | (duration_min
% 10);
712 msg
->msg
[8] = recording_seq
;
713 msg
->msg
[9] = ext_src_spec
;
715 msg
->msg
[11] = phys_addr
>> 8;
716 msg
->msg
[12] = phys_addr
& 0xff;
717 msg
->reply
= reply
? CEC_MSG_TIMER_STATUS
: 0;
720 static inline void cec_ops_set_ext_timer(const struct cec_msg
*msg
,
733 *month
= msg
->msg
[3];
734 /* Hours and minutes are in BCD format */
735 *start_hr
= (msg
->msg
[4] >> 4) * 10 + (msg
->msg
[4] & 0xf);
736 *start_min
= (msg
->msg
[5] >> 4) * 10 + (msg
->msg
[5] & 0xf);
737 *duration_hr
= (msg
->msg
[6] >> 4) * 10 + (msg
->msg
[6] & 0xf);
738 *duration_min
= (msg
->msg
[7] >> 4) * 10 + (msg
->msg
[7] & 0xf);
739 *recording_seq
= msg
->msg
[8];
740 *ext_src_spec
= msg
->msg
[9];
741 *plug
= msg
->msg
[10];
742 *phys_addr
= (msg
->msg
[11] << 8) | msg
->msg
[12];
745 static inline void cec_msg_set_timer_program_title(struct cec_msg
*msg
,
746 const char *prog_title
)
748 unsigned int len
= strlen(prog_title
);
753 msg
->msg
[1] = CEC_MSG_SET_TIMER_PROGRAM_TITLE
;
754 memcpy(msg
->msg
+ 2, prog_title
, len
);
757 static inline void cec_ops_set_timer_program_title(const struct cec_msg
*msg
,
760 unsigned int len
= msg
->len
> 2 ? msg
->len
- 2 : 0;
764 memcpy(prog_title
, msg
->msg
+ 2, len
);
765 prog_title
[len
] = '\0';
768 /* System Information Feature */
769 static inline void cec_msg_cec_version(struct cec_msg
*msg
, __u8 cec_version
)
772 msg
->msg
[1] = CEC_MSG_CEC_VERSION
;
773 msg
->msg
[2] = cec_version
;
776 static inline void cec_ops_cec_version(const struct cec_msg
*msg
,
779 *cec_version
= msg
->msg
[2];
782 static inline void cec_msg_get_cec_version(struct cec_msg
*msg
,
786 msg
->msg
[1] = CEC_MSG_GET_CEC_VERSION
;
787 msg
->reply
= reply
? CEC_MSG_CEC_VERSION
: 0;
790 static inline void cec_msg_report_physical_addr(struct cec_msg
*msg
,
791 __u16 phys_addr
, __u8 prim_devtype
)
794 msg
->msg
[0] |= 0xf; /* broadcast */
795 msg
->msg
[1] = CEC_MSG_REPORT_PHYSICAL_ADDR
;
796 msg
->msg
[2] = phys_addr
>> 8;
797 msg
->msg
[3] = phys_addr
& 0xff;
798 msg
->msg
[4] = prim_devtype
;
801 static inline void cec_ops_report_physical_addr(const struct cec_msg
*msg
,
802 __u16
*phys_addr
, __u8
*prim_devtype
)
804 *phys_addr
= (msg
->msg
[2] << 8) | msg
->msg
[3];
805 *prim_devtype
= msg
->msg
[4];
808 static inline void cec_msg_give_physical_addr(struct cec_msg
*msg
,
812 msg
->msg
[1] = CEC_MSG_GIVE_PHYSICAL_ADDR
;
813 msg
->reply
= reply
? CEC_MSG_REPORT_PHYSICAL_ADDR
: 0;
816 static inline void cec_msg_set_menu_language(struct cec_msg
*msg
,
817 const char *language
)
820 msg
->msg
[0] |= 0xf; /* broadcast */
821 msg
->msg
[1] = CEC_MSG_SET_MENU_LANGUAGE
;
822 memcpy(msg
->msg
+ 2, language
, 3);
825 static inline void cec_ops_set_menu_language(const struct cec_msg
*msg
,
828 memcpy(language
, msg
->msg
+ 2, 3);
832 static inline void cec_msg_get_menu_language(struct cec_msg
*msg
,
836 msg
->msg
[1] = CEC_MSG_GET_MENU_LANGUAGE
;
837 msg
->reply
= reply
? CEC_MSG_SET_MENU_LANGUAGE
: 0;
841 * Assumes a single RC Profile byte and a single Device Features byte,
842 * i.e. no extended features are supported by this helper function.
844 * As of CEC 2.0 no extended features are defined, should those be added
845 * in the future, then this function needs to be adapted or a new function
848 static inline void cec_msg_report_features(struct cec_msg
*msg
,
849 __u8 cec_version
, __u8 all_device_types
,
850 __u8 rc_profile
, __u8 dev_features
)
853 msg
->msg
[0] |= 0xf; /* broadcast */
854 msg
->msg
[1] = CEC_MSG_REPORT_FEATURES
;
855 msg
->msg
[2] = cec_version
;
856 msg
->msg
[3] = all_device_types
;
857 msg
->msg
[4] = rc_profile
;
858 msg
->msg
[5] = dev_features
;
861 static inline void cec_ops_report_features(const struct cec_msg
*msg
,
862 __u8
*cec_version
, __u8
*all_device_types
,
863 const __u8
**rc_profile
, const __u8
**dev_features
)
865 const __u8
*p
= &msg
->msg
[4];
867 *cec_version
= msg
->msg
[2];
868 *all_device_types
= msg
->msg
[3];
870 *dev_features
= NULL
;
871 while (p
< &msg
->msg
[14] && (*p
& CEC_OP_FEAT_EXT
))
873 if (!(*p
& CEC_OP_FEAT_EXT
)) {
874 *dev_features
= p
+ 1;
875 while (p
< &msg
->msg
[15] && (*p
& CEC_OP_FEAT_EXT
))
878 if (*p
& CEC_OP_FEAT_EXT
)
879 *rc_profile
= *dev_features
= NULL
;
882 static inline void cec_msg_give_features(struct cec_msg
*msg
,
886 msg
->msg
[1] = CEC_MSG_GIVE_FEATURES
;
887 msg
->reply
= reply
? CEC_MSG_REPORT_FEATURES
: 0;
890 /* Deck Control Feature */
891 static inline void cec_msg_deck_control(struct cec_msg
*msg
,
892 __u8 deck_control_mode
)
895 msg
->msg
[1] = CEC_MSG_DECK_CONTROL
;
896 msg
->msg
[2] = deck_control_mode
;
899 static inline void cec_ops_deck_control(const struct cec_msg
*msg
,
900 __u8
*deck_control_mode
)
902 *deck_control_mode
= msg
->msg
[2];
905 static inline void cec_msg_deck_status(struct cec_msg
*msg
,
909 msg
->msg
[1] = CEC_MSG_DECK_STATUS
;
910 msg
->msg
[2] = deck_info
;
913 static inline void cec_ops_deck_status(const struct cec_msg
*msg
,
916 *deck_info
= msg
->msg
[2];
919 static inline void cec_msg_give_deck_status(struct cec_msg
*msg
,
924 msg
->msg
[1] = CEC_MSG_GIVE_DECK_STATUS
;
925 msg
->msg
[2] = status_req
;
926 msg
->reply
= (reply
&& status_req
!= CEC_OP_STATUS_REQ_OFF
) ?
927 CEC_MSG_DECK_STATUS
: 0;
930 static inline void cec_ops_give_deck_status(const struct cec_msg
*msg
,
933 *status_req
= msg
->msg
[2];
936 static inline void cec_msg_play(struct cec_msg
*msg
,
940 msg
->msg
[1] = CEC_MSG_PLAY
;
941 msg
->msg
[2] = play_mode
;
944 static inline void cec_ops_play(const struct cec_msg
*msg
,
947 *play_mode
= msg
->msg
[2];
951 /* Tuner Control Feature */
952 struct cec_op_tuner_device_info
{
954 __u8 tuner_display_info
;
957 struct cec_op_digital_service_id digital
;
966 static inline void cec_msg_tuner_device_status_analog(struct cec_msg
*msg
,
968 __u8 tuner_display_info
,
974 msg
->msg
[1] = CEC_MSG_TUNER_DEVICE_STATUS
;
975 msg
->msg
[2] = (rec_flag
<< 7) | tuner_display_info
;
976 msg
->msg
[3] = ana_bcast_type
;
977 msg
->msg
[4] = ana_freq
>> 8;
978 msg
->msg
[5] = ana_freq
& 0xff;
979 msg
->msg
[6] = bcast_system
;
982 static inline void cec_msg_tuner_device_status_digital(struct cec_msg
*msg
,
983 __u8 rec_flag
, __u8 tuner_display_info
,
984 const struct cec_op_digital_service_id
*digital
)
987 msg
->msg
[1] = CEC_MSG_TUNER_DEVICE_STATUS
;
988 msg
->msg
[2] = (rec_flag
<< 7) | tuner_display_info
;
989 cec_set_digital_service_id(msg
->msg
+ 3, digital
);
992 static inline void cec_msg_tuner_device_status(struct cec_msg
*msg
,
993 const struct cec_op_tuner_device_info
*tuner_dev_info
)
995 if (tuner_dev_info
->is_analog
)
996 cec_msg_tuner_device_status_analog(msg
,
997 tuner_dev_info
->rec_flag
,
998 tuner_dev_info
->tuner_display_info
,
999 tuner_dev_info
->analog
.ana_bcast_type
,
1000 tuner_dev_info
->analog
.ana_freq
,
1001 tuner_dev_info
->analog
.bcast_system
);
1003 cec_msg_tuner_device_status_digital(msg
,
1004 tuner_dev_info
->rec_flag
,
1005 tuner_dev_info
->tuner_display_info
,
1006 &tuner_dev_info
->digital
);
1009 static inline void cec_ops_tuner_device_status(const struct cec_msg
*msg
,
1010 struct cec_op_tuner_device_info
*tuner_dev_info
)
1012 tuner_dev_info
->is_analog
= msg
->len
< 10;
1013 tuner_dev_info
->rec_flag
= msg
->msg
[2] >> 7;
1014 tuner_dev_info
->tuner_display_info
= msg
->msg
[2] & 0x7f;
1015 if (tuner_dev_info
->is_analog
) {
1016 tuner_dev_info
->analog
.ana_bcast_type
= msg
->msg
[3];
1017 tuner_dev_info
->analog
.ana_freq
= (msg
->msg
[4] << 8) | msg
->msg
[5];
1018 tuner_dev_info
->analog
.bcast_system
= msg
->msg
[6];
1021 cec_get_digital_service_id(msg
->msg
+ 3, &tuner_dev_info
->digital
);
1024 static inline void cec_msg_give_tuner_device_status(struct cec_msg
*msg
,
1029 msg
->msg
[1] = CEC_MSG_GIVE_TUNER_DEVICE_STATUS
;
1030 msg
->msg
[2] = status_req
;
1031 msg
->reply
= (reply
&& status_req
!= CEC_OP_STATUS_REQ_OFF
) ?
1032 CEC_MSG_TUNER_DEVICE_STATUS
: 0;
1035 static inline void cec_ops_give_tuner_device_status(const struct cec_msg
*msg
,
1038 *status_req
= msg
->msg
[2];
1041 static inline void cec_msg_select_analogue_service(struct cec_msg
*msg
,
1042 __u8 ana_bcast_type
,
1047 msg
->msg
[1] = CEC_MSG_SELECT_ANALOGUE_SERVICE
;
1048 msg
->msg
[2] = ana_bcast_type
;
1049 msg
->msg
[3] = ana_freq
>> 8;
1050 msg
->msg
[4] = ana_freq
& 0xff;
1051 msg
->msg
[5] = bcast_system
;
1054 static inline void cec_ops_select_analogue_service(const struct cec_msg
*msg
,
1055 __u8
*ana_bcast_type
,
1059 *ana_bcast_type
= msg
->msg
[2];
1060 *ana_freq
= (msg
->msg
[3] << 8) | msg
->msg
[4];
1061 *bcast_system
= msg
->msg
[5];
1064 static inline void cec_msg_select_digital_service(struct cec_msg
*msg
,
1065 const struct cec_op_digital_service_id
*digital
)
1068 msg
->msg
[1] = CEC_MSG_SELECT_DIGITAL_SERVICE
;
1069 cec_set_digital_service_id(msg
->msg
+ 2, digital
);
1072 static inline void cec_ops_select_digital_service(const struct cec_msg
*msg
,
1073 struct cec_op_digital_service_id
*digital
)
1075 cec_get_digital_service_id(msg
->msg
+ 2, digital
);
1078 static inline void cec_msg_tuner_step_decrement(struct cec_msg
*msg
)
1081 msg
->msg
[1] = CEC_MSG_TUNER_STEP_DECREMENT
;
1084 static inline void cec_msg_tuner_step_increment(struct cec_msg
*msg
)
1087 msg
->msg
[1] = CEC_MSG_TUNER_STEP_INCREMENT
;
1091 /* Vendor Specific Commands Feature */
1092 static inline void cec_msg_device_vendor_id(struct cec_msg
*msg
, __u32 vendor_id
)
1095 msg
->msg
[0] |= 0xf; /* broadcast */
1096 msg
->msg
[1] = CEC_MSG_DEVICE_VENDOR_ID
;
1097 msg
->msg
[2] = vendor_id
>> 16;
1098 msg
->msg
[3] = (vendor_id
>> 8) & 0xff;
1099 msg
->msg
[4] = vendor_id
& 0xff;
1102 static inline void cec_ops_device_vendor_id(const struct cec_msg
*msg
,
1105 *vendor_id
= (msg
->msg
[2] << 16) | (msg
->msg
[3] << 8) | msg
->msg
[4];
1108 static inline void cec_msg_give_device_vendor_id(struct cec_msg
*msg
,
1112 msg
->msg
[1] = CEC_MSG_GIVE_DEVICE_VENDOR_ID
;
1113 msg
->reply
= reply
? CEC_MSG_DEVICE_VENDOR_ID
: 0;
1116 static inline void cec_msg_vendor_command(struct cec_msg
*msg
,
1117 __u8 size
, const __u8
*vendor_cmd
)
1121 msg
->len
= 2 + size
;
1122 msg
->msg
[1] = CEC_MSG_VENDOR_COMMAND
;
1123 memcpy(msg
->msg
+ 2, vendor_cmd
, size
);
1126 static inline void cec_ops_vendor_command(const struct cec_msg
*msg
,
1128 const __u8
**vendor_cmd
)
1130 *size
= msg
->len
- 2;
1134 *vendor_cmd
= msg
->msg
+ 2;
1137 static inline void cec_msg_vendor_command_with_id(struct cec_msg
*msg
,
1138 __u32 vendor_id
, __u8 size
,
1139 const __u8
*vendor_cmd
)
1143 msg
->len
= 5 + size
;
1144 msg
->msg
[1] = CEC_MSG_VENDOR_COMMAND_WITH_ID
;
1145 msg
->msg
[2] = vendor_id
>> 16;
1146 msg
->msg
[3] = (vendor_id
>> 8) & 0xff;
1147 msg
->msg
[4] = vendor_id
& 0xff;
1148 memcpy(msg
->msg
+ 5, vendor_cmd
, size
);
1151 static inline void cec_ops_vendor_command_with_id(const struct cec_msg
*msg
,
1152 __u32
*vendor_id
, __u8
*size
,
1153 const __u8
**vendor_cmd
)
1155 *size
= msg
->len
- 5;
1159 *vendor_id
= (msg
->msg
[2] << 16) | (msg
->msg
[3] << 8) | msg
->msg
[4];
1160 *vendor_cmd
= msg
->msg
+ 5;
1163 static inline void cec_msg_vendor_remote_button_down(struct cec_msg
*msg
,
1165 const __u8
*rc_code
)
1169 msg
->len
= 2 + size
;
1170 msg
->msg
[1] = CEC_MSG_VENDOR_REMOTE_BUTTON_DOWN
;
1171 memcpy(msg
->msg
+ 2, rc_code
, size
);
1174 static inline void cec_ops_vendor_remote_button_down(const struct cec_msg
*msg
,
1176 const __u8
**rc_code
)
1178 *size
= msg
->len
- 2;
1182 *rc_code
= msg
->msg
+ 2;
1185 static inline void cec_msg_vendor_remote_button_up(struct cec_msg
*msg
)
1188 msg
->msg
[1] = CEC_MSG_VENDOR_REMOTE_BUTTON_UP
;
1192 /* OSD Display Feature */
1193 static inline void cec_msg_set_osd_string(struct cec_msg
*msg
,
1197 unsigned int len
= strlen(osd
);
1202 msg
->msg
[1] = CEC_MSG_SET_OSD_STRING
;
1203 msg
->msg
[2] = disp_ctl
;
1204 memcpy(msg
->msg
+ 3, osd
, len
);
1207 static inline void cec_ops_set_osd_string(const struct cec_msg
*msg
,
1211 unsigned int len
= msg
->len
> 3 ? msg
->len
- 3 : 0;
1213 *disp_ctl
= msg
->msg
[2];
1216 memcpy(osd
, msg
->msg
+ 3, len
);
1221 /* Device OSD Transfer Feature */
1222 static inline void cec_msg_set_osd_name(struct cec_msg
*msg
, const char *name
)
1224 unsigned int len
= strlen(name
);
1229 msg
->msg
[1] = CEC_MSG_SET_OSD_NAME
;
1230 memcpy(msg
->msg
+ 2, name
, len
);
1233 static inline void cec_ops_set_osd_name(const struct cec_msg
*msg
,
1236 unsigned int len
= msg
->len
> 2 ? msg
->len
- 2 : 0;
1240 memcpy(name
, msg
->msg
+ 2, len
);
1244 static inline void cec_msg_give_osd_name(struct cec_msg
*msg
,
1248 msg
->msg
[1] = CEC_MSG_GIVE_OSD_NAME
;
1249 msg
->reply
= reply
? CEC_MSG_SET_OSD_NAME
: 0;
1253 /* Device Menu Control Feature */
1254 static inline void cec_msg_menu_status(struct cec_msg
*msg
,
1258 msg
->msg
[1] = CEC_MSG_MENU_STATUS
;
1259 msg
->msg
[2] = menu_state
;
1262 static inline void cec_ops_menu_status(const struct cec_msg
*msg
,
1265 *menu_state
= msg
->msg
[2];
1268 static inline void cec_msg_menu_request(struct cec_msg
*msg
,
1273 msg
->msg
[1] = CEC_MSG_MENU_REQUEST
;
1274 msg
->msg
[2] = menu_req
;
1275 msg
->reply
= reply
? CEC_MSG_MENU_STATUS
: 0;
1278 static inline void cec_ops_menu_request(const struct cec_msg
*msg
,
1281 *menu_req
= msg
->msg
[2];
1284 struct cec_op_ui_command
{
1288 struct cec_op_channel_data channel_identifier
;
1289 __u8 ui_broadcast_type
;
1290 __u8 ui_sound_presentation_control
;
1292 __u8 ui_function_media
;
1293 __u8 ui_function_select_av_input
;
1294 __u8 ui_function_select_audio_input
;
1298 static inline void cec_msg_user_control_pressed(struct cec_msg
*msg
,
1299 const struct cec_op_ui_command
*ui_cmd
)
1302 msg
->msg
[1] = CEC_MSG_USER_CONTROL_PRESSED
;
1303 msg
->msg
[2] = ui_cmd
->ui_cmd
;
1304 if (!ui_cmd
->has_opt_arg
)
1306 switch (ui_cmd
->ui_cmd
) {
1307 case CEC_OP_UI_CMD_SELECT_BROADCAST_TYPE
:
1308 case CEC_OP_UI_CMD_SELECT_SOUND_PRESENTATION
:
1309 case CEC_OP_UI_CMD_PLAY_FUNCTION
:
1310 case CEC_OP_UI_CMD_SELECT_MEDIA_FUNCTION
:
1311 case CEC_OP_UI_CMD_SELECT_AV_INPUT_FUNCTION
:
1312 case CEC_OP_UI_CMD_SELECT_AUDIO_INPUT_FUNCTION
:
1313 /* The optional operand is one byte for all these ui commands */
1315 msg
->msg
[3] = ui_cmd
->play_mode
;
1317 case CEC_OP_UI_CMD_TUNE_FUNCTION
:
1319 msg
->msg
[3] = (ui_cmd
->channel_identifier
.channel_number_fmt
<< 2) |
1320 (ui_cmd
->channel_identifier
.major
>> 8);
1321 msg
->msg
[4] = ui_cmd
->channel_identifier
.major
& 0xff;
1322 msg
->msg
[5] = ui_cmd
->channel_identifier
.minor
>> 8;
1323 msg
->msg
[6] = ui_cmd
->channel_identifier
.minor
& 0xff;
1328 static inline void cec_ops_user_control_pressed(const struct cec_msg
*msg
,
1329 struct cec_op_ui_command
*ui_cmd
)
1331 ui_cmd
->ui_cmd
= msg
->msg
[2];
1332 ui_cmd
->has_opt_arg
= 0;
1335 switch (ui_cmd
->ui_cmd
) {
1336 case CEC_OP_UI_CMD_SELECT_BROADCAST_TYPE
:
1337 case CEC_OP_UI_CMD_SELECT_SOUND_PRESENTATION
:
1338 case CEC_OP_UI_CMD_PLAY_FUNCTION
:
1339 case CEC_OP_UI_CMD_SELECT_MEDIA_FUNCTION
:
1340 case CEC_OP_UI_CMD_SELECT_AV_INPUT_FUNCTION
:
1341 case CEC_OP_UI_CMD_SELECT_AUDIO_INPUT_FUNCTION
:
1342 /* The optional operand is one byte for all these ui commands */
1343 ui_cmd
->play_mode
= msg
->msg
[3];
1344 ui_cmd
->has_opt_arg
= 1;
1346 case CEC_OP_UI_CMD_TUNE_FUNCTION
:
1349 ui_cmd
->has_opt_arg
= 1;
1350 ui_cmd
->channel_identifier
.channel_number_fmt
= msg
->msg
[3] >> 2;
1351 ui_cmd
->channel_identifier
.major
= ((msg
->msg
[3] & 3) << 6) | msg
->msg
[4];
1352 ui_cmd
->channel_identifier
.minor
= (msg
->msg
[5] << 8) | msg
->msg
[6];
1357 static inline void cec_msg_user_control_released(struct cec_msg
*msg
)
1360 msg
->msg
[1] = CEC_MSG_USER_CONTROL_RELEASED
;
1363 /* Remote Control Passthrough Feature */
1365 /* Power Status Feature */
1366 static inline void cec_msg_report_power_status(struct cec_msg
*msg
,
1370 msg
->msg
[1] = CEC_MSG_REPORT_POWER_STATUS
;
1371 msg
->msg
[2] = pwr_state
;
1374 static inline void cec_ops_report_power_status(const struct cec_msg
*msg
,
1377 *pwr_state
= msg
->msg
[2];
1380 static inline void cec_msg_give_device_power_status(struct cec_msg
*msg
,
1384 msg
->msg
[1] = CEC_MSG_GIVE_DEVICE_POWER_STATUS
;
1385 msg
->reply
= reply
? CEC_MSG_REPORT_POWER_STATUS
: 0;
1388 /* General Protocol Messages */
1389 static inline void cec_msg_feature_abort(struct cec_msg
*msg
,
1390 __u8 abort_msg
, __u8 reason
)
1393 msg
->msg
[1] = CEC_MSG_FEATURE_ABORT
;
1394 msg
->msg
[2] = abort_msg
;
1395 msg
->msg
[3] = reason
;
1398 static inline void cec_ops_feature_abort(const struct cec_msg
*msg
,
1399 __u8
*abort_msg
, __u8
*reason
)
1401 *abort_msg
= msg
->msg
[2];
1402 *reason
= msg
->msg
[3];
1405 /* This changes the current message into a feature abort message */
1406 static inline void cec_msg_reply_feature_abort(struct cec_msg
*msg
, __u8 reason
)
1408 cec_msg_set_reply_to(msg
, msg
);
1410 msg
->msg
[2] = msg
->msg
[1];
1411 msg
->msg
[3] = reason
;
1412 msg
->msg
[1] = CEC_MSG_FEATURE_ABORT
;
1415 static inline void cec_msg_abort(struct cec_msg
*msg
)
1418 msg
->msg
[1] = CEC_MSG_ABORT
;
1422 /* System Audio Control Feature */
1423 static inline void cec_msg_report_audio_status(struct cec_msg
*msg
,
1424 __u8 aud_mute_status
,
1425 __u8 aud_vol_status
)
1428 msg
->msg
[1] = CEC_MSG_REPORT_AUDIO_STATUS
;
1429 msg
->msg
[2] = (aud_mute_status
<< 7) | (aud_vol_status
& 0x7f);
1432 static inline void cec_ops_report_audio_status(const struct cec_msg
*msg
,
1433 __u8
*aud_mute_status
,
1434 __u8
*aud_vol_status
)
1436 *aud_mute_status
= msg
->msg
[2] >> 7;
1437 *aud_vol_status
= msg
->msg
[2] & 0x7f;
1440 static inline void cec_msg_give_audio_status(struct cec_msg
*msg
,
1444 msg
->msg
[1] = CEC_MSG_GIVE_AUDIO_STATUS
;
1445 msg
->reply
= reply
? CEC_MSG_REPORT_AUDIO_STATUS
: 0;
1448 static inline void cec_msg_set_system_audio_mode(struct cec_msg
*msg
,
1449 __u8 sys_aud_status
)
1452 msg
->msg
[1] = CEC_MSG_SET_SYSTEM_AUDIO_MODE
;
1453 msg
->msg
[2] = sys_aud_status
;
1456 static inline void cec_ops_set_system_audio_mode(const struct cec_msg
*msg
,
1457 __u8
*sys_aud_status
)
1459 *sys_aud_status
= msg
->msg
[2];
1462 static inline void cec_msg_system_audio_mode_request(struct cec_msg
*msg
,
1466 msg
->len
= phys_addr
== 0xffff ? 2 : 4;
1467 msg
->msg
[1] = CEC_MSG_SYSTEM_AUDIO_MODE_REQUEST
;
1468 msg
->msg
[2] = phys_addr
>> 8;
1469 msg
->msg
[3] = phys_addr
& 0xff;
1470 msg
->reply
= reply
? CEC_MSG_SET_SYSTEM_AUDIO_MODE
: 0;
1474 static inline void cec_ops_system_audio_mode_request(const struct cec_msg
*msg
,
1478 *phys_addr
= 0xffff;
1480 *phys_addr
= (msg
->msg
[2] << 8) | msg
->msg
[3];
1483 static inline void cec_msg_system_audio_mode_status(struct cec_msg
*msg
,
1484 __u8 sys_aud_status
)
1487 msg
->msg
[1] = CEC_MSG_SYSTEM_AUDIO_MODE_STATUS
;
1488 msg
->msg
[2] = sys_aud_status
;
1491 static inline void cec_ops_system_audio_mode_status(const struct cec_msg
*msg
,
1492 __u8
*sys_aud_status
)
1494 *sys_aud_status
= msg
->msg
[2];
1497 static inline void cec_msg_give_system_audio_mode_status(struct cec_msg
*msg
,
1501 msg
->msg
[1] = CEC_MSG_GIVE_SYSTEM_AUDIO_MODE_STATUS
;
1502 msg
->reply
= reply
? CEC_MSG_SYSTEM_AUDIO_MODE_STATUS
: 0;
1505 static inline void cec_msg_report_short_audio_descriptor(struct cec_msg
*msg
,
1506 __u8 num_descriptors
,
1507 const __u32
*descriptors
)
1511 if (num_descriptors
> 4)
1512 num_descriptors
= 4;
1513 msg
->len
= 2 + num_descriptors
* 3;
1514 msg
->msg
[1] = CEC_MSG_REPORT_SHORT_AUDIO_DESCRIPTOR
;
1515 for (i
= 0; i
< num_descriptors
; i
++) {
1516 msg
->msg
[2 + i
* 3] = (descriptors
[i
] >> 16) & 0xff;
1517 msg
->msg
[3 + i
* 3] = (descriptors
[i
] >> 8) & 0xff;
1518 msg
->msg
[4 + i
* 3] = descriptors
[i
] & 0xff;
1522 static inline void cec_ops_report_short_audio_descriptor(const struct cec_msg
*msg
,
1523 __u8
*num_descriptors
,
1528 *num_descriptors
= (msg
->len
- 2) / 3;
1529 if (*num_descriptors
> 4)
1530 *num_descriptors
= 4;
1531 for (i
= 0; i
< *num_descriptors
; i
++)
1532 descriptors
[i
] = (msg
->msg
[2 + i
* 3] << 16) |
1533 (msg
->msg
[3 + i
* 3] << 8) |
1534 msg
->msg
[4 + i
* 3];
1537 static inline void cec_msg_request_short_audio_descriptor(struct cec_msg
*msg
,
1539 __u8 num_descriptors
,
1540 const __u8
*audio_format_id
,
1541 const __u8
*audio_format_code
)
1545 if (num_descriptors
> 4)
1546 num_descriptors
= 4;
1547 msg
->len
= 2 + num_descriptors
;
1548 msg
->msg
[1] = CEC_MSG_REQUEST_SHORT_AUDIO_DESCRIPTOR
;
1549 msg
->reply
= reply
? CEC_MSG_REPORT_SHORT_AUDIO_DESCRIPTOR
: 0;
1550 for (i
= 0; i
< num_descriptors
; i
++)
1551 msg
->msg
[2 + i
] = (audio_format_id
[i
] << 6) |
1552 (audio_format_code
[i
] & 0x3f);
1555 static inline void cec_ops_request_short_audio_descriptor(const struct cec_msg
*msg
,
1556 __u8
*num_descriptors
,
1557 __u8
*audio_format_id
,
1558 __u8
*audio_format_code
)
1562 *num_descriptors
= msg
->len
- 2;
1563 if (*num_descriptors
> 4)
1564 *num_descriptors
= 4;
1565 for (i
= 0; i
< *num_descriptors
; i
++) {
1566 audio_format_id
[i
] = msg
->msg
[2 + i
] >> 6;
1567 audio_format_code
[i
] = msg
->msg
[2 + i
] & 0x3f;
1571 static inline void cec_msg_set_audio_volume_level(struct cec_msg
*msg
,
1572 __u8 audio_volume_level
)
1575 msg
->msg
[1] = CEC_MSG_SET_AUDIO_VOLUME_LEVEL
;
1576 msg
->msg
[2] = audio_volume_level
;
1579 static inline void cec_ops_set_audio_volume_level(const struct cec_msg
*msg
,
1580 __u8
*audio_volume_level
)
1582 *audio_volume_level
= msg
->msg
[2];
1586 /* Audio Rate Control Feature */
1587 static inline void cec_msg_set_audio_rate(struct cec_msg
*msg
,
1591 msg
->msg
[1] = CEC_MSG_SET_AUDIO_RATE
;
1592 msg
->msg
[2] = audio_rate
;
1595 static inline void cec_ops_set_audio_rate(const struct cec_msg
*msg
,
1598 *audio_rate
= msg
->msg
[2];
1602 /* Audio Return Channel Control Feature */
1603 static inline void cec_msg_report_arc_initiated(struct cec_msg
*msg
)
1606 msg
->msg
[1] = CEC_MSG_REPORT_ARC_INITIATED
;
1609 static inline void cec_msg_initiate_arc(struct cec_msg
*msg
,
1613 msg
->msg
[1] = CEC_MSG_INITIATE_ARC
;
1614 msg
->reply
= reply
? CEC_MSG_REPORT_ARC_INITIATED
: 0;
1617 static inline void cec_msg_request_arc_initiation(struct cec_msg
*msg
,
1621 msg
->msg
[1] = CEC_MSG_REQUEST_ARC_INITIATION
;
1622 msg
->reply
= reply
? CEC_MSG_INITIATE_ARC
: 0;
1625 static inline void cec_msg_report_arc_terminated(struct cec_msg
*msg
)
1628 msg
->msg
[1] = CEC_MSG_REPORT_ARC_TERMINATED
;
1631 static inline void cec_msg_terminate_arc(struct cec_msg
*msg
,
1635 msg
->msg
[1] = CEC_MSG_TERMINATE_ARC
;
1636 msg
->reply
= reply
? CEC_MSG_REPORT_ARC_TERMINATED
: 0;
1639 static inline void cec_msg_request_arc_termination(struct cec_msg
*msg
,
1643 msg
->msg
[1] = CEC_MSG_REQUEST_ARC_TERMINATION
;
1644 msg
->reply
= reply
? CEC_MSG_TERMINATE_ARC
: 0;
1648 /* Dynamic Audio Lipsync Feature */
1649 /* Only for CEC 2.0 and up */
1650 static inline void cec_msg_report_current_latency(struct cec_msg
*msg
,
1653 __u8 low_latency_mode
,
1654 __u8 audio_out_compensated
,
1655 __u8 audio_out_delay
)
1658 msg
->msg
[0] |= 0xf; /* broadcast */
1659 msg
->msg
[1] = CEC_MSG_REPORT_CURRENT_LATENCY
;
1660 msg
->msg
[2] = phys_addr
>> 8;
1661 msg
->msg
[3] = phys_addr
& 0xff;
1662 msg
->msg
[4] = video_latency
;
1663 msg
->msg
[5] = (low_latency_mode
<< 2) | audio_out_compensated
;
1664 if (audio_out_compensated
== 3)
1665 msg
->msg
[msg
->len
++] = audio_out_delay
;
1668 static inline void cec_ops_report_current_latency(const struct cec_msg
*msg
,
1670 __u8
*video_latency
,
1671 __u8
*low_latency_mode
,
1672 __u8
*audio_out_compensated
,
1673 __u8
*audio_out_delay
)
1675 *phys_addr
= (msg
->msg
[2] << 8) | msg
->msg
[3];
1676 *video_latency
= msg
->msg
[4];
1677 *low_latency_mode
= (msg
->msg
[5] >> 2) & 1;
1678 *audio_out_compensated
= msg
->msg
[5] & 3;
1679 if (*audio_out_compensated
== 3 && msg
->len
>= 7)
1680 *audio_out_delay
= msg
->msg
[6];
1682 *audio_out_delay
= 1;
1685 static inline void cec_msg_request_current_latency(struct cec_msg
*msg
,
1690 msg
->msg
[0] |= 0xf; /* broadcast */
1691 msg
->msg
[1] = CEC_MSG_REQUEST_CURRENT_LATENCY
;
1692 msg
->msg
[2] = phys_addr
>> 8;
1693 msg
->msg
[3] = phys_addr
& 0xff;
1694 msg
->reply
= reply
? CEC_MSG_REPORT_CURRENT_LATENCY
: 0;
1697 static inline void cec_ops_request_current_latency(const struct cec_msg
*msg
,
1700 *phys_addr
= (msg
->msg
[2] << 8) | msg
->msg
[3];
1704 /* Capability Discovery and Control Feature */
1705 static inline void cec_msg_cdc_hec_inquire_state(struct cec_msg
*msg
,
1710 msg
->msg
[0] |= 0xf; /* broadcast */
1711 msg
->msg
[1] = CEC_MSG_CDC_MESSAGE
;
1712 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1713 msg
->msg
[4] = CEC_MSG_CDC_HEC_INQUIRE_STATE
;
1714 msg
->msg
[5] = phys_addr1
>> 8;
1715 msg
->msg
[6] = phys_addr1
& 0xff;
1716 msg
->msg
[7] = phys_addr2
>> 8;
1717 msg
->msg
[8] = phys_addr2
& 0xff;
1720 static inline void cec_ops_cdc_hec_inquire_state(const struct cec_msg
*msg
,
1725 *phys_addr
= (msg
->msg
[2] << 8) | msg
->msg
[3];
1726 *phys_addr1
= (msg
->msg
[5] << 8) | msg
->msg
[6];
1727 *phys_addr2
= (msg
->msg
[7] << 8) | msg
->msg
[8];
1730 static inline void cec_msg_cdc_hec_report_state(struct cec_msg
*msg
,
1731 __u16 target_phys_addr
,
1732 __u8 hec_func_state
,
1733 __u8 host_func_state
,
1734 __u8 enc_func_state
,
1739 msg
->len
= has_field
? 10 : 8;
1740 msg
->msg
[0] |= 0xf; /* broadcast */
1741 msg
->msg
[1] = CEC_MSG_CDC_MESSAGE
;
1742 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1743 msg
->msg
[4] = CEC_MSG_CDC_HEC_REPORT_STATE
;
1744 msg
->msg
[5] = target_phys_addr
>> 8;
1745 msg
->msg
[6] = target_phys_addr
& 0xff;
1746 msg
->msg
[7] = (hec_func_state
<< 6) |
1747 (host_func_state
<< 4) |
1748 (enc_func_state
<< 2) |
1751 msg
->msg
[8] = hec_field
>> 8;
1752 msg
->msg
[9] = hec_field
& 0xff;
1756 static inline void cec_ops_cdc_hec_report_state(const struct cec_msg
*msg
,
1758 __u16
*target_phys_addr
,
1759 __u8
*hec_func_state
,
1760 __u8
*host_func_state
,
1761 __u8
*enc_func_state
,
1766 *phys_addr
= (msg
->msg
[2] << 8) | msg
->msg
[3];
1767 *target_phys_addr
= (msg
->msg
[5] << 8) | msg
->msg
[6];
1768 *hec_func_state
= msg
->msg
[7] >> 6;
1769 *host_func_state
= (msg
->msg
[7] >> 4) & 3;
1770 *enc_func_state
= (msg
->msg
[7] >> 4) & 3;
1771 *cdc_errcode
= msg
->msg
[7] & 3;
1772 *has_field
= msg
->len
>= 10;
1773 *hec_field
= *has_field
? ((msg
->msg
[8] << 8) | msg
->msg
[9]) : 0;
1776 static inline void cec_msg_cdc_hec_set_state(struct cec_msg
*msg
,
1785 msg
->msg
[0] |= 0xf; /* broadcast */
1786 msg
->msg
[1] = CEC_MSG_CDC_MESSAGE
;
1787 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1788 msg
->msg
[4] = CEC_MSG_CDC_HEC_INQUIRE_STATE
;
1789 msg
->msg
[5] = phys_addr1
>> 8;
1790 msg
->msg
[6] = phys_addr1
& 0xff;
1791 msg
->msg
[7] = phys_addr2
>> 8;
1792 msg
->msg
[8] = phys_addr2
& 0xff;
1793 msg
->msg
[9] = hec_set_state
;
1794 if (phys_addr3
!= CEC_PHYS_ADDR_INVALID
) {
1795 msg
->msg
[msg
->len
++] = phys_addr3
>> 8;
1796 msg
->msg
[msg
->len
++] = phys_addr3
& 0xff;
1797 if (phys_addr4
!= CEC_PHYS_ADDR_INVALID
) {
1798 msg
->msg
[msg
->len
++] = phys_addr4
>> 8;
1799 msg
->msg
[msg
->len
++] = phys_addr4
& 0xff;
1800 if (phys_addr5
!= CEC_PHYS_ADDR_INVALID
) {
1801 msg
->msg
[msg
->len
++] = phys_addr5
>> 8;
1802 msg
->msg
[msg
->len
++] = phys_addr5
& 0xff;
1808 static inline void cec_ops_cdc_hec_set_state(const struct cec_msg
*msg
,
1812 __u8
*hec_set_state
,
1817 *phys_addr
= (msg
->msg
[2] << 8) | msg
->msg
[3];
1818 *phys_addr1
= (msg
->msg
[5] << 8) | msg
->msg
[6];
1819 *phys_addr2
= (msg
->msg
[7] << 8) | msg
->msg
[8];
1820 *hec_set_state
= msg
->msg
[9];
1821 *phys_addr3
= *phys_addr4
= *phys_addr5
= CEC_PHYS_ADDR_INVALID
;
1823 *phys_addr3
= (msg
->msg
[10] << 8) | msg
->msg
[11];
1825 *phys_addr4
= (msg
->msg
[12] << 8) | msg
->msg
[13];
1827 *phys_addr5
= (msg
->msg
[14] << 8) | msg
->msg
[15];
1830 static inline void cec_msg_cdc_hec_set_state_adjacent(struct cec_msg
*msg
,
1835 msg
->msg
[0] |= 0xf; /* broadcast */
1836 msg
->msg
[1] = CEC_MSG_CDC_MESSAGE
;
1837 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1838 msg
->msg
[4] = CEC_MSG_CDC_HEC_SET_STATE_ADJACENT
;
1839 msg
->msg
[5] = phys_addr1
>> 8;
1840 msg
->msg
[6] = phys_addr1
& 0xff;
1841 msg
->msg
[7] = hec_set_state
;
1844 static inline void cec_ops_cdc_hec_set_state_adjacent(const struct cec_msg
*msg
,
1847 __u8
*hec_set_state
)
1849 *phys_addr
= (msg
->msg
[2] << 8) | msg
->msg
[3];
1850 *phys_addr1
= (msg
->msg
[5] << 8) | msg
->msg
[6];
1851 *hec_set_state
= msg
->msg
[7];
1854 static inline void cec_msg_cdc_hec_request_deactivation(struct cec_msg
*msg
,
1860 msg
->msg
[0] |= 0xf; /* broadcast */
1861 msg
->msg
[1] = CEC_MSG_CDC_MESSAGE
;
1862 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1863 msg
->msg
[4] = CEC_MSG_CDC_HEC_REQUEST_DEACTIVATION
;
1864 msg
->msg
[5] = phys_addr1
>> 8;
1865 msg
->msg
[6] = phys_addr1
& 0xff;
1866 msg
->msg
[7] = phys_addr2
>> 8;
1867 msg
->msg
[8] = phys_addr2
& 0xff;
1868 msg
->msg
[9] = phys_addr3
>> 8;
1869 msg
->msg
[10] = phys_addr3
& 0xff;
1872 static inline void cec_ops_cdc_hec_request_deactivation(const struct cec_msg
*msg
,
1878 *phys_addr
= (msg
->msg
[2] << 8) | msg
->msg
[3];
1879 *phys_addr1
= (msg
->msg
[5] << 8) | msg
->msg
[6];
1880 *phys_addr2
= (msg
->msg
[7] << 8) | msg
->msg
[8];
1881 *phys_addr3
= (msg
->msg
[9] << 8) | msg
->msg
[10];
1884 static inline void cec_msg_cdc_hec_notify_alive(struct cec_msg
*msg
)
1887 msg
->msg
[0] |= 0xf; /* broadcast */
1888 msg
->msg
[1] = CEC_MSG_CDC_MESSAGE
;
1889 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1890 msg
->msg
[4] = CEC_MSG_CDC_HEC_NOTIFY_ALIVE
;
1893 static inline void cec_ops_cdc_hec_notify_alive(const struct cec_msg
*msg
,
1896 *phys_addr
= (msg
->msg
[2] << 8) | msg
->msg
[3];
1899 static inline void cec_msg_cdc_hec_discover(struct cec_msg
*msg
)
1902 msg
->msg
[0] |= 0xf; /* broadcast */
1903 msg
->msg
[1] = CEC_MSG_CDC_MESSAGE
;
1904 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1905 msg
->msg
[4] = CEC_MSG_CDC_HEC_DISCOVER
;
1908 static inline void cec_ops_cdc_hec_discover(const struct cec_msg
*msg
,
1911 *phys_addr
= (msg
->msg
[2] << 8) | msg
->msg
[3];
1914 static inline void cec_msg_cdc_hpd_set_state(struct cec_msg
*msg
,
1919 msg
->msg
[0] |= 0xf; /* broadcast */
1920 msg
->msg
[1] = CEC_MSG_CDC_MESSAGE
;
1921 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1922 msg
->msg
[4] = CEC_MSG_CDC_HPD_SET_STATE
;
1923 msg
->msg
[5] = (input_port
<< 4) | hpd_state
;
1926 static inline void cec_ops_cdc_hpd_set_state(const struct cec_msg
*msg
,
1931 *phys_addr
= (msg
->msg
[2] << 8) | msg
->msg
[3];
1932 *input_port
= msg
->msg
[5] >> 4;
1933 *hpd_state
= msg
->msg
[5] & 0xf;
1936 static inline void cec_msg_cdc_hpd_report_state(struct cec_msg
*msg
,
1941 msg
->msg
[0] |= 0xf; /* broadcast */
1942 msg
->msg
[1] = CEC_MSG_CDC_MESSAGE
;
1943 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1944 msg
->msg
[4] = CEC_MSG_CDC_HPD_REPORT_STATE
;
1945 msg
->msg
[5] = (hpd_state
<< 4) | hpd_error
;
1948 static inline void cec_ops_cdc_hpd_report_state(const struct cec_msg
*msg
,
1953 *phys_addr
= (msg
->msg
[2] << 8) | msg
->msg
[3];
1954 *hpd_state
= msg
->msg
[5] >> 4;
1955 *hpd_error
= msg
->msg
[5] & 0xf;