Home | History | Annotate | Download | only in linux
      1 /* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
      2 /*
      3  * cec - HDMI Consumer Electronics Control message functions
      4  *
      5  * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
      6  */
      7 
      8 #ifndef _CEC_UAPI_FUNCS_H
      9 #define _CEC_UAPI_FUNCS_H
     10 
     11 #include <linux/cec.h>
     12 
     13 /* One Touch Play Feature */
     14 static 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 
     23 static 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 
     29 static 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 
     35 static 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 */
     43 static 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 
     52 static 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 
     58 static 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 
     67 static 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 
     77 static 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 
     83 static 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 
     98 static 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 
    106 static 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 
    115 static 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 */
    123 static 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 */
    131 static 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 
    138 struct cec_op_arib_data {
    139 	__u16 transport_id;
    140 	__u16 service_id;
    141 	__u16 orig_network_id;
    142 };
    143 
    144 struct cec_op_atsc_data {
    145 	__u16 transport_id;
    146 	__u16 program_number;
    147 };
    148 
    149 struct cec_op_dvb_data {
    150 	__u16 transport_id;
    151 	__u16 service_id;
    152 	__u16 orig_network_id;
    153 };
    154 
    155 struct cec_op_channel_data {
    156 	__u8 channel_number_fmt;
    157 	__u16 major;
    158 	__u16 minor;
    159 };
    160 
    161 struct 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 
    172 struct 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 
    190 static 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 
    227 static 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 
    243 static 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 
    250 static 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 
    259 static 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 
    273 static 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 
    282 static 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 
    292 static 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 
    320 static 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 
    346 static 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 
    353 static inline void cec_ops_record_status(const struct cec_msg *msg,
    354 					 __u8 *rec_status)
    355 {
    356 	*rec_status = msg->msg[2];
    357 }
    358 
    359 static 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 */
    369 static 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 
    392 static 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 
    419 static 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 
    427 static 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 
    433 static 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 
    463 static 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 
    488 static 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 
    513 static 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 
    534 static 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 
    564 static 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 
    589 static 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 
    619 static 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 
    644 static 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 
    669 static 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 
    690 static 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 
    720 static 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 
    745 static 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 
    757 static 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 */
    769 static 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 
    776 static inline void cec_ops_cec_version(const struct cec_msg *msg,
    777 				       __u8 *cec_version)
    778 {
    779 	*cec_version = msg->msg[2];
    780 }
    781 
    782 static 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 
    790 static 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 
    801 static 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 
    808 static 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 
    816 static 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 
    825 static 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 
    832 static 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 added
    845  * in the future, then this function needs to be adapted or a new function
    846  * should be added.
    847  */
    848 static inline void cec_msg_report_features(struct cec_msg *msg,
    849 				__u8 cec_version, __u8 all_device_types,
    850 				__u8 rc_profile, __u8 dev_features)
    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 
    861 static inline void cec_ops_report_features(const struct cec_msg *msg,
    862 			__u8 *cec_version, __u8 *all_device_types,
    863 			const __u8 **rc_profile, const __u8 **dev_features)
    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 
    882 static 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 */
    891 static 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 
    899 static 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 
    905 static 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 
    913 static inline void cec_ops_deck_status(const struct cec_msg *msg,
    914 				       __u8 *deck_info)
    915 {
    916 	*deck_info = msg->msg[2];
    917 }
    918 
    919 static 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 ? CEC_MSG_DECK_STATUS : 0;
    927 }
    928 
    929 static inline void cec_ops_give_deck_status(const struct cec_msg *msg,
    930 					    __u8 *status_req)
    931 {
    932 	*status_req = msg->msg[2];
    933 }
    934 
    935 static inline void cec_msg_play(struct cec_msg *msg,
    936 				__u8 play_mode)
    937 {
    938 	msg->len = 3;
    939 	msg->msg[1] = CEC_MSG_PLAY;
    940 	msg->msg[2] = play_mode;
    941 }
    942 
    943 static inline void cec_ops_play(const struct cec_msg *msg,
    944 				__u8 *play_mode)
    945 {
    946 	*play_mode = msg->msg[2];
    947 }
    948 
    949 
    950 /* Tuner Control Feature */
    951 struct cec_op_tuner_device_info {
    952 	__u8 rec_flag;
    953 	__u8 tuner_display_info;
    954 	__u8 is_analog;
    955 	union {
    956 		struct cec_op_digital_service_id digital;
    957 		struct {
    958 			__u8 ana_bcast_type;
    959 			__u16 ana_freq;
    960 			__u8 bcast_system;
    961 		} analog;
    962 	};
    963 };
    964 
    965 static inline void cec_msg_tuner_device_status_analog(struct cec_msg *msg,
    966 						      __u8 rec_flag,
    967 						      __u8 tuner_display_info,
    968 						      __u8 ana_bcast_type,
    969 						      __u16 ana_freq,
    970 						      __u8 bcast_system)
    971 {
    972 	msg->len = 7;
    973 	msg->msg[1] = CEC_MSG_TUNER_DEVICE_STATUS;
    974 	msg->msg[2] = (rec_flag << 7) | tuner_display_info;
    975 	msg->msg[3] = ana_bcast_type;
    976 	msg->msg[4] = ana_freq >> 8;
    977 	msg->msg[5] = ana_freq & 0xff;
    978 	msg->msg[6] = bcast_system;
    979 }
    980 
    981 static inline void cec_msg_tuner_device_status_digital(struct cec_msg *msg,
    982 		   __u8 rec_flag, __u8 tuner_display_info,
    983 		   const struct cec_op_digital_service_id *digital)
    984 {
    985 	msg->len = 10;
    986 	msg->msg[1] = CEC_MSG_TUNER_DEVICE_STATUS;
    987 	msg->msg[2] = (rec_flag << 7) | tuner_display_info;
    988 	cec_set_digital_service_id(msg->msg + 3, digital);
    989 }
    990 
    991 static inline void cec_msg_tuner_device_status(struct cec_msg *msg,
    992 			const struct cec_op_tuner_device_info *tuner_dev_info)
    993 {
    994 	if (tuner_dev_info->is_analog)
    995 		cec_msg_tuner_device_status_analog(msg,
    996 			tuner_dev_info->rec_flag,
    997 			tuner_dev_info->tuner_display_info,
    998 			tuner_dev_info->analog.ana_bcast_type,
    999 			tuner_dev_info->analog.ana_freq,
   1000 			tuner_dev_info->analog.bcast_system);
   1001 	else
   1002 		cec_msg_tuner_device_status_digital(msg,
   1003 			tuner_dev_info->rec_flag,
   1004 			tuner_dev_info->tuner_display_info,
   1005 			&tuner_dev_info->digital);
   1006 }
   1007 
   1008 static inline void cec_ops_tuner_device_status(const struct cec_msg *msg,
   1009 				struct cec_op_tuner_device_info *tuner_dev_info)
   1010 {
   1011 	tuner_dev_info->is_analog = msg->len < 10;
   1012 	tuner_dev_info->rec_flag = msg->msg[2] >> 7;
   1013 	tuner_dev_info->tuner_display_info = msg->msg[2] & 0x7f;
   1014 	if (tuner_dev_info->is_analog) {
   1015 		tuner_dev_info->analog.ana_bcast_type = msg->msg[3];
   1016 		tuner_dev_info->analog.ana_freq = (msg->msg[4] << 8) | msg->msg[5];
   1017 		tuner_dev_info->analog.bcast_system = msg->msg[6];
   1018 		return;
   1019 	}
   1020 	cec_get_digital_service_id(msg->msg + 3, &tuner_dev_info->digital);
   1021 }
   1022 
   1023 static inline void cec_msg_give_tuner_device_status(struct cec_msg *msg,
   1024 						    int reply,
   1025 						    __u8 status_req)
   1026 {
   1027 	msg->len = 3;
   1028 	msg->msg[1] = CEC_MSG_GIVE_TUNER_DEVICE_STATUS;
   1029 	msg->msg[2] = status_req;
   1030 	msg->reply = reply ? CEC_MSG_TUNER_DEVICE_STATUS : 0;
   1031 }
   1032 
   1033 static inline void cec_ops_give_tuner_device_status(const struct cec_msg *msg,
   1034 						    __u8 *status_req)
   1035 {
   1036 	*status_req = msg->msg[2];
   1037 }
   1038 
   1039 static inline void cec_msg_select_analogue_service(struct cec_msg *msg,
   1040 						   __u8 ana_bcast_type,
   1041 						   __u16 ana_freq,
   1042 						   __u8 bcast_system)
   1043 {
   1044 	msg->len = 6;
   1045 	msg->msg[1] = CEC_MSG_SELECT_ANALOGUE_SERVICE;
   1046 	msg->msg[2] = ana_bcast_type;
   1047 	msg->msg[3] = ana_freq >> 8;
   1048 	msg->msg[4] = ana_freq & 0xff;
   1049 	msg->msg[5] = bcast_system;
   1050 }
   1051 
   1052 static inline void cec_ops_select_analogue_service(const struct cec_msg *msg,
   1053 						   __u8 *ana_bcast_type,
   1054 						   __u16 *ana_freq,
   1055 						   __u8 *bcast_system)
   1056 {
   1057 	*ana_bcast_type = msg->msg[2];
   1058 	*ana_freq = (msg->msg[3] << 8) | msg->msg[4];
   1059 	*bcast_system = msg->msg[5];
   1060 }
   1061 
   1062 static inline void cec_msg_select_digital_service(struct cec_msg *msg,
   1063 				const struct cec_op_digital_service_id *digital)
   1064 {
   1065 	msg->len = 9;
   1066 	msg->msg[1] = CEC_MSG_SELECT_DIGITAL_SERVICE;
   1067 	cec_set_digital_service_id(msg->msg + 2, digital);
   1068 }
   1069 
   1070 static inline void cec_ops_select_digital_service(const struct cec_msg *msg,
   1071 				struct cec_op_digital_service_id *digital)
   1072 {
   1073 	cec_get_digital_service_id(msg->msg + 2, digital);
   1074 }
   1075 
   1076 static inline void cec_msg_tuner_step_decrement(struct cec_msg *msg)
   1077 {
   1078 	msg->len = 2;
   1079 	msg->msg[1] = CEC_MSG_TUNER_STEP_DECREMENT;
   1080 }
   1081 
   1082 static inline void cec_msg_tuner_step_increment(struct cec_msg *msg)
   1083 {
   1084 	msg->len = 2;
   1085 	msg->msg[1] = CEC_MSG_TUNER_STEP_INCREMENT;
   1086 }
   1087 
   1088 
   1089 /* Vendor Specific Commands Feature */
   1090 static inline void cec_msg_device_vendor_id(struct cec_msg *msg, __u32 vendor_id)
   1091 {
   1092 	msg->len = 5;
   1093 	msg->msg[0] |= 0xf; /* broadcast */
   1094 	msg->msg[1] = CEC_MSG_DEVICE_VENDOR_ID;
   1095 	msg->msg[2] = vendor_id >> 16;
   1096 	msg->msg[3] = (vendor_id >> 8) & 0xff;
   1097 	msg->msg[4] = vendor_id & 0xff;
   1098 }
   1099 
   1100 static inline void cec_ops_device_vendor_id(const struct cec_msg *msg,
   1101 					    __u32 *vendor_id)
   1102 {
   1103 	*vendor_id = (msg->msg[2] << 16) | (msg->msg[3] << 8) | msg->msg[4];
   1104 }
   1105 
   1106 static inline void cec_msg_give_device_vendor_id(struct cec_msg *msg,
   1107 						 int reply)
   1108 {
   1109 	msg->len = 2;
   1110 	msg->msg[1] = CEC_MSG_GIVE_DEVICE_VENDOR_ID;
   1111 	msg->reply = reply ? CEC_MSG_DEVICE_VENDOR_ID : 0;
   1112 }
   1113 
   1114 static inline void cec_msg_vendor_command(struct cec_msg *msg,
   1115 					  __u8 size, const __u8 *vendor_cmd)
   1116 {
   1117 	if (size > 14)
   1118 		size = 14;
   1119 	msg->len = 2 + size;
   1120 	msg->msg[1] = CEC_MSG_VENDOR_COMMAND;
   1121 	memcpy(msg->msg + 2, vendor_cmd, size);
   1122 }
   1123 
   1124 static inline void cec_ops_vendor_command(const struct cec_msg *msg,
   1125 					  __u8 *size,
   1126 					  const __u8 **vendor_cmd)
   1127 {
   1128 	*size = msg->len - 2;
   1129 
   1130 	if (*size > 14)
   1131 		*size = 14;
   1132 	*vendor_cmd = msg->msg + 2;
   1133 }
   1134 
   1135 static inline void cec_msg_vendor_command_with_id(struct cec_msg *msg,
   1136 						  __u32 vendor_id, __u8 size,
   1137 						  const __u8 *vendor_cmd)
   1138 {
   1139 	if (size > 11)
   1140 		size = 11;
   1141 	msg->len = 5 + size;
   1142 	msg->msg[1] = CEC_MSG_VENDOR_COMMAND_WITH_ID;
   1143 	msg->msg[2] = vendor_id >> 16;
   1144 	msg->msg[3] = (vendor_id >> 8) & 0xff;
   1145 	msg->msg[4] = vendor_id & 0xff;
   1146 	memcpy(msg->msg + 5, vendor_cmd, size);
   1147 }
   1148 
   1149 static inline void cec_ops_vendor_command_with_id(const struct cec_msg *msg,
   1150 						  __u32 *vendor_id,  __u8 *size,
   1151 						  const __u8 **vendor_cmd)
   1152 {
   1153 	*size = msg->len - 5;
   1154 
   1155 	if (*size > 11)
   1156 		*size = 11;
   1157 	*vendor_id = (msg->msg[2] << 16) | (msg->msg[3] << 8) | msg->msg[4];
   1158 	*vendor_cmd = msg->msg + 5;
   1159 }
   1160 
   1161 static inline void cec_msg_vendor_remote_button_down(struct cec_msg *msg,
   1162 						     __u8 size,
   1163 						     const __u8 *rc_code)
   1164 {
   1165 	if (size > 14)
   1166 		size = 14;
   1167 	msg->len = 2 + size;
   1168 	msg->msg[1] = CEC_MSG_VENDOR_REMOTE_BUTTON_DOWN;
   1169 	memcpy(msg->msg + 2, rc_code, size);
   1170 }
   1171 
   1172 static inline void cec_ops_vendor_remote_button_down(const struct cec_msg *msg,
   1173 						     __u8 *size,
   1174 						     const __u8 **rc_code)
   1175 {
   1176 	*size = msg->len - 2;
   1177 
   1178 	if (*size > 14)
   1179 		*size = 14;
   1180 	*rc_code = msg->msg + 2;
   1181 }
   1182 
   1183 static inline void cec_msg_vendor_remote_button_up(struct cec_msg *msg)
   1184 {
   1185 	msg->len = 2;
   1186 	msg->msg[1] = CEC_MSG_VENDOR_REMOTE_BUTTON_UP;
   1187 }
   1188 
   1189 
   1190 /* OSD Display Feature */
   1191 static inline void cec_msg_set_osd_string(struct cec_msg *msg,
   1192 					  __u8 disp_ctl,
   1193 					  const char *osd)
   1194 {
   1195 	unsigned int len = strlen(osd);
   1196 
   1197 	if (len > 13)
   1198 		len = 13;
   1199 	msg->len = 3 + len;
   1200 	msg->msg[1] = CEC_MSG_SET_OSD_STRING;
   1201 	msg->msg[2] = disp_ctl;
   1202 	memcpy(msg->msg + 3, osd, len);
   1203 }
   1204 
   1205 static inline void cec_ops_set_osd_string(const struct cec_msg *msg,
   1206 					  __u8 *disp_ctl,
   1207 					  char *osd)
   1208 {
   1209 	unsigned int len = msg->len > 3 ? msg->len - 3 : 0;
   1210 
   1211 	*disp_ctl = msg->msg[2];
   1212 	if (len > 13)
   1213 		len = 13;
   1214 	memcpy(osd, msg->msg + 3, len);
   1215 	osd[len] = '\0';
   1216 }
   1217 
   1218 
   1219 /* Device OSD Transfer Feature */
   1220 static inline void cec_msg_set_osd_name(struct cec_msg *msg, const char *name)
   1221 {
   1222 	unsigned int len = strlen(name);
   1223 
   1224 	if (len > 14)
   1225 		len = 14;
   1226 	msg->len = 2 + len;
   1227 	msg->msg[1] = CEC_MSG_SET_OSD_NAME;
   1228 	memcpy(msg->msg + 2, name, len);
   1229 }
   1230 
   1231 static inline void cec_ops_set_osd_name(const struct cec_msg *msg,
   1232 					char *name)
   1233 {
   1234 	unsigned int len = msg->len > 2 ? msg->len - 2 : 0;
   1235 
   1236 	if (len > 14)
   1237 		len = 14;
   1238 	memcpy(name, msg->msg + 2, len);
   1239 	name[len] = '\0';
   1240 }
   1241 
   1242 static inline void cec_msg_give_osd_name(struct cec_msg *msg,
   1243 					 int reply)
   1244 {
   1245 	msg->len = 2;
   1246 	msg->msg[1] = CEC_MSG_GIVE_OSD_NAME;
   1247 	msg->reply = reply ? CEC_MSG_SET_OSD_NAME : 0;
   1248 }
   1249 
   1250 
   1251 /* Device Menu Control Feature */
   1252 static inline void cec_msg_menu_status(struct cec_msg *msg,
   1253 				       __u8 menu_state)
   1254 {
   1255 	msg->len = 3;
   1256 	msg->msg[1] = CEC_MSG_MENU_STATUS;
   1257 	msg->msg[2] = menu_state;
   1258 }
   1259 
   1260 static inline void cec_ops_menu_status(const struct cec_msg *msg,
   1261 				       __u8 *menu_state)
   1262 {
   1263 	*menu_state = msg->msg[2];
   1264 }
   1265 
   1266 static inline void cec_msg_menu_request(struct cec_msg *msg,
   1267 					int reply,
   1268 					__u8 menu_req)
   1269 {
   1270 	msg->len = 3;
   1271 	msg->msg[1] = CEC_MSG_MENU_REQUEST;
   1272 	msg->msg[2] = menu_req;
   1273 	msg->reply = reply ? CEC_MSG_MENU_STATUS : 0;
   1274 }
   1275 
   1276 static inline void cec_ops_menu_request(const struct cec_msg *msg,
   1277 					__u8 *menu_req)
   1278 {
   1279 	*menu_req = msg->msg[2];
   1280 }
   1281 
   1282 struct cec_op_ui_command {
   1283 	__u8 ui_cmd;
   1284 	__u8 has_opt_arg;
   1285 	union {
   1286 		struct cec_op_channel_data channel_identifier;
   1287 		__u8 ui_broadcast_type;
   1288 		__u8 ui_sound_presentation_control;
   1289 		__u8 play_mode;
   1290 		__u8 ui_function_media;
   1291 		__u8 ui_function_select_av_input;
   1292 		__u8 ui_function_select_audio_input;
   1293 	};
   1294 };
   1295 
   1296 static inline void cec_msg_user_control_pressed(struct cec_msg *msg,
   1297 					const struct cec_op_ui_command *ui_cmd)
   1298 {
   1299 	msg->len = 3;
   1300 	msg->msg[1] = CEC_MSG_USER_CONTROL_PRESSED;
   1301 	msg->msg[2] = ui_cmd->ui_cmd;
   1302 	if (!ui_cmd->has_opt_arg)
   1303 		return;
   1304 	switch (ui_cmd->ui_cmd) {
   1305 	case 0x56:
   1306 	case 0x57:
   1307 	case 0x60:
   1308 	case 0x68:
   1309 	case 0x69:
   1310 	case 0x6a:
   1311 		/* The optional operand is one byte for all these ui commands */
   1312 		msg->len++;
   1313 		msg->msg[3] = ui_cmd->play_mode;
   1314 		break;
   1315 	case 0x67:
   1316 		msg->len += 4;
   1317 		msg->msg[3] = (ui_cmd->channel_identifier.channel_number_fmt << 2) |
   1318 			      (ui_cmd->channel_identifier.major >> 8);
   1319 		msg->msg[4] = ui_cmd->channel_identifier.major & 0xff;
   1320 		msg->msg[5] = ui_cmd->channel_identifier.minor >> 8;
   1321 		msg->msg[6] = ui_cmd->channel_identifier.minor & 0xff;
   1322 		break;
   1323 	}
   1324 }
   1325 
   1326 static inline void cec_ops_user_control_pressed(const struct cec_msg *msg,
   1327 						struct cec_op_ui_command *ui_cmd)
   1328 {
   1329 	ui_cmd->ui_cmd = msg->msg[2];
   1330 	ui_cmd->has_opt_arg = 0;
   1331 	if (msg->len == 3)
   1332 		return;
   1333 	switch (ui_cmd->ui_cmd) {
   1334 	case 0x56:
   1335 	case 0x57:
   1336 	case 0x60:
   1337 	case 0x68:
   1338 	case 0x69:
   1339 	case 0x6a:
   1340 		/* The optional operand is one byte for all these ui commands */
   1341 		ui_cmd->play_mode = msg->msg[3];
   1342 		ui_cmd->has_opt_arg = 1;
   1343 		break;
   1344 	case 0x67:
   1345 		if (msg->len < 7)
   1346 			break;
   1347 		ui_cmd->has_opt_arg = 1;
   1348 		ui_cmd->channel_identifier.channel_number_fmt = msg->msg[3] >> 2;
   1349 		ui_cmd->channel_identifier.major = ((msg->msg[3] & 3) << 6) | msg->msg[4];
   1350 		ui_cmd->channel_identifier.minor = (msg->msg[5] << 8) | msg->msg[6];
   1351 		break;
   1352 	}
   1353 }
   1354 
   1355 static inline void cec_msg_user_control_released(struct cec_msg *msg)
   1356 {
   1357 	msg->len = 2;
   1358 	msg->msg[1] = CEC_MSG_USER_CONTROL_RELEASED;
   1359 }
   1360 
   1361 /* Remote Control Passthrough Feature */
   1362 
   1363 /* Power Status Feature */
   1364 static inline void cec_msg_report_power_status(struct cec_msg *msg,
   1365 					       __u8 pwr_state)
   1366 {
   1367 	msg->len = 3;
   1368 	msg->msg[1] = CEC_MSG_REPORT_POWER_STATUS;
   1369 	msg->msg[2] = pwr_state;
   1370 }
   1371 
   1372 static inline void cec_ops_report_power_status(const struct cec_msg *msg,
   1373 					       __u8 *pwr_state)
   1374 {
   1375 	*pwr_state = msg->msg[2];
   1376 }
   1377 
   1378 static inline void cec_msg_give_device_power_status(struct cec_msg *msg,
   1379 						    int reply)
   1380 {
   1381 	msg->len = 2;
   1382 	msg->msg[1] = CEC_MSG_GIVE_DEVICE_POWER_STATUS;
   1383 	msg->reply = reply ? CEC_MSG_REPORT_POWER_STATUS : 0;
   1384 }
   1385 
   1386 /* General Protocol Messages */
   1387 static inline void cec_msg_feature_abort(struct cec_msg *msg,
   1388 					 __u8 abort_msg, __u8 reason)
   1389 {
   1390 	msg->len = 4;
   1391 	msg->msg[1] = CEC_MSG_FEATURE_ABORT;
   1392 	msg->msg[2] = abort_msg;
   1393 	msg->msg[3] = reason;
   1394 }
   1395 
   1396 static inline void cec_ops_feature_abort(const struct cec_msg *msg,
   1397 					 __u8 *abort_msg, __u8 *reason)
   1398 {
   1399 	*abort_msg = msg->msg[2];
   1400 	*reason = msg->msg[3];
   1401 }
   1402 
   1403 /* This changes the current message into a feature abort message */
   1404 static inline void cec_msg_reply_feature_abort(struct cec_msg *msg, __u8 reason)
   1405 {
   1406 	cec_msg_set_reply_to(msg, msg);
   1407 	msg->len = 4;
   1408 	msg->msg[2] = msg->msg[1];
   1409 	msg->msg[3] = reason;
   1410 	msg->msg[1] = CEC_MSG_FEATURE_ABORT;
   1411 }
   1412 
   1413 static inline void cec_msg_abort(struct cec_msg *msg)
   1414 {
   1415 	msg->len = 2;
   1416 	msg->msg[1] = CEC_MSG_ABORT;
   1417 }
   1418 
   1419 
   1420 /* System Audio Control Feature */
   1421 static inline void cec_msg_report_audio_status(struct cec_msg *msg,
   1422 					       __u8 aud_mute_status,
   1423 					       __u8 aud_vol_status)
   1424 {
   1425 	msg->len = 3;
   1426 	msg->msg[1] = CEC_MSG_REPORT_AUDIO_STATUS;
   1427 	msg->msg[2] = (aud_mute_status << 7) | (aud_vol_status & 0x7f);
   1428 }
   1429 
   1430 static inline void cec_ops_report_audio_status(const struct cec_msg *msg,
   1431 					       __u8 *aud_mute_status,
   1432 					       __u8 *aud_vol_status)
   1433 {
   1434 	*aud_mute_status = msg->msg[2] >> 7;
   1435 	*aud_vol_status = msg->msg[2] & 0x7f;
   1436 }
   1437 
   1438 static inline void cec_msg_give_audio_status(struct cec_msg *msg,
   1439 					     int reply)
   1440 {
   1441 	msg->len = 2;
   1442 	msg->msg[1] = CEC_MSG_GIVE_AUDIO_STATUS;
   1443 	msg->reply = reply ? CEC_MSG_REPORT_AUDIO_STATUS : 0;
   1444 }
   1445 
   1446 static inline void cec_msg_set_system_audio_mode(struct cec_msg *msg,
   1447 						 __u8 sys_aud_status)
   1448 {
   1449 	msg->len = 3;
   1450 	msg->msg[1] = CEC_MSG_SET_SYSTEM_AUDIO_MODE;
   1451 	msg->msg[2] = sys_aud_status;
   1452 }
   1453 
   1454 static inline void cec_ops_set_system_audio_mode(const struct cec_msg *msg,
   1455 						 __u8 *sys_aud_status)
   1456 {
   1457 	*sys_aud_status = msg->msg[2];
   1458 }
   1459 
   1460 static inline void cec_msg_system_audio_mode_request(struct cec_msg *msg,
   1461 						     int reply,
   1462 						     __u16 phys_addr)
   1463 {
   1464 	msg->len = phys_addr == 0xffff ? 2 : 4;
   1465 	msg->msg[1] = CEC_MSG_SYSTEM_AUDIO_MODE_REQUEST;
   1466 	msg->msg[2] = phys_addr >> 8;
   1467 	msg->msg[3] = phys_addr & 0xff;
   1468 	msg->reply = reply ? CEC_MSG_SET_SYSTEM_AUDIO_MODE : 0;
   1469 
   1470 }
   1471 
   1472 static inline void cec_ops_system_audio_mode_request(const struct cec_msg *msg,
   1473 						     __u16 *phys_addr)
   1474 {
   1475 	if (msg->len < 4)
   1476 		*phys_addr = 0xffff;
   1477 	else
   1478 		*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
   1479 }
   1480 
   1481 static inline void cec_msg_system_audio_mode_status(struct cec_msg *msg,
   1482 						    __u8 sys_aud_status)
   1483 {
   1484 	msg->len = 3;
   1485 	msg->msg[1] = CEC_MSG_SYSTEM_AUDIO_MODE_STATUS;
   1486 	msg->msg[2] = sys_aud_status;
   1487 }
   1488 
   1489 static inline void cec_ops_system_audio_mode_status(const struct cec_msg *msg,
   1490 						    __u8 *sys_aud_status)
   1491 {
   1492 	*sys_aud_status = msg->msg[2];
   1493 }
   1494 
   1495 static inline void cec_msg_give_system_audio_mode_status(struct cec_msg *msg,
   1496 							 int reply)
   1497 {
   1498 	msg->len = 2;
   1499 	msg->msg[1] = CEC_MSG_GIVE_SYSTEM_AUDIO_MODE_STATUS;
   1500 	msg->reply = reply ? CEC_MSG_SYSTEM_AUDIO_MODE_STATUS : 0;
   1501 }
   1502 
   1503 static inline void cec_msg_report_short_audio_descriptor(struct cec_msg *msg,
   1504 					__u8 num_descriptors,
   1505 					const __u32 *descriptors)
   1506 {
   1507 	unsigned int i;
   1508 
   1509 	if (num_descriptors > 4)
   1510 		num_descriptors = 4;
   1511 	msg->len = 2 + num_descriptors * 3;
   1512 	msg->msg[1] = CEC_MSG_REPORT_SHORT_AUDIO_DESCRIPTOR;
   1513 	for (i = 0; i < num_descriptors; i++) {
   1514 		msg->msg[2 + i * 3] = (descriptors[i] >> 16) & 0xff;
   1515 		msg->msg[3 + i * 3] = (descriptors[i] >> 8) & 0xff;
   1516 		msg->msg[4 + i * 3] = descriptors[i] & 0xff;
   1517 	}
   1518 }
   1519 
   1520 static inline void cec_ops_report_short_audio_descriptor(const struct cec_msg *msg,
   1521 							 __u8 *num_descriptors,
   1522 							 __u32 *descriptors)
   1523 {
   1524 	unsigned int i;
   1525 
   1526 	*num_descriptors = (msg->len - 2) / 3;
   1527 	if (*num_descriptors > 4)
   1528 		*num_descriptors = 4;
   1529 	for (i = 0; i < *num_descriptors; i++)
   1530 		descriptors[i] = (msg->msg[2 + i * 3] << 16) |
   1531 			(msg->msg[3 + i * 3] << 8) |
   1532 			msg->msg[4 + i * 3];
   1533 }
   1534 
   1535 static inline void cec_msg_request_short_audio_descriptor(struct cec_msg *msg,
   1536 					int reply,
   1537 					__u8 num_descriptors,
   1538 					const __u8 *audio_format_id,
   1539 					const __u8 *audio_format_code)
   1540 {
   1541 	unsigned int i;
   1542 
   1543 	if (num_descriptors > 4)
   1544 		num_descriptors = 4;
   1545 	msg->len = 2 + num_descriptors;
   1546 	msg->msg[1] = CEC_MSG_REQUEST_SHORT_AUDIO_DESCRIPTOR;
   1547 	msg->reply = reply ? CEC_MSG_REPORT_SHORT_AUDIO_DESCRIPTOR : 0;
   1548 	for (i = 0; i < num_descriptors; i++)
   1549 		msg->msg[2 + i] = (audio_format_id[i] << 6) |
   1550 				  (audio_format_code[i] & 0x3f);
   1551 }
   1552 
   1553 static inline void cec_ops_request_short_audio_descriptor(const struct cec_msg *msg,
   1554 					__u8 *num_descriptors,
   1555 					__u8 *audio_format_id,
   1556 					__u8 *audio_format_code)
   1557 {
   1558 	unsigned int i;
   1559 
   1560 	*num_descriptors = msg->len - 2;
   1561 	if (*num_descriptors > 4)
   1562 		*num_descriptors = 4;
   1563 	for (i = 0; i < *num_descriptors; i++) {
   1564 		audio_format_id[i] = msg->msg[2 + i] >> 6;
   1565 		audio_format_code[i] = msg->msg[2 + i] & 0x3f;
   1566 	}
   1567 }
   1568 
   1569 
   1570 /* Audio Rate Control Feature */
   1571 static inline void cec_msg_set_audio_rate(struct cec_msg *msg,
   1572 					  __u8 audio_rate)
   1573 {
   1574 	msg->len = 3;
   1575 	msg->msg[1] = CEC_MSG_SET_AUDIO_RATE;
   1576 	msg->msg[2] = audio_rate;
   1577 }
   1578 
   1579 static inline void cec_ops_set_audio_rate(const struct cec_msg *msg,
   1580 					  __u8 *audio_rate)
   1581 {
   1582 	*audio_rate = msg->msg[2];
   1583 }
   1584 
   1585 
   1586 /* Audio Return Channel Control Feature */
   1587 static inline void cec_msg_report_arc_initiated(struct cec_msg *msg)
   1588 {
   1589 	msg->len = 2;
   1590 	msg->msg[1] = CEC_MSG_REPORT_ARC_INITIATED;
   1591 }
   1592 
   1593 static inline void cec_msg_initiate_arc(struct cec_msg *msg,
   1594 					int reply)
   1595 {
   1596 	msg->len = 2;
   1597 	msg->msg[1] = CEC_MSG_INITIATE_ARC;
   1598 	msg->reply = reply ? CEC_MSG_REPORT_ARC_INITIATED : 0;
   1599 }
   1600 
   1601 static inline void cec_msg_request_arc_initiation(struct cec_msg *msg,
   1602 						  int reply)
   1603 {
   1604 	msg->len = 2;
   1605 	msg->msg[1] = CEC_MSG_REQUEST_ARC_INITIATION;
   1606 	msg->reply = reply ? CEC_MSG_INITIATE_ARC : 0;
   1607 }
   1608 
   1609 static inline void cec_msg_report_arc_terminated(struct cec_msg *msg)
   1610 {
   1611 	msg->len = 2;
   1612 	msg->msg[1] = CEC_MSG_REPORT_ARC_TERMINATED;
   1613 }
   1614 
   1615 static inline void cec_msg_terminate_arc(struct cec_msg *msg,
   1616 					 int reply)
   1617 {
   1618 	msg->len = 2;
   1619 	msg->msg[1] = CEC_MSG_TERMINATE_ARC;
   1620 	msg->reply = reply ? CEC_MSG_REPORT_ARC_TERMINATED : 0;
   1621 }
   1622 
   1623 static inline void cec_msg_request_arc_termination(struct cec_msg *msg,
   1624 						   int reply)
   1625 {
   1626 	msg->len = 2;
   1627 	msg->msg[1] = CEC_MSG_REQUEST_ARC_TERMINATION;
   1628 	msg->reply = reply ? CEC_MSG_TERMINATE_ARC : 0;
   1629 }
   1630 
   1631 
   1632 /* Dynamic Audio Lipsync Feature */
   1633 /* Only for CEC 2.0 and up */
   1634 static inline void cec_msg_report_current_latency(struct cec_msg *msg,
   1635 						  __u16 phys_addr,
   1636 						  __u8 video_latency,
   1637 						  __u8 low_latency_mode,
   1638 						  __u8 audio_out_compensated,
   1639 						  __u8 audio_out_delay)
   1640 {
   1641 	msg->len = 6;
   1642 	msg->msg[0] |= 0xf; /* broadcast */
   1643 	msg->msg[1] = CEC_MSG_REPORT_CURRENT_LATENCY;
   1644 	msg->msg[2] = phys_addr >> 8;
   1645 	msg->msg[3] = phys_addr & 0xff;
   1646 	msg->msg[4] = video_latency;
   1647 	msg->msg[5] = (low_latency_mode << 2) | audio_out_compensated;
   1648 	if (audio_out_compensated == 3)
   1649 		msg->msg[msg->len++] = audio_out_delay;
   1650 }
   1651 
   1652 static inline void cec_ops_report_current_latency(const struct cec_msg *msg,
   1653 						  __u16 *phys_addr,
   1654 						  __u8 *video_latency,
   1655 						  __u8 *low_latency_mode,
   1656 						  __u8 *audio_out_compensated,
   1657 						  __u8 *audio_out_delay)
   1658 {
   1659 	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
   1660 	*video_latency = msg->msg[4];
   1661 	*low_latency_mode = (msg->msg[5] >> 2) & 1;
   1662 	*audio_out_compensated = msg->msg[5] & 3;
   1663 	if (*audio_out_compensated == 3 && msg->len >= 7)
   1664 		*audio_out_delay = msg->msg[6];
   1665 	else
   1666 		*audio_out_delay = 0;
   1667 }
   1668 
   1669 static inline void cec_msg_request_current_latency(struct cec_msg *msg,
   1670 						   int reply,
   1671 						   __u16 phys_addr)
   1672 {
   1673 	msg->len = 4;
   1674 	msg->msg[0] |= 0xf; /* broadcast */
   1675 	msg->msg[1] = CEC_MSG_REQUEST_CURRENT_LATENCY;
   1676 	msg->msg[2] = phys_addr >> 8;
   1677 	msg->msg[3] = phys_addr & 0xff;
   1678 	msg->reply = reply ? CEC_MSG_REPORT_CURRENT_LATENCY : 0;
   1679 }
   1680 
   1681 static inline void cec_ops_request_current_latency(const struct cec_msg *msg,
   1682 						   __u16 *phys_addr)
   1683 {
   1684 	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
   1685 }
   1686 
   1687 
   1688 /* Capability Discovery and Control Feature */
   1689 static inline void cec_msg_cdc_hec_inquire_state(struct cec_msg *msg,
   1690 						 __u16 phys_addr1,
   1691 						 __u16 phys_addr2)
   1692 {
   1693 	msg->len = 9;
   1694 	msg->msg[0] |= 0xf; /* broadcast */
   1695 	msg->msg[1] = CEC_MSG_CDC_MESSAGE;
   1696 	/* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
   1697 	msg->msg[4] = CEC_MSG_CDC_HEC_INQUIRE_STATE;
   1698 	msg->msg[5] = phys_addr1 >> 8;
   1699 	msg->msg[6] = phys_addr1 & 0xff;
   1700 	msg->msg[7] = phys_addr2 >> 8;
   1701 	msg->msg[8] = phys_addr2 & 0xff;
   1702 }
   1703 
   1704 static inline void cec_ops_cdc_hec_inquire_state(const struct cec_msg *msg,
   1705 						 __u16 *phys_addr,
   1706 						 __u16 *phys_addr1,
   1707 						 __u16 *phys_addr2)
   1708 {
   1709 	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
   1710 	*phys_addr1 = (msg->msg[5] << 8) | msg->msg[6];
   1711 	*phys_addr2 = (msg->msg[7] << 8) | msg->msg[8];
   1712 }
   1713 
   1714 static inline void cec_msg_cdc_hec_report_state(struct cec_msg *msg,
   1715 						__u16 target_phys_addr,
   1716 						__u8 hec_func_state,
   1717 						__u8 host_func_state,
   1718 						__u8 enc_func_state,
   1719 						__u8 cdc_errcode,
   1720 						__u8 has_field,
   1721 						__u16 hec_field)
   1722 {
   1723 	msg->len = has_field ? 10 : 8;
   1724 	msg->msg[0] |= 0xf; /* broadcast */
   1725 	msg->msg[1] = CEC_MSG_CDC_MESSAGE;
   1726 	/* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
   1727 	msg->msg[4] = CEC_MSG_CDC_HEC_REPORT_STATE;
   1728 	msg->msg[5] = target_phys_addr >> 8;
   1729 	msg->msg[6] = target_phys_addr & 0xff;
   1730 	msg->msg[7] = (hec_func_state << 6) |
   1731 		      (host_func_state << 4) |
   1732 		      (enc_func_state << 2) |
   1733 		      cdc_errcode;
   1734 	if (has_field) {
   1735 		msg->msg[8] = hec_field >> 8;
   1736 		msg->msg[9] = hec_field & 0xff;
   1737 	}
   1738 }
   1739 
   1740 static inline void cec_ops_cdc_hec_report_state(const struct cec_msg *msg,
   1741 						__u16 *phys_addr,
   1742 						__u16 *target_phys_addr,
   1743 						__u8 *hec_func_state,
   1744 						__u8 *host_func_state,
   1745 						__u8 *enc_func_state,
   1746 						__u8 *cdc_errcode,
   1747 						__u8 *has_field,
   1748 						__u16 *hec_field)
   1749 {
   1750 	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
   1751 	*target_phys_addr = (msg->msg[5] << 8) | msg->msg[6];
   1752 	*hec_func_state = msg->msg[7] >> 6;
   1753 	*host_func_state = (msg->msg[7] >> 4) & 3;
   1754 	*enc_func_state = (msg->msg[7] >> 4) & 3;
   1755 	*cdc_errcode = msg->msg[7] & 3;
   1756 	*has_field = msg->len >= 10;
   1757 	*hec_field = *has_field ? ((msg->msg[8] << 8) | msg->msg[9]) : 0;
   1758 }
   1759 
   1760 static inline void cec_msg_cdc_hec_set_state(struct cec_msg *msg,
   1761 					     __u16 phys_addr1,
   1762 					     __u16 phys_addr2,
   1763 					     __u8 hec_set_state,
   1764 					     __u16 phys_addr3,
   1765 					     __u16 phys_addr4,
   1766 					     __u16 phys_addr5)
   1767 {
   1768 	msg->len = 10;
   1769 	msg->msg[0] |= 0xf; /* broadcast */
   1770 	msg->msg[1] = CEC_MSG_CDC_MESSAGE;
   1771 	/* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
   1772 	msg->msg[4] = CEC_MSG_CDC_HEC_INQUIRE_STATE;
   1773 	msg->msg[5] = phys_addr1 >> 8;
   1774 	msg->msg[6] = phys_addr1 & 0xff;
   1775 	msg->msg[7] = phys_addr2 >> 8;
   1776 	msg->msg[8] = phys_addr2 & 0xff;
   1777 	msg->msg[9] = hec_set_state;
   1778 	if (phys_addr3 != CEC_PHYS_ADDR_INVALID) {
   1779 		msg->msg[msg->len++] = phys_addr3 >> 8;
   1780 		msg->msg[msg->len++] = phys_addr3 & 0xff;
   1781 		if (phys_addr4 != CEC_PHYS_ADDR_INVALID) {
   1782 			msg->msg[msg->len++] = phys_addr4 >> 8;
   1783 			msg->msg[msg->len++] = phys_addr4 & 0xff;
   1784 			if (phys_addr5 != CEC_PHYS_ADDR_INVALID) {
   1785 				msg->msg[msg->len++] = phys_addr5 >> 8;
   1786 				msg->msg[msg->len++] = phys_addr5 & 0xff;
   1787 			}
   1788 		}
   1789 	}
   1790 }
   1791 
   1792 static inline void cec_ops_cdc_hec_set_state(const struct cec_msg *msg,
   1793 					     __u16 *phys_addr,
   1794 					     __u16 *phys_addr1,
   1795 					     __u16 *phys_addr2,
   1796 					     __u8 *hec_set_state,
   1797 					     __u16 *phys_addr3,
   1798 					     __u16 *phys_addr4,
   1799 					     __u16 *phys_addr5)
   1800 {
   1801 	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
   1802 	*phys_addr1 = (msg->msg[5] << 8) | msg->msg[6];
   1803 	*phys_addr2 = (msg->msg[7] << 8) | msg->msg[8];
   1804 	*hec_set_state = msg->msg[9];
   1805 	*phys_addr3 = *phys_addr4 = *phys_addr5 = CEC_PHYS_ADDR_INVALID;
   1806 	if (msg->len >= 12)
   1807 		*phys_addr3 = (msg->msg[10] << 8) | msg->msg[11];
   1808 	if (msg->len >= 14)
   1809 		*phys_addr4 = (msg->msg[12] << 8) | msg->msg[13];
   1810 	if (msg->len >= 16)
   1811 		*phys_addr5 = (msg->msg[14] << 8) | msg->msg[15];
   1812 }
   1813 
   1814 static inline void cec_msg_cdc_hec_set_state_adjacent(struct cec_msg *msg,
   1815 						      __u16 phys_addr1,
   1816 						      __u8 hec_set_state)
   1817 {
   1818 	msg->len = 8;
   1819 	msg->msg[0] |= 0xf; /* broadcast */
   1820 	msg->msg[1] = CEC_MSG_CDC_MESSAGE;
   1821 	/* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
   1822 	msg->msg[4] = CEC_MSG_CDC_HEC_SET_STATE_ADJACENT;
   1823 	msg->msg[5] = phys_addr1 >> 8;
   1824 	msg->msg[6] = phys_addr1 & 0xff;
   1825 	msg->msg[7] = hec_set_state;
   1826 }
   1827 
   1828 static inline void cec_ops_cdc_hec_set_state_adjacent(const struct cec_msg *msg,
   1829 						      __u16 *phys_addr,
   1830 						      __u16 *phys_addr1,
   1831 						      __u8 *hec_set_state)
   1832 {
   1833 	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
   1834 	*phys_addr1 = (msg->msg[5] << 8) | msg->msg[6];
   1835 	*hec_set_state = msg->msg[7];
   1836 }
   1837 
   1838 static inline void cec_msg_cdc_hec_request_deactivation(struct cec_msg *msg,
   1839 							__u16 phys_addr1,
   1840 							__u16 phys_addr2,
   1841 							__u16 phys_addr3)
   1842 {
   1843 	msg->len = 11;
   1844 	msg->msg[0] |= 0xf; /* broadcast */
   1845 	msg->msg[1] = CEC_MSG_CDC_MESSAGE;
   1846 	/* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
   1847 	msg->msg[4] = CEC_MSG_CDC_HEC_REQUEST_DEACTIVATION;
   1848 	msg->msg[5] = phys_addr1 >> 8;
   1849 	msg->msg[6] = phys_addr1 & 0xff;
   1850 	msg->msg[7] = phys_addr2 >> 8;
   1851 	msg->msg[8] = phys_addr2 & 0xff;
   1852 	msg->msg[9] = phys_addr3 >> 8;
   1853 	msg->msg[10] = phys_addr3 & 0xff;
   1854 }
   1855 
   1856 static inline void cec_ops_cdc_hec_request_deactivation(const struct cec_msg *msg,
   1857 							__u16 *phys_addr,
   1858 							__u16 *phys_addr1,
   1859 							__u16 *phys_addr2,
   1860 							__u16 *phys_addr3)
   1861 {
   1862 	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
   1863 	*phys_addr1 = (msg->msg[5] << 8) | msg->msg[6];
   1864 	*phys_addr2 = (msg->msg[7] << 8) | msg->msg[8];
   1865 	*phys_addr3 = (msg->msg[9] << 8) | msg->msg[10];
   1866 }
   1867 
   1868 static inline void cec_msg_cdc_hec_notify_alive(struct cec_msg *msg)
   1869 {
   1870 	msg->len = 5;
   1871 	msg->msg[0] |= 0xf; /* broadcast */
   1872 	msg->msg[1] = CEC_MSG_CDC_MESSAGE;
   1873 	/* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
   1874 	msg->msg[4] = CEC_MSG_CDC_HEC_NOTIFY_ALIVE;
   1875 }
   1876 
   1877 static inline void cec_ops_cdc_hec_notify_alive(const struct cec_msg *msg,
   1878 						__u16 *phys_addr)
   1879 {
   1880 	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
   1881 }
   1882 
   1883 static inline void cec_msg_cdc_hec_discover(struct cec_msg *msg)
   1884 {
   1885 	msg->len = 5;
   1886 	msg->msg[0] |= 0xf; /* broadcast */
   1887 	msg->msg[1] = CEC_MSG_CDC_MESSAGE;
   1888 	/* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
   1889 	msg->msg[4] = CEC_MSG_CDC_HEC_DISCOVER;
   1890 }
   1891 
   1892 static inline void cec_ops_cdc_hec_discover(const struct cec_msg *msg,
   1893 					    __u16 *phys_addr)
   1894 {
   1895 	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
   1896 }
   1897 
   1898 static inline void cec_msg_cdc_hpd_set_state(struct cec_msg *msg,
   1899 					     __u8 input_port,
   1900 					     __u8 hpd_state)
   1901 {
   1902 	msg->len = 6;
   1903 	msg->msg[0] |= 0xf; /* broadcast */
   1904 	msg->msg[1] = CEC_MSG_CDC_MESSAGE;
   1905 	/* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
   1906 	msg->msg[4] = CEC_MSG_CDC_HPD_SET_STATE;
   1907 	msg->msg[5] = (input_port << 4) | hpd_state;
   1908 }
   1909 
   1910 static inline void cec_ops_cdc_hpd_set_state(const struct cec_msg *msg,
   1911 					    __u16 *phys_addr,
   1912 					    __u8 *input_port,
   1913 					    __u8 *hpd_state)
   1914 {
   1915 	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
   1916 	*input_port = msg->msg[5] >> 4;
   1917 	*hpd_state = msg->msg[5] & 0xf;
   1918 }
   1919 
   1920 static inline void cec_msg_cdc_hpd_report_state(struct cec_msg *msg,
   1921 						__u8 hpd_state,
   1922 						__u8 hpd_error)
   1923 {
   1924 	msg->len = 6;
   1925 	msg->msg[0] |= 0xf; /* broadcast */
   1926 	msg->msg[1] = CEC_MSG_CDC_MESSAGE;
   1927 	/* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
   1928 	msg->msg[4] = CEC_MSG_CDC_HPD_REPORT_STATE;
   1929 	msg->msg[5] = (hpd_state << 4) | hpd_error;
   1930 }
   1931 
   1932 static inline void cec_ops_cdc_hpd_report_state(const struct cec_msg *msg,
   1933 						__u16 *phys_addr,
   1934 						__u8 *hpd_state,
   1935 						__u8 *hpd_error)
   1936 {
   1937 	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
   1938 	*hpd_state = msg->msg[5] >> 4;
   1939 	*hpd_error = msg->msg[5] & 0xf;
   1940 }
   1941 
   1942 #endif
   1943