Re: [PATCH v3 3/6] extcon: Add the support for the capability of each property
From: Roger Quadros
Date: Tue Aug 02 2016 - 04:14:30 EST
Hi,
On 02/08/16 04:58, Chanwoo Choi wrote:
> This patch adds the support of the property capability setting. This function
> decides the supported properties of each external connector on extcon provider
> driver.
>
> Ths list of new extcon APIs to get/set the capability of property as following:
> - int extcon_get_property_capability(struct extcon_dev *edev,
> unsigned int id, unsigned int prop);
> - int extcon_set_property_capability(struct extcon_dev *edev,
> unsigned int id, unsigned int prop);
>
> Signed-off-by: Chanwoo Choi <cw00.choi@xxxxxxxxxxx>
> Tested-by: Chris Zhong <zyw@xxxxxxxxxxxxxx>
> Tested-by: Guenter Roeck <groeck@xxxxxxxxxxxx>
> Reviewed-by: Guenter Roeck <groeck@xxxxxxxxxxxx>
> ---
> drivers/extcon/extcon.c | 141 ++++++++++++++++++++++++++++++++++++++++++++++++
> include/linux/extcon.h | 22 ++++++++
> 2 files changed, 163 insertions(+)
>
> diff --git a/drivers/extcon/extcon.c b/drivers/extcon/extcon.c
> index bb6e99fe84c8..7ae0771f29e7 100644
> --- a/drivers/extcon/extcon.c
> +++ b/drivers/extcon/extcon.c
> @@ -201,6 +201,11 @@ struct extcon_cable {
> union extcon_property_value chg_propval[EXTCON_PROP_CHG_CNT];
> union extcon_property_value jack_propval[EXTCON_PROP_JACK_CNT];
> union extcon_property_value disp_propval[EXTCON_PROP_DISP_CNT];
> +
> + unsigned long usb_bits[BITS_TO_LONGS(EXTCON_PROP_USB_CNT)];
> + unsigned long chg_bits[BITS_TO_LONGS(EXTCON_PROP_CHG_CNT)];
> + unsigned long jack_bits[BITS_TO_LONGS(EXTCON_PROP_JACK_CNT)];
> + unsigned long disp_bits[BITS_TO_LONGS(EXTCON_PROP_DISP_CNT)];
This can be replaced by a single
unsigned long cap_bits;
As different type cables have separate extcon_cable instances.
> };
>
> static struct class *extcon_class;
> @@ -297,6 +302,39 @@ static bool is_extcon_property_supported(unsigned int id, unsigned int prop)
> return !!(extcon_info[id].type & type);
> }
>
> +static int is_extcon_property_capability(struct extcon_dev *edev,
> + unsigned int id, int index,unsigned int prop)
> +{
> + struct extcon_cable *cable;
> + int type, ret;
> +
> + /* Check whether the property is supported or not. */
> + type = get_extcon_type(prop);
> + if (type < 0)
> + return type;
> +
> + cable = &edev->cables[index];
> +
> + switch (type) {
> + case EXTCON_TYPE_USB:
> + ret = test_bit(prop - EXTCON_PROP_USB_MIN, cable->usb_bits);
ret = test_bit(prop, cable->cap_bits);
> + break;
> + case EXTCON_TYPE_CHG:
> + ret = test_bit(prop - EXTCON_PROP_CHG_MIN, cable->chg_bits);
> + break;
> + case EXTCON_TYPE_JACK:
> + ret = test_bit(prop - EXTCON_PROP_JACK_MIN, cable->jack_bits);
> + break;
> + case EXTCON_TYPE_DISP:
> + ret = test_bit(prop - EXTCON_PROP_DISP_MIN, cable->disp_bits);
> + break;
> + default:
> + ret = -EINVAL;
> + }
> +
> + return ret;
> +}
> +
> static void init_property(struct extcon_dev *edev, unsigned int id, int index)
> {
> unsigned int type = extcon_info[id].type;
> @@ -554,6 +592,12 @@ int extcon_get_property(struct extcon_dev *edev, unsigned int id,
>
> spin_lock_irqsave(&edev->lock, flags);
>
> + /* Check whether the property is available or not. */
> + if (!is_extcon_property_capability(edev, id, index, prop)) {
> + spin_unlock_irqrestore(&edev->lock, flags);
> + return -EPERM;
> + }
> +
> /*
> * Check whether the external connector is attached.
> * If external connector is detached, the user can not
> @@ -626,6 +670,12 @@ int extcon_set_property(struct extcon_dev *edev, unsigned int id,
>
> spin_lock_irqsave(&edev->lock, flags);
>
> + /* Check whether the property is available or not. */
> + if (!is_extcon_property_capability(edev, id, index, prop)) {
> + spin_unlock_irqrestore(&edev->lock, flags);
> + return -EPERM;
> + }
> +
> cable = &edev->cables[index];
>
> /* Set the property value according to extcon type */
> @@ -654,6 +704,97 @@ int extcon_set_property(struct extcon_dev *edev, unsigned int id,
> EXPORT_SYMBOL_GPL(extcon_set_property);
>
> /**
> + * extcon_get_property_capability() - Get the capability of property
> + * of an external connector.
> + * @edev: the extcon device that has the cable.
> + * @id: the unique id of each external connector
> + * in extcon enumeration.
> + * @prop: the property id among enum extcon_property.
> + *
> + * Returns 1 if the property is available or 0 if not available.
> + */
> +int extcon_get_property_capability(struct extcon_dev *edev, unsigned int id,
> + unsigned int prop)
> +{
> + int index;
> +
> + if (!edev)
> + return -EINVAL;
> +
> + /* Check whether the property is supported or not */
> + if (!is_extcon_property_supported(id, prop))
> + return -EINVAL;
> +
> + /* Find the cable index of external connector by using id */
> + index = find_cable_index_by_id(edev, id);
> + if (index < 0)
> + return index;
> +
> + return is_extcon_property_capability(edev, id, index, prop);
> +}
> +EXPORT_SYMBOL_GPL(extcon_get_property_capability);
> +
> +/**
> + * extcon_set_property_capability() - Set the capability of a property
> + * of an external connector.
> + * @edev: the extcon device that has the cable.
> + * @id: the unique id of each external connector
> + * in extcon enumeration.
> + * @prop: the property id among enum extcon_property.
> + *
> + * This function set the capability of a property for an external connector
> + * to mark the bit in capability bitmap which mean the available state of
> + * a property.
> + *
> + * Returns 0 if success or error number if fail
> + */
So extcon drivers must explicitly enable all properties?
Isn't this an unnecessary step? Why can't all properties by supported by default.
If the hardware doesn't generate that property, the driver will just not toggle it.
Can you please give an example why this won't work?
> +int extcon_set_property_capability(struct extcon_dev *edev, unsigned int id,
> + unsigned int prop)
> +{
> + struct extcon_cable *cable;
> + int index, type, ret = 0;
> +
> + if (!edev)
> + return -EINVAL;
> +
> + /* Check whether the property is supported or not. */
> + if (!is_extcon_property_supported(id, prop))
> + return -EINVAL;
> +
> + /* Find the cable index of external connector by using id. */
> + index = find_cable_index_by_id(edev, id);
> + if (index < 0)
> + return index;
> +
> + /* Check whether the property is supported or not. */
Again? we've already checked whether property is supported or not.
> + type = get_extcon_type(prop);
> + if (type < 0)
> + return type;
> +
> + cable = &edev->cables[index];
> +
> + switch (type) {
> + case EXTCON_TYPE_USB:
> + __set_bit(prop - EXTCON_PROP_USB_MIN, cable->usb_bits);
> + break;
> + case EXTCON_TYPE_CHG:
> + __set_bit(prop - EXTCON_PROP_CHG_MIN, cable->chg_bits);
> + break;
> + case EXTCON_TYPE_JACK:
> + __set_bit(prop - EXTCON_PROP_JACK_MIN, cable->jack_bits);
> + break;
> + case EXTCON_TYPE_DISP:
> + __set_bit(prop - EXTCON_PROP_DISP_MIN, cable->disp_bits);
> + break;
> + default:
> + ret = -EINVAL;
> + }
> +
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(extcon_set_property_capability);
> +
> +/**
> * extcon_get_extcon_dev() - Get the extcon device instance from the name
> * @extcon_name: The extcon name provided with extcon_dev_register()
> */
> diff --git a/include/linux/extcon.h b/include/linux/extcon.h
> index fe583fca7732..ffd32a8975d5 100644
> --- a/include/linux/extcon.h
> +++ b/include/linux/extcon.h
> @@ -240,6 +240,16 @@ extern int extcon_set_property(struct extcon_dev *edev, unsigned int id,
> union extcon_property_value prop_val);
>
> /*
> + * get/set_property_capability set the capability of the property for each
> + * external connector. They are used to set the capability of the property
> + * of each external connector based on the id and property.
> + */
> +extern int extcon_get_property_capability(struct extcon_dev *edev,
> + unsigned int id, unsigned int prop);
> +extern int extcon_set_property_capability(struct extcon_dev *edev,
> + unsigned int id, unsigned int prop);
> +
> +/*
> * Following APIs are to monitor every action of a notifier.
> * Registrar gets notified for every external port of a connection device.
> * Probably this could be used to debug an action of notifier; however,
> @@ -325,6 +335,18 @@ static inline int extcon_set_property(struct extcon_dev *edev, unsigned int id,
> return 0;
> }
>
> +static inline int extcon_get_property_capability(struct extcon_dev *edev,
> + unsigned int id, unsigned int prop)
> +{
> + return 0;
> +}
> +
> +static inline int extcon_set_property_capability(struct extcon_dev *edev,
> + unsigned int id, unsigned int prop)
> +{
> + return 0;
> +}
> +
> static inline struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name)
> {
> return NULL;
>