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.
7 * This program is free software; you may redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
11 * Alternatively you can redistribute this file under the terms of the
12 * BSD license as stated below:
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in
21 * the documentation and/or other materials provided with the
23 * 3. The names of its contributors may not be used to endorse or promote
24 * products derived from this software without specific prior written
27 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
31 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
32 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
33 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
37 #ifndef _CEC_UAPI_FUNCS_H
38 #define _CEC_UAPI_FUNCS_H
40 #include <linux/cec.h>
42 /* One Touch Play Feature */
43 static inline void cec_msg_active_source(struct cec_msg
*msg
, __u16 phys_addr
)
46 msg
->msg
[0] |= 0xf; /* broadcast */
47 msg
->msg
[1] = CEC_MSG_ACTIVE_SOURCE
;
48 msg
->msg
[2] = phys_addr
>> 8;
49 msg
->msg
[3] = phys_addr
& 0xff;
52 static inline void cec_ops_active_source(const struct cec_msg
*msg
,
55 *phys_addr
= (msg
->msg
[2] << 8) | msg
->msg
[3];
58 static inline void cec_msg_image_view_on(struct cec_msg
*msg
)
61 msg
->msg
[1] = CEC_MSG_IMAGE_VIEW_ON
;
64 static inline void cec_msg_text_view_on(struct cec_msg
*msg
)
67 msg
->msg
[1] = CEC_MSG_TEXT_VIEW_ON
;
71 /* Routing Control Feature */
72 static inline void cec_msg_inactive_source(struct cec_msg
*msg
,
76 msg
->msg
[1] = CEC_MSG_INACTIVE_SOURCE
;
77 msg
->msg
[2] = phys_addr
>> 8;
78 msg
->msg
[3] = phys_addr
& 0xff;
81 static inline void cec_ops_inactive_source(const struct cec_msg
*msg
,
84 *phys_addr
= (msg
->msg
[2] << 8) | msg
->msg
[3];
87 static inline void cec_msg_request_active_source(struct cec_msg
*msg
,
91 msg
->msg
[0] |= 0xf; /* broadcast */
92 msg
->msg
[1] = CEC_MSG_REQUEST_ACTIVE_SOURCE
;
93 msg
->reply
= reply
? CEC_MSG_ACTIVE_SOURCE
: 0;
96 static inline void cec_msg_routing_information(struct cec_msg
*msg
,
100 msg
->msg
[0] |= 0xf; /* broadcast */
101 msg
->msg
[1] = CEC_MSG_ROUTING_INFORMATION
;
102 msg
->msg
[2] = phys_addr
>> 8;
103 msg
->msg
[3] = phys_addr
& 0xff;
106 static inline void cec_ops_routing_information(const struct cec_msg
*msg
,
109 *phys_addr
= (msg
->msg
[2] << 8) | msg
->msg
[3];
112 static inline void cec_msg_routing_change(struct cec_msg
*msg
,
114 __u16 orig_phys_addr
,
118 msg
->msg
[0] |= 0xf; /* broadcast */
119 msg
->msg
[1] = CEC_MSG_ROUTING_CHANGE
;
120 msg
->msg
[2] = orig_phys_addr
>> 8;
121 msg
->msg
[3] = orig_phys_addr
& 0xff;
122 msg
->msg
[4] = new_phys_addr
>> 8;
123 msg
->msg
[5] = new_phys_addr
& 0xff;
124 msg
->reply
= reply
? CEC_MSG_ROUTING_INFORMATION
: 0;
127 static inline void cec_ops_routing_change(const struct cec_msg
*msg
,
128 __u16
*orig_phys_addr
,
129 __u16
*new_phys_addr
)
131 *orig_phys_addr
= (msg
->msg
[2] << 8) | msg
->msg
[3];
132 *new_phys_addr
= (msg
->msg
[4] << 8) | msg
->msg
[5];
135 static inline void cec_msg_set_stream_path(struct cec_msg
*msg
, __u16 phys_addr
)
138 msg
->msg
[0] |= 0xf; /* broadcast */
139 msg
->msg
[1] = CEC_MSG_SET_STREAM_PATH
;
140 msg
->msg
[2] = phys_addr
>> 8;
141 msg
->msg
[3] = phys_addr
& 0xff;
144 static inline void cec_ops_set_stream_path(const struct cec_msg
*msg
,
147 *phys_addr
= (msg
->msg
[2] << 8) | msg
->msg
[3];
151 /* Standby Feature */
152 static inline void cec_msg_standby(struct cec_msg
*msg
)
155 msg
->msg
[1] = CEC_MSG_STANDBY
;
159 /* One Touch Record Feature */
160 static inline void cec_msg_record_off(struct cec_msg
*msg
, int reply
)
163 msg
->msg
[1] = CEC_MSG_RECORD_OFF
;
164 msg
->reply
= reply
? CEC_MSG_RECORD_STATUS
: 0;
167 struct cec_op_arib_data
{
170 __u16 orig_network_id
;
173 struct cec_op_atsc_data
{
175 __u16 program_number
;
178 struct cec_op_dvb_data
{
181 __u16 orig_network_id
;
184 struct cec_op_channel_data
{
185 __u8 channel_number_fmt
;
190 struct cec_op_digital_service_id
{
191 __u8 service_id_method
;
192 __u8 dig_bcast_system
;
194 struct cec_op_arib_data arib
;
195 struct cec_op_atsc_data atsc
;
196 struct cec_op_dvb_data dvb
;
197 struct cec_op_channel_data channel
;
201 struct cec_op_record_src
{
204 struct cec_op_digital_service_id digital
;
219 static inline void cec_set_digital_service_id(__u8
*msg
,
220 const struct cec_op_digital_service_id
*digital
)
222 *msg
++ = (digital
->service_id_method
<< 7) | digital
->dig_bcast_system
;
223 if (digital
->service_id_method
== CEC_OP_SERVICE_ID_METHOD_BY_CHANNEL
) {
224 *msg
++ = (digital
->channel
.channel_number_fmt
<< 2) |
225 (digital
->channel
.major
>> 8);
226 *msg
++ = digital
->channel
.major
& 0xff;
227 *msg
++ = digital
->channel
.minor
>> 8;
228 *msg
++ = digital
->channel
.minor
& 0xff;
233 switch (digital
->dig_bcast_system
) {
234 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_GEN
:
235 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_CABLE
:
236 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_SAT
:
237 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_T
:
238 *msg
++ = digital
->atsc
.transport_id
>> 8;
239 *msg
++ = digital
->atsc
.transport_id
& 0xff;
240 *msg
++ = digital
->atsc
.program_number
>> 8;
241 *msg
++ = digital
->atsc
.program_number
& 0xff;
246 *msg
++ = digital
->dvb
.transport_id
>> 8;
247 *msg
++ = digital
->dvb
.transport_id
& 0xff;
248 *msg
++ = digital
->dvb
.service_id
>> 8;
249 *msg
++ = digital
->dvb
.service_id
& 0xff;
250 *msg
++ = digital
->dvb
.orig_network_id
>> 8;
251 *msg
++ = digital
->dvb
.orig_network_id
& 0xff;
256 static inline void cec_get_digital_service_id(const __u8
*msg
,
257 struct cec_op_digital_service_id
*digital
)
259 digital
->service_id_method
= msg
[0] >> 7;
260 digital
->dig_bcast_system
= msg
[0] & 0x7f;
261 if (digital
->service_id_method
== CEC_OP_SERVICE_ID_METHOD_BY_CHANNEL
) {
262 digital
->channel
.channel_number_fmt
= msg
[1] >> 2;
263 digital
->channel
.major
= ((msg
[1] & 3) << 6) | msg
[2];
264 digital
->channel
.minor
= (msg
[3] << 8) | msg
[4];
267 digital
->dvb
.transport_id
= (msg
[1] << 8) | msg
[2];
268 digital
->dvb
.service_id
= (msg
[3] << 8) | msg
[4];
269 digital
->dvb
.orig_network_id
= (msg
[5] << 8) | msg
[6];
272 static inline void cec_msg_record_on_own(struct cec_msg
*msg
)
275 msg
->msg
[1] = CEC_MSG_RECORD_ON
;
276 msg
->msg
[2] = CEC_OP_RECORD_SRC_OWN
;
279 static inline void cec_msg_record_on_digital(struct cec_msg
*msg
,
280 const struct cec_op_digital_service_id
*digital
)
283 msg
->msg
[1] = CEC_MSG_RECORD_ON
;
284 msg
->msg
[2] = CEC_OP_RECORD_SRC_DIGITAL
;
285 cec_set_digital_service_id(msg
->msg
+ 3, digital
);
288 static inline void cec_msg_record_on_analog(struct cec_msg
*msg
,
294 msg
->msg
[1] = CEC_MSG_RECORD_ON
;
295 msg
->msg
[2] = CEC_OP_RECORD_SRC_ANALOG
;
296 msg
->msg
[3] = ana_bcast_type
;
297 msg
->msg
[4] = ana_freq
>> 8;
298 msg
->msg
[5] = ana_freq
& 0xff;
299 msg
->msg
[6] = bcast_system
;
302 static inline void cec_msg_record_on_plug(struct cec_msg
*msg
,
306 msg
->msg
[1] = CEC_MSG_RECORD_ON
;
307 msg
->msg
[2] = CEC_OP_RECORD_SRC_EXT_PLUG
;
311 static inline void cec_msg_record_on_phys_addr(struct cec_msg
*msg
,
315 msg
->msg
[1] = CEC_MSG_RECORD_ON
;
316 msg
->msg
[2] = CEC_OP_RECORD_SRC_EXT_PHYS_ADDR
;
317 msg
->msg
[3] = phys_addr
>> 8;
318 msg
->msg
[4] = phys_addr
& 0xff;
321 static inline void cec_msg_record_on(struct cec_msg
*msg
,
323 const struct cec_op_record_src
*rec_src
)
325 switch (rec_src
->type
) {
326 case CEC_OP_RECORD_SRC_OWN
:
327 cec_msg_record_on_own(msg
);
329 case CEC_OP_RECORD_SRC_DIGITAL
:
330 cec_msg_record_on_digital(msg
, &rec_src
->digital
);
332 case CEC_OP_RECORD_SRC_ANALOG
:
333 cec_msg_record_on_analog(msg
,
334 rec_src
->analog
.ana_bcast_type
,
335 rec_src
->analog
.ana_freq
,
336 rec_src
->analog
.bcast_system
);
338 case CEC_OP_RECORD_SRC_EXT_PLUG
:
339 cec_msg_record_on_plug(msg
, rec_src
->ext_plug
.plug
);
341 case CEC_OP_RECORD_SRC_EXT_PHYS_ADDR
:
342 cec_msg_record_on_phys_addr(msg
,
343 rec_src
->ext_phys_addr
.phys_addr
);
346 msg
->reply
= reply
? CEC_MSG_RECORD_STATUS
: 0;
349 static inline void cec_ops_record_on(const struct cec_msg
*msg
,
350 struct cec_op_record_src
*rec_src
)
352 rec_src
->type
= msg
->msg
[2];
353 switch (rec_src
->type
) {
354 case CEC_OP_RECORD_SRC_OWN
:
356 case CEC_OP_RECORD_SRC_DIGITAL
:
357 cec_get_digital_service_id(msg
->msg
+ 3, &rec_src
->digital
);
359 case CEC_OP_RECORD_SRC_ANALOG
:
360 rec_src
->analog
.ana_bcast_type
= msg
->msg
[3];
361 rec_src
->analog
.ana_freq
=
362 (msg
->msg
[4] << 8) | msg
->msg
[5];
363 rec_src
->analog
.bcast_system
= msg
->msg
[6];
365 case CEC_OP_RECORD_SRC_EXT_PLUG
:
366 rec_src
->ext_plug
.plug
= msg
->msg
[3];
368 case CEC_OP_RECORD_SRC_EXT_PHYS_ADDR
:
369 rec_src
->ext_phys_addr
.phys_addr
=
370 (msg
->msg
[3] << 8) | msg
->msg
[4];
375 static inline void cec_msg_record_status(struct cec_msg
*msg
, __u8 rec_status
)
378 msg
->msg
[1] = CEC_MSG_RECORD_STATUS
;
379 msg
->msg
[2] = rec_status
;
382 static inline void cec_ops_record_status(const struct cec_msg
*msg
,
385 *rec_status
= msg
->msg
[2];
388 static inline void cec_msg_record_tv_screen(struct cec_msg
*msg
,
392 msg
->msg
[1] = CEC_MSG_RECORD_TV_SCREEN
;
393 msg
->reply
= reply
? CEC_MSG_RECORD_ON
: 0;
397 /* Timer Programming Feature */
398 static inline void cec_msg_timer_status(struct cec_msg
*msg
,
399 __u8 timer_overlap_warning
,
407 msg
->msg
[1] = CEC_MSG_TIMER_STATUS
;
408 msg
->msg
[2] = (timer_overlap_warning
<< 7) |
410 (prog_info
? 0x10 : 0) |
411 (prog_info
? prog_info
: prog_error
);
412 if (prog_info
== CEC_OP_PROG_INFO_NOT_ENOUGH_SPACE
||
413 prog_info
== CEC_OP_PROG_INFO_MIGHT_NOT_BE_ENOUGH_SPACE
||
414 prog_error
== CEC_OP_PROG_ERROR_DUPLICATE
) {
416 msg
->msg
[3] = ((duration_hr
/ 10) << 4) | (duration_hr
% 10);
417 msg
->msg
[4] = ((duration_min
/ 10) << 4) | (duration_min
% 10);
421 static inline void cec_ops_timer_status(const struct cec_msg
*msg
,
422 __u8
*timer_overlap_warning
,
429 *timer_overlap_warning
= msg
->msg
[2] >> 7;
430 *media_info
= (msg
->msg
[2] >> 5) & 3;
431 if (msg
->msg
[2] & 0x10) {
432 *prog_info
= msg
->msg
[2] & 0xf;
436 *prog_error
= msg
->msg
[2] & 0xf;
438 if (*prog_info
== CEC_OP_PROG_INFO_NOT_ENOUGH_SPACE
||
439 *prog_info
== CEC_OP_PROG_INFO_MIGHT_NOT_BE_ENOUGH_SPACE
||
440 *prog_error
== CEC_OP_PROG_ERROR_DUPLICATE
) {
441 *duration_hr
= (msg
->msg
[3] >> 4) * 10 + (msg
->msg
[3] & 0xf);
442 *duration_min
= (msg
->msg
[4] >> 4) * 10 + (msg
->msg
[4] & 0xf);
444 *duration_hr
= *duration_min
= 0;
448 static inline void cec_msg_timer_cleared_status(struct cec_msg
*msg
,
449 __u8 timer_cleared_status
)
452 msg
->msg
[1] = CEC_MSG_TIMER_CLEARED_STATUS
;
453 msg
->msg
[2] = timer_cleared_status
;
456 static inline void cec_ops_timer_cleared_status(const struct cec_msg
*msg
,
457 __u8
*timer_cleared_status
)
459 *timer_cleared_status
= msg
->msg
[2];
462 static inline void cec_msg_clear_analogue_timer(struct cec_msg
*msg
,
476 msg
->msg
[1] = CEC_MSG_CLEAR_ANALOGUE_TIMER
;
479 /* Hours and minutes are in BCD format */
480 msg
->msg
[4] = ((start_hr
/ 10) << 4) | (start_hr
% 10);
481 msg
->msg
[5] = ((start_min
/ 10) << 4) | (start_min
% 10);
482 msg
->msg
[6] = ((duration_hr
/ 10) << 4) | (duration_hr
% 10);
483 msg
->msg
[7] = ((duration_min
/ 10) << 4) | (duration_min
% 10);
484 msg
->msg
[8] = recording_seq
;
485 msg
->msg
[9] = ana_bcast_type
;
486 msg
->msg
[10] = ana_freq
>> 8;
487 msg
->msg
[11] = ana_freq
& 0xff;
488 msg
->msg
[12] = bcast_system
;
489 msg
->reply
= reply
? CEC_MSG_TIMER_CLEARED_STATUS
: 0;
492 static inline void cec_ops_clear_analogue_timer(const struct cec_msg
*msg
,
500 __u8
*ana_bcast_type
,
505 *month
= msg
->msg
[3];
506 /* Hours and minutes are in BCD format */
507 *start_hr
= (msg
->msg
[4] >> 4) * 10 + (msg
->msg
[4] & 0xf);
508 *start_min
= (msg
->msg
[5] >> 4) * 10 + (msg
->msg
[5] & 0xf);
509 *duration_hr
= (msg
->msg
[6] >> 4) * 10 + (msg
->msg
[6] & 0xf);
510 *duration_min
= (msg
->msg
[7] >> 4) * 10 + (msg
->msg
[7] & 0xf);
511 *recording_seq
= msg
->msg
[8];
512 *ana_bcast_type
= msg
->msg
[9];
513 *ana_freq
= (msg
->msg
[10] << 8) | msg
->msg
[11];
514 *bcast_system
= msg
->msg
[12];
517 static inline void cec_msg_clear_digital_timer(struct cec_msg
*msg
,
526 const struct cec_op_digital_service_id
*digital
)
529 msg
->reply
= reply
? CEC_MSG_TIMER_CLEARED_STATUS
: 0;
530 msg
->msg
[1] = CEC_MSG_CLEAR_DIGITAL_TIMER
;
533 /* Hours and minutes are in BCD format */
534 msg
->msg
[4] = ((start_hr
/ 10) << 4) | (start_hr
% 10);
535 msg
->msg
[5] = ((start_min
/ 10) << 4) | (start_min
% 10);
536 msg
->msg
[6] = ((duration_hr
/ 10) << 4) | (duration_hr
% 10);
537 msg
->msg
[7] = ((duration_min
/ 10) << 4) | (duration_min
% 10);
538 msg
->msg
[8] = recording_seq
;
539 cec_set_digital_service_id(msg
->msg
+ 9, digital
);
542 static inline void cec_ops_clear_digital_timer(const struct cec_msg
*msg
,
550 struct cec_op_digital_service_id
*digital
)
553 *month
= msg
->msg
[3];
554 /* Hours and minutes are in BCD format */
555 *start_hr
= (msg
->msg
[4] >> 4) * 10 + (msg
->msg
[4] & 0xf);
556 *start_min
= (msg
->msg
[5] >> 4) * 10 + (msg
->msg
[5] & 0xf);
557 *duration_hr
= (msg
->msg
[6] >> 4) * 10 + (msg
->msg
[6] & 0xf);
558 *duration_min
= (msg
->msg
[7] >> 4) * 10 + (msg
->msg
[7] & 0xf);
559 *recording_seq
= msg
->msg
[8];
560 cec_get_digital_service_id(msg
->msg
+ 9, digital
);
563 static inline void cec_msg_clear_ext_timer(struct cec_msg
*msg
,
577 msg
->msg
[1] = CEC_MSG_CLEAR_EXT_TIMER
;
580 /* Hours and minutes are in BCD format */
581 msg
->msg
[4] = ((start_hr
/ 10) << 4) | (start_hr
% 10);
582 msg
->msg
[5] = ((start_min
/ 10) << 4) | (start_min
% 10);
583 msg
->msg
[6] = ((duration_hr
/ 10) << 4) | (duration_hr
% 10);
584 msg
->msg
[7] = ((duration_min
/ 10) << 4) | (duration_min
% 10);
585 msg
->msg
[8] = recording_seq
;
586 msg
->msg
[9] = ext_src_spec
;
588 msg
->msg
[11] = phys_addr
>> 8;
589 msg
->msg
[12] = phys_addr
& 0xff;
590 msg
->reply
= reply
? CEC_MSG_TIMER_CLEARED_STATUS
: 0;
593 static inline void cec_ops_clear_ext_timer(const struct cec_msg
*msg
,
606 *month
= msg
->msg
[3];
607 /* Hours and minutes are in BCD format */
608 *start_hr
= (msg
->msg
[4] >> 4) * 10 + (msg
->msg
[4] & 0xf);
609 *start_min
= (msg
->msg
[5] >> 4) * 10 + (msg
->msg
[5] & 0xf);
610 *duration_hr
= (msg
->msg
[6] >> 4) * 10 + (msg
->msg
[6] & 0xf);
611 *duration_min
= (msg
->msg
[7] >> 4) * 10 + (msg
->msg
[7] & 0xf);
612 *recording_seq
= msg
->msg
[8];
613 *ext_src_spec
= msg
->msg
[9];
614 *plug
= msg
->msg
[10];
615 *phys_addr
= (msg
->msg
[11] << 8) | msg
->msg
[12];
618 static inline void cec_msg_set_analogue_timer(struct cec_msg
*msg
,
632 msg
->msg
[1] = CEC_MSG_SET_ANALOGUE_TIMER
;
635 /* Hours and minutes are in BCD format */
636 msg
->msg
[4] = ((start_hr
/ 10) << 4) | (start_hr
% 10);
637 msg
->msg
[5] = ((start_min
/ 10) << 4) | (start_min
% 10);
638 msg
->msg
[6] = ((duration_hr
/ 10) << 4) | (duration_hr
% 10);
639 msg
->msg
[7] = ((duration_min
/ 10) << 4) | (duration_min
% 10);
640 msg
->msg
[8] = recording_seq
;
641 msg
->msg
[9] = ana_bcast_type
;
642 msg
->msg
[10] = ana_freq
>> 8;
643 msg
->msg
[11] = ana_freq
& 0xff;
644 msg
->msg
[12] = bcast_system
;
645 msg
->reply
= reply
? CEC_MSG_TIMER_STATUS
: 0;
648 static inline void cec_ops_set_analogue_timer(const struct cec_msg
*msg
,
656 __u8
*ana_bcast_type
,
661 *month
= msg
->msg
[3];
662 /* Hours and minutes are in BCD format */
663 *start_hr
= (msg
->msg
[4] >> 4) * 10 + (msg
->msg
[4] & 0xf);
664 *start_min
= (msg
->msg
[5] >> 4) * 10 + (msg
->msg
[5] & 0xf);
665 *duration_hr
= (msg
->msg
[6] >> 4) * 10 + (msg
->msg
[6] & 0xf);
666 *duration_min
= (msg
->msg
[7] >> 4) * 10 + (msg
->msg
[7] & 0xf);
667 *recording_seq
= msg
->msg
[8];
668 *ana_bcast_type
= msg
->msg
[9];
669 *ana_freq
= (msg
->msg
[10] << 8) | msg
->msg
[11];
670 *bcast_system
= msg
->msg
[12];
673 static inline void cec_msg_set_digital_timer(struct cec_msg
*msg
,
682 const struct cec_op_digital_service_id
*digital
)
685 msg
->reply
= reply
? CEC_MSG_TIMER_STATUS
: 0;
686 msg
->msg
[1] = CEC_MSG_SET_DIGITAL_TIMER
;
689 /* Hours and minutes are in BCD format */
690 msg
->msg
[4] = ((start_hr
/ 10) << 4) | (start_hr
% 10);
691 msg
->msg
[5] = ((start_min
/ 10) << 4) | (start_min
% 10);
692 msg
->msg
[6] = ((duration_hr
/ 10) << 4) | (duration_hr
% 10);
693 msg
->msg
[7] = ((duration_min
/ 10) << 4) | (duration_min
% 10);
694 msg
->msg
[8] = recording_seq
;
695 cec_set_digital_service_id(msg
->msg
+ 9, digital
);
698 static inline void cec_ops_set_digital_timer(const struct cec_msg
*msg
,
706 struct cec_op_digital_service_id
*digital
)
709 *month
= msg
->msg
[3];
710 /* Hours and minutes are in BCD format */
711 *start_hr
= (msg
->msg
[4] >> 4) * 10 + (msg
->msg
[4] & 0xf);
712 *start_min
= (msg
->msg
[5] >> 4) * 10 + (msg
->msg
[5] & 0xf);
713 *duration_hr
= (msg
->msg
[6] >> 4) * 10 + (msg
->msg
[6] & 0xf);
714 *duration_min
= (msg
->msg
[7] >> 4) * 10 + (msg
->msg
[7] & 0xf);
715 *recording_seq
= msg
->msg
[8];
716 cec_get_digital_service_id(msg
->msg
+ 9, digital
);
719 static inline void cec_msg_set_ext_timer(struct cec_msg
*msg
,
733 msg
->msg
[1] = CEC_MSG_SET_EXT_TIMER
;
736 /* Hours and minutes are in BCD format */
737 msg
->msg
[4] = ((start_hr
/ 10) << 4) | (start_hr
% 10);
738 msg
->msg
[5] = ((start_min
/ 10) << 4) | (start_min
% 10);
739 msg
->msg
[6] = ((duration_hr
/ 10) << 4) | (duration_hr
% 10);
740 msg
->msg
[7] = ((duration_min
/ 10) << 4) | (duration_min
% 10);
741 msg
->msg
[8] = recording_seq
;
742 msg
->msg
[9] = ext_src_spec
;
744 msg
->msg
[11] = phys_addr
>> 8;
745 msg
->msg
[12] = phys_addr
& 0xff;
746 msg
->reply
= reply
? CEC_MSG_TIMER_STATUS
: 0;
749 static inline void cec_ops_set_ext_timer(const struct cec_msg
*msg
,
762 *month
= msg
->msg
[3];
763 /* Hours and minutes are in BCD format */
764 *start_hr
= (msg
->msg
[4] >> 4) * 10 + (msg
->msg
[4] & 0xf);
765 *start_min
= (msg
->msg
[5] >> 4) * 10 + (msg
->msg
[5] & 0xf);
766 *duration_hr
= (msg
->msg
[6] >> 4) * 10 + (msg
->msg
[6] & 0xf);
767 *duration_min
= (msg
->msg
[7] >> 4) * 10 + (msg
->msg
[7] & 0xf);
768 *recording_seq
= msg
->msg
[8];
769 *ext_src_spec
= msg
->msg
[9];
770 *plug
= msg
->msg
[10];
771 *phys_addr
= (msg
->msg
[11] << 8) | msg
->msg
[12];
774 static inline void cec_msg_set_timer_program_title(struct cec_msg
*msg
,
775 const char *prog_title
)
777 unsigned int len
= strlen(prog_title
);
782 msg
->msg
[1] = CEC_MSG_SET_TIMER_PROGRAM_TITLE
;
783 memcpy(msg
->msg
+ 2, prog_title
, len
);
786 static inline void cec_ops_set_timer_program_title(const struct cec_msg
*msg
,
789 unsigned int len
= msg
->len
> 2 ? msg
->len
- 2 : 0;
793 memcpy(prog_title
, msg
->msg
+ 2, len
);
794 prog_title
[len
] = '\0';
797 /* System Information Feature */
798 static inline void cec_msg_cec_version(struct cec_msg
*msg
, __u8 cec_version
)
801 msg
->msg
[1] = CEC_MSG_CEC_VERSION
;
802 msg
->msg
[2] = cec_version
;
805 static inline void cec_ops_cec_version(const struct cec_msg
*msg
,
808 *cec_version
= msg
->msg
[2];
811 static inline void cec_msg_get_cec_version(struct cec_msg
*msg
,
815 msg
->msg
[1] = CEC_MSG_GET_CEC_VERSION
;
816 msg
->reply
= reply
? CEC_MSG_CEC_VERSION
: 0;
819 static inline void cec_msg_report_physical_addr(struct cec_msg
*msg
,
820 __u16 phys_addr
, __u8 prim_devtype
)
823 msg
->msg
[0] |= 0xf; /* broadcast */
824 msg
->msg
[1] = CEC_MSG_REPORT_PHYSICAL_ADDR
;
825 msg
->msg
[2] = phys_addr
>> 8;
826 msg
->msg
[3] = phys_addr
& 0xff;
827 msg
->msg
[4] = prim_devtype
;
830 static inline void cec_ops_report_physical_addr(const struct cec_msg
*msg
,
831 __u16
*phys_addr
, __u8
*prim_devtype
)
833 *phys_addr
= (msg
->msg
[2] << 8) | msg
->msg
[3];
834 *prim_devtype
= msg
->msg
[4];
837 static inline void cec_msg_give_physical_addr(struct cec_msg
*msg
,
841 msg
->msg
[1] = CEC_MSG_GIVE_PHYSICAL_ADDR
;
842 msg
->reply
= reply
? CEC_MSG_REPORT_PHYSICAL_ADDR
: 0;
845 static inline void cec_msg_set_menu_language(struct cec_msg
*msg
,
846 const char *language
)
849 msg
->msg
[0] |= 0xf; /* broadcast */
850 msg
->msg
[1] = CEC_MSG_SET_MENU_LANGUAGE
;
851 memcpy(msg
->msg
+ 2, language
, 3);
854 static inline void cec_ops_set_menu_language(const struct cec_msg
*msg
,
857 memcpy(language
, msg
->msg
+ 2, 3);
861 static inline void cec_msg_get_menu_language(struct cec_msg
*msg
,
865 msg
->msg
[1] = CEC_MSG_GET_MENU_LANGUAGE
;
866 msg
->reply
= reply
? CEC_MSG_SET_MENU_LANGUAGE
: 0;
870 * Assumes a single RC Profile byte and a single Device Features byte,
871 * i.e. no extended features are supported by this helper function.
873 * As of CEC 2.0 no extended features are defined, should those be added
874 * in the future, then this function needs to be adapted or a new function
877 static inline void cec_msg_report_features(struct cec_msg
*msg
,
878 __u8 cec_version
, __u8 all_device_types
,
879 __u8 rc_profile
, __u8 dev_features
)
882 msg
->msg
[0] |= 0xf; /* broadcast */
883 msg
->msg
[1] = CEC_MSG_REPORT_FEATURES
;
884 msg
->msg
[2] = cec_version
;
885 msg
->msg
[3] = all_device_types
;
886 msg
->msg
[4] = rc_profile
;
887 msg
->msg
[5] = dev_features
;
890 static inline void cec_ops_report_features(const struct cec_msg
*msg
,
891 __u8
*cec_version
, __u8
*all_device_types
,
892 const __u8
**rc_profile
, const __u8
**dev_features
)
894 const __u8
*p
= &msg
->msg
[4];
896 *cec_version
= msg
->msg
[2];
897 *all_device_types
= msg
->msg
[3];
899 *dev_features
= NULL
;
900 while (p
< &msg
->msg
[14] && (*p
& CEC_OP_FEAT_EXT
))
902 if (!(*p
& CEC_OP_FEAT_EXT
)) {
903 *dev_features
= p
+ 1;
904 while (p
< &msg
->msg
[15] && (*p
& CEC_OP_FEAT_EXT
))
907 if (*p
& CEC_OP_FEAT_EXT
)
908 *rc_profile
= *dev_features
= NULL
;
911 static inline void cec_msg_give_features(struct cec_msg
*msg
,
915 msg
->msg
[1] = CEC_MSG_GIVE_FEATURES
;
916 msg
->reply
= reply
? CEC_MSG_REPORT_FEATURES
: 0;
919 /* Deck Control Feature */
920 static inline void cec_msg_deck_control(struct cec_msg
*msg
,
921 __u8 deck_control_mode
)
924 msg
->msg
[1] = CEC_MSG_DECK_CONTROL
;
925 msg
->msg
[2] = deck_control_mode
;
928 static inline void cec_ops_deck_control(const struct cec_msg
*msg
,
929 __u8
*deck_control_mode
)
931 *deck_control_mode
= msg
->msg
[2];
934 static inline void cec_msg_deck_status(struct cec_msg
*msg
,
938 msg
->msg
[1] = CEC_MSG_DECK_STATUS
;
939 msg
->msg
[2] = deck_info
;
942 static inline void cec_ops_deck_status(const struct cec_msg
*msg
,
945 *deck_info
= msg
->msg
[2];
948 static inline void cec_msg_give_deck_status(struct cec_msg
*msg
,
953 msg
->msg
[1] = CEC_MSG_GIVE_DECK_STATUS
;
954 msg
->msg
[2] = status_req
;
955 msg
->reply
= reply
? CEC_MSG_DECK_STATUS
: 0;
958 static inline void cec_ops_give_deck_status(const struct cec_msg
*msg
,
961 *status_req
= msg
->msg
[2];
964 static inline void cec_msg_play(struct cec_msg
*msg
,
968 msg
->msg
[1] = CEC_MSG_PLAY
;
969 msg
->msg
[2] = play_mode
;
972 static inline void cec_ops_play(const struct cec_msg
*msg
,
975 *play_mode
= msg
->msg
[2];
979 /* Tuner Control Feature */
980 struct cec_op_tuner_device_info
{
982 __u8 tuner_display_info
;
985 struct cec_op_digital_service_id digital
;
994 static inline void cec_msg_tuner_device_status_analog(struct cec_msg
*msg
,
996 __u8 tuner_display_info
,
1002 msg
->msg
[1] = CEC_MSG_TUNER_DEVICE_STATUS
;
1003 msg
->msg
[2] = (rec_flag
<< 7) | tuner_display_info
;
1004 msg
->msg
[3] = ana_bcast_type
;
1005 msg
->msg
[4] = ana_freq
>> 8;
1006 msg
->msg
[5] = ana_freq
& 0xff;
1007 msg
->msg
[6] = bcast_system
;
1010 static inline void cec_msg_tuner_device_status_digital(struct cec_msg
*msg
,
1011 __u8 rec_flag
, __u8 tuner_display_info
,
1012 const struct cec_op_digital_service_id
*digital
)
1015 msg
->msg
[1] = CEC_MSG_TUNER_DEVICE_STATUS
;
1016 msg
->msg
[2] = (rec_flag
<< 7) | tuner_display_info
;
1017 cec_set_digital_service_id(msg
->msg
+ 3, digital
);
1020 static inline void cec_msg_tuner_device_status(struct cec_msg
*msg
,
1021 const struct cec_op_tuner_device_info
*tuner_dev_info
)
1023 if (tuner_dev_info
->is_analog
)
1024 cec_msg_tuner_device_status_analog(msg
,
1025 tuner_dev_info
->rec_flag
,
1026 tuner_dev_info
->tuner_display_info
,
1027 tuner_dev_info
->analog
.ana_bcast_type
,
1028 tuner_dev_info
->analog
.ana_freq
,
1029 tuner_dev_info
->analog
.bcast_system
);
1031 cec_msg_tuner_device_status_digital(msg
,
1032 tuner_dev_info
->rec_flag
,
1033 tuner_dev_info
->tuner_display_info
,
1034 &tuner_dev_info
->digital
);
1037 static inline void cec_ops_tuner_device_status(const struct cec_msg
*msg
,
1038 struct cec_op_tuner_device_info
*tuner_dev_info
)
1040 tuner_dev_info
->is_analog
= msg
->len
< 10;
1041 tuner_dev_info
->rec_flag
= msg
->msg
[2] >> 7;
1042 tuner_dev_info
->tuner_display_info
= msg
->msg
[2] & 0x7f;
1043 if (tuner_dev_info
->is_analog
) {
1044 tuner_dev_info
->analog
.ana_bcast_type
= msg
->msg
[3];
1045 tuner_dev_info
->analog
.ana_freq
= (msg
->msg
[4] << 8) | msg
->msg
[5];
1046 tuner_dev_info
->analog
.bcast_system
= msg
->msg
[6];
1049 cec_get_digital_service_id(msg
->msg
+ 3, &tuner_dev_info
->digital
);
1052 static inline void cec_msg_give_tuner_device_status(struct cec_msg
*msg
,
1057 msg
->msg
[1] = CEC_MSG_GIVE_TUNER_DEVICE_STATUS
;
1058 msg
->msg
[2] = status_req
;
1059 msg
->reply
= reply
? CEC_MSG_TUNER_DEVICE_STATUS
: 0;
1062 static inline void cec_ops_give_tuner_device_status(const struct cec_msg
*msg
,
1065 *status_req
= msg
->msg
[2];
1068 static inline void cec_msg_select_analogue_service(struct cec_msg
*msg
,
1069 __u8 ana_bcast_type
,
1074 msg
->msg
[1] = CEC_MSG_SELECT_ANALOGUE_SERVICE
;
1075 msg
->msg
[2] = ana_bcast_type
;
1076 msg
->msg
[3] = ana_freq
>> 8;
1077 msg
->msg
[4] = ana_freq
& 0xff;
1078 msg
->msg
[5] = bcast_system
;
1081 static inline void cec_ops_select_analogue_service(const struct cec_msg
*msg
,
1082 __u8
*ana_bcast_type
,
1086 *ana_bcast_type
= msg
->msg
[2];
1087 *ana_freq
= (msg
->msg
[3] << 8) | msg
->msg
[4];
1088 *bcast_system
= msg
->msg
[5];
1091 static inline void cec_msg_select_digital_service(struct cec_msg
*msg
,
1092 const struct cec_op_digital_service_id
*digital
)
1095 msg
->msg
[1] = CEC_MSG_SELECT_DIGITAL_SERVICE
;
1096 cec_set_digital_service_id(msg
->msg
+ 2, digital
);
1099 static inline void cec_ops_select_digital_service(const struct cec_msg
*msg
,
1100 struct cec_op_digital_service_id
*digital
)
1102 cec_get_digital_service_id(msg
->msg
+ 2, digital
);
1105 static inline void cec_msg_tuner_step_decrement(struct cec_msg
*msg
)
1108 msg
->msg
[1] = CEC_MSG_TUNER_STEP_DECREMENT
;
1111 static inline void cec_msg_tuner_step_increment(struct cec_msg
*msg
)
1114 msg
->msg
[1] = CEC_MSG_TUNER_STEP_INCREMENT
;
1118 /* Vendor Specific Commands Feature */
1119 static inline void cec_msg_device_vendor_id(struct cec_msg
*msg
, __u32 vendor_id
)
1122 msg
->msg
[0] |= 0xf; /* broadcast */
1123 msg
->msg
[1] = CEC_MSG_DEVICE_VENDOR_ID
;
1124 msg
->msg
[2] = vendor_id
>> 16;
1125 msg
->msg
[3] = (vendor_id
>> 8) & 0xff;
1126 msg
->msg
[4] = vendor_id
& 0xff;
1129 static inline void cec_ops_device_vendor_id(const struct cec_msg
*msg
,
1132 *vendor_id
= (msg
->msg
[2] << 16) | (msg
->msg
[3] << 8) | msg
->msg
[4];
1135 static inline void cec_msg_give_device_vendor_id(struct cec_msg
*msg
,
1139 msg
->msg
[1] = CEC_MSG_GIVE_DEVICE_VENDOR_ID
;
1140 msg
->reply
= reply
? CEC_MSG_DEVICE_VENDOR_ID
: 0;
1143 static inline void cec_msg_vendor_command(struct cec_msg
*msg
,
1144 __u8 size
, const __u8
*vendor_cmd
)
1148 msg
->len
= 2 + size
;
1149 msg
->msg
[1] = CEC_MSG_VENDOR_COMMAND
;
1150 memcpy(msg
->msg
+ 2, vendor_cmd
, size
);
1153 static inline void cec_ops_vendor_command(const struct cec_msg
*msg
,
1155 const __u8
**vendor_cmd
)
1157 *size
= msg
->len
- 2;
1161 *vendor_cmd
= msg
->msg
+ 2;
1164 static inline void cec_msg_vendor_command_with_id(struct cec_msg
*msg
,
1165 __u32 vendor_id
, __u8 size
,
1166 const __u8
*vendor_cmd
)
1170 msg
->len
= 5 + size
;
1171 msg
->msg
[1] = CEC_MSG_VENDOR_COMMAND_WITH_ID
;
1172 msg
->msg
[2] = vendor_id
>> 16;
1173 msg
->msg
[3] = (vendor_id
>> 8) & 0xff;
1174 msg
->msg
[4] = vendor_id
& 0xff;
1175 memcpy(msg
->msg
+ 5, vendor_cmd
, size
);
1178 static inline void cec_ops_vendor_command_with_id(const struct cec_msg
*msg
,
1179 __u32
*vendor_id
, __u8
*size
,
1180 const __u8
**vendor_cmd
)
1182 *size
= msg
->len
- 5;
1186 *vendor_id
= (msg
->msg
[2] << 16) | (msg
->msg
[3] << 8) | msg
->msg
[4];
1187 *vendor_cmd
= msg
->msg
+ 5;
1190 static inline void cec_msg_vendor_remote_button_down(struct cec_msg
*msg
,
1192 const __u8
*rc_code
)
1196 msg
->len
= 2 + size
;
1197 msg
->msg
[1] = CEC_MSG_VENDOR_REMOTE_BUTTON_DOWN
;
1198 memcpy(msg
->msg
+ 2, rc_code
, size
);
1201 static inline void cec_ops_vendor_remote_button_down(const struct cec_msg
*msg
,
1203 const __u8
**rc_code
)
1205 *size
= msg
->len
- 2;
1209 *rc_code
= msg
->msg
+ 2;
1212 static inline void cec_msg_vendor_remote_button_up(struct cec_msg
*msg
)
1215 msg
->msg
[1] = CEC_MSG_VENDOR_REMOTE_BUTTON_UP
;
1219 /* OSD Display Feature */
1220 static inline void cec_msg_set_osd_string(struct cec_msg
*msg
,
1224 unsigned int len
= strlen(osd
);
1229 msg
->msg
[1] = CEC_MSG_SET_OSD_STRING
;
1230 msg
->msg
[2] = disp_ctl
;
1231 memcpy(msg
->msg
+ 3, osd
, len
);
1234 static inline void cec_ops_set_osd_string(const struct cec_msg
*msg
,
1238 unsigned int len
= msg
->len
> 3 ? msg
->len
- 3 : 0;
1240 *disp_ctl
= msg
->msg
[2];
1243 memcpy(osd
, msg
->msg
+ 3, len
);
1248 /* Device OSD Transfer Feature */
1249 static inline void cec_msg_set_osd_name(struct cec_msg
*msg
, const char *name
)
1251 unsigned int len
= strlen(name
);
1256 msg
->msg
[1] = CEC_MSG_SET_OSD_NAME
;
1257 memcpy(msg
->msg
+ 2, name
, len
);
1260 static inline void cec_ops_set_osd_name(const struct cec_msg
*msg
,
1263 unsigned int len
= msg
->len
> 2 ? msg
->len
- 2 : 0;
1267 memcpy(name
, msg
->msg
+ 2, len
);
1271 static inline void cec_msg_give_osd_name(struct cec_msg
*msg
,
1275 msg
->msg
[1] = CEC_MSG_GIVE_OSD_NAME
;
1276 msg
->reply
= reply
? CEC_MSG_SET_OSD_NAME
: 0;
1280 /* Device Menu Control Feature */
1281 static inline void cec_msg_menu_status(struct cec_msg
*msg
,
1285 msg
->msg
[1] = CEC_MSG_MENU_STATUS
;
1286 msg
->msg
[2] = menu_state
;
1289 static inline void cec_ops_menu_status(const struct cec_msg
*msg
,
1292 *menu_state
= msg
->msg
[2];
1295 static inline void cec_msg_menu_request(struct cec_msg
*msg
,
1300 msg
->msg
[1] = CEC_MSG_MENU_REQUEST
;
1301 msg
->msg
[2] = menu_req
;
1302 msg
->reply
= reply
? CEC_MSG_MENU_STATUS
: 0;
1305 static inline void cec_ops_menu_request(const struct cec_msg
*msg
,
1308 *menu_req
= msg
->msg
[2];
1311 struct cec_op_ui_command
{
1315 struct cec_op_channel_data channel_identifier
;
1316 __u8 ui_broadcast_type
;
1317 __u8 ui_sound_presentation_control
;
1319 __u8 ui_function_media
;
1320 __u8 ui_function_select_av_input
;
1321 __u8 ui_function_select_audio_input
;
1325 static inline void cec_msg_user_control_pressed(struct cec_msg
*msg
,
1326 const struct cec_op_ui_command
*ui_cmd
)
1329 msg
->msg
[1] = CEC_MSG_USER_CONTROL_PRESSED
;
1330 msg
->msg
[2] = ui_cmd
->ui_cmd
;
1331 if (!ui_cmd
->has_opt_arg
)
1333 switch (ui_cmd
->ui_cmd
) {
1340 /* The optional operand is one byte for all these ui commands */
1342 msg
->msg
[3] = ui_cmd
->play_mode
;
1346 msg
->msg
[3] = (ui_cmd
->channel_identifier
.channel_number_fmt
<< 2) |
1347 (ui_cmd
->channel_identifier
.major
>> 8);
1348 msg
->msg
[4] = ui_cmd
->channel_identifier
.major
& 0xff;
1349 msg
->msg
[5] = ui_cmd
->channel_identifier
.minor
>> 8;
1350 msg
->msg
[6] = ui_cmd
->channel_identifier
.minor
& 0xff;
1355 static inline void cec_ops_user_control_pressed(const struct cec_msg
*msg
,
1356 struct cec_op_ui_command
*ui_cmd
)
1358 ui_cmd
->ui_cmd
= msg
->msg
[2];
1359 ui_cmd
->has_opt_arg
= 0;
1362 switch (ui_cmd
->ui_cmd
) {
1369 /* The optional operand is one byte for all these ui commands */
1370 ui_cmd
->play_mode
= msg
->msg
[3];
1371 ui_cmd
->has_opt_arg
= 1;
1376 ui_cmd
->has_opt_arg
= 1;
1377 ui_cmd
->channel_identifier
.channel_number_fmt
= msg
->msg
[3] >> 2;
1378 ui_cmd
->channel_identifier
.major
= ((msg
->msg
[3] & 3) << 6) | msg
->msg
[4];
1379 ui_cmd
->channel_identifier
.minor
= (msg
->msg
[5] << 8) | msg
->msg
[6];
1384 static inline void cec_msg_user_control_released(struct cec_msg
*msg
)
1387 msg
->msg
[1] = CEC_MSG_USER_CONTROL_RELEASED
;
1390 /* Remote Control Passthrough Feature */
1392 /* Power Status Feature */
1393 static inline void cec_msg_report_power_status(struct cec_msg
*msg
,
1397 msg
->msg
[1] = CEC_MSG_REPORT_POWER_STATUS
;
1398 msg
->msg
[2] = pwr_state
;
1401 static inline void cec_ops_report_power_status(const struct cec_msg
*msg
,
1404 *pwr_state
= msg
->msg
[2];
1407 static inline void cec_msg_give_device_power_status(struct cec_msg
*msg
,
1411 msg
->msg
[1] = CEC_MSG_GIVE_DEVICE_POWER_STATUS
;
1412 msg
->reply
= reply
? CEC_MSG_REPORT_POWER_STATUS
: 0;
1415 /* General Protocol Messages */
1416 static inline void cec_msg_feature_abort(struct cec_msg
*msg
,
1417 __u8 abort_msg
, __u8 reason
)
1420 msg
->msg
[1] = CEC_MSG_FEATURE_ABORT
;
1421 msg
->msg
[2] = abort_msg
;
1422 msg
->msg
[3] = reason
;
1425 static inline void cec_ops_feature_abort(const struct cec_msg
*msg
,
1426 __u8
*abort_msg
, __u8
*reason
)
1428 *abort_msg
= msg
->msg
[2];
1429 *reason
= msg
->msg
[3];
1432 /* This changes the current message into a feature abort message */
1433 static inline void cec_msg_reply_feature_abort(struct cec_msg
*msg
, __u8 reason
)
1435 cec_msg_set_reply_to(msg
, msg
);
1437 msg
->msg
[2] = msg
->msg
[1];
1438 msg
->msg
[3] = reason
;
1439 msg
->msg
[1] = CEC_MSG_FEATURE_ABORT
;
1442 static inline void cec_msg_abort(struct cec_msg
*msg
)
1445 msg
->msg
[1] = CEC_MSG_ABORT
;
1449 /* System Audio Control Feature */
1450 static inline void cec_msg_report_audio_status(struct cec_msg
*msg
,
1451 __u8 aud_mute_status
,
1452 __u8 aud_vol_status
)
1455 msg
->msg
[1] = CEC_MSG_REPORT_AUDIO_STATUS
;
1456 msg
->msg
[2] = (aud_mute_status
<< 7) | (aud_vol_status
& 0x7f);
1459 static inline void cec_ops_report_audio_status(const struct cec_msg
*msg
,
1460 __u8
*aud_mute_status
,
1461 __u8
*aud_vol_status
)
1463 *aud_mute_status
= msg
->msg
[2] >> 7;
1464 *aud_vol_status
= msg
->msg
[2] & 0x7f;
1467 static inline void cec_msg_give_audio_status(struct cec_msg
*msg
,
1471 msg
->msg
[1] = CEC_MSG_GIVE_AUDIO_STATUS
;
1472 msg
->reply
= reply
? CEC_MSG_REPORT_AUDIO_STATUS
: 0;
1475 static inline void cec_msg_set_system_audio_mode(struct cec_msg
*msg
,
1476 __u8 sys_aud_status
)
1479 msg
->msg
[1] = CEC_MSG_SET_SYSTEM_AUDIO_MODE
;
1480 msg
->msg
[2] = sys_aud_status
;
1483 static inline void cec_ops_set_system_audio_mode(const struct cec_msg
*msg
,
1484 __u8
*sys_aud_status
)
1486 *sys_aud_status
= msg
->msg
[2];
1489 static inline void cec_msg_system_audio_mode_request(struct cec_msg
*msg
,
1493 msg
->len
= phys_addr
== 0xffff ? 2 : 4;
1494 msg
->msg
[1] = CEC_MSG_SYSTEM_AUDIO_MODE_REQUEST
;
1495 msg
->msg
[2] = phys_addr
>> 8;
1496 msg
->msg
[3] = phys_addr
& 0xff;
1497 msg
->reply
= reply
? CEC_MSG_SET_SYSTEM_AUDIO_MODE
: 0;
1501 static inline void cec_ops_system_audio_mode_request(const struct cec_msg
*msg
,
1505 *phys_addr
= 0xffff;
1507 *phys_addr
= (msg
->msg
[2] << 8) | msg
->msg
[3];
1510 static inline void cec_msg_system_audio_mode_status(struct cec_msg
*msg
,
1511 __u8 sys_aud_status
)
1514 msg
->msg
[1] = CEC_MSG_SYSTEM_AUDIO_MODE_STATUS
;
1515 msg
->msg
[2] = sys_aud_status
;
1518 static inline void cec_ops_system_audio_mode_status(const struct cec_msg
*msg
,
1519 __u8
*sys_aud_status
)
1521 *sys_aud_status
= msg
->msg
[2];
1524 static inline void cec_msg_give_system_audio_mode_status(struct cec_msg
*msg
,
1528 msg
->msg
[1] = CEC_MSG_GIVE_SYSTEM_AUDIO_MODE_STATUS
;
1529 msg
->reply
= reply
? CEC_MSG_SYSTEM_AUDIO_MODE_STATUS
: 0;
1532 static inline void cec_msg_report_short_audio_descriptor(struct cec_msg
*msg
,
1533 __u8 num_descriptors
,
1534 const __u32
*descriptors
)
1538 if (num_descriptors
> 4)
1539 num_descriptors
= 4;
1540 msg
->len
= 2 + num_descriptors
* 3;
1541 msg
->msg
[1] = CEC_MSG_REPORT_SHORT_AUDIO_DESCRIPTOR
;
1542 for (i
= 0; i
< num_descriptors
; i
++) {
1543 msg
->msg
[2 + i
* 3] = (descriptors
[i
] >> 16) & 0xff;
1544 msg
->msg
[3 + i
* 3] = (descriptors
[i
] >> 8) & 0xff;
1545 msg
->msg
[4 + i
* 3] = descriptors
[i
] & 0xff;
1549 static inline void cec_ops_report_short_audio_descriptor(const struct cec_msg
*msg
,
1550 __u8
*num_descriptors
,
1555 *num_descriptors
= (msg
->len
- 2) / 3;
1556 if (*num_descriptors
> 4)
1557 *num_descriptors
= 4;
1558 for (i
= 0; i
< *num_descriptors
; i
++)
1559 descriptors
[i
] = (msg
->msg
[2 + i
* 3] << 16) |
1560 (msg
->msg
[3 + i
* 3] << 8) |
1561 msg
->msg
[4 + i
* 3];
1564 static inline void cec_msg_request_short_audio_descriptor(struct cec_msg
*msg
,
1566 __u8 num_descriptors
,
1567 const __u8
*audio_format_id
,
1568 const __u8
*audio_format_code
)
1572 if (num_descriptors
> 4)
1573 num_descriptors
= 4;
1574 msg
->len
= 2 + num_descriptors
;
1575 msg
->msg
[1] = CEC_MSG_REQUEST_SHORT_AUDIO_DESCRIPTOR
;
1576 msg
->reply
= reply
? CEC_MSG_REPORT_SHORT_AUDIO_DESCRIPTOR
: 0;
1577 for (i
= 0; i
< num_descriptors
; i
++)
1578 msg
->msg
[2 + i
] = (audio_format_id
[i
] << 6) |
1579 (audio_format_code
[i
] & 0x3f);
1582 static inline void cec_ops_request_short_audio_descriptor(const struct cec_msg
*msg
,
1583 __u8
*num_descriptors
,
1584 __u8
*audio_format_id
,
1585 __u8
*audio_format_code
)
1589 *num_descriptors
= msg
->len
- 2;
1590 if (*num_descriptors
> 4)
1591 *num_descriptors
= 4;
1592 for (i
= 0; i
< *num_descriptors
; i
++) {
1593 audio_format_id
[i
] = msg
->msg
[2 + i
] >> 6;
1594 audio_format_code
[i
] = msg
->msg
[2 + i
] & 0x3f;
1599 /* Audio Rate Control Feature */
1600 static inline void cec_msg_set_audio_rate(struct cec_msg
*msg
,
1604 msg
->msg
[1] = CEC_MSG_SET_AUDIO_RATE
;
1605 msg
->msg
[2] = audio_rate
;
1608 static inline void cec_ops_set_audio_rate(const struct cec_msg
*msg
,
1611 *audio_rate
= msg
->msg
[2];
1615 /* Audio Return Channel Control Feature */
1616 static inline void cec_msg_report_arc_initiated(struct cec_msg
*msg
)
1619 msg
->msg
[1] = CEC_MSG_REPORT_ARC_INITIATED
;
1622 static inline void cec_msg_initiate_arc(struct cec_msg
*msg
,
1626 msg
->msg
[1] = CEC_MSG_INITIATE_ARC
;
1627 msg
->reply
= reply
? CEC_MSG_REPORT_ARC_INITIATED
: 0;
1630 static inline void cec_msg_request_arc_initiation(struct cec_msg
*msg
,
1634 msg
->msg
[1] = CEC_MSG_REQUEST_ARC_INITIATION
;
1635 msg
->reply
= reply
? CEC_MSG_INITIATE_ARC
: 0;
1638 static inline void cec_msg_report_arc_terminated(struct cec_msg
*msg
)
1641 msg
->msg
[1] = CEC_MSG_REPORT_ARC_TERMINATED
;
1644 static inline void cec_msg_terminate_arc(struct cec_msg
*msg
,
1648 msg
->msg
[1] = CEC_MSG_TERMINATE_ARC
;
1649 msg
->reply
= reply
? CEC_MSG_REPORT_ARC_TERMINATED
: 0;
1652 static inline void cec_msg_request_arc_termination(struct cec_msg
*msg
,
1656 msg
->msg
[1] = CEC_MSG_REQUEST_ARC_TERMINATION
;
1657 msg
->reply
= reply
? CEC_MSG_TERMINATE_ARC
: 0;
1661 /* Dynamic Audio Lipsync Feature */
1662 /* Only for CEC 2.0 and up */
1663 static inline void cec_msg_report_current_latency(struct cec_msg
*msg
,
1666 __u8 low_latency_mode
,
1667 __u8 audio_out_compensated
,
1668 __u8 audio_out_delay
)
1671 msg
->msg
[0] |= 0xf; /* broadcast */
1672 msg
->msg
[1] = CEC_MSG_REPORT_CURRENT_LATENCY
;
1673 msg
->msg
[2] = phys_addr
>> 8;
1674 msg
->msg
[3] = phys_addr
& 0xff;
1675 msg
->msg
[4] = video_latency
;
1676 msg
->msg
[5] = (low_latency_mode
<< 2) | audio_out_compensated
;
1677 if (audio_out_compensated
== 3)
1678 msg
->msg
[msg
->len
++] = audio_out_delay
;
1681 static inline void cec_ops_report_current_latency(const struct cec_msg
*msg
,
1683 __u8
*video_latency
,
1684 __u8
*low_latency_mode
,
1685 __u8
*audio_out_compensated
,
1686 __u8
*audio_out_delay
)
1688 *phys_addr
= (msg
->msg
[2] << 8) | msg
->msg
[3];
1689 *video_latency
= msg
->msg
[4];
1690 *low_latency_mode
= (msg
->msg
[5] >> 2) & 1;
1691 *audio_out_compensated
= msg
->msg
[5] & 3;
1692 if (*audio_out_compensated
== 3 && msg
->len
>= 7)
1693 *audio_out_delay
= msg
->msg
[6];
1695 *audio_out_delay
= 0;
1698 static inline void cec_msg_request_current_latency(struct cec_msg
*msg
,
1703 msg
->msg
[0] |= 0xf; /* broadcast */
1704 msg
->msg
[1] = CEC_MSG_REQUEST_CURRENT_LATENCY
;
1705 msg
->msg
[2] = phys_addr
>> 8;
1706 msg
->msg
[3] = phys_addr
& 0xff;
1707 msg
->reply
= reply
? CEC_MSG_REPORT_CURRENT_LATENCY
: 0;
1710 static inline void cec_ops_request_current_latency(const struct cec_msg
*msg
,
1713 *phys_addr
= (msg
->msg
[2] << 8) | msg
->msg
[3];
1717 /* Capability Discovery and Control Feature */
1718 static inline void cec_msg_cdc_hec_inquire_state(struct cec_msg
*msg
,
1723 msg
->msg
[0] |= 0xf; /* broadcast */
1724 msg
->msg
[1] = CEC_MSG_CDC_MESSAGE
;
1725 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1726 msg
->msg
[4] = CEC_MSG_CDC_HEC_INQUIRE_STATE
;
1727 msg
->msg
[5] = phys_addr1
>> 8;
1728 msg
->msg
[6] = phys_addr1
& 0xff;
1729 msg
->msg
[7] = phys_addr2
>> 8;
1730 msg
->msg
[8] = phys_addr2
& 0xff;
1733 static inline void cec_ops_cdc_hec_inquire_state(const struct cec_msg
*msg
,
1738 *phys_addr
= (msg
->msg
[2] << 8) | msg
->msg
[3];
1739 *phys_addr1
= (msg
->msg
[5] << 8) | msg
->msg
[6];
1740 *phys_addr2
= (msg
->msg
[7] << 8) | msg
->msg
[8];
1743 static inline void cec_msg_cdc_hec_report_state(struct cec_msg
*msg
,
1744 __u16 target_phys_addr
,
1745 __u8 hec_func_state
,
1746 __u8 host_func_state
,
1747 __u8 enc_func_state
,
1752 msg
->len
= has_field
? 10 : 8;
1753 msg
->msg
[0] |= 0xf; /* broadcast */
1754 msg
->msg
[1] = CEC_MSG_CDC_MESSAGE
;
1755 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1756 msg
->msg
[4] = CEC_MSG_CDC_HEC_REPORT_STATE
;
1757 msg
->msg
[5] = target_phys_addr
>> 8;
1758 msg
->msg
[6] = target_phys_addr
& 0xff;
1759 msg
->msg
[7] = (hec_func_state
<< 6) |
1760 (host_func_state
<< 4) |
1761 (enc_func_state
<< 2) |
1764 msg
->msg
[8] = hec_field
>> 8;
1765 msg
->msg
[9] = hec_field
& 0xff;
1769 static inline void cec_ops_cdc_hec_report_state(const struct cec_msg
*msg
,
1771 __u16
*target_phys_addr
,
1772 __u8
*hec_func_state
,
1773 __u8
*host_func_state
,
1774 __u8
*enc_func_state
,
1779 *phys_addr
= (msg
->msg
[2] << 8) | msg
->msg
[3];
1780 *target_phys_addr
= (msg
->msg
[5] << 8) | msg
->msg
[6];
1781 *hec_func_state
= msg
->msg
[7] >> 6;
1782 *host_func_state
= (msg
->msg
[7] >> 4) & 3;
1783 *enc_func_state
= (msg
->msg
[7] >> 4) & 3;
1784 *cdc_errcode
= msg
->msg
[7] & 3;
1785 *has_field
= msg
->len
>= 10;
1786 *hec_field
= *has_field
? ((msg
->msg
[8] << 8) | msg
->msg
[9]) : 0;
1789 static inline void cec_msg_cdc_hec_set_state(struct cec_msg
*msg
,
1798 msg
->msg
[0] |= 0xf; /* broadcast */
1799 msg
->msg
[1] = CEC_MSG_CDC_MESSAGE
;
1800 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1801 msg
->msg
[4] = CEC_MSG_CDC_HEC_INQUIRE_STATE
;
1802 msg
->msg
[5] = phys_addr1
>> 8;
1803 msg
->msg
[6] = phys_addr1
& 0xff;
1804 msg
->msg
[7] = phys_addr2
>> 8;
1805 msg
->msg
[8] = phys_addr2
& 0xff;
1806 msg
->msg
[9] = hec_set_state
;
1807 if (phys_addr3
!= CEC_PHYS_ADDR_INVALID
) {
1808 msg
->msg
[msg
->len
++] = phys_addr3
>> 8;
1809 msg
->msg
[msg
->len
++] = phys_addr3
& 0xff;
1810 if (phys_addr4
!= CEC_PHYS_ADDR_INVALID
) {
1811 msg
->msg
[msg
->len
++] = phys_addr4
>> 8;
1812 msg
->msg
[msg
->len
++] = phys_addr4
& 0xff;
1813 if (phys_addr5
!= CEC_PHYS_ADDR_INVALID
) {
1814 msg
->msg
[msg
->len
++] = phys_addr5
>> 8;
1815 msg
->msg
[msg
->len
++] = phys_addr5
& 0xff;
1821 static inline void cec_ops_cdc_hec_set_state(const struct cec_msg
*msg
,
1825 __u8
*hec_set_state
,
1830 *phys_addr
= (msg
->msg
[2] << 8) | msg
->msg
[3];
1831 *phys_addr1
= (msg
->msg
[5] << 8) | msg
->msg
[6];
1832 *phys_addr2
= (msg
->msg
[7] << 8) | msg
->msg
[8];
1833 *hec_set_state
= msg
->msg
[9];
1834 *phys_addr3
= *phys_addr4
= *phys_addr5
= CEC_PHYS_ADDR_INVALID
;
1836 *phys_addr3
= (msg
->msg
[10] << 8) | msg
->msg
[11];
1838 *phys_addr4
= (msg
->msg
[12] << 8) | msg
->msg
[13];
1840 *phys_addr5
= (msg
->msg
[14] << 8) | msg
->msg
[15];
1843 static inline void cec_msg_cdc_hec_set_state_adjacent(struct cec_msg
*msg
,
1848 msg
->msg
[0] |= 0xf; /* broadcast */
1849 msg
->msg
[1] = CEC_MSG_CDC_MESSAGE
;
1850 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1851 msg
->msg
[4] = CEC_MSG_CDC_HEC_SET_STATE_ADJACENT
;
1852 msg
->msg
[5] = phys_addr1
>> 8;
1853 msg
->msg
[6] = phys_addr1
& 0xff;
1854 msg
->msg
[7] = hec_set_state
;
1857 static inline void cec_ops_cdc_hec_set_state_adjacent(const struct cec_msg
*msg
,
1860 __u8
*hec_set_state
)
1862 *phys_addr
= (msg
->msg
[2] << 8) | msg
->msg
[3];
1863 *phys_addr1
= (msg
->msg
[5] << 8) | msg
->msg
[6];
1864 *hec_set_state
= msg
->msg
[7];
1867 static inline void cec_msg_cdc_hec_request_deactivation(struct cec_msg
*msg
,
1873 msg
->msg
[0] |= 0xf; /* broadcast */
1874 msg
->msg
[1] = CEC_MSG_CDC_MESSAGE
;
1875 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1876 msg
->msg
[4] = CEC_MSG_CDC_HEC_REQUEST_DEACTIVATION
;
1877 msg
->msg
[5] = phys_addr1
>> 8;
1878 msg
->msg
[6] = phys_addr1
& 0xff;
1879 msg
->msg
[7] = phys_addr2
>> 8;
1880 msg
->msg
[8] = phys_addr2
& 0xff;
1881 msg
->msg
[9] = phys_addr3
>> 8;
1882 msg
->msg
[10] = phys_addr3
& 0xff;
1885 static inline void cec_ops_cdc_hec_request_deactivation(const struct cec_msg
*msg
,
1891 *phys_addr
= (msg
->msg
[2] << 8) | msg
->msg
[3];
1892 *phys_addr1
= (msg
->msg
[5] << 8) | msg
->msg
[6];
1893 *phys_addr2
= (msg
->msg
[7] << 8) | msg
->msg
[8];
1894 *phys_addr3
= (msg
->msg
[9] << 8) | msg
->msg
[10];
1897 static inline void cec_msg_cdc_hec_notify_alive(struct cec_msg
*msg
)
1900 msg
->msg
[0] |= 0xf; /* broadcast */
1901 msg
->msg
[1] = CEC_MSG_CDC_MESSAGE
;
1902 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1903 msg
->msg
[4] = CEC_MSG_CDC_HEC_NOTIFY_ALIVE
;
1906 static inline void cec_ops_cdc_hec_notify_alive(const struct cec_msg
*msg
,
1909 *phys_addr
= (msg
->msg
[2] << 8) | msg
->msg
[3];
1912 static inline void cec_msg_cdc_hec_discover(struct cec_msg
*msg
)
1915 msg
->msg
[0] |= 0xf; /* broadcast */
1916 msg
->msg
[1] = CEC_MSG_CDC_MESSAGE
;
1917 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1918 msg
->msg
[4] = CEC_MSG_CDC_HEC_DISCOVER
;
1921 static inline void cec_ops_cdc_hec_discover(const struct cec_msg
*msg
,
1924 *phys_addr
= (msg
->msg
[2] << 8) | msg
->msg
[3];
1927 static inline void cec_msg_cdc_hpd_set_state(struct cec_msg
*msg
,
1932 msg
->msg
[0] |= 0xf; /* broadcast */
1933 msg
->msg
[1] = CEC_MSG_CDC_MESSAGE
;
1934 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1935 msg
->msg
[4] = CEC_MSG_CDC_HPD_SET_STATE
;
1936 msg
->msg
[5] = (input_port
<< 4) | hpd_state
;
1939 static inline void cec_ops_cdc_hpd_set_state(const struct cec_msg
*msg
,
1944 *phys_addr
= (msg
->msg
[2] << 8) | msg
->msg
[3];
1945 *input_port
= msg
->msg
[5] >> 4;
1946 *hpd_state
= msg
->msg
[5] & 0xf;
1949 static inline void cec_msg_cdc_hpd_report_state(struct cec_msg
*msg
,
1954 msg
->msg
[0] |= 0xf; /* broadcast */
1955 msg
->msg
[1] = CEC_MSG_CDC_MESSAGE
;
1956 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1957 msg
->msg
[4] = CEC_MSG_CDC_HPD_REPORT_STATE
;
1958 msg
->msg
[5] = (hpd_state
<< 4) | hpd_error
;
1961 static inline void cec_ops_cdc_hpd_report_state(const struct cec_msg
*msg
,
1966 *phys_addr
= (msg
->msg
[2] << 8) | msg
->msg
[3];
1967 *hpd_state
= msg
->msg
[5] >> 4;
1968 *hpd_error
= msg
->msg
[5] & 0xf;