On Sun, Jul 31, 2016 at 10:50 PM, Chanwoo Choi <cw00.c...@samsung.com> 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.c...@samsung.com> > Tested-by: Chris Zhong <z...@rock-chips.com>
Reviewed-by: Guenter Roeck <gro...@chromium.org> > --- > 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 >