2007年1月31日星期三

GCC Extension

http://gcc.gnu.org/onlinedocs/gcc-4.0.1/gcc/Designated-Inits.html#Designated-Inits

1. To initialize a range of elements to the same value, write `[first ... last] = value'. This is a GNU extension. For example,

     int widths[] = { [0 ... 9] = 1, [10 ... 99] = 2, [100] = 3 };


2. In a structure initializer, specify the name of a field to initialize with `.fieldname =' before the element value. For example, given the following structure,

struct point { int x, y; };

the following initialization

struct point p = { .y = yvalue, .x = xvalue };

2007年1月29日星期一

IrDA器件及其应用电路设计

IrDA器件及其应用电路设计
文章作者:上海豪威IC设计有限公司 怯肇乾
文章类型:设计应用 文章加入时间:2004年9月12日23:31
文章出处:单片机及嵌入式系统应用



摘要:简要介绍IrDA红外数据传输的特征;详细说明各种常见IrDA类型器件的构成;重点阐述常用红外数据传输电路的设计及其注意事项。

关键词:红外数据传输 红外检测 IrDA 编/解码 调制/解调

引 言

红外数据传输,成本低廉、连接方便、简单易用、结构紧凑,在小型移动设备中得到了广泛的应用。近年来,很多著名半导体厂商,如Agilent、Vishay、Sharp、Zilog、Omron等,相继推出了许多遵循同一规范的不同类型的器件。本文就IrDA红外数据传输、各种IrDA器件的构成及其不同类型的红外通信电路设计进行综合阐述。

1 红外数据传输及其规范简介

  红外数据传输,使用传播介质——红外线。红外线是波长在750nm~1mm之间的电磁波,是人眼看不到的光线。红外数据传输一般采用红外波段内的近红外线,波长在0.75μm~25μm之间。红外数据协会成立后,为保证不同厂商的红外产品能获得最佳的通信效果,限定所用红外波长在850nm~900nm。

  IrDA是国际红外数据协会的英文缩写,IrDA相继制定了很多红外通信协议,有侧重于传输速率方面的,有侧重于低功耗方面的, 也有二者兼顾的。IrDA1.0协议基于异步收发器UART,最高通信速率在115.2kbps,简称SIR(Serial Infrared,串行红外协议),采用3/16 ENDEC编/解码机制。 IrDA1.1协议提高通信速率到4Mbps,简称FIR(Fast Infrared,快速红外协议),采用4PPM (Pulse Position Modulation,脉冲相位调制)编译码机制, 同时在低速时保留1.0协议规定。之后,IrDA又推出了最高通信速率在16Mbps的协议,简称VFIR(Very Fast Infrared,特速红外协议)。

  IrDA标准包括三个基本的规范和协议:红外物理层连接规范IrPHY(Infrared Physical Layer Link Specification),红外连接访问协议IrLAP (Infrared Link Access Protocol) 和红外连接管理协议IrLMP(Infrared Link Management Protocol)。IrPHY规范制定了红外通信硬件设计上的目标和要求;IrLAP和IrLMP为两个软件层,负责对连接进行设置、管理和维护。在IrLAP和IrLMP基础上,针对一些特定的红外通信应用领域,IrDA还陆续发布了一些更高级别的红外协议,如TinyTP、IrOBEX、IrCOMM、IrLAN、IrTran-P等等。[1~3]

  红外传输距离在几cm到几十m,发射角度通常在0~15°,发射强度与接收灵敏度因不同器件不同应用设计而强弱不一。使用时只能以半双工方式进行红外通信。

  在此把符合IrDA红外通信协议的器件称为IrDA器件,符合SIR协议的器件称为SIR器件,符合FIR协议的器件称为FIR器件,符合VFIR协议的器件称为VFIR器件。

2 红外数据传输的基本模型

红外数据传输可用图1简单表示。

3 IrDA器件的类型划分[3~8]

  根据图1所述模型,把IrDA器件划分类型,如图2所示。

  根据传输速率的大小,可以把IrDA器件区分为SIR、FIR、VFIR类型。如Vishay的红外收发器,TFDU4300是SIR器件,TFDU6102是FIR器件,TFDU8108是VFIR器件。

  根据应用功耗的大小,可以把IrDA器件区分为标准型和低功耗型。低功耗型器件,通常使用1.8~3.6V电源,传输距离较小(约20cm),如Agilent的红外收发器HSDL-3203。标准型器件,通常使用DC5V电源,传输距离大(在30cm~几十m),如Vishay的红外接收器TSOP12xx系列,配合其发射器TSAL5100,传输距离可达35m。

  使用上述三种分类方法,可以清晰地表明一个IrDA红外器件的性能。如Agilent的SIR标准型红外收发器HSDL-3000。

4 IrDA器件的构成及其使用[3~8]

4.1 红外发送器件

  红外发送器大多是使用Ga、As等材料制成的红外发射二极管,其能够通过的LED电流越大,发射角度越小,产生的发射强度就越大;发射强度越大,红外传输距离就越远,传输距离正比于发射强度的平方根。有少数厂商的红外发送器件内置有驱动电路。该类器件的构成如图3所示。

  红外发送器件在使用时通常需要串联电阻,用以分压限流。

4.2 红外检测器件

  红外检测器件的主要部件是红外敏感接收管件,有独立接收管构成器件的,有内含放大器的,有集成放大器与解调器的。后面两种类型的红外检测器件构成如图4所示。

  接收灵敏度是衡量红检测器件的主要性能指标,接收灵敏度越高,传输距离越远,误码率越低。

  内部集成有放大与解调功能的红外检测器件通常还含有带通滤波器,这类器件常用于固定载波频率(如40kHz)的应用。

4.3 红外收发器件

  红外收发器件集发射与接收于一体。通常,器件的发射部分含有驱动器,接收部分含有放大器,并且内部集成有关断控制逻辑。关断控制逻辑在发送时关断接收,以避免引入干扰;不使用红外传输时,该控制逻辑通过SD引脚接受指令,关断器件电源供应,以降耗节能。使用器件时需要在LED引脚接入适当的限流电阻。大多数红外收发器件带有屏蔽层。该层不要直接接地,可以通过串联一磁珠再接地,以引入干扰影响接收灵敏度。红外收发器件的构成如图5所示。

4.4 红外编/解码器件

  编/解码,英文简称ENDEC,即实现调制/解调。编/解码机制,SIR器件多采用3/16 ENDEC,FIR器件多采用4PPM ENDEC。在此解释一下3/16 ENDEC,其它可参阅有关资料。3/16 ENDEC,即把一个有效数字位(bit)时间段,划分为16等分小时间段,以连续3个小时间段内有无脉冲表示调制/解调信息。红外编/解码器件,需要从外部接入时钟或使用自身的晶体振荡电路,进行调制或解调。

  红外编/解码器件,有单独编码的集成器件,如键盘遥控红外编码器Mitsubishi的M50462AP;也有集编码/解码于一体的,这类器件较为多见,其构成如图6所示。

4.5 红外接口器件

  红外接口器件,实现红外传输系统与微控制器、PC机或网络系统的连接。设计中经常使用的器件有UART串行异步收发器件、USB接口转换器件等。

  USB接口器件,实现红外收发与PC机的USB连接。集成度较高的USB接口器件如SigmaTel的STIr4200。STIr4200全兼容IrDA1.3和USB1.1,IrDA速率在2.4k~4Mbps,内含有红外编/解码器和4KB的FIFO缓存,20/28脚封装,可直接相联标准的IrDA收发器件,其构成如图7所示。

5 常用红外数据传输电路设计[3~9]

5.1 家电红外遥控收发电路的设计

  彩电、空调、VCD等家用电器的遥控收发,是单向传输,通信距离通常在3~5m,调制/解调的载波频率通常在36~40kHz,可用"集成键盘编码IC+带驱动的红外发射管"构成发射遥控器,用"带放大与解调功能的红外检测器"构成接收端,接收后的信息可直接送给简易单片机(如AT89C2051),由单片机通过软件进行遥控功能识别并产生相应动作。

  图8是一个通用的家电遥控收发电路框图。

5.2 PC机简易红外收发装置设计

  现在的笔记本电脑、掌上电脑、移动手机等,常常集成有含编/解码功能(38kHz载波)的5针红外接口;可以很容易地设计电路,给PC机配上红外收发装置,无须考虑调制/解调。

  5针红外接口插座引脚定义了:一对电源脚Vcc和GND,一对收发接口IrTx(红外发射端)和IrRx(红外接收端),有一针NC未定义。

  根据IrDA异步串行通信有关标准,IrTx引脚能提供 >6.0mA的输出电流,IrRx引脚在吸收<1.5>)所示的简易红外收发装置。为进一步提高收发传输能力,可在发射端增加驱动,在接收端增加放大。这样做,分立元件过多,电路不够简洁。为简化电路,可以使用带有驱动和放大能力的红外收发器件。图9(b)就是用Zilog的红外收发器ZHX1010构成的简易收发装置。

  给PC机加上红外收发装置后,需要对系统做如下设置:在BIOS中打开红外线接口,在使用时于设备管理器中启动"红外线监视器"。通常,PC机红外接口与其COM2口共用同一地址和中断,打开了红外接口,COM2口就不能再使用了。

5.3 RS232-IrDA红外收发电路设计

  这种类型电路工作在异步串行通信方式下,可以直接采用"UART电平转换器件 + 红外编/解码器件 + 红外收发器件"构成。图10是一个设计举例,图中器件使用了Maxim的MAX232。MAX232完成RS232信号电平到标准数字信号电平(如5V系统)的转换,HSDL-7000是红外编/解码器。

5.4 USB-IrDA红外收发电路设计

  设计这种类型的电路,最简捷的途经就是使用USB-IrDA接口器件。图11是采用SigmaTel的STIr4200接口器件的一个设计举例。STIr4200有一个可选择的外部增强性发射端口,如果要增强红外传输能力(如传输距离),可在该端口增加发射管。对于STIr4200,SigamTel提供有各种Windows版本的驱动程序,使用十分方便。

5.5 微控制器-IrDA红外收发电路设计

  现在很多微控制器,内部集成有UART单元及其接口,支持IrDA标准,并可以直接与红外收发体系连接。图12是这类电路设计的一个举例。图中MCP2120是Microchip的红外可编程波特率编/解码器件。

  有些微控制器,如80C51单片机,虽然内含有UART,却不支持IrDA标准或高速通信,不能直接相连红外收发体系。还有些微控制器,虽然所含的UART可以直接连接红外收发体系,但UART已用于其它目的。此时,可以选用UART接口器件。图13是80C51通过Maxim的MAX3110连接红外收发体系的,80C51单片机没有SPI接口。这里使用其I/O口,通过软件模拟SPI工作机制。MAX3110有一个收发传输中断脚,十分有利于软件编制。

6 红外数据传输电路设计的注意事项

① 要做好红外器件的选型。要求传输快速时,可选择FIR、VFIR收发器与编/解码器。要求长距离传输时,可选择大LED电流、小发射角发射器和灵敏度高的接收检测器。低功耗场合应用时,可选取低功耗的红外器件。要注意低功耗与传输性能之间存在着矛盾:通常低功耗器件,传输距离很小。这一点在应用时应该综合考虑。

② 红外数据传输是半双工性质的。为避免自身产生的信号干扰自身,要确保发送时不接收,接收时不发送,可以着眼于软件设计,使软件在一种状态时暂不理会另一种状态;同时要合理设置好收发之间的时间间隔,不立即从一种方式转入另一种方式。

③ 要合理设计好各种红外器件的供电电路,选择适当的DC-DC器件,恰当地进行电磁抑制,做好电源滤波。同时还要注意尽可能减少功耗,不使用红外电路时要在软件上能够控制关闭其供电。很多厂家对自己推出的红外器件都有推荐的电路设计,要注意参考并实验。

④ PCB设计时,要合理布局器件。滤波电感、电容等要就近器件放置,以确保滤波效果;红外器件与系统的地线要分开布置,仅在一点相连;晶体等振荡器件要靠近所供器件,以减少辐射干扰。

⑤ 增大红外传输距离、提高收发灵敏度的方法:增加发射电路的数量,使几只发射管同时启动发送;在接收管前加装红色滤光片,以滤除其它光线的干扰;在接收管和发射管前面加凸透镜,提高其光线采集能力等等。

GDB使用手册(中文版)

START-INFO-DIR-ENTRY
* Gdb: (gdb). The GNU debugger.
END-INFO-DIR-ENTRY
This file documents the GNU debugger GDB.

This is Edition 4.12, January 1994, of `Debugging with GDB: the GNU
Source-Level Debugger' for GDB Version 4.16.

Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995 Free
Software Foundation, Inc.

Permission is granted to make and distribute verbatim copies of this
manual provided the copyright notice and this permission notice are
preserved on all copies.

Permission is granted to copy and distribute modified versions of
this manual under the conditions for verbatim copying, provided also
that the entire resulting derived work is distributed under the terms
of a permission notice identical to this one.

Permission is granted to copy and distribute translations of this
manual into another language, under the above conditions for modified
versions.

使用GDB:
本文描述GDB,GNU的原代码调试器。(这是4.12版1994年一月,GDB版本4。16)
* 目录:
* 摘要: GDB的摘要
* 实例: 一个使用实例
* 入门: 进入和退出GDB
* 命令: GDB 的命令
* 运行: 在GDB下运行程序
* 停止: 暂停和继续执行
* 栈: 检查堆栈
* 原文件: 检查原文件
* 数据: 检查数据
* 语言: 用不同的语言来使用GDB
* 符号: 检查符号表
* 更改: 更改执行
* GDB的文件 文件
* 对象 指定调试对象
* 控制GDB 控制
* 执行序列: 执行一序列命令
* Emacs: 使GDB和Emacs一起工作
* GDB的bug:
* 命令行编辑: 行编辑
* 使用历史记录交互:
* 格式化文档: 如何格式化和打印GDB文档
* 安装GDB :

* 索引:

GDB简介:
**************

调试器(比如象GDB)能让你观察另一个程序在执行时的内部活动,或程序出错时
发生了什么。
GDB主要能为你做四件事(包括为了完成这些事而附加的功能),帮助你找出程序
中的错误。
* 运行你的程序,设置所有的能影响程序运行的东西。

* 保证你的程序在指定的条件下停止。

* 当你程序停止时,让你检查发生了什么。

* 改变你的程序。那样你可以试着修正某个bug引起的问题,然后继续查找另一
个bug.

你可以用GDB来调试C和C++写的程序。(参考 *C 和C++)

部分支持Modula-2和chill,但现在还没有这方面的文档。

调试Pascal程序时,有一些功能还不能使用。

GDB还可以用来调试FORTRAN程序,尽管现在还不支持表达式的输入,输出变量,
或类FORTRAN的词法。
* GDB是"free software",大家都可以免费拷贝。也可以为GDB增加新的功能,不
过可要遵守GNU的许可协议幺。反正我认为GNU还是比较不错的:-)
就这句话:
Fundamentally, the General Public License is a license which says
that you have these freedoms and that you cannot take these freedoms
away from anyone else.
GDB的作者:
Richard Stallman是GDB的始作俑者,另外还有许多别的GNU的成员。许多人
为此作出了贡献。(都是老外不提也罢,但愿他们不要来找我麻烦:-))
这里是GDB的一个例子:
原文中是使用一个叫m4的程序。但很遗憾我找不到这个程序的原代码,
所以没有办法来按照原文来说明。不过反正是个例子,我就拿一个操作系统的
进程调度原码来说明把,原代码我会附在后面。
首先这个程序叫os.c是一个模拟进程调度的原程序(也许是个老古董了:-))。
先说明一下如何取得包括原代码符号的可执行代码。大家有心的话可以去看一下gcc的
man文件(在shell下打man gcc)。gcc -g <原文件.c> -o <要生成的文件名>
-g 的意思是生成带原代码调试符号的可执行文件。
-o 的意思是指定可执行文件名。
(gcc 的命令行参数有一大堆,有兴趣可以自己去看看。)
反正在linux下把os.c用以上方法编译连接以后就产生了可供gdb使用的可执行文件。
我用gcc -g os.c -o os,产生的可执行文档叫os.
然后打gdb os,就可进入gdb,屏幕提示:
GDB is free software and you are welcome to distribute copies
of it under certain conditions; type "show copying" to see
the conditions.
There is absolutely no warranty for GDB; type "show warranty"
for details.

GDB 4.16, Copyright 1995 Free Software Foundation, Inc...
(gdb)
(gdb)是提示符,在这提示符下可以输入命令,直到退出。(退出命令是q/Q)
为了尽量和原文档说明的命令相符,即使在本例子中没用的命令我也将演示。
首先我们可以设置gdb的屏幕大小。键入:
(gdb)set width 70
就是把标准屏幕设为70列。
然后让我们来设置断点。设置方法很简单:break或简单打b后面加行号或函数名
比如我们可以在main 函数上设断点:
(gdb)break main
或(gdb)b main
系统提示:Breakpoint 1 at 0x8049552: file os.c, line 455.
然后我们可以运行这个程序,当程序运行到main函数时程序就会停止返回到gdb的
提示符下。运行的命令是run或r(gdb中有不少alias,可以看一下help,在gdb下打help)
run 后面可以跟参数,就是为程序指定命令行参数。
比如r abcd,则程序就会abcd以作为参数。(这里要说明的是可以用set args来指定参
数)。打入r或run后,程序就开始运行直到进入main的入口停止,显示:
Starting program: <路径>/os

Breakpoint 1, main () at os.c:455
455 Initial();
这里455 Initial();是将要执行的命令或函数。
gdb提供两种方式:1.单步进入,step into就是跟踪到函数内啦。命令是step或s
2.单步,next,就是简单的单步,不会进入函数。命令是next或n
这两个命令还有别的用法以后再说。
我们用n命令,键入:
(gdb)n
Success forking process# 1 ,pid is 31474

Success forking process# 2 ,pid is 31475

Success forking process# 3 ,pid is 31476

Success forking process# 4 ,pid is 31477

Success forking process# 5 ,pid is 31478

Success forking process# 6 ,pid is 31479

Dispatching Algorithm : FIFO
********************************************************************************

PCB# PID Priority PC State
1 31474 24 0 WAITING
2 31475 19 0 WAITING
3 31476 16 0 WAITING
4 31477 23 0 WAITING
5 31478 22 0 WAITING
6 31479 20 0 WAITING

******************************************************************************

CPU : NO process running
IO : No process
Waiting CPU!!! 31474 31475 31476 31477 31478 31479
Waiting IO NONE
456 State=WAITING;
最后的一行就是下一句要执行的命令。我们现在在另一个函数上加断点。注意我们
可以用l/list命令来显示原代码。这里我们键入
(gdb)l
451 main()
452 {
453 int message;
454
455 Initial();
456 State=WAITING;
457 printf("Use Control-C to halt \n");
458 signal(SIGALRM,AlarmMessage);
459 signal(SIGINT,InteruptMessage);
460 signal(SIGUSR2,IoMessage);
(gdb) l
461 alarm(TimeSlot);
462 for(;;)
463 {
464 message=GetMessage();
465 switch(message)
466 {
467 case INTERRUPT : printf("Use Control-C t;

468 break;
469 case CHILD_IO: WaitingIo();
470 break;
显示了原代码,现在在AlarmMessage上加断点。
(gdb) b AlarmMessage
Breakpoint 2 at 0x8048ee3: file os.c, line 259.
(gdb)
然后我们继续运行程序。
(gdb)c
c或continue命令让我们继续被中断的程序。 显示:
Continuing.
Use Control-C to halt

Breakpoint 2, AlarmMessage () at os.c:259
259 ClearSignal();
注意我们下一句语句就是ClearSignal();
我们用s/step跟踪进入这个函数看看它是干什么的。
(gdb) s
ClearSignal () at os.c:227
227 signal(SIGINT,SIG_IGN);
用l命令列出原代码:
(gdb) l
222 }
223
224
225 void ClearSignal() /* Clear other signals */
226 {
227 signal(SIGINT,SIG_IGN);
228 signal(SIGALRM,SIG_IGN);
229 signal(SIGUSR2,SIG_IGN);
230 }
231
(gdb)
我们可以用s命令继续跟踪。现在让我们来试试bt或backtrace命令。这个命令可以
显示栈中的内容。
(gdb) bt
#0 ClearSignal () at os.c:227
#1 0x8048ee8 in AlarmMessage () at os.c:259
#2 0xbffffaec in ?? ()
#3 0x80486ae in ___crt_dummy__ ()
(gdb)
大家一定能看懂显示的意思。栈顶是AlarmMessage,接下来的函数没有名字--就是
没有原代码符号。这显示了函数调用的嵌套。
好了,我们跟踪了半天还没有检查过变量的值呢。检查表达式的值的命令是p或print
格式是p <表达式>
444444让我们来找一个变量来看看。:-)
(gdb)l 1
还记得l的作用吗?l或list显示原代码符号,l或list加<行号>就显示从<行号>开始的
原代码。好了找到一个让我们来看看WaitingQueue的内容
(gdb) p WaitingQueue
$1 = {1, 2, 3, 4, 5, 6, 0}
(gdb)
WaitingQueue是一个数组,gdb还支持结构的显示,
(gdb) p Pcb
$2 = {{Pid = 0, State = 0, Prior = 0, pc = 0}, {Pid = 31474, State = 2,
Prior = 24, pc = 0}, {Pid = 31475, State = 2, Prior = 19, pc = 0}, {
Pid = 31476, State = 2, Prior = 16, pc = 0}, {Pid = 31477, State = 2,
Prior = 23, pc = 0}, {Pid = 31478, State = 2, Prior = 22, pc = 0}, {
Pid = 31479, State = 2, Prior = 20, pc = 0}}
(gdb)
这里可以对照原程序看看。
原文档里是一个调试过程,不过我想这里我已经把gdb的常用功能介绍了一遍,基本上
可以用来调试程序了。:-)
 
运行GDB(一些详细的说明):

前面已经提到过如何运行GDB了,现在让我们来看一些更有趣的东西。你可以在运行
GDB时通过许多命令行参数指定大量的参数和选项,通过这个你可以在一开始就设置好
程序运行的环境。
这里将要描述的命令行参数覆盖了大多数的情况,事实上在一定环境下有的并没有
什么大用处。最通常的命令就是使用一个参数:
$gdb <可执行文档名>
你还可以同时为你的执行文件指定一个core文件:
$gdb <可执行文件名> core
你也可以为你要执行的文件指定一个进程号:
$gdb <可执行文件名> <进程号> 如:&gdb os 1234将使gdb与进程1234相联系(attach)
除非你还有一个文件叫1234的。gdb首先检查一个core文件。
如果你是使用一个远程终端进行远程调试的话,那如果你的终端不支持的话,你将无法
使用第二个参数甚至没有core dump。如果你觉得开头的提示信息比较碍眼的话,你可以
用gdb -silent。你还可以用命令行参数更加详细的控制GDB的行为。
打入gdb -help或-h 可以得到这方面的提示。所有的参数都被按照排列的顺序传给gdb
除非你用了-x参数。
当gdb开始运行时,它把任何一个不带选项前缀的参数都当作为一个可执行文件或core
文件(或进程号)。就象在前面加了-se或-c选项。gdb把第一个前面没有选项说明的参数
看作前面加了-se 选项,而第二个(如果有的话)看作是跟着-c选项后面的。
许多选项有缩写,用gdb -h可以看到。在gdb中你也可以任意的把选项名掐头去尾,只
要保证gdb能判断唯一的一个参数就行。
在这里我们说明一些最常用的参数选项
-symbols <文件名>(-s <文件名>)------从<文件名>中读去符号。
-exec <文件名>(-e <文件名>)----在合适的时候执行<文件名>来做用正确的数据与core
dump的作比较。
-se <文件名>------从<文件名>中读取符号并把它作为可执行文件。
-core <文件名>(-c <文件名>)--指定<文件名>为一个core dump 文件。
-c <数字>----连接到进程号为<数字>,与attach命令相似。
-command <文件名>
-x <文件名>-----执行gdb命令,在<文件名>指定的文件中存放着一序列的gdb命令,就
象一个批处理。
-directory(-d) <路径>---指定路径。把<路径>加入到搜索原文件的路径中。
-m
-mapped----
注意这个命令不是在所有的系统上都能用。如果你可以通过mmap系统调用来获得内存
映象文件,你可以用这个命令来使gdb把你当前文件里的符号写入一个文件中,这个文件
将存放在你的当前路径中。如果你调试的程序叫/temp/fred那么map文件就叫
./fred.syms这样当你以后再调试这个程序时,gdb会认识到这个文件的存在,从而从这
个文件中读取符号,而不是从可执行文件中读取。.syms与主机有关不能共享。
-r
-readnow---马上从符号文件中读取整个符号表,而不是使用缺省的。缺省的符号表是
调入一部分符号,当需要时再读入一部分。这会使开始进入gdb慢一些,但可以加快以后
的调试速度。

-m和-r一般在一起使用来建立.syms文件


接下来再谈谈模式的设置(请听下回分解 :-))
附:在gdb文档里使用的调试例子我找到了在minix下有这个程序,叫m4有兴趣的
可以自己去看看模式的选择
--------------
现在我们来聊聊gdb运行模式的选择。我们可以用许多模式来运行gdb,例如在"批模式"
或"安静模式"。这些模式都是在gdb运行时在命令行作为选项指定的。
`-nx'
`-n'
不执行任何初始化文件中的命令。(一般初始化文件叫做`.gdbinit').一般情况下在
这些文件中的命令会在所有的命令行参数都被传给gdb后执行。

`-quiet'
`-q'
"安静模式"。不输出介绍和版权信息。这些信息在"批模式"中也被跳过。

`-batch'
"批模式"。在"批模式"下运行。当在命令文件中的所有命令都被成功的执行后
gdb返回状态"0",如果在执行过程中出错,gdb返回一个非零值。
"批模式"在把gdb作为一个过滤器运行时很有用。比如在一台远程计算机上下载且
执行一个程序。信息" Program exited normally"(一般是当运行的程序正常结束
时出现)不会在这种模式中出现。
`-cd DIRECTORY'
把DIRECTORY作为gdb的工作目录,而非当前目录(一般gdb缺省把当前目录作为工作目
录)。
`-fullname'
`-f'
GNU Emacs 设置这个选项,当我们在Emacs下,把gdb作为它的一个子进程来运行时,
Emacs告诉gdb按标准输出完整的文件名和行号,一个可视的栈内容。这个格式跟在
文件名的后面。行号和字符重新按列排,Emacs-to-GDB界面使用\032字符作为一个
显示一页原文件的信号。
`-b BPS'
为远程调试设置波特率。

`-tty DEVICE'
使用DEVICE来作为你程序的标准输入输出。
退出gdb
============

`quit'
使用'quit'命令来退出gdb,或打一个文件结束符(通常是' CTROL-D')。如果
你没有使用表达式,gdb会正常退出,否则它会把表达式的至作为error code
返回。

一个中断(通常是'CTROL-c)不会导致从gdb中退出,而是结束任何一个gdb的命
令,返回gdb的命令输入模式。一般在任何时候使用'CTROL-C'是安全的,因为
gdb会截获它,只有当安全时,中断才会起作用。
如果你正在用gdb控制一个被连接的进程或设备,你可以用'detach'命令来释放
它。

Shell命令
==============
当你偶尔要运行一些shell命令时,你不必退出调试过程,也不需要挂起它;你
可以使用'shell'命令。

`shell COMMAND STRING'
调用标准shell来执行'COMMAND STRING'.环境变量'SHELL'决定了那个shell被
运行。否则gdb使用'/bin/sh'.
'make'工具经常在开发环境中使用,所以你可以不用'shell'命令而直接打'make'

`make MAKE-ARGS'
用指定的命令行变量来运行'make'程序,这等于使用'shell make MAKE-ARGS'
GDB 命令
************
我们可以把一个gdb命令缩写成开头几个字母,如果这没有二意性你可以直接回车来
运行。你还可以使用TAB键让gdb给你完成接下来的键入,或向你显示可选择的命令,
如果有不止一个选择的话。

Command语法
==============

一个gdb命令是一个单行的输入。长度没有限制。它一个命令开头,后面可以跟参量。
比如命令'step'接受一个参量表示单步执行多少步。你也可以不用参量。有的命令
不接受任何参量。

gdb命令只要没有二意性的话就可以被缩写。另外一些缩写作为一个命令列出。在某些
情况下二意也是允许的。比如's'是指定'step'的缩写,但还有命令'start'。你可以把
这些缩写作为'help'命令的参量来测试它们。
空行(直接回车)表示重复上一个命令。但有些命令不能重复比如象'run',就不会以这
种方式重复,另外一些当不小心重复会产生严重后果的命令也不能用这种方法重复。
'list'和'x'命令当你简单的打回车时,会建立新的变量,而不是简单的重复上一个命
令。这样你可以方便的浏览原代码和内存。
gdb还有一种解释RET的方法:分割长输出。这种方法就和'more'命令相似。由于这时经
常会不小心多打回车,gdb将禁止重复当一个命令产生很长的输出时。
任何用'#'开头一直到行尾的命令行被看作是注释。主要在命令文件中使用。
输入命令的技巧
==================
前面已经提到过TAB键的使用。使用TAB键能让你方便的得到所要的命令。比如
在gdb中:
(gdb)info bre (键入info bre,后按TAB键)
gdb能为你完成剩下的输入。它还能萎蔫提供选择的可能性。如果有两个以上可
能的话,第一次按键,gdb会响铃提示,第二次则显示可能的选择。同样gdb
也可以为一些子命令提供快速的访问。用法与上相同。
上例中显示
(gdb)info breakepoints
你也可以直接打回车,gdb就将你输入的作为命令的可能的缩写。来判断执行。
如果你打入的缩写不足以判断,那么gdb会显示一个列表,列出可能的命令。同样的
情况对于命令的参数。在显示完后gdb把你的输入拷贝到当前行以便让你继续输入。
如果你只想看看命令的列表或选项,你可以在命令行下打M-?(就是按着ESC键
同时按SHIFT和?键)。你可以直接在命令行下打试试。
(gdb)
gdb会响铃并显示所有的命令。不过这种方式好象在远程调试是不行。当有的命令
使用一个字符串时,你可以用" ' "将其括起来。这种方法在调试C++程序时特别有用。
因为C++支持函数的重载。当你要在某个有重载函数上设断点时,不得不给出函数参数
以区分不同的重载函数。这时你就应该把整个函数用" ' "括起来。比如,你要在一个
叫name的函数上设断点,而这个函数被重载了(name(int)和name(float))。你将不得
不给出参变量以区分不同的函数。使用'name(int)'和'name(float)'。这里有个技巧,
你可以在函数名前加一个" ' "符号。然后打M-?.
得到帮助
============
你可以使用help命令来得到gdb的在线帮助。

`help'
`h'
你可以使用help或h后面不加任何参数来得到一个gdb命令类的列表。

(gdb) help
List of classes of commands:

running -- Running the program
stack -- Examining the stack
data -- Examining data
breakpoints -- Making program stop at certain points
files -- Specifying and examining files
status -- Status inquiries
support -- Support facilities
user-defined -- User-defined commands
aliases -- Aliases of other commands
obscure -- Obscure features

Type "help" followed by a class name for a list of
commands in that class.
Type "help" followed by command name for full
documentation.
Command name abbreviations are allowed if unambiguous.
(gdb)

`help CLASS'
使用上面列出的help class作为help或h的参量,你可以得到单一的命令列表。
例如显示一个'status'类的列表。

(gdb) help status
Status inquiries.

List of commands:

show -- Generic command for showing things set
with "set"
info -- Generic command for printing status

Type "help" followed by command name for full
documentation.
Command name abbreviations are allowed if unambiguous.
(gdb)

`help COMMAND'
详细列出单个命令的资料。

`complete ARGS'
列出所有以ARGS开头的命令。例如:

complete i

results in:

info
inspect
ignore

This is intended for use by GNU Emacs.

除了使用'help'你还可以使用gdb的命令'info'和'show'来查询你程序的
状态,每个命令可以查询一系列的状态。这些命令以恰当的方式显示所有的
子命令。

`info'
此命令(可以缩写为'i')用来显示你程序的状态。比如,你可以使用info
args 列出你程序所接受的命令行参数。使用info registers列出寄存器的状态。
或用info breakpoint列出在程序中设的断点。要获得详细的关于info的信息打
help info.
`set'
这个命令用来为你的程序设置一个运行环境(使用一个表达式)。比如你
可以用set prompt $来把gdb的提示符设为$.

`show'
与'info'相反,'show'命令用来显示gdb自身的状态。你使用'set'命令来
可以改变绝大多数由'show'显示的信息。比如使用show radix命令来显示基数。
用不带任何参变量的'set'命令你可以显示所有你可以设置的变量的值。
有三个变量是不可以用'set'命令来设置的。
`show version'
显示gdb的版本号。如果你发现gdb有bug的话你应该在bug-reports里加
入gdb的版本号。

`show copying'
显示版权信息。

`show warranty'
显示担保信息。
在gdb下运行你的程序
**************************
当你在gdb下运行程序时,你必须先为gdb准备好带有调试信息的可执行文档。
还可以在gdb中为你的程序设置参变量,重定向你程序的输入/输出,设置环境变
量,调试一个已经执行的程序或kill掉一个子进程。
这里许多内容在早先的例子中都已经用到过,可以参见gdb(二)。
目录:

* 编译:: 为调试编译带调试信息的代码
* 运行:: 运行你的程序
* 参变量:: 为你的程序设置参变量
* 运行环境:: 为你的程序设置运行时环境
* 设置工作目录:: 在gdb中设置程序的工作目录。
* 输入/输出:: 设定你程序的输入和输出
* 连接:: 调试一个已经运行的程序
* 结束子进程:: Kill子进程
* 进程信息:: 附加的进程信息
* 线程:: 调试带多线程的程序
* 多进程:: 调试带多进程的程序
为调试准备带调试信息的代码
===========================
为了高效的调试一个程序,你需要使用编译器来产生附带调试信息的可执行代码
这些调试信息存储在目标文件中;描述了变量数据类型和函数声明,在原文件代码行
和执行代码之间建立联系。
为产生调试信息,当你使用编译器时指定'-g'选项,就可以为你的程序产生带有
调试信息的可执行代码。
有些c编译器不支持'-g'选项和'-O'选项,那你就有麻烦了,或者有别的方法产生
带调试信息的可执行代码,要不就没办法了。
gcc,GNU的c语言编译器支持'-g'和'-O'选项。这样你就可以产生带调试信息的且
优化过的可执行代码.
当你使用gdb来调试一个使用'-g','-O'选项产生的程序时,千万记住编译器为了优
化你的程序重新安排了你的程序。不要为运行次序与你原来设想的不同,最简单的例子
就是当你定义了一个变量但从未使用过它时,gdb中是看不到这个变量的--因为它已经
被优化掉了。
所以有时你不要使用'-O'选项,如果当你不用优化时产生的程序是正确的,而优化
过后变的不正确了,那么这是编译器的bug你可以向开发者提供bug-reports(包括出错
的例子)。
早期的GUN C语言编译器允许'-gg'选项,也用来产生调试信息,gdb不再支持这种格
式的调试信息,如果你的编译器支持'-gg'选项,请不要使用它。

开运行你的程序
=====================

`run'
`r'
使用'run'命令在gdb下启动你的程序。你必须先指定你程序的名字(用gdb的命令行
参数)或使用'file'命令,来指定文件名。如果你在一个支持多进程的环境下运行你的程
序'run'命令创建一个子进程然后加载你的程序。如果环境不支持进程,则gdb直接调到
程序的第一条命令。
一些父进程设置的参量可以决定程序的运行。gdb提供了指定参量的途径,但你必须
在程序执行前设置好他们。你也可以在运行过程中改变它们,但每次改变只有在下一次
运行中才会体现出来。这些参量可以分为四类:
---参数
你可以在使用'run'命令时设置,如果shell支持的话,你还可以使用通配符,或
变量代换。在UNIX系统中你可以使用'shell环境变量'来控制shell。
---环境:
你的程序一般直接从gdb那里继承环境变量。但是你可以使用'set environment'
命令来设置专门的环境变量。
---工作目录
你的程序还同时从gdb那里继承了工作目录,你可以使用'cd'命令在gdb中改变工作
目录。
---标准输入/输出
你的程序一般使用与gdb所用的相似的设备来输入/输出。不过你可以为你的程序的
输入/输出进行重定向。使用'run'或'tty'命令来设置于gdb所用不同的设备。
*注意:当你使用输入/输出重定向时,你将不能使用无名管道来把你所调试的程序的输出
传给另一个程序。这样gdb会认为调试程序出错。
当你发出'run'命令后,你的程序就开始运行。
如果你的符号文件的时间与gdb上一次读入的不同,gdb会废弃原来的符号表并重新读
入。当前的断点不变。
程序环境
==========================
"环境"包括了一系列的环境变量和它们的值。环境变量一般记录了一些常用的信息,
比如你的用户名,主目录,你的终端型号和你的运行程序的搜索路径。一般你可以在shell
下设置环境变量,然后这些变量被所有你所运行的程序所共享。在调试中,可以设置恰当
的环境变量而不用退出gdb.

`path DIRECTORY'
在'PATH'环境变量前加入新的内容('PATH'提供了搜索执行文件的路径)。对于gdb和
你的程序来说你也许要设置一些专门的路径。使用':'或空格来分隔。如果DIRECTORY已经
在路径中了,这个操作将会把它移到前面。
你可以使用串'$cmd'来代表当前路径,如果你用'.'的话,它代表你使用'path'命令
时的路径,gdb将在把DIRECTORY加入搜索路径前用'.'代替当前路径

`show paths'
显示当前路径变量的设置情况。

`show environment [VARNAME]'
显示某个环境变量的值。如果你不指明变量名,则gdb会显示所有的变量名和它们的
内容。environment可以被缩写成'env'

`set environment VARNAME [=] VALUE'
设置某个环境变量的值。不过只对你所调试的程序有效。对gdb本身是不起作用的。
值可以是任何串。如果未指定值,则该变量值将被设为NULL.
看一个例子:
set env USER = foo
告诉一个linux程序,当它下一次运行是用户名将是'foo'

`unset environment VARNAME'
删除某环境变量。

注意:gdb使用'shell'环境变量所指定的shell来运行你的程序。


工作路径
================================
当你每次用'run'命令来运行你的程序时,你的程序将继承gdb的
当前工作目录。而gdb的工作目录是从它的父进程继承而来的(一般是
shell)。但你可以自己使用'cd'命令指定工作目录。
gdb的工作目录就是它去寻找某些文件或信息的途径。
`cd DIRECTORY'
把gdb的工作目录设为DIRECTORY
`pwd'
打印输出当前目录。
你程序的输入/输出
===============================
缺省时,你的程序的输入/输出和gdb的输入/输出使用同一个终端。
gdb在它自己和你的程序之间切换来和你交互,但这会引起混乱。
`info terminal'
显示你当前所使用的终端的类型信息。
你可以把你程序的输入/输出重定向。
例如:
run > outfile
运行你的程序并把你程序的标准输出写入文件outfile中。
另一个为你程序指定输入/输出的方法是使用'tty'命令,这个命令
接受一个文件名作为参量把这个文件作为以后使用'run'命令的缺省命
令文件。它还重新为子进程设置控制终端。
例如:
tty /dev/ttyb
指定以后用'run'命令启动的进程使用终端'/dev/ttyb'作为程序的输入
/输出,而且把这个终端设为你进程的控制终端。
一个清楚的使用'run'命令的重定向将重新设置'tty'所设置的内容
,但不影响控制终端。 当你使用'tty'命令或在'run'命令中对输入
/输出进行重定向时,只有你当前调试的程序的输入/输出被改变了,
并不会影响到别的程序。
调试一个已经运行的程序:
====================================

`attach PROCESS-ID'
这个命令把一个已经运行的进程(在gdb外启动)连接入gdb,以便
调试。PROCESS-ID是进程号。(UNIX中使用'ps'或'jobs -l'来查看进程)
'attach'一般不重复。(当你打了一个以上的回车时)
当然要使用'attach'命令的话,你的操作系统环境必须支持进程。
另外你还要有向此进程发信号的权力。
当使用'attach'命令时,你应该先使用'file'命令来指定进程所
联系的程序源代码和符号表。 当gdb接到'attach'命令后第一件
事就是停止进程的运行,你可以使用所有gdb的命令来调试一个"连接"
的进程,就象你用'run'命令在gdb中启动它一样。如果你要进程继续运
行,使用'continue'或'c'命令就行了。
`detach'
当你结束调试后可以使用此命令来断开进程和gdb的连接。(解除gdb
对它的控制)在这个命令执行后进程将继续执行。
如果你在用'attach'连接一个进程后退出了gdb,或使用'run'命令执
行了另一个进程,这个被'attach'的进程将被kill掉。但缺省时,gdb会
要求你确认你是否要退出或执行一个新的进程。
结束子进程
=========================
`kill'
Kill命令结束你程序在gdb下开的子进程
这个命令当你想要调试(检查)一个core dump文件时更有用。gdb在调试过程中
会忽略所有的core dump。
在一些操作系统上,一个程序当你在上面加了断点以后就不能离开gdb独立运行。
你可以用kill命令来解决这个问题。
'kill'命令当你想重新编译和连接你的程序时也很有用。因为有些系统不允许修改
正在执行的可执行程序。这样当你再一次使用'run'命令时gdb会知道你的程序已经被改
变了,那么gdb会重新load新的符号。(而且尽量保持你当前的断点设置。
附加的进程信息
==============================
一些操作系统提供了一个设备目录叫做'/proc'的,供检查进程映象。如果gdb被在这
样的操作系统下运行,你可以使用命令'info proc'来查询进程的信息。('info proc'命
令只在支持'procfs'的SVR4系统上有用。
`info proc'
显示进程的概要信息。
`info proc mappings'
报告你进程所能访问的地址范围。
`info proc times'
你进程和子进程的开始时间,用户时间(user CPU time),和系统CPU时间。
`info proc id'
报告有关进程id的信息。
`info proc status'
报告你进程的一般状态信息。如果进程停止了。这个报告还包括停止的原因和收到的
信号。
`info proc all'
显示上面这些命令返回的所有信息。
对多线程程序的调试
========================================
一些操作系统中,一个单独的程序可以有一个以上的线程在运行。线程和进程精确的定?nbsp;
?nbsp;

?nbsp;
?nbsp;
有自己的寄存器,运行时堆栈或许还会有私有内存。
gdb提供了以下供调试多线程的进程的功能:
* 自动通告新线程。
* 'thread THREADNO',一个用来在线程之间切换的命令。
* 'info threads',一个用来查询现存线程的命令。
* 'thread apply [THREADNO] [ALL] ARGS',一个用来向线程提供命令的命令。
* 线程有关的断点设置。
注意:这些特性不是在所有gdb版本都能使用,归根结底要看操作系统是否支持。
如果你的gdb不支持这些命令,会显示出错信息:
(gdb) info threads
(gdb) thread 1
Thread ID 1 not known. Use the "info threads" command to
see the IDs of currently known threads.
gdb的线程级调试功能允许你观察你程序运行中所有的线程,但无论什么时候
gdb控制,总有一个"当前"线程。调试命令对"当前"进程起作用。
一旦gdb发现了你程序中的一个新的线程,它会自动显示有关此线程的系统信
息。比如:
[New process 35 thread 27]
不过格式和操作系统有关。
为了调试的目的,gdb自己设置线程号。
`info threads'
显示进程中所有的线程的概要信息。gdb按顺序显示:
1.线程号(gdb设置)
2.目标系统的线程标识。
3.此线程的当前堆栈。
一前面打'*'的线程表示是当前线程。
例如:
(gdb) info threads
3 process 35 thread 27 0x34e5 in sigpause ()
2 process 35 thread 23 0x34e5 in sigpause ()
* 1 process 35 thread 13 main (argc=1, argv=0x7ffffff8)
at threadtest.c:68
`thread THREADNO'
把线程号为THREADNO的线程设为当前线程。命令行参数THREADNO是gdb内定的
线程号。你可以用'info threads'命令来查看gdb内设置的线程号。gdb显示该线程
的系统定义的标识号和线程对应的堆栈。比如:

(gdb) thread 2
[Switching to process 35 thread 23]
0x34e5 in sigpause ()
"Switching后的内容取决于你的操作系统对线程标识的定义。

`thread apply [THREADNO] [ALL] ARGS'
此命令让你对一个以上的线程发出相同的命令"ARGS",[THREADNO]的含义同上。
如果你要向你进程中的所有的线程发出命令使用[ALL]选项。
无论gdb何时中断了你的程序(因为一个断点或是一个信号),它自动选择信号或
断点发生的线程为当前线程。gdb将用一个格式为'[Switching to SYSTAG]'的消息
来向你报告。
*参见:运行和停止多线程程序。
*参见:设置观察点

调试多进程的程序
==========================================
gdb对调试使用'fork'系统调用产生新进程的程序没有很多支持。当一个程序开始
一个新进程时,gdb将继续对父进程进行调试,子进程将不受影响的运行。如果你在子
进程可能会执行到的地方设了断点,那么子进程将收到'SIGTRAP'信号,如果子进程没
有对这个信号进行处理的话那么缺省的处理就是使子进程终止。
然而,如果你要一定要调试子进程的话,这儿有一个不是很麻烦的折衷的办法。在
子进程被运行起来的开头几句语句前加上一个'sleep'命令。这在调试过程中并不会引
起程序中很大的麻烦(不过你要自己注意例外的情况幺:-))。然后再使用'ps'命令列出
新开的子进程号,最后使用'attach'命令。这样就没有问题了。
关于这一段,本人觉得实际使用上并不全是这样。我在调试程中就试过,好象不一定
能起作用,要看gdb的版本和你所使用的操作系统了。
停止和继续
***********************
调试器的基本功能就是让你能够在程序运行时在终止之前在某些条件下停止下来,然
后再继续运行,这样的话你就可以检查当你的程序出错时你的程序究竟做了些什么。
在gdb内部,你的程序会由于各种原因而暂时停止,比如一个信号,一个断点,或是
由于你用了'step'命令。在程序停止的时候你就可以检查和改变变量的值,设置或去掉
断点,然后继续你程序的运行。一般当程序停下来时gdb都会显示一些有关程序状态的信
息。比如象程序停止的原因,堆栈等等。如果你要了解更详细的信息,你可以使用'info
program'命令。另外,在任何时候你输入这条命令,gdb都会显示当前程序运行的状态信
息。

`info program'
显示有关你程序状态的信息:你的程序是在运行还是停止,是什么进程,为什么停
止。

断点,观察点和异常
========================================
断点的作用是当你程序运行到断点时,无论它在做什么都会被停止下来。对于每个断点
你都可以设置一些更高级的信息以决定断点在什么时候起作用。你可以使用'break'命令
来在你的程序中设置断点,在前面的例子中我们已经提到过一些这个命令的使用方法了。
你可以在行上,函数上,甚至在确切的地址上设置断点。在含有异常处理的语言(比如象
c++)中,你还可以在异常发生的地方设置断点。
在SunOS 4.x,SVR4和Alpha OSF/1的设置中,你还可以在共享库中设置断点。
观察点是一种特殊的断点。它们在你程序中某个表达式的值发生变化时起作用。你必
须使用另外一些命令来设置观察点。除了这个特性以外,你可以象对普通断点一样对观察
点进行操作--使用和普通断点操作一样的命令来对观察点使能,使不能,删除。
你可以安排当你程序被中断时显示的程序变量。
当你在程序中设置断点或观察点时gdb为每个断点或观察点赋一个数值.在许多对断点
操作的命令中都要使用这个数值。
设置断点
=============
使用'break'或简写成'b'来设置断点。gdb使用环境变量$bpnum来记录你最新设置的
断点。
你有不少方法来设置断点。


`break FUNCTION'
此命令用来在某个函数上设置断点。当你使用允许函数重载的语言比如C++时,有可
能同时在几个重载的函数上设置了断点。

`break +OFFSET'
`break -OFFSET'
在当前程序运行到的前几行或后几行设置断点。OFFSET为行号。

`break LINENUM'
在行号为LINENUM的行上设置断点。程序在运行到此行之前停止。

`break FILENAME:LINENUM'
在文件名为FILENAME的原文件的第LINENUM行设置断点。

`break FILENAME:FUNCTION'
在文件名为FILENAME的原文件的名为FUNCTION的函数上设置断点。
当你的多个文件中可能含有相同的函数名时必须给出文件名。

`break *ADDRESS'
在地址ADDRESS上设置断点,这个命令允许你在没有调试信息的程
序中设置断点。
`break'
当'break'命令不包含任何参数时,'break'命令在当前执行到的程
序运行栈中的下一条指令上设置一个断点。除了栈底以外,这个命令使
程序在一旦从当前函数返回时停止。相似的命令是'finish',但'finish'
并不设置断点。这一点在循环语句中很有用。
gdb在恢复执行时,至少执行一条指令。

`break ... if COND'
这个命令设置一个条件断点,条件由COND指定;在gdb每次执行到此
断点时COND都被计算当COND的值为非零时,程序在断点处停止。这意味着
COND的值为真时程序停止。...可以为下面所说的一些参量。

`tbreak ARGS'
设置断点为只有效一次。ARGS的使用同'break'中的参量的使用。

`hbreak ARGS'
设置一个由硬件支持的断点。ARGS同'break'命令,设置方法也和
'break'相同。但这种断点需要由硬件支持,所以不是所有的系统上这个
命令都有效。这个命令的主要目的是用于对EPROM/ROM程序的调试。因为
这条命令可以在不改变代码的情况下设置断点。这可以同SPARCLite DSU
一起使用。当程序访问某些变量和代码时,DSU将设置"陷井"。注意:
你只能一次使用一个断点,在新设置断点时,先删除原断点。
`thbreak ARGS'
设置只有一次作用的硬件支持断点。ARGS用法同'hbreak'命令。这个命令
和'tbreak'命令相似,它所设置的断点只起一次作用,然后就被自动的删除。这
个命令所设置的断点需要有硬件支持。

`rbreak REGEX'
在所有满足表达式REGEX的函数上设置断点。这个命令在所有相匹配的函数
上设置无条件断点,当这个命令完成时显示所有被设置的断点信息。这个命令设
置的断点和'break'命令设置的没有什么不同。这样你可以象操作一般的断点一
样对这个命令设置的断点进行删除,使能,使不能等操作。当调试C++程序时这
个命令在重载函数上设置断点时非常有用。

`info breakpoints [N]'
`info break [N]'
`info watchpoints [N]'
显示所有的断点和观察点的设置表,有下列一些列

*Breakpoint Numbers*----断点号
*Type*----断点类型(断点或是观察点)
*Disposition*---显示断点的状态。

*Enabled or Disabled*---使能或不使能。'y'表示使能,'n'表示不使能。

*Address*----地址,断点在你程序中的地址(内存地址)
*What*---地址,断点在你程序中的行号。
如果断点是条件断点,此命令还显示断点所需要的条件。
带参数N的'info break'命令只显示由N指定的断点的信息。
此命令还显示断点的运行信息(被执行过几次),这个功能在使用'ignore'
命令时很有用。你可以'ignore'一个断点许多次。使用这个命令可以查看断点
被执行了多少次。这样可以更快的找到错误。
gdb允许你在一个地方设置多个断点。但设置相同的断点无疑是弱智的。不过
你可以使用条件断点,这样就非常有用。
gdb有时会自动在你的程序中加入断点。这主要是gdb自己的需要。比如为了正
确的处理C语言中的'longjmp'。这些内部断点都是负值,以'-1'开始。'info
breakpoints'不会显示它们。
不过你可以使用命令'maint info breakpoints'来查看这些断点。

`maint info breakpoints'
使用格式和'info breakpoints'相同,显示所有的断点,无论是你设置的还是
gdb自动设置的。
以下列的含义:

`breakpoint'
断点,普通断点。
`watchpoint'
普通观察点。

`longjmp'
内部断点,用于处理'longjmp'调用。

`longjmp resume'
内部断点,设置在'longjmp'调用的目标上。

`until'
'until'命令所使用的内部断点。

`finish'
'finish'命令所使用的内部断点。
设置观察点
==============
你可以使用观察点来停止一个程序,当某个表达式的值改变时,观察点会将程序
停止。而不需要先指定在某个地方设置一个断点。
由于观察点的这个特性,使观察点的使用时开销比较大,但在捕捉错误时非常有
用。特别是你不知道你的程序什么地方出了问题时。

`watch EXPR'
这个命令使用EXPR作为表达式设置一个观察点。GDB将把表达式加入到程序中
并监视程序的运行,当表达式的值被改变时GDB就使程序停止。这个也可以被用在
SPARClite DSU提供的新的自陷工具中。当程序存取某个地址或某条指令时(这个地
址在调试寄存器中指定),DSU将产生自陷。对于数据地址DSU支持'watch'命令,然而
硬件断点寄存器只能存储两个断点地址,而且断点的类型必须相同。就是两个
'rwatch'型断点,或是两个'awatch'型断点。

`rwatch EXPR'
设置一个观察点,当EXPR被程序读时,程序被暂停。

`awatch EXPR'
设置一个观察点,当EXPR被读出然后被写入时程序被暂停。这个命令和'awatch'
命令合用。

`info watchpoints'
显示所设置的观察点的列表,和'info break'命令相似。
*注意:*在多线程的程序中,观察点的作用很有限,GDB只能观察在一个线程中
的表达式的值如果你确信表达式只被当前线程所存取,那么使用观察点才有效。GDB
不能注意一个非当前线程对表达式值的改变。

断点和异常
==============
在一些语言中比如象GNU C++,实现了异常处理。你可以使用GDB来检查异常发生的
原因。而且GDB还可以列出在某个点上异常处理的所有过程。

`catch EXCEPTIONS'
你可以使用这个命令来在一个被激活的异常处理句柄中设置断点。EXCEPTIONS是
一个你要抓住的异常。
你一样可以使用'info catch'命令来列出活跃的异常处理句柄。
现在GDB中对于异常处理由以下情况不能处理。
* 如果你使用一个交互的函数,当函数运行结束时,GDB将象普通情况一样把控制返
回给你。如果在调用中发生了异常,这个函数将继续运行直到遇到一个断点,一个信号
或是退出运行。
* 你不能手工产生一个异常( 即异常只能由程序运行中产生 )
* 你不能手工设置一个异常处理句柄。
有时'catch'命令不一定是调试异常处理的最好的方法。如果你需要知道异常产生的
确切位置,最好在异常处理句柄被调用以前设置一个断点,这样你可以检查栈的内容。
如果你在一个异常处理句柄上设置断点,那么你就不容易知道异常发生的位置和原因。
要仅仅只在异常处理句柄被唤醒之前设置断点,你必须了解一些语言的实现细节。
比如在GNU C++中异常被一个叫'__raise_exception'的库函数所调用。这个函数的原
型是:

/* ADDR is where the exception identifier is stored.
ID is the exception identifier. */
void __raise_exception (void **ADDR, void *ID);
要使GDB在栈展开之前抓住所有的句柄,你可以在函数'__raise_exception'上设置断点。
对于一个条件断点,由于它取决于ID的值,你可以在你程序中设置断点,当某个特
别的异常被唤醒。当有一系列异常被唤醒时,你可以使用多重条件断点来停止你的程序。
断点条件
===========
最简单的断点就是当你的程序每次执行到的时候就简单将程序挂起。你也可以为断点
设置"条件"。条件只是你所使用的编程语言的一个布尔表达式,带有条件表达式的断点
在每次执行时判断计算表达式的值,当表达式值为真时才挂起程序。
这是使用"断言"的一中形式,在这种形式中你只有在断言为真时才挂起程序。如果
在C语言中你要使断言为假时挂起程序则使用:"!表达式"。
条件表达式对观察点也同样有效,但你并不需要它,因为观察点本身就计算一个表达式?nbsp;
?nbsp;
但它也许会简单一些。比如只在一个变量名上设置观察点然后设置一个条件来测试新的赋
值。
断点条件可能有副作用(side effects)会影响程序的运行。这一点有时也是很有用的
比如来激活一个显示程序完成情况的的函数,或使用你自己的打印函数来格式化特殊的
数据结构。当在同一位置没有另一个断点设置时,结果是可预见的。(在gdb中如果在同一
个地方使用了一个断点和一个条件断点则普通断点可能先被激活。)在条件断点的应用上
有很多技巧。
断点条件可以在设置断点的同时被设置。使用'if'命令作为'break'命令的参数。断点
条件也可以在任何时候使用'condition'命令来设置。'watch'命令不能以'if'作为参数

所以使用'condition'命令是在观察点上设置条件的唯一方法。

`condition BNUM EXPRESSION'
把'EXPRESSIN'作为断点条件。断点用'BNUM'来指定。在你为BNUM号断点设置了条件
后,只有在条件为真时程序才被暂停。当你使用'condition'命令GDB马上同步的检查
'EXPRESSION'的值判断表达式中的符号在断点处是否有效,但GDB并不真正计算表达式
的值。

`condition BNUM'
删除在'BNUM'号断点处的条件。使之成为一个普通断点。
一个条件断点的特殊例子是时一个程序在执行了某句语句若干次后停止。由于这
个功能非常常用,你可以使用一个命令来直接设置它那就是'ignore count'。每个
断点都有'ignore count',缺省是零。如果'ignore count'是正的那么你的程序在
运行过断点处'count'次后被暂停。

`ignore BNUM COUNT'
设置第BNUM号断点的'ignore count'为'COUNT'。
如果要让断点在下次执行到时就暂停程序,那么把'COUNT'设为0.
当你使用'continue'命令来继续你程序的执行时,你可以直接把'ignore count'
作为'continue'的参数使用。你只要直接在'continue'命令后直接跟要"ignore"的
次数就行。
如果一个断点同时有一个ignore count和一个条件时,条件不被检查。只有当
'ignore count'为零时GDB才开始检查条件的真假。
另外你可以用'condition'命令来获得与用‘ignore count'同样效果的断点。用法
是用类似于'$foo--<=0'的参量作为'condition'命令的参数(使用一个不停减量的变量
作为条件表达式的成员)。
断点命令列表
==================
你可以为任一个断点或观察点指定一系列命令,当你程序执行到断点时,GDB自动执行
这些命令。例如:你可以打印一些表达式的值,或使能其他的断点。

`commands [BNUM]'
`... COMMAND-LIST ...'
`end'
为断点号为BNUM的断点设置一个命令列表。这些命令在'...COMMAND-LIST...'中列
出使用'end'命令来表示列表的结束。
要删除断点上设置的命令序列,你只需在'command'命令后直接跟'end'命令就可以
了。
当不指定BNUM时,GDB缺省为最近遇到的断点或是观察点设置命令列表。
使用回车来表示重复使用命令的特性在'...command list...'中不能使用。
你可以使用命令列表中的命令来再次使你的程序进入运行状态。简单的在命令列表
中使用'continue'命令,或'step'命令。
在使程序恢复执行的命令后的命令都被忽略。这是因为一旦你的程序重新运行就可
能遇到新的命令列表,那么就应该执行新的命令。防止了二义。
如果你在命令列表中使用了'silent'命令,那么你程序在断点处停止的信息将不被
显示。这对于用一个断点然后显示一些信息,接着再继续执行很有用。但'silent'命令
只有在命令列表的开头有效。
命令'echo','output'和'printf'允许你精确的控制显示信息,这些命令在"silent"
断点中很有用。
例如:这个例子演示了使用断点命令列表来打印'x'的值.

break foo if x>0
commands
silent
printf "x is %d\n",x
cont
end
断点命令列表的一个应用是在遇到一个buf之后改正数据然后继续调试的过程。
使用命令来修改含有错误值的变量,然后使用'continue'命令继续程序的运行。
使用'silent'命令屏蔽输出:

break 403
commands
silent
set x = y + 4
cont
end
断点菜单
==============
一些编程语言(比如象C++)允许一个函数名被多次使用(重载),以方便应用的使用。
当一个函数名被重载时,'break FUNCITON'命令向GDB提供的信息不够GDB了解你要设置
断点的确切位置。如果你了解到这个问题,你可以使用'break FUNCITONS(TYPES)'命令
来指定断点的确切位置。否则GDB会提供一个函数的选择的菜单供你选择。使用提示符
'>'来等待你的输入。开始的两个选择一般是'[0] cancel'和'[1] all'输入1则在所有
同名函数上加入断点。输入0则退出选择。
下例为企图在重载的函数符号'String::after'上设置断点。
(gdb) b String::after
[0] cancel
[1] all
[2] file:String.cc; line number:867
[3] file:String.cc; line number:860
[4] file:String.cc; line number:875
[5] file:String.cc; line number:853
[6] file:String.cc; line number:846
[7] file:String.cc; line number:735
> 2 4 6
Breakpoint 1 at 0xb26c: file String.cc, line 867.
Breakpoint 2 at 0xb344: file String.cc, line 875.
Breakpoint 3 at 0xafcc: file String.cc, line 846.
Multiple breakpoints were set.
Use the "delete" command to delete unwanted
breakpoints.
(gdb)


2007年1月28日星期日

Linux-IrDA quick tutorial

http://www.hpl.hp.com/personal/Jean_Tourrilhes/IrDA/IrDA.html

Linux-IrDA quick tutorial
IrNET
e-Squirt
Java-IrDA
Linux & Wireless LANs
Papers
Main page
Status & Patches
Links
Configuration
Checking
Applications
Debugging
Pitfalls

Linux-IrDA
The Linux IrDA project is an Open Source projects to develop an generic IrDA stack for Linux that has many contributors all over the world. I did contribute many bug fixes and enhancement to it since 1999 thanks to Hewlett Packard sponsoring my work. The list of patches is too long to put here ;-)
Let's face it, one of the main roadblock to the use of e-Squirt is getting the IrDA stack up and running, whatever the platform is. We had our share of horror stories on all the OSes involved.
When it come to Linux, I've been hacking the stack often enough to have a few words of advices. Here are a few instructions on how to get it working enough to be able to use e-Squirt or IrNET...
The instructions presented here should work for Linux Kernel 2.4.X and Kernel 2.6.X. And they may work equally well for later kernels and kernel 2.2.15, and maybe others. Some other documentations on the web, like the Linux-IrDA Howto are more generic and complete but not totally up to date, so beware...

Linux-IrDA current status

Willing or not, it seem that I'm the one responsible of making sure the Linux-IrDA stack work properly. Here is a quick status report...
The archive of the mailing list at SourceForge is erratic, some post disapear, which mean that I sometimes misses some e-mail. The new archive at Gmane may behave better. The archive for the old mailing list at pasta no longer exist (a shame).
It is my belief that all known issue regarding the IrDA stack are resolved (I'm not talking here about drivers and installation, which are know to be problematic). Don't prove me wrong ;-)
What's the latest version ? Things are always evolving, so I recommend to get a very recent kernel 2.6.X (like the latest one) and optionally apply some patches from this page (see below). Kernel 2.4.21 and later are also good choices. Versions prior to kernel 2.4.21 have various known bugs, therefore I don't even want to hear about those. And don't mention 2.2.X ;-)
The latest essential update of 2.4.X was in kernel 2.4.21, which fixed various race conditions and connection issues. Kernel 2.4.22 fixes some IrCOMM problems with chat, add workarounds for interoperability with buggy devices and fix a common memory leak. Note the the development of Linux-IrDA in 2.4.X is stopped, and I will no longer accept major patches for it.
The IrDA stack in 2.6.X contains a large number of fixes and improvement over what is available in 2.4.X, and this is where new development is happening, so you are welcome to try it. Usually later version are better. Some of the changes are non-trivial and require your testing, because I can't test all hardwares and configurations.
This is a short list of fixes available in 2.6.X and not in 2.4.X :
Non-modular compilation was fixed.
SMP locking was fixed, and many race condition were fixed.
Internal database (HashBin) use was made safer, especially with the IAS database.
Many SKB memory leaks and were fixed.
/proc filesystem was fixed.
SIR frame wrapping was CPU optimised.
Performance at SIR was dramatically improved.
IrTTY driver was rewritten to work with the new serial driver, along with new dongle drivers. Dongle driver have been simplified, and dongle driver removal is much safer.
VIA driver was added.
SMC driver was rewritten.
IrPORT driver was fixed.
NSC driver add support for PC8739x chipset and speed change fixes.
VLSI and IrDA-USB driver were improved.
New SigmaTel stir4200 USB driver.
This is a short list of things that need to be fixed in 2.6.X :
Test and finish fixing new SMC driver
Get rid of internal use of driver ioctls
My changes to IrTTP and the addition of the Socket scheduler in 2.4.21 are pretty big changes. I've tested those changes and measured the performance with irtty+actisys and the performance with nsc-ircc. You can see that unidirectional small packet performance has increased by a factor 3 at 4Mb/s. Also, the maximum number of Tx buffers queued in the IrDA stack decreased from 21 to 10, which improves latency. Lastly, it seems that the TTY layer is becoming a bottleneck.
The fixes for the dynamic window pf bit marking and the f-timer expiry calculation in 2.6.2 were smaller changes but fixed the remaining protocol performance bottlenecks. I've tested those changes and measured the performance with irtty+actisys. You can see a performance increase of up to 40% for large packets at SIR, and overall make performance more predictable and even (no more pathologic cases for some packet sizes).
The new irtty-sir driver in kernel 2.6.X replace the old irtty driver. It fixes some architectural issue in the interaction with the serial driver. The downside is that all dongle drivers need to be updated to the new dongle infrastructure. Martin has documented that.
irda-utils 0.9.15 is out. Don't use anything older than that. I don't want to look at bug reports using old irdadump, because they don't show some common problems, I really want irdadump 0.9.15 or later. New version of irda-utils :
irda-utils-0.9.15 : add new dongles drivers, new irdadump formating options, fix irdadump TTP and IrCOMM decoding, add LAP QoS decoding, fix irattach error detection, and add new socket samples. With this version, you can't use the incorrect form irattach irda0 -s 1 any longer, you must use irattach irda0 -s instead.
irda-utils-0.9.16 : fixes a few irdadump bugs and allow to disable irdadump parsing, fix a bug with irattach over usb-serial, adds irnetd, and improve man pages.
irda-utils-0.9.17-pre5 : add libpcap raw capture support to irdadump (read/write), add patch for IrDA support in Ethereal.
Linux-IrDA patches included in 2.4.20-pre2 :
Max-Tx sysctl : Fix a contradiction in IrDA spec regarding max frame size, necessary for FIR operation using IrComm or some socket applications.
IrNET disconnect fix : Fix IrNET to re-enable passive mode and retries (bug added in latest kernel patches).
Very important fixes : fix a race condition in IrLAP, fix "unkillable" application in IrSock, and fix transmit before ready in ircomm.
Discovery fixes : ignore passive discoveries in IrComm and IrLAN (to avoid simultaneous connections, mostly useful as server) and force log expiry on LAP disconnect.
NSC OB6100 : Enable the nsc-ircc driver to recognise the FIR chip on the HP OmniBook 6100. Contributed by Kevin Thayer.
irtty stat fixes : increment irtty tx counter at the right time. Contributed by Frank Becker.
USB disconnect fixes : fix race conditions in USB disconnect code. Allow you to unplug the dongle even with heavy transfer going on.
Discovery expiry fix : Make discovery expiry work properly for non default discovery period/timeout.
MCP2120 driver, ActiSys 200L and MA600 driver for 2.4.X : MCP2120 dongle driver contributed by Felix Tang, ActiSys 200L dongle driver contributed by Shimizu Takuja (patch from Gerhard Bertelsmann) and MA600 dongle driver contributed by Leung.
Linux-IrDA patches included in 2.4.21-pre3 :
Socket scheduler : add socket packet scheduler for fairness between socket, add LAP flow control to minimse LAP Tx buffer queue (10 => 2). Need IrTTP fixes.
IrTTP big fixes : fix 3 race conditions (start timer, give credit, flow ind), fix Rx queue flow control (could become infinite), protect Rx credit update, fix TTP flow control, implement packet scheduler, reduce Tx queue max size (11 => 8), reduce latency (by skipping timer), optimise threshold and flow parameters. Need socket scheduler. This seem to have fixed my all my IrNET Oopses and weirdness...
Fix dongle autoloading : avoid loading dongle modules with irq disabled in irtty.
Minor fixes : Always close LAP on LSAP closure, disable LAP timer on accept socket, and header fix for Alpha (by Felix Tang).
Simultaneous IrNET race : fix race condition when the two peer simultaneously create an IrNET connection to each other (thanks to Martin Diehl for reporting this race). As opposed to the IrCOMM/IrLAN discovery workaround, this fixes the race properly and cleanly.
SMC small fixes : Fix SMC driver removal code and various messages. Patch from Jeff Snyder.
Donauboe driver : new driver for Toshiba IrDA chip. Patch from Christian Gennerat & Martin Lucina. Updated version.
Four small bugs in /proc : fix four cases where interrupts would not be re-enabled on failure. Found by the Stanford checker.
Linux-IrDA patches included in 2.4.22-pre2 :
Fixes chat over IrCOMM problem : workaround a bug in the kernel (TTY layer) triggered by chat brokeness by accepting data before IrCOMM is initialised. Also remove the IrCOMM-IAS entry to accept multiple incomming connections.
Handle invalid QoS parameter : handle better case where the peer feed us invalid or oversized parameters. Also add various warning so that users knows when the IrDA peer is buggy (and doesn't start blaming Linux-IrDA). Also add a new sysctl, max_tx_window.
LMP timer race condition : fix a race condition when starting the IrLMP watchdog timer, and improve the debugging messages.
Export CRC-16 routine : export to drivers the routine doing CRC calculations. Original patch from Martin Diehl.
Fix secondary nack code : fix the secondary function to send RR and frames without the poll bit when it detect packet losses.
IrIAP SKB leak : fix an obvious SKB leak in IrIAP. This is only a localised fix, and the same fix need to be applied to all Linux-IrDA state machines. Original patch from Jan Kiszka.
USB driver cleanup : Handle properly failure of URB with new speed settings, fix endianess and various other cleanups.
caddr fix : ignore the C/R bit in the LAP connection address. Patch from Jan Kiszka.
static driver fix : fix some obvious static init bugs.
Linux-IrDA patches included in 2.4.25-pre6 :
NSC '39x support : Add support for NSC PC8739x chipset, such as found in IBM R31/A30/A31 laptops. Original patch from Jan Frey.
VIA FIR driver : driver for the IrDA module of some VIA chipsets. Written by Frank Liu (VIA).
Experimental Linux-IrDA patches for 2.4.22 and later :
Dynamic window fixes (2.4.X) : fix the dynamic window code to properly send the pf bit - patch for 2.4.22 kernel (already in 2.5.67).
Dynamic window fixes (2.4.X) : fix the dynamic window code to properly send the pf bit - patch for 2.4.23+ kernel (already in 2.5.67).
F-timer expiry fix : Fix F-timer timeout calculation - patch for 2.4.23+ kernel.
Other Linux-IrDA patches included in 2.5.13 :
Fix races waiting for events : use proper logic to wait for events instead of obsoleted kernel calls, to avoid race conditions. Most of those races were theoretical or had workaround. Original patch from Martin Diehl.
IrCOMM export rules for 2.5.X : Add proper export rules to IrCOMM modules to make it work properly in kernel 2.5.10 and later. Patch from Kai Germaschews.
Other Linux-IrDA patches included in 2.5.16 :
set_bit fixes : change all arguments of set_long to "unsigned long". Patch from Paul Mackerras.
LSAP cache fix : replace the global LSAP cache with LSAP caches private to each LAP. Fix a bug where two simultaneous connections from two devices using the same LSAPs would get mixed up. Should also improve performance in similar cases. Patch from Christoph Bartelmus.
Other Linux-IrDA patches included in 2.5.24 :
USB driver cleanup : Handle properly failure of URB with new speed settings, and various other cleanups.
Init & Headers cleanup for 2.5.X : Cleanup the header includes (should speed up dependancies & compile) and module init (should enable static compiles). new version for 2.5.22 (use "patch -l" if needed).
LSAP cache and socket receive fixes : fix one instance were we forgot to clear LSAP cache, and fix a bogus conversion to wait_event() where the socket closure would never propagate to the app waiting on a socket. This fixes bugs introduced in 2.5.13 and 2.5.16. Also reserve enough skb header space in IrSOCK so that drivers don't complain. new version for 2.5.22 (use "patch -l" if needed).
Other Linux-IrDA patches included in 2.5.39 :
HashBins fixes : fix kernel crash after removal of IAS object or IAS attribute with duplicated name, simplify LMP registration to avoid using random generator in static init, and make all hashbin uses 64 bit safe.
Unique LAP address : Make sure LAP address is sane, which mean not NULL, not BROADCAST and not already in use by another link.
NSC speed fix : try to fix the NSC driver so that it changes speed back to 9600 properly. Aggregate of both original patches.
Hashbin locking fixes : Fix locking for 2.5.32. Final patch. Apply after two first patches above.
IrCOMM/IrLAN locking fixes : Fix locking for 2.5.32. Final patch. Apply after locking hashbin fixes.
Driver locking fixes : Fix locking for 2.5.32. Final patch. Apply after locking hashbin fixes & nsc speed patch.
ALI locking fixes : Fix locking for 2.5.32. Final patch. Apply after locking hashbin fixes.
Other Linux-IrDA patches included in 2.5.42 :
VLSI driver v0.4 : major update of the VLSI driver. Patch from Martin Diehl.
Donauboe driver : new driver for Toshiba IrDA chip. Patch from Christian Gennerat & Martin Lucina. Updated version.
Export CRC-16 routine : export to drivers the routine doing CRC calculations. Original patch from Martin Diehl.
Fixes chat over IrCOMM problem : workaround a bug in the kernel (TTY layer) triggered by chat brokeness by accepting data before IrCOMM is initialised. Also remove the IrCOMM-IAS entry to accept multiple incomming connections.
Handle invalid QoS parameter : handle better case where the peer feed us invalid or oversized parameters. Also add various warning so that users knows when the IrDA peer is buggy (and doesn't start blaming Linux-IrDA). Also add a new sysctl, max_tx_window. new patch, complete fix.
LMP timer race condition : fix a race condition when starting the IrLMP watchdog timer, and improve the debugging messages.
Other Linux-IrDA patches included in 2.5.47 :
Fix packet type : migrate the IrDA stack to the multithreaded receive path of the networking stack and cleanup the packet type definition. This should fix an annoying warning on SMP.
Fix donauboe init : fix donauboe driver function names to avoid clashes with toshoboe driver.
New irtty driver (2.5.44) : new IrTTY driver to go with the new serial driver in 2.5.X. Original patch from Martin Diehl.
New irtty driver (2.5.45) : new IrTTY driver to go with the new serial driver in 2.5.X. Patch from Martin Diehl.
Linux-IrDA patches included in 2.5.61 :
IrDA driver module fixes : Use SET_MODULE_OWNER() in various IrDA drivers.
Partial rewrite of the SIR wrapper : optimise the SIR wrapper (stuff/unstuff bytes) for better performance. Will only decrease the CPU overhead, not the network overhead. Improved version. Also add the optional ZeroCopy-Rx mechanism for drivers that support it (like this experimental patch for sir-dev).
Fix secondary nack code : fix the secondary function to send RR and frames without the poll bit when it detect packet losses.
IrCOMM status line fix : fix status line initialisation in IrCOMM. Patch from Jan Kiszka.
IrIAP namespace cleanup : reduce namespace pollution in IrIAP. Patch from Arnd Bergmann.
IrQoS namespace cleanup : reduce namespace pollution in IrDA QoS. Patch from Arnd Bergmann.
Linux-IrDA patches included in 2.5.67 :
Discovery fixes and cleanup : fix the last locking problems in discovery and expiry, simplify, cleanup and optimise the discovery/expiry code (i.e. smaller and faster).
Dynamic window fixes : fix the dynamic window code to properly send the pf bit. Up to 40% improvement from large packets at SIR (i.e. most bulk transfer at SIR). Performance unchanged for FIR or small packet. More complete performance analysis later on.
IrDA-USB cleanups : cleanup the Rx path, the USB registration and others in the IrDA-USB driver.
Sir-dev ZeroCopy : Enable ZeroCopy Rx in irtty-sir (provided by the new SIR wrapper).
Minor timer optimisation : make IrDA timers use mod_timer (safer & faster).
IrNET update : Fix module refcounting and add hints to discovery.
Linux-IrDA patches included in 2.5.70 :
skb leak audit : Fix many real and potential skb (packet buffer) memory leaks in the IrDA stack. This patch is so good that over time the number of skb used decrease ;-) Thanks to Jan Kiszka for pointing out the issue.
IrNET context fix : fix IrNET locking to be compatible with PPP, fix a couple of crash in 2.5.67+.
caddr fix : ignore the C/R bit in the LAP connection address. Patch from Jan Kiszka.
sir_kthread comment : add comment to explain task state, new module stuff in irtty-sir.
irport fixes #3 : various fixes and optimisation for irport.
New SMSC driver #6 : new SMSC driver, this one works, even in FIR (but still need testing). Original patch from Daniele Peri. Improved version, for 2.5.69
trans_start fixes : minor fix in various drivers.
TTY API fix : Add an extra call to the TTY API so that irtty-sir can work again. Russell eventually implemented something similar.
Linux-IrDA patches included in 2.6.0-test1 :
IrDA-USB endian fixes : Trivial fix for irda-usb to make it work on big endian boxes (such as PPC). Original patch from Jacek Jakubowski. Add new USB device ID.
NSC '39x support : Add preliminary support for NSC PC8739x chipset, such as found in IBM R31/A30/A31 laptops. This patch needs more work. Original patch from Jan Frey.
Header cleanup : cleanup the header.
IrNET cast fix : remove pointer casting in IrNET debug code. Patch suggested by David S. Miller.
More skb leaks : fix two additional potential skb leaks in IrTTP. Found by the Stanford checker.
setup_dma fix : mark all drivers that need setup_dma() as requiring CONFIG_ISA. Mark new dongle driver as needing sir-dev.
Verify structs : verify the size of packed structures. Patch suggested by Russell King.
IrCOMM devfs fix : make sure that the devfs name for IrCOMM devices are not bogus. Original patch suggested by Martin Diehl.
sir-dev cleanup : various cleanups in irtty-sir and sir-dev drivers. Patch from Martin Diehl.
refrigerator support : support software suspend in irtty-sir. Patch from Neil Brown.
Linux-IrDA patches included in 2.6.0-test3 :
Donauboe probe : disable the probe in Donauboe driver by default and minor cleanups. Patch from Christian Gennerat.
irda-usb probe : minor fix to the probe failure path of irda-usb. Merge of patches from Oliver Neukum and Daniele Bellucci.
IrLAP retry count : add interoperability workaround for a bug in 2.4.X IrDA stacks : 2.4.X secondary forget to set pf bit when reaching window byte capacity without sending the max number of packets (ex: 115 kb/s, max packet size, window=7), and we would eventually close the connection. This bug was fixed in 2.5.67 (Dynamic window fixes).
VIA FIR driver : driver for the IrDA module of some VIA chipsets. Improved version. Written by Frank Liu (VIA).
tekram-sir driver fix : update tekram-sir to latest sir-dev changes. Patch from Martin Diehl.
vlsi driver update : update VLSI driver to version 0.5. Patch from Martin Diehl.
Linux-IrDA patches included in 2.6.0-test5 :
IrCOMM module fix : fix some comments.
NSC '39x fixes : Make support for NSC PC8739x chipset really work. Patch from Jan Frey.
irtty cleanup : Finish removing irtty driver from the kernel.
LAP close race fix : Fix a race condition when closing the LAP, prevent the stack to open new LSAPs while we are killing them.
Connect watchdog fix : Fix problem with the connect watchdog, where we would dup an invalid TSAP. May happen is a IrDA server is suspended.
Init cleanups : Fix various minor problems whith initialisation. Based on a patch from Guennadi Liakhovetski.
Module aliases : Add module aliases to dongle drivers. Patch from Rusty Russell.
Linux-IrDA patches included in 2.6.0-test10 :
IrCOMM might_sleep Oops : Don't do copy_from_user() under spinlock in ircomm_tty_write.
IrNET race Oops : Fix two rare race condition in IrNET, ppp unregister and status event.
af_irda skb leak : Fix a potential skb leak in error code of af-irda.
irlmp_open leak : Fix a potential leak in debug code of IrLMP.
Linux-IrDA patches included in 2.6.2-rc1 :
IrCOMM detach Opps : fix locking problems in IrCOMM.
F-timer expiry fix : F-timer is calculated from end of window, however we set it at start of window. Add the window transmision time to the timer setting. This increase performance for bidirectional large packets at SIR by 10%.
Sir-Dev locking : Fix sir-dev locking problems and make it compatible with irport. Patch from Martin Diehl.
Sir-Dev raw mode : Fix sir-dev raw mode support (necessary for some SIR dongles - ma600 and tekram). Patch from Martin Diehl.
IrCOMM module alias : add module alias for IrCOMM pseudo serial device. Patch from Martin Diehl.
IAS max string : fix a stupid compiler warning.
SMSC release region : fix a stupid cut'n'paste error.
Socket API cleanup : Convert IrDA sockets to unsigned length for send/recv msg. Patch from Stephen Hemminger.
TTY API fixes : Update IrCOMM to the new TTY API for tiocmget/tiocmset. Patch from Russell King.
More Socket API cleanup : Properly check return from memcpy_fromiovec and exit. Patch from Chris Wright.
Linux-IrDA patches included in 2.6.2-rc2 :
sir-dev update : change dongle api such that raw r/w and modem line helpers are directly called, not virtual callbacks. Patch from Martin Diehl.
actisys-sir update : convert to de-virtualized sirdev helpers. Patch from Martin Diehl.
esi-sir update : convert to de-virtualized sirdev helpers. Patch from Martin Diehl.
tekram-sir update : convert to de-virtualized sirdev helpers. Cleanup the tekram-sir dongle driver and make speed change faster. Patch from Martin Diehl.
litelink-sir driver : convert Parallax Litelink driver to the new irtty dongle API. Patch from Eugene Crosser. Convert to de-virtualized sirdev helpers. Patch from Martin Diehl.
act200l-sir driver : converted for new api from old driver. Patch from Martin Diehl.
act200l-sir driver : converted for new api from old driver. Patch from Martin Diehl.
girbil-sir driver : converted for new api from old driver. Patch from Martin Diehl.
ma600-sir driver : converted for new api from old driver. Patch from Martin Diehl.
mcp2120 driver : converted for new api from old driver. Patch from Martin Diehl.
old_belkin-sir driver : converted for new api from old driver. Patch from Martin Diehl.
Makefile update : include build information for new style dongle. Patch from Martin Diehl.
Linux-IrDA patches included in 2.6.3 :
Ultra sendto support : Don't require bind on ultra sockets, and prevent use of unbound sockets if no address given. Original patch from Stephen Hemminger.
Notifier cleanup : Remove unused IrDA device notify handler. Patch from Stephen Hemminger.
IrLAP disconnect race : Cancel IrLAP disconnect is a new connection request arrived before we had time to disconnect. Bug found by Christoph Bartelmus.
Shared IRQ for nsc-ircc : Return proper IRQ status in IRQ handler of nsc-ircc driver. Patch from Stephen Hemminger.
Shared IRQ for ali-ircc : Return proper IRQ status in IRQ handler of ali-ircc driver. Patch from Stephen Hemminger.
Shared IRQ for smsc-ircc2 : Return proper IRQ status in IRQ handler of smsc-ircc2 driver. Patch from Stephen Hemminger.
Shared IRQ for via-ircc : Return proper IRQ status in IRQ handler of via-ircc driver. Patch from Stephen Hemminger.
Shared IRQ for w83977af_ir : Return proper IRQ status in IRQ handler of w83977af_ir driver. Patch from Stephen Hemminger.
Linux-IrDA patches included in 2.6.4 :
Header cleanup : Remove obsolete smc-ircc.h header file (note : do the same with toshoboe.h). Patch from Stephen Hemminger.
Static for the w83977af_ir driver : Add the "static" qualifier to various private functions. Patch from Stephen Hemminger.
Static for the irtty-sir driver : Add the "static" qualifier to various private functions. Patch from Stephen Hemminger.
Static for the irport driver : Add the "static" qualifier to various private functions. Patch from Stephen Hemminger.
Static for the via_ircc driver : Add the "static" qualifier to various private functions. Patch from Stephen Hemminger.
Linux-IrDA patches included in 2.6.6 :
VLSI /proc update : Convert VLSI driver to use seq_file functions. Patch from Stephen Hemminger.
Donauboe crc fix : Make donauboe driver use the standard CRC table instead of its own. Patch from Stephen Hemminger.
RD:RSP fix : Fix handling of RD:RSP frames to properly retry them. Patch from Martin Diehl.
IrLAN print_ret optimisation : Move print_ret to minimise namespace polution and allow inlining. Patch from Stephen Hemminger.
IrLAN handle_filter rename : Rename handle_filter to minimise namespace polution. Patch from Stephen Hemminger.
IrLAN cleanup : Cleanup IrLAN module. Patch from Stephen Hemminger.
IrLAN race condition : Remove a potential race condition in IrLAN. Patch from Stephen Hemminger.
IrLAN flow control : Fix IrLAN flow control and other cleanup. Original patch from Stephen Hemminger.
Linux-IrDA patches included in 2.6.10-rc1 :
Fix LSAP allocation : Fix locking in error path in IrLMP, found by the Stanford checker. Don't reuse unconnected LSAPs, they belong to server sockets. Make sure the LSAP we are picking has just not been grabed. And wrap around the LSAP space properly.
NSC dongle-id check : Make sure the nsc-ircc don't Oops on invalid dongle-id. Original patch from Maik Broemme.
IrNET module alias : Add module alias for IrNET char dev.
IAS delete clarification : Clarify and make optional the destruction of an IAS object when the last attribute is removed.
Adaptive passive discovery : Adapt to the rate of the peer discovery and add some extra safety margin. Allow to interoperate properly with device performing slow discovery. Bug found by Nokia.
IrCOMM IAS restore : Restore properly the IAS object when IrCOMM gets disconnected. Allow "pppd passive persist" to work properly. Bug found by Jan Kiszka.
VIA speed change fixes : various changes to make the VIA driver really work on speed changes, and various other cleanups. Patch untested (port from 2.4.X). Original patch from Sancho Dauskard.
Fix module info : Fix the module parameter info for irda_debug. Patch from Stephen Hemminger.
stir4200 - no USB reset : Get rid of usb-reset on speed change because the Sigmatel 4200 doesn't accept the new address setting. Patch from Stephen Hemminger.
stir4200 - suspend fix : The suspend/resume code only needs to be compiled in if power management is enabled. Patch from Stephen Hemminger.
stir4200 - use netdev_priv : Use netdev_priv and various message cleanups. Patch from Stephen Hemminger.
Linux-IrDA patches included in 2.6.10 :
Fix via_ircc pci init code : Try to make the via-ircc driver usable again and comment on all the problem in the PCI init code. Suggested by Arkadiusz Miskiewicz.
stir4200 - use kill_urb() : Use usb_kill_urb() instead of usb_unlink_urb. Patch from Stephen Hemminger.
irda-usb - use kill_urb() : Use usb_kill_urb() instead of usb_unlink_urb plus other cleanups. Patch from Stephen Hemminger.
Linux-IrDA patches included in 2.6.12-rc1 :
IrNET poll fix : fix the poll method of IrNET so that it properly blocks if the initial discovery log is empty.
irda-usb sysfs fix : add minimal sysfs support to the irda-usb driver. Patch from John K. Luebs.
stir4200 turnaround fix : fix invalid turnaround calculations in the stir4200 driver. Patch from John K. Luebs.
VIA devexit fix : mark properly the exist code in the VIA driver. Patch from Randy Dunlap.
LSAP socket connect : allow IrDA socket to connect on arbitrary LSAPs. Original patch from Iavor Fetvadjie.
NSC PC8738x support : Add support for the NSC PC8738x chipset as found in the IBM X40. Patch from Steffen Pingel.
IrCOMM write cleanup : cleanup some obsolete construct.
Linux-IrDA patches pending for 2.6.12 :
ASSERT fixes : fix the DEBUG and ASSERT macro to be safer, rename ASSERT, MESSAGE and WARNING with an IRDA_ prefix to minimise namespace pollution. Huge patch.
Experimental Linux-IrDA patches for 2.6.X :
SmSC PnP support : Add PnP support to the SmSC driver. Patch from Ville Syrjala. Unfortunately, does not work properly with all hardware...
NSC PnP test : Add PnP debugging to the NSC driver. This seems to make my hardware fail.
ep7211_ir driver locking fix : fix locking in the ep7211_ir driver. Patch from Chris Wilson.
sa1100_ir driver locking fix : fix locking in the sa1100_ir driver. Patch from Chris Wilson.
donauboe comments cleanup : Patch from Pavel Machek.
Fix LAP race condition : improve previous fix for IrLAP race condition to protect in more cases. This patch is not totally safe and need a rewrite.

More information and links
Our work on IrDA :
My IrNET implementation for Linux.
My e-Squirt implementation for Linux.
Our Java-IrDA API for Linux (IrDA sockets in Java).
CoolTown official web site.
More IrDA links :
The Linux-IrDA web pages, to download irda-utils and for the very helpful mailing list...
The Linux-IrDA SourceForge project, which host the above web page and mailing lists.
The Linux-IrDA mailing list at SourceForge for discussions related to the Linux-IrDA stack.
The Linux-IrDA mailing list at Gmane should be the same with a different UI.
The old Linux-IrDA mailing list for discussions related to the Linux-IrDA stack.
The old IrDA mailing list for generic questions regarding IrDA.
Linux kernel source archive (the latest IrDA stack is in the 2.4.X kernels).
The OpenObex web page, where you will find the latest version of the Obex code (and the OpenObex SourceForge project).
The Old Obex homepage, with the mailing list archive...
The Linux-IrDA Howto (note : almost up to date...)
The IrDA organisation, with on-line specs Random Linux-IrDA links that should be on the Linux-IrDA web page :
The OpenObex web page, where you will find the latest version of the Obex code. Obex is the protocol that allow to exchange objects (vCard, vCal) with your Palm or cellular phone over IrDA or BlueTooth.
ObexFTP, an implementation of FTP over OpenObex, with a nice graphical interface. Also include a working implementation of OpenObex over Serial cable. Can be used to browse some cellular phones.
ObexTool, an graphical front end for ObexFTP, including plug-in capability.
MultiSync allow you to synchrnonise data over OBEX with your cell phone.
Gnokii, a package to communicate with your cellular phone over IrDA.
GIrDA, an IrDA monitor that display devices in range and support OpenObex.
Felix Tang has a page on how to build a cheap SIR dongle.
Daniele Peri has some utility to help configure the IrDA port on Toshiba 1800 laptops and is the maintainer of the new SMC driver.
Rob Miller has some utility to help configure the IrDA port on Toshiba 2400, 4600 and 5100 laptops.
James McKenzie and Christian Gennerat have done a rewrite of the toshoboe driver called donauboe.
Paul Stewart is the original author of the stir4200 USB Dongle FIR driver, and is maintaining the version for kernel 2.4.X.
Stephen Hemminger has an improved version of the stir4200 USB Dongle FIR driver for 2.6.X.
Martin Diehl has written a document on the new dongle driver interface he has created in kernel 2.5.X.
Martin Diehl has written some notes about the MA 620 USB dongle.
Ben Moore has created a Window Maker dockapp for managing the Hewlett-Packard CapShare document scanner (boy, that does bring some memories !).
Jan Kiszka has created IrCOMM2k to provide improved IrCOMM support in W2k and Wxp. IrCOMM2k version 2.0 and later is based on a port of the Linux-IrDA stack to the WinNT architecture, version 2.0alphaX was based on the stack in Kernel 2.4.20 (with known bugs), version 2.0betaX is based on my latest version (2.5.67 + updates). Jan has provided me many useful bugfixes and suggestions as the result of this work, thanks...
Cambridge University has some instruction on how to make GPRS connections using Linux-IrDA (of course, assuming you have a GPRS phone).
Tor-Ake Fransson have some instructions on how to use a Linux iPaq with a IrDA enabled cell phone.
Arthur Tyde and Bryan Abshier have some instructions on how to connect a WinCE device to Linux.
Andy has instructions on how to do Telnet from a Palm to Linux over IrDA.
David Desrosiers have some instructions on how to connect a Palm to Linux over IrDA via PPP over IrCOMM.
Rev has instructions on how to exchange Obex objects with an Ericsson phone.
Ian Barry explain how to set up network connections between various handhelds and Linux.
Alan J. McFarlane maintains a short FAQ on Windows IrDA support and has instructions on Win32 IrDA programming (which is very similar to Linux-IrDA programming).
Howard has various instructions and link on Windows IrDA support. More stuff on my web site :
My Linux Wireless LAN Howto
How to setup BlueTooth on Linux

Tutorial : How to use Linux-IrDA
The remaining of this document will give you some tips on how to configure Linux-IrDA.
A lot of IrDA novices mix up the low level and high level of the IrDA stack. A few words...
Low level of Linux-IrDA : this is the part of the IrDA stack dealing with the IrDA hardware on your computer and managing it. The key words are IrDA driver, IrDA ports (either SIR or FIR), IrDA dongles and TTY/serial port.
High level of Linux-IrDA : this is the part of the IrDA stack dealing with communicating with the other IrDA device and exchanging the data (the protocol). The key words are protocol, IrCOMM, IrLPT, OBEX, IrLAN and IrNET. The low level and high level are totally independant of each other, however each need to be configured properly for what you want to do.
The procedure to get IrDA working looks usually like this :
Configure everything
Set up the low level to recognise your IrDA hardware
Verify that the low level works
Set up your application on top of the proper high level protocol
I also offer various debugging tips at the end of this document.

Common configuration
Most Linux kernels don't come with IrDA enabled, and most distributions come with very approximate config scripts. I don't trust those and I always do things by myself.
Get kernel of your choice, unpack the source in /usr/src
Compile yourself a fresh kernel and make it boot properly.
Configure the IrDA stack as a module, enable all options (as module if possible) and the driver/protocols you need (as modules).
Configure serial port as a module. Static is ok as well, except for the NSC or FIR setup.
Recompile the modules and install them : > make modules ; make modules_install
Install irda-utils-0.9.15 or later
Add the following stuff in /etc/modules.conf : # IrDA stuff...
alias tty-ldisc-11 irtty
alias char-major-161 ircomm-tty # if you want IrCOMM support
# These values are hard-coded in irattach (not instance order)
alias irda-dongle-0 tekram # Tekram IrMate IR-210B
alias irda-dongle-1 esi # ESI JetEye
alias irda-dongle-2 actisys # ACTiSYS IR-220L
alias irda-dongle-3 actisys # ACTiSYS IR-220L+
alias irda-dongle-4 girbil # Greenwich GIrBIL
alias irda-dongle-5 litelink # Parallax LiteLink/ESI JetEye
alias irda-dongle-6 airport # Adaptec Airport 1000 and 2000
alias irda-dongle-7 old_belkin # Belkin (old) SmartBeam dongle
alias irda-dongle-8 ep7211_ir # Cirrus Logic EP7211 Processor (ARM)
alias irda-dongle-9 mcp2120 # MCP2120 (Microchip) based
alias irda-dongle-10 act200l # ACTiSYS Ir-200L
alias irda-dongle-11 ma600 # Mobile Action ma600
# IrNET module...
alias char-major-10-187 irnet # Official allocation of IrNET
Create the IrDA devices : > mknod /dev/ircomm0 c 161 0
> mknod /dev/ircomm1 c 161 1
> mknod /dev/irlpt0 c 161 16
> mknod /dev/irlpt1 c 161 17
> mknod /dev/irnet c 10 187
> chmod 666 /dev/ir*
Reboot Now, it's time to check which hardware you want to make run...

Kernel 2.6.X differences
Kernel 2.6.X drivers are slightly different from kernel 2.4.X described above. The main driver differences are listed below. This list is known to not be final.
Driver irtty-sir replaces irtty for SIR mode
Dongles drivers for irtty-sir have the -sir prefix added to their name (to distinguish them from old style dongle drivers).
Driver donauboe replaces toshoboe
Driver smsc-ircc2 may replace smc-ircc
Module configuration is also different, you need to add the following in /etc/modules.conf : alias tty-ldisc-11 irtty-sir
alias char-major-161 ircomm-tty
alias irda-dongle-0 tekram-sir
alias irda-dongle-1 esi-sir
alias irda-dongle-2 actisys-sir
alias irda-dongle-3 actisys-sir
alias char-major-10-187 irnet

Low level drivers
This really depend on the IrDA hardware that you have. I describe a few of the options below. The two safest options are Laptop in SIR mode and Serial dongle.

Serial dongle (using irtty driver)
For all serial dongles, you need an IrDA driver, which is irtty, and a dongle driver. The dongle I use if the Actisys 220L+, and the dongle driver is called actisys (see list above). The setup for other dongles should be very similar. I'm also using the first serial port in this example (ttyS0), you may need to adapt to your case.
Attach dongle to the serial port, and check which serial port it is.
Check if the serial config is ok : > setserial /dev/ttyS0
/dev/ttyS0, UART: 16550A, Port: 0x03f8, IRQ: 4
If it say UART: unknown, your serial configuration is invalid.
Start the IrDA stack : > irattach /dev/ttyS0 -d actisys -s
If you want to unload/stop the IrDA stack just kill all the IrDA applications and do : > killall irattach
> rmmod irtty actisys
> rmmod irda
Note : all the modern ESI dongles work better with the litelink driver.

Laptop port in SIR mode (using irtty driver)
SIR (Serial Infrared) is not fast but almost always work and is easy to set-up, so it's a safe bet. It will work only if the BIOS is set to SIR mode, so don't bother otherwise. Some BIOS don't offer the setting and try to be clever and autodetect the proper setting, but it doesn't always works.
Note that some laptops (Toshiba) need special magic for their IrDA port to be enabled, see link section above.
The irtty driver will use the standard Linux serial driver.
Go in the BIOS of the laptop, enable the Infrared port, and set it to SIR mode.
While in the BIOS, note the IO address and IRQ assigned to it.
Using setserial or in the boot log messages, find the ttyS* that correspond to this port. Let's assume /dev/ttyS1 (as in my laptop).
Check if the serial config is ok : > setserial /dev/ttyS1
/dev/ttyS1, UART: 16550A, Port: 0x02f8, IRQ: 3
If it say UART: unknown, your serial configuration is invalid. If the port and IRQ are different, it's usually OK.
Start the IrDA stack : > irattach /dev/ttyS1 -s
Refer to previous example for more Now, you just need to figure out on which side of the laptop if the IrDA port...
HP Omnibook 6000 in FIR modeIt seems that each laptop has its quirk when it come to FIR mode. I've managed to get my OB6000 to work (great laptop BTW). Other laptops will be different (different driver, different settings).
Go in the BIOS of the laptop, enable the Infrared port, and set it to FIR mode.
Add the following stuff in /etc/modules.conf : # NSC FIR chipset in the OB6000
alias irda0 nsc-ircc
options nsc-ircc dongle_id=0x08
Remove the serial driver that gets in the way : > setserial /dev/ttyS1 uart none
> rmmod serial
Start the IrDA stack : > irattach irda0 -s
The NSC driver gives me some pretty good performance.
Other laptops in FIR modeThere is different FIR hardwares included in the various laptops. Linux-IrDA support some of them (not all) in various degrees (from good to bad). Moreover, it seems that each laptop has its quirk, so it's difficult to list everything here.
For this reason, I recommend to make it work first in SIR mode. After that, you can experiment, check the Howto and query the mailing list...
THe setup for most FIR drivers will follow the same pattern as the Omnibook 6000 example above. You will need to find the proper value of the modules parameters, set the BIOS properly, take care of conflicting hardware (serial, Pcmcia cards and other interrupt conflicts) and start the stack with irattach.
As a rule of thumb, the NSC driver seems to be the most functional (if you set the proper dongle_id, which most likely 0x9, but sometimes 0x8), and the old SMC driver the most problematic.

USB FIR dongles
This driver is included in recent kernel. It's not as efficient as other FIR hardware, but at least is supported and is relatively easy to get working. Also, all the current products are based on the same hardware, and we know most of its bugs.
The latest version of the driver has been tested with usb-uhci and usb-ohci.
Start the USB stack. If you have an UHCI hardware, it looks like : > modprobe usb-uhci
Load USB driver and start the IrDA stack : > modprobe irda-usb
> irattach irda0 -s
If you have already some other IrDA hardware configured on the PC, the driver won't load as irda0, so check the message log with dmesg. Also, the driver can manage up to 4 IrDA-USB dongles per PC (that can be increased in the source).
Recently a new type of USB dongle from SigmaTel has appeared on the market which is not compliant with the IrDA-USB specification, and therefore doesn't work with this driver. On the other hand, SigmaTel has made available the full technical specification, so writing a driver for it is possible. There is a alpha driver for 2.6.X in my patch list.
The MA 620 USB dongle is a SIR USB dongle, there is some howto for it written by Martin Diehl.
Important note : in recent kernels, the USB team has added a driver called ir-usb. Not only this driver is not compatible with the IrDA stack (the IrDA driver is called irda-usb), but this driver will load automatically before irda-usb, therefore preventing you to use it. Solution : get rid of ir-usb. It may also be possible to blacklist ir-usb in /etc/hotplug/blacklist. I would like to thank warmly the USB team for the confusion they created. For complains, please direct it to them.
SIR with irportThe standard SIR driver is irtty, which uses the standard serial driver and tty layer. This is the easiest and safest way to get IrDA working.
However, the tty layer adds some overhead and doesn't understand the IrDA protocol, which make it unsuitable in some case (dongle without echo cancelation) and less performant in others (small packets). That is why there is a second driver, irport, which allow the IrDA stack direct access to the serial port.
Unfortunately, the procedure to use irport is more complicated and less well tested. Actually, I personally never managed to make irport work reliably on any of my systems.
Remove the serial driver that gets in the way : > setserial /dev/ttyS0 uart none
> rmmod serial
Load the irport driver and attach the dongle driver. > modprobe irport io=0x3f8 irq=4
> dongle_attach irda0 -d actisys+
Start the IrDA stack : > irattach irda0 -s

Checking that it work
The first test is to check if the discovery is happening properly. If the IrDA driver is properly configured, the Linux-IrDA will discover other IrDA devices in range. If the discover doesn't work, this indicate that the low level is not configured properly (and you don't need to go any further).
You can check if there is any device listed in the discovery log with : > cat /proc/net/irda/discovery
IrLMP: Discovery log:
nickname: Jean Tourrilhes, hint: 0x8220, saddr: 0x913b1bbc, daddr: 0x5619b45e
You can also check various other files in /proc, or use irdadump, check the debugging section.
Then, you might want to use a simple aplication, such as e-Squirt to verify that everything works fine. Or you can skip directly to the next section.
The big advantage of e-Squirt is that it is a really simple protocol, doesn't stress the IrDA stack too much and we have implementation for various platforms, so that you can test your setup with almost anything on the other side (Linux, Win32, WinCE or Palm).
Compile the Linux e-Squirt library and the test programs on all Linux computers, and go in the tests directory. On other platforms, load and start the relevant the e-Squirt application.
If you want to use Linux as a receiver, just do : ./squirt
To use Linux as a sender, you can do : ./ultra_beacon http://cooltown.hp.com/
./socket_squirt http://cooltown.hp.com/
With that, you should be able to exchange back and forth URLs and check that your IrDA stack works. If not, continue to read below.
On caveat : Most implementations have two exclusive receiving modes, IrDA and Ultra, and they switch between these (either as a preference setting, or automatically triggerd by discovery packets). Linux is an exception and can listen to both at the same time. This means that unless you do a Linux-Linux test, only one of the two sender tests listed above will work properly.

Apps and protocols on top of the IrDA stack
If you want to run e-Squirt applications, you are done, and you just need to run the application themselves, they should work.
Other applications and protocols you may want to run :
TCP/IP over IrNET
Terminal over IrCOMM
TCP/IP over IrCOMM
TCP/IP over IrLAN
Connect to a mobile phones
Obex to exchange files/objects with PDAs, Phones and other Obex devices Note that I don't use IrCOMM and IrLAN, so I can't help much with that...

Terminal over IrComm
This is a simple test to check that IrComm is working between two PCs. After that, you can try more complex applications such as PPP. The original instructions were sent on the mailing list.
Server side : Start the terminal server > getty ircomm0 DT19200 vt100 # Red-Hat syntax
or > getty -L ircomm0 19200 vt100 # Debian syntax
At this point, your text terminal should get reset and you come back to a login prompt. That's normal. I don't know what happen in X.
Client side with kermit : Start the terminal emulator > kermit
> > set line /dev/ircomm0
> > set speed 19200
> > connect
> > > stty sane # Get backspace to work ok
The prompt shouls appear after connect. Also, you need to ignore the following message : "Warning: no access to tty (Inappropriate ioctl for device). Thus, no job control enabled", and "Can't open terminal /dev/tty"
Client side with minicom : Minicom is a bit more problematic, and I'm still fighting with it. I still don't understand how to connect. I managed to make it work like this :
start minicom
Configure (^A O)
sub-menu serial
set to /dev/ircomm0
set speed to 19200
exit
sub-menu "save as dft"
exit
Exit (^A X)
restart minicom

TCP/IP over IrCOMM between two PCs
This simple example of PPP over IrCOMM is somewhat similar to TCP/IP over IrNET, and is not much use, except to verify the IrCOMM works properly. Real life PPP over IrCOMM to a mobile phone will involve a much more complex configuration (to configure the modem and dial).
Server side : Start the ppp deamon > pppd /dev/ircomm0 9600 local noauth passive
As you can see, the visible difference with IrNET is that we use /dev/ircomm0 instead of /dev/irnet. Also, IrCOMM doesn't have the advanced features of IrNET to specify IrDA peer.
Client side : Start the ppp deamon Start the terminal emulator > pppd /dev/ircomm0 9600 local noauth
At this point, the IrDA stack should connect (check with irdadump) and PPP should create a new network device (usually ppp0) and configure IP and route. You should be able to ping and connect to the other side using its IP address.

TCP/IP over IrLAN
I don't use IrLAN any longer, because I'm only using IrNET. I just did a refresh on the original instructions that I sent on the mailing list (removing mentions of irmanager which no longer exist).
IrLAN as an access option, which can be 1 (direct mode), 2 (peer to peer) and 3 (hosted). Basically, you would use 2 if you connect to another PC, 1 if you connect to a transparent access point, and 3 if you are the access point (Dag, correct me if I'm wrong). The HP Netbeamer is an access point, but it accept connections only if the PC is in peer mode. Go figure...
PC -> HP NetBeamer : Here is how to hook to the NetBeamer... After aligning the IrDA port or after starting irattach, the light of the NetBeamer should flash. If it doesn't, you may want to play with the slot_timeout value. > insmod irlan access=2
> ifconfig irlan0 10.0.0.1 netmask 255.255.255.0 broadcast 10.0.0.255
At this point, the light goes solid green. Link is on, you can ping and everybody is happy. You may want to add a gateway with "route add default gw ...".
PC -> PC : Not everybody has a NetBeamer, so here is a step by step on how to create a link between two PCs.
On the first PC : > insmod irlan access=2
> ifconfig irlan0 10.0.0.1 netmask 255.255.255.0 broadcast 10.0.0.255
On the second PC : > insmod irlan access=2
> ifconfig irlan0 10.0.0.2 netmask 255.255.255.0 broadcast 10.0.0.255
After that, you should be able to ping and telnet...
Automated ifconfig : By default, /etc/irda/network.opts is not used. In the previous example, we ifconfig-ure irlan by hand. If you have a Red-Hat/Mandrake distribution, irmanager can do the job automatically at the condition that you create a file /etc/sysconfig/network-scripts/ifcfg-irlan0 and set the right values in there... There might be more needed, but I'm not totally expert on this...
For other distribution (like Debian), you need to replace the file /etc/irda/network with possibly something from a Pcmcia package, and with some editing you might get it to load network.opts...
You might also want to add in your /etc/conf.modules a "option irlan access=2". So, if you use modprobe instead of insmod, you won't have to specify access=2 on the command line.

IrDA and mobile phones or PDAs
I don't have any mobile phone, and I don't use IrCOMM, so I can't help...
There is many people using IrDA to connect either to their mobile phone or PDA, and lot's of them have put instructions in their web pages. You may use OBEX to transfer simple objects, or PPP over IrCOMM to establish connections, depending on the application and the device. The people doing Gnokii are also quite knowledgeable in this area, so you may ask advice on their mailing list, but please report IrDA bugs in the IrDA mailing lists.
One of the most common gotcha is that applications need to be configured to use the proper IrCOMM virtual port (which most often is /dev/ircomm0).
If I can't reproduce your problem, I can't debug it, so I can't fix it. If I can't see anything obvious in the irdadump log, I won't bother. You may also want to try to reproduce the problem between two Linux boxes (because I may be able to reproduce that).

Checking Linux-IrDA state and debugging
Of course, I'm sure that you won't get things smooth the first time. Actually, I'm pretty sure you will struggle a little bit.
If you get the Obex stuff out of the loop (so, using Ultra or Socket, as described above), the e-Squirt stuff is so simple that if anything doesn't work you can bet that it's the IrDA stack.
The first trick is to check is the modules are loaded : > cat /proc/modules
actisys 1652 1 (autoclean)
irtty 7524 2 (autoclean)
irda 151905 11 (autoclean) [actisys irtty]
This is what a serial dongle setup would look like. If the modules don't show up, check you modules configuration and check the error messages in the log (with dmesg).
Then, check the bunch of files in /proc/net/irda : > cat /proc/net/irda/discovery
IrLMP: Discovery log:
nickname: Jean Tourrilhes, hint: 0x8220, saddr: 0x913b1bbc, daddr: 0x5619b45e
> cat /proc/net/irda/irlap
irlap0 state: LAP_NDM
device name: irda0, hardware name: ttyS0
caddr: 0x52, saddr: 0x913b1bbc, daddr: 0x5619b45e
win size: 1, win: 1, line capacity: 4800, bytes left: 4800
tx queue len: 0 win queue len: 0 rbusy: FALSE mbusy: FALSE
retrans: 0 vs: 2 vr: 2 va: 0
qos bps maxtt dsize winsize addbofs mintt ldisc comp
tx 9600 0 64 1 12 0 0
rx 9600 0 64 1 12 0 0
> cat /proc/net/irda/irias
LM-IAS Objects:
name: hp:esquirt, id=76371435
- Attribute name: "IrDA:TinyTP:LsapSel", value[IAS_INTEGER]: 96
name: OBEX:ESquirt, id=76371435
- Attribute name: "IrDA:TinyTP:LsapSel", value[IAS_INTEGER]: 95
name: Device, id=0
- Attribute name: "IrLMPSupport", value[IAS_OCT_SEQ]: octet sequence
- Attribute name: "DeviceName", value[IAS_STRING]: "lagaffe"
name: hp:beacon, id=76371435
- Attribute name: "IrDA:TinyTP:LsapSel", value[IAS_INTEGER]: 97
There, you can see that the IrDA stack has discovered my Palm V, that my IrDA port is ttyS0, that I'm not connected, and you can also see that I have an e-Squirt application running that has opened a bunch of server sockets (of course, if you haven't started e-Squirt, the IAS won't contains all those sockets).
The ultimate debugging tool is irdadump (and remember that I require you to use version 0.9.15 or later). You should run irdadump while attempting to connect and check what's happening. A normal irdadump log with a IrDA device in front of the port (not connected) should show something like this : > irdadump
22:04:48.000713 xid:cmd 6f1e8511 > ffffffff S=6 s=0 (14)
22:04:48.090705 xid:cmd 6f1e8511 > ffffffff S=6 s=1 (14)
22:04:48.180714 xid:cmd 6f1e8511 > ffffffff S=6 s=2 (14)
22:04:48.270734 xid:cmd 6f1e8511 > ffffffff S=6 s=3 (14)
22:04:48.270698 xid:rsp 6f1e8511 < fb48d412 S=6 s=2 Jean Tourrilhes hint=8220 [ PDA/Palmtop IrOBEX ] (32)
22:04:48.360742 xid:cmd 6f1e8511 > ffffffff S=6 s=4 (14)
22:04:48.450733 xid:cmd 6f1e8511 > ffffffff S=6 s=5 (14)
22:04:48.540762 xid:cmd 6f1e8511 > ffffffff S=6 s=* weblab10 hint=0400 [ Computer ] (24)
You see my Palm V answering the discoveries of Linux. The Palm shows the infamous "Waiting for sender" pop-up.
On the other hand, if the stack is not properly configured (wrong port, wrong driver), or if the device in front is not active, you will get something like this : 22:02:47.988983 xid:cmd 6f1e8511 > ffffffff S=6 s=0 (14)
22:02:48.078981 xid:cmd 6f1e8511 > ffffffff S=6 s=1 (14)
22:02:48.168992 xid:cmd 6f1e8511 > ffffffff S=6 s=2 (14)
22:02:48.258995 xid:cmd 6f1e8511 > ffffffff S=6 s=3 (14)
22:02:48.349018 xid:cmd 6f1e8511 > ffffffff S=6 s=4 (14)
22:02:48.439035 xid:cmd 6f1e8511 > ffffffff S=6 s=5 (14)
22:02:48.529063 xid:cmd 6f1e8511 > ffffffff S=6 s=* weblab10 hint=0400 [ Computer ] (24)
As you can see, nobody answer us...
After that, send a good bug report to the Linux-IrDA mailing list.

The connection just "hang"
The first type of hang is a very classical problem, where the connection hanging just after beeing negociated (after the packets called SNRM and UA). The irdadump looks like the following : 18:03:28.766071 xid:cmd ffffffff < af28ca67 S=6 s=0 (14)
18:03:28.856067 xid:cmd ffffffff < af28ca67 S=6 s=1 (14)
18:03:28.947685 xid:cmd ffffffff < af28ca67 S=6 s=2 (14)
18:03:29.037383 xid:cmd ffffffff < af28ca67 S=6 s=3 (14)
18:03:29.037549 xid:rsp 977f612c > af28ca67 S=6 s=3 lagaffe hint=4400 [ Computer LAN Access ] (23)
18:03:29.126099 xid:cmd ffffffff < af28ca67 S=6 s=4 (14)
18:03:29.216071 xid:cmd ffffffff < af28ca67 S=6 s=5 (14)
18:03:29.316257 xid:cmd ffffffff < af28ca67 S=6 s=* tanguy hint=4400 [ Computer LAN Access ] (22)
18:03:29.316433 snrm:cmd ca=fe pf=1 977f612c > af28ca67 new-ca=ba (32)
18:03:29.417508 ua:rsp ca=ba pf=1 977f612c < af28ca67 (31)
18:03:29.417646 rr:cmd > ca=ba pf=1 nr=0 (2)
18:03:29.666173 rr:cmd > ca=ba pf=1 nr=0 (2)
If you are on the primary, you will see a series of rr:cmd until it times-out. On the secondary, you won't see anything after the ua:rsp and it will eventually timeout.
What most likely happening is that the negociated connection parameters don't match. Usually, one end doesn't implement properly the speed that is beeing negociated, so the two nodes can't hear each other after changing speed. And most likely it happens at FIR speeds.
Of course, it would be nice to fix the driver, but in the short term the solution is to force the IrDA stack to negociate a lower speed : > echo 115200 > /proc/sys/net/irda/max_baud_rate
You can of course try lower values, and there is also other parameters you can tweak in this directory.
There is second type of hang, that may look similar but is not. You may see the IrDA stack "hanging" on transmitting a large packet (the last number between parenthesis). This seems due to a bug in the some FIR hardware. 18:03:30.458569 i:rsp < ca=ba pf=1 nr=6 ns=5 LM slsap=12 dlsap=10 CONN_CMD TTP credits=0(12)
18:03:30.458740 i:cmd > ca=ba pf=1 nr=6 ns=6 LM slsap=10 dlsap=12 CONN_RSP TTP credits=0(12)
18:03:30.466399 rr:rsp < ca=ba pf=1 nr=7 (2)
18:03:30.516548 rr:cmd > ca=ba pf=1 nr=6 (2)
18:03:30.537423 i:rsp < ca=ba pf=1 nr=7 ns=6 LM slsap=12 dlsap=10 TTP credits=0 (29)
18:03:30.537663 rr:cmd > ca=ba pf=1 nr=7 (2)
18:03:30.547328 rr:rsp < ca=ba pf=1 nr=7 (2)
18:03:30.555025 i:cmd > ca=ba pf=1 nr=7 ns=7 LM slsap=10 dlsap=12 TTP credits=1 (2050)
18:03:30.566804 i:cmd > ca=ba pf=1 nr=7 ns=7 LM slsap=10 dlsap=12 TTP credits=1 (2050)
18:03:30.596405 i:cmd > ca=ba pf=1 nr=7 ns=7 LM slsap=10 dlsap=12 TTP credits=1 (2050)
It may look a bit different for you, but you get the idea, the packet doesn't goes through and is retried, and the communication just dies there.
As we can't fix the hardware, the solution is to force the IrDA stack to transmit smaller packets : > echo 2000 > /proc/sys/net/irda/max_tx_data_size
Now, I've seen is a third type of hang which happen during the connection, and not related to a large packet. This happens with buggy phones, such as Ericsson phones (T39/T68/...). 14:53:57.741656 snrm:cmd ca=fe pf=1 2cc4b1b4 > 29c42130 new-ca=ae
LAP QoS: Baud Rate=4000000bps Max Turn Time=500ms Data Size=2048B
Window Size=7 Add BOFS=0 Min Turn Time=1000us Link Disc=12s (33)
14:53:57.877021 ua:rsp ca=ae pf=1 2cc4b1b4 < 29c42130
LAP QoS: Baud Rate=1152000bps Max Turn Time=500ms Data Size=256B Window
Size=3 Add BOFS=0 Min Turn Time=0us Link Disc=12s (31)
14:53:57.877622 rr:cmd > ca=ae pf=1 nr=0 (2)
14:53:57.889399 rr:rsp < ca=ae pf=1 nr=0 (2)
14:53:57.889468 i:cmd > ca=ae pf=1 nr=0 ns=0 LM slsap=11 dlsap=00 CONN_CMD (6)
14:53:57.895119 i:rsp < ca=ae pf=1 nr=1 ns=0 LM slsap=00 dlsap=11 CONN_RSP (6)
14:53:57.895264 i:cmd > ca=ae pf=1 nr=1 ns=1 LM slsap=11 dlsap=00
GET_VALUE_BY_CLASS: "IrDA:IrCOMM" "Parameters" (28)
14:53:57.899848 i:rsp < ca=ae pf=1 nr=2 ns=1 LM slsap=00 dlsap=11
GET_VALUE_BY_CLASS: Success
IrCOMM Parameters Service Type=NINE_WIRE THREE_WIRE Port Type=PARALLEL (19)
14:53:57.900690 i:cmd > ca=ae pf=0 nr=2 ns=2 LM slsap=11 dlsap=00 DISC (6)
14:53:57.900803 i:cmd > ca=ae pf=1 nr=2 ns=3 LM slsap=12 dlsap=00 CONN_CMD (6)
14:53:57.914408 rr:rsp < ca=ae pf=1 nr=4 (2)
14:53:57.914453 rr:cmd > ca=ae pf=1 nr=2 (2)
14:53:57.924388 rr:rsp < ca=ae pf=1 nr=4 (2)
14:53:57.965741 rr:cmd > ca=ae pf=1 nr=2 (2)
The first interesting part of the log above is the Min Turn Time=0us. The peer says that it can turn the link around in 0us, but I've never seen any device that fast.
The problem here is that the Linux-IrDA stack gives the peer exactly what he ask for, and the Linux-IrDA stack can be very fast in turning around. And of course the peer can't keep up and doesn't receive properly the frames, and after that it usually goes downhill.
In those cases, you may want mandate that Linux uses a large turnaround time : > echo 1000 > /proc/sys/net/irda/min_tx_turn_time
The second interesting part of the log above is that it fails just after the Linux-IrDA sends two consecutive packets. IrLAP is a windowed protocol (up to 7 consecutive frames), but some devices have trouble managing that (such as the Ericsson phones and USB dongles).
In those cases, you may want limit Linux to send one frame per IrLAP window : > echo 1 > /proc/sys/net/irda/max_tx_window
Note that the patch adding max_tx_window to the IrDA stack is included only in kernel 2.4.22, for earlier kernel to fetch a patch up here.

irattach print "tcsetattr" in the log
People using FIR drivers (nsc-ircc, smc-ircc...) are often confronted to this simple problem. When they start irattach, it doesn't work and the following message (or similar) is printed in the log : irattach: tcsetattr: Invalid argument
This is due to a conflict between the Linux-IrDA FIR driver and the regular Linux serial driver. Both want to manage the same hardware, the serial driver has registered the FIR port as a pseudo serial port and is owning it, and the kernel rightly prevent the FIR driver to get ownership of it (it's first come first serve).
The solution is simple. You need to tell the serial driver that it should not manage this port.
The safest way is to remove the serial driver : > rmmod serial
Unfortunately, the trick above doesn't always work (non-modular driver, another serial port in use). Another way is to declare the port invalid : > setserial /dev/ttyS1 uart none
On the other hand, if you do that, you won't be able to use irtty (SIR mode driver), because irtty uses the regular Linux serial driver. If you change your mind and want to use the irtty driver, you can reenable the serial port with : > insmod serial
> setserial /dev/ttyS1 uart 16550A

Common pitfalls
There is many way to get the IrDA stack to not run properly. Not following instructions seems to be one of the most guaranteed way to reach that goal.
Here are mistakes I've seen user make :
IrDA ports not properly aligned
irmanager running (it's obsolete, get rid of it)
Let the init scripts of the distribution do the job
irdaping running (prevent the LAP connection)
Obsolete irda-utils
using the wrong driver (FIR/irtty/irport)
using the wrong port (/dev/ttyS0 vs /dev/ttyS1)
Wrong permissions on the serial port (irattach must run as root)
Some other application (such as pppd) grabbing the serial port
Some other driver (most likely a Pcmcia card) using the IRQ that the IrDA driver needs (for Pcmcia drivers, play with "exclude" directives in /etc/pcmcia/config.opts)
Wrong irattach command (irattach /dev/ttySX for SIR vs irattach irdaX for FIR)
Multiple instances of irattach for the same port (staying in background)
Wrong modules names (should be ircomm-tty, not ircomm_tty)
IrDA modules not loaded
Mixing up /dev/ttySX and /dev/ircommX. The stack runs on top of /dev/ttySX and provides serial emulation through /dev/ircommX, so serial apps should run on top of /dev/ircommX.
Compiling the IrDA stack static (i.e. non module - it may work, but this is not what the developpers work with)
Compiling the IrDA stack without the IRDA_DEBUG option. This option enable extra checks that prevent your kernel to crash.
Mixing modules belonging to different versions of the IrDA stack
Unclean IrDA source (failed patch)
Mixing modules belonging to different kernel versions
Trying to load an IrDA module on a stack wich has this code compiled static (or loading module twice)
Wrong version of modules tools (for kernel 2.4)
Failed to do depmod -a (usually automatic at reboot)
Using a version of the kernel which is not used and recommended by developpers.
Compilation problemsSometimes, when you compile the IrDA stack or some various IrDA package, you may have the compiler complaining the things such as IRLMP_HINT_MASK_SET or IRDAPROTO_ULTRA are not defined.
This is because of a mess related to kernel headers and the way most distributions deal with it. If you have the 2.4.X kernel source lying around, the fix is simple. Just copy the header irda.h from the kernel to your include directory : cp /usr/src/linux/include/linux/irda.h /usr/include/linux
That should fix it ;-)