tapi-core.c 5.4 KB

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