Friday, December 19, 2008

Apache virtual hosts (Done on F10)

This is about the name based virtual hosts using apache. I haven't tried ip-based virtual hosts. This is because of two reasons. (a) I do not have multiple IPs. (b) Even though it is possible to try this with private ips, it will only have only academic value and for a fact, I know that doing that will be really simple. (A simple soln: Run one apache per ip and set document root to any given directory)

To create a virtual host, go to the last line of your httpd.conf. You will see an example there. Just copy-n-paste the example and make the necessary changes. To create a virtual host, just do this much:

NameVirtualHost *:80


ServerAdmin webmaster@sarin.net.in
DocumentRoot /var/www/mydomain
ServerName mydomain.co.in
ErrorLog logs/mydomain-error_log
CustomLog logs/mydomain-access_log common


Now create the directory.
mkdir /var/www/mydomain
echo My homepage > /var/www/mydomain/index.html
Change the ownership of the directory
chown -R apache.apache /var/www/mydomain

Now, just restart httpd
service httpd restart

Note 1: You can create multiple virtual host entries by repeating ... block. (Also create directories with correct permission and restart service). "mydomain" & "mydomain.co.in" need to be replaced with your domain name.
Note 2: I have noticed that log file names cannot be same. They have to be different for different domains.

Thursday, December 18, 2008

Customizing BCM96338 (3)

Eventually I found some time to complete it.

We now know

1. How to enter the modem
2. What settings need to be made to forward a port

Now, we will see how to automate this.

Automating this is very simple. I used expect to do this job.

I can directly post all the scripts here. But they are too long and the same expect scripts might not work for someone else.

First you need to manually make the settings at the modem.
Then, just follow the steps below

1. autoexpect telnet 192.168.1.1
1.1 When you get the login prompt, login by giving the user-name and password.
1.2 At the prompt type "sh" and get a shell.
1.3 At the shell type "iptables -L -t nat"
1.4 Once you see the o/p, press "Ctrl-D", , 14
1.5 This will take you out of the modem
1.6 Auto expect would have now created a script to do this (script.exp)

2. Edit the script, set force_conservative 1, rename it to something else (poke.exp in my case)

3. Repeat step 1. At 1.3, instead of listing the table, enter the DNAT command (Eg. iptables -t nat -I PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.1.10)

4. Repeat step 2, save it in some other name (ipt.exp in my case)

5. Now extract the rule from the poke.exp and save it in a file. It will look like something like this,
DNAT tcp -- anywhere anywhere tcp dpt:www to:192.168.1.10
Save it to a file (grep)

6. It is time to create a script (monitor.sh). RUNDIR is where all your files will be kept.

#!/bin/bash

RUNDIR=/root/bin/bsnl
${RUNDIR}/poke.exp > ${RUNDIR}/op
grep -q -- "`cat ${RUNDIR}/grep`" ${RUNDIR}/op || ${RUNDIR}/ipt.exp

7. Now you can add this to your crontab using the command "crontab -e"
*/5 * * * * /root/bin/monitor.sh
(Save and quit)

It won't be complete if I don't mention about ddns. Get an account there. This modem has a ddns client. Once you enable this, you can access your machine using the name that you got from dyndns. (I have actually done this also using a script since I maintain my dns records at zoneedit.com. More about it in another post)

Wednesday, December 17, 2008

Making of a (SIP) call (1)

I am currently looking at the call flow in asterisk when a sip message reaches the client.

1. The i/o callback generates a sip request (struct sip_request) and then calls the handle_request_do function
2. The handle request function calls tje find_call function
3. The find call function find a call corresponding to the request with the help of callid
4. If the find call function cannot find the correspond call, it will check if the call can be created (Only some type of sip requests can create a call. For example, A 'BYE' cannot create a call)
5. If a call can be created, the same will be created.
6. If a call is found/created, the corresponding private structure is returned to the callee

Tuesday, December 2, 2008

F10

I got it installed eventually. But it did not start. In the evening, I went to install screen again, selected an upgrade and removed splash image from grub after mounting the bootable partition from the text console. In the upgrade selected not to install grub. Upgrade did nothing and restarted the m/c. I am not getting the graphical screen with Intel drivers. Just started X with vesa driver. Will do the R&D later.

F10 installation

I was downloading a few other items, so F10 happened just yesterday. I have started installation on my sister's computer using one of my old 80GB ATA hard drives. This is what I did.



(I already have dhcp, tftp and httpd running on my machine)
1. mount Fedora-10-i386-DVD.iso /mnt -o loop
2. cp /mnt/images/pxeboot/vmlinuz /tftpboot/F10InstKern
3. cp /mnt/images/pxeboot/initrd.img /tftpboot/F10InstInitrd
4. Edit pxeconfig and create an entry for F10 installation
LABEL F10Inst
KERNEL F10InstKernel
APPEND initrd=F10InstInitrd ip=:::::::dhcp admin
(I also made this default)
5. ln -s /mnt/ /var/www/html/f10

Just started the target machine and selected network boot. This started the installation. The installer could not start X. I chose to use vnc. A screen-shot is attached.

Friday, November 28, 2008

OSS: A galore of choice or confusion

This thread gave birth to this post.

If you are a simple windows user and if you want to voice chat with a friend of yours, what will you do? Most likely you will download gtalk or YM messenger programs and chat with your friend.

But, what if you are using Linux? Will you use pidgin, kopete, ekiga, gizmo, kphone with your own asterisk/sipx setup, empathy, meebo, imo or the browser avatars of the YM or gtalk? While lot of this won't support voice or video, it is very unlikely that, as a novice user, you know about them.

So, you go and ask in a fsug forum. What do you find? 10 different users of the forum suggest 20 different solutions to you. It is not bad per say. After all, OSS is about choice, isn't it? However, our poor novice user tries these solutions one after the other. He may install a few which may not support some or other feature that he needs or after a successful installation of application (remember he is a novice user, he might have struggled for hours and hours), he will find that OS does support his hardware :(.

Result? Pop in a windows CD and say install and forget about OSS, free and geekdom. After all, windows is free for him, right? ;)

Now I had posted about this years back when there was a flood office suits in Linux which were using incompatible formats to save same kind of files. I don't know whether my arguments are still valid. However, let me start this argument with myself. I am not going into the details. Just adding some points as a starting point.

The arguments in favour of choice:
1. Well, how about same rice and sambar every day, everywhere? (A world with out choice will simply be... boring)

2. Every user has a different need. Different software are needed to satisfy this varying need.

3. It is impossible to combine all the features into one software. Even if we do that, it will lead to monopoly.

4. When a new user is asking for help, you should not try to impose your choice, but allow him to make his choice

5. Even on windows, today there is lot of choice

The arguments against choice
1. Ok, you want seven course dinner with varying dishes every day? Try telling this to your mom
(There are some cases at least, where choice is simply not possible. For instance, try choosing not to breathe or choose ears for breathing and keep yourself alive :) )

2. The classic example. MS Office. For years this has remained as the only office suite of choice. Even after the arrival of SO/OO, MS office is still there at the helm. Its positioned is not even threatened as much as IE is threatened by FF. So, it is possible, at least to a large extend, to satisfy the needs of a large user base with a single software. (Flare me... with the OOXML story..)

3. Monopoly? Tomorrow if Linux becomes the best OS and every one start using it, will you call that monopoly? Remember, it may not knowingly become anti-competitive deliberately. But, when you 'have' the 'best', will there be any desire for better than best?

4. Advice or informed advice?

5. Yes, but you guys are against windows, aren't you? Is it pro-choice or just against monopoly? There is a very subtle difference here!

There is lot more to write. But I have to do some coding now. I can only say BFN, the IM way :)

Thursday, November 27, 2008

FSUGTSR: Free Software User Group Thrissur

http://fsugtsr.org

Just came across this today through Google. They seem to be restarting their operations at Thrissur now. The first meeting is on 4th of next month. I will make an attempt to attend it.

Fedora 10

Just a small note:

Yesterday night I tried the live CD (F10-i686-Live.iso) on my laptop. It had FireFox 1.9. The most attractive stuff was the desktop background and Malayalam i/p methods. I liked swanalekha but I should say that almost all of them were insufficient for me to do anything meaningful. May be they had support, but was not too apparent. The most noticeable stuff was that it was slooooooooow. Could not get my wireless device working (Broadcom Corporation Dell Wireless 1390 WLAN Mini-PCI).

(Acer aspire 4310, Intel celeron 1.6 GHz, 1MB cache, 1 GB RAM)

Tuesday, November 18, 2008

What am I doing currently?

I am working on some DSP API and some expect scripts. Will post the details soon. But I also want to seriously start working new hobby project soon. (Well 'hobby' and 'serious' in one sentence does not look nice. Can't help :) )

Wednesday, November 12, 2008

Vsftpd virtual Users

I had to create a few virtual users in vsftpd for our clients. Googled a bit first and then experimented with what I found. A good tutorial can be found at

http://alien2thisworld.net/sitePages/tutorials/vsftpd_virtual_users_setup.html

But, this blocks normal users. I made a few modification to the suggested configuration and enabled the following.

1. Local user login
2. Restricting a all local users to their home directories by default
3. Enabling a set of selected set of local users to see the entire file system

I assume that you already have vsftpd, db4 and pam installed.

Step 1: In the vsftpd configuration file (/etc/vsftpd/vsftpd.conf in FC7), Enable anonymous access, setup chroot parameters and specify a per user configuration directory

anonymous_enable=YES
local_enable=YES
write_enable=YES
local_umask=022
dirmessage_enable=YES
xferlog_enable=YES
connect_from_port_20=YES
xferlog_std_format=YES
listen=YES
pam_service_name=vsftpd
userlist_enable=YES
tcp_wrappers=YES

#MY CHANGES
user_config_dir=/etc/vsftpd/users
chroot_local_user=YES
chroot_list_enable=YES
chroot_list_file=/etc/vsftpd/chroot_list


Step 2: Create the per user config directory
mkdir /etc/vsftpd/users

Step 3: Create a password file (user1 is the user name and passwd1 is the password)
echo -e "user1\npasswd1">>users.txt

Step 4: Convert the passwd file to db format

rm users.db
db42_load -T -t hash -f users.txt users.db
mv users.txt /root/vsftpd_users.bkup
chmod 600 users.db


Step 5: Edit the pam configuration file for vsftpd to enable checking newly cerated users.db
#%PAM-1.0
session optional pam_keyinit.so force revoke
auth sufficient /lib/security/pam_userdb.so db=/etc/vsftpd/users
account sufficient /lib/security/pam_userdb.so db=/etc/vsftpd/users

auth required pam_listfile.so item=user sense=deny file=/etc/vsftpd/ftpusers onerr=succeed
auth required pam_shells.so
auth include system-auth
account include system-auth
session include system-auth
session required pam_loginuid.so

Step 6: Create the virtual ftp user
adduser -d /var/ftp/clients clients
mkdir -p /var/ftp/clients
#Add directories for virtual users
mkdir -p /var/ftp/clients/user1 /var/ftp/clients/user2
chown -R clients.clients /var/ftp/clients


Step 7: Create the per user configuration in /etc/vsftpd/users/
mkdir /etc/vsftpd/users/
#Create one config file per user. My user configuration looks like this (/etc/vsftpd/users/user1)
user_sub_token=$USER
local_root=/var/ftp/clients/$USER
guest_enable=YES
guest_username=clients
anon_umask=0022
anon_upload_enable=YES
anon_mkdir_write_enable=YES
anon_other_write_enable=YES

Step 8: Add the trusted users to /etc/vsftpd/chroot_list. They can see the entire FS.

Step 9: Restart vsftpd and your new set of virtual users are ready.

Thursday, September 25, 2008

Customizing BCM96338 (2)

Its after a long time I got time to re-visit this topic. First let me give you the iptables rules to forward the connection.

Step 1: Find your external interface
Do a "ifconfig". You will see an array of devices. One of this will have your global ip.
(Check the index page of your device if you are doubtful about which one is the global ip. You can find your global ip there)

Step 2: iptables rules
iptables -t nat -I PREROUTING -p tcp --dport 22 -i ppp_0_35_2 -j DNAT --to 192.168.1.100
iptables -t filter -I FORWARD -p tcp --dport 22 -d 192.168.1.100 -j ACCEPT

ppp_0_35_2 -> Replace this with the name of your external interface
192.168.1.100 -> Replace this with the ip of your local ssh server

Step 3: How to forward for other connections?
Say you want to have external access to a web server running inside your local network. All that you have to do is issue the above to commands with following differences.

1) --dport 22 will change to --dport 80
2) 192.168.1.100 will be replaced with the ip of your local web server.

If you have any other service running inside, use the portocol (tcp/udp), port and ip of that service.

Tuesday, September 9, 2008

Shady Asterisk

Hmm... you must be wondering why I call him so. Because he is of dubious character. He appears nice outside and what does he do within?

I got a feel of it when I was writing the channel. I wrote the skeleton channel and made an entry for that in extensions.conf.

exten => 200,1,Dial(Sarin/200)
exten => 200,n,Hangup()

From the console do "console dial 200". Then I got a message that "Couldn't call 200". I checked again and again to find what has gone wrong. Nothing as far as I could see.

Then I enabled debug mode. To enable the debug mode in asterisk, I had to do two things.

1.1 Edit the /etc/asterisk/logger.conf.
1.2 Look for a line that looks like "console => notice,warning,error"
1.3 Add debug to that list. "console => notice,warning,error,debug"
2. Now start asterisk with debug option. "asterisk -vvvdc"

(This for enabling debug prints on console)

Then, when I tried to call that number, I found that response from "ast_call" indicates a failure. And, what was causing it?

ast_call checks ast_check_hangup. Inside that function, there is this block of code:

if (!chan->tech_pvt) /* yes if no technology private data */
return 1;
Shame on you asterisk. You were checking the private elements of a channel!. You had no business poking around that pointer. It is private to the channel and it is upto the channel to decide to have it or not to have it (have it as NULL). If you wanted to do anything with it, you should not have called it pvt!

Anyway, I assigned a int pointer to it and then things went fine.

Monday, September 1, 2008

The channel woes

Today I was trying to register an asterisk channel. However my module registration failed with the error that module does not provide any description. I had half a mind to edit the line from Loader.c and load my module. However, I also noticed that I was compiling the module for one version (SVN trunk) and using it on some other version (1.4.15).

Then I downloaded asterisk from svn and compiled and installed it on some other machine. Then I just put in my simple module code, compiled, copied to /usr/lib/asterisk/modules/ and on the command line told "module load chan_thin" The stuff that was not happening for last two days just happened!

The sad part of my story is this. Till now the asterisk was giving me this message: "Module 'chan_thin.so' does not provide a description". I had tried various things including injecting the code of AST_MODULE_INFO macro into my module and adding checks on the functions used by that macro. I kept getting that vague error only because of some version change. (OK, it is still my mistake. Lot of things could have happened in a version change)

Anyway, now I have a module that goes in and does nothing. I have also checked oss channel driver in asterisk. I feel that is the most simple channel driver which I can use as a datum. More on it later. Before I end, let me put down a partial function call tree.

1. AST_MODULE_INFO -> Defines the module info and the register function. This registers ast_module_info
2. load_module -> This is made available to asterisk using ast_module_info structure. It is called when we load the module. For channel registration, ast_channel_register is called during load module. It passes a structure ast_channel_tech
3. ast_channel_tech -> This has all the callback functions. For OSS channel, the structure is as follows.

static struct ast_channel_tech oss_tech = {
.type = "Console",
.description = tdesc,
.capabilities = AST_FORMAT_SLINEAR, /* overwritten later */
.requester = oss_request,
.send_digit_begin = oss_digit_begin,
.send_digit_end = oss_digit_end,
.send_text = oss_text,
.hangup = oss_hangup,
.answer = oss_answer,
.read = oss_read,
.call = oss_call,
.write = oss_write,
.write_video = console_write_video,
.indicate = oss_indicate,
.fixup = oss_fixup,
};

4. oss_request -> This is the function that is called by asterisk when a call comes to your channel. The number is passed to you as a parameter to the function.

Got to do few more things. Rest later.

Sunday, August 31, 2008

The power of NC

Today my sister asked how to download songs from a particular site. (I am not revealing the details of the site here). When I checked the front page of the site, I found a note there saying I cannot download songs from there.
I decided to do a bit of work to find out what is happening. First I searched for an RTP capturing software. Then I thought to have a look at the data being transferred over the network. I used a network sniffer to get the stream. This is what I saw.

GET /$sitepreview/hidden.in/movie/medium/MovieName_OmKaram%2Emp3 HTTP/1.1^M
Host: 10.10.10.10^M
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.9.0.1) Gecko/2008070206 Firefox/3.0.1^M
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8^M
Accept-Language: en-gb,en;q=0.5^M
Accept-Encoding: gzip,deflate^M
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7^M
Keep-Alive: 300^M
Connection: keep-alive^M
Cookie: 1E1AC73C-EC31-4f8f-9A6C-305961899082=Hidden.in^M
Range: bytes=1699944-^M
If-Range: "0bf337a64b4c81:19434"^M
^M
HTTP/1.1 206 Partial Content^M
[402 bytes missing in capture file]^M

This was followed by some binary data. (I need to switch the browser. FF3 does something vague with the fonts. It pumps in Malayalam in the middle!). Too bad, konqueror does not even show me the compose window.
I first extracted the binary data (Just deleted the above shown lines) and played it. I could hear the song almost completely. But there were glitches. That must have been some part of application protocol. The notable point was that it was an HTTP stream and not a RTP stream.
That means, if I can pump in the text lines seen above (Till the blank ^M line just before "HTTP/1.1 206 Partial Content") and capture the raw binary bits that came from the server, that will be my song! Then I remembered about NetCat and it worked out perfectly well.
This is what I did.

1. Opened the webpage in the browser
2. Started the song by clicking it. It was being played by a flash player
3. Captured the initial few bytes of network traffic using my favourite sniffer.
4. Extracted the HTTP request from the message & saved in a file (s1.req)
5. cat s1.req | nc 80 > song.mp3

But then editing the captures were a pain. I found a way for that also. In every request, only the first line was different. So, I saved s1.req and for the rest of the files, just captured and saved first 3 to 5 seconds of data. Then I ran the following script.

#!/bin/bash
[ $# -eq 1 ] || echo "Usage $0 "
[ $# -eq 1 ] || exit 0
head -n1 $1.req > .req
tail -n10 s1.req >> .req
cat .req | nc 10.10.10.10 80 > $1.mp3

this will take the first line of the captured file, append it with the editied captured data and create a new request file for the current song.

I am currently planning to get the whole of that site on my laptop :)

Making of a channel

I need to answer 5 technical questions before I start making the channel

1. What does asterisk need from the channel? (What are the bare minimum features/functionalities of a channel?)
2. What all can asterisk take from the channel? (What is the largest possible set of features/functionalities that a channel can support out of the box?)
3. What are the features of the channel needed by the customer?
4. Is there any feature that a normal asterisk channel cannot support or it is very difficult to support?
5. How to add support to a new feature in channel?

I am searching the answer for the first question now.

Asterisk Channel

We have decided to make a new channel in Asterisk and almost completely move away from the zaptel channel. We had a discussion where we discussed how to proceed with the creation of the channel. In the discussion I was told that there is only a standard load_module function that is provided by Asterisk to define the channel. However, I was sure from my previous encounters with the channel that there needs to be something more than that and I even vaguely remembered that it is a structure.
Today I went back and had a look at the channel code and I found that channels infact use the structure ast_channel. I have not seen the code in detail. Will come back and post more once I see the channels in detail.

Saturday, August 30, 2008

Terminal emulation

For the past two weeks I was working on PRS terminal emulation. We have managed to get the emulation working to a large extend. Today, I helped the UTS guys with this program which wrote the status of their database sync to the terminal.
There were two issues they were facing.
1. Where to write?
The information has to be on screen when the PRS application runs. However, this can be running on any terminal. So, the programmer does not know if his application is going to run on tty1 or tty6, or even pts1 or pts25.
The solution was simple. I told him to write to /dev/tty. This is because, in Linux, /dev/tty always points to your current terminal. So, if I am in tty5 and do a echo 1 > /dev/tty, it will get echoed on my terminal (tty5). If I go to a virtual terminal like /dev/pts/2 and then do a echo 1 > /dev/tty, it will still appear on my current terminal, because /dev/tty will be pointing to /dev/pts/2!.

2. We need to write only one line that needs to be refreshed always. Other programs will be writing to same terminal but not on our line. How do I send the cursor back to where it was after I write my string?
Answer to this terminal sharing issue came from VT220 emulation commands. When you want to save the current cursor position and the characteristic, you just need to print ESC 7 ("\0337"). After that you can do whatever that you want with the termianl. Then you again write ESC 8 ("\0338") to the screen. It will restore all the settings that was present at the time of sending last ESC 7.

I am still working on a few other issues. Will post here once I find a solution.

Friday, August 29, 2008

MSP 455 XL & Serial port

I had to deal with this printer today at CRIS (Center for Railways Information Systems). We are doing POC (Proof Of Concept: A stage making the company eligible for taking part in CRIS tenders) for UTS (Un-reserved Ticketing System) and PRS (Passenger Reservation System) terminals at CRIS. What they want is to be able to run both applications simultaneously on the same thin client. However, both UTS and PRS need to print to line printers and the line printers of CRIS does not support USB. The solution was to use serial port for PRS and parallel port for UTS. MSP 455 has both ports and we decided to use it for testing.
However, we did not know the baud rates and the kind of cable to be used with the printer. We tried with a cross serial cable first. We tried all the bauds possible. (Baud setting: stty -F /dev/ttyS0 9600). Eventually I called up the TVS 'care line'. After a few hops, I reached a guy who told me that baud is 19200 and I need special TVS printer cables.
At this point I asked the hardware engineer with me to change the cable from cross to straight. He did that and then I started with 19200 and went all the way up to 1Mbps. Nope... only junk. Then I noticed that as I increase the speed, the data printed is getting lesser and lesser. => The speed need to be very low. I then tried 9600 and viola... It worked!
The lesson is MSP 455 from TVS needs a straight serial cable and it works at 9600 baud. We did simultaneous printing for UTS and PRS and it worked fine. Now I need to find a way to get the status of the serial printer. Will work on that tomorrow.

Friday, August 22, 2008

webmin

Had to modify a webmin module today and when I checked the page, the description was still the same. Then I remembered there was a cache.

>/etc/webmin/module.infos.cache

Access the page again and it is all fine.

Tuesday, August 19, 2008

DAHDI

As we know that zaptel is renamed to DAHDI, below are the links from which you can fetch DAHDI. I have not gone into the depths of DAHDI, but it looks like it is just a name change.

http://svn.digium.com/svn/dahdi/tools/trunk
http://svn.digium.com/svn/dahdi/linux/trunk

Wednesday, August 13, 2008

Training for Ankit (3)

The zap driver:

1. Used wcfxo.c as the datum

2. Created the following dummy functions
wcfxo_open
wcfxo_close
wcfxo_read
wcfxo_write
wcfxo_hooksig

3. Made the hello_spaninit function to initialize the span

4. Made the zaptel settings as I have shown in the first post in this series

5. Start zaptel service

6. Build and insert module

7. Run ztcfg

8. On the console, dial 1000

9. tail -f /var/log/messages should show message from hooksig

10. On the console, hangup

11. tail -f /var/log/messages should show message from hooksig

12. Since syslog buffers the message and does stuff like "Last message repeated X times" you might not see the second message immediately

#include
#include
#include "zaptel.h"

MODULE_LICENSE("GPL");

extern int gpltest;

struct hpvt {
int pos;
struct zt_span span;
struct zt_chan chan;
char variety[128];
}hello;

static int hello_spanInit();

static int hello_init(void)
{
printk(KERN_ALERT "Before: Hello, world %d \n",gpltest);
hello_spanInit();
printk(KERN_ALERT "After: Hello, world\n");
return 0;
}

static void hello_exit(void)
{
printk(KERN_ALERT "Before: Goodbye, cruel world\n");
zt_unregister(&hello.span);
printk(KERN_ALERT "After: Goodbye, cruel world\n");
}

static int wcfxo_open(struct zt_chan *c)
{

printk(KERN_ALERT "Open called\n");
return 0;
}

static int wcfxo_close(struct zt_chan *c)
{

printk(KERN_ALERT "Close called\n");
return 0;
}

static int wcfxo_hooksig(struct zt_chan *chan, zt_txsig_t txsig)
{

printk(KERN_ALERT "Hooksig called\n");
return 0;

}

static int wcfxo_watchdog(struct zt_span *span, int event)
{
printk("FXO: Restarting DMA\n");
return 0;
}


static int hello_spanInit()
{
struct hpvt *wc=&hello;

strcpy(hello.variety,"Thinvent");
hello.pos=0;
/* Zapata stuff */
sprintf(hello.span.name, "SARIN/%d", wc->pos);
snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Board %d", wc->variety, wc->pos + 1);
sprintf(wc->chan.name, "SARIN/%d/%d", wc->pos, 0);
snprintf(wc->span.location, sizeof(wc->span.location) - 1,"HERE!");
wc->span.manufacturer = "SARIN";
strncpy(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype) - 1);
wc->chan.sigcap = ZT_SIG_FXSKS | ZT_SIG_FXSLS | ZT_SIG_SF;
wc->chan.chanpos = 1;
wc->span.chans = &wc->chan;
wc->span.channels = 1;
wc->span.hooksig = wcfxo_hooksig;
// wc->span.irq = wc->dev->irq;
wc->span.open = wcfxo_open;
wc->span.close = wcfxo_close;
wc->span.flags = ZT_FLAG_RBS;
wc->span.deflaw = ZT_LAW_MULAW;
wc->span.watchdog = wcfxo_watchdog;
#ifdef ENABLE_TASKLETS
tasklet_init(&wc->wcfxo_tlet, wcfxo_tasklet, (unsigned long)wc);
#endif
init_waitqueue_head(&wc->span.maintq);

wc->span.pvt = wc;
wc->chan.pvt = wc;
if (zt_register(&wc->span, 0)) {
printk("Unable to register span with zaptel\n");
return -1;
}
return 0;

}

module_init(hello_init);
module_exit(hello_exit);

Make file

obj-m += tzap.o
EXTRA_CFLAGS += -I/root/zaptel/kernel

all:
make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules

Tuesday, August 12, 2008

Training for Ankit (2)

Ok, we built the kernel module. What do we do with it now?

1. Insert the kernel module to kernel
insmod tzap.ko

2. See the messages appearing in /var/log/messages

At this point, Ankit asked me why tail /var/log/messages? Why can't we see that directly?
Ans: Insmod calls the hello_init function. The message comes from

printk(KERN_ALERT "Before: Hello, world %d \n",gpltest);

Now, KERN_ALERT is a priority for kernel messages. ALERT is not a high priority so that the message comes on our Terminal. We changed the line to

printk(KERN_EMERG "Before: Hello, world %d \n",gpltest);

This time, the message appeared on the Terminal. I then showed him /etc/syslog.conf and told him that, it is syslog which reads these messages and decides what to do with it. I showed him my /etc/syslog.conf and explained how various messages are destined to go to various locations.

3. Unloading the module

This is done with the command rmmod tzap. hello_exit is called when this happens.

4. Module license line.

MODULE_LICENSE("GPL"); or something like that tells the module is licensed under GPL license. This has an important for our customer. They will have to GPL the code if they plan to access the symbols that are exported using EXPORT_SYMBOL_GPL. Anyway, they are lucky and zaptel does not have GPL exports.

5. Init & Exit

module_init and module_exit defines the entry points for insmod and rmmod.

6. One more step __init and __exit

These macros tell the kernel that the functions thus defined are specific to module loading and unloading. I told him to remember the Linux boot process and the line "Freeing unused kernel memory". This is possible because if I mark a function as __init, the kernel knows it has no need of the function after initialization. This allows the kernel to free some memory after boot-up

Training for Ankit (1)

Today I was at customers development centre. Ankit is to develop the driver for the hardware they develop. This post will record the session that I had with Ankit.

Ankit was new to kernel programming. Even I have not mastered this beast well. Neverthless, I got Ankit started with it.

1. Zaptel discussion

It is not necessary to define a span in case of an FXS/FXO. Just need to define a channel.
However, for registering fxs/fxo also, we pass a span argument to zaptel. I asked Ankit to look at span as an abstraction for a device (E1 card, FXS etc) which 'n' channels. (n = 1, for FXS)
I showed him how to define a fxo channel.
zaptel.conf
loadzone = us
defaultzone = us
fxsks=1
zapata.conf (Additions only)
signalling=fxs_ks
callerid="Green Phone"<(256) 428-6121>
channel => 1
extensions.conf additions
exten => 1000,1,Dial(Zap/1)

2. Kernel module programming

To program kernel modules, you need to have kernel source for your current kernel.
I asked him to first download LDD3.
Then, we copied the code from second chapter and compiled the module.
This had to be done on my laptop, as he did not have kernel sources installed on his system.

#include
#include
MODULE_LICENSE("Dual BSD/GPL");
static int hello_init(void)
{
printk(KERN_ALERT "Hello, world\n");
return 0;
}
static void hello_exit(void)
{
printk(KERN_ALERT "Goodbye, cruel world\n");
}
module_init(hello_init);
module_exit(hello_exit);

Then we created the makefile

obj-m += tzap.o
EXTRA_CFLAGS += -I/root/zaptel/kernel

all:
make -C /lib/modules/$(shell uname -r)/build M=`pwd` modules

With the make file in place, we compiled the module and inserted it.


  1. obj-m is a variable understood by kernel build system
  2. obj-m = tzap.o indicates that the name of your module source file is tzap.c
  3. EXTRA_CFLAGS defines the extra compile time flags specific for your module
  4. In this case that extra flag is not really necessary. But as we do more work with this driver, we will need it.
  5. Make command arguments: -C Tells the make to change to before actually running
  6. Make command arguments: M=`pwd`defines M, which will be used by kernel build system to determine the directory in which module source is present
  7. Make command arguments: modules is the target to build
We invoke the kernel build system which in turn compiles the module for us.

Wednesday, July 30, 2008

Customizing BCM96338 (1)

First of all, a big thanks to Google and http://www.cyberciti.biz/tips/hacking-beetel-220x-adsl-router-broadcom-bcm6338.html

Once you are in (Ok, if you haven't opened that page till now, telnet to device, login as admin, enter 'sh' as the option), explore the device file system. Go to bin and do a echo *

You will find that there are iptables and a bunch of other applications that we can use. In the coming posts I will explain how to setup the iptable rules to forward a connection coming from outside to a host within your local network.

Well, this could have been achieved by setting up a DMZ or NAT from the webpage. Unfortunately, these did not work for me. This is the only reason that I am forced to try my luck with iptables.

Wednesday, July 23, 2008

more on data flow

In the ZAP_IRQ_HANDLER, (This is a macro defined in the zaptel.h) the data is copied from the hardware and back. This is done in a card specific manner. In tor2.c, the data is present in specific locations of xilinx memory region. We read and write from that region.

The next step is to read the rbs (robbed bits signaling) bits. These bits are read and compared with the stored rbs bits. If there is a difference, zt_rbsbits is called. The signaling bits are processed based on what is the type of the channel signaling (FXO, FXS, E1, E&M etc). This function in turn calls __zt_hooksig_pvt. This in turn stores the signaling bits in the event buffer of the channel and then wakes up the processes waiting on the eventbufq.

In case of tro2.c, the status byte is read and it is used in processing alarms. Time sync channel is also handled here.

The processing of the data happens in the bottom half. In case of tor2.c, it also depends on if the tasklets are enabled for the driver. If the tasklets are enabled, a corresponding function is scheduled to run. Else, the processing happens in the interrupt context only. In this case, tor2_run is called directly.

tor2_run then calls zt_receive and zt_transmit. This is done for every span. Also, the argument to the function is the span structure in each case.

data flow

In a program, data flow diagrams are as important as the function call trees. As we now have some idea of the working how zaptel calls hardware specific functions, let us briefly see how the data is moving across zaptel and hardware drivers.

Responsible functions: ZAP_IRQ_HANDLER, tor2_run

data -> interrupt -> ZAP_IRQ_HANDLER -> tor2_run -> zt_receive / zt_transmit

Details soon...

Tuesday, July 22, 2008

open & close

Function: tor2_open
Argument: struct zt_chan *chan
Function: Do device specific open. In this case, just increments module usage count

Function: tor2_close
Argument: struct zt_chan *chan
Function: Do device specific open. In this case,just decrements module usage count

The call flow


Before we proceed further, let us have a look at the call flow. Asterisk calls the zaptel using system calls on the devices created by zaptel. A large chunk of such calls are ioctl calls.

To give an example, when a channel has to be configured, asterisk, through chan_zap.so, makes a ZT_CHANCONFIG ioctl. The user data is put into the form of zt_chanconfig structure and passed to the ioctl function.

zt_ctl_ioctl function is invoked as a result of this. This in turn does some generic operations such as error checking etc and then assigns the values from the user space structure to the kernel space structure.

When, there are device specific job to be done, zt_ctl_ioctl calls the device specific function that is already populated in the span structure that we used while registering our device with zaptel. In this particular case, they don't handle the clear function. For clear, they call the

res = chans[ch.chan]->span->chanconfig(chans[ch.chan], ch.sigtype);

In short, in this example we have seen
Asterisk <--> chan_zap.so <-> zaptel.ko (kernel) <-> device driver <-> Zaptel device <-> Phone/switch/PSTN

Monday, July 21, 2008

tor2_spanconfig

Arguments:
  1. struct zt_span *span - This is a pointer to current span structure on which the operation is taking place
  2. struct zt_lineconfig *lc - This is the user supplied data
Functionalities: This is used to set the parameters present in zaptel.conf to the driver. The parameters are present in the lc structure. These parameters are extracted and set in the span structure. In tor2.c, this function is responsible mainly for changing the sync source status of the span.

sync source status of the span: Is whether the current span is an input source, output source or a sink of a time pulse.

This function also takes care about restarting the card if it is currently running


static int tor2_spanconfig(struct zt_span *span, struct zt_lineconfig *lc)
{
int i;
struct tor2_span *p = span->pvt;

if (debug)
printk("Tor2: Configuring span %d\n", span->spanno);

span->syncsrc = p->tor->syncsrc;

/* remove this span number from the current sync sources, if there */
for (i = 0; i <>tor->syncs[i] == span->spanno) {
p->tor->syncs[i] = 0;
p->tor->psyncs[i] = 0;
}
}
p->tor->syncpos[p->span] = lc->sync;
/* if a sync src, put it in the proper place */
if (lc->sync) {
p->tor->syncs[lc->sync - 1] = span->spanno;
p->tor->psyncs[lc->sync - 1] = p->span + 1;
}
/* If we're already running, then go ahead and apply the changes */
if (span->flags & ZT_FLAG_RUNNING)
return tor2_startup(span);

return 0;
}

Moral of my asterisk story

Very simple...

If you have to make a PRI E1/T1 card driver compatible with asterisk...

1. The driver should define span structure
2. The driver should define functions such as ioctl, spanconfig, open, close, rbsbits etc
3. The span variables should be populated with corresponding functions and values
4. In the device init, call zt_register with the populated span.

Next: What are the functions of methods populated in span?

How span is populated

The function that configures a span is


static void init_spans(struct tor2 *tor)
{
int x, y, c;
for (x = 0; x <>spans[x].name, "Tor2/%d/%d", tor->num, x + 1);
snprintf(tor->spans[x].desc, sizeof(tor->spans[x].desc) - 1,
"Tormenta 2 (PCI) fQuad %s Card %d Span %d",
(tor->cardtype == TYPE_T1) ? "T1" : "E1", tor->num, x + 1);
tor->spans[x].manufacturer = "Digium";
strncpy(tor->spans[x].devicetype, tor->type, sizeof(tor->spans[x].devicetype) - 1);
snprintf(tor->spans[x].location, sizeof(tor->spans[x].location) - 1,
"PCI Bus %02d Slot %02d", tor->pci->bus->number, PCI_SLOT(tor->pci->devfn) + 1);
tor->spans[x].spanconfig = tor2_spanconfig;
tor->spans[x].chanconfig = tor2_chanconfig;
tor->spans[x].startup = tor2_startup;
tor->spans[x].shutdown = tor2_shutdown;
tor->spans[x].rbsbits = tor2_rbsbits;
tor->spans[x].maint = tor2_maint;
tor->spans[x].open = tor2_open;
tor->spans[x].close = tor2_close;
if (tor->cardtype == TYPE_T1) {
tor->spans[x].channels = 24;
tor->spans[x].deflaw = ZT_LAW_MULAW;
tor->spans[x].linecompat = ZT_CONFIG_AMI | ZT_CONFIG_B8ZS | ZT_CONFIG_D4 | ZT_CONFIG_ESF;
tor->spans[x].spantype = "T1";
} else {
tor->spans[x].channels = 31;
tor->spans[x].deflaw = ZT_LAW_ALAW;
tor->spans[x].linecompat = ZT_CONFIG_HDB3 | ZT_CONFIG_CCS | ZT_CONFIG_CRC4;
tor->spans[x].spantype = "E1";
}
tor->spans[x].chans = tor->chans[x];
tor->spans[x].flags = ZT_FLAG_RBS;
tor->spans[x].ioctl = tor2_ioctl;
tor->spans[x].pvt = &tor->tspans[x];
tor->tspans[x].tor = tor;
tor->tspans[x].span = x;
init_waitqueue_head(&tor->spans[x].maintq);
for (y=0;yspans[x].channels;y++) {
struct zt_chan *mychans = tor->chans[x] + y;
sprintf(mychans->name, "Tor2/%d/%d/%d", tor->num, x + 1, y + 1);
mychans->sigcap = ZT_SIG_EM | ZT_SIG_CLEAR | ZT_SIG_FXSLS | ZT_SIG_FXSGS | ZT_SIG_FXSKS |
ZT_SIG_FXOLS | ZT_SIG_FXOGS | ZT_SIG_FXOKS | ZT_SIG_CAS | ZT_SIG_SF | ZT_SIG_EM_E1;
c = (x * tor->spans[x].channels) + y;
mychans->pvt = &tor->tchans[c];
mychans->chanpos = y + 1;
tor->tchans[c].span = x;
tor->tchans[c].tor = tor;
}
}
}


These are the function assignments:
tor->spans[x].spanconfig = tor2_spanconfig;
tor->spans[x].chanconfig = tor2_chanconfig;
tor->spans[x].startup = tor2_startup;
tor->spans[x].shutdown = tor2_shutdown;
tor->spans[x].rbsbits = tor2_rbsbits;
tor->spans[x].maint = tor2_maint;
tor->spans[x].open = tor2_open;
tor->spans[x].close = tor2_close;
tor->spans[x].ioctl = tor2_ioctl;

The variable initialization
<snip what="name initialization">

tor->spans[x].channels = 24;
tor->spans[x].deflaw = ZT_LAW_MULAW;
tor->spans[x].linecompat = ZT_CONFIG_AMI | ZT_CONFIG_B8ZS | ZT_CONFIG_D4 | ZT_CONFIG_ESF;
tor->spans[x].spantype = "T1";
Or
tor->spans[x].channels = 31;
tor->spans[x].deflaw = ZT_LAW_ALAW;
tor->spans[x].linecompat = ZT_CONFIG_HDB3 | ZT_CONFIG_CCS | ZT_CONFIG_CRC4;
tor->spans[x].spantype = "E1";

tor->spans[x].chans = tor->chans[x];
tor->spans[x].flags = ZT_FLAG_RBS;
tor->spans[x].pvt = &tor->tspans[x];


tor2.c scratch pad

I am going to use this post as the scratch pad while reading through tor2.c

Init function: tor2_init
This function registers a pci driver. The driver structure is a global variable "tor2_driver". It has a probe function called "tor2_probe" and a function to remove the driver "tor2_remove".

Probe function: tor2_probe
  1. Does card specific PCI initialization
  2. Calls init_spans(tor);
  3. Calls tor2_launch(cards[x]);
Span initialization: init_spans
This function populates the spans structure within tor structure.

Register with zaptel: tor2_launch
This function registers the spans with the zaptel driver.
And then... the action begins...

Saturday, July 19, 2008

case study

I am just starting the study of tor2.c. This will help me understand the device driver for a asterisk compatible card better. As I understand, this driver is registered as a pci driver. The interesting part is the probe function. It is through this function the drivers get registered in the zaptel. The details will follow.

A simpler key

Just the same structure from my previous post with all the optional components removed.

struct zt_span {
spinlock_t lock;
void *pvt; /* Private stuff */
char name[40]; /* Span name */
char desc[80]; /* Span description */
const char *spantype; /* span type in text form */
const char *manufacturer; /* span's device manufacturer */
char devicetype[80]; /* span's device type */
char location[40]; /* span device's location in system */
int deflaw; /* Default law (ZT_MULAW or ZT_ALAW) */
int alarms; /* Pending alarms on span */
int flags;
int irq; /* IRQ for this span's hardware */
int lbo; /* Span Line-Buildout */
int lineconfig; /* Span line configuration */
int linecompat; /* Span line compatibility */
int channels; /* Number of channels in span */
int txlevel; /* Tx level */
int rxlevel; /* Rx level */
int syncsrc; /* current sync src (gets copied here) */
unsigned int bpvcount; /* BPV counter */
unsigned int crc4count; /* CRC4 error counter */
unsigned int ebitcount; /* current E-bit error count */
unsigned int fascount; /* current FAS error count */

int maintstat; /* Maintenance state */
wait_queue_head_t maintq; /* Maintenance queue */
int mainttimer; /* Maintenance timer */

int irqmisses; /* Interrupt misses */

int timingslips; /* Clock slips */

struct zt_chan *chans; /* Member channel structures */

/* ==== Span Callback Operations ==== */
/* Req: Set the requested chunk size. This is the unit in which you must
report results for conferencing, etc */
int (*setchunksize)(struct zt_span *span, int chunksize);

/* ==== Channel Callback Operations ==== */

int (*echocan_with_params)(struct zt_chan *chan, struct zt_echocanparams *ecp, struct zt_echocanparam *p);

/* Okay, now we get to the signalling. You have several options: */

/* Option 1: If you're a T1 like interface, you can just provide a
rbsbits function and we'll assert robbed bits for you. Be sure to
set the ZT_FLAG_RBS in this case. */

/* Opt: If the span uses A/B bits, set them here */
int (*rbsbits)(struct zt_chan *chan, int bits);


/* Used by zaptel only -- no user servicable parts inside */
int spanno; /* Span number for zaptel */
int offset; /* Offset within a given card */
int lastalarms; /* Previous alarms */

#ifdef CONFIG_DEVFS_FS
devfs_handle_t dhandle; /* Directory name */
#endif
/* If the watchdog detects no received data, it will call the
watchdog routine */
int (*watchdog)(struct zt_span *span, int cause);
#ifdef CONFIG_ZAPTEL_WATCHDOG
int watchcounter;
int watchstate;
#endif
};

The key to zaptel

We need to have a deep understanding of the following structure to work with zaptel. This is the structure passed by individual driver to zaptel at the time of registration.

struct zt_span {
spinlock_t lock;
void *pvt; /* Private stuff */
char name[40]; /* Span name */
char desc[80]; /* Span description */
const char *spantype; /* span type in text form */
const char *manufacturer; /* span's device manufacturer */
char devicetype[80]; /* span's device type */
char location[40]; /* span device's location in system */
int deflaw; /* Default law (ZT_MULAW or ZT_ALAW) */
int alarms; /* Pending alarms on span */
int flags;
int irq; /* IRQ for this span's hardware */
int lbo; /* Span Line-Buildout */
int lineconfig; /* Span line configuration */
int linecompat; /* Span line compatibility */
int channels; /* Number of channels in span */
int txlevel; /* Tx level */
int rxlevel; /* Rx level */
int syncsrc; /* current sync src (gets copied here) */
unsigned int bpvcount; /* BPV counter */
unsigned int crc4count; /* CRC4 error counter */
unsigned int ebitcount; /* current E-bit error count */
unsigned int fascount; /* current FAS error count */

int maintstat; /* Maintenance state */
wait_queue_head_t maintq; /* Maintenance queue */
int mainttimer; /* Maintenance timer */

int irqmisses; /* Interrupt misses */

int timingslips; /* Clock slips */

struct zt_chan *chans; /* Member channel structures */

/* ==== Span Callback Operations ==== */
/* Req: Set the requested chunk size. This is the unit in which you must
report results for conferencing, etc */
int (*setchunksize)(struct zt_span *span, int chunksize);

/* Opt: Configure the span (if appropriate) */
int (*spanconfig)(struct zt_span *span, struct zt_lineconfig *lc);

/* Opt: Start the span */
int (*startup)(struct zt_span *span);

/* Opt: Shutdown the span */
int (*shutdown)(struct zt_span *span);

/* Opt: Enable maintenance modes */
int (*maint)(struct zt_span *span, int mode);

#ifdef ZAPTEL_SYNC_TICK
/* Opt: send sync to spans */
int (*sync_tick)(struct zt_span *span, int is_master);
#endif

/* ==== Channel Callback Operations ==== */
/* Opt: Set signalling type (if appropriate) */
int (*chanconfig)(struct zt_chan *chan, int sigtype);

/* Opt: Prepare a channel for I/O */
int (*open)(struct zt_chan *chan);

/* Opt: Close channel for I/O */
int (*close)(struct zt_chan *chan);

/* Opt: IOCTL */
int (*ioctl)(struct zt_chan *chan, unsigned int cmd, unsigned long data);

/* Opt: Native echo cancellation (simple) */
int (*echocan)(struct zt_chan *chan, int ecval);

int (*echocan_with_params)(struct zt_chan *chan, struct zt_echocanparams *ecp, struct zt_echocanparam *p);

/* Okay, now we get to the signalling. You have several options: */

/* Option 1: If you're a T1 like interface, you can just provide a
rbsbits function and we'll assert robbed bits for you. Be sure to
set the ZT_FLAG_RBS in this case. */

/* Opt: If the span uses A/B bits, set them here */
int (*rbsbits)(struct zt_chan *chan, int bits);

/* Option 2: If you don't know about sig bits, but do have their
equivalents (i.e. you can disconnect battery, detect off hook,
generate ring, etc directly) then you can just specify a
sethook function, and we'll call you with appropriate hook states
to set. Still set the ZT_FLAG_RBS in this case as well */
int (*hooksig)(struct zt_chan *chan, zt_txsig_t hookstate);

/* Option 3: If you can't use sig bits, you can write a function
which handles the individual hook states */
int (*sethook)(struct zt_chan *chan, int hookstate);

/* Opt: Dacs the contents of chan2 into chan1 if possible */
int (*dacs)(struct zt_chan *chan1, struct zt_chan *chan2);

/* Opt: Used to tell an onboard HDLC controller that there is data ready to transmit */
void (*hdlc_hard_xmit)(struct zt_chan *chan);

/* Used by zaptel only -- no user servicable parts inside */
int spanno; /* Span number for zaptel */
int offset; /* Offset within a given card */
int lastalarms; /* Previous alarms */

#ifdef CONFIG_DEVFS_FS
devfs_handle_t dhandle; /* Directory name */
#endif
/* If the watchdog detects no received data, it will call the
watchdog routine */
int (*watchdog)(struct zt_span *span, int cause);
#ifdef CONFIG_ZAPTEL_WATCHDOG
int watchcounter;
int watchstate;
#endif
};

Saturday, June 14, 2008

pxa255 again

We need to bring up a board based on pxa255. The following drivers needs to be added

1. P33 Intel flash driver
2. DM9k driver

We have no idea how the devices are connected as of now. When I last looked at it, I had merged the drivers for these devices. But the platform device structure needs to be populated and I am stuck there.

Wednesday, May 28, 2008

Echo cancellation in Asterisk

"This software is not part of a normal Asterisk download because Digium has to pay to license it separately. Nevertheless, it has grandfathered it into all of its cards, so it is available for free to anyone who has a Digium analog card that is still under warranty. If you are running a non-Digium analog card, you can purchase a keycode for this software echo canceller from Digium’s web site."


Just tells me that I don't have to waste time on echo cancellation.

Monday, May 26, 2008

Exported functions of zaptel

Asterisk

zt_transcode_fops
A pointer to file operations structure. This is actually populated by zttranscode module. This is a pointer to __zt_transcode_fops defined by the zttranscode module. There is support for: open, release, ioctl, poll and mmap. This structure helps in transcoding.


zt_init_tone_state
Used to initialize the tone state for DTMF tone generation. These initialized values are used in tone generation.


zt_dtmf_tone
For the current channel, returns the DTMF tone structure for the specified digit.


zt_register
Registers a span with zaptel driver. This, I feel, is a method of registering a device with zaptel. The structure zt_span has all the components that is required for accessing/controlling the device. zt_span structure need to be studied in detail.


zt_unregister
Unregister spans registered using zt_register.


__zt_mulaw
ulaw conversion table.


__zt_alaw
alaw conversion table.


__zt_lineartoulaw
Function to convert linear samples to ulaw samples.


__zt_lineartoalaw
Function to convert linear samples to alaw samples.


__zt_lin2mu
Table for converting linear samples to ulaw samples


__zt_lin2a
Table for converting linear samples to alaw samples.


zt_lboname
Retrieve the LBO name strings from an array. LBO: Line build-out. Expressed in DBs. Decides the electrical length


zt_transmit
Transmit a chunk from the channel. There is more to it. Does some processing of slave channels etc. Need to see in detail.


zt_receive
Receives a chunk.Similar to zt_transmit. But it also handles in-band tones.


zt_rbsbits
Process robbed bit signaling. This is based on the channel signaling type.


zt_qevent_nolock
Queue an event for a channel. Do not lock the channel before doing it.


zt_qevent_lock
Queue an event for a channel. Lock the channel before queuing it.


zt_hooksig
Send hook status. (Off hook, on hook, ring etc)


zt_alarm_notify
Send an alarm to all channels in a span.


zt_set_dynamic_ioctl
Dynamically change the ioctl functions by passing a pointer to a new ioctl function.


zt_ec_chunk
Does echo cancellation on a chunk.


zt_ec_span
Does echo cancellation on an entire span.


zt_hdlc_abort
Send hdlc abort events to the channel.


zt_hdlc_finish
Read any remaining data from the channel.


zt_hdlc_getbuf
Copy data from the passed buffer to the output buffer.


zt_hdlc_putbuf
Copy data from the channel buffer to the passed buffer.


zt_alarm_channel
Send the alarm events to the channel.


zt_register_chardev
Register a character driver. Used by transcode module.


zt_unregister_chardev
Unregister the character device. Used by transcode module.


zt_dynamic_register
Takes a pointer to the driver structure and puts it on top of a linked list. The head of the linked list is a global variable called drivers.


zt_dynamic_unregister
Removes the driver from drivers linked list.


zt_dynamic_receive
Receive data for a channel. (Note: This and 3 functions above are for TDM over X. Currently X is ethernet)


zt_transcoder_register
List the transcoder in the global linked list 'trans'.


zt_transcoder_unregister
Remove the transcoder from the linked list pointed by trans


zt_transcoder_alert
Send an alert to the transcoder by setting an alert bit on transcoder status variable.


zt_transcoder_alloc
Allocate memory for a specified number of channels and initialize associated variables.


zt_transcoder_free
Free the memory allocated for a given transcoder.

Whats next?
a. Study the user space interaction of asterisk with zaptel (Chan_zap?)
b. Study the data flow in kernel
c. Study the working of a particular driver

I think, I will start with a & later move to b & c. In fact, it will be difficult to separate b & c.

Sunday, May 25, 2008

Installing F9

I had installed Fedora using qemu on a file a while back. I wanted it on my thumb drive also. The immediate solution that came to my mind was
qemu -cdrom f9.iso -hda /dev/sdb -m 256 -boot d

This worked fine till it started installing selinux targeted policy. Then it hung (crashed?). I tried to get rid of it by de-selecting some packages. But, I could not find selinux related packages in the customization list. So, I decided to pass enforcing=0 to kernel. Installing the package should not have caused a difference if the policy was not enforcing. I have no idea why, but, even that did not work.

Currently I am trying to install it using yum. Will post the details once I am done with it.

&lt;update&gt;
yum -c yum.conf --disablerepo=livna --disablerepo=fedora --disablerepo=updates --disablerepo=openswan --enablerepo=Fedora9 --installroot=/mnt install coreutils
yum -c yum.conf --disablerepo=livna --disablerepo=fedora --disablerepo=updates --disablerepo=openswan --enablerepo=Fedora9 --installroot=/mnt install vim
yum -c yum.conf --disablerepo=livna --disablerepo=fedora --disablerepo=updates --disablerepo=openswan --enablerepo=Fedora9 --installroot=/mnt install rpm
yum -c yum.conf --disablerepo=livna --disablerepo=fedora --disablerepo=updates --disablerepo=openswan --enablerepo=Fedora9 --installroot=/mnt install kernel
yum --disablerepo=updates --enablerepo=fedora --installroot=/mnt install grub

You will see that the last line is a bit different. This is because, previous line had installed yum and the new repos defined by the newly installed yum was used.

Fedora9 is my local Fedora9 repo created from rpms found in install DVD.

I could have done all these in one step.
yum -c yum.conf --disablerepo=livna --disablerepo=fedora
--disablerepo=updates --disablerepo=openswan --enablerepo=Fedora9
--installroot=/mnt install coreutils vim rpm kernel grub



Friday, May 23, 2008

Files

Below are the files that I want to concentrate on at the beginning

zaptel-base.c
zaptel.h
zconfig.h
ztd-eth.c
ztd-loc.c
ztdummy.c
ztdummy.h
ztdynamic.c
zttranscode.c

There is a large set of symbols that zaptel-base.c exports. First let me list all symbols that are being exported. (This symbol set, I guess, should define the API available for zaptel compatible drivers)

From zaptel-base.c

zt_transcode_fops
zt_init_tone_state
zt_dtmf_tone
zt_register
zt_unregister
__zt_mulaw
__zt_alaw
__zt_lineartoulaw
__zt_lineartoalaw
__zt_lin2mu
__zt_lin2a
zt_lboname
zt_transmit
zt_receive
zt_rbsbits
zt_qevent_nolock
zt_qevent_lock
zt_hooksig
zt_alarm_notify
zt_set_dynamic_ioctl
zt_ec_chunk
zt_ec_span
zt_hdlc_abort
zt_hdlc_finish
zt_hdlc_getbuf
zt_hdlc_putbuf
zt_alarm_channel
zt_register_chardev
zt_unregister_chardev


From ztdynamic.c

t_dynamic_register
zt_dynamic_unregister
zt_dynamic_receive


From zttranscode.c

zt_transcoder_register
zt_transcoder_unregister
zt_transcoder_alert
zt_transcoder_alloc
zt_transcoder_free


In coming days/hours I plan to make each of this symbol a link and write about the functionality of each item.

Asterisk/Zaptel/DAHDI

This is an attempt to study the zaptel interface used by Asterisk for enabling a few custom cards to work with Asterisk. I had started it few days back and plan to continue it for a while. When ever I find something interesting, I will post it here.

Wednesday, April 9, 2008

Mysql data replication

Chapter 15 of mysql manual (version 5.0) deals with this.

At the master server: (Assumption: Mysql is installed and running)

1. Edit /etc/my.cnf
1.1 Add the following into [mysqld] section
[mysqld]
log-bin=mysql-bin
server-id=1
2. Add a user for replication

grant replication slave on *.* to 'slaveuser'@'192.168.1.%' identified by 'slavepass';

3. Restart service at the master
service mysqld restart

4. Find the position of the current log

flush tables with read lock;
show master status;
(Note the position of the log file. This will be used at slave)

At the slave server:

1. Add the following to /etc/my.cnf in the [mysqld] section
[mysqld]
server-id=2
2. Add the master information to slave server.

change master to MASTER_HOST='192.168.1.5', MASTER_USER='slaveuser', MASTER_PASSWORD='slavepass', MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=90;

Noticed this issue: After reboot, the log filename changes. How to fix this issue?

Monday, April 7, 2008

tar backups

If you have to backup the entire /, using cp not be nice since some special files will misbehave. I had to copy a chroot environment recently. This is how I did it

(It was executed in /storage/bkup. The chrrot-ed env was in /storage/dl)
tar cvf - ../dl | tar xvf -

Wednesday, March 19, 2008

Privacy Policy

Privacy Policy for flyingtux.blogspot.com

If you require any more information or have any questions about our privacy policy, please feel free to leave a comment here and we will respond to you at the earliest.

At flyingtux.blogspot.com, the privacy of our visitors is of extreme importance to us. This privacy policy document outlines the types of personal information is received and collected by flyingtux.blogspot.com and how it is used.

Log Files
Like many other Web sites, flyingtux.blogspot.com makes use of log files. The information inside the log files includes internet protocol ( IP ) addresses, type of browser, Internet Service Provider ( ISP ), date/time stamp, referring/exit pages, and number of clicks to analyze trends, administer the site, track user’s movement around the site, and gather demographic information. IP addresses, and other such information are not linked to any information that is personally identifiable.

Cookies and Web Beacons
flyingtux.blogspot.com does use cookies to store information about visitors preferences, record user-specific information on which pages the user access or visit, customize Web page content based on visitors browser type or other information that the visitor sends via their browser.

Some of our advertising partners may use cookies and web beacons on our site. Our advertising partners include Google Adsense, .

These third-party ad servers or ad networks use technology to the advertisements and links that appear on flyingtux.blogspot.com send directly to your browsers. They automatically receive your IP address when this occurs. Other technologies ( such as cookies, JavaScript, or Web Beacons ) may also be used by the third-party ad networks to measure the effectiveness of their advertisements and / or to personalize the advertising content that you see.

flyingtux.blogspot.com has no access to or control over these cookies that are used by third-party advertisers.

You should consult the respective privacy policies of these third-party ad servers for more detailed information on their practices as well as for instructions about how to opt-out of certain practices. flyingtux.blogspot.com's privacy policy does not apply to, and we cannot control the activities of, such other advertisers or web sites.

If you wish to disable cookies, you may do so through your individual browser options. More detailed information about cookie management with specific web browsers can be found at the browsers' respective websites.

Sunday, February 10, 2008

VoIP in office

We did it eventually! We moved coral telecom's voip server to one of ours. Though it was an open source software, we had made some changes to fix its behavior with SI120s. This is now running on a machine with a quad core processor, 2 GB and gigabit ether net. It is currently serving about 50 users. We used stock FC8 with all updates till date. Currently it is having some issues when the call is between our home grown PRI gw and MP124 (24 port FXS from audiocodes). I need to see this on Monday. Anyway, the release is done. What is left is only a bug fix :)

Powered by ScribeFire.