diff options
| author | MyungJoo Ham <myungjoo.ham@samsung.com> | 2012-04-20 01:16:22 -0400 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-04-20 12:21:11 -0400 |
| commit | de55d8716ac50a356cea736c29bb7db5ac3d0190 (patch) | |
| tree | d63f799c7859c97ee7089609bd183d28ca63e2bf | |
| parent | 7cd9c9bb57476167e83b7780dbc06d1dd601789d (diff) | |
Extcon (external connector): import Android's switch class and modify.
External connector class (extcon) is based on and an extension of
Android kernel's switch class located at linux/drivers/switch/.
This patch provides the before-extension switch class moved to the
location where the extcon will be located (linux/drivers/extcon/) and
updates to handle class properly.
The before-extension class, switch class of Android kernel, commits
imported are:
switch: switch class and GPIO drivers. (splitted)
Author: Mike Lockwood <lockwood@android.com>
switch: Use device_create instead of device_create_drvdata.
Author: Arve Hjønnevåg <arve@android.com>
In this patch, upon the commits of Android kernel, we have added:
- Relocated and renamed for extcon.
- Comments, module name, and author information are updated
- Code clean for successing patches
- Bugfix: enabling write access without write functions
- Class/device/sysfs create/remove handling
- Added comments about uevents
- Format changes for extcon_dev_register() to have a parent dev.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
--
Changes from v7
- Compiler error fixed when it is compiled as a module.
- Removed out-of-date Kconfig entry
Changes from v6
- Updated comment/strings
- Revised "Android-compatible" mode.
* Automatically activated if CONFIG_ANDROID && !CONFIG_ANDROID_SWITCH
* Creates /sys/class/switch/*, which is a copy of /sys/class/extcon/*
Changes from v5
- Split the patch
- Style fixes
- "Android-compatible" mode is enabled by Kconfig option.
Changes from v2
- Updated name_show
- Sysfs entries are handled by class itself.
- Updated the method to add/remove devices for the class
- Comments on uevent send
- Able to become a module
- Compatible with Android platform
Changes from RFC
- Renamed to extcon (external connector) from multistate switch
- Added a seperated directory (drivers/extcon)
- Added kerneldoc comments
- Removed unused variables from extcon_gpio.c
- Added ABI Documentation.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
| -rw-r--r-- | Documentation/ABI/testing/sysfs-class-extcon | 26 | ||||
| -rw-r--r-- | drivers/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/Makefile | 1 | ||||
| -rw-r--r-- | drivers/extcon/Kconfig | 17 | ||||
| -rw-r--r-- | drivers/extcon/Makefile | 5 | ||||
| -rw-r--r-- | drivers/extcon/extcon_class.c | 236 | ||||
| -rw-r--r-- | include/linux/extcon.h | 82 |
7 files changed, 369 insertions, 0 deletions
diff --git a/Documentation/ABI/testing/sysfs-class-extcon b/Documentation/ABI/testing/sysfs-class-extcon new file mode 100644 index 000000000000..59a4b1c708d5 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-class-extcon | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | What: /sys/class/extcon/.../ | ||
| 2 | Date: December 2011 | ||
| 3 | Contact: MyungJoo Ham <myungjoo.ham@samsung.com> | ||
| 4 | Description: | ||
| 5 | Provide a place in sysfs for the extcon objects. | ||
| 6 | This allows accessing extcon specific variables. | ||
| 7 | The name of extcon object denoted as ... is the name given | ||
| 8 | with extcon_dev_register. | ||
| 9 | |||
| 10 | What: /sys/class/extcon/.../name | ||
| 11 | Date: December 2011 | ||
| 12 | Contact: MyungJoo Ham <myungjoo.ham@samsung.com> | ||
| 13 | Description: | ||
| 14 | The /sys/class/extcon/.../name shows the name of the extcon | ||
| 15 | object. If the extcon object has an optional callback | ||
| 16 | "show_name" defined, the callback will provide the name with | ||
| 17 | this sysfs node. | ||
| 18 | |||
| 19 | What: /sys/class/extcon/.../state | ||
| 20 | Date: December 2011 | ||
| 21 | Contact: MyungJoo Ham <myungjoo.ham@samsung.com> | ||
| 22 | Description: | ||
| 23 | The /sys/class/extcon/.../state shows the cable attach/detach | ||
| 24 | information of the corresponding extcon object. If the extcon | ||
| 25 | objecct has an optional callback "show_state" defined, the | ||
| 26 | callback will provide the name with this sysfs node. | ||
diff --git a/drivers/Kconfig b/drivers/Kconfig index d236aef7e59f..0233ad979b7d 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig | |||
| @@ -140,4 +140,6 @@ source "drivers/virt/Kconfig" | |||
| 140 | 140 | ||
| 141 | source "drivers/devfreq/Kconfig" | 141 | source "drivers/devfreq/Kconfig" |
| 142 | 142 | ||
| 143 | source "drivers/extcon/Kconfig" | ||
| 144 | |||
| 143 | endmenu | 145 | endmenu |
diff --git a/drivers/Makefile b/drivers/Makefile index 95952c82bf16..c41dfa92cd79 100644 --- a/drivers/Makefile +++ b/drivers/Makefile | |||
| @@ -134,3 +134,4 @@ obj-$(CONFIG_VIRT_DRIVERS) += virt/ | |||
| 134 | obj-$(CONFIG_HYPERV) += hv/ | 134 | obj-$(CONFIG_HYPERV) += hv/ |
| 135 | 135 | ||
| 136 | obj-$(CONFIG_PM_DEVFREQ) += devfreq/ | 136 | obj-$(CONFIG_PM_DEVFREQ) += devfreq/ |
| 137 | obj-$(CONFIG_EXTCON) += extcon/ | ||
diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig new file mode 100644 index 000000000000..7932e1bd9b02 --- /dev/null +++ b/drivers/extcon/Kconfig | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | menuconfig EXTCON | ||
| 2 | tristate "External Connector Class (extcon) support" | ||
| 3 | help | ||
| 4 | Say Y here to enable external connector class (extcon) support. | ||
| 5 | This allows monitoring external connectors by userspace | ||
| 6 | via sysfs and uevent and supports external connectors with | ||
| 7 | multiple states; i.e., an extcon that may have multiple | ||
| 8 | cables attached. For example, an external connector of a device | ||
| 9 | may be used to connect an HDMI cable and a AC adaptor, and to | ||
| 10 | host USB ports. Many of 30-pin connectors including PDMI are | ||
| 11 | also good examples. | ||
| 12 | |||
| 13 | if EXTCON | ||
| 14 | |||
| 15 | comment "Extcon Device Drivers" | ||
| 16 | |||
| 17 | endif # MULTISTATE_SWITCH | ||
diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile new file mode 100644 index 000000000000..6bc69214fcd7 --- /dev/null +++ b/drivers/extcon/Makefile | |||
| @@ -0,0 +1,5 @@ | |||
| 1 | # | ||
| 2 | # Makefile for external connector class (extcon) devices | ||
| 3 | # | ||
| 4 | |||
| 5 | obj-$(CONFIG_EXTCON) += extcon_class.o | ||
diff --git a/drivers/extcon/extcon_class.c b/drivers/extcon/extcon_class.c new file mode 100644 index 000000000000..3c46368c279a --- /dev/null +++ b/drivers/extcon/extcon_class.c | |||
| @@ -0,0 +1,236 @@ | |||
| 1 | /* | ||
| 2 | * drivers/extcon/extcon_class.c | ||
| 3 | * | ||
| 4 | * External connector (extcon) class driver | ||
| 5 | * | ||
| 6 | * Copyright (C) 2012 Samsung Electronics | ||
| 7 | * Author: Donggeun Kim <dg77.kim@samsung.com> | ||
| 8 | * Author: MyungJoo Ham <myungjoo.ham@samsung.com> | ||
| 9 | * | ||
| 10 | * based on android/drivers/switch/switch_class.c | ||
| 11 | * Copyright (C) 2008 Google, Inc. | ||
| 12 | * Author: Mike Lockwood <lockwood@android.com> | ||
| 13 | * | ||
| 14 | * This software is licensed under the terms of the GNU General Public | ||
| 15 | * License version 2, as published by the Free Software Foundation, and | ||
| 16 | * may be copied, distributed, and modified under those terms. | ||
| 17 | * | ||
| 18 | * This program is distributed in the hope that it will be useful, | ||
| 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 21 | * GNU General Public License for more details. | ||
| 22 | * | ||
| 23 | */ | ||
| 24 | |||
| 25 | #include <linux/module.h> | ||
| 26 | #include <linux/types.h> | ||
| 27 | #include <linux/init.h> | ||
| 28 | #include <linux/device.h> | ||
| 29 | #include <linux/fs.h> | ||
| 30 | #include <linux/err.h> | ||
| 31 | #include <linux/extcon.h> | ||
| 32 | #include <linux/slab.h> | ||
| 33 | |||
| 34 | struct class *extcon_class; | ||
| 35 | #if defined(CONFIG_ANDROID) && !defined(CONFIG_ANDROID_SWITCH) | ||
| 36 | static struct class_compat *switch_class; | ||
| 37 | #endif /* CONFIG_ANDROID && !defined(CONFIG_ANDROID_SWITCH) */ | ||
| 38 | |||
| 39 | static ssize_t state_show(struct device *dev, struct device_attribute *attr, | ||
| 40 | char *buf) | ||
| 41 | { | ||
| 42 | struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev); | ||
| 43 | |||
| 44 | if (edev->print_state) { | ||
| 45 | int ret = edev->print_state(edev, buf); | ||
| 46 | |||
| 47 | if (ret >= 0) | ||
| 48 | return ret; | ||
| 49 | /* Use default if failed */ | ||
| 50 | } | ||
| 51 | return sprintf(buf, "%u\n", edev->state); | ||
| 52 | } | ||
| 53 | |||
| 54 | static ssize_t name_show(struct device *dev, struct device_attribute *attr, | ||
| 55 | char *buf) | ||
| 56 | { | ||
| 57 | struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev); | ||
| 58 | |||
| 59 | /* Optional callback given by the user */ | ||
| 60 | if (edev->print_name) { | ||
| 61 | int ret = edev->print_name(edev, buf); | ||
| 62 | if (ret >= 0) | ||
| 63 | return ret; | ||
| 64 | } | ||
| 65 | |||
| 66 | return sprintf(buf, "%s\n", dev_name(edev->dev)); | ||
| 67 | } | ||
| 68 | |||
| 69 | /** | ||
| 70 | * extcon_set_state() - Set the cable attach states of the extcon device. | ||
| 71 | * @edev: the extcon device | ||
| 72 | * @state: new cable attach status for @edev | ||
| 73 | * | ||
| 74 | * Changing the state sends uevent with environment variable containing | ||
| 75 | * the name of extcon device (envp[0]) and the state output (envp[1]). | ||
| 76 | * Tizen uses this format for extcon device to get events from ports. | ||
| 77 | * Android uses this format as well. | ||
| 78 | */ | ||
| 79 | void extcon_set_state(struct extcon_dev *edev, u32 state) | ||
| 80 | { | ||
| 81 | char name_buf[120]; | ||
| 82 | char state_buf[120]; | ||
| 83 | char *prop_buf; | ||
| 84 | char *envp[3]; | ||
| 85 | int env_offset = 0; | ||
| 86 | int length; | ||
| 87 | |||
| 88 | if (edev->state != state) { | ||
| 89 | edev->state = state; | ||
| 90 | |||
| 91 | prop_buf = (char *)get_zeroed_page(GFP_KERNEL); | ||
| 92 | if (prop_buf) { | ||
| 93 | length = name_show(edev->dev, NULL, prop_buf); | ||
| 94 | if (length > 0) { | ||
| 95 | if (prop_buf[length - 1] == '\n') | ||
| 96 | prop_buf[length - 1] = 0; | ||
| 97 | snprintf(name_buf, sizeof(name_buf), | ||
| 98 | "NAME=%s", prop_buf); | ||
| 99 | envp[env_offset++] = name_buf; | ||
| 100 | } | ||
| 101 | length = state_show(edev->dev, NULL, prop_buf); | ||
| 102 | if (length > 0) { | ||
| 103 | if (prop_buf[length - 1] == '\n') | ||
| 104 | prop_buf[length - 1] = 0; | ||
