├── README.md
├── _config.yml
├── electroniccats_.7z
├── google561d16a79c30cdcf.html
├── image
├── .gitkeep
├── WCHISPTool.png
├── ali1.png
├── ali2.png
├── board.png
├── ch592f.png
├── ch592fpinlayout.png
├── ch59xx.png
├── fakeshield.png
├── soumu.png
└── vsnano.png
├── install.md
├── libraries
└── xxx
│ └── examples
│ └── ,gitkeep
├── misc
├── .gitkeep
├── CH592Fピンレイアウト.ods
├── CH592Fピンレイアウト.pdf
└── CH592Fボード.png
├── review.md
├── sample.md
└── sample
├── .gitkeep
├── WCHISPTool
├── .gitkeep
├── CH592F.INI
├── WCH55xISPDLL.dll
├── WCHISPTool_CH57x-59x.exe
├── download.bat
└── led_fade_internal.ino.bin
├── test_ch592f_ble_hid_keyboard
├── .gitkeep
├── IMG_0712.png
├── battservice.c
├── battservice.h
├── devinfoservice.c
├── devinfoservice.h
├── hiddev.c
├── hiddev.h
├── hidkbd.c
├── hidkbd.h
├── hidkbdservice.c
├── hidkbdservice.h
├── scanparamservice.c
├── scanparamservice.h
└── test_ch592f_ble_hid_keyboard.ino
├── test_ch592f_ble_hid_keyboard_org
├── .gitkeep
├── battservice.c
├── battservice.h
├── devinfoservice.c
├── devinfoservice.h
├── hiddev.c
├── hiddev.h
├── hidkbd.c
├── hidkbd.h
├── hidkbdservice.c
├── hidkbdservice.h
├── scanparamservice.c
├── scanparamservice.h
└── test_ch592f_ble_hid_keyboard_org.ino
├── test_ch592f_button
├── .gitkeep
└── test_ch592f_button.ino
├── test_ch592f_button2
├── .gitkeep
├── IMG_0712.png
└── test_ch592f_button2.ino
└── test_ch592f_serial
├── .gitkeep
├── IMG_0713.png
└── test_ch592f_serial.ino
/README.md:
--------------------------------------------------------------------------------
1 | # WCH CH592F for Arduino IDE
2 |
3 | ### 詳しくは [**GitHub**](https://github.com/PEARLPALMS/Arduino-CH592F) ページへ
4 |
5 | CH592F 用の Arduino IDE 実装ですが、実物を持ってませんので、開発環境を作っただけです(その後入手しました)。
6 | 以下の場所に CH58x 用の実装がありますので、それに上書きする形でインストールします。
7 | > [https://github.com/ElectronicCats/arduino-wch58x](https://github.com/ElectronicCats/arduino-wch58x)
8 |
9 | 動作確認は Lチカ までしか行っておりません。
10 | 詳しいインストールは、別ページにまとめました。
11 |
12 | > [インストールからLチカまで](install.md)
13 |
14 | モノは AliExpress などで購入できますが、技適の問題もありますので、取り扱いにはご注意ください。
15 | 2023年12月現在、230円~250円程度で販売されています。
16 | 詳しいレビューは、別ページにまとめました。
17 |
18 | > [レビューページ](review.md)
19 |
20 |
21 |
22 |
23 | # 実際に使えるの?
24 |
25 | 幾つかプログラムを作成して、どのような動作をするか実験してみました。
26 |
27 | > [サンプルプログラム](sample.md)
28 |
29 |
30 |
31 | # 概要 (Google翻訳) [原文](https://www.wch-ic.com/products/CH592.html)
32 | CH592 は、BLE ワイヤレス通信を統合した RISC-V MCU マイクロコントローラーです。2Mbps BLE通信モジュール、フルスピードUSBホストおよびデバイスコントローラおよびトランシーバ、セグメントLCDドライバモジュール、SPI、4つのシリアルポート、12チャネルADC、タッチキー検出モジュールおよびその他の豊富な周辺リソースをオンチップ統合。
33 |
34 |
35 | # システムブロック図
36 |
37 |
38 |
39 | # 特徴
40 | ・ QingKe 32 ビット RISC-V4C コア
41 | ・ RV32IMAC 命令セットおよび自己拡張命令をサポート
42 | ・ 26KB SRAM、512KB フラッシュ、ICP、ISP、IAP をサポート、OTA ワイヤレス アップグレードをサポート
43 | ・ 内蔵2.4GHz RFトランシーバー、ベースバンドおよびリンク制御、BLE5.4をサポート
44 | ・ 2Mbps、1Mbpsをサポート
45 | ・ -95dBm RX 感度、プログラム可能な +4.5dBm TX パワー
46 | ・ 最適化されたプロトコルスタックとアプリケーション層APIを提供し、ネットワーキングをサポート
47 | ・ 内蔵温度センサー(TS)
48 | ・ 内蔵RTC、タイミングとトリガの2つのモードをサポート
49 | ・ USB2.0フルスピードホスト/デバイス
50 | ・ 12チャンネルタッチキー
51 | ・ 12チャンネル12ビットADC
52 | ・ 4 UART、1 SPI、12 チャネル PWM、1 チャネル I2C
53 | ・ セグメントLCDドライバーインターフェイス。80 ポイント (20*4) LCD パネルをサポート
54 | ・ 24 GPIO、そのうち 4 つは 5V 信号入力をサポート
55 | ・ 最小サポート 1.7V 電源電圧
56 | ・ 内蔵のAES-128暗号化および復号化、固有のチップID
57 | ・ パッケージ: QFN32、QFN28
58 |
59 |
60 | # セレクションガイド
61 |
62 |
63 |
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | plugins:
2 | - jekyll-sitemap
3 |
--------------------------------------------------------------------------------
/electroniccats_.7z:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PEARLPALMS/Arduino-CH592F/b9ea2b5ecd53673252ccbe5e307a02ed8d93274f/electroniccats_.7z
--------------------------------------------------------------------------------
/google561d16a79c30cdcf.html:
--------------------------------------------------------------------------------
1 | google-site-verification: google561d16a79c30cdcf.html
--------------------------------------------------------------------------------
/image/.gitkeep:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/image/WCHISPTool.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PEARLPALMS/Arduino-CH592F/b9ea2b5ecd53673252ccbe5e307a02ed8d93274f/image/WCHISPTool.png
--------------------------------------------------------------------------------
/image/ali1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PEARLPALMS/Arduino-CH592F/b9ea2b5ecd53673252ccbe5e307a02ed8d93274f/image/ali1.png
--------------------------------------------------------------------------------
/image/ali2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PEARLPALMS/Arduino-CH592F/b9ea2b5ecd53673252ccbe5e307a02ed8d93274f/image/ali2.png
--------------------------------------------------------------------------------
/image/board.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PEARLPALMS/Arduino-CH592F/b9ea2b5ecd53673252ccbe5e307a02ed8d93274f/image/board.png
--------------------------------------------------------------------------------
/image/ch592f.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PEARLPALMS/Arduino-CH592F/b9ea2b5ecd53673252ccbe5e307a02ed8d93274f/image/ch592f.png
--------------------------------------------------------------------------------
/image/ch592fpinlayout.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PEARLPALMS/Arduino-CH592F/b9ea2b5ecd53673252ccbe5e307a02ed8d93274f/image/ch592fpinlayout.png
--------------------------------------------------------------------------------
/image/ch59xx.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PEARLPALMS/Arduino-CH592F/b9ea2b5ecd53673252ccbe5e307a02ed8d93274f/image/ch59xx.png
--------------------------------------------------------------------------------
/image/fakeshield.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PEARLPALMS/Arduino-CH592F/b9ea2b5ecd53673252ccbe5e307a02ed8d93274f/image/fakeshield.png
--------------------------------------------------------------------------------
/image/soumu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PEARLPALMS/Arduino-CH592F/b9ea2b5ecd53673252ccbe5e307a02ed8d93274f/image/soumu.png
--------------------------------------------------------------------------------
/image/vsnano.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PEARLPALMS/Arduino-CH592F/b9ea2b5ecd53673252ccbe5e307a02ed8d93274f/image/vsnano.png
--------------------------------------------------------------------------------
/install.md:
--------------------------------------------------------------------------------
1 | # Arduino IDE 環境作成
2 |
3 | まず CH58x の実装を作成されている方がいらっしゃいますので、そちらをインストールします。
4 | > [https://github.com/ElectronicCats/arduino-wch58x](https://github.com/ElectronicCats/arduino-wch58x)
5 |
6 | 実際は、ボードの URL を追加してパッケージをインストールする方法になりますので、詳しい方法が書かれています。
7 | > [https://github.com/ElectronicCats/arduino-wch58x/wiki/1.-First-steps-with-Arduino](https://github.com/ElectronicCats/arduino-wch58x/wiki/1.-First-steps-with-Arduino)
8 |
9 | ここまでで、CH58x が動作すると思われます。
10 |
11 |
12 | # CH592F 用ファイルを上書きインストール
13 |
14 | 以下のファイルをダウンロードし、CH58x 環境に上書きします。
15 | > [https://pearlpalms.github.io/Arduino-CH592F/electroniccats_.7z](https://pearlpalms.github.io/Arduino-CH592F/electroniccats_.7z)
16 |
17 | > [!WARNING]
18 | > CH58x環境が壊れますので、ご注意ください。両方の実装が必要な方は、各自で切り分けを行ってください。
19 |
20 | (そのための環境を作る必要があるので、かなり面倒だと思われます)
21 | 上書き先は、環境によると思われますが、以下のディレクトリに上書きします。
22 | ```
23 | C:\Users\ユーザー名\AppData\Local\Arduino15\packages\electroniccats
24 | ```
25 |
26 | なお以下のディレクトリーを削除する必要があります。リネームではインクルードされますので、バックアップが必要な方は、より上位の階層に移動してください。
27 | ```
28 | C:\Users\ユーザー名\AppData\Local\Arduino15\packages\electroniccats\hardware\wch\0.0.1\cores\arduino\ch583
29 | ```
30 |
31 |
32 |
33 | # LEDのピン番号は?
34 |
35 | 基盤のシルク印刷に A8 と書かれている通り、8番ピンが LED に接続されています。PWM も使えます。
36 |
37 | ```
38 | #undef LED_BUILTIN
39 | #define LED_BUILTIN 8
40 | ```
41 | 上記のコードを入れますが、スマートに実装するには、以下のコードが良いです。
42 |
43 | ```
44 | #ifdef ID_CH592
45 | #undef LED_BUILTIN
46 | #define LED_BUILTIN 8
47 | #endif
48 | ```
49 |
50 |
51 |
52 | # コンパイル
53 |
54 | プログラム内容に問題がなければ、以下のようにプログラムサイズを表示して終了します。
55 |
56 | ```
57 | 最大448000バイトのフラッシュメモリのうち、スケッチが24184バイト(5%)を使っています。
58 | 最大32000バイトのRAMのうち、グローバル変数が256バイト(0%)を使っていて、ローカル変数で31744バイト使うことができます。
59 | ```
60 |
61 |
62 |
63 | # ボードへ書き込み
64 |
65 | 書き込みを指定すると、プログラムサイズの表示後に管理者権限を要求されます。
66 | > [!IMPORTANT]
67 | > ここで USBコネクタ に CH592F を差し込みますが、**BOOTボタンを押しながら差し込みます**。
68 |
69 | 管理者権限の要求には、そのまま「はい」を指定すると、ボードへ書き込みが行われます。
70 |
71 |
72 | > [!NOTE]
73 | > 管理者権限を突破する方法を取得していませんので、毎回出力されるたびに指定する必要があります。
74 | > 現時点で、書き込み経過が表示されません。
75 |
76 |
77 |
78 | # 手動による、コンパイルからボードへの書き込み準備
79 |
80 | > [!IMPORTANT]
81 | > コンパイル後に以下の記述があり、**\*.elf** ファイルの場所をメモしておきます。
82 | ```
83 | "C:\\Users\\ユーザー名\\... "C:\\Users\\pearl\\.../led_fade_internal.ino.elf"
84 | 最大448000バイトのフラッシュメモリのうち、スケッチが24184バイト(5%)を使っています。
85 | 最大32000バイトのRAMのうち、グローバル変数が256バイト(0%)を使っていて、ローカル変数で31744バイト使うことができます。
86 | ```
87 |
88 |
89 |
90 | # 手動による、ボードへの書き込み
91 |
92 | 書き込みにはソフト WCHISPTool が必要です。以下の場所からダウンロードが可能です。
93 | デフォルトインストール先が、Cドライブ直下になりますので、嫌な方はインストール後、ファイルだけ退避してアンインストールしても構いません。
94 | > [https://www.wch-ic.com/downloads/WCHISPTool_Setup_exe.html](https://www.wch-ic.com/downloads/WCHISPTool_Setup_exe.html)
95 |
96 | > [!CAUTION]
97 | > ここで USBコネクタ に CH592F を刺さないでください。
98 |
99 | WCHISPTool_CH57x-59x.exe を起動し、上記でメモした **\*.elf** と同じディレクトリにある、**\*.bin** ファイルまたは **\*.hex** ファイルを指定します。
100 | > [!IMPORTANT]
101 | > 必ず **ObjectFile1** に指定すること。指定するファイルは、**elfファイル** ではなく、**binファイル** または **hexファイル** を指定すること。
102 |
103 | ここで USBコネクタ に CH592F を差し込みますが、**BOOTボタンを押しながら差し込みます**。
104 | スイッチ付き USBハブ が無いと現実的に運用は不可能かと思われます。
105 |
106 | 画像の通り、Lチカ程度であれば、1秒以下で終了します。
107 |
108 |
109 |
110 | # おまけ
111 |
112 | > [!NOTE]
113 | > デフォルトの Lチカ と区別するために、フェードする Lチカ を以下のディレクトリに置きました。
114 | > ご自由にお使いください。とりあえず Arduino IDE 環境を作らずとも、ボードの動作テストぐらいは出来ます。
115 |
116 | > [https://github.com/PEARLPALMS/Arduino-CH592F/tree/main/sample](https://github.com/PEARLPALMS/Arduino-CH592F/tree/main/sample)
117 |
--------------------------------------------------------------------------------
/libraries/xxx/examples/,gitkeep:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/misc/.gitkeep:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/misc/CH592Fピンレイアウト.ods:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PEARLPALMS/Arduino-CH592F/b9ea2b5ecd53673252ccbe5e307a02ed8d93274f/misc/CH592Fピンレイアウト.ods
--------------------------------------------------------------------------------
/misc/CH592Fピンレイアウト.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PEARLPALMS/Arduino-CH592F/b9ea2b5ecd53673252ccbe5e307a02ed8d93274f/misc/CH592Fピンレイアウト.pdf
--------------------------------------------------------------------------------
/misc/CH592Fボード.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PEARLPALMS/Arduino-CH592F/b9ea2b5ecd53673252ccbe5e307a02ed8d93274f/misc/CH592Fボード.png
--------------------------------------------------------------------------------
/review.md:
--------------------------------------------------------------------------------
1 | # WeAct Studio WCH CH592F
2 |
3 | 実物は以下の写真です。
4 | ・ ボードは最近はやりのつや消し黒。
5 | ・ コネクタは USB Type-C、スケッチのアップロードも可能。
6 | ・ 裏面に実装部品なし。
7 | ・ 基盤には、BOOTボタン、RESETボタン、LEDが青色1個(プラグラムで操作できる)、電源LEDは無し。
8 | ・ 付属ピンは黄色で、磁石に付かない。材質は不明。
9 | ・ 帯電防止袋は、なにげに嬉しいチャック付き(直ぐに捨てるんだけど)。
10 | 全体的に丁寧な作りと、安っぽい梱包でなく、好感が持てる。と言ってられるのも今のうちで、
11 | 既に日本製では、同等製品を作成できないレベルだとも。。。
12 | 
13 |
14 |
15 |
16 | # 詳細写真
17 |
18 | 付属ピンヘッダは、スルーホールが小さいためにギリギリ刺さる感じで、はんだの濡れが良くなく、
19 | あらかじめフラックスたっぷりで作業するほうが良かった。STM32 付属のピンも同様だった記憶。
20 | 裏面には、実装部品が皆無で、シルク印刷でデバッグピン番号が書かれている。
21 | V1.0の下にあるジャンパー部分は、分かりません。導通を確認すれば直ぐに分かるでしょうが、やってません。
22 | 
23 |
24 |
25 |
26 | # ピン配列
27 |
28 | 
29 |
30 | ```
31 | ==== CH592F ====
32 | A8 RXD1 AIN LED | GND
33 | A9 TMR0 TXD1 AIN | +5V
34 | B15 TCK MISO_ SCL DTR | GND
35 | B14 TIO MOSI_ SDA PWM DSR | 3V3
36 | B13 SCK0_ TXD1_ DCD_ | A10 TMR1
37 | B12 SCS_ RXD1_ RI_ | A11 TMR2
38 | B11 TMR2_ UD+ | A12 SCS PWM AIN
39 | B10 TMR1_ UD- | A13 SCK0 PWM AIN
40 | B7 TXD0 PWM | A14 MOSI TXD0_ AIN
41 | B4 RXD0 PWM | A15 MISO RXD0_ AIN
42 | B23 TMR0_ TXD2 PWM RST | A5 TXD3 AIN
43 | B22 TMR3 RXD2 BOOT | A4 RXD3 AIN
44 | ```
45 |
46 |
47 |
48 | # 大きさ比較
49 |
50 | Nano互換と比べると、幅は同じですが、ピン数が少なくアンテナ部分を含めても小さいです。
51 | Seeeduino や ATtiny などを除けば、実用性のある小サイズだと思われます。
52 | 
53 |
54 |
55 | 幅が同じなので、Nanoのシールドも使えますが、ピン番号によってはショートするので、自己責任で。。。
56 | そもそも、こんな使い方する人、いませんね。
57 | 
58 |
59 |
60 | # 技適マーク
61 |
62 | そんなもん存在しません。見える場所に FCC ID、CEマーク も存在しません。
63 | 総務省のホームページで手続きが行える、「技適未取得機器を用いた実験等の特例制度」にも
64 | Bluetooth5.2 までしか選択肢がありません。
65 | ですので、自宅内であっても多少スピードが早くて癖のあるマイコンでしかありません。
66 | 今日も明日も暇なんだから、仕事ぐらいしろよ。これじゃ中華250円マイコンに勝てるわけ無いよね。
67 |
68 | 
69 |
70 |
--------------------------------------------------------------------------------
/sample.md:
--------------------------------------------------------------------------------
1 |
2 | # サンプルプログラム
3 |
4 | 幾つかのプログラムは、意図しない動作をする可能性もあります。
5 | 自己責任で内容を理解した上で動作確認をお願いします。
6 |
7 |
8 |
9 | > [test_ch592f_button](https://github.com/PEARLPALMS/Arduino-CH592F/tree/main/sample/test_ch592f_button)
10 |
11 | ボタン動作確認するために、全てのピンを確認します。
12 | 各種ピンを GND とショートさせると、内蔵LEDが光ります。
13 |
14 |
15 | > [test_ch592f_button2](https://github.com/PEARLPALMS/Arduino-CH592F/tree/main/sample/test_ch592f_button2)
16 |
17 | 実際にボタンを実装して動作を確認します。
18 | ボタンを押下すると、内蔵LEDが光ります。
19 |
20 |
21 |
22 |
23 | > [test_ch592f_serial](https://github.com/PEARLPALMS/Arduino-CH592F/tree/main/sample/test_ch592f_serial)
24 |
25 | 現時点では内蔵の USB端子 から COMポート としてシリアル通信が出来ておりません。
26 | UART0 を使って別途用意するシリアル通信機器へ単純な通信を行います。デバッグ出力が行なえます。
27 |
28 |
29 |
30 |
31 | > [test_ch592f_ble_hid_keyboard_org](https://github.com/PEARLPALMS/Arduino-CH592F/tree/main/sample/test_ch592f_ble_hid_keyboard_org)
32 |
33 | WeActの開発ページに存在する Bluetooth HID Keyboard のサンプルプログラムです。
34 | b~z まで 2秒毎に出力します。
35 |
36 |
37 | > [test_ch592f_ble_hid_keyboard](https://github.com/PEARLPALMS/Arduino-CH592F/tree/main/sample/test_ch592f_ble_hid_keyboard)
38 |
39 | 実際にボタンを実装して簡易キーボードを作成します。
40 | ボタンを押下すると、ボタンにより [a] [b] [c] を出力します。長押しの場合は、[A] [B] [C] を出力します。
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/sample/.gitkeep:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/sample/WCHISPTool/.gitkeep:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/sample/WCHISPTool/CH592F.INI:
--------------------------------------------------------------------------------
1 | [Public]
2 | MCUName=CH592
3 | bMCULine=12
4 | bMCUType=146
5 | DataFlashFile=.
6 | swzUserFile1=.
7 | swzUserFile2=.
8 | swzUserFile3=.
9 | swzUserFile4=.
10 | swzUserFile5=.
11 | DataFlashFileSel=0
12 | IsUserFile1Sel=0
13 | IsUserFile2Sel=0
14 | IsUserFile3Sel=0
15 | IsUserFile4Sel=0
16 | IsUserFile5Sel=0
17 | [CH57x-58xUICfg]
18 | bDnInterType=0
19 | Baud=2M
20 | DwnldCfgPin=PB22
21 | BootPinNum=1
22 | WProtectAddr=.
23 | IsCodeProtect=1
24 | IsRSTAsInputPin=1
25 | IsSerialNoBtnDwnld=1
26 | IsClearDataFlash=0
27 | IsEraseAllCFlash=0
28 | IsAfterDownRest=1
29 | bVerifyType=0
30 |
--------------------------------------------------------------------------------
/sample/WCHISPTool/WCH55xISPDLL.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PEARLPALMS/Arduino-CH592F/b9ea2b5ecd53673252ccbe5e307a02ed8d93274f/sample/WCHISPTool/WCH55xISPDLL.dll
--------------------------------------------------------------------------------
/sample/WCHISPTool/WCHISPTool_CH57x-59x.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PEARLPALMS/Arduino-CH592F/b9ea2b5ecd53673252ccbe5e307a02ed8d93274f/sample/WCHISPTool/WCHISPTool_CH57x-59x.exe
--------------------------------------------------------------------------------
/sample/WCHISPTool/download.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 | WCHISPTool_CH57x-59x.exe -c .\CH592F.INI -f .\led_fade_internal.ino.bin
3 | @PAUSE
4 |
--------------------------------------------------------------------------------
/sample/WCHISPTool/led_fade_internal.ino.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PEARLPALMS/Arduino-CH592F/b9ea2b5ecd53673252ccbe5e307a02ed8d93274f/sample/WCHISPTool/led_fade_internal.ino.bin
--------------------------------------------------------------------------------
/sample/test_ch592f_ble_hid_keyboard/.gitkeep:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/sample/test_ch592f_ble_hid_keyboard/IMG_0712.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PEARLPALMS/Arduino-CH592F/b9ea2b5ecd53673252ccbe5e307a02ed8d93274f/sample/test_ch592f_ble_hid_keyboard/IMG_0712.png
--------------------------------------------------------------------------------
/sample/test_ch592f_ble_hid_keyboard/battservice.c:
--------------------------------------------------------------------------------
1 | /********************************** (C) COPYRIGHT *******************************
2 | * File Name : battservice.c
3 | * Author : WCH
4 | * Version : V1.0
5 | * Date : 2018/12/10
6 | * Description : ��ط���
7 | *********************************************************************************
8 | * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
9 | * Attention: This software (modified or not) and binary are used for
10 | * microcontroller manufactured by Nanjing Qinheng Microelectronics.
11 | *******************************************************************************/
12 |
13 | /*********************************************************************
14 | * INCLUDES
15 | */
16 | #include "CONFIG.h"
17 | #include "hiddev.h"
18 | #include "battservice.h"
19 |
20 | /*********************************************************************
21 | * MACROS
22 | */
23 |
24 | /*********************************************************************
25 | * CONSTANTS
26 | */
27 |
28 | // ADC voltage levels
29 | #define BATT_ADC_LEVEL_3V 409
30 | #define BATT_ADC_LEVEL_2V 273
31 |
32 | #define BATT_LEVEL_VALUE_IDX 2 // Position of battery level in attribute array
33 | #define BATT_LEVEL_VALUE_CCCD_IDX 3 // Position of battery level CCCD in attribute array
34 |
35 | #define BATT_LEVEL_VALUE_LEN 1
36 | /*********************************************************************
37 | * TYPEDEFS
38 | */
39 |
40 | /*********************************************************************
41 | * GLOBAL VARIABLES
42 | */
43 | // Battery service
44 | const uint8_t battServUUID[ATT_BT_UUID_SIZE] = {
45 | LO_UINT16(BATT_SERV_UUID), HI_UINT16(BATT_SERV_UUID)};
46 |
47 | // Battery level characteristic
48 | const uint8_t battLevelUUID[ATT_BT_UUID_SIZE] = {
49 | LO_UINT16(BATT_LEVEL_UUID), HI_UINT16(BATT_LEVEL_UUID)};
50 |
51 | /*********************************************************************
52 | * EXTERNAL VARIABLES
53 | */
54 |
55 | /*********************************************************************
56 | * EXTERNAL FUNCTIONS
57 | */
58 |
59 | /*********************************************************************
60 | * LOCAL VARIABLES
61 | */
62 |
63 | // Application callback
64 | static battServiceCB_t battServiceCB;
65 |
66 | // Measurement setup callback
67 | static battServiceSetupCB_t battServiceSetupCB = NULL;
68 |
69 | // Measurement teardown callback
70 | static battServiceTeardownCB_t battServiceTeardownCB = NULL;
71 |
72 | // Measurement calculation callback
73 | static battServiceCalcCB_t battServiceCalcCB = NULL;
74 |
75 | static uint16_t battMinLevel = BATT_ADC_LEVEL_2V; // For VDD/3 measurements
76 | static uint16_t battMaxLevel = BATT_ADC_LEVEL_3V; // For VDD/3 measurements
77 |
78 | // Critical battery level setting
79 | static uint8_t battCriticalLevel;
80 |
81 | // ADC channel to be used for reading
82 | //static uint8_t battServiceAdcCh = HAL_ADC_CHANNEL_VDD;
83 |
84 | /*********************************************************************
85 | * Profile Attributes - variables
86 | */
87 |
88 | // Battery Service attribute
89 | static const gattAttrType_t battService = {ATT_BT_UUID_SIZE, battServUUID};
90 |
91 | // Battery level characteristic
92 | static uint8_t battLevelProps = GATT_PROP_READ | GATT_PROP_NOTIFY;
93 | static uint8_t battLevel = 100;
94 | static gattCharCfg_t battLevelClientCharCfg[GATT_MAX_NUM_CONN];
95 |
96 | // HID Report Reference characteristic descriptor, battery level
97 | static uint8_t hidReportRefBattLevel[HID_REPORT_REF_LEN] = {
98 | HID_RPT_ID_BATT_LEVEL_IN, HID_REPORT_TYPE_INPUT};
99 |
100 | /*********************************************************************
101 | * Profile Attributes - Table
102 | */
103 |
104 | static gattAttribute_t battAttrTbl[] = {
105 | // Battery Service
106 | {
107 | {ATT_BT_UUID_SIZE, primaryServiceUUID}, /* type */
108 | GATT_PERMIT_READ, /* permissions */
109 | 0, /* handle */
110 | (uint8_t *)&battService /* pValue */
111 | },
112 |
113 | // Battery Level Declaration
114 | {
115 | {ATT_BT_UUID_SIZE, characterUUID},
116 | GATT_PERMIT_READ,
117 | 0,
118 | &battLevelProps},
119 |
120 | // Battery Level Value
121 | {
122 | {ATT_BT_UUID_SIZE, battLevelUUID},
123 | GATT_PERMIT_READ,
124 | 0,
125 | &battLevel},
126 |
127 | // Battery Level Client Characteristic Configuration
128 | {
129 | {ATT_BT_UUID_SIZE, clientCharCfgUUID},
130 | GATT_PERMIT_READ | GATT_PERMIT_WRITE,
131 | 0,
132 | (uint8_t *)&battLevelClientCharCfg},
133 |
134 | // HID Report Reference characteristic descriptor, batter level input
135 | {
136 | {ATT_BT_UUID_SIZE, reportRefUUID},
137 | GATT_PERMIT_READ,
138 | 0,
139 | hidReportRefBattLevel}
140 | };
141 |
142 | /*********************************************************************
143 | * LOCAL FUNCTIONS
144 | */
145 | static bStatus_t battReadAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
146 | uint8_t *pValue, uint16_t *pLen, uint16_t offset, uint16_t maxLen, uint8_t method);
147 | static bStatus_t battWriteAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
148 | uint8_t *pValue, uint16_t len, uint16_t offset, uint8_t method);
149 | static void battNotifyCB(linkDBItem_t *pLinkItem);
150 | static uint8_t battMeasure(void);
151 | static void battNotifyLevel(void);
152 |
153 | /*********************************************************************
154 | * PROFILE CALLBACKS
155 | */
156 | // Battery Service Callbacks
157 | gattServiceCBs_t battCBs = {
158 | battReadAttrCB, // Read callback function pointer
159 | battWriteAttrCB, // Write callback function pointer
160 | NULL // Authorization callback function pointer
161 | };
162 |
163 | /*********************************************************************
164 | * PUBLIC FUNCTIONS
165 | */
166 |
167 | /*********************************************************************
168 | * @fn Batt_AddService
169 | *
170 | * @brief Initializes the Battery Service by registering
171 | * GATT attributes with the GATT server.
172 | *
173 | * @return Success or Failure
174 | */
175 | bStatus_t Batt_AddService(void)
176 | {
177 | uint8_t status = SUCCESS;
178 |
179 | // Initialize Client Characteristic Configuration attributes
180 | GATTServApp_InitCharCfg(INVALID_CONNHANDLE, battLevelClientCharCfg);
181 |
182 | // Register GATT attribute list and CBs with GATT Server App
183 | status = GATTServApp_RegisterService(battAttrTbl,
184 | GATT_NUM_ATTRS(battAttrTbl),
185 | GATT_MAX_ENCRYPT_KEY_SIZE,
186 | &battCBs);
187 |
188 | return (status);
189 | }
190 |
191 | /*********************************************************************
192 | * @fn Batt_Register
193 | *
194 | * @brief Register a callback function with the Battery Service.
195 | *
196 | * @param pfnServiceCB - Callback function.
197 | *
198 | * @return None.
199 | */
200 | extern void Batt_Register(battServiceCB_t pfnServiceCB)
201 | {
202 | battServiceCB = pfnServiceCB;
203 | }
204 |
205 | /*********************************************************************
206 | * @fn Batt_SetParameter
207 | *
208 | * @brief Set a Battery Service parameter.
209 | *
210 | * @param param - Profile parameter ID
211 | * @param len - length of data to right
212 | * @param value - pointer to data to write. This is dependent on
213 | * the parameter ID and WILL be cast to the appropriate
214 | * data type (example: data type of uint16_t will be cast to
215 | * uint16_t pointer).
216 | *
217 | * @return bStatus_t
218 | */
219 | bStatus_t Batt_SetParameter(uint8_t param, uint8_t len, void *value)
220 | {
221 | bStatus_t ret = SUCCESS;
222 |
223 | switch(param)
224 | {
225 | case BATT_PARAM_CRITICAL_LEVEL:
226 | battCriticalLevel = *((uint8_t *)value);
227 |
228 | // If below the critical level and critical state not set, notify it
229 | if(battLevel < battCriticalLevel)
230 | {
231 | battNotifyLevel();
232 | }
233 | break;
234 |
235 | default:
236 | ret = INVALIDPARAMETER;
237 | break;
238 | }
239 |
240 | return (ret);
241 | }
242 |
243 | /*********************************************************************
244 | * @fn Batt_GetParameter
245 | *
246 | * @brief Get a Battery Service parameter.
247 | *
248 | * @param param - Profile parameter ID
249 | * @param value - pointer to data to get. This is dependent on
250 | * the parameter ID and WILL be cast to the appropriate
251 | * data type (example: data type of uint16_t will be cast to
252 | * uint16_t pointer).
253 | *
254 | * @return bStatus_t
255 | */
256 | bStatus_t Batt_GetParameter(uint8_t param, void *value)
257 | {
258 | bStatus_t ret = SUCCESS;
259 | switch(param)
260 | {
261 | case BATT_PARAM_LEVEL:
262 | *((uint8_t *)value) = battLevel;
263 | break;
264 |
265 | case BATT_PARAM_CRITICAL_LEVEL:
266 | *((uint8_t *)value) = battCriticalLevel;
267 | break;
268 |
269 | case BATT_PARAM_SERVICE_HANDLE:
270 | *((uint16_t *)value) = GATT_SERVICE_HANDLE(battAttrTbl);
271 | break;
272 |
273 | case BATT_PARAM_BATT_LEVEL_IN_REPORT:
274 | {
275 | hidRptMap_t *pRpt = (hidRptMap_t *)value;
276 |
277 | pRpt->id = hidReportRefBattLevel[0];
278 | pRpt->type = hidReportRefBattLevel[1];
279 | pRpt->handle = battAttrTbl[BATT_LEVEL_VALUE_IDX].handle;
280 | pRpt->cccdHandle = battAttrTbl[BATT_LEVEL_VALUE_CCCD_IDX].handle;
281 | pRpt->mode = HID_PROTOCOL_MODE_REPORT;
282 | }
283 | break;
284 |
285 | default:
286 | ret = INVALIDPARAMETER;
287 | break;
288 | }
289 |
290 | return (ret);
291 | }
292 |
293 | /*********************************************************************
294 | * @fn Batt_MeasLevel
295 | *
296 | * @brief Measure the battery level and update the battery
297 | * level value in the service characteristics. If
298 | * the battery level-state characteristic is configured
299 | * for notification and the battery level has changed
300 | * since the last measurement, then a notification
301 | * will be sent.
302 | *
303 | * @return Success
304 | */
305 | bStatus_t Batt_MeasLevel(void)
306 | {
307 | uint8_t level;
308 |
309 | level = battMeasure();
310 |
311 | // If level has gone down
312 | if(level < battLevel)
313 | {
314 | // Update level
315 | battLevel = level;
316 |
317 | // Send a notification
318 | battNotifyLevel();
319 | }
320 |
321 | return SUCCESS;
322 | }
323 |
324 | /*********************************************************************
325 | * @fn Batt_Setup
326 | *
327 | * @brief Set up which ADC source is to be used. Defaults to VDD/3.
328 | *
329 | * @param adc_ch - ADC Channel, e.g. HAL_ADC_CHN_AIN6
330 | * @param minVal - max battery level
331 | * @param maxVal - min battery level
332 | * @param sCB - HW setup callback
333 | * @param tCB - HW tear down callback
334 | * @param cCB - percentage calculation callback
335 | *
336 | * @return none.
337 | */
338 | void Batt_Setup(uint8_t adc_ch, uint16_t minVal, uint16_t maxVal,
339 | battServiceSetupCB_t sCB, battServiceTeardownCB_t tCB,
340 | battServiceCalcCB_t cCB)
341 | {
342 | //battServiceAdcCh = adc_ch;
343 | battMinLevel = minVal;
344 | battMaxLevel = maxVal;
345 |
346 | battServiceSetupCB = sCB;
347 | battServiceTeardownCB = tCB;
348 | battServiceCalcCB = cCB;
349 | }
350 |
351 | /*********************************************************************
352 | * @fn battReadAttrCB
353 | *
354 | * @brief Read an attribute.
355 | *
356 | * @param connHandle - connection message was received on
357 | * @param pAttr - pointer to attribute
358 | * @param pValue - pointer to data to be read
359 | * @param pLen - length of data to be read
360 | * @param offset - offset of the first octet to be read
361 | * @param maxLen - maximum length of data to be read
362 | *
363 | * @return Success or Failure
364 | */
365 | static bStatus_t battReadAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
366 | uint8_t *pValue, uint16_t *pLen, uint16_t offset, uint16_t maxLen, uint8_t method)
367 | {
368 | uint16_t uuid;
369 | bStatus_t status = SUCCESS;
370 |
371 | // Make sure it's not a blob operation (no attributes in the profile are long)
372 | if(offset > 0)
373 | {
374 | return (ATT_ERR_ATTR_NOT_LONG);
375 | }
376 |
377 | uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]);
378 |
379 | // Measure battery level if reading level
380 | if(uuid == BATT_LEVEL_UUID)
381 | {
382 | uint8_t level;
383 |
384 | level = battMeasure();
385 |
386 | // If level has gone down
387 | if(level < battLevel)
388 | {
389 | // Update level
390 | battLevel = level;
391 | }
392 |
393 | *pLen = 1;
394 | pValue[0] = battLevel;
395 | }
396 | else if(uuid == GATT_REPORT_REF_UUID)
397 | {
398 | *pLen = HID_REPORT_REF_LEN;
399 | tmos_memcpy(pValue, pAttr->pValue, HID_REPORT_REF_LEN);
400 | }
401 | else
402 | {
403 | status = ATT_ERR_ATTR_NOT_FOUND;
404 | }
405 |
406 | return (status);
407 | }
408 |
409 | /*********************************************************************
410 | * @fn battWriteAttrCB
411 | *
412 | * @brief Validate attribute data prior to a write operation
413 | *
414 | * @param connHandle - connection message was received on
415 | * @param pAttr - pointer to attribute
416 | * @param pValue - pointer to data to be written
417 | * @param len - length of data
418 | * @param offset - offset of the first octet to be written
419 | *
420 | * @return Success or Failure
421 | */
422 | static bStatus_t battWriteAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
423 | uint8_t *pValue, uint16_t len, uint16_t offset, uint8_t method)
424 | {
425 | bStatus_t status = SUCCESS;
426 |
427 | uint16_t uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]);
428 | switch(uuid)
429 | {
430 | case GATT_CLIENT_CHAR_CFG_UUID:
431 | status = GATTServApp_ProcessCCCWriteReq(connHandle, pAttr, pValue, len,
432 | offset, GATT_CLIENT_CFG_NOTIFY);
433 | if(status == SUCCESS)
434 | {
435 | uint16_t charCfg = BUILD_UINT16(pValue[0], pValue[1]);
436 |
437 | if(battServiceCB)
438 | {
439 | (*battServiceCB)((charCfg == GATT_CFG_NO_OPERATION) ? BATT_LEVEL_NOTI_DISABLED : BATT_LEVEL_NOTI_ENABLED);
440 | }
441 | }
442 | break;
443 |
444 | default:
445 | status = ATT_ERR_ATTR_NOT_FOUND;
446 | break;
447 | }
448 |
449 | return (status);
450 | }
451 |
452 | /*********************************************************************
453 | * @fn battNotifyCB
454 | *
455 | * @brief Send a notification of the level state characteristic.
456 | *
457 | * @param connHandle - linkDB item
458 | *
459 | * @return None.
460 | */
461 | static void battNotifyCB(linkDBItem_t *pLinkItem)
462 | {
463 | if(pLinkItem->stateFlags & LINK_CONNECTED)
464 | {
465 | uint16_t value = GATTServApp_ReadCharCfg(pLinkItem->connectionHandle,
466 | battLevelClientCharCfg);
467 | if(value & GATT_CLIENT_CFG_NOTIFY)
468 | {
469 | attHandleValueNoti_t noti;
470 |
471 | noti.pValue = GATT_bm_alloc(pLinkItem->connectionHandle, ATT_HANDLE_VALUE_NOTI,
472 | BATT_LEVEL_VALUE_LEN, NULL, 0);
473 | if(noti.pValue != NULL)
474 | {
475 | noti.handle = battAttrTbl[BATT_LEVEL_VALUE_IDX].handle;
476 | noti.len = BATT_LEVEL_VALUE_LEN;
477 | noti.pValue[0] = battLevel;
478 |
479 | if(GATT_Notification(pLinkItem->connectionHandle, ¬i, FALSE) != SUCCESS)
480 | {
481 | GATT_bm_free((gattMsg_t *)¬i, ATT_HANDLE_VALUE_NOTI);
482 | }
483 | }
484 | }
485 | }
486 | }
487 |
488 | /*********************************************************************
489 | * @fn battMeasure
490 | *
491 | * @brief Measure the battery level with the ADC and return
492 | * it as a percentage 0-100%.
493 | *
494 | * @return Battery level.
495 | */
496 | static uint8_t battMeasure(void)
497 | {
498 | uint16_t adc;
499 | uint8_t percent;
500 |
501 | // Call measurement setup callback
502 | if(battServiceSetupCB != NULL)
503 | {
504 | battServiceSetupCB();
505 | }
506 |
507 | // Configure ADC and perform a read
508 | adc = 300;
509 | // Call measurement teardown callback
510 | if(battServiceTeardownCB != NULL)
511 | {
512 | battServiceTeardownCB();
513 | }
514 |
515 | if(adc >= battMaxLevel)
516 | {
517 | percent = 100;
518 | }
519 | else if(adc <= battMinLevel)
520 | {
521 | percent = 0;
522 | }
523 | else
524 | {
525 | if(battServiceCalcCB != NULL)
526 | {
527 | percent = battServiceCalcCB(adc);
528 | }
529 | else
530 | {
531 | uint16_t range = battMaxLevel - battMinLevel + 1;
532 |
533 | // optional if you want to keep it even, otherwise just take floor of divide
534 | // range += (range & 1);
535 | range >>= 2; // divide by 4
536 |
537 | percent = (uint8_t)((((adc - battMinLevel) * 25) + (range - 1)) / range);
538 | }
539 | }
540 |
541 | return percent;
542 | }
543 |
544 | /*********************************************************************
545 | * @fn battNotifyLevelState
546 | *
547 | * @brief Send a notification of the battery level state
548 | * characteristic if a connection is established.
549 | *
550 | * @return None.
551 | */
552 | static void battNotifyLevel(void)
553 | {
554 | // Execute linkDB callback to send notification
555 | linkDB_PerformFunc(battNotifyCB);
556 | }
557 |
558 | /*********************************************************************
559 | * @fn Batt_HandleConnStatusCB
560 | *
561 | * @brief Battery Service link status change handler function.
562 | *
563 | * @param connHandle - connection handle
564 | * @param changeType - type of change
565 | *
566 | * @return none
567 | */
568 | void Batt_HandleConnStatusCB(uint16_t connHandle, uint8_t changeType)
569 | {
570 | // Make sure this is not loopback connection
571 | if(connHandle != LOOPBACK_CONNHANDLE)
572 | {
573 | // Reset Client Char Config if connection has dropped
574 | if((changeType == LINKDB_STATUS_UPDATE_REMOVED) ||
575 | ((changeType == LINKDB_STATUS_UPDATE_STATEFLAGS) &&
576 | (!linkDB_Up(connHandle))))
577 | {
578 | GATTServApp_InitCharCfg(connHandle, battLevelClientCharCfg);
579 | }
580 | }
581 | }
582 |
583 | /*********************************************************************
584 | *********************************************************************/
585 |
--------------------------------------------------------------------------------
/sample/test_ch592f_ble_hid_keyboard/battservice.h:
--------------------------------------------------------------------------------
1 | /********************************** (C) COPYRIGHT *******************************
2 | * File Name : battservice.h
3 | * Author : WCH
4 | * Version : V1.0
5 | * Date : 2018/12/11
6 | * Description :
7 | *********************************************************************************
8 | * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
9 | * Attention: This software (modified or not) and binary are used for
10 | * microcontroller manufactured by Nanjing Qinheng Microelectronics.
11 | *******************************************************************************/
12 |
13 | #ifndef BATTSERVICE_H
14 | #define BATTSERVICE_H
15 |
16 | #ifdef __cplusplus
17 | extern "C" {
18 | #endif
19 |
20 | /*********************************************************************
21 | * INCLUDES
22 | */
23 |
24 | /*********************************************************************
25 | * CONSTANTS
26 | */
27 |
28 | // Battery Service Get/Set Parameters
29 | #define BATT_PARAM_LEVEL 0
30 | #define BATT_PARAM_CRITICAL_LEVEL 1
31 | #define BATT_PARAM_SERVICE_HANDLE 2
32 | #define BATT_PARAM_BATT_LEVEL_IN_REPORT 3
33 |
34 | // Callback events
35 | #define BATT_LEVEL_NOTI_ENABLED 1
36 | #define BATT_LEVEL_NOTI_DISABLED 2
37 |
38 | // HID Report IDs for the service
39 | #define HID_RPT_ID_BATT_LEVEL_IN 4 // Battery Level input report ID
40 |
41 | /*********************************************************************
42 | * TYPEDEFS
43 | */
44 |
45 | // Battery Service callback function
46 | typedef void (*battServiceCB_t)(uint8_t event);
47 |
48 | // Battery measure HW setup function
49 | typedef void (*battServiceSetupCB_t)(void);
50 |
51 | // Battery measure percentage calculation function
52 | typedef uint8_t (*battServiceCalcCB_t)(uint16_t adcVal);
53 |
54 | // Battery measure HW teardown function
55 | typedef void (*battServiceTeardownCB_t)(void);
56 |
57 | /*********************************************************************
58 | * MACROS
59 | */
60 |
61 | /*********************************************************************
62 | * Profile Callbacks
63 | */
64 |
65 | /*********************************************************************
66 | * API FUNCTIONS
67 | */
68 |
69 | /*********************************************************************
70 | * @fn Batt_AddService
71 | *
72 | * @brief Initializes the Battery service by registering
73 | * GATT attributes with the GATT server.
74 | *
75 | * @return Success or Failure
76 | */
77 | extern bStatus_t Batt_AddService(void);
78 |
79 | /*********************************************************************
80 | * @fn Batt_Register
81 | *
82 | * @brief Register a callback function with the Battery Service.
83 | *
84 | * @param pfnServiceCB - Callback function.
85 | *
86 | * @return None.
87 | */
88 | extern void Batt_Register(battServiceCB_t pfnServiceCB);
89 |
90 | /*********************************************************************
91 | * @fn Batt_SetParameter
92 | *
93 | * @brief Set a Battery Service parameter.
94 | *
95 | * @param param - Profile parameter ID
96 | * @param len - length of data to right
97 | * @param value - pointer to data to write. This is dependent on
98 | * the parameter ID and WILL be cast to the appropriate
99 | * data type (example: data type of uint16_t will be cast to
100 | * uint16_t pointer).
101 | *
102 | * @return bStatus_t
103 | */
104 | extern bStatus_t Batt_SetParameter(uint8_t param, uint8_t len, void *value);
105 |
106 | /*********************************************************************
107 | * @fn Batt_GetParameter
108 | *
109 | * @brief Get a Battery parameter.
110 | *
111 | * @param param - Profile parameter ID
112 | * @param value - pointer to data to get. This is dependent on
113 | * the parameter ID and WILL be cast to the appropriate
114 | * data type (example: data type of uint16_t will be cast to
115 | * uint16_t pointer).
116 | *
117 | * @return bStatus_t
118 | */
119 | extern bStatus_t Batt_GetParameter(uint8_t param, void *value);
120 |
121 | /*********************************************************************
122 | * @fn Batt_MeasLevel
123 | *
124 | * @brief Measure the battery level and update the battery
125 | * level value in the service characteristics. If
126 | * the battery level-state characteristic is configured
127 | * for notification and the battery level has changed
128 | * since the last measurement, then a notification
129 | * will be sent.
130 | *
131 | * @return Success or Failure
132 | */
133 | extern bStatus_t Batt_MeasLevel(void);
134 |
135 | /*********************************************************************
136 | * @fn Batt_Setup
137 | *
138 | * @brief Set up which ADC source is to be used. Defaults to VDD/3.
139 | *
140 | * @param adc_ch - ADC Channel, e.g. HAL_ADC_CHN_AIN6
141 | * @param minVal - max battery level
142 | * @param maxVal - min battery level
143 | * @param sCB - HW setup callback
144 | * @param tCB - HW tear down callback
145 | * @param cCB - percentage calculation callback
146 | *
147 | * @return none.
148 | */
149 | extern void Batt_Setup(uint8_t adc_ch, uint16_t minVal, uint16_t maxVal,
150 | battServiceSetupCB_t sCB, battServiceTeardownCB_t tCB,
151 | battServiceCalcCB_t cCB);
152 |
153 | /*********************************************************************
154 | * @fn Batt_HandleConnStatusCB
155 | *
156 | * @brief Battery Service link status change handler function.
157 | *
158 | * @param connHandle - connection handle
159 | * @param changeType - type of change
160 | *
161 | * @return none
162 | */
163 | void Batt_HandleConnStatusCB(uint16_t connHandle, uint8_t changeType);
164 |
165 | /*********************************************************************
166 | *********************************************************************/
167 |
168 | #ifdef __cplusplus
169 | }
170 | #endif
171 |
172 | #endif /* BATTSERVICE_H */
173 |
--------------------------------------------------------------------------------
/sample/test_ch592f_ble_hid_keyboard/devinfoservice.c:
--------------------------------------------------------------------------------
1 | /********************************** (C) COPYRIGHT *******************************
2 | * File Name : devinfoservice.c
3 | * Author : WCH
4 | * Version : V1.0
5 | * Date : 2018/12/10
6 | * Description : �豸��Ϣ����
7 | *********************************************************************************
8 | * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
9 | * Attention: This software (modified or not) and binary are used for
10 | * microcontroller manufactured by Nanjing Qinheng Microelectronics.
11 | *******************************************************************************/
12 |
13 | /*********************************************************************
14 | * INCLUDES
15 | */
16 | #include "CONFIG.h"
17 | #include "devinfoservice.h"
18 |
19 | /*********************************************************************
20 | * MACROS
21 | */
22 |
23 | /*********************************************************************
24 | * CONSTANTS
25 | */
26 |
27 | /*********************************************************************
28 | * TYPEDEFS
29 | */
30 |
31 | /*********************************************************************
32 | * GLOBAL VARIABLES
33 | */
34 | // Device information service
35 | const uint8_t devInfoServUUID[ATT_BT_UUID_SIZE] = {
36 | LO_UINT16(DEVINFO_SERV_UUID), HI_UINT16(DEVINFO_SERV_UUID)};
37 |
38 | // System ID
39 | const uint8_t devInfoSystemIdUUID[ATT_BT_UUID_SIZE] = {
40 | LO_UINT16(SYSTEM_ID_UUID), HI_UINT16(SYSTEM_ID_UUID)};
41 |
42 | // Model Number String
43 | const uint8_t devInfoModelNumberUUID[ATT_BT_UUID_SIZE] = {
44 | LO_UINT16(MODEL_NUMBER_UUID), HI_UINT16(MODEL_NUMBER_UUID)};
45 |
46 | // Serial Number String
47 | const uint8_t devInfoSerialNumberUUID[ATT_BT_UUID_SIZE] = {
48 | LO_UINT16(SERIAL_NUMBER_UUID), HI_UINT16(SERIAL_NUMBER_UUID)};
49 |
50 | // Firmware Revision String
51 | const uint8_t devInfoFirmwareRevUUID[ATT_BT_UUID_SIZE] = {
52 | LO_UINT16(FIRMWARE_REV_UUID), HI_UINT16(FIRMWARE_REV_UUID)};
53 |
54 | // Hardware Revision String
55 | const uint8_t devInfoHardwareRevUUID[ATT_BT_UUID_SIZE] = {
56 | LO_UINT16(HARDWARE_REV_UUID), HI_UINT16(HARDWARE_REV_UUID)};
57 |
58 | // Software Revision String
59 | const uint8_t devInfoSoftwareRevUUID[ATT_BT_UUID_SIZE] = {
60 | LO_UINT16(SOFTWARE_REV_UUID), HI_UINT16(SOFTWARE_REV_UUID)};
61 |
62 | // Manufacturer Name String
63 | const uint8_t devInfoMfrNameUUID[ATT_BT_UUID_SIZE] = {
64 | LO_UINT16(MANUFACTURER_NAME_UUID), HI_UINT16(MANUFACTURER_NAME_UUID)};
65 |
66 | // IEEE 11073-20601 Regulatory Certification Data List
67 | const uint8_t devInfo11073CertUUID[ATT_BT_UUID_SIZE] = {
68 | LO_UINT16(IEEE_11073_CERT_DATA_UUID), HI_UINT16(IEEE_11073_CERT_DATA_UUID)};
69 |
70 | // PnP ID
71 | const uint8_t devInfoPnpIdUUID[ATT_BT_UUID_SIZE] = {
72 | LO_UINT16(PNP_ID_UUID), HI_UINT16(PNP_ID_UUID)};
73 |
74 | /*********************************************************************
75 | * EXTERNAL VARIABLES
76 | */
77 |
78 | /*********************************************************************
79 | * EXTERNAL FUNCTIONS
80 | */
81 |
82 | /*********************************************************************
83 | * LOCAL VARIABLES
84 | */
85 |
86 | /*********************************************************************
87 | * Profile Attributes - variables
88 | */
89 |
90 | // Device Information Service attribute
91 | static const gattAttrType_t devInfoService = {ATT_BT_UUID_SIZE, devInfoServUUID};
92 |
93 | // System ID characteristic
94 | static uint8_t devInfoSystemIdProps = GATT_PROP_READ;
95 | static uint8_t devInfoSystemId[DEVINFO_SYSTEM_ID_LEN] = {0, 0, 0, 0, 0, 0, 0, 0};
96 |
97 | // Model Number String characteristic
98 | static uint8_t devInfoModelNumberProps = GATT_PROP_READ;
99 | static const uint8_t devInfoModelNumber[] = "Model Number";
100 |
101 | // Serial Number String characteristic
102 | static uint8_t devInfoSerialNumberProps = GATT_PROP_READ;
103 | static const uint8_t devInfoSerialNumber[] = "Serial Number";
104 |
105 | // Firmware Revision String characteristic
106 | static uint8_t devInfoFirmwareRevProps = GATT_PROP_READ;
107 | static const uint8_t devInfoFirmwareRev[] = "Firmware Revision";
108 |
109 | // Hardware Revision String characteristic
110 | static uint8_t devInfoHardwareRevProps = GATT_PROP_READ;
111 | static const uint8_t devInfoHardwareRev[] = "Hardware Revision";
112 |
113 | // Software Revision String characteristic
114 | static uint8_t devInfoSoftwareRevProps = GATT_PROP_READ;
115 | static const uint8_t devInfoSoftwareRev[] = "Software Revision";
116 |
117 | // Manufacturer Name String characteristic
118 | static uint8_t devInfoMfrNameProps = GATT_PROP_READ;
119 | static const uint8_t devInfoMfrName[] = "Manufacturer Name";
120 |
121 | // IEEE 11073-20601 Regulatory Certification Data List characteristic
122 | static uint8_t devInfo11073CertProps = GATT_PROP_READ;
123 | static const uint8_t devInfo11073Cert[] = {
124 | DEVINFO_11073_BODY_EXP, // authoritative body type
125 | 0x00, // authoritative body structure type
126 | // authoritative body data follows below:
127 | 'e', 'x', 'p', 'e', 'r', 'i', 'm', 'e', 'n', 't', 'a', 'l'};
128 |
129 | // System ID characteristic
130 | static uint8_t devInfoPnpIdProps = GATT_PROP_READ;
131 | static uint8_t devInfoPnpId[DEVINFO_PNP_ID_LEN] = {
132 | 1, // Vendor ID source (1=Bluetooth SIG)
133 | LO_UINT16(0x07D7), HI_UINT16(0x07D7), // Vendor ID (WCH)
134 | LO_UINT16(0x0000), HI_UINT16(0x0000), // Product ID (vendor-specific)
135 | LO_UINT16(0x0110), HI_UINT16(0x0110) // Product version (JJ.M.N)
136 | };
137 |
138 | /*********************************************************************
139 | * Profile Attributes - Table
140 | */
141 |
142 | static gattAttribute_t devInfoAttrTbl[] = {
143 | // Device Information Service
144 | {
145 | {ATT_BT_UUID_SIZE, primaryServiceUUID}, /* type */
146 | GATT_PERMIT_READ, /* permissions */
147 | 0, /* handle */
148 | (uint8_t *)&devInfoService /* pValue */
149 | },
150 |
151 | // System ID Declaration
152 | {
153 | {ATT_BT_UUID_SIZE, characterUUID},
154 | GATT_PERMIT_READ,
155 | 0,
156 | &devInfoSystemIdProps},
157 |
158 | // System ID Value
159 | {
160 | {ATT_BT_UUID_SIZE, devInfoSystemIdUUID},
161 | GATT_PERMIT_READ,
162 | 0,
163 | (uint8_t *)devInfoSystemId},
164 |
165 | // Model Number String Declaration
166 | {
167 | {ATT_BT_UUID_SIZE, characterUUID},
168 | GATT_PERMIT_READ,
169 | 0,
170 | &devInfoModelNumberProps},
171 |
172 | // Model Number Value
173 | {
174 | {ATT_BT_UUID_SIZE, devInfoModelNumberUUID},
175 | GATT_PERMIT_READ,
176 | 0,
177 | (uint8_t *)devInfoModelNumber},
178 |
179 | // Serial Number String Declaration
180 | {
181 | {ATT_BT_UUID_SIZE, characterUUID},
182 | GATT_PERMIT_READ,
183 | 0,
184 | &devInfoSerialNumberProps},
185 |
186 | // Serial Number Value
187 | {
188 | {ATT_BT_UUID_SIZE, devInfoSerialNumberUUID},
189 | GATT_PERMIT_READ,
190 | 0,
191 | (uint8_t *)devInfoSerialNumber},
192 |
193 | // Firmware Revision String Declaration
194 | {
195 | {ATT_BT_UUID_SIZE, characterUUID},
196 | GATT_PERMIT_READ,
197 | 0,
198 | &devInfoFirmwareRevProps},
199 |
200 | // Firmware Revision Value
201 | {
202 | {ATT_BT_UUID_SIZE, devInfoFirmwareRevUUID},
203 | GATT_PERMIT_READ,
204 | 0,
205 | (uint8_t *)devInfoFirmwareRev},
206 |
207 | // Hardware Revision String Declaration
208 | {
209 | {ATT_BT_UUID_SIZE, characterUUID},
210 | GATT_PERMIT_READ,
211 | 0,
212 | &devInfoHardwareRevProps},
213 |
214 | // Hardware Revision Value
215 | {
216 | {ATT_BT_UUID_SIZE, devInfoHardwareRevUUID},
217 | GATT_PERMIT_READ,
218 | 0,
219 | (uint8_t *)devInfoHardwareRev},
220 |
221 | // Software Revision String Declaration
222 | {
223 | {ATT_BT_UUID_SIZE, characterUUID},
224 | GATT_PERMIT_READ,
225 | 0,
226 | &devInfoSoftwareRevProps},
227 |
228 | // Software Revision Value
229 | {
230 | {ATT_BT_UUID_SIZE, devInfoSoftwareRevUUID},
231 | GATT_PERMIT_READ,
232 | 0,
233 | (uint8_t *)devInfoSoftwareRev},
234 |
235 | // Manufacturer Name String Declaration
236 | {
237 | {ATT_BT_UUID_SIZE, characterUUID},
238 | GATT_PERMIT_READ,
239 | 0,
240 | &devInfoMfrNameProps},
241 |
242 | // Manufacturer Name Value
243 | {
244 | {ATT_BT_UUID_SIZE, devInfoMfrNameUUID},
245 | GATT_PERMIT_READ,
246 | 0,
247 | (uint8_t *)devInfoMfrName},
248 |
249 | // IEEE 11073-20601 Regulatory Certification Data List Declaration
250 | {
251 | {ATT_BT_UUID_SIZE, characterUUID},
252 | GATT_PERMIT_READ,
253 | 0,
254 | &devInfo11073CertProps},
255 |
256 | // IEEE 11073-20601 Regulatory Certification Data List Value
257 | {
258 | {ATT_BT_UUID_SIZE, devInfo11073CertUUID},
259 | GATT_PERMIT_READ,
260 | 0,
261 | (uint8_t *)devInfo11073Cert},
262 |
263 | // PnP ID Declaration
264 | {
265 | {ATT_BT_UUID_SIZE, characterUUID},
266 | GATT_PERMIT_READ,
267 | 0,
268 | &devInfoPnpIdProps},
269 |
270 | // PnP ID Value
271 | {
272 | {ATT_BT_UUID_SIZE, devInfoPnpIdUUID},
273 | GATT_PERMIT_READ,
274 | 0,
275 | (uint8_t *)devInfoPnpId}};
276 |
277 | /*********************************************************************
278 | * LOCAL FUNCTIONS
279 | */
280 | static bStatus_t devInfo_ReadAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
281 | uint8_t *pValue, uint16_t *pLen, uint16_t offset, uint16_t maxLen, uint8_t method);
282 |
283 | /*********************************************************************
284 | * PROFILE CALLBACKS
285 | */
286 | // Device Info Service Callbacks
287 | gattServiceCBs_t devInfoCBs = {
288 | devInfo_ReadAttrCB, // Read callback function pointer
289 | NULL, // Write callback function pointer
290 | NULL // Authorization callback function pointer
291 | };
292 |
293 | /*********************************************************************
294 | * NETWORK LAYER CALLBACKS
295 | */
296 |
297 | /*********************************************************************
298 | * PUBLIC FUNCTIONS
299 | */
300 |
301 | /*********************************************************************
302 | * @fn DevInfo_AddService
303 | *
304 | * @brief Initializes the Device Information service by registering
305 | * GATT attributes with the GATT server.
306 | *
307 | * @return Success or Failure
308 | */
309 | bStatus_t DevInfo_AddService(void)
310 | {
311 | // Register GATT attribute list and CBs with GATT Server App
312 | return GATTServApp_RegisterService(devInfoAttrTbl,
313 | GATT_NUM_ATTRS(devInfoAttrTbl),
314 | GATT_MAX_ENCRYPT_KEY_SIZE,
315 | &devInfoCBs);
316 | }
317 |
318 | /*********************************************************************
319 | * @fn DevInfo_SetParameter
320 | *
321 | * @brief Set a Device Information parameter.
322 | *
323 | * @param param - Profile parameter ID
324 | * @param len - length of data to write
325 | * @param value - pointer to data to write. This is dependent on
326 | * the parameter ID and WILL be cast to the appropriate
327 | * data type (example: data type of uint16_t will be cast to
328 | * uint16_t pointer).
329 | *
330 | * @return bStatus_t
331 | */
332 | bStatus_t DevInfo_SetParameter(uint8_t param, uint8_t len, void *value)
333 | {
334 | bStatus_t ret = SUCCESS;
335 |
336 | switch(param)
337 | {
338 | case DEVINFO_SYSTEM_ID:
339 | tmos_memcpy(devInfoSystemId, value, len);
340 | break;
341 |
342 | default:
343 | ret = INVALIDPARAMETER;
344 | break;
345 | }
346 |
347 | return (ret);
348 | }
349 |
350 | /*********************************************************************
351 | * @fn DevInfo_GetParameter
352 | *
353 | * @brief Get a Device Information parameter.
354 | *
355 | * @param param - Profile parameter ID
356 | * @param value - pointer to data to get. This is dependent on
357 | * the parameter ID and WILL be cast to the appropriate
358 | * data type (example: data type of uint16_t will be cast to
359 | * uint16_t pointer).
360 | *
361 | * @return bStatus_t
362 | */
363 | bStatus_t DevInfo_GetParameter(uint8_t param, void *value)
364 | {
365 | bStatus_t ret = SUCCESS;
366 |
367 | switch(param)
368 | {
369 | case DEVINFO_SYSTEM_ID:
370 | tmos_memcpy(value, devInfoSystemId, sizeof(devInfoSystemId));
371 | break;
372 |
373 | case DEVINFO_MODEL_NUMBER:
374 | tmos_memcpy(value, devInfoModelNumber, sizeof(devInfoModelNumber));
375 | break;
376 | case DEVINFO_SERIAL_NUMBER:
377 | tmos_memcpy(value, devInfoSerialNumber, sizeof(devInfoSerialNumber));
378 | break;
379 |
380 | case DEVINFO_FIRMWARE_REV:
381 | tmos_memcpy(value, devInfoFirmwareRev, sizeof(devInfoFirmwareRev));
382 | break;
383 |
384 | case DEVINFO_HARDWARE_REV:
385 | tmos_memcpy(value, devInfoHardwareRev, sizeof(devInfoHardwareRev));
386 | break;
387 |
388 | case DEVINFO_SOFTWARE_REV:
389 | tmos_memcpy(value, devInfoSoftwareRev, sizeof(devInfoSoftwareRev));
390 | break;
391 |
392 | case DEVINFO_MANUFACTURER_NAME:
393 | tmos_memcpy(value, devInfoMfrName, sizeof(devInfoMfrName));
394 | break;
395 |
396 | case DEVINFO_11073_CERT_DATA:
397 | tmos_memcpy(value, devInfo11073Cert, sizeof(devInfo11073Cert));
398 | break;
399 |
400 | case DEVINFO_PNP_ID:
401 | tmos_memcpy(value, devInfoPnpId, sizeof(devInfoPnpId));
402 | break;
403 |
404 | default:
405 | ret = INVALIDPARAMETER;
406 | break;
407 | }
408 |
409 | return (ret);
410 | }
411 |
412 | /*********************************************************************
413 | * @fn devInfo_ReadAttrCB
414 | *
415 | * @brief Read an attribute.
416 | *
417 | * @param connHandle - connection message was received on
418 | * @param pAttr - pointer to attribute
419 | * @param pValue - pointer to data to be read
420 | * @param pLen - length of data to be read
421 | * @param offset - offset of the first octet to be read
422 | * @param maxLen - maximum length of data to be read
423 | *
424 | * @return Success or Failure
425 | */
426 | static bStatus_t devInfo_ReadAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
427 | uint8_t *pValue, uint16_t *pLen, uint16_t offset, uint16_t maxLen, uint8_t method)
428 | {
429 | bStatus_t status = SUCCESS;
430 | uint16_t uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]);
431 |
432 | switch(uuid)
433 | {
434 | case SYSTEM_ID_UUID:
435 | // verify offset
436 | if(offset >= sizeof(devInfoSystemId))
437 | {
438 | status = ATT_ERR_INVALID_OFFSET;
439 | }
440 | else
441 | {
442 | // determine read length
443 | *pLen = MIN(maxLen, (sizeof(devInfoSystemId) - offset));
444 |
445 | // copy data
446 | tmos_memcpy(pValue, &devInfoSystemId[offset], *pLen);
447 | }
448 | break;
449 |
450 | case MODEL_NUMBER_UUID:
451 | // verify offset
452 | if(offset >= (sizeof(devInfoModelNumber) - 1))
453 | {
454 | status = ATT_ERR_INVALID_OFFSET;
455 | }
456 | else
457 | {
458 | // determine read length (exclude null terminating character)
459 | *pLen = MIN(maxLen, ((sizeof(devInfoModelNumber) - 1) - offset));
460 |
461 | // copy data
462 | tmos_memcpy(pValue, &devInfoModelNumber[offset], *pLen);
463 | }
464 | break;
465 |
466 | case SERIAL_NUMBER_UUID:
467 | // verify offset
468 | if(offset >= (sizeof(devInfoSerialNumber) - 1))
469 | {
470 | status = ATT_ERR_INVALID_OFFSET;
471 | }
472 | else
473 | {
474 | // determine read length (exclude null terminating character)
475 | *pLen = MIN(maxLen, ((sizeof(devInfoSerialNumber) - 1) - offset));
476 |
477 | // copy data
478 | tmos_memcpy(pValue, &devInfoSerialNumber[offset], *pLen);
479 | }
480 | break;
481 |
482 | case FIRMWARE_REV_UUID:
483 | // verify offset
484 | if(offset >= (sizeof(devInfoFirmwareRev) - 1))
485 | {
486 | status = ATT_ERR_INVALID_OFFSET;
487 | }
488 | else
489 | {
490 | // determine read length (exclude null terminating character)
491 | *pLen = MIN(maxLen, ((sizeof(devInfoFirmwareRev) - 1) - offset));
492 |
493 | // copy data
494 | tmos_memcpy(pValue, &devInfoFirmwareRev[offset], *pLen);
495 | }
496 | break;
497 |
498 | case HARDWARE_REV_UUID:
499 | // verify offset
500 | if(offset >= (sizeof(devInfoHardwareRev) - 1))
501 | {
502 | status = ATT_ERR_INVALID_OFFSET;
503 | }
504 | else
505 | {
506 | // determine read length (exclude null terminating character)
507 | *pLen = MIN(maxLen, ((sizeof(devInfoHardwareRev) - 1) - offset));
508 |
509 | // copy data
510 | tmos_memcpy(pValue, &devInfoHardwareRev[offset], *pLen);
511 | }
512 | break;
513 |
514 | case SOFTWARE_REV_UUID:
515 | // verify offset
516 | if(offset >= (sizeof(devInfoSoftwareRev) - 1))
517 | {
518 | status = ATT_ERR_INVALID_OFFSET;
519 | }
520 | else
521 | {
522 | // determine read length (exclude null terminating character)
523 | *pLen = MIN(maxLen, ((sizeof(devInfoSoftwareRev) - 1) - offset));
524 |
525 | // copy data
526 | tmos_memcpy(pValue, &devInfoSoftwareRev[offset], *pLen);
527 | }
528 | break;
529 |
530 | case MANUFACTURER_NAME_UUID:
531 | // verify offset
532 | if(offset >= (sizeof(devInfoMfrName) - 1))
533 | {
534 | status = ATT_ERR_INVALID_OFFSET;
535 | }
536 | else
537 | {
538 | // determine read length (exclude null terminating character)
539 | *pLen = MIN(maxLen, ((sizeof(devInfoMfrName) - 1) - offset));
540 |
541 | // copy data
542 | tmos_memcpy(pValue, &devInfoMfrName[offset], *pLen);
543 | }
544 | break;
545 |
546 | case IEEE_11073_CERT_DATA_UUID:
547 | // verify offset
548 | if(offset >= sizeof(devInfo11073Cert))
549 | {
550 | status = ATT_ERR_INVALID_OFFSET;
551 | }
552 | else
553 | {
554 | // determine read length
555 | *pLen = MIN(maxLen, (sizeof(devInfo11073Cert) - offset));
556 |
557 | // copy data
558 | tmos_memcpy(pValue, &devInfo11073Cert[offset], *pLen);
559 | }
560 | break;
561 |
562 | case PNP_ID_UUID:
563 | // verify offset
564 | if(offset >= sizeof(devInfoPnpId))
565 | {
566 | status = ATT_ERR_INVALID_OFFSET;
567 | }
568 | else
569 | {
570 | // determine read length
571 | *pLen = MIN(maxLen, (sizeof(devInfoPnpId) - offset));
572 |
573 | // copy data
574 | tmos_memcpy(pValue, &devInfoPnpId[offset], *pLen);
575 | }
576 | break;
577 |
578 | default:
579 | *pLen = 0;
580 | status = ATT_ERR_ATTR_NOT_FOUND;
581 | break;
582 | }
583 |
584 | return (status);
585 | }
586 |
587 | /*********************************************************************
588 | *********************************************************************/
589 |
--------------------------------------------------------------------------------
/sample/test_ch592f_ble_hid_keyboard/devinfoservice.h:
--------------------------------------------------------------------------------
1 | /********************************** (C) COPYRIGHT *******************************
2 | * File Name : devinfoservice.h
3 | * Author : WCH
4 | * Version : V1.0
5 | * Date : 2018/12/11
6 | * Description :
7 | *********************************************************************************
8 | * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
9 | * Attention: This software (modified or not) and binary are used for
10 | * microcontroller manufactured by Nanjing Qinheng Microelectronics.
11 | *******************************************************************************/
12 |
13 | #ifndef DEVINFOSERVICE_H
14 | #define DEVINFOSERVICE_H
15 |
16 | #ifdef __cplusplus
17 | extern "C" {
18 | #endif
19 |
20 | /*********************************************************************
21 | * INCLUDES
22 | */
23 |
24 | /*********************************************************************
25 | * CONSTANTS
26 | */
27 |
28 | // Device Information Service Parameters
29 | #define DEVINFO_SYSTEM_ID 0
30 | #define DEVINFO_MODEL_NUMBER 1
31 | #define DEVINFO_SERIAL_NUMBER 2
32 | #define DEVINFO_FIRMWARE_REV 3
33 | #define DEVINFO_HARDWARE_REV 4
34 | #define DEVINFO_SOFTWARE_REV 5
35 | #define DEVINFO_MANUFACTURER_NAME 6
36 | #define DEVINFO_11073_CERT_DATA 7
37 | #define DEVINFO_PNP_ID 8
38 |
39 | // IEEE 11073 authoritative body values
40 | #define DEVINFO_11073_BODY_EMPTY 0
41 | #define DEVINFO_11073_BODY_IEEE 1
42 | #define DEVINFO_11073_BODY_CONTINUA 2
43 | #define DEVINFO_11073_BODY_EXP 254
44 |
45 | // System ID length
46 | #define DEVINFO_SYSTEM_ID_LEN 8
47 |
48 | // PnP ID length
49 | #define DEVINFO_PNP_ID_LEN 7
50 |
51 | /*********************************************************************
52 | * TYPEDEFS
53 | */
54 |
55 | /*********************************************************************
56 | * MACROS
57 | */
58 |
59 | /*********************************************************************
60 | * Profile Callbacks
61 | */
62 |
63 | /*********************************************************************
64 | * API FUNCTIONS
65 | */
66 |
67 | /*
68 | * DevInfo_AddService- Initializes the Device Information service by registering
69 | * GATT attributes with the GATT server.
70 | *
71 | */
72 |
73 | extern bStatus_t DevInfo_AddService(void);
74 |
75 | /*********************************************************************
76 | * @fn DevInfo_SetParameter
77 | *
78 | * @brief Set a Device Information parameter.
79 | *
80 | * @param param - Profile parameter ID
81 | * @param len - length of data to right
82 | * @param value - pointer to data to write. This is dependent on
83 | * the parameter ID and WILL be cast to the appropriate
84 | * data type (example: data type of uint16_t will be cast to
85 | * uint16_t pointer).
86 | *
87 | * @return bStatus_t
88 | */
89 | bStatus_t DevInfo_SetParameter(uint8_t param, uint8_t len, void *value);
90 |
91 | /*
92 | * DevInfo_GetParameter - Get a Device Information parameter.
93 | *
94 | * param - Profile parameter ID
95 | * value - pointer to data to write. This is dependent on
96 | * the parameter ID and WILL be cast to the appropriate
97 | * data type (example: data type of uint16_t will be cast to
98 | * uint16_t pointer).
99 | */
100 | extern bStatus_t DevInfo_GetParameter(uint8_t param, void *value);
101 |
102 | /*********************************************************************
103 | *********************************************************************/
104 |
105 | #ifdef __cplusplus
106 | }
107 | #endif
108 |
109 | #endif /* DEVINFOSERVICE_H */
110 |
--------------------------------------------------------------------------------
/sample/test_ch592f_ble_hid_keyboard/hidkbd.c:
--------------------------------------------------------------------------------
1 | /********************************** (C) COPYRIGHT *******************************
2 | * File Name : hidkbd.c
3 | * Author : WCH
4 | * Version : V1.0
5 | * Date : 2018/12/10
6 | * Description : ��������Ӧ�ó���ʼ���㲥���Ӳ�����Ȼ��㲥��ֱ������������ʱ�ϴ���ֵ
7 | *********************************************************************************
8 | * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
9 | * Attention: This software (modified or not) and binary are used for
10 | * microcontroller manufactured by Nanjing Qinheng Microelectronics.
11 | *******************************************************************************/
12 |
13 | /*********************************************************************
14 | * INCLUDES
15 | */
16 | #include "CONFIG.h"
17 | #include "devinfoservice.h"
18 | #include "battservice.h"
19 | #include "hidkbdservice.h"
20 | #include "hiddev.h"
21 | #include "hidkbd.h"
22 |
23 | /*********************************************************************
24 | * MACROS
25 | */
26 | // HID keyboard input report length
27 | #define HID_KEYBOARD_IN_RPT_LEN 8
28 |
29 | // HID LED output report length
30 | #define HID_LED_OUT_RPT_LEN 1
31 |
32 | /*********************************************************************
33 | * CONSTANTS
34 | */
35 | // Param update delay
36 | #define START_PARAM_UPDATE_EVT_DELAY 12800
37 |
38 | // Param update delay
39 | #define START_PHY_UPDATE_DELAY 1600
40 |
41 | // HID idle timeout in msec; set to zero to disable timeout
42 | #define DEFAULT_HID_IDLE_TIMEOUT 60000
43 |
44 | // Minimum connection interval (units of 1.25ms)
45 | #define DEFAULT_DESIRED_MIN_CONN_INTERVAL 8
46 |
47 | // Maximum connection interval (units of 1.25ms)
48 | #define DEFAULT_DESIRED_MAX_CONN_INTERVAL 8
49 |
50 | // Slave latency to use if parameter update request
51 | #define DEFAULT_DESIRED_SLAVE_LATENCY 0
52 |
53 | // Supervision timeout value (units of 10ms)
54 | #define DEFAULT_DESIRED_CONN_TIMEOUT 500
55 |
56 | // Default passcode
57 | #define DEFAULT_PASSCODE 0
58 |
59 | // Default GAP pairing mode
60 | #define DEFAULT_PAIRING_MODE GAPBOND_PAIRING_MODE_WAIT_FOR_REQ
61 |
62 | // Default MITM mode (TRUE to require passcode or OOB when pairing)
63 | #define DEFAULT_MITM_MODE FALSE
64 |
65 | // Default bonding mode, TRUE to bond
66 | #define DEFAULT_BONDING_MODE TRUE
67 |
68 | // Default GAP bonding I/O capabilities
69 | #define DEFAULT_IO_CAPABILITIES GAPBOND_IO_CAP_NO_INPUT_NO_OUTPUT
70 |
71 | // Battery level is critical when it is less than this %
72 | #define DEFAULT_BATT_CRITICAL_LEVEL 6
73 |
74 | /*********************************************************************
75 | * TYPEDEFS
76 | */
77 |
78 | /*********************************************************************
79 | * GLOBAL VARIABLES
80 | */
81 |
82 | // Task ID
83 | static uint8_t hidEmuTaskId = INVALID_TASK_ID;
84 |
85 | /*********************************************************************
86 | * EXTERNAL VARIABLES
87 | */
88 |
89 | /*********************************************************************
90 | * EXTERNAL FUNCTIONS
91 | */
92 |
93 | /*********************************************************************
94 | * LOCAL VARIABLES
95 | */
96 |
97 | // GAP Profile - Name attribute for SCAN RSP data
98 | static uint8_t scanRspData[] = {
99 | 0x0F, // length of this data
100 | GAP_ADTYPE_LOCAL_NAME_COMPLETE, // AD Type = Complete local name
101 | 'C',
102 | 'H',
103 | '5',
104 | '9',
105 | '2',
106 | 'F',
107 | ' ',
108 | 'H',
109 | 'I',
110 | 'D',
111 | ' ',
112 | 'K',
113 | 'e',
114 | 'y', // connection interval range
115 | 0x05, // length of this data
116 | GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE,
117 | LO_UINT16(DEFAULT_DESIRED_MIN_CONN_INTERVAL), // 100ms
118 | HI_UINT16(DEFAULT_DESIRED_MIN_CONN_INTERVAL),
119 | LO_UINT16(DEFAULT_DESIRED_MAX_CONN_INTERVAL), // 1s
120 | HI_UINT16(DEFAULT_DESIRED_MAX_CONN_INTERVAL),
121 |
122 | // service UUIDs
123 | 0x05, // length of this data
124 | GAP_ADTYPE_16BIT_MORE,
125 | LO_UINT16(HID_SERV_UUID),
126 | HI_UINT16(HID_SERV_UUID),
127 | LO_UINT16(BATT_SERV_UUID),
128 | HI_UINT16(BATT_SERV_UUID),
129 |
130 | // Tx power level
131 | 0x02, // length of this data
132 | GAP_ADTYPE_POWER_LEVEL,
133 | 0 // 0dBm
134 | };
135 |
136 | // Advertising data
137 | static uint8_t advertData[] = {
138 | // flags
139 | 0x02, // length of this data
140 | GAP_ADTYPE_FLAGS,
141 | GAP_ADTYPE_FLAGS_LIMITED | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED,
142 |
143 | // appearance
144 | 0x03, // length of this data
145 | GAP_ADTYPE_APPEARANCE,
146 | LO_UINT16(GAP_APPEARE_HID_KEYBOARD),
147 | HI_UINT16(GAP_APPEARE_HID_KEYBOARD)};
148 |
149 | // Device name attribute value
150 | static CONST uint8_t attDeviceName[GAP_DEVICE_NAME_LEN] = "CH592F HID Key";
151 |
152 | // HID Dev configuration
153 | static hidDevCfg_t hidEmuCfg = {
154 | DEFAULT_HID_IDLE_TIMEOUT, // Idle timeout
155 | HID_FEATURE_FLAGS // HID feature flags
156 | };
157 |
158 | static uint16_t hidEmuConnHandle = GAP_CONNHANDLE_INIT;
159 |
160 | /*********************************************************************
161 | * LOCAL FUNCTIONS
162 | */
163 |
164 | static void hidEmu_ProcessTMOSMsg(tmos_event_hdr_t *pMsg);
165 | extern void hidEmuSendKbdReport(uint8_t keycode);
166 | extern void hidEmuSendKbdReport2(uint8_t keycode);
167 | static uint8_t hidEmuRcvReport(uint8_t len, uint8_t *pData);
168 | static uint8_t hidEmuRptCB(uint8_t id, uint8_t type, uint16_t uuid,
169 | uint8_t oper, uint16_t *pLen, uint8_t *pData);
170 | static void hidEmuEvtCB(uint8_t evt);
171 | static void hidEmuStateCB(gapRole_States_t newState, gapRoleEvent_t *pEvent);
172 |
173 | /*********************************************************************
174 | * PROFILE CALLBACKS
175 | */
176 |
177 | static hidDevCB_t hidEmuHidCBs = {
178 | hidEmuRptCB,
179 | hidEmuEvtCB,
180 | NULL,
181 | hidEmuStateCB};
182 |
183 | /*********************************************************************
184 | * PUBLIC FUNCTIONS
185 | */
186 |
187 | /*********************************************************************
188 | * @fn HidEmu_Init
189 | *
190 | * @brief Initialization function for the HidEmuKbd App Task.
191 | * This is called during initialization and should contain
192 | * any application specific initialization (ie. hardware
193 | * initialization/setup, table initialization, power up
194 | * notificaiton ... ).
195 | *
196 | * @param task_id - the ID assigned by TMOS. This ID should be
197 | * used to send messages and set timers.
198 | *
199 | * @return none
200 | */
201 | void HidEmu_Init()
202 | {
203 | hidEmuTaskId = TMOS_ProcessEventRegister(HidEmu_ProcessEvent);
204 |
205 | // Setup the GAP Peripheral Role Profile
206 | {
207 | uint8_t initial_advertising_enable = TRUE;
208 |
209 | // Set the GAP Role Parameters
210 | GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &initial_advertising_enable);
211 |
212 | GAPRole_SetParameter(GAPROLE_ADVERT_DATA, sizeof(advertData), advertData);
213 | GAPRole_SetParameter(GAPROLE_SCAN_RSP_DATA, sizeof(scanRspData), scanRspData);
214 | }
215 |
216 | // Set the GAP Characteristics
217 | GGS_SetParameter(GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, (void *)attDeviceName);
218 |
219 | // Setup the GAP Bond Manager
220 | {
221 | uint32_t passkey = DEFAULT_PASSCODE;
222 | uint8_t pairMode = DEFAULT_PAIRING_MODE;
223 | uint8_t mitm = DEFAULT_MITM_MODE;
224 | uint8_t ioCap = DEFAULT_IO_CAPABILITIES;
225 | uint8_t bonding = DEFAULT_BONDING_MODE;
226 | GAPBondMgr_SetParameter(GAPBOND_PERI_DEFAULT_PASSCODE, sizeof(uint32_t), &passkey);
227 | GAPBondMgr_SetParameter(GAPBOND_PERI_PAIRING_MODE, sizeof(uint8_t), &pairMode);
228 | GAPBondMgr_SetParameter(GAPBOND_PERI_MITM_PROTECTION, sizeof(uint8_t), &mitm);
229 | GAPBondMgr_SetParameter(GAPBOND_PERI_IO_CAPABILITIES, sizeof(uint8_t), &ioCap);
230 | GAPBondMgr_SetParameter(GAPBOND_PERI_BONDING_ENABLED, sizeof(uint8_t), &bonding);
231 | }
232 |
233 | // Setup Battery Characteristic Values
234 | {
235 | uint8_t critical = DEFAULT_BATT_CRITICAL_LEVEL;
236 | Batt_SetParameter(BATT_PARAM_CRITICAL_LEVEL, sizeof(uint8_t), &critical);
237 | }
238 |
239 | // Set up HID keyboard service
240 | Hid_AddService();
241 |
242 | // Register for HID Dev callback
243 | HidDev_Register(&hidEmuCfg, &hidEmuHidCBs);
244 |
245 | // Setup a delayed profile startup
246 | tmos_set_event(hidEmuTaskId, START_DEVICE_EVT);
247 | }
248 |
249 | /*********************************************************************
250 | * @fn HidEmu_ProcessEvent
251 | *
252 | * @brief HidEmuKbd Application Task event processor. This function
253 | * is called to process all events for the task. Events
254 | * include timers, messages and any other user defined events.
255 | *
256 | * @param task_id - The TMOS assigned task ID.
257 | * @param events - events to process. This is a bit map and can
258 | * contain more than one event.
259 | *
260 | * @return events not processed
261 | */
262 | uint16_t HidEmu_ProcessEvent(uint8_t task_id, uint16_t events)
263 | {
264 | static uint8_t send_char = 4;
265 |
266 | if(events & SYS_EVENT_MSG)
267 | {
268 | uint8_t *pMsg;
269 |
270 | if((pMsg = tmos_msg_receive(hidEmuTaskId)) != NULL)
271 | {
272 | hidEmu_ProcessTMOSMsg((tmos_event_hdr_t *)pMsg);
273 |
274 | // Release the TMOS message
275 | tmos_msg_deallocate(pMsg);
276 | }
277 |
278 | // return unprocessed events
279 | return (events ^ SYS_EVENT_MSG);
280 | }
281 |
282 | if(events & START_DEVICE_EVT)
283 | {
284 | return (events ^ START_DEVICE_EVT);
285 | }
286 |
287 | if(events & START_PARAM_UPDATE_EVT)
288 | {
289 | // Send connect param update request
290 | GAPRole_PeripheralConnParamUpdateReq(hidEmuConnHandle,
291 | DEFAULT_DESIRED_MIN_CONN_INTERVAL,
292 | DEFAULT_DESIRED_MAX_CONN_INTERVAL,
293 | DEFAULT_DESIRED_SLAVE_LATENCY,
294 | DEFAULT_DESIRED_CONN_TIMEOUT,
295 | hidEmuTaskId);
296 |
297 | return (events ^ START_PARAM_UPDATE_EVT);
298 | }
299 |
300 | if(events & START_PHY_UPDATE_EVT)
301 | {
302 | // start phy update
303 | PRINT("Send Phy Update %x...\n", GAPRole_UpdatePHY(hidEmuConnHandle, 0,
304 | GAP_PHY_BIT_LE_2M, GAP_PHY_BIT_LE_2M, 0));
305 |
306 | return (events ^ START_PHY_UPDATE_EVT);
307 | }
308 |
309 | if(events & START_REPORT_EVT){
310 | int i = 0;
311 | // Button 1
312 | if(GPIOB_ReadPortPin(GPIO_Pin_12) == 0){
313 | GPIOA_ResetBits(GPIO_Pin_8);
314 | while(GPIOB_ReadPortPin(GPIO_Pin_12) == 0){
315 | delay(1);
316 | i++;
317 | }
318 | if(i > 500)
319 | hidEmuSendKbdReport2(HID_KEYBOARD_A);
320 | else
321 | hidEmuSendKbdReport(HID_KEYBOARD_A);
322 | hidEmuSendKbdReport(0x00);
323 | // Button 2
324 | }else if(GPIOB_ReadPortPin(GPIO_Pin_7) == 0){
325 | GPIOA_ResetBits(GPIO_Pin_8);
326 | while(GPIOB_ReadPortPin(GPIO_Pin_7) == 0){
327 | delay(1);
328 | i++;
329 | }
330 | if(i > 500)
331 | hidEmuSendKbdReport2(HID_KEYBOARD_B);
332 | else
333 | hidEmuSendKbdReport(HID_KEYBOARD_B);
334 | hidEmuSendKbdReport(0x00);
335 | // Button 3
336 | }else if(GPIOB_ReadPortPin(GPIO_Pin_22) == 0){
337 | GPIOA_ResetBits(GPIO_Pin_8);
338 | while(GPIOB_ReadPortPin(GPIO_Pin_22) == 0){
339 | delay(1);
340 | i++;
341 | }
342 | if(i > 500)
343 | hidEmuSendKbdReport2(HID_KEYBOARD_C);
344 | else
345 | hidEmuSendKbdReport(HID_KEYBOARD_C);
346 | hidEmuSendKbdReport(0x00);
347 | }else{
348 | GPIOA_SetBits(GPIO_Pin_8);
349 | }
350 |
351 | tmos_start_task(hidEmuTaskId, START_REPORT_EVT, 0);
352 | return (events ^ START_REPORT_EVT);
353 | }
354 | return 0;
355 | }
356 | void sendStrKey(char *s){
357 | // for(int i = 0; i < sizeof(s); i++){
358 | for(int i = 0; i < 12; i++){
359 | // hidEmuSendKbdReport(HID_KEYBOARD_0);
360 | char2keycode(s[i]);
361 | hidEmuSendKbdReport(0x00);
362 | tmos_start_task(hidEmuTaskId, START_REPORT_EVT, 0);
363 | }
364 | hidEmuSendKbdReport(0x00);
365 | }
366 |
367 | /*********************************************************************
368 | * @fn hidEmu_ProcessTMOSMsg
369 | *
370 | * @brief Process an incoming task message.
371 | *
372 | * @param pMsg - message to process
373 | *
374 | * @return none
375 | */
376 | static void hidEmu_ProcessTMOSMsg(tmos_event_hdr_t *pMsg)
377 | {
378 | switch(pMsg->event)
379 | {
380 | default:
381 | break;
382 | }
383 | }
384 |
385 | /*********************************************************************
386 | * @fn hidEmuSendKbdReport
387 | *
388 | * @brief Build and send a HID keyboard report.
389 | *
390 | * @param keycode - HID keycode.
391 | *
392 | * @return none
393 | */
394 | void hidEmuSendKbdReport(uint8_t keycode)
395 | {
396 | uint8_t buf[HID_KEYBOARD_IN_RPT_LEN];
397 |
398 | buf[0] = 0; // Modifier keys
399 | // bit0 Left Control 0x01
400 | // bit1 Left Shift 0x02
401 | // bit2 Left Alt 0x04
402 | // bit3 Left GUI 0x08
403 | // bit4 Right Control 0x10
404 | // bit5 Right Shift 0x20
405 | // bit6 Right Alt 0x40
406 | // bit7 Right GUI 0x80
407 | buf[1] = 0; // Reserved
408 | buf[2] = keycode; // Keycode 1
409 | buf[3] = 0; // Keycode 2
410 | buf[4] = 0; // Keycode 3
411 | buf[5] = 0; // Keycode 4
412 | buf[6] = 0; // Keycode 5
413 | buf[7] = 0; // Keycode 6
414 |
415 | HidDev_Report(HID_RPT_ID_KEY_IN, HID_REPORT_TYPE_INPUT,
416 | HID_KEYBOARD_IN_RPT_LEN, buf);
417 | }
418 | void hidEmuSendKbdReport2(uint8_t keycode)
419 | {
420 | uint8_t buf[HID_KEYBOARD_IN_RPT_LEN];
421 |
422 | buf[0] = 0x02; // Modifier keys
423 | buf[1] = 0; // Reserved
424 | buf[2] = keycode; // Keycode 1
425 | buf[3] = 0; // Keycode 2
426 | buf[4] = 0; // Keycode 3
427 | buf[5] = 0; // Keycode 4
428 | buf[6] = 0; // Keycode 5
429 | buf[7] = 0; // Keycode 6
430 |
431 | HidDev_Report(HID_RPT_ID_KEY_IN, HID_REPORT_TYPE_INPUT,
432 | HID_KEYBOARD_IN_RPT_LEN, buf);
433 | }
434 |
435 | /*********************************************************************
436 | * @fn hidEmuStateCB
437 | *
438 | * @brief GAP state change callback.
439 | *
440 | * @param newState - new state
441 | *
442 | * @return none
443 | */
444 | static void hidEmuStateCB(gapRole_States_t newState, gapRoleEvent_t *pEvent)
445 | {
446 | switch(newState & GAPROLE_STATE_ADV_MASK)
447 | {
448 | case GAPROLE_STARTED:
449 | {
450 | uint8_t ownAddr[6];
451 | GAPRole_GetParameter(GAPROLE_BD_ADDR, ownAddr);
452 | GAP_ConfigDeviceAddr(ADDRTYPE_STATIC, ownAddr);
453 | PRINT("Initialized..\n");
454 | }
455 | break;
456 |
457 | case GAPROLE_ADVERTISING:
458 | if(pEvent->gap.opcode == GAP_MAKE_DISCOVERABLE_DONE_EVENT)
459 | {
460 | PRINT("Advertising..\n");
461 | }
462 | break;
463 |
464 | case GAPROLE_CONNECTED:
465 | if(pEvent->gap.opcode == GAP_LINK_ESTABLISHED_EVENT)
466 | {
467 | gapEstLinkReqEvent_t *event = (gapEstLinkReqEvent_t *)pEvent;
468 |
469 | // get connection handle
470 | hidEmuConnHandle = event->connectionHandle;
471 | tmos_start_task(hidEmuTaskId, START_PARAM_UPDATE_EVT, START_PARAM_UPDATE_EVT_DELAY);
472 | PRINT("Connected..\n");
473 | }
474 | break;
475 |
476 | case GAPROLE_CONNECTED_ADV:
477 | if(pEvent->gap.opcode == GAP_MAKE_DISCOVERABLE_DONE_EVENT)
478 | {
479 | PRINT("Connected Advertising..\n");
480 | }
481 | break;
482 |
483 | case GAPROLE_WAITING:
484 | if(pEvent->gap.opcode == GAP_END_DISCOVERABLE_DONE_EVENT)
485 | {
486 | PRINT("Waiting for advertising..\n");
487 | }
488 | else if(pEvent->gap.opcode == GAP_LINK_TERMINATED_EVENT)
489 | {
490 | PRINT("Disconnected.. Reason:%x\n", pEvent->linkTerminate.reason);
491 | }
492 | else if(pEvent->gap.opcode == GAP_LINK_ESTABLISHED_EVENT)
493 | {
494 | PRINT("Advertising timeout..\n");
495 | }
496 | // Enable advertising
497 | {
498 | uint8_t initial_advertising_enable = TRUE;
499 | // Set the GAP Role Parameters
500 | GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &initial_advertising_enable);
501 | }
502 | break;
503 |
504 | case GAPROLE_ERROR:
505 | PRINT("Error %x ..\n", pEvent->gap.opcode);
506 | break;
507 |
508 | default:
509 | break;
510 | }
511 | }
512 |
513 | /*********************************************************************
514 | * @fn hidEmuRcvReport
515 | *
516 | * @brief Process an incoming HID keyboard report.
517 | *
518 | * @param len - Length of report.
519 | * @param pData - Report data.
520 | *
521 | * @return status
522 | */
523 | static uint8_t hidEmuRcvReport(uint8_t len, uint8_t *pData)
524 | {
525 | // verify data length
526 | if(len == HID_LED_OUT_RPT_LEN)
527 | {
528 | // set LEDs
529 | return SUCCESS;
530 | }
531 | else
532 | {
533 | return ATT_ERR_INVALID_VALUE_SIZE;
534 | }
535 | }
536 |
537 | /*********************************************************************
538 | * @fn hidEmuRptCB
539 | *
540 | * @brief HID Dev report callback.
541 | *
542 | * @param id - HID report ID.
543 | * @param type - HID report type.
544 | * @param uuid - attribute uuid.
545 | * @param oper - operation: read, write, etc.
546 | * @param len - Length of report.
547 | * @param pData - Report data.
548 | *
549 | * @return GATT status code.
550 | */
551 | static uint8_t hidEmuRptCB(uint8_t id, uint8_t type, uint16_t uuid,
552 | uint8_t oper, uint16_t *pLen, uint8_t *pData)
553 | {
554 | uint8_t status = SUCCESS;
555 |
556 | // write
557 | if(oper == HID_DEV_OPER_WRITE)
558 | {
559 | if(uuid == REPORT_UUID)
560 | {
561 | // process write to LED output report; ignore others
562 | if(type == HID_REPORT_TYPE_OUTPUT)
563 | {
564 | status = hidEmuRcvReport(*pLen, pData);
565 | }
566 | }
567 |
568 | if(status == SUCCESS)
569 | {
570 | status = Hid_SetParameter(id, type, uuid, *pLen, pData);
571 | }
572 | }
573 | // read
574 | else if(oper == HID_DEV_OPER_READ)
575 | {
576 | status = Hid_GetParameter(id, type, uuid, pLen, pData);
577 | }
578 | // notifications enabled
579 | else if(oper == HID_DEV_OPER_ENABLE)
580 | {
581 | tmos_start_task(hidEmuTaskId, START_REPORT_EVT, 500);
582 | }
583 | return status;
584 | }
585 |
586 | /*********************************************************************
587 | * @fn hidEmuEvtCB
588 | *
589 | * @brief HID Dev event callback.
590 | *
591 | * @param evt - event ID.
592 | *
593 | * @return HID response code.
594 | */
595 | static void hidEmuEvtCB(uint8_t evt)
596 | {
597 | // process enter/exit suspend or enter/exit boot mode
598 | return;
599 | }
600 |
601 | /*********************************************************************
602 | *********************************************************************/
603 |
--------------------------------------------------------------------------------
/sample/test_ch592f_ble_hid_keyboard/hidkbd.h:
--------------------------------------------------------------------------------
1 | /********************************** (C) COPYRIGHT *******************************
2 | * File Name : hidkbd.h
3 | * Author : WCH
4 | * Version : V1.0
5 | * Date : 2018/12/10
6 | * Description :
7 | *********************************************************************************
8 | * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
9 | * Attention: This software (modified or not) and binary are used for
10 | * microcontroller manufactured by Nanjing Qinheng Microelectronics.
11 | *******************************************************************************/
12 |
13 | #ifndef HIDKBD_H
14 | #define HIDKBD_H
15 |
16 | #ifdef __cplusplus
17 | extern "C" {
18 | #endif
19 |
20 | /*********************************************************************
21 | * INCLUDES
22 | */
23 |
24 | /*********************************************************************
25 | * CONSTANTS
26 | */
27 |
28 | // Task Events
29 | #define START_DEVICE_EVT 0x0001
30 | #define START_REPORT_EVT 0x0002
31 | #define START_PARAM_UPDATE_EVT 0x0004
32 | #define START_PHY_UPDATE_EVT 0x0008
33 | /*********************************************************************
34 | * MACROS
35 | */
36 |
37 | /*********************************************************************
38 | * FUNCTIONS
39 | */
40 |
41 | /*********************************************************************
42 | * GLOBAL VARIABLES
43 | */
44 |
45 | /*
46 | * Task Initialization for the BLE Application
47 | */
48 | extern void HidEmu_Init(void);
49 |
50 | /*
51 | * Task Event Processor for the BLE Application
52 | */
53 | extern uint16_t HidEmu_ProcessEvent(uint8_t task_id, uint16_t events);
54 |
55 | /*********************************************************************
56 | *********************************************************************/
57 |
58 | #ifdef __cplusplus
59 | }
60 | #endif
61 |
62 | #endif
63 |
--------------------------------------------------------------------------------
/sample/test_ch592f_ble_hid_keyboard/hidkbdservice.h:
--------------------------------------------------------------------------------
1 | /********************************** (C) COPYRIGHT *******************************
2 | * File Name : hidkbdservice.h
3 | * Author : WCH
4 | * Version : V1.0
5 | * Date : 2018/12/10
6 | * Description :
7 | *********************************************************************************
8 | * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
9 | * Attention: This software (modified or not) and binary are used for
10 | * microcontroller manufactured by Nanjing Qinheng Microelectronics.
11 | *******************************************************************************/
12 |
13 | #ifndef HIDKBDSERVICE_H
14 | #define HIDKBDSERVICE_H
15 |
16 | #ifdef __cplusplus
17 | extern "C" {
18 | #endif
19 |
20 | /*********************************************************************
21 | * INCLUDES
22 | */
23 |
24 | /*********************************************************************
25 | * CONSTANTS
26 | */
27 |
28 | // Number of HID reports defined in the service
29 | #define HID_NUM_REPORTS 7
30 |
31 | // HID Report IDs for the service
32 | #define HID_RPT_ID_KEY_IN 0 // Keyboard input report ID
33 | #define HID_RPT_ID_MOUSE_IN 1 // Mouse input report ID
34 | #define HID_RPT_ID_LED_OUT 0 // LED output report ID
35 | #define HID_RPT_ID_FEATURE 0 // Feature report ID
36 |
37 | // HID feature flags
38 | #define HID_FEATURE_FLAGS HID_FLAGS_REMOTE_WAKE
39 |
40 | /*********************************************************************
41 | * TYPEDEFS
42 | */
43 |
44 | /*********************************************************************
45 | * MACROS
46 | */
47 |
48 | /*********************************************************************
49 | * Profile Callbacks
50 | */
51 |
52 | /*********************************************************************
53 | * API FUNCTIONS
54 | */
55 |
56 | /*********************************************************************
57 | * @fn Hid_AddService
58 | *
59 | * @brief Initializes the HID service for keyboard by registering
60 | * GATT attributes with the GATT server.
61 | *
62 | * @param none
63 | *
64 | * @return Success or Failure
65 | */
66 | extern bStatus_t Hid_AddService(void);
67 |
68 | /*********************************************************************
69 | * @fn Hid_SetParameter
70 | *
71 | * @brief Set a HID Kbd parameter.
72 | *
73 | * @param id - HID report ID.
74 | * @param type - HID report type.
75 | * @param uuid - attribute uuid.
76 | * @param len - length of data to right.
77 | * @param pValue - pointer to data to write. This is dependent on
78 | * the input parameters and WILL be cast to the appropriate
79 | * data type (example: data type of uint16_t will be cast to
80 | * uint16_t pointer).
81 | *
82 | * @return GATT status code.
83 | */
84 | extern uint8_t Hid_SetParameter(uint8_t id, uint8_t type, uint16_t uuid, uint8_t len,
85 | void *pValue);
86 |
87 | /*********************************************************************
88 | * @fn Hid_GetParameter
89 | *
90 | * @brief Get a HID Kbd parameter.
91 | *
92 | * @param id - HID report ID.
93 | * @param type - HID report type.
94 | * @param uuid - attribute uuid.
95 | * @param pLen - length of data to be read.
96 | * @param pValue - pointer to data to get. This is dependent on
97 | * the input parameters and WILL be cast to the appropriate
98 | * data type (example: data type of uint16_t will be cast to
99 | * uint16_t pointer).
100 | *
101 | * @return GATT status code.
102 | */
103 | extern uint8_t Hid_GetParameter(uint8_t id, uint8_t type, uint16_t uuid, uint16_t *pLen, void *pValue);
104 |
105 | /*********************************************************************
106 | *********************************************************************/
107 |
108 | #ifdef __cplusplus
109 | }
110 | #endif
111 |
112 | #endif /* HIDKBDSERVICE_H */
113 |
--------------------------------------------------------------------------------
/sample/test_ch592f_ble_hid_keyboard/scanparamservice.c:
--------------------------------------------------------------------------------
1 | /********************************** (C) COPYRIGHT *******************************
2 | * File Name : scanparamservice.c
3 | * Author : WCH
4 | * Version : V1.0
5 | * Date : 2018/12/10
6 | * Description : ɨ���������
7 | *********************************************************************************
8 | * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
9 | * Attention: This software (modified or not) and binary are used for
10 | * microcontroller manufactured by Nanjing Qinheng Microelectronics.
11 | *******************************************************************************/
12 |
13 | /*********************************************************************
14 | * INCLUDES
15 | */
16 | #include "CONFIG.h"
17 | #include "scanparamservice.h"
18 |
19 | /*********************************************************************
20 | * MACROS
21 | */
22 |
23 | /*********************************************************************
24 | * CONSTANTS
25 | */
26 |
27 | /*********************************************************************
28 | * TYPEDEFS
29 | */
30 |
31 | /*********************************************************************
32 | * GLOBAL VARIABLES
33 | */
34 | // Scan parameters service
35 | const uint8_t scanParamServUUID[ATT_BT_UUID_SIZE] = {
36 | LO_UINT16(SCAN_PARAM_SERV_UUID), HI_UINT16(SCAN_PARAM_SERV_UUID)};
37 |
38 | // Scan interval window characteristic
39 | const uint8_t scanIntervalWindowUUID[ATT_BT_UUID_SIZE] = {
40 | LO_UINT16(SCAN_INTERVAL_WINDOW_UUID), HI_UINT16(SCAN_INTERVAL_WINDOW_UUID)};
41 |
42 | // Scan parameter refresh characteristic
43 | const uint8_t scanParamRefreshUUID[ATT_BT_UUID_SIZE] = {
44 | LO_UINT16(SCAN_REFRESH_UUID), HI_UINT16(SCAN_REFRESH_UUID)};
45 |
46 | /*********************************************************************
47 | * EXTERNAL VARIABLES
48 | */
49 |
50 | /*********************************************************************
51 | * EXTERNAL FUNCTIONS
52 | */
53 |
54 | /*********************************************************************
55 | * LOCAL VARIABLES
56 | */
57 |
58 | // Application callback
59 | static scanParamServiceCB_t scanParamServiceCB;
60 |
61 | /*********************************************************************
62 | * Profile Attributes - variables
63 | */
64 |
65 | // Scan Parameters Service attribute
66 | static const gattAttrType_t scanParamService = {ATT_BT_UUID_SIZE, scanParamServUUID};
67 |
68 | // Scan Interval Window characteristic
69 | static uint8_t scanIntervalWindowProps = GATT_PROP_WRITE_NO_RSP;
70 | static uint8_t scanIntervalWindow[SCAN_INTERVAL_WINDOW_CHAR_LEN];
71 |
72 | // Scan Parameter Refresh characteristic
73 | static uint8_t scanParamRefreshProps = GATT_PROP_NOTIFY;
74 | static uint8_t scanParamRefresh[SCAN_PARAM_REFRESH_LEN];
75 | static gattCharCfg_t scanParamRefreshClientCharCfg[GATT_MAX_NUM_CONN];
76 |
77 | /*********************************************************************
78 | * Profile Attributes - Table
79 | */
80 |
81 | static gattAttribute_t scanParamAttrTbl[] = {
82 | // Scan Parameters Service attribute
83 | {
84 | {ATT_BT_UUID_SIZE, primaryServiceUUID}, /* type */
85 | GATT_PERMIT_READ, /* permissions */
86 | 0, /* handle */
87 | (uint8_t *)&scanParamService /* pValue */
88 | },
89 |
90 | // Scan Interval Window declaration
91 | {
92 | {ATT_BT_UUID_SIZE, characterUUID},
93 | GATT_PERMIT_READ,
94 | 0,
95 | &scanIntervalWindowProps},
96 |
97 | // Scan Interval Window characteristic
98 | {
99 | {ATT_BT_UUID_SIZE, scanIntervalWindowUUID},
100 | GATT_PERMIT_ENCRYPT_WRITE,
101 | 0,
102 | scanIntervalWindow},
103 |
104 | // Scan Parameter Refresh declaration
105 | {
106 | {ATT_BT_UUID_SIZE, characterUUID},
107 | GATT_PERMIT_READ,
108 | 0,
109 | &scanParamRefreshProps},
110 |
111 | // Scan Parameter Refresh characteristic
112 | {
113 | {ATT_BT_UUID_SIZE, scanParamRefreshUUID},
114 | 0,
115 | 0,
116 | scanParamRefresh},
117 |
118 | // Scan Parameter Refresh characteristic client characteristic configuration
119 | {
120 | {ATT_BT_UUID_SIZE, clientCharCfgUUID},
121 | GATT_PERMIT_READ | GATT_PERMIT_ENCRYPT_WRITE,
122 | 0,
123 | (uint8_t *)&scanParamRefreshClientCharCfg}
124 | };
125 |
126 | // Attribute index enumeration-- these indexes match array elements above
127 | enum
128 | {
129 | SCAN_PARAM_SERVICE_IDX, // Scan Parameters Service
130 | SCAN_PARAM_INTERVAL_DECL_IDX, // Scan Interval Window declaration
131 | SCAN_PARAM_INTERVAL_IDX, // Scan Interval Window characteristic
132 | SCAN_PARAM_REFRESH_DECL_IDX, // Scan Parameter Refresh declaration
133 | SCAN_PARAM_REFRESH_IDX, // Scan Parameter Refresh characteristic
134 | SCAN_PARAM_REFRESH_CCCD_IDX // Scan Parameter Refresh characteristic client characteristic configuration
135 | };
136 |
137 | /*********************************************************************
138 | * LOCAL FUNCTIONS
139 | */
140 | static bStatus_t scanParamWriteAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
141 | uint8_t *pValue, uint16_t len, uint16_t offset, uint8_t method);
142 | static bStatus_t scanParamReadAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
143 | uint8_t *pValue, uint16_t *pLen, uint16_t offset, uint16_t maxLen, uint8_t method);
144 |
145 | /*********************************************************************
146 | * PROFILE CALLBACKS
147 | */
148 |
149 | // Service Callbacks
150 | gattServiceCBs_t scanParamCBs = {
151 | scanParamReadAttrCB, // Read callback function pointer
152 | scanParamWriteAttrCB, // Write callback function pointer
153 | NULL // Authorization callback function pointer
154 | };
155 |
156 | /*********************************************************************
157 | * PUBLIC FUNCTIONS
158 | */
159 |
160 | /*********************************************************************
161 | * @fn ScanParam_AddService
162 | *
163 | * @brief Initializes the Battery Service by registering
164 | * GATT attributes with the GATT server.
165 | *
166 | * @return Success or Failure
167 | */
168 | bStatus_t ScanParam_AddService(void)
169 | {
170 | uint8_t status = SUCCESS;
171 |
172 | // Initialize Client Characteristic Configuration attributes
173 | GATTServApp_InitCharCfg(INVALID_CONNHANDLE, scanParamRefreshClientCharCfg);
174 |
175 | // Register GATT attribute list and CBs with GATT Server App
176 | status = GATTServApp_RegisterService(scanParamAttrTbl, GATT_NUM_ATTRS(scanParamAttrTbl), GATT_MAX_ENCRYPT_KEY_SIZE,
177 | &scanParamCBs);
178 |
179 | return (status);
180 | }
181 |
182 | /*********************************************************************
183 | * @fn ScanParam_Register
184 | *
185 | * @brief Register a callback function with the Battery Service.
186 | *
187 | * @param pfnServiceCB - Callback function.
188 | *
189 | * @return None.
190 | */
191 | extern void ScanParam_Register(scanParamServiceCB_t pfnServiceCB)
192 | {
193 | scanParamServiceCB = pfnServiceCB;
194 | }
195 |
196 | /*********************************************************************
197 | * @fn ScanParam_SetParameter
198 | *
199 | * @brief Set a Battery Service parameter.
200 | *
201 | * @param param - Profile parameter ID
202 | * @param len - length of data to right
203 | * @param value - pointer to data to write. This is dependent on
204 | * the parameter ID and WILL be cast to the appropriate
205 | * data type (example: data type of uint16_t will be cast to
206 | * uint16_t pointer).
207 | *
208 | * @return bStatus_t
209 | */
210 | bStatus_t ScanParam_SetParameter(uint8_t param, uint8_t len, void *value)
211 | {
212 | bStatus_t ret = SUCCESS;
213 |
214 | switch(param)
215 | {
216 | default:
217 | ret = INVALIDPARAMETER;
218 | break;
219 | }
220 |
221 | return (ret);
222 | }
223 |
224 | /*********************************************************************
225 | * @fn ScanParam_GetParameter
226 | *
227 | * @brief Get a Battery Service parameter.
228 | *
229 | * @param param - Profile parameter ID
230 | * @param value - pointer to data to get. This is dependent on
231 | * the parameter ID and WILL be cast to the appropriate
232 | * data type (example: data type of uint16_t will be cast to
233 | * uint16_t pointer).
234 | *
235 | * @return bStatus_t
236 | */
237 | bStatus_t ScanParam_GetParameter(uint8_t param, void *value)
238 | {
239 | bStatus_t ret = SUCCESS;
240 | switch(param)
241 | {
242 | case SCAN_PARAM_PARAM_INTERVAL:
243 | *((uint16_t *)value) = BUILD_UINT16(scanIntervalWindow[0],
244 | scanIntervalWindow[1]);
245 | break;
246 |
247 | case SCAN_PARAM_PARAM_WINDOW:
248 | *((uint16_t *)value) = BUILD_UINT16(scanIntervalWindow[2],
249 | scanIntervalWindow[3]);
250 | break;
251 |
252 | default:
253 | ret = INVALIDPARAMETER;
254 | break;
255 | }
256 |
257 | return (ret);
258 | }
259 |
260 | /*********************************************************************
261 | * @fn ScanParam_RefreshNotify
262 | *
263 | * @brief Notify the peer to refresh the scan parameters.
264 | *
265 | * @param connHandle - connection handle
266 | *
267 | * @return None
268 | */
269 | void ScanParam_RefreshNotify(uint16_t connHandle)
270 | {
271 | uint16_t value;
272 |
273 | value = GATTServApp_ReadCharCfg(connHandle, scanParamRefreshClientCharCfg);
274 | if(value & GATT_CLIENT_CFG_NOTIFY)
275 | {
276 | attHandleValueNoti_t noti;
277 |
278 | noti.pValue = GATT_bm_alloc(connHandle, ATT_HANDLE_VALUE_NOTI,
279 | SCAN_PARAM_REFRESH_LEN, NULL, 0);
280 | if(noti.pValue != NULL)
281 | {
282 | // send notification
283 | noti.handle = scanParamAttrTbl[SCAN_PARAM_REFRESH_CCCD_IDX].handle;
284 | noti.len = SCAN_PARAM_REFRESH_LEN;
285 | noti.pValue[0] = SCAN_PARAM_REFRESH_REQ;
286 |
287 | if(GATT_Notification(connHandle, ¬i, FALSE) != SUCCESS)
288 | {
289 | GATT_bm_free((gattMsg_t *)¬i, ATT_HANDLE_VALUE_NOTI);
290 | }
291 | }
292 | }
293 | }
294 |
295 | /*********************************************************************
296 | * @fn scanParamReadAttrCB
297 | *
298 | * @brief GATT read callback.
299 | *
300 | * @param connHandle - connection message was received on
301 | * @param pAttr - pointer to attribute
302 | * @param pValue - pointer to data to be read
303 | * @param pLen - length of data to be read
304 | * @param offset - offset of the first octet to be read
305 | * @param maxLen - maximum length of data to be read
306 | *
307 | * @return Success or Failure
308 | */
309 | static bStatus_t scanParamReadAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
310 | uint8_t *pValue, uint16_t *pLen, uint16_t offset, uint16_t maxLen, uint8_t method)
311 | {
312 | bStatus_t status = SUCCESS;
313 |
314 | return (status);
315 | }
316 |
317 | /*********************************************************************
318 | * @fn scanParamWriteAttrCB
319 | *
320 | * @brief Validate attribute data prior to a write operation
321 | *
322 | * @param connHandle - connection message was received on
323 | * @param pAttr - pointer to attribute
324 | * @param pValue - pointer to data to be written
325 | * @param len - length of data
326 | * @param offset - offset of the first octet to be written
327 | *
328 | * @return Success or Failure
329 | */
330 | static bStatus_t scanParamWriteAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
331 | uint8_t *pValue, uint16_t len, uint16_t offset, uint8_t method)
332 | {
333 | uint16_t uuid;
334 | bStatus_t status = SUCCESS;
335 |
336 | // Make sure it's not a blob operation (no attributes in the profile are long)
337 | if(offset > 0)
338 | {
339 | return (ATT_ERR_ATTR_NOT_LONG);
340 | }
341 |
342 | uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]);
343 |
344 | // Only one writeable attribute
345 | if(uuid == SCAN_INTERVAL_WINDOW_UUID)
346 | {
347 | if(len == SCAN_INTERVAL_WINDOW_CHAR_LEN)
348 | {
349 | uint16_t interval = BUILD_UINT16(pValue[0], pValue[1]);
350 | uint16_t window = BUILD_UINT16(pValue[0], pValue[1]);
351 |
352 | // Validate values
353 | if(window <= interval)
354 | {
355 | tmos_memcpy(pAttr->pValue, pValue, len);
356 |
357 | (*scanParamServiceCB)(SCAN_INTERVAL_WINDOW_SET);
358 | }
359 | else
360 | {
361 | status = ATT_ERR_INVALID_VALUE;
362 | }
363 | }
364 | else
365 | {
366 | status = ATT_ERR_INVALID_VALUE_SIZE;
367 | }
368 | }
369 | else if(uuid == GATT_CLIENT_CHAR_CFG_UUID)
370 | {
371 | status = GATTServApp_ProcessCCCWriteReq(connHandle, pAttr, pValue, len,
372 | offset, GATT_CLIENT_CFG_NOTIFY);
373 | }
374 | else
375 | {
376 | status = ATT_ERR_ATTR_NOT_FOUND;
377 | }
378 |
379 | return (status);
380 | }
381 |
382 | /*********************************************************************
383 | * @fn ScanParam_HandleConnStatusCB
384 | *
385 | * @brief Service link status change handler function.
386 | *
387 | * @param connHandle - connection handle
388 | * @param changeType - type of change
389 | *
390 | * @return none
391 | */
392 | void ScanParam_HandleConnStatusCB(uint16_t connHandle, uint8_t changeType)
393 | {
394 | // Make sure this is not loopback connection
395 | if(connHandle != LOOPBACK_CONNHANDLE)
396 | {
397 | // Reset Client Char Config if connection has dropped
398 | if((changeType == LINKDB_STATUS_UPDATE_REMOVED) ||
399 | ((changeType == LINKDB_STATUS_UPDATE_STATEFLAGS) &&
400 | (!linkDB_Up(connHandle))))
401 | {
402 | GATTServApp_InitCharCfg(connHandle, scanParamRefreshClientCharCfg);
403 | }
404 | }
405 | }
406 |
--------------------------------------------------------------------------------
/sample/test_ch592f_ble_hid_keyboard/scanparamservice.h:
--------------------------------------------------------------------------------
1 | /********************************** (C) COPYRIGHT *******************************
2 | * File Name : scanparamservice.h
3 | * Author : WCH
4 | * Version : V1.0
5 | * Date : 2018/12/11
6 | * Description :
7 | *********************************************************************************
8 | * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
9 | * Attention: This software (modified or not) and binary are used for
10 | * microcontroller manufactured by Nanjing Qinheng Microelectronics.
11 | *******************************************************************************/
12 |
13 | #ifndef SCANPARAMSERVICE_H
14 | #define SCANPARAMSERVICE_H
15 |
16 | #ifdef __cplusplus
17 | extern "C" {
18 | #endif
19 |
20 | /*********************************************************************
21 | * INCLUDES
22 | */
23 |
24 | /*********************************************************************
25 | * CONSTANTS
26 | */
27 |
28 | // Scan Characteristic Lengths
29 | #define SCAN_INTERVAL_WINDOW_CHAR_LEN 4
30 | #define SCAN_PARAM_REFRESH_LEN 1
31 |
32 | // Scan Parameter Refresh Values
33 | #define SCAN_PARAM_REFRESH_REQ 0x00
34 |
35 | // Callback events
36 | #define SCAN_INTERVAL_WINDOW_SET 1
37 |
38 | // Get/Set parameters
39 | #define SCAN_PARAM_PARAM_INTERVAL 0
40 | #define SCAN_PARAM_PARAM_WINDOW 1
41 |
42 | /*********************************************************************
43 | * TYPEDEFS
44 | */
45 |
46 | /*********************************************************************
47 | * MACROS
48 | */
49 |
50 | /*********************************************************************
51 | * Profile Callbacks
52 | */
53 |
54 | // Scan Parameters Service callback function
55 | typedef void (*scanParamServiceCB_t)(uint8_t event);
56 |
57 | /*********************************************************************
58 | * API FUNCTIONS
59 | */
60 |
61 | /*********************************************************************
62 | * @fn ScanParam_AddService
63 | *
64 | * @brief Initializes the Service by registering
65 | * GATT attributes with the GATT server.
66 | *
67 | * @return Success or Failure
68 | */
69 | extern bStatus_t ScanParam_AddService(void);
70 |
71 | /*********************************************************************
72 | * @fn ScanParam_Register
73 | *
74 | * @brief Register a callback function with the Scan Parameters Service.
75 | *
76 | * @param pfnServiceCB - Callback function.
77 | *
78 | * @return None.
79 | */
80 | extern void ScanParam_Register(scanParamServiceCB_t pfnServiceCB);
81 |
82 | /*********************************************************************
83 | * @fn ScanParam_SetParameter
84 | *
85 | * @brief Set a Scan Parameters Service parameter.
86 | *
87 | * @param param - Profile parameter ID
88 | * @param len - length of data to right
89 | * @param value - pointer to data to write. This is dependent on
90 | * the parameter ID and WILL be cast to the appropriate
91 | * data type (example: data type of uint16_t will be cast to
92 | * uint16_t pointer).
93 | *
94 | * @return bStatus_t
95 | */
96 | extern bStatus_t ScanParam_SetParameter(uint8_t param, uint8_t len, void *value);
97 |
98 | /*********************************************************************
99 | * @fn ScanParam_GetParameter
100 | *
101 | * @brief Get a Scan Parameters Service parameter.
102 | *
103 | * @param param - Profile parameter ID
104 | * @param value - pointer to data to get. This is dependent on
105 | * the parameter ID and WILL be cast to the appropriate
106 | * data type (example: data type of uint16_t will be cast to
107 | * uint16_t pointer).
108 | *
109 | * @return bStatus_t
110 | */
111 | extern bStatus_t ScanParam_GetParameter(uint8_t param, void *value);
112 |
113 | /*********************************************************************
114 | * @fn ScanParam_RefreshNotify
115 | *
116 | * @brief Notify the peer to refresh the scan parameters.
117 | *
118 | * @param connHandle - connection handle
119 | *
120 | * @return None
121 | */
122 | extern void ScanParam_RefreshNotify(uint16_t connHandle);
123 |
124 | extern void ScanParam_HandleConnStatusCB(uint16_t connHandle, uint8_t changeType);
125 |
126 | /*********************************************************************
127 | *********************************************************************/
128 |
129 | #ifdef __cplusplus
130 | }
131 | #endif
132 |
133 | #endif /* SCANPARAMSERVICE_H */
134 |
--------------------------------------------------------------------------------
/sample/test_ch592f_ble_hid_keyboard/test_ch592f_ble_hid_keyboard.ino:
--------------------------------------------------------------------------------
1 | /********************************** (C) COPYRIGHT *******************************
2 | * File Name : main.c
3 | * Author : WCH
4 | * Version : V1.0
5 | * Date : 2020/08/06
6 | * Description : タカムタシ・フモヲモテヨッハシーネホホオヘウウシサッ
7 | *********************************************************************************
8 | * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
9 | * Attention: This software (modified or not) and binary are used for
10 | * microcontroller manufactured by Nanjing Qinheng Microelectronics.
11 | *******************************************************************************/
12 |
13 | /******************************************************************************/
14 | /* ヘキホトシー・ャ */
15 | #include "CONFIG.h"
16 | #include "HAL.h"
17 | #include "hiddev.h"
18 | #include "hidkbd.h"
19 |
20 | /*********************************************************************
21 | * GLOBAL TYPEDEFS
22 | */
23 | __attribute__((aligned(4))) uint32_t MEM_BUF[BLE_MEMHEAP_SIZE / 4];
24 |
25 | #if(defined(BLE_MAC)) && (BLE_MAC == TRUE)
26 | const uint8_t MacAddr[6] = {0x84, 0xC2, 0xE4, 0x03, 0x02, 0x02};
27 | #endif
28 |
29 | /*********************************************************************
30 | * @fn Main_Circulation
31 | *
32 | * @brief ヨュサキ
33 | *
34 | * @return none
35 | */
36 | __HIGH_CODE
37 | __attribute__((noinline))
38 | void Main_Circulation()
39 | {
40 | while(1)
41 | {
42 | TMOS_SystemProcess();
43 | }
44 | }
45 |
46 | /*********************************************************************
47 | * @fn main
48 | *
49 | * @brief ヨッハ
50 | *
51 | * @return none
52 | */
53 | void setup()
54 | {
55 | #if(defined(DCDC_ENABLE)) && (DCDC_ENABLE == TRUE)
56 | // PWR_DCDCCfg(ENABLE);
57 | #endif
58 | SetSysClock(CLK_SOURCE_PLL_60MHz);
59 | #if(defined(HAL_SLEEP)) && (HAL_SLEEP == TRUE)
60 | // GPIOA_ModeCfg(GPIO_Pin_All, GPIO_ModeIN_PU);
61 | // GPIOB_ModeCfg(GPIO_Pin_All, GPIO_ModeIN_PU);
62 | #endif
63 | #ifdef DEBUG
64 | // GPIOA_SetBits(bTXD1);
65 | // GPIOA_ModeCfg(bTXD1, GPIO_ModeOut_PP_5mA);
66 | // UART1_DefInit();
67 | #endif
68 |
69 | // Internal LED
70 | GPIOA_SetBits(GPIO_Pin_8);
71 | GPIOA_ModeCfg(GPIO_Pin_8, GPIO_ModeOut_PP_5mA);
72 |
73 | // Button 1
74 | GPIOA_SetBits(GPIO_Pin_14);
75 | GPIOB_ModeCfg(GPIO_Pin_14, GPIO_ModeOut_PP_5mA);
76 | GPIOB_ModeCfg(GPIO_Pin_12, GPIO_ModeIN_PU);
77 |
78 | // Button 2
79 | GPIOA_SetBits(GPIO_Pin_11);
80 | GPIOB_ModeCfg(GPIO_Pin_11, GPIO_ModeOut_PP_5mA);
81 | GPIOB_ModeCfg(GPIO_Pin_7, GPIO_ModeIN_PU);
82 |
83 | // Button 3
84 | GPIOA_SetBits(GPIO_Pin_4);
85 | GPIOB_ModeCfg(GPIO_Pin_4, GPIO_ModeOut_PP_5mA);
86 | GPIOB_ModeCfg(GPIO_Pin_22, GPIO_ModeIN_PU);
87 |
88 | // Ready Indicator
89 | for(int i = 0; i < 9; i++){
90 | // LED on
91 | GPIOA_ResetBits(GPIO_Pin_8);
92 | delay(40);
93 | // LED off
94 | GPIOA_SetBits(GPIO_Pin_8);
95 | delay(40);
96 | }
97 |
98 | PRINT("%s\n", VER_LIB);
99 | CH59x_BLEInit();
100 | HAL_Init();
101 | GAPRole_PeripheralInit();
102 | HidDev_Init();
103 | HidEmu_Init();
104 | Main_Circulation();
105 | }
106 |
107 | void loop(){}
108 |
109 | /******************************** endfile @ main ******************************/
110 |
--------------------------------------------------------------------------------
/sample/test_ch592f_ble_hid_keyboard_org/.gitkeep:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/sample/test_ch592f_ble_hid_keyboard_org/battservice.c:
--------------------------------------------------------------------------------
1 | /********************************** (C) COPYRIGHT *******************************
2 | * File Name : battservice.c
3 | * Author : WCH
4 | * Version : V1.0
5 | * Date : 2018/12/10
6 | * Description : ��ط���
7 | *********************************************************************************
8 | * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
9 | * Attention: This software (modified or not) and binary are used for
10 | * microcontroller manufactured by Nanjing Qinheng Microelectronics.
11 | *******************************************************************************/
12 |
13 | /*********************************************************************
14 | * INCLUDES
15 | */
16 | #include "CONFIG.h"
17 | #include "hiddev.h"
18 | #include "battservice.h"
19 |
20 | /*********************************************************************
21 | * MACROS
22 | */
23 |
24 | /*********************************************************************
25 | * CONSTANTS
26 | */
27 |
28 | // ADC voltage levels
29 | #define BATT_ADC_LEVEL_3V 409
30 | #define BATT_ADC_LEVEL_2V 273
31 |
32 | #define BATT_LEVEL_VALUE_IDX 2 // Position of battery level in attribute array
33 | #define BATT_LEVEL_VALUE_CCCD_IDX 3 // Position of battery level CCCD in attribute array
34 |
35 | #define BATT_LEVEL_VALUE_LEN 1
36 | /*********************************************************************
37 | * TYPEDEFS
38 | */
39 |
40 | /*********************************************************************
41 | * GLOBAL VARIABLES
42 | */
43 | // Battery service
44 | const uint8_t battServUUID[ATT_BT_UUID_SIZE] = {
45 | LO_UINT16(BATT_SERV_UUID), HI_UINT16(BATT_SERV_UUID)};
46 |
47 | // Battery level characteristic
48 | const uint8_t battLevelUUID[ATT_BT_UUID_SIZE] = {
49 | LO_UINT16(BATT_LEVEL_UUID), HI_UINT16(BATT_LEVEL_UUID)};
50 |
51 | /*********************************************************************
52 | * EXTERNAL VARIABLES
53 | */
54 |
55 | /*********************************************************************
56 | * EXTERNAL FUNCTIONS
57 | */
58 |
59 | /*********************************************************************
60 | * LOCAL VARIABLES
61 | */
62 |
63 | // Application callback
64 | static battServiceCB_t battServiceCB;
65 |
66 | // Measurement setup callback
67 | static battServiceSetupCB_t battServiceSetupCB = NULL;
68 |
69 | // Measurement teardown callback
70 | static battServiceTeardownCB_t battServiceTeardownCB = NULL;
71 |
72 | // Measurement calculation callback
73 | static battServiceCalcCB_t battServiceCalcCB = NULL;
74 |
75 | static uint16_t battMinLevel = BATT_ADC_LEVEL_2V; // For VDD/3 measurements
76 | static uint16_t battMaxLevel = BATT_ADC_LEVEL_3V; // For VDD/3 measurements
77 |
78 | // Critical battery level setting
79 | static uint8_t battCriticalLevel;
80 |
81 | // ADC channel to be used for reading
82 | //static uint8_t battServiceAdcCh = HAL_ADC_CHANNEL_VDD;
83 |
84 | /*********************************************************************
85 | * Profile Attributes - variables
86 | */
87 |
88 | // Battery Service attribute
89 | static const gattAttrType_t battService = {ATT_BT_UUID_SIZE, battServUUID};
90 |
91 | // Battery level characteristic
92 | static uint8_t battLevelProps = GATT_PROP_READ | GATT_PROP_NOTIFY;
93 | static uint8_t battLevel = 100;
94 | static gattCharCfg_t battLevelClientCharCfg[GATT_MAX_NUM_CONN];
95 |
96 | // HID Report Reference characteristic descriptor, battery level
97 | static uint8_t hidReportRefBattLevel[HID_REPORT_REF_LEN] = {
98 | HID_RPT_ID_BATT_LEVEL_IN, HID_REPORT_TYPE_INPUT};
99 |
100 | /*********************************************************************
101 | * Profile Attributes - Table
102 | */
103 |
104 | static gattAttribute_t battAttrTbl[] = {
105 | // Battery Service
106 | {
107 | {ATT_BT_UUID_SIZE, primaryServiceUUID}, /* type */
108 | GATT_PERMIT_READ, /* permissions */
109 | 0, /* handle */
110 | (uint8_t *)&battService /* pValue */
111 | },
112 |
113 | // Battery Level Declaration
114 | {
115 | {ATT_BT_UUID_SIZE, characterUUID},
116 | GATT_PERMIT_READ,
117 | 0,
118 | &battLevelProps},
119 |
120 | // Battery Level Value
121 | {
122 | {ATT_BT_UUID_SIZE, battLevelUUID},
123 | GATT_PERMIT_READ,
124 | 0,
125 | &battLevel},
126 |
127 | // Battery Level Client Characteristic Configuration
128 | {
129 | {ATT_BT_UUID_SIZE, clientCharCfgUUID},
130 | GATT_PERMIT_READ | GATT_PERMIT_WRITE,
131 | 0,
132 | (uint8_t *)&battLevelClientCharCfg},
133 |
134 | // HID Report Reference characteristic descriptor, batter level input
135 | {
136 | {ATT_BT_UUID_SIZE, reportRefUUID},
137 | GATT_PERMIT_READ,
138 | 0,
139 | hidReportRefBattLevel}
140 | };
141 |
142 | /*********************************************************************
143 | * LOCAL FUNCTIONS
144 | */
145 | static bStatus_t battReadAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
146 | uint8_t *pValue, uint16_t *pLen, uint16_t offset, uint16_t maxLen, uint8_t method);
147 | static bStatus_t battWriteAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
148 | uint8_t *pValue, uint16_t len, uint16_t offset, uint8_t method);
149 | static void battNotifyCB(linkDBItem_t *pLinkItem);
150 | static uint8_t battMeasure(void);
151 | static void battNotifyLevel(void);
152 |
153 | /*********************************************************************
154 | * PROFILE CALLBACKS
155 | */
156 | // Battery Service Callbacks
157 | gattServiceCBs_t battCBs = {
158 | battReadAttrCB, // Read callback function pointer
159 | battWriteAttrCB, // Write callback function pointer
160 | NULL // Authorization callback function pointer
161 | };
162 |
163 | /*********************************************************************
164 | * PUBLIC FUNCTIONS
165 | */
166 |
167 | /*********************************************************************
168 | * @fn Batt_AddService
169 | *
170 | * @brief Initializes the Battery Service by registering
171 | * GATT attributes with the GATT server.
172 | *
173 | * @return Success or Failure
174 | */
175 | bStatus_t Batt_AddService(void)
176 | {
177 | uint8_t status = SUCCESS;
178 |
179 | // Initialize Client Characteristic Configuration attributes
180 | GATTServApp_InitCharCfg(INVALID_CONNHANDLE, battLevelClientCharCfg);
181 |
182 | // Register GATT attribute list and CBs with GATT Server App
183 | status = GATTServApp_RegisterService(battAttrTbl,
184 | GATT_NUM_ATTRS(battAttrTbl),
185 | GATT_MAX_ENCRYPT_KEY_SIZE,
186 | &battCBs);
187 |
188 | return (status);
189 | }
190 |
191 | /*********************************************************************
192 | * @fn Batt_Register
193 | *
194 | * @brief Register a callback function with the Battery Service.
195 | *
196 | * @param pfnServiceCB - Callback function.
197 | *
198 | * @return None.
199 | */
200 | extern void Batt_Register(battServiceCB_t pfnServiceCB)
201 | {
202 | battServiceCB = pfnServiceCB;
203 | }
204 |
205 | /*********************************************************************
206 | * @fn Batt_SetParameter
207 | *
208 | * @brief Set a Battery Service parameter.
209 | *
210 | * @param param - Profile parameter ID
211 | * @param len - length of data to right
212 | * @param value - pointer to data to write. This is dependent on
213 | * the parameter ID and WILL be cast to the appropriate
214 | * data type (example: data type of uint16_t will be cast to
215 | * uint16_t pointer).
216 | *
217 | * @return bStatus_t
218 | */
219 | bStatus_t Batt_SetParameter(uint8_t param, uint8_t len, void *value)
220 | {
221 | bStatus_t ret = SUCCESS;
222 |
223 | switch(param)
224 | {
225 | case BATT_PARAM_CRITICAL_LEVEL:
226 | battCriticalLevel = *((uint8_t *)value);
227 |
228 | // If below the critical level and critical state not set, notify it
229 | if(battLevel < battCriticalLevel)
230 | {
231 | battNotifyLevel();
232 | }
233 | break;
234 |
235 | default:
236 | ret = INVALIDPARAMETER;
237 | break;
238 | }
239 |
240 | return (ret);
241 | }
242 |
243 | /*********************************************************************
244 | * @fn Batt_GetParameter
245 | *
246 | * @brief Get a Battery Service parameter.
247 | *
248 | * @param param - Profile parameter ID
249 | * @param value - pointer to data to get. This is dependent on
250 | * the parameter ID and WILL be cast to the appropriate
251 | * data type (example: data type of uint16_t will be cast to
252 | * uint16_t pointer).
253 | *
254 | * @return bStatus_t
255 | */
256 | bStatus_t Batt_GetParameter(uint8_t param, void *value)
257 | {
258 | bStatus_t ret = SUCCESS;
259 | switch(param)
260 | {
261 | case BATT_PARAM_LEVEL:
262 | *((uint8_t *)value) = battLevel;
263 | break;
264 |
265 | case BATT_PARAM_CRITICAL_LEVEL:
266 | *((uint8_t *)value) = battCriticalLevel;
267 | break;
268 |
269 | case BATT_PARAM_SERVICE_HANDLE:
270 | *((uint16_t *)value) = GATT_SERVICE_HANDLE(battAttrTbl);
271 | break;
272 |
273 | case BATT_PARAM_BATT_LEVEL_IN_REPORT:
274 | {
275 | hidRptMap_t *pRpt = (hidRptMap_t *)value;
276 |
277 | pRpt->id = hidReportRefBattLevel[0];
278 | pRpt->type = hidReportRefBattLevel[1];
279 | pRpt->handle = battAttrTbl[BATT_LEVEL_VALUE_IDX].handle;
280 | pRpt->cccdHandle = battAttrTbl[BATT_LEVEL_VALUE_CCCD_IDX].handle;
281 | pRpt->mode = HID_PROTOCOL_MODE_REPORT;
282 | }
283 | break;
284 |
285 | default:
286 | ret = INVALIDPARAMETER;
287 | break;
288 | }
289 |
290 | return (ret);
291 | }
292 |
293 | /*********************************************************************
294 | * @fn Batt_MeasLevel
295 | *
296 | * @brief Measure the battery level and update the battery
297 | * level value in the service characteristics. If
298 | * the battery level-state characteristic is configured
299 | * for notification and the battery level has changed
300 | * since the last measurement, then a notification
301 | * will be sent.
302 | *
303 | * @return Success
304 | */
305 | bStatus_t Batt_MeasLevel(void)
306 | {
307 | uint8_t level;
308 |
309 | level = battMeasure();
310 |
311 | // If level has gone down
312 | if(level < battLevel)
313 | {
314 | // Update level
315 | battLevel = level;
316 |
317 | // Send a notification
318 | battNotifyLevel();
319 | }
320 |
321 | return SUCCESS;
322 | }
323 |
324 | /*********************************************************************
325 | * @fn Batt_Setup
326 | *
327 | * @brief Set up which ADC source is to be used. Defaults to VDD/3.
328 | *
329 | * @param adc_ch - ADC Channel, e.g. HAL_ADC_CHN_AIN6
330 | * @param minVal - max battery level
331 | * @param maxVal - min battery level
332 | * @param sCB - HW setup callback
333 | * @param tCB - HW tear down callback
334 | * @param cCB - percentage calculation callback
335 | *
336 | * @return none.
337 | */
338 | void Batt_Setup(uint8_t adc_ch, uint16_t minVal, uint16_t maxVal,
339 | battServiceSetupCB_t sCB, battServiceTeardownCB_t tCB,
340 | battServiceCalcCB_t cCB)
341 | {
342 | //battServiceAdcCh = adc_ch;
343 | battMinLevel = minVal;
344 | battMaxLevel = maxVal;
345 |
346 | battServiceSetupCB = sCB;
347 | battServiceTeardownCB = tCB;
348 | battServiceCalcCB = cCB;
349 | }
350 |
351 | /*********************************************************************
352 | * @fn battReadAttrCB
353 | *
354 | * @brief Read an attribute.
355 | *
356 | * @param connHandle - connection message was received on
357 | * @param pAttr - pointer to attribute
358 | * @param pValue - pointer to data to be read
359 | * @param pLen - length of data to be read
360 | * @param offset - offset of the first octet to be read
361 | * @param maxLen - maximum length of data to be read
362 | *
363 | * @return Success or Failure
364 | */
365 | static bStatus_t battReadAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
366 | uint8_t *pValue, uint16_t *pLen, uint16_t offset, uint16_t maxLen, uint8_t method)
367 | {
368 | uint16_t uuid;
369 | bStatus_t status = SUCCESS;
370 |
371 | // Make sure it's not a blob operation (no attributes in the profile are long)
372 | if(offset > 0)
373 | {
374 | return (ATT_ERR_ATTR_NOT_LONG);
375 | }
376 |
377 | uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]);
378 |
379 | // Measure battery level if reading level
380 | if(uuid == BATT_LEVEL_UUID)
381 | {
382 | uint8_t level;
383 |
384 | level = battMeasure();
385 |
386 | // If level has gone down
387 | if(level < battLevel)
388 | {
389 | // Update level
390 | battLevel = level;
391 | }
392 |
393 | *pLen = 1;
394 | pValue[0] = battLevel;
395 | }
396 | else if(uuid == GATT_REPORT_REF_UUID)
397 | {
398 | *pLen = HID_REPORT_REF_LEN;
399 | tmos_memcpy(pValue, pAttr->pValue, HID_REPORT_REF_LEN);
400 | }
401 | else
402 | {
403 | status = ATT_ERR_ATTR_NOT_FOUND;
404 | }
405 |
406 | return (status);
407 | }
408 |
409 | /*********************************************************************
410 | * @fn battWriteAttrCB
411 | *
412 | * @brief Validate attribute data prior to a write operation
413 | *
414 | * @param connHandle - connection message was received on
415 | * @param pAttr - pointer to attribute
416 | * @param pValue - pointer to data to be written
417 | * @param len - length of data
418 | * @param offset - offset of the first octet to be written
419 | *
420 | * @return Success or Failure
421 | */
422 | static bStatus_t battWriteAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
423 | uint8_t *pValue, uint16_t len, uint16_t offset, uint8_t method)
424 | {
425 | bStatus_t status = SUCCESS;
426 |
427 | uint16_t uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]);
428 | switch(uuid)
429 | {
430 | case GATT_CLIENT_CHAR_CFG_UUID:
431 | status = GATTServApp_ProcessCCCWriteReq(connHandle, pAttr, pValue, len,
432 | offset, GATT_CLIENT_CFG_NOTIFY);
433 | if(status == SUCCESS)
434 | {
435 | uint16_t charCfg = BUILD_UINT16(pValue[0], pValue[1]);
436 |
437 | if(battServiceCB)
438 | {
439 | (*battServiceCB)((charCfg == GATT_CFG_NO_OPERATION) ? BATT_LEVEL_NOTI_DISABLED : BATT_LEVEL_NOTI_ENABLED);
440 | }
441 | }
442 | break;
443 |
444 | default:
445 | status = ATT_ERR_ATTR_NOT_FOUND;
446 | break;
447 | }
448 |
449 | return (status);
450 | }
451 |
452 | /*********************************************************************
453 | * @fn battNotifyCB
454 | *
455 | * @brief Send a notification of the level state characteristic.
456 | *
457 | * @param connHandle - linkDB item
458 | *
459 | * @return None.
460 | */
461 | static void battNotifyCB(linkDBItem_t *pLinkItem)
462 | {
463 | if(pLinkItem->stateFlags & LINK_CONNECTED)
464 | {
465 | uint16_t value = GATTServApp_ReadCharCfg(pLinkItem->connectionHandle,
466 | battLevelClientCharCfg);
467 | if(value & GATT_CLIENT_CFG_NOTIFY)
468 | {
469 | attHandleValueNoti_t noti;
470 |
471 | noti.pValue = GATT_bm_alloc(pLinkItem->connectionHandle, ATT_HANDLE_VALUE_NOTI,
472 | BATT_LEVEL_VALUE_LEN, NULL, 0);
473 | if(noti.pValue != NULL)
474 | {
475 | noti.handle = battAttrTbl[BATT_LEVEL_VALUE_IDX].handle;
476 | noti.len = BATT_LEVEL_VALUE_LEN;
477 | noti.pValue[0] = battLevel;
478 |
479 | if(GATT_Notification(pLinkItem->connectionHandle, ¬i, FALSE) != SUCCESS)
480 | {
481 | GATT_bm_free((gattMsg_t *)¬i, ATT_HANDLE_VALUE_NOTI);
482 | }
483 | }
484 | }
485 | }
486 | }
487 |
488 | /*********************************************************************
489 | * @fn battMeasure
490 | *
491 | * @brief Measure the battery level with the ADC and return
492 | * it as a percentage 0-100%.
493 | *
494 | * @return Battery level.
495 | */
496 | static uint8_t battMeasure(void)
497 | {
498 | uint16_t adc;
499 | uint8_t percent;
500 |
501 | // Call measurement setup callback
502 | if(battServiceSetupCB != NULL)
503 | {
504 | battServiceSetupCB();
505 | }
506 |
507 | // Configure ADC and perform a read
508 | adc = 300;
509 | // Call measurement teardown callback
510 | if(battServiceTeardownCB != NULL)
511 | {
512 | battServiceTeardownCB();
513 | }
514 |
515 | if(adc >= battMaxLevel)
516 | {
517 | percent = 100;
518 | }
519 | else if(adc <= battMinLevel)
520 | {
521 | percent = 0;
522 | }
523 | else
524 | {
525 | if(battServiceCalcCB != NULL)
526 | {
527 | percent = battServiceCalcCB(adc);
528 | }
529 | else
530 | {
531 | uint16_t range = battMaxLevel - battMinLevel + 1;
532 |
533 | // optional if you want to keep it even, otherwise just take floor of divide
534 | // range += (range & 1);
535 | range >>= 2; // divide by 4
536 |
537 | percent = (uint8_t)((((adc - battMinLevel) * 25) + (range - 1)) / range);
538 | }
539 | }
540 |
541 | return percent;
542 | }
543 |
544 | /*********************************************************************
545 | * @fn battNotifyLevelState
546 | *
547 | * @brief Send a notification of the battery level state
548 | * characteristic if a connection is established.
549 | *
550 | * @return None.
551 | */
552 | static void battNotifyLevel(void)
553 | {
554 | // Execute linkDB callback to send notification
555 | linkDB_PerformFunc(battNotifyCB);
556 | }
557 |
558 | /*********************************************************************
559 | * @fn Batt_HandleConnStatusCB
560 | *
561 | * @brief Battery Service link status change handler function.
562 | *
563 | * @param connHandle - connection handle
564 | * @param changeType - type of change
565 | *
566 | * @return none
567 | */
568 | void Batt_HandleConnStatusCB(uint16_t connHandle, uint8_t changeType)
569 | {
570 | // Make sure this is not loopback connection
571 | if(connHandle != LOOPBACK_CONNHANDLE)
572 | {
573 | // Reset Client Char Config if connection has dropped
574 | if((changeType == LINKDB_STATUS_UPDATE_REMOVED) ||
575 | ((changeType == LINKDB_STATUS_UPDATE_STATEFLAGS) &&
576 | (!linkDB_Up(connHandle))))
577 | {
578 | GATTServApp_InitCharCfg(connHandle, battLevelClientCharCfg);
579 | }
580 | }
581 | }
582 |
583 | /*********************************************************************
584 | *********************************************************************/
585 |
--------------------------------------------------------------------------------
/sample/test_ch592f_ble_hid_keyboard_org/battservice.h:
--------------------------------------------------------------------------------
1 | /********************************** (C) COPYRIGHT *******************************
2 | * File Name : battservice.h
3 | * Author : WCH
4 | * Version : V1.0
5 | * Date : 2018/12/11
6 | * Description :
7 | *********************************************************************************
8 | * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
9 | * Attention: This software (modified or not) and binary are used for
10 | * microcontroller manufactured by Nanjing Qinheng Microelectronics.
11 | *******************************************************************************/
12 |
13 | #ifndef BATTSERVICE_H
14 | #define BATTSERVICE_H
15 |
16 | #ifdef __cplusplus
17 | extern "C" {
18 | #endif
19 |
20 | /*********************************************************************
21 | * INCLUDES
22 | */
23 |
24 | /*********************************************************************
25 | * CONSTANTS
26 | */
27 |
28 | // Battery Service Get/Set Parameters
29 | #define BATT_PARAM_LEVEL 0
30 | #define BATT_PARAM_CRITICAL_LEVEL 1
31 | #define BATT_PARAM_SERVICE_HANDLE 2
32 | #define BATT_PARAM_BATT_LEVEL_IN_REPORT 3
33 |
34 | // Callback events
35 | #define BATT_LEVEL_NOTI_ENABLED 1
36 | #define BATT_LEVEL_NOTI_DISABLED 2
37 |
38 | // HID Report IDs for the service
39 | #define HID_RPT_ID_BATT_LEVEL_IN 4 // Battery Level input report ID
40 |
41 | /*********************************************************************
42 | * TYPEDEFS
43 | */
44 |
45 | // Battery Service callback function
46 | typedef void (*battServiceCB_t)(uint8_t event);
47 |
48 | // Battery measure HW setup function
49 | typedef void (*battServiceSetupCB_t)(void);
50 |
51 | // Battery measure percentage calculation function
52 | typedef uint8_t (*battServiceCalcCB_t)(uint16_t adcVal);
53 |
54 | // Battery measure HW teardown function
55 | typedef void (*battServiceTeardownCB_t)(void);
56 |
57 | /*********************************************************************
58 | * MACROS
59 | */
60 |
61 | /*********************************************************************
62 | * Profile Callbacks
63 | */
64 |
65 | /*********************************************************************
66 | * API FUNCTIONS
67 | */
68 |
69 | /*********************************************************************
70 | * @fn Batt_AddService
71 | *
72 | * @brief Initializes the Battery service by registering
73 | * GATT attributes with the GATT server.
74 | *
75 | * @return Success or Failure
76 | */
77 | extern bStatus_t Batt_AddService(void);
78 |
79 | /*********************************************************************
80 | * @fn Batt_Register
81 | *
82 | * @brief Register a callback function with the Battery Service.
83 | *
84 | * @param pfnServiceCB - Callback function.
85 | *
86 | * @return None.
87 | */
88 | extern void Batt_Register(battServiceCB_t pfnServiceCB);
89 |
90 | /*********************************************************************
91 | * @fn Batt_SetParameter
92 | *
93 | * @brief Set a Battery Service parameter.
94 | *
95 | * @param param - Profile parameter ID
96 | * @param len - length of data to right
97 | * @param value - pointer to data to write. This is dependent on
98 | * the parameter ID and WILL be cast to the appropriate
99 | * data type (example: data type of uint16_t will be cast to
100 | * uint16_t pointer).
101 | *
102 | * @return bStatus_t
103 | */
104 | extern bStatus_t Batt_SetParameter(uint8_t param, uint8_t len, void *value);
105 |
106 | /*********************************************************************
107 | * @fn Batt_GetParameter
108 | *
109 | * @brief Get a Battery parameter.
110 | *
111 | * @param param - Profile parameter ID
112 | * @param value - pointer to data to get. This is dependent on
113 | * the parameter ID and WILL be cast to the appropriate
114 | * data type (example: data type of uint16_t will be cast to
115 | * uint16_t pointer).
116 | *
117 | * @return bStatus_t
118 | */
119 | extern bStatus_t Batt_GetParameter(uint8_t param, void *value);
120 |
121 | /*********************************************************************
122 | * @fn Batt_MeasLevel
123 | *
124 | * @brief Measure the battery level and update the battery
125 | * level value in the service characteristics. If
126 | * the battery level-state characteristic is configured
127 | * for notification and the battery level has changed
128 | * since the last measurement, then a notification
129 | * will be sent.
130 | *
131 | * @return Success or Failure
132 | */
133 | extern bStatus_t Batt_MeasLevel(void);
134 |
135 | /*********************************************************************
136 | * @fn Batt_Setup
137 | *
138 | * @brief Set up which ADC source is to be used. Defaults to VDD/3.
139 | *
140 | * @param adc_ch - ADC Channel, e.g. HAL_ADC_CHN_AIN6
141 | * @param minVal - max battery level
142 | * @param maxVal - min battery level
143 | * @param sCB - HW setup callback
144 | * @param tCB - HW tear down callback
145 | * @param cCB - percentage calculation callback
146 | *
147 | * @return none.
148 | */
149 | extern void Batt_Setup(uint8_t adc_ch, uint16_t minVal, uint16_t maxVal,
150 | battServiceSetupCB_t sCB, battServiceTeardownCB_t tCB,
151 | battServiceCalcCB_t cCB);
152 |
153 | /*********************************************************************
154 | * @fn Batt_HandleConnStatusCB
155 | *
156 | * @brief Battery Service link status change handler function.
157 | *
158 | * @param connHandle - connection handle
159 | * @param changeType - type of change
160 | *
161 | * @return none
162 | */
163 | void Batt_HandleConnStatusCB(uint16_t connHandle, uint8_t changeType);
164 |
165 | /*********************************************************************
166 | *********************************************************************/
167 |
168 | #ifdef __cplusplus
169 | }
170 | #endif
171 |
172 | #endif /* BATTSERVICE_H */
173 |
--------------------------------------------------------------------------------
/sample/test_ch592f_ble_hid_keyboard_org/devinfoservice.c:
--------------------------------------------------------------------------------
1 | /********************************** (C) COPYRIGHT *******************************
2 | * File Name : devinfoservice.c
3 | * Author : WCH
4 | * Version : V1.0
5 | * Date : 2018/12/10
6 | * Description : �豸��Ϣ����
7 | *********************************************************************************
8 | * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
9 | * Attention: This software (modified or not) and binary are used for
10 | * microcontroller manufactured by Nanjing Qinheng Microelectronics.
11 | *******************************************************************************/
12 |
13 | /*********************************************************************
14 | * INCLUDES
15 | */
16 | #include "CONFIG.h"
17 | #include "devinfoservice.h"
18 |
19 | /*********************************************************************
20 | * MACROS
21 | */
22 |
23 | /*********************************************************************
24 | * CONSTANTS
25 | */
26 |
27 | /*********************************************************************
28 | * TYPEDEFS
29 | */
30 |
31 | /*********************************************************************
32 | * GLOBAL VARIABLES
33 | */
34 | // Device information service
35 | const uint8_t devInfoServUUID[ATT_BT_UUID_SIZE] = {
36 | LO_UINT16(DEVINFO_SERV_UUID), HI_UINT16(DEVINFO_SERV_UUID)};
37 |
38 | // System ID
39 | const uint8_t devInfoSystemIdUUID[ATT_BT_UUID_SIZE] = {
40 | LO_UINT16(SYSTEM_ID_UUID), HI_UINT16(SYSTEM_ID_UUID)};
41 |
42 | // Model Number String
43 | const uint8_t devInfoModelNumberUUID[ATT_BT_UUID_SIZE] = {
44 | LO_UINT16(MODEL_NUMBER_UUID), HI_UINT16(MODEL_NUMBER_UUID)};
45 |
46 | // Serial Number String
47 | const uint8_t devInfoSerialNumberUUID[ATT_BT_UUID_SIZE] = {
48 | LO_UINT16(SERIAL_NUMBER_UUID), HI_UINT16(SERIAL_NUMBER_UUID)};
49 |
50 | // Firmware Revision String
51 | const uint8_t devInfoFirmwareRevUUID[ATT_BT_UUID_SIZE] = {
52 | LO_UINT16(FIRMWARE_REV_UUID), HI_UINT16(FIRMWARE_REV_UUID)};
53 |
54 | // Hardware Revision String
55 | const uint8_t devInfoHardwareRevUUID[ATT_BT_UUID_SIZE] = {
56 | LO_UINT16(HARDWARE_REV_UUID), HI_UINT16(HARDWARE_REV_UUID)};
57 |
58 | // Software Revision String
59 | const uint8_t devInfoSoftwareRevUUID[ATT_BT_UUID_SIZE] = {
60 | LO_UINT16(SOFTWARE_REV_UUID), HI_UINT16(SOFTWARE_REV_UUID)};
61 |
62 | // Manufacturer Name String
63 | const uint8_t devInfoMfrNameUUID[ATT_BT_UUID_SIZE] = {
64 | LO_UINT16(MANUFACTURER_NAME_UUID), HI_UINT16(MANUFACTURER_NAME_UUID)};
65 |
66 | // IEEE 11073-20601 Regulatory Certification Data List
67 | const uint8_t devInfo11073CertUUID[ATT_BT_UUID_SIZE] = {
68 | LO_UINT16(IEEE_11073_CERT_DATA_UUID), HI_UINT16(IEEE_11073_CERT_DATA_UUID)};
69 |
70 | // PnP ID
71 | const uint8_t devInfoPnpIdUUID[ATT_BT_UUID_SIZE] = {
72 | LO_UINT16(PNP_ID_UUID), HI_UINT16(PNP_ID_UUID)};
73 |
74 | /*********************************************************************
75 | * EXTERNAL VARIABLES
76 | */
77 |
78 | /*********************************************************************
79 | * EXTERNAL FUNCTIONS
80 | */
81 |
82 | /*********************************************************************
83 | * LOCAL VARIABLES
84 | */
85 |
86 | /*********************************************************************
87 | * Profile Attributes - variables
88 | */
89 |
90 | // Device Information Service attribute
91 | static const gattAttrType_t devInfoService = {ATT_BT_UUID_SIZE, devInfoServUUID};
92 |
93 | // System ID characteristic
94 | static uint8_t devInfoSystemIdProps = GATT_PROP_READ;
95 | static uint8_t devInfoSystemId[DEVINFO_SYSTEM_ID_LEN] = {0, 0, 0, 0, 0, 0, 0, 0};
96 |
97 | // Model Number String characteristic
98 | static uint8_t devInfoModelNumberProps = GATT_PROP_READ;
99 | static const uint8_t devInfoModelNumber[] = "Model Number";
100 |
101 | // Serial Number String characteristic
102 | static uint8_t devInfoSerialNumberProps = GATT_PROP_READ;
103 | static const uint8_t devInfoSerialNumber[] = "Serial Number";
104 |
105 | // Firmware Revision String characteristic
106 | static uint8_t devInfoFirmwareRevProps = GATT_PROP_READ;
107 | static const uint8_t devInfoFirmwareRev[] = "Firmware Revision";
108 |
109 | // Hardware Revision String characteristic
110 | static uint8_t devInfoHardwareRevProps = GATT_PROP_READ;
111 | static const uint8_t devInfoHardwareRev[] = "Hardware Revision";
112 |
113 | // Software Revision String characteristic
114 | static uint8_t devInfoSoftwareRevProps = GATT_PROP_READ;
115 | static const uint8_t devInfoSoftwareRev[] = "Software Revision";
116 |
117 | // Manufacturer Name String characteristic
118 | static uint8_t devInfoMfrNameProps = GATT_PROP_READ;
119 | static const uint8_t devInfoMfrName[] = "Manufacturer Name";
120 |
121 | // IEEE 11073-20601 Regulatory Certification Data List characteristic
122 | static uint8_t devInfo11073CertProps = GATT_PROP_READ;
123 | static const uint8_t devInfo11073Cert[] = {
124 | DEVINFO_11073_BODY_EXP, // authoritative body type
125 | 0x00, // authoritative body structure type
126 | // authoritative body data follows below:
127 | 'e', 'x', 'p', 'e', 'r', 'i', 'm', 'e', 'n', 't', 'a', 'l'};
128 |
129 | // System ID characteristic
130 | static uint8_t devInfoPnpIdProps = GATT_PROP_READ;
131 | static uint8_t devInfoPnpId[DEVINFO_PNP_ID_LEN] = {
132 | 1, // Vendor ID source (1=Bluetooth SIG)
133 | LO_UINT16(0x07D7), HI_UINT16(0x07D7), // Vendor ID (WCH)
134 | LO_UINT16(0x0000), HI_UINT16(0x0000), // Product ID (vendor-specific)
135 | LO_UINT16(0x0110), HI_UINT16(0x0110) // Product version (JJ.M.N)
136 | };
137 |
138 | /*********************************************************************
139 | * Profile Attributes - Table
140 | */
141 |
142 | static gattAttribute_t devInfoAttrTbl[] = {
143 | // Device Information Service
144 | {
145 | {ATT_BT_UUID_SIZE, primaryServiceUUID}, /* type */
146 | GATT_PERMIT_READ, /* permissions */
147 | 0, /* handle */
148 | (uint8_t *)&devInfoService /* pValue */
149 | },
150 |
151 | // System ID Declaration
152 | {
153 | {ATT_BT_UUID_SIZE, characterUUID},
154 | GATT_PERMIT_READ,
155 | 0,
156 | &devInfoSystemIdProps},
157 |
158 | // System ID Value
159 | {
160 | {ATT_BT_UUID_SIZE, devInfoSystemIdUUID},
161 | GATT_PERMIT_READ,
162 | 0,
163 | (uint8_t *)devInfoSystemId},
164 |
165 | // Model Number String Declaration
166 | {
167 | {ATT_BT_UUID_SIZE, characterUUID},
168 | GATT_PERMIT_READ,
169 | 0,
170 | &devInfoModelNumberProps},
171 |
172 | // Model Number Value
173 | {
174 | {ATT_BT_UUID_SIZE, devInfoModelNumberUUID},
175 | GATT_PERMIT_READ,
176 | 0,
177 | (uint8_t *)devInfoModelNumber},
178 |
179 | // Serial Number String Declaration
180 | {
181 | {ATT_BT_UUID_SIZE, characterUUID},
182 | GATT_PERMIT_READ,
183 | 0,
184 | &devInfoSerialNumberProps},
185 |
186 | // Serial Number Value
187 | {
188 | {ATT_BT_UUID_SIZE, devInfoSerialNumberUUID},
189 | GATT_PERMIT_READ,
190 | 0,
191 | (uint8_t *)devInfoSerialNumber},
192 |
193 | // Firmware Revision String Declaration
194 | {
195 | {ATT_BT_UUID_SIZE, characterUUID},
196 | GATT_PERMIT_READ,
197 | 0,
198 | &devInfoFirmwareRevProps},
199 |
200 | // Firmware Revision Value
201 | {
202 | {ATT_BT_UUID_SIZE, devInfoFirmwareRevUUID},
203 | GATT_PERMIT_READ,
204 | 0,
205 | (uint8_t *)devInfoFirmwareRev},
206 |
207 | // Hardware Revision String Declaration
208 | {
209 | {ATT_BT_UUID_SIZE, characterUUID},
210 | GATT_PERMIT_READ,
211 | 0,
212 | &devInfoHardwareRevProps},
213 |
214 | // Hardware Revision Value
215 | {
216 | {ATT_BT_UUID_SIZE, devInfoHardwareRevUUID},
217 | GATT_PERMIT_READ,
218 | 0,
219 | (uint8_t *)devInfoHardwareRev},
220 |
221 | // Software Revision String Declaration
222 | {
223 | {ATT_BT_UUID_SIZE, characterUUID},
224 | GATT_PERMIT_READ,
225 | 0,
226 | &devInfoSoftwareRevProps},
227 |
228 | // Software Revision Value
229 | {
230 | {ATT_BT_UUID_SIZE, devInfoSoftwareRevUUID},
231 | GATT_PERMIT_READ,
232 | 0,
233 | (uint8_t *)devInfoSoftwareRev},
234 |
235 | // Manufacturer Name String Declaration
236 | {
237 | {ATT_BT_UUID_SIZE, characterUUID},
238 | GATT_PERMIT_READ,
239 | 0,
240 | &devInfoMfrNameProps},
241 |
242 | // Manufacturer Name Value
243 | {
244 | {ATT_BT_UUID_SIZE, devInfoMfrNameUUID},
245 | GATT_PERMIT_READ,
246 | 0,
247 | (uint8_t *)devInfoMfrName},
248 |
249 | // IEEE 11073-20601 Regulatory Certification Data List Declaration
250 | {
251 | {ATT_BT_UUID_SIZE, characterUUID},
252 | GATT_PERMIT_READ,
253 | 0,
254 | &devInfo11073CertProps},
255 |
256 | // IEEE 11073-20601 Regulatory Certification Data List Value
257 | {
258 | {ATT_BT_UUID_SIZE, devInfo11073CertUUID},
259 | GATT_PERMIT_READ,
260 | 0,
261 | (uint8_t *)devInfo11073Cert},
262 |
263 | // PnP ID Declaration
264 | {
265 | {ATT_BT_UUID_SIZE, characterUUID},
266 | GATT_PERMIT_READ,
267 | 0,
268 | &devInfoPnpIdProps},
269 |
270 | // PnP ID Value
271 | {
272 | {ATT_BT_UUID_SIZE, devInfoPnpIdUUID},
273 | GATT_PERMIT_READ,
274 | 0,
275 | (uint8_t *)devInfoPnpId}};
276 |
277 | /*********************************************************************
278 | * LOCAL FUNCTIONS
279 | */
280 | static bStatus_t devInfo_ReadAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
281 | uint8_t *pValue, uint16_t *pLen, uint16_t offset, uint16_t maxLen, uint8_t method);
282 |
283 | /*********************************************************************
284 | * PROFILE CALLBACKS
285 | */
286 | // Device Info Service Callbacks
287 | gattServiceCBs_t devInfoCBs = {
288 | devInfo_ReadAttrCB, // Read callback function pointer
289 | NULL, // Write callback function pointer
290 | NULL // Authorization callback function pointer
291 | };
292 |
293 | /*********************************************************************
294 | * NETWORK LAYER CALLBACKS
295 | */
296 |
297 | /*********************************************************************
298 | * PUBLIC FUNCTIONS
299 | */
300 |
301 | /*********************************************************************
302 | * @fn DevInfo_AddService
303 | *
304 | * @brief Initializes the Device Information service by registering
305 | * GATT attributes with the GATT server.
306 | *
307 | * @return Success or Failure
308 | */
309 | bStatus_t DevInfo_AddService(void)
310 | {
311 | // Register GATT attribute list and CBs with GATT Server App
312 | return GATTServApp_RegisterService(devInfoAttrTbl,
313 | GATT_NUM_ATTRS(devInfoAttrTbl),
314 | GATT_MAX_ENCRYPT_KEY_SIZE,
315 | &devInfoCBs);
316 | }
317 |
318 | /*********************************************************************
319 | * @fn DevInfo_SetParameter
320 | *
321 | * @brief Set a Device Information parameter.
322 | *
323 | * @param param - Profile parameter ID
324 | * @param len - length of data to write
325 | * @param value - pointer to data to write. This is dependent on
326 | * the parameter ID and WILL be cast to the appropriate
327 | * data type (example: data type of uint16_t will be cast to
328 | * uint16_t pointer).
329 | *
330 | * @return bStatus_t
331 | */
332 | bStatus_t DevInfo_SetParameter(uint8_t param, uint8_t len, void *value)
333 | {
334 | bStatus_t ret = SUCCESS;
335 |
336 | switch(param)
337 | {
338 | case DEVINFO_SYSTEM_ID:
339 | tmos_memcpy(devInfoSystemId, value, len);
340 | break;
341 |
342 | default:
343 | ret = INVALIDPARAMETER;
344 | break;
345 | }
346 |
347 | return (ret);
348 | }
349 |
350 | /*********************************************************************
351 | * @fn DevInfo_GetParameter
352 | *
353 | * @brief Get a Device Information parameter.
354 | *
355 | * @param param - Profile parameter ID
356 | * @param value - pointer to data to get. This is dependent on
357 | * the parameter ID and WILL be cast to the appropriate
358 | * data type (example: data type of uint16_t will be cast to
359 | * uint16_t pointer).
360 | *
361 | * @return bStatus_t
362 | */
363 | bStatus_t DevInfo_GetParameter(uint8_t param, void *value)
364 | {
365 | bStatus_t ret = SUCCESS;
366 |
367 | switch(param)
368 | {
369 | case DEVINFO_SYSTEM_ID:
370 | tmos_memcpy(value, devInfoSystemId, sizeof(devInfoSystemId));
371 | break;
372 |
373 | case DEVINFO_MODEL_NUMBER:
374 | tmos_memcpy(value, devInfoModelNumber, sizeof(devInfoModelNumber));
375 | break;
376 | case DEVINFO_SERIAL_NUMBER:
377 | tmos_memcpy(value, devInfoSerialNumber, sizeof(devInfoSerialNumber));
378 | break;
379 |
380 | case DEVINFO_FIRMWARE_REV:
381 | tmos_memcpy(value, devInfoFirmwareRev, sizeof(devInfoFirmwareRev));
382 | break;
383 |
384 | case DEVINFO_HARDWARE_REV:
385 | tmos_memcpy(value, devInfoHardwareRev, sizeof(devInfoHardwareRev));
386 | break;
387 |
388 | case DEVINFO_SOFTWARE_REV:
389 | tmos_memcpy(value, devInfoSoftwareRev, sizeof(devInfoSoftwareRev));
390 | break;
391 |
392 | case DEVINFO_MANUFACTURER_NAME:
393 | tmos_memcpy(value, devInfoMfrName, sizeof(devInfoMfrName));
394 | break;
395 |
396 | case DEVINFO_11073_CERT_DATA:
397 | tmos_memcpy(value, devInfo11073Cert, sizeof(devInfo11073Cert));
398 | break;
399 |
400 | case DEVINFO_PNP_ID:
401 | tmos_memcpy(value, devInfoPnpId, sizeof(devInfoPnpId));
402 | break;
403 |
404 | default:
405 | ret = INVALIDPARAMETER;
406 | break;
407 | }
408 |
409 | return (ret);
410 | }
411 |
412 | /*********************************************************************
413 | * @fn devInfo_ReadAttrCB
414 | *
415 | * @brief Read an attribute.
416 | *
417 | * @param connHandle - connection message was received on
418 | * @param pAttr - pointer to attribute
419 | * @param pValue - pointer to data to be read
420 | * @param pLen - length of data to be read
421 | * @param offset - offset of the first octet to be read
422 | * @param maxLen - maximum length of data to be read
423 | *
424 | * @return Success or Failure
425 | */
426 | static bStatus_t devInfo_ReadAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
427 | uint8_t *pValue, uint16_t *pLen, uint16_t offset, uint16_t maxLen, uint8_t method)
428 | {
429 | bStatus_t status = SUCCESS;
430 | uint16_t uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]);
431 |
432 | switch(uuid)
433 | {
434 | case SYSTEM_ID_UUID:
435 | // verify offset
436 | if(offset >= sizeof(devInfoSystemId))
437 | {
438 | status = ATT_ERR_INVALID_OFFSET;
439 | }
440 | else
441 | {
442 | // determine read length
443 | *pLen = MIN(maxLen, (sizeof(devInfoSystemId) - offset));
444 |
445 | // copy data
446 | tmos_memcpy(pValue, &devInfoSystemId[offset], *pLen);
447 | }
448 | break;
449 |
450 | case MODEL_NUMBER_UUID:
451 | // verify offset
452 | if(offset >= (sizeof(devInfoModelNumber) - 1))
453 | {
454 | status = ATT_ERR_INVALID_OFFSET;
455 | }
456 | else
457 | {
458 | // determine read length (exclude null terminating character)
459 | *pLen = MIN(maxLen, ((sizeof(devInfoModelNumber) - 1) - offset));
460 |
461 | // copy data
462 | tmos_memcpy(pValue, &devInfoModelNumber[offset], *pLen);
463 | }
464 | break;
465 |
466 | case SERIAL_NUMBER_UUID:
467 | // verify offset
468 | if(offset >= (sizeof(devInfoSerialNumber) - 1))
469 | {
470 | status = ATT_ERR_INVALID_OFFSET;
471 | }
472 | else
473 | {
474 | // determine read length (exclude null terminating character)
475 | *pLen = MIN(maxLen, ((sizeof(devInfoSerialNumber) - 1) - offset));
476 |
477 | // copy data
478 | tmos_memcpy(pValue, &devInfoSerialNumber[offset], *pLen);
479 | }
480 | break;
481 |
482 | case FIRMWARE_REV_UUID:
483 | // verify offset
484 | if(offset >= (sizeof(devInfoFirmwareRev) - 1))
485 | {
486 | status = ATT_ERR_INVALID_OFFSET;
487 | }
488 | else
489 | {
490 | // determine read length (exclude null terminating character)
491 | *pLen = MIN(maxLen, ((sizeof(devInfoFirmwareRev) - 1) - offset));
492 |
493 | // copy data
494 | tmos_memcpy(pValue, &devInfoFirmwareRev[offset], *pLen);
495 | }
496 | break;
497 |
498 | case HARDWARE_REV_UUID:
499 | // verify offset
500 | if(offset >= (sizeof(devInfoHardwareRev) - 1))
501 | {
502 | status = ATT_ERR_INVALID_OFFSET;
503 | }
504 | else
505 | {
506 | // determine read length (exclude null terminating character)
507 | *pLen = MIN(maxLen, ((sizeof(devInfoHardwareRev) - 1) - offset));
508 |
509 | // copy data
510 | tmos_memcpy(pValue, &devInfoHardwareRev[offset], *pLen);
511 | }
512 | break;
513 |
514 | case SOFTWARE_REV_UUID:
515 | // verify offset
516 | if(offset >= (sizeof(devInfoSoftwareRev) - 1))
517 | {
518 | status = ATT_ERR_INVALID_OFFSET;
519 | }
520 | else
521 | {
522 | // determine read length (exclude null terminating character)
523 | *pLen = MIN(maxLen, ((sizeof(devInfoSoftwareRev) - 1) - offset));
524 |
525 | // copy data
526 | tmos_memcpy(pValue, &devInfoSoftwareRev[offset], *pLen);
527 | }
528 | break;
529 |
530 | case MANUFACTURER_NAME_UUID:
531 | // verify offset
532 | if(offset >= (sizeof(devInfoMfrName) - 1))
533 | {
534 | status = ATT_ERR_INVALID_OFFSET;
535 | }
536 | else
537 | {
538 | // determine read length (exclude null terminating character)
539 | *pLen = MIN(maxLen, ((sizeof(devInfoMfrName) - 1) - offset));
540 |
541 | // copy data
542 | tmos_memcpy(pValue, &devInfoMfrName[offset], *pLen);
543 | }
544 | break;
545 |
546 | case IEEE_11073_CERT_DATA_UUID:
547 | // verify offset
548 | if(offset >= sizeof(devInfo11073Cert))
549 | {
550 | status = ATT_ERR_INVALID_OFFSET;
551 | }
552 | else
553 | {
554 | // determine read length
555 | *pLen = MIN(maxLen, (sizeof(devInfo11073Cert) - offset));
556 |
557 | // copy data
558 | tmos_memcpy(pValue, &devInfo11073Cert[offset], *pLen);
559 | }
560 | break;
561 |
562 | case PNP_ID_UUID:
563 | // verify offset
564 | if(offset >= sizeof(devInfoPnpId))
565 | {
566 | status = ATT_ERR_INVALID_OFFSET;
567 | }
568 | else
569 | {
570 | // determine read length
571 | *pLen = MIN(maxLen, (sizeof(devInfoPnpId) - offset));
572 |
573 | // copy data
574 | tmos_memcpy(pValue, &devInfoPnpId[offset], *pLen);
575 | }
576 | break;
577 |
578 | default:
579 | *pLen = 0;
580 | status = ATT_ERR_ATTR_NOT_FOUND;
581 | break;
582 | }
583 |
584 | return (status);
585 | }
586 |
587 | /*********************************************************************
588 | *********************************************************************/
589 |
--------------------------------------------------------------------------------
/sample/test_ch592f_ble_hid_keyboard_org/devinfoservice.h:
--------------------------------------------------------------------------------
1 | /********************************** (C) COPYRIGHT *******************************
2 | * File Name : devinfoservice.h
3 | * Author : WCH
4 | * Version : V1.0
5 | * Date : 2018/12/11
6 | * Description :
7 | *********************************************************************************
8 | * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
9 | * Attention: This software (modified or not) and binary are used for
10 | * microcontroller manufactured by Nanjing Qinheng Microelectronics.
11 | *******************************************************************************/
12 |
13 | #ifndef DEVINFOSERVICE_H
14 | #define DEVINFOSERVICE_H
15 |
16 | #ifdef __cplusplus
17 | extern "C" {
18 | #endif
19 |
20 | /*********************************************************************
21 | * INCLUDES
22 | */
23 |
24 | /*********************************************************************
25 | * CONSTANTS
26 | */
27 |
28 | // Device Information Service Parameters
29 | #define DEVINFO_SYSTEM_ID 0
30 | #define DEVINFO_MODEL_NUMBER 1
31 | #define DEVINFO_SERIAL_NUMBER 2
32 | #define DEVINFO_FIRMWARE_REV 3
33 | #define DEVINFO_HARDWARE_REV 4
34 | #define DEVINFO_SOFTWARE_REV 5
35 | #define DEVINFO_MANUFACTURER_NAME 6
36 | #define DEVINFO_11073_CERT_DATA 7
37 | #define DEVINFO_PNP_ID 8
38 |
39 | // IEEE 11073 authoritative body values
40 | #define DEVINFO_11073_BODY_EMPTY 0
41 | #define DEVINFO_11073_BODY_IEEE 1
42 | #define DEVINFO_11073_BODY_CONTINUA 2
43 | #define DEVINFO_11073_BODY_EXP 254
44 |
45 | // System ID length
46 | #define DEVINFO_SYSTEM_ID_LEN 8
47 |
48 | // PnP ID length
49 | #define DEVINFO_PNP_ID_LEN 7
50 |
51 | /*********************************************************************
52 | * TYPEDEFS
53 | */
54 |
55 | /*********************************************************************
56 | * MACROS
57 | */
58 |
59 | /*********************************************************************
60 | * Profile Callbacks
61 | */
62 |
63 | /*********************************************************************
64 | * API FUNCTIONS
65 | */
66 |
67 | /*
68 | * DevInfo_AddService- Initializes the Device Information service by registering
69 | * GATT attributes with the GATT server.
70 | *
71 | */
72 |
73 | extern bStatus_t DevInfo_AddService(void);
74 |
75 | /*********************************************************************
76 | * @fn DevInfo_SetParameter
77 | *
78 | * @brief Set a Device Information parameter.
79 | *
80 | * @param param - Profile parameter ID
81 | * @param len - length of data to right
82 | * @param value - pointer to data to write. This is dependent on
83 | * the parameter ID and WILL be cast to the appropriate
84 | * data type (example: data type of uint16_t will be cast to
85 | * uint16_t pointer).
86 | *
87 | * @return bStatus_t
88 | */
89 | bStatus_t DevInfo_SetParameter(uint8_t param, uint8_t len, void *value);
90 |
91 | /*
92 | * DevInfo_GetParameter - Get a Device Information parameter.
93 | *
94 | * param - Profile parameter ID
95 | * value - pointer to data to write. This is dependent on
96 | * the parameter ID and WILL be cast to the appropriate
97 | * data type (example: data type of uint16_t will be cast to
98 | * uint16_t pointer).
99 | */
100 | extern bStatus_t DevInfo_GetParameter(uint8_t param, void *value);
101 |
102 | /*********************************************************************
103 | *********************************************************************/
104 |
105 | #ifdef __cplusplus
106 | }
107 | #endif
108 |
109 | #endif /* DEVINFOSERVICE_H */
110 |
--------------------------------------------------------------------------------
/sample/test_ch592f_ble_hid_keyboard_org/hidkbd.c:
--------------------------------------------------------------------------------
1 | /********************************** (C) COPYRIGHT *******************************
2 | * File Name : hidkbd.c
3 | * Author : WCH
4 | * Version : V1.0
5 | * Date : 2018/12/10
6 | * Description : ��������Ӧ�ó���ʼ���㲥���Ӳ�����Ȼ��㲥��ֱ������������ʱ�ϴ���ֵ
7 | *********************************************************************************
8 | * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
9 | * Attention: This software (modified or not) and binary are used for
10 | * microcontroller manufactured by Nanjing Qinheng Microelectronics.
11 | *******************************************************************************/
12 |
13 | /*********************************************************************
14 | * INCLUDES
15 | */
16 | #include "CONFIG.h"
17 | #include "devinfoservice.h"
18 | #include "battservice.h"
19 | #include "hidkbdservice.h"
20 | #include "hiddev.h"
21 | #include "hidkbd.h"
22 |
23 | /*********************************************************************
24 | * MACROS
25 | */
26 | // HID keyboard input report length
27 | #define HID_KEYBOARD_IN_RPT_LEN 8
28 |
29 | // HID LED output report length
30 | #define HID_LED_OUT_RPT_LEN 1
31 |
32 | /*********************************************************************
33 | * CONSTANTS
34 | */
35 | // Param update delay
36 | #define START_PARAM_UPDATE_EVT_DELAY 12800
37 |
38 | // Param update delay
39 | #define START_PHY_UPDATE_DELAY 1600
40 |
41 | // HID idle timeout in msec; set to zero to disable timeout
42 | #define DEFAULT_HID_IDLE_TIMEOUT 60000
43 |
44 | // Minimum connection interval (units of 1.25ms)
45 | #define DEFAULT_DESIRED_MIN_CONN_INTERVAL 8
46 |
47 | // Maximum connection interval (units of 1.25ms)
48 | #define DEFAULT_DESIRED_MAX_CONN_INTERVAL 8
49 |
50 | // Slave latency to use if parameter update request
51 | #define DEFAULT_DESIRED_SLAVE_LATENCY 0
52 |
53 | // Supervision timeout value (units of 10ms)
54 | #define DEFAULT_DESIRED_CONN_TIMEOUT 500
55 |
56 | // Default passcode
57 | #define DEFAULT_PASSCODE 0
58 |
59 | // Default GAP pairing mode
60 | #define DEFAULT_PAIRING_MODE GAPBOND_PAIRING_MODE_WAIT_FOR_REQ
61 |
62 | // Default MITM mode (TRUE to require passcode or OOB when pairing)
63 | #define DEFAULT_MITM_MODE FALSE
64 |
65 | // Default bonding mode, TRUE to bond
66 | #define DEFAULT_BONDING_MODE TRUE
67 |
68 | // Default GAP bonding I/O capabilities
69 | #define DEFAULT_IO_CAPABILITIES GAPBOND_IO_CAP_NO_INPUT_NO_OUTPUT
70 |
71 | // Battery level is critical when it is less than this %
72 | #define DEFAULT_BATT_CRITICAL_LEVEL 6
73 |
74 | /*********************************************************************
75 | * TYPEDEFS
76 | */
77 |
78 | /*********************************************************************
79 | * GLOBAL VARIABLES
80 | */
81 |
82 | // Task ID
83 | static uint8_t hidEmuTaskId = INVALID_TASK_ID;
84 |
85 | /*********************************************************************
86 | * EXTERNAL VARIABLES
87 | */
88 |
89 | /*********************************************************************
90 | * EXTERNAL FUNCTIONS
91 | */
92 |
93 | /*********************************************************************
94 | * LOCAL VARIABLES
95 | */
96 |
97 | // GAP Profile - Name attribute for SCAN RSP data
98 | static uint8_t scanRspData[] = {
99 | 0x0D, // length of this data
100 | GAP_ADTYPE_LOCAL_NAME_COMPLETE, // AD Type = Complete local name
101 | 'H',
102 | 'I',
103 | 'D',
104 | ' ',
105 | 'K',
106 | 'e',
107 | 'y',
108 | 'b',
109 | 'r',
110 | 'o',
111 | 'a',
112 | 'd', // connection interval range
113 | 0x05, // length of this data
114 | GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE,
115 | LO_UINT16(DEFAULT_DESIRED_MIN_CONN_INTERVAL), // 100ms
116 | HI_UINT16(DEFAULT_DESIRED_MIN_CONN_INTERVAL),
117 | LO_UINT16(DEFAULT_DESIRED_MAX_CONN_INTERVAL), // 1s
118 | HI_UINT16(DEFAULT_DESIRED_MAX_CONN_INTERVAL),
119 |
120 | // service UUIDs
121 | 0x05, // length of this data
122 | GAP_ADTYPE_16BIT_MORE,
123 | LO_UINT16(HID_SERV_UUID),
124 | HI_UINT16(HID_SERV_UUID),
125 | LO_UINT16(BATT_SERV_UUID),
126 | HI_UINT16(BATT_SERV_UUID),
127 |
128 | // Tx power level
129 | 0x02, // length of this data
130 | GAP_ADTYPE_POWER_LEVEL,
131 | 0 // 0dBm
132 | };
133 |
134 | // Advertising data
135 | static uint8_t advertData[] = {
136 | // flags
137 | 0x02, // length of this data
138 | GAP_ADTYPE_FLAGS,
139 | GAP_ADTYPE_FLAGS_LIMITED | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED,
140 |
141 | // appearance
142 | 0x03, // length of this data
143 | GAP_ADTYPE_APPEARANCE,
144 | LO_UINT16(GAP_APPEARE_HID_KEYBOARD),
145 | HI_UINT16(GAP_APPEARE_HID_KEYBOARD)};
146 |
147 | // Device name attribute value
148 | static CONST uint8_t attDeviceName[GAP_DEVICE_NAME_LEN] = "HID Keyboard";
149 |
150 | // HID Dev configuration
151 | static hidDevCfg_t hidEmuCfg = {
152 | DEFAULT_HID_IDLE_TIMEOUT, // Idle timeout
153 | HID_FEATURE_FLAGS // HID feature flags
154 | };
155 |
156 | static uint16_t hidEmuConnHandle = GAP_CONNHANDLE_INIT;
157 |
158 | /*********************************************************************
159 | * LOCAL FUNCTIONS
160 | */
161 |
162 | static void hidEmu_ProcessTMOSMsg(tmos_event_hdr_t *pMsg);
163 | static void hidEmuSendKbdReport(uint8_t keycode);
164 | static uint8_t hidEmuRcvReport(uint8_t len, uint8_t *pData);
165 | static uint8_t hidEmuRptCB(uint8_t id, uint8_t type, uint16_t uuid,
166 | uint8_t oper, uint16_t *pLen, uint8_t *pData);
167 | static void hidEmuEvtCB(uint8_t evt);
168 | static void hidEmuStateCB(gapRole_States_t newState, gapRoleEvent_t *pEvent);
169 |
170 | /*********************************************************************
171 | * PROFILE CALLBACKS
172 | */
173 |
174 | static hidDevCB_t hidEmuHidCBs = {
175 | hidEmuRptCB,
176 | hidEmuEvtCB,
177 | NULL,
178 | hidEmuStateCB};
179 |
180 | /*********************************************************************
181 | * PUBLIC FUNCTIONS
182 | */
183 |
184 | /*********************************************************************
185 | * @fn HidEmu_Init
186 | *
187 | * @brief Initialization function for the HidEmuKbd App Task.
188 | * This is called during initialization and should contain
189 | * any application specific initialization (ie. hardware
190 | * initialization/setup, table initialization, power up
191 | * notificaiton ... ).
192 | *
193 | * @param task_id - the ID assigned by TMOS. This ID should be
194 | * used to send messages and set timers.
195 | *
196 | * @return none
197 | */
198 | void HidEmu_Init()
199 | {
200 | hidEmuTaskId = TMOS_ProcessEventRegister(HidEmu_ProcessEvent);
201 |
202 | // Setup the GAP Peripheral Role Profile
203 | {
204 | uint8_t initial_advertising_enable = TRUE;
205 |
206 | // Set the GAP Role Parameters
207 | GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &initial_advertising_enable);
208 |
209 | GAPRole_SetParameter(GAPROLE_ADVERT_DATA, sizeof(advertData), advertData);
210 | GAPRole_SetParameter(GAPROLE_SCAN_RSP_DATA, sizeof(scanRspData), scanRspData);
211 | }
212 |
213 | // Set the GAP Characteristics
214 | GGS_SetParameter(GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, (void *)attDeviceName);
215 |
216 | // Setup the GAP Bond Manager
217 | {
218 | uint32_t passkey = DEFAULT_PASSCODE;
219 | uint8_t pairMode = DEFAULT_PAIRING_MODE;
220 | uint8_t mitm = DEFAULT_MITM_MODE;
221 | uint8_t ioCap = DEFAULT_IO_CAPABILITIES;
222 | uint8_t bonding = DEFAULT_BONDING_MODE;
223 | GAPBondMgr_SetParameter(GAPBOND_PERI_DEFAULT_PASSCODE, sizeof(uint32_t), &passkey);
224 | GAPBondMgr_SetParameter(GAPBOND_PERI_PAIRING_MODE, sizeof(uint8_t), &pairMode);
225 | GAPBondMgr_SetParameter(GAPBOND_PERI_MITM_PROTECTION, sizeof(uint8_t), &mitm);
226 | GAPBondMgr_SetParameter(GAPBOND_PERI_IO_CAPABILITIES, sizeof(uint8_t), &ioCap);
227 | GAPBondMgr_SetParameter(GAPBOND_PERI_BONDING_ENABLED, sizeof(uint8_t), &bonding);
228 | }
229 |
230 | // Setup Battery Characteristic Values
231 | {
232 | uint8_t critical = DEFAULT_BATT_CRITICAL_LEVEL;
233 | Batt_SetParameter(BATT_PARAM_CRITICAL_LEVEL, sizeof(uint8_t), &critical);
234 | }
235 |
236 | // Set up HID keyboard service
237 | Hid_AddService();
238 |
239 | // Register for HID Dev callback
240 | HidDev_Register(&hidEmuCfg, &hidEmuHidCBs);
241 |
242 | // Setup a delayed profile startup
243 | tmos_set_event(hidEmuTaskId, START_DEVICE_EVT);
244 | }
245 |
246 | /*********************************************************************
247 | * @fn HidEmu_ProcessEvent
248 | *
249 | * @brief HidEmuKbd Application Task event processor. This function
250 | * is called to process all events for the task. Events
251 | * include timers, messages and any other user defined events.
252 | *
253 | * @param task_id - The TMOS assigned task ID.
254 | * @param events - events to process. This is a bit map and can
255 | * contain more than one event.
256 | *
257 | * @return events not processed
258 | */
259 | uint16_t HidEmu_ProcessEvent(uint8_t task_id, uint16_t events)
260 | {
261 | static uint8_t send_char = 4;
262 |
263 | if(events & SYS_EVENT_MSG)
264 | {
265 | uint8_t *pMsg;
266 |
267 | if((pMsg = tmos_msg_receive(hidEmuTaskId)) != NULL)
268 | {
269 | hidEmu_ProcessTMOSMsg((tmos_event_hdr_t *)pMsg);
270 |
271 | // Release the TMOS message
272 | tmos_msg_deallocate(pMsg);
273 | }
274 |
275 | // return unprocessed events
276 | return (events ^ SYS_EVENT_MSG);
277 | }
278 |
279 | if(events & START_DEVICE_EVT)
280 | {
281 | return (events ^ START_DEVICE_EVT);
282 | }
283 |
284 | if(events & START_PARAM_UPDATE_EVT)
285 | {
286 | // Send connect param update request
287 | GAPRole_PeripheralConnParamUpdateReq(hidEmuConnHandle,
288 | DEFAULT_DESIRED_MIN_CONN_INTERVAL,
289 | DEFAULT_DESIRED_MAX_CONN_INTERVAL,
290 | DEFAULT_DESIRED_SLAVE_LATENCY,
291 | DEFAULT_DESIRED_CONN_TIMEOUT,
292 | hidEmuTaskId);
293 |
294 | return (events ^ START_PARAM_UPDATE_EVT);
295 | }
296 |
297 | if(events & START_PHY_UPDATE_EVT)
298 | {
299 | // start phy update
300 | PRINT("Send Phy Update %x...\n", GAPRole_UpdatePHY(hidEmuConnHandle, 0,
301 | GAP_PHY_BIT_LE_2M, GAP_PHY_BIT_LE_2M, 0));
302 |
303 | return (events ^ START_PHY_UPDATE_EVT);
304 | }
305 |
306 | if(events & START_REPORT_EVT)
307 | {
308 | hidEmuSendKbdReport(send_char);
309 | send_char++;
310 | if(send_char >= 29)
311 | send_char = 4;
312 | hidEmuSendKbdReport(0x00);
313 | tmos_start_task(hidEmuTaskId, START_REPORT_EVT, 2000);
314 | return (events ^ START_REPORT_EVT);
315 | }
316 | return 0;
317 | }
318 |
319 | /*********************************************************************
320 | * @fn hidEmu_ProcessTMOSMsg
321 | *
322 | * @brief Process an incoming task message.
323 | *
324 | * @param pMsg - message to process
325 | *
326 | * @return none
327 | */
328 | static void hidEmu_ProcessTMOSMsg(tmos_event_hdr_t *pMsg)
329 | {
330 | switch(pMsg->event)
331 | {
332 | default:
333 | break;
334 | }
335 | }
336 |
337 | /*********************************************************************
338 | * @fn hidEmuSendKbdReport
339 | *
340 | * @brief Build and send a HID keyboard report.
341 | *
342 | * @param keycode - HID keycode.
343 | *
344 | * @return none
345 | */
346 | static void hidEmuSendKbdReport(uint8_t keycode)
347 | {
348 | uint8_t buf[HID_KEYBOARD_IN_RPT_LEN];
349 |
350 | buf[0] = 0; // Modifier keys
351 | buf[1] = 0; // Reserved
352 | buf[2] = keycode; // Keycode 1
353 | buf[3] = 0; // Keycode 2
354 | buf[4] = 0; // Keycode 3
355 | buf[5] = 0; // Keycode 4
356 | buf[6] = 0; // Keycode 5
357 | buf[7] = 0; // Keycode 6
358 |
359 | HidDev_Report(HID_RPT_ID_KEY_IN, HID_REPORT_TYPE_INPUT,
360 | HID_KEYBOARD_IN_RPT_LEN, buf);
361 | }
362 |
363 | /*********************************************************************
364 | * @fn hidEmuStateCB
365 | *
366 | * @brief GAP state change callback.
367 | *
368 | * @param newState - new state
369 | *
370 | * @return none
371 | */
372 | static void hidEmuStateCB(gapRole_States_t newState, gapRoleEvent_t *pEvent)
373 | {
374 | switch(newState & GAPROLE_STATE_ADV_MASK)
375 | {
376 | case GAPROLE_STARTED:
377 | {
378 | uint8_t ownAddr[6];
379 | GAPRole_GetParameter(GAPROLE_BD_ADDR, ownAddr);
380 | GAP_ConfigDeviceAddr(ADDRTYPE_STATIC, ownAddr);
381 | PRINT("Initialized..\n");
382 | }
383 | break;
384 |
385 | case GAPROLE_ADVERTISING:
386 | if(pEvent->gap.opcode == GAP_MAKE_DISCOVERABLE_DONE_EVENT)
387 | {
388 | PRINT("Advertising..\n");
389 | }
390 | break;
391 |
392 | case GAPROLE_CONNECTED:
393 | if(pEvent->gap.opcode == GAP_LINK_ESTABLISHED_EVENT)
394 | {
395 | gapEstLinkReqEvent_t *event = (gapEstLinkReqEvent_t *)pEvent;
396 |
397 | // get connection handle
398 | hidEmuConnHandle = event->connectionHandle;
399 | tmos_start_task(hidEmuTaskId, START_PARAM_UPDATE_EVT, START_PARAM_UPDATE_EVT_DELAY);
400 | PRINT("Connected..\n");
401 | }
402 | break;
403 |
404 | case GAPROLE_CONNECTED_ADV:
405 | if(pEvent->gap.opcode == GAP_MAKE_DISCOVERABLE_DONE_EVENT)
406 | {
407 | PRINT("Connected Advertising..\n");
408 | }
409 | break;
410 |
411 | case GAPROLE_WAITING:
412 | if(pEvent->gap.opcode == GAP_END_DISCOVERABLE_DONE_EVENT)
413 | {
414 | PRINT("Waiting for advertising..\n");
415 | }
416 | else if(pEvent->gap.opcode == GAP_LINK_TERMINATED_EVENT)
417 | {
418 | PRINT("Disconnected.. Reason:%x\n", pEvent->linkTerminate.reason);
419 | }
420 | else if(pEvent->gap.opcode == GAP_LINK_ESTABLISHED_EVENT)
421 | {
422 | PRINT("Advertising timeout..\n");
423 | }
424 | // Enable advertising
425 | {
426 | uint8_t initial_advertising_enable = TRUE;
427 | // Set the GAP Role Parameters
428 | GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &initial_advertising_enable);
429 | }
430 | break;
431 |
432 | case GAPROLE_ERROR:
433 | PRINT("Error %x ..\n", pEvent->gap.opcode);
434 | break;
435 |
436 | default:
437 | break;
438 | }
439 | }
440 |
441 | /*********************************************************************
442 | * @fn hidEmuRcvReport
443 | *
444 | * @brief Process an incoming HID keyboard report.
445 | *
446 | * @param len - Length of report.
447 | * @param pData - Report data.
448 | *
449 | * @return status
450 | */
451 | static uint8_t hidEmuRcvReport(uint8_t len, uint8_t *pData)
452 | {
453 | // verify data length
454 | if(len == HID_LED_OUT_RPT_LEN)
455 | {
456 | // set LEDs
457 | return SUCCESS;
458 | }
459 | else
460 | {
461 | return ATT_ERR_INVALID_VALUE_SIZE;
462 | }
463 | }
464 |
465 | /*********************************************************************
466 | * @fn hidEmuRptCB
467 | *
468 | * @brief HID Dev report callback.
469 | *
470 | * @param id - HID report ID.
471 | * @param type - HID report type.
472 | * @param uuid - attribute uuid.
473 | * @param oper - operation: read, write, etc.
474 | * @param len - Length of report.
475 | * @param pData - Report data.
476 | *
477 | * @return GATT status code.
478 | */
479 | static uint8_t hidEmuRptCB(uint8_t id, uint8_t type, uint16_t uuid,
480 | uint8_t oper, uint16_t *pLen, uint8_t *pData)
481 | {
482 | uint8_t status = SUCCESS;
483 |
484 | // write
485 | if(oper == HID_DEV_OPER_WRITE)
486 | {
487 | if(uuid == REPORT_UUID)
488 | {
489 | // process write to LED output report; ignore others
490 | if(type == HID_REPORT_TYPE_OUTPUT)
491 | {
492 | status = hidEmuRcvReport(*pLen, pData);
493 | }
494 | }
495 |
496 | if(status == SUCCESS)
497 | {
498 | status = Hid_SetParameter(id, type, uuid, *pLen, pData);
499 | }
500 | }
501 | // read
502 | else if(oper == HID_DEV_OPER_READ)
503 | {
504 | status = Hid_GetParameter(id, type, uuid, pLen, pData);
505 | }
506 | // notifications enabled
507 | else if(oper == HID_DEV_OPER_ENABLE)
508 | {
509 | tmos_start_task(hidEmuTaskId, START_REPORT_EVT, 500);
510 | }
511 | return status;
512 | }
513 |
514 | /*********************************************************************
515 | * @fn hidEmuEvtCB
516 | *
517 | * @brief HID Dev event callback.
518 | *
519 | * @param evt - event ID.
520 | *
521 | * @return HID response code.
522 | */
523 | static void hidEmuEvtCB(uint8_t evt)
524 | {
525 | // process enter/exit suspend or enter/exit boot mode
526 | return;
527 | }
528 |
529 | /*********************************************************************
530 | *********************************************************************/
531 |
--------------------------------------------------------------------------------
/sample/test_ch592f_ble_hid_keyboard_org/hidkbd.h:
--------------------------------------------------------------------------------
1 | /********************************** (C) COPYRIGHT *******************************
2 | * File Name : hidkbd.h
3 | * Author : WCH
4 | * Version : V1.0
5 | * Date : 2018/12/10
6 | * Description :
7 | *********************************************************************************
8 | * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
9 | * Attention: This software (modified or not) and binary are used for
10 | * microcontroller manufactured by Nanjing Qinheng Microelectronics.
11 | *******************************************************************************/
12 |
13 | #ifndef HIDKBD_H
14 | #define HIDKBD_H
15 |
16 | #ifdef __cplusplus
17 | extern "C" {
18 | #endif
19 |
20 | /*********************************************************************
21 | * INCLUDES
22 | */
23 |
24 | /*********************************************************************
25 | * CONSTANTS
26 | */
27 |
28 | // Task Events
29 | #define START_DEVICE_EVT 0x0001
30 | #define START_REPORT_EVT 0x0002
31 | #define START_PARAM_UPDATE_EVT 0x0004
32 | #define START_PHY_UPDATE_EVT 0x0008
33 | /*********************************************************************
34 | * MACROS
35 | */
36 |
37 | /*********************************************************************
38 | * FUNCTIONS
39 | */
40 |
41 | /*********************************************************************
42 | * GLOBAL VARIABLES
43 | */
44 |
45 | /*
46 | * Task Initialization for the BLE Application
47 | */
48 | extern void HidEmu_Init(void);
49 |
50 | /*
51 | * Task Event Processor for the BLE Application
52 | */
53 | extern uint16_t HidEmu_ProcessEvent(uint8_t task_id, uint16_t events);
54 |
55 | /*********************************************************************
56 | *********************************************************************/
57 |
58 | #ifdef __cplusplus
59 | }
60 | #endif
61 |
62 | #endif
63 |
--------------------------------------------------------------------------------
/sample/test_ch592f_ble_hid_keyboard_org/hidkbdservice.h:
--------------------------------------------------------------------------------
1 | /********************************** (C) COPYRIGHT *******************************
2 | * File Name : hidkbdservice.h
3 | * Author : WCH
4 | * Version : V1.0
5 | * Date : 2018/12/10
6 | * Description :
7 | *********************************************************************************
8 | * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
9 | * Attention: This software (modified or not) and binary are used for
10 | * microcontroller manufactured by Nanjing Qinheng Microelectronics.
11 | *******************************************************************************/
12 |
13 | #ifndef HIDKBDSERVICE_H
14 | #define HIDKBDSERVICE_H
15 |
16 | #ifdef __cplusplus
17 | extern "C" {
18 | #endif
19 |
20 | /*********************************************************************
21 | * INCLUDES
22 | */
23 |
24 | /*********************************************************************
25 | * CONSTANTS
26 | */
27 |
28 | // Number of HID reports defined in the service
29 | #define HID_NUM_REPORTS 7
30 |
31 | // HID Report IDs for the service
32 | #define HID_RPT_ID_KEY_IN 0 // Keyboard input report ID
33 | #define HID_RPT_ID_MOUSE_IN 1 // Mouse input report ID
34 | #define HID_RPT_ID_LED_OUT 0 // LED output report ID
35 | #define HID_RPT_ID_FEATURE 0 // Feature report ID
36 |
37 | // HID feature flags
38 | #define HID_FEATURE_FLAGS HID_FLAGS_REMOTE_WAKE
39 |
40 | /*********************************************************************
41 | * TYPEDEFS
42 | */
43 |
44 | /*********************************************************************
45 | * MACROS
46 | */
47 |
48 | /*********************************************************************
49 | * Profile Callbacks
50 | */
51 |
52 | /*********************************************************************
53 | * API FUNCTIONS
54 | */
55 |
56 | /*********************************************************************
57 | * @fn Hid_AddService
58 | *
59 | * @brief Initializes the HID service for keyboard by registering
60 | * GATT attributes with the GATT server.
61 | *
62 | * @param none
63 | *
64 | * @return Success or Failure
65 | */
66 | extern bStatus_t Hid_AddService(void);
67 |
68 | /*********************************************************************
69 | * @fn Hid_SetParameter
70 | *
71 | * @brief Set a HID Kbd parameter.
72 | *
73 | * @param id - HID report ID.
74 | * @param type - HID report type.
75 | * @param uuid - attribute uuid.
76 | * @param len - length of data to right.
77 | * @param pValue - pointer to data to write. This is dependent on
78 | * the input parameters and WILL be cast to the appropriate
79 | * data type (example: data type of uint16_t will be cast to
80 | * uint16_t pointer).
81 | *
82 | * @return GATT status code.
83 | */
84 | extern uint8_t Hid_SetParameter(uint8_t id, uint8_t type, uint16_t uuid, uint8_t len,
85 | void *pValue);
86 |
87 | /*********************************************************************
88 | * @fn Hid_GetParameter
89 | *
90 | * @brief Get a HID Kbd parameter.
91 | *
92 | * @param id - HID report ID.
93 | * @param type - HID report type.
94 | * @param uuid - attribute uuid.
95 | * @param pLen - length of data to be read.
96 | * @param pValue - pointer to data to get. This is dependent on
97 | * the input parameters and WILL be cast to the appropriate
98 | * data type (example: data type of uint16_t will be cast to
99 | * uint16_t pointer).
100 | *
101 | * @return GATT status code.
102 | */
103 | extern uint8_t Hid_GetParameter(uint8_t id, uint8_t type, uint16_t uuid, uint16_t *pLen, void *pValue);
104 |
105 | /*********************************************************************
106 | *********************************************************************/
107 |
108 | #ifdef __cplusplus
109 | }
110 | #endif
111 |
112 | #endif /* HIDKBDSERVICE_H */
113 |
--------------------------------------------------------------------------------
/sample/test_ch592f_ble_hid_keyboard_org/scanparamservice.c:
--------------------------------------------------------------------------------
1 | /********************************** (C) COPYRIGHT *******************************
2 | * File Name : scanparamservice.c
3 | * Author : WCH
4 | * Version : V1.0
5 | * Date : 2018/12/10
6 | * Description : ɨ���������
7 | *********************************************************************************
8 | * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
9 | * Attention: This software (modified or not) and binary are used for
10 | * microcontroller manufactured by Nanjing Qinheng Microelectronics.
11 | *******************************************************************************/
12 |
13 | /*********************************************************************
14 | * INCLUDES
15 | */
16 | #include "CONFIG.h"
17 | #include "scanparamservice.h"
18 |
19 | /*********************************************************************
20 | * MACROS
21 | */
22 |
23 | /*********************************************************************
24 | * CONSTANTS
25 | */
26 |
27 | /*********************************************************************
28 | * TYPEDEFS
29 | */
30 |
31 | /*********************************************************************
32 | * GLOBAL VARIABLES
33 | */
34 | // Scan parameters service
35 | const uint8_t scanParamServUUID[ATT_BT_UUID_SIZE] = {
36 | LO_UINT16(SCAN_PARAM_SERV_UUID), HI_UINT16(SCAN_PARAM_SERV_UUID)};
37 |
38 | // Scan interval window characteristic
39 | const uint8_t scanIntervalWindowUUID[ATT_BT_UUID_SIZE] = {
40 | LO_UINT16(SCAN_INTERVAL_WINDOW_UUID), HI_UINT16(SCAN_INTERVAL_WINDOW_UUID)};
41 |
42 | // Scan parameter refresh characteristic
43 | const uint8_t scanParamRefreshUUID[ATT_BT_UUID_SIZE] = {
44 | LO_UINT16(SCAN_REFRESH_UUID), HI_UINT16(SCAN_REFRESH_UUID)};
45 |
46 | /*********************************************************************
47 | * EXTERNAL VARIABLES
48 | */
49 |
50 | /*********************************************************************
51 | * EXTERNAL FUNCTIONS
52 | */
53 |
54 | /*********************************************************************
55 | * LOCAL VARIABLES
56 | */
57 |
58 | // Application callback
59 | static scanParamServiceCB_t scanParamServiceCB;
60 |
61 | /*********************************************************************
62 | * Profile Attributes - variables
63 | */
64 |
65 | // Scan Parameters Service attribute
66 | static const gattAttrType_t scanParamService = {ATT_BT_UUID_SIZE, scanParamServUUID};
67 |
68 | // Scan Interval Window characteristic
69 | static uint8_t scanIntervalWindowProps = GATT_PROP_WRITE_NO_RSP;
70 | static uint8_t scanIntervalWindow[SCAN_INTERVAL_WINDOW_CHAR_LEN];
71 |
72 | // Scan Parameter Refresh characteristic
73 | static uint8_t scanParamRefreshProps = GATT_PROP_NOTIFY;
74 | static uint8_t scanParamRefresh[SCAN_PARAM_REFRESH_LEN];
75 | static gattCharCfg_t scanParamRefreshClientCharCfg[GATT_MAX_NUM_CONN];
76 |
77 | /*********************************************************************
78 | * Profile Attributes - Table
79 | */
80 |
81 | static gattAttribute_t scanParamAttrTbl[] = {
82 | // Scan Parameters Service attribute
83 | {
84 | {ATT_BT_UUID_SIZE, primaryServiceUUID}, /* type */
85 | GATT_PERMIT_READ, /* permissions */
86 | 0, /* handle */
87 | (uint8_t *)&scanParamService /* pValue */
88 | },
89 |
90 | // Scan Interval Window declaration
91 | {
92 | {ATT_BT_UUID_SIZE, characterUUID},
93 | GATT_PERMIT_READ,
94 | 0,
95 | &scanIntervalWindowProps},
96 |
97 | // Scan Interval Window characteristic
98 | {
99 | {ATT_BT_UUID_SIZE, scanIntervalWindowUUID},
100 | GATT_PERMIT_ENCRYPT_WRITE,
101 | 0,
102 | scanIntervalWindow},
103 |
104 | // Scan Parameter Refresh declaration
105 | {
106 | {ATT_BT_UUID_SIZE, characterUUID},
107 | GATT_PERMIT_READ,
108 | 0,
109 | &scanParamRefreshProps},
110 |
111 | // Scan Parameter Refresh characteristic
112 | {
113 | {ATT_BT_UUID_SIZE, scanParamRefreshUUID},
114 | 0,
115 | 0,
116 | scanParamRefresh},
117 |
118 | // Scan Parameter Refresh characteristic client characteristic configuration
119 | {
120 | {ATT_BT_UUID_SIZE, clientCharCfgUUID},
121 | GATT_PERMIT_READ | GATT_PERMIT_ENCRYPT_WRITE,
122 | 0,
123 | (uint8_t *)&scanParamRefreshClientCharCfg}
124 | };
125 |
126 | // Attribute index enumeration-- these indexes match array elements above
127 | enum
128 | {
129 | SCAN_PARAM_SERVICE_IDX, // Scan Parameters Service
130 | SCAN_PARAM_INTERVAL_DECL_IDX, // Scan Interval Window declaration
131 | SCAN_PARAM_INTERVAL_IDX, // Scan Interval Window characteristic
132 | SCAN_PARAM_REFRESH_DECL_IDX, // Scan Parameter Refresh declaration
133 | SCAN_PARAM_REFRESH_IDX, // Scan Parameter Refresh characteristic
134 | SCAN_PARAM_REFRESH_CCCD_IDX // Scan Parameter Refresh characteristic client characteristic configuration
135 | };
136 |
137 | /*********************************************************************
138 | * LOCAL FUNCTIONS
139 | */
140 | static bStatus_t scanParamWriteAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
141 | uint8_t *pValue, uint16_t len, uint16_t offset, uint8_t method);
142 | static bStatus_t scanParamReadAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
143 | uint8_t *pValue, uint16_t *pLen, uint16_t offset, uint16_t maxLen, uint8_t method);
144 |
145 | /*********************************************************************
146 | * PROFILE CALLBACKS
147 | */
148 |
149 | // Service Callbacks
150 | gattServiceCBs_t scanParamCBs = {
151 | scanParamReadAttrCB, // Read callback function pointer
152 | scanParamWriteAttrCB, // Write callback function pointer
153 | NULL // Authorization callback function pointer
154 | };
155 |
156 | /*********************************************************************
157 | * PUBLIC FUNCTIONS
158 | */
159 |
160 | /*********************************************************************
161 | * @fn ScanParam_AddService
162 | *
163 | * @brief Initializes the Battery Service by registering
164 | * GATT attributes with the GATT server.
165 | *
166 | * @return Success or Failure
167 | */
168 | bStatus_t ScanParam_AddService(void)
169 | {
170 | uint8_t status = SUCCESS;
171 |
172 | // Initialize Client Characteristic Configuration attributes
173 | GATTServApp_InitCharCfg(INVALID_CONNHANDLE, scanParamRefreshClientCharCfg);
174 |
175 | // Register GATT attribute list and CBs with GATT Server App
176 | status = GATTServApp_RegisterService(scanParamAttrTbl, GATT_NUM_ATTRS(scanParamAttrTbl), GATT_MAX_ENCRYPT_KEY_SIZE,
177 | &scanParamCBs);
178 |
179 | return (status);
180 | }
181 |
182 | /*********************************************************************
183 | * @fn ScanParam_Register
184 | *
185 | * @brief Register a callback function with the Battery Service.
186 | *
187 | * @param pfnServiceCB - Callback function.
188 | *
189 | * @return None.
190 | */
191 | extern void ScanParam_Register(scanParamServiceCB_t pfnServiceCB)
192 | {
193 | scanParamServiceCB = pfnServiceCB;
194 | }
195 |
196 | /*********************************************************************
197 | * @fn ScanParam_SetParameter
198 | *
199 | * @brief Set a Battery Service parameter.
200 | *
201 | * @param param - Profile parameter ID
202 | * @param len - length of data to right
203 | * @param value - pointer to data to write. This is dependent on
204 | * the parameter ID and WILL be cast to the appropriate
205 | * data type (example: data type of uint16_t will be cast to
206 | * uint16_t pointer).
207 | *
208 | * @return bStatus_t
209 | */
210 | bStatus_t ScanParam_SetParameter(uint8_t param, uint8_t len, void *value)
211 | {
212 | bStatus_t ret = SUCCESS;
213 |
214 | switch(param)
215 | {
216 | default:
217 | ret = INVALIDPARAMETER;
218 | break;
219 | }
220 |
221 | return (ret);
222 | }
223 |
224 | /*********************************************************************
225 | * @fn ScanParam_GetParameter
226 | *
227 | * @brief Get a Battery Service parameter.
228 | *
229 | * @param param - Profile parameter ID
230 | * @param value - pointer to data to get. This is dependent on
231 | * the parameter ID and WILL be cast to the appropriate
232 | * data type (example: data type of uint16_t will be cast to
233 | * uint16_t pointer).
234 | *
235 | * @return bStatus_t
236 | */
237 | bStatus_t ScanParam_GetParameter(uint8_t param, void *value)
238 | {
239 | bStatus_t ret = SUCCESS;
240 | switch(param)
241 | {
242 | case SCAN_PARAM_PARAM_INTERVAL:
243 | *((uint16_t *)value) = BUILD_UINT16(scanIntervalWindow[0],
244 | scanIntervalWindow[1]);
245 | break;
246 |
247 | case SCAN_PARAM_PARAM_WINDOW:
248 | *((uint16_t *)value) = BUILD_UINT16(scanIntervalWindow[2],
249 | scanIntervalWindow[3]);
250 | break;
251 |
252 | default:
253 | ret = INVALIDPARAMETER;
254 | break;
255 | }
256 |
257 | return (ret);
258 | }
259 |
260 | /*********************************************************************
261 | * @fn ScanParam_RefreshNotify
262 | *
263 | * @brief Notify the peer to refresh the scan parameters.
264 | *
265 | * @param connHandle - connection handle
266 | *
267 | * @return None
268 | */
269 | void ScanParam_RefreshNotify(uint16_t connHandle)
270 | {
271 | uint16_t value;
272 |
273 | value = GATTServApp_ReadCharCfg(connHandle, scanParamRefreshClientCharCfg);
274 | if(value & GATT_CLIENT_CFG_NOTIFY)
275 | {
276 | attHandleValueNoti_t noti;
277 |
278 | noti.pValue = GATT_bm_alloc(connHandle, ATT_HANDLE_VALUE_NOTI,
279 | SCAN_PARAM_REFRESH_LEN, NULL, 0);
280 | if(noti.pValue != NULL)
281 | {
282 | // send notification
283 | noti.handle = scanParamAttrTbl[SCAN_PARAM_REFRESH_CCCD_IDX].handle;
284 | noti.len = SCAN_PARAM_REFRESH_LEN;
285 | noti.pValue[0] = SCAN_PARAM_REFRESH_REQ;
286 |
287 | if(GATT_Notification(connHandle, ¬i, FALSE) != SUCCESS)
288 | {
289 | GATT_bm_free((gattMsg_t *)¬i, ATT_HANDLE_VALUE_NOTI);
290 | }
291 | }
292 | }
293 | }
294 |
295 | /*********************************************************************
296 | * @fn scanParamReadAttrCB
297 | *
298 | * @brief GATT read callback.
299 | *
300 | * @param connHandle - connection message was received on
301 | * @param pAttr - pointer to attribute
302 | * @param pValue - pointer to data to be read
303 | * @param pLen - length of data to be read
304 | * @param offset - offset of the first octet to be read
305 | * @param maxLen - maximum length of data to be read
306 | *
307 | * @return Success or Failure
308 | */
309 | static bStatus_t scanParamReadAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
310 | uint8_t *pValue, uint16_t *pLen, uint16_t offset, uint16_t maxLen, uint8_t method)
311 | {
312 | bStatus_t status = SUCCESS;
313 |
314 | return (status);
315 | }
316 |
317 | /*********************************************************************
318 | * @fn scanParamWriteAttrCB
319 | *
320 | * @brief Validate attribute data prior to a write operation
321 | *
322 | * @param connHandle - connection message was received on
323 | * @param pAttr - pointer to attribute
324 | * @param pValue - pointer to data to be written
325 | * @param len - length of data
326 | * @param offset - offset of the first octet to be written
327 | *
328 | * @return Success or Failure
329 | */
330 | static bStatus_t scanParamWriteAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
331 | uint8_t *pValue, uint16_t len, uint16_t offset, uint8_t method)
332 | {
333 | uint16_t uuid;
334 | bStatus_t status = SUCCESS;
335 |
336 | // Make sure it's not a blob operation (no attributes in the profile are long)
337 | if(offset > 0)
338 | {
339 | return (ATT_ERR_ATTR_NOT_LONG);
340 | }
341 |
342 | uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]);
343 |
344 | // Only one writeable attribute
345 | if(uuid == SCAN_INTERVAL_WINDOW_UUID)
346 | {
347 | if(len == SCAN_INTERVAL_WINDOW_CHAR_LEN)
348 | {
349 | uint16_t interval = BUILD_UINT16(pValue[0], pValue[1]);
350 | uint16_t window = BUILD_UINT16(pValue[0], pValue[1]);
351 |
352 | // Validate values
353 | if(window <= interval)
354 | {
355 | tmos_memcpy(pAttr->pValue, pValue, len);
356 |
357 | (*scanParamServiceCB)(SCAN_INTERVAL_WINDOW_SET);
358 | }
359 | else
360 | {
361 | status = ATT_ERR_INVALID_VALUE;
362 | }
363 | }
364 | else
365 | {
366 | status = ATT_ERR_INVALID_VALUE_SIZE;
367 | }
368 | }
369 | else if(uuid == GATT_CLIENT_CHAR_CFG_UUID)
370 | {
371 | status = GATTServApp_ProcessCCCWriteReq(connHandle, pAttr, pValue, len,
372 | offset, GATT_CLIENT_CFG_NOTIFY);
373 | }
374 | else
375 | {
376 | status = ATT_ERR_ATTR_NOT_FOUND;
377 | }
378 |
379 | return (status);
380 | }
381 |
382 | /*********************************************************************
383 | * @fn ScanParam_HandleConnStatusCB
384 | *
385 | * @brief Service link status change handler function.
386 | *
387 | * @param connHandle - connection handle
388 | * @param changeType - type of change
389 | *
390 | * @return none
391 | */
392 | void ScanParam_HandleConnStatusCB(uint16_t connHandle, uint8_t changeType)
393 | {
394 | // Make sure this is not loopback connection
395 | if(connHandle != LOOPBACK_CONNHANDLE)
396 | {
397 | // Reset Client Char Config if connection has dropped
398 | if((changeType == LINKDB_STATUS_UPDATE_REMOVED) ||
399 | ((changeType == LINKDB_STATUS_UPDATE_STATEFLAGS) &&
400 | (!linkDB_Up(connHandle))))
401 | {
402 | GATTServApp_InitCharCfg(connHandle, scanParamRefreshClientCharCfg);
403 | }
404 | }
405 | }
406 |
--------------------------------------------------------------------------------
/sample/test_ch592f_ble_hid_keyboard_org/scanparamservice.h:
--------------------------------------------------------------------------------
1 | /********************************** (C) COPYRIGHT *******************************
2 | * File Name : scanparamservice.h
3 | * Author : WCH
4 | * Version : V1.0
5 | * Date : 2018/12/11
6 | * Description :
7 | *********************************************************************************
8 | * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
9 | * Attention: This software (modified or not) and binary are used for
10 | * microcontroller manufactured by Nanjing Qinheng Microelectronics.
11 | *******************************************************************************/
12 |
13 | #ifndef SCANPARAMSERVICE_H
14 | #define SCANPARAMSERVICE_H
15 |
16 | #ifdef __cplusplus
17 | extern "C" {
18 | #endif
19 |
20 | /*********************************************************************
21 | * INCLUDES
22 | */
23 |
24 | /*********************************************************************
25 | * CONSTANTS
26 | */
27 |
28 | // Scan Characteristic Lengths
29 | #define SCAN_INTERVAL_WINDOW_CHAR_LEN 4
30 | #define SCAN_PARAM_REFRESH_LEN 1
31 |
32 | // Scan Parameter Refresh Values
33 | #define SCAN_PARAM_REFRESH_REQ 0x00
34 |
35 | // Callback events
36 | #define SCAN_INTERVAL_WINDOW_SET 1
37 |
38 | // Get/Set parameters
39 | #define SCAN_PARAM_PARAM_INTERVAL 0
40 | #define SCAN_PARAM_PARAM_WINDOW 1
41 |
42 | /*********************************************************************
43 | * TYPEDEFS
44 | */
45 |
46 | /*********************************************************************
47 | * MACROS
48 | */
49 |
50 | /*********************************************************************
51 | * Profile Callbacks
52 | */
53 |
54 | // Scan Parameters Service callback function
55 | typedef void (*scanParamServiceCB_t)(uint8_t event);
56 |
57 | /*********************************************************************
58 | * API FUNCTIONS
59 | */
60 |
61 | /*********************************************************************
62 | * @fn ScanParam_AddService
63 | *
64 | * @brief Initializes the Service by registering
65 | * GATT attributes with the GATT server.
66 | *
67 | * @return Success or Failure
68 | */
69 | extern bStatus_t ScanParam_AddService(void);
70 |
71 | /*********************************************************************
72 | * @fn ScanParam_Register
73 | *
74 | * @brief Register a callback function with the Scan Parameters Service.
75 | *
76 | * @param pfnServiceCB - Callback function.
77 | *
78 | * @return None.
79 | */
80 | extern void ScanParam_Register(scanParamServiceCB_t pfnServiceCB);
81 |
82 | /*********************************************************************
83 | * @fn ScanParam_SetParameter
84 | *
85 | * @brief Set a Scan Parameters Service parameter.
86 | *
87 | * @param param - Profile parameter ID
88 | * @param len - length of data to right
89 | * @param value - pointer to data to write. This is dependent on
90 | * the parameter ID and WILL be cast to the appropriate
91 | * data type (example: data type of uint16_t will be cast to
92 | * uint16_t pointer).
93 | *
94 | * @return bStatus_t
95 | */
96 | extern bStatus_t ScanParam_SetParameter(uint8_t param, uint8_t len, void *value);
97 |
98 | /*********************************************************************
99 | * @fn ScanParam_GetParameter
100 | *
101 | * @brief Get a Scan Parameters Service parameter.
102 | *
103 | * @param param - Profile parameter ID
104 | * @param value - pointer to data to get. This is dependent on
105 | * the parameter ID and WILL be cast to the appropriate
106 | * data type (example: data type of uint16_t will be cast to
107 | * uint16_t pointer).
108 | *
109 | * @return bStatus_t
110 | */
111 | extern bStatus_t ScanParam_GetParameter(uint8_t param, void *value);
112 |
113 | /*********************************************************************
114 | * @fn ScanParam_RefreshNotify
115 | *
116 | * @brief Notify the peer to refresh the scan parameters.
117 | *
118 | * @param connHandle - connection handle
119 | *
120 | * @return None
121 | */
122 | extern void ScanParam_RefreshNotify(uint16_t connHandle);
123 |
124 | extern void ScanParam_HandleConnStatusCB(uint16_t connHandle, uint8_t changeType);
125 |
126 | /*********************************************************************
127 | *********************************************************************/
128 |
129 | #ifdef __cplusplus
130 | }
131 | #endif
132 |
133 | #endif /* SCANPARAMSERVICE_H */
134 |
--------------------------------------------------------------------------------
/sample/test_ch592f_ble_hid_keyboard_org/test_ch592f_ble_hid_keyboard_org.ino:
--------------------------------------------------------------------------------
1 | /********************************** (C) COPYRIGHT *******************************
2 | * File Name : main.c
3 | * Author : WCH
4 | * Version : V1.0
5 | * Date : 2020/08/06
6 | * Description : タカムタシ・フモヲモテヨッハシーネホホオヘウウシサッ
7 | *********************************************************************************
8 | * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
9 | * Attention: This software (modified or not) and binary are used for
10 | * microcontroller manufactured by Nanjing Qinheng Microelectronics.
11 | *******************************************************************************/
12 |
13 | /******************************************************************************/
14 | /* ヘキホトシー・ャ */
15 | #include "CONFIG.h"
16 | #include "HAL.h"
17 | #include "hiddev.h"
18 | #include "hidkbd.h"
19 |
20 | /*********************************************************************
21 | * GLOBAL TYPEDEFS
22 | */
23 | __attribute__((aligned(4))) uint32_t MEM_BUF[BLE_MEMHEAP_SIZE / 4];
24 |
25 | #if(defined(BLE_MAC)) && (BLE_MAC == TRUE)
26 | const uint8_t MacAddr[6] = {0x84, 0xC2, 0xE4, 0x03, 0x02, 0x02};
27 | #endif
28 |
29 | /*********************************************************************
30 | * @fn Main_Circulation
31 | *
32 | * @brief ヨュサキ
33 | *
34 | * @return none
35 | */
36 | __HIGH_CODE
37 | __attribute__((noinline))
38 | void Main_Circulation()
39 | {
40 | while(1)
41 | {
42 | TMOS_SystemProcess();
43 | }
44 | }
45 |
46 | /*********************************************************************
47 | * @fn main
48 | *
49 | * @brief ヨッハ
50 | *
51 | * @return none
52 | */
53 | void setup()
54 | {
55 | #if(defined(DCDC_ENABLE)) && (DCDC_ENABLE == TRUE)
56 | PWR_DCDCCfg(ENABLE);
57 | #endif
58 | SetSysClock(CLK_SOURCE_PLL_60MHz);
59 | #if(defined(HAL_SLEEP)) && (HAL_SLEEP == TRUE)
60 | GPIOA_ModeCfg(GPIO_Pin_All, GPIO_ModeIN_PU);
61 | GPIOB_ModeCfg(GPIO_Pin_All, GPIO_ModeIN_PU);
62 | #endif
63 | #ifdef DEBUG
64 | GPIOA_SetBits(bTXD1);
65 | GPIOA_ModeCfg(bTXD1, GPIO_ModeOut_PP_5mA);
66 | UART1_DefInit();
67 | #endif
68 | PRINT("%s\n", VER_LIB);
69 | CH59x_BLEInit();
70 | HAL_Init();
71 | GAPRole_PeripheralInit();
72 | HidDev_Init();
73 | HidEmu_Init();
74 | Main_Circulation();
75 | }
76 |
77 | void loop(){}
78 |
79 | /******************************** endfile @ main ******************************/
80 |
--------------------------------------------------------------------------------
/sample/test_ch592f_button/.gitkeep:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/sample/test_ch592f_button/test_ch592f_button.ino:
--------------------------------------------------------------------------------
1 | /**
2 | * CH592F Button test
3 | * 2024/01/06 Sat pearlpalms@gmail.com
4 | * $Id:$
5 | *
6 | * GND <-> Switch <-> GPIO
7 | */
8 |
9 | void setup(){
10 |
11 | // GPIO_ModeIN_Floating
12 | // GPIO_ModeIN_PU
13 | // GPIO_ModeIN_PD
14 | // GPIO_ModeOut_PP_5mA
15 | // GPIO_ModeOut_PP_20mA
16 |
17 | GPIOA_SetBits(GPIO_Pin_8);
18 | GPIOA_ModeCfg(GPIO_Pin_8, GPIO_ModeOut_PP_5mA);
19 |
20 | GPIOA_ModeCfg(GPIO_Pin_4, GPIO_ModeIN_PU);
21 | GPIOA_ModeCfg(GPIO_Pin_5, GPIO_ModeIN_PU);
22 | // GPIOA_ModeCfg(GPIO_Pin_8, GPIO_ModeIN_PU);
23 | GPIOA_ModeCfg(GPIO_Pin_9, GPIO_ModeIN_PU);
24 | GPIOA_ModeCfg(GPIO_Pin_10, GPIO_ModeIN_PU);
25 | GPIOA_ModeCfg(GPIO_Pin_11, GPIO_ModeIN_PU);
26 | GPIOA_ModeCfg(GPIO_Pin_12, GPIO_ModeIN_PU);
27 | GPIOA_ModeCfg(GPIO_Pin_13, GPIO_ModeIN_PU);
28 | GPIOA_ModeCfg(GPIO_Pin_14, GPIO_ModeIN_PU);
29 | GPIOA_ModeCfg(GPIO_Pin_15, GPIO_ModeIN_PU);
30 |
31 | GPIOB_ModeCfg(GPIO_Pin_4, GPIO_ModeIN_PU);
32 | GPIOB_ModeCfg(GPIO_Pin_7, GPIO_ModeIN_PU);
33 | GPIOB_ModeCfg(GPIO_Pin_10, GPIO_ModeIN_PU);
34 | GPIOB_ModeCfg(GPIO_Pin_11, GPIO_ModeIN_PU);
35 | GPIOB_ModeCfg(GPIO_Pin_12, GPIO_ModeIN_PU);
36 | GPIOB_ModeCfg(GPIO_Pin_13, GPIO_ModeIN_PU);
37 | GPIOB_ModeCfg(GPIO_Pin_14, GPIO_ModeIN_PU);
38 | GPIOB_ModeCfg(GPIO_Pin_15, GPIO_ModeIN_PU);
39 | // GPIOB_ModeCfg(GPIO_Pin_22, GPIO_ModeIN_PU);
40 | // GPIOB_ModeCfg(GPIO_Pin_23, GPIO_ModeIN_PU);
41 |
42 | // Ready Indicator
43 | for(int i = 0; i < 9; i++){
44 | // LED on
45 | GPIOA_ResetBits(GPIO_Pin_8);
46 | delay(40);
47 | // LED off
48 | GPIOA_SetBits(GPIO_Pin_8);
49 | delay(40);
50 | }
51 | }
52 |
53 | void loop(){
54 |
55 | // Input Pin A
56 | if(GPIOA_ReadPortPin(GPIO_Pin_4) == 0)
57 | GPIOA_ResetBits(GPIO_Pin_8);
58 | else if(GPIOA_ReadPortPin(GPIO_Pin_5) == 0)
59 | GPIOA_ResetBits(GPIO_Pin_8);
60 | else if(GPIOA_ReadPortPin(GPIO_Pin_9) == 0)
61 | GPIOA_ResetBits(GPIO_Pin_8);
62 | else if(GPIOA_ReadPortPin(GPIO_Pin_10) == 0)
63 | GPIOA_ResetBits(GPIO_Pin_8);
64 | else if(GPIOA_ReadPortPin(GPIO_Pin_11) == 0)
65 | GPIOA_ResetBits(GPIO_Pin_8);
66 | else if(GPIOA_ReadPortPin(GPIO_Pin_12) == 0)
67 | GPIOA_ResetBits(GPIO_Pin_8);
68 | else if(GPIOA_ReadPortPin(GPIO_Pin_13) == 0)
69 | GPIOA_ResetBits(GPIO_Pin_8);
70 | else if(GPIOA_ReadPortPin(GPIO_Pin_14) == 0)
71 | GPIOA_ResetBits(GPIO_Pin_8);
72 | else if(GPIOA_ReadPortPin(GPIO_Pin_15) == 0)
73 | GPIOA_ResetBits(GPIO_Pin_8);
74 |
75 | // Input Pin B
76 | else if(GPIOB_ReadPortPin(GPIO_Pin_4) == 0)
77 | GPIOA_ResetBits(GPIO_Pin_8);
78 | else if(GPIOB_ReadPortPin(GPIO_Pin_7) == 0)
79 | GPIOA_ResetBits(GPIO_Pin_8);
80 | else if(GPIOB_ReadPortPin(GPIO_Pin_10) == 0)
81 | GPIOA_ResetBits(GPIO_Pin_8);
82 | else if(GPIOB_ReadPortPin(GPIO_Pin_11) == 0)
83 | GPIOA_ResetBits(GPIO_Pin_8);
84 | else if(GPIOB_ReadPortPin(GPIO_Pin_12) == 0)
85 | GPIOA_ResetBits(GPIO_Pin_8);
86 | else if(GPIOB_ReadPortPin(GPIO_Pin_13) == 0)
87 | GPIOA_ResetBits(GPIO_Pin_8);
88 | else if(GPIOB_ReadPortPin(GPIO_Pin_14) == 0)
89 | GPIOA_ResetBits(GPIO_Pin_8);
90 | else if(GPIOB_ReadPortPin(GPIO_Pin_15) == 0)
91 | GPIOA_ResetBits(GPIO_Pin_8);
92 | // else if(GPIOB_ReadPortPin(GPIO_Pin_22) == 0)
93 | // GPIOA_ResetBits(GPIO_Pin_8);
94 | // else if(GPIOB_ReadPortPin(GPIO_Pin_23) == 0)
95 | // GPIOA_ResetBits(GPIO_Pin_8);
96 | else
97 | GPIOA_SetBits(GPIO_Pin_8);
98 | }
--------------------------------------------------------------------------------
/sample/test_ch592f_button2/.gitkeep:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/sample/test_ch592f_button2/IMG_0712.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PEARLPALMS/Arduino-CH592F/b9ea2b5ecd53673252ccbe5e307a02ed8d93274f/sample/test_ch592f_button2/IMG_0712.png
--------------------------------------------------------------------------------
/sample/test_ch592f_button2/test_ch592f_button2.ino:
--------------------------------------------------------------------------------
1 | /**
2 | * CH592F Button2 test
3 | * 2024/01/09 Sat pearlpalms@gmail.com
4 | * $Id:$
5 | *
6 | * B14 <-> Switch <-> B12
7 | * B11 <-> Switch <-> B7
8 | * B4 <-> Switch <-> B22
9 | */
10 |
11 | void setup(){
12 |
13 | // Internal LED
14 | GPIOA_SetBits(GPIO_Pin_8);
15 | GPIOA_ModeCfg(GPIO_Pin_8, GPIO_ModeOut_PP_5mA);
16 |
17 | // Button 1
18 | GPIOA_SetBits(GPIO_Pin_14);
19 | GPIOB_ModeCfg(GPIO_Pin_14, GPIO_ModeOut_PP_5mA);
20 | GPIOB_ModeCfg(GPIO_Pin_12, GPIO_ModeIN_PU);
21 |
22 | // Button 2
23 | GPIOA_SetBits(GPIO_Pin_11);
24 | GPIOB_ModeCfg(GPIO_Pin_11, GPIO_ModeOut_PP_5mA);
25 | GPIOB_ModeCfg(GPIO_Pin_7, GPIO_ModeIN_PU);
26 |
27 | // Button 3
28 | GPIOA_SetBits(GPIO_Pin_4);
29 | GPIOB_ModeCfg(GPIO_Pin_4, GPIO_ModeOut_PP_5mA);
30 | GPIOB_ModeCfg(GPIO_Pin_22, GPIO_ModeIN_PU);
31 |
32 | // Ready Indicator
33 | for(int i = 0; i < 9; i++){
34 | // LED on
35 | GPIOA_ResetBits(GPIO_Pin_8);
36 | delay(40);
37 | // LED off
38 | GPIOA_SetBits(GPIO_Pin_8);
39 | delay(40);
40 | }
41 | }
42 |
43 | void loop(){
44 |
45 | // Button 1
46 | if(GPIOB_ReadPortPin(GPIO_Pin_7) == 0)
47 | GPIOA_ResetBits(GPIO_Pin_8);
48 | // Button 2
49 | else if(GPIOB_ReadPortPin(GPIO_Pin_12) == 0)
50 | GPIOA_ResetBits(GPIO_Pin_8);
51 | // Button 3
52 | else if(GPIOB_ReadPortPin(GPIO_Pin_22) == 0)
53 | GPIOA_ResetBits(GPIO_Pin_8);
54 | else
55 | GPIOA_SetBits(GPIO_Pin_8);
56 | }
--------------------------------------------------------------------------------
/sample/test_ch592f_serial/.gitkeep:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/sample/test_ch592f_serial/IMG_0713.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PEARLPALMS/Arduino-CH592F/b9ea2b5ecd53673252ccbe5e307a02ed8d93274f/sample/test_ch592f_serial/IMG_0713.png
--------------------------------------------------------------------------------
/sample/test_ch592f_serial/test_ch592f_serial.ino:
--------------------------------------------------------------------------------
1 | /**
2 | * CH592F Serial test
3 | * 2023/12/31 Sun pearlpalms@gmail.com
4 | * $Id:$
5 | *
6 | * CH592F === UART
7 | * GND <-> GND
8 | * +5V <-> +5V
9 | * (TX0)B7 <-> RX
10 | * (RX0)B4 <-> TX
11 | */
12 |
13 | #include
14 |
15 | // Send buffer
16 | uint8_t TxBuff[1024];
17 | // Receive buffer
18 | uint8_t RxBuff[1024];
19 |
20 | void setup(){
21 |
22 | // System Clock
23 | SetSysClock(CLK_SOURCE_PLL_60MHz);
24 |
25 | // Internal LED
26 | GPIOA_SetBits(GPIO_Pin_8);
27 | GPIOA_ModeCfg(GPIO_Pin_8, GPIO_ModeOut_PP_5mA);
28 |
29 | // B7 PIN is TXD0
30 | GPIOB_SetBits(GPIO_Pin_7);
31 | GPIOB_ModeCfg(GPIO_Pin_7, GPIO_ModeOut_PP_5mA);
32 | // B4 PIN is RXD0
33 | GPIOB_ModeCfg(GPIO_Pin_4, GPIO_ModeIN_PU);
34 |
35 | // UART0
36 | UART0_DefInit();
37 |
38 | // Ready Indicator
39 | for(int i = 0; i < 9; i++){
40 | // LED on
41 | GPIOA_ResetBits(GPIO_Pin_8);
42 | delay(40);
43 | // LED off
44 | GPIOA_SetBits(GPIO_Pin_8);
45 | delay(40);
46 | }
47 | }
48 |
49 | void loop(){
50 |
51 | // Send TXD0
52 | sprintf((char*)TxBuff, "This is a tx and rx example\n");
53 | UART0_SendString((uint8_t*)TxBuff, length(TxBuff));
54 | GPIOA_ResetBits(GPIO_Pin_8);
55 | delay(500);
56 |
57 | // Receive RXD0 and Send TXD0
58 | uint8_t len = UART0_RecvString(RxBuff);
59 | if(len){
60 | if(RxBuff[len - 1] == '\n')
61 | RxBuff[len - 1] = '\0';
62 | sprintf((char*)TxBuff, "> Received data is [%s]\n", RxBuff);
63 | UART0_SendString((uint8_t*)TxBuff, length(TxBuff));
64 | }
65 | GPIOA_SetBits(GPIO_Pin_8);
66 | delay(1000);
67 | }
68 |
69 | /**
70 | * calculate uint8_t array length
71 | */
72 | int length(uint8_t *s){
73 | int i = 0;
74 | while(true){
75 | if(s[i] == '\0')
76 | return(i);
77 | i++;
78 | }
79 | }
--------------------------------------------------------------------------------