aboutsummaryrefslogtreecommitdiffstats
path: root/include/uapi/linux/cec-funcs.h
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2016-11-02 06:25:28 -0400
committerMauro Carvalho Chehab <mchehab@s-opensource.com>2016-11-16 12:40:20 -0500
commit0dbacebede1e4e44bf500f94d692fad05eb2c293 (patch)
tree633cbfbfed04251cbdb35fe158ad81ee8ed380ef /include/uapi/linux/cec-funcs.h
parenta69a168a1bd470cb8a8c5f2ff4b54463de615226 (diff)
[media] cec: move the CEC framework out of staging and to media
The last open issues have been addressed, so it is time to move this out of staging and into the mainline and to move the public cec headers to include/uapi/linux. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Diffstat (limited to 'include/uapi/linux/cec-funcs.h')
-rw-r--r--include/uapi/linux/cec-funcs.h1965
1 files changed, 1965 insertions, 0 deletions
diff --git a/include/uapi/linux/cec-funcs.h b/include/uapi/linux/cec-funcs.h
new file mode 100644
index 000000000000..1a1de2169f48
--- /dev/null
+++ b/include/uapi/linux/cec-funcs.h
@@ -0,0 +1,1965 @@
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 */
42static 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
51static 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
57static 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
63static 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 */
71static 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
80static 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
86static inline void cec_msg_request_active_source(struct cec_msg *msg,
87 bool 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
95static 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
105static 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
111static inline void cec_msg_routing_change(struct cec_msg *msg,
112 bool 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
126static 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
134static 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
143static 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 */
151static 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 */
159static inline void cec_msg_record_off(struct cec_msg *msg, bool 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
166struct cec_op_arib_data {
167 __u16 transport_id;
168 __u16 service_id;
169 __u16 orig_network_id;
170};
171
172struct cec_op_atsc_data {
173 __u16 transport_id;
174 __u16 program_number;
175};
176
177struct cec_op_dvb_data {
178 __u16 transport_id;
179 __u16 service_id;
180 __u16 orig_network_id;
181};
182
183struct cec_op_channel_data {
184 __u8 channel_number_fmt;
185 __u16 major;
186 __u16 minor;
187};
188
189struct 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
200struct 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
218static 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
255static 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
271static 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
278static 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
287static 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
301static 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
310static 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
320static inline void cec_msg_record_on(struct cec_msg *msg,
321 bool 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
348static 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
374static 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
381static inline void cec_ops_record_status(const struct cec_msg *msg,
382 __u8 *rec_status)
383{
384 *rec_status = msg->msg[2];
385}
386
387static inline void cec_msg_record_tv_screen(struct cec_msg *msg,
388 bool 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 */
397static 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
420static 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
447static 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
455static 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
461static inline void cec_msg_clear_analogue_timer(struct cec_msg *msg,
462 bool 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
491static 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
516static inline void cec_msg_clear_digital_timer(struct cec_msg *msg,
517 bool 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
541static 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
562static inline void cec_msg_clear_ext_timer(struct cec_msg *msg,
563 bool 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
592static 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
617static inline void cec_msg_set_analogue_timer(struct cec_msg *msg,
618 bool 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
647static 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
672static inline void cec_msg_set_digital_timer(struct cec_msg *msg,
673 bool 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
697static 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
718static inline void cec_msg_set_ext_timer(struct cec_msg *msg,
719 bool 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
748static 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
773static 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
785static 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 */
797static 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
804static inline void cec_ops_cec_version(const struct cec_msg *msg,
805 __u8 *cec_version)
806{
807 *cec_version = msg->msg[2];
808}
809
810static inline void cec_msg_get_cec_version(struct cec_msg *msg,
811 bool 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
818static 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
829static 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
836static inline void cec_msg_give_physical_addr(struct cec_msg *msg,
837 bool 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
844static 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
853static 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
860static inline void cec_msg_get_menu_language(struct cec_msg *msg,
861 bool 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 */
876static 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
889static 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 while (p < &msg->msg[14] && (*p & CEC_OP_FEAT_EXT))
899 p++;
900 if (!(*p & CEC_OP_FEAT_EXT)) {
901 *dev_features = p + 1;
902 while (p < &msg->msg[15] && (*p & CEC_OP_FEAT_EXT))
903 p++;
904 }
905 if (*p & CEC_OP_FEAT_EXT)
906 *rc_profile = *dev_features = NULL;
907}
908
909static inline void cec_msg_give_features(struct cec_msg *msg,
910 bool reply)
911{
912 msg->len = 2;
913 msg->msg[1] = CEC_MSG_GIVE_FEATURES;
914 msg->reply = reply ? CEC_MSG_REPORT_FEATURES : 0;
915}
916
917/* Deck Control Feature */
918static inline void cec_msg_deck_control(struct cec_msg *msg,
919 __u8 deck_control_mode)
920{
921 msg->len = 3;
922 msg->msg[1] = CEC_MSG_DECK_CONTROL;
923 msg->msg[2] = deck_control_mode;
924}
925
926static inline void cec_ops_deck_control(const struct cec_msg *msg,
927 __u8 *deck_control_mode)
928{
929 *deck_control_mode = msg->msg[2];
930}
931
932static inline void cec_msg_deck_status(struct cec_msg *msg,
933 __u8 deck_info)
934{
935 msg->len = 3;
936 msg->msg[1] = CEC_MSG_DECK_STATUS;
937 msg->msg[2] = deck_info;
938}
939
940static inline void cec_ops_deck_status(const struct cec_msg *msg,
941 __u8 *deck_info)
942{
943 *deck_info = msg->msg[2];
944}
945
946static inline void cec_msg_give_deck_status(struct cec_msg *msg,
947 bool reply,
948 __u8 status_req)
949{
950 msg->len = 3;
951 msg->msg[1] = CEC_MSG_GIVE_DECK_STATUS;
952 msg->msg[2] = status_req;
953 msg->reply = reply ? CEC_MSG_DECK_STATUS : 0;
954}
955
956static inline void cec_ops_give_deck_status(const struct cec_msg *msg,
957 __u8 *status_req)
958{
959 *status_req = msg->msg[2];
960}
961
962static inline void cec_msg_play(struct cec_msg *msg,
963 __u8 play_mode)
964{
965 msg->len = 3;
966 msg->msg[1] = CEC_MSG_PLAY;
967 msg->msg[2] = play_mode;
968}
969
970static inline void cec_ops_play(const struct cec_msg *msg,
971 __u8 *play_mode)
972{
973 *play_mode = msg->msg[2];
974}
975
976
977/* Tuner Control Feature */
978struct cec_op_tuner_device_info {
979 __u8 rec_flag;
980 __u8 tuner_display_info;
981 bool is_analog;
982 union {
983 struct cec_op_digital_service_id digital;
984 struct {
985 __u8 ana_bcast_type;
986 __u16 ana_freq;
987 __u8 bcast_system;
988 } analog;
989 };
990};
991
992static inline void cec_msg_tuner_device_status_analog(struct cec_msg *msg,
993 __u8 rec_flag,
994 __u8 tuner_display_info,
995 __u8 ana_bcast_type,
996 __u16 ana_freq,
997 __u8 bcast_system)
998{
999 msg->len = 7;
1000 msg->msg[1] = CEC_MSG_TUNER_DEVICE_STATUS;
1001 msg->msg[2] = (rec_flag << 7) | tuner_display_info;
1002 msg->msg[3] = ana_bcast_type;
1003 msg->msg[4] = ana_freq >> 8;
1004 msg->msg[5] = ana_freq & 0xff;
1005 msg->msg[6] = bcast_system;
1006}
1007
1008static inline void cec_msg_tuner_device_status_digital(struct cec_msg *msg,
1009 __u8 rec_flag, __u8 tuner_display_info,
1010 const struct cec_op_digital_service_id *digital)
1011{
1012 msg->len = 10;
1013 msg->msg[1] = CEC_MSG_TUNER_DEVICE_STATUS;
1014 msg->msg[2] = (rec_flag << 7) | tuner_display_info;
1015 cec_set_digital_service_id(msg->msg + 3, digital);
1016}
1017
1018static inline void cec_msg_tuner_device_status(struct cec_msg *msg,
1019 const struct cec_op_tuner_device_info *tuner_dev_info)
1020{
1021 if (tuner_dev_info->is_analog)
1022 cec_msg_tuner_device_status_analog(msg,
1023 tuner_dev_info->rec_flag,
1024 tuner_dev_info->tuner_display_info,
1025 tuner_dev_info->analog.ana_bcast_type,
1026 tuner_dev_info->analog.ana_freq,
1027 tuner_dev_info->analog.bcast_system);
1028 else
1029 cec_msg_tuner_device_status_digital(msg,
1030 tuner_dev_info->rec_flag,
1031 tuner_dev_info->tuner_display_info,
1032 &tuner_dev_info->digital);
1033}
1034
1035static inline void cec_ops_tuner_device_status(const struct cec_msg *msg,
1036 struct cec_op_tuner_device_info *tuner_dev_info)
1037{
1038 tuner_dev_info->is_analog = msg->len < 10;
1039 tuner_dev_info->rec_flag = msg->msg[2] >> 7;
1040 tuner_dev_info->tuner_display_info = msg->msg[2] & 0x7f;
1041 if (tuner_dev_info->is_analog) {
1042 tuner_dev_info->analog.ana_bcast_type = msg->msg[3];
1043 tuner_dev_info->analog.ana_freq = (msg->msg[4] << 8) | msg->msg[5];
1044 tuner_dev_info->analog.bcast_system = msg->msg[6];
1045 return;
1046 }
1047 cec_get_digital_service_id(msg->msg + 3, &tuner_dev_info->digital);
1048}
1049
1050static inline void cec_msg_give_tuner_device_status(struct cec_msg *msg,
1051 bool reply,
1052 __u8 status_req)
1053{
1054 msg->len = 3;
1055 msg->msg[1] = CEC_MSG_GIVE_TUNER_DEVICE_STATUS;
1056 msg->msg[2] = status_req;
1057 msg->reply = reply ? CEC_MSG_TUNER_DEVICE_STATUS : 0;
1058}
1059
1060static inline void cec_ops_give_tuner_device_status(const struct cec_msg *msg,
1061 __u8 *status_req)
1062{
1063 *status_req = msg->msg[2];
1064}
1065
1066static inline void cec_msg_select_analogue_service(struct cec_msg *msg,
1067 __u8 ana_bcast_type,
1068 __u16 ana_freq,
1069 __u8 bcast_system)
1070{
1071 msg->len = 6;
1072 msg->msg[1] = CEC_MSG_SELECT_ANALOGUE_SERVICE;
1073 msg->msg[2] = ana_bcast_type;
1074 msg->msg[3] = ana_freq >> 8;
1075 msg->msg[4] = ana_freq & 0xff;
1076 msg->msg[5] = bcast_system;
1077}
1078
1079static inline void cec_ops_select_analogue_service(const struct cec_msg *msg,
1080 __u8 *ana_bcast_type,
1081 __u16 *ana_freq,
1082 __u8 *bcast_system)
1083{
1084 *ana_bcast_type = msg->msg[2];
1085 *ana_freq = (msg->msg[3] << 8) | msg->msg[4];
1086 *bcast_system = msg->msg[5];
1087}
1088
1089static inline void cec_msg_select_digital_service(struct cec_msg *msg,
1090 const struct cec_op_digital_service_id *digital)
1091{
1092 msg->len = 9;
1093 msg->msg[1] = CEC_MSG_SELECT_DIGITAL_SERVICE;
1094 cec_set_digital_service_id(msg->msg + 2, digital);
1095}
1096
1097static inline void cec_ops_select_digital_service(const struct cec_msg *msg,
1098 struct cec_op_digital_service_id *digital)
1099{
1100 cec_get_digital_service_id(msg->msg + 2, digital);
1101}
1102
1103static inline void cec_msg_tuner_step_decrement(struct cec_msg *msg)
1104{
1105 msg->len = 2;
1106 msg->msg[1] = CEC_MSG_TUNER_STEP_DECREMENT;
1107}
1108
1109static inline void cec_msg_tuner_step_increment(struct cec_msg *msg)
1110{
1111 msg->len = 2;
1112 msg->msg[1] = CEC_MSG_TUNER_STEP_INCREMENT;
1113}
1114
1115
1116/* Vendor Specific Commands Feature */
1117static inline void cec_msg_device_vendor_id(struct cec_msg *msg, __u32 vendor_id)
1118{
1119 msg->len = 5;
1120 msg->msg[0] |= 0xf; /* broadcast */
1121 msg->msg[1] = CEC_MSG_DEVICE_VENDOR_ID;
1122 msg->msg[2] = vendor_id >> 16;
1123 msg->msg[3] = (vendor_id >> 8) & 0xff;
1124 msg->msg[4] = vendor_id & 0xff;
1125}
1126
1127static inline void cec_ops_device_vendor_id(const struct cec_msg *msg,
1128 __u32 *vendor_id)
1129{
1130 *vendor_id = (msg->msg[2] << 16) | (msg->msg[3] << 8) | msg->msg[4];
1131}
1132
1133static inline void cec_msg_give_device_vendor_id(struct cec_msg *msg,
1134 bool reply)
1135{
1136 msg->len = 2;
1137 msg->msg[1] = CEC_MSG_GIVE_DEVICE_VENDOR_ID;
1138 msg->reply = reply ? CEC_MSG_DEVICE_VENDOR_ID : 0;
1139}
1140
1141static inline void cec_msg_vendor_command(struct cec_msg *msg,
1142 __u8 size, const __u8 *vendor_cmd)
1143{
1144 if (size > 14)
1145 size = 14;
1146 msg->len = 2 + size;
1147 msg->msg[1] = CEC_MSG_VENDOR_COMMAND;
1148 memcpy(msg->msg + 2, vendor_cmd, size);
1149}
1150
1151static inline void cec_ops_vendor_command(const struct cec_msg *msg,
1152 __u8 *size,
1153 const __u8 **vendor_cmd)
1154{
1155 *size = msg->len - 2;
1156
1157 if (*size > 14)
1158 *size = 14;
1159 *vendor_cmd = msg->msg + 2;
1160}
1161
1162static inline void cec_msg_vendor_command_with_id(struct cec_msg *msg,
1163 __u32 vendor_id, __u8 size,
1164 const __u8 *vendor_cmd)
1165{
1166 if (size > 11)
1167 size = 11;
1168 msg->len = 5 + size;
1169 msg->msg[1] = CEC_MSG_VENDOR_COMMAND_WITH_ID;
1170 msg->msg[2] = vendor_id >> 16;
1171 msg->msg[3] = (vendor_id >> 8) & 0xff;
1172 msg->msg[4] = vendor_id & 0xff;
1173 memcpy(msg->msg + 5, vendor_cmd, size);
1174}
1175
1176static inline void cec_ops_vendor_command_with_id(const struct cec_msg *msg,
1177 __u32 *vendor_id, __u8 *size,
1178 const __u8 **vendor_cmd)
1179{
1180 *size = msg->len - 5;
1181
1182 if (*size > 11)
1183 *size = 11;
1184 *vendor_id = (msg->msg[2] << 16) | (msg->msg[3] << 8) | msg->msg[4];
1185 *vendor_cmd = msg->msg + 5;
1186}
1187
1188static inline void cec_msg_vendor_remote_button_down(struct cec_msg *msg,
1189 __u8 size,
1190 const __u8 *rc_code)
1191{
1192 if (size > 14)
1193 size = 14;
1194 msg->len = 2 + size;
1195 msg->msg[1] = CEC_MSG_VENDOR_REMOTE_BUTTON_DOWN;
1196 memcpy(msg->msg + 2, rc_code, size);
1197}
1198
1199static inline void cec_ops_vendor_remote_button_down(const struct cec_msg *msg,
1200 __u8 *size,
1201 const __u8 **rc_code)
1202{
1203 *size = msg->len - 2;
1204
1205 if (*size > 14)
1206 *size = 14;
1207 *rc_code = msg->msg + 2;
1208}
1209
1210static inline void cec_msg_vendor_remote_button_up(struct cec_msg *msg)
1211{
1212 msg->len = 2;
1213 msg->msg[1] = CEC_MSG_VENDOR_REMOTE_BUTTON_UP;
1214}
1215
1216
1217/* OSD Display Feature */
1218static inline void cec_msg_set_osd_string(struct cec_msg *msg,
1219 __u8 disp_ctl,
1220 const char *osd)
1221{
1222 unsigned int len = strlen(osd);
1223
1224 if (len > 13)
1225 len = 13;
1226 msg->len = 3 + len;
1227 msg->msg[1] = CEC_MSG_SET_OSD_STRING;
1228 msg->msg[2] = disp_ctl;
1229 memcpy(msg->msg + 3, osd, len);
1230}
1231
1232static inline void cec_ops_set_osd_string(const struct cec_msg *msg,
1233 __u8 *disp_ctl,
1234 char *osd)
1235{
1236 unsigned int len = msg->len > 3 ? msg->len - 3 : 0;
1237
1238 *disp_ctl = msg->msg[2];
1239 if (len > 13)
1240 len = 13;
1241 memcpy(osd, msg->msg + 3, len);
1242 osd[len] = '\0';
1243}
1244
1245
1246/* Device OSD Transfer Feature */
1247static inline void cec_msg_set_osd_name(struct cec_msg *msg, const char *name)
1248{
1249 unsigned int len = strlen(name);
1250
1251 if (len > 14)
1252 len = 14;
1253 msg->len = 2 + len;
1254 msg->msg[1] = CEC_MSG_SET_OSD_NAME;
1255 memcpy(msg->msg + 2, name, len);
1256}
1257
1258static inline void cec_ops_set_osd_name(const struct cec_msg *msg,
1259 char *name)
1260{
1261 unsigned int len = msg->len > 2 ? msg->len - 2 : 0;
1262
1263 if (len > 14)
1264 len = 14;
1265 memcpy(name, msg->msg + 2, len);
1266 name[len] = '\0';
1267}
1268
1269static inline void cec_msg_give_osd_name(struct cec_msg *msg,
1270 bool reply)
1271{
1272 msg->len = 2;
1273 msg->msg[1] = CEC_MSG_GIVE_OSD_NAME;
1274 msg->reply = reply ? CEC_MSG_SET_OSD_NAME : 0;
1275}
1276
1277
1278/* Device Menu Control Feature */
1279static inline void cec_msg_menu_status(struct cec_msg *msg,
1280 __u8 menu_state)
1281{
1282 msg->len = 3;
1283 msg->msg[1] = CEC_MSG_MENU_STATUS;
1284 msg->msg[2] = menu_state;
1285}
1286
1287static inline void cec_ops_menu_status(const struct cec_msg *msg,
1288 __u8 *menu_state)
1289{
1290 *menu_state = msg->msg[2];
1291}
1292
1293static inline void cec_msg_menu_request(struct cec_msg *msg,
1294 bool reply,
1295 __u8 menu_req)
1296{
1297 msg->len = 3;
1298 msg->msg[1] = CEC_MSG_MENU_REQUEST;
1299 msg->msg[2] = menu_req;
1300 msg->reply = reply ? CEC_MSG_MENU_STATUS : 0;
1301}
1302
1303static inline void cec_ops_menu_request(const struct cec_msg *msg,
1304 __u8 *menu_req)
1305{
1306 *menu_req = msg->msg[2];
1307}
1308
1309struct cec_op_ui_command {
1310 __u8 ui_cmd;
1311 bool has_opt_arg;
1312 union {
1313 struct cec_op_channel_data channel_identifier;
1314 __u8 ui_broadcast_type;
1315 __u8 ui_sound_presentation_control;
1316 __u8 play_mode;
1317 __u8 ui_function_media;
1318 __u8 ui_function_select_av_input;
1319 __u8 ui_function_select_audio_input;
1320 };
1321};
1322
1323static inline void cec_msg_user_control_pressed(struct cec_msg *msg,
1324 const struct cec_op_ui_command *ui_cmd)
1325{
1326 msg->len = 3;
1327 msg->msg[1] = CEC_MSG_USER_CONTROL_PRESSED;
1328 msg->msg[2] = ui_cmd->ui_cmd;
1329 if (!ui_cmd->has_opt_arg)
1330 return;
1331 switch (ui_cmd->ui_cmd) {
1332 case 0x56:
1333 case 0x57:
1334 case 0x60:
1335 case 0x68:
1336 case 0x69:
1337 case 0x6a:
1338 /* The optional operand is one byte for all these ui commands */
1339 msg->len++;
1340 msg->msg[3] = ui_cmd->play_mode;
1341 break;
1342 case 0x67:
1343 msg->len += 4;
1344 msg->msg[3] = (ui_cmd->channel_identifier.channel_number_fmt << 2) |
1345 (ui_cmd->channel_identifier.major >> 8);
1346 msg->msg[4] = ui_cmd->channel_identifier.major & 0xff;
1347 msg->msg[5] = ui_cmd->channel_identifier.minor >> 8;
1348 msg->msg[6] = ui_cmd->channel_identifier.minor & 0xff;
1349 break;
1350 }
1351}
1352
1353static inline void cec_ops_user_control_pressed(const struct cec_msg *msg,
1354 struct cec_op_ui_command *ui_cmd)
1355{
1356 ui_cmd->ui_cmd = msg->msg[2];
1357 ui_cmd->has_opt_arg = false;
1358 if (msg->len == 3)
1359 return;
1360 switch (ui_cmd->ui_cmd) {
1361 case 0x56:
1362 case 0x57:
1363 case 0x60:
1364 case 0x68:
1365 case 0x69:
1366 case 0x6a:
1367 /* The optional operand is one byte for all these ui commands */
1368 ui_cmd->play_mode = msg->msg[3];
1369 ui_cmd->has_opt_arg = true;
1370 break;
1371 case 0x67:
1372 if (msg->len < 7)
1373 break;
1374 ui_cmd->has_opt_arg = true;
1375 ui_cmd->channel_identifier.channel_number_fmt = msg->msg[3] >> 2;
1376 ui_cmd->channel_identifier.major = ((msg->msg[3] & 3) << 6) | msg->msg[4];
1377 ui_cmd->channel_identifier.minor = (msg->msg[5] << 8) | msg->msg[6];
1378 break;
1379 }
1380}
1381
1382static inline void cec_msg_user_control_released(struct cec_msg *msg)
1383{
1384 msg->len = 2;
1385 msg->msg[1] = CEC_MSG_USER_CONTROL_RELEASED;
1386}
1387
1388/* Remote Control Passthrough Feature */
1389
1390/* Power Status Feature */
1391static inline void cec_msg_report_power_status(struct cec_msg *msg,
1392 __u8 pwr_state)
1393{
1394 msg->len = 3;
1395 msg->msg[1] = CEC_MSG_REPORT_POWER_STATUS;
1396 msg->msg[2] = pwr_state;
1397}
1398
1399static inline void cec_ops_report_power_status(const struct cec_msg *msg,
1400 __u8 *pwr_state)
1401{
1402 *pwr_state = msg->msg[2];
1403}
1404
1405static inline void cec_msg_give_device_power_status(struct cec_msg *msg,
1406 bool reply)
1407{
1408 msg->len = 2;
1409 msg->msg[1] = CEC_MSG_GIVE_DEVICE_POWER_STATUS;
1410 msg->reply = reply ? CEC_MSG_REPORT_POWER_STATUS : 0;
1411}
1412
1413/* General Protocol Messages */
1414static inline void cec_msg_feature_abort(struct cec_msg *msg,
1415 __u8 abort_msg, __u8 reason)
1416{
1417 msg->len = 4;
1418 msg->msg[1] = CEC_MSG_FEATURE_ABORT;
1419 msg->msg[2] = abort_msg;
1420 msg->msg[3] = reason;
1421}
1422
1423static inline void cec_ops_feature_abort(const struct cec_msg *msg,
1424 __u8 *abort_msg, __u8 *reason)
1425{
1426 *abort_msg = msg->msg[2];
1427 *reason = msg->msg[3];
1428}
1429
1430/* This changes the current message into a feature abort message */
1431static inline void cec_msg_reply_feature_abort(struct cec_msg *msg, __u8 reason)
1432{
1433 cec_msg_set_reply_to(msg, msg);
1434 msg->len = 4;
1435 msg->msg[2] = msg->msg[1];
1436 msg->msg[3] = reason;
1437 msg->msg[1] = CEC_MSG_FEATURE_ABORT;
1438}
1439
1440static inline void cec_msg_abort(struct cec_msg *msg)
1441{
1442 msg->len = 2;
1443 msg->msg[1] = CEC_MSG_ABORT;
1444}
1445
1446
1447/* System Audio Control Feature */
1448static inline void cec_msg_report_audio_status(struct cec_msg *msg,
1449 __u8 aud_mute_status,
1450 __u8 aud_vol_status)
1451{
1452 msg->len = 3;
1453 msg->msg[1] = CEC_MSG_REPORT_AUDIO_STATUS;
1454 msg->msg[2] = (aud_mute_status << 7) | (aud_vol_status & 0x7f);
1455}
1456
1457static inline void cec_ops_report_audio_status(const struct cec_msg *msg,
1458 __u8 *aud_mute_status,
1459 __u8 *aud_vol_status)
1460{
1461 *aud_mute_status = msg->msg[2] >> 7;
1462 *aud_vol_status = msg->msg[2] & 0x7f;
1463}
1464
1465static inline void cec_msg_give_audio_status(struct cec_msg *msg,
1466 bool reply)
1467{
1468 msg->len = 2;
1469 msg->msg[1] = CEC_MSG_GIVE_AUDIO_STATUS;
1470 msg->reply = reply ? CEC_MSG_REPORT_AUDIO_STATUS : 0;
1471}
1472
1473static inline void cec_msg_set_system_audio_mode(struct cec_msg *msg,
1474 __u8 sys_aud_status)
1475{
1476 msg->len = 3;
1477 msg->msg[1] = CEC_MSG_SET_SYSTEM_AUDIO_MODE;
1478 msg->msg[2] = sys_aud_status;
1479}
1480
1481static inline void cec_ops_set_system_audio_mode(const struct cec_msg *msg,
1482 __u8 *sys_aud_status)
1483{
1484 *sys_aud_status = msg->msg[2];
1485}
1486
1487static inline void cec_msg_system_audio_mode_request(struct cec_msg *msg,
1488 bool reply,
1489 __u16 phys_addr)
1490{
1491 msg->len = phys_addr == 0xffff ? 2 : 4;
1492 msg->msg[1] = CEC_MSG_SYSTEM_AUDIO_MODE_REQUEST;
1493 msg->msg[2] = phys_addr >> 8;
1494 msg->msg[3] = phys_addr & 0xff;
1495 msg->reply = reply ? CEC_MSG_SET_SYSTEM_AUDIO_MODE : 0;
1496
1497}
1498
1499static inline void cec_ops_system_audio_mode_request(const struct cec_msg *msg,
1500 __u16 *phys_addr)
1501{
1502 if (msg->len < 4)
1503 *phys_addr = 0xffff;
1504 else
1505 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1506}
1507
1508static inline void cec_msg_system_audio_mode_status(struct cec_msg *msg,
1509 __u8 sys_aud_status)
1510{
1511 msg->len = 3;
1512 msg->msg[1] = CEC_MSG_SYSTEM_AUDIO_MODE_STATUS;
1513 msg->msg[2] = sys_aud_status;
1514}
1515
1516static inline void cec_ops_system_audio_mode_status(const struct cec_msg *msg,
1517 __u8 *sys_aud_status)
1518{
1519 *sys_aud_status = msg->msg[2];
1520}
1521
1522static inline void cec_msg_give_system_audio_mode_status(struct cec_msg *msg,
1523 bool reply)
1524{
1525 msg->len = 2;
1526 msg->msg[1] = CEC_MSG_GIVE_SYSTEM_AUDIO_MODE_STATUS;
1527 msg->reply = reply ? CEC_MSG_SYSTEM_AUDIO_MODE_STATUS : 0;
1528}
1529
1530static inline void cec_msg_report_short_audio_descriptor(struct cec_msg *msg,
1531 __u8 num_descriptors,
1532 const __u32 *descriptors)
1533{
1534 unsigned int i;
1535
1536 if (num_descriptors > 4)
1537 num_descriptors = 4;
1538 msg->len = 2 + num_descriptors * 3;
1539 msg->msg[1] = CEC_MSG_REPORT_SHORT_AUDIO_DESCRIPTOR;
1540 for (i = 0; i < num_descriptors; i++) {
1541 msg->msg[2 + i * 3] = (descriptors[i] >> 16) & 0xff;
1542 msg->msg[3 + i * 3] = (descriptors[i] >> 8) & 0xff;
1543 msg->msg[4 + i * 3] = descriptors[i] & 0xff;
1544 }
1545}
1546
1547static inline void cec_ops_report_short_audio_descriptor(const struct cec_msg *msg,
1548 __u8 *num_descriptors,
1549 __u32 *descriptors)
1550{
1551 unsigned int i;
1552
1553 *num_descriptors = (msg->len - 2) / 3;
1554 if (*num_descriptors > 4)
1555 *num_descriptors = 4;
1556 for (i = 0; i < *num_descriptors; i++)
1557 descriptors[i] = (msg->msg[2 + i * 3] << 16) |
1558 (msg->msg[3 + i * 3] << 8) |
1559 msg->msg[4 + i * 3];
1560}
1561
1562static inline void cec_msg_request_short_audio_descriptor(struct cec_msg *msg,
1563 bool reply,
1564 __u8 num_descriptors,
1565 const __u8 *audio_format_id,
1566 const __u8 *audio_format_code)
1567{
1568 unsigned int i;
1569
1570 if (num_descriptors > 4)
1571 num_descriptors = 4;
1572 msg->len = 2 + num_descriptors;
1573 msg->msg[1] = CEC_MSG_REQUEST_SHORT_AUDIO_DESCRIPTOR;
1574 msg->reply = reply ? CEC_MSG_REPORT_SHORT_AUDIO_DESCRIPTOR : 0;
1575 for (i = 0; i < num_descriptors; i++)
1576 msg->msg[2 + i] = (audio_format_id[i] << 6) |
1577 (audio_format_code[i] & 0x3f);
1578}
1579
1580static inline void cec_ops_request_short_audio_descriptor(const struct cec_msg *msg,
1581 __u8 *num_descriptors,
1582 __u8 *audio_format_id,
1583 __u8 *audio_format_code)
1584{
1585 unsigned int i;
1586
1587 *num_descriptors = msg->len - 2;
1588 if (*num_descriptors > 4)
1589 *num_descriptors = 4;
1590 for (i = 0; i < *num_descriptors; i++) {
1591 audio_format_id[i] = msg->msg[2 + i] >> 6;
1592 audio_format_code[i] = msg->msg[2 + i] & 0x3f;
1593 }
1594}
1595
1596
1597/* Audio Rate Control Feature */
1598static inline void cec_msg_set_audio_rate(struct cec_msg *msg,
1599 __u8 audio_rate)
1600{
1601 msg->len = 3;
1602 msg->msg[1] = CEC_MSG_SET_AUDIO_RATE;
1603 msg->msg[2] = audio_rate;
1604}
1605
1606static inline void cec_ops_set_audio_rate(const struct cec_msg *msg,
1607 __u8 *audio_rate)
1608{
1609 *audio_rate = msg->msg[2];
1610}
1611
1612
1613/* Audio Return Channel Control Feature */
1614static inline void cec_msg_report_arc_initiated(struct cec_msg *msg)
1615{
1616 msg->len = 2;
1617 msg->msg[1] = CEC_MSG_REPORT_ARC_INITIATED;
1618}
1619
1620static inline void cec_msg_initiate_arc(struct cec_msg *msg,
1621 bool reply)
1622{
1623 msg->len = 2;
1624 msg->msg[1] = CEC_MSG_INITIATE_ARC;
1625 msg->reply = reply ? CEC_MSG_REPORT_ARC_INITIATED : 0;
1626}
1627
1628static inline void cec_msg_request_arc_initiation(struct cec_msg *msg,
1629 bool reply)
1630{
1631 msg->len = 2;
1632 msg->msg[1] = CEC_MSG_REQUEST_ARC_INITIATION;
1633 msg->reply = reply ? CEC_MSG_INITIATE_ARC : 0;
1634}
1635
1636static inline void cec_msg_report_arc_terminated(struct cec_msg *msg)
1637{
1638 msg->len = 2;
1639 msg->msg[1] = CEC_MSG_REPORT_ARC_TERMINATED;
1640}
1641
1642static inline void cec_msg_terminate_arc(struct cec_msg *msg,
1643 bool reply)
1644{
1645 msg->len = 2;
1646 msg->msg[1] = CEC_MSG_TERMINATE_ARC;
1647 msg->reply = reply ? CEC_MSG_REPORT_ARC_TERMINATED : 0;
1648}
1649
1650static inline void cec_msg_request_arc_termination(struct cec_msg *msg,
1651 bool reply)
1652{
1653 msg->len = 2;
1654 msg->msg[1] = CEC_MSG_REQUEST_ARC_TERMINATION;
1655 msg->reply = reply ? CEC_MSG_TERMINATE_ARC : 0;
1656}
1657
1658
1659/* Dynamic Audio Lipsync Feature */
1660/* Only for CEC 2.0 and up */
1661static inline void cec_msg_report_current_latency(struct cec_msg *msg,
1662 __u16 phys_addr,
1663 __u8 video_latency,
1664 __u8 low_latency_mode,
1665 __u8 audio_out_compensated,
1666 __u8 audio_out_delay)
1667{
1668 msg->len = 7;
1669 msg->msg[0] |= 0xf; /* broadcast */
1670 msg->msg[1] = CEC_MSG_REPORT_CURRENT_LATENCY;
1671 msg->msg[2] = phys_addr >> 8;
1672 msg->msg[3] = phys_addr & 0xff;
1673 msg->msg[4] = video_latency;
1674 msg->msg[5] = (low_latency_mode << 2) | audio_out_compensated;
1675 msg->msg[6] = audio_out_delay;
1676}
1677
1678static inline void cec_ops_report_current_latency(const struct cec_msg *msg,
1679 __u16 *phys_addr,
1680 __u8 *video_latency,
1681 __u8 *low_latency_mode,
1682 __u8 *audio_out_compensated,
1683 __u8 *audio_out_delay)
1684{
1685 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1686 *video_latency = msg->msg[4];
1687 *low_latency_mode = (msg->msg[5] >> 2) & 1;
1688 *audio_out_compensated = msg->msg[5] & 3;
1689 *audio_out_delay = msg->msg[6];
1690}
1691
1692static inline void cec_msg_request_current_latency(struct cec_msg *msg,
1693 bool reply,
1694 __u16 phys_addr)
1695{
1696 msg->len = 4;
1697 msg->msg[0] |= 0xf; /* broadcast */
1698 msg->msg[1] = CEC_MSG_REQUEST_CURRENT_LATENCY;
1699 msg->msg[2] = phys_addr >> 8;
1700 msg->msg[3] = phys_addr & 0xff;
1701 msg->reply = reply ? CEC_MSG_REPORT_CURRENT_LATENCY : 0;
1702}
1703
1704static inline void cec_ops_request_current_latency(const struct cec_msg *msg,
1705 __u16 *phys_addr)
1706{
1707 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1708}
1709
1710
1711/* Capability Discovery and Control Feature */
1712static inline void cec_msg_cdc_hec_inquire_state(struct cec_msg *msg,
1713 __u16 phys_addr1,
1714 __u16 phys_addr2)
1715{
1716 msg->len = 9;
1717 msg->msg[0] |= 0xf; /* broadcast */
1718 msg->msg[1] = CEC_MSG_CDC_MESSAGE;
1719 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1720 msg->msg[4] = CEC_MSG_CDC_HEC_INQUIRE_STATE;
1721 msg->msg[5] = phys_addr1 >> 8;
1722 msg->msg[6] = phys_addr1 & 0xff;
1723 msg->msg[7] = phys_addr2 >> 8;
1724 msg->msg[8] = phys_addr2 & 0xff;
1725}
1726
1727static inline void cec_ops_cdc_hec_inquire_state(const struct cec_msg *msg,
1728 __u16 *phys_addr,
1729 __u16 *phys_addr1,
1730 __u16 *phys_addr2)
1731{
1732 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1733 *phys_addr1 = (msg->msg[5] << 8) | msg->msg[6];
1734 *phys_addr2 = (msg->msg[7] << 8) | msg->msg[8];
1735}
1736
1737static inline void cec_msg_cdc_hec_report_state(struct cec_msg *msg,
1738 __u16 target_phys_addr,
1739 __u8 hec_func_state,
1740 __u8 host_func_state,
1741 __u8 enc_func_state,
1742 __u8 cdc_errcode,
1743 __u8 has_field,
1744 __u16 hec_field)
1745{
1746 msg->len = has_field ? 10 : 8;
1747 msg->msg[0] |= 0xf; /* broadcast */
1748 msg->msg[1] = CEC_MSG_CDC_MESSAGE;
1749 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1750 msg->msg[4] = CEC_MSG_CDC_HEC_REPORT_STATE;
1751 msg->msg[5] = target_phys_addr >> 8;
1752 msg->msg[6] = target_phys_addr & 0xff;
1753 msg->msg[7] = (hec_func_state << 6) |
1754 (host_func_state << 4) |
1755 (enc_func_state << 2) |
1756 cdc_errcode;
1757 if (has_field) {
1758 msg->msg[8] = hec_field >> 8;
1759 msg->msg[9] = hec_field & 0xff;
1760 }
1761}
1762
1763static inline void cec_ops_cdc_hec_report_state(const struct cec_msg *msg,
1764 __u16 *phys_addr,
1765 __u16 *target_phys_addr,
1766 __u8 *hec_func_state,
1767 __u8 *host_func_state,
1768 __u8 *enc_func_state,
1769 __u8 *cdc_errcode,
1770 __u8 *has_field,
1771 __u16 *hec_field)
1772{
1773 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1774 *target_phys_addr = (msg->msg[5] << 8) | msg->msg[6];
1775 *hec_func_state = msg->msg[7] >> 6;
1776 *host_func_state = (msg->msg[7] >> 4) & 3;
1777 *enc_func_state = (msg->msg[7] >> 4) & 3;
1778 *cdc_errcode = msg->msg[7] & 3;
1779 *has_field = msg->len >= 10;
1780 *hec_field = *has_field ? ((msg->msg[8] << 8) | msg->msg[9]) : 0;
1781}
1782
1783static inline void cec_msg_cdc_hec_set_state(struct cec_msg *msg,
1784 __u16 phys_addr1,
1785 __u16 phys_addr2,
1786 __u8 hec_set_state,
1787 __u16 phys_addr3,
1788 __u16 phys_addr4,
1789 __u16 phys_addr5)
1790{
1791 msg->len = 10;
1792 msg->msg[0] |= 0xf; /* broadcast */
1793 msg->msg[1] = CEC_MSG_CDC_MESSAGE;
1794 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1795 msg->msg[4] = CEC_MSG_CDC_HEC_INQUIRE_STATE;
1796 msg->msg[5] = phys_addr1 >> 8;
1797 msg->msg[6] = phys_addr1 & 0xff;
1798 msg->msg[7] = phys_addr2 >> 8;
1799 msg->msg[8] = phys_addr2 & 0xff;
1800 msg->msg[9] = hec_set_state;
1801 if (phys_addr3 != CEC_PHYS_ADDR_INVALID) {
1802 msg->msg[msg->len++] = phys_addr3 >> 8;
1803 msg->msg[msg->len++] = phys_addr3 & 0xff;
1804 if (phys_addr4 != CEC_PHYS_ADDR_INVALID) {
1805 msg->msg[msg->len++] = phys_addr4 >> 8;
1806 msg->msg[msg->len++] = phys_addr4 & 0xff;
1807 if (phys_addr5 != CEC_PHYS_ADDR_INVALID) {
1808 msg->msg[msg->len++] = phys_addr5 >> 8;
1809 msg->msg[msg->len++] = phys_addr5 & 0xff;
1810 }
1811 }
1812 }
1813}
1814
1815static inline void cec_ops_cdc_hec_set_state(const struct cec_msg *msg,
1816 __u16 *phys_addr,
1817 __u16 *phys_addr1,
1818 __u16 *phys_addr2,
1819 __u8 *hec_set_state,
1820 __u16 *phys_addr3,
1821 __u16 *phys_addr4,
1822 __u16 *phys_addr5)
1823{
1824 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1825 *phys_addr1 = (msg->msg[5] << 8) | msg->msg[6];
1826 *phys_addr2 = (msg->msg[7] << 8) | msg->msg[8];
1827 *hec_set_state = msg->msg[9];
1828 *phys_addr3 = *phys_addr4 = *phys_addr5 = CEC_PHYS_ADDR_INVALID;
1829 if (msg->len >= 12)
1830 *phys_addr3 = (msg->msg[10] << 8) | msg->msg[11];
1831 if (msg->len >= 14)
1832 *phys_addr4 = (msg->msg[12] << 8) | msg->msg[13];
1833 if (msg->len >= 16)
1834 *phys_addr5 = (msg->msg[14] << 8) | msg->msg[15];
1835}
1836
1837static inline void cec_msg_cdc_hec_set_state_adjacent(struct cec_msg *msg,
1838 __u16 phys_addr1,
1839 __u8 hec_set_state)
1840{
1841 msg->len = 8;
1842 msg->msg[0] |= 0xf; /* broadcast */
1843 msg->msg[1] = CEC_MSG_CDC_MESSAGE;
1844 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1845 msg->msg[4] = CEC_MSG_CDC_HEC_SET_STATE_ADJACENT;
1846 msg->msg[5] = phys_addr1 >> 8;
1847 msg->msg[6] = phys_addr1 & 0xff;
1848 msg->msg[7] = hec_set_state;
1849}
1850
1851static inline void cec_ops_cdc_hec_set_state_adjacent(const struct cec_msg *msg,
1852 __u16 *phys_addr,
1853 __u16 *phys_addr1,
1854 __u8 *hec_set_state)
1855{
1856 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1857 *phys_addr1 = (msg->msg[5] << 8) | msg->msg[6];
1858 *hec_set_state = msg->msg[7];
1859}
1860
1861static inline void cec_msg_cdc_hec_request_deactivation(struct cec_msg *msg,
1862 __u16 phys_addr1,
1863 __u16 phys_addr2,
1864 __u16 phys_addr3)
1865{
1866 msg->len = 11;
1867 msg->msg[0] |= 0xf; /* broadcast */
1868 msg->msg[1] = CEC_MSG_CDC_MESSAGE;
1869 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1870 msg->msg[4] = CEC_MSG_CDC_HEC_REQUEST_DEACTIVATION;
1871 msg->msg[5] = phys_addr1 >> 8;
1872 msg->msg[6] = phys_addr1 & 0xff;
1873 msg->msg[7] = phys_addr2 >> 8;
1874 msg->msg[8] = phys_addr2 & 0xff;
1875 msg->msg[9] = phys_addr3 >> 8;
1876 msg->msg[10] = phys_addr3 & 0xff;
1877}
1878
1879static inline void cec_ops_cdc_hec_request_deactivation(const struct cec_msg *msg,
1880 __u16 *phys_addr,
1881 __u16 *phys_addr1,
1882 __u16 *phys_addr2,
1883 __u16 *phys_addr3)
1884{
1885 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1886 *phys_addr1 = (msg->msg[5] << 8) | msg->msg[6];
1887 *phys_addr2 = (msg->msg[7] << 8) | msg->msg[8];
1888 *phys_addr3 = (msg->msg[9] << 8) | msg->msg[10];
1889}
1890
1891static inline void cec_msg_cdc_hec_notify_alive(struct cec_msg *msg)
1892{
1893 msg->len = 5;
1894 msg->msg[0] |= 0xf; /* broadcast */
1895 msg->msg[1] = CEC_MSG_CDC_MESSAGE;
1896 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1897 msg->msg[4] = CEC_MSG_CDC_HEC_NOTIFY_ALIVE;
1898}
1899
1900static inline void cec_ops_cdc_hec_notify_alive(const struct cec_msg *msg,
1901 __u16 *phys_addr)
1902{
1903 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1904}
1905
1906static inline void cec_msg_cdc_hec_discover(struct cec_msg *msg)
1907{
1908 msg->len = 5;
1909 msg->msg[0] |= 0xf; /* broadcast */
1910 msg->msg[1] = CEC_MSG_CDC_MESSAGE;
1911 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1912 msg->msg[4] = CEC_MSG_CDC_HEC_DISCOVER;
1913}
1914
1915static inline void cec_ops_cdc_hec_discover(const struct cec_msg *msg,
1916 __u16 *phys_addr)
1917{
1918 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1919}
1920
1921static inline void cec_msg_cdc_hpd_set_state(struct cec_msg *msg,
1922 __u8 input_port,
1923 __u8 hpd_state)
1924{
1925 msg->len = 6;
1926 msg->msg[0] |= 0xf; /* broadcast */
1927 msg->msg[1] = CEC_MSG_CDC_MESSAGE;
1928 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1929 msg->msg[4] = CEC_MSG_CDC_HPD_SET_STATE;
1930 msg->msg[5] = (input_port << 4) | hpd_state;
1931}
1932
1933static inline void cec_ops_cdc_hpd_set_state(const struct cec_msg *msg,
1934 __u16 *phys_addr,
1935 __u8 *input_port,
1936 __u8 *hpd_state)
1937{
1938 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1939 *input_port = msg->msg[5] >> 4;
1940 *hpd_state = msg->msg[5] & 0xf;
1941}
1942
1943static inline void cec_msg_cdc_hpd_report_state(struct cec_msg *msg,
1944 __u8 hpd_state,
1945 __u8 hpd_error)
1946{
1947 msg->len = 6;
1948 msg->msg[0] |= 0xf; /* broadcast */
1949 msg->msg[1] = CEC_MSG_CDC_MESSAGE;
1950 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1951 msg->msg[4] = CEC_MSG_CDC_HPD_REPORT_STATE;
1952 msg->msg[5] = (hpd_state << 4) | hpd_error;
1953}
1954
1955static inline void cec_ops_cdc_hpd_report_state(const struct cec_msg *msg,
1956 __u16 *phys_addr,
1957 __u8 *hpd_state,
1958 __u8 *hpd_error)
1959{
1960 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1961 *hpd_state = msg->msg[5] >> 4;
1962 *hpd_error = msg->msg[5] & 0xf;
1963}
1964
1965#endif