Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 304039
b: refs/heads/master
c: 74c5d09
h: refs/heads/master
i:
  304037: 1d729bf
  304035: e8f0491
  304031: 62ca5b3
v: v3
  • Loading branch information
Donggeun Kim authored and Greg Kroah-Hartman committed Apr 20, 2012
1 parent 023ee4d commit fc8bf62
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: be48308a24c7651bf968b561dbd590edb8166d62
refs/heads/master: 74c5d09bd562edc220d6e076b8f1e118819c178f
66 changes: 66 additions & 0 deletions trunk/drivers/extcon/extcon_class.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ struct class *extcon_class;
static struct class_compat *switch_class;
#endif /* CONFIG_ANDROID && !defined(CONFIG_ANDROID_SWITCH) */

static LIST_HEAD(extcon_dev_list);
static DEFINE_MUTEX(extcon_dev_list_lock);

static ssize_t state_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
Expand Down Expand Up @@ -75,6 +78,9 @@ static ssize_t name_show(struct device *dev, struct device_attribute *attr,
* the name of extcon device (envp[0]) and the state output (envp[1]).
* Tizen uses this format for extcon device to get events from ports.
* Android uses this format as well.
*
* Note that notifier provides the which bits are changes in the state
* variable with "val" to the callback.
*/
void extcon_set_state(struct extcon_dev *edev, u32 state)
{
Expand All @@ -84,10 +90,14 @@ void extcon_set_state(struct extcon_dev *edev, u32 state)
char *envp[3];
int env_offset = 0;
int length;
u32 old_state = edev->state;

if (edev->state != state) {
edev->state = state;

raw_notifier_call_chain(&edev->nh, old_state ^ edev->state,
edev);

prop_buf = (char *)get_zeroed_page(GFP_KERNEL);
if (prop_buf) {
length = name_show(edev->dev, NULL, prop_buf);
Expand Down Expand Up @@ -117,6 +127,51 @@ void extcon_set_state(struct extcon_dev *edev, u32 state)
}
EXPORT_SYMBOL_GPL(extcon_set_state);

/**
* extcon_get_extcon_dev() - Get the extcon device instance from the name
* @extcon_name: The extcon name provided with extcon_dev_register()
*/
struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name)
{
struct extcon_dev *sd;

mutex_lock(&extcon_dev_list_lock);
list_for_each_entry(sd, &extcon_dev_list, entry) {
if (!strcmp(sd->name, extcon_name))
goto out;
}
sd = NULL;
out:
mutex_unlock(&extcon_dev_list_lock);
return sd;
}
EXPORT_SYMBOL_GPL(extcon_get_extcon_dev);

/**
* extcon_register_notifier() - Register a notifee to get notified by
* any attach status changes from the extcon.
* @edev: the extcon device.
* @nb: a notifier block to be registered.
*/
int extcon_register_notifier(struct extcon_dev *edev,
struct notifier_block *nb)
{
return raw_notifier_chain_register(&edev->nh, nb);
}
EXPORT_SYMBOL_GPL(extcon_register_notifier);

/**
* extcon_unregister_notifier() - Unregister a notifee from the extcon device.
* @edev: the extcon device.
* @nb: a registered notifier block to be unregistered.
*/
int extcon_unregister_notifier(struct extcon_dev *edev,
struct notifier_block *nb)
{
return raw_notifier_chain_unregister(&edev->nh, nb);
}
EXPORT_SYMBOL_GPL(extcon_unregister_notifier);

static struct device_attribute extcon_attrs[] = {
__ATTR_RO(state),
__ATTR_RO(name),
Expand All @@ -142,6 +197,10 @@ static int create_extcon_class(void)

static void extcon_cleanup(struct extcon_dev *edev, bool skip)
{
mutex_lock(&extcon_dev_list_lock);
list_del(&edev->entry);
mutex_unlock(&extcon_dev_list_lock);

if (!skip && get_device(edev->dev)) {
device_unregister(edev->dev);
put_device(edev->dev);
Expand Down Expand Up @@ -194,8 +253,15 @@ int extcon_dev_register(struct extcon_dev *edev, struct device *dev)
dev);
#endif /* CONFIG_ANDROID && !defined(CONFIG_ANDROID_SWITCH) */

RAW_INIT_NOTIFIER_HEAD(&edev->nh);

dev_set_drvdata(edev->dev, edev);
edev->state = 0;

mutex_lock(&extcon_dev_list_lock);
list_add(&edev->entry, &extcon_dev_list);
mutex_unlock(&extcon_dev_list_lock);

return 0;

err_dev:
Expand Down
38 changes: 38 additions & 0 deletions trunk/include/linux/extcon.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#ifndef __LINUX_EXTCON_H__
#define __LINUX_EXTCON_H__

#include <linux/notifier.h>
/**
* struct extcon_dev - An extcon device represents one external connector.
* @name The name of this extcon device. Parent device name is used
Expand All @@ -34,6 +35,9 @@
* @dev Device of this extcon. Do not provide at register-time.
* @state Attach/detach state of this extcon. Do not provide at
* register-time
* @nh Notifier for the state change events from this extcon
* @entry To support list of extcon devices so that uses can search
* for extcon devices based on the extcon name.
*
* In most cases, users only need to provide "User initializing data" of
* this struct when registering an extcon. In some exceptional cases,
Expand All @@ -51,18 +55,35 @@ struct extcon_dev {
/* --- Internal data. Please do not set. --- */
struct device *dev;
u32 state;
struct raw_notifier_head nh;
struct list_head entry;
};

#if IS_ENABLED(CONFIG_EXTCON)

/*
* Following APIs are for notifiers or configurations.
* Notifiers are the external port and connection devices.
*/
extern int extcon_dev_register(struct extcon_dev *edev, struct device *dev);
extern void extcon_dev_unregister(struct extcon_dev *edev);
extern struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name);

static inline u32 extcon_get_state(struct extcon_dev *edev)
{
return edev->state;
}

extern void extcon_set_state(struct extcon_dev *edev, u32 state);

/*
* Following APIs are to monitor every action of a notifier.
* Registerer gets notified for every external port of a connection device.
*/
extern int extcon_register_notifier(struct extcon_dev *edev,
struct notifier_block *nb);
extern int extcon_unregister_notifier(struct extcon_dev *edev,
struct notifier_block *nb);
#else /* CONFIG_EXTCON */
static inline int extcon_dev_register(struct extcon_dev *edev,
struct device *dev)
Expand All @@ -78,5 +99,22 @@ static inline u32 extcon_get_state(struct extcon_dev *edev)
}

static inline void extcon_set_state(struct extcon_dev *edev, u32 state) { }
static inline struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name)
{
return NULL;
}

static inline int extcon_register_notifier(struct extcon_dev *edev,
struct notifier_block *nb)
{
return 0;
}

static inline int extcon_unregister_notifier(struct extcon_dev *edev,
struct notifier_block *nb)
{
return 0;
}

#endif /* CONFIG_EXTCON */
#endif /* __LINUX_EXTCON_H__ */

0 comments on commit fc8bf62

Please sign in to comment.