diff options
author | Chanwoo Choi <cw00.choi@samsung.com> | 2021-03-12 17:08:31 +0900 |
---|---|---|
committer | Chanwoo Choi <cw00.choi@samsung.com> | 2022-06-06 15:03:46 +0900 |
commit | f0ddda961c6b76730445f886748eb069bdba8edf (patch) | |
tree | adcff01798e9add107cb4414039fe580d7b43f7a | |
parent | f2906aa863381afb0015a9eb7fefad885d4e5a56 (diff) | |
download | extcon-testing.tar.gz |
extcon: Add support of multiple external connector on a deviceextcon-testing
TODO
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
-rw-r--r-- | drivers/extcon/extcon.c | 14 | ||||
-rw-r--r-- | drivers/extcon/extcon.h | 5 | ||||
-rw-r--r-- | include/linux/extcon-provider.h | 61 | ||||
-rw-r--r-- | include/linux/extcon.h | 74 |
4 files changed, 152 insertions, 2 deletions
diff --git a/drivers/extcon/extcon.c b/drivers/extcon/extcon.c index d3a32b8064994..b03ccd7ee3992 100644 --- a/drivers/extcon/extcon.c +++ b/drivers/extcon/extcon.c @@ -192,6 +192,8 @@ static const struct __extcon_info { * struct extcon_cable - An internal data for an external connector. * @edev: the extcon device * @cable_index: the index of this cable in the edev + * @devnum: the devnum of this cable among the same connector type + * in the edev * @attr_g: the attribute group for the cable * @attr_name: "name" sysfs entry * @attr_state: "state" sysfs entry @@ -200,6 +202,7 @@ static const struct __extcon_info { struct extcon_cable { struct extcon_dev *edev; int cable_index; + int devnum; struct attribute_group attr_g; struct device_attribute attr_name; @@ -1075,7 +1078,7 @@ EXPORT_SYMBOL_GPL(extcon_dev_free); */ int extcon_dev_register(struct extcon_dev *edev) { - int ret, index = 0; + int ret, id, index = 0; static atomic_t edev_no = ATOMIC_INIT(-1); if (!extcon_class) { @@ -1087,7 +1090,11 @@ int extcon_dev_register(struct extcon_dev *edev) if (!edev || !edev->supported_cable) return -EINVAL; - for (; edev->supported_cable[index] != EXTCON_NONE; index++); + for (; edev->supported_cable[index] != EXTCON_NONE; index++) { + id = edev->supported_cable[index]; + if (id < 0 || id >= EXTCON_NUM || extcon_info[id].type == EXTCON_NONE) + return -EINVAL; + } edev->max_supported = index; if (index > SUPPORTED_CABLE_MAX) { @@ -1120,7 +1127,10 @@ int extcon_dev_register(struct extcon_dev *edev) goto err_sysfs_alloc; } for (index = 0; index < edev->max_supported; index++) { + id = edev->supported_cable[index]; + cable = &edev->cables[index]; + cable->devnum = edev->max_supported_type[id]++; str = kasprintf(GFP_KERNEL, "cable.%d", index); if (!str) { diff --git a/drivers/extcon/extcon.h b/drivers/extcon/extcon.h index 93b5e0306966d..385aed3726321 100644 --- a/drivers/extcon/extcon.h +++ b/drivers/extcon/extcon.h @@ -24,11 +24,14 @@ * register-time. * @nh_all: Notifier for the state change events for all supported * external connectors from this extcon. + * @nh_type: Notifier for the state change events for specific type + * among supported external connectors from this extcon. * @nh: Notifier for the state change events from this extcon * @entry: To support list of extcon devices so that users can * search for extcon devices based on the extcon name. * @lock: * @max_supported: Internal value to store the number of cables. + * @max_supported_type: Internal value to store the number of cable types. * @extcon_dev_type: Device_type struct to provide attribute_groups * customized for each extcon device. * @cables: Sysfs subdirectories. Each represents one cable. @@ -47,9 +50,11 @@ struct extcon_dev { /* Internal data. Please do not set. */ struct device dev; struct raw_notifier_head nh_all; + struct raw_notifier_head *nh_type; struct raw_notifier_head *nh; struct list_head entry; int max_supported; + int max_supported_type[EXTCON_NUM]; spinlock_t lock; /* could be called by irq handler */ u32 state; diff --git a/include/linux/extcon-provider.h b/include/linux/extcon-provider.h index fa70945f4e6b8..d548d232ab6c7 100644 --- a/include/linux/extcon-provider.h +++ b/include/linux/extcon-provider.h @@ -33,6 +33,8 @@ void devm_extcon_dev_free(struct device *dev, struct extcon_dev *edev); /* Synchronize the state and property value for each external connector. */ int extcon_sync(struct extcon_dev *edev, unsigned int id); +int extcon_sync_with_devnum(struct extcon_dev *edev, unsigned int id, + unsigned int devnum); /* * Following APIs set the connected state of each external connector. @@ -42,6 +44,10 @@ int extcon_set_state(struct extcon_dev *edev, unsigned int id, bool state); int extcon_set_state_sync(struct extcon_dev *edev, unsigned int id, bool state); +int extcon_set_state_with_devnum(struct extcon_dev *edev, unsigned int id, + unsigned int devnum, bool state); +int extcon_set_state_sync_devnum(struct extcon_dev *edev, unsigned int id, + unsigned int devnum, bool state); /* * Following APIs set the property of each external connector. @@ -60,6 +66,17 @@ int extcon_set_property_sync(struct extcon_dev *edev, unsigned int id, union extcon_property_value prop_val); int extcon_set_property_capability(struct extcon_dev *edev, unsigned int id, unsigned int prop); +int extcon_set_property_with_devnum(struct extcon_dev *edev, unsigned int id, + unsigned int devnum, + unsigned int prop, + union extcon_property_value prop_val); +int extcon_set_property_sync_devnum(struct extcon_dev *edev, unsigned int id, + unsigned int devnum, + unsigned int prop, + union extcon_property_value prop_val); +int extcon_set_property_capability_devnum(struct extcon_dev *edev, + unsigned int devnum, + unsigned int id, unsigned int prop); #else /* CONFIG_EXTCON */ static inline int extcon_dev_register(struct extcon_dev *edev) @@ -106,11 +123,31 @@ static inline int extcon_set_state_sync(struct extcon_dev *edev, unsigned int id return 0; } +static inline int extcon_set_state_with_devnum(struct extcon_dev *edev, + unsigned int id, unsigned int devnum, + bool state) +{ + return 0; +} + +static inline int extcon_set_state_sync_devnum(struct extcon_dev *edev, + unsigned int id, unsigned int devnum, + bool state) +{ + return 0; +} + static inline int extcon_sync(struct extcon_dev *edev, unsigned int id) { return 0; } +static inline int extcon_sync_with_devnum(struct extcon_dev *edev, + unsigned int id, unsigned int devnum) +{ + return 0; +} + static inline int extcon_set_property(struct extcon_dev *edev, unsigned int id, unsigned int prop, union extcon_property_value prop_val) @@ -130,5 +167,29 @@ static inline int extcon_set_property_capability(struct extcon_dev *edev, { return 0; } + +static inline int extcon_set_property_with_devnum(struct extcon_dev *edev, + unsigned int id, unsigned int devnum, + unsigned int prop, + union extcon_property_value prop_val) +{ + return 0; +} + +static inline int extcon_set_property_sync_devnum(struct extcon_dev *edev, + unsigned int id, unsigned int devnum, + unsigned int prop, + union extcon_property_value prop_val) +{ + return 0; +} + +static inline int extcon_set_property_capability_devnum(struct extcon_dev *edev, + unsigned int id, unsigned int devnum, + unsigned int prop) +{ + return 0; +} + #endif /* CONFIG_EXTCON */ #endif /* __LINUX_EXTCON_PROVIDER_H__ */ diff --git a/include/linux/extcon.h b/include/linux/extcon.h index 685401d94d398..ddfcfc8c80ced 100644 --- a/include/linux/extcon.h +++ b/include/linux/extcon.h @@ -171,6 +171,8 @@ struct extcon_dev; * The 'id' argument indicates the defined external connector. */ int extcon_get_state(struct extcon_dev *edev, unsigned int id); +int extcon_get_state_with_devnum(struct extcon_dev *edev, unsigned int id, + unsigned int devnum); /* * Following APIs get the property of each external connector. @@ -186,6 +188,17 @@ int extcon_get_property(struct extcon_dev *edev, unsigned int id, union extcon_property_value *prop_val); int extcon_get_property_capability(struct extcon_dev *edev, unsigned int id, unsigned int prop); +int extcon_get_property_with_devnum(struct extcon_dev *edev, unsigned int id, + unsigned int devnum, + unsigned int prop, + union extcon_property_value *prop_val); +int extcon_get_property_capability_with_devnum(struct extcon_dev *edev, + unsigned int devnum, + unsigned int id, unsigned int prop); + +/* TODO */ +int extcon_is_supported(struct extcon_dev *edev, unsigned int id); +int extcon_get_dev_count(struct extcon_dev *edev, unsigned int id); /* * Following APIs register the notifier block in order to detect @@ -206,6 +219,22 @@ int devm_extcon_register_notifier(struct device *dev, void devm_extcon_unregister_notifier(struct device *dev, struct extcon_dev *edev, unsigned int id, struct notifier_block *nb); +int extcon_register_notifier_with_devnum(struct extcon_dev *edev, + unsigned int id, + unsigned int devnum, + struct notifier_block *nb); +int extcon_unregister_notifier_with_devnum(struct extcon_dev *edev, + unsigned int id, + unsigned int devnum, + struct notifier_block *nb); +int devm_extcon_register_notifier_with_devnum(struct device *dev, + struct extcon_dev *edev, unsigned int id, + unsigned int devnum, + struct notifier_block *nb); +void devm_extcon_unregister_notifier_with_devnum(struct device *dev, + struct extcon_dev *edev, unsigned int id, + unsigned int devnum, + struct notifier_block *nb); int extcon_register_notifier_all(struct extcon_dev *edev, struct notifier_block *nb); @@ -235,6 +264,13 @@ static inline int extcon_get_state(struct extcon_dev *edev, unsigned int id) return 0; } +static inline int extcon_get_state_with_devnum(struct extcon_dev *edev, + unsigned int id, + unsigned int devnum) +{ + return 0; +} + static inline int extcon_get_property(struct extcon_dev *edev, unsigned int id, unsigned int prop, union extcon_property_value *prop_val) @@ -248,6 +284,24 @@ static inline int extcon_get_property_capability(struct extcon_dev *edev, return 0; } +static inline int extcon_get_property_with_devnum(struct extcon_dev *edev, + unsigned int id, + unsigned int devnum, + unsigned int prop, + union extcon_property_value *prop_val) +{ + return 0; +} + +static inline int extcon_get_property_capability_with_devnum( + struct extcon_dev *edev, + unsigned int devnum, + unsigned int id, + unsigned int prop) +{ + return 0; +} + static inline int extcon_register_notifier(struct extcon_dev *edev, unsigned int id, struct notifier_block *nb) { @@ -271,6 +325,26 @@ static inline void devm_extcon_unregister_notifier(struct device *dev, struct extcon_dev *edev, unsigned int id, struct notifier_block *nb) { } +static inline int extcon_register_notifier_with_devnum(struct extcon_dev *edev, + unsigned int id, + unsigned int devnum, + struct notifier_block *nb) { return 0; } + +static inline int extcon_unregister_notifier_with_devnum(struct extcon_dev *edev, + unsigned int id, + unsigned int devnum, + struct notifier_block *nb) { return 0; } + +static inline int devm_extcon_register_notifier_with_devnum(struct device *dev, + struct extcon_dev *edev, unsigned int id, + unsigned int devnum, + struct notifier_block *nb) { return 0; } + +static inline void devm_extcon_unregister_notifier_with_devnum(struct device *dev, + struct extcon_dev *edev, unsigned int id, + unsigned int devnum, + struct notifier_block *nb) { } + static inline int extcon_register_notifier_all(struct extcon_dev *edev, struct notifier_block *nb) { |