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