master
   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 */
  14static __inline__ void cec_msg_active_source(struct cec_msg *msg, __u16 phys_addr)
  15{
  16	msg->len = 4;
  17	msg->msg[0] |= CEC_LOG_ADDR_BROADCAST;
  18	msg->msg[1] = CEC_MSG_ACTIVE_SOURCE;
  19	msg->msg[2] = phys_addr >> 8;
  20	msg->msg[3] = phys_addr & 0xff;
  21}
  22
  23static __inline__ void cec_ops_active_source(const struct cec_msg *msg,
  24					 __u16 *phys_addr)
  25{
  26	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
  27}
  28
  29static __inline__ void cec_msg_image_view_on(struct cec_msg *msg)
  30{
  31	msg->len = 2;
  32	msg->msg[1] = CEC_MSG_IMAGE_VIEW_ON;
  33}
  34
  35static __inline__ void cec_msg_text_view_on(struct cec_msg *msg)
  36{
  37	msg->len = 2;
  38	msg->msg[1] = CEC_MSG_TEXT_VIEW_ON;
  39}
  40
  41
  42/* Routing Control Feature */
  43static __inline__ void cec_msg_inactive_source(struct cec_msg *msg,
  44					   __u16 phys_addr)
  45{
  46	msg->len = 4;
  47	msg->msg[1] = CEC_MSG_INACTIVE_SOURCE;
  48	msg->msg[2] = phys_addr >> 8;
  49	msg->msg[3] = phys_addr & 0xff;
  50}
  51
  52static __inline__ void cec_ops_inactive_source(const struct cec_msg *msg,
  53					   __u16 *phys_addr)
  54{
  55	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
  56}
  57
  58static __inline__ void cec_msg_request_active_source(struct cec_msg *msg,
  59						 int reply)
  60{
  61	msg->len = 2;
  62	msg->msg[0] |= CEC_LOG_ADDR_BROADCAST;
  63	msg->msg[1] = CEC_MSG_REQUEST_ACTIVE_SOURCE;
  64	msg->reply = reply ? CEC_MSG_ACTIVE_SOURCE : 0;
  65}
  66
  67static __inline__ void cec_msg_routing_information(struct cec_msg *msg,
  68					       __u16 phys_addr)
  69{
  70	msg->len = 4;
  71	msg->msg[0] |= CEC_LOG_ADDR_BROADCAST;
  72	msg->msg[1] = CEC_MSG_ROUTING_INFORMATION;
  73	msg->msg[2] = phys_addr >> 8;
  74	msg->msg[3] = phys_addr & 0xff;
  75}
  76
  77static __inline__ void cec_ops_routing_information(const struct cec_msg *msg,
  78					       __u16 *phys_addr)
  79{
  80	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
  81}
  82
  83static __inline__ void cec_msg_routing_change(struct cec_msg *msg,
  84					  int reply,
  85					  __u16 orig_phys_addr,
  86					  __u16 new_phys_addr)
  87{
  88	msg->len = 6;
  89	msg->msg[0] |= CEC_LOG_ADDR_BROADCAST;
  90	msg->msg[1] = CEC_MSG_ROUTING_CHANGE;
  91	msg->msg[2] = orig_phys_addr >> 8;
  92	msg->msg[3] = orig_phys_addr & 0xff;
  93	msg->msg[4] = new_phys_addr >> 8;
  94	msg->msg[5] = new_phys_addr & 0xff;
  95	msg->reply = reply ? CEC_MSG_ROUTING_INFORMATION : 0;
  96}
  97
  98static __inline__ void cec_ops_routing_change(const struct cec_msg *msg,
  99					  __u16 *orig_phys_addr,
 100					  __u16 *new_phys_addr)
 101{
 102	*orig_phys_addr = (msg->msg[2] << 8) | msg->msg[3];
 103	*new_phys_addr = (msg->msg[4] << 8) | msg->msg[5];
 104}
 105
 106static __inline__ void cec_msg_set_stream_path(struct cec_msg *msg, __u16 phys_addr)
 107{
 108	msg->len = 4;
 109	msg->msg[0] |= CEC_LOG_ADDR_BROADCAST;
 110	msg->msg[1] = CEC_MSG_SET_STREAM_PATH;
 111	msg->msg[2] = phys_addr >> 8;
 112	msg->msg[3] = phys_addr & 0xff;
 113}
 114
 115static __inline__ void cec_ops_set_stream_path(const struct cec_msg *msg,
 116					   __u16 *phys_addr)
 117{
 118	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
 119}
 120
 121
 122/* Standby Feature */
 123static __inline__ void cec_msg_standby(struct cec_msg *msg)
 124{
 125	msg->len = 2;
 126	msg->msg[1] = CEC_MSG_STANDBY;
 127}
 128
 129
 130/* One Touch Record Feature */
 131static __inline__ void cec_msg_record_off(struct cec_msg *msg, int reply)
 132{
 133	msg->len = 2;
 134	msg->msg[1] = CEC_MSG_RECORD_OFF;
 135	msg->reply = reply ? CEC_MSG_RECORD_STATUS : 0;
 136}
 137
 138struct cec_op_arib_data {
 139	__u16 transport_id;
 140	__u16 service_id;
 141	__u16 orig_network_id;
 142};
 143
 144struct cec_op_atsc_data {
 145	__u16 transport_id;
 146	__u16 program_number;
 147};
 148
 149struct cec_op_dvb_data {
 150	__u16 transport_id;
 151	__u16 service_id;
 152	__u16 orig_network_id;
 153};
 154
 155struct cec_op_channel_data {
 156	__u8 channel_number_fmt;
 157	__u16 major;
 158	__u16 minor;
 159};
 160
 161struct cec_op_digital_service_id {
 162	__u8 service_id_method;
 163	__u8 dig_bcast_system;
 164	union {
 165		struct cec_op_arib_data arib;
 166		struct cec_op_atsc_data atsc;
 167		struct cec_op_dvb_data dvb;
 168		struct cec_op_channel_data channel;
 169	};
 170};
 171
 172struct cec_op_record_src {
 173	__u8 type;
 174	union {
 175		struct cec_op_digital_service_id digital;
 176		struct {
 177			__u8 ana_bcast_type;
 178			__u16 ana_freq;
 179			__u8 bcast_system;
 180		} analog;
 181		struct {
 182			__u8 plug;
 183		} ext_plug;
 184		struct {
 185			__u16 phys_addr;
 186		} ext_phys_addr;
 187	};
 188};
 189
 190static __inline__ void cec_set_digital_service_id(__u8 *msg,
 191	      const struct cec_op_digital_service_id *digital)
 192{
 193	*msg++ = (digital->service_id_method << 7) | digital->dig_bcast_system;
 194	if (digital->service_id_method == CEC_OP_SERVICE_ID_METHOD_BY_CHANNEL) {
 195		*msg++ = (digital->channel.channel_number_fmt << 2) |
 196			 (digital->channel.major >> 8);
 197		*msg++ = digital->channel.major & 0xff;
 198		*msg++ = digital->channel.minor >> 8;
 199		*msg++ = digital->channel.minor & 0xff;
 200		*msg++ = 0;
 201		*msg++ = 0;
 202		return;
 203	}
 204	switch (digital->dig_bcast_system) {
 205	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_GEN:
 206	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_CABLE:
 207	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_SAT:
 208	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_T:
 209		*msg++ = digital->atsc.transport_id >> 8;
 210		*msg++ = digital->atsc.transport_id & 0xff;
 211		*msg++ = digital->atsc.program_number >> 8;
 212		*msg++ = digital->atsc.program_number & 0xff;
 213		*msg++ = 0;
 214		*msg++ = 0;
 215		break;
 216	default:
 217		*msg++ = digital->dvb.transport_id >> 8;
 218		*msg++ = digital->dvb.transport_id & 0xff;
 219		*msg++ = digital->dvb.service_id >> 8;
 220		*msg++ = digital->dvb.service_id & 0xff;
 221		*msg++ = digital->dvb.orig_network_id >> 8;
 222		*msg++ = digital->dvb.orig_network_id & 0xff;
 223		break;
 224	}
 225}
 226
 227static __inline__ void cec_get_digital_service_id(const __u8 *msg,
 228	      struct cec_op_digital_service_id *digital)
 229{
 230	digital->service_id_method = msg[0] >> 7;
 231	digital->dig_bcast_system = msg[0] & 0x7f;
 232	if (digital->service_id_method == CEC_OP_SERVICE_ID_METHOD_BY_CHANNEL) {
 233		digital->channel.channel_number_fmt = msg[1] >> 2;
 234		digital->channel.major = ((msg[1] & 3) << 6) | msg[2];
 235		digital->channel.minor = (msg[3] << 8) | msg[4];
 236		return;
 237	}
 238	digital->dvb.transport_id = (msg[1] << 8) | msg[2];
 239	digital->dvb.service_id = (msg[3] << 8) | msg[4];
 240	digital->dvb.orig_network_id = (msg[5] << 8) | msg[6];
 241}
 242
 243static __inline__ void cec_msg_record_on_own(struct cec_msg *msg)
 244{
 245	msg->len = 3;
 246	msg->msg[1] = CEC_MSG_RECORD_ON;
 247	msg->msg[2] = CEC_OP_RECORD_SRC_OWN;
 248}
 249
 250static __inline__ void cec_msg_record_on_digital(struct cec_msg *msg,
 251			     const struct cec_op_digital_service_id *digital)
 252{
 253	msg->len = 10;
 254	msg->msg[1] = CEC_MSG_RECORD_ON;
 255	msg->msg[2] = CEC_OP_RECORD_SRC_DIGITAL;
 256	cec_set_digital_service_id(msg->msg + 3, digital);
 257}
 258
 259static __inline__ void cec_msg_record_on_analog(struct cec_msg *msg,
 260					    __u8 ana_bcast_type,
 261					    __u16 ana_freq,
 262					    __u8 bcast_system)
 263{
 264	msg->len = 7;
 265	msg->msg[1] = CEC_MSG_RECORD_ON;
 266	msg->msg[2] = CEC_OP_RECORD_SRC_ANALOG;
 267	msg->msg[3] = ana_bcast_type;
 268	msg->msg[4] = ana_freq >> 8;
 269	msg->msg[5] = ana_freq & 0xff;
 270	msg->msg[6] = bcast_system;
 271}
 272
 273static __inline__ void cec_msg_record_on_plug(struct cec_msg *msg,
 274					  __u8 plug)
 275{
 276	msg->len = 4;
 277	msg->msg[1] = CEC_MSG_RECORD_ON;
 278	msg->msg[2] = CEC_OP_RECORD_SRC_EXT_PLUG;
 279	msg->msg[3] = plug;
 280}
 281
 282static __inline__ void cec_msg_record_on_phys_addr(struct cec_msg *msg,
 283					       __u16 phys_addr)
 284{
 285	msg->len = 5;
 286	msg->msg[1] = CEC_MSG_RECORD_ON;
 287	msg->msg[2] = CEC_OP_RECORD_SRC_EXT_PHYS_ADDR;
 288	msg->msg[3] = phys_addr >> 8;
 289	msg->msg[4] = phys_addr & 0xff;
 290}
 291
 292static __inline__ void cec_msg_record_on(struct cec_msg *msg,
 293				     int reply,
 294				     const struct cec_op_record_src *rec_src)
 295{
 296	switch (rec_src->type) {
 297	case CEC_OP_RECORD_SRC_OWN:
 298		cec_msg_record_on_own(msg);
 299		break;
 300	case CEC_OP_RECORD_SRC_DIGITAL:
 301		cec_msg_record_on_digital(msg, &rec_src->digital);
 302		break;
 303	case CEC_OP_RECORD_SRC_ANALOG:
 304		cec_msg_record_on_analog(msg,
 305					 rec_src->analog.ana_bcast_type,
 306					 rec_src->analog.ana_freq,
 307					 rec_src->analog.bcast_system);
 308		break;
 309	case CEC_OP_RECORD_SRC_EXT_PLUG:
 310		cec_msg_record_on_plug(msg, rec_src->ext_plug.plug);
 311		break;
 312	case CEC_OP_RECORD_SRC_EXT_PHYS_ADDR:
 313		cec_msg_record_on_phys_addr(msg,
 314					    rec_src->ext_phys_addr.phys_addr);
 315		break;
 316	}
 317	msg->reply = reply ? CEC_MSG_RECORD_STATUS : 0;
 318}
 319
 320static __inline__ void cec_ops_record_on(const struct cec_msg *msg,
 321				     struct cec_op_record_src *rec_src)
 322{
 323	rec_src->type = msg->msg[2];
 324	switch (rec_src->type) {
 325	case CEC_OP_RECORD_SRC_OWN:
 326		break;
 327	case CEC_OP_RECORD_SRC_DIGITAL:
 328		cec_get_digital_service_id(msg->msg + 3, &rec_src->digital);
 329		break;
 330	case CEC_OP_RECORD_SRC_ANALOG:
 331		rec_src->analog.ana_bcast_type = msg->msg[3];
 332		rec_src->analog.ana_freq =
 333			(msg->msg[4] << 8) | msg->msg[5];
 334		rec_src->analog.bcast_system = msg->msg[6];
 335		break;
 336	case CEC_OP_RECORD_SRC_EXT_PLUG:
 337		rec_src->ext_plug.plug = msg->msg[3];
 338		break;
 339	case CEC_OP_RECORD_SRC_EXT_PHYS_ADDR:
 340		rec_src->ext_phys_addr.phys_addr =
 341			(msg->msg[3] << 8) | msg->msg[4];
 342		break;
 343	}
 344}
 345
 346static __inline__ void cec_msg_record_status(struct cec_msg *msg, __u8 rec_status)
 347{
 348	msg->len = 3;
 349	msg->msg[1] = CEC_MSG_RECORD_STATUS;
 350	msg->msg[2] = rec_status;
 351}
 352
 353static __inline__ void cec_ops_record_status(const struct cec_msg *msg,
 354					 __u8 *rec_status)
 355{
 356	*rec_status = msg->msg[2];
 357}
 358
 359static __inline__ void cec_msg_record_tv_screen(struct cec_msg *msg,
 360					    int reply)
 361{
 362	msg->len = 2;
 363	msg->msg[1] = CEC_MSG_RECORD_TV_SCREEN;
 364	msg->reply = reply ? CEC_MSG_RECORD_ON : 0;
 365}
 366
 367
 368/* Timer Programming Feature */
 369static __inline__ void cec_msg_timer_status(struct cec_msg *msg,
 370					__u8 timer_overlap_warning,
 371					__u8 media_info,
 372					__u8 prog_info,
 373					__u8 prog_error,
 374					__u8 duration_hr,
 375					__u8 duration_min)
 376{
 377	msg->len = 3;
 378	msg->msg[1] = CEC_MSG_TIMER_STATUS;
 379	msg->msg[2] = (timer_overlap_warning << 7) |
 380		(media_info << 5) |
 381		(prog_info ? 0x10 : 0) |
 382		(prog_info ? prog_info : prog_error);
 383	if (prog_info == CEC_OP_PROG_INFO_NOT_ENOUGH_SPACE ||
 384	    prog_info == CEC_OP_PROG_INFO_MIGHT_NOT_BE_ENOUGH_SPACE ||
 385	    prog_error == CEC_OP_PROG_ERROR_DUPLICATE) {
 386		msg->len += 2;
 387		msg->msg[3] = ((duration_hr / 10) << 4) | (duration_hr % 10);
 388		msg->msg[4] = ((duration_min / 10) << 4) | (duration_min % 10);
 389	}
 390}
 391
 392static __inline__ void cec_ops_timer_status(const struct cec_msg *msg,
 393					__u8 *timer_overlap_warning,
 394					__u8 *media_info,
 395					__u8 *prog_info,
 396					__u8 *prog_error,
 397					__u8 *duration_hr,
 398					__u8 *duration_min)
 399{
 400	*timer_overlap_warning = msg->msg[2] >> 7;
 401	*media_info = (msg->msg[2] >> 5) & 3;
 402	if (msg->msg[2] & 0x10) {
 403		*prog_info = msg->msg[2] & 0xf;
 404		*prog_error = 0;
 405	} else {
 406		*prog_info = 0;
 407		*prog_error = msg->msg[2] & 0xf;
 408	}
 409	if (*prog_info == CEC_OP_PROG_INFO_NOT_ENOUGH_SPACE ||
 410	    *prog_info == CEC_OP_PROG_INFO_MIGHT_NOT_BE_ENOUGH_SPACE ||
 411	    *prog_error == CEC_OP_PROG_ERROR_DUPLICATE) {
 412		*duration_hr = (msg->msg[3] >> 4) * 10 + (msg->msg[3] & 0xf);
 413		*duration_min = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf);
 414	} else {
 415		*duration_hr = *duration_min = 0;
 416	}
 417}
 418
 419static __inline__ void cec_msg_timer_cleared_status(struct cec_msg *msg,
 420						__u8 timer_cleared_status)
 421{
 422	msg->len = 3;
 423	msg->msg[1] = CEC_MSG_TIMER_CLEARED_STATUS;
 424	msg->msg[2] = timer_cleared_status;
 425}
 426
 427static __inline__ void cec_ops_timer_cleared_status(const struct cec_msg *msg,
 428						__u8 *timer_cleared_status)
 429{
 430	*timer_cleared_status = msg->msg[2];
 431}
 432
 433static __inline__ void cec_msg_clear_analogue_timer(struct cec_msg *msg,
 434						int reply,
 435						__u8 day,
 436						__u8 month,
 437						__u8 start_hr,
 438						__u8 start_min,
 439						__u8 duration_hr,
 440						__u8 duration_min,
 441						__u8 recording_seq,
 442						__u8 ana_bcast_type,
 443						__u16 ana_freq,
 444						__u8 bcast_system)
 445{
 446	msg->len = 13;
 447	msg->msg[1] = CEC_MSG_CLEAR_ANALOGUE_TIMER;
 448	msg->msg[2] = day;
 449	msg->msg[3] = month;
 450	/* Hours and minutes are in BCD format */
 451	msg->msg[4] = ((start_hr / 10) << 4) | (start_hr % 10);
 452	msg->msg[5] = ((start_min / 10) << 4) | (start_min % 10);
 453	msg->msg[6] = ((duration_hr / 10) << 4) | (duration_hr % 10);
 454	msg->msg[7] = ((duration_min / 10) << 4) | (duration_min % 10);
 455	msg->msg[8] = recording_seq;
 456	msg->msg[9] = ana_bcast_type;
 457	msg->msg[10] = ana_freq >> 8;
 458	msg->msg[11] = ana_freq & 0xff;
 459	msg->msg[12] = bcast_system;
 460	msg->reply = reply ? CEC_MSG_TIMER_CLEARED_STATUS : 0;
 461}
 462
 463static __inline__ void cec_ops_clear_analogue_timer(const struct cec_msg *msg,
 464						__u8 *day,
 465						__u8 *month,
 466						__u8 *start_hr,
 467						__u8 *start_min,
 468						__u8 *duration_hr,
 469						__u8 *duration_min,
 470						__u8 *recording_seq,
 471						__u8 *ana_bcast_type,
 472						__u16 *ana_freq,
 473						__u8 *bcast_system)
 474{
 475	*day = msg->msg[2];
 476	*month = msg->msg[3];
 477	/* Hours and minutes are in BCD format */
 478	*start_hr = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf);
 479	*start_min = (msg->msg[5] >> 4) * 10 + (msg->msg[5] & 0xf);
 480	*duration_hr = (msg->msg[6] >> 4) * 10 + (msg->msg[6] & 0xf);
 481	*duration_min = (msg->msg[7] >> 4) * 10 + (msg->msg[7] & 0xf);
 482	*recording_seq = msg->msg[8];
 483	*ana_bcast_type = msg->msg[9];
 484	*ana_freq = (msg->msg[10] << 8) | msg->msg[11];
 485	*bcast_system = msg->msg[12];
 486}
 487
 488static __inline__ void cec_msg_clear_digital_timer(struct cec_msg *msg,
 489				int reply,
 490				__u8 day,
 491				__u8 month,
 492				__u8 start_hr,
 493				__u8 start_min,
 494				__u8 duration_hr,
 495				__u8 duration_min,
 496				__u8 recording_seq,
 497				const struct cec_op_digital_service_id *digital)
 498{
 499	msg->len = 16;
 500	msg->reply = reply ? CEC_MSG_TIMER_CLEARED_STATUS : 0;
 501	msg->msg[1] = CEC_MSG_CLEAR_DIGITAL_TIMER;
 502	msg->msg[2] = day;
 503	msg->msg[3] = month;
 504	/* Hours and minutes are in BCD format */
 505	msg->msg[4] = ((start_hr / 10) << 4) | (start_hr % 10);
 506	msg->msg[5] = ((start_min / 10) << 4) | (start_min % 10);
 507	msg->msg[6] = ((duration_hr / 10) << 4) | (duration_hr % 10);
 508	msg->msg[7] = ((duration_min / 10) << 4) | (duration_min % 10);
 509	msg->msg[8] = recording_seq;
 510	cec_set_digital_service_id(msg->msg + 9, digital);
 511}
 512
 513static __inline__ void cec_ops_clear_digital_timer(const struct cec_msg *msg,
 514				__u8 *day,
 515				__u8 *month,
 516				__u8 *start_hr,
 517				__u8 *start_min,
 518				__u8 *duration_hr,
 519				__u8 *duration_min,
 520				__u8 *recording_seq,
 521				struct cec_op_digital_service_id *digital)
 522{
 523	*day = msg->msg[2];
 524	*month = msg->msg[3];
 525	/* Hours and minutes are in BCD format */
 526	*start_hr = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf);
 527	*start_min = (msg->msg[5] >> 4) * 10 + (msg->msg[5] & 0xf);
 528	*duration_hr = (msg->msg[6] >> 4) * 10 + (msg->msg[6] & 0xf);
 529	*duration_min = (msg->msg[7] >> 4) * 10 + (msg->msg[7] & 0xf);
 530	*recording_seq = msg->msg[8];
 531	cec_get_digital_service_id(msg->msg + 9, digital);
 532}
 533
 534static __inline__ void cec_msg_clear_ext_timer(struct cec_msg *msg,
 535					   int reply,
 536					   __u8 day,
 537					   __u8 month,
 538					   __u8 start_hr,
 539					   __u8 start_min,
 540					   __u8 duration_hr,
 541					   __u8 duration_min,
 542					   __u8 recording_seq,
 543					   __u8 ext_src_spec,
 544					   __u8 plug,
 545					   __u16 phys_addr)
 546{
 547	msg->len = 13;
 548	msg->msg[1] = CEC_MSG_CLEAR_EXT_TIMER;
 549	msg->msg[2] = day;
 550	msg->msg[3] = month;
 551	/* Hours and minutes are in BCD format */
 552	msg->msg[4] = ((start_hr / 10) << 4) | (start_hr % 10);
 553	msg->msg[5] = ((start_min / 10) << 4) | (start_min % 10);
 554	msg->msg[6] = ((duration_hr / 10) << 4) | (duration_hr % 10);
 555	msg->msg[7] = ((duration_min / 10) << 4) | (duration_min % 10);
 556	msg->msg[8] = recording_seq;
 557	msg->msg[9] = ext_src_spec;
 558	msg->msg[10] = plug;
 559	msg->msg[11] = phys_addr >> 8;
 560	msg->msg[12] = phys_addr & 0xff;
 561	msg->reply = reply ? CEC_MSG_TIMER_CLEARED_STATUS : 0;
 562}
 563
 564static __inline__ void cec_ops_clear_ext_timer(const struct cec_msg *msg,
 565					   __u8 *day,
 566					   __u8 *month,
 567					   __u8 *start_hr,
 568					   __u8 *start_min,
 569					   __u8 *duration_hr,
 570					   __u8 *duration_min,
 571					   __u8 *recording_seq,
 572					   __u8 *ext_src_spec,
 573					   __u8 *plug,
 574					   __u16 *phys_addr)
 575{
 576	*day = msg->msg[2];
 577	*month = msg->msg[3];
 578	/* Hours and minutes are in BCD format */
 579	*start_hr = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf);
 580	*start_min = (msg->msg[5] >> 4) * 10 + (msg->msg[5] & 0xf);
 581	*duration_hr = (msg->msg[6] >> 4) * 10 + (msg->msg[6] & 0xf);
 582	*duration_min = (msg->msg[7] >> 4) * 10 + (msg->msg[7] & 0xf);
 583	*recording_seq = msg->msg[8];
 584	*ext_src_spec = msg->msg[9];
 585	*plug = msg->msg[10];
 586	*phys_addr = (msg->msg[11] << 8) | msg->msg[12];
 587}
 588
 589static __inline__ void cec_msg_set_analogue_timer(struct cec_msg *msg,
 590					      int reply,
 591					      __u8 day,
 592					      __u8 month,
 593					      __u8 start_hr,
 594					      __u8 start_min,
 595					      __u8 duration_hr,
 596					      __u8 duration_min,
 597					      __u8 recording_seq,
 598					      __u8 ana_bcast_type,
 599					      __u16 ana_freq,
 600					      __u8 bcast_system)
 601{
 602	msg->len = 13;
 603	msg->msg[1] = CEC_MSG_SET_ANALOGUE_TIMER;
 604	msg->msg[2] = day;
 605	msg->msg[3] = month;
 606	/* Hours and minutes are in BCD format */
 607	msg->msg[4] = ((start_hr / 10) << 4) | (start_hr % 10);
 608	msg->msg[5] = ((start_min / 10) << 4) | (start_min % 10);
 609	msg->msg[6] = ((duration_hr / 10) << 4) | (duration_hr % 10);
 610	msg->msg[7] = ((duration_min / 10) << 4) | (duration_min % 10);
 611	msg->msg[8] = recording_seq;
 612	msg->msg[9] = ana_bcast_type;
 613	msg->msg[10] = ana_freq >> 8;
 614	msg->msg[11] = ana_freq & 0xff;
 615	msg->msg[12] = bcast_system;
 616	msg->reply = reply ? CEC_MSG_TIMER_STATUS : 0;
 617}
 618
 619static __inline__ void cec_ops_set_analogue_timer(const struct cec_msg *msg,
 620					      __u8 *day,
 621					      __u8 *month,
 622					      __u8 *start_hr,
 623					      __u8 *start_min,
 624					      __u8 *duration_hr,
 625					      __u8 *duration_min,
 626					      __u8 *recording_seq,
 627					      __u8 *ana_bcast_type,
 628					      __u16 *ana_freq,
 629					      __u8 *bcast_system)
 630{
 631	*day = msg->msg[2];
 632	*month = msg->msg[3];
 633	/* Hours and minutes are in BCD format */
 634	*start_hr = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf);
 635	*start_min = (msg->msg[5] >> 4) * 10 + (msg->msg[5] & 0xf);
 636	*duration_hr = (msg->msg[6] >> 4) * 10 + (msg->msg[6] & 0xf);
 637	*duration_min = (msg->msg[7] >> 4) * 10 + (msg->msg[7] & 0xf);
 638	*recording_seq = msg->msg[8];
 639	*ana_bcast_type = msg->msg[9];
 640	*ana_freq = (msg->msg[10] << 8) | msg->msg[11];
 641	*bcast_system = msg->msg[12];
 642}
 643
 644static __inline__ void cec_msg_set_digital_timer(struct cec_msg *msg,
 645			int reply,
 646			__u8 day,
 647			__u8 month,
 648			__u8 start_hr,
 649			__u8 start_min,
 650			__u8 duration_hr,
 651			__u8 duration_min,
 652			__u8 recording_seq,
 653			const struct cec_op_digital_service_id *digital)
 654{
 655	msg->len = 16;
 656	msg->reply = reply ? CEC_MSG_TIMER_STATUS : 0;
 657	msg->msg[1] = CEC_MSG_SET_DIGITAL_TIMER;
 658	msg->msg[2] = day;
 659	msg->msg[3] = month;
 660	/* Hours and minutes are in BCD format */
 661	msg->msg[4] = ((start_hr / 10) << 4) | (start_hr % 10);
 662	msg->msg[5] = ((start_min / 10) << 4) | (start_min % 10);
 663	msg->msg[6] = ((duration_hr / 10) << 4) | (duration_hr % 10);
 664	msg->msg[7] = ((duration_min / 10) << 4) | (duration_min % 10);
 665	msg->msg[8] = recording_seq;
 666	cec_set_digital_service_id(msg->msg + 9, digital);
 667}
 668
 669static __inline__ void cec_ops_set_digital_timer(const struct cec_msg *msg,
 670			__u8 *day,
 671			__u8 *month,
 672			__u8 *start_hr,
 673			__u8 *start_min,
 674			__u8 *duration_hr,
 675			__u8 *duration_min,
 676			__u8 *recording_seq,
 677			struct cec_op_digital_service_id *digital)
 678{
 679	*day = msg->msg[2];
 680	*month = msg->msg[3];
 681	/* Hours and minutes are in BCD format */
 682	*start_hr = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf);
 683	*start_min = (msg->msg[5] >> 4) * 10 + (msg->msg[5] & 0xf);
 684	*duration_hr = (msg->msg[6] >> 4) * 10 + (msg->msg[6] & 0xf);
 685	*duration_min = (msg->msg[7] >> 4) * 10 + (msg->msg[7] & 0xf);
 686	*recording_seq = msg->msg[8];
 687	cec_get_digital_service_id(msg->msg + 9, digital);
 688}
 689
 690static __inline__ void cec_msg_set_ext_timer(struct cec_msg *msg,
 691					 int reply,
 692					 __u8 day,
 693					 __u8 month,
 694					 __u8 start_hr,
 695					 __u8 start_min,
 696					 __u8 duration_hr,
 697					 __u8 duration_min,
 698					 __u8 recording_seq,
 699					 __u8 ext_src_spec,
 700					 __u8 plug,
 701					 __u16 phys_addr)
 702{
 703	msg->len = 13;
 704	msg->msg[1] = CEC_MSG_SET_EXT_TIMER;
 705	msg->msg[2] = day;
 706	msg->msg[3] = month;
 707	/* Hours and minutes are in BCD format */
 708	msg->msg[4] = ((start_hr / 10) << 4) | (start_hr % 10);
 709	msg->msg[5] = ((start_min / 10) << 4) | (start_min % 10);
 710	msg->msg[6] = ((duration_hr / 10) << 4) | (duration_hr % 10);
 711	msg->msg[7] = ((duration_min / 10) << 4) | (duration_min % 10);
 712	msg->msg[8] = recording_seq;
 713	msg->msg[9] = ext_src_spec;
 714	msg->msg[10] = plug;
 715	msg->msg[11] = phys_addr >> 8;
 716	msg->msg[12] = phys_addr & 0xff;
 717	msg->reply = reply ? CEC_MSG_TIMER_STATUS : 0;
 718}
 719
 720static __inline__ void cec_ops_set_ext_timer(const struct cec_msg *msg,
 721					 __u8 *day,
 722					 __u8 *month,
 723					 __u8 *start_hr,
 724					 __u8 *start_min,
 725					 __u8 *duration_hr,
 726					 __u8 *duration_min,
 727					 __u8 *recording_seq,
 728					 __u8 *ext_src_spec,
 729					 __u8 *plug,
 730					 __u16 *phys_addr)
 731{
 732	*day = msg->msg[2];
 733	*month = msg->msg[3];
 734	/* Hours and minutes are in BCD format */
 735	*start_hr = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf);
 736	*start_min = (msg->msg[5] >> 4) * 10 + (msg->msg[5] & 0xf);
 737	*duration_hr = (msg->msg[6] >> 4) * 10 + (msg->msg[6] & 0xf);
 738	*duration_min = (msg->msg[7] >> 4) * 10 + (msg->msg[7] & 0xf);
 739	*recording_seq = msg->msg[8];
 740	*ext_src_spec = msg->msg[9];
 741	*plug = msg->msg[10];
 742	*phys_addr = (msg->msg[11] << 8) | msg->msg[12];
 743}
 744
 745static __inline__ void cec_msg_set_timer_program_title(struct cec_msg *msg,
 746						   const char *prog_title)
 747{
 748	unsigned int len = strlen(prog_title);
 749
 750	if (len > 14)
 751		len = 14;
 752	msg->len = 2 + len;
 753	msg->msg[1] = CEC_MSG_SET_TIMER_PROGRAM_TITLE;
 754	memcpy(msg->msg + 2, prog_title, len);
 755}
 756
 757static __inline__ void cec_ops_set_timer_program_title(const struct cec_msg *msg,
 758						   char *prog_title)
 759{
 760	unsigned int len = msg->len > 2 ? msg->len - 2 : 0;
 761
 762	if (len > 14)
 763		len = 14;
 764	memcpy(prog_title, msg->msg + 2, len);
 765	prog_title[len] = '\0';
 766}
 767
 768/* System Information Feature */
 769static __inline__ void cec_msg_cec_version(struct cec_msg *msg, __u8 cec_version)
 770{
 771	msg->len = 3;
 772	msg->msg[1] = CEC_MSG_CEC_VERSION;
 773	msg->msg[2] = cec_version;
 774}
 775
 776static __inline__ void cec_ops_cec_version(const struct cec_msg *msg,
 777				       __u8 *cec_version)
 778{
 779	*cec_version = msg->msg[2];
 780}
 781
 782static __inline__ void cec_msg_get_cec_version(struct cec_msg *msg,
 783					   int reply)
 784{
 785	msg->len = 2;
 786	msg->msg[1] = CEC_MSG_GET_CEC_VERSION;
 787	msg->reply = reply ? CEC_MSG_CEC_VERSION : 0;
 788}
 789
 790static __inline__ void cec_msg_report_physical_addr(struct cec_msg *msg,
 791					__u16 phys_addr, __u8 prim_devtype)
 792{
 793	msg->len = 5;
 794	msg->msg[0] |= CEC_LOG_ADDR_BROADCAST;
 795	msg->msg[1] = CEC_MSG_REPORT_PHYSICAL_ADDR;
 796	msg->msg[2] = phys_addr >> 8;
 797	msg->msg[3] = phys_addr & 0xff;
 798	msg->msg[4] = prim_devtype;
 799}
 800
 801static __inline__ void cec_ops_report_physical_addr(const struct cec_msg *msg,
 802					__u16 *phys_addr, __u8 *prim_devtype)
 803{
 804	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
 805	*prim_devtype = msg->msg[4];
 806}
 807
 808static __inline__ void cec_msg_give_physical_addr(struct cec_msg *msg,
 809					      int reply)
 810{
 811	msg->len = 2;
 812	msg->msg[1] = CEC_MSG_GIVE_PHYSICAL_ADDR;
 813	msg->reply = reply ? CEC_MSG_REPORT_PHYSICAL_ADDR : 0;
 814}
 815
 816static __inline__ void cec_msg_set_menu_language(struct cec_msg *msg,
 817					     const char *language)
 818{
 819	msg->len = 5;
 820	msg->msg[0] |= CEC_LOG_ADDR_BROADCAST;
 821	msg->msg[1] = CEC_MSG_SET_MENU_LANGUAGE;
 822	memcpy(msg->msg + 2, language, 3);
 823}
 824
 825static __inline__ void cec_ops_set_menu_language(const struct cec_msg *msg,
 826					     char *language)
 827{
 828	memcpy(language, msg->msg + 2, 3);
 829	language[3] = '\0';
 830}
 831
 832static __inline__ void cec_msg_get_menu_language(struct cec_msg *msg,
 833					     int reply)
 834{
 835	msg->len = 2;
 836	msg->msg[1] = CEC_MSG_GET_MENU_LANGUAGE;
 837	msg->reply = reply ? CEC_MSG_SET_MENU_LANGUAGE : 0;
 838}
 839
 840/*
 841 * Assumes a single RC Profile byte and a single Device Features byte,
 842 * i.e. no extended features are supported by this helper function.
 843 *
 844 * As of CEC 2.0 no extended features are defined, should those be added
 845 * in the future, then this function needs to be adapted or a new function
 846 * should be added.
 847 */
 848static __inline__ void cec_msg_report_features(struct cec_msg *msg,
 849				__u8 cec_version, __u8 all_device_types,
 850				__u8 rc_profile, __u8 dev_features)
 851{
 852	msg->len = 6;
 853	msg->msg[0] |= CEC_LOG_ADDR_BROADCAST;
 854	msg->msg[1] = CEC_MSG_REPORT_FEATURES;
 855	msg->msg[2] = cec_version;
 856	msg->msg[3] = all_device_types;
 857	msg->msg[4] = rc_profile;
 858	msg->msg[5] = dev_features;
 859}
 860
 861static __inline__ void cec_ops_report_features(const struct cec_msg *msg,
 862			__u8 *cec_version, __u8 *all_device_types,
 863			const __u8 **rc_profile, const __u8 **dev_features)
 864{
 865	const __u8 *p = &msg->msg[4];
 866
 867	*cec_version = msg->msg[2];
 868	*all_device_types = msg->msg[3];
 869	*rc_profile = p;
 870	*dev_features = NULL;
 871	while (p < &msg->msg[14] && (*p & CEC_OP_FEAT_EXT))
 872		p++;
 873	if (!(*p & CEC_OP_FEAT_EXT)) {
 874		*dev_features = p + 1;
 875		while (p < &msg->msg[15] && (*p & CEC_OP_FEAT_EXT))
 876			p++;
 877	}
 878	if (*p & CEC_OP_FEAT_EXT)
 879		*rc_profile = *dev_features = NULL;
 880}
 881
 882static __inline__ void cec_msg_give_features(struct cec_msg *msg,
 883					 int reply)
 884{
 885	msg->len = 2;
 886	msg->msg[1] = CEC_MSG_GIVE_FEATURES;
 887	msg->reply = reply ? CEC_MSG_REPORT_FEATURES : 0;
 888}
 889
 890/* Deck Control Feature */
 891static __inline__ void cec_msg_deck_control(struct cec_msg *msg,
 892					__u8 deck_control_mode)
 893{
 894	msg->len = 3;
 895	msg->msg[1] = CEC_MSG_DECK_CONTROL;
 896	msg->msg[2] = deck_control_mode;
 897}
 898
 899static __inline__ void cec_ops_deck_control(const struct cec_msg *msg,
 900					__u8 *deck_control_mode)
 901{
 902	*deck_control_mode = msg->msg[2];
 903}
 904
 905static __inline__ void cec_msg_deck_status(struct cec_msg *msg,
 906				       __u8 deck_info)
 907{
 908	msg->len = 3;
 909	msg->msg[1] = CEC_MSG_DECK_STATUS;
 910	msg->msg[2] = deck_info;
 911}
 912
 913static __inline__ void cec_ops_deck_status(const struct cec_msg *msg,
 914				       __u8 *deck_info)
 915{
 916	*deck_info = msg->msg[2];
 917}
 918
 919static __inline__ void cec_msg_give_deck_status(struct cec_msg *msg,
 920					    int reply,
 921					    __u8 status_req)
 922{
 923	msg->len = 3;
 924	msg->msg[1] = CEC_MSG_GIVE_DECK_STATUS;
 925	msg->msg[2] = status_req;
 926	msg->reply = (reply && status_req != CEC_OP_STATUS_REQ_OFF) ?
 927				CEC_MSG_DECK_STATUS : 0;
 928}
 929
 930static __inline__ void cec_ops_give_deck_status(const struct cec_msg *msg,
 931					    __u8 *status_req)
 932{
 933	*status_req = msg->msg[2];
 934}
 935
 936static __inline__ void cec_msg_play(struct cec_msg *msg,
 937				__u8 play_mode)
 938{
 939	msg->len = 3;
 940	msg->msg[1] = CEC_MSG_PLAY;
 941	msg->msg[2] = play_mode;
 942}
 943
 944static __inline__ void cec_ops_play(const struct cec_msg *msg,
 945				__u8 *play_mode)
 946{
 947	*play_mode = msg->msg[2];
 948}
 949
 950
 951/* Tuner Control Feature */
 952struct cec_op_tuner_device_info {
 953	__u8 rec_flag;
 954	__u8 tuner_display_info;
 955	__u8 is_analog;
 956	union {
 957		struct cec_op_digital_service_id digital;
 958		struct {
 959			__u8 ana_bcast_type;
 960			__u16 ana_freq;
 961			__u8 bcast_system;
 962		} analog;
 963	};
 964};
 965
 966static __inline__ void cec_msg_tuner_device_status_analog(struct cec_msg *msg,
 967						      __u8 rec_flag,
 968						      __u8 tuner_display_info,
 969						      __u8 ana_bcast_type,
 970						      __u16 ana_freq,
 971						      __u8 bcast_system)
 972{
 973	msg->len = 7;
 974	msg->msg[1] = CEC_MSG_TUNER_DEVICE_STATUS;
 975	msg->msg[2] = (rec_flag << 7) | tuner_display_info;
 976	msg->msg[3] = ana_bcast_type;
 977	msg->msg[4] = ana_freq >> 8;
 978	msg->msg[5] = ana_freq & 0xff;
 979	msg->msg[6] = bcast_system;
 980}
 981
 982static __inline__ void cec_msg_tuner_device_status_digital(struct cec_msg *msg,
 983		   __u8 rec_flag, __u8 tuner_display_info,
 984		   const struct cec_op_digital_service_id *digital)
 985{
 986	msg->len = 10;
 987	msg->msg[1] = CEC_MSG_TUNER_DEVICE_STATUS;
 988	msg->msg[2] = (rec_flag << 7) | tuner_display_info;
 989	cec_set_digital_service_id(msg->msg + 3, digital);
 990}
 991
 992static __inline__ void cec_msg_tuner_device_status(struct cec_msg *msg,
 993			const struct cec_op_tuner_device_info *tuner_dev_info)
 994{
 995	if (tuner_dev_info->is_analog)
 996		cec_msg_tuner_device_status_analog(msg,
 997			tuner_dev_info->rec_flag,
 998			tuner_dev_info->tuner_display_info,
 999			tuner_dev_info->analog.ana_bcast_type,
1000			tuner_dev_info->analog.ana_freq,
1001			tuner_dev_info->analog.bcast_system);
1002	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
1009static __inline__ void cec_ops_tuner_device_status(const struct cec_msg *msg,
1010				struct cec_op_tuner_device_info *tuner_dev_info)
1011{
1012	tuner_dev_info->is_analog = msg->len < 10;
1013	tuner_dev_info->rec_flag = msg->msg[2] >> 7;
1014	tuner_dev_info->tuner_display_info = msg->msg[2] & 0x7f;
1015	if (tuner_dev_info->is_analog) {
1016		tuner_dev_info->analog.ana_bcast_type = msg->msg[3];
1017		tuner_dev_info->analog.ana_freq = (msg->msg[4] << 8) | msg->msg[5];
1018		tuner_dev_info->analog.bcast_system = msg->msg[6];
1019		return;
1020	}
1021	cec_get_digital_service_id(msg->msg + 3, &tuner_dev_info->digital);
1022}
1023
1024static __inline__ void cec_msg_give_tuner_device_status(struct cec_msg *msg,
1025						    int reply,
1026						    __u8 status_req)
1027{
1028	msg->len = 3;
1029	msg->msg[1] = CEC_MSG_GIVE_TUNER_DEVICE_STATUS;
1030	msg->msg[2] = status_req;
1031	msg->reply = (reply && status_req != CEC_OP_STATUS_REQ_OFF) ?
1032				CEC_MSG_TUNER_DEVICE_STATUS : 0;
1033}
1034
1035static __inline__ void cec_ops_give_tuner_device_status(const struct cec_msg *msg,
1036						    __u8 *status_req)
1037{
1038	*status_req = msg->msg[2];
1039}
1040
1041static __inline__ void cec_msg_select_analogue_service(struct cec_msg *msg,
1042						   __u8 ana_bcast_type,
1043						   __u16 ana_freq,
1044						   __u8 bcast_system)
1045{
1046	msg->len = 6;
1047	msg->msg[1] = CEC_MSG_SELECT_ANALOGUE_SERVICE;
1048	msg->msg[2] = ana_bcast_type;
1049	msg->msg[3] = ana_freq >> 8;
1050	msg->msg[4] = ana_freq & 0xff;
1051	msg->msg[5] = bcast_system;
1052}
1053
1054static __inline__ void cec_ops_select_analogue_service(const struct cec_msg *msg,
1055						   __u8 *ana_bcast_type,
1056						   __u16 *ana_freq,
1057						   __u8 *bcast_system)
1058{
1059	*ana_bcast_type = msg->msg[2];
1060	*ana_freq = (msg->msg[3] << 8) | msg->msg[4];
1061	*bcast_system = msg->msg[5];
1062}
1063
1064static __inline__ void cec_msg_select_digital_service(struct cec_msg *msg,
1065				const struct cec_op_digital_service_id *digital)
1066{
1067	msg->len = 9;
1068	msg->msg[1] = CEC_MSG_SELECT_DIGITAL_SERVICE;
1069	cec_set_digital_service_id(msg->msg + 2, digital);
1070}
1071
1072static __inline__ void cec_ops_select_digital_service(const struct cec_msg *msg,
1073				struct cec_op_digital_service_id *digital)
1074{
1075	cec_get_digital_service_id(msg->msg + 2, digital);
1076}
1077
1078static __inline__ void cec_msg_tuner_step_decrement(struct cec_msg *msg)
1079{
1080	msg->len = 2;
1081	msg->msg[1] = CEC_MSG_TUNER_STEP_DECREMENT;
1082}
1083
1084static __inline__ void cec_msg_tuner_step_increment(struct cec_msg *msg)
1085{
1086	msg->len = 2;
1087	msg->msg[1] = CEC_MSG_TUNER_STEP_INCREMENT;
1088}
1089
1090
1091/* Vendor Specific Commands Feature */
1092static __inline__ void cec_msg_device_vendor_id(struct cec_msg *msg, __u32 vendor_id)
1093{
1094	msg->len = 5;
1095	msg->msg[0] |= CEC_LOG_ADDR_BROADCAST;
1096	msg->msg[1] = CEC_MSG_DEVICE_VENDOR_ID;
1097	msg->msg[2] = vendor_id >> 16;
1098	msg->msg[3] = (vendor_id >> 8) & 0xff;
1099	msg->msg[4] = vendor_id & 0xff;
1100}
1101
1102static __inline__ void cec_ops_device_vendor_id(const struct cec_msg *msg,
1103					    __u32 *vendor_id)
1104{
1105	*vendor_id = (msg->msg[2] << 16) | (msg->msg[3] << 8) | msg->msg[4];
1106}
1107
1108static __inline__ void cec_msg_give_device_vendor_id(struct cec_msg *msg,
1109						 int reply)
1110{
1111	msg->len = 2;
1112	msg->msg[1] = CEC_MSG_GIVE_DEVICE_VENDOR_ID;
1113	msg->reply = reply ? CEC_MSG_DEVICE_VENDOR_ID : 0;
1114}
1115
1116static __inline__ void cec_msg_vendor_command(struct cec_msg *msg,
1117					  __u8 size, const __u8 *vendor_cmd)
1118{
1119	if (size > 14)
1120		size = 14;
1121	msg->len = 2 + size;
1122	msg->msg[1] = CEC_MSG_VENDOR_COMMAND;
1123	memcpy(msg->msg + 2, vendor_cmd, size);
1124}
1125
1126static __inline__ void cec_ops_vendor_command(const struct cec_msg *msg,
1127					  __u8 *size,
1128					  const __u8 **vendor_cmd)
1129{
1130	*size = msg->len - 2;
1131
1132	if (*size > 14)
1133		*size = 14;
1134	*vendor_cmd = msg->msg + 2;
1135}
1136
1137static __inline__ void cec_msg_vendor_command_with_id(struct cec_msg *msg,
1138						  __u32 vendor_id, __u8 size,
1139						  const __u8 *vendor_cmd)
1140{
1141	if (size > 11)
1142		size = 11;
1143	msg->len = 5 + size;
1144	msg->msg[1] = CEC_MSG_VENDOR_COMMAND_WITH_ID;
1145	msg->msg[2] = vendor_id >> 16;
1146	msg->msg[3] = (vendor_id >> 8) & 0xff;
1147	msg->msg[4] = vendor_id & 0xff;
1148	memcpy(msg->msg + 5, vendor_cmd, size);
1149}
1150
1151static __inline__ void cec_ops_vendor_command_with_id(const struct cec_msg *msg,
1152						  __u32 *vendor_id,  __u8 *size,
1153						  const __u8 **vendor_cmd)
1154{
1155	*size = msg->len - 5;
1156
1157	if (*size > 11)
1158		*size = 11;
1159	*vendor_id = (msg->msg[2] << 16) | (msg->msg[3] << 8) | msg->msg[4];
1160	*vendor_cmd = msg->msg + 5;
1161}
1162
1163static __inline__ void cec_msg_vendor_remote_button_down(struct cec_msg *msg,
1164						     __u8 size,
1165						     const __u8 *rc_code)
1166{
1167	if (size > 14)
1168		size = 14;
1169	msg->len = 2 + size;
1170	msg->msg[1] = CEC_MSG_VENDOR_REMOTE_BUTTON_DOWN;
1171	memcpy(msg->msg + 2, rc_code, size);
1172}
1173
1174static __inline__ void cec_ops_vendor_remote_button_down(const struct cec_msg *msg,
1175						     __u8 *size,
1176						     const __u8 **rc_code)
1177{
1178	*size = msg->len - 2;
1179
1180	if (*size > 14)
1181		*size = 14;
1182	*rc_code = msg->msg + 2;
1183}
1184
1185static __inline__ void cec_msg_vendor_remote_button_up(struct cec_msg *msg)
1186{
1187	msg->len = 2;
1188	msg->msg[1] = CEC_MSG_VENDOR_REMOTE_BUTTON_UP;
1189}
1190
1191
1192/* OSD Display Feature */
1193static __inline__ void cec_msg_set_osd_string(struct cec_msg *msg,
1194					  __u8 disp_ctl,
1195					  const char *osd)
1196{
1197	unsigned int len = strlen(osd);
1198
1199	if (len > 13)
1200		len = 13;
1201	msg->len = 3 + len;
1202	msg->msg[1] = CEC_MSG_SET_OSD_STRING;
1203	msg->msg[2] = disp_ctl;
1204	memcpy(msg->msg + 3, osd, len);
1205}
1206
1207static __inline__ void cec_ops_set_osd_string(const struct cec_msg *msg,
1208					  __u8 *disp_ctl,
1209					  char *osd)
1210{
1211	unsigned int len = msg->len > 3 ? msg->len - 3 : 0;
1212
1213	*disp_ctl = msg->msg[2];
1214	if (len > 13)
1215		len = 13;
1216	memcpy(osd, msg->msg + 3, len);
1217	osd[len] = '\0';
1218}
1219
1220
1221/* Device OSD Transfer Feature */
1222static __inline__ void cec_msg_set_osd_name(struct cec_msg *msg, const char *name)
1223{
1224	unsigned int len = strlen(name);
1225
1226	if (len > 14)
1227		len = 14;
1228	msg->len = 2 + len;
1229	msg->msg[1] = CEC_MSG_SET_OSD_NAME;
1230	memcpy(msg->msg + 2, name, len);
1231}
1232
1233static __inline__ void cec_ops_set_osd_name(const struct cec_msg *msg,
1234					char *name)
1235{
1236	unsigned int len = msg->len > 2 ? msg->len - 2 : 0;
1237
1238	if (len > 14)
1239		len = 14;
1240	memcpy(name, msg->msg + 2, len);
1241	name[len] = '\0';
1242}
1243
1244static __inline__ void cec_msg_give_osd_name(struct cec_msg *msg,
1245					 int reply)
1246{
1247	msg->len = 2;
1248	msg->msg[1] = CEC_MSG_GIVE_OSD_NAME;
1249	msg->reply = reply ? CEC_MSG_SET_OSD_NAME : 0;
1250}
1251
1252
1253/* Device Menu Control Feature */
1254static __inline__ void cec_msg_menu_status(struct cec_msg *msg,
1255				       __u8 menu_state)
1256{
1257	msg->len = 3;
1258	msg->msg[1] = CEC_MSG_MENU_STATUS;
1259	msg->msg[2] = menu_state;
1260}
1261
1262static __inline__ void cec_ops_menu_status(const struct cec_msg *msg,
1263				       __u8 *menu_state)
1264{
1265	*menu_state = msg->msg[2];
1266}
1267
1268static __inline__ void cec_msg_menu_request(struct cec_msg *msg,
1269					int reply,
1270					__u8 menu_req)
1271{
1272	msg->len = 3;
1273	msg->msg[1] = CEC_MSG_MENU_REQUEST;
1274	msg->msg[2] = menu_req;
1275	msg->reply = reply ? CEC_MSG_MENU_STATUS : 0;
1276}
1277
1278static __inline__ void cec_ops_menu_request(const struct cec_msg *msg,
1279					__u8 *menu_req)
1280{
1281	*menu_req = msg->msg[2];
1282}
1283
1284struct cec_op_ui_command {
1285	__u8 ui_cmd;
1286	__u8 has_opt_arg;
1287	union {
1288		struct cec_op_channel_data channel_identifier;
1289		__u8 ui_broadcast_type;
1290		__u8 ui_sound_presentation_control;
1291		__u8 play_mode;
1292		__u8 ui_function_media;
1293		__u8 ui_function_select_av_input;
1294		__u8 ui_function_select_audio_input;
1295	};
1296};
1297
1298static __inline__ void cec_msg_user_control_pressed(struct cec_msg *msg,
1299					const struct cec_op_ui_command *ui_cmd)
1300{
1301	msg->len = 3;
1302	msg->msg[1] = CEC_MSG_USER_CONTROL_PRESSED;
1303	msg->msg[2] = ui_cmd->ui_cmd;
1304	if (!ui_cmd->has_opt_arg)
1305		return;
1306	switch (ui_cmd->ui_cmd) {
1307	case CEC_OP_UI_CMD_SELECT_BROADCAST_TYPE:
1308	case CEC_OP_UI_CMD_SELECT_SOUND_PRESENTATION:
1309	case CEC_OP_UI_CMD_PLAY_FUNCTION:
1310	case CEC_OP_UI_CMD_SELECT_MEDIA_FUNCTION:
1311	case CEC_OP_UI_CMD_SELECT_AV_INPUT_FUNCTION:
1312	case CEC_OP_UI_CMD_SELECT_AUDIO_INPUT_FUNCTION:
1313		/* The optional operand is one byte for all these ui commands */
1314		msg->len++;
1315		msg->msg[3] = ui_cmd->play_mode;
1316		break;
1317	case CEC_OP_UI_CMD_TUNE_FUNCTION:
1318		msg->len += 4;
1319		msg->msg[3] = (ui_cmd->channel_identifier.channel_number_fmt << 2) |
1320			      (ui_cmd->channel_identifier.major >> 8);
1321		msg->msg[4] = ui_cmd->channel_identifier.major & 0xff;
1322		msg->msg[5] = ui_cmd->channel_identifier.minor >> 8;
1323		msg->msg[6] = ui_cmd->channel_identifier.minor & 0xff;
1324		break;
1325	}
1326}
1327
1328static __inline__ void cec_ops_user_control_pressed(const struct cec_msg *msg,
1329						struct cec_op_ui_command *ui_cmd)
1330{
1331	ui_cmd->ui_cmd = msg->msg[2];
1332	ui_cmd->has_opt_arg = 0;
1333	if (msg->len == 3)
1334		return;
1335	switch (ui_cmd->ui_cmd) {
1336	case CEC_OP_UI_CMD_SELECT_BROADCAST_TYPE:
1337	case CEC_OP_UI_CMD_SELECT_SOUND_PRESENTATION:
1338	case CEC_OP_UI_CMD_PLAY_FUNCTION:
1339	case CEC_OP_UI_CMD_SELECT_MEDIA_FUNCTION:
1340	case CEC_OP_UI_CMD_SELECT_AV_INPUT_FUNCTION:
1341	case CEC_OP_UI_CMD_SELECT_AUDIO_INPUT_FUNCTION:
1342		/* The optional operand is one byte for all these ui commands */
1343		ui_cmd->play_mode = msg->msg[3];
1344		ui_cmd->has_opt_arg = 1;
1345		break;
1346	case CEC_OP_UI_CMD_TUNE_FUNCTION:
1347		if (msg->len < 7)
1348			break;
1349		ui_cmd->has_opt_arg = 1;
1350		ui_cmd->channel_identifier.channel_number_fmt = msg->msg[3] >> 2;
1351		ui_cmd->channel_identifier.major = ((msg->msg[3] & 3) << 6) | msg->msg[4];
1352		ui_cmd->channel_identifier.minor = (msg->msg[5] << 8) | msg->msg[6];
1353		break;
1354	}
1355}
1356
1357static __inline__ void cec_msg_user_control_released(struct cec_msg *msg)
1358{
1359	msg->len = 2;
1360	msg->msg[1] = CEC_MSG_USER_CONTROL_RELEASED;
1361}
1362
1363/* Remote Control Passthrough Feature */
1364
1365/* Power Status Feature */
1366static __inline__ void cec_msg_report_power_status(struct cec_msg *msg,
1367					       __u8 pwr_state)
1368{
1369	msg->len = 3;
1370	msg->msg[1] = CEC_MSG_REPORT_POWER_STATUS;
1371	msg->msg[2] = pwr_state;
1372}
1373
1374static __inline__ void cec_ops_report_power_status(const struct cec_msg *msg,
1375					       __u8 *pwr_state)
1376{
1377	*pwr_state = msg->msg[2];
1378}
1379
1380static __inline__ void cec_msg_give_device_power_status(struct cec_msg *msg,
1381						    int reply)
1382{
1383	msg->len = 2;
1384	msg->msg[1] = CEC_MSG_GIVE_DEVICE_POWER_STATUS;
1385	msg->reply = reply ? CEC_MSG_REPORT_POWER_STATUS : 0;
1386}
1387
1388/* General Protocol Messages */
1389static __inline__ void cec_msg_feature_abort(struct cec_msg *msg,
1390					 __u8 abort_msg, __u8 reason)
1391{
1392	msg->len = 4;
1393	msg->msg[1] = CEC_MSG_FEATURE_ABORT;
1394	msg->msg[2] = abort_msg;
1395	msg->msg[3] = reason;
1396}
1397
1398static __inline__ void cec_ops_feature_abort(const struct cec_msg *msg,
1399					 __u8 *abort_msg, __u8 *reason)
1400{
1401	*abort_msg = msg->msg[2];
1402	*reason = msg->msg[3];
1403}
1404
1405/* This changes the current message into a feature abort message */
1406static __inline__ void cec_msg_reply_feature_abort(struct cec_msg *msg, __u8 reason)
1407{
1408	cec_msg_set_reply_to(msg, msg);
1409	msg->len = 4;
1410	msg->msg[2] = msg->msg[1];
1411	msg->msg[3] = reason;
1412	msg->msg[1] = CEC_MSG_FEATURE_ABORT;
1413}
1414
1415static __inline__ void cec_msg_abort(struct cec_msg *msg)
1416{
1417	msg->len = 2;
1418	msg->msg[1] = CEC_MSG_ABORT;
1419}
1420
1421
1422/* System Audio Control Feature */
1423static __inline__ void cec_msg_report_audio_status(struct cec_msg *msg,
1424					       __u8 aud_mute_status,
1425					       __u8 aud_vol_status)
1426{
1427	msg->len = 3;
1428	msg->msg[1] = CEC_MSG_REPORT_AUDIO_STATUS;
1429	msg->msg[2] = (aud_mute_status << 7) | (aud_vol_status & 0x7f);
1430}
1431
1432static __inline__ void cec_ops_report_audio_status(const struct cec_msg *msg,
1433					       __u8 *aud_mute_status,
1434					       __u8 *aud_vol_status)
1435{
1436	*aud_mute_status = msg->msg[2] >> 7;
1437	*aud_vol_status = msg->msg[2] & 0x7f;
1438}
1439
1440static __inline__ void cec_msg_give_audio_status(struct cec_msg *msg,
1441					     int reply)
1442{
1443	msg->len = 2;
1444	msg->msg[1] = CEC_MSG_GIVE_AUDIO_STATUS;
1445	msg->reply = reply ? CEC_MSG_REPORT_AUDIO_STATUS : 0;
1446}
1447
1448static __inline__ void cec_msg_set_system_audio_mode(struct cec_msg *msg,
1449						 __u8 sys_aud_status)
1450{
1451	msg->len = 3;
1452	msg->msg[1] = CEC_MSG_SET_SYSTEM_AUDIO_MODE;
1453	msg->msg[2] = sys_aud_status;
1454}
1455
1456static __inline__ void cec_ops_set_system_audio_mode(const struct cec_msg *msg,
1457						 __u8 *sys_aud_status)
1458{
1459	*sys_aud_status = msg->msg[2];
1460}
1461
1462static __inline__ void cec_msg_system_audio_mode_request(struct cec_msg *msg,
1463						     int reply,
1464						     __u16 phys_addr)
1465{
1466	msg->len = phys_addr == 0xffff ? 2 : 4;
1467	msg->msg[1] = CEC_MSG_SYSTEM_AUDIO_MODE_REQUEST;
1468	msg->msg[2] = phys_addr >> 8;
1469	msg->msg[3] = phys_addr & 0xff;
1470	msg->reply = reply ? CEC_MSG_SET_SYSTEM_AUDIO_MODE : 0;
1471
1472}
1473
1474static __inline__ void cec_ops_system_audio_mode_request(const struct cec_msg *msg,
1475						     __u16 *phys_addr)
1476{
1477	if (msg->len < 4)
1478		*phys_addr = 0xffff;
1479	else
1480		*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1481}
1482
1483static __inline__ void cec_msg_system_audio_mode_status(struct cec_msg *msg,
1484						    __u8 sys_aud_status)
1485{
1486	msg->len = 3;
1487	msg->msg[1] = CEC_MSG_SYSTEM_AUDIO_MODE_STATUS;
1488	msg->msg[2] = sys_aud_status;
1489}
1490
1491static __inline__ void cec_ops_system_audio_mode_status(const struct cec_msg *msg,
1492						    __u8 *sys_aud_status)
1493{
1494	*sys_aud_status = msg->msg[2];
1495}
1496
1497static __inline__ void cec_msg_give_system_audio_mode_status(struct cec_msg *msg,
1498							 int reply)
1499{
1500	msg->len = 2;
1501	msg->msg[1] = CEC_MSG_GIVE_SYSTEM_AUDIO_MODE_STATUS;
1502	msg->reply = reply ? CEC_MSG_SYSTEM_AUDIO_MODE_STATUS : 0;
1503}
1504
1505static __inline__ void cec_msg_report_short_audio_descriptor(struct cec_msg *msg,
1506					__u8 num_descriptors,
1507					const __u32 *descriptors)
1508{
1509	unsigned int i;
1510
1511	if (num_descriptors > 4)
1512		num_descriptors = 4;
1513	msg->len = 2 + num_descriptors * 3;
1514	msg->msg[1] = CEC_MSG_REPORT_SHORT_AUDIO_DESCRIPTOR;
1515	for (i = 0; i < num_descriptors; i++) {
1516		msg->msg[2 + i * 3] = (descriptors[i] >> 16) & 0xff;
1517		msg->msg[3 + i * 3] = (descriptors[i] >> 8) & 0xff;
1518		msg->msg[4 + i * 3] = descriptors[i] & 0xff;
1519	}
1520}
1521
1522static __inline__ void cec_ops_report_short_audio_descriptor(const struct cec_msg *msg,
1523							 __u8 *num_descriptors,
1524							 __u32 *descriptors)
1525{
1526	unsigned int i;
1527
1528	*num_descriptors = (msg->len - 2) / 3;
1529	if (*num_descriptors > 4)
1530		*num_descriptors = 4;
1531	for (i = 0; i < *num_descriptors; i++)
1532		descriptors[i] = (msg->msg[2 + i * 3] << 16) |
1533			(msg->msg[3 + i * 3] << 8) |
1534			msg->msg[4 + i * 3];
1535}
1536
1537static __inline__ void cec_msg_request_short_audio_descriptor(struct cec_msg *msg,
1538					int reply,
1539					__u8 num_descriptors,
1540					const __u8 *audio_format_id,
1541					const __u8 *audio_format_code)
1542{
1543	unsigned int i;
1544
1545	if (num_descriptors > 4)
1546		num_descriptors = 4;
1547	msg->len = 2 + num_descriptors;
1548	msg->msg[1] = CEC_MSG_REQUEST_SHORT_AUDIO_DESCRIPTOR;
1549	msg->reply = reply ? CEC_MSG_REPORT_SHORT_AUDIO_DESCRIPTOR : 0;
1550	for (i = 0; i < num_descriptors; i++)
1551		msg->msg[2 + i] = (audio_format_id[i] << 6) |
1552				  (audio_format_code[i] & 0x3f);
1553}
1554
1555static __inline__ void cec_ops_request_short_audio_descriptor(const struct cec_msg *msg,
1556					__u8 *num_descriptors,
1557					__u8 *audio_format_id,
1558					__u8 *audio_format_code)
1559{
1560	unsigned int i;
1561
1562	*num_descriptors = msg->len - 2;
1563	if (*num_descriptors > 4)
1564		*num_descriptors = 4;
1565	for (i = 0; i < *num_descriptors; i++) {
1566		audio_format_id[i] = msg->msg[2 + i] >> 6;
1567		audio_format_code[i] = msg->msg[2 + i] & 0x3f;
1568	}
1569}
1570
1571static __inline__ void cec_msg_set_audio_volume_level(struct cec_msg *msg,
1572						  __u8 audio_volume_level)
1573{
1574	msg->len = 3;
1575	msg->msg[1] = CEC_MSG_SET_AUDIO_VOLUME_LEVEL;
1576	msg->msg[2] = audio_volume_level;
1577}
1578
1579static __inline__ void cec_ops_set_audio_volume_level(const struct cec_msg *msg,
1580						  __u8 *audio_volume_level)
1581{
1582	*audio_volume_level = msg->msg[2];
1583}
1584
1585
1586/* Audio Rate Control Feature */
1587static __inline__ void cec_msg_set_audio_rate(struct cec_msg *msg,
1588					  __u8 audio_rate)
1589{
1590	msg->len = 3;
1591	msg->msg[1] = CEC_MSG_SET_AUDIO_RATE;
1592	msg->msg[2] = audio_rate;
1593}
1594
1595static __inline__ void cec_ops_set_audio_rate(const struct cec_msg *msg,
1596					  __u8 *audio_rate)
1597{
1598	*audio_rate = msg->msg[2];
1599}
1600
1601
1602/* Audio Return Channel Control Feature */
1603static __inline__ void cec_msg_report_arc_initiated(struct cec_msg *msg)
1604{
1605	msg->len = 2;
1606	msg->msg[1] = CEC_MSG_REPORT_ARC_INITIATED;
1607}
1608
1609static __inline__ void cec_msg_initiate_arc(struct cec_msg *msg,
1610					int reply)
1611{
1612	msg->len = 2;
1613	msg->msg[1] = CEC_MSG_INITIATE_ARC;
1614	msg->reply = reply ? CEC_MSG_REPORT_ARC_INITIATED : 0;
1615}
1616
1617static __inline__ void cec_msg_request_arc_initiation(struct cec_msg *msg,
1618						  int reply)
1619{
1620	msg->len = 2;
1621	msg->msg[1] = CEC_MSG_REQUEST_ARC_INITIATION;
1622	msg->reply = reply ? CEC_MSG_INITIATE_ARC : 0;
1623}
1624
1625static __inline__ void cec_msg_report_arc_terminated(struct cec_msg *msg)
1626{
1627	msg->len = 2;
1628	msg->msg[1] = CEC_MSG_REPORT_ARC_TERMINATED;
1629}
1630
1631static __inline__ void cec_msg_terminate_arc(struct cec_msg *msg,
1632					 int reply)
1633{
1634	msg->len = 2;
1635	msg->msg[1] = CEC_MSG_TERMINATE_ARC;
1636	msg->reply = reply ? CEC_MSG_REPORT_ARC_TERMINATED : 0;
1637}
1638
1639static __inline__ void cec_msg_request_arc_termination(struct cec_msg *msg,
1640						   int reply)
1641{
1642	msg->len = 2;
1643	msg->msg[1] = CEC_MSG_REQUEST_ARC_TERMINATION;
1644	msg->reply = reply ? CEC_MSG_TERMINATE_ARC : 0;
1645}
1646
1647
1648/* Dynamic Audio Lipsync Feature */
1649/* Only for CEC 2.0 and up */
1650static __inline__ void cec_msg_report_current_latency(struct cec_msg *msg,
1651						  __u16 phys_addr,
1652						  __u8 video_latency,
1653						  __u8 low_latency_mode,
1654						  __u8 audio_out_compensated,
1655						  __u8 audio_out_delay)
1656{
1657	msg->len = 6;
1658	msg->msg[0] |= CEC_LOG_ADDR_BROADCAST;
1659	msg->msg[1] = CEC_MSG_REPORT_CURRENT_LATENCY;
1660	msg->msg[2] = phys_addr >> 8;
1661	msg->msg[3] = phys_addr & 0xff;
1662	msg->msg[4] = video_latency;
1663	msg->msg[5] = (low_latency_mode << 2) | audio_out_compensated;
1664	if (audio_out_compensated == 3)
1665		msg->msg[msg->len++] = audio_out_delay;
1666}
1667
1668static __inline__ void cec_ops_report_current_latency(const struct cec_msg *msg,
1669						  __u16 *phys_addr,
1670						  __u8 *video_latency,
1671						  __u8 *low_latency_mode,
1672						  __u8 *audio_out_compensated,
1673						  __u8 *audio_out_delay)
1674{
1675	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1676	*video_latency = msg->msg[4];
1677	*low_latency_mode = (msg->msg[5] >> 2) & 1;
1678	*audio_out_compensated = msg->msg[5] & 3;
1679	if (*audio_out_compensated == 3 && msg->len >= 7)
1680		*audio_out_delay = msg->msg[6];
1681	else
1682		*audio_out_delay = 1;
1683}
1684
1685static __inline__ void cec_msg_request_current_latency(struct cec_msg *msg,
1686						   int reply,
1687						   __u16 phys_addr)
1688{
1689	msg->len = 4;
1690	msg->msg[0] |= CEC_LOG_ADDR_BROADCAST;
1691	msg->msg[1] = CEC_MSG_REQUEST_CURRENT_LATENCY;
1692	msg->msg[2] = phys_addr >> 8;
1693	msg->msg[3] = phys_addr & 0xff;
1694	msg->reply = reply ? CEC_MSG_REPORT_CURRENT_LATENCY : 0;
1695}
1696
1697static __inline__ void cec_ops_request_current_latency(const struct cec_msg *msg,
1698						   __u16 *phys_addr)
1699{
1700	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1701}
1702
1703
1704/* Capability Discovery and Control Feature */
1705static __inline__ void cec_msg_cdc_hec_inquire_state(struct cec_msg *msg,
1706						 __u16 phys_addr1,
1707						 __u16 phys_addr2)
1708{
1709	msg->len = 9;
1710	msg->msg[0] |= CEC_LOG_ADDR_BROADCAST;
1711	msg->msg[1] = CEC_MSG_CDC_MESSAGE;
1712	/* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1713	msg->msg[4] = CEC_MSG_CDC_HEC_INQUIRE_STATE;
1714	msg->msg[5] = phys_addr1 >> 8;
1715	msg->msg[6] = phys_addr1 & 0xff;
1716	msg->msg[7] = phys_addr2 >> 8;
1717	msg->msg[8] = phys_addr2 & 0xff;
1718}
1719
1720static __inline__ void cec_ops_cdc_hec_inquire_state(const struct cec_msg *msg,
1721						 __u16 *phys_addr,
1722						 __u16 *phys_addr1,
1723						 __u16 *phys_addr2)
1724{
1725	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1726	*phys_addr1 = (msg->msg[5] << 8) | msg->msg[6];
1727	*phys_addr2 = (msg->msg[7] << 8) | msg->msg[8];
1728}
1729
1730static __inline__ void cec_msg_cdc_hec_report_state(struct cec_msg *msg,
1731						__u16 target_phys_addr,
1732						__u8 hec_func_state,
1733						__u8 host_func_state,
1734						__u8 enc_func_state,
1735						__u8 cdc_errcode,
1736						__u8 has_field,
1737						__u16 hec_field)
1738{
1739	msg->len = has_field ? 10 : 8;
1740	msg->msg[0] |= CEC_LOG_ADDR_BROADCAST;
1741	msg->msg[1] = CEC_MSG_CDC_MESSAGE;
1742	/* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1743	msg->msg[4] = CEC_MSG_CDC_HEC_REPORT_STATE;
1744	msg->msg[5] = target_phys_addr >> 8;
1745	msg->msg[6] = target_phys_addr & 0xff;
1746	msg->msg[7] = (hec_func_state << 6) |
1747		      (host_func_state << 4) |
1748		      (enc_func_state << 2) |
1749		      cdc_errcode;
1750	if (has_field) {
1751		msg->msg[8] = hec_field >> 8;
1752		msg->msg[9] = hec_field & 0xff;
1753	}
1754}
1755
1756static __inline__ void cec_ops_cdc_hec_report_state(const struct cec_msg *msg,
1757						__u16 *phys_addr,
1758						__u16 *target_phys_addr,
1759						__u8 *hec_func_state,
1760						__u8 *host_func_state,
1761						__u8 *enc_func_state,
1762						__u8 *cdc_errcode,
1763						__u8 *has_field,
1764						__u16 *hec_field)
1765{
1766	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1767	*target_phys_addr = (msg->msg[5] << 8) | msg->msg[6];
1768	*hec_func_state = msg->msg[7] >> 6;
1769	*host_func_state = (msg->msg[7] >> 4) & 3;
1770	*enc_func_state = (msg->msg[7] >> 4) & 3;
1771	*cdc_errcode = msg->msg[7] & 3;
1772	*has_field = msg->len >= 10;
1773	*hec_field = *has_field ? ((msg->msg[8] << 8) | msg->msg[9]) : 0;
1774}
1775
1776static __inline__ void cec_msg_cdc_hec_set_state(struct cec_msg *msg,
1777					     __u16 phys_addr1,
1778					     __u16 phys_addr2,
1779					     __u8 hec_set_state,
1780					     __u16 phys_addr3,
1781					     __u16 phys_addr4,
1782					     __u16 phys_addr5)
1783{
1784	msg->len = 10;
1785	msg->msg[0] |= CEC_LOG_ADDR_BROADCAST;
1786	msg->msg[1] = CEC_MSG_CDC_MESSAGE;
1787	/* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1788	msg->msg[4] = CEC_MSG_CDC_HEC_INQUIRE_STATE;
1789	msg->msg[5] = phys_addr1 >> 8;
1790	msg->msg[6] = phys_addr1 & 0xff;
1791	msg->msg[7] = phys_addr2 >> 8;
1792	msg->msg[8] = phys_addr2 & 0xff;
1793	msg->msg[9] = hec_set_state;
1794	if (phys_addr3 != CEC_PHYS_ADDR_INVALID) {
1795		msg->msg[msg->len++] = phys_addr3 >> 8;
1796		msg->msg[msg->len++] = phys_addr3 & 0xff;
1797		if (phys_addr4 != CEC_PHYS_ADDR_INVALID) {
1798			msg->msg[msg->len++] = phys_addr4 >> 8;
1799			msg->msg[msg->len++] = phys_addr4 & 0xff;
1800			if (phys_addr5 != CEC_PHYS_ADDR_INVALID) {
1801				msg->msg[msg->len++] = phys_addr5 >> 8;
1802				msg->msg[msg->len++] = phys_addr5 & 0xff;
1803			}
1804		}
1805	}
1806}
1807
1808static __inline__ void cec_ops_cdc_hec_set_state(const struct cec_msg *msg,
1809					     __u16 *phys_addr,
1810					     __u16 *phys_addr1,
1811					     __u16 *phys_addr2,
1812					     __u8 *hec_set_state,
1813					     __u16 *phys_addr3,
1814					     __u16 *phys_addr4,
1815					     __u16 *phys_addr5)
1816{
1817	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1818	*phys_addr1 = (msg->msg[5] << 8) | msg->msg[6];
1819	*phys_addr2 = (msg->msg[7] << 8) | msg->msg[8];
1820	*hec_set_state = msg->msg[9];
1821	*phys_addr3 = *phys_addr4 = *phys_addr5 = CEC_PHYS_ADDR_INVALID;
1822	if (msg->len >= 12)
1823		*phys_addr3 = (msg->msg[10] << 8) | msg->msg[11];
1824	if (msg->len >= 14)
1825		*phys_addr4 = (msg->msg[12] << 8) | msg->msg[13];
1826	if (msg->len >= 16)
1827		*phys_addr5 = (msg->msg[14] << 8) | msg->msg[15];
1828}
1829
1830static __inline__ void cec_msg_cdc_hec_set_state_adjacent(struct cec_msg *msg,
1831						      __u16 phys_addr1,
1832						      __u8 hec_set_state)
1833{
1834	msg->len = 8;
1835	msg->msg[0] |= CEC_LOG_ADDR_BROADCAST;
1836	msg->msg[1] = CEC_MSG_CDC_MESSAGE;
1837	/* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1838	msg->msg[4] = CEC_MSG_CDC_HEC_SET_STATE_ADJACENT;
1839	msg->msg[5] = phys_addr1 >> 8;
1840	msg->msg[6] = phys_addr1 & 0xff;
1841	msg->msg[7] = hec_set_state;
1842}
1843
1844static __inline__ void cec_ops_cdc_hec_set_state_adjacent(const struct cec_msg *msg,
1845						      __u16 *phys_addr,
1846						      __u16 *phys_addr1,
1847						      __u8 *hec_set_state)
1848{
1849	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1850	*phys_addr1 = (msg->msg[5] << 8) | msg->msg[6];
1851	*hec_set_state = msg->msg[7];
1852}
1853
1854static __inline__ void cec_msg_cdc_hec_request_deactivation(struct cec_msg *msg,
1855							__u16 phys_addr1,
1856							__u16 phys_addr2,
1857							__u16 phys_addr3)
1858{
1859	msg->len = 11;
1860	msg->msg[0] |= CEC_LOG_ADDR_BROADCAST;
1861	msg->msg[1] = CEC_MSG_CDC_MESSAGE;
1862	/* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1863	msg->msg[4] = CEC_MSG_CDC_HEC_REQUEST_DEACTIVATION;
1864	msg->msg[5] = phys_addr1 >> 8;
1865	msg->msg[6] = phys_addr1 & 0xff;
1866	msg->msg[7] = phys_addr2 >> 8;
1867	msg->msg[8] = phys_addr2 & 0xff;
1868	msg->msg[9] = phys_addr3 >> 8;
1869	msg->msg[10] = phys_addr3 & 0xff;
1870}
1871
1872static __inline__ void cec_ops_cdc_hec_request_deactivation(const struct cec_msg *msg,
1873							__u16 *phys_addr,
1874							__u16 *phys_addr1,
1875							__u16 *phys_addr2,
1876							__u16 *phys_addr3)
1877{
1878	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1879	*phys_addr1 = (msg->msg[5] << 8) | msg->msg[6];
1880	*phys_addr2 = (msg->msg[7] << 8) | msg->msg[8];
1881	*phys_addr3 = (msg->msg[9] << 8) | msg->msg[10];
1882}
1883
1884static __inline__ void cec_msg_cdc_hec_notify_alive(struct cec_msg *msg)
1885{
1886	msg->len = 5;
1887	msg->msg[0] |= CEC_LOG_ADDR_BROADCAST;
1888	msg->msg[1] = CEC_MSG_CDC_MESSAGE;
1889	/* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1890	msg->msg[4] = CEC_MSG_CDC_HEC_NOTIFY_ALIVE;
1891}
1892
1893static __inline__ void cec_ops_cdc_hec_notify_alive(const struct cec_msg *msg,
1894						__u16 *phys_addr)
1895{
1896	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1897}
1898
1899static __inline__ void cec_msg_cdc_hec_discover(struct cec_msg *msg)
1900{
1901	msg->len = 5;
1902	msg->msg[0] |= CEC_LOG_ADDR_BROADCAST;
1903	msg->msg[1] = CEC_MSG_CDC_MESSAGE;
1904	/* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1905	msg->msg[4] = CEC_MSG_CDC_HEC_DISCOVER;
1906}
1907
1908static __inline__ void cec_ops_cdc_hec_discover(const struct cec_msg *msg,
1909					    __u16 *phys_addr)
1910{
1911	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1912}
1913
1914static __inline__ void cec_msg_cdc_hpd_set_state(struct cec_msg *msg,
1915					     __u8 input_port,
1916					     __u8 hpd_state)
1917{
1918	msg->len = 6;
1919	msg->msg[0] |= CEC_LOG_ADDR_BROADCAST;
1920	msg->msg[1] = CEC_MSG_CDC_MESSAGE;
1921	/* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1922	msg->msg[4] = CEC_MSG_CDC_HPD_SET_STATE;
1923	msg->msg[5] = (input_port << 4) | hpd_state;
1924}
1925
1926static __inline__ void cec_ops_cdc_hpd_set_state(const struct cec_msg *msg,
1927					    __u16 *phys_addr,
1928					    __u8 *input_port,
1929					    __u8 *hpd_state)
1930{
1931	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1932	*input_port = msg->msg[5] >> 4;
1933	*hpd_state = msg->msg[5] & 0xf;
1934}
1935
1936static __inline__ void cec_msg_cdc_hpd_report_state(struct cec_msg *msg,
1937						__u8 hpd_state,
1938						__u8 hpd_error)
1939{
1940	msg->len = 6;
1941	msg->msg[0] |= CEC_LOG_ADDR_BROADCAST;
1942	msg->msg[1] = CEC_MSG_CDC_MESSAGE;
1943	/* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1944	msg->msg[4] = CEC_MSG_CDC_HPD_REPORT_STATE;
1945	msg->msg[5] = (hpd_state << 4) | hpd_error;
1946}
1947
1948static __inline__ void cec_ops_cdc_hpd_report_state(const struct cec_msg *msg,
1949						__u16 *phys_addr,
1950						__u8 *hpd_state,
1951						__u8 *hpd_error)
1952{
1953	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1954	*hpd_state = msg->msg[5] >> 4;
1955	*hpd_error = msg->msg[5] & 0xf;
1956}
1957
1958#endif