Использование Bluetooth в FreeBSD


Отмазки
-------

Данная заметка не претендует на универсальность и совершенно не заменяет чтение соответствующей главы руководства и манов bluetooth(3), l2ping(8), hcsecd(8), sdpcontrol(8), sdpd(8), ng_ubt(4), sdp(3), obexapp(1)). Цель заметки - обобщить полученные в результате экспериментов результаты и собрать все это в одном документе

Дано

Из Bluetooth устройств у меня имеется мобильник Siemens S55, Palm Zire 72s и безымянный Bluetooth USB адаптер (vendor 0x1131, product 0x1001)
купленный в ближайшей компьютерной лавке. Судя по данным http://www.linux-usb.org/usb.ids им оказался Integrated System Solution Corp. KY-BT100 Bluetooth Adapter. ОС - FreeBSD 6-STABLE, впрочем, все описываемое должно работать и в 5.xx.

Первоначальные настройки.

Bluetooth стек в FreeBSD реализован как нода netgraph(3) ng_ubt. Я рекомендую использовать динамическую загрузку netgraph модулей вместо
компиляции в ядре. Для того, чтобы загрузить модуль Bluetooth наберите до подключения устройства:

# kldload ng_ubt

Чтобы добавить данный драйвер в автозагрузку - добавте в /boot/loader.conf строку

ng_ubt_load="YES"

После подключения устройства вы должны увидеть в логах и/или на консоли строки такого вида:

ubt0: vendor 0x1131 product 0x1001, rev 1.10/3.73, addr 2
ubt0: vendor 0x1131 product 0x1001, rev 1.10/3.73, addr 2
ubt0: Interface 0 endpoints: interrupt=0x81, bulk-in=0x82, bulk-out=0x2
ubt0: Interface 1 (alt.config 5) endpoints: isoc-in=0x83, isoc-out=0x3; wMaxPac
ketSize=49; nframes=6, buffer size=294

Если после подключения ничего не происходит - проверьте работоспособность USB.

Запуск и остановка стека.

Для того, чтобы стек Bluetooth начал работать необходимо скопировать /usr/share/examples/netgraph/bluetooth/rc.bluetooth, например в
/usr/local/etc/rc.bluetooth.

Теперь командой

# sh /usr/local/etc/rc.bluetoots start ubt0

мы запустим Bluetooth стек, а командой

# sh /usr/local/etc/rc.bluetoots stop ubt0

остановим его (рекомендуется перед вытаскиванием адаптера). Так как адаптер без стека мне не сильно нужен я добавил такие команды в
/etc/usbd.conf

device "Bluetooth adapter"
vendor 0x1131
product 0x1001
attach "/usr/local/etc/rc.bluetooth start ${DEVNAME}"
detach "/usr/local/etc/rc.bluetooth stop ${DEVNAME}"

Теперь во время вставления адаптера (или при загрузке если он уже в разъеме) стек будет автоматически включен. В файле rc.bluetooth осуществляется загрузка модулей ng_hci(4), ng_l2cap(4), ng_btsocket(4) и ng_bluetooth(4), создание и соединение netgraph(4) нод. На мой взгляд в нём также целесообразно размещать загрузку/выгрузку демонов, необходимых для работы Bluetooth.
Дополнительные настройки стека bluetooth доступны через переменные sysctl(8) net.bluetooth.*.

Находим устройства

Теперь пришло время узнать MAC адреса наших устройств. Для этого включаем Bluetooth в PDA и S55 (в том числе и "Local Discovery") и запускаем поиск.

~: hccontrol -n ubt0hci inquiry

Inquiry result, num_responses=1
Inquiry result #0
BD_ADDR: 00:07:e0:45:ff:71
Page Scan Rep. Mode: 0x1
Page Scan Period Mode: 00
Page Scan Mode: 00
Class: 10:01:14
Clock offset: 0x7c71
Inquiry result, num_responses=1
Inquiry result #0
BD_ADDR: 00:01:e3:31:c8:53
Page Scan Rep. Mode: 0x1
Page Scan Period Mode: 00
Page Scan Mode: 00
Class: 72:02:04
Clock offset: 0xccb
Inquiry complete. Status: No error [00]

Как видно из вывода программы на наш запрос откликнулось 2 устройства.
Мы, конечно, можем узнать кто есть кто отключив одно из них и повторив попытку, но есть и более удобный метод:

~: hccontrol -n ubt0hci remote_name_request 00:07:e0:45:ff:71
BD_ADDR: 00:07:e0:45:ff:71
Name: SammPalm

~: hccontrol -n ubt0hci remote_name_request 00:01:e3:31:c8:53
BD_ADDR: 00:01:e3:31:c8:53
Name: Samm phone

Кстати, было замечено что устройства часто неохотно говорят свое имя сообщая:

Could not execute command "remote_name_request". Operation timed out

Теперь, когда нам известно кто есть кто - пропишем адреса устройств в файл /etc/bluetooth/hosts добавив такие строки строки:

00:01:e3:31:c8:53 s55
00:07:e0:45:ff:71 palm

Это позволит нам в дальнейшем обращаться к устройствам по имени, а не по адресу. Для проверки связи с устройством используется утилита
l2ping. l2ping нормально функционирует только из под рута (как и ping, впрочем), но suid бита не имеет (видимо из-за соображений безопасности).

# l2ping
# l2ping -a s55 -c 3
0 bytes from s55 seq_no=0 time=17.463 ms result=0
0 bytes from s55 seq_no=5 time=18.039 ms result=0
0 bytes from s55 seq_no=6 time=16.882 ms result=0

# l2ping -a palm -c 3
20 bytes from palm seq_no=0 time=1547.784 ms result=0
20 bytes from palm seq_no=1 time=37.662 ms result=0
20 bytes from palm seq_no=2 time=38.524 ms result=0

Palm во время ping`а высвечивает на экране Connecting и включает звуковой сигнал, Siemens показывает на экране активность Bluetooth соединения.

"Дружим" устройства

Для защиты соединения в протоколе Bluetooth предусмотрена процедура обмена PIN кодом между устройствами (Bluetooth Pairing), после чего (в
случае совпадения PIN кода) создается ключ, с помощью которого и шифруются данные. В OS FreeBSD за эту эти действия отвечает демон
hcsecd(8). Его настройки хранятся в файле /etc/bluetooth/hcsecd.conf. Добавим туда наши устройства:

device {
bdaddr 00:07:e0:45:ff:71;
name "Palm Zire";
key nokey;
pin "12345";
}

device {
bdaddr 00:01:e3:31:c8:53;
name "Siemens S55";
key nokey;
pin "12345";
}

Теперь запустим /usr/sbin/hcsecd. Для отладки, в первый раз это можно сделать с ключем -d, так мы сможем наблюдать за выводом демона.
Процедура создания ключа может быть инициирована как компьютером, так и мобильным устройством (если оно это умеет). В случае Palm это можно сделать используя меню prefs -> Bluetooth -> Setup Devices -> Trusted Devices -> Add Device. Теперь выбираем в списке устройств ubt0 и
вводим назначенный ранее PIN. В случае успешного завершения операции устройство будет добавлено в список Trusted. Демон hcsecd хранит
созданные ключи в файле /var/db/hcsecd.keys. S55 не умеет сам инициировать процедуру создания ключа (по крайней мере, я не нашёл как это сделать). При обращении к телефону с PC данная процедура будет выполнена автоматически. Так как для работы с устройствами требуется наличие hcsecd, я добавил его в rc.bluetooth.

Возможности Bluetooth

Теперь посмотрим, что мы можем делать с помощью Bluetooth. Протокол Bluetooth предусматривает передачу данных (синхронную или асинхронную) и передачу голоса. При этом устройства могут реализовывать только нужную им функциональность стандарта. Протокол предусматривает возможность спросить у устройства, какие возможности в нем реализованы. В FreeBSD для этого используется утилита sdpcontrol.
Запустив sdpcontrol -a s55 browse мы получим подробный список сервисов, поддерживаемых телефоном. Palm ничего не отвечает на эту команду. Эксперементальным путем я выяснил, что Palm поддерживает только OPUSH сервис (передача файлов). Узнать подробности о интересующей нас службе можно набрав:

samm>~: sdpcontrol -a palm search OPUSH

Record Handle: 0x00010001
Service Class ID List:
OBEX Object Push (0x1105)
Protocol Descriptor List:
L2CAP (0x0100)
RFCOMM (0x0003)
Protocol specific parameter #1: u/int8/bool 1
OBEX (0x0008)

Передача файлов

Собственно, самое важное, что мне требовалось от Bluetooth - это получить возможность передавать данные от/к устройствам без использования кабелей. Для передачи файлов в мобильный устройствах стандартом де-факто стал протокол OBEX. Для работы с этим протоколом в FreeBSD существует программа obexapp(1), которая находится в дереве портов FreeBSD (/usr/ports/comms/obexapp). Протокол OBEX позволяет передавать файлы используя OPUSH - простая передача файла от одного устройства к другому и FTRN - полноценный доступ к файловой системе устройства (удаление, копирование, создание папок и так далее). Palm поддерживает только OPUSH протокол, S55 - как OPUSH так и
FTRN.

Доступ к FS мобильного телефона:

samm>~: obexapp -C FTRN -a s55 -f
obex> ls
Access Owner Group Size Modified Name
WD W n/a n/a n/a 01-Jan-02 00:00 Cache/
WD W n/a n/a n/a 01-Jan-02 00:00 PersistentData/
RWD W n/a n/a n/a 01-Jan-02 00:00 Animation/
RWD W n/a n/a n/a 01-Jan-02 00:00 Pictures/
RWD W n/a n/a n/a 01-Jan-02 00:00 Sounds/
RWD W n/a n/a n/a 01-Jan-02 00:00 Java/
RWD W n/a n/a n/a 01-Jan-03 00:03 Data objects/
WD W n/a n/a n/a 01-Jan-03 00:03 Address book/
WD W n/a n/a n/a 01-Jan-03 00:03 apo/
RWD W n/a n/a n/a 01-Jan-03 00:00 Internet/
WD W n/a n/a n/a 01-Jan-03 00:00 email/
RWD W n/a n/a n/a 07-Apr-04 16:45 Voice memo/
RWD W n/a n/a n/a 07-Apr-04 22:58 Text module/
RWD W n/a n/a n/a 07-Apr-04 23:02 Colour scheme/
RWD W n/a n/a n/a 11-Apr-04 10:13 Sms/
RWD W n/a n/a n/a 17-May-04 20:05 Misc/
Success, response: OK, Success (0x20)

Кроме того, OBEX резервирует некоторые имена файлов для специальных функций. Так, через файловые операции можно удалять/добавлять записи в телефонную книгу, календарь, просматривать параметры устройства и изменять системное время. Например, для того, чтобы получить из мобильника телефонный справочник (в формате vCard) следует использовать команду obexapp -n -a s55 -f -C ircom get "telecom/pb.vcf". Более подробная информация о использовании OBEX находится в man файле obexapp.

Для передачи файлов используя протокол OPUSH введем obexapp -C OPUSH -a palm -n PUT samm.txt после чего файл samm.txt будет передан на
Palm. Также вы можете настроить прием файлов по протоколу OPUSH на локальный PC используя возможности obexapp.

PPP доступ к PC для Palm PDA

Для того, чтобы тестировать интернет приложения Palm и синхронизироваться с PC (например, используя JPilot) я решил настроить Bluetooth PPP доступ. Для того, чтобы наш компьютер смог регистрировать локальные сервисы нам потребуется запустить демон sdpd (/usr/sbin/sdpd). Для его автозапуска я прописал запуск и остановку sdpd в файл rc.bluetooth.

Теперь займемся настройкой pppd. Для начала создадим запись для нашего соединения в файле /etc/ppp/ppp.conf:

rfcomm-server:
set timeout 0
set lqrperiod 10
enable lqr
accept lqr
# Do not use PPP authentication. Assume that
# Bluetooth connection was authenticated already
disable pap
deny pap
disable chap
deny chap
accept dns
set ifaddr 10.0.1.1 10.0.1.2

Теперь запустим Bluetooth ppp сервер

# /usr/sbin/rfcomm_pppd -s -C 1 -l rfcomm-server -u 1

Набрав

# sdpcontrol -l browse

мы должны увидеть наш PPP сервис.

Теперь, настроив Bluetooth PPP соединение в PDA, можно подключаться к сети. Для доступа в интернет следует настроить на PC NAT или Proxy.
Для синхронизации - выбираем в Palm network sync, адрес хоста (10.0.1.1 в нашем примере). На PC прописываем в Jpilot устройство net:any и выбираем синхронизацию. После этого выбираем sync на palm.
Должна начаться синхронизация.

Доступ к модему телефона и выход в интернет GPRS

В большинстве телефонов встроен модем, поддерживающий как стандартный набор AT команд, так и расширенный синтаксис. Это позволяет звонить с телефона, использовать GPRS интернет, отсылать SMS, синхронизировать время и данные. Для доступа к серийному порту Bluetooth FreeBSD содержит программу rfcomm_sppd(1). Запуск rfcomm_sppd -a s55 -t /dev/ttypf позволит использовать устройство ttypf как обычный серийный порт. Например:

samm>~: sudo cu -l /dev/ttypf
Connected
at
OK
atdp02
NO CARRIER

При этом вы можете использовать программы, работающие с телефоном через COM шнурок (например - scmxx, /usr/ports/comm/scmxx) указав
вместо com порта назначенное устройство. Также существует возможность использовать GPRS интернет (конечно, если ваш провайдер это
позволяет). Для выхода в интернет используется утилита rfcomm_pppd(8). Ниже я опишу настройки для выхода в интернет используя Kyivstar GPRS (корпоративный пакет).

Для начала создадим запись для нашего соединения в файле /etc/ppp/ppp.conf

rfcomm-dialup:
enable force-scripts
# force dial script execution
set dial "ABORT BUSY ""
ATE1 OK AT+CGDCONT=1,\"IP\",\"www.kyivstar.net\" OK
ATD*99***1# CONNECT"
# set kyivstar APN in dial script
enable dns # if you're on local network and don't like ppp overwriting your
# resolv.conf every time you connect, comment this out
set authname igprs
set authkey internet
set ifaddr 0 0 255.255.255.0
add default HISADDR

Теперь пропишем в /etc/resolv.conf строку nameserver 0.0.0.0 (без этого kyivstar не хотел назначать DNS) и попытаемся установить соединение:

# rfcomm_pppd -a s55 -c -C dun -l rfcomm-dialup
# ping -c 3 193.193.193.100
PING 193.193.193.100 (193.193.193.100): 56 data bytes
64 bytes from 193.193.193.100: icmp_seq=1 ttl=56 time=1176.167 ms
64 bytes from 193.193.193.100: icmp_seq=2 ttl=56 time=683.977 ms
64 bytes from 193.193.193.100: icmp_seq=3 ttl=56 time=624.890 ms

Для того, чтобы завершить соединение достаточно убить процесс rfcomm_pppd. Замечу, что качество соединения у компании kyivstar невысокое, IP - серый, а цена трафика - огромна, так что данной услугой имеет смысл пользоваться только там, где недоступны другие способы выхода в сеть.

В завершение

Насколько мне известно, в настоящий момент в FreeBSD не реализована возможность использования Bluetooth гарнитуры как dsp устройства (хотя работы ведутся). Недавно данная возможность была реализована как драйвер для ALSA Linux. В данный момент у меня нет гарнитуры для экспериментов. Возможно, я приобрету это устройство, так как возможность общения в Skype используя BT гарнитуру мне кажется интересной идеей. Буду рад любым советам и дополнениям.

Обновлено: 12.03.2015