1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright 2008 by Karsten Keil <kkeil@novell.com> 4 */ 5 6#include <linux/slab.h> 7#include <linux/types.h> 8#include <linux/stddef.h> 9#include <linux/module.h> 10#include <linux/spinlock.h> 11#include <linux/mISDNif.h> 12#include "core.h" 13 14static u_int debug; 15 16MODULE_AUTHOR("Karsten Keil"); 17MODULE_LICENSE("GPL"); 18module_param(debug, uint, S_IRUGO | S_IWUSR); 19 20static u64 device_ids; 21#define MAX_DEVICE_ID 63 22 23static LIST_HEAD(Bprotocols); 24static DEFINE_RWLOCK(bp_lock); 25 26static void mISDN_dev_release(struct device *dev) 27{ 28 /* nothing to do: the device is part of its parent's data structure */ 29} 30 31static ssize_t id_show(struct device *dev, 32 struct device_attribute *attr, char *buf) 33{ 34 struct mISDNdevice *mdev = dev_to_mISDN(dev); 35 36 if (!mdev) 37 return -ENODEV; 38 return sprintf(buf, "%d\n", mdev->id); 39} 40static DEVICE_ATTR_RO(id); 41 42static ssize_t nrbchan_show(struct device *dev, 43 struct device_attribute *attr, char *buf) 44{ 45 struct mISDNdevice *mdev = dev_to_mISDN(dev); 46 47 if (!mdev) 48 return -ENODEV; 49 return sprintf(buf, "%d\n", mdev->nrbchan); 50} 51static DEVICE_ATTR_RO(nrbchan); 52 53static ssize_t d_protocols_show(struct device *dev, 54 struct device_attribute *attr, char *buf) 55{ 56 struct mISDNdevice *mdev = dev_to_mISDN(dev); 57 58 if (!mdev) 59 return -ENODEV; 60 return sprintf(buf, "%d\n", mdev->Dprotocols); 61} 62static DEVICE_ATTR_RO(d_protocols); 63 64static ssize_t b_protocols_show(struct device *dev, 65 struct device_attribute *attr, char *buf) 66{ 67 struct mISDNdevice *mdev = dev_to_mISDN(dev); 68 69 if (!mdev) 70 return -ENODEV; 71 return sprintf(buf, "%d\n", mdev->Bprotocols | get_all_Bprotocols()); 72} 73static DEVICE_ATTR_RO(b_protocols); 74 75static ssize_t protocol_show(struct device *dev, 76 struct device_attribute *attr, char *buf) 77{ 78 struct mISDNdevice *mdev = dev_to_mISDN(dev); 79 80 if (!mdev) 81 return -ENODEV; 82 return sprintf(buf, "%d\n", mdev->D.protocol); 83} 84static DEVICE_ATTR_RO(protocol); 85 86static ssize_t name_show(struct device *dev, 87 struct device_attribute *attr, char *buf) 88{ 89 strcpy(buf, dev_name(dev)); 90 return strlen(buf); 91} 92static DEVICE_ATTR_RO(name); 93 94#if 0 /* hangs */ 95static ssize_t name_set(struct device *dev, struct device_attribute *attr, 96 const char *buf, size_t count) 97{ 98 int err = 0; 99 char *out = kmalloc(count + 1, GFP_KERNEL); 100 101 if (!out) 102 return -ENOMEM; 103 104 memcpy(out, buf, count); 105 if (count && out[count - 1] == '\n') 106 out[--count] = 0; 107 if (count) 108 err = device_rename(dev, out); 109 kfree(out); 110 111 return (err < 0) ? err : count; 112} 113static DEVICE_ATTR_RW(name); 114#endif 115 116static ssize_t channelmap_show(struct device *dev, 117 struct device_attribute *attr, char *buf) 118{ 119 struct mISDNdevice *mdev = dev_to_mISDN(dev); 120 char *bp = buf; 121 int i; 122 123 for (i = 0; i <= mdev->nrbchan; i++) 124 *bp++ = test_channelmap(i, mdev->channelmap) ? '1' : '0'; 125 126 return bp - buf; 127} 128static DEVICE_ATTR_RO(channelmap); 129 130static struct attribute *mISDN_attrs[] = { 131 &dev_attr_id.attr, 132 &dev_attr_d_protocols.attr, 133 &dev_attr_b_protocols.attr, 134 &dev_attr_protocol.attr, 135 &dev_attr_channelmap.attr, 136 &dev_attr_nrbchan.attr, 137 &dev_attr_name.attr, 138 NULL, 139}; 140ATTRIBUTE_GROUPS(mISDN); 141 142static int mISDN_uevent(const struct device *dev, struct kobj_uevent_env *env) 143{ 144 const struct mISDNdevice *mdev = dev_to_mISDN(dev); 145 146 if (!mdev) 147 return 0; 148 149 if (add_uevent_var(env, "nchans=%d", mdev->nrbchan)) 150 return -ENOMEM; 151 152 return 0; 153} 154 155static struct class mISDN_class = { 156 .name = "mISDN", 157 .dev_uevent = mISDN_uevent, 158 .dev_groups = mISDN_groups, 159 .dev_release = mISDN_dev_release, 160}; 161 162static int 163_get_mdevice(struct device *dev, const void *id) 164{ 165 struct mISDNdevice *mdev = dev_to_mISDN(dev); 166 167 if (!mdev) 168 return 0; 169 if (mdev->id != *(const u_int *)id) 170 return 0; 171 return 1; 172} 173 174struct mISDNdevice 175*get_mdevice(u_int id) 176{ 177 return dev_to_mISDN(class_find_device(&mISDN_class, NULL, &id, 178 _get_mdevice)); 179} 180 181static int 182_get_mdevice_count(struct device *dev, void *cnt) 183{ 184 *(int *)cnt += 1; 185 return 0; 186} 187 188int 189get_mdevice_count(void) 190{ 191 int cnt = 0; 192 193 class_for_each_device(&mISDN_class, NULL, &cnt, _get_mdevice_count); 194 return cnt; 195} 196 197static int 198get_free_devid(void) 199{ 200 u_int i; 201 202 for (i = 0; i <= MAX_DEVICE_ID; i++) 203 if (!test_and_set_bit(i, (u_long *)&device_ids)) 204 break; 205 if (i > MAX_DEVICE_ID) 206 return -EBUSY; 207 return i; 208} 209 210int 211mISDN_register_device(struct mISDNdevice *dev, 212 struct device *parent, char *name) 213{ 214 int err; 215 216 err = get_free_devid(); 217 if (err < 0) 218 return err; 219 dev->id = err; 220 221 device_initialize(&dev->dev); 222 if (name && name[0]) 223 dev_set_name(&dev->dev, "%s", name); 224 else 225 dev_set_name(&dev->dev, "mISDN%d", dev->id); 226 if (debug & DEBUG_CORE) 227 printk(KERN_DEBUG "mISDN_register %s %d\n", 228 dev_name(&dev->dev), dev->id); 229 dev->dev.class = &mISDN_class; 230 231 err = create_stack(dev); 232 if (err) 233 goto error1; 234 235 dev->dev.platform_data = dev; 236 dev->dev.parent = parent; 237 dev_set_drvdata(&dev->dev, dev); 238 239 err = device_add(&dev->dev); 240 if (err) 241 goto error3; 242 return 0; 243 244error3: 245 delete_stack(dev); 246error1: 247 put_device(&dev->dev); 248 return err; 249 250} 251EXPORT_SYMBOL(mISDN_register_device); 252 253void 254mISDN_unregister_device(struct mISDNdevice *dev) { 255 if (debug & DEBUG_CORE) 256 printk(KERN_DEBUG "mISDN_unregister %s %d\n", 257 dev_name(&dev->dev), dev->id); 258 /* sysfs_remove_link(&dev->dev.kobj, "device"); */ 259 device_del(&dev->dev); 260 dev_set_drvdata(&dev->dev, NULL); 261 262 test_and_clear_bit(dev->id, (u_long *)&device_ids); 263 delete_stack(dev); 264 put_device(&dev->dev); 265} 266EXPORT_SYMBOL(mISDN_unregister_device); 267 268u_int 269get_all_Bprotocols(void) 270{ 271 struct Bprotocol *bp; 272 u_int m = 0; 273 274 read_lock(&bp_lock); 275 list_for_each_entry(bp, &Bprotocols, list) 276 m |= bp->Bprotocols; 277 read_unlock(&bp_lock); 278 return m; 279} 280 281struct Bprotocol * 282get_Bprotocol4mask(u_int m) 283{ 284 struct Bprotocol *bp; 285 286 read_lock(&bp_lock); 287 list_for_each_entry(bp, &Bprotocols, list) 288 if (bp->Bprotocols & m) { 289 read_unlock(&bp_lock); 290 return bp; 291 } 292 read_unlock(&bp_lock); 293 return NULL; 294} 295 296struct Bprotocol * 297get_Bprotocol4id(u_int id) 298{ 299 u_int m; 300 301 if (id < ISDN_P_B_START || id > 63) { 302 printk(KERN_WARNING "%s id not in range %d\n", 303 __func__, id); 304 return NULL; 305 } 306 m = 1 << (id & ISDN_P_B_MASK); 307 return get_Bprotocol4mask(m); 308} 309 310int 311mISDN_register_Bprotocol(struct Bprotocol *bp) 312{ 313 u_long flags; 314 struct Bprotocol *old; 315 316 if (debug & DEBUG_CORE) 317 printk(KERN_DEBUG "%s: %s/%x\n", __func__, 318 bp->name, bp->Bprotocols); 319 old = get_Bprotocol4mask(bp->Bprotocols); 320 if (old) { 321 printk(KERN_WARNING 322 "register duplicate protocol old %s/%x new %s/%x\n", 323 old->name, old->Bprotocols, bp->name, bp->Bprotocols); 324 return -EBUSY; 325 } 326 write_lock_irqsave(&bp_lock, flags); 327 list_add_tail(&bp->list, &Bprotocols); 328 write_unlock_irqrestore(&bp_lock, flags); 329 return 0; 330} 331EXPORT_SYMBOL(mISDN_register_Bprotocol); 332 333void 334mISDN_unregister_Bprotocol(struct Bprotocol *bp) 335{ 336 u_long flags; 337 338 if (debug & DEBUG_CORE) 339 printk(KERN_DEBUG "%s: %s/%x\n", __func__, bp->name, 340 bp->Bprotocols); 341 write_lock_irqsave(&bp_lock, flags); 342 list_del(&bp->list); 343 write_unlock_irqrestore(&bp_lock, flags); 344} 345EXPORT_SYMBOL(mISDN_unregister_Bprotocol); 346 347static const char *msg_no_channel = "<no channel>"; 348static const char *msg_no_stack = "<no stack>"; 349static const char *msg_no_stackdev = "<no stack device>"; 350 351const char *mISDNDevName4ch(struct mISDNchannel *ch) 352{ 353 if (!ch) 354 return msg_no_channel; 355 if (!ch->st) 356 return msg_no_stack; 357 if (!ch->st->dev) 358 return msg_no_stackdev; 359 return dev_name(&ch->st->dev->dev); 360}; 361EXPORT_SYMBOL(mISDNDevName4ch); 362 363static int 364mISDNInit(void) 365{ 366 int err; 367 368 printk(KERN_INFO "Modular ISDN core version %d.%d.%d\n", 369 MISDN_MAJOR_VERSION, MISDN_MINOR_VERSION, MISDN_RELEASE); 370 mISDN_init_clock(&debug); 371 mISDN_initstack(&debug); 372 err = class_register(&mISDN_class); 373 if (err) 374 goto error1; 375 err = mISDN_inittimer(&debug); 376 if (err) 377 goto error2; 378 err = Isdnl1_Init(&debug); 379 if (err) 380 goto error3; 381 err = Isdnl2_Init(&debug); 382 if (err) 383 goto error4; 384 err = misdn_sock_init(&debug); 385 if (err) 386 goto error5; 387 return 0; 388 389error5: 390 Isdnl2_cleanup(); 391error4: 392 Isdnl1_cleanup(); 393error3: 394 mISDN_timer_cleanup(); 395error2: 396 class_unregister(&mISDN_class); 397error1: 398 return err; 399} 400 401static void mISDN_cleanup(void) 402{ 403 misdn_sock_cleanup(); 404 Isdnl2_cleanup(); 405 Isdnl1_cleanup(); 406 mISDN_timer_cleanup(); 407 class_unregister(&mISDN_class); 408 409 printk(KERN_DEBUG "mISDNcore unloaded\n"); 410} 411 412module_init(mISDNInit); 413module_exit(mISDN_cleanup); 414