root/drivers/isdn/mISDN/core.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mISDN_dev_release
  2. id_show
  3. nrbchan_show
  4. d_protocols_show
  5. b_protocols_show
  6. protocol_show
  7. name_show
  8. name_set
  9. channelmap_show
  10. mISDN_uevent
  11. mISDN_class_release
  12. _get_mdevice
  13. get_mdevice
  14. _get_mdevice_count
  15. get_mdevice_count
  16. get_free_devid
  17. mISDN_register_device
  18. mISDN_unregister_device
  19. get_all_Bprotocols
  20. get_Bprotocol4mask
  21. get_Bprotocol4id
  22. mISDN_register_Bprotocol
  23. mISDN_unregister_Bprotocol
  24. mISDNDevName4ch
  25. mISDNInit
  26. mISDN_cleanup

   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 
  14 static u_int debug;
  15 
  16 MODULE_AUTHOR("Karsten Keil");
  17 MODULE_LICENSE("GPL");
  18 module_param(debug, uint, S_IRUGO | S_IWUSR);
  19 
  20 static u64              device_ids;
  21 #define MAX_DEVICE_ID   63
  22 
  23 static LIST_HEAD(Bprotocols);
  24 static DEFINE_RWLOCK(bp_lock);
  25 
  26 static void mISDN_dev_release(struct device *dev)
  27 {
  28         /* nothing to do: the device is part of its parent's data structure */
  29 }
  30 
  31 static 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 }
  40 static DEVICE_ATTR_RO(id);
  41 
  42 static 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 }
  51 static DEVICE_ATTR_RO(nrbchan);
  52 
  53 static 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 }
  62 static DEVICE_ATTR_RO(d_protocols);
  63 
  64 static 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 }
  73 static DEVICE_ATTR_RO(b_protocols);
  74 
  75 static 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 }
  84 static DEVICE_ATTR_RO(protocol);
  85 
  86 static 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 }
  92 static DEVICE_ATTR_RO(name);
  93 
  94 #if 0 /* hangs */
  95 static 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 }
 113 static DEVICE_ATTR_RW(name);
 114 #endif
 115 
 116 static 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 }
 128 static DEVICE_ATTR_RO(channelmap);
 129 
 130 static 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 };
 140 ATTRIBUTE_GROUPS(mISDN);
 141 
 142 static int mISDN_uevent(struct device *dev, struct kobj_uevent_env *env)
 143 {
 144         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 
 155 static void mISDN_class_release(struct class *cls)
 156 {
 157         /* do nothing, it's static */
 158 }
 159 
 160 static struct class mISDN_class = {
 161         .name = "mISDN",
 162         .owner = THIS_MODULE,
 163         .dev_uevent = mISDN_uevent,
 164         .dev_groups = mISDN_groups,
 165         .dev_release = mISDN_dev_release,
 166         .class_release = mISDN_class_release,
 167 };
 168 
 169 static int
 170 _get_mdevice(struct device *dev, const void *id)
 171 {
 172         struct mISDNdevice *mdev = dev_to_mISDN(dev);
 173 
 174         if (!mdev)
 175                 return 0;
 176         if (mdev->id != *(const u_int *)id)
 177                 return 0;
 178         return 1;
 179 }
 180 
 181 struct mISDNdevice
 182 *get_mdevice(u_int id)
 183 {
 184         return dev_to_mISDN(class_find_device(&mISDN_class, NULL, &id,
 185                                               _get_mdevice));
 186 }
 187 
 188 static int
 189 _get_mdevice_count(struct device *dev, void *cnt)
 190 {
 191         *(int *)cnt += 1;
 192         return 0;
 193 }
 194 
 195 int
 196 get_mdevice_count(void)
 197 {
 198         int cnt = 0;
 199 
 200         class_for_each_device(&mISDN_class, NULL, &cnt, _get_mdevice_count);
 201         return cnt;
 202 }
 203 
 204 static int
 205 get_free_devid(void)
 206 {
 207         u_int   i;
 208 
 209         for (i = 0; i <= MAX_DEVICE_ID; i++)
 210                 if (!test_and_set_bit(i, (u_long *)&device_ids))
 211                         break;
 212         if (i > MAX_DEVICE_ID)
 213                 return -EBUSY;
 214         return i;
 215 }
 216 
 217 int
 218 mISDN_register_device(struct mISDNdevice *dev,
 219                       struct device *parent, char *name)
 220 {
 221         int     err;
 222 
 223         err = get_free_devid();
 224         if (err < 0)
 225                 goto error1;
 226         dev->id = err;
 227 
 228         device_initialize(&dev->dev);
 229         if (name && name[0])
 230                 dev_set_name(&dev->dev, "%s", name);
 231         else
 232                 dev_set_name(&dev->dev, "mISDN%d", dev->id);
 233         if (debug & DEBUG_CORE)
 234                 printk(KERN_DEBUG "mISDN_register %s %d\n",
 235                        dev_name(&dev->dev), dev->id);
 236         err = create_stack(dev);
 237         if (err)
 238                 goto error1;
 239 
 240         dev->dev.class = &mISDN_class;
 241         dev->dev.platform_data = dev;
 242         dev->dev.parent = parent;
 243         dev_set_drvdata(&dev->dev, dev);
 244 
 245         err = device_add(&dev->dev);
 246         if (err)
 247                 goto error3;
 248         return 0;
 249 
 250 error3:
 251         delete_stack(dev);
 252         return err;
 253 error1:
 254         return err;
 255 
 256 }
 257 EXPORT_SYMBOL(mISDN_register_device);
 258 
 259 void
 260 mISDN_unregister_device(struct mISDNdevice *dev) {
 261         if (debug & DEBUG_CORE)
 262                 printk(KERN_DEBUG "mISDN_unregister %s %d\n",
 263                        dev_name(&dev->dev), dev->id);
 264         /* sysfs_remove_link(&dev->dev.kobj, "device"); */
 265         device_del(&dev->dev);
 266         dev_set_drvdata(&dev->dev, NULL);
 267 
 268         test_and_clear_bit(dev->id, (u_long *)&device_ids);
 269         delete_stack(dev);
 270         put_device(&dev->dev);
 271 }
 272 EXPORT_SYMBOL(mISDN_unregister_device);
 273 
 274 u_int
 275 get_all_Bprotocols(void)
 276 {
 277         struct Bprotocol        *bp;
 278         u_int   m = 0;
 279 
 280         read_lock(&bp_lock);
 281         list_for_each_entry(bp, &Bprotocols, list)
 282                 m |= bp->Bprotocols;
 283         read_unlock(&bp_lock);
 284         return m;
 285 }
 286 
 287 struct Bprotocol *
 288 get_Bprotocol4mask(u_int m)
 289 {
 290         struct Bprotocol        *bp;
 291 
 292         read_lock(&bp_lock);
 293         list_for_each_entry(bp, &Bprotocols, list)
 294                 if (bp->Bprotocols & m) {
 295                         read_unlock(&bp_lock);
 296                         return bp;
 297                 }
 298         read_unlock(&bp_lock);
 299         return NULL;
 300 }
 301 
 302 struct Bprotocol *
 303 get_Bprotocol4id(u_int id)
 304 {
 305         u_int   m;
 306 
 307         if (id < ISDN_P_B_START || id > 63) {
 308                 printk(KERN_WARNING "%s id not in range  %d\n",
 309                        __func__, id);
 310                 return NULL;
 311         }
 312         m = 1 << (id & ISDN_P_B_MASK);
 313         return get_Bprotocol4mask(m);
 314 }
 315 
 316 int
 317 mISDN_register_Bprotocol(struct Bprotocol *bp)
 318 {
 319         u_long                  flags;
 320         struct Bprotocol        *old;
 321 
 322         if (debug & DEBUG_CORE)
 323                 printk(KERN_DEBUG "%s: %s/%x\n", __func__,
 324                        bp->name, bp->Bprotocols);
 325         old = get_Bprotocol4mask(bp->Bprotocols);
 326         if (old) {
 327                 printk(KERN_WARNING
 328                        "register duplicate protocol old %s/%x new %s/%x\n",
 329                        old->name, old->Bprotocols, bp->name, bp->Bprotocols);
 330                 return -EBUSY;
 331         }
 332         write_lock_irqsave(&bp_lock, flags);
 333         list_add_tail(&bp->list, &Bprotocols);
 334         write_unlock_irqrestore(&bp_lock, flags);
 335         return 0;
 336 }
 337 EXPORT_SYMBOL(mISDN_register_Bprotocol);
 338 
 339 void
 340 mISDN_unregister_Bprotocol(struct Bprotocol *bp)
 341 {
 342         u_long  flags;
 343 
 344         if (debug & DEBUG_CORE)
 345                 printk(KERN_DEBUG "%s: %s/%x\n", __func__, bp->name,
 346                        bp->Bprotocols);
 347         write_lock_irqsave(&bp_lock, flags);
 348         list_del(&bp->list);
 349         write_unlock_irqrestore(&bp_lock, flags);
 350 }
 351 EXPORT_SYMBOL(mISDN_unregister_Bprotocol);
 352 
 353 static const char *msg_no_channel = "<no channel>";
 354 static const char *msg_no_stack = "<no stack>";
 355 static const char *msg_no_stackdev = "<no stack device>";
 356 
 357 const char *mISDNDevName4ch(struct mISDNchannel *ch)
 358 {
 359         if (!ch)
 360                 return msg_no_channel;
 361         if (!ch->st)
 362                 return msg_no_stack;
 363         if (!ch->st->dev)
 364                 return msg_no_stackdev;
 365         return dev_name(&ch->st->dev->dev);
 366 };
 367 EXPORT_SYMBOL(mISDNDevName4ch);
 368 
 369 static int
 370 mISDNInit(void)
 371 {
 372         int     err;
 373 
 374         printk(KERN_INFO "Modular ISDN core version %d.%d.%d\n",
 375                MISDN_MAJOR_VERSION, MISDN_MINOR_VERSION, MISDN_RELEASE);
 376         mISDN_init_clock(&debug);
 377         mISDN_initstack(&debug);
 378         err = class_register(&mISDN_class);
 379         if (err)
 380                 goto error1;
 381         err = mISDN_inittimer(&debug);
 382         if (err)
 383                 goto error2;
 384         err = l1_init(&debug);
 385         if (err)
 386                 goto error3;
 387         err = Isdnl2_Init(&debug);
 388         if (err)
 389                 goto error4;
 390         err = misdn_sock_init(&debug);
 391         if (err)
 392                 goto error5;
 393         return 0;
 394 
 395 error5:
 396         Isdnl2_cleanup();
 397 error4:
 398         l1_cleanup();
 399 error3:
 400         mISDN_timer_cleanup();
 401 error2:
 402         class_unregister(&mISDN_class);
 403 error1:
 404         return err;
 405 }
 406 
 407 static void mISDN_cleanup(void)
 408 {
 409         misdn_sock_cleanup();
 410         Isdnl2_cleanup();
 411         l1_cleanup();
 412         mISDN_timer_cleanup();
 413         class_unregister(&mISDN_class);
 414 
 415         printk(KERN_DEBUG "mISDNcore unloaded\n");
 416 }
 417 
 418 module_init(mISDNInit);
 419 module_exit(mISDN_cleanup);

/* [<][>][^][v][top][bottom][index][help] */