Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0+
  2/*
  3 * Copyright (C) 2015 Karol Kosik <karo9@interia.eu>
  4 * Copyright (C) 2015-2016 Samsung Electronics
  5 *               Igor Kotrasinski <i.kotrasinsk@samsung.com>
  6 *               Krzysztof Opasiak <k.opasiak@samsung.com>
  7 */
  8
  9#include <linux/device.h>
 10#include <linux/list.h>
 11#include <linux/module.h>
 12
 13#include "vudc.h"
 14
 15static unsigned int vudc_number = 1;
 16
 17module_param_named(num, vudc_number, uint, S_IRUGO);
 18MODULE_PARM_DESC(num, "number of emulated controllers");
 19
 20static struct platform_driver vudc_driver = {
 21	.probe		= vudc_probe,
 22	.remove		= vudc_remove,
 23	.driver		= {
 24		.name	= GADGET_NAME,
 25	},
 26};
 27
 28static struct list_head vudc_devices = LIST_HEAD_INIT(vudc_devices);
 29
 30static int __init init(void)
 31{
 32	int retval = -ENOMEM;
 33	int i;
 34	struct vudc_device *udc_dev = NULL, *udc_dev2 = NULL;
 35
 36	if (usb_disabled())
 37		return -ENODEV;
 38
 39	if (vudc_number < 1) {
 40		pr_err("Number of emulated UDC must be no less than 1");
 41		return -EINVAL;
 42	}
 43
 44	retval = platform_driver_register(&vudc_driver);
 45	if (retval < 0)
 46		goto out;
 47
 48	for (i = 0; i < vudc_number; i++) {
 49		udc_dev = alloc_vudc_device(i);
 50		if (!udc_dev) {
 51			retval = -ENOMEM;
 52			goto cleanup;
 53		}
 54
 55		retval = platform_device_add(udc_dev->pdev);
 56		if (retval < 0) {
 57			put_vudc_device(udc_dev);
 58			goto cleanup;
 59		}
 60
 61		list_add_tail(&udc_dev->dev_entry, &vudc_devices);
 62		if (!platform_get_drvdata(udc_dev->pdev)) {
 63			/*
 64			 * The udc was added successfully but its probe
 65			 * function failed for some reason.
 66			 */
 67			retval = -EINVAL;
 68			goto cleanup;
 69		}
 70	}
 71	goto out;
 72
 73cleanup:
 74	list_for_each_entry_safe(udc_dev, udc_dev2, &vudc_devices, dev_entry) {
 75		list_del(&udc_dev->dev_entry);
 76		platform_device_del(udc_dev->pdev);
 77		put_vudc_device(udc_dev);
 78	}
 79
 80	platform_driver_unregister(&vudc_driver);
 81out:
 82	return retval;
 83}
 84module_init(init);
 85
 86static void __exit cleanup(void)
 87{
 88	struct vudc_device *udc_dev = NULL, *udc_dev2 = NULL;
 89
 90	list_for_each_entry_safe(udc_dev, udc_dev2, &vudc_devices, dev_entry) {
 91		list_del(&udc_dev->dev_entry);
 92		platform_device_unregister(udc_dev->pdev);
 93		put_vudc_device(udc_dev);
 94	}
 95	platform_driver_unregister(&vudc_driver);
 96}
 97module_exit(cleanup);
 98
 99MODULE_DESCRIPTION("USB over IP Device Controller");
100MODULE_AUTHOR("Krzysztof Opasiak, Karol Kosik, Igor Kotrasinski");
101MODULE_LICENSE("GPL");