Tuesday, July 21, 2015

Is my Raspberry Pi overheating?

Recently I am getting annoying misbehaviors on my Raspberry Pi.

This Raspberry Pi is NOT the one I used for network tests in my previous posts (Wi-Fi AP hosting is NOT stable on my Raspberry Pi and Hosting a Wi-Fi access point on Debian with Edimax EW-7811Un [Realtek RTL8188CUS]). This is the one I am using for my project. I need to work outdoors with this Raspberry Pi powered on a USB power bank (a.k.a battery pack), so it is pretty tricky to know what the problem exactly is.

Fortunately, with a Bluetooth serial interface, I am able to have my Raspberry Pi talk to a Bluetooth terminal application on my Android phone. Now I plan to figure out if the problem is caused by overheating. Before this post, I have already tried troubleshooting with these possible causes:
  1. Too much data being generated and processed by my program.
  2. Too much data flowing through the on-board database.
I once thought 1 was the cause. Solving 1 actually gave me pretty many peaceful days with my Raspberry Pi. However, I just found that the problem was not completely solved. I doubt if the temperature is causing these troubles because I personally feel that the problem occurred more frequently in hot days.

I plan to let my Raspberry Pi report its chip temperature(s). Here's what I am going to do with it tomorrow:

http://raspberrypi.stackexchange.com/questions/8689/how-do-i-display-the-temperature-from-the-internal-sensor-on-a-html-page

Since on-board temperature is a pretty commonly asked question for Raspberry Pi, I will not copy and paste the solution to my post. I am not going to do any HTML work either. It is just that the solution was also given in Python.

I like Raspberry Pi Stack Exchange now, however it doesn't seem to have enough active users.
---
Updated on July 23

I implemented the CPU temperature monitoring functionality yesterday, and did some outdoor tests. However it was much cooler yesterday than it was on Wednesday. I didn't notice any abnormal behavior on my Pi. When that Raspberry Pi ran indoors with a room temperature of 18 Celsius, the CPU temperature was 40. When it ran outdoors with an estimated air temperature of 28 Celsius, the CPU temperature was 50.

Probably next time when it gets hot enough outdoors, I can testify my assumption.

Wi-Fi AP hosting is NOT stable on my Raspberry Pi

Two weeks ago I have posted about Hosting a Wi-Fi access point on Debian with Edimax EW-7811Un [Realtek RTL8188CUS].

However I found it NOT stable enough. While the Raspberry Pi seemed working well, the AP hosting feature failed occasionally, approximately once every 2 or 3 days. Sometimes it seemed that the dongle stopped working, and sometimes the dongle was blinking, but clients could not access the Internet when connected to that hosted AP.

Here are my assumptions:

1. The power supply is still not enough for the Raspberry Pi with two Wi-Fi adapters on a 4-port USB hub powered on the Pi's USB port.


Clues: The situation became worse (AP hosting stopped more frequently) after I added a Bluetooth dongle to the USB hub.

2. Instability occurred in DNS service dnsmasq, or AP hosting service hostapd.


I am not sure if this is the truth because I have never left my laptop running at the same place for more than 3 days, thus I have got nothing for comparison. Even if these services work well on my laptop, I cannot conclude they worked well on the Raspberry Pi too, because they are not based on the same architecture on these two different platforms.

I don't have enough time to testify all these things out at present. I will try to do some tests on my Raspberry Pi, after I have accomplished the current phase of the project I am working on.

Monday, July 6, 2015

Basic Bluetooth operations in command-line interface (CLI)

First of all, this post talks about Bluetooth management on Linux.

I have Ubuntu 14.04 LTS on my personal laptop. Actually Ubuntu has a pretty good Bluetooth management GUI.

Ubuntu 14.04 LTS: Bluetooth management GUI in Settings
However there might be certain scenarios that we would like to manage Bluetooth devices in CLI. When I work with Bluetooth on my Raspberry Pi, I also need CLI-based Bluetooth tools.

The official Bluetooth protocol stack for Linux is BlueZ (http://www.bluez.org/). It has several simple CLI executives with which you can manage the Bluetooth functionalities on your Linux machine just in CLI. If you open a terminal window and type "blue" and tab (for auto completion), you will probably see a bunch of executives named bluetooth* or bluez-*.

Bluetooth management commands
If you don't find some of these commands, you can install them with

sudo apt-get install bluez-utils

This post will only cover basic Bluetooth management operations in CLI, which include
  1. View local adapters
  2. Pair with other devices
  3. Trust other devices
  4. Browse local services
  5. Check and modify local configurations
These operations are usually required to work with any Bluetooth device in CLI.

I. Environment


Commands and operations presented in this post have been tested on the following platforms.

1. Laptop PC


CPU: Intel® Core™2 Duo CPU T7700 @ 2.40GHz × 2
RAM: 4GB
OS: Ubuntu 14.04 LTS (trusty) 64-bit, Linux 3.13.0-44-generic
Bluetooth adapter: Alps Electric Co., Ltd Bluetooth Controller (ALPS/UGPZ6)

2. Raspberry Pi 1 Model B


RAM: 512MB
OS: Raspbian, Debian 7.8 (wheezy), Linux 3.10-3-rpi
Bluetooth adapter: Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode)

The Bluetooth adapter I use on my Raspberry Pi is SoundBot® SB340 Bluetooth 4.0 USB Adapter. It can be found on Amazon at http://www.amazon.com/SoundBot%C2%AE-SB340-Bluetooth-Transmitter-Compatible/dp/B00F25Z0FS/ref=sr_1_1?ie=UTF8&qid=1436200385&sr=8-1&keywords=soundbot+bluetooth+usb. It looks like this:

SoundBot® SB340 Bluetooth 4.0 USB Adapter
However, there should be many different brands of USB Bluetooth adapter using the CSR chip. For example, this one on eBay: http://www.ebay.com/itm/Bluetooth-4-0-USB-2-0-CSR4-0-Dongle-Adapter-for-PC-LAPTOP-WIN-XP-VISTA-7-8-New-/231273407094?pt=LH_DefaultDomain_0&hash=item35d8f82276. I will be surprised if they don't work the same way.

Notice for Cambridge Silicon Radio, Ltd Bluetooth Dongle

If you would like to choose this USB Bluetooth adapter, or another module with the same chip, please be aware that this module has been identified as a very cheap module, and has a significant problem:

ALL modules with this chip have EXACTLY THE SAME BD address!
ALL modules with this chip have EXACTLY THE SAME BD address!
ALL modules with this chip have EXACTLY THE SAME BD address! 

Important things be stressed three times.

This will cause very big problems if you plan to use multiple of these adapters in the same room. However, difficulties can be overcome by modifying the hardware addresses for them. Since that's not related to our topic, I would not prefer to talk about that in this post.

I am not persuading you to buy or not to buy this module or this chip. This is just for your information.

II. Basic operations


This section will cover the basic operations I mentioned at the beginning of this post.

1. View local adapters


A USB Bluetooth adapter should work in HCI mode for BlueZ to recognize and control. As you can use ifconfig to view local network interfaces and use iwconfig to view local wireless network interfaces, you can also use hciconfig to view local HCI devices. For example, this is what I got on my laptop with hciconfig (with my BD address concealed):

$ hciconfig
hci0:    Type: BR/EDR  Bus: USB
    BD Address: 00:1B:FB:xx:xx:xx  ACL MTU: 384:8  SCO MTU: 64:8
    UP RUNNING PSCAN
    RX bytes:21693 acl:645 sco:0 events:353 errors:0
    TX bytes:4653 acl:285 sco:0 commands:53 errors:0


And this is what I got on my Raspberry Pi:

$ hciconfig
hci0:    Type: BR/EDR  Bus: USB
    BD Address: 00:1A:7D:xx:xx:xx  ACL MTU: 310:10  SCO MTU: 64:8
    UP RUNNING PSCAN
    RX bytes:10302 acl:287 sco:0 events:717 errors:0
    TX bytes:19001 acl:645 sco:0 commands:54 errors:0


2. Pair with other devices


Let's say we have two Bluetooth enabled devices. Device 0 is the Linux machine we are working with in CLI (terminal emulator, TTY, SSH, etc.), and device 1 is a device you would like to pair with device 0, e.g. an Android phone, a Bluetooth GPS module, or simply another Bluetooth enabled PC. Then, there are usually two ways you can get them paired with each other.

(a) Make device 0 discoverable and initiate pairing on device 1


This approach is usually easier, because you don't need to do too much on device 0 where we only have CLI access. However, this requires your device 1 to be interactively operable. If your device 1 is an Android phone or another PC, it would be fine. However, if your device 1 is a Bluetooth GPS module, a Bluetooth keyboard, or something else, which is not so smart, it would be impossible, because you cannot initiate pairing on your device 1.

Basically what you are going to do is: make device 0 discoverable, run a simple agent to listen to incoming pairing requests, and initiate pairing on device 1.

To make device 0 discoverable, execute

sudo hciconfig hci0 piscan

Where "hci0" is the device name of the Bluetooth adapter you would like to use, which can be found in a general hciconfig output. "piscan" stands for PSCAN and ISCAN, both of which are required for a Bluetooth adapter to be discoverable by other devices. After that, you will get the following output with hciconfig:

$ hciconfig
hci0:    Type: BR/EDR  Bus: USB
    BD Address: 00:1A:7D:xx:xx:xx  ACL MTU: 310:10  SCO MTU: 64:8
    UP RUNNING PSCAN ISCAN
    RX bytes:10315 acl:287 sco:0 events:719 errors:0
    TX bytes:19008 acl:645 sco:0 commands:56 errors:0


Note that the third line of the output changed from UP RUNNING PSCAN to UP RUNNING PISCAN.

Then you are going to run bluez-simple-agent with root privileges:

$ sudo bluez-simple-agent
Agent registered


It will show "Agent registered" and stay blocked here. Now on your device 1, scan for your device 0 and pair with it. bluez-simple-agent will prompt you when to input the PIN.

(b) Make device 1 discoverable and initiate pairing on device 0


As I mentioned before, if your device 1 is a non-interactive device like a Bluetooth GPS module or a Bluetooth keyboard, you will have to initiate pairing on device 0. You can, of course, do these with an interactive device 1 as well. Therefore, this approach seems more general when talking about Bluetooth pairing in CLI.

We will refer to Bluetooth GPS and Sat Nav on the official Raspberry Pi forum [1], and Bluetooth Keyboard on the Raspberry Pi by Lodewijk Sioen [2], for this approach.

First of all, if your device 1 is an interactive device, like an Android phone, don't forget to turn on discoverable mode.

On your device 0, run

hcitool inq

This will give you a list of nearby discoverable devices, including their BD addresses, like this:

$ hcitool inq
Inquiring ...
    00:0D:B5:xx:xx:xx    clock offset: 0x0763    class: 0x001f00


Or this:

$ hcitool scan
Scanning ...
    00:0D:B5:xx:xx:xx    BT-GPS-xxxxxx


Then you should be able to initiate pairing on your device 0 with

sudo bluez-simple-agent hci0 xx:xx:xx:xx:xx:xx

Replace the BD address with that of your device 1. bluez-simple-agent will start and prompt you what to do next. The next steps may depend on the device type of your device 1. If your device 1 is a Bluetooth keyboard, it will show you a PIN and let you type it on that keyboard. If it is a device with a pre-configured PIN (some audio devices work this way), it will prompt you to enter the PIN on your device 0. For example, with my Bluetooth GPS module, 00:0D:B5:xx:xx:xx, what I got was:

$ sudo bluez-simple-agent hci0 00:0D:B5:xx:xx:xx
RequestPinCode (/org/bluez/2370/hci0/dev_00_0D_B5_xx_xx_xx)
Enter PIN Code:


However, Bluetooth GPS modules don't usually require pairing, and I don't know what its PIN is either. Therefore I will not continue pairing with it :-)

After these steps, you should have your device 0 paired with your device 1.

3. Trust other devices


When another Bluetooth device would like to initiate a Bluetooth connection to your device 0, you will have to have bluez-simple-agent running and manually approve this connection when it prompts you to do so, in order for the connection to be established successfully. Sometimes we hope our device 0 to work unattended and automatically approve some incoming connections. For example, I would like my Raspberry Pi to automatically approve incoming connections from my laptop, but my Raspberry Pi usually works without any keyboard or monitor. That's when we need this "trusting" feature.

Only trusted devices can initiate a Bluetooth connection to your Bluetooth device, i.e. your device 0, without a manual authentication process.

According to Ubuntu Community Help Wiki [3], to trust a device on your device 0, simply execute

sudo bluez-test-device trusted xx:xx:xx:xx:xx:xx yes

To test if a device is trusted, use

sudo bluez-test-device trusted xx:xx:xx:xx:xx:xx

And it will output 0 for untrusted and 1 for trusted.

4. Browse local services


Bluetooth radios work on several different channels simultaneously. A Bluetooth service will listen on a specific channel and respond to requests sent in this channel. To browse local services, execute

sdptool browse local

Root privileges are not required for this browsing command.

What I got on my laptop is

$ sdptool browse local
Browsing FF:FF:FF:00:00:00 ...
Service Name: SIM Access Server
Service RecHandle: 0x10000
Service Class ID List:
  "SIM Access" (0x112d)
  "Generic Telephony" (0x1204)
Protocol Descriptor List:
  "L2CAP" (0x0100)
  "RFCOMM" (0x0003)
    Channel: 8
Profile Descriptor List:
  "SIM Access" (0x112d)
    Version: 0x0101

Service Name: Headset Audio Gateway
Service RecHandle: 0x10001
Service Class ID List:
  "Headset Audio Gateway" (0x1112)
  "Generic Audio" (0x1203)
Protocol Descriptor List:
  "L2CAP" (0x0100)
  "RFCOMM" (0x0003)
    Channel: 12
Profile Descriptor List:
  "Headset" (0x1108)
    Version: 0x0102

Service Name: Hands-Free Audio Gateway
Service RecHandle: 0x10002
Service Class ID List:
  "Handsfree Audio Gateway" (0x111f)
  "Generic Audio" (0x1203)
Protocol Descriptor List:
  "L2CAP" (0x0100)
  "RFCOMM" (0x0003)
    Channel: 13
Profile Descriptor List:
  "Handsfree" (0x111e)
    Version: 0x0105

Service Name: Hands-Free
Service RecHandle: 0x10003
Service Class ID List:
  "Handsfree" (0x111e)
  "Generic Audio" (0x1203)
Protocol Descriptor List:
  "L2CAP" (0x0100)
  "RFCOMM" (0x0003)
    Channel: 7
Profile Descriptor List:
  "Handsfree" (0x111e)
    Version: 0x0105

Service Name: AVRCP TG
Service RecHandle: 0x10004
Service Class ID List:
  "AV Remote Target" (0x110c)
Protocol Descriptor List:
  "L2CAP" (0x0100)
    PSM: 23
  "AVCTP" (0x0017)
    uint16: 0x103
Profile Descriptor List:
  "AV Remote" (0x110e)
    Version: 0x0104

Service Name: AVRCP CT
Service RecHandle: 0x10005
Service Class ID List:
  "AV Remote" (0x110e)
Protocol Descriptor List:
  "L2CAP" (0x0100)
    PSM: 23
  "AVCTP" (0x0017)
    uint16: 0x103
Profile Descriptor List:
  "AV Remote" (0x110e)
    Version: 0x0100

Service Name: Audio Source
Service RecHandle: 0x10006
Service Class ID List:
  "Audio Source" (0x110a)
Protocol Descriptor List:
  "L2CAP" (0x0100)
    PSM: 25
  "AVDTP" (0x0019)
    uint16: 0x102
Profile Descriptor List:
  "Advanced Audio" (0x110d)
    Version: 0x0102

Service Name: Audio Sink
Service RecHandle: 0x10007
Service Class ID List:
  "Audio Sink" (0x110b)
Protocol Descriptor List:
  "L2CAP" (0x0100)
    PSM: 25
  "AVDTP" (0x0019)
    uint16: 0x102
Profile Descriptor List:
  "Advanced Audio" (0x110d)
    Version: 0x0102


What I got on my Raspberry Pi is

$ sdptool browse local
Browsing FF:FF:FF:00:00:00 ...
Service Name: Headset Audio Gateway
Service RecHandle: 0x10000
Service Class ID List:
  "Headset Audio Gateway" (0x1112)
  "Generic Audio" (0x1203)
Protocol Descriptor List:
  "L2CAP" (0x0100)
  "RFCOMM" (0x0003)
    Channel: 12
Profile Descriptor List:
  "Headset" (0x1108)
    Version: 0x0102

Service Name: Hands-Free Audio Gateway
Service RecHandle: 0x10001
Service Class ID List:
  "Handsfree Audio Gateway" (0x111f)
  "Generic Audio" (0x1203)
Protocol Descriptor List:
  "L2CAP" (0x0100)
  "RFCOMM" (0x0003)
    Channel: 13
Profile Descriptor List:
  "Handsfree" (0x111e)
    Version: 0x0105

Service Name: AVRCP TG
Service RecHandle: 0x10002
Service Class ID List:
  "AV Remote Target" (0x110c)
Protocol Descriptor List:
  "L2CAP" (0x0100)
    PSM: 23
  "AVCTP" (0x0017)
    uint16: 0x103
Profile Descriptor List:
  "AV Remote" (0x110e)
    Version: 0x0103

Service Name: AVRCP CT
Service RecHandle: 0x10003
Service Class ID List:
  "AV Remote" (0x110e)
Protocol Descriptor List:
  "L2CAP" (0x0100)
    PSM: 23
  "AVCTP" (0x0017)
    uint16: 0x103
Profile Descriptor List:
  "AV Remote" (0x110e)
    Version: 0x0100

Service Name: Dial-Up Networking
Service RecHandle: 0x10004
Service Class ID List:
  "Dialup Networking" (0x1103)
  "Generic Networking" (0x1201)
Protocol Descriptor List:
  "L2CAP" (0x0100)
  "RFCOMM" (0x0003)
    Channel: 1
Profile Descriptor List:
  "Dialup Networking" (0x1103)
    Version: 0x0100

Service Name: Serial Port
Service Description: COM Port
Service Provider: BlueZ
Service RecHandle: 0x10006
Service Class ID List:
  "Serial Port" (0x1101)
Protocol Descriptor List:
  "L2CAP" (0x0100)
  "RFCOMM" (0x0003)
    Channel: 4
Language Base Attr List:
  code_ISO639: 0x656e
  encoding:    0x6a
  base_offset: 0x100
Profile Descriptor List:
  "Serial Port" (0x1101)
    Version: 0x0100

Service Name: Serial Port
Service Description: COM Port
Service Provider: BlueZ
Service RecHandle: 0x10007
Service Class ID List:
  "Serial Port" (0x1101)
Protocol Descriptor List:
  "L2CAP" (0x0100)
  "RFCOMM" (0x0003)
    Channel: 22
Language Base Attr List:
  code_ISO639: 0x656e
  encoding:    0x6a
  base_offset: 0x100
Profile Descriptor List:
  "Serial Port" (0x1101)
    Version: 0x0100


Each separated section in the output stands for a Bluetooth service, the succeeding details will reveal its service class ID, the channel it listens on, etc.

5. Check and modify local configurations


There are two places on your Linux machine where you can find Bluetooth related configurations. The first one is /etc/bluetooth, and the second one is /var/lib/bluetooth. The difference is, the first place is for configuration files for your Linux Bluetooth service, namely, BlueZ, and the second place is for configuration files for each of your Bluetooth adapters. Files in the second path are automatically generated, but modifications to them also take effect.

(a) Discoverable device name


In /etc/bluetooth/main.conf, at the beginning of file there's such a section:

# Default adaper name
# %h - substituted for hostname
# %d - substituted for adapter id
Name = %h-%d

# Default device class. Only the major and minor device class bits are
# considered.
Class = 0x000100


This is where you can change your discoverable device name (or the naming rule). It affects the name, that your device (actually, each Bluetooth adapter on your device) appears on other Bluetooth devices when set to discoverable. For example, if the host-name of my laptop is PEPOVAIO and I just keep main.conf unchanged like that, "hci0" on my laptop will appear to be "PEPOVAIO-0" on my Android phone.

However, this is the place where the naming rule is defined. The actual name will be stored in a folder under /var/lib/bluetooth. For example, on my Raspberry Pi I have these things in /var/lib/bluetooth:

$ ls -1 /var/lib/bluetooth
00:00:00:00:00:00
00:1A:7D:xx:xx:xx


I don't really know what the first one (00:00:00:00:00:00) is for. However, the second one is the BD address of my CSR adapter. These are all directories so we can look into them:

$ ls -1 /var/lib/bluetooth/00:1A:7D:xx:xx:xx
classes
config
did
eir
features
lastseen
lastused
linkkeys
manufacturers
names
profiles
sdp
trusts


These files are the actual configuration files that are in effect. For example, in config, you will see something like:

$ cat config
name cycletest-0
pairable yes
class 0x420100


If you changed the naming rule in /etc/bluetooth/main.conf but keep this config file unchanged, nothing will happen even if you restart your device. To make things synchronized, simply remove this config, and it will be re-created using configurations in /etc/bluetooth/main.conf.

Notice for Ubuntu 14.04 LTS' default device name

If you have a built-in Bluetooth adapter on your laptop and had it enabled during Ubuntu 14.04 LTS installation (probably for some other releases, too), it may have named your adapter "ubuntu-0", regardless what you have named your laptop later in your installation process.

This problem is probably caused when that config file was created before you give your laptop a preferred host-name, and stayed unchanged after then. To fix (work around) this, just remove the corresponding config file in the adapter directory, and reboot your machine, or restart the bluetooth service with

sudo service bluetooth restart

This is not a big issue, though, because that name shouldn't be expected to change frequently :-)

(b) Trusted devices


I think you also noticed the file trusts in /var/lib/bluetooth/00:1A:7D:xx:xx:xx. Yes, it contains information of trusted devices. Therefore, to list all trusted devices, simply under that path, use

$ cat trusts
00:1B:FB:xx:xx:xx [all]
00:18:31:xx:xx:xx [all]


Where you can tell that the first one is my laptop, trusted by my Raspberry Pi :-) And the second one is actually my Android phone.

III. References


[1] Bluetooth GPS and Sat Nav. https://www.raspberrypi.org/forums/viewtopic.php?t=25759&p=234809
[2] Bluetooth Keyboard on the Raspberry Pi. http://www.correlatedcontent.com/blog/bluetooth-keyboard-on-the-raspberry-pi/
[3] BluetoothSetup. https://help.ubuntu.com/community/BluetoothSetup

Sunday, July 5, 2015

Hosting a Wi-Fi access point on Debian with Edimax EW-7811Un [Realtek RTL8188CUS]

Recently I managed to host one Wi-Fi access point (AP) on my personal laptop, which runs Ubuntu 14.04 LTS, and the other on my Raspberry Pi, which runs Raspbian (Debian). In spite of the large amount of related articles I could find on Google, I still struggled a lot, because of the Wi-Fi adapter I used.

Edimax EW-7811Un
The Wi-Fi adapter I used was Edimax EW-7811Un, which might be the #1 best seller on Amazon among USB 2.0 Wi-Fi dongles. It supports 802.11n and works well on Raspberry Pi when in managed mode. I will describe in details later, the reason why I chose this model, and the problems I encountered with in my earlier attempts.

In this post, I will cover (1) the hardware and software environment that I succeeded with, (2) a brief introduction to the generic solution for Wi-Fi AP hosting on Debian, including related posts, (3) the difficulties I had with Edimax EW-7811Un, (4) my solutions and workarounds to these problems, and (5) the results.

I. Environment


First thing first, what I am trying to achieve is:
  • Creating a Wi-Fi access point (AP) with my personal laptop or my Raspberry Pi, using an additional Edimax EW-7811Un adapter which works on USB 2.0
  • The additional adapter should be dedicated for AP hosting
  • All devices that are connected to the AP I created with this adapter will join a private network, and get Internet access through NAT using another network interface on my machine that has a working Internet connection
  • Everything is ready at system start-up, automatically

The last one of my goals is important. If you only want a temporary AP that you can start/stop manually, configurations will NOT be exactly the same. However, you can still refer to the steps in this article to make this specific Edimax EW-7811Un adapter work on your machine.

As I mentioned above, I succeeded on two different platforms.

1. Laptop PC


CPU: Intel® Core™2 Duo CPU T7700 @ 2.40GHz × 2
RAM: 4GB
OS: Ubuntu 14.04 LTS (trusty) 64-bit, Linux 3.13.0-44-generic
Network adapters:
  • Marvell Technology Group Ltd. 88E8055 PCI-E Gigabit Ethernet Controller (eth0)
  • Intel Corporation PRO/Wireless 3945ABG [Golan] Network Connection (wlan0)
  • Edimax Technology Co., Ltd EW-7811Un 802.11n Wireless Adapter [Realtek RTL8188CUS] (wlan4)

2. Raspberry Pi 1 Model B


RAM: 512MB
OS: Raspbian, Debian 7.8 (wheezy), Linux 3.10-3-rpi
Network adapters:
  • Edimax Technology Co., Ltd EW-7811Un 802.11n Wireless Adapter [Realtek RTL8188CUS] (wlan4)
  • Edimax Technology Co., Ltd EW-7811Un 802.11n Wireless Adapter [Realtek RTL8188CUS] (wlan9)
Actually the Raspberry Pi also has an Ethernet adapter. However lspci doesn't work with the current Debian release on my Pi so I don't know its manufacturer and model now. This is not important anyway, because I am not using the Ethernet port at all.

II. Brief introduction to Wi-Fi AP hosting on Debian


Since you have made it here, I will assume that you know why you want to do Wi-Fi AP hosting instead of ad hoc or other alternative solutions, and I agree with you on that. :-)

Generally speaking, if you would like to host a Wi-Fi AP on your Linux machine, these are the steps you should go through:
  1. Check if your adapter supports AP mode
  2. Install and configure hostapd
  3. Give your Wi-Fi interface a static IP address so it works as a gateway
  4. Install and configure a DHCP server and a DNS server
  5. Configure IP forwarding and firewall (if necessary)
There is an answer [1] posted on Ask Ubuntu that gives a pretty comprehensive description on this topic. The post is dedicated to Ubuntu, which is a derivative distribution of Debian. Therefore the same methodology also works on Debian, probably on many other Linux distributions too.

I will list some steps and issues below that I believe to be important.

1. Mode compatibility


A Wi-Fi adapter may work in one of several modes. managed mode is the most commonplace mode, also known as infrastructure mode, in which the adapter connects to the infrastructure (AP) and looks for network connectivity. To host a Wi-Fi access point with your adapter, it is required to work in AP mode. Not every model/driver supports AP mode.

To check if your adapter supports AP mode, you will need the package iw. Install it with

sudo apt-get install iw

Then, you will be able to check the list of modes supported by your adapter with

iw list

You are looking for "AP" in the "Supported interface modes" section. For example, the build-in Wi-Fi adapter on my laptop gives me results like this:

Supported interface modes:
         * IBSS
         * managed
         * monitor


If you found "AP" in this list, then congratulations. Otherwise you will probably think of buying some other Wi-Fi adapter or simply throw up :-)

If you are using Edimax EW-7811Un, it supports AP mode. Unfortunately I cannot show you any screenshot with the results for it, because I installed a third-party driver for this adapter in order to make it actually work, but iw only supports the default nl80211 driver. I will talk about this again in Section III.

2. Host-AP daemon


hostapd is the AP hosting daemon you will use for hosting an AP on your Linux machine. This package can also be installed with apt-get.

The configuration file for hostapd is at /etc/hostapd/hostapd.conf. A typical working configuration will look like the one presented in [1]:

interface=wlan0
driver=nl80211
ssid=
hw_mode=g
channel=1
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=3
wpa_passphrase=
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP


I will briefly explain some of the fields:
  • interface:  Device name of the Wi-Fi adapter you would like to use for AP hosting. You can list the device names with ifconfig (all network interfaces) or iwconfig (wireless network interfaces only).
  • driver: Driver to use with hostapd. nl80211 is the default wireless driver but it doesn't work well with Edimax EW-7811Un [Realtek RTL8188CUS].
  • ssid: SSID of your wireless network, also known as ESSID. This is the name you will see on your mobile devices when you are trying to connect them to your wireless network.
  • channel: A 2.4GHz Wi-Fi device will work in one of the 11~13 channels, named 1, 2, 3, ..., 13 respectively. As far as I see, many Wi-Fi routers work on channel 6 by default. To avoid conflicts, you can define your AP to broadcast on a different channel, that's far away from 6. The example configuration above will make the AP work on channel 1.
  • wpa: WPA mode. This is for authentication purpose. Set it to 1 for WPA, 2 for WPA2, and 3 for both. Personally speaking I will recommend that you use WPA2 only.
  • wpa_passphrase: Commonly known as "Wi-Fi password", should be no less than 8 characters.
As for the other fields, I will suggest that you keep them unchanged.

Notice for Ubuntu 14.04 LTS network manager

It is observed on Ubuntu 14.04 LTS, probably also on some other Ubuntu releases, that the built-in network manager conflicts with hostapd, which makes hostapd fail to start [5]. In order to resolve this conflict, we need to disable network manager on the interface we would like to use for AP hosting. The configuration file is /etc/NetworkManager/NetworkManager.conf. Add these lines:

[keyfile]
unmanaged-devices=mac:80:1f:02:xx:xx:xx


You will need to restart the networking service or reboot your machine in order for the new configurations to take effect. Then the device with the MAC address identified here will be released from the built-in network manager, and available for hostapd. Then you will find it to be "not managed" in your network manager.

Wi-Fi network appears to be "not managed" in Ubuntu's built-in network manager
Notice for persistent interface device naming

If you would like to change the device name of your adapter to make it persistent on each system start-up, you can add a line in /etc/udev/rules.d/70-persistent-net.rules. If the file does not exist (which is likely to happen on a Raspberry Pi), you can create it yourself. The line to add is:

SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="80:1f:02:xx:xx:xx", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="wlan*", NAME="wlan4"

I concealed the MAC address of my adapter in the example above, please replace the MAC address to that of the adapter, which you are going to use for AP hosting.

You can change "wlan4" to whatever you like - it doesn't even need to start with "wlan". However, don't name it something that's likely to conflict with a system default name, e.g. "eth0", "ppp0", etc.

You will need to reboot your machine in order for the new configurations to take effect.

3. Static IP address


The IP address of a device can be static - which is guaranteed to be persistent, or dynamic - which is assigned to the device by a DHCP server on the network upon connection.

Generally speaking, static public IP addresses on Internet are expensive but pretty lovely for DNS A records, thus they are mostly owned by big companies and organizations. Normal Internet users usually get assigned dynamic IP addressed by their Internet service providers (ISP) upon connection. In some areas, it's pretty common that many users share one IP address using Network Address Translation (NAT). This is not that related to our topic, so I would not prefer to explain it here too much.

In private networks, devices use private IP address, which are restricted in the same private network only. A typical private IP address may look like 10.*.*.*, e.g. 10.0.0.1, or 192.168.*.*, e.g. 192.168.0.1. If a private network is connected to the Internet, there must be one machine that serves as the gateway (also known as the router) and also runs NAT for them.

Network Address Translation (NAT)
In our case, we are going to have NAT and IP forwarding for our Wi-Fi AP. All devices connecting to your AP will join a private network where your Linux machine serves as the gateway. Therefore, we are going to assign your Linux machine a static private IP address on the corresponding interface, so that other devices know where to go when they want to connect to the Internet through the wireless network we create.

In order to assign your interface a static IP address, we are going to edit the network configuration at /etc/network/interfaces. By default on Ubuntu it may look like this:

auto lo
iface lo inet loopback


That's for the loopback interface... There's nothing else because other interfaces are managed by the built-in network manager. On Raspberry Pi there might be some other configurations. Don't change any of those default lines, unless it operates on the same interface we are going to use, e.g. wlan4 in our case. Add the following lines for the interface we want to use for AP hosting:

allow-hotplug wlan4
auto wlan4
iface wlan4 inet static
address 192.168.244.1
netmask 255.255.255.0


The "address" field doesn't need to be the same with the one I use here. However, it is expected to be a private address, in order not to mess up with public addresses (in your private network only). For different ranges of private IPv4 addresses, see the Wikipedia page [2]. Also, "netmask" should better be consistent with the private address space you choose in order to avoid future problems.

4. DHCP server and DNS server


There are multiple choices for DHCP and DNS servers on Debian. I will just recommend my choices.

My DHCP server is isc-dhcp-server as is suggested in [1] as well. That's the package name with which you can install it using apt-get install. We need to modify multiple places in its configuration file /etc/default/isc-dhcp-server and /etc/dhcp/dhcpd.conf.

First, in /etc/default/isc-dhcp-server, the interface which the DHCP server listens on. It should look like

INTERFACES="wlan4"

Where "wlan4" should be consistent with the name of your interface used for AP hosting. Don't have your DHCP server listen on an interface that is connected to the public network or your home router. That may lead to DHCP conflicts and chances to prevent your device from accessing the Internet correctly.

Second, in /etc/dhcp/dhcpd.conf, comment out domain name options if there's any, and add the following lines at the end of the file:

subnet 192.168.244.0 netmask 255.255.255.0 {
  range 192.168.244.130 192.168.244.254;
  option broadcast-address 192.168.244.255;
  option routers 192.168.244.1;
  option domain-name "local";
  option domain-name-servers 192.168.244.1;
  #option domain-name-servers 8.8.4.4, 8.8.8.8;
}


Explanations:
  1. range: When a device (that is configured to use a dynamic IP address) connects to your network and asks for a dynamic IP address, the DHCP server will respond with an address from this range.
  2. option routers: The IP address of the router (gateway). This should be consistent with the static IP address you assigned to your interface.
  3. option domain-name-servers: It should be filled with either your machine's address (when it is set to that static IP address, 192.168.244.1) or addresses of some public DNS servers, e.g. 8.8.4.4 and 8.8.8.8, the Google DNS servers. If you prefer to use your machine as the DNS server on your private network (recommended), please also configure a DNS server on your machine.
You will need to restart the isc-dhcp-server service or reboot your machine in order for the new configurations to take effect.

Post [1] doesn't cover DNS server installation and configuration. I am using dnsmasq. If you would like to use it, please install it with apt-get install. Its configuration is at /etc/dnsmasq.conf. All you need to do is to add this line:

interface=wlan4

Where "wlan4" should be consistent with the name of your interface used for AP hosting. And also, uncomment this line:

bind-interfaces

You will need to restart the dnsmasq service or reboot your machine in order for the new configurations to take effect. Then the DNS server dnsmasq will do whatever you expect it to do as a normal DNS server. It will query higher-level DNS servers for records it doesn't have.

5. IP forwarding


To enable IP forwarding, execute

echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward

However, this effect is not persistent. As is suggested in [3], to make it persistent instead, you can edit /etc/sysctl.conf, uncomment this line or add it at the end of the file:

net.ipv4.ip_forward=1

This configuration takes effect on next boot of your machine. Also, we need to configure the IP table. Execute this command:

sudo iptables -t nat -A POSTROUTING -s 192.168.244.0/24 -o wlan0 -j MASQUERADE

In the command above, replace "192.168.244.0/24" with your private network IP space and the length of mask, and replace "wlan0" with the name of the interface you would like to forward the traffic from your private network TO, namely, an interface that has access to Internet. If you have multiple interfaces or potential interfaces, for example, when you use PPPoE at home or VPN at school dormitory, you can execute the command above for multiple times with different "-o" options.

However, this effect is not persistent either. Actually IP table changes are not designed to be persistent. In order to achieve the persistence (so we don't execute this command every time we reboot our machine, we need package iptables-persistent. It loads /etc/iptables/rules.v4 at system start-up. To save your changes, execute iptables-save and write its output to that file [4].

Notice for firewall

If you have a firewall on your machine, you will need to allow related traffics through your machine so it works as a gateway correctly. By default, neither Ubuntu or Raspbian as any firewall enabled, therefore I will not cover this. Configurations are expected to be different, for different firewalls.

III. Problems with Edimax EW-7811Un


In this section, I will explain why I chose this specific model, and what problems I was encountered with when I attempted to configure it with the steps I presented in Section II.

1. Why Edimax EW-7811Un


These are the reasons why I chose this model:
  • It is the #1 best seller on Amazon among USB 2.0 Wi-Fi dongles.
  • It is cheap.
  • It is power efficient, so it work on a Raspberry Pi.

2. Driver problems


The essential problem which leads to all difficulties on my laptop is, the built-in wireless driver nl80211 doesn't work with hostapd on the RTL8188CUS chip. I forgot what error I got exactly, but it was like to be

nl80211: Failed to set interface wlan4 into AP mode

The explanation was that, the chip RTL8188CUS which is used in Edimax EW-7811Un was too new and the built-in wireless driver nl80211 was not perfectly compatible with it. The imperfect compatibility may also cause failures and instabilities even when operated in managed mode.

Therefore there came a series of problems:
  1. Since nl80211 doesn't work with hostapd on RTL8188CUS, we hope to find an official driver from Realtek's website.
  2. You will find out that the driver from Realtek's website is obsolete and won't compile on Linux 3.10 or later! Actually if your search on Google "RTL8188CUS linux driver", you will get a lot of "problem" results: https://www.google.com/search?client=ubuntu&channel=fs&q=RTL8188CUS+linux+driver&ie=utf-8&oe=utf-8
  3. You will find some third-party driver for RTL8188CUS, but you may have problem patching it to hostapd.
In the following Section IV, we will solve these problem in a series too.

3. Dual-adapter problems on Raspberry Pi


When it came to Raspberry Pi, there were other difficulties too.

The first problem was, I was using two Edimax EW-7811Un on my Raspberry Pi. Except for the one I used for AP hosting, the other one of them was configured in wpa-supplicant whose configuration file is at /etc/wpa_supplicant/wpa_supplicant.conf, for Internet access. This behavior is also defined in /etc/network/interfaces.

Then I found that, upon connection of any device to the AP hosting adapter, the Internet adapter got turned off. Thus, of course, the Internet sharing plan could not work at all because I no longer had Internet on my Raspberry Pi after any device connected to the private network. This issue was also mentioned in this post on the official Raspberry Pi forum [6]. It seemed that for some stupid reasons, Raspbian allowed at most one active network interface at the same time. In previous tests in my other projects, I found that plugging an Ethernet cable into the Ethernet port on the Pi will disable the Wi-Fi connectivity.

There was probably not a solution for that, but a workaround was published in a following-up post in the same thread. I will describe this workaround in Section IV.

After the first problem got worked around, there came the second problem. This time, after only a short period of connection, the AP hosting adapter got turned off (while the Internet adapter was still on and working).

With a series of experiments, I believe that the second problem was due to the short of power supply. Again, possible solutions will be described in Section IV.

IV. Solutions and Workarounds


To fix the driver problems I encountered with in III.2, I did a lot of research on Google and found a mixed solution that solved my own problems and hopefully would also solve yours - problems with the Realtek RTL8188CUS chip. The steps for this solutions are:
  1. Get a compatible third-party driver of RTL8188CUS for Linux 3.10+
  2. Compile and install the third-party driver, including disabling and enabling corresponding system modules
  3. Get a compatible version of hostapd source and patch it with the third-party driver
  4. Compile and install the patched hostapd, remove the one we installed with apt-get, and make sure the new executive can be called the same way as the one installed by apt-get
  5. Modify hostapd.conf
As for the Raspberry Pi problems, as I mentioned in Section III, the first problem could not be solved completely but could be worked around. The workaround is an alternative network manager which is not restricted by /etc/network/interfaces. The second problem does not seem solvable unless we improve the power supply to Raspberry Pi or the Wi-Fi adapters. More details for working around or solving these two problems will be presented at the end of this section.

1. Compatible third-party driver for Linux 3.10 or later


We need a third-party driver because the official driver provided by Realtek (on this website) is obsolete, and does not support Linux kernel 3.10 or newer.

Drivers are closely related to the OS kernel and usually need to be compiled yourself, with the kernel headers on your own machine. Linux kernel is occasionally updated with changes in function prototypes or implementation. If a driver source contains some code that happen to depend on the changed functions it may fail to compile with the updated kernel headers.

Chinese Linux user frogsu [7] has presented his research in his post 解决Ubuntu 14.04 Realtek RTL8188CUS USB无线网卡不稳定问题, where the author uses a third-party driver for RTL8188C and RTL8192C provided by dr0zy on GitHub [8].

That's the third-party driver I succeeded with. To get the driver, you will need git on your Linux system. Install it with

sudo apt-get install git

When git is successfully installed, we can download the entire git repository using

git clone https://github.com/dz0ny/rt8192cu

Execute the command above in your preferred path. This command will create a sub-folder called rt8192cu in your present working directory, and put everything in the repository in that sub-folder.

2. Driver compilation and installation


When you have the rt8192cu source repository ready, change your working directory to the source path, and execute the following commands:

make modules
sudo make install

These commands will compile the driver on your machine with your Linux header and install the compiled rt8192cu module to your system. If you update your Linux kernel later, you may need to redo this step.

Then, we need to disable the built-in rtl8192cu module. Note that there's an "L" in the module name. You can manually add this line

blacklist rtl8192cu

to the end of /etc/modprobe.d/blacklist.conf, or you may also do this with one command:

echo "blacklist rtl8192cu" | sudo tee -a /etc/modprobe.d/blacklist.conf

Please be aware that the following command will not write anything to a system configuration owned by root, and set writable by owner only, e.g. 644:

sudo echo "blacklist rtl8192cu" >> /etc/modprobe.d/blacklist.conf

That's because the output redirection is actually applied to sudo instead of echo, and the redirected output will still be opened with the current user ID. sudo will only be applied to echo.

Finally, we need to enable our new module. Add this line

8192cu

to the end of /etc/modules. Again, you can achieve this by simply using one command with echo and sudo tee:

echo "8192cu" | sudo tee -a /etc/modules

You will need to reboot your machine in order for the changes to take effect. Hopefully, you will get a much more stable network interface on your RTL8188CUS adapter now. Make sure the interface is working before you move to the next step.

3. Patching the daemon source


What we have done so far would be enough for the built-in networking functionality to use our third-party rt8192cu driver. However, hostapd will not work with it because it is not prepared with the driver essentials. Actually, the integration of hostapd with the driver needs to be accomplished before compilation.

Therefore, we need to download the source code of hostapd. The source code can be found at https://w1.fi/hostapd/. The current (June, 2015) latest release of hostapd is 2.4. The patch hostapd-rtl871xdrv can be found at https://github.com/pritambaral/hostapd-rtl871xdrv [9].

However, The current (June, 2015) version of hostapd-rtl871xdrv does not support hostapd 2.4. According to this GitHub issue [10], the latest supported release of hostapd is 2.2. Therefore on the hostapd website, we need to go to "Old releases" and download hostapd-2.2.tar.gz.

Put the downloaded archive somewhere you prefer, and extract it with

tar zxvf hostapd-2.2.tar.gz

Then you will find a source directory called hostapd-2.2. Next, in the same parent directory with hostapd-2.2, download the GitHub repository of hostapd-rtl871xdrv with

git clone https://github.com/pritambaral/hostapd-rtl871xdrv

Now, you will have two directories in your present working directory: hostapd-2.2 and hostapd-rtl871xdrv. Patch the hostapd source with instructions presented in the "Installation" section of the README.md of hostapd-rtl871xdrv.

Finally you will get two executives as is said in the README.md. What we will need is the hostapd executive.

4. Customized daemon installation


First of all, we need to know that the hostapd executive we got in last step, which is a binary executive, IS the daemon. In an apt-get installation, the binary daemon executive is placed at /usr/sbin/hostapd, and a Linux service script is placed at /etc/init.d/hostapd - this is not a same file, though named the same.

If we have already compiled our customized (patched) daemon, we will have the binary executive now. However, we may want to start hostapd automatically at system start-up, that's where we need the service script. To get the service script, you can install hostapd with apt-get install first, keep the service script at /etc/init.d/hostapd somewhere, remove hostapd with apt-get remove or apt-get purge, and restore the script.

To use our customized hostapd, make sure you have already removed the one installed by apt-get. Put the binary file wherever you like, e.g. /usr/local/bin/hostapd. Note that the service script is configured to find the daemon binary at /usr/sbin/hostapd. Thus, we need to make a symbolic link at /usr/sbin/hostapd that refers to /usr/local/bin/hostapd. This can be achieve by executing this command:

sudo ln -s /usr/local/bin/hostapd /usr/sbin/hostapd

Now if you run hostapd -v you will see:

hostapd v2.2 for Realtek rtl871xdrv
User space daemon for IEEE 802.11 AP management,
IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator
Copyright (c) 2002-2014, Jouni Malinen <j@w1.fi> and contributors


Where you can find "rtl871xdrv" in the output, which means that our patch is successful.

5. Modification on daemon configuration


This step will be trivial. Just replace the "driver=nl80211" line in hostapd.conf with

driver=rtl871xdrv

And append this line to the end of the same file:

ieee80211n=1

The patched hostapd will now work with Edimax EW-7811Un and other USB Wi-Fi adapters that use the Realtek RTL8188CUS chip. My working configuration file on my laptop looks like this:

interface=wlan4
driver=rtl871xdrv
ssid=PEPORunAPAtVAIO
hw_mode=g
channel=9
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=2
wpa_psk=
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP
ieee80211n=1


6. Alternative network manager for Raspberry Pi


wicd-curses is a good alternative network manager for Raspberry Pi.

wicd-curses
If you also have the same problem as I described in Section III, you will probably need to remove the Internet adapter interface from /etc/network/interfaces, and manage it with wicd-curses. Be careful with the order of operations if you are working on your Raspberry Pi through SSH on that adapter :-)

7. Power supply improvement for Raspberry Pi


There are two solutions if you are faced with a power supply problem with your Raspberry Pi.
  1. Use a better power adapter for your Raspberry Pi. It is recommended to get a USB power adapter with at least 2.0A output (or 10W capacity).
  2. Use a powered USB hub to power your Wi-Fi adapters separately
Unsolved problem with power supply

Sometimes, even if I read a much lower current intensity with a USB amp-meter, say 0.5A, the Raspberry Pi still seems to suffer from insufficient power supply.

V. Results


Now I have both my laptop and my Raspberry Pi hosting Wi-Fi access points.

Wi-Fi networks discovered on an iPod touch
I actually configured my laptop to forward private network traffics to three different outbound interfaces, including wlan0 (built-in Wi-Fi interface), eth0 (built-in Ethernet interface), and vpn0 (VPN interface).

VI. References


[1] How to setup an Access Point mode Wi-Fi Hotspot? http://askubuntu.com/questions/180733/how-to-setup-an-access-point-mode-wi-fi-hotspot
[2] Private IPv4 address spaces. https://en.wikipedia.org/wiki/Private_network#Private_IPv4_address_spaces
[3] How to Enable IP Forwarding in Linux. http://www.ducea.com/2006/08/01/how-to-enable-ip-forwarding-in-linux/
[4] IptablesHowTo. https://help.ubuntu.com/community/IptablesHowTo
[5] hostapd error “nl80211: Could not configure driver mode”. http://askubuntu.com/questions/472794/hostapd-error-nl80211-could-not-configure-driver-mode
[6] Wifi Access Point with Two Adapters. https://www.raspberrypi.org/forums/viewtopic.php?f=28&t=89756&p=783127#p783127
[7] 解决Ubuntu 14.04 Realtek RTL8188CUS USB无线网卡不稳定问题. http://blog.chinaunix.net/uid-22883023-id-4392914.html
[8] Realtek driver for USB wlan cards: 8188C, 8192C. https://github.com/dz0ny/rt8192cu
[9] Hostapd driver for RTL8188{C|CU|CUS} wifi chips. https://github.com/pritambaral/hostapd-rtl871xdrv
[10] patch failed for hostapd-2.3. https://github.com/pritambaral/hostapd-rtl871xdrv/issues/2