Wifi cards txpower, Linux, mac80211 and regulationsΒΆ

Date:2010-06-05
../_images/logo2.jpg

So you just got a new 500mW wifi card, like this mighty Alfa Networks AWUS036H.

However, you cannot use the most recent Linux driver with it, because your power is limited to 20db (100mW). Thats even if you set you country to Bolivia or what not (which has a much higher power restriction).

You just get a nasty:

Error for wireless request "Set Tx Power" (8B26) :
SET failed on device blah0; Invalid argument.

You must use an old kernel, or revert to pretty old drivers which aren’t really stable. Setting the regulatory domain to your country does not seems to work, somehow, the device tells your kernel that your maximum transmit power just cannot exceed 20db. How annoying isn’t it?

And kind of dumb, when you live in a country where higher power is allowed, or you’ve got a license, or you’ve got a license and use the chipset in raw packet mode for non-wifi activities (oh, guess why I’m saying that!).

Anyway, make sure that using a higher power is legal for you, and if you are, as I could not find any direction how to do this, well, here’s how to override the protection. Note that while you’re doing this AT YOUR OWN RISK and there is NO WARRANTY this will work, or kill your card or is legal for you, I pretty much hate when they decide to block features by software.

Pretty much against what I would call the free software spirit, but hey, let’s not discuss that.

Get the latest Linux kernel for your distribution, or just a vanilla kernel from http://www.kernel.org. I use 2.6.34, which is currently latest stable. Newer kernel might have different structures, code, etc.

Unpack it, and follow your distribution’s instructions and how to compile it, and make it boot. When it works properly, you can start modifying.

File:net/mac80211/cfg.c

This file handles the card’s configuration and interfacing with iwconfig.

Look for the function ieee80211_set_tx_power, and in the case TX_POWER_FIXED, you’ll see a check, if requested dbm value is higher than channel max power, it returns EINVAL (Invalid Argument). Just comment that return -EINVAL out.

That allow the iwconfig command to work when you set the power higher than 20db.

File:net/mac80211/main.c

This file is, well, the main mac80211 file alright?

Look for the function ieee80211_hw_config. This function is called after the code in the cfg.c file we’ve just edited. Somewhere you will find a check, if local user power level is higher than 0 (aka, if you’re trying to set your own power level), it will set the power to whatever is the minimum value between the maximum allowed power and your local power. You can see that just above, when it assigns chan->max_power to power, or max_power - power_constr_level.

Simply replace it to always take your local power. So like that:

//power = min(power, local->user_power_level);
power = local->user_power_level;

Now just save and compile.

rmmod mac80211
insmod net/mac80211/mac80211.ko

and try !

It should work. You can also replace your original .ko (kernel extension) by the one you’ve just created.

Warning

A last word of warning, do not exceed your device maximum manufacturer power rating. You have just removed the safe-guard completely, and you may burn your device. And finally, remember to only use a power level that is legal in your area.

Have fun.