├── 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 | } --------------------------------------------------------------------------------