phonedev.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:3k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *            Telephony registration for Linux
  3.  *
  4.  *              (c) Copyright 1999 Red Hat Software Inc.
  5.  *
  6.  *              This program is free software; you can redistribute it and/or
  7.  *              modify it under the terms of the GNU General Public License
  8.  *              as published by the Free Software Foundation; either version
  9.  *              2 of the License, or (at your option) any later version.
  10.  *
  11.  * Author:      Alan Cox, <alan@redhat.com>
  12.  *
  13.  * Fixes:       Mar 01 2000 Thomas Sparr, <thomas.l.sparr@telia.com>
  14.  *              phone_register_device now works with unit!=PHONE_UNIT_ANY
  15.  */
  16. #include <linux/version.h>
  17. #include <linux/module.h>
  18. #include <linux/types.h>
  19. #include <linux/kernel.h>
  20. #include <linux/sched.h>
  21. #include <linux/mm.h>
  22. #include <linux/string.h>
  23. #include <linux/errno.h>
  24. #include <linux/phonedev.h>
  25. #include <linux/init.h>
  26. #include <asm/uaccess.h>
  27. #include <asm/system.h>
  28. #include <linux/kmod.h>
  29. #include <linux/sem.h>
  30. #define PHONE_NUM_DEVICES 256
  31. /*
  32.  *    Active devices 
  33.  */
  34. static struct phone_device *phone_device[PHONE_NUM_DEVICES];
  35. static DECLARE_MUTEX(phone_lock);
  36. /*
  37.  *    Open a phone device.
  38.  */
  39. static int phone_open(struct inode *inode, struct file *file)
  40. {
  41. unsigned int minor = MINOR(inode->i_rdev);
  42. int err = 0;
  43. struct phone_device *p;
  44. struct file_operations *old_fops, *new_fops = NULL;
  45. if (minor >= PHONE_NUM_DEVICES)
  46. return -ENODEV;
  47. down(&phone_lock);
  48. p = phone_device[minor];
  49. if (p)
  50. new_fops = fops_get(p->f_op);
  51. if (!new_fops) {
  52. char modname[32];
  53. up(&phone_lock);
  54. sprintf(modname, "char-major-%d-%d", PHONE_MAJOR, minor);
  55. request_module(modname);
  56. down(&phone_lock);
  57. p = phone_device[minor];
  58. if (p == NULL || (new_fops = fops_get(p->f_op)) == NULL)
  59. {
  60. err=-ENODEV;
  61. goto end;
  62. }
  63. }
  64. old_fops = file->f_op;
  65. file->f_op = new_fops;
  66. if (p->open)
  67. err = p->open(p, file); /* Tell the device it is open */
  68. if (err) {
  69. fops_put(file->f_op);
  70. file->f_op = fops_get(old_fops);
  71. }
  72. fops_put(old_fops);
  73. end:
  74. up(&phone_lock);
  75. return err;
  76. }
  77. /*
  78.  *    Telephony For Linux device drivers request registration here.
  79.  */
  80. int phone_register_device(struct phone_device *p, int unit)
  81. {
  82. int base;
  83. int end;
  84. int i;
  85. base = 0;
  86. end = PHONE_NUM_DEVICES - 1;
  87. if (unit != PHONE_UNIT_ANY) {
  88. base = unit;
  89. end = unit + 1;  /* enter the loop at least one time */
  90. }
  91. down(&phone_lock);
  92. for (i = base; i < end; i++) {
  93. if (phone_device[i] == NULL) {
  94. phone_device[i] = p;
  95. p->minor = i;
  96. MOD_INC_USE_COUNT;
  97. up(&phone_lock);
  98. return 0;
  99. }
  100. }
  101. up(&phone_lock);
  102. return -ENFILE;
  103. }
  104. /*
  105.  *    Unregister an unused Telephony for linux device
  106.  */
  107. void phone_unregister_device(struct phone_device *pfd)
  108. {
  109. down(&phone_lock);
  110. if (phone_device[pfd->minor] != pfd)
  111. panic("phone: bad unregister");
  112. phone_device[pfd->minor] = NULL;
  113. up(&phone_lock);
  114. MOD_DEC_USE_COUNT;
  115. }
  116. static struct file_operations phone_fops =
  117. {
  118. owner: THIS_MODULE,
  119. open: phone_open,
  120. };
  121. /*
  122.  * Board init functions
  123.  */
  124.  
  125. /*
  126.  *    Initialise Telephony for linux
  127.  */
  128. static int __init telephony_init(void)
  129. {
  130. printk(KERN_INFO "Linux telephony interface: v1.00n");
  131. if (register_chrdev(PHONE_MAJOR, "telephony", &phone_fops)) {
  132. printk("phonedev: unable to get major %dn", PHONE_MAJOR);
  133. return -EIO;
  134. }
  135. return 0;
  136. }
  137. static void __exit telephony_exit(void)
  138. {
  139. unregister_chrdev(PHONE_MAJOR, "telephony");
  140. }
  141. module_init(telephony_init);
  142. module_exit(telephony_exit);
  143. MODULE_LICENSE("GPL");
  144. EXPORT_SYMBOL(phone_register_device);
  145. EXPORT_SYMBOL(phone_unregister_device);