The Linux Telephony Kernel API
At the operating system level, all devices are referred to by numbers. We look in /dev and see a collection of file names, but down deep Linux looks at devices based on a major and a minor number. Devices of a particular type all share a single major number; individual devices of that type must each have their own minor number. For example, if you do ls -al /dev/ttyS0 you'll see:
gherlein@tux:~/lj > ls -al /dev/ttyS0 crwxrwxr-x 1 root uucp 4, 64 Oct 27 06:23 /dev/ttyS0
Note that that the file permissions mask has the first character as a “c”, indicating that it's a character device. It's owned by root and is in the uucp group. The next two numbers are not file sizes, like you'd see on a normal file; they are the major and minor number. In this case ttyS0 has a major number of 4 and a minor number of 64.
The Linux Telephony API assigns the major device number of 100 to phone-type devices. Your distribution of Linux has probably not created the devices for you, like it has for /dev/ttyS*, /dev/audio and other older, commonly accepted device mappings. If /dev/phone* devices are not present on your system, you'll need to make them before using the Linux Telephony API. You can fix this yourself quickly with the following command (as root):
mknod /dev/phone0 c 100 0
This creates a new device file called /dev/phone0. It's a character device with a major number of 100 and a minor number of 0. Refer to the mknod man page for more details on this command. You only actually need enough device files for your hardware, but most folks create devices 0 15 by default.
Note that there is presently an error in the file /usr/src/linux/Documentation/devices.txt. This file, which provides official assignments for all major numbers it currently states that Linux telephony is to use major number 159 and that 100 is deprecated. This is an acknowledged error and will be fixed in future documentation. The correct major number for Linux telephony (and the number used in the kernel) is 100.
Alan Cox developed the phonedev module based on a similar approach that he took for the Video4Linux Project. There will be many vendors who create products capable of being a phone device. Rather than having multiple telephony product vendors, each requiring their own major number, they can all use major number 100 and the commonly defined /dev/phoneN (where N is the device number).
All of these must present a common basic interface to user-space software, that is, they must all follow the same common API.al, though they may provide extensions particular to their product. Vendors will create their own device driver module that will implement this common API as an external interface by dealing with the inner details of their particular hardware.
The phonedev module solved the problem of mapping the minor device number to a specific vendor-type module at runtime. The source code is in the files/usr/src/linux/drivers/telephony/phonedev.c and the header files, phonedev.h and telephony.h, are located in /usr/include/linux. Here's how it works.
Every phone device must use a phone_device structure (see Listing 1). Likewise, every phone device must call two functions to interact with the phonedev module in order to register and unregister itself. These are defined as:
extern int phone_register_device (struct phone_device *, int unit); extern void phone_unregister_device (struct phone_device *);
At load time, the phonedev module sets itself up and waits to service other telephony devices. When a telephony driver is loaded (by modprobe or insmod, as discussed later) it calls the phone_register_device function. A simple explanation of this function is that it keeps a pointer within the phonedev module to the phone_device structure, searches for the first open minor number and assigns that to the phone device, and then increments a counter to track the fact that something is using the phonedev module (to prevent it being unloaded while in use).
The practical implications of this are simple: the first telephony modules loaded will be assigned the first available (lowest numbered) minor numbers. This is crucial to understand in cases where modules from different vendors need to coexist on the same system, and specific assignment of a particular card is desired to match a particular minor number (a specific /dev/phoneN device). In other words, if you have a device from XYZ company and a device from ABC company, and you want ABC's card to be /dev/phone0, you'll have to make sure that the driver for ABC gets loaded first.
All devices must provide at least the basic functions to interact with the device: open, read, write, close, etc. These are all part of the “file operations structure” (see linux/fs.h for details). Each device defines the functions appropriate for itself.
Anytime a program opens a /dev/phoneN device, it's actually calling the fopen function defined in the phonedev module's file operations structure. This function performs the following operations:
It grabs the minor device number from /dev/phoneN inode.
It builds a string of the form char-major-%d-%d using the major and minor numbers. In the case of minor number 0 (corresponding to /dev/phone0), this string would be char-major-100-0.
It uses this string in a call to request_module to ask that the module be loaded. This has the same effect as if the program modprobe was called (in fact, it actually starts a separate kernel thread and executes modprobe in it). This ensures that, if the device is a module instead of a part of the kernel, kmod has a chance to load the module before phonedev tries to use it.
It then calls the fopen function in the phone device module to perform the actual act of opening the individual device.
As you can see, the phonedev module has two basic purposes: to assign minor numbers to phone devices dynamically at load time and provide a clean way to autoload needed phone device modules at run time. It's clear, though, that a good understanding of modprobe and module dependency is needed to fully understand the telephony modules and their interactions.
Fast/Flexible Linux OS Recovery
On Demand Now
In this live one-hour webinar, learn how to enhance your existing backup strategies for complete disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible full-system recovery solution for UNIX and Linux systems.
Join Linux Journal's Shawn Powers and David Huffman, President/CEO, Storix, Inc.
Free to Linux Journal readers.Register Now!
- Download "Linux Management with Red Hat Satellite: Measuring Business Impact and ROI"
- Peppermint 7 Released
- Sony Settles in Linux Battle
- Libarchive Security Flaw Discovered
- Maru OS Brings Debian to Your Phone
- Profiles and RC Files
- Snappy Moves to New Platforms
- Git 2.9 Released
- The Giant Zero, Part 0.x
- Susan Lauber's Linux Command Line Complete Video Course (Prentice Hall)
With all the industry talk about the benefits of Linux on Power and all the performance advantages offered by its open architecture, you may be considering a move in that direction. If you are thinking about analytics, big data and cloud computing, you would be right to evaluate Power. The idea of using commodity x86 hardware and replacing it every three years is an outdated cost model. It doesn’t consider the total cost of ownership, and it doesn’t consider the advantage of real processing power, high-availability and multithreading like a demon.
This ebook takes a look at some of the practical applications of the Linux on Power platform and ways you might bring all the performance power of this open architecture to bear for your organization. There are no smoke and mirrors here—just hard, cold, empirical evidence provided by independent sources. I also consider some innovative ways Linux on Power will be used in the future.Get the Guide