summaryrefslogtreecommitdiff
path: root/drivers/input/sensors/bmi160/bstclass.c
blob: 4937ccac51c5d856b5a82dfb0e4076e30fe2f9f0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
/*!
 * @section LICENSE
 * (C) Copyright 2011~2016 Bosch Sensortec GmbH All Rights Reserved
 *
 * This software program is licensed subject to the GNU General
 * Public License (GPL).Version 2,June 1991,
 * available at http://www.fsf.org/copyleft/gpl.html
 *
 * @filename bstclass.c
 * @date     2015/11/17 13:44
 * @id       "836294d"
 * @version  1.5.9
 *
 * @brief    
 */
#include <linux/init.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/random.h>
#include <linux/sched.h>
#include <linux/seq_file.h>
#include <linux/poll.h>
#include <linux/mutex.h>
#include <linux/rcupdate.h>
#include <linux/compiler.h>
#include <linux/compat.h>
#include "bstclass.h"
#include "bs_log.h"

static LIST_HEAD(bst_dev_list);

/*
 * bst_mutex protects access to both bst_dev_list and input_handler_list.
 * This also causes bst_[un]register_device and bst_[un]register_handler
 * be mutually exclusive which simplifies locking in drivers implementing
 * input handlers.
 */
static DEFINE_MUTEX(bst_mutex);


static void bst_dev_release(struct device *device)
{
	struct bst_dev *dev = to_bst_dev(device);
	if (NULL != dev)
		kfree(dev);
	module_put(THIS_MODULE);
}


#ifdef CONFIG_PM
static int bst_dev_suspend(struct device *dev)
{
	return 0;
}

static int bst_dev_resume(struct device *dev)
{
	return 0;
}

static const struct dev_pm_ops bst_dev_pm_ops = {
	.suspend    = bst_dev_suspend,
	.resume     = bst_dev_resume,
	.poweroff   = bst_dev_suspend,
	.restore    = bst_dev_resume,
};
#endif /* CONFIG_PM */

static const struct attribute_group *bst_dev_attr_groups[] = {
	NULL
};

static struct device_type bst_dev_type = {
	.groups      = bst_dev_attr_groups,
	.release = bst_dev_release,
#ifdef CONFIG_PM
	.pm      = &bst_dev_pm_ops,
#endif
};



static char *bst_devnode(struct device *dev, mode_t *mode)
{
	return kasprintf(GFP_KERNEL, "%s", dev_name(dev));
}

struct class bst_class = {
	.name        = "bst",
	.owner       = THIS_MODULE,
	.devnode     = (void*)bst_devnode,
	.dev_release = bst_dev_release,
};
EXPORT_SYMBOL_GPL(bst_class);

/**
 * bst_allocate_device - allocate memory for new input device
 *
 * Returns prepared struct bst_dev or NULL.
 *
 * NOTE: Use bst_free_device() to free devices that have not been
 * registered; bst_unregister_device() should be used for already
 * registered devices.
 */
struct bst_dev *bst_allocate_device(void)
{
	struct bst_dev *dev;

	dev = kzalloc(sizeof(struct bst_dev), GFP_KERNEL);
	if (dev) {
		dev->dev.type = &bst_dev_type;
		dev->dev.class = &bst_class;
		device_initialize(&dev->dev);
		mutex_init(&dev->mutex);
		INIT_LIST_HEAD(&dev->node);
		__module_get(THIS_MODULE);
	}
	return dev;
}
EXPORT_SYMBOL(bst_allocate_device);



/**
 * bst_free_device - free memory occupied by bst_dev structure
 * @dev: input device to free
 *
 * This function should only be used if bst_register_device()
 * was not called yet or if it failed. Once device was registered
 * use bst_unregister_device() and memory will be freed once last
 * reference to the device is dropped.
 *
 * Device should be allocated by bst_allocate_device().
 *
 * NOTE: If there are references to the input device then memory
 * will not be freed until last reference is dropped.
 */
void bst_free_device(struct bst_dev *dev)
{
	if (dev)
		bst_put_device(dev);
}
EXPORT_SYMBOL(bst_free_device);

/**
 * bst_register_device - register device with input core
 * @dev: device to be registered
 *
 * This function registers device with input core. The device must be
 * allocated with bst_allocate_device() and all it's capabilities
 * set up before registering.
 * If function fails the device must be freed with bst_free_device().
 * Once device has been successfully registered it can be unregistered
 * with bst_unregister_device(); bst_free_device() should not be
 * called in this case.
 */
int bst_register_device(struct bst_dev *dev)
{
	const char *path;
	int error;


	/*
	 * If delay and period are pre-set by the driver, then autorepeating
	 * is handled by the driver itself and we don't do it in input.c.
	 */
	dev_set_name(&dev->dev, dev->name);

	error = device_add(&dev->dev);
	if (error)
		return error;

	path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
	PINFO("%s as %s\n",
			dev->name ? dev->name : "Unspecified device",
			path ? path : "N/A");
	kfree(path);
	error = mutex_lock_interruptible(&bst_mutex);
	if (error) {
		device_del(&dev->dev);
		return error;
	}

	list_add_tail(&dev->node, &bst_dev_list);

	mutex_unlock(&bst_mutex);
	return 0;
}
EXPORT_SYMBOL(bst_register_device);

/**
 * bst_unregister_device - unregister previously registered device
 * @dev: device to be unregistered
 *
 * This function unregisters an input device. Once device is unregistered
 * the caller should not try to access it as it may get freed at any moment.
 */
void bst_unregister_device(struct bst_dev *dev)
{
	int ret = 0;
	ret = mutex_lock_interruptible(&bst_mutex);
	if(ret){
		return;
	}

	list_del_init(&dev->node);
	mutex_unlock(&bst_mutex);
	device_unregister(&dev->dev);
}
EXPORT_SYMBOL(bst_unregister_device);

static int __init bst_init(void)
{
	int err;
	/*bst class register*/
	err = class_register(&bst_class);
	if (err) {
		pr_err("unable to register bst_dev class\n");
		return err;
	}
	return err;
}

static void __exit bst_exit(void)
{
	/*bst class*/
	class_unregister(&bst_class);
}

/*subsys_initcall(bst_init);*/

MODULE_AUTHOR("contact@bosch-sensortec.com");
MODULE_DESCRIPTION("BST CLASS CORE");
MODULE_LICENSE("GPL V2");

module_init(bst_init);
module_exit(bst_exit);