Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[media] cec: add proper support for CDC-Only CEC devices

CDC-Only CEC devices are CEC devices that can only handle CDC messages,
all other messages are ignored.

Add a flag to signal that this is a CDC-Only device and act accordingly.

Also add helper functions to identify if a CEC device is configured as a
CDC-Only device, a second TV, a switch or a processor, since these variations
cannot be determined by the logical address alone.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>

authored by

Hans Verkuil and committed by
Mauro Carvalho Chehab
a69a168a f5580d8d

+90 -6
-4
drivers/staging/media/cec/TODO
··· 1 1 TODOs: 2 2 3 - - Should CEC_LOG_ADDR_TYPE_SPECIFIC be replaced by TYPE_2ND_TV and TYPE_PROCESSOR? 4 - And also TYPE_SWITCH and TYPE_CDC_ONLY in addition to the TYPE_UNREGISTERED? 5 - This should give the framework more information about the device type 6 - since SPECIFIC and UNREGISTERED give no useful information. 7 3 - Once this is out of staging this should no longer be a separate 8 4 config option, instead it should be selected by drivers that want it. 9 5 - Revisit the IS_REACHABLE(RC_CORE): perhaps the RC_CORE support should
+30 -1
drivers/staging/media/cec/cec-adap.c
··· 1233 1233 mutex_unlock(&adap->lock); 1234 1234 1235 1235 for (i = 0; i < las->num_log_addrs; i++) { 1236 - if (las->log_addr[i] == CEC_LOG_ADDR_INVALID) 1236 + if (las->log_addr[i] == CEC_LOG_ADDR_INVALID || 1237 + (las->flags & CEC_LOG_ADDRS_FL_CDC_ONLY)) 1237 1238 continue; 1238 1239 1239 1240 /* ··· 1354 1353 adap->log_addrs.num_log_addrs = 0; 1355 1354 cec_adap_unconfigure(adap); 1356 1355 return 0; 1356 + } 1357 + 1358 + if (log_addrs->flags & CEC_LOG_ADDRS_FL_CDC_ONLY) { 1359 + /* 1360 + * Sanitize log_addrs fields if a CDC-Only device is 1361 + * requested. 1362 + */ 1363 + log_addrs->num_log_addrs = 1; 1364 + log_addrs->osd_name[0] = '\0'; 1365 + log_addrs->vendor_id = CEC_VENDOR_ID_NONE; 1366 + log_addrs->log_addr_type[0] = CEC_LOG_ADDR_TYPE_UNREGISTERED; 1367 + /* 1368 + * This is just an internal convention since a CDC-Only device 1369 + * doesn't have to be a switch. But switches already use 1370 + * unregistered, so it makes some kind of sense to pick this 1371 + * as the primary device. Since a CDC-Only device never sends 1372 + * any 'normal' CEC messages this primary device type is never 1373 + * sent over the CEC bus. 1374 + */ 1375 + log_addrs->primary_device_type[0] = CEC_OP_PRIM_DEVTYPE_SWITCH; 1376 + log_addrs->all_device_types[0] = 0; 1377 + log_addrs->features[0][0] = 0; 1378 + log_addrs->features[0][1] = 0; 1357 1379 } 1358 1380 1359 1381 /* Ensure the osd name is 0-terminated */ ··· 1598 1574 struct cec_msg tx_cec_msg = { }; 1599 1575 1600 1576 dprintk(1, "cec_receive_notify: %*ph\n", msg->len, msg->msg); 1577 + 1578 + /* If this is a CDC-Only device, then ignore any non-CDC messages */ 1579 + if (cec_is_cdc_only(&adap->log_addrs) && 1580 + msg->msg[1] != CEC_MSG_CDC_MESSAGE) 1581 + return 0; 1601 1582 1602 1583 if (adap->ops->received) { 1603 1584 /* Allow drivers to process the message first */
+8 -1
drivers/staging/media/cec/cec-api.c
··· 163 163 if (copy_from_user(&log_addrs, parg, sizeof(log_addrs))) 164 164 return -EFAULT; 165 165 log_addrs.flags &= CEC_LOG_ADDRS_FL_ALLOW_UNREG_FALLBACK | 166 - CEC_LOG_ADDRS_FL_ALLOW_RC_PASSTHRU; 166 + CEC_LOG_ADDRS_FL_ALLOW_RC_PASSTHRU | 167 + CEC_LOG_ADDRS_FL_CDC_ONLY; 167 168 mutex_lock(&adap->lock); 168 169 if (!adap->is_configuring && 169 170 (!log_addrs.num_log_addrs || !adap->is_configured) && ··· 191 190 return -ENOTTY; 192 191 if (copy_from_user(&msg, parg, sizeof(msg))) 193 192 return -EFAULT; 193 + 194 + /* A CDC-Only device can only send CDC messages */ 195 + if ((adap->log_addrs.flags & CEC_LOG_ADDRS_FL_CDC_ONLY) && 196 + (msg.len == 1 || msg.msg[1] != CEC_MSG_CDC_MESSAGE)) 197 + return -EINVAL; 198 + 194 199 msg.flags &= CEC_MSG_FL_REPLY_TO_FOLLOWERS; 195 200 mutex_lock(&adap->lock); 196 201 if (!adap->is_configured)
+52
include/linux/cec.h
··· 396 396 #define CEC_LOG_ADDRS_FL_ALLOW_UNREG_FALLBACK (1 << 0) 397 397 /* Passthrough RC messages to the input subsystem */ 398 398 #define CEC_LOG_ADDRS_FL_ALLOW_RC_PASSTHRU (1 << 1) 399 + /* CDC-Only device: supports only CDC messages */ 400 + #define CEC_LOG_ADDRS_FL_CDC_ONLY (1 << 2) 399 401 400 402 /* Events */ 401 403 ··· 1017 1015 #define CEC_OP_HPD_ERROR_INITIATOR_WRONG_STATE 2 1018 1016 #define CEC_OP_HPD_ERROR_OTHER 3 1019 1017 #define CEC_OP_HPD_ERROR_NONE_NO_VIDEO 4 1018 + 1019 + /* End of Messages */ 1020 + 1021 + /* Helper functions to identify the 'special' CEC devices */ 1022 + 1023 + static inline bool cec_is_2nd_tv(const struct cec_log_addrs *las) 1024 + { 1025 + /* 1026 + * It is a second TV if the logical address is 14 or 15 and the 1027 + * primary device type is a TV. 1028 + */ 1029 + return las->num_log_addrs && 1030 + las->log_addr[0] >= CEC_LOG_ADDR_SPECIFIC && 1031 + las->primary_device_type[0] == CEC_OP_PRIM_DEVTYPE_TV; 1032 + } 1033 + 1034 + static inline bool cec_is_processor(const struct cec_log_addrs *las) 1035 + { 1036 + /* 1037 + * It is a processor if the logical address is 12-15 and the 1038 + * primary device type is a Processor. 1039 + */ 1040 + return las->num_log_addrs && 1041 + las->log_addr[0] >= CEC_LOG_ADDR_BACKUP_1 && 1042 + las->primary_device_type[0] == CEC_OP_PRIM_DEVTYPE_PROCESSOR; 1043 + } 1044 + 1045 + static inline bool cec_is_switch(const struct cec_log_addrs *las) 1046 + { 1047 + /* 1048 + * It is a switch if the logical address is 15 and the 1049 + * primary device type is a Switch and the CDC-Only flag is not set. 1050 + */ 1051 + return las->num_log_addrs == 1 && 1052 + las->log_addr[0] == CEC_LOG_ADDR_UNREGISTERED && 1053 + las->primary_device_type[0] == CEC_OP_PRIM_DEVTYPE_SWITCH && 1054 + !(las->flags & CEC_LOG_ADDRS_FL_CDC_ONLY); 1055 + } 1056 + 1057 + static inline bool cec_is_cdc_only(const struct cec_log_addrs *las) 1058 + { 1059 + /* 1060 + * It is a CDC-only device if the logical address is 15 and the 1061 + * primary device type is a Switch and the CDC-Only flag is set. 1062 + */ 1063 + return las->num_log_addrs == 1 && 1064 + las->log_addr[0] == CEC_LOG_ADDR_UNREGISTERED && 1065 + las->primary_device_type[0] == CEC_OP_PRIM_DEVTYPE_SWITCH && 1066 + (las->flags & CEC_LOG_ADDRS_FL_CDC_ONLY); 1067 + } 1020 1068 1021 1069 #endif