Re: [PATCH v2 3/6] extcon: Add the support for the capability of each property

From: Guenter Roeck
Date: Mon Aug 01 2016 - 15:51:00 EST


On Sun, Jul 31, 2016 at 10:50 PM, Chanwoo Choi <cw00.choi@xxxxxxxxxxx> 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>

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 4027aee08ce5..10b201b161ac 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)];
> };
>
> 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);
> + 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
> + */
> +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. */
> + 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 5a97e52abefb..80b740d81b1f 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;
> --
> 1.9.1
>