<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Xiaofeng&#039;s Blog</title>
	<atom:link href="http://www.webbertech.com/blog/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://www.webbertech.com/blog</link>
	<description>Technical blog</description>
	<lastBuildDate>Fri, 18 May 2012 07:42:49 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Android Intro</title>
		<link>http://www.webbertech.com/blog/?p=812</link>
		<comments>http://www.webbertech.com/blog/?p=812#comments</comments>
		<pubDate>Fri, 18 May 2012 06:52:52 +0000</pubDate>
		<dc:creator>xiaofeng</dc:creator>
				<category><![CDATA[Linux system programming]]></category>

		<guid isPermaLink="false">http://www.webbertech.com/blog/?p=812</guid>
		<description><![CDATA[Android is a Linux-based operating system for mobile devices such as smartphones and tablet computers. It is developed by the Open Handset Alliance, led by Google, and other companies. Google purchased the initial developer of the software, Android Inc., in 2005.The unveiling of the Android distribution in 2007 was announced with the founding of the [...]]]></description>
			<content:encoded><![CDATA[<p>Android is a Linux-based operating system for mobile devices such as smartphones and tablet computers. It is developed by the Open Handset Alliance, led by Google, and other companies.<br />
Google purchased the initial developer of the software, Android Inc., in 2005.The unveiling of the Android distribution in 2007 was announced with the founding of the Open Handset Alliance, a consortium of 86 hardware, software, and telecommunication companies devoted to advancing open standards for mobile devices.</p>
<p>Android has a large community of developers writing applications (&#8220;apps&#8221;) that extend the functionality of the devices. Developers write primarily in a customized version of Java.[11] Apps can be downloaded from third-party sites or through online stores such as Google Play (formerly Android Market), the app store run by Google. </p>
<p>http://android.yaohuiji.com/about</p>
<p>http://www.android-study.com/</p>
<p>推荐几个比较好的android学习网站：</p>
<p>1．www.android.com：这是android的官网</p>
<p>2．www.android123.com.cn：android开发网</p>
<p>3．www.javaeye.com/groups/tag/Android: 一个开放的android交流平台</p>
<p>4．http://ophone.csdn.net/：ophone csdn专区</p>
<p>5．http://www.ophonesdn.com/：Ophone开发者官网，版主往往是Ophone SDK的开发成员。</p>
<p>6．http://www.3gdci.com/:东方尚智3G数字学院，从这里也不乏找到一些好文章。</p>
<p>7．http://www.jollen.org/blog/android_os/: jollen的博客，很喜欢其中的文章</p>
]]></content:encoded>
			<wfw:commentRss>http://www.webbertech.com/blog/?feed=rss2&#038;p=812</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Write image to AVI</title>
		<link>http://www.webbertech.com/blog/?p=808</link>
		<comments>http://www.webbertech.com/blog/?p=808#comments</comments>
		<pubDate>Thu, 17 May 2012 21:51:37 +0000</pubDate>
		<dc:creator>xiaofeng</dc:creator>
				<category><![CDATA[c++]]></category>

		<guid isPermaLink="false">http://www.webbertech.com/blog/?p=808</guid>
		<description><![CDATA[Write image to AVI using OpenCV. http://answers.oreilly.com/topic/1366-how-to-write-to-an-avi-file-with-opencv/ or you can use ffmpeg.]]></description>
			<content:encoded><![CDATA[<p>Write image to AVI using OpenCV.</p>
<p>http://answers.oreilly.com/topic/1366-how-to-write-to-an-avi-file-with-opencv/</p>
<p>or you can use ffmpeg.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.webbertech.com/blog/?feed=rss2&#038;p=808</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Linux packaging .deb</title>
		<link>http://www.webbertech.com/blog/?p=805</link>
		<comments>http://www.webbertech.com/blog/?p=805#comments</comments>
		<pubDate>Wed, 16 May 2012 19:59:57 +0000</pubDate>
		<dc:creator>xiaofeng</dc:creator>
				<category><![CDATA[Linux system programming]]></category>

		<guid isPermaLink="false">http://www.webbertech.com/blog/?p=805</guid>
		<description><![CDATA[https://wiki.ubuntu.com/PackagingGuide/Complete https://wiki.ubuntu.com/PbuilderHowto]]></description>
			<content:encoded><![CDATA[<p>https://wiki.ubuntu.com/PackagingGuide/Complete</p>
<p>https://wiki.ubuntu.com/PbuilderHowto</p>
]]></content:encoded>
			<wfw:commentRss>http://www.webbertech.com/blog/?feed=rss2&#038;p=805</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Compile and Install Linux Kernel</title>
		<link>http://www.webbertech.com/blog/?p=802</link>
		<comments>http://www.webbertech.com/blog/?p=802#comments</comments>
		<pubDate>Wed, 16 May 2012 18:47:11 +0000</pubDate>
		<dc:creator>xiaofeng</dc:creator>
				<category><![CDATA[Linux system programming]]></category>

		<guid isPermaLink="false">http://www.webbertech.com/blog/?p=802</guid>
		<description><![CDATA[This tutorial is about kernel compiling version 2.6.xx under Debian GNU Linux. 1. Get latest linux kernel code from kernel.org $ cd /tmp $ wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-x.y.z.tar.bz2 x.y.z is the version number. 2. Extract tar (.tar.bz3) file Type the following command: # tar -xjvf linux-2.6.25.tar.bz2 -C /usr/src # cd /usr/src 3. Configure kernel make sure you [...]]]></description>
			<content:encoded><![CDATA[<p>This tutorial is about kernel compiling version 2.6.xx under Debian GNU Linux.</p>
<p>1. Get latest linux kernel code from kernel.org<br />
$ cd /tmp<br />
$ wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-x.y.z.tar.bz2<br />
x.y.z is the version number.</p>
<p>2. Extract tar (.tar.bz3) file</p>
<p>Type the following command:<br />
# tar -xjvf linux-2.6.25.tar.bz2 -C /usr/src<br />
# cd /usr/src</p>
<p>3. Configure kernel<br />
make sure you have gcc installed. Do the following if the lib is missing.</p>
<p>apt-get install libncurses*<br />
apt-get install build-essential libncurses5-dev</p>
<p>Now you can start kernel configuration by typing any one of the command:</p>
<p>$ make menuconfig &#8211; Text based color menus, radiolists &#038; dialogs. This option also useful on remote server if you wanna compile kernel remotely. The following are the same thing, you just gonna file one,configure the kernel tree and make.</p>
<p>$ make xconfig &#8211; X windows (Qt) based configuration tool, works best under KDE desktop<br />
$ make gconfig &#8211; X windows (Gtk) based configuration tool, works best under Gnome Dekstop.</p>
<p>4. Compile kernel<br />
Start compiling to create a compressed kernel image, enter:<br />
$ make</p>
<p>Start compiling to kernel modules:<br />
$ make modules</p>
<p>Install kernel modules (become a root user, use su command):<br />
$ su -<br />
# make modules_install</p>
<p>5 Install kernel</p>
<p>So far we have compiled kernel and installed kernel modules. It is time to install kernel itself.<br />
# make install</p>
<p>It will install three files into /boot directory as well as modification to your kernel grub configuration file:</p>
<p>System.map-2.6.25<br />
config-2.6.25<br />
vmlinuz-2.6.25</p>
<p>6: Create an initrd image</p>
<p>Type the following command at a shell prompt:<br />
# cd /boot<br />
# mkinitrd -o initrd.img-2.6.25 2.6.25</p>
<p>initrd images contains device driver which needed to load rest of the operating system later on. Not all computer requires initrd, but it is safe to create one.</p>
<p>7. Modify Grub configuration file &#8211; /boot/grub/menu.lst</p>
<p>Open file using vi:<br />
# vi /boot/grub/menu.lst</p>
<p>title           Debian GNU/Linux, kernel 2.6.25 Default<br />
root            (hd0,0)<br />
kernel          /boot/vmlinuz root=/dev/hdb1 ro<br />
initrd          /boot/initrd.img-2.6.25<br />
savedefault<br />
boot</p>
<p>Remember to setup correct root=/dev/hdXX device. Save and close the file. If you think editing and writing all lines by hand is too much for you, try out update-grub command to update the lines for each kernel in /boot/grub/menu.lst file. Just type the command:</p>
<p># update-grub</p>
<p>8 : Reboot computer and boot into your new kernel</p>
<p>Just issue reboot command:<br />
# reboot</p>
]]></content:encoded>
			<wfw:commentRss>http://www.webbertech.com/blog/?feed=rss2&#038;p=802</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>static</title>
		<link>http://www.webbertech.com/blog/?p=795</link>
		<comments>http://www.webbertech.com/blog/?p=795#comments</comments>
		<pubDate>Wed, 16 May 2012 18:08:36 +0000</pubDate>
		<dc:creator>xiaofeng</dc:creator>
				<category><![CDATA[c++]]></category>

		<guid isPermaLink="false">http://www.webbertech.com/blog/?p=795</guid>
		<description><![CDATA[Rules: 1. ISO C++ forbids in-class initialization of non-const static member. You have to make it static. For static var defined in .h file, you have to define it in the .cpp file class:: var. 3. Any static member function defined in .h, in .cpp file, you do not put static keyword when you implement [...]]]></description>
			<content:encoded><![CDATA[<p>Rules:</p>
<p>1. ISO C++ forbids in-class initialization of non-const static member. You have to make it static.</p>
<p>For static var defined in .h file, you have to define it in the .cpp file<br />
class:: var.</p>
<p>3. Any static member function defined in .h, in .cpp file, you do not put static keyword when you implement them.</p>
<p>Examples:</p>
<p>non-const static var,<br />
//b.h<br />
class B<br />
{<br />
  public:<br />
  void f();<br />
  static void t();</p>
<p>  private:<br />
  const static int count=1;<br />
  int c;<br />
};</p>
<p>//b.cpp</p>
<p>#include &#8220;b.h&#8221;<br />
#include <iostream><br />
using namespace std;</p>
<p>void B::f(){<br />
cout<<"f()"<<endl;<br />
cout<<B::count<<endl;<br />
}</p>
<p>void B::t(){<br />
cout<<"t()"<<endl;<br />
cout<<B::count<<endl;<br />
}</p>
<p>int main()<br />
{<br />
B b;<br />
 b.f();<br />
 b.t();<br />
 B::t();<br />
}</p>
<p>Take the const off, the following compilation fails, because, it would expect you initialize it in implementation not in the declaration. This make class clean. Why const static is ok? Because you can think it is a constant.</p>
<p>class B<br />
{<br />
  public:<br />
  void f();<br />
  static void t();</p>
<p>  private:<br />
  static int count=1;<br />
  int c;<br />
};</p>
<p>error:b.h:8: error: ISO C++ forbids in-class initialization of non-const static member ‘count’</p>
<p>Now delete the assignment of count, you get another error.</p>
<p>xiaofengmaclap:~ wolfram$ g++ b.cpp -o b.exe<br />
Undefined symbols:<br />
  "B::count", referenced from:<br />
      __ZN1B5countE$non_lazy_ptr in ccviRxVn.o<br />
     (maybe you meant: __ZN1B5countE$non_lazy_ptr)<br />
ld: symbol(s) not found<br />
collect2: ld returned 1 exit status</p>
<p>What you need to do is to declare the static count in .cpp file.</p>
<p>#include <iostream><br />
using namespace std;</p>
<p>int B::count=1;</p>
<p>void B::f(){<br />
cout<<"f()"<<endl;<br />
cout<<B::count<<endl;<br />
}</p>
<p>void B::t(){<br />
cout<<"t()"<<endl;<br />
cout<<B::count<<endl;<br />
}</p>
<p>int main()<br />
{<br />
B b;<br />
 b.f();<br />
 b.t();<br />
 B::t();<br />
}</p>
<p>Usually it is initialize in the constructor,</p>
<p>xiaofengmaclap:~ wolfram$ vi b.cpp</p>
<p>//b.cpp<br />
#include "b.h"<br />
#include <iostream><br />
using namespace std;</p>
<p>int B::count;</p>
<p>B::B()<br />
{<br />
 B::count=1;<br />
}</p>
<p>void B::f(){<br />
cout<<"f()"<<endl;<br />
cout<<B::count<<endl;<br />
}</p>
<p>void B::t(){<br />
cout<<"t()"<<endl;<br />
cout<<B::count<<endl;<br />
}</p>
<p>Not to say for int c, initialization in class is forbidden too.</p>
<p>non-static function can call both non-static variable and static variable.<br />
static function can only call static variable.</p>
<p>The following example shows it,</p>
<p>//b.h<br />
class B<br />
{<br />
  public:<br />
  B();<br />
  void f();<br />
  static void t();</p>
<p>  private:<br />
  static int count;<br />
  int c;<br />
};</p>
<p>//b.cpp<br />
#include "b.h"<br />
#include <iostream><br />
using namespace std;</p>
<p>int B::count;</p>
<p>B::B()<br />
{<br />
 B::count=1;<br />
 this->c=2;<br />
}</p>
<p>void B::f(){<br />
cout<<&#8220;f()&#8221;<<endl;<br />
cout<<B::count<<endl;<br />
cout<<c<<endl;<br />
}</p>
<p>void B::t(){<br />
cout<<&#8220;t()&#8221;<<endl;<br />
cout<<B::count<<endl;<br />
//cout<<c<<endl;<br />
}</p>
<p>int main()<br />
{<br />
B b;<br />
 b.f();<br />
 b.t();<br />
 B::t();<br />
}</p>
]]></content:encoded>
			<wfw:commentRss>http://www.webbertech.com/blog/?feed=rss2&#038;p=795</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Callback function in C++ class</title>
		<link>http://www.webbertech.com/blog/?p=789</link>
		<comments>http://www.webbertech.com/blog/?p=789#comments</comments>
		<pubDate>Wed, 16 May 2012 16:17:06 +0000</pubDate>
		<dc:creator>xiaofeng</dc:creator>
				<category><![CDATA[c++]]></category>

		<guid isPermaLink="false">http://www.webbertech.com/blog/?p=789</guid>
		<description><![CDATA[Simply put, make the callback function static. Here is a working example, #include using std::cout; using std::endl; class Test { public: Test() {} void my_func(void (*f)()) { cout]]></description>
			<content:encoded><![CDATA[<p>Simply put, make the callback function static.</p>
<p>Here is a working example,<br />
<code><br />
#include <iostream><br />
using std::cout;<br />
using std::endl;</p>
<p>class Test<br />
{<br />
public:<br />
    Test() {}</p>
<p>    void my_func(void (*f)())<br />
    {<br />
        cout << "In My Function" << endl;<br />
        f(); //Invoke callback function<br />
    }</p>
<p>    static void callback_func()<br />
    {cout << "In Callback function" << endl;}<br />
};</p>
<p>int main()<br />
{<br />
    Test Obj;<br />
    Obj.my_func(Obj.callback_func);<br />
}<br />
</code></p>
<p>How to pass arguments to callback function?</p>
<p>#include <iostream></p>
<p>template< typename A, typename B ><br />
void foo( A a, B b )<br />
{<br />
    a( b );<br />
}</p>
<p>void boo1( const int p )<br />
{<br />
    std::cout<<"boo( " << p << " )" << std::endl;<br />
}</p>
<p>void boo2( const std::string p )<br />
{<br />
    std::cout<<"boo( " << p << " )" << std::endl;<br />
}</p>
<p>int main()<br />
{<br />
    foo( boo1, 3 );<br />
    foo( boo2, "abc" );<br />
}</p>
<p>or,</p>
<p>template<class T><br />
void function(void (*handler)(T), T variable)<br />
{<br />
   handler(variable);<br />
}</p>
]]></content:encoded>
			<wfw:commentRss>http://www.webbertech.com/blog/?feed=rss2&#038;p=789</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to write Linux Driver</title>
		<link>http://www.webbertech.com/blog/?p=776</link>
		<comments>http://www.webbertech.com/blog/?p=776#comments</comments>
		<pubDate>Tue, 15 May 2012 16:21:55 +0000</pubDate>
		<dc:creator>xiaofeng</dc:creator>
				<category><![CDATA[Linux system programming]]></category>

		<guid isPermaLink="false">http://www.webbertech.com/blog/?p=776</guid>
		<description><![CDATA[Features of a Driver The main features of a driver are: It performs input/output (I/O) management. It provides transparent device management, avoiding low-level programming (ports). It increases I/O speed, because usually it has been optimized. It includes software and hardware error management. It allows concurrent access to the hardware by several processes. There are four [...]]]></description>
			<content:encoded><![CDATA[<p>Features of a Driver</p>
<p>The main features of a driver are:</p>
<div>
<ul type="disc">
<li>It performs input/output (I/O) management.</li>
<li>It provides transparent device management, avoiding low-level programming (ports).</li>
<li>It increases I/O speed, because usually it has been optimized.</li>
<li>It includes software and hardware error management.</li>
<li>It allows concurrent access to the hardware by several processes.</li>
</ul>
</div>
<p>There are four types of drivers: character drivers, block drivers, terminal drivers and streams. <em>Character drivers</em> transmit information from the user to the device (or vice versa) byte per byte. Two examples are the printer, /dev/lp, and the memory (yes, the memory is also a device), /dev/mem.</p>
<p><em>Block drivers</em> transmit information block per block. This means that the incoming data (from the user or from the device) are stored in a buffer until the buffer is full. When this occurs, the buffer content is physically sent to the device or to the user. This is the reason why all the printed messages do not appear in the screen when a user program crashes (the messages in the buffer were lost), or the floppy drive light does not always turn on when the user writes to a file. The clearest examples of this type of driver are disks: floppy disks (/dev/fd0), IDE hard disks (/dev/hda) and SCSI hard disks (/dev/sd1).</p>
<p><em>Terminal drivers</em> (see Figure 4) constitute a special set of character drivers for user communication. For example, command tools in an open windows environment, an X terminal or a console, are devices which require special functions, e.g., the up and down arrows for a command buffer manager or tabbing in the bash shell. Examples of block drivers are /dev/tty0 or /dev/ttya (a serial port). In both cases the kernel includes special routines, and the driver special procedures, to cope with all particular features.</p>
<p><em>Streams</em> are the youngest drivers (see Figure 5) and are designed for very high speed data flows. Both the kernel and the driver include several protocol layers. The best example of this type is a network driver.</p>
<p>&nbsp;</p>
<p>As we have said, a driver is a piece of a program. It is composed of a set of C functions, some of which are mandatory. For example, for a printer device, some typical functions only called by the kernel, may be:</p>
<div>
<ul type="disc">
<li><strong>lp_init()</strong>: Initializes the driver and is called only at boot time.</li>
<li><strong>lp_open()</strong>: Opens a connection with the device.</li>
<li><strong>lp_read()</strong>: Reads from the device.</li>
<li><strong>lp_write()</strong>: Writes to the device.</li>
<li><strong>lp_ioctl()</strong>: Performs device configuration operations.</li>
<li><strong>lp_release()</strong>: Interrupts connection with device.</li>
<li><strong>lp_irqhandler()</strong>: Specific functions called by the device to handle interrupts.</li>
</ul>
</div>
<p>Some additional functions are available for particular applications, like <strong>*_lseek()</strong>, <strong>*_readdir()</strong>, <strong>*_select()</strong> and <strong>*_mmap()</strong>. You may find more information about them in Michael Johnson&#8217;s <em>Hacker&#8217;s Guide</em> (see Resources).</p>
<p>Do I Really Need to Write a Driver?</p>
<p>There are several reasons for writing our own device driver:</p>
<div>
<ul type="disc">
<li>To solve concurrency problems when two or more processes try to access a device at the same time.</li>
<li>To use hardware interrupts: as the kernel runs in protected mode, the user cannot manage interrupts directly from a program.</li>
<li>To handle other unusual applications, such as managing a virtual device (a RAM disk or a device simulator).</li>
<li>To obtain satisfaction as a programmer: writing a driver increases personal motivation as well as control over the computer.</li>
<li>To learn about the internal parts of the system.</li>
</ul>
</div>
<p>Conversely, there are also several reasons for not writing our own driver:</p>
<div>
<ul type="disc">
<li>It requires a good deal of mental preparation.</li>
<li>It requires low-level programming, i.e., direct management of ports and interrupt handlers.</li>
<li>In the debug process, the kernel hangs easily, and it is not possible to use debuggers or C library functions such as <strong>printf</strong>.</li>
</ul>
</div>
<p>However, both the directory structure and the driver interface with the kernel are OS dependent. Indeed small changes may appear from one version or release to the next. For example, several things changed from Linux 1.2.x to Linux 2.0.x, such as the prototypes of the driver functions, the kernel configuration method and the Makefiles for kernel compilation.</p>
<p>The mobile platform is composed of a set of wheels coupled with two motors (the drive and the steer), a set of 24 sonars which act as proximity sensors for obstacle detection and a set of bumpers which detect collisions. We need to implement a driver with, at least, the following services (<strong>init</strong>, <strong>open</strong> and <strong>release</strong> are mandatory):</p>
<div>
<ul type="disc">
<li><strong>write</strong>: to send linear and angular velocity commands</li>
<li><strong>read</strong>: to read sonar measures and encoder values</li>
<li><strong>three interrupt handlers</strong>: to store sonar measures when a sonar echo is received, to implement an emergency stop when a bumper detects a collision and to stop the steer motor when the wheels are located at 0 (zero) degrees and a <em>go to home</em> flag is active</li>
<li><strong>ioctl commands</strong>: <em>go to home</em> which sends a constant angular velocity to the wheels and activates the <em>go to home</em> flag; and configuration of motors and sonars</li>
</ul>
</div>
<p>The <em>go to home</em> service allows the user to stop the wheels at an initial position which is always the same (0 degrees). The incoming values from sonars and encoders, as well as the velocity commands, might be part of the main loop of the control program of the robot.</p>
<p>Returning to the initial scheme (Figure 1), the device is the MRV-4 robot, the hardware interface is the motor/sonar card, the source file of the driver will be mrv4.c, the new kernel we will generate will be vmlinuz, the user program for kernel testing will be <strong>mrv4test.c</strong> and the device will be /dev/mrv4</p>
<p>General Programming Considerations</p>
<p>To build a driver, these are the steps to follow:</p>
<div>
<ol type="1">
<li>Program the driver source files, giving special attention to the kernel interface.</li>
<li>Integrate the driver into the kernel, including in the kernel source calls to the driver functions.</li>
<li>Configure and compile the new kernel.</li>
<li>Test the driver, writing a user program.</li>
</ol>
</div>
<p>The directory structure of the Linux source files can be described as follows: the /usr/src contains subdirectories such as /xview and /linux. Inside the /linux directory, the different parts of the kernel are classified into subdirectories: init, kernel, ipc, drivers, etc. The directory /usr/src/linux/drivers/ contains the driver sources, classified into categories such as block, char, net, etc.</p>
<p>Another interesting directory is /usr/include, where the main header files, such as stdio.h, are located. It contains two special subdirectories:</p>
<div>
<ul type="disc">
<li>/usr/include/system/, which includes system header files, such as types.h</li>
<li>/usr/include/linux/, which includes the Linux kernel headers such as lp.h, serial.h, mem.h and mrv4.h.</li>
</ul>
</div>
<p>The first task when programming the source files of a driver is to select a name to identify it uniquely, such as hd, sd, fd, lp, etc. In our case we decided to use mrv4. Our driver is going to be a character driver, so we will write the source into the file /usr/src/linux/drivers/char/mrv4.c, and its header into /usr/include/linux/mrv4.h.</p>
<p>The second task is to implement the driver I/O functions. In our case, <strong>mrv4_open()</strong>, <strong>mrv4_read()</strong>, <strong>mrv4_write()</strong>, <strong>mrv4_ioctl()</strong> and <strong>mrv4_release()</strong>.</p>
<p>Special care must be taken when programming the driver because of the following limitations:</p>
<div>
<ul type="disc">
<li>Standard library functions are not available.</li>
<li>Some floating-point operations are not available.</li>
<li>Stack size is limited.</li>
<li>It is not possible to wait for events, because the kernel, and so all the processes, are stopped.</li>
</ul>
</div>
<p>The OS functions supported at kernel level are, of course, only those functions programmed inside it:</p>
<div>
<ul type="disc">
<li><strong>kmalloc()</strong>, <strong>kfree()</strong>: memory management</li>
<li><strong>cli()</strong>, <strong>sti()</strong>: enable/disable interrupts</li>
<li><strong>add_timer()</strong>, <strong>init_timer()</strong>, <strong>del_timer()</strong>: timing management</li>
<li><strong>request_irq()</strong>, <strong>free_irq()</strong>: irq management</li>
<li><strong>inb_p()</strong>, <strong>outb_p()</strong>: port management</li>
<li><strong>memcpy_*fs()</strong>: data management</li>
<li><strong>printk()</strong>: input/output</li>
<li><strong>register_*dev()</strong>, <strong>unregister_*dev()</strong>: device management</li>
<li><strong>*sleep_on()</strong>, <strong>wake_up*()</strong>: process management</li>
</ul>
</div>
<p>Detailed information on these functions is given in Johnson&#8217;s <em>Guide</em> (see Resources) or even inside the kernel source files.</p>
<p>Low-Level Programming</p>
<p>Access to the hardware interface (the card) is provided through low-memory addressing. The I/O registers of the card, where we can read/write information, are physically connected to memory addresses of the PC (i.e., ports). For instance, the motor/sonar card of the MRV-4 mobile robot is associated with the address <strong>0x1b0</strong>. Sixteen registers are used in this card, so the port map includes addresses from <strong>0x1b0</strong> to <strong>0x1be</strong>. A typical list of port addressing is shown in Table 1.:</p>
<p>&nbsp;</p>
<h3>Table 1. Typical Port Addresses</h3>
<table>
<tbody>
<tr>
<td><strong>Ports</strong></td>
<td><strong>Device</strong></td>
<td></td>
<td></td>
</tr>
<tr>
<td>000-01f</td>
<td>dma</td>
</tr>
<tr>
<td>020-03f</td>
<td>pic1</td>
</tr>
<tr>
<td>040-05f</td>
<td>timer</td>
</tr>
<tr>
<td>060-06f</td>
<td>keyboard</td>
</tr>
<tr>
<td>080-09f</td>
<td>dma</td>
<td>page</td>
<td>reg</td>
</tr>
<tr>
<td>0a0-0bf</td>
<td>pic2</td>
</tr>
<tr>
<td>0c0-0df</td>
<td>dma2</td>
</tr>
<tr>
<td>0f0-0ff</td>
<td>npu</td>
</tr>
<tr>
<td>1b0-1be</td>
<td>mrv4</td>
</tr>
<tr>
<td>2f8-2ff</td>
<td>serial (auto)</td>
</tr>
<tr>
<td>3c0-3df</td>
<td>vga+</td>
</tr>
<tr>
<td>3f8-3ff</td>
<td>serial (auto)</td>
</tr>
</tbody>
</table>
<p>Ref:</p>
<p>http://www.linuxjournal.com/article/2476?page=0,1</p>
]]></content:encoded>
			<wfw:commentRss>http://www.webbertech.com/blog/?feed=rss2&#038;p=776</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>c++ pure virtual function &amp; virtual function</title>
		<link>http://www.webbertech.com/blog/?p=773</link>
		<comments>http://www.webbertech.com/blog/?p=773#comments</comments>
		<pubDate>Tue, 15 May 2012 00:14:05 +0000</pubDate>
		<dc:creator>xiaofeng</dc:creator>
				<category><![CDATA[c++]]></category>

		<guid isPermaLink="false">http://www.webbertech.com/blog/?p=773</guid>
		<description><![CDATA[If A has a pure function, derived class B must implement it, or even leave an empty implementation. Otherwise B can not instantiate an object.  Pure virtual function servers as a contract, so c++ abstract class is like java interface. &#160; #include &#60;iostream&#62; using namespace std; class A { public: virtual void f()=0; }; class [...]]]></description>
			<content:encoded><![CDATA[<p>If A has a pure function, derived class B must implement it, or even leave an empty implementation. Otherwise B can not instantiate an object.  Pure virtual function servers as a contract, so c++ abstract class is like java interface.</p>
<p>&nbsp;</p>
<p>#include &lt;iostream&gt;<br />
using namespace std;</p>
<p>class A<br />
{<br />
public:<br />
virtual void f()=0;<br />
};</p>
<p>class B: public A<br />
{<br />
public:<br />
using A::f;</p>
<p>void f(int)<br />
{<br />
cout&lt;&lt;&#8221;B&#8217;s f(int)&#8221;;<br />
}</p>
<p>void f()<br />
{}<br />
};</p>
<p>int main()<br />
{<br />
B b;<br />
// b.f();<br />
b.f(1);<br />
}</p>
<p>Or, if A does not have pure virtual function but normal pure function.</p>
<p>A must implement virtual function or leave it empty implementation. Or it will not compile. It does not matter B implements its own or not.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>#include &lt;iostream&gt;<br />
using namespace std;</p>
<p>class A<br />
{<br />
public:<br />
virtual void f(){};  //without {} it will not compile<br />
};</p>
<p>class B: public A<br />
{<br />
public:<br />
using A::f;</p>
<p>void f(int)<br />
{<br />
cout&lt;&lt;&#8221;B&#8217;s f(int)&#8221;;<br />
}<br />
};</p>
<p>&nbsp;</p>
<p>int main()<br />
{<br />
B b;<br />
// b.f();<br />
b.f(1);<br />
}</p>
<p>&nbsp;</p>
<p>Now let us take out A::f, the compilation will fail.  The above program overloads the function inherited from the base class.</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.webbertech.com/blog/?feed=rss2&#038;p=773</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Perl Daemon</title>
		<link>http://www.webbertech.com/blog/?p=766</link>
		<comments>http://www.webbertech.com/blog/?p=766#comments</comments>
		<pubDate>Sat, 12 May 2012 04:38:16 +0000</pubDate>
		<dc:creator>xiaofeng</dc:creator>
				<category><![CDATA[perl]]></category>

		<guid isPermaLink="false">http://www.webbertech.com/blog/?p=766</guid>
		<description><![CDATA[1. Manual way sub daemonize { use POSIX; POSIX::setsid or die &#8220;setsid: $!&#8221;; my $pid = fork (); if ($pid < 0) { die "fork: $!"; } elsif ($pid) { exit 0; } chdir "/"; umask 0; foreach (0 .. (POSIX::sysconf (&#038;POSIX::_SC_OPEN_MAX) &#124;&#124; 1024)) { POSIX::close $_ } open (STDIN, "/dev/null&#8221;); open (STDERR, &#8220;>&#038;STDOUT&#8221;); } [...]]]></description>
			<content:encoded><![CDATA[<p>1. Manual way</p>
<p>sub daemonize {<br />
   use POSIX;<br />
   POSIX::setsid or die &#8220;setsid: $!&#8221;;<br />
   my $pid = fork ();<br />
   if ($pid < 0) {<br />
      die "fork: $!";<br />
   }<br />
   elsif ($pid) {<br />
      exit 0;<br />
   }<br />
   chdir "/";<br />
   umask 0;<br />
   foreach (0 .. (POSIX::sysconf (&#038;POSIX::_SC_OPEN_MAX) || 1024))<br />
      {<br />
         POSIX::close $_<br />
      }<br />
   open (STDIN, "</dev/null");<br />
   open (STDOUT, ">/dev/null&#8221;);<br />
   open (STDERR, &#8220;>&#038;STDOUT&#8221;);<br />
 }</p>
<p>2.<br />
The easiest way is to use Proc::Daemon.</p>
<p>#!/usr/bin/perl</p>
<p>use strict;<br />
use warnings;<br />
use Proc::Daemon;</p>
<p>Proc::Daemon::Init;</p>
<p>my $continue = 1;<br />
$SIG{TERM} = sub { $continue = 0 };</p>
<p>while ($continue) {<br />
     #do stuff<br />
}</p>
<p>Alternately you could do all of the things Proc::Daemon does:</p>
<p>   1. Fork a child and exits the parent process.<br />
   2. Become a session leader (which detaches the program from the controlling terminal).<br />
   3. Fork another child process and exit first child. This prevents the potential of acquiring a controlling terminal.<br />
   4. Change the current working directory to &#8220;/&#8221;.<br />
   5. Clear the file creation mask.<br />
   6. Close all open file descriptors.</p>
<p>Ref:</p>
<p>http://stackoverflow.com/questions/766397/how-can-i-run-a-perl-script-as-a-system-daemon-in-linux</p>
<p>http://www.andrewault.net/2010/05/27/creating-a-perl-daemon-in-ubuntu/</p>
]]></content:encoded>
			<wfw:commentRss>http://www.webbertech.com/blog/?feed=rss2&#038;p=766</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>c++ exception</title>
		<link>http://www.webbertech.com/blog/?p=762</link>
		<comments>http://www.webbertech.com/blog/?p=762#comments</comments>
		<pubDate>Fri, 11 May 2012 22:20:06 +0000</pubDate>
		<dc:creator>xiaofeng</dc:creator>
				<category><![CDATA[c++]]></category>

		<guid isPermaLink="false">http://www.webbertech.com/blog/?p=762</guid>
		<description><![CDATA[What if you do not do the throw()? It does not work. Explain &#8230; class DeviceException : public std::exception { public: DeviceException(); ~DeviceException() throw(); //TODO stub in exception methods //TODO add ability to embed file and line number info into exception }; http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.10 http://www.daniweb.com/software-development/cpp/threads/114299/undefined-reference-to-vtable-for-]]></description>
			<content:encoded><![CDATA[<p>What if you do not do the throw()? It does not work. Explain &#8230;</p>
<p>class DeviceException : public std::exception<br />
	{<br />
	public:<br />
		DeviceException();<br />
		~DeviceException() throw();</p>
<p>		//TODO stub in exception methods<br />
		//TODO add ability to embed file and line number info into exception<br />
	};</p>
<p>http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.10</p>
<p>http://www.daniweb.com/software-development/cpp/threads/114299/undefined-reference-to-vtable-for-</p>
]]></content:encoded>
			<wfw:commentRss>http://www.webbertech.com/blog/?feed=rss2&#038;p=762</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

