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