В статье Профиль HID и протокол L2CAP были описаны различия в подходе к реализации HID для разных стеков. Здесь я в двух словах опишу попытку реализации применительно к стеку Broadcom и дам ссылку на проект для его изучения.
Когда у меня был легендарный HP iPAQ 4700, я наивный думал, что все девайсы имеют один и тот же bluetooth стек, а именно Broadcom, по этому начал реализовывать идею, основываясь на нем.
Первая трудность, с которой я столкнулся, заключалась в подготовке SDP записи. Broadcom предоставляет класс CSdpService, используемый на стороне сервера, а мышь — это сервер :), для создания и управления сервисными записями. Я создал класс всего с одной функцией:
cpp |copy code |?
1 2 #pragma once3 #include "btifclasses.h"4 class CHIDMouseSDPRecord : public CSdpService5 {6 public: CHIDMouseSDPRecord(void);7 ~CHIDMouseSDPRecord(void);8 BOOL CreateRecord(CString m_service_name, GUID *p_service_guid);9 };
А вот как сформировать имеющуюся сервисную запись, я не знал. После мук чтения документации по профилям и экспериментов, функция «CreateRecord» все-таки была написана. Когда Вы увидите код (а он без косметики), по комментариям Вы всё поймете :). Только не спрашивайте у меня, зачем я для этого делал отдельный класс и функцию создания записи, этот проект — ЭКСПЕРИМЕНТ. Забегая вперед хочу сказать, что сделать SDP запись для стека Microsoft гораздо проще.
Теперь пришла очередь разбираться с реализацией L2CAP. Как я уже писал, нам надо 2 канала PSM, а значит надо создать по 2 объекта CL2CapConn и CL2CapIf. Один для данных, другой для управления. Объект для данных я сделал в отдельном классе, а объект для прерываний просто внедрил в CDialog.
С L2CAP в части, касающейся HID, есть один ньюанс и его надо обязательно соблюдать, а именно, канал данных нельзя регистрировать, т.е. выполнять ф-ю CL2CapIf::Register() пока не произойдет соединение по каналу управления. Это написано в спецификации протокола HID.
Далее надо было создать структуру, которая содержала бы в себе передаваемые данные, т.н. Report.
cpp |copy code |?
01 02 struct TAG_InputReport03 {04 UCHAR L_btn : 1;05 UCHAR R_btn : 1;06 UCHAR M_Btn : 1;07 UCHAR NoUsage : 5;08 char X_axis;09 char Y_axis;10 };
Осталось только ловить перемещение стилуса по экрану девайса, формировать эту структуру и передавать ее в ф-ю Write() объекта CL2CapConn, того, который отвечает за передачу данных. Ловля перемещения стилуса производилась ф-й OnMouseMove класса CDialog.
Все заработало :), правда программа не учитывает то, что стилус может быть перемещен по воздуху, хотя она много чего не учитывает, главное, это реализована сама идея.
Да, для реализации нужен Broadcomm CE SDK.