Голубые зубы.
Feb. 15th, 2007 12:03 pm![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Bluetooth, если кто не в курсе, это такой стэк сетевых протоколов для взамодействия с помощью радиоволн между близко (до 15-20 метров) расположенными устройствами - телефонами, гарнитурами, компьютерами, наладонниками.
Документированность этого добра оставляет желать лучшего. Можно, конечно, зарегистрироваться на www.bluetooth.org и выкачать оттуда несколько тысяч страниц документации, можно прочитать от корки до корки исходники соответствующей подсистемы в ядре Linux (и то вряд ли что поможет. Видимо, для полного понимания нужно и то, и другое, а желательно и исходники прошивок какого-нибудь смартфона).
Поскольку у меня не было времени на столь углубленное изучение, все мои предыдущие попытки понять что такое Bluetooth и с чем его едят, напоиминали попытки представить слона по рассказам нескольких слепых, его ощупывавших. Дело в том, что времени на изучение этих мегабайт документации и кода не было не только у меня. А у тех, кто писал этот код, не было времени рассказать простыми словами о том, что они, собственно, сделали.
Но вот вчера в RU.UNIX пробежала ссылка на курсовую работу в МИТ, автор которой, похоже, документацию на протоколы действительно читал. Теперь я знаю что у слона есть не только что-то похожее на змею, что-то похожее на веер и что-то похожее на веревку, но и что-то похожее на колонны, и, вероятно именно это последнее служит для передвижения слона в пространстве.
Так что можно попробовать пересказать своими словами
Bluetooth это, как уже отмечалось, стэк сетевых протоколов. Любой стэк сетевых протоколов разработанный на Земле в конце XX - начале XXI века с неизбежностью будет нести на себе родовые пятна модели OSI и стэка TCP/IP. Так и здесь.
Любое устройство, умеющее работать с Bluetooth, имеет 48-битный уникальный адрес, нечто подобное MAC-адресу в ethernet.
Но вот аналога IP-адресов, которые отображаются в эти адреса тут нет. Bluetooth не предназначен для глобального рутинга, он более похож на микрософтовский стэк SMB-протоколов, он предназначен для работы с устройствами в пределах зоны радиовидимости, которые появляются и исчезают по собственной инициативе. Поэтому все на бродкастах. Устройствам можно назначить удобопонятные имена, но для того чтобы отрезолвить имя устройства нужно у устройства спросить "а как тебя зовут". Причем в отличие от ARP и WINS вопрос задается не "а кто тут имеет такое имя, скажите свой адрес", а "устройство с таким-то адресом, как тебя зовут".
Для того чтобы узнать адрес, посылается бродкаст "Эй, кто меня слышит, скажите свои адреса". Этот процесс называется discovery.
И на большинстве устройств его можно отключить. Если мы знаем адрес устройства, с которым хотим работать, отключенное на устройстве discovery нам совершенно не мешает. Но почему-то и автор вышеупомянутой курсовой работы, и, по-моему, разработчики стэка Bluez, входящего в официальное ядро Linux, проблемой поиска non-discoverable устройства (прогулки по списку уже известных компьютеру устройств) не озаботились. В текущей версии bluez есть файл /var/lib/bluetooth/<адрес адаптера>/names, но тута попадают не все устройства, с которыми мы устанавливаем соединения, а только те, у которых мы явным образом спросили имя.
Поскольку в радиусе радиовидимости могут оказаться устройства, принадлежащие совершенно разным людям, и совершенно не гарантировано что владелец одного из них хочет давать доступ владельцу другого, практически все виды взаимодействия, кроме
discovery и запроса имени, требуют авторизации.
Авторизация осуществляется по ключу симметричному соединения, который запоминается на обоих устройствах и соответствует паре bd-адресов. Процесс выработки этого ключа называетcz pairing. Для того чтобы он сработал, нужно на обоих устройствах ввести одинаковый PIN-код. Многие устройства, работающие с bluetooth, такие как беспроводные мыши, гарнитуры для мобильных телефонов и т.д. не имеют никаких интерфейсов для ввода PIN-кода, и поэтому для спаривания с ними используется жестко прошитый разработчиком устройства PIN-код (обычно четыре нуля).
Насколько мне известно, запрос на спаривание может сопровождаться неким дополнительным текстом. По крайней мере имя устройства туда точно передается.
Pairing - процесс небезопасный. Подслушав переговоры между устройствами в процессе pairing-а, можно определить PIN, хотя он и шифруется, по крайней мене если он меньше 64 бит. 64 бита это примерно 19 десятичных цифр. Никто не пользуется такими длинными PIN, и не все устройства позволяют их ввести. Если ваши устройства уже спарены а pairing вы провели в безопасном месте (в чистом поле, на расстоянии в несколько сотен метров от ближайшего человека), то не следует успокаиваться. Где-то я встречал, хотя сейчас сходу найти не могу, описание активной атаки, которая заставляет два уже спаренных устройства повторить процесс спаривания. Так что если устройства помнят не только link key, но и PIN-ы, их можно выкрасть. Правда, не факт, что это много даст атакующему. Ему ещё bd-адрес подделать придется, и дождаться чтобы настоящее устройство с этим bd-адресом было offline.
Upd: Нижеследующее про протоколы не соответствует истине. См в комментах
Все вышеперечисленные операции выполняются на самом низком уровне стэка протоколов Bluetooth - HCI, Host Controller Interface.
Как и все остальные уровни, в Linux этот уровень представлен как соответствующий тип сокетов.
Для ответов на вышеописанные низкоуровневые запросы в Linux используется демон hcid, который слушает на соответствующих сокетах и выдает ответы. Для того чтобы спросить у юзера PIN демон обращается к отдельной программе pin-хелперу. В старых версиях Bluez он просто вызывал эту программу, и ожидал, что она выдаст PIN на stdout, а уж как добраться до юзера и спросить - сама разберется. В более новых версиях для коммуникации между hcid и pin-хелпером используется DBUS (что это такое, я пока не разбирался).
В конфигурационном файле hcid задаются параметры безопасности - требуется ли обязательный pairing, спрашивать ли каждый раз PIN у юзера, шифровать ли соединение и т.д.
Существует утилита hcitool, которая позволяет посылать запросы на этом уровне протокола. Наиболее часто используемые её возможности:
hcitool scan - послать discovery запрос и выдать список всех discoverable устройств в зоне видимости
hcitool name bdaddr - спросить у устройства с указанным адресом его имя
hcitool con - получить список активных соединений
hcitool rssi bdaddr - посмотреть уровень сигнала, получаемого от указанного устройства
hcitool tpl bdaddr [type] посмотреть/изменить уровень передаваемого сигнала
bcitool lq bdaddr - показать качество связи с указанным устройством (не знаю что такое, надо экспериментировать).
На следующем уровне стэка протоколов используются протоколы RFCOMM, L2CAP, BNEP и SCO. Может быть я перечислил не все, но с прочими я пока не сталкивался.
RFCOMM - это аналог TCP - протокол с установлением соединения и гарантированной доставкой пакетов. Исходно он задуман для эмуляции RS232 (т.е. для коммуникации с модемами и GPS-ами), но может использоваться и просто как двусторонний канал связи. Например, через него работает OBEX - Object Exchange протокол, на котором мы еще остановимся.
L2CAP - это дейтаграммный протокол. Его можно рассматривать как аналог UDP, но на самом деле он умеет больше. В отличие от UDP в L2CAP предусмотрено подтверждение доставки сообщений и повторная передача (которые можно отключить).
BNEP - это Bluetooth Network encapsulation protocol. Можно сказать, что если RTCOMM это эмуляция последовательного порта, то BNEP - эмуляция Ethernet. Очень удобный способ создания маленькой беспроводной сети, если под рукой нет Wi-Fi оборудования, а Bluetooth оборудование есть. К сожалению, поддерживется не всеми наладонниками. Windows Mobile его умеет, а вот в Nokia 770 поддержку BNEP забыли вкомпилировать в ядро. Хотя pand - демон, управляющий BNEP-соединениями - положили. Во FreeBSD поддержки BNEP нет вовсе. Во всяком случае до 6.2. Про создание сети с помощью BNEP/PAN я уже писал.
SCO - это протокол для передачи звука. Используется гарнитурами для сотовых телефонов. Реализация для linux, позволяющая цеплять BT-гарнитуру вместо звуковой карты и использовать, например, в Skype существует
Протокол SDP
Если в TCP существует 65536 портов, и можно для определенных сервисов зарезервировать конкретные номера портов (например, 80 для http, 25 для SMTP и т.д.) то в RFCOMM есть всего 30 каналов (channels). Поэтому распределение каналов между конкретными прикладными протоколами (profiles) происходит динамически. Или во всяком случае - на каждом устройстве по своему.
Для того чтобы можно было определить, куда коннектиться для работы определеного сервиса, используется протокол SDP (Service Discovery Protocol). Командно-строчным клиентом к нему является утилита sdptool. Для sdp-запросов обычно требуется наличие pairing. Если Linux-машина предоставляет какие-то bluetooth-сервисы (не только RFCOMM, но и L2CAP и BNEP), должен быть запущен sdpd, и сервисы должны в нем себя регистрировать. Правильно написанный bluetooth-сервис это делает сам, используя соответствующее API из libbluetooth. Если в качестве bluetooth сервиса применяется что-то не умеющее регистрировать себя, например утилита obex_test из пакета openobex, то можно вручную зарегистрировать сервис с помощью sdptool.
Поиск сервиса осуществляется по 128-битному UUID. Bluetooth консорциум определил достаточноо большое количество прикладных протоколов (profiles) и зарезервировал за ними UUID (правда, по-моему, все они вполне умещаются в 16 бит).
sdptool знает буквенные сокращения для многих из этих профайлов (например DUN - dialup networking, OPUSH - object push etc), но можно использовать и числовые значаения.
Ответ от sdp-сервера приходит в виде ASN.1 структуры. Если вы считаете, что XML - неудобочитаемая бяка, молитесь, чтобы вам никогда в жизни не пришлось работать с ASN.1. Впрочем, разбирать ASN.1 данные самостоятельно при работе с SDP программисту вряд ли понадобится. libbluetooth содержит уже готовое (правда, достаточно замысловатое) API для разбора ответов от SDP-сервера, а sdptool делает всё что может, чтобы показать эти ответы в удобочитаемом виде.
Две основных команды, которые мне приходилось использовать в sdptool это
sdptool browse bdaddr - получить список всех сервисов с указанного устройства
sdptool search [ --bdaddr bdaddr] имя сериса - получить информацию о конкретном сервисе. Если bdaddr не указать, сервис будет искаться по всей округе (по всем discoverable устрофтвам).
Что удивительно, в sdptool не существует удобного способа посмотреть список локально зарегистрированных сервисов. Команда browse на локальный адрес не проходит. Оперировать с локальными service records можно только по их record handle, который назначается автоматически и команда sdptool add его не возвращает. Правда, опытным путем выяснено, что эти номера назначаются начиная с 0x10000 и можно перебором номеров их все получить. С локальным sdpd sdptool общается через unix-domain сокет /var/run/sdp
Upd Я - тормоз Матросова. Команда sdptool browse local описана на первом же экране man sdptool. А я проглядел
Сервисы на основе RFCOMM
Не претендуя на полноту перечисления, можно выделить три группы сервисов на основе RFCOMM - это эмуляция последовательного соединения, передача объектов и human interface devices (клавиатуры и мыши). Возможно, последние - частный сл
Эмуляция последовательного соединения это в первую очередь эмуляция PPP-соединения с локальной сетью. Почему-то для этого существуют целых два UUID-а - LAN и DUN (Dialup networking) Документация на dund - демон, принимающий эти соединения, как-то расходится с актуальной реализацией. (есть еще MROUTER - тоже из этой же серии). Но что касается клиентской части, то тут всё просто - c помощью sdptool serch DUN определяете, какой channel на вашем телефоне используется для Dialup networking и с помощью команды rfcomm bind связываете с определенным устройством из /dev/rfcommX этот канал. после этого работаете с этим устройством при помощи pppd как с обычным модемом (ну скорее всего, вы при этом будете использовать не команду ATDномер IP-шлюза провайдера, а команды работы с GPRS, но на самом деле можно и так и так). Можно даже прописать адрес телефона и номер канала в /etc/bluetooth/rfcomm.conf, с тем чтобы связывание файла в /dev с соответствующим устройством выполнялось при загрузки системы (в загрузочном скрипте утилита rfcomm вызывается с параметром bind all и ключиком, указывающим имя конфигурационного файла). Видимо, аналогичным способом следует поступать при работе с Bluetooth GPS, но я не пробовал, за неимением такового.
Еще частным случаем эмуляции последовательного порта является Microsoft ActiveSync. С ним также работает dund. Что представляютс собой профайлы SYNCML, HOTSYNC, PALMOS, NOKID, PCSUITE и APPLE - я не в курсе.
C human interface devices картина примерно такая же как с DUN. Есть демон hidd, который производит то взаимодействие, которое удобнее производить в userlevel. Единственное, что при подключении bluetooth клавиатуры к машине вам понадобится какой-нибудь другой способ ввода (ssh, обычная клавиатура, xvkbd) чтобы ввести PIN.
OBEX
Протокол OBEX вообще говоря, не является Bluetooth-специфичным. Он используется также и поверх инфракрасных соединений, и по последовательному кабелю, и даже поверх TCP. Правда, поверх TCP его используют редко - там обычно есть более удобные протоколы, тот же HTTP.
Возможности OBEX сравнимы с возможностями HTTP+WebDAV - можно лазить по некоей "файловой системе", получать оттуда объекты, помещать туда объекты, и вообще всячески ими манипулировать.
В мобильных телефонах протокол OBEX используется для передачи записей записной книжки, картинок, заметок и прочей полезной информации. Вплоть до того, что по OBEX можно загружать в телефон Java-программы (что гораздо удобнее, чем делать это через wap так как не надо платить денег провайдеру).
Существуют несколько разных profiles, через которые осуществляется работа по OBEX. Это примерно как несколько виртуальных HTTP-серверов на одной физической машине на разных портах.
На мой взгляд, интересны следующие профайлы:
OPUSH (0bject push) - позволяет передать какой-нибудь объект (контакт из записной книжки, Java-программу, картинку) и предоставить владельцу устройства-получателя решать что с этим объектом делать - сохранить его или выкинуть. На многих мобильных телефонах прием контакта по OPUSH не требует пэйринга. Это привело к возникновению новой разновидности спама bluejacking. Если у вас есть компьютер со встроенным или хотя бы систематически воткнутым туда Bluetooth адаптером, крайне полезно держать на нем OPUSH-сервер. Можно будет легко и непринужденно скидывать на него с телефона контакты, фотографии, диктофонные записи. К сожалению, хорошего и удобного OPUSH-сервера я не знаю. В Debian stable есть пакет obexserver, но его автор не разобрался с тем, что такое каналы RFCOMM и зачем нужен SDP, что сильно снижает его usability. Есть еще opd - он задуман гораздо лушче, но с 2003 года не менялся. Возможно что-то более лучшее есть в KDE или GNOME, но за отсутствием опыта работы с этими средами, ничего сказать не могу.
FTP (OBEX File transfer) - полный read-write доступ к файловой системе телефона. Из-за потенциальных рисков, с которыми это связано, некоторые телефоны, в частности мой Ericsson T610, ведут себя просто параноидально, запрашивая у пользователя подтверждения на каждовую файловую операцию. Если у вас такой телефон, то OBEX File Transfer для вас просто бесполезен, потому что работать с файловой системой телефона с компьютера удобно тогда, когда не надо пытаться давить кнопки на телефоне. Способа объяснить телефону, что устройство с вот этим bd-адресом имеет право вытворять с его файловой системой всё, что угодно, я не нашёл.
IrMC Synchornization (0x1104) - крайне удобный инструмент для синхронизации записной книжки, календаря и контактов. Использует ту же виртуальную файловую систему, что и синхронизация через IRDA (каталог telecom с файлами pb.vcf, notes.vnt etc). Для работы с этим профайлом я использую утилиту t68tool. К сожалению, сайт оригинального автора испарился из интернета, поэтому взять её можно только у меня в Debian-cosy. Надо бы в соответствии с вновь обретенным знанием дописать туда поиск номера канала через SDP и резолвинг имен устройств в адреса.
Кроме этого инструменты для работы с IrMC Sync есть и во всяких Desktop environments.
BIP (Basic Image Profile) - еще один OBEX-based протокол, заточенный под работу с картинками. Поскольку мой телефон его не поддерживает, с чем его едят - не знаю.
Вот в общем-то и всё, что я на данный момент знаю о Bluetooth и его использовании в Linux. Исправления и дополнения приветствуются.
Документированность этого добра оставляет желать лучшего. Можно, конечно, зарегистрироваться на www.bluetooth.org и выкачать оттуда несколько тысяч страниц документации, можно прочитать от корки до корки исходники соответствующей подсистемы в ядре Linux (и то вряд ли что поможет. Видимо, для полного понимания нужно и то, и другое, а желательно и исходники прошивок какого-нибудь смартфона).
Поскольку у меня не было времени на столь углубленное изучение, все мои предыдущие попытки понять что такое Bluetooth и с чем его едят, напоиминали попытки представить слона по рассказам нескольких слепых, его ощупывавших. Дело в том, что времени на изучение этих мегабайт документации и кода не было не только у меня. А у тех, кто писал этот код, не было времени рассказать простыми словами о том, что они, собственно, сделали.
Но вот вчера в RU.UNIX пробежала ссылка на курсовую работу в МИТ, автор которой, похоже, документацию на протоколы действительно читал. Теперь я знаю что у слона есть не только что-то похожее на змею, что-то похожее на веер и что-то похожее на веревку, но и что-то похожее на колонны, и, вероятно именно это последнее служит для передвижения слона в пространстве.
Так что можно попробовать пересказать своими словами
Bluetooth это, как уже отмечалось, стэк сетевых протоколов. Любой стэк сетевых протоколов разработанный на Земле в конце XX - начале XXI века с неизбежностью будет нести на себе родовые пятна модели OSI и стэка TCP/IP. Так и здесь.
Любое устройство, умеющее работать с Bluetooth, имеет 48-битный уникальный адрес, нечто подобное MAC-адресу в ethernet.
Но вот аналога IP-адресов, которые отображаются в эти адреса тут нет. Bluetooth не предназначен для глобального рутинга, он более похож на микрософтовский стэк SMB-протоколов, он предназначен для работы с устройствами в пределах зоны радиовидимости, которые появляются и исчезают по собственной инициативе. Поэтому все на бродкастах. Устройствам можно назначить удобопонятные имена, но для того чтобы отрезолвить имя устройства нужно у устройства спросить "а как тебя зовут". Причем в отличие от ARP и WINS вопрос задается не "а кто тут имеет такое имя, скажите свой адрес", а "устройство с таким-то адресом, как тебя зовут".
Для того чтобы узнать адрес, посылается бродкаст "Эй, кто меня слышит, скажите свои адреса". Этот процесс называется discovery.
И на большинстве устройств его можно отключить. Если мы знаем адрес устройства, с которым хотим работать, отключенное на устройстве discovery нам совершенно не мешает. Но почему-то и автор вышеупомянутой курсовой работы, и, по-моему, разработчики стэка Bluez, входящего в официальное ядро Linux, проблемой поиска non-discoverable устройства (прогулки по списку уже известных компьютеру устройств) не озаботились. В текущей версии bluez есть файл /var/lib/bluetooth/<адрес адаптера>/names, но тута попадают не все устройства, с которыми мы устанавливаем соединения, а только те, у которых мы явным образом спросили имя.
Поскольку в радиусе радиовидимости могут оказаться устройства, принадлежащие совершенно разным людям, и совершенно не гарантировано что владелец одного из них хочет давать доступ владельцу другого, практически все виды взаимодействия, кроме
discovery и запроса имени, требуют авторизации.
Авторизация осуществляется по ключу симметричному соединения, который запоминается на обоих устройствах и соответствует паре bd-адресов. Процесс выработки этого ключа называетcz pairing. Для того чтобы он сработал, нужно на обоих устройствах ввести одинаковый PIN-код. Многие устройства, работающие с bluetooth, такие как беспроводные мыши, гарнитуры для мобильных телефонов и т.д. не имеют никаких интерфейсов для ввода PIN-кода, и поэтому для спаривания с ними используется жестко прошитый разработчиком устройства PIN-код (обычно четыре нуля).
Насколько мне известно, запрос на спаривание может сопровождаться неким дополнительным текстом. По крайней мере имя устройства туда точно передается.
Pairing - процесс небезопасный. Подслушав переговоры между устройствами в процессе pairing-а, можно определить PIN, хотя он и шифруется, по крайней мене если он меньше 64 бит. 64 бита это примерно 19 десятичных цифр. Никто не пользуется такими длинными PIN, и не все устройства позволяют их ввести. Если ваши устройства уже спарены а pairing вы провели в безопасном месте (в чистом поле, на расстоянии в несколько сотен метров от ближайшего человека), то не следует успокаиваться. Где-то я встречал, хотя сейчас сходу найти не могу, описание активной атаки, которая заставляет два уже спаренных устройства повторить процесс спаривания. Так что если устройства помнят не только link key, но и PIN-ы, их можно выкрасть. Правда, не факт, что это много даст атакующему. Ему ещё bd-адрес подделать придется, и дождаться чтобы настоящее устройство с этим bd-адресом было offline.
Upd: Нижеследующее про протоколы не соответствует истине. См в комментах
Все вышеперечисленные операции выполняются на самом низком уровне стэка протоколов Bluetooth - HCI, Host Controller Interface.
Как и все остальные уровни, в Linux этот уровень представлен как соответствующий тип сокетов.
Для ответов на вышеописанные низкоуровневые запросы в Linux используется демон hcid, который слушает на соответствующих сокетах и выдает ответы. Для того чтобы спросить у юзера PIN демон обращается к отдельной программе pin-хелперу. В старых версиях Bluez он просто вызывал эту программу, и ожидал, что она выдаст PIN на stdout, а уж как добраться до юзера и спросить - сама разберется. В более новых версиях для коммуникации между hcid и pin-хелпером используется DBUS (что это такое, я пока не разбирался).
В конфигурационном файле hcid задаются параметры безопасности - требуется ли обязательный pairing, спрашивать ли каждый раз PIN у юзера, шифровать ли соединение и т.д.
Существует утилита hcitool, которая позволяет посылать запросы на этом уровне протокола. Наиболее часто используемые её возможности:
hcitool scan - послать discovery запрос и выдать список всех discoverable устройств в зоне видимости
hcitool name bdaddr - спросить у устройства с указанным адресом его имя
hcitool con - получить список активных соединений
hcitool rssi bdaddr - посмотреть уровень сигнала, получаемого от указанного устройства
hcitool tpl bdaddr [type] посмотреть/изменить уровень передаваемого сигнала
bcitool lq bdaddr - показать качество связи с указанным устройством (не знаю что такое, надо экспериментировать).
На следующем уровне стэка протоколов используются протоколы RFCOMM, L2CAP, BNEP и SCO. Может быть я перечислил не все, но с прочими я пока не сталкивался.
RFCOMM - это аналог TCP - протокол с установлением соединения и гарантированной доставкой пакетов. Исходно он задуман для эмуляции RS232 (т.е. для коммуникации с модемами и GPS-ами), но может использоваться и просто как двусторонний канал связи. Например, через него работает OBEX - Object Exchange протокол, на котором мы еще остановимся.
L2CAP - это дейтаграммный протокол. Его можно рассматривать как аналог UDP, но на самом деле он умеет больше. В отличие от UDP в L2CAP предусмотрено подтверждение доставки сообщений и повторная передача (которые можно отключить).
BNEP - это Bluetooth Network encapsulation protocol. Можно сказать, что если RTCOMM это эмуляция последовательного порта, то BNEP - эмуляция Ethernet. Очень удобный способ создания маленькой беспроводной сети, если под рукой нет Wi-Fi оборудования, а Bluetooth оборудование есть. К сожалению, поддерживется не всеми наладонниками. Windows Mobile его умеет, а вот в Nokia 770 поддержку BNEP забыли вкомпилировать в ядро. Хотя pand - демон, управляющий BNEP-соединениями - положили. Во FreeBSD поддержки BNEP нет вовсе. Во всяком случае до 6.2. Про создание сети с помощью BNEP/PAN я уже писал.
SCO - это протокол для передачи звука. Используется гарнитурами для сотовых телефонов. Реализация для linux, позволяющая цеплять BT-гарнитуру вместо звуковой карты и использовать, например, в Skype существует
Протокол SDP
Если в TCP существует 65536 портов, и можно для определенных сервисов зарезервировать конкретные номера портов (например, 80 для http, 25 для SMTP и т.д.) то в RFCOMM есть всего 30 каналов (channels). Поэтому распределение каналов между конкретными прикладными протоколами (profiles) происходит динамически. Или во всяком случае - на каждом устройстве по своему.
Для того чтобы можно было определить, куда коннектиться для работы определеного сервиса, используется протокол SDP (Service Discovery Protocol). Командно-строчным клиентом к нему является утилита sdptool. Для sdp-запросов обычно требуется наличие pairing. Если Linux-машина предоставляет какие-то bluetooth-сервисы (не только RFCOMM, но и L2CAP и BNEP), должен быть запущен sdpd, и сервисы должны в нем себя регистрировать. Правильно написанный bluetooth-сервис это делает сам, используя соответствующее API из libbluetooth. Если в качестве bluetooth сервиса применяется что-то не умеющее регистрировать себя, например утилита obex_test из пакета openobex, то можно вручную зарегистрировать сервис с помощью sdptool.
Поиск сервиса осуществляется по 128-битному UUID. Bluetooth консорциум определил достаточноо большое количество прикладных протоколов (profiles) и зарезервировал за ними UUID (правда, по-моему, все они вполне умещаются в 16 бит).
sdptool знает буквенные сокращения для многих из этих профайлов (например DUN - dialup networking, OPUSH - object push etc), но можно использовать и числовые значаения.
Ответ от sdp-сервера приходит в виде ASN.1 структуры. Если вы считаете, что XML - неудобочитаемая бяка, молитесь, чтобы вам никогда в жизни не пришлось работать с ASN.1. Впрочем, разбирать ASN.1 данные самостоятельно при работе с SDP программисту вряд ли понадобится. libbluetooth содержит уже готовое (правда, достаточно замысловатое) API для разбора ответов от SDP-сервера, а sdptool делает всё что может, чтобы показать эти ответы в удобочитаемом виде.
Две основных команды, которые мне приходилось использовать в sdptool это
sdptool browse bdaddr - получить список всех сервисов с указанного устройства
sdptool search [ --bdaddr bdaddr] имя сериса - получить информацию о конкретном сервисе. Если bdaddr не указать, сервис будет искаться по всей округе (по всем discoverable устрофтвам).
Что удивительно, в sdptool не существует удобного способа посмотреть список локально зарегистрированных сервисов. Команда browse на локальный адрес не проходит. Оперировать с локальными service records можно только по их record handle, который назначается автоматически и команда sdptool add его не возвращает. Правда, опытным путем выяснено, что эти номера назначаются начиная с 0x10000 и можно перебором номеров их все получить. С локальным sdpd sdptool общается через unix-domain сокет /var/run/sdp
Upd Я - тормоз Матросова. Команда sdptool browse local описана на первом же экране man sdptool. А я проглядел
Сервисы на основе RFCOMM
Не претендуя на полноту перечисления, можно выделить три группы сервисов на основе RFCOMM - это эмуляция последовательного соединения, передача объектов и human interface devices (клавиатуры и мыши). Возможно, последние - частный сл
Эмуляция последовательного соединения это в первую очередь эмуляция PPP-соединения с локальной сетью. Почему-то для этого существуют целых два UUID-а - LAN и DUN (Dialup networking) Документация на dund - демон, принимающий эти соединения, как-то расходится с актуальной реализацией. (есть еще MROUTER - тоже из этой же серии). Но что касается клиентской части, то тут всё просто - c помощью sdptool serch DUN определяете, какой channel на вашем телефоне используется для Dialup networking и с помощью команды rfcomm bind связываете с определенным устройством из /dev/rfcommX этот канал. после этого работаете с этим устройством при помощи pppd как с обычным модемом (ну скорее всего, вы при этом будете использовать не команду ATDномер IP-шлюза провайдера, а команды работы с GPRS, но на самом деле можно и так и так). Можно даже прописать адрес телефона и номер канала в /etc/bluetooth/rfcomm.conf, с тем чтобы связывание файла в /dev с соответствующим устройством выполнялось при загрузки системы (в загрузочном скрипте утилита rfcomm вызывается с параметром bind all и ключиком, указывающим имя конфигурационного файла). Видимо, аналогичным способом следует поступать при работе с Bluetooth GPS, но я не пробовал, за неимением такового.
Еще частным случаем эмуляции последовательного порта является Microsoft ActiveSync. С ним также работает dund. Что представляютс собой профайлы SYNCML, HOTSYNC, PALMOS, NOKID, PCSUITE и APPLE - я не в курсе.
C human interface devices картина примерно такая же как с DUN. Есть демон hidd, который производит то взаимодействие, которое удобнее производить в userlevel. Единственное, что при подключении bluetooth клавиатуры к машине вам понадобится какой-нибудь другой способ ввода (ssh, обычная клавиатура, xvkbd) чтобы ввести PIN.
OBEX
Протокол OBEX вообще говоря, не является Bluetooth-специфичным. Он используется также и поверх инфракрасных соединений, и по последовательному кабелю, и даже поверх TCP. Правда, поверх TCP его используют редко - там обычно есть более удобные протоколы, тот же HTTP.
Возможности OBEX сравнимы с возможностями HTTP+WebDAV - можно лазить по некоей "файловой системе", получать оттуда объекты, помещать туда объекты, и вообще всячески ими манипулировать.
В мобильных телефонах протокол OBEX используется для передачи записей записной книжки, картинок, заметок и прочей полезной информации. Вплоть до того, что по OBEX можно загружать в телефон Java-программы (что гораздо удобнее, чем делать это через wap так как не надо платить денег провайдеру).
Существуют несколько разных profiles, через которые осуществляется работа по OBEX. Это примерно как несколько виртуальных HTTP-серверов на одной физической машине на разных портах.
На мой взгляд, интересны следующие профайлы:
OPUSH (0bject push) - позволяет передать какой-нибудь объект (контакт из записной книжки, Java-программу, картинку) и предоставить владельцу устройства-получателя решать что с этим объектом делать - сохранить его или выкинуть. На многих мобильных телефонах прием контакта по OPUSH не требует пэйринга. Это привело к возникновению новой разновидности спама bluejacking. Если у вас есть компьютер со встроенным или хотя бы систематически воткнутым туда Bluetooth адаптером, крайне полезно держать на нем OPUSH-сервер. Можно будет легко и непринужденно скидывать на него с телефона контакты, фотографии, диктофонные записи. К сожалению, хорошего и удобного OPUSH-сервера я не знаю. В Debian stable есть пакет obexserver, но его автор не разобрался с тем, что такое каналы RFCOMM и зачем нужен SDP, что сильно снижает его usability. Есть еще opd - он задуман гораздо лушче, но с 2003 года не менялся. Возможно что-то более лучшее есть в KDE или GNOME, но за отсутствием опыта работы с этими средами, ничего сказать не могу.
FTP (OBEX File transfer) - полный read-write доступ к файловой системе телефона. Из-за потенциальных рисков, с которыми это связано, некоторые телефоны, в частности мой Ericsson T610, ведут себя просто параноидально, запрашивая у пользователя подтверждения на каждовую файловую операцию. Если у вас такой телефон, то OBEX File Transfer для вас просто бесполезен, потому что работать с файловой системой телефона с компьютера удобно тогда, когда не надо пытаться давить кнопки на телефоне. Способа объяснить телефону, что устройство с вот этим bd-адресом имеет право вытворять с его файловой системой всё, что угодно, я не нашёл.
IrMC Synchornization (0x1104) - крайне удобный инструмент для синхронизации записной книжки, календаря и контактов. Использует ту же виртуальную файловую систему, что и синхронизация через IRDA (каталог telecom с файлами pb.vcf, notes.vnt etc). Для работы с этим профайлом я использую утилиту t68tool. К сожалению, сайт оригинального автора испарился из интернета, поэтому взять её можно только у меня в Debian-cosy. Надо бы в соответствии с вновь обретенным знанием дописать туда поиск номера канала через SDP и резолвинг имен устройств в адреса.
Кроме этого инструменты для работы с IrMC Sync есть и во всяких Desktop environments.
BIP (Basic Image Profile) - еще один OBEX-based протокол, заточенный под работу с картинками. Поскольку мой телефон его не поддерживает, с чем его едят - не знаю.
Вот в общем-то и всё, что я на данный момент знаю о Bluetooth и его использовании в Linux. Исправления и дополнения приветствуются.
no subject
Date: 2007-02-15 12:33 pm (UTC)no subject
Date: 2007-02-15 12:36 pm (UTC)no subject
Date: 2007-02-15 12:44 pm (UTC)(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:no subject
Date: 2007-02-15 12:44 pm (UTC)no subject
Date: 2007-02-15 12:58 pm (UTC)no subject
Date: 2007-02-15 01:08 pm (UTC)no subject
Date: 2007-02-15 01:31 pm (UTC)no subject
Date: 2007-02-15 02:00 pm (UTC)Нормальной реализации aligned/unaligned PER encoding я еще не видел.
PS Открытой. Реализация от Objective вполне вменяема, но компилятор закрыт.
PPS Сам два раза пытался -- проект был свернут за отсутствием финансирования.
no subject
Date: 2007-02-15 02:45 pm (UTC)но хотя до хмл в этом смысле ему далеко
no subject
Date: 2007-02-15 12:59 pm (UTC)no subject
Date: 2007-02-15 01:08 pm (UTC)no subject
Date: 2007-02-15 01:28 pm (UTC)no subject
Date: 2007-02-15 02:48 pm (UTC)Практической пользы от OSI - мало (никакой?). Но ИМХО это довольно удобная линейка, по которой можно указываеть положение того или иного протокола-интерфейса - даже не в OSIшном стеке.
no subject
Date: 2007-02-15 01:14 pm (UTC)no subject
Date: 2007-02-15 01:46 pm (UTC)(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:no subject
Date: 2007-02-15 01:27 pm (UTC)что совершенно не мешает организиции сети
no subject
Date: 2007-02-15 01:33 pm (UTC)no subject
Date: 2007-02-15 01:36 pm (UTC)Осмелюсь внести свой камент. Самый низкий уровень стэка Bluetooth - это IEEE 802.15.1 (или 15.3, забыл). HCI - это всего лишь стандарт производителей контроллеров, который позволяет написать один драйвер для всех чипов. Аналоги этой практики - UHCI, OHCI и EHCI в USB, и AHCI - в SATA, (есть ещё похожее в Fireware).
L2CAP - представляет собой не дейтаграммный протокол, а нечто очень похожее (может даже подмножество) HDLC. Аналоги его в других протоколах: IrLAP в IrDA, LAP-B в X.25, V.42bis (LAP-M) - в модемах. Он осуществляет нарезку на фреймы и контроль ошибок с подтверждением и selective reject'ом. Он скорее на TCP похож, но опять-таки сравнение не лепо.
На самом деле по своей структуре Bluetooth больше похож на IrDA. И между их протоколами есть прямое соответствие. SDP <-> IAS (IrLMP), RFCOMM <-> IrCOM, OBEX - вообще одинаков, ну и т.д.
no subject
Date: 2007-02-15 01:44 pm (UTC)К сожалению, со стеком протоколов IrDA я знаком достаточно слабо, его Linux-реализация документирована не сильно лучше, чем реализация стека Bluetooth. Я даже не знаю что в случае IrDA сокетов в connect в качестве адреса передается (и, соответственно, что по этому поводу должен возвращать аналог SDP).
(no subject)
From:no subject
Date: 2007-02-15 05:04 pm (UTC)Кстати, в 3.9 функционал sdpd опционально запихали в hcid зачем-то.
no subject
Date: 2007-02-15 06:03 pm (UTC)А вот про kbtobexsrv хотелось бы узнать поподробнее. Насколько там продуманный интерфейс и всё такое.
(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:no subject
Date: 2007-02-16 08:23 am (UTC)no subject
Date: 2007-02-16 12:31 pm (UTC)Которые быстрые/простые и при этом opensource?
(no subject)
From:(no subject)
From:no subject
Date: 2007-02-16 02:04 pm (UTC)Напоминает печатную машинку с акцентом из "Золотого теленка".
no subject
Date: 2007-02-17 02:31 pm (UTC)Да, полный стандарт выглядит страшно (1200 страниц + отдельные описания клиентских протоколов), но большая его часть посвящена радио, и простому человеку (в смысле тому, кто не занимается проектированием аппаратной части) не нужна. Разработчику BT драйверов/стека нужны только HCI, ACL и SCO - а это уже сильно меньше текста (~200-300 страниц). Клиентские протоколы достаточно просты (HID - он и в BT HID; L2CAP - достаточно похож на TCP, а RFCOMM с некоторой долей абстрации можно представить, как COM-порт).
А по тексту полно неточностей и складывания апельсинов с ящиками. Например, упоминание через запятую RFCOMM и SCO - неуместно - это разные уровни. Дэйтаграммный протокол - это как раз SCO. В большинстве мест, где по тексту упоминается L2CAP - на самом деле, речь идет про ACL. Звук, в зависимости от клиентского протокола, может передаваться как через ACL, так и через SCO (A2DP (aka Bluetooth Hi-fi audio), например, передается over L2CAP (в свою очередь, over ACL)). И т.д.
Если интересно, я могу пройтись по тексту подробно, и перечислить что не так, заодно рассказать, что вспомню из своих экспериментов. (А что не вспомню - уточнить из описаний).
И еще. Я года полтора назад залезал в bluez, и он мне очень не понравился по реализации. После netgraph реализации во фряхе, он смотрелся просто страшненько.
no subject
Date: 2007-02-17 02:53 pm (UTC)Если интересно, я могу пройтись по тексту подробно, и перечислить что не так, заодно рассказать, что вспомню из своих экспериментов. (А что не вспомню - уточнить из описаний).
Было бы полезно. В идеале хотелось бы получить нечто вроде кирховской "Network Administrator Guide" - руководства не столько для программистов, сколько для пользователей - несколько страниц на общую концепцию как и что устроено, страниц двадцать про существующие примения (с описанием явных глюков распространенных приложений и гаджетов - а их хвататет, этих глюков) и глава про то, как на этом правильно программировать. Объемом примерно с ту хаутушку, на которую я ссылался но без её ляпов.
(no subject)
From:(no subject)
From:(no subject)
From: