Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at 33bc227e4e48ddadcf2eacb381c19df338f0a6c8 170 lines 3.6 kB view raw
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 17#include <linux/module.h> 18#include <linux/types.h> 19#include <linux/kernel.h> 20#include <linux/fs.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 29#include <linux/kmod.h> 30#include <linux/sem.h> 31#include <linux/devfs_fs_kernel.h> 32 33#define PHONE_NUM_DEVICES 256 34 35/* 36 * Active devices 37 */ 38 39static struct phone_device *phone_device[PHONE_NUM_DEVICES]; 40static DECLARE_MUTEX(phone_lock); 41 42/* 43 * Open a phone device. 44 */ 45 46static int phone_open(struct inode *inode, struct file *file) 47{ 48 unsigned int minor = iminor(inode); 49 int err = 0; 50 struct phone_device *p; 51 struct file_operations *old_fops, *new_fops = NULL; 52 53 if (minor >= PHONE_NUM_DEVICES) 54 return -ENODEV; 55 56 down(&phone_lock); 57 p = phone_device[minor]; 58 if (p) 59 new_fops = fops_get(p->f_op); 60 if (!new_fops) { 61 up(&phone_lock); 62 request_module("char-major-%d-%d", PHONE_MAJOR, minor); 63 down(&phone_lock); 64 p = phone_device[minor]; 65 if (p == NULL || (new_fops = fops_get(p->f_op)) == NULL) 66 { 67 err=-ENODEV; 68 goto end; 69 } 70 } 71 old_fops = file->f_op; 72 file->f_op = new_fops; 73 if (p->open) 74 err = p->open(p, file); /* Tell the device it is open */ 75 if (err) { 76 fops_put(file->f_op); 77 file->f_op = fops_get(old_fops); 78 } 79 fops_put(old_fops); 80end: 81 up(&phone_lock); 82 return err; 83} 84 85/* 86 * Telephony For Linux device drivers request registration here. 87 */ 88 89int phone_register_device(struct phone_device *p, int unit) 90{ 91 int base; 92 int end; 93 int i; 94 95 base = 0; 96 end = PHONE_NUM_DEVICES - 1; 97 98 if (unit != PHONE_UNIT_ANY) { 99 base = unit; 100 end = unit + 1; /* enter the loop at least one time */ 101 } 102 103 down(&phone_lock); 104 for (i = base; i < end; i++) { 105 if (phone_device[i] == NULL) { 106 phone_device[i] = p; 107 p->minor = i; 108 devfs_mk_cdev(MKDEV(PHONE_MAJOR,i), 109 S_IFCHR|S_IRUSR|S_IWUSR, "phone/%d", i); 110 up(&phone_lock); 111 return 0; 112 } 113 } 114 up(&phone_lock); 115 return -ENFILE; 116} 117 118/* 119 * Unregister an unused Telephony for linux device 120 */ 121 122void phone_unregister_device(struct phone_device *pfd) 123{ 124 down(&phone_lock); 125 if (phone_device[pfd->minor] != pfd) 126 panic("phone: bad unregister"); 127 devfs_remove("phone/%d", pfd->minor); 128 phone_device[pfd->minor] = NULL; 129 up(&phone_lock); 130} 131 132 133static struct file_operations phone_fops = 134{ 135 .owner = THIS_MODULE, 136 .open = phone_open, 137}; 138 139/* 140 * Board init functions 141 */ 142 143 144/* 145 * Initialise Telephony for linux 146 */ 147 148static int __init telephony_init(void) 149{ 150 printk(KERN_INFO "Linux telephony interface: v1.00\n"); 151 if (register_chrdev(PHONE_MAJOR, "telephony", &phone_fops)) { 152 printk("phonedev: unable to get major %d\n", PHONE_MAJOR); 153 return -EIO; 154 } 155 156 return 0; 157} 158 159static void __exit telephony_exit(void) 160{ 161 unregister_chrdev(PHONE_MAJOR, "telephony"); 162} 163 164module_init(telephony_init); 165module_exit(telephony_exit); 166 167MODULE_LICENSE("GPL"); 168 169EXPORT_SYMBOL(phone_register_device); 170EXPORT_SYMBOL(phone_unregister_device);