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