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