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