zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

cec-funcs.h (54418B) - Raw


      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 && status_req != CEC_OP_STATUS_REQ_OFF) ?
    927 				CEC_MSG_DECK_STATUS : 0;
    928 }
    929 
    930 static __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 
    936 static __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 
    944 static __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 */
    952 struct 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 
    966 static __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 
    982 static __inline__ void cec_msg_tuner_device_status_digital(struct cec_msg *msg,
    983 		   __u8 rec_flag, __u8 tuner_display_info,
    984 		   const struct cec_op_digital_service_id *digital)
    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 
    992 static __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 	else
   1003 		cec_msg_tuner_device_status_digital(msg,
   1004 			tuner_dev_info->rec_flag,
   1005 			tuner_dev_info->tuner_display_info,
   1006 			&tuner_dev_info->digital);
   1007 }
   1008 
   1009 static __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 
   1024 static __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 
   1035 static __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 
   1041 static __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 
   1054 static __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 
   1064 static __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 
   1072 static __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 
   1078 static __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 
   1084 static __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 */
   1092 static __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 
   1102 static __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 
   1108 static __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 
   1116 static __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 
   1126 static __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 
   1137 static __inline__ void cec_msg_vendor_command_with_id(struct cec_msg *msg,
   1138 						  __u32 vendor_id, __u8 size,
   1139 						  const __u8 *vendor_cmd)
   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 
   1151 static __inline__ void cec_ops_vendor_command_with_id(const struct cec_msg *msg,
   1152 						  __u32 *vendor_id,  __u8 *size,
   1153 						  const __u8 **vendor_cmd)
   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 
   1163 static __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 
   1174 static __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 
   1185 static __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 */
   1193 static __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 
   1207 static __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 */
   1222 static __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 
   1233 static __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 
   1244 static __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 */
   1254 static __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 
   1262 static __inline__ void cec_ops_menu_status(const struct cec_msg *msg,
   1263 				       __u8 *menu_state)
   1264 {
   1265 	*menu_state = msg->msg[2];
   1266 }
   1267 
   1268 static __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 
   1278 static __inline__ void cec_ops_menu_request(const struct cec_msg *msg,
   1279 					__u8 *menu_req)
   1280 {
   1281 	*menu_req = msg->msg[2];
   1282 }
   1283 
   1284 struct 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 
   1298 static __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 
   1328 static __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 
   1357 static __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 */
   1366 static __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 
   1374 static __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 
   1380 static __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 */
   1389 static __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 
   1398 static __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 */
   1406 static __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 
   1415 static __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 */
   1423 static __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 
   1432 static __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 
   1440 static __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 
   1448 static __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 
   1456 static __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 
   1462 static __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 
   1474 static __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 	else
   1480 		*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
   1481 }
   1482 
   1483 static __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 
   1491 static __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 
   1497 static __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 
   1505 static __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 
   1522 static __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 
   1537 static __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 
   1555 static __inline__ void cec_ops_request_short_audio_descriptor(const struct cec_msg *msg,
   1556 					__u8 *num_descriptors,
   1557 					__u8 *audio_format_id,
   1558 					__u8 *audio_format_code)
   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 
   1571 static __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 
   1579 static __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 */
   1587 static __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 
   1595 static __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 */
   1603 static __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 
   1609 static __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 
   1617 static __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 
   1625 static __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 
   1631 static __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 
   1639 static __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 */
   1650 static __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 
   1668 static __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 	else
   1682 		*audio_out_delay = 1;
   1683 }
   1684 
   1685 static __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 
   1697 static __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 */
   1705 static __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 
   1720 static __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 
   1730 static __inline__ void cec_msg_cdc_hec_report_state(struct cec_msg *msg,
   1731 						__u16 target_phys_addr,
   1732 						__u8 hec_func_state,
   1733 						__u8 host_func_state,
   1734 						__u8 enc_func_state,
   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 
   1756 static __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 
   1776 static __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 
   1808 static __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 
   1830 static __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 
   1844 static __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 
   1854 static __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 
   1872 static __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 
   1884 static __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 
   1893 static __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 
   1899 static __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 
   1908 static __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 
   1914 static __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 
   1926 static __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 
   1936 static __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 
   1948 static __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 #endif