1 /* 2 * cec - HDMI Consumer Electronics Control message functions 3 * 4 * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved. 5 * 6 * This program is free software; you may redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; version 2 of the License. 9 * 10 * Alternatively you can redistribute this file under the terms of the 11 * BSD license as stated below: 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in 20 * the documentation and/or other materials provided with the 21 * distribution. 22 * 3. The names of its contributors may not be used to endorse or promote 23 * products derived from this software without specific prior written 24 * permission. 25 * 26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 27 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 28 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 29 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 30 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 31 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 32 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 33 * SOFTWARE. 34 */ 35 36 #ifndef _CEC_UAPI_FUNCS_H 37 #define _CEC_UAPI_FUNCS_H 38 39 #include <linux/cec.h> 40 41 /* One Touch Play Feature */ 42 static inline void cec_msg_active_source(struct cec_msg *msg, __u16 phys_addr) 43 { 44 msg->len = 4; 45 msg->msg[0] |= 0xf; /* broadcast */ 46 msg->msg[1] = CEC_MSG_ACTIVE_SOURCE; 47 msg->msg[2] = phys_addr >> 8; 48 msg->msg[3] = phys_addr & 0xff; 49 } 50 51 static inline void cec_ops_active_source(const struct cec_msg *msg, 52 __u16 *phys_addr) 53 { 54 *phys_addr = (msg->msg[2] << 8) | msg->msg[3]; 55 } 56 57 static inline void cec_msg_image_view_on(struct cec_msg *msg) 58 { 59 msg->len = 2; 60 msg->msg[1] = CEC_MSG_IMAGE_VIEW_ON; 61 } 62 63 static inline void cec_msg_text_view_on(struct cec_msg *msg) 64 { 65 msg->len = 2; 66 msg->msg[1] = CEC_MSG_TEXT_VIEW_ON; 67 } 68 69 70 /* Routing Control Feature */ 71 static inline void cec_msg_inactive_source(struct cec_msg *msg, 72 __u16 phys_addr) 73 { 74 msg->len = 4; 75 msg->msg[1] = CEC_MSG_INACTIVE_SOURCE; 76 msg->msg[2] = phys_addr >> 8; 77 msg->msg[3] = phys_addr & 0xff; 78 } 79 80 static inline void cec_ops_inactive_source(const struct cec_msg *msg, 81 __u16 *phys_addr) 82 { 83 *phys_addr = (msg->msg[2] << 8) | msg->msg[3]; 84 } 85 86 static inline void cec_msg_request_active_source(struct cec_msg *msg, 87 int reply) 88 { 89 msg->len = 2; 90 msg->msg[0] |= 0xf; /* broadcast */ 91 msg->msg[1] = CEC_MSG_REQUEST_ACTIVE_SOURCE; 92 msg->reply = reply ? CEC_MSG_ACTIVE_SOURCE : 0; 93 } 94 95 static inline void cec_msg_routing_information(struct cec_msg *msg, 96 __u16 phys_addr) 97 { 98 msg->len = 4; 99 msg->msg[0] |= 0xf; /* broadcast */ 100 msg->msg[1] = CEC_MSG_ROUTING_INFORMATION; 101 msg->msg[2] = phys_addr >> 8; 102 msg->msg[3] = phys_addr & 0xff; 103 } 104 105 static inline void cec_ops_routing_information(const struct cec_msg *msg, 106 __u16 *phys_addr) 107 { 108 *phys_addr = (msg->msg[2] << 8) | msg->msg[3]; 109 } 110 111 static inline void cec_msg_routing_change(struct cec_msg *msg, 112 int reply, 113 __u16 orig_phys_addr, 114 __u16 new_phys_addr) 115 { 116 msg->len = 6; 117 msg->msg[0] |= 0xf; /* broadcast */ 118 msg->msg[1] = CEC_MSG_ROUTING_CHANGE; 119 msg->msg[2] = orig_phys_addr >> 8; 120 msg->msg[3] = orig_phys_addr & 0xff; 121 msg->msg[4] = new_phys_addr >> 8; 122 msg->msg[5] = new_phys_addr & 0xff; 123 msg->reply = reply ? CEC_MSG_ROUTING_INFORMATION : 0; 124 } 125 126 static inline void cec_ops_routing_change(const struct cec_msg *msg, 127 __u16 *orig_phys_addr, 128 __u16 *new_phys_addr) 129 { 130 *orig_phys_addr = (msg->msg[2] << 8) | msg->msg[3]; 131 *new_phys_addr = (msg->msg[4] << 8) | msg->msg[5]; 132 } 133 134 static inline void cec_msg_set_stream_path(struct cec_msg *msg, __u16 phys_addr) 135 { 136 msg->len = 4; 137 msg->msg[0] |= 0xf; /* broadcast */ 138 msg->msg[1] = CEC_MSG_SET_STREAM_PATH; 139 msg->msg[2] = phys_addr >> 8; 140 msg->msg[3] = phys_addr & 0xff; 141 } 142 143 static inline void cec_ops_set_stream_path(const struct cec_msg *msg, 144 __u16 *phys_addr) 145 { 146 *phys_addr = (msg->msg[2] << 8) | msg->msg[3]; 147 } 148 149 150 /* Standby Feature */ 151 static inline void cec_msg_standby(struct cec_msg *msg) 152 { 153 msg->len = 2; 154 msg->msg[1] = CEC_MSG_STANDBY; 155 } 156 157 158 /* One Touch Record Feature */ 159 static inline void cec_msg_record_off(struct cec_msg *msg, int reply) 160 { 161 msg->len = 2; 162 msg->msg[1] = CEC_MSG_RECORD_OFF; 163 msg->reply = reply ? CEC_MSG_RECORD_STATUS : 0; 164 } 165 166 struct cec_op_arib_data { 167 __u16 transport_id; 168 __u16 service_id; 169 __u16 orig_network_id; 170 }; 171 172 struct cec_op_atsc_data { 173 __u16 transport_id; 174 __u16 program_number; 175 }; 176 177 struct cec_op_dvb_data { 178 __u16 transport_id; 179 __u16 service_id; 180 __u16 orig_network_id; 181 }; 182 183 struct cec_op_channel_data { 184 __u8 channel_number_fmt; 185 __u16 major; 186 __u16 minor; 187 }; 188 189 struct cec_op_digital_service_id { 190 __u8 service_id_method; 191 __u8 dig_bcast_system; 192 union { 193 struct cec_op_arib_data arib; 194 struct cec_op_atsc_data atsc; 195 struct cec_op_dvb_data dvb; 196 struct cec_op_channel_data channel; 197 }; 198 }; 199 200 struct cec_op_record_src { 201 __u8 type; 202 union { 203 struct cec_op_digital_service_id digital; 204 struct { 205 __u8 ana_bcast_type; 206 __u16 ana_freq; 207 __u8 bcast_system; 208 } analog; 209 struct { 210 __u8 plug; 211 } ext_plug; 212 struct { 213 __u16 phys_addr; 214 } ext_phys_addr; 215 }; 216 }; 217 218 static inline void cec_set_digital_service_id(__u8 *msg, 219 const struct cec_op_digital_service_id *digital) 220 { 221 *msg++ = (digital->service_id_method << 7) | digital->dig_bcast_system; 222 if (digital->service_id_method == CEC_OP_SERVICE_ID_METHOD_BY_CHANNEL) { 223 *msg++ = (digital->channel.channel_number_fmt << 2) | 224 (digital->channel.major >> 8); 225 *msg++ = digital->channel.major & 0xff; 226 *msg++ = digital->channel.minor >> 8; 227 *msg++ = digital->channel.minor & 0xff; 228 *msg++ = 0; 229 *msg++ = 0; 230 return; 231 } 232 switch (digital->dig_bcast_system) { 233 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_GEN: 234 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_CABLE: 235 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_SAT: 236 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_T: 237 *msg++ = digital->atsc.transport_id >> 8; 238 *msg++ = digital->atsc.transport_id & 0xff; 239 *msg++ = digital->atsc.program_number >> 8; 240 *msg++ = digital->atsc.program_number & 0xff; 241 *msg++ = 0; 242 *msg++ = 0; 243 break; 244 default: 245 *msg++ = digital->dvb.transport_id >> 8; 246 *msg++ = digital->dvb.transport_id & 0xff; 247 *msg++ = digital->dvb.service_id >> 8; 248 *msg++ = digital->dvb.service_id & 0xff; 249 *msg++ = digital->dvb.orig_network_id >> 8; 250 *msg++ = digital->dvb.orig_network_id & 0xff; 251 break; 252 } 253 } 254 255 static inline void cec_get_digital_service_id(const __u8 *msg, 256 struct cec_op_digital_service_id *digital) 257 { 258 digital->service_id_method = msg[0] >> 7; 259 digital->dig_bcast_system = msg[0] & 0x7f; 260 if (digital->service_id_method == CEC_OP_SERVICE_ID_METHOD_BY_CHANNEL) { 261 digital->channel.channel_number_fmt = msg[1] >> 2; 262 digital->channel.major = ((msg[1] & 3) << 6) | msg[2]; 263 digital->channel.minor = (msg[3] << 8) | msg[4]; 264 return; 265 } 266 digital->dvb.transport_id = (msg[1] << 8) | msg[2]; 267 digital->dvb.service_id = (msg[3] << 8) | msg[4]; 268 digital->dvb.orig_network_id = (msg[5] << 8) | msg[6]; 269 } 270 271 static inline void cec_msg_record_on_own(struct cec_msg *msg) 272 { 273 msg->len = 3; 274 msg->msg[1] = CEC_MSG_RECORD_ON; 275 msg->msg[2] = CEC_OP_RECORD_SRC_OWN; 276 } 277 278 static inline void cec_msg_record_on_digital(struct cec_msg *msg, 279 const struct cec_op_digital_service_id *digital) 280 { 281 msg->len = 10; 282 msg->msg[1] = CEC_MSG_RECORD_ON; 283 msg->msg[2] = CEC_OP_RECORD_SRC_DIGITAL; 284 cec_set_digital_service_id(msg->msg + 3, digital); 285 } 286 287 static inline void cec_msg_record_on_analog(struct cec_msg *msg, 288 __u8 ana_bcast_type, 289 __u16 ana_freq, 290 __u8 bcast_system) 291 { 292 msg->len = 7; 293 msg->msg[1] = CEC_MSG_RECORD_ON; 294 msg->msg[2] = CEC_OP_RECORD_SRC_ANALOG; 295 msg->msg[3] = ana_bcast_type; 296 msg->msg[4] = ana_freq >> 8; 297 msg->msg[5] = ana_freq & 0xff; 298 msg->msg[6] = bcast_system; 299 } 300 301 static inline void cec_msg_record_on_plug(struct cec_msg *msg, 302 __u8 plug) 303 { 304 msg->len = 4; 305 msg->msg[1] = CEC_MSG_RECORD_ON; 306 msg->msg[2] = CEC_OP_RECORD_SRC_EXT_PLUG; 307 msg->msg[3] = plug; 308 } 309 310 static inline void cec_msg_record_on_phys_addr(struct cec_msg *msg, 311 __u16 phys_addr) 312 { 313 msg->len = 5; 314 msg->msg[1] = CEC_MSG_RECORD_ON; 315 msg->msg[2] = CEC_OP_RECORD_SRC_EXT_PHYS_ADDR; 316 msg->msg[3] = phys_addr >> 8; 317 msg->msg[4] = phys_addr & 0xff; 318 } 319 320 static inline void cec_msg_record_on(struct cec_msg *msg, 321 int reply, 322 const struct cec_op_record_src *rec_src) 323 { 324 switch (rec_src->type) { 325 case CEC_OP_RECORD_SRC_OWN: 326 cec_msg_record_on_own(msg); 327 break; 328 case CEC_OP_RECORD_SRC_DIGITAL: 329 cec_msg_record_on_digital(msg, &rec_src->digital); 330 break; 331 case CEC_OP_RECORD_SRC_ANALOG: 332 cec_msg_record_on_analog(msg, 333 rec_src->analog.ana_bcast_type, 334 rec_src->analog.ana_freq, 335 rec_src->analog.bcast_system); 336 break; 337 case CEC_OP_RECORD_SRC_EXT_PLUG: 338 cec_msg_record_on_plug(msg, rec_src->ext_plug.plug); 339 break; 340 case CEC_OP_RECORD_SRC_EXT_PHYS_ADDR: 341 cec_msg_record_on_phys_addr(msg, 342 rec_src->ext_phys_addr.phys_addr); 343 break; 344 } 345 msg->reply = reply ? CEC_MSG_RECORD_STATUS : 0; 346 } 347 348 static inline void cec_ops_record_on(const struct cec_msg *msg, 349 struct cec_op_record_src *rec_src) 350 { 351 rec_src->type = msg->msg[2]; 352 switch (rec_src->type) { 353 case CEC_OP_RECORD_SRC_OWN: 354 break; 355 case CEC_OP_RECORD_SRC_DIGITAL: 356 cec_get_digital_service_id(msg->msg + 3, &rec_src->digital); 357 break; 358 case CEC_OP_RECORD_SRC_ANALOG: 359 rec_src->analog.ana_bcast_type = msg->msg[3]; 360 rec_src->analog.ana_freq = 361 (msg->msg[4] << 8) | msg->msg[5]; 362 rec_src->analog.bcast_system = msg->msg[6]; 363 break; 364 case CEC_OP_RECORD_SRC_EXT_PLUG: 365 rec_src->ext_plug.plug = msg->msg[3]; 366 break; 367 case CEC_OP_RECORD_SRC_EXT_PHYS_ADDR: 368 rec_src->ext_phys_addr.phys_addr = 369 (msg->msg[3] << 8) | msg->msg[4]; 370 break; 371 } 372 } 373 374 static inline void cec_msg_record_status(struct cec_msg *msg, __u8 rec_status) 375 { 376 msg->len = 3; 377 msg->msg[1] = CEC_MSG_RECORD_STATUS; 378 msg->msg[2] = rec_status; 379 } 380 381 static inline void cec_ops_record_status(const struct cec_msg *msg, 382 __u8 *rec_status) 383 { 384 *rec_status = msg->msg[2]; 385 } 386 387 static inline void cec_msg_record_tv_screen(struct cec_msg *msg, 388 int reply) 389 { 390 msg->len = 2; 391 msg->msg[1] = CEC_MSG_RECORD_TV_SCREEN; 392 msg->reply = reply ? CEC_MSG_RECORD_ON : 0; 393 } 394 395 396 /* Timer Programming Feature */ 397 static inline void cec_msg_timer_status(struct cec_msg *msg, 398 __u8 timer_overlap_warning, 399 __u8 media_info, 400 __u8 prog_info, 401 __u8 prog_error, 402 __u8 duration_hr, 403 __u8 duration_min) 404 { 405 msg->len = 3; 406 msg->msg[1] = CEC_MSG_TIMER_STATUS; 407 msg->msg[2] = (timer_overlap_warning << 7) | 408 (media_info << 5) | 409 (prog_info ? 0x10 : 0) | 410 (prog_info ? prog_info : prog_error); 411 if (prog_info == CEC_OP_PROG_INFO_NOT_ENOUGH_SPACE || 412 prog_info == CEC_OP_PROG_INFO_MIGHT_NOT_BE_ENOUGH_SPACE || 413 prog_error == CEC_OP_PROG_ERROR_DUPLICATE) { 414 msg->len += 2; 415 msg->msg[3] = ((duration_hr / 10) << 4) | (duration_hr % 10); 416 msg->msg[4] = ((duration_min / 10) << 4) | (duration_min % 10); 417 } 418 } 419 420 static inline void cec_ops_timer_status(const struct cec_msg *msg, 421 __u8 *timer_overlap_warning, 422 __u8 *media_info, 423 __u8 *prog_info, 424 __u8 *prog_error, 425 __u8 *duration_hr, 426 __u8 *duration_min) 427 { 428 *timer_overlap_warning = msg->msg[2] >> 7; 429 *media_info = (msg->msg[2] >> 5) & 3; 430 if (msg->msg[2] & 0x10) { 431 *prog_info = msg->msg[2] & 0xf; 432 *prog_error = 0; 433 } else { 434 *prog_info = 0; 435 *prog_error = msg->msg[2] & 0xf; 436 } 437 if (*prog_info == CEC_OP_PROG_INFO_NOT_ENOUGH_SPACE || 438 *prog_info == CEC_OP_PROG_INFO_MIGHT_NOT_BE_ENOUGH_SPACE || 439 *prog_error == CEC_OP_PROG_ERROR_DUPLICATE) { 440 *duration_hr = (msg->msg[3] >> 4) * 10 + (msg->msg[3] & 0xf); 441 *duration_min = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf); 442 } else { 443 *duration_hr = *duration_min = 0; 444 } 445 } 446 447 static inline void cec_msg_timer_cleared_status(struct cec_msg *msg, 448 __u8 timer_cleared_status) 449 { 450 msg->len = 3; 451 msg->msg[1] = CEC_MSG_TIMER_CLEARED_STATUS; 452 msg->msg[2] = timer_cleared_status; 453 } 454 455 static inline void cec_ops_timer_cleared_status(const struct cec_msg *msg, 456 __u8 *timer_cleared_status) 457 { 458 *timer_cleared_status = msg->msg[2]; 459 } 460 461 static inline void cec_msg_clear_analogue_timer(struct cec_msg *msg, 462 int reply, 463 __u8 day, 464 __u8 month, 465 __u8 start_hr, 466 __u8 start_min, 467 __u8 duration_hr, 468 __u8 duration_min, 469 __u8 recording_seq, 470 __u8 ana_bcast_type, 471 __u16 ana_freq, 472 __u8 bcast_system) 473 { 474 msg->len = 13; 475 msg->msg[1] = CEC_MSG_CLEAR_ANALOGUE_TIMER; 476 msg->msg[2] = day; 477 msg->msg[3] = month; 478 /* Hours and minutes are in BCD format */ 479 msg->msg[4] = ((start_hr / 10) << 4) | (start_hr % 10); 480 msg->msg[5] = ((start_min / 10) << 4) | (start_min % 10); 481 msg->msg[6] = ((duration_hr / 10) << 4) | (duration_hr % 10); 482 msg->msg[7] = ((duration_min / 10) << 4) | (duration_min % 10); 483 msg->msg[8] = recording_seq; 484 msg->msg[9] = ana_bcast_type; 485 msg->msg[10] = ana_freq >> 8; 486 msg->msg[11] = ana_freq & 0xff; 487 msg->msg[12] = bcast_system; 488 msg->reply = reply ? CEC_MSG_TIMER_CLEARED_STATUS : 0; 489 } 490 491 static inline void cec_ops_clear_analogue_timer(const struct cec_msg *msg, 492 __u8 *day, 493 __u8 *month, 494 __u8 *start_hr, 495 __u8 *start_min, 496 __u8 *duration_hr, 497 __u8 *duration_min, 498 __u8 *recording_seq, 499 __u8 *ana_bcast_type, 500 __u16 *ana_freq, 501 __u8 *bcast_system) 502 { 503 *day = msg->msg[2]; 504 *month = msg->msg[3]; 505 /* Hours and minutes are in BCD format */ 506 *start_hr = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf); 507 *start_min = (msg->msg[5] >> 4) * 10 + (msg->msg[5] & 0xf); 508 *duration_hr = (msg->msg[6] >> 4) * 10 + (msg->msg[6] & 0xf); 509 *duration_min = (msg->msg[7] >> 4) * 10 + (msg->msg[7] & 0xf); 510 *recording_seq = msg->msg[8]; 511 *ana_bcast_type = msg->msg[9]; 512 *ana_freq = (msg->msg[10] << 8) | msg->msg[11]; 513 *bcast_system = msg->msg[12]; 514 } 515 516 static inline void cec_msg_clear_digital_timer(struct cec_msg *msg, 517 int reply, 518 __u8 day, 519 __u8 month, 520 __u8 start_hr, 521 __u8 start_min, 522 __u8 duration_hr, 523 __u8 duration_min, 524 __u8 recording_seq, 525 const struct cec_op_digital_service_id *digital) 526 { 527 msg->len = 16; 528 msg->reply = reply ? CEC_MSG_TIMER_CLEARED_STATUS : 0; 529 msg->msg[1] = CEC_MSG_CLEAR_DIGITAL_TIMER; 530 msg->msg[2] = day; 531 msg->msg[3] = month; 532 /* Hours and minutes are in BCD format */ 533 msg->msg[4] = ((start_hr / 10) << 4) | (start_hr % 10); 534 msg->msg[5] = ((start_min / 10) << 4) | (start_min % 10); 535 msg->msg[6] = ((duration_hr / 10) << 4) | (duration_hr % 10); 536 msg->msg[7] = ((duration_min / 10) << 4) | (duration_min % 10); 537 msg->msg[8] = recording_seq; 538 cec_set_digital_service_id(msg->msg + 9, digital); 539 } 540 541 static inline void cec_ops_clear_digital_timer(const struct cec_msg *msg, 542 __u8 *day, 543 __u8 *month, 544 __u8 *start_hr, 545 __u8 *start_min, 546 __u8 *duration_hr, 547 __u8 *duration_min, 548 __u8 *recording_seq, 549 struct cec_op_digital_service_id *digital) 550 { 551 *day = msg->msg[2]; 552 *month = msg->msg[3]; 553 /* Hours and minutes are in BCD format */ 554 *start_hr = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf); 555 *start_min = (msg->msg[5] >> 4) * 10 + (msg->msg[5] & 0xf); 556 *duration_hr = (msg->msg[6] >> 4) * 10 + (msg->msg[6] & 0xf); 557 *duration_min = (msg->msg[7] >> 4) * 10 + (msg->msg[7] & 0xf); 558 *recording_seq = msg->msg[8]; 559 cec_get_digital_service_id(msg->msg + 9, digital); 560 } 561 562 static inline void cec_msg_clear_ext_timer(struct cec_msg *msg, 563 int reply, 564 __u8 day, 565 __u8 month, 566 __u8 start_hr, 567 __u8 start_min, 568 __u8 duration_hr, 569 __u8 duration_min, 570 __u8 recording_seq, 571 __u8 ext_src_spec, 572 __u8 plug, 573 __u16 phys_addr) 574 { 575 msg->len = 13; 576 msg->msg[1] = CEC_MSG_CLEAR_EXT_TIMER; 577 msg->msg[2] = day; 578 msg->msg[3] = month; 579 /* Hours and minutes are in BCD format */ 580 msg->msg[4] = ((start_hr / 10) << 4) | (start_hr % 10); 581 msg->msg[5] = ((start_min / 10) << 4) | (start_min % 10); 582 msg->msg[6] = ((duration_hr / 10) << 4) | (duration_hr % 10); 583 msg->msg[7] = ((duration_min / 10) << 4) | (duration_min % 10); 584 msg->msg[8] = recording_seq; 585 msg->msg[9] = ext_src_spec; 586 msg->msg[10] = plug; 587 msg->msg[11] = phys_addr >> 8; 588 msg->msg[12] = phys_addr & 0xff; 589 msg->reply = reply ? CEC_MSG_TIMER_CLEARED_STATUS : 0; 590 } 591 592 static inline void cec_ops_clear_ext_timer(const struct cec_msg *msg, 593 __u8 *day, 594 __u8 *month, 595 __u8 *start_hr, 596 __u8 *start_min, 597 __u8 *duration_hr, 598 __u8 *duration_min, 599 __u8 *recording_seq, 600 __u8 *ext_src_spec, 601 __u8 *plug, 602 __u16 *phys_addr) 603 { 604 *day = msg->msg[2]; 605 *month = msg->msg[3]; 606 /* Hours and minutes are in BCD format */ 607 *start_hr = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf); 608 *start_min = (msg->msg[5] >> 4) * 10 + (msg->msg[5] & 0xf); 609 *duration_hr = (msg->msg[6] >> 4) * 10 + (msg->msg[6] & 0xf); 610 *duration_min = (msg->msg[7] >> 4) * 10 + (msg->msg[7] & 0xf); 611 *recording_seq = msg->msg[8]; 612 *ext_src_spec = msg->msg[9]; 613 *plug = msg->msg[10]; 614 *phys_addr = (msg->msg[11] << 8) | msg->msg[12]; 615 } 616 617 static inline void cec_msg_set_analogue_timer(struct cec_msg *msg, 618 int reply, 619 __u8 day, 620 __u8 month, 621 __u8 start_hr, 622 __u8 start_min, 623 __u8 duration_hr, 624 __u8 duration_min, 625 __u8 recording_seq, 626 __u8 ana_bcast_type, 627 __u16 ana_freq, 628 __u8 bcast_system) 629 { 630 msg->len = 13; 631 msg->msg[1] = CEC_MSG_SET_ANALOGUE_TIMER; 632 msg->msg[2] = day; 633 msg->msg[3] = month; 634 /* Hours and minutes are in BCD format */ 635 msg->msg[4] = ((start_hr / 10) << 4) | (start_hr % 10); 636 msg->msg[5] = ((start_min / 10) << 4) | (start_min % 10); 637 msg->msg[6] = ((duration_hr / 10) << 4) | (duration_hr % 10); 638 msg->msg[7] = ((duration_min / 10) << 4) | (duration_min % 10); 639 msg->msg[8] = recording_seq; 640 msg->msg[9] = ana_bcast_type; 641 msg->msg[10] = ana_freq >> 8; 642 msg->msg[11] = ana_freq & 0xff; 643 msg->msg[12] = bcast_system; 644 msg->reply = reply ? CEC_MSG_TIMER_STATUS : 0; 645 } 646 647 static inline void cec_ops_set_analogue_timer(const struct cec_msg *msg, 648 __u8 *day, 649 __u8 *month, 650 __u8 *start_hr, 651 __u8 *start_min, 652 __u8 *duration_hr, 653 __u8 *duration_min, 654 __u8 *recording_seq, 655 __u8 *ana_bcast_type, 656 __u16 *ana_freq, 657 __u8 *bcast_system) 658 { 659 *day = msg->msg[2]; 660 *month = msg->msg[3]; 661 /* Hours and minutes are in BCD format */ 662 *start_hr = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf); 663 *start_min = (msg->msg[5] >> 4) * 10 + (msg->msg[5] & 0xf); 664 *duration_hr = (msg->msg[6] >> 4) * 10 + (msg->msg[6] & 0xf); 665 *duration_min = (msg->msg[7] >> 4) * 10 + (msg->msg[7] & 0xf); 666 *recording_seq = msg->msg[8]; 667 *ana_bcast_type = msg->msg[9]; 668 *ana_freq = (msg->msg[10] << 8) | msg->msg[11]; 669 *bcast_system = msg->msg[12]; 670 } 671 672 static inline void cec_msg_set_digital_timer(struct cec_msg *msg, 673 int reply, 674 __u8 day, 675 __u8 month, 676 __u8 start_hr, 677 __u8 start_min, 678 __u8 duration_hr, 679 __u8 duration_min, 680 __u8 recording_seq, 681 const struct cec_op_digital_service_id *digital) 682 { 683 msg->len = 16; 684 msg->reply = reply ? CEC_MSG_TIMER_STATUS : 0; 685 msg->msg[1] = CEC_MSG_SET_DIGITAL_TIMER; 686 msg->msg[2] = day; 687 msg->msg[3] = month; 688 /* Hours and minutes are in BCD format */ 689 msg->msg[4] = ((start_hr / 10) << 4) | (start_hr % 10); 690 msg->msg[5] = ((start_min / 10) << 4) | (start_min % 10); 691 msg->msg[6] = ((duration_hr / 10) << 4) | (duration_hr % 10); 692 msg->msg[7] = ((duration_min / 10) << 4) | (duration_min % 10); 693 msg->msg[8] = recording_seq; 694 cec_set_digital_service_id(msg->msg + 9, digital); 695 } 696 697 static inline void cec_ops_set_digital_timer(const struct cec_msg *msg, 698 __u8 *day, 699 __u8 *month, 700 __u8 *start_hr, 701 __u8 *start_min, 702 __u8 *duration_hr, 703 __u8 *duration_min, 704 __u8 *recording_seq, 705 struct cec_op_digital_service_id *digital) 706 { 707 *day = msg->msg[2]; 708 *month = msg->msg[3]; 709 /* Hours and minutes are in BCD format */ 710 *start_hr = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf); 711 *start_min = (msg->msg[5] >> 4) * 10 + (msg->msg[5] & 0xf); 712 *duration_hr = (msg->msg[6] >> 4) * 10 + (msg->msg[6] & 0xf); 713 *duration_min = (msg->msg[7] >> 4) * 10 + (msg->msg[7] & 0xf); 714 *recording_seq = msg->msg[8]; 715 cec_get_digital_service_id(msg->msg + 9, digital); 716 } 717 718 static inline void cec_msg_set_ext_timer(struct cec_msg *msg, 719 int reply, 720 __u8 day, 721 __u8 month, 722 __u8 start_hr, 723 __u8 start_min, 724 __u8 duration_hr, 725 __u8 duration_min, 726 __u8 recording_seq, 727 __u8 ext_src_spec, 728 __u8 plug, 729 __u16 phys_addr) 730 { 731 msg->len = 13; 732 msg->msg[1] = CEC_MSG_SET_EXT_TIMER; 733 msg->msg[2] = day; 734 msg->msg[3] = month; 735 /* Hours and minutes are in BCD format */ 736 msg->msg[4] = ((start_hr / 10) << 4) | (start_hr % 10); 737 msg->msg[5] = ((start_min / 10) << 4) | (start_min % 10); 738 msg->msg[6] = ((duration_hr / 10) << 4) | (duration_hr % 10); 739 msg->msg[7] = ((duration_min / 10) << 4) | (duration_min % 10); 740 msg->msg[8] = recording_seq; 741 msg->msg[9] = ext_src_spec; 742 msg->msg[10] = plug; 743 msg->msg[11] = phys_addr >> 8; 744 msg->msg[12] = phys_addr & 0xff; 745 msg->reply = reply ? CEC_MSG_TIMER_STATUS : 0; 746 } 747 748 static inline void cec_ops_set_ext_timer(const struct cec_msg *msg, 749 __u8 *day, 750 __u8 *month, 751 __u8 *start_hr, 752 __u8 *start_min, 753 __u8 *duration_hr, 754 __u8 *duration_min, 755 __u8 *recording_seq, 756 __u8 *ext_src_spec, 757 __u8 *plug, 758 __u16 *phys_addr) 759 { 760 *day = msg->msg[2]; 761 *month = msg->msg[3]; 762 /* Hours and minutes are in BCD format */ 763 *start_hr = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf); 764 *start_min = (msg->msg[5] >> 4) * 10 + (msg->msg[5] & 0xf); 765 *duration_hr = (msg->msg[6] >> 4) * 10 + (msg->msg[6] & 0xf); 766 *duration_min = (msg->msg[7] >> 4) * 10 + (msg->msg[7] & 0xf); 767 *recording_seq = msg->msg[8]; 768 *ext_src_spec = msg->msg[9]; 769 *plug = msg->msg[10]; 770 *phys_addr = (msg->msg[11] << 8) | msg->msg[12]; 771 } 772 773 static inline void cec_msg_set_timer_program_title(struct cec_msg *msg, 774 const char *prog_title) 775 { 776 unsigned int len = strlen(prog_title); 777 778 if (len > 14) 779 len = 14; 780 msg->len = 2 + len; 781 msg->msg[1] = CEC_MSG_SET_TIMER_PROGRAM_TITLE; 782 memcpy(msg->msg + 2, prog_title, len); 783 } 784 785 static inline void cec_ops_set_timer_program_title(const struct cec_msg *msg, 786 char *prog_title) 787 { 788 unsigned int len = msg->len > 2 ? msg->len - 2 : 0; 789 790 if (len > 14) 791 len = 14; 792 memcpy(prog_title, msg->msg + 2, len); 793 prog_title[len] = '\0'; 794 } 795 796 /* System Information Feature */ 797 static inline void cec_msg_cec_version(struct cec_msg *msg, __u8 cec_version) 798 { 799 msg->len = 3; 800 msg->msg[1] = CEC_MSG_CEC_VERSION; 801 msg->msg[2] = cec_version; 802 } 803 804 static inline void cec_ops_cec_version(const struct cec_msg *msg, 805 __u8 *cec_version) 806 { 807 *cec_version = msg->msg[2]; 808 } 809 810 static inline void cec_msg_get_cec_version(struct cec_msg *msg, 811 int reply) 812 { 813 msg->len = 2; 814 msg->msg[1] = CEC_MSG_GET_CEC_VERSION; 815 msg->reply = reply ? CEC_MSG_CEC_VERSION : 0; 816 } 817 818 static inline void cec_msg_report_physical_addr(struct cec_msg *msg, 819 __u16 phys_addr, __u8 prim_devtype) 820 { 821 msg->len = 5; 822 msg->msg[0] |= 0xf; /* broadcast */ 823 msg->msg[1] = CEC_MSG_REPORT_PHYSICAL_ADDR; 824 msg->msg[2] = phys_addr >> 8; 825 msg->msg[3] = phys_addr & 0xff; 826 msg->msg[4] = prim_devtype; 827 } 828 829 static inline void cec_ops_report_physical_addr(const struct cec_msg *msg, 830 __u16 *phys_addr, __u8 *prim_devtype) 831 { 832 *phys_addr = (msg->msg[2] << 8) | msg->msg[3]; 833 *prim_devtype = msg->msg[4]; 834 } 835 836 static inline void cec_msg_give_physical_addr(struct cec_msg *msg, 837 int reply) 838 { 839 msg->len = 2; 840 msg->msg[1] = CEC_MSG_GIVE_PHYSICAL_ADDR; 841 msg->reply = reply ? CEC_MSG_REPORT_PHYSICAL_ADDR : 0; 842 } 843 844 static inline void cec_msg_set_menu_language(struct cec_msg *msg, 845 const char *language) 846 { 847 msg->len = 5; 848 msg->msg[0] |= 0xf; /* broadcast */ 849 msg->msg[1] = CEC_MSG_SET_MENU_LANGUAGE; 850 memcpy(msg->msg + 2, language, 3); 851 } 852 853 static inline void cec_ops_set_menu_language(const struct cec_msg *msg, 854 char *language) 855 { 856 memcpy(language, msg->msg + 2, 3); 857 language[3] = '\0'; 858 } 859 860 static inline void cec_msg_get_menu_language(struct cec_msg *msg, 861 int reply) 862 { 863 msg->len = 2; 864 msg->msg[1] = CEC_MSG_GET_MENU_LANGUAGE; 865 msg->reply = reply ? CEC_MSG_SET_MENU_LANGUAGE : 0; 866 } 867 868 /* 869 * Assumes a single RC Profile byte and a single Device Features byte, 870 * i.e. no extended features are supported by this helper function. 871 * 872 * As of CEC 2.0 no extended features are defined, should those be added 873 * in the future, then this function needs to be adapted or a new function 874 * should be added. 875 */ 876 static inline void cec_msg_report_features(struct cec_msg *msg, 877 __u8 cec_version, __u8 all_device_types, 878 __u8 rc_profile, __u8 dev_features) 879 { 880 msg->len = 6; 881 msg->msg[0] |= 0xf; /* broadcast */ 882 msg->msg[1] = CEC_MSG_REPORT_FEATURES; 883 msg->msg[2] = cec_version; 884 msg->msg[3] = all_device_types; 885 msg->msg[4] = rc_profile; 886 msg->msg[5] = dev_features; 887 } 888 889 static inline void cec_ops_report_features(const struct cec_msg *msg, 890 __u8 *cec_version, __u8 *all_device_types, 891 const __u8 **rc_profile, const __u8 **dev_features) 892 { 893 const __u8 *p = &msg->msg[4]; 894 895 *cec_version = msg->msg[2]; 896 *all_device_types = msg->msg[3]; 897 *rc_profile = p; 898 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 909 static inline void cec_msg_give_features(struct cec_msg *msg, 910 int 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 */ 918 static 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 926 static 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 932 static 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 940 static inline void cec_ops_deck_status(const struct cec_msg *msg, 941 __u8 *deck_info) 942 { 943 *deck_info = msg->msg[2]; 944 } 945 946 static inline void cec_msg_give_deck_status(struct cec_msg *msg, 947 int 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 956 static 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 962 static 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 970 static 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 */ 978 struct cec_op_tuner_device_info { 979 __u8 rec_flag; 980 __u8 tuner_display_info; 981 __u8 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 992 static 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 1008 static 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 1018 static 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 1035 static 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 1050 static inline void cec_msg_give_tuner_device_status(struct cec_msg *msg, 1051 int 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 1060 static 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 1066 static 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 1079 static 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 1089 static 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 1097 static 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 1103 static 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 1109 static 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 */ 1117 static 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 1127 static 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 1133 static inline void cec_msg_give_device_vendor_id(struct cec_msg *msg, 1134 int 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 1141 static 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 1151 static 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 1162 static 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 1176 static 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 1188 static 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 1199 static 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 1210 static 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 */ 1218 static 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 1232 static 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 */ 1247 static 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 1258 static 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 1269 static inline void cec_msg_give_osd_name(struct cec_msg *msg, 1270 int 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 */ 1279 static 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 1287 static inline void cec_ops_menu_status(const struct cec_msg *msg, 1288 __u8 *menu_state) 1289 { 1290 *menu_state = msg->msg[2]; 1291 } 1292 1293 static inline void cec_msg_menu_request(struct cec_msg *msg, 1294 int 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 1303 static inline void cec_ops_menu_request(const struct cec_msg *msg, 1304 __u8 *menu_req) 1305 { 1306 *menu_req = msg->msg[2]; 1307 } 1308 1309 struct cec_op_ui_command { 1310 __u8 ui_cmd; 1311 __u8 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 1323 static 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 1353 static 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 = 0; 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 = 1; 1370 break; 1371 case 0x67: 1372 if (msg->len < 7) 1373 break; 1374 ui_cmd->has_opt_arg = 1; 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 1382 static 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 */ 1391 static 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 1399 static 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 1405 static inline void cec_msg_give_device_power_status(struct cec_msg *msg, 1406 int 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 */ 1414 static 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 1423 static 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 */ 1431 static 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 1440 static 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 */ 1448 static 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 1457 static 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 1465 static inline void cec_msg_give_audio_status(struct cec_msg *msg, 1466 int 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 1473 static 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 1481 static 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 1487 static inline void cec_msg_system_audio_mode_request(struct cec_msg *msg, 1488 int 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 1499 static 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 1508 static 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 1516 static 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 1522 static inline void cec_msg_give_system_audio_mode_status(struct cec_msg *msg, 1523 int 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 1530 static 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 1547 static 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 1562 static inline void cec_msg_request_short_audio_descriptor(struct cec_msg *msg, 1563 int 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 1580 static 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 */ 1598 static 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 1606 static 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 */ 1614 static 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 1620 static inline void cec_msg_initiate_arc(struct cec_msg *msg, 1621 int 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 1628 static inline void cec_msg_request_arc_initiation(struct cec_msg *msg, 1629 int 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 1636 static 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 1642 static inline void cec_msg_terminate_arc(struct cec_msg *msg, 1643 int 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 1650 static inline void cec_msg_request_arc_termination(struct cec_msg *msg, 1651 int 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 */ 1661 static 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 = 6; 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 if (audio_out_compensated == 3) 1676 msg->msg[msg->len++] = audio_out_delay; 1677 } 1678 1679 static inline void cec_ops_report_current_latency(const struct cec_msg *msg, 1680 __u16 *phys_addr, 1681 __u8 *video_latency, 1682 __u8 *low_latency_mode, 1683 __u8 *audio_out_compensated, 1684 __u8 *audio_out_delay) 1685 { 1686 *phys_addr = (msg->msg[2] << 8) | msg->msg[3]; 1687 *video_latency = msg->msg[4]; 1688 *low_latency_mode = (msg->msg[5] >> 2) & 1; 1689 *audio_out_compensated = msg->msg[5] & 3; 1690 if (*audio_out_compensated == 3 && msg->len >= 7) 1691 *audio_out_delay = msg->msg[6]; 1692 else 1693 *audio_out_delay = 0; 1694 } 1695 1696 static inline void cec_msg_request_current_latency(struct cec_msg *msg, 1697 int reply, 1698 __u16 phys_addr) 1699 { 1700 msg->len = 4; 1701 msg->msg[0] |= 0xf; /* broadcast */ 1702 msg->msg[1] = CEC_MSG_REQUEST_CURRENT_LATENCY; 1703 msg->msg[2] = phys_addr >> 8; 1704 msg->msg[3] = phys_addr & 0xff; 1705 msg->reply = reply ? CEC_MSG_REPORT_CURRENT_LATENCY : 0; 1706 } 1707 1708 static inline void cec_ops_request_current_latency(const struct cec_msg *msg, 1709 __u16 *phys_addr) 1710 { 1711 *phys_addr = (msg->msg[2] << 8) | msg->msg[3]; 1712 } 1713 1714 1715 /* Capability Discovery and Control Feature */ 1716 static inline void cec_msg_cdc_hec_inquire_state(struct cec_msg *msg, 1717 __u16 phys_addr1, 1718 __u16 phys_addr2) 1719 { 1720 msg->len = 9; 1721 msg->msg[0] |= 0xf; /* broadcast */ 1722 msg->msg[1] = CEC_MSG_CDC_MESSAGE; 1723 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */ 1724 msg->msg[4] = CEC_MSG_CDC_HEC_INQUIRE_STATE; 1725 msg->msg[5] = phys_addr1 >> 8; 1726 msg->msg[6] = phys_addr1 & 0xff; 1727 msg->msg[7] = phys_addr2 >> 8; 1728 msg->msg[8] = phys_addr2 & 0xff; 1729 } 1730 1731 static inline void cec_ops_cdc_hec_inquire_state(const struct cec_msg *msg, 1732 __u16 *phys_addr, 1733 __u16 *phys_addr1, 1734 __u16 *phys_addr2) 1735 { 1736 *phys_addr = (msg->msg[2] << 8) | msg->msg[3]; 1737 *phys_addr1 = (msg->msg[5] << 8) | msg->msg[6]; 1738 *phys_addr2 = (msg->msg[7] << 8) | msg->msg[8]; 1739 } 1740 1741 static inline void cec_msg_cdc_hec_report_state(struct cec_msg *msg, 1742 __u16 target_phys_addr, 1743 __u8 hec_func_state, 1744 __u8 host_func_state, 1745 __u8 enc_func_state, 1746 __u8 cdc_errcode, 1747 __u8 has_field, 1748 __u16 hec_field) 1749 { 1750 msg->len = has_field ? 10 : 8; 1751 msg->msg[0] |= 0xf; /* broadcast */ 1752 msg->msg[1] = CEC_MSG_CDC_MESSAGE; 1753 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */ 1754 msg->msg[4] = CEC_MSG_CDC_HEC_REPORT_STATE; 1755 msg->msg[5] = target_phys_addr >> 8; 1756 msg->msg[6] = target_phys_addr & 0xff; 1757 msg->msg[7] = (hec_func_state << 6) | 1758 (host_func_state << 4) | 1759 (enc_func_state << 2) | 1760 cdc_errcode; 1761 if (has_field) { 1762 msg->msg[8] = hec_field >> 8; 1763 msg->msg[9] = hec_field & 0xff; 1764 } 1765 } 1766 1767 static inline void cec_ops_cdc_hec_report_state(const struct cec_msg *msg, 1768 __u16 *phys_addr, 1769 __u16 *target_phys_addr, 1770 __u8 *hec_func_state, 1771 __u8 *host_func_state, 1772 __u8 *enc_func_state, 1773 __u8 *cdc_errcode, 1774 __u8 *has_field, 1775 __u16 *hec_field) 1776 { 1777 *phys_addr = (msg->msg[2] << 8) | msg->msg[3]; 1778 *target_phys_addr = (msg->msg[5] << 8) | msg->msg[6]; 1779 *hec_func_state = msg->msg[7] >> 6; 1780 *host_func_state = (msg->msg[7] >> 4) & 3; 1781 *enc_func_state = (msg->msg[7] >> 4) & 3; 1782 *cdc_errcode = msg->msg[7] & 3; 1783 *has_field = msg->len >= 10; 1784 *hec_field = *has_field ? ((msg->msg[8] << 8) | msg->msg[9]) : 0; 1785 } 1786 1787 static inline void cec_msg_cdc_hec_set_state(struct cec_msg *msg, 1788 __u16 phys_addr1, 1789 __u16 phys_addr2, 1790 __u8 hec_set_state, 1791 __u16 phys_addr3, 1792 __u16 phys_addr4, 1793 __u16 phys_addr5) 1794 { 1795 msg->len = 10; 1796 msg->msg[0] |= 0xf; /* broadcast */ 1797 msg->msg[1] = CEC_MSG_CDC_MESSAGE; 1798 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */ 1799 msg->msg[4] = CEC_MSG_CDC_HEC_INQUIRE_STATE; 1800 msg->msg[5] = phys_addr1 >> 8; 1801 msg->msg[6] = phys_addr1 & 0xff; 1802 msg->msg[7] = phys_addr2 >> 8; 1803 msg->msg[8] = phys_addr2 & 0xff; 1804 msg->msg[9] = hec_set_state; 1805 if (phys_addr3 != CEC_PHYS_ADDR_INVALID) { 1806 msg->msg[msg->len++] = phys_addr3 >> 8; 1807 msg->msg[msg->len++] = phys_addr3 & 0xff; 1808 if (phys_addr4 != CEC_PHYS_ADDR_INVALID) { 1809 msg->msg[msg->len++] = phys_addr4 >> 8; 1810 msg->msg[msg->len++] = phys_addr4 & 0xff; 1811 if (phys_addr5 != CEC_PHYS_ADDR_INVALID) { 1812 msg->msg[msg->len++] = phys_addr5 >> 8; 1813 msg->msg[msg->len++] = phys_addr5 & 0xff; 1814 } 1815 } 1816 } 1817 } 1818 1819 static inline void cec_ops_cdc_hec_set_state(const struct cec_msg *msg, 1820 __u16 *phys_addr, 1821 __u16 *phys_addr1, 1822 __u16 *phys_addr2, 1823 __u8 *hec_set_state, 1824 __u16 *phys_addr3, 1825 __u16 *phys_addr4, 1826 __u16 *phys_addr5) 1827 { 1828 *phys_addr = (msg->msg[2] << 8) | msg->msg[3]; 1829 *phys_addr1 = (msg->msg[5] << 8) | msg->msg[6]; 1830 *phys_addr2 = (msg->msg[7] << 8) | msg->msg[8]; 1831 *hec_set_state = msg->msg[9]; 1832 *phys_addr3 = *phys_addr4 = *phys_addr5 = CEC_PHYS_ADDR_INVALID; 1833 if (msg->len >= 12) 1834 *phys_addr3 = (msg->msg[10] << 8) | msg->msg[11]; 1835 if (msg->len >= 14) 1836 *phys_addr4 = (msg->msg[12] << 8) | msg->msg[13]; 1837 if (msg->len >= 16) 1838 *phys_addr5 = (msg->msg[14] << 8) | msg->msg[15]; 1839 } 1840 1841 static inline void cec_msg_cdc_hec_set_state_adjacent(struct cec_msg *msg, 1842 __u16 phys_addr1, 1843 __u8 hec_set_state) 1844 { 1845 msg->len = 8; 1846 msg->msg[0] |= 0xf; /* broadcast */ 1847 msg->msg[1] = CEC_MSG_CDC_MESSAGE; 1848 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */ 1849 msg->msg[4] = CEC_MSG_CDC_HEC_SET_STATE_ADJACENT; 1850 msg->msg[5] = phys_addr1 >> 8; 1851 msg->msg[6] = phys_addr1 & 0xff; 1852 msg->msg[7] = hec_set_state; 1853 } 1854 1855 static inline void cec_ops_cdc_hec_set_state_adjacent(const struct cec_msg *msg, 1856 __u16 *phys_addr, 1857 __u16 *phys_addr1, 1858 __u8 *hec_set_state) 1859 { 1860 *phys_addr = (msg->msg[2] << 8) | msg->msg[3]; 1861 *phys_addr1 = (msg->msg[5] << 8) | msg->msg[6]; 1862 *hec_set_state = msg->msg[7]; 1863 } 1864 1865 static inline void cec_msg_cdc_hec_request_deactivation(struct cec_msg *msg, 1866 __u16 phys_addr1, 1867 __u16 phys_addr2, 1868 __u16 phys_addr3) 1869 { 1870 msg->len = 11; 1871 msg->msg[0] |= 0xf; /* broadcast */ 1872 msg->msg[1] = CEC_MSG_CDC_MESSAGE; 1873 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */ 1874 msg->msg[4] = CEC_MSG_CDC_HEC_REQUEST_DEACTIVATION; 1875 msg->msg[5] = phys_addr1 >> 8; 1876 msg->msg[6] = phys_addr1 & 0xff; 1877 msg->msg[7] = phys_addr2 >> 8; 1878 msg->msg[8] = phys_addr2 & 0xff; 1879 msg->msg[9] = phys_addr3 >> 8; 1880 msg->msg[10] = phys_addr3 & 0xff; 1881 } 1882 1883 static inline void cec_ops_cdc_hec_request_deactivation(const struct cec_msg *msg, 1884 __u16 *phys_addr, 1885 __u16 *phys_addr1, 1886 __u16 *phys_addr2, 1887 __u16 *phys_addr3) 1888 { 1889 *phys_addr = (msg->msg[2] << 8) | msg->msg[3]; 1890 *phys_addr1 = (msg->msg[5] << 8) | msg->msg[6]; 1891 *phys_addr2 = (msg->msg[7] << 8) | msg->msg[8]; 1892 *phys_addr3 = (msg->msg[9] << 8) | msg->msg[10]; 1893 } 1894 1895 static inline void cec_msg_cdc_hec_notify_alive(struct cec_msg *msg) 1896 { 1897 msg->len = 5; 1898 msg->msg[0] |= 0xf; /* broadcast */ 1899 msg->msg[1] = CEC_MSG_CDC_MESSAGE; 1900 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */ 1901 msg->msg[4] = CEC_MSG_CDC_HEC_NOTIFY_ALIVE; 1902 } 1903 1904 static inline void cec_ops_cdc_hec_notify_alive(const struct cec_msg *msg, 1905 __u16 *phys_addr) 1906 { 1907 *phys_addr = (msg->msg[2] << 8) | msg->msg[3]; 1908 } 1909 1910 static inline void cec_msg_cdc_hec_discover(struct cec_msg *msg) 1911 { 1912 msg->len = 5; 1913 msg->msg[0] |= 0xf; /* broadcast */ 1914 msg->msg[1] = CEC_MSG_CDC_MESSAGE; 1915 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */ 1916 msg->msg[4] = CEC_MSG_CDC_HEC_DISCOVER; 1917 } 1918 1919 static inline void cec_ops_cdc_hec_discover(const struct cec_msg *msg, 1920 __u16 *phys_addr) 1921 { 1922 *phys_addr = (msg->msg[2] << 8) | msg->msg[3]; 1923 } 1924 1925 static inline void cec_msg_cdc_hpd_set_state(struct cec_msg *msg, 1926 __u8 input_port, 1927 __u8 hpd_state) 1928 { 1929 msg->len = 6; 1930 msg->msg[0] |= 0xf; /* broadcast */ 1931 msg->msg[1] = CEC_MSG_CDC_MESSAGE; 1932 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */ 1933 msg->msg[4] = CEC_MSG_CDC_HPD_SET_STATE; 1934 msg->msg[5] = (input_port << 4) | hpd_state; 1935 } 1936 1937 static inline void cec_ops_cdc_hpd_set_state(const struct cec_msg *msg, 1938 __u16 *phys_addr, 1939 __u8 *input_port, 1940 __u8 *hpd_state) 1941 { 1942 *phys_addr = (msg->msg[2] << 8) | msg->msg[3]; 1943 *input_port = msg->msg[5] >> 4; 1944 *hpd_state = msg->msg[5] & 0xf; 1945 } 1946 1947 static inline void cec_msg_cdc_hpd_report_state(struct cec_msg *msg, 1948 __u8 hpd_state, 1949 __u8 hpd_error) 1950 { 1951 msg->len = 6; 1952 msg->msg[0] |= 0xf; /* broadcast */ 1953 msg->msg[1] = CEC_MSG_CDC_MESSAGE; 1954 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */ 1955 msg->msg[4] = CEC_MSG_CDC_HPD_REPORT_STATE; 1956 msg->msg[5] = (hpd_state << 4) | hpd_error; 1957 } 1958 1959 static inline void cec_ops_cdc_hpd_report_state(const struct cec_msg *msg, 1960 __u16 *phys_addr, 1961 __u8 *hpd_state, 1962 __u8 *hpd_error) 1963 { 1964 *phys_addr = (msg->msg[2] << 8) | msg->msg[3]; 1965 *hpd_state = msg->msg[5] >> 4; 1966 *hpd_error = msg->msg[5] & 0xf; 1967 } 1968 1969 #endif 1970