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