25. void setup()
{
Serial.begin(115200);
Bluefruit.begin(0, 1);
Bluefruit.setTxPower(4); // Check bluefruit.h for supported values
Bluefruit.setName("Bluefruit52");
// Start Central Scan
Bluefruit.setConnLedInterval(250);
Bluefruit.Scanner.setRxCallback(scan_callback);
Bluefruit.Scanner.start(0);
}
void scan_callback(ble_gap_evt_adv_report_t* report)
{
Serial.println("Timestamp Addr Rssi Data");
Serial.printf("%09d ", millis());
// MAC is in little endian --> print reverse
Serial.printBufferReverse(report->peer_addr.addr, 6, ':');
Serial.printBuffer(report->data.p_data, report->data.len, '-');
Serial.println();
if ( Bluefruit.Scanner.checkReportForUuid(report, UUID16_SVC_HUMAN_INTERFACE_DEVICE) )
{
Serial.println(" BLE HID service detected");
}
Bluefruit.Scanner.resume();
}
void loop()
{
// nothing to do
}
26.
27.
28. 1. BLE 스캔을 하여 광고중인 키보드 검색 및 페어링
2. 페어링 이후 Boot 모드로 키보드 연결
3. 키보드로 advertising(광고)을 하여 아이폰과 키보드로 연결 시도
4. 아이폰과 연결이 되면 키보드에서 오는 report를 아이폰으로 전달
5. 키보드와 블루투스 연결이 끊기면 아이폰과의 연결도 끊음
6. 아이폰과 연결만 끊기면 다시 BLE 키보드로 광고 시작
29. Boot 모드에서는 8바이트의 고정 길이의 report가 전달된다
typedef struct TU_ATTR_PACKED
{
uint8_t modifier; /**< Keyboard modifier (KEYBOARD_MODIFIER_* masks). */
uint8_t reserved; /**< Reserved for OEM use, always set to 0. */
uint8_t keycode[6]; /**< Key codes of the currently pressed keys. */
} hid_keyboard_report_t;
32. a 0x04 0x00 0x00 0x00 0x00 0x00
a b 0x04 0x05 0x00 0x00 0x00 0x00
a b c 0x04 0x05 0x06 0x00 0x00 0x00
a b 0x04 0x05 0x00 0x00 0x00 0x00
a 0x04 0x00 0x00 0x00 0x00 0x00
0x00 0x00 0x00 0x00 0x00 0x00
33. 세벌식을 두벌식으로 바꾸는 것이 1:1 대응 불가
동시에 키 세 개를 누르는 경우 중복 자음 입력 안 됨
‘ㄴ’ ‘ㅡ’ ‘ㄴ’
초성이 종성으로 들어가 쌍자음 조합 안 됨
‘느끼다’ ‘늑기다’
34. 1. 세벌식 초성, 중성, 종성의 위치의 키를 나타내는 키코드를 찾아 냄
2. 두벌식에 대응하는 키코드로 대응하는 키코드로 1:1 대응 테이블 작성
3. 쉬프트 키를 눌러서 입력을 하였지만 두벌식에서는 쉬프트 키를 누르지 않고 입력하는
경우가 있어 이를 구분하기 위한 플래그 설정
4. ‘ᆻ’처럼 세벌식에서는 쉬프트키를 누르지 않고 입력할 수 있지만 두벌식에서는 쉬프트
키를 눌러야 입력이 가능한 경우가 있어 이를 위한 플래그 설정
5. 하나의 키로 두 개의 키코드를 생성하는 경우. ‘ㅢ'와 같은 복모음이나 ‘ᆰ’, ‘ᆹ’ 같은
종성을 위해 키코드를 두 개를 전달하기 위한 데이터 구조 설계
6. 직전에 입력한 키가 중성/종성이고 지금 입력하려는 키가 초성이면 한글 조합을
중지하도록 하여 현재 키가 초성으로 입력되도록 플래그를 설정
핵심
41. ESP32 시스템(WiFi / BLE / Classic BT)
• 기존 아두이노 시스템과 많이 다르며 필요한 예제 부족
• ESP-IDF 예제는 클래식 블루투스 HID 지원 부족
• 결국 BTstack 이라는 독자적인 블루투스 스택 선택
42. 1. 클래식 블루투스의 HID host 초기화
2. Hid keyboard 서비스 탐색 스캔(host 가 시작)
3. 스캔에서 발견한 키보드와 Report 모드로 연결/페어링 진행
4. 키보드에서 HID Descriptor가 오면 연결 과정 종료
5. 키보드 연결 성공 후 ESP32를 BLE 키보드로 광고 시작
6. 아이폰과 BLE키보드로 연결된 후 키보드에서 오는 report를 아이폰으로 전달
7. 아이폰과 연결이 끊겨도 키보드와 연결을 유지하고 그대로 대기함
47. 그런데 말입니다…
1. 문제없이 잘 될 것으로 예상했지만 페어링이 끝나고 HID descriptor를
받아오는 중에 연결이 종료가 됨
2. HID host 초기화 옵션을 바꿔보고 BLE 초기화를 먼저 하거나 온갖 조합을
시도하였으나 연결에 실패…
3. 결국 BTstack의 소스 코드를 한 줄 한 줄 읽기 시작. 리모트 디버깅을 하려면
추가 하드웨어가 필요해서 포기. 로그 위치와 코드를 추정해서 무슨 일이
일어났는지 코드를 쫓아 다니면서 읽었습니다
48. 결국, 한 줄 고쳐서 애플 매직 키보드 문제는 해결했습니다.
HID_PROTOCOL_MODE_REPORT_WITH_FALLBACK_TO_BOOT
키보드 연결 시 REPORT 모드로 시도를 하고 실패하면 BOOT 모드로 연결하는 옵션
BTstack의 경우 애플 매직 키보드에서 페어링이 끝나고 연결 과정 중에 에러를 발생
이 옵션을 HID_PROTOCOL_MODE_REPORT 로 변경하니 정상적으로 연결 완료
그런데 또 다른 문제가 발생. 애플 페어링 문제 디버깅 때문에 기존 페어링 기록을 초기화
기계식 블루투스 키보드 bonding 정보가 지운 후 다시 페어링을 하니 Pin code 입력
없이 페어링이 되지 않고 Pin code 입력을 요구하는 것을 발견. 클래식 블루투스 2.1
이전 페어링 스펙을 사용
51. • 조용히 참고 살던 세벌식 사용자들의 엄청난 관심과 개발에 대한 지지
• 완성되면 꼭 갖고 싶다던 사람, 상품화를 해달라는 사람들
• 하지만 과연 이 물건을 필요로 하는 세벌식 사용자가 얼마나 될까요?
• 애플이 사용자 키보드를 추가할 수 있도록 해주면 되는 일
• 언제까지나 세벌식 키보드를 계속해서 업그레이드를 하며 살아야
할까요? 차라리 오픈소스로 공개하는 것이 더 낫지 않을까 생각을
했지만 쉽게 결정할 문제가 아니었습니다
52. 키보드와 스마트폰을 동시에 연결한다는 것은 악용될 가능성 높음
보안툴을 우회하여 게임 매크로에 사용되는 사례가 있음
키보드 변환기에 키 매크로나 레코더 등의 기능을 덧붙여 확장도 가능
예) 스마트 키 릴레이를 통한 차량 도난 사례
54. § 막연히 블루투스 키보드가 간단한 구조를 가지고 있을 것이라 생각하고 시작
§ 아두이노 프로그래밍만으로 블루투스 프로그래밍이 가능하다고 믿음
§ 블루투스 표준이 파편화로 여러 프로토콜을 동시에 지원해야 함
§ 블루투스 키보드의 구현이 제각각이라 주된 기능이 아닌 것에 버그가 있음
§ 블루투스 기기도 스펙에 따라 페어링 과정에서 다른 동작을 함
§ 아이폰/아이패드가 외장형 키보드를 크게 고려한 시스템이 아님
§ 블루투스 키보드가 절전 모드에서 깨어나 재접속을 할 때도 생각해야 함
Wrap up