lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAMz4kuLrEMRQDgH928+sXeeVs2OfyDbnSy=VJoCfZV7qRhfdXg@mail.gmail.com>
Date:	Fri, 7 Aug 2015 16:33:46 +0800
From:	Baolin Wang <baolin.wang@...aro.org>
To:	Peter Chen <peter.chen@...escale.com>
Cc:	Felipe Balbi <balbi@...com>, Mark Brown <broonie@...nel.org>,
	LKML <linux-kernel@...r.kernel.org>,
	Greg KH <gregkh@...uxfoundation.org>, sojka@...ica.cz,
	Alan Stern <stern@...land.harvard.edu>, andreas@...sler.com,
	linux-usb@...r.kernel.org,
	device-mainlining@...ts.linuxfoundation.org
Subject: Re: [PATCH 1/2] gadget: Introduce the usb charger framework

On 7 August 2015 at 13:41, Peter Chen <peter.chen@...escale.com> wrote:
> On Thu, Aug 06, 2015 at 03:03:48PM +0800, Baolin Wang wrote:
>> This patch introduces the usb charger driver based on usb gadget that
>> makes an enhancement to a power driver. It works well in practice but
>> that requires a system with suitable hardware.
>>
>> The basic conception of the usb charger is that, when one usb charger
>> is added or removed by reporting from the usb gadget state change or
>> the extcon device state change, the usb charger will report to power
>> user to set the current limitation.
>>
>> The usb charger will register notifiees on the usb gadget or the extcon
>> device to get notified the usb charger state.
>>
>> Power user will register a notifiee on the usb charger to get notified
>> by status changes from the usb charger. It will report to power user
>> to set the current limitation when detecting the usb charger is added
>> or removed from extcon device state or usb gadget state.
>>
>> Signed-off-by: Baolin Wang <baolin.wang@...aro.org>
>> ---
>>  drivers/usb/gadget/charger.c    |  547 +++++++++++++++++++++++++++++++++++++++
>>  include/linux/usb/usb_charger.h |  101 ++++++++
>>  2 files changed, 648 insertions(+)
>>  create mode 100644 drivers/usb/gadget/charger.c
>>  create mode 100644 include/linux/usb/usb_charger.h
>>
>> diff --git a/drivers/usb/gadget/charger.c b/drivers/usb/gadget/charger.c
>> new file mode 100644
>> index 0000000..3ca0180
>> --- /dev/null
>> +++ b/drivers/usb/gadget/charger.c
>> @@ -0,0 +1,547 @@
>> +/*
>> + * usb charger.c -- USB charger driver
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> + */
>> +
>> +#include <linux/device.h>
>> +#include <linux/err.h>
>> +#include <linux/extcon.h>
>> +#include <linux/export.h>
>> +#include <linux/kernel.h>
>> +#include <linux/module.h>
>> +#include <linux/of.h>
>> +#include <linux/of_device.h>
>> +#include <linux/of_address.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/slab.h>
>> +#include <linux/usb.h>
>> +#include <linux/usb/ch9.h>
>> +#include <linux/usb/gadget.h>
>> +#include <linux/usb/usb_charger.h>
>> +
>> +#define DEFAULT_CUR_PROTECT  (50)
>> +#define DEFAULT_SDP_CUR_LIMIT        (500 - DEFAULT_CUR_PROTECT)
>> +#define DEFAULT_DCP_CUR_LIMIT        (1500 - DEFAULT_CUR_PROTECT)
>> +#define DEFAULT_CDP_CUR_LIMIT        (1500 - DEFAULT_CUR_PROTECT)
>> +#define DEFAULT_ACA_CUR_LIMIT        (1500 - DEFAULT_CUR_PROTECT)
>> +
>> +static LIST_HEAD(usb_charger_list);
>> +static DEFINE_MUTEX(usb_charger_list_lock);
>> +
>> +/*
>> + * usb_charger_find_by_name - Get the usb charger device by name.
>> + * @name - usb charger device name.
>> + *
>> + * notes: when this function walks the list and returns a charger
>> + * it's dropped the lock which means that something else could come
>> + * along and delete the charger before we dereference the pointer.
>> + * It's very unlikely but it's a possibility so you should take care
>> + * of it.
>> + * Thus when you get the usb charger by name, you should call
>> + * put_usb_charger() to derease the reference count of the usb charger.
>> + *
>> + * return the instance of usb charger device.
>> + */
>> +struct usb_charger *usb_charger_find_by_name(char *name)
>> +{
>> +     struct usb_charger *uchger;
>> +
>> +     if (!name)
>> +             return ERR_PTR(-EINVAL);
>> +
>> +     mutex_lock(&usb_charger_list_lock);
>> +     list_for_each_entry(uchger, &usb_charger_list, entry) {
>> +             if (!strcmp(uchger->name, name)) {
>> +                     get_usb_charger(uchger);
>> +                     mutex_unlock(&usb_charger_list_lock);
>> +                     return uchger;
>> +             }
>> +     }
>> +     mutex_unlock(&usb_charger_list_lock);
>> +
>> +     return NULL;
>> +}
>> +
>> +/*
>> + * usb_charger_register_notify() - Register a notifiee to get notified by
>> + *           any attach status changes from the usb charger type detection.
>> + * @uchger - the usb charger device which is monitored.
>> + * @nb - a notifier block to be registered.
>> + */
>> +void usb_charger_register_notify(struct usb_charger *uchger,
>> +                              struct notifier_block *nb)
>> +{
>> +     unsigned long flags;
>> +
>> +     spin_lock_irqsave(&uchger->lock, flags);
>> +     raw_notifier_chain_register(&uchger->uchger_nh, nb);
>> +     spin_unlock_irqrestore(&uchger->lock, flags);
>> +}
>> +
>> +/*
>> + * usb_charger_unregister_notify() - Unregister a notifiee from the usb charger.
>> + * @uchger - the usb charger device which is monitored.
>> + * @nb - a notifier block to be unregistered.
>> + */
>> +void usb_charger_unregister_notify(struct usb_charger *uchger,
>> +                                struct notifier_block *nb)
>> +{
>> +     unsigned long flags;
>> +
>> +     spin_lock_irqsave(&uchger->lock, flags);
>> +     raw_notifier_chain_unregister(&uchger->uchger_nh, nb);
>> +     spin_unlock_irqrestore(&uchger->lock, flags);
>> +}
>> +
>> +/*
>> + * usb_charger_register_extcon_notifier() - Register a notifiee of the usb
>> + *           charger to get notified by any attach status changes from
>> + *           the extcon device.
>> + * @uchger - the usb charger device.
>> + * @edev - the extcon device.
>> + * @extcon_id - extcon id.
>> + */
>> +int usb_charger_register_extcon_notifier(struct usb_charger *uchger,
>> +                                      struct extcon_dev *edev,
>> +                                      unsigned int extcon_id)
>> +{
>> +     if (!uchger || !edev)
>> +             return -EINVAL;
>> +
>> +     return extcon_register_notifier(edev, extcon_id, &uchger->extcon_nb.nb);
>> +}
>> +
>> +/*
>> + * usb_charger_unregister_extcon_notifier() - Unregister a notifiee of the
>> + *            usb charger from the extcon device.
>> + * @uchger - the usb charger device.
>> + * @edev - the extcon device.
>> + * @extcon_id - extcon id.
>> + */
>> +int usb_charger_unregister_extcon_notifier(struct usb_charger *uchger,
>> +                                        struct extcon_dev *edev,
>> +                                        unsigned int extcon_id)
>> +{
>> +     if (!uchger || !edev)
>> +             return -EINVAL;
>> +
>> +     return extcon_unregister_notifier(edev, extcon_id, &uchger->extcon_nb.nb);
>> +}
>> +
>> +/*
>> + * usb_charger_register_gadget_notifier() - Register a notifiee of the usb
>> + *           charger to get notified by any attach status changes from
>> + *           the usb gadget device.
>> + * @uchger - the usb charger device.
>> + */
>> +int usb_charger_register_gadget_notifier(struct usb_charger *uchger)
>> +{
>> +     struct usb_gadget *ugadget = uchger->gadget;
>> +
>> +     return usb_gadget_register_notify(ugadget, &uchger->gadget_nb);
>> +}
>
> usb_gadget_register_notify is defined at your 2nd patch, it will
> cause 'git bisect' problem.
>

Oh, I miss that and will fix that.

>> +
>> +/*
>> + * usb_charger_unregister_gadget_notifier() - Unregister a notifiee of the usb
>> + *           charger from the usb gadget device.
>> + * @uchger - the usb charger device.
>> + */
>> +int usb_charger_unregister_gadget_notifier(struct usb_charger *uchger)
>> +{
>> +     struct usb_gadget *ugadget = uchger->gadget;
>> +
>> +     return usb_gadget_unregister_notify(ugadget, &uchger->gadget_nb);
>> +}
>> +
>> +/*
>> + * usb_charger_set_cur_limit() - Set the current limitation.
>> + * @uchger - the usb charger device.
>> + * @xxx_cur - the current limit by different charger type.
>> + *
>> + */
>> +int usb_charger_set_cur_limit(struct usb_charger *uchger,
>> +                           struct usb_charger_cur_limit *cur_limit_set)
>> +{
>> +     if (!uchger || !cur_limit_set)
>> +             return -EINVAL;
>> +
>> +     uchger->cur_limit.sdp_cur_limit = cur_limit_set->sdp_cur_limit;
>> +     uchger->cur_limit.dcp_cur_limit = cur_limit_set->dcp_cur_limit;
>> +     uchger->cur_limit.cdp_cur_limit = cur_limit_set->cdp_cur_limit;
>> +     uchger->cur_limit.aca_cur_limit = cur_limit_set->aca_cur_limit;
>> +     return 0;
>> +}
>> +
>> +/*
>> + * usb_charger_get_cur_limit() - Get the current limitation by different usb
>> + *           charger type.
>> + * @uchger - the usb charger device.
>> + * @type - the usb charger type.
>> + *
>> + * return the current limitation to set.
>> + */
>> +static unsigned int
>> +usb_charger_get_cur_limit(struct usb_charger *uchger)
>> +{
>> +     enum usb_charger_type uchger_type = uchger->type;
>> +     unsigned int cur_limit;
>> +
>> +     switch (uchger_type) {
>> +     case SDP_TYPE:
>> +             cur_limit = uchger->cur_limit.sdp_cur_limit;
>> +             break;
>> +     case DCP_TYPE:
>> +             cur_limit = uchger->cur_limit.dcp_cur_limit;
>> +             break;
>> +     case CDP_TYPE:
>> +             cur_limit = uchger->cur_limit.cdp_cur_limit;
>> +             break;
>> +     case ACA_TYPE:
>> +             cur_limit = uchger->cur_limit.aca_cur_limit;
>> +             break;
>> +     default:
>> +             return 0;
>> +     }
>> +
>> +     return cur_limit;
>> +}
>> +
>> +/*
>> + * usb_charger_detect_type() - Get the usb charger type by the callback which is
>> + *           implemented by user.
>> + * @uchger - the usb charger device.
>> + *
>> + * return the usb charger type.
>> + */
>> +enum usb_charger_type
>> +usb_charger_detect_type(struct usb_charger *uchger)
>> +{
>> +     if (uchger->gadget && uchger->gadget->ops
>> +         && uchger->gadget->ops->get_charger_type)
>> +             uchger->type =
>> +                     uchger->gadget->ops->get_charger_type(uchger->gadget);
>> +     else
>> +             uchger->type = UNKNOWN_TYPE;
>> +
>> +     return uchger->type;
>> +}
>> +
>> +/*
>> + * usb_charger_notifier_others() - It will notify other device registered on
>> + *           usb charger.
>> + * @uchger - the usb charger device.
>> + *
>> + */
>> +static void
>> +usb_charger_notify_others(struct usb_charger *uchger,
>> +                       enum usb_charger_state state)
>> +{
>> +     unsigned long flags;
>> +
>> +     spin_lock_irqsave(&uchger->lock, flags);
>
> it is better to use mutex_lock instead of disabling interrupt since
> checking charger type may cause sleeping.
>

Yes, I'll think about the lock again.

>> +     uchger->state = state;
>> +
>> +     switch (state) {
>> +     case USB_CHARGER_PRESENT:
>> +             usb_charger_detect_type(uchger);
>> +             raw_notifier_call_chain(&uchger->uchger_nh,
>> +                     usb_charger_get_cur_limit(uchger),
>> +                     uchger);
>> +             break;
>> +     case USB_CHARGER_REMOVE:
>> +             uchger->type = UNKNOWN_TYPE;
>> +             raw_notifier_call_chain(&uchger->uchger_nh, 0, uchger);
>> +             break;
>> +     default:
>> +             dev_warn(&uchger->dev, "Unknown USB charger state: %d\n",
>> +                      state);
>> +             break;
>> +     }
>> +     spin_unlock_irqrestore(&uchger->lock, flags);
>> +}
>> +
>> +/*
>> + * usb_charger_plug_by_extcon() - The notifier call function which is registered
>> + *           on the extcon device.
>> + * @nb - thr notifier block that notified by extcon device.
>> + * @state - the extcon device state changed.
>> + * @data - here specify a extcon device.
>> + *
>> + * return the notify flag.
>> + */
>> +static int
>> +usb_charger_plug_by_extcon(struct notifier_block *nb,
>> +                        unsigned long state, void *data)
>> +{
>> +     struct usb_charger_nb *extcon_nb =
>> +             container_of(nb, struct usb_charger_nb, nb);
>> +     struct usb_charger *uchger = extcon_nb->uchger;
>> +     enum usb_charger_state uchger_state;
>> +
>> +     if (!uchger)
>> +             return NOTIFY_BAD;
>> +
>> +     /* Report event to power to setting the current limitation
>> +      * for this usb charger when one usb charger is added or removed
>> +      * with detecting by extcon device.
>> +      */
>> +     if (state)
>> +             uchger_state = USB_CHARGER_PRESENT;
>> +     else
>> +             uchger_state = USB_CHARGER_REMOVE;
>> +
>> +     usb_charger_notify_others(uchger, uchger_state);
>> +
>> +     return NOTIFY_OK;
>> +}
>> +
>> +/*
>> + * usb_charger_plug_by_gadget() - Set the usb charger current limitation
>> + *           according to the usb gadget device state.
>> + * @data - here specify a usb charger device.
>> + *
>> + */
>> +static int
>> +usb_charger_plug_by_gadget(struct notifier_block *nb,
>> +                        unsigned long state, void *data)
>> +{
>> +     struct usb_gadget *gadget = (struct usb_gadget *)data;
>> +     struct usb_charger *uchger = gadget->uchger;
>> +     enum usb_charger_state uchger_state;
>> +
>> +     if (!uchger)
>> +             return NOTIFY_BAD;
>> +
>> +     /* Report event to power to setting the current limitation
>> +      * for this usb charger when one usb charger state is changed
>> +      * with detecting by usb gadget state.
>> +      */
>> +     if (uchger->old_gadget_state != state) {
>> +             uchger->old_gadget_state = state;
>> +
>> +             if (state >= USB_STATE_ATTACHED)
>> +                     uchger_state = USB_CHARGER_PRESENT;
>> +             else if (state == USB_STATE_NOTATTACHED)
>> +                     uchger_state = USB_CHARGER_REMOVE;
>> +             else
>> +                     uchger_state = USB_CHARGER_DEFAULT;
>> +
>> +             usb_charger_notify_others(uchger, uchger_state);
>> +     }
>> +
>> +     return NOTIFY_OK;
>> +}
>> +
>> +static int devm_uchger_dev_match(struct device *dev, void *res, void *data)
>> +{
>> +     struct usb_charger **r = res;
>> +
>> +     if (WARN_ON(!r || !*r))
>> +             return 0;
>> +
>> +     return *r == data;
>> +}
>> +
>> +static void usb_charger_release(struct device *dev)
>> +{
>> +     struct usb_charger *uchger = dev_get_drvdata(dev);
>> +
>> +     if (!atomic_dec_and_test(&uchger->count)) {
>> +             dev_err(dev, "The usb charger is still in use\n");
>> +             return;
>> +     }
>> +
>> +     kfree(uchger->name);
>> +     kfree(uchger);
>> +}
>> +
>> +/*
>> + * usb_charger_unregister() - Unregister a usb charger device.
>> + * @uchger - the usb charger device.
>> + *
>> + */
>> +int usb_charger_unregister(struct usb_charger *uchger)
>> +{
>> +     if (!uchger)
>> +             return -EINVAL;
>> +
>> +     mutex_lock(&usb_charger_list_lock);
>> +     list_del(&uchger->entry);
>> +     mutex_unlock(&usb_charger_list_lock);
>> +
>> +     device_unregister(&uchger->dev);
>> +     return 0;
>> +}
>> +
>> +static void devm_uchger_dev_unreg(struct device *dev, void *res)
>> +{
>> +     usb_charger_unregister(*(struct usb_charger **)res);
>> +}
>> +
>> +void devm_usb_charger_unregister(struct device *dev,
>> +                              struct usb_charger *uchger)
>> +{
>> +     devres_release(dev, devm_uchger_dev_unreg,
>> +                    devm_uchger_dev_match, uchger);
>> +}
>> +
>> +/*
>> + * usb_charger_register() - Register a new usb charger device.
>> + * @uchger - the new usb charger device.
>> + *
>> + */
>> +int usb_charger_register(struct device *dev, struct usb_charger *uchger)
>> +{
>> +     static atomic_t uchger_no = ATOMIC_INIT(-1);
>> +     struct usb_charger *tmp;
>> +     int ret;
>> +
>> +     if (!uchger) {
>> +             dev_err(dev, "no device provided for charger\n");
>> +             return -EINVAL;
>> +     }
>> +
>> +     uchger->dev.parent = dev;
>> +     uchger->dev.release = usb_charger_release;
>> +     dev_set_name(&uchger->dev, "usb-chger%lu",
>> +                  (unsigned long)atomic_inc_return(&uchger_no));
>
> For the name of usb-charger, which not using "usb-charger.x" directly?

OK.

>> +
>> +     ret = device_register(&uchger->dev);
>> +     if (ret) {
>> +             put_device(&uchger->dev);
>> +             return ret;
>> +     }
>> +
>> +     dev_set_drvdata(&uchger->dev, uchger);
>> +
>> +     mutex_lock(&usb_charger_list_lock);
>> +     list_for_each_entry(tmp, &usb_charger_list, entry) {
>> +             if (!(strcmp(tmp->name, uchger->name))) {
>> +                     mutex_unlock(&usb_charger_list_lock);
>> +                     ret = -EEXIST;
>> +                     goto out;
>> +             }
>> +     }
>> +     list_add_tail(&uchger->entry, &usb_charger_list);
>> +     mutex_unlock(&usb_charger_list_lock);
>> +
>> +     return 0;
>> +
>> +out:
>> +     dev_err(dev, "Failed to register usb charger (%s)\n",
>> +             uchger->name);
>> +     device_unregister(&uchger->dev);
>> +     put_device(&uchger->dev);
>> +     return ret;
>> +}
>> +
>> +int devm_usb_charger_register(struct device *dev,
>> +                           struct usb_charger *uchger)
>> +{
>> +     struct usb_charger **ptr;
>> +     int ret;
>> +
>> +     ptr = devres_alloc(devm_uchger_dev_unreg, sizeof(*ptr), GFP_KERNEL);
>> +     if (!ptr)
>> +             return -ENOMEM;
>> +
>> +     ret = usb_charger_register(dev, uchger);
>> +     if (ret) {
>> +             devres_free(ptr);
>> +             return ret;
>> +     }
>> +
>> +     *ptr = uchger;
>> +     devres_add(dev, ptr);
>> +
>> +     return 0;
>> +}
>> +
>> +int usb_charger_init(struct usb_gadget *ugadget)
>> +{
>> +     struct usb_charger *uchger;
>> +     struct extcon_dev *edev;
>> +     char buf[100];
>> +     char *str;
>> +     int ret;
>> +
>> +     if (!ugadget)
>> +             return -EINVAL;
>> +
>> +     uchger = devm_kzalloc(&ugadget->dev, sizeof(struct usb_charger),
>> +                           GFP_KERNEL);
>> +     if (!uchger)
>> +             return -ENOMEM;
>> +
>> +     sprintf(buf, "usb-charger.%s", ugadget->name);
>> +     str = devm_kzalloc(&ugadget->dev, sizeof(char) * (strlen(buf) + 1),
>> +                        GFP_KERNEL);
>> +     if (!str)
>> +             return -ENOMEM;
>> +
>> +     strcpy(str, buf);
>> +     uchger->name = str;
>> +     uchger->type = UNKNOWN_TYPE;
>> +     uchger->state = USB_CHARGER_DEFAULT;
>> +     uchger->cur_limit.sdp_cur_limit = DEFAULT_SDP_CUR_LIMIT;
>> +     uchger->cur_limit.dcp_cur_limit = DEFAULT_DCP_CUR_LIMIT;
>> +     uchger->cur_limit.cdp_cur_limit = DEFAULT_CDP_CUR_LIMIT;
>> +     uchger->cur_limit.aca_cur_limit = DEFAULT_ACA_CUR_LIMIT;
>> +
>> +     atomic_set(&uchger->count, 1);
>> +     spin_lock_init(&uchger->lock);
>> +     INIT_LIST_HEAD(&uchger->entry);
>> +     RAW_INIT_NOTIFIER_HEAD(&uchger->uchger_nh);
>> +
>> +     /* register a notifier on a extcon device if it is exsited */
>> +     edev = extcon_get_edev_by_phandle(ugadget->dev.parent, 0);
>> +     if (!IS_ERR_OR_NULL(edev)) {
>> +             uchger->extcon_dev = edev;
>> +             uchger->extcon_nb.nb.notifier_call = usb_charger_plug_by_extcon;
>> +             uchger->extcon_nb.uchger = uchger;
>> +             usb_charger_register_extcon_notifier(uchger, edev, EXTCON_USB);
>> +     }
>> +
>> +     /* register a notifier on a usb gadget device */
>> +     uchger->gadget = ugadget;
>> +     ugadget->uchger = uchger;
>> +     uchger->old_gadget_state = ugadget->state;
>> +     uchger->gadget_nb.notifier_call = usb_charger_plug_by_gadget;
>> +     usb_charger_register_gadget_notifier(uchger);
>> +
>> +     ret = usb_charger_register(&ugadget->dev, uchger);
>> +     if (ret)
>> +             goto reg_fail;
>> +
>> +     return 0;
>> +
>> +reg_fail:
>> +     if (uchger->extcon_dev)
>> +             usb_charger_unregister_extcon_notifier(uchger,
>> +                             uchger->extcon_dev, EXTCON_USB);
>> +
>> +     usb_charger_unregister_gadget_notifier(uchger);
>> +     return ret;
>> +}
>> +
>> +int usb_charger_exit(struct usb_gadget *ugadget)
>> +{
>> +     struct usb_charger *uchger = ugadget->uchger;
>> +
>> +     if (!uchger)
>> +             return -EINVAL;
>> +
>> +     if (uchger->extcon_dev)
>> +             usb_charger_unregister_extcon_notifier(uchger,
>> +                             uchger->extcon_dev, EXTCON_USB);
>> +
>> +     usb_charger_unregister_gadget_notifier(uchger);
>> +     return usb_charger_unregister(uchger);
>> +}
>> +
>> +MODULE_AUTHOR("Baolin Wang <baolin.wang@...aro.org>");
>> +MODULE_DESCRIPTION("USB charger driver");
>> diff --git a/include/linux/usb/usb_charger.h b/include/linux/usb/usb_charger.h
>> new file mode 100644
>> index 0000000..da4d3c9
>> --- /dev/null
>> +++ b/include/linux/usb/usb_charger.h
>> @@ -0,0 +1,101 @@
>> +#ifndef __LINUX_USB_CHARGER_H__
>> +#define __LINUX_USB_CHARGER_H__
>> +
>> +#include <linux/device.h>
>> +#include <linux/notifier.h>
>> +#include <linux/sysfs.h>
>> +#include <linux/usb/ch9.h>
>> +
>> +/* USB charger type:
>> + * SDP (Standard Downstream Port)
>> + * DCP (Dedicated Charging Port)
>> + * CDP (Charging Downstream Port)
>> + * ACA (Accessory Charger Adapters)
>> + */
>> +enum usb_charger_type {
>> +     UNKNOWN_TYPE,
>> +     SDP_TYPE,
>> +     DCP_TYPE,
>> +     CDP_TYPE,
>> +     ACA_TYPE,
>> +};
>> +
>> +/* USB charger state */
>> +enum usb_charger_state {
>> +     USB_CHARGER_DEFAULT,
>> +     USB_CHARGER_PRESENT,
>> +     USB_CHARGER_REMOVE,
>> +};
>> +
>> +/* Current limitation by charger type */
>> +struct usb_charger_cur_limit {
>> +     unsigned int sdp_cur_limit;
>> +     unsigned int dcp_cur_limit;
>> +     unsigned int cdp_cur_limit;
>> +     unsigned int aca_cur_limit;
>> +};
>> +
>> +struct usb_charger_nb {
>> +     struct notifier_block   nb;
>> +     struct usb_charger      *uchger;
>> +};
>> +
>> +struct usb_charger {
>> +     /* Internal data. Please do not set. */
>> +     const char              *name;
>> +     struct device           dev;
>> +     struct raw_notifier_head        uchger_nh;
>> +     struct list_head        entry;
>> +     spinlock_t              lock;
>> +     enum usb_charger_type   type;
>> +     enum usb_charger_state  state;
>> +     atomic_t                count;
>> +
>> +     /* For supporting extcon usb gpio */
>> +     struct extcon_dev       *extcon_dev;
>> +     struct usb_charger_nb   extcon_nb;
>> +
>> +     /* For supporting usb gadget */
>> +     struct usb_gadget       *gadget;
>> +     enum usb_device_state   old_gadget_state;
>> +     struct notifier_block   gadget_nb;
>> +
>> +     /* Current limitation */
>> +     struct usb_charger_cur_limit    cur_limit;
>> +};
>> +
>> +extern struct usb_charger *usb_charger_find_by_name(char *name);
>> +
>> +extern void usb_charger_register_notify(struct usb_charger *uchger,
>> +                                     struct notifier_block *nb);
>> +extern void usb_charger_unregister_notify(struct usb_charger *uchger,
>> +                                       struct notifier_block *nb);
>> +
>> +extern int usb_charger_register_extcon_notifier(struct usb_charger *uchger,
>> +                                             struct extcon_dev *edev,
>> +                                             unsigned int extcon_id);
>> +extern int usb_charger_unregister_extcon_notifier(struct usb_charger *uchger,
>> +                                               struct extcon_dev *edev,
>> +                                               unsigned int extcon_id);
>> +
>> +extern int usb_charger_register_gadget_notifier(struct usb_charger *uchger);
>> +extern int usb_charger_unregister_gadget_notifier(struct usb_charger *uchger);
>> +
>> +extern int usb_charger_set_cur_limit(struct usb_charger *uchger,
>> +                           struct usb_charger_cur_limit *cur_limit_set);
>> +extern enum usb_charger_type usb_charger_detect_type(struct usb_charger *uchger);
>> +
>> +extern int usb_charger_init(struct usb_gadget *ugadget);
>> +extern int usb_charger_exit(struct usb_gadget *ugadget);
>> +
>> +static inline void get_usb_charger(struct usb_charger *uchger)
>> +{
>> +     atomic_inc(&uchger->count);
>> +}
>> +
>> +static inline void put_usb_charger(struct usb_charger *uchger)
>> +{
>> +     atomic_dec(&uchger->count);
>> +}
>> +
>> +#endif /* __LINUX_USB_CHARGER_H__ */
>> --
>> 1.7.9.5
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
>> the body of a message to majordomo@...r.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
> --
>
> Best Regards,
> Peter Chen



-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ