1959 lines · c
1/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */2/*3 * cec - HDMI Consumer Electronics Control message functions4 *5 * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved.6 */7 8#ifndef _CEC_UAPI_FUNCS_H9#define _CEC_UAPI_FUNCS_H10 11#include <linux/cec.h>12 13/* One Touch Play Feature */14static inline void cec_msg_active_source(struct cec_msg *msg, __u16 phys_addr)15{16 msg->len = 4;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;21}22 23static inline void cec_ops_active_source(const struct cec_msg *msg,24 __u16 *phys_addr)25{26 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];27}28 29static inline void cec_msg_image_view_on(struct cec_msg *msg)30{31 msg->len = 2;32 msg->msg[1] = CEC_MSG_IMAGE_VIEW_ON;33}34 35static inline void cec_msg_text_view_on(struct cec_msg *msg)36{37 msg->len = 2;38 msg->msg[1] = CEC_MSG_TEXT_VIEW_ON;39}40 41 42/* Routing Control Feature */43static inline void cec_msg_inactive_source(struct cec_msg *msg,44 __u16 phys_addr)45{46 msg->len = 4;47 msg->msg[1] = CEC_MSG_INACTIVE_SOURCE;48 msg->msg[2] = phys_addr >> 8;49 msg->msg[3] = phys_addr & 0xff;50}51 52static inline void cec_ops_inactive_source(const struct cec_msg *msg,53 __u16 *phys_addr)54{55 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];56}57 58static inline void cec_msg_request_active_source(struct cec_msg *msg,59 int reply)60{61 msg->len = 2;62 msg->msg[0] |= 0xf; /* broadcast */63 msg->msg[1] = CEC_MSG_REQUEST_ACTIVE_SOURCE;64 msg->reply = reply ? CEC_MSG_ACTIVE_SOURCE : 0;65}66 67static inline void cec_msg_routing_information(struct cec_msg *msg,68 __u16 phys_addr)69{70 msg->len = 4;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;75}76 77static inline void cec_ops_routing_information(const struct cec_msg *msg,78 __u16 *phys_addr)79{80 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];81}82 83static inline void cec_msg_routing_change(struct cec_msg *msg,84 int reply,85 __u16 orig_phys_addr,86 __u16 new_phys_addr)87{88 msg->len = 6;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;96}97 98static inline void cec_ops_routing_change(const struct cec_msg *msg,99 __u16 *orig_phys_addr,100 __u16 *new_phys_addr)101{102 *orig_phys_addr = (msg->msg[2] << 8) | msg->msg[3];103 *new_phys_addr = (msg->msg[4] << 8) | msg->msg[5];104}105 106static inline void cec_msg_set_stream_path(struct cec_msg *msg, __u16 phys_addr)107{108 msg->len = 4;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;113}114 115static inline void cec_ops_set_stream_path(const struct cec_msg *msg,116 __u16 *phys_addr)117{118 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];119}120 121 122/* Standby Feature */123static inline void cec_msg_standby(struct cec_msg *msg)124{125 msg->len = 2;126 msg->msg[1] = CEC_MSG_STANDBY;127}128 129 130/* One Touch Record Feature */131static inline void cec_msg_record_off(struct cec_msg *msg, int reply)132{133 msg->len = 2;134 msg->msg[1] = CEC_MSG_RECORD_OFF;135 msg->reply = reply ? CEC_MSG_RECORD_STATUS : 0;136}137 138struct cec_op_arib_data {139 __u16 transport_id;140 __u16 service_id;141 __u16 orig_network_id;142};143 144struct cec_op_atsc_data {145 __u16 transport_id;146 __u16 program_number;147};148 149struct cec_op_dvb_data {150 __u16 transport_id;151 __u16 service_id;152 __u16 orig_network_id;153};154 155struct cec_op_channel_data {156 __u8 channel_number_fmt;157 __u16 major;158 __u16 minor;159};160 161struct cec_op_digital_service_id {162 __u8 service_id_method;163 __u8 dig_bcast_system;164 union {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;169 };170};171 172struct cec_op_record_src {173 __u8 type;174 union {175 struct cec_op_digital_service_id digital;176 struct {177 __u8 ana_bcast_type;178 __u16 ana_freq;179 __u8 bcast_system;180 } analog;181 struct {182 __u8 plug;183 } ext_plug;184 struct {185 __u16 phys_addr;186 } ext_phys_addr;187 };188};189 190static inline void cec_set_digital_service_id(__u8 *msg,191 const struct cec_op_digital_service_id *digital)192{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;200 *msg++ = 0;201 *msg++ = 0;202 return;203 }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;213 *msg++ = 0;214 *msg++ = 0;215 break;216 default: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;223 break;224 }225}226 227static inline void cec_get_digital_service_id(const __u8 *msg,228 struct cec_op_digital_service_id *digital)229{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];236 return;237 }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];241}242 243static inline void cec_msg_record_on_own(struct cec_msg *msg)244{245 msg->len = 3;246 msg->msg[1] = CEC_MSG_RECORD_ON;247 msg->msg[2] = CEC_OP_RECORD_SRC_OWN;248}249 250static inline void cec_msg_record_on_digital(struct cec_msg *msg,251 const struct cec_op_digital_service_id *digital)252{253 msg->len = 10;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);257}258 259static inline void cec_msg_record_on_analog(struct cec_msg *msg,260 __u8 ana_bcast_type,261 __u16 ana_freq,262 __u8 bcast_system)263{264 msg->len = 7;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;271}272 273static inline void cec_msg_record_on_plug(struct cec_msg *msg,274 __u8 plug)275{276 msg->len = 4;277 msg->msg[1] = CEC_MSG_RECORD_ON;278 msg->msg[2] = CEC_OP_RECORD_SRC_EXT_PLUG;279 msg->msg[3] = plug;280}281 282static inline void cec_msg_record_on_phys_addr(struct cec_msg *msg,283 __u16 phys_addr)284{285 msg->len = 5;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;290}291 292static inline void cec_msg_record_on(struct cec_msg *msg,293 int reply,294 const struct cec_op_record_src *rec_src)295{296 switch (rec_src->type) {297 case CEC_OP_RECORD_SRC_OWN:298 cec_msg_record_on_own(msg);299 break;300 case CEC_OP_RECORD_SRC_DIGITAL:301 cec_msg_record_on_digital(msg, &rec_src->digital);302 break;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);308 break;309 case CEC_OP_RECORD_SRC_EXT_PLUG:310 cec_msg_record_on_plug(msg, rec_src->ext_plug.plug);311 break;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);315 break;316 }317 msg->reply = reply ? CEC_MSG_RECORD_STATUS : 0;318}319 320static inline void cec_ops_record_on(const struct cec_msg *msg,321 struct cec_op_record_src *rec_src)322{323 rec_src->type = msg->msg[2];324 switch (rec_src->type) {325 case CEC_OP_RECORD_SRC_OWN:326 break;327 case CEC_OP_RECORD_SRC_DIGITAL:328 cec_get_digital_service_id(msg->msg + 3, &rec_src->digital);329 break;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];335 break;336 case CEC_OP_RECORD_SRC_EXT_PLUG:337 rec_src->ext_plug.plug = msg->msg[3];338 break;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];342 break;343 }344}345 346static inline void cec_msg_record_status(struct cec_msg *msg, __u8 rec_status)347{348 msg->len = 3;349 msg->msg[1] = CEC_MSG_RECORD_STATUS;350 msg->msg[2] = rec_status;351}352 353static inline void cec_ops_record_status(const struct cec_msg *msg,354 __u8 *rec_status)355{356 *rec_status = msg->msg[2];357}358 359static inline void cec_msg_record_tv_screen(struct cec_msg *msg,360 int reply)361{362 msg->len = 2;363 msg->msg[1] = CEC_MSG_RECORD_TV_SCREEN;364 msg->reply = reply ? CEC_MSG_RECORD_ON : 0;365}366 367 368/* Timer Programming Feature */369static inline void cec_msg_timer_status(struct cec_msg *msg,370 __u8 timer_overlap_warning,371 __u8 media_info,372 __u8 prog_info,373 __u8 prog_error,374 __u8 duration_hr,375 __u8 duration_min)376{377 msg->len = 3;378 msg->msg[1] = CEC_MSG_TIMER_STATUS;379 msg->msg[2] = (timer_overlap_warning << 7) |380 (media_info << 5) |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) {386 msg->len += 2;387 msg->msg[3] = ((duration_hr / 10) << 4) | (duration_hr % 10);388 msg->msg[4] = ((duration_min / 10) << 4) | (duration_min % 10);389 }390}391 392static inline void cec_ops_timer_status(const struct cec_msg *msg,393 __u8 *timer_overlap_warning,394 __u8 *media_info,395 __u8 *prog_info,396 __u8 *prog_error,397 __u8 *duration_hr,398 __u8 *duration_min)399{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;404 *prog_error = 0;405 } else {406 *prog_info = 0;407 *prog_error = msg->msg[2] & 0xf;408 }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);414 } else {415 *duration_hr = *duration_min = 0;416 }417}418 419static inline void cec_msg_timer_cleared_status(struct cec_msg *msg,420 __u8 timer_cleared_status)421{422 msg->len = 3;423 msg->msg[1] = CEC_MSG_TIMER_CLEARED_STATUS;424 msg->msg[2] = timer_cleared_status;425}426 427static inline void cec_ops_timer_cleared_status(const struct cec_msg *msg,428 __u8 *timer_cleared_status)429{430 *timer_cleared_status = msg->msg[2];431}432 433static inline void cec_msg_clear_analogue_timer(struct cec_msg *msg,434 int reply,435 __u8 day,436 __u8 month,437 __u8 start_hr,438 __u8 start_min,439 __u8 duration_hr,440 __u8 duration_min,441 __u8 recording_seq,442 __u8 ana_bcast_type,443 __u16 ana_freq,444 __u8 bcast_system)445{446 msg->len = 13;447 msg->msg[1] = CEC_MSG_CLEAR_ANALOGUE_TIMER;448 msg->msg[2] = day;449 msg->msg[3] = month;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;461}462 463static inline void cec_ops_clear_analogue_timer(const struct cec_msg *msg,464 __u8 *day,465 __u8 *month,466 __u8 *start_hr,467 __u8 *start_min,468 __u8 *duration_hr,469 __u8 *duration_min,470 __u8 *recording_seq,471 __u8 *ana_bcast_type,472 __u16 *ana_freq,473 __u8 *bcast_system)474{475 *day = msg->msg[2];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];486}487 488static inline void cec_msg_clear_digital_timer(struct cec_msg *msg,489 int reply,490 __u8 day,491 __u8 month,492 __u8 start_hr,493 __u8 start_min,494 __u8 duration_hr,495 __u8 duration_min,496 __u8 recording_seq,497 const struct cec_op_digital_service_id *digital)498{499 msg->len = 16;500 msg->reply = reply ? CEC_MSG_TIMER_CLEARED_STATUS : 0;501 msg->msg[1] = CEC_MSG_CLEAR_DIGITAL_TIMER;502 msg->msg[2] = day;503 msg->msg[3] = month;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);511}512 513static inline void cec_ops_clear_digital_timer(const struct cec_msg *msg,514 __u8 *day,515 __u8 *month,516 __u8 *start_hr,517 __u8 *start_min,518 __u8 *duration_hr,519 __u8 *duration_min,520 __u8 *recording_seq,521 struct cec_op_digital_service_id *digital)522{523 *day = msg->msg[2];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);532}533 534static inline void cec_msg_clear_ext_timer(struct cec_msg *msg,535 int reply,536 __u8 day,537 __u8 month,538 __u8 start_hr,539 __u8 start_min,540 __u8 duration_hr,541 __u8 duration_min,542 __u8 recording_seq,543 __u8 ext_src_spec,544 __u8 plug,545 __u16 phys_addr)546{547 msg->len = 13;548 msg->msg[1] = CEC_MSG_CLEAR_EXT_TIMER;549 msg->msg[2] = day;550 msg->msg[3] = month;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;558 msg->msg[10] = plug;559 msg->msg[11] = phys_addr >> 8;560 msg->msg[12] = phys_addr & 0xff;561 msg->reply = reply ? CEC_MSG_TIMER_CLEARED_STATUS : 0;562}563 564static inline void cec_ops_clear_ext_timer(const struct cec_msg *msg,565 __u8 *day,566 __u8 *month,567 __u8 *start_hr,568 __u8 *start_min,569 __u8 *duration_hr,570 __u8 *duration_min,571 __u8 *recording_seq,572 __u8 *ext_src_spec,573 __u8 *plug,574 __u16 *phys_addr)575{576 *day = msg->msg[2];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];587}588 589static inline void cec_msg_set_analogue_timer(struct cec_msg *msg,590 int reply,591 __u8 day,592 __u8 month,593 __u8 start_hr,594 __u8 start_min,595 __u8 duration_hr,596 __u8 duration_min,597 __u8 recording_seq,598 __u8 ana_bcast_type,599 __u16 ana_freq,600 __u8 bcast_system)601{602 msg->len = 13;603 msg->msg[1] = CEC_MSG_SET_ANALOGUE_TIMER;604 msg->msg[2] = day;605 msg->msg[3] = month;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;617}618 619static inline void cec_ops_set_analogue_timer(const struct cec_msg *msg,620 __u8 *day,621 __u8 *month,622 __u8 *start_hr,623 __u8 *start_min,624 __u8 *duration_hr,625 __u8 *duration_min,626 __u8 *recording_seq,627 __u8 *ana_bcast_type,628 __u16 *ana_freq,629 __u8 *bcast_system)630{631 *day = msg->msg[2];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];642}643 644static inline void cec_msg_set_digital_timer(struct cec_msg *msg,645 int reply,646 __u8 day,647 __u8 month,648 __u8 start_hr,649 __u8 start_min,650 __u8 duration_hr,651 __u8 duration_min,652 __u8 recording_seq,653 const struct cec_op_digital_service_id *digital)654{655 msg->len = 16;656 msg->reply = reply ? CEC_MSG_TIMER_STATUS : 0;657 msg->msg[1] = CEC_MSG_SET_DIGITAL_TIMER;658 msg->msg[2] = day;659 msg->msg[3] = month;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);667}668 669static inline void cec_ops_set_digital_timer(const struct cec_msg *msg,670 __u8 *day,671 __u8 *month,672 __u8 *start_hr,673 __u8 *start_min,674 __u8 *duration_hr,675 __u8 *duration_min,676 __u8 *recording_seq,677 struct cec_op_digital_service_id *digital)678{679 *day = msg->msg[2];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);688}689 690static inline void cec_msg_set_ext_timer(struct cec_msg *msg,691 int reply,692 __u8 day,693 __u8 month,694 __u8 start_hr,695 __u8 start_min,696 __u8 duration_hr,697 __u8 duration_min,698 __u8 recording_seq,699 __u8 ext_src_spec,700 __u8 plug,701 __u16 phys_addr)702{703 msg->len = 13;704 msg->msg[1] = CEC_MSG_SET_EXT_TIMER;705 msg->msg[2] = day;706 msg->msg[3] = month;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;714 msg->msg[10] = plug;715 msg->msg[11] = phys_addr >> 8;716 msg->msg[12] = phys_addr & 0xff;717 msg->reply = reply ? CEC_MSG_TIMER_STATUS : 0;718}719 720static inline void cec_ops_set_ext_timer(const struct cec_msg *msg,721 __u8 *day,722 __u8 *month,723 __u8 *start_hr,724 __u8 *start_min,725 __u8 *duration_hr,726 __u8 *duration_min,727 __u8 *recording_seq,728 __u8 *ext_src_spec,729 __u8 *plug,730 __u16 *phys_addr)731{732 *day = msg->msg[2];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];743}744 745static inline void cec_msg_set_timer_program_title(struct cec_msg *msg,746 const char *prog_title)747{748 unsigned int len = strlen(prog_title);749 750 if (len > 14)751 len = 14;752 msg->len = 2 + len;753 msg->msg[1] = CEC_MSG_SET_TIMER_PROGRAM_TITLE;754 memcpy(msg->msg + 2, prog_title, len);755}756 757static inline void cec_ops_set_timer_program_title(const struct cec_msg *msg,758 char *prog_title)759{760 unsigned int len = msg->len > 2 ? msg->len - 2 : 0;761 762 if (len > 14)763 len = 14;764 memcpy(prog_title, msg->msg + 2, len);765 prog_title[len] = '\0';766}767 768/* System Information Feature */769static inline void cec_msg_cec_version(struct cec_msg *msg, __u8 cec_version)770{771 msg->len = 3;772 msg->msg[1] = CEC_MSG_CEC_VERSION;773 msg->msg[2] = cec_version;774}775 776static inline void cec_ops_cec_version(const struct cec_msg *msg,777 __u8 *cec_version)778{779 *cec_version = msg->msg[2];780}781 782static inline void cec_msg_get_cec_version(struct cec_msg *msg,783 int reply)784{785 msg->len = 2;786 msg->msg[1] = CEC_MSG_GET_CEC_VERSION;787 msg->reply = reply ? CEC_MSG_CEC_VERSION : 0;788}789 790static inline void cec_msg_report_physical_addr(struct cec_msg *msg,791 __u16 phys_addr, __u8 prim_devtype)792{793 msg->len = 5;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;799}800 801static inline void cec_ops_report_physical_addr(const struct cec_msg *msg,802 __u16 *phys_addr, __u8 *prim_devtype)803{804 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];805 *prim_devtype = msg->msg[4];806}807 808static inline void cec_msg_give_physical_addr(struct cec_msg *msg,809 int reply)810{811 msg->len = 2;812 msg->msg[1] = CEC_MSG_GIVE_PHYSICAL_ADDR;813 msg->reply = reply ? CEC_MSG_REPORT_PHYSICAL_ADDR : 0;814}815 816static inline void cec_msg_set_menu_language(struct cec_msg *msg,817 const char *language)818{819 msg->len = 5;820 msg->msg[0] |= 0xf; /* broadcast */821 msg->msg[1] = CEC_MSG_SET_MENU_LANGUAGE;822 memcpy(msg->msg + 2, language, 3);823}824 825static inline void cec_ops_set_menu_language(const struct cec_msg *msg,826 char *language)827{828 memcpy(language, msg->msg + 2, 3);829 language[3] = '\0';830}831 832static inline void cec_msg_get_menu_language(struct cec_msg *msg,833 int reply)834{835 msg->len = 2;836 msg->msg[1] = CEC_MSG_GET_MENU_LANGUAGE;837 msg->reply = reply ? CEC_MSG_SET_MENU_LANGUAGE : 0;838}839 840/*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.843 *844 * As of CEC 2.0 no extended features are defined, should those be added845 * in the future, then this function needs to be adapted or a new function846 * should be added.847 */848static 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)851{852 msg->len = 6;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;859}860 861static 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)864{865 const __u8 *p = &msg->msg[4];866 867 *cec_version = msg->msg[2];868 *all_device_types = msg->msg[3];869 *rc_profile = p;870 *dev_features = NULL;871 while (p < &msg->msg[14] && (*p & CEC_OP_FEAT_EXT))872 p++;873 if (!(*p & CEC_OP_FEAT_EXT)) {874 *dev_features = p + 1;875 while (p < &msg->msg[15] && (*p & CEC_OP_FEAT_EXT))876 p++;877 }878 if (*p & CEC_OP_FEAT_EXT)879 *rc_profile = *dev_features = NULL;880}881 882static inline void cec_msg_give_features(struct cec_msg *msg,883 int reply)884{885 msg->len = 2;886 msg->msg[1] = CEC_MSG_GIVE_FEATURES;887 msg->reply = reply ? CEC_MSG_REPORT_FEATURES : 0;888}889 890/* Deck Control Feature */891static inline void cec_msg_deck_control(struct cec_msg *msg,892 __u8 deck_control_mode)893{894 msg->len = 3;895 msg->msg[1] = CEC_MSG_DECK_CONTROL;896 msg->msg[2] = deck_control_mode;897}898 899static inline void cec_ops_deck_control(const struct cec_msg *msg,900 __u8 *deck_control_mode)901{902 *deck_control_mode = msg->msg[2];903}904 905static inline void cec_msg_deck_status(struct cec_msg *msg,906 __u8 deck_info)907{908 msg->len = 3;909 msg->msg[1] = CEC_MSG_DECK_STATUS;910 msg->msg[2] = deck_info;911}912 913static inline void cec_ops_deck_status(const struct cec_msg *msg,914 __u8 *deck_info)915{916 *deck_info = msg->msg[2];917}918 919static inline void cec_msg_give_deck_status(struct cec_msg *msg,920 int reply,921 __u8 status_req)922{923 msg->len = 3;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;928}929 930static inline void cec_ops_give_deck_status(const struct cec_msg *msg,931 __u8 *status_req)932{933 *status_req = msg->msg[2];934}935 936static inline void cec_msg_play(struct cec_msg *msg,937 __u8 play_mode)938{939 msg->len = 3;940 msg->msg[1] = CEC_MSG_PLAY;941 msg->msg[2] = play_mode;942}943 944static inline void cec_ops_play(const struct cec_msg *msg,945 __u8 *play_mode)946{947 *play_mode = msg->msg[2];948}949 950 951/* Tuner Control Feature */952struct cec_op_tuner_device_info {953 __u8 rec_flag;954 __u8 tuner_display_info;955 __u8 is_analog;956 union {957 struct cec_op_digital_service_id digital;958 struct {959 __u8 ana_bcast_type;960 __u16 ana_freq;961 __u8 bcast_system;962 } analog;963 };964};965 966static inline void cec_msg_tuner_device_status_analog(struct cec_msg *msg,967 __u8 rec_flag,968 __u8 tuner_display_info,969 __u8 ana_bcast_type,970 __u16 ana_freq,971 __u8 bcast_system)972{973 msg->len = 7;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;980}981 982static 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)985{986 msg->len = 10;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);990}991 992static inline void cec_msg_tuner_device_status(struct cec_msg *msg,993 const struct cec_op_tuner_device_info *tuner_dev_info)994{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);1002 else1003 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);1007}1008 1009static inline void cec_ops_tuner_device_status(const struct cec_msg *msg,1010 struct cec_op_tuner_device_info *tuner_dev_info)1011{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];1019 return;1020 }1021 cec_get_digital_service_id(msg->msg + 3, &tuner_dev_info->digital);1022}1023 1024static inline void cec_msg_give_tuner_device_status(struct cec_msg *msg,1025 int reply,1026 __u8 status_req)1027{1028 msg->len = 3;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;1033}1034 1035static inline void cec_ops_give_tuner_device_status(const struct cec_msg *msg,1036 __u8 *status_req)1037{1038 *status_req = msg->msg[2];1039}1040 1041static inline void cec_msg_select_analogue_service(struct cec_msg *msg,1042 __u8 ana_bcast_type,1043 __u16 ana_freq,1044 __u8 bcast_system)1045{1046 msg->len = 6;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;1052}1053 1054static inline void cec_ops_select_analogue_service(const struct cec_msg *msg,1055 __u8 *ana_bcast_type,1056 __u16 *ana_freq,1057 __u8 *bcast_system)1058{1059 *ana_bcast_type = msg->msg[2];1060 *ana_freq = (msg->msg[3] << 8) | msg->msg[4];1061 *bcast_system = msg->msg[5];1062}1063 1064static inline void cec_msg_select_digital_service(struct cec_msg *msg,1065 const struct cec_op_digital_service_id *digital)1066{1067 msg->len = 9;1068 msg->msg[1] = CEC_MSG_SELECT_DIGITAL_SERVICE;1069 cec_set_digital_service_id(msg->msg + 2, digital);1070}1071 1072static inline void cec_ops_select_digital_service(const struct cec_msg *msg,1073 struct cec_op_digital_service_id *digital)1074{1075 cec_get_digital_service_id(msg->msg + 2, digital);1076}1077 1078static inline void cec_msg_tuner_step_decrement(struct cec_msg *msg)1079{1080 msg->len = 2;1081 msg->msg[1] = CEC_MSG_TUNER_STEP_DECREMENT;1082}1083 1084static inline void cec_msg_tuner_step_increment(struct cec_msg *msg)1085{1086 msg->len = 2;1087 msg->msg[1] = CEC_MSG_TUNER_STEP_INCREMENT;1088}1089 1090 1091/* Vendor Specific Commands Feature */1092static inline void cec_msg_device_vendor_id(struct cec_msg *msg, __u32 vendor_id)1093{1094 msg->len = 5;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;1100}1101 1102static inline void cec_ops_device_vendor_id(const struct cec_msg *msg,1103 __u32 *vendor_id)1104{1105 *vendor_id = (msg->msg[2] << 16) | (msg->msg[3] << 8) | msg->msg[4];1106}1107 1108static inline void cec_msg_give_device_vendor_id(struct cec_msg *msg,1109 int reply)1110{1111 msg->len = 2;1112 msg->msg[1] = CEC_MSG_GIVE_DEVICE_VENDOR_ID;1113 msg->reply = reply ? CEC_MSG_DEVICE_VENDOR_ID : 0;1114}1115 1116static inline void cec_msg_vendor_command(struct cec_msg *msg,1117 __u8 size, const __u8 *vendor_cmd)1118{1119 if (size > 14)1120 size = 14;1121 msg->len = 2 + size;1122 msg->msg[1] = CEC_MSG_VENDOR_COMMAND;1123 memcpy(msg->msg + 2, vendor_cmd, size);1124}1125 1126static inline void cec_ops_vendor_command(const struct cec_msg *msg,1127 __u8 *size,1128 const __u8 **vendor_cmd)1129{1130 *size = msg->len - 2;1131 1132 if (*size > 14)1133 *size = 14;1134 *vendor_cmd = msg->msg + 2;1135}1136 1137static inline void cec_msg_vendor_command_with_id(struct cec_msg *msg,1138 __u32 vendor_id, __u8 size,1139 const __u8 *vendor_cmd)1140{1141 if (size > 11)1142 size = 11;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);1149}1150 1151static inline void cec_ops_vendor_command_with_id(const struct cec_msg *msg,1152 __u32 *vendor_id, __u8 *size,1153 const __u8 **vendor_cmd)1154{1155 *size = msg->len - 5;1156 1157 if (*size > 11)1158 *size = 11;1159 *vendor_id = (msg->msg[2] << 16) | (msg->msg[3] << 8) | msg->msg[4];1160 *vendor_cmd = msg->msg + 5;1161}1162 1163static inline void cec_msg_vendor_remote_button_down(struct cec_msg *msg,1164 __u8 size,1165 const __u8 *rc_code)1166{1167 if (size > 14)1168 size = 14;1169 msg->len = 2 + size;1170 msg->msg[1] = CEC_MSG_VENDOR_REMOTE_BUTTON_DOWN;1171 memcpy(msg->msg + 2, rc_code, size);1172}1173 1174static inline void cec_ops_vendor_remote_button_down(const struct cec_msg *msg,1175 __u8 *size,1176 const __u8 **rc_code)1177{1178 *size = msg->len - 2;1179 1180 if (*size > 14)1181 *size = 14;1182 *rc_code = msg->msg + 2;1183}1184 1185static inline void cec_msg_vendor_remote_button_up(struct cec_msg *msg)1186{1187 msg->len = 2;1188 msg->msg[1] = CEC_MSG_VENDOR_REMOTE_BUTTON_UP;1189}1190 1191 1192/* OSD Display Feature */1193static inline void cec_msg_set_osd_string(struct cec_msg *msg,1194 __u8 disp_ctl,1195 const char *osd)1196{1197 unsigned int len = strlen(osd);1198 1199 if (len > 13)1200 len = 13;1201 msg->len = 3 + len;1202 msg->msg[1] = CEC_MSG_SET_OSD_STRING;1203 msg->msg[2] = disp_ctl;1204 memcpy(msg->msg + 3, osd, len);1205}1206 1207static inline void cec_ops_set_osd_string(const struct cec_msg *msg,1208 __u8 *disp_ctl,1209 char *osd)1210{1211 unsigned int len = msg->len > 3 ? msg->len - 3 : 0;1212 1213 *disp_ctl = msg->msg[2];1214 if (len > 13)1215 len = 13;1216 memcpy(osd, msg->msg + 3, len);1217 osd[len] = '\0';1218}1219 1220 1221/* Device OSD Transfer Feature */1222static inline void cec_msg_set_osd_name(struct cec_msg *msg, const char *name)1223{1224 unsigned int len = strlen(name);1225 1226 if (len > 14)1227 len = 14;1228 msg->len = 2 + len;1229 msg->msg[1] = CEC_MSG_SET_OSD_NAME;1230 memcpy(msg->msg + 2, name, len);1231}1232 1233static inline void cec_ops_set_osd_name(const struct cec_msg *msg,1234 char *name)1235{1236 unsigned int len = msg->len > 2 ? msg->len - 2 : 0;1237 1238 if (len > 14)1239 len = 14;1240 memcpy(name, msg->msg + 2, len);1241 name[len] = '\0';1242}1243 1244static inline void cec_msg_give_osd_name(struct cec_msg *msg,1245 int reply)1246{1247 msg->len = 2;1248 msg->msg[1] = CEC_MSG_GIVE_OSD_NAME;1249 msg->reply = reply ? CEC_MSG_SET_OSD_NAME : 0;1250}1251 1252 1253/* Device Menu Control Feature */1254static inline void cec_msg_menu_status(struct cec_msg *msg,1255 __u8 menu_state)1256{1257 msg->len = 3;1258 msg->msg[1] = CEC_MSG_MENU_STATUS;1259 msg->msg[2] = menu_state;1260}1261 1262static inline void cec_ops_menu_status(const struct cec_msg *msg,1263 __u8 *menu_state)1264{1265 *menu_state = msg->msg[2];1266}1267 1268static inline void cec_msg_menu_request(struct cec_msg *msg,1269 int reply,1270 __u8 menu_req)1271{1272 msg->len = 3;1273 msg->msg[1] = CEC_MSG_MENU_REQUEST;1274 msg->msg[2] = menu_req;1275 msg->reply = reply ? CEC_MSG_MENU_STATUS : 0;1276}1277 1278static inline void cec_ops_menu_request(const struct cec_msg *msg,1279 __u8 *menu_req)1280{1281 *menu_req = msg->msg[2];1282}1283 1284struct cec_op_ui_command {1285 __u8 ui_cmd;1286 __u8 has_opt_arg;1287 union {1288 struct cec_op_channel_data channel_identifier;1289 __u8 ui_broadcast_type;1290 __u8 ui_sound_presentation_control;1291 __u8 play_mode;1292 __u8 ui_function_media;1293 __u8 ui_function_select_av_input;1294 __u8 ui_function_select_audio_input;1295 };1296};1297 1298static inline void cec_msg_user_control_pressed(struct cec_msg *msg,1299 const struct cec_op_ui_command *ui_cmd)1300{1301 msg->len = 3;1302 msg->msg[1] = CEC_MSG_USER_CONTROL_PRESSED;1303 msg->msg[2] = ui_cmd->ui_cmd;1304 if (!ui_cmd->has_opt_arg)1305 return;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 */1314 msg->len++;1315 msg->msg[3] = ui_cmd->play_mode;1316 break;1317 case CEC_OP_UI_CMD_TUNE_FUNCTION:1318 msg->len += 4;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;1324 break;1325 }1326}1327 1328static inline void cec_ops_user_control_pressed(const struct cec_msg *msg,1329 struct cec_op_ui_command *ui_cmd)1330{1331 ui_cmd->ui_cmd = msg->msg[2];1332 ui_cmd->has_opt_arg = 0;1333 if (msg->len == 3)1334 return;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;1345 break;1346 case CEC_OP_UI_CMD_TUNE_FUNCTION:1347 if (msg->len < 7)1348 break;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];1353 break;1354 }1355}1356 1357static inline void cec_msg_user_control_released(struct cec_msg *msg)1358{1359 msg->len = 2;1360 msg->msg[1] = CEC_MSG_USER_CONTROL_RELEASED;1361}1362 1363/* Remote Control Passthrough Feature */1364 1365/* Power Status Feature */1366static inline void cec_msg_report_power_status(struct cec_msg *msg,1367 __u8 pwr_state)1368{1369 msg->len = 3;1370 msg->msg[1] = CEC_MSG_REPORT_POWER_STATUS;1371 msg->msg[2] = pwr_state;1372}1373 1374static inline void cec_ops_report_power_status(const struct cec_msg *msg,1375 __u8 *pwr_state)1376{1377 *pwr_state = msg->msg[2];1378}1379 1380static inline void cec_msg_give_device_power_status(struct cec_msg *msg,1381 int reply)1382{1383 msg->len = 2;1384 msg->msg[1] = CEC_MSG_GIVE_DEVICE_POWER_STATUS;1385 msg->reply = reply ? CEC_MSG_REPORT_POWER_STATUS : 0;1386}1387 1388/* General Protocol Messages */1389static inline void cec_msg_feature_abort(struct cec_msg *msg,1390 __u8 abort_msg, __u8 reason)1391{1392 msg->len = 4;1393 msg->msg[1] = CEC_MSG_FEATURE_ABORT;1394 msg->msg[2] = abort_msg;1395 msg->msg[3] = reason;1396}1397 1398static inline void cec_ops_feature_abort(const struct cec_msg *msg,1399 __u8 *abort_msg, __u8 *reason)1400{1401 *abort_msg = msg->msg[2];1402 *reason = msg->msg[3];1403}1404 1405/* This changes the current message into a feature abort message */1406static inline void cec_msg_reply_feature_abort(struct cec_msg *msg, __u8 reason)1407{1408 cec_msg_set_reply_to(msg, msg);1409 msg->len = 4;1410 msg->msg[2] = msg->msg[1];1411 msg->msg[3] = reason;1412 msg->msg[1] = CEC_MSG_FEATURE_ABORT;1413}1414 1415static inline void cec_msg_abort(struct cec_msg *msg)1416{1417 msg->len = 2;1418 msg->msg[1] = CEC_MSG_ABORT;1419}1420 1421 1422/* System Audio Control Feature */1423static inline void cec_msg_report_audio_status(struct cec_msg *msg,1424 __u8 aud_mute_status,1425 __u8 aud_vol_status)1426{1427 msg->len = 3;1428 msg->msg[1] = CEC_MSG_REPORT_AUDIO_STATUS;1429 msg->msg[2] = (aud_mute_status << 7) | (aud_vol_status & 0x7f);1430}1431 1432static inline void cec_ops_report_audio_status(const struct cec_msg *msg,1433 __u8 *aud_mute_status,1434 __u8 *aud_vol_status)1435{1436 *aud_mute_status = msg->msg[2] >> 7;1437 *aud_vol_status = msg->msg[2] & 0x7f;1438}1439 1440static inline void cec_msg_give_audio_status(struct cec_msg *msg,1441 int reply)1442{1443 msg->len = 2;1444 msg->msg[1] = CEC_MSG_GIVE_AUDIO_STATUS;1445 msg->reply = reply ? CEC_MSG_REPORT_AUDIO_STATUS : 0;1446}1447 1448static inline void cec_msg_set_system_audio_mode(struct cec_msg *msg,1449 __u8 sys_aud_status)1450{1451 msg->len = 3;1452 msg->msg[1] = CEC_MSG_SET_SYSTEM_AUDIO_MODE;1453 msg->msg[2] = sys_aud_status;1454}1455 1456static inline void cec_ops_set_system_audio_mode(const struct cec_msg *msg,1457 __u8 *sys_aud_status)1458{1459 *sys_aud_status = msg->msg[2];1460}1461 1462static inline void cec_msg_system_audio_mode_request(struct cec_msg *msg,1463 int reply,1464 __u16 phys_addr)1465{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;1471 1472}1473 1474static inline void cec_ops_system_audio_mode_request(const struct cec_msg *msg,1475 __u16 *phys_addr)1476{1477 if (msg->len < 4)1478 *phys_addr = 0xffff;1479 else1480 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];1481}1482 1483static inline void cec_msg_system_audio_mode_status(struct cec_msg *msg,1484 __u8 sys_aud_status)1485{1486 msg->len = 3;1487 msg->msg[1] = CEC_MSG_SYSTEM_AUDIO_MODE_STATUS;1488 msg->msg[2] = sys_aud_status;1489}1490 1491static inline void cec_ops_system_audio_mode_status(const struct cec_msg *msg,1492 __u8 *sys_aud_status)1493{1494 *sys_aud_status = msg->msg[2];1495}1496 1497static inline void cec_msg_give_system_audio_mode_status(struct cec_msg *msg,1498 int reply)1499{1500 msg->len = 2;1501 msg->msg[1] = CEC_MSG_GIVE_SYSTEM_AUDIO_MODE_STATUS;1502 msg->reply = reply ? CEC_MSG_SYSTEM_AUDIO_MODE_STATUS : 0;1503}1504 1505static inline void cec_msg_report_short_audio_descriptor(struct cec_msg *msg,1506 __u8 num_descriptors,1507 const __u32 *descriptors)1508{1509 unsigned int i;1510 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;1519 }1520}1521 1522static inline void cec_ops_report_short_audio_descriptor(const struct cec_msg *msg,1523 __u8 *num_descriptors,1524 __u32 *descriptors)1525{1526 unsigned int i;1527 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];1535}1536 1537static inline void cec_msg_request_short_audio_descriptor(struct cec_msg *msg,1538 int reply,1539 __u8 num_descriptors,1540 const __u8 *audio_format_id,1541 const __u8 *audio_format_code)1542{1543 unsigned int i;1544 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);1553}1554 1555static 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)1559{1560 unsigned int i;1561 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;1568 }1569}1570 1571static inline void cec_msg_set_audio_volume_level(struct cec_msg *msg,1572 __u8 audio_volume_level)1573{1574 msg->len = 3;1575 msg->msg[1] = CEC_MSG_SET_AUDIO_VOLUME_LEVEL;1576 msg->msg[2] = audio_volume_level;1577}1578 1579static inline void cec_ops_set_audio_volume_level(const struct cec_msg *msg,1580 __u8 *audio_volume_level)1581{1582 *audio_volume_level = msg->msg[2];1583}1584 1585 1586/* Audio Rate Control Feature */1587static inline void cec_msg_set_audio_rate(struct cec_msg *msg,1588 __u8 audio_rate)1589{1590 msg->len = 3;1591 msg->msg[1] = CEC_MSG_SET_AUDIO_RATE;1592 msg->msg[2] = audio_rate;1593}1594 1595static inline void cec_ops_set_audio_rate(const struct cec_msg *msg,1596 __u8 *audio_rate)1597{1598 *audio_rate = msg->msg[2];1599}1600 1601 1602/* Audio Return Channel Control Feature */1603static inline void cec_msg_report_arc_initiated(struct cec_msg *msg)1604{1605 msg->len = 2;1606 msg->msg[1] = CEC_MSG_REPORT_ARC_INITIATED;1607}1608 1609static inline void cec_msg_initiate_arc(struct cec_msg *msg,1610 int reply)1611{1612 msg->len = 2;1613 msg->msg[1] = CEC_MSG_INITIATE_ARC;1614 msg->reply = reply ? CEC_MSG_REPORT_ARC_INITIATED : 0;1615}1616 1617static inline void cec_msg_request_arc_initiation(struct cec_msg *msg,1618 int reply)1619{1620 msg->len = 2;1621 msg->msg[1] = CEC_MSG_REQUEST_ARC_INITIATION;1622 msg->reply = reply ? CEC_MSG_INITIATE_ARC : 0;1623}1624 1625static inline void cec_msg_report_arc_terminated(struct cec_msg *msg)1626{1627 msg->len = 2;1628 msg->msg[1] = CEC_MSG_REPORT_ARC_TERMINATED;1629}1630 1631static inline void cec_msg_terminate_arc(struct cec_msg *msg,1632 int reply)1633{1634 msg->len = 2;1635 msg->msg[1] = CEC_MSG_TERMINATE_ARC;1636 msg->reply = reply ? CEC_MSG_REPORT_ARC_TERMINATED : 0;1637}1638 1639static inline void cec_msg_request_arc_termination(struct cec_msg *msg,1640 int reply)1641{1642 msg->len = 2;1643 msg->msg[1] = CEC_MSG_REQUEST_ARC_TERMINATION;1644 msg->reply = reply ? CEC_MSG_TERMINATE_ARC : 0;1645}1646 1647 1648/* Dynamic Audio Lipsync Feature */1649/* Only for CEC 2.0 and up */1650static inline void cec_msg_report_current_latency(struct cec_msg *msg,1651 __u16 phys_addr,1652 __u8 video_latency,1653 __u8 low_latency_mode,1654 __u8 audio_out_compensated,1655 __u8 audio_out_delay)1656{1657 msg->len = 6;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;1666}1667 1668static inline void cec_ops_report_current_latency(const struct cec_msg *msg,1669 __u16 *phys_addr,1670 __u8 *video_latency,1671 __u8 *low_latency_mode,1672 __u8 *audio_out_compensated,1673 __u8 *audio_out_delay)1674{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];1681 else1682 *audio_out_delay = 1;1683}1684 1685static inline void cec_msg_request_current_latency(struct cec_msg *msg,1686 int reply,1687 __u16 phys_addr)1688{1689 msg->len = 4;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;1695}1696 1697static inline void cec_ops_request_current_latency(const struct cec_msg *msg,1698 __u16 *phys_addr)1699{1700 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];1701}1702 1703 1704/* Capability Discovery and Control Feature */1705static inline void cec_msg_cdc_hec_inquire_state(struct cec_msg *msg,1706 __u16 phys_addr1,1707 __u16 phys_addr2)1708{1709 msg->len = 9;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;1718}1719 1720static inline void cec_ops_cdc_hec_inquire_state(const struct cec_msg *msg,1721 __u16 *phys_addr,1722 __u16 *phys_addr1,1723 __u16 *phys_addr2)1724{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];1728}1729 1730static 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,1735 __u8 cdc_errcode,1736 __u8 has_field,1737 __u16 hec_field)1738{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) |1749 cdc_errcode;1750 if (has_field) {1751 msg->msg[8] = hec_field >> 8;1752 msg->msg[9] = hec_field & 0xff;1753 }1754}1755 1756static inline void cec_ops_cdc_hec_report_state(const struct cec_msg *msg,1757 __u16 *phys_addr,1758 __u16 *target_phys_addr,1759 __u8 *hec_func_state,1760 __u8 *host_func_state,1761 __u8 *enc_func_state,1762 __u8 *cdc_errcode,1763 __u8 *has_field,1764 __u16 *hec_field)1765{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;1774}1775 1776static inline void cec_msg_cdc_hec_set_state(struct cec_msg *msg,1777 __u16 phys_addr1,1778 __u16 phys_addr2,1779 __u8 hec_set_state,1780 __u16 phys_addr3,1781 __u16 phys_addr4,1782 __u16 phys_addr5)1783{1784 msg->len = 10;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;1803 }1804 }1805 }1806}1807 1808static inline void cec_ops_cdc_hec_set_state(const struct cec_msg *msg,1809 __u16 *phys_addr,1810 __u16 *phys_addr1,1811 __u16 *phys_addr2,1812 __u8 *hec_set_state,1813 __u16 *phys_addr3,1814 __u16 *phys_addr4,1815 __u16 *phys_addr5)1816{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;1822 if (msg->len >= 12)1823 *phys_addr3 = (msg->msg[10] << 8) | msg->msg[11];1824 if (msg->len >= 14)1825 *phys_addr4 = (msg->msg[12] << 8) | msg->msg[13];1826 if (msg->len >= 16)1827 *phys_addr5 = (msg->msg[14] << 8) | msg->msg[15];1828}1829 1830static inline void cec_msg_cdc_hec_set_state_adjacent(struct cec_msg *msg,1831 __u16 phys_addr1,1832 __u8 hec_set_state)1833{1834 msg->len = 8;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;1842}1843 1844static inline void cec_ops_cdc_hec_set_state_adjacent(const struct cec_msg *msg,1845 __u16 *phys_addr,1846 __u16 *phys_addr1,1847 __u8 *hec_set_state)1848{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];1852}1853 1854static inline void cec_msg_cdc_hec_request_deactivation(struct cec_msg *msg,1855 __u16 phys_addr1,1856 __u16 phys_addr2,1857 __u16 phys_addr3)1858{1859 msg->len = 11;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;1870}1871 1872static inline void cec_ops_cdc_hec_request_deactivation(const struct cec_msg *msg,1873 __u16 *phys_addr,1874 __u16 *phys_addr1,1875 __u16 *phys_addr2,1876 __u16 *phys_addr3)1877{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];1882}1883 1884static inline void cec_msg_cdc_hec_notify_alive(struct cec_msg *msg)1885{1886 msg->len = 5;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;1891}1892 1893static inline void cec_ops_cdc_hec_notify_alive(const struct cec_msg *msg,1894 __u16 *phys_addr)1895{1896 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];1897}1898 1899static inline void cec_msg_cdc_hec_discover(struct cec_msg *msg)1900{1901 msg->len = 5;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;1906}1907 1908static inline void cec_ops_cdc_hec_discover(const struct cec_msg *msg,1909 __u16 *phys_addr)1910{1911 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];1912}1913 1914static inline void cec_msg_cdc_hpd_set_state(struct cec_msg *msg,1915 __u8 input_port,1916 __u8 hpd_state)1917{1918 msg->len = 6;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;1924}1925 1926static inline void cec_ops_cdc_hpd_set_state(const struct cec_msg *msg,1927 __u16 *phys_addr,1928 __u8 *input_port,1929 __u8 *hpd_state)1930{1931 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];1932 *input_port = msg->msg[5] >> 4;1933 *hpd_state = msg->msg[5] & 0xf;1934}1935 1936static inline void cec_msg_cdc_hpd_report_state(struct cec_msg *msg,1937 __u8 hpd_state,1938 __u8 hpd_error)1939{1940 msg->len = 6;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;1946}1947 1948static inline void cec_ops_cdc_hpd_report_state(const struct cec_msg *msg,1949 __u16 *phys_addr,1950 __u8 *hpd_state,1951 __u8 *hpd_error)1952{1953 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];1954 *hpd_state = msg->msg[5] >> 4;1955 *hpd_error = msg->msg[5] & 0xf;1956}1957 1958#endif1959