Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
core.c
Go to the documentation of this file.
1 /*
2  * Copyright 2008 by Karsten Keil <[email protected]>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  */
14 
15 #include <linux/slab.h>
16 #include <linux/types.h>
17 #include <linux/stddef.h>
18 #include <linux/module.h>
19 #include <linux/spinlock.h>
20 #include <linux/mISDNif.h>
21 #include "core.h"
22 
23 static u_int debug;
24 
25 MODULE_AUTHOR("Karsten Keil");
26 MODULE_LICENSE("GPL");
28 
29 static u64 device_ids;
30 #define MAX_DEVICE_ID 63
31 
32 static LIST_HEAD(Bprotocols);
33 static DEFINE_RWLOCK(bp_lock);
34 
35 static void mISDN_dev_release(struct device *dev)
36 {
37  /* nothing to do: the device is part of its parent's data structure */
38 }
39 
40 static ssize_t _show_id(struct device *dev,
41  struct device_attribute *attr, char *buf)
42 {
43  struct mISDNdevice *mdev = dev_to_mISDN(dev);
44 
45  if (!mdev)
46  return -ENODEV;
47  return sprintf(buf, "%d\n", mdev->id);
48 }
49 
50 static ssize_t _show_nrbchan(struct device *dev,
51  struct device_attribute *attr, char *buf)
52 {
53  struct mISDNdevice *mdev = dev_to_mISDN(dev);
54 
55  if (!mdev)
56  return -ENODEV;
57  return sprintf(buf, "%d\n", mdev->nrbchan);
58 }
59 
60 static ssize_t _show_d_protocols(struct device *dev,
61  struct device_attribute *attr, char *buf)
62 {
63  struct mISDNdevice *mdev = dev_to_mISDN(dev);
64 
65  if (!mdev)
66  return -ENODEV;
67  return sprintf(buf, "%d\n", mdev->Dprotocols);
68 }
69 
70 static ssize_t _show_b_protocols(struct device *dev,
71  struct device_attribute *attr, char *buf)
72 {
73  struct mISDNdevice *mdev = dev_to_mISDN(dev);
74 
75  if (!mdev)
76  return -ENODEV;
77  return sprintf(buf, "%d\n", mdev->Bprotocols | get_all_Bprotocols());
78 }
79 
80 static ssize_t _show_protocol(struct device *dev,
81  struct device_attribute *attr, char *buf)
82 {
83  struct mISDNdevice *mdev = dev_to_mISDN(dev);
84 
85  if (!mdev)
86  return -ENODEV;
87  return sprintf(buf, "%d\n", mdev->D.protocol);
88 }
89 
90 static ssize_t _show_name(struct device *dev,
91  struct device_attribute *attr, char *buf)
92 {
93  strcpy(buf, dev_name(dev));
94  return strlen(buf);
95 }
96 
97 #if 0 /* hangs */
98 static ssize_t _set_name(struct device *dev, struct device_attribute *attr,
99  const char *buf, size_t count)
100 {
101  int err = 0;
102  char *out = kmalloc(count + 1, GFP_KERNEL);
103 
104  if (!out)
105  return -ENOMEM;
106 
107  memcpy(out, buf, count);
108  if (count && out[count - 1] == '\n')
109  out[--count] = 0;
110  if (count)
111  err = device_rename(dev, out);
112  kfree(out);
113 
114  return (err < 0) ? err : count;
115 }
116 #endif
117 
118 static ssize_t _show_channelmap(struct device *dev,
119  struct device_attribute *attr, char *buf)
120 {
121  struct mISDNdevice *mdev = dev_to_mISDN(dev);
122  char *bp = buf;
123  int i;
124 
125  for (i = 0; i <= mdev->nrbchan; i++)
126  *bp++ = test_channelmap(i, mdev->channelmap) ? '1' : '0';
127 
128  return bp - buf;
129 }
130 
131 static struct device_attribute mISDN_dev_attrs[] = {
132  __ATTR(id, S_IRUGO, _show_id, NULL),
133  __ATTR(d_protocols, S_IRUGO, _show_d_protocols, NULL),
134  __ATTR(b_protocols, S_IRUGO, _show_b_protocols, NULL),
135  __ATTR(protocol, S_IRUGO, _show_protocol, NULL),
136  __ATTR(channelmap, S_IRUGO, _show_channelmap, NULL),
137  __ATTR(nrbchan, S_IRUGO, _show_nrbchan, NULL),
138  __ATTR(name, S_IRUGO, _show_name, NULL),
139 /* __ATTR(name, S_IRUGO | S_IWUSR, _show_name, _set_name), */
140  {}
141 };
142 
143 #ifdef CONFIG_HOTPLUG
144 static int mISDN_uevent(struct device *dev, struct kobj_uevent_env *env)
145 {
146  struct mISDNdevice *mdev = dev_to_mISDN(dev);
147 
148  if (!mdev)
149  return 0;
150 
151  if (add_uevent_var(env, "nchans=%d", mdev->nrbchan))
152  return -ENOMEM;
153 
154  return 0;
155 }
156 #endif
157 
158 static void mISDN_class_release(struct class *cls)
159 {
160  /* do nothing, it's static */
161 }
162 
163 static struct class mISDN_class = {
164  .name = "mISDN",
165  .owner = THIS_MODULE,
166 #ifdef CONFIG_HOTPLUG
167  .dev_uevent = mISDN_uevent,
168 #endif
169  .dev_attrs = mISDN_dev_attrs,
170  .dev_release = mISDN_dev_release,
171  .class_release = mISDN_class_release,
172 };
173 
174 static int
175 _get_mdevice(struct device *dev, void *id)
176 {
177  struct mISDNdevice *mdev = dev_to_mISDN(dev);
178 
179  if (!mdev)
180  return 0;
181  if (mdev->id != *(u_int *)id)
182  return 0;
183  return 1;
184 }
185 
186 struct mISDNdevice
188 {
189  return dev_to_mISDN(class_find_device(&mISDN_class, NULL, &id,
190  _get_mdevice));
191 }
192 
193 static int
194 _get_mdevice_count(struct device *dev, void *cnt)
195 {
196  *(int *)cnt += 1;
197  return 0;
198 }
199 
200 int
202 {
203  int cnt = 0;
204 
205  class_for_each_device(&mISDN_class, NULL, &cnt, _get_mdevice_count);
206  return cnt;
207 }
208 
209 static int
210 get_free_devid(void)
211 {
212  u_int i;
213 
214  for (i = 0; i <= MAX_DEVICE_ID; i++)
215  if (!test_and_set_bit(i, (u_long *)&device_ids))
216  break;
217  if (i > MAX_DEVICE_ID)
218  return -EBUSY;
219  return i;
220 }
221 
222 int
223 mISDN_register_device(struct mISDNdevice *dev,
224  struct device *parent, char *name)
225 {
226  int err;
227 
228  err = get_free_devid();
229  if (err < 0)
230  goto error1;
231  dev->id = err;
232 
233  device_initialize(&dev->dev);
234  if (name && name[0])
235  dev_set_name(&dev->dev, "%s", name);
236  else
237  dev_set_name(&dev->dev, "mISDN%d", dev->id);
238  if (debug & DEBUG_CORE)
239  printk(KERN_DEBUG "mISDN_register %s %d\n",
240  dev_name(&dev->dev), dev->id);
241  err = create_stack(dev);
242  if (err)
243  goto error1;
244 
245  dev->dev.class = &mISDN_class;
246  dev->dev.platform_data = dev;
247  dev->dev.parent = parent;
248  dev_set_drvdata(&dev->dev, dev);
249 
250  err = device_add(&dev->dev);
251  if (err)
252  goto error3;
253  return 0;
254 
255 error3:
256  delete_stack(dev);
257  return err;
258 error1:
259  return err;
260 
261 }
263 
264 void
265 mISDN_unregister_device(struct mISDNdevice *dev) {
266  if (debug & DEBUG_CORE)
267  printk(KERN_DEBUG "mISDN_unregister %s %d\n",
268  dev_name(&dev->dev), dev->id);
269  /* sysfs_remove_link(&dev->dev.kobj, "device"); */
270  device_del(&dev->dev);
271  dev_set_drvdata(&dev->dev, NULL);
272 
273  test_and_clear_bit(dev->id, (u_long *)&device_ids);
274  delete_stack(dev);
275  put_device(&dev->dev);
276 }
278 
279 u_int
281 {
282  struct Bprotocol *bp;
283  u_int m = 0;
284 
285  read_lock(&bp_lock);
286  list_for_each_entry(bp, &Bprotocols, list)
287  m |= bp->Bprotocols;
288  read_unlock(&bp_lock);
289  return m;
290 }
291 
292 struct Bprotocol *
294 {
295  struct Bprotocol *bp;
296 
297  read_lock(&bp_lock);
298  list_for_each_entry(bp, &Bprotocols, list)
299  if (bp->Bprotocols & m) {
300  read_unlock(&bp_lock);
301  return bp;
302  }
303  read_unlock(&bp_lock);
304  return NULL;
305 }
306 
307 struct Bprotocol *
309 {
310  u_int m;
311 
313  printk(KERN_WARNING "%s id not in range %d\n",
314  __func__, id);
315  return NULL;
316  }
317  m = 1 << (id & ISDN_P_B_MASK);
318  return get_Bprotocol4mask(m);
319 }
320 
321 int
322 mISDN_register_Bprotocol(struct Bprotocol *bp)
323 {
324  u_long flags;
325  struct Bprotocol *old;
326 
327  if (debug & DEBUG_CORE)
328  printk(KERN_DEBUG "%s: %s/%x\n", __func__,
329  bp->name, bp->Bprotocols);
330  old = get_Bprotocol4mask(bp->Bprotocols);
331  if (old) {
333  "register duplicate protocol old %s/%x new %s/%x\n",
334  old->name, old->Bprotocols, bp->name, bp->Bprotocols);
335  return -EBUSY;
336  }
337  write_lock_irqsave(&bp_lock, flags);
338  list_add_tail(&bp->list, &Bprotocols);
339  write_unlock_irqrestore(&bp_lock, flags);
340  return 0;
341 }
343 
344 void
345 mISDN_unregister_Bprotocol(struct Bprotocol *bp)
346 {
347  u_long flags;
348 
349  if (debug & DEBUG_CORE)
350  printk(KERN_DEBUG "%s: %s/%x\n", __func__, bp->name,
351  bp->Bprotocols);
352  write_lock_irqsave(&bp_lock, flags);
353  list_del(&bp->list);
354  write_unlock_irqrestore(&bp_lock, flags);
355 }
357 
358 static const char *msg_no_channel = "<no channel>";
359 static const char *msg_no_stack = "<no stack>";
360 static const char *msg_no_stackdev = "<no stack device>";
361 
362 const char *mISDNDevName4ch(struct mISDNchannel *ch)
363 {
364  if (!ch)
365  return msg_no_channel;
366  if (!ch->st)
367  return msg_no_stack;
368  if (!ch->st->dev)
369  return msg_no_stackdev;
370  return dev_name(&ch->st->dev->dev);
371 };
373 
374 static int
375 mISDNInit(void)
376 {
377  int err;
378 
379  printk(KERN_INFO "Modular ISDN core version %d.%d.%d\n",
383  err = class_register(&mISDN_class);
384  if (err)
385  goto error1;
386  err = mISDN_inittimer(&debug);
387  if (err)
388  goto error2;
389  err = l1_init(&debug);
390  if (err)
391  goto error3;
392  err = Isdnl2_Init(&debug);
393  if (err)
394  goto error4;
395  err = misdn_sock_init(&debug);
396  if (err)
397  goto error5;
398  return 0;
399 
400 error5:
401  Isdnl2_cleanup();
402 error4:
403  l1_cleanup();
404 error3:
406 error2:
407  class_unregister(&mISDN_class);
408 error1:
409  return err;
410 }
411 
412 static void mISDN_cleanup(void)
413 {
415  Isdnl2_cleanup();
416  l1_cleanup();
418  class_unregister(&mISDN_class);
419 
420  printk(KERN_DEBUG "mISDNcore unloaded\n");
421 }
422 
423 module_init(mISDNInit);
424 module_exit(mISDN_cleanup);