该文件sdk的hid_user.c的最下面有这样的描述,告诉开发者应该怎么打开自定义的蓝牙hid报告描述符
c
// 用户修改成自定义的描述符说明
// 1、在void bredr_handle_register();中调用user_hid_descriptor_init;
// 2、user_hid_sdp_init换成自己的表
// 3、文件上方HID_CHANGE_DESCRIPTOR定义为1
// 4、在bt_profile_config.c文件中extern sdp_make_hid_service_data数组,
// 把sdp_hid_service_data替换为sdp_make_hid_service_data.
// 5、把const u8 hid_conn_depend_on_dev_company的值置0;
当你把上面步骤弄完,下面我解析一下这个.c文件的应该如何调用api连接手机测试.
c
const u8 use_hid_descriptor[] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop Controls)
0x09, 0x02, // USAGE (Mouse)
0xA1, 0x01, // COLLECTION (Application)
0x85, 0x01, // REPORT_ID (1)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x03, // USAGE_MAXIMUM (Button 3)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x03, // REPORT_COUNT (3)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x75, 0x05, // REPORT_SIZE (5)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x05, 0x01, // USAGE_PAGE (Generic Desktop Controls)
0x09, 0x01, // USAGE (Pointer)
0xA1, 0x00, // COLLECTION (Physical)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x16, 0x00, 0xD8, // LOGICAL_MINIMUM (-6000)
0x26, 0x00, 0x28, // LOGICAL_MAXIMUM (6000)
0x75, 0x10, // REPORT_SIZE (16)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x06, // INPUT (Data,Var,Rel)
0xC0, // END_COLLECTION
0xC0, // END_COLLECTION
0x05, 0x0C, // USAGE_PAGE (Consumer Devices)
0x09, 0x01, // USAGE (Consumer Control)
0xA1, 0x01, // COLLECTION (Application)
0x85, 0x02, // REPORT_ID (2)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x09, 0x34, // USAGE (Stop) 0000 0001 (0x01)
0x09, 0x40, // USAGE (Menu) 0000 0010 (0x02)
0x0A, 0x23, 0x02, // USAGE (Forward) 0000 0100 (0x04)
0x0A, 0x24, 0x02, // USAGE (Backward) 0000 1000 (0x08)
0x09, 0xE9, // USAGE (Volume Up) 0001 0000 (0x10)
0x09, 0xEA, // USAGE (Volume Down) 0010 0000 (0x20)
0x09, 0xB0, // USAGE (Play) 0100 0000 (0x40)
0x09, 0xB1, // USAGE (Pause) 1000 0000 (0x80)
0x09, 0xB3, // USAGE (Fast Forward) 0000 0001 0000 0000 (0x0100)
0x09, 0xB4, // USAGE (Rewind) 0000 0010 0000 0000 (0x0200)
0x09, 0xB5, // USAGE (Scan Next Track) 0000 0100 0000 0000 (0x0400)
0x09, 0xB6, // USAGE (Scan Previous Track) 0000 1000 0000 0000 (0x0800)
0x09, 0xB7, // USAGE (Stop) 0001 0000 0000 0000 (0x010000)
0x09, 0xCD, // USAGE (Play/Pause) 0010 0000 0000 0000 (0x020000)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x0E, // REPORT_COUNT (14) //只用到16个bit的14个bit
0x81, 0x22, // INPUT (Data,Var,Abs,No Wrap,Linear,No Preferred State,No Null Position)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x02, // REPORT_COUNT (2) //要补齐多余2个没用的bit
0x81, 0x02, // INPUT (Data,Var,Abs)
0xC0 // END_COLLECTION
};
上面的是他的报告描述符,我给他增加了注释.如果你不懂hid协议,建议去看看这篇文章usb hid报告描述符,
那么我们根据报告描述符创建c语言的数据结构
c
struct user_hid_consumer_cmd
{
// Bluetooth HID Protocol Message Header Octet
u8 HIDP_Hdr;
// Bluetooth HID Boot Reports
u8 report_id;
u8 button;
s16 x;
s16 y;
} _GNU_PACKED_;
static struct user_hid_consumer_cmd u_consumer = {
.HIDP_Hdr = 0xA1,
.report_id = 0x01,
.button = 1, // 1:mouse left 2:mid 3:mouse right
.x = 1, // 应该是相对坐标,因为值不变,下一次的坐标点会变化
.y = -50,
};
前3个是原本就有的,x和y是我根据报告描述符增加的,
最后你在合适的地方调用下面这个2个函数
c
put_buf((u8 *)&u_consumer, sizeof(u_consumer));
user_data_write_sub((u8 *)&u_consumer, sizeof(u_consumer));
你增加一个2s的定时器,当手机连接上单片机后,手机就会有一个模拟鼠标的值一点一点往下滑动.
//
当你想根据报告描述符控制手机的音量,返回,播放等以下等功能时
c
// USAGE (Stop)
// USAGE (Menu)
// USAGE (Forward)
// USAGE (Backward)
// USAGE (Volume Up)
// USAGE (Volume Down)
// USAGE (Play)
// USAGE (Pause)
// USAGE (Fast Forward)
// USAGE (Rewind)
// USAGE (Scan Next Track)
// USAGE (Scan Previous Track)
// USAGE (Stop)
可以根据厂商原本的测试案例
u_consumer.button=的值就是我最上面注释后面写的16进制
就能通过杰理这款芯片控制手机的各种按键操作
c
struct user_hid_consumer_cmd {
//Bluetooth HID Protocol Message Header Octet
u8 HIDP_Hdr;
//Bluetooth HID Boot Reports
u8 report_id;
u8 button;
} _GNU_PACKED_;
static struct user_hid_consumer_cmd u_consumer = {
.HIDP_Hdr = 0xA1,
.report_id = 0x02, //注意这里的赋值跟上面鼠标滑动的赋值不一样
.button = 0,
};
void hid_consumer_send_test(u8 menu)
{
if (menu == 1)
{
// u_consumer.button = CONSUMER_MENU;
}
if (menu == 2)
{
// u_consumer.button = CONSUMER_MENU_ESCAPE;
}
if (menu == 3)
{
// u_consumer.button = CONSUMER_AC_HOME;
}
if (menu == 4)
{
// u_consumer.button = 0x40;
}
put_buf((u8 *)&u_consumer, sizeof(u_consumer));
user_data_write_sub((u8 *)&u_consumer, sizeof(u_consumer));
u_consumer.button = 0x00;
user_data_write_sub((u8 *)&u_consumer, sizeof(u_consumer));
}
//最后在合适的地方调用hid_consumer_send_test(u8 menu)这个函数,
//menu的值你可以根据报告描述符后面的16进制的注释自己追加进去
有不懂再留言提问