linux/drivers/extcon/extcon-class.c
<<
>>
Prefs
   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#include <linux/sysfs.h>
  34#include <linux/of.h>
  35
  36/*
  37 * extcon_cable_name suggests the standard cable names for commonly used
  38 * cable types.
  39 *
  40 * However, please do not use extcon_cable_name directly for extcon_dev
  41 * struct's supported_cable pointer unless your device really supports
  42 * every single port-type of the following cable names. Please choose cable
  43 * names that are actually used in your extcon device.
  44 */
  45const char extcon_cable_name[][CABLE_NAME_MAX + 1] = {
  46        [EXTCON_USB]            = "USB",
  47        [EXTCON_USB_HOST]       = "USB-Host",
  48        [EXTCON_TA]             = "TA",
  49        [EXTCON_FAST_CHARGER]   = "Fast-charger",
  50        [EXTCON_SLOW_CHARGER]   = "Slow-charger",
  51        [EXTCON_CHARGE_DOWNSTREAM]      = "Charge-downstream",
  52        [EXTCON_HDMI]           = "HDMI",
  53        [EXTCON_MHL]            = "MHL",
  54        [EXTCON_DVI]            = "DVI",
  55        [EXTCON_VGA]            = "VGA",
  56        [EXTCON_DOCK]           = "Dock",
  57        [EXTCON_LINE_IN]        = "Line-in",
  58        [EXTCON_LINE_OUT]       = "Line-out",
  59        [EXTCON_MIC_IN]         = "Microphone",
  60        [EXTCON_HEADPHONE_OUT]  = "Headphone",
  61        [EXTCON_SPDIF_IN]       = "SPDIF-in",
  62        [EXTCON_SPDIF_OUT]      = "SPDIF-out",
  63        [EXTCON_VIDEO_IN]       = "Video-in",
  64        [EXTCON_VIDEO_OUT]      = "Video-out",
  65        [EXTCON_MECHANICAL]     = "Mechanical",
  66};
  67
  68static struct class *extcon_class;
  69#if defined(CONFIG_ANDROID)
  70static struct class_compat *switch_class;
  71#endif /* CONFIG_ANDROID */
  72
  73static LIST_HEAD(extcon_dev_list);
  74static DEFINE_MUTEX(extcon_dev_list_lock);
  75
  76/**
  77 * check_mutually_exclusive - Check if new_state violates mutually_exclusive
  78 *                            condition.
  79 * @edev:       the extcon device
  80 * @new_state:  new cable attach status for @edev
  81 *
  82 * Returns 0 if nothing violates. Returns the index + 1 for the first
  83 * violated condition.
  84 */
  85static int check_mutually_exclusive(struct extcon_dev *edev, u32 new_state)
  86{
  87        int i = 0;
  88
  89        if (!edev->mutually_exclusive)
  90                return 0;
  91
  92        for (i = 0; edev->mutually_exclusive[i]; i++) {
  93                int weight;
  94                u32 correspondants = new_state & edev->mutually_exclusive[i];
  95
  96                /* calculate the total number of bits set */
  97                weight = hweight32(correspondants);
  98                if (weight > 1)
  99                        return i + 1;
 100        }
 101
 102        return 0;
 103}
 104
 105static ssize_t state_show(struct device *dev, struct device_attribute *attr,
 106                          char *buf)
 107{
 108        int i, count = 0;
 109        struct extcon_dev *edev = dev_get_drvdata(dev);
 110
 111        if (edev->print_state) {
 112                int ret = edev->print_state(edev, buf);
 113
 114                if (ret >= 0)
 115                        return ret;
 116                /* Use default if failed */
 117        }
 118
 119        if (edev->max_supported == 0)
 120                return sprintf(buf, "%u\n", edev->state);
 121
 122        for (i = 0; i < SUPPORTED_CABLE_MAX; i++) {
 123                if (!edev->supported_cable[i])
 124                        break;
 125                count += sprintf(buf + count, "%s=%d\n",
 126                                 edev->supported_cable[i],
 127                                 !!(edev->state & (1 << i)));
 128        }
 129
 130        return count;
 131}
 132
 133static ssize_t state_store(struct device *dev, struct device_attribute *attr,
 134                           const char *buf, size_t count)
 135{
 136        u32 state;
 137        ssize_t ret = 0;
 138        struct extcon_dev *edev = dev_get_drvdata(dev);
 139
 140        ret = sscanf(buf, "0x%x", &state);
 141        if (ret == 0)
 142                ret = -EINVAL;
 143        else
 144                ret = extcon_set_state(edev, state);
 145
 146        if (ret < 0)
 147                return ret;
 148
 149        return count;
 150}
 151static DEVICE_ATTR_RW(state);
 152
 153static ssize_t name_show(struct device *dev, struct device_attribute *attr,
 154                char *buf)
 155{
 156        struct extcon_dev *edev = dev_get_drvdata(dev);
 157
 158        /* Optional callback given by the user */
 159        if (edev->print_name) {
 160                int ret = edev->print_name(edev, buf);
 161                if (ret >= 0)
 162                        return ret;
 163        }
 164
 165        return sprintf(buf, "%s\n", dev_name(&edev->dev));
 166}
 167static DEVICE_ATTR_RO(name);
 168
 169static ssize_t cable_name_show(struct device *dev,
 170                               struct device_attribute *attr, char *buf)
 171{
 172        struct extcon_cable *cable = container_of(attr, struct extcon_cable,
 173                                                  attr_name);
 174
 175        return sprintf(buf, "%s\n",
 176                       cable->edev->supported_cable[cable->cable_index]);
 177}
 178
 179static ssize_t cable_state_show(struct device *dev,
 180                                struct device_attribute *attr, char *buf)
 181{
 182        struct extcon_cable *cable = container_of(attr, struct extcon_cable,
 183                                                  attr_state);
 184
 185        return sprintf(buf, "%d\n",
 186                       extcon_get_cable_state_(cable->edev,
 187                                               cable->cable_index));
 188}
 189
 190/**
 191 * extcon_update_state() - Update the cable attach states of the extcon device
 192 *                         only for the masked bits.
 193 * @edev:       the extcon device
 194 * @mask:       the bit mask to designate updated bits.
 195 * @state:      new cable attach status for @edev
 196 *
 197 * Changing the state sends uevent with environment variable containing
 198 * the name of extcon device (envp[0]) and the state output (envp[1]).
 199 * Tizen uses this format for extcon device to get events from ports.
 200 * Android uses this format as well.
 201 *
 202 * Note that the notifier provides which bits are changed in the state
 203 * variable with the val parameter (second) to the callback.
 204 */
 205int extcon_update_state(struct extcon_dev *edev, u32 mask, u32 state)
 206{
 207        char name_buf[120];
 208        char state_buf[120];
 209        char *prop_buf;
 210        char *envp[3];
 211        int env_offset = 0;
 212        int length;
 213        unsigned long flags;
 214
 215        spin_lock_irqsave(&edev->lock, flags);
 216
 217        if (edev->state != ((edev->state & ~mask) | (state & mask))) {
 218                u32 old_state = edev->state;
 219
 220                if (check_mutually_exclusive(edev, (edev->state & ~mask) |
 221                                                   (state & mask))) {
 222                        spin_unlock_irqrestore(&edev->lock, flags);
 223                        return -EPERM;
 224                }
 225
 226                edev->state &= ~mask;
 227                edev->state |= state & mask;
 228
 229                raw_notifier_call_chain(&edev->nh, old_state, edev);
 230                /* This could be in interrupt handler */
 231                prop_buf = (char *)get_zeroed_page(GFP_ATOMIC);
 232                if (prop_buf) {
 233                        length = name_show(&edev->dev, NULL, prop_buf);
 234                        if (length > 0) {
 235                                if (prop_buf[length - 1] == '\n')
 236                                        prop_buf[length - 1] = 0;
 237                                snprintf(name_buf, sizeof(name_buf),
 238                                        "NAME=%s", prop_buf);
 239                                envp[env_offset++] = name_buf;
 240                        }
 241                        length = state_show(&edev->dev, NULL, prop_buf);
 242                        if (length > 0) {
 243                                if (prop_buf[length - 1] == '\n')
 244                                        prop_buf[length - 1] = 0;
 245                                snprintf(state_buf, sizeof(state_buf),
 246                                        "STATE=%s", prop_buf);
 247                                envp[env_offset++] = state_buf;
 248                        }
 249                        envp[env_offset] = NULL;
 250                        /* Unlock early before uevent */
 251                        spin_unlock_irqrestore(&edev->lock, flags);
 252
 253                        kobject_uevent_env(&edev->dev.kobj, KOBJ_CHANGE, envp);
 254                        free_page((unsigned long)prop_buf);
 255                } else {
 256                        /* Unlock early before uevent */
 257                        spin_unlock_irqrestore(&edev->lock, flags);
 258
 259                        dev_err(&edev->dev, "out of memory in extcon_set_state\n");
 260                        kobject_uevent(&edev->dev.kobj, KOBJ_CHANGE);
 261                }
 262        } else {
 263                /* No changes */
 264                spin_unlock_irqrestore(&edev->lock, flags);
 265        }
 266
 267        return 0;
 268}
 269EXPORT_SYMBOL_GPL(extcon_update_state);
 270
 271/**
 272 * extcon_set_state() - Set the cable attach states of the extcon device.
 273 * @edev:       the extcon device
 274 * @state:      new cable attach status for @edev
 275 *
 276 * Note that notifier provides which bits are changed in the state
 277 * variable with the val parameter (second) to the callback.
 278 */
 279int extcon_set_state(struct extcon_dev *edev, u32 state)
 280{
 281        return extcon_update_state(edev, 0xffffffff, state);
 282}
 283EXPORT_SYMBOL_GPL(extcon_set_state);
 284
 285/**
 286 * extcon_find_cable_index() - Get the cable index based on the cable name.
 287 * @edev:       the extcon device that has the cable.
 288 * @cable_name: cable name to be searched.
 289 *
 290 * Note that accessing a cable state based on cable_index is faster than
 291 * cable_name because using cable_name induces a loop with strncmp().
 292 * Thus, when get/set_cable_state is repeatedly used, using cable_index
 293 * is recommended.
 294 */
 295int extcon_find_cable_index(struct extcon_dev *edev, const char *cable_name)
 296{
 297        int i;
 298
 299        if (edev->supported_cable) {
 300                for (i = 0; edev->supported_cable[i]; i++) {
 301                        if (!strncmp(edev->supported_cable[i],
 302                                cable_name, CABLE_NAME_MAX))
 303                                return i;
 304                }
 305        }
 306
 307        return -EINVAL;
 308}
 309EXPORT_SYMBOL_GPL(extcon_find_cable_index);
 310
 311/**
 312 * extcon_get_cable_state_() - Get the status of a specific cable.
 313 * @edev:       the extcon device that has the cable.
 314 * @index:      cable index that can be retrieved by extcon_find_cable_index().
 315 */
 316int extcon_get_cable_state_(struct extcon_dev *edev, int index)
 317{
 318        if (index < 0 || (edev->max_supported && edev->max_supported <= index))
 319                return -EINVAL;
 320
 321        return !!(edev->state & (1 << index));
 322}
 323EXPORT_SYMBOL_GPL(extcon_get_cable_state_);
 324
 325/**
 326 * extcon_get_cable_state() - Get the status of a specific cable.
 327 * @edev:       the extcon device that has the cable.
 328 * @cable_name: cable name.
 329 *
 330 * Note that this is slower than extcon_get_cable_state_.
 331 */
 332int extcon_get_cable_state(struct extcon_dev *edev, const char *cable_name)
 333{
 334        return extcon_get_cable_state_(edev, extcon_find_cable_index
 335                                                (edev, cable_name));
 336}
 337EXPORT_SYMBOL_GPL(extcon_get_cable_state);
 338
 339/**
 340 * extcon_set_cable_state_() - Set the status of a specific cable.
 341 * @edev:               the extcon device that has the cable.
 342 * @index:              cable index that can be retrieved by
 343 *                      extcon_find_cable_index().
 344 * @cable_state:        the new cable status. The default semantics is
 345 *                      true: attached / false: detached.
 346 */
 347int extcon_set_cable_state_(struct extcon_dev *edev,
 348                        int index, bool cable_state)
 349{
 350        u32 state;
 351
 352        if (index < 0 || (edev->max_supported && edev->max_supported <= index))
 353                return -EINVAL;
 354
 355        state = cable_state ? (1 << index) : 0;
 356        return extcon_update_state(edev, 1 << index, state);
 357}
 358EXPORT_SYMBOL_GPL(extcon_set_cable_state_);
 359
 360/**
 361 * extcon_set_cable_state() - Set the status of a specific cable.
 362 * @edev:               the extcon device that has the cable.
 363 * @cable_name:         cable name.
 364 * @cable_state:        the new cable status. The default semantics is
 365 *                      true: attached / false: detached.
 366 *
 367 * Note that this is slower than extcon_set_cable_state_.
 368 */
 369int extcon_set_cable_state(struct extcon_dev *edev,
 370                        const char *cable_name, bool cable_state)
 371{
 372        return extcon_set_cable_state_(edev, extcon_find_cable_index
 373                                        (edev, cable_name), cable_state);
 374}
 375EXPORT_SYMBOL_GPL(extcon_set_cable_state);
 376
 377/**
 378 * extcon_get_extcon_dev() - Get the extcon device instance from the name
 379 * @extcon_name:        The extcon name provided with extcon_dev_register()
 380 */
 381struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name)
 382{
 383        struct extcon_dev *sd;
 384
 385        mutex_lock(&extcon_dev_list_lock);
 386        list_for_each_entry(sd, &extcon_dev_list, entry) {
 387                if (!strcmp(sd->name, extcon_name))
 388                        goto out;
 389        }
 390        sd = NULL;
 391out:
 392        mutex_unlock(&extcon_dev_list_lock);
 393        return sd;
 394}
 395EXPORT_SYMBOL_GPL(extcon_get_extcon_dev);
 396
 397static int _call_per_cable(struct notifier_block *nb, unsigned long val,
 398                           void *ptr)
 399{
 400        struct extcon_specific_cable_nb *obj = container_of(nb,
 401                        struct extcon_specific_cable_nb, internal_nb);
 402        struct extcon_dev *edev = ptr;
 403
 404        if ((val & (1 << obj->cable_index)) !=
 405            (edev->state & (1 << obj->cable_index))) {
 406                bool cable_state = true;
 407
 408                obj->previous_value = val;
 409
 410                if (val & (1 << obj->cable_index))
 411                        cable_state = false;
 412
 413                return obj->user_nb->notifier_call(obj->user_nb,
 414                                cable_state, ptr);
 415        }
 416
 417        return NOTIFY_OK;
 418}
 419
 420/**
 421 * extcon_register_interest() - Register a notifier for a state change of a
 422 *                              specific cable, not an entier set of cables of a
 423 *                              extcon device.
 424 * @obj:                an empty extcon_specific_cable_nb object to be returned.
 425 * @extcon_name:        the name of extcon device.
 426 *                      if NULL, extcon_register_interest will register
 427 *                      every cable with the target cable_name given.
 428 * @cable_name:         the target cable name.
 429 * @nb:                 the notifier block to get notified.
 430 *
 431 * Provide an empty extcon_specific_cable_nb. extcon_register_interest() sets
 432 * the struct for you.
 433 *
 434 * extcon_register_interest is a helper function for those who want to get
 435 * notification for a single specific cable's status change. If a user wants
 436 * to get notification for any changes of all cables of a extcon device,
 437 * he/she should use the general extcon_register_notifier().
 438 *
 439 * Note that the second parameter given to the callback of nb (val) is
 440 * "old_state", not the current state. The current state can be retrieved
 441 * by looking at the third pameter (edev pointer)'s state value.
 442 */
 443int extcon_register_interest(struct extcon_specific_cable_nb *obj,
 444                             const char *extcon_name, const char *cable_name,
 445                             struct notifier_block *nb)
 446{
 447        if (!obj || !cable_name || !nb)
 448                return -EINVAL;
 449
 450        if (extcon_name) {
 451                obj->edev = extcon_get_extcon_dev(extcon_name);
 452                if (!obj->edev)
 453                        return -ENODEV;
 454
 455                obj->cable_index = extcon_find_cable_index(obj->edev,
 456                                                          cable_name);
 457                if (obj->cable_index < 0)
 458                        return obj->cable_index;
 459
 460                obj->user_nb = nb;
 461
 462                obj->internal_nb.notifier_call = _call_per_cable;
 463
 464                return raw_notifier_chain_register(&obj->edev->nh,
 465                                                  &obj->internal_nb);
 466        } else {
 467                struct class_dev_iter iter;
 468                struct extcon_dev *extd;
 469                struct device *dev;
 470
 471                if (!extcon_class)
 472                        return -ENODEV;
 473                class_dev_iter_init(&iter, extcon_class, NULL, NULL);
 474                while ((dev = class_dev_iter_next(&iter))) {
 475                        extd = dev_get_drvdata(dev);
 476
 477                        if (extcon_find_cable_index(extd, cable_name) < 0)
 478                                continue;
 479
 480                        class_dev_iter_exit(&iter);
 481                        return extcon_register_interest(obj, extd->name,
 482                                                cable_name, nb);
 483                }
 484
 485                return -ENODEV;
 486        }
 487}
 488EXPORT_SYMBOL_GPL(extcon_register_interest);
 489
 490/**
 491 * extcon_unregister_interest() - Unregister the notifier registered by
 492 *                                extcon_register_interest().
 493 * @obj:        the extcon_specific_cable_nb object returned by
 494 *              extcon_register_interest().
 495 */
 496int extcon_unregister_interest(struct extcon_specific_cable_nb *obj)
 497{
 498        if (!obj)
 499                return -EINVAL;
 500
 501        return raw_notifier_chain_unregister(&obj->edev->nh, &obj->internal_nb);
 502}
 503EXPORT_SYMBOL_GPL(extcon_unregister_interest);
 504
 505/**
 506 * extcon_register_notifier() - Register a notifiee to get notified by
 507 *                              any attach status changes from the extcon.
 508 * @edev:       the extcon device.
 509 * @nb:         a notifier block to be registered.
 510 *
 511 * Note that the second parameter given to the callback of nb (val) is
 512 * "old_state", not the current state. The current state can be retrieved
 513 * by looking at the third pameter (edev pointer)'s state value.
 514 */
 515int extcon_register_notifier(struct extcon_dev *edev,
 516                        struct notifier_block *nb)
 517{
 518        return raw_notifier_chain_register(&edev->nh, nb);
 519}
 520EXPORT_SYMBOL_GPL(extcon_register_notifier);
 521
 522/**
 523 * extcon_unregister_notifier() - Unregister a notifiee from the extcon device.
 524 * @edev:       the extcon device.
 525 * @nb:         a registered notifier block to be unregistered.
 526 */
 527int extcon_unregister_notifier(struct extcon_dev *edev,
 528                        struct notifier_block *nb)
 529{
 530        return raw_notifier_chain_unregister(&edev->nh, nb);
 531}
 532EXPORT_SYMBOL_GPL(extcon_unregister_notifier);
 533
 534static struct attribute *extcon_attrs[] = {
 535        &dev_attr_state.attr,
 536        &dev_attr_name.attr,
 537        NULL,
 538};
 539ATTRIBUTE_GROUPS(extcon);
 540
 541static int create_extcon_class(void)
 542{
 543        if (!extcon_class) {
 544                extcon_class = class_create(THIS_MODULE, "extcon");
 545                if (IS_ERR(extcon_class))
 546                        return PTR_ERR(extcon_class);
 547                extcon_class->dev_groups = extcon_groups;
 548
 549#if defined(CONFIG_ANDROID)
 550                switch_class = class_compat_register("switch");
 551                if (WARN(!switch_class, "cannot allocate"))
 552                        return -ENOMEM;
 553#endif /* CONFIG_ANDROID */
 554        }
 555
 556        return 0;
 557}
 558
 559static void extcon_dev_release(struct device *dev)
 560{
 561}
 562
 563static const char *muex_name = "mutually_exclusive";
 564static void dummy_sysfs_dev_release(struct device *dev)
 565{
 566}
 567
 568/*
 569 * extcon_dev_allocate() - Allocate the memory of extcon device.
 570 * @supported_cable:    Array of supported cable names ending with NULL.
 571 *                      If supported_cable is NULL, cable name related APIs
 572 *                      are disabled.
 573 *
 574 * This function allocates the memory for extcon device without allocating
 575 * memory in each extcon provider driver and initialize default setting for
 576 * extcon device.
 577 *
 578 * Return the pointer of extcon device if success or ERR_PTR(err) if fail
 579 */
 580struct extcon_dev *extcon_dev_allocate(const char **supported_cable)
 581{
 582        struct extcon_dev *edev;
 583
 584        edev = kzalloc(sizeof(*edev), GFP_KERNEL);
 585        if (!edev)
 586                return ERR_PTR(-ENOMEM);
 587
 588        edev->max_supported = 0;
 589        edev->supported_cable = supported_cable;
 590
 591        return edev;
 592}
 593
 594/*
 595 * extcon_dev_free() - Free the memory of extcon device.
 596 * @edev:       the extcon device to free
 597 */
 598void extcon_dev_free(struct extcon_dev *edev)
 599{
 600        kfree(edev);
 601}
 602EXPORT_SYMBOL_GPL(extcon_dev_free);
 603
 604static int devm_extcon_dev_match(struct device *dev, void *res, void *data)
 605{
 606        struct extcon_dev **r = res;
 607
 608        if (WARN_ON(!r || !*r))
 609                return 0;
 610
 611        return *r == data;
 612}
 613
 614static void devm_extcon_dev_release(struct device *dev, void *res)
 615{
 616        extcon_dev_free(*(struct extcon_dev **)res);
 617}
 618
 619/**
 620 * devm_extcon_dev_allocate - Allocate managed extcon device
 621 * @dev:                device owning the extcon device being created
 622 * @supported_cable:    Array of supported cable names ending with NULL.
 623 *                      If supported_cable is NULL, cable name related APIs
 624 *                      are disabled.
 625 *
 626 * This function manages automatically the memory of extcon device using device
 627 * resource management and simplify the control of freeing the memory of extcon
 628 * device.
 629 *
 630 * Returns the pointer memory of allocated extcon_dev if success
 631 * or ERR_PTR(err) if fail
 632 */
 633struct extcon_dev *devm_extcon_dev_allocate(struct device *dev,
 634                                            const char **supported_cable)
 635{
 636        struct extcon_dev **ptr, *edev;
 637
 638        ptr = devres_alloc(devm_extcon_dev_release, sizeof(*ptr), GFP_KERNEL);
 639        if (!ptr)
 640                return ERR_PTR(-ENOMEM);
 641
 642        edev = extcon_dev_allocate(supported_cable);
 643        if (IS_ERR(edev)) {
 644                devres_free(ptr);
 645                return edev;
 646        }
 647
 648        edev->dev.parent = dev;
 649
 650        *ptr = edev;
 651        devres_add(dev, ptr);
 652
 653        return edev;
 654}
 655EXPORT_SYMBOL_GPL(devm_extcon_dev_allocate);
 656
 657void devm_extcon_dev_free(struct device *dev, struct extcon_dev *edev)
 658{
 659        WARN_ON(devres_release(dev, devm_extcon_dev_release,
 660                               devm_extcon_dev_match, edev));
 661}
 662EXPORT_SYMBOL_GPL(devm_extcon_dev_free);
 663
 664/**
 665 * extcon_dev_register() - Register a new extcon device
 666 * @edev        : the new extcon device (should be allocated before calling)
 667 *
 668 * Among the members of edev struct, please set the "user initializing data"
 669 * in any case and set the "optional callbacks" if required. However, please
 670 * do not set the values of "internal data", which are initialized by
 671 * this function.
 672 */
 673int extcon_dev_register(struct extcon_dev *edev)
 674{
 675        int ret, index = 0;
 676
 677        if (!extcon_class) {
 678                ret = create_extcon_class();
 679                if (ret < 0)
 680                        return ret;
 681        }
 682
 683        if (edev->supported_cable) {
 684                /* Get size of array */
 685                for (index = 0; edev->supported_cable[index]; index++)
 686                        ;
 687                edev->max_supported = index;
 688        } else {
 689                edev->max_supported = 0;
 690        }
 691
 692        if (index > SUPPORTED_CABLE_MAX) {
 693                dev_err(&edev->dev, "extcon: maximum number of supported cables exceeded.\n");
 694                return -EINVAL;
 695        }
 696
 697        edev->dev.class = extcon_class;
 698        edev->dev.release = extcon_dev_release;
 699
 700        edev->name = edev->name ? edev->name : dev_name(edev->dev.parent);
 701        if (IS_ERR_OR_NULL(edev->name)) {
 702                dev_err(&edev->dev,
 703                        "extcon device name is null\n");
 704                return -EINVAL;
 705        }
 706        dev_set_name(&edev->dev, "%s", edev->name);
 707
 708        if (edev->max_supported) {
 709                char buf[10];
 710                char *str;
 711                struct extcon_cable *cable;
 712
 713                edev->cables = kzalloc(sizeof(struct extcon_cable) *
 714                                       edev->max_supported, GFP_KERNEL);
 715                if (!edev->cables) {
 716                        ret = -ENOMEM;
 717                        goto err_sysfs_alloc;
 718                }
 719                for (index = 0; index < edev->max_supported; index++) {
 720                        cable = &edev->cables[index];
 721
 722                        snprintf(buf, 10, "cable.%d", index);
 723                        str = kzalloc(sizeof(char) * (strlen(buf) + 1),
 724                                      GFP_KERNEL);
 725                        if (!str) {
 726                                for (index--; index >= 0; index--) {
 727                                        cable = &edev->cables[index];
 728                                        kfree(cable->attr_g.name);
 729                                }
 730                                ret = -ENOMEM;
 731
 732                                goto err_alloc_cables;
 733                        }
 734                        strcpy(str, buf);
 735
 736                        cable->edev = edev;
 737                        cable->cable_index = index;
 738                        cable->attrs[0] = &cable->attr_name.attr;
 739                        cable->attrs[1] = &cable->attr_state.attr;
 740                        cable->attrs[2] = NULL;
 741                        cable->attr_g.name = str;
 742                        cable->attr_g.attrs = cable->attrs;
 743
 744                        sysfs_attr_init(&cable->attr_name.attr);
 745                        cable->attr_name.attr.name = "name";
 746                        cable->attr_name.attr.mode = 0444;
 747                        cable->attr_name.show = cable_name_show;
 748
 749                        sysfs_attr_init(&cable->attr_state.attr);
 750                        cable->attr_state.attr.name = "state";
 751                        cable->attr_state.attr.mode = 0444;
 752                        cable->attr_state.show = cable_state_show;
 753                }
 754        }
 755
 756        if (edev->max_supported && edev->mutually_exclusive) {
 757                char buf[80];
 758                char *name;
 759
 760                /* Count the size of mutually_exclusive array */
 761                for (index = 0; edev->mutually_exclusive[index]; index++)
 762                        ;
 763
 764                edev->attrs_muex = kzalloc(sizeof(struct attribute *) *
 765                                           (index + 1), GFP_KERNEL);
 766                if (!edev->attrs_muex) {
 767                        ret = -ENOMEM;
 768                        goto err_muex;
 769                }
 770
 771                edev->d_attrs_muex = kzalloc(sizeof(struct device_attribute) *
 772                                             index, GFP_KERNEL);
 773                if (!edev->d_attrs_muex) {
 774                        ret = -ENOMEM;
 775                        kfree(edev->attrs_muex);
 776                        goto err_muex;
 777                }
 778
 779                for (index = 0; edev->mutually_exclusive[index]; index++) {
 780                        sprintf(buf, "0x%x", edev->mutually_exclusive[index]);
 781                        name = kzalloc(sizeof(char) * (strlen(buf) + 1),
 782                                       GFP_KERNEL);
 783                        if (!name) {
 784                                for (index--; index >= 0; index--) {
 785                                        kfree(edev->d_attrs_muex[index].attr.
 786                                              name);
 787                                }
 788                                kfree(edev->d_attrs_muex);
 789                                kfree(edev->attrs_muex);
 790                                ret = -ENOMEM;
 791                                goto err_muex;
 792                        }
 793                        strcpy(name, buf);
 794                        sysfs_attr_init(&edev->d_attrs_muex[index].attr);
 795                        edev->d_attrs_muex[index].attr.name = name;
 796                        edev->d_attrs_muex[index].attr.mode = 0000;
 797                        edev->attrs_muex[index] = &edev->d_attrs_muex[index]
 798                                                        .attr;
 799                }
 800                edev->attr_g_muex.name = muex_name;
 801                edev->attr_g_muex.attrs = edev->attrs_muex;
 802
 803        }
 804
 805        if (edev->max_supported) {
 806                edev->extcon_dev_type.groups =
 807                        kzalloc(sizeof(struct attribute_group *) *
 808                                (edev->max_supported + 2), GFP_KERNEL);
 809                if (!edev->extcon_dev_type.groups) {
 810                        ret = -ENOMEM;
 811                        goto err_alloc_groups;
 812                }
 813
 814                edev->extcon_dev_type.name = dev_name(&edev->dev);
 815                edev->extcon_dev_type.release = dummy_sysfs_dev_release;
 816
 817                for (index = 0; index < edev->max_supported; index++)
 818                        edev->extcon_dev_type.groups[index] =
 819                                &edev->cables[index].attr_g;
 820                if (edev->mutually_exclusive)
 821                        edev->extcon_dev_type.groups[index] =
 822                                &edev->attr_g_muex;
 823
 824                edev->dev.type = &edev->extcon_dev_type;
 825        }
 826
 827        ret = device_register(&edev->dev);
 828        if (ret) {
 829                put_device(&edev->dev);
 830                goto err_dev;
 831        }
 832#if defined(CONFIG_ANDROID)
 833        if (switch_class)
 834                ret = class_compat_create_link(switch_class, &edev->dev, NULL);
 835#endif /* CONFIG_ANDROID */
 836
 837        spin_lock_init(&edev->lock);
 838
 839        RAW_INIT_NOTIFIER_HEAD(&edev->nh);
 840
 841        dev_set_drvdata(&edev->dev, edev);
 842        edev->state = 0;
 843
 844        mutex_lock(&extcon_dev_list_lock);
 845        list_add(&edev->entry, &extcon_dev_list);
 846        mutex_unlock(&extcon_dev_list_lock);
 847
 848        return 0;
 849
 850err_dev:
 851        if (edev->max_supported)
 852                kfree(edev->extcon_dev_type.groups);
 853err_alloc_groups:
 854        if (edev->max_supported && edev->mutually_exclusive) {
 855                for (index = 0; edev->mutually_exclusive[index]; index++)
 856                        kfree(edev->d_attrs_muex[index].attr.name);
 857                kfree(edev->d_attrs_muex);
 858                kfree(edev->attrs_muex);
 859        }
 860err_muex:
 861        for (index = 0; index < edev->max_supported; index++)
 862                kfree(edev->cables[index].attr_g.name);
 863err_alloc_cables:
 864        if (edev->max_supported)
 865                kfree(edev->cables);
 866err_sysfs_alloc:
 867        return ret;
 868}
 869EXPORT_SYMBOL_GPL(extcon_dev_register);
 870
 871/**
 872 * extcon_dev_unregister() - Unregister the extcon device.
 873 * @edev:       the extcon device instance to be unregistered.
 874 *
 875 * Note that this does not call kfree(edev) because edev was not allocated
 876 * by this class.
 877 */
 878void extcon_dev_unregister(struct extcon_dev *edev)
 879{
 880        int index;
 881
 882        mutex_lock(&extcon_dev_list_lock);
 883        list_del(&edev->entry);
 884        mutex_unlock(&extcon_dev_list_lock);
 885
 886        if (IS_ERR_OR_NULL(get_device(&edev->dev))) {
 887                dev_err(&edev->dev, "Failed to unregister extcon_dev (%s)\n",
 888                                dev_name(&edev->dev));
 889                return;
 890        }
 891
 892        device_unregister(&edev->dev);
 893
 894        if (edev->mutually_exclusive && edev->max_supported) {
 895                for (index = 0; edev->mutually_exclusive[index];
 896                                index++)
 897                        kfree(edev->d_attrs_muex[index].attr.name);
 898                kfree(edev->d_attrs_muex);
 899                kfree(edev->attrs_muex);
 900        }
 901
 902        for (index = 0; index < edev->max_supported; index++)
 903                kfree(edev->cables[index].attr_g.name);
 904
 905        if (edev->max_supported) {
 906                kfree(edev->extcon_dev_type.groups);
 907                kfree(edev->cables);
 908        }
 909
 910#if defined(CONFIG_ANDROID)
 911        if (switch_class)
 912                class_compat_remove_link(switch_class, &edev->dev, NULL);
 913#endif
 914        put_device(&edev->dev);
 915}
 916EXPORT_SYMBOL_GPL(extcon_dev_unregister);
 917
 918static void devm_extcon_dev_unreg(struct device *dev, void *res)
 919{
 920        extcon_dev_unregister(*(struct extcon_dev **)res);
 921}
 922
 923/**
 924 * devm_extcon_dev_register() - Resource-managed extcon_dev_register()
 925 * @dev:        device to allocate extcon device
 926 * @edev:       the new extcon device to register
 927 *
 928 * Managed extcon_dev_register() function. If extcon device is attached with
 929 * this function, that extcon device is automatically unregistered on driver
 930 * detach. Internally this function calls extcon_dev_register() function.
 931 * To get more information, refer that function.
 932 *
 933 * If extcon device is registered with this function and the device needs to be
 934 * unregistered separately, devm_extcon_dev_unregister() should be used.
 935 *
 936 * Returns 0 if success or negaive error number if failure.
 937 */
 938int devm_extcon_dev_register(struct device *dev, struct extcon_dev *edev)
 939{
 940        struct extcon_dev **ptr;
 941        int ret;
 942
 943        ptr = devres_alloc(devm_extcon_dev_unreg, sizeof(*ptr), GFP_KERNEL);
 944        if (!ptr)
 945                return -ENOMEM;
 946
 947        ret = extcon_dev_register(edev);
 948        if (ret) {
 949                devres_free(ptr);
 950                return ret;
 951        }
 952
 953        *ptr = edev;
 954        devres_add(dev, ptr);
 955
 956        return 0;
 957}
 958EXPORT_SYMBOL_GPL(devm_extcon_dev_register);
 959
 960/**
 961 * devm_extcon_dev_unregister() - Resource-managed extcon_dev_unregister()
 962 * @dev:        device the extcon belongs to
 963 * @edev:       the extcon device to unregister
 964 *
 965 * Unregister extcon device that is registered with devm_extcon_dev_register()
 966 * function.
 967 */
 968void devm_extcon_dev_unregister(struct device *dev, struct extcon_dev *edev)
 969{
 970        WARN_ON(devres_release(dev, devm_extcon_dev_unreg,
 971                               devm_extcon_dev_match, edev));
 972}
 973EXPORT_SYMBOL_GPL(devm_extcon_dev_unregister);
 974
 975#ifdef CONFIG_OF
 976/*
 977 * extcon_get_edev_by_phandle - Get the extcon device from devicetree
 978 * @dev - instance to the given device
 979 * @index - index into list of extcon_dev
 980 *
 981 * return the instance of extcon device
 982 */
 983struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index)
 984{
 985        struct device_node *node;
 986        struct extcon_dev *edev;
 987
 988        if (!dev->of_node) {
 989                dev_err(dev, "device does not have a device node entry\n");
 990                return ERR_PTR(-EINVAL);
 991        }
 992
 993        node = of_parse_phandle(dev->of_node, "extcon", index);
 994        if (!node) {
 995                dev_err(dev, "failed to get phandle in %s node\n",
 996                        dev->of_node->full_name);
 997                return ERR_PTR(-ENODEV);
 998        }
 999
1000        edev = extcon_get_extcon_dev(node->name);
1001        if (!edev) {
1002                dev_err(dev, "unable to get extcon device : %s\n", node->name);
1003                return ERR_PTR(-ENODEV);
1004        }
1005
1006        return edev;
1007}
1008#else
1009struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index)
1010{
1011        return ERR_PTR(-ENOSYS);
1012}
1013#endif /* CONFIG_OF */
1014EXPORT_SYMBOL_GPL(extcon_get_edev_by_phandle);
1015
1016static int __init extcon_class_init(void)
1017{
1018        return create_extcon_class();
1019}
1020module_init(extcon_class_init);
1021
1022static void __exit extcon_class_exit(void)
1023{
1024#if defined(CONFIG_ANDROID)
1025        class_compat_unregister(switch_class);
1026#endif
1027        class_destroy(extcon_class);
1028}
1029module_exit(extcon_class_exit);
1030
1031MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>");
1032MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
1033MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
1034MODULE_DESCRIPTION("External connector (extcon) class driver");
1035MODULE_LICENSE("GPL");
1036