// SPDX-License-Identifier: GPL-2.0
/*
 * driver.c - device id matching, driver model, etc.
 *
 * Copyright 2002 Adam Belay <ambx1@neo.rr.com>
 */

#include <linux/string.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/ctype.h>
#include <linux/slab.h>
#include <linux/pnp.h>
#include "base.h"

static int compare_func(const char *ida, const char *idb)
{
	int i;

	/* we only need to compare the last 4 chars */
	for (i = 3; i < 7; i++) {
		if (ida[i] != 'X' &&
		    idb[i] != 'X' && toupper(ida[i]) != toupper(idb[i]))
			return 0;
	}
	return 1;
}

int compare_pnp_id(struct pnp_id *pos, const char *id)
{
	if (!pos || !id || (strlen(id) != 7))
		return 0;
	if (memcmp(id, "ANYDEVS", 7) == 0)
		return 1;
	while (pos) {
		if (memcmp(pos->id, id, 3) == 0)
			if (compare_func(pos->id, id) == 1)
				return 1;
		pos = pos->next;
	}
	return 0;
}

static const struct pnp_device_id *match_device(struct pnp_driver *drv,
						struct pnp_dev *dev)
{
	const struct pnp_device_id *drv_id = drv->id_table;

	if (!drv_id)
		return NULL;

	while (*drv_id->id) {
		if (compare_pnp_id(dev->id, drv_id->id))
			return drv_id;
		drv_id++;
	}
	return NULL;
}

int pnp_device_attach(struct pnp_dev *pnp_dev)
{
	mutex_lock(&pnp_lock);
	if (pnp_dev->status != PNP_READY) {
		mutex_unlock(&pnp_lock);
		return -EBUSY;
	}
	pnp_dev->status = PNP_ATTACHED;
	mutex_unlock(&pnp_lock);
	return 0;
}
EXPORT_SYMBOL(pnp_device_attach);

void pnp_device_detach(struct pnp_dev *pnp_dev)
{
	mutex_lock(&pnp_lock);
	if (pnp_dev->status == PNP_ATTACHED)
		pnp_dev->status = PNP_READY;
	mutex_unlock(&pnp_lock);
}
EXPORT_SYMBOL(pnp_device_detach);

static int pnp_device_probe(struct device *dev)
{
	int error;
	struct pnp_driver *pnp_drv;
	struct pnp_dev *pnp_dev;
	const struct pnp_device_id *dev_id = NULL;
	pnp_dev = to_pnp_dev(dev);
	pnp_drv = to_pnp_driver(dev->driver);

	error = pnp_device_attach(pnp_dev);
	if (error < 0)
		return error;

	if (pnp_dev->active == 0) {
		if (!(pnp_drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE)) {
			error = pnp_activate_dev(pnp_dev);
			if (error < 0)
				return error;
		}
	} else if ((pnp_drv->flags & PNP_DRIVER_RES_DISABLE)
		   == PNP_DRIVER_RES_DISABLE) {
		error = pnp_disable_dev(pnp_dev);
		if (error < 0)
			return error;
	}
	error = 0;
	if (pnp_drv->probe) {
		dev_id = match_device(pnp_drv, pnp_dev);
		if (dev_id != NULL)
			error = pnp_drv->probe(pnp_dev, dev_id);
	}
	if (error >= 0) {
		pnp_dev->driver = pnp_drv;
		error = 0;
	} else
		goto fail;

	return error;

fail:
	pnp_device_detach(pnp_dev);
	return error;
}

static void pnp_device_remove(struct device *dev)
{
	struct pnp_dev *pnp_dev = to_pnp_dev(dev);
	struct pnp_driver *drv = pnp_dev->driver;

	if (drv) {
		if (drv->remove)
			drv->remove(pnp_dev);
		pnp_dev->driver = NULL;
	}

	if (pnp_dev->active &&
	    (!drv || !(drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE)))
		pnp_disable_dev(pnp_dev);

	pnp_device_detach(pnp_dev);
}

static void pnp_device_shutdown(struct device *dev)
{
	struct pnp_dev *pnp_dev = to_pnp_dev(dev);
	struct pnp_driver *drv = pnp_dev->driver;

	if (drv && drv->shutdown)
		drv->shutdown(pnp_dev);
}

static int pnp_bus_match(struct device *dev, struct device_driver *drv)
{
	struct pnp_dev *pnp_dev = to_pnp_dev(dev);
	struct pnp_driver *pnp_drv = to_pnp_driver(drv);

	if (match_device(pnp_drv, pnp_dev) == NULL)
		return 0;
	return 1;
}

static int __pnp_bus_suspend(struct device *dev, pm_message_t state)
{
	struct pnp_dev *pnp_dev = to_pnp_dev(dev);
	struct pnp_driver *pnp_drv = pnp_dev->driver;
	int error;

	if (!pnp_drv)
		return 0;

	if (pnp_drv->driver.pm && pnp_drv->driver.pm->suspend) {
		error = pnp_drv->driver.pm->suspend(dev);
		suspend_report_result(pnp_drv->driver.pm->suspend, error);
		if (error)
			return error;
	}

	if (pnp_drv->suspend) {
		error = pnp_drv->suspend(pnp_dev, state);
		if (error)
			return error;
	}

	if (pnp_can_disable(pnp_dev)) {
		error = pnp_stop_dev(pnp_dev);
		if (error)
			return error;
	}

	if (pnp_can_suspend(pnp_dev))
		pnp_dev->protocol->suspend(pnp_dev, state);
	return 0;
}

static int pnp_bus_suspend(struct device *dev)
{
	return __pnp_bus_suspend(dev, PMSG_SUSPEND);
}

static int pnp_bus_freeze(struct device *dev)
{
	return __pnp_bus_suspend(dev, PMSG_FREEZE);
}

static int pnp_bus_poweroff(struct device *dev)
{
	return __pnp_bus_suspend(dev, PMSG_HIBERNATE);
}

static int pnp_bus_resume(struct device *dev)
{
	struct pnp_dev *pnp_dev = to_pnp_dev(dev);
	struct pnp_driver *pnp_drv = pnp_dev->driver;
	int error;

	if (!pnp_drv)
		return 0;

	if (pnp_dev->protocol->resume) {
		error = pnp_dev->protocol->resume(pnp_dev);
		if (error)
			return error;
	}

	if (pnp_can_write(pnp_dev)) {
		error = pnp_start_dev(pnp_dev);
		if (error)
			return error;
	}

	if (pnp_drv->driver.pm && pnp_drv->driver.pm->resume) {
		error = pnp_drv->driver.pm->resume(dev);
		if (error)
			return error;
	}

	if (pnp_drv->resume) {
		error = pnp_drv->resume(pnp_dev);
		if (error)
			return error;
	}

	return 0;
}

static const struct dev_pm_ops pnp_bus_dev_pm_ops = {
	/* Suspend callbacks */
	.suspend = pnp_bus_suspend,
	.resume = pnp_bus_resume,
	/* Hibernate callbacks */
	.freeze = pnp_bus_freeze,
	.thaw = pnp_bus_resume,
	.poweroff = pnp_bus_poweroff,
	.restore = pnp_bus_resume,
};

struct bus_type pnp_bus_type = {
	.name    = "pnp",
	.match   = pnp_bus_match,
	.probe   = pnp_device_probe,
	.remove  = pnp_device_remove,
	.shutdown = pnp_device_shutdown,
	.pm	 = &pnp_bus_dev_pm_ops,
	.dev_groups = pnp_dev_groups,
};

int pnp_register_driver(struct pnp_driver *drv)
{
	drv->driver.name = drv->name;
	drv->driver.bus = &pnp_bus_type;

	return driver_register(&drv->driver);
}
EXPORT_SYMBOL(pnp_register_driver);

void pnp_unregister_driver(struct pnp_driver *drv)
{
	driver_unregister(&drv->driver);
}
EXPORT_SYMBOL(pnp_unregister_driver);

/**
 * pnp_add_id - adds an EISA id to the specified device
 * @dev: pointer to the desired device
 * @id: pointer to an EISA id string
 */
struct pnp_id *pnp_add_id(struct pnp_dev *dev, const char *id)
{
	struct pnp_id *dev_id, *ptr;

	dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
	if (!dev_id)
		return NULL;

	dev_id->id[0] = id[0];
	dev_id->id[1] = id[1];
	dev_id->id[2] = id[2];
	dev_id->id[3] = tolower(id[3]);
	dev_id->id[4] = tolower(id[4]);
	dev_id->id[5] = tolower(id[5]);
	dev_id->id[6] = tolower(id[6]);
	dev_id->id[7] = '\0';

	dev_id->next = NULL;
	ptr = dev->id;
	while (ptr && ptr->next)
		ptr = ptr->next;
	if (ptr)
		ptr->next = dev_id;
	else
		dev->id = dev_id;

	return dev_id;
}
