1f08c3bdfSopenharmony_ci/*
2f08c3bdfSopenharmony_ci *
3f08c3bdfSopenharmony_ci *   Copyright (c) International Business Machines  Corp., 2001
4f08c3bdfSopenharmony_ci *
5f08c3bdfSopenharmony_ci *   This program is free software;  you can redistribute it and/or modify
6f08c3bdfSopenharmony_ci *   it under the terms of the GNU General Public License as published by
7f08c3bdfSopenharmony_ci *   the Free Software Foundation; either version 2 of the License, or
8f08c3bdfSopenharmony_ci *   (at your option) any later version.
9f08c3bdfSopenharmony_ci *
10f08c3bdfSopenharmony_ci *   This program is distributed in the hope that it will be useful,
11f08c3bdfSopenharmony_ci *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
12f08c3bdfSopenharmony_ci *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13f08c3bdfSopenharmony_ci *   the GNU General Public License for more details.
14f08c3bdfSopenharmony_ci *
15f08c3bdfSopenharmony_ci *   You should have received a copy of the GNU General Public License
16f08c3bdfSopenharmony_ci *   along with this program;  if not, write to the Free Software
17f08c3bdfSopenharmony_ci *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18f08c3bdfSopenharmony_ci */
19f08c3bdfSopenharmony_ci/*
20f08c3bdfSopenharmony_ci * This test module is for executing and testing
21f08c3bdfSopenharmony_ci * the kernel code from drivers/base. This module
22f08c3bdfSopenharmony_ci * is driven by a user space program through
23f08c3bdfSopenharmony_ci * calls to the ioctl
24f08c3bdfSopenharmony_ci *
25f08c3bdfSopenharmony_ci * author: Sean Ruyle
26f08c3bdfSopenharmony_ci * date:   07/14/2003
27f08c3bdfSopenharmony_ci *
28f08c3bdfSopenharmony_ci * module: tbase
29f08c3bdfSopenharmony_ci */
30f08c3bdfSopenharmony_ci
31f08c3bdfSopenharmony_ci#include <linux/types.h>
32f08c3bdfSopenharmony_ci#include <linux/kernel.h>
33f08c3bdfSopenharmony_ci#include <linux/fs.h>
34f08c3bdfSopenharmony_ci#include <linux/ioctl.h>
35f08c3bdfSopenharmony_ci#include <linux/module.h>
36f08c3bdfSopenharmony_ci#include <linux/init.h>
37f08c3bdfSopenharmony_ci#include <linux/device.h>
38f08c3bdfSopenharmony_ci#include <linux/pci.h>
39f08c3bdfSopenharmony_ci#include <linux/sysdev.h>
40f08c3bdfSopenharmony_ci#include <asm/uaccess.h>
41f08c3bdfSopenharmony_ci
42f08c3bdfSopenharmony_ci#include "tbase.h"
43f08c3bdfSopenharmony_ci#include "str_mod.h"
44f08c3bdfSopenharmony_ci
45f08c3bdfSopenharmony_ciMODULE_AUTHOR("Sean Ruyle <srruyle@us.ibm.com>");
46f08c3bdfSopenharmony_ciMODULE_DESCRIPTION(TMOD_DRIVER_NAME);
47f08c3bdfSopenharmony_ciMODULE_LICENSE("GPL");
48f08c3bdfSopenharmony_ci
49f08c3bdfSopenharmony_cistatic int tbase_ioctl(struct inode *, struct file *, unsigned int,
50f08c3bdfSopenharmony_ci		       unsigned long);
51f08c3bdfSopenharmony_cistatic int tbase_open(struct inode *, struct file *);
52f08c3bdfSopenharmony_cistatic int tbase_close(struct inode *, struct file *);
53f08c3bdfSopenharmony_ci
54f08c3bdfSopenharmony_cistatic int test_device_register(void);
55f08c3bdfSopenharmony_cistatic int test_device_unregister(void);
56f08c3bdfSopenharmony_cistatic int test_bus_add(void);
57f08c3bdfSopenharmony_cistatic int test_get_drv(void);
58f08c3bdfSopenharmony_cistatic int test_put_drv(void);
59f08c3bdfSopenharmony_cistatic int test_reg_firm(void);
60f08c3bdfSopenharmony_cistatic int test_create_file(void);
61f08c3bdfSopenharmony_cistatic int test_dev_suspend(void);
62f08c3bdfSopenharmony_cistatic int test_dev_file(void);
63f08c3bdfSopenharmony_cistatic int test_bus_rescan(void);
64f08c3bdfSopenharmony_cistatic int test_bus_file(void);
65f08c3bdfSopenharmony_cistatic int test_class_reg(void);
66f08c3bdfSopenharmony_cistatic int test_class_get(void);
67f08c3bdfSopenharmony_cistatic int test_class_file(void);
68f08c3bdfSopenharmony_cistatic int test_classdev_reg(void);
69f08c3bdfSopenharmony_cistatic int test_classint_reg(void);
70f08c3bdfSopenharmony_cistatic int test_sysdev_cls_reg(void);
71f08c3bdfSopenharmony_cistatic int test_sysdev_reg(void);
72f08c3bdfSopenharmony_ci
73f08c3bdfSopenharmony_cistatic int Major = TBASEMAJOR;
74f08c3bdfSopenharmony_cistatic ltpmod_user_t ltp_mod;
75f08c3bdfSopenharmony_ci
76f08c3bdfSopenharmony_ci/*
77f08c3bdfSopenharmony_ci * File operations struct, to use operations find the
78f08c3bdfSopenharmony_ci * correct file descriptor
79f08c3bdfSopenharmony_ci */
80f08c3bdfSopenharmony_cistatic struct file_operations tbase_fops = {
81f08c3bdfSopenharmony_ciopen:	tbase_open,
82f08c3bdfSopenharmony_cirelease:tbase_close,
83f08c3bdfSopenharmony_ciioctl:	tbase_ioctl,
84f08c3bdfSopenharmony_ci};
85f08c3bdfSopenharmony_ci
86f08c3bdfSopenharmony_cistatic int tbase_open(struct inode *ino, struct file *f)
87f08c3bdfSopenharmony_ci{
88f08c3bdfSopenharmony_ci	return 0;
89f08c3bdfSopenharmony_ci}
90f08c3bdfSopenharmony_ci
91f08c3bdfSopenharmony_cistatic int tbase_close(struct inode *ino, struct file *f)
92f08c3bdfSopenharmony_ci{
93f08c3bdfSopenharmony_ci	return 0;
94f08c3bdfSopenharmony_ci}
95f08c3bdfSopenharmony_ci
96f08c3bdfSopenharmony_ci/* my bus stuff */
97f08c3bdfSopenharmony_cistruct device_driver test_driver;
98f08c3bdfSopenharmony_cistruct device test_device;
99f08c3bdfSopenharmony_ci
100f08c3bdfSopenharmony_cistatic int test_device_match(struct device *dev, struct device_driver *drv)
101f08c3bdfSopenharmony_ci{
102f08c3bdfSopenharmony_ci
103f08c3bdfSopenharmony_ci	printk("tbase: driver is %s\n", drv->name);
104f08c3bdfSopenharmony_ci//      printk("tbase: device is %s\n", dev->name);
105f08c3bdfSopenharmony_ci
106f08c3bdfSopenharmony_ci	if (drv == &test_driver && dev == &test_device) {
107f08c3bdfSopenharmony_ci		printk("tbase: match\n");
108f08c3bdfSopenharmony_ci		return 1;
109f08c3bdfSopenharmony_ci	} else {
110f08c3bdfSopenharmony_ci		printk("tbase: no match\n");
111f08c3bdfSopenharmony_ci		return 0;
112f08c3bdfSopenharmony_ci	}
113f08c3bdfSopenharmony_ci
114f08c3bdfSopenharmony_ci}
115f08c3bdfSopenharmony_ci
116f08c3bdfSopenharmony_cistruct bus_type test_bus_type = {
117f08c3bdfSopenharmony_ci	.name = "test_bus",
118f08c3bdfSopenharmony_ci	.match = test_device_match,
119f08c3bdfSopenharmony_ci};
120f08c3bdfSopenharmony_ci
121f08c3bdfSopenharmony_ci/* my driver stuff */
122f08c3bdfSopenharmony_ciint test_dev_probe(struct device *dev)
123f08c3bdfSopenharmony_ci{
124f08c3bdfSopenharmony_ci	printk("tbase: Entered test_dev_probe\n");
125f08c3bdfSopenharmony_ci	return 0;
126f08c3bdfSopenharmony_ci}
127f08c3bdfSopenharmony_ci
128f08c3bdfSopenharmony_ciint test_dev_remove(struct device *dev)
129f08c3bdfSopenharmony_ci{
130f08c3bdfSopenharmony_ci	printk("tbase: Entered test_dev_remove\n");
131f08c3bdfSopenharmony_ci	return 0;
132f08c3bdfSopenharmony_ci}
133f08c3bdfSopenharmony_ci
134f08c3bdfSopenharmony_cistruct device_driver test_driver = {
135f08c3bdfSopenharmony_ci	.name = "TestDriver",
136f08c3bdfSopenharmony_ci	.bus = &test_bus_type,
137f08c3bdfSopenharmony_ci	.probe = test_dev_probe,
138f08c3bdfSopenharmony_ci	.remove = test_dev_remove,
139f08c3bdfSopenharmony_ci};
140f08c3bdfSopenharmony_ci
141f08c3bdfSopenharmony_ci/* my device stuff */
142f08c3bdfSopenharmony_cistruct device test_device = {
143f08c3bdfSopenharmony_ci//      .name = "TestDevice",
144f08c3bdfSopenharmony_ci	.bus = &test_bus_type,
145f08c3bdfSopenharmony_ci	.bus_id = "test_bus",
146f08c3bdfSopenharmony_ci};
147f08c3bdfSopenharmony_ci
148f08c3bdfSopenharmony_ci/* my class stuff */
149f08c3bdfSopenharmony_cistatic void test_class_release(struct class_device *class_dev)
150f08c3bdfSopenharmony_ci{
151f08c3bdfSopenharmony_ci	printk("tbase: Entered test_class_release\n");
152f08c3bdfSopenharmony_ci}
153f08c3bdfSopenharmony_ci
154f08c3bdfSopenharmony_ciint test_class_hotplug(struct class_device *dev, char **envp,
155f08c3bdfSopenharmony_ci		       int num_envp, char *buffer, int buffer_size)
156f08c3bdfSopenharmony_ci{
157f08c3bdfSopenharmony_ci	printk("tbase: Entered test_class_hotplug\n");
158f08c3bdfSopenharmony_ci	return 0;
159f08c3bdfSopenharmony_ci}
160f08c3bdfSopenharmony_ci
161f08c3bdfSopenharmony_cistruct class test_class = {
162f08c3bdfSopenharmony_ci	.name = "TestClass",
163f08c3bdfSopenharmony_ci	.hotplug = test_class_hotplug,
164f08c3bdfSopenharmony_ci	.release = test_class_release,
165f08c3bdfSopenharmony_ci};
166f08c3bdfSopenharmony_ci
167f08c3bdfSopenharmony_ci/* my class device stuff */
168f08c3bdfSopenharmony_cistruct class_device test_class_dev = {
169f08c3bdfSopenharmony_ci	.class_id = "test_bus",
170f08c3bdfSopenharmony_ci	.dev = &test_device,
171f08c3bdfSopenharmony_ci	.class = &test_class,
172f08c3bdfSopenharmony_ci};
173f08c3bdfSopenharmony_ci
174f08c3bdfSopenharmony_ci/* my class interface stuff */
175f08c3bdfSopenharmony_ciint test_intf_add(struct class_device *class_dev)
176f08c3bdfSopenharmony_ci{
177f08c3bdfSopenharmony_ci	printk("tbase: Entered test_intf_add for the test class_interface\n");
178f08c3bdfSopenharmony_ci	return 0;
179f08c3bdfSopenharmony_ci}
180f08c3bdfSopenharmony_ci
181f08c3bdfSopenharmony_civoid test_intf_rem(struct class_device *class_dev)
182f08c3bdfSopenharmony_ci{
183f08c3bdfSopenharmony_ci	printk("tbase: Entered test_intf_rem for the test class interface\n");
184f08c3bdfSopenharmony_ci}
185f08c3bdfSopenharmony_ci
186f08c3bdfSopenharmony_cistruct class_interface test_interface = {
187f08c3bdfSopenharmony_ci	.class = &test_class,
188f08c3bdfSopenharmony_ci	.add = &test_intf_add,
189f08c3bdfSopenharmony_ci	.remove = &test_intf_rem,
190f08c3bdfSopenharmony_ci};
191f08c3bdfSopenharmony_ci
192f08c3bdfSopenharmony_ci/* my sys_device stuff */
193f08c3bdfSopenharmony_ciint test_resume(struct sys_device *dev)
194f08c3bdfSopenharmony_ci{
195f08c3bdfSopenharmony_ci	printk("tbase: Entered test resume for sys device\n");
196f08c3bdfSopenharmony_ci	return 0;
197f08c3bdfSopenharmony_ci}
198f08c3bdfSopenharmony_ci
199f08c3bdfSopenharmony_cistruct sysdev_class test_sysclass = {
200f08c3bdfSopenharmony_ci	set_kset_name("TestSysclass"),
201f08c3bdfSopenharmony_ci	.resume = test_resume,
202f08c3bdfSopenharmony_ci};
203f08c3bdfSopenharmony_ci
204f08c3bdfSopenharmony_cistruct sys_device test_sys_device = {
205f08c3bdfSopenharmony_ci	.id = 0,
206f08c3bdfSopenharmony_ci	.cls = &test_sysclass,
207f08c3bdfSopenharmony_ci};
208f08c3bdfSopenharmony_ci
209f08c3bdfSopenharmony_ci/* my attribute stuff */
210f08c3bdfSopenharmony_cistatic inline ssize_t
211f08c3bdfSopenharmony_cistore_new_id(struct device_driver *driver, const char *buf, size_t count)
212f08c3bdfSopenharmony_ci{
213f08c3bdfSopenharmony_ci	printk("tbase: Entered store new id\n");
214f08c3bdfSopenharmony_ci	return count;
215f08c3bdfSopenharmony_ci}
216f08c3bdfSopenharmony_ci
217f08c3bdfSopenharmony_ci/* create attribute driver_attr_new_id */
218f08c3bdfSopenharmony_ciDRIVER_ATTR(new_id, 0200, NULL, store_new_id);
219f08c3bdfSopenharmony_ci
220f08c3bdfSopenharmony_ci/* create attribute dev_attr_test_id */
221f08c3bdfSopenharmony_ciDEVICE_ATTR(test_id, S_IRUGO, NULL, NULL);
222f08c3bdfSopenharmony_ci
223f08c3bdfSopenharmony_ci/* create attribute bus_attr_test_id */
224f08c3bdfSopenharmony_ciBUS_ATTR(test_id, S_IRUGO, NULL, NULL);
225f08c3bdfSopenharmony_ci
226f08c3bdfSopenharmony_ci/* create attribute class_attr_test_id */
227f08c3bdfSopenharmony_ciCLASS_ATTR(test_id, 0644, NULL, NULL);
228f08c3bdfSopenharmony_ci
229f08c3bdfSopenharmony_ci/* create attribute class_device_attr_test_id */
230f08c3bdfSopenharmony_ciCLASS_DEVICE_ATTR(test_id, 0644, NULL, NULL);
231f08c3bdfSopenharmony_ci
232f08c3bdfSopenharmony_ci/*
233f08c3bdfSopenharmony_ci * tbase_ioctl:
234f08c3bdfSopenharmony_ci *      a user space program can drive the test functions
235f08c3bdfSopenharmony_ci *      through a call to ioctl once the correct file
236f08c3bdfSopenharmony_ci *      descriptor has been attained
237f08c3bdfSopenharmony_ci */
238f08c3bdfSopenharmony_cistatic int tbase_ioctl(struct inode *ino, struct file *f,
239f08c3bdfSopenharmony_ci		       unsigned int cmd, unsigned long l)
240f08c3bdfSopenharmony_ci{
241f08c3bdfSopenharmony_ci	int rc;
242f08c3bdfSopenharmony_ci	tmod_interface_t tif;
243f08c3bdfSopenharmony_ci	caddr_t *inparms;
244f08c3bdfSopenharmony_ci	caddr_t *outparms;
245f08c3bdfSopenharmony_ci
246f08c3bdfSopenharmony_ci	printk("Enter tbase_ioctl\n");
247f08c3bdfSopenharmony_ci
248f08c3bdfSopenharmony_ci	inparms = NULL;
249f08c3bdfSopenharmony_ci	outparms = NULL;
250f08c3bdfSopenharmony_ci	rc = 0;
251f08c3bdfSopenharmony_ci
252f08c3bdfSopenharmony_ci	/*
253f08c3bdfSopenharmony_ci	 * the following calls are used to setup the
254f08c3bdfSopenharmony_ci	 * parameters that might need to be passed
255f08c3bdfSopenharmony_ci	 * between user and kernel space, using the tif
256f08c3bdfSopenharmony_ci	 * pointer that is passed in as the last
257f08c3bdfSopenharmony_ci	 * parameter to the ioctl
258f08c3bdfSopenharmony_ci	 *
259f08c3bdfSopenharmony_ci	 */
260f08c3bdfSopenharmony_ci	if (copy_from_user(&tif, (void *)l, sizeof(tif))) {
261f08c3bdfSopenharmony_ci		/* Bad address */
262f08c3bdfSopenharmony_ci		return (-EFAULT);
263f08c3bdfSopenharmony_ci	}
264f08c3bdfSopenharmony_ci
265f08c3bdfSopenharmony_ci	/*
266f08c3bdfSopenharmony_ci	 * Setup inparms and outparms as needed
267f08c3bdfSopenharmony_ci	 */
268f08c3bdfSopenharmony_ci	if (tif.in_len > 0) {
269f08c3bdfSopenharmony_ci		inparms = (caddr_t *) kmalloc(tif.in_len, GFP_KERNEL);
270f08c3bdfSopenharmony_ci		if (!inparms) {
271f08c3bdfSopenharmony_ci			return (-ENOMEM);
272f08c3bdfSopenharmony_ci		}
273f08c3bdfSopenharmony_ci
274f08c3bdfSopenharmony_ci		rc = copy_from_user(inparms, tif.in_data, tif.in_len);
275f08c3bdfSopenharmony_ci		if (rc) {
276f08c3bdfSopenharmony_ci			kfree(inparms);
277f08c3bdfSopenharmony_ci			return (-EFAULT);
278f08c3bdfSopenharmony_ci		}
279f08c3bdfSopenharmony_ci	}
280f08c3bdfSopenharmony_ci	if (tif.out_len > 0) {
281f08c3bdfSopenharmony_ci		outparms = (caddr_t *) kmalloc(tif.out_len, GFP_KERNEL);
282f08c3bdfSopenharmony_ci		if (!outparms) {
283f08c3bdfSopenharmony_ci			kfree(inparms);
284f08c3bdfSopenharmony_ci			return (-ENOMEM);
285f08c3bdfSopenharmony_ci		}
286f08c3bdfSopenharmony_ci	}
287f08c3bdfSopenharmony_ci
288f08c3bdfSopenharmony_ci	/*
289f08c3bdfSopenharmony_ci	 * Use a switch statement to determine which function
290f08c3bdfSopenharmony_ci	 * to call, based on the cmd flag that is specified
291f08c3bdfSopenharmony_ci	 * in user space. Pass in inparms or outparms as
292f08c3bdfSopenharmony_ci	 * needed
293f08c3bdfSopenharmony_ci	 *
294f08c3bdfSopenharmony_ci	 */
295f08c3bdfSopenharmony_ci	switch (cmd) {
296f08c3bdfSopenharmony_ci	case REG_DEVICE:
297f08c3bdfSopenharmony_ci		rc = test_device_register();
298f08c3bdfSopenharmony_ci		break;
299f08c3bdfSopenharmony_ci	case UNREG_DEVICE:
300f08c3bdfSopenharmony_ci		rc = test_device_unregister();
301f08c3bdfSopenharmony_ci		break;
302f08c3bdfSopenharmony_ci	case BUS_ADD:
303f08c3bdfSopenharmony_ci		rc = test_bus_add();
304f08c3bdfSopenharmony_ci		break;
305f08c3bdfSopenharmony_ci	case GET_DRV:
306f08c3bdfSopenharmony_ci		rc = test_get_drv();
307f08c3bdfSopenharmony_ci		break;
308f08c3bdfSopenharmony_ci	case PUT_DRV:
309f08c3bdfSopenharmony_ci		rc = test_put_drv();
310f08c3bdfSopenharmony_ci		break;
311f08c3bdfSopenharmony_ci	case REG_FIRM:
312f08c3bdfSopenharmony_ci		rc = test_reg_firm();
313f08c3bdfSopenharmony_ci		break;
314f08c3bdfSopenharmony_ci	case CREATE_FILE:
315f08c3bdfSopenharmony_ci		rc = test_create_file();
316f08c3bdfSopenharmony_ci		break;
317f08c3bdfSopenharmony_ci	case DEV_SUSPEND:
318f08c3bdfSopenharmony_ci		rc = test_dev_suspend();
319f08c3bdfSopenharmony_ci		break;
320f08c3bdfSopenharmony_ci	case DEV_FILE:
321f08c3bdfSopenharmony_ci		rc = test_dev_file();
322f08c3bdfSopenharmony_ci		break;
323f08c3bdfSopenharmony_ci	case BUS_RESCAN:
324f08c3bdfSopenharmony_ci		rc = test_bus_rescan();
325f08c3bdfSopenharmony_ci		break;
326f08c3bdfSopenharmony_ci	case BUS_FILE:
327f08c3bdfSopenharmony_ci		rc = test_bus_file();
328f08c3bdfSopenharmony_ci		break;
329f08c3bdfSopenharmony_ci	case CLASS_REG:
330f08c3bdfSopenharmony_ci		rc = test_class_reg();
331f08c3bdfSopenharmony_ci		break;
332f08c3bdfSopenharmony_ci	case CLASS_UNREG:
333f08c3bdfSopenharmony_ci		class_unregister(&test_class);
334f08c3bdfSopenharmony_ci		break;
335f08c3bdfSopenharmony_ci	case CLASS_GET:
336f08c3bdfSopenharmony_ci		rc = test_class_get();
337f08c3bdfSopenharmony_ci		break;
338f08c3bdfSopenharmony_ci	case CLASS_FILE:
339f08c3bdfSopenharmony_ci		rc = test_class_file();
340f08c3bdfSopenharmony_ci		break;
341f08c3bdfSopenharmony_ci	case CLASSDEV_REG:
342f08c3bdfSopenharmony_ci		rc = test_classdev_reg();
343f08c3bdfSopenharmony_ci		break;
344f08c3bdfSopenharmony_ci	case CLASSINT_REG:
345f08c3bdfSopenharmony_ci		rc = test_classint_reg();
346f08c3bdfSopenharmony_ci		break;
347f08c3bdfSopenharmony_ci	case SYSDEV_CLS_REG:
348f08c3bdfSopenharmony_ci		rc = test_sysdev_cls_reg();
349f08c3bdfSopenharmony_ci		break;
350f08c3bdfSopenharmony_ci	case SYSDEV_CLS_UNREG:
351f08c3bdfSopenharmony_ci		sysdev_class_unregister(&test_sysclass);
352f08c3bdfSopenharmony_ci		break;
353f08c3bdfSopenharmony_ci	case SYSDEV_REG:
354f08c3bdfSopenharmony_ci		rc = test_sysdev_reg();
355f08c3bdfSopenharmony_ci		break;
356f08c3bdfSopenharmony_ci	case SYSDEV_UNREG:
357f08c3bdfSopenharmony_ci		sys_device_unregister(&test_sys_device);
358f08c3bdfSopenharmony_ci		break;
359f08c3bdfSopenharmony_ci	default:
360f08c3bdfSopenharmony_ci		printk("tbase: Mismatching ioctl command\n");
361f08c3bdfSopenharmony_ci		break;
362f08c3bdfSopenharmony_ci	}
363f08c3bdfSopenharmony_ci
364f08c3bdfSopenharmony_ci	/*
365f08c3bdfSopenharmony_ci	 * copy in the test return code, the reason we
366f08c3bdfSopenharmony_ci	 * this is so that in user space we can tell the
367f08c3bdfSopenharmony_ci	 * difference between an error in one of our test
368f08c3bdfSopenharmony_ci	 * calls or an error in the ioctl function
369f08c3bdfSopenharmony_ci	 */
370f08c3bdfSopenharmony_ci	tif.out_rc = rc;
371f08c3bdfSopenharmony_ci	rc = 0;
372f08c3bdfSopenharmony_ci
373f08c3bdfSopenharmony_ci	/*
374f08c3bdfSopenharmony_ci	 * setup the rest of tif pointer for returning to
375f08c3bdfSopenharmony_ci	 * to user space, using copy_to_user if needed
376f08c3bdfSopenharmony_ci	 */
377f08c3bdfSopenharmony_ci
378f08c3bdfSopenharmony_ci	/* if outparms then copy outparms into tif.out_data */
379f08c3bdfSopenharmony_ci	if (outparms) {
380f08c3bdfSopenharmony_ci		if (copy_to_user(tif.out_data, outparms, tif.out_len)) {
381f08c3bdfSopenharmony_ci			printk
382f08c3bdfSopenharmony_ci			    ("tbase: Unsuccessful copy_to_user of outparms\n");
383f08c3bdfSopenharmony_ci			rc = -EFAULT;
384f08c3bdfSopenharmony_ci		}
385f08c3bdfSopenharmony_ci	}
386f08c3bdfSopenharmony_ci
387f08c3bdfSopenharmony_ci	/* copy tif structure into l so that can be used by user program */
388f08c3bdfSopenharmony_ci	if (copy_to_user((void *)l, &tif, sizeof(tif))) {
389f08c3bdfSopenharmony_ci		printk("tbase: Unsuccessful copy_to_user of tif\n");
390f08c3bdfSopenharmony_ci		rc = -EFAULT;
391f08c3bdfSopenharmony_ci	}
392f08c3bdfSopenharmony_ci
393f08c3bdfSopenharmony_ci	/*
394f08c3bdfSopenharmony_ci	 * free inparms and outparms
395f08c3bdfSopenharmony_ci	 */
396f08c3bdfSopenharmony_ci	if (inparms) {
397f08c3bdfSopenharmony_ci		kfree(inparms);
398f08c3bdfSopenharmony_ci	}
399f08c3bdfSopenharmony_ci	if (outparms) {
400f08c3bdfSopenharmony_ci		kfree(outparms);
401f08c3bdfSopenharmony_ci	}
402f08c3bdfSopenharmony_ci
403f08c3bdfSopenharmony_ci	return rc;
404f08c3bdfSopenharmony_ci}
405f08c3bdfSopenharmony_ci
406f08c3bdfSopenharmony_ci/*
407f08c3bdfSopenharmony_ci * test_device_register
408f08c3bdfSopenharmony_ci *	makes call to device register passing in
409f08c3bdfSopenharmony_ci *	the device pointer that we found in a previos
410f08c3bdfSopenharmony_ci *	function, returns an error code
411f08c3bdfSopenharmony_ci */
412f08c3bdfSopenharmony_cistatic int test_device_register()
413f08c3bdfSopenharmony_ci{
414f08c3bdfSopenharmony_ci	struct device *dev = ltp_mod.dev;
415f08c3bdfSopenharmony_ci	struct device_driver *drv = dev->driver;
416f08c3bdfSopenharmony_ci
417f08c3bdfSopenharmony_ci	/* check if device register returns an error */
418f08c3bdfSopenharmony_ci	if (device_register(dev)) {
419f08c3bdfSopenharmony_ci		printk("tbase: Device not registered\n");
420f08c3bdfSopenharmony_ci		return 1;
421f08c3bdfSopenharmony_ci	} else
422f08c3bdfSopenharmony_ci		printk("tbase: Device registered\n");
423f08c3bdfSopenharmony_ci
424f08c3bdfSopenharmony_ci	driver_unregister(drv);
425f08c3bdfSopenharmony_ci
426f08c3bdfSopenharmony_ci	/* check if driver_register returns an error */
427f08c3bdfSopenharmony_ci	if (driver_register(drv)) {
428f08c3bdfSopenharmony_ci		printk("tbase: Driver not registered\n");
429f08c3bdfSopenharmony_ci		return 1;
430f08c3bdfSopenharmony_ci	} else
431f08c3bdfSopenharmony_ci		printk("tbase: Driver registered\n");
432f08c3bdfSopenharmony_ci
433f08c3bdfSopenharmony_ci	return 0;
434f08c3bdfSopenharmony_ci
435f08c3bdfSopenharmony_ci}
436f08c3bdfSopenharmony_ci
437f08c3bdfSopenharmony_ci/*
438f08c3bdfSopenharmony_ci * test_device_unregister
439f08c3bdfSopenharmony_ci * 	make test call to device_unregister which
440f08c3bdfSopenharmony_ci * 	will in turn make calls that will decrememnt
441f08c3bdfSopenharmony_ci * 	the reference count and clean up as required
442f08c3bdfSopenharmony_ci */
443f08c3bdfSopenharmony_cistatic int test_device_unregister()
444f08c3bdfSopenharmony_ci{
445f08c3bdfSopenharmony_ci	struct device *dev = ltp_mod.dev;
446f08c3bdfSopenharmony_ci
447f08c3bdfSopenharmony_ci	/* increment reference count */
448f08c3bdfSopenharmony_ci	get_device(dev);
449f08c3bdfSopenharmony_ci
450f08c3bdfSopenharmony_ci	/* reset remove pointer */
451f08c3bdfSopenharmony_ci	if (dev->driver->remove)
452f08c3bdfSopenharmony_ci		dev->driver->remove = NULL;
453f08c3bdfSopenharmony_ci
454f08c3bdfSopenharmony_ci	device_unregister(dev);
455f08c3bdfSopenharmony_ci	//check that reference count is smaller by one
456f08c3bdfSopenharmony_ci
457f08c3bdfSopenharmony_ci	return 0;
458f08c3bdfSopenharmony_ci}
459f08c3bdfSopenharmony_ci
460f08c3bdfSopenharmony_ci/*
461f08c3bdfSopenharmony_ci * test_bus_add
462f08c3bdfSopenharmony_ci *	make call to bus_add_device, which will
463f08c3bdfSopenharmony_ci *	in turn add the device that is passed in
464f08c3bdfSopenharmony_ci *	to the bus
465f08c3bdfSopenharmony_ci */
466f08c3bdfSopenharmony_cistatic int test_bus_add()
467f08c3bdfSopenharmony_ci{
468f08c3bdfSopenharmony_ci	/* check if device register returns an error */
469f08c3bdfSopenharmony_ci	if (bus_add_device(&test_device)) {
470f08c3bdfSopenharmony_ci		printk("tbase: Device not added to bus\n");
471f08c3bdfSopenharmony_ci		return 1;
472f08c3bdfSopenharmony_ci	} else {
473f08c3bdfSopenharmony_ci		printk("tbase: Device added to bus\n");
474f08c3bdfSopenharmony_ci		return 0;
475f08c3bdfSopenharmony_ci	}
476f08c3bdfSopenharmony_ci}
477f08c3bdfSopenharmony_ci
478f08c3bdfSopenharmony_ci/*
479f08c3bdfSopenharmony_ci * test_get_drv
480f08c3bdfSopenharmony_ci *	make test call to get_driver which should
481f08c3bdfSopenharmony_ci *	return a pointer to the driver passed in
482f08c3bdfSopenharmony_ci *	and increase the reference count to that
483f08c3bdfSopenharmony_ci *	kobject
484f08c3bdfSopenharmony_ci */
485f08c3bdfSopenharmony_cistatic int test_get_drv()
486f08c3bdfSopenharmony_ci{
487f08c3bdfSopenharmony_ci	int a, rc;
488f08c3bdfSopenharmony_ci	struct device_driver *drv = &test_driver, *tmp = NULL;
489f08c3bdfSopenharmony_ci
490f08c3bdfSopenharmony_ci	/* get reference count before test call */
491f08c3bdfSopenharmony_ci	a = atomic_read(&drv->kobj.refcount);
492f08c3bdfSopenharmony_ci
493f08c3bdfSopenharmony_ci	/* make test call */
494f08c3bdfSopenharmony_ci	if ((tmp = get_driver(drv))) {
495f08c3bdfSopenharmony_ci		rc = 0;
496f08c3bdfSopenharmony_ci		printk("tbase: get driver returned driver\n");
497f08c3bdfSopenharmony_ci	} else {
498f08c3bdfSopenharmony_ci		rc = 1;
499f08c3bdfSopenharmony_ci		printk("tbase: get driver failed to return driver\n");
500f08c3bdfSopenharmony_ci	}
501f08c3bdfSopenharmony_ci
502f08c3bdfSopenharmony_ci	/* check reference count */
503f08c3bdfSopenharmony_ci	if ((a == (atomic_read(&drv->kobj.refcount) - 1))) {
504f08c3bdfSopenharmony_ci		rc = 0;
505f08c3bdfSopenharmony_ci		printk("tbase: correctly set ref count get driver\n");
506f08c3bdfSopenharmony_ci	} else {
507f08c3bdfSopenharmony_ci		rc = 1;
508f08c3bdfSopenharmony_ci		printk("tbase: incorrect ref count get driver\n");
509f08c3bdfSopenharmony_ci	}
510f08c3bdfSopenharmony_ci
511f08c3bdfSopenharmony_ci	return rc;
512f08c3bdfSopenharmony_ci}
513f08c3bdfSopenharmony_ci
514f08c3bdfSopenharmony_ci/*
515f08c3bdfSopenharmony_ci * test_class_get
516f08c3bdfSopenharmony_ci *	make test call to class_get which should return
517f08c3bdfSopenharmony_ci *	a pointer to the class passed in and increase
518f08c3bdfSopenharmony_ci *	the reference count to that kobject
519f08c3bdfSopenharmony_ci */
520f08c3bdfSopenharmony_cistatic int test_class_get()
521f08c3bdfSopenharmony_ci{
522f08c3bdfSopenharmony_ci	int rc;
523f08c3bdfSopenharmony_ci	struct class *tmp = NULL;
524f08c3bdfSopenharmony_ci
525f08c3bdfSopenharmony_ci	/* get reference count before test call */
526f08c3bdfSopenharmony_ci	tmp = class_get(&test_class);
527f08c3bdfSopenharmony_ci	if (tmp == &test_class) {
528f08c3bdfSopenharmony_ci		printk("tbase: Success get class\n");
529f08c3bdfSopenharmony_ci		rc = 0;
530f08c3bdfSopenharmony_ci	} else {
531f08c3bdfSopenharmony_ci		printk("tbase: Failure get class\n");
532f08c3bdfSopenharmony_ci		rc = 1;
533f08c3bdfSopenharmony_ci	}
534f08c3bdfSopenharmony_ci
535f08c3bdfSopenharmony_ci	class_put(&test_class);
536f08c3bdfSopenharmony_ci	return rc;
537f08c3bdfSopenharmony_ci}
538f08c3bdfSopenharmony_ci
539f08c3bdfSopenharmony_ci/*
540f08c3bdfSopenharmony_ci * test_put_drv
541f08c3bdfSopenharmony_ci *      make test call to put_driver which should
542f08c3bdfSopenharmony_ci *      decrease the reference count to the kobject
543f08c3bdfSopenharmony_ci *      pointer in the driver structure
544f08c3bdfSopenharmony_ci */
545f08c3bdfSopenharmony_cistatic int test_put_drv()
546f08c3bdfSopenharmony_ci{
547f08c3bdfSopenharmony_ci	int a, rc;
548f08c3bdfSopenharmony_ci	struct device_driver *drv = &test_driver;
549f08c3bdfSopenharmony_ci
550f08c3bdfSopenharmony_ci	/* get reference count before test call */
551f08c3bdfSopenharmony_ci	a = atomic_read(&drv->kobj.refcount);
552f08c3bdfSopenharmony_ci
553f08c3bdfSopenharmony_ci	/* make test call */
554f08c3bdfSopenharmony_ci	put_driver(drv);
555f08c3bdfSopenharmony_ci
556f08c3bdfSopenharmony_ci	/* check reference count */
557f08c3bdfSopenharmony_ci	if ((a == (atomic_read(&drv->kobj.refcount) + 1))) {
558f08c3bdfSopenharmony_ci		rc = 0;
559f08c3bdfSopenharmony_ci		printk("tbase: correctly set ref count put driver\n");
560f08c3bdfSopenharmony_ci	} else {
561f08c3bdfSopenharmony_ci		rc = 1;
562f08c3bdfSopenharmony_ci		printk("tbase: incorrect ref count put driver\n");
563f08c3bdfSopenharmony_ci	}
564f08c3bdfSopenharmony_ci
565f08c3bdfSopenharmony_ci	return rc;
566f08c3bdfSopenharmony_ci}
567f08c3bdfSopenharmony_ci
568f08c3bdfSopenharmony_ci/*
569f08c3bdfSopenharmony_ci * test_reg_firm
570f08c3bdfSopenharmony_ci *	test call to register_firmware, which will
571f08c3bdfSopenharmony_ci *	register the subsystem, takes in a struct
572f08c3bdfSopenharmony_ci *	subsystem pointer, we can use our bus pointer
573f08c3bdfSopenharmony_ci *	that should have been found in a previous test
574f08c3bdfSopenharmony_ci *	to pass in a subsystem pointer, returns an
575f08c3bdfSopenharmony_ci *	error code
576f08c3bdfSopenharmony_ci */
577f08c3bdfSopenharmony_cistatic int test_reg_firm()
578f08c3bdfSopenharmony_ci{
579f08c3bdfSopenharmony_ci	struct subsystem *subsys = NULL;
580f08c3bdfSopenharmony_ci
581f08c3bdfSopenharmony_ci	/* check pointer exists */
582f08c3bdfSopenharmony_ci	if (!(subsys = &test_bus_type.subsys)) {
583f08c3bdfSopenharmony_ci		printk("tbase: subsys pointer not set in reg firmware\n");
584f08c3bdfSopenharmony_ci		return 1;
585f08c3bdfSopenharmony_ci	}
586f08c3bdfSopenharmony_ci
587f08c3bdfSopenharmony_ci	/* unregiser firmware */
588f08c3bdfSopenharmony_ci	firmware_unregister(subsys);
589f08c3bdfSopenharmony_ci
590f08c3bdfSopenharmony_ci	/* make test call */
591f08c3bdfSopenharmony_ci	if (firmware_register(subsys)) {
592f08c3bdfSopenharmony_ci		printk("tbase: failed register firmware\n");
593f08c3bdfSopenharmony_ci		return 1;
594f08c3bdfSopenharmony_ci	} else {
595f08c3bdfSopenharmony_ci		printk("tbase: regsitered firmware\n");
596f08c3bdfSopenharmony_ci		return 0;
597f08c3bdfSopenharmony_ci	}
598f08c3bdfSopenharmony_ci
599f08c3bdfSopenharmony_ci}
600f08c3bdfSopenharmony_ci
601f08c3bdfSopenharmony_ci/*
602f08c3bdfSopenharmony_ci * test_create_file
603f08c3bdfSopenharmony_ci *	make test call to create sysfs file for the
604f08c3bdfSopenharmony_ci *	driver and if that call is successful then
605f08c3bdfSopenharmony_ci *	make a call to remove the file
606f08c3bdfSopenharmony_ci */
607f08c3bdfSopenharmony_cistatic int test_create_file()
608f08c3bdfSopenharmony_ci{
609f08c3bdfSopenharmony_ci	struct device_driver *drv = &test_driver;
610f08c3bdfSopenharmony_ci
611f08c3bdfSopenharmony_ci	if (driver_create_file(drv, &driver_attr_new_id)) {
612f08c3bdfSopenharmony_ci		printk("tbase: failed create sysfs file\n");
613f08c3bdfSopenharmony_ci		return 1;
614f08c3bdfSopenharmony_ci	} else {
615f08c3bdfSopenharmony_ci		printk("tbase: created sysfs file\n");
616f08c3bdfSopenharmony_ci		driver_remove_file(drv, &driver_attr_new_id);
617f08c3bdfSopenharmony_ci		return 0;
618f08c3bdfSopenharmony_ci	}
619f08c3bdfSopenharmony_ci
620f08c3bdfSopenharmony_ci}
621f08c3bdfSopenharmony_ci
622f08c3bdfSopenharmony_ci/*
623f08c3bdfSopenharmony_ci * test_dev_suspend
624f08c3bdfSopenharmony_ci *	make test call to device_suspend and
625f08c3bdfSopenharmony_ci *	if that call is successful then make
626f08c3bdfSopenharmony_ci *	a call to device_resume
627f08c3bdfSopenharmony_ci */
628f08c3bdfSopenharmony_cistatic int test_dev_suspend()
629f08c3bdfSopenharmony_ci{
630f08c3bdfSopenharmony_ci	int error = 0;
631f08c3bdfSopenharmony_ci
632f08c3bdfSopenharmony_ci	error = device_suspend(SUSPEND_SAVE_STATE);
633f08c3bdfSopenharmony_ci	if (error)
634f08c3bdfSopenharmony_ci		printk("tbase: Failed on device suspend call\n");
635f08c3bdfSopenharmony_ci	else {
636f08c3bdfSopenharmony_ci		printk("tbase: Successful on device suspend call\n");
637f08c3bdfSopenharmony_ci		device_resume();
638f08c3bdfSopenharmony_ci	}
639f08c3bdfSopenharmony_ci
640f08c3bdfSopenharmony_ci	error = device_suspend(SUSPEND_DISABLE);
641f08c3bdfSopenharmony_ci	if (error)
642f08c3bdfSopenharmony_ci		printk("tbase: Failed on device suspend call\n");
643f08c3bdfSopenharmony_ci	else {
644f08c3bdfSopenharmony_ci		printk("tbase: Successful on device suspend call\n");
645f08c3bdfSopenharmony_ci		device_resume();
646f08c3bdfSopenharmony_ci	}
647f08c3bdfSopenharmony_ci
648f08c3bdfSopenharmony_ci	return error;
649f08c3bdfSopenharmony_ci
650f08c3bdfSopenharmony_ci}
651f08c3bdfSopenharmony_ci
652f08c3bdfSopenharmony_ci/*
653f08c3bdfSopenharmony_ci * test_dev_file
654f08c3bdfSopenharmony_ci *	make test call to device_create_file
655f08c3bdfSopenharmony_ci *	and if that call is successful make
656f08c3bdfSopenharmony_ci *	another call to device_remove_file
657f08c3bdfSopenharmony_ci */
658f08c3bdfSopenharmony_cistatic int test_dev_file()
659f08c3bdfSopenharmony_ci{
660f08c3bdfSopenharmony_ci	struct device *dev = &test_device;
661f08c3bdfSopenharmony_ci
662f08c3bdfSopenharmony_ci	if (device_create_file(dev, &dev_attr_test_id)) {
663f08c3bdfSopenharmony_ci		printk("tbase: failed to create dev sysfs file\n");
664f08c3bdfSopenharmony_ci		return 1;
665f08c3bdfSopenharmony_ci	} else {
666f08c3bdfSopenharmony_ci		printk("tbase: created dev sysfs file\n");
667f08c3bdfSopenharmony_ci		device_remove_file(dev, &dev_attr_test_id);
668f08c3bdfSopenharmony_ci		return 0;
669f08c3bdfSopenharmony_ci	}
670f08c3bdfSopenharmony_ci
671f08c3bdfSopenharmony_ci}
672f08c3bdfSopenharmony_ci
673f08c3bdfSopenharmony_ci/*
674f08c3bdfSopenharmony_ci * test_bus_rescan
675f08c3bdfSopenharmony_ci *	make test call to bus_rescan_devices which
676f08c3bdfSopenharmony_ci *	will rescan the bus and attempt to match devices
677f08c3bdfSopenharmony_ci *	to drivers, will return 0 for no matches or
678f08c3bdfSopenharmony_ci *	the number of matches made, check that the
679f08c3bdfSopenharmony_ci *	value returned is not negative
680f08c3bdfSopenharmony_ci */
681f08c3bdfSopenharmony_cistatic int test_bus_rescan()
682f08c3bdfSopenharmony_ci{
683f08c3bdfSopenharmony_ci	int count = 0;
684f08c3bdfSopenharmony_ci
685f08c3bdfSopenharmony_ci	count = bus_rescan_devices(&test_bus_type);
686f08c3bdfSopenharmony_ci	if (count == 0)
687f08c3bdfSopenharmony_ci		printk("tbase: found no device/driver matches\n");
688f08c3bdfSopenharmony_ci	else if (count > 0)
689f08c3bdfSopenharmony_ci		printk("tbase; found match\n");
690f08c3bdfSopenharmony_ci	else {
691f08c3bdfSopenharmony_ci		printk("tbase: bus rescan failed\n");
692f08c3bdfSopenharmony_ci		return count;
693f08c3bdfSopenharmony_ci	}
694f08c3bdfSopenharmony_ci
695f08c3bdfSopenharmony_ci	return 0;
696f08c3bdfSopenharmony_ci}
697f08c3bdfSopenharmony_ci
698f08c3bdfSopenharmony_ci/*
699f08c3bdfSopenharmony_ci * test_bus_file
700f08c3bdfSopenharmony_ci *      make test call to bus_create_file
701f08c3bdfSopenharmony_ci *      and if that call is successful make
702f08c3bdfSopenharmony_ci *      another call to bus_remove_file
703f08c3bdfSopenharmony_ci */
704f08c3bdfSopenharmony_cistatic int test_bus_file()
705f08c3bdfSopenharmony_ci{
706f08c3bdfSopenharmony_ci	struct bus_type *bus = &test_bus_type;
707f08c3bdfSopenharmony_ci
708f08c3bdfSopenharmony_ci	if (bus_create_file(bus, &bus_attr_test_id)) {
709f08c3bdfSopenharmony_ci		printk("tbase: failed to create bus sysfs file\n");
710f08c3bdfSopenharmony_ci		return 1;
711f08c3bdfSopenharmony_ci	} else {
712f08c3bdfSopenharmony_ci		printk("tbase: created bus sysfs file\n");
713f08c3bdfSopenharmony_ci		bus_remove_file(bus, &bus_attr_test_id);
714f08c3bdfSopenharmony_ci		return 0;
715f08c3bdfSopenharmony_ci	}
716f08c3bdfSopenharmony_ci
717f08c3bdfSopenharmony_ci}
718f08c3bdfSopenharmony_ci
719f08c3bdfSopenharmony_ci/*
720f08c3bdfSopenharmony_ci * test_class_file
721f08c3bdfSopenharmony_ci *      make test call to class_create_file
722f08c3bdfSopenharmony_ci *      and if that call is successful make
723f08c3bdfSopenharmony_ci *      another call to class_remove_file
724f08c3bdfSopenharmony_ci */
725f08c3bdfSopenharmony_cistatic int test_class_file()
726f08c3bdfSopenharmony_ci{
727f08c3bdfSopenharmony_ci	struct class *cls = &test_class;
728f08c3bdfSopenharmony_ci
729f08c3bdfSopenharmony_ci	if (class_create_file(cls, &class_attr_test_id)) {
730f08c3bdfSopenharmony_ci		printk("tbase: failed to create class sysfs file\n");
731f08c3bdfSopenharmony_ci		return 1;
732f08c3bdfSopenharmony_ci	} else {
733f08c3bdfSopenharmony_ci		printk("tbase: created class sysfs file\n");
734f08c3bdfSopenharmony_ci		class_remove_file(cls, &class_attr_test_id);
735f08c3bdfSopenharmony_ci		return 0;
736f08c3bdfSopenharmony_ci	}
737f08c3bdfSopenharmony_ci
738f08c3bdfSopenharmony_ci}
739f08c3bdfSopenharmony_ci
740f08c3bdfSopenharmony_ci/*
741f08c3bdfSopenharmony_ci * test_class_reg
742f08c3bdfSopenharmony_ci *	make test call to class_register
743f08c3bdfSopenharmony_ci *	with the test_class that is defined
744f08c3bdfSopenharmony_ci *	in this module, if that call is
745f08c3bdfSopenharmony_ci *	successful then call unregister
746f08c3bdfSopenharmony_ci */
747f08c3bdfSopenharmony_cistatic int test_class_reg()
748f08c3bdfSopenharmony_ci{
749f08c3bdfSopenharmony_ci	int error;
750f08c3bdfSopenharmony_ci
751f08c3bdfSopenharmony_ci	error = class_register(&test_class);
752f08c3bdfSopenharmony_ci	if (error)
753f08c3bdfSopenharmony_ci		printk("tbase: class register failed\n");
754f08c3bdfSopenharmony_ci	else
755f08c3bdfSopenharmony_ci		printk("tbase: class register succeeded\n");
756f08c3bdfSopenharmony_ci
757f08c3bdfSopenharmony_ci	return error;
758f08c3bdfSopenharmony_ci}
759f08c3bdfSopenharmony_ci
760f08c3bdfSopenharmony_ci/*
761f08c3bdfSopenharmony_ci * test_classdev_reg
762f08c3bdfSopenharmony_ci *	make test call to class_device_register
763f08c3bdfSopenharmony_ci *	and if that returns successful then
764f08c3bdfSopenharmony_ci *	make call to class_device_unregister
765f08c3bdfSopenharmony_ci */
766f08c3bdfSopenharmony_cistatic int test_classdev_reg()
767f08c3bdfSopenharmony_ci{
768f08c3bdfSopenharmony_ci	int rc = 0;
769f08c3bdfSopenharmony_ci
770f08c3bdfSopenharmony_ci	if (class_device_register(&test_class_dev)) {
771f08c3bdfSopenharmony_ci		printk("tbase: Failed to register class device\n");
772f08c3bdfSopenharmony_ci		rc = 1;
773f08c3bdfSopenharmony_ci	} else {
774f08c3bdfSopenharmony_ci		printk("tbase: Registered class device\n");
775f08c3bdfSopenharmony_ci
776f08c3bdfSopenharmony_ci		/* make class device sysfs file */
777f08c3bdfSopenharmony_ci		if (class_device_create_file
778f08c3bdfSopenharmony_ci		    (&test_class_dev, &class_device_attr_test_id)) {
779f08c3bdfSopenharmony_ci			rc = 1;
780f08c3bdfSopenharmony_ci			printk
781f08c3bdfSopenharmony_ci			    ("tbase: Failed to create class device sysfs file\n");
782f08c3bdfSopenharmony_ci		} else {
783f08c3bdfSopenharmony_ci			printk("tbase: Created class device sysfs file\n");
784f08c3bdfSopenharmony_ci			class_device_remove_file(&test_class_dev,
785f08c3bdfSopenharmony_ci						 &class_device_attr_test_id);
786f08c3bdfSopenharmony_ci		}
787f08c3bdfSopenharmony_ci
788f08c3bdfSopenharmony_ci		class_device_unregister(&test_class_dev);
789f08c3bdfSopenharmony_ci	}
790f08c3bdfSopenharmony_ci
791f08c3bdfSopenharmony_ci	return rc;
792f08c3bdfSopenharmony_ci}
793f08c3bdfSopenharmony_ci
794f08c3bdfSopenharmony_ci/*
795f08c3bdfSopenharmony_ci * test_classint_reg
796f08c3bdfSopenharmony_ci *	make test call to class_interface_register
797f08c3bdfSopenharmony_ci *	and if that returns successfule then
798f08c3bdfSopenharmony_ci *	make call to class_interface_unregister
799f08c3bdfSopenharmony_ci */
800f08c3bdfSopenharmony_cistatic int test_classint_reg()
801f08c3bdfSopenharmony_ci{
802f08c3bdfSopenharmony_ci
803f08c3bdfSopenharmony_ci	if (class_interface_register(&test_interface)) {
804f08c3bdfSopenharmony_ci		printk("tbase: Failed to register class interface\n");
805f08c3bdfSopenharmony_ci		return 1;
806f08c3bdfSopenharmony_ci	} else {
807f08c3bdfSopenharmony_ci		printk("tbase: Registered class interface\n");
808f08c3bdfSopenharmony_ci		class_interface_unregister(&test_interface);
809f08c3bdfSopenharmony_ci		return 0;
810f08c3bdfSopenharmony_ci	}
811f08c3bdfSopenharmony_ci
812f08c3bdfSopenharmony_ci}
813f08c3bdfSopenharmony_ci
814f08c3bdfSopenharmony_ci/*
815f08c3bdfSopenharmony_ci * test_sysdev_cls_reg
816f08c3bdfSopenharmony_ci *	make test call to sysdev_class_register
817f08c3bdfSopenharmony_ci *	to register the test_sysclass pointer
818f08c3bdfSopenharmony_ci *	as a sysdev_class with the system, check
819f08c3bdfSopenharmony_ci *	the return code
820f08c3bdfSopenharmony_ci */
821f08c3bdfSopenharmony_cistatic int test_sysdev_cls_reg()
822f08c3bdfSopenharmony_ci{
823f08c3bdfSopenharmony_ci
824f08c3bdfSopenharmony_ci	if (sysdev_class_register(&test_sysclass)) {
825f08c3bdfSopenharmony_ci		printk("tbase: Failed to register sysdev class\n");
826f08c3bdfSopenharmony_ci		return 1;
827f08c3bdfSopenharmony_ci	} else {
828f08c3bdfSopenharmony_ci		printk("tbase: Registered sysdev class\n");
829f08c3bdfSopenharmony_ci		return 0;
830f08c3bdfSopenharmony_ci	}
831f08c3bdfSopenharmony_ci
832f08c3bdfSopenharmony_ci}
833f08c3bdfSopenharmony_ci
834f08c3bdfSopenharmony_ci/*
835f08c3bdfSopenharmony_ci * test_sysdev_reg
836f08c3bdfSopenharmony_ci *      make test call to sys_device_register
837f08c3bdfSopenharmony_ci *      to register the test_sysdev pointer
838f08c3bdfSopenharmony_ci *      as a sys_device with the system, check
839f08c3bdfSopenharmony_ci *      the return code
840f08c3bdfSopenharmony_ci */
841f08c3bdfSopenharmony_cistatic int test_sysdev_reg()
842f08c3bdfSopenharmony_ci{
843f08c3bdfSopenharmony_ci
844f08c3bdfSopenharmony_ci	if (sys_device_register(&test_sys_device)) {
845f08c3bdfSopenharmony_ci		printk("tbase: Failed to register sysdev \n");
846f08c3bdfSopenharmony_ci		return 1;
847f08c3bdfSopenharmony_ci	} else {
848f08c3bdfSopenharmony_ci		printk("tbase: Registered sysdev \n");
849f08c3bdfSopenharmony_ci		return 0;
850f08c3bdfSopenharmony_ci	}
851f08c3bdfSopenharmony_ci
852f08c3bdfSopenharmony_ci}
853f08c3bdfSopenharmony_ci
854f08c3bdfSopenharmony_ci/*
855f08c3bdfSopenharmony_ci * tbase_init_module
856f08c3bdfSopenharmony_ci *      set the owner of tbase_fops, register the module
857f08c3bdfSopenharmony_ci *      as a char device, and perform any necessary
858f08c3bdfSopenharmony_ci *      initialization
859f08c3bdfSopenharmony_ci */
860f08c3bdfSopenharmony_cistatic int tbase_init_module(void)
861f08c3bdfSopenharmony_ci{
862f08c3bdfSopenharmony_ci	int rc;
863f08c3bdfSopenharmony_ci
864f08c3bdfSopenharmony_ci	bus_register(&test_bus_type);
865f08c3bdfSopenharmony_ci	driver_register(&test_driver);
866f08c3bdfSopenharmony_ci	device_register(&test_device);
867f08c3bdfSopenharmony_ci
868f08c3bdfSopenharmony_ci	tbase_fops.owner = THIS_MODULE;
869f08c3bdfSopenharmony_ci
870f08c3bdfSopenharmony_ci	printk("tbase: *** Register device %s **\n", DEVICE_NAME);
871f08c3bdfSopenharmony_ci
872f08c3bdfSopenharmony_ci	rc = register_chrdev(Major, DEVICE_NAME, &tbase_fops);
873f08c3bdfSopenharmony_ci	if (rc < 0) {
874f08c3bdfSopenharmony_ci		printk("tbase: Failed to register device.\n");
875f08c3bdfSopenharmony_ci		return rc;
876f08c3bdfSopenharmony_ci	}
877f08c3bdfSopenharmony_ci
878f08c3bdfSopenharmony_ci	if (Major == 0)
879f08c3bdfSopenharmony_ci		Major = rc;
880f08c3bdfSopenharmony_ci
881f08c3bdfSopenharmony_ci	/* call any other init functions you might use here */
882f08c3bdfSopenharmony_ci
883f08c3bdfSopenharmony_ci	printk("tbase: Registration success.\n");
884f08c3bdfSopenharmony_ci	return 0;
885f08c3bdfSopenharmony_ci}
886f08c3bdfSopenharmony_ci
887f08c3bdfSopenharmony_ci/*
888f08c3bdfSopenharmony_ci * tmod_exit_module
889f08c3bdfSopenharmony_ci *      unregister the device and any necessary
890f08c3bdfSopenharmony_ci *      operations to close devices
891f08c3bdfSopenharmony_ci */
892f08c3bdfSopenharmony_cistatic void tbase_exit_module(void)
893f08c3bdfSopenharmony_ci{
894f08c3bdfSopenharmony_ci	int rc;
895f08c3bdfSopenharmony_ci
896f08c3bdfSopenharmony_ci	device_unregister(&test_device);
897f08c3bdfSopenharmony_ci	driver_unregister(&test_driver);
898f08c3bdfSopenharmony_ci	bus_unregister(&test_bus_type);
899f08c3bdfSopenharmony_ci
900f08c3bdfSopenharmony_ci	/* free any pointers still allocated, using kfree */
901f08c3bdfSopenharmony_ci
902f08c3bdfSopenharmony_ci	rc = unregister_chrdev(Major, DEVICE_NAME);
903f08c3bdfSopenharmony_ci	if (rc < 0)
904f08c3bdfSopenharmony_ci		printk("tbase: unregister failed\n");
905f08c3bdfSopenharmony_ci	else
906f08c3bdfSopenharmony_ci		printk("tbase: unregister success\n");
907f08c3bdfSopenharmony_ci
908f08c3bdfSopenharmony_ci}
909f08c3bdfSopenharmony_ci
910f08c3bdfSopenharmony_ci/* specify what that init is run when the module is first
911f08c3bdfSopenharmony_ciloaded and that exit is run when it is removed */
912f08c3bdfSopenharmony_ci
913f08c3bdfSopenharmony_cimodule_init(tbase_init_module)
914f08c3bdfSopenharmony_ci    module_exit(tbase_exit_module)
915