2004年09月20日

hciconfig的结构

int main(int argc, char **argv, char **env)
{
 int opt, ctl, i, cmd=0;

 while ((opt=getopt_long(argc, argv, “ah”, main_options, NULL)) != -1) {
  switch(opt) {
  case ‘a’:
   all = 1;
   break;

  case ‘h’:
  default:
   usage();
   exit(0);
  }
 }

 argc -= optind;
 argv += optind;
 optind = 0;

 /* Open HCI socket  */
 if ((ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI)) < 0) {
  perror(“Can’t open HCI socket.”);
  exit(1);
 }

 if (argc < 1) {
  print_dev_list(ctl, 0);
  exit(0);
 }

 di.dev_id = atoi(argv[0] + 3);
 argc–; argv++;

 if (ioctl(ctl, HCIGETDEVINFO, (void*)&di)) {
  perror(“Can’t get device info”);
  exit(1);
 }

 while (argc > 0) {
  for (i=0; command[i].cmd; i++) {
   if (strncmp(command[i].cmd, *argv, 5))
    continue;

   if (command[i].opt) {
    argc–; argv++;
   }

   command[i].func(ctl, di.dev_id, *argv);
   cmd = 1;
   break;
  }
  argc–; argv++;
 }

 if (!cmd)
  print_dev_info(ctl, &di);

 close(ctl);
 return 0;
}
结构说明:

建立socket, socket()

利用ioctl操纵硬件设备,ioctl

关闭socket, close()

其中:还包括了命令行参数的解析,

如getopt_long,以及argc,argv的使用。

自从linux-2.4.x以后,用户不用安装bluez-kernel package,只要安装bluez-libs,bluez-utils即可;其中bluetooth的核心部分在linxu的源码目录dirvers/bluetooth and net/bluetooth;

bluez的各层协议实现socket interface,使用icotl直接操作设备。

 

icotl具体调用的函数:

bluez-utils/tools/hciconfig.c(编译后是hciconfig程序)

main->print_dev_list(ctl, 0)-> ioctl(ctl, HCIGETDEVLIST, (void*)dl)

hci’s icotl函数在net/bluetooth/hci_core.c中

static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
 struct sock *sk = sock->sk;
 int err;

 BT_DBG(“cmd %x arg %lx”, cmd, arg);

 switch (cmd) {
 case HCIGETDEVLIST:
  return hci_get_dev_list(arg);

 case HCIGETDEVINFO:
  return hci_get_dev_info(arg);

 case HCIGETCONNLIST:
  return hci_get_conn_list(arg);

 case HCIDEVUP:
  if (!capable(CAP_NET_ADMIN))
   return -EACCES;
  return hci_dev_open(arg);

 case HCIDEVDOWN:
  if (!capable(CAP_NET_ADMIN))
   return -EACCES;
  return hci_dev_close(arg);

 case HCIDEVRESET:
  if (!capable(CAP_NET_ADMIN))
   return -EACCES;
  return hci_dev_reset(arg);

 case HCIDEVRESTAT:
  if (!capable(CAP_NET_ADMIN))
   return -EACCES;
  return hci_dev_reset_stat(arg);

 case HCISETSCAN:
 case HCISETAUTH:
 case HCISETENCRYPT:
 case HCISETPTYPE:
 case HCISETLINKPOL:
 case HCISETLINKMODE:
 case HCISETACLMTU:
 case HCISETSCOMTU:
  if (!capable(CAP_NET_ADMIN))
   return -EACCES;
  return hci_dev_cmd(cmd, arg);

 case HCIINQUIRY:
  return hci_inquiry(arg);

 default:
  lock_sock(sk);
  err = hci_sock_bound_ioctl(sk, cmd, arg);
  release_sock(sk);
  return err;
 };
}
至于 hci_sock_ioctl是如何注册为icotl的调用的,还不知道?

2.get_user and copy_to_user

get_user 从用户空间向内核空间拷贝,copy_to_user则相反。

用途:

举例,hciconfig程序是用户空间的程序,执行hciconfig指令,系统应该列出当前所有的hci设备,程序的实现是在hciconfig.c文件中分配hci_dev_list_req 变量;

 struct hci_dev_list_req *dl;
 struct hci_dev_req *dr;
 int i;

 if( !(dl = malloc(HCI_MAX_DEV * sizeof(struct hci_dev_req) + sizeof(uint16_t))) ) {
  perror(“Can’t allocate memory”);
  exit(1);
 }
 dl->dev_num = HCI_MAX_DEV;
 dr = dl->dev_req;

 if( ioctl(ctl, HCIGETDEVLIST, (void*)dl) ) {

调用icotl后,根据hci_sock_ioctl执行

 switch (cmd) {
 case HCIGETDEVLIST:
  return hci_get_dev_list(arg);

其中hci_get_dev_list在net/bluetooth/hci_core.c中

int hci_get_dev_list(unsigned long arg)
{
 struct hci_dev_list_req *dl;
 struct hci_dev_req *dr;
 struct list_head *p;
 int n = 0, size, err;
 __u16 dev_num;

 if (get_user(dev_num, (__u16 *) arg))
  return -EFAULT;

 if (!dev_num || dev_num > (PAGE_SIZE * 2) / sizeof(*dr))
  return -EINVAL;

 size = sizeof(*dl) + dev_num * sizeof(*dr);

 if (!(dl = kmalloc(size, GFP_KERNEL)))

//注意,内核空间也同样分配了hci_dev_list_req结构;

实际数据的拷贝就依赖get_user and copy_to_user函数。

感觉上hci_sock.c文件中的这几行语句根ioctl的注册有关

struct proto_ops hci_sock_ops = {
 family:  PF_BLUETOOTH,
 release: hci_sock_release,
 bind:  hci_sock_bind,
 getname: hci_sock_getname,
 sendmsg: hci_sock_sendmsg,
 recvmsg: hci_sock_recvmsg,
 ioctl:  hci_sock_ioctl,
 poll:  datagram_poll,
 listen:  sock_no_listen,
 shutdown: sock_no_shutdown,
 setsockopt: hci_sock_setsockopt,
 getsockopt: hci_sock_getsockopt,
 connect: sock_no_connect,
 socketpair: sock_no_socketpair,
 accept:  sock_no_accept,
 mmap:  sock_no_mmap
};

static int hci_sock_create(struct socket *sock, int protocol)
{
 struct sock *sk;

 BT_DBG(“sock %p”, sock);

 if (sock->type != SOCK_RAW)
  return -ESOCKTNOSUPPORT;

 sock->ops = &hci_sock_ops;

//sock的操作函数变成了hci的操作函数

 if (!(sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, 1)))
  return -ENOMEM;

 sock->state = SS_UNCONNECTED;
 sock_init_data(sock, sk);

 memset(&sk->protinfo, 0, sizeof(struct hci_pinfo));
 sk->destruct = NULL;
 sk->protocol = protocol;
 sk->state    = BT_OPEN;

 bluez_sock_link(&hci_sk_list, sk);

 MOD_INC_USE_COUNT;
 return 0;
}

struct net_proto_family hci_sock_family_ops = {
 family: PF_BLUETOOTH,
 create: hci_sock_create
};

不知道什么函数调用hci_sock_init,

找到af_bluettooth.c’s bluez_init调用它,

#ifdef MODULE
module_init(bluez_init);
module_exit(bluez_cleanup);

//上面这几句说明,我们使用insmod bluez加载bluez模块时,

根据驱动程序一书,会自动调用bluez_init函数。

int bluez_init(void)
{
 BT_INFO(“BlueZ Core ver %s Copyright (C) 2000,2001 Qualcomm Inc”,
   VERSION);
 BT_INFO(“Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>”);

 proc_mkdir(“bluetooth”, NULL);

//这句说明我们可以通过/proc/bluetooth文件监视蓝牙设备

 sock_register(&bluez_sock_family_ops);

1624 *      This function is called by a protocol handler that wants to
1625 *      advertise its address family, and have it linked into the
1626 *      SOCKET module.
1627 */
1628
1629 int sock_register(struct net_proto_family *ops)
1630 {
1631         int err;
1632
1633         if (ops->family >= NPROTO) {
1634                 printk(KERN_CRIT “protocol %d >= NPROTO(%d)\n”, ops->family, NPROTO);
1635                 return -ENOBUFS;
1636         }
1637         net_family_write_lock();
1638         err = -EEXIST;
1639         if (net_families[ops->family] == NULL) {
1640                 net_families[ops->family]=ops;
1641                 err = 0;
1642         }
1643         net_family_write_unlock();
1644         return err;
1645 }

struct net_proto_family bluez_sock_family_ops =
{
 PF_BLUETOOTH, bluez_sock_create
};

struct net_proto_family
{
 int family;
 int (*create)(struct socket *sock, int protocol);
 /* These are counters for the number of different methods of
    each we support */
 short authentication;
 short encryption;
 short encrypt_net;
};

static int bluez_sock_create(struct socket *sock, int proto)
{
 if (proto >= BLUEZ_MAX_PROTO)
  return -EINVAL;

#if defined(CONFIG_KMOD)
 if (!bluez_proto[proto]) {
  char module_name[30];
  sprintf(module_name, “bt-proto-%d”, proto);
  request_module(module_name);
 }
#endif

 if (!bluez_proto[proto])
  return -ENOENT;

 return bluez_proto[proto]->create(sock, proto);
}

 /* Init HCI Core */
 hci_core_init();

 /* Init sockets */
 hci_sock_init();

 return 0;
}

int hci_sock_init(void)
{
 if (bluez_sock_register(BTPROTO_HCI, &hci_sock_family_ops)) {
  BT_ERR(“Can’t register HCI socket”);
  return -EPROTO;
 }

 hci_register_notifier(&hci_sock_nblock);
 return 0;
}

/* Bluetooth sockets */
#define BLUEZ_MAX_PROTO 7
static struct net_proto_family *bluez_proto[BLUEZ_MAX_PROTO];

int bluez_sock_register(int proto, struct net_proto_family *ops)
{
 if (proto >= BLUEZ_MAX_PROTO)
  return -EINVAL;

 if (bluez_proto[proto])
  return -EEXIST;

 bluez_proto[proto] = ops;
 return 0;
}
  

2004年09月19日



关于驱动程序中的ioctl


coly(李勇)[本站会员]

  我这里说的ioctl函数是在驱动程序里的,因为我不知道还有没有别的场合用到了ioctl, 所以就规定了我们讨论的范围。为什么要写篇文章呢,是因为我前一阵子被ioctl给搞混 了,这几天才弄明白它,于是在这里清理一下头脑。 一、 什么是ioctl。 ioctl是设备驱动程序中对设备的I/O通道进行管理的函数。所谓对I/O通道进行管理,就 是对设备的一些特性进行控制,例如串口的传输波特率、马达的转速等等。它的调用个数 如下: int ioctl(int fd, ind cmd, …); 其中fd就是用户程序打开设备时使用open函数返回的文件标示符,cmd就是用户程序对设 备的控制命令,至于后面的省略号,那是一些补充参数,一般最多一个,有或没有是和 cmd的意义相关的。 ioctl函数是文件结构中的一个属性分量,就是说如果你的驱动程序提供了对ioctl的支 持,用户就可以在用户程序中使用ioctl函数控制设备的I/O通道。 二、 ioctl的必要性 如果不用ioctl的话,也可以实现对设备I/O通道的控制,但那就是蛮拧了。例如,我们可 以在驱动程序中实现write的时候检查一下是否有特殊约定的数据流通过,如果有的话, 那么后面就跟着控制命令(一般在socket编程中常常这样做)。但是如果这样做的话,会 导致代码分工不明,程序结构混乱,程序员自己也会头昏眼花的。 所以,我们就使用ioctl来实现控制的功能。要记住,用户程序所作的只是通过命令码告 诉驱动程序它想做什么,至于怎么解释这些命令和怎么实现这些命令,这都是驱动程序要 做的事情。 三、 ioctl如何实现 这是一个很麻烦的问题,我是能省则省。要说清楚它,没有四五千字是不行的,所以我这 里是不可能把它说得非常清楚了,不过如果有读者对用户程序怎么和驱动程序联系起来感 兴趣的话,可以看我前一阵子写的《write的奥秘》。读者只要把write换成ioctl,就知 道用户程序的ioctl是怎么和驱动程序中的ioctl实现联系在一起的了。 我这里说一个大概思路,因为我觉得《Linux设备驱动程序》这本书已经说的非常清楚 了,但是得化一些时间来看。 在驱动程序中实现的ioctl函数体内,实际上是有一个switch{case}结构,每一个case对 应一个命令码,做出一些相应的操作。怎么实现这些操作,这是每一个程序员自己的事 情,因为设备都是特定的,这里也没法说。关键在于怎么样组织命令码,因为在ioctl中 命令码是唯一联系用户程序命令和驱动程序支持的途径。 命令码的组织是有一些讲究的,因为我们一定要做到命令和设备是一一对应的,这样才不 会将正确的命令发给错误的设备,或者是把错误的命令发给正确的设备,或者是把错误的 命令发给错误的设备。这些错误都会导致不可预料的事情发生,而当程序员发现了这些奇 怪的事情的时候,再来调试程序查找错误,那将是非常困难的事情。 所以在Linux核心中是这样定义一个命令码的: ____________________________________ | 设备类型 | 序列号 | 方向 |数据尺寸| |----------|--------|------|--------| | 8 bit | 8 bit |2 bit |8~14 bit| |----------|--------|------|--------| 这样一来,一个命令就变成了一个整数形式的命令码。但是命令码非常的不直观,所以 Linux Kernel中提供了一些宏,这些宏可根据便于理解的字符串生成命令码,或者是从 命令码得到一些用户可以理解的字符串以标明这个命令对应的设备类型、设备序列号、数 据传送方向和数据传输尺寸。 这些宏我就不在这里解释了,具体的形式请读者察看Linux核心源代码中的和,文件里给 除了这些宏完整的定义。这里我只多说一个地方,那就是"幻数"。 幻数是一个字母,数据长度也是8,所以就用一个特定的字母来标明设备类型,这和用一 个数字是一样的,只是更加利于记忆和理解。就是这样,再没有更复杂的了。 更多的说了也没有,读者还是看一看源代码吧,推荐各位阅读《Linux 设备驱动程序》所 带源代码中的short一例,因为它比较短小,功能比较简单,可以看明白ioctl的功能和细 节。 四、 cmd参数如何得出 这里确实要说一说,cmd参数在用户程序端由一些宏根据设备类型、序列号、传送方向、 数据尺寸等生成,这个整数通过系统调用传递到内核中的驱动程序,再由驱动程序使用解 码宏从这个整数中得到设备的类型、序列号、传送方向、数据尺寸等信息,然后通过 switch{case}结构进行相应的操作。 要透彻理解,只能是通过阅读源代码,我这篇文章实际上只是一个引子。Cmd参数的组织 还是比较复杂的,我认为要搞熟它还是得花不少时间的,但是这是值得的,驱动程序中最 难的是对中断的理解。 五、 小结 ioctl其实没有什么很难的东西需要理解,关键是理解cmd命令码是怎么在用户程序里生成 并在驱动程序里解析的,程序员最主要的工作量在switch{case}结构中,因为对设备的 I/O控制都是通过这一部分的代码实现的。 参考资料: 1.《Linux 设备驱动程序》,鲁宾尼著,中国电力出版社。 2.《write的奥秘》,coly,真情流露(202.204.7.235)->电脑技术->Linux技术。  

 
中国Linux论坛 版权所有



Copyright 1999,2000, 2001 China Linux Forum

2004年09月18日

What do I need to use Bluetooth on Linux? You need Linux system with 2.4.x or newer kernel, BlueZ user space packages and a Bluetooth device. If you do not have actual Bluetooth device you could use HCI Emulation daemon provided in BlueZ-HCIEmu package. it says bluez-libs and bluez-utils package is user space application. What interfaces are available for Bluetooth applications? Linux provides standard Berkeley socket interface to all Bluetooth layers. The RFCOMM layer also provides a TTY interface. 所有的层都提供socket接口 What is ‘rfcommd’? RFCOMMd (or rfcommd) is the user space implementation of the RFCOMM protocol. It was replaced by RFCOMM kernel module and shouldn’t be used anymore. 协议实现的应用程序可以在用户空间或者是内核。

2004年09月14日

Bluetooth 规范支持针对 Bluetooth HCI 数据分组的 UART(通用异步接收器/传送器)和 USB 传输机制。BlueZ 栈对这两个传输机制(drivers/Bluetooth/)都支持。

BlueZ BNEP(Bluetooth 网络封装协议)实现了 Bluetooth 上的以太网仿真,这使 TCP/IP 可以直接运行于 Bluetooth 之上。BNEP 模块(net/bluetooth/bnep/)和用户模式 pand 后台进程实现了 Bluetooth 个人区域网(PAN)。BNEP 使用 register_netdev 将自己作为以太网设备注册到 Linux 网络层,并使用上面为 WLAN 驱动程序描述的 netif_rx 来填充 sk_buffs 并将其发送到协议栈。

BlueZ RFCOMM(net/bluetooth/rfcomm/) 提供 Bluetooth 上的串行仿真,这使得串行端口应用程序(如 minicom)和协议(如点对点协议(PPP))不加更改地在 Bluetooth 上运行。RFCOMM 模块和用户模式 dund 后台进程实现了 Bluetooth 拨号网络。下面的列表给出了配置 Bluetooth 上的各种协议服务所必需的 BlueZ 模块、实用程序、后台进程以及配置文件。
简单的理解是:模块是内核支持的,由linux kernel 打bluez-kernel完成,用户程序则可以通过安装bluez-libs,bluez-utils得到;

而且值得注意的是:bnep,rfcomm都是蓝牙协议speciality,pand,dund都是蓝牙的profile。可以猜测还有l2cap模块,至于sdp为什么实现为用户程序就搞不懂了?

insmod serial_cs
insmod bluez
insmod l2cap
insmod hci_uart
insmod bnep (for pand)
insmod rfcomm (for dund)

BlueZ 用户空间后台进程、实用程序以及配置文件:
hciattach ttySx any [baud_rate] [flow]
hciconfig -a:检查 HCI 接口。
hcitool -a hci0 scan ‘flush:发现其他设备。
hcidump:HCI 嗅探器。
hcid:HCI 后台进程。
/etc/bluetooth/hcid.conf:hcid 所用的 HCI 后台进程配置文件,它指定了链接模式(主或从)、链接策略、询问和扫描模式,等等。
/etc/bluetooth/pinDB:BlueZ PIN 数据库。
hcidump:Service Discovery Protocol 后台进程。
pand:在 Bluetooth 上运行 TCP/IP(–listen 用于服务器,–connect 用于客户机)。
/etc/bluetooth/pan/dev-up:pand 在激活 TCP/IP 时调用此脚本。此脚本能够包含一个类似于 ifconfig bnep0 的命令,用以为 Bluetooth 接口配置 IP 地址。
hcidump:在 Bluetooth RFCOMM 上运行 PPP(–listen 用于服务器,–connect 用于客户机)。

具有内置 CSR Bluetooth 芯片组的母板

现在,关注一下具有内置 Bluetooth 芯片组的设备上的 Bluetooth 网络数据流。考虑一种拥有内置 CSR Bluetooth 芯片组的手持设备与使用 UART 接口的系统的连接。针对 UART 接口而言,在 Bluetooth 设备和系统之间传输 HCI 数据分组的可用协议有 BlueCore Serial Protocol (BCSP)、H4/UART 和 H3/RS232。而 H4 充当通过 UART 传输 Bluetooth 数据的标准方法。UART 是在规范中定义的来自 CSR 的专有 BCSP 协议,支持错误校验和重传。BCSP 用在基于 CSR BlueCore 芯片的非 USB 设备上,包括 PCMCIA 和 CF 卡。BlueZ 支持 BCSP 和 H4。

这个母板的 UART 通道使用的传统串行驱动程序可以从 BlueZ UART 传输驱动程序上收发数据。如果使用 BSCP 协议将 CSR 芯片设计为封装 HCI 数据分组,您必须使用 hciattach (hciattach ttySx bcsp) 通知 BlueZ 链接驱动程序,在这里 x 是连接到 CSR 芯片组的 UART 通道号。现在 hci_uart 与 CSR 芯片交互并且传送 Bluetooth 数据往返于 BlueZ 栈。
insmod serial_cs
insmod bluez
insmod l2cap
insmod hci_uart
insmod bnep (for pand)
insmod rfcomm (for dund)

hciattach ttySx bcsp [baud_rate] [flow]

hciconfig -a

1.bluez maillist:

bcsp not working (bcsp bluecore serial protocol)

he execute the following script to start all the bluetooth stuff:
————————————————————
#!/bin/sh
/bluez/hcid -n &
/bluez/bluezmain hciattach -n /dev/tts/2 bcsp 115200 &
/bluez/bluezmain hciconfig hci0 up
/bluez/sdpd -n &
/bluez/bluezmain sdptool add sp
#my own program
/bluez/rfcomm-server 1
————————————————————
I used “-n” because the uclinux fork call does not behave as normal linux.
The uclinux hangs in hciattach.

I successfully executed this script with the same bluetooth hardware in a Linux 2.6 PC with bluez 2.7.
Everything worked fine.

其中:

1.hcid -n: Don’t fork to run daemon in background.

& 后台执行

bluezmain应该是目录吧,/bluez/bluezmain/hciattach

2.hciattach -n /dev/tts/2 csr 115200 &

-n: Don’t detach from controlling terminal

 /dev/tts/2: This specifies the serial device to attach.(指定连那一个串口)

csr:CSR Casira serial adapter or BrainBoxes serial dongle (BL642)

bcsp: Serial adapters using CSR chips with BCSP serial protocol

3.hciconfig hci0 up

up: Open and initialize HCI device

4.sdptool add sp

Add a service to the local

sp: what service is sp?

funking source code; sp is Serial Port service

2004年09月12日

1.阅读打印的两篇文章,如有可能,应该考虑演示

2.给老师公司帐号

2004年09月09日

BlueZ 2.3 setup

Maksim and their friends are working too hard, and BlueZ has matured significantely since I last tested it, so it was time to revisit the issue. With version 2.2, the most interesting new feature is of course PAN/BNEP support. With version 2.3, we have the new RfCOMM support which is a big improvement.

So, I did again limited testing with BlueZ 2.2, both with the Brainboxes Pcmcia card and the USB dongle. I also did extensive testing of BlueZ 2.3 with the 3Com 3CREB96 USB dongle. A lot of the tools and procedure have changed with respect to BlueZ 1.2

As opposed to OpenBT, BlueZ use a network abstraction to interface both to drivers and applications. BlueZ need special network driver for serial and USB devices, and BlueTooth devices will be referenced as hciX (most often hci0). Applications talk to the BlueZ stack using sockets (using the AF_BLUETOOTH family).

Common configuration

The BlueZ web site already contains an excellent Howto, so you may want to start by reading that…

To enable BlueZ, you will need to do the following operations :

  1. Get a fairly recent Linux kernel, BlueZ 2.3 is included in kernel 2.4.21-pre3 and later.
  2. Enable BlueZ and related options in your kernel, under the menu Bluetooth support.
  3. Compile and reinstall your kernel.
  4. Download and install the BlueZ library package.
  5. Download and install the BlueZ utilities and BlueZ sdp package. Those will compile only if the library is fully installed.
  6. Optionally, download and install the hcidump package. It’s a good debugging tool and necessary to do proper bug reports.
  7. Download and install the PAN package. This will compile only if both the utils and sdp packages are fully installed.

To get module auto-loading to work, you need to add in /etc/modules.conf the following :

alias net-pf-31 bluez alias bt-proto-0 l2cap alias bt-proto-2 sco alias bt-proto-3 rfcomm alias bt-proto-4 bnep 

BlueZ and the USB dongle

BlueZ has strong support for USB dongles. As opposed to OpenBT, BlueZ doesn’t use the BlueTooth USB to serial converter, but uses its own USB driver (and of course, you can’t have both running at the same time).

First, you need to get the USB stack up and running. This depend on your USB controller (UHCI vs OHCI).

To get you USB dongle working, you then need to do :

> modprobe bluez > modprobe hci_usb > modprobe l2cap > hciconfig hci0 up 

BlueZ and the Brainboxes Pcmcia card

The version 1.6 of BlueZ has changed the way serial devices are initialised. Instead of using hcid, you will need to use hciattach.

My obsolete patchthat adds CSR chip support to hciattach has been included in BlueZ 2.0 (and improved), so it will work out of the box at 460800 bauds. With a few more patches you will be able to do 921600 bauds.

You start the stack like this :

> modprobe bluez > modprobe hci_uart > modprobe l2cap > hciattach /dev/ttyS2 csr 460800 > hciconfig hci0 up 

TCP/IP over PAN/BNEP

PAN and BNEP are the “official” way to do networking with BlueTooth. BNEP is a simple encapsulation of Ethernet frames in a L2CAP session. PAN is the BlueTooth profile using BNEP and defining how to do networking. It includes the definition of the SDP attributes and various node roles.

What are the node roles ? It’s just something to make your life more complex. In a typical Ad-Hoc scenario, the server will have the role GN, and up to 7 clients with role PANU can be connected to it. An Access Point would take a NAP (yeah, boring).

The support of BNEP in BlueZ is quite new and and not yet documented in the Official Howto, but there is an alternate Unofficial Howto.

As usual, I’ll go straight to a very simple example of setting up TCP/IP between two nodes. You can do more complex stuff by reading the Howto above.

First, you need to set up the server. The server will listen for incomming connections. In our example, it’s not an Access Point, so we do :

> modprobe bnep > pand --listen --role GN 

On the client side, we first need to know the address of the server ; the inquiry is currently done like this :

> hcitool inq Inquiring ... 50:C2:00:03:C4:DC clock offset: 0x2454 class: 0x020300 

Now, you just need to connect to the other side :

> modprobe bnep > pand --connect 50:C2:00:03:C4:DC 

Unfortunately, pand can fail silently, so the way to check if this succeed is to see if a new device bnep0 has been created, either using cat /proc/net/dev or ifconfig bnep0. You may notice that the interface is down, that’s perfectly normal at this point. In case of problem, you need to check the logs for details, in my case /var/log/daemon.log.

What’s left ? BNEP is only a Ethernet emulation. We need to configure TCP/IP on the new interface. This is done with :

> ifconfig bnep0 10.10.10.1 broadcast 10.10.10.255 netmask 255.255.255.0 

Just remember that you need to assign an different IP address on each node, otherwise it won’t work. After that, you should be able to ping, telnet and all that jazz.

To terminate your connection on the client, just do :

> ifconfig bnep0 down > pand --kill 50:C2:00:03:C4:DC 

If you want to get more fancy, you can use HotPlug to automatically assign IP addresses to the bnep interfaces, and you can start playing with the SPD to know which node support PAN or not. And, if you want to build an Access Point, you will need to enable bridging. The HOWTO explains that in details.

BlueZ 2.3 setup

Maksim and their friends are working too hard, and BlueZ has matured significantely since I last tested it, so it was time to revisit the issue. With version 2.2, the most interesting new feature is of course PAN/BNEP support. With version 2.3, we have the new RfCOMM support which is a big improvement.

So, I did again limited testing with BlueZ 2.2, both with the Brainboxes Pcmcia card and the USB dongle. I also did extensive testing of BlueZ 2.3 with the 3Com 3CREB96 USB dongle. A lot of the tools and procedure have changed with respect to BlueZ 1.2

As opposed to OpenBT, BlueZ use a network abstraction to interface both to drivers and applications. BlueZ need special network driver for serial and USB devices, and BlueTooth devices will be referenced as hciX (most often hci0). Applications talk to the BlueZ stack using sockets (using the AF_BLUETOOTH family).

Common configuration

The BlueZ web site already contains an excellent Howto, so you may want to start by reading that…

To enable BlueZ, you will need to do the following operations :

  1. Get a fairly recent Linux kernel, BlueZ 2.3 is included in kernel 2.4.21-pre3 and later.
  2. Enable BlueZ and related options in your kernel, under the menu Bluetooth support.
  3. Compile and reinstall your kernel.
  4. Download and install the BlueZ library package.
  5. Download and install the BlueZ utilities and BlueZ sdp package. Those will compile only if the library is fully installed.
  6. Optionally, download and install the hcidump package. It’s a good debugging tool and necessary to do proper bug reports.
  7. Download and install the PAN package. This will compile only if both the utils and sdp packages are fully installed.

To get module auto-loading to work, you need to add in /etc/modules.conf the following :

alias net-pf-31 bluez alias bt-proto-0 l2cap alias bt-proto-2 sco alias bt-proto-3 rfcomm alias bt-proto-4 bnep 

BlueZ and the USB dongle

BlueZ has strong support for USB dongles. As opposed to OpenBT, BlueZ doesn’t use the BlueTooth USB to serial converter, but uses its own USB driver (and of course, you can’t have both running at the same time).

First, you need to get the USB stack up and running. This depend on your USB controller (UHCI vs OHCI).

To get you USB dongle working, you then need to do :

> modprobe bluez > modprobe hci_usb > modprobe l2cap > hciconfig hci0 up 

BlueZ and the Brainboxes Pcmcia card

The version 1.6 of BlueZ has changed the way serial devices are initialised. Instead of using hcid, you will need to use hciattach.

My obsolete patchthat adds CSR chip support to hciattach has been included in BlueZ 2.0 (and improved), so it will work out of the box at 460800 bauds. With a few more patches you will be able to do 921600 bauds.

You start the stack like this :

> modprobe bluez > modprobe hci_uart > modprobe l2cap > hciattach /dev/ttyS2 csr 460800 > hciconfig hci0 up 

TCP/IP over PAN/BNEP

PAN and BNEP are the “official” way to do networking with BlueTooth. BNEP is a simple encapsulation of Ethernet frames in a L2CAP session. PAN is the BlueTooth profile using BNEP and defining how to do networking. It includes the definition of the SDP attributes and various node roles.

What are the node roles ? It’s just something to make your life more complex. In a typical Ad-Hoc scenario, the server will have the role GN, and up to 7 clients with role PANU can be connected to it. An Access Point would take a NAP (yeah, boring).

The support of BNEP in BlueZ is quite new and and not yet documented in the Official Howto, but there is an alternate Unofficial Howto.

As usual, I’ll go straight to a very simple example of setting up TCP/IP between two nodes. You can do more complex stuff by reading the Howto above.

First, you need to set up the server. The server will listen for incomming connections. In our example, it’s not an Access Point, so we do :

> modprobe bnep > pand --listen --role GN 

On the client side, we first need to know the address of the server ; the inquiry is currently done like this :

> hcitool inq Inquiring ... 50:C2:00:03:C4:DC clock offset: 0x2454 class: 0x020300 

Now, you just need to connect to the other side :

> modprobe bnep > pand --connect 50:C2:00:03:C4:DC 

Unfortunately, pand can fail silently, so the way to check if this succeed is to see if a new device bnep0 has been created, either using cat /proc/net/dev or ifconfig bnep0. You may notice that the interface is down, that’s perfectly normal at this point. In case of problem, you need to check the logs for details, in my case /var/log/daemon.log.

What’s left ? BNEP is only a Ethernet emulation. We need to configure TCP/IP on the new interface. This is done with :

> ifconfig bnep0 10.10.10.1 broadcast 10.10.10.255 netmask 255.255.255.0 

Just remember that you need to assign an different IP address on each node, otherwise it won’t work. After that, you should be able to ping, telnet and all that jazz.

To terminate your connection on the client, just do :

> ifconfig bnep0 down > pand --kill 50:C2:00:03:C4:DC 

If you want to get more fancy, you can use HotPlug to automatically assign IP addresses to the bnep interfaces, and you can start playing with the SPD to know which node support PAN or not. And, if you want to build an Access Point, you will need to enable bridging. The HOWTO explains that in details.

努力