/*
 * Copyright (C) 2011 Google, Inc.
 *
 * Author:
 *	Colin Cross <ccross@android.com>
 *
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
 * may be copied, distributed, and modified under those terms.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 */

#include <linux/kernel.h>
#include <linux/mutex.h>
#include <linux/notifier.h>
#include <linux/usb/otg_id.h>

static DEFINE_MUTEX(otg_id_lock);
static struct plist_head otg_id_plist =
	PLIST_HEAD_INIT(otg_id_plist);
static struct otg_id_notifier_block *otg_id_active;
static bool otg_id_cancelling;
static bool otg_id_inited;
static int otg_id_suspended;
static bool otg_id_pending;

static void otg_id_cancel(void)
{
	if (otg_id_active) {
		otg_id_cancelling = true;
		mutex_unlock(&otg_id_lock);

		otg_id_active->cancel(otg_id_active);

		mutex_lock(&otg_id_lock);
		otg_id_cancelling = false;
	}
}

static void __otg_id_notify(void)
{
	int ret = 0;
	struct otg_id_notifier_block *otg_id_nb;
	bool proxy_wait = false;
	if (plist_head_empty(&otg_id_plist))
		return;

	plist_for_each_entry(otg_id_nb, &otg_id_plist, p) {
		if (proxy_wait) {
			if (otg_id_nb->proxy_wait)
				ret = otg_id_nb->proxy_wait(otg_id_nb);
		} else {
			ret = otg_id_nb->detect(otg_id_nb);
		}
		if (ret == OTG_ID_HANDLED) {
			otg_id_active = otg_id_nb;
			return;
		}
		if (ret == OTG_ID_PROXY_WAIT)
			proxy_wait = true;

	}

	WARN(1, "otg id event not handled");
	otg_id_active = NULL;
}

int otg_id_init(void)
{
	mutex_lock(&otg_id_lock);

	otg_id_inited = true;
	__otg_id_notify();

	mutex_unlock(&otg_id_lock);
	return 0;
}
late_initcall(otg_id_init);

/**
 * otg_id_register_notifier
 * @otg_id_nb: notifier block containing priority and callback function
 *
 * Register a notifier that will be called on any USB cable state change.
 * The priority determines the order the callback will be called in, a higher
 * number will be called first.  A callback function needs to determine the
 * type of USB cable that is connected.  If it can determine the type, it
 * should notify the appropriate drivers (for example, call an otg notifier
 * with USB_EVENT_VBUS), and return OTG_ID_HANDLED.  Once a callback has
 * returned OTG_ID_HANDLED, it is responsible for calling otg_id_notify() when
 * the detected USB cable is disconnected.
 */
int otg_id_register_notifier(struct otg_id_notifier_block *otg_id_nb)
{
	plist_node_init(&otg_id_nb->p, otg_id_nb->priority);

	mutex_lock(&otg_id_lock);
	plist_add(&otg_id_nb->p, &otg_id_plist);

	if (otg_id_inited) {
		otg_id_cancel();
		__otg_id_notify();
	}

	mutex_unlock(&otg_id_lock);

	return 0;
}

void otg_id_unregister_notifier(struct otg_id_notifier_block *otg_id_nb)
{
	mutex_lock(&otg_id_lock);

	plist_del(&otg_id_nb->p, &otg_id_plist);

	if (otg_id_inited && (otg_id_active == otg_id_nb)) {
		otg_id_cancel();
		__otg_id_notify();
	}

	mutex_unlock(&otg_id_lock);
}

/**
 * otg_id_notify
 *
 * Notify listeners on any USB cable state change.
 *
 * A driver may only call otg_id_notify if it returned OTG_ID_HANDLED the last
 * time it's notifier was called, and it's cancel function has not been called.
 */
void otg_id_notify(void)
{
	mutex_lock(&otg_id_lock);

	if (otg_id_cancelling)
		goto out;

	if (otg_id_suspended != 0) {
		otg_id_pending = true;
		goto out;
	}

	__otg_id_notify();
out:
	mutex_unlock(&otg_id_lock);
}

/**
 * otg_id_suspend
 *
 * Mark the otg_id subsystem as going into suspend. From here on out,
 * any notifications will be deferred until the last otg_id client resumes.
 * If there is a pending notification when calling this function, it will
 * return a negative errno and expects that the caller will abort suspend.
 * Returs 0 on success.
 */
int otg_id_suspend(void)
{
	int ret = 0;

	mutex_lock(&otg_id_lock);

	/*
	 * if there's a pending notification, tell the caller to abort suspend
	 */
	if (otg_id_suspended != 0 && otg_id_pending) {
		pr_info("otg_id: pending notification, should abort suspend\n");
		ret = -EBUSY;
		goto out;
	}

	otg_id_suspended++;
out:
	mutex_unlock(&otg_id_lock);
	return ret;
}

/**
 * otg_id_resume
 *
 * Inform the otg_id subsystem that a client is resuming. If this is the
 * last client to be resumed and there's a pending notification,
 * otg_id_notify() is called.
 */
void otg_id_resume(void)
{
	mutex_lock(&otg_id_lock);
	if (WARN(!otg_id_suspended, "unbalanced otg_id_resume\n"))
		goto out;
	if (--otg_id_suspended == 0) {
		if (otg_id_pending) {
			pr_info("otg_id: had pending notification\n");
			otg_id_pending = false;
			__otg_id_notify();
		}
	}
out:
	mutex_unlock(&otg_id_lock);
}
