Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1/*
  2 * Copyright (C) 2015 Karol Kosik <karo9@interia.eu>
  3 * Copyright (C) 2015-2016 Samsung Electronics
  4 *               Igor Kotrasinski <i.kotrasinsk@samsung.com>
  5 *               Krzysztof Opasiak <k.opasiak@samsung.com>
  6 *
  7 * This program is free software; you can redistribute it and/or modify
  8 * it under the terms of the GNU General Public License as published by
  9 * the Free Software Foundation; either version 2 of the License, or
 10 * (at your option) any later version.
 11 *
 12 * This program is distributed in the hope that it will be useful,
 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15 * GNU General Public License for more details.
 16 *
 17 * You should have received a copy of the GNU General Public License
 18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 19 */
 20
 21#include <linux/device.h>
 22#include <linux/list.h>
 23#include <linux/module.h>
 24
 25#include "vudc.h"
 26
 27static unsigned int vudc_number = 1;
 28
 29module_param_named(num, vudc_number, uint, S_IRUGO);
 30MODULE_PARM_DESC(num, "number of emulated controllers");
 31
 32static struct platform_driver vudc_driver = {
 33	.probe		= vudc_probe,
 34	.remove		= vudc_remove,
 35	.driver		= {
 36		.name	= GADGET_NAME,
 37	},
 38};
 39
 40static struct list_head vudc_devices = LIST_HEAD_INIT(vudc_devices);
 41
 42static int __init init(void)
 43{
 44	int retval = -ENOMEM;
 45	int i;
 46	struct vudc_device *udc_dev = NULL, *udc_dev2 = NULL;
 47
 48	if (usb_disabled())
 49		return -ENODEV;
 50
 51	if (vudc_number < 1) {
 52		pr_err("Number of emulated UDC must be no less than 1");
 53		return -EINVAL;
 54	}
 55
 56	retval = platform_driver_register(&vudc_driver);
 57	if (retval < 0)
 58		goto out;
 59
 60	for (i = 0; i < vudc_number; i++) {
 61		udc_dev = alloc_vudc_device(i);
 62		if (!udc_dev) {
 63			retval = -ENOMEM;
 64			goto cleanup;
 65		}
 66
 67		retval = platform_device_add(udc_dev->pdev);
 68		if (retval < 0) {
 69			put_vudc_device(udc_dev);
 70			goto cleanup;
 71		}
 72
 73		list_add_tail(&udc_dev->dev_entry, &vudc_devices);
 74		if (!platform_get_drvdata(udc_dev->pdev)) {
 75			/*
 76			 * The udc was added successfully but its probe
 77			 * function failed for some reason.
 78			 */
 79			retval = -EINVAL;
 80			goto cleanup;
 81		}
 82	}
 83	goto out;
 84
 85cleanup:
 86	list_for_each_entry_safe(udc_dev, udc_dev2, &vudc_devices, dev_entry) {
 87		list_del(&udc_dev->dev_entry);
 88		platform_device_del(udc_dev->pdev);
 89		put_vudc_device(udc_dev);
 90	}
 91
 92	platform_driver_unregister(&vudc_driver);
 93out:
 94	return retval;
 95}
 96module_init(init);
 97
 98static void __exit cleanup(void)
 99{
100	struct vudc_device *udc_dev = NULL, *udc_dev2 = NULL;
101
102	list_for_each_entry_safe(udc_dev, udc_dev2, &vudc_devices, dev_entry) {
103		list_del(&udc_dev->dev_entry);
104		platform_device_unregister(udc_dev->pdev);
105		put_vudc_device(udc_dev);
106	}
107	platform_driver_unregister(&vudc_driver);
108}
109module_exit(cleanup);
110
111MODULE_DESCRIPTION("USB over IP Device Controller");
112MODULE_AUTHOR("Krzysztof Opasiak, Karol Kosik, Igor Kotrasinski");
113MODULE_LICENSE("GPL");