package/swconfig: add sanity checks to prevent a segfault
[openwrt.git] / package / lqtapi / src / tapi / tapi-core.c
1 #include <linux/kernel.h>
2 #include <linux/module.h>
3 #include <linux/device.h>
4 #include <linux/list.h>
5
6 #include <linux/cdev.h>
7 #include <linux/err.h>
8
9 #include <linux/tapi/tapi.h>
10
11
12 void tapi_alloc_input(struct tapi_device *tdev, struct tapi_port *port);
13 int tapi_register_port_device(struct tapi_device* tdev, struct tapi_port *port);
14 int tapi_register_stream_device(struct tapi_device* tdev);
15 int tapi_register_control_device(struct tapi_device* tdev);
16
17 static struct class *tapi_class;
18 static int tapi_major;
19
20 #define TAPI_MAX_MINORS 255
21
22 static bool tapi_minors[TAPI_MAX_MINORS];
23
24 static int tapi_get_free_minor(void)
25 {
26 int i;
27 for (i = 0; i < TAPI_MAX_MINORS; ++i) {
28 if (!tapi_minors[i]) {
29 tapi_minors[i] = true;
30 return i;
31 }
32 }
33
34 return -1;
35 }
36
37 /*
38 int tapi_port_send_dtmf_events(struct tapi_device *tdev, unsigned int port, struct tapi_dtmf *, size_t num_events, unsigned int dealy)
39 {
40 }
41 EXPORT_SYMBOL_GPL(tapi_port_send_dtmf_events);
42 */
43
44 void tapi_report_hook_event(struct tapi_device *tdev, struct tapi_port *port,
45 bool on)
46 {
47 struct tapi_event event;
48 event.type = TAPI_EVENT_TYPE_HOOK;
49 event.port = port->id;
50 event.hook.on = on;
51
52 tapi_report_event(tdev, &event);
53 }
54 EXPORT_SYMBOL_GPL(tapi_report_hook_event);
55
56 void tapi_report_dtmf_event(struct tapi_device *tdev, struct tapi_port *port,
57 unsigned char code)
58 {
59 struct tapi_event event;
60 event.type = TAPI_EVENT_TYPE_DTMF;
61 event.port = port->id;
62 event.dtmf.code = code;
63
64 tapi_report_event(tdev, &event);
65 }
66 EXPORT_SYMBOL_GPL(tapi_report_dtmf_event);
67
68 struct tapi_stream *tapi_stream_alloc(struct tapi_device *tdev)
69 {
70 struct tapi_stream *stream;
71 printk("tdev %p\n", tdev);
72
73 if (!tdev->ops || !tdev->ops->stream_alloc)
74 return ERR_PTR(-ENOSYS);
75
76 stream = tdev->ops->stream_alloc(tdev);
77 printk("stream %p\n", stream);
78 if (IS_ERR(stream))
79 return stream;
80
81 stream->id = atomic_inc_return(&tdev->stream_id) - 1;
82 stream->ep.id = stream->id;
83
84 /* mutex_lock(&tdev->lock);*/
85 list_add_tail(&stream->head, &tdev->streams);
86 /* mutex_unlock(&tdev->lock);*/
87
88 return stream;
89 }
90 EXPORT_SYMBOL_GPL(tapi_stream_alloc);
91
92 void tapi_stream_free(struct tapi_device *tdev, struct tapi_stream *stream)
93 {
94 mutex_lock(&tdev->lock);
95 list_del(&stream->head);
96 mutex_unlock(&tdev->lock);
97
98 tdev->ops->stream_free(tdev, stream);
99 }
100 EXPORT_SYMBOL_GPL(tapi_stream_free);
101
102 struct tapi_link *tapi_link_alloc(struct tapi_device *tdev,
103 struct tapi_endpoint *ep1, struct tapi_endpoint *ep2)
104 {
105 struct tapi_link *link;
106
107 if (!tdev->ops || !tdev->ops->link_alloc)
108 return ERR_PTR(-ENOSYS);
109
110 link = tdev->ops->link_alloc(tdev, ep1, ep2);
111 if (IS_ERR(link))
112 return link;
113
114 link->id = atomic_inc_return(&tdev->link_id) - 1;
115
116 /*
117 mutex_lock(&tdev->lock);
118 list_add_tail(&link->head, &tdev->links);
119 mutex_unlock(&tdev->lock);
120 */
121 return link;
122 }
123 EXPORT_SYMBOL_GPL(tapi_link_alloc);
124
125 void tapi_link_free(struct tapi_device *tdev, struct tapi_link *link)
126 {
127 /*
128 mutex_lock(&tdev->lock);
129 list_del(&link->head);
130 mutex_unlock(&tdev->lock);
131 */
132 tdev->ops->link_free(tdev, link);
133 }
134 EXPORT_SYMBOL_GPL(tapi_link_free);
135
136 int tapi_char_device_register(struct tapi_device *tdev,
137 struct tapi_char_device *tchrdev, const struct file_operations *fops)
138 {
139 int ret;
140 struct device *dev = &tchrdev->dev;
141 dev_t devt;
142 int minor = tapi_get_free_minor();
143
144 devt = MKDEV(tapi_major, minor);
145
146 dev->devt = devt;
147 dev->class = tapi_class;
148 dev->parent = &tdev->dev;
149
150 tchrdev->tdev = tdev;
151
152 cdev_init(&tchrdev->cdev, fops);
153 tchrdev->cdev.owner = THIS_MODULE;
154 ret = cdev_add(&tchrdev->cdev, devt, 1);
155 if (ret)
156 return ret;
157
158 ret = device_register(&tchrdev->dev);
159 if (ret)
160 goto err_cdev_del;
161
162 return 0;
163
164 err_cdev_del:
165 cdev_del(&tchrdev->cdev);
166
167 return ret;
168 }
169
170 int tapi_device_register(struct tapi_device *tdev, const char *name,
171 struct device *parent)
172 {
173 static atomic_t tapi_device_id = ATOMIC_INIT(0);
174 int ret, i;
175
176 tdev->dev.class = tapi_class;
177 tdev->dev.parent = parent;
178 dev_set_name(&tdev->dev, "%s", name);
179
180 ret = device_register(&tdev->dev);
181 if (ret)
182 return ret;
183
184 tdev->id = atomic_inc_return(&tapi_device_id) - 1;
185
186 mutex_init(&tdev->lock);
187 INIT_LIST_HEAD(&tdev->streams);
188 INIT_LIST_HEAD(&tdev->links);
189 atomic_set(&tdev->link_id, 0);
190 atomic_set(&tdev->stream_id, tdev->num_ports);
191
192 tapi_register_stream_device(tdev);
193 tapi_register_control_device(tdev);
194
195 for (i = 0; i < tdev->num_ports; ++i) {
196 tapi_port_alloc(tdev, i);
197 tapi_alloc_input(tdev, &tdev->ports[i]);
198 tapi_register_port_device(tdev, &tdev->ports[i]);
199 tdev->ports[i].id = i;
200 tdev->ports[i].ep.id = i;
201 }
202
203 return 0;
204 }
205 EXPORT_SYMBOL_GPL(tapi_device_register);
206
207 void tapi_device_unregister(struct tapi_device *tdev)
208 {
209 device_unregister(&tdev->dev);
210 }
211 EXPORT_SYMBOL_GPL(tapi_device_unregister);
212
213 static int __init tapi_class_init(void)
214 {
215 int ret;
216 dev_t dev;
217
218 tapi_class = class_create(THIS_MODULE, "tapi");
219
220 if (IS_ERR(tapi_class)) {
221 ret = PTR_ERR(tapi_class);
222 printk(KERN_ERR "tapi: Failed to create device class: %d\n", ret);
223 goto err;
224 }
225
226 ret = alloc_chrdev_region(&dev, 0, TAPI_MAX_MINORS, "tapi");
227 if (ret) {
228 printk(KERN_ERR "tapi: Failed to allocate chrdev region: %d\n", ret);
229 goto err_class_destory;
230 }
231 tapi_major = MAJOR(dev);
232
233 return 0;
234 err_class_destory:
235 class_destroy(tapi_class);
236 err:
237 return ret;
238 }
239 subsys_initcall(tapi_class_init);
240
241 static void __exit tapi_class_exit(void)
242 {
243 unregister_chrdev_region(MKDEV(tapi_major, 0), TAPI_MAX_MINORS);
244 class_destroy(tapi_class);
245 }
246 module_exit(tapi_class_exit);
247
248 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
249 MODULE_DESCRIPTION("TAPI class");
250 MODULE_LICENSE("GPL");
This page took 0.088211 seconds and 5 git commands to generate.