蓝牙hid协议源码解析

来源:互联网 发布:成都室内设计公司 知乎 编辑:程序博客网 时间:2024/05/16 08:46

1,概述

1.1 HID协议

HID协议: Hunman Interface Device Profile人机交互设备协议

使用场景:支持人机交互设备之间的控制

市场产品:蓝牙键盘,蓝牙鼠标,蓝牙游戏手柄等。

1.2 代码路径

客户端: frameworks\base\core\java\android\bluetooth


服务端: packages\apps\Bluetooth\src\com\android\bluetooth\ hid

HidDevService.java                 hid协议的服务端

开发流程和健康设备类似,但是稍微麻烦

2,接口

接口如下


3,开发步骤

在官方文档中有一个建立通信的流程:

1、调用getProfileProxy(Context,BluetoothProfile.ServiceListener, int)来获取代理对象的连接。

2、创建BluetoothHidDeviceAppSdpSettings, BluetoothHidDeviceAppQosSettings对象,创建BluetoothHidDeviceCallback回调,调用registerApp方法注册

3、将手机与设备配对,并且进行连接。

4、实现BluetoothHidDeviceCallback的7个回调方法

5、调用sendReport方法分别实现蓝牙鼠标,蓝牙键盘等。

3.1 获取客户端代理对象

一般在oncreate方法中,直接调用getProfileProxy方法,这个没什么好说的。

BluetoothAdapter.getDefaultAdapter().getProfileProxy(getApplicationContext(), mProfileServiceListener,BluetoothProfile. HID_DEVICE);
private BluetoothProfile.ServiceListener mProfileServiceListener = new BluetoothProfile.ServiceListener() {@Overridepublic void onServiceDisconnected(int profile) {if (profile == BluetoothProfile.HEALTH){     mBluetoothHealth = null;}}@SuppressLint("NewApi")@Overridepublic void onServiceConnected(int profile, BluetoothProfile proxy) {if (profile == BluetoothProfile.HEALTH) {mHidDevice = (BluetoothHidDevice) proxy;                 // 获取代理对象之后就进行注册                 ...}}};

一般经过这个步骤,客户端的BluetoothHidDevice对象已经和服务端的HidDevService对象绑定了。

3.2 注册registerApp

BluetoothHidDeviceAppSdpSettings sdp = new BluetoothHidDeviceAppSdpSettings(                            HidConsts.NAME, HidConsts.DESCRIPTION, HidConsts.PROVIDER,                            BluetoothHidDevice.SUBCLASS1_COMBO, HidConsts.DESCRIPTOR);BluetoothHidDeviceAppQosSettings inQos = new BluetoothHidDeviceAppQosSettings(                        BluetoothHidDeviceAppQosSettings.SERVICE_GUARANTEED, 200, 2, 200,                        10000 /* 10 ms */, 10000 /* 10 ms */);BluetoothHidDeviceAppQosSettings outQos = new BluetoothHidDeviceAppQosSettings(                        BluetoothHidDeviceAppQosSettings.SERVICE_GUARANTEED, 900, 9, 900,                        10000 /* 10 ms */, 10000 /* 10 ms */);boolean result = mHidDevice.registerApp(sdp, inQos, outQos, mCallback);

HidConsts类的定义如下:

public class HidConsts {    public final static String NAME = "HID Device Testapp";    public final static String DESCRIPTION = "";    public final static String PROVIDER = "Codeaurora";    /* @formatter:off */    public final static byte[] DESCRIPTOR = {        (byte) 0x05, (byte) 0x01,                    // USAGE_PAGE (Generic Desktop)        (byte) 0x09, (byte) 0x02,                    // USAGE (Mouse)        (byte) 0xa1, (byte) 0x01,                    // COLLECTION (Application)        (byte) 0x09, (byte) 0x01,                    //   USAGE (Pointer)        (byte) 0xa1, (byte) 0x00,                    //   COLLECTION (Physical)        (byte) 0x85, (byte) 0x02,                    //     REPORT_ID (2)        (byte) 0x05, (byte) 0x09,                    //     USAGE_PAGE (Button)        (byte) 0x19, (byte) 0x01,                    //     USAGE_MINIMUM (Button 1)        (byte) 0x29, (byte) 0x03,                    //     USAGE_MAXIMUM (Button 3)        (byte) 0x15, (byte) 0x00,                    //     LOGICAL_MINIMUM (0)        (byte) 0x25, (byte) 0x01,                    //     LOGICAL_MAXIMUM (1)        (byte) 0x95, (byte) 0x03,                    //     REPORT_COUNT (3)        (byte) 0x75, (byte) 0x01,                    //     REPORT_SIZE (1)        (byte) 0x81, (byte) 0x02,                    //     INPUT (Data,Var,Abs)        (byte) 0x95, (byte) 0x01,                    //     REPORT_COUNT (1)        (byte) 0x75, (byte) 0x05,                    //     REPORT_SIZE (5)        (byte) 0x81, (byte) 0x03,                    //     INPUT (Cnst,Var,Abs)        (byte) 0x05, (byte) 0x01,                    //     USAGE_PAGE (Generic Desktop)        (byte) 0x09, (byte) 0x30,                    //     USAGE (X)        (byte) 0x09, (byte) 0x31,                    //     USAGE (Y)        (byte) 0x15, (byte) 0x81,                    //     LOGICAL_MINIMUM (-127)        (byte) 0x25, (byte) 0x7f,                    //     LOGICAL_MAXIMUM (127)        (byte) 0x75, (byte) 0x08,                    //     REPORT_SIZE (8)        (byte) 0x95, (byte) 0x02,                    //     REPORT_COUNT (2)        (byte) 0x81, (byte) 0x06,                    //     INPUT (Data,Var,Rel)        (byte) 0x09, (byte) 0x38,                    //     USAGE (Wheel)        (byte) 0x15, (byte) 0x81,                    //     LOGICAL_MINIMUM (-127)        (byte) 0x25, (byte) 0x7f,                    //     LOGICAL_MAXIMUM (127)        (byte) 0x75, (byte) 0x08,                    //     REPORT_SIZE (8)        (byte) 0x95, (byte) 0x01,                    //     REPORT_COUNT (1)        (byte) 0x81, (byte) 0x06,                    //     INPUT (Data,Var,Rel)        (byte) 0xc0,                                 //   END_COLLECTION        (byte) 0xc0,                                 // END_COLLECTION        // battery strength        (byte) 0x05, (byte) 0x0c,        (byte) 0x09, (byte) 0x01,        (byte) 0xa1, (byte) 0x01,        (byte) 0x85, (byte) 0x20,                    //   REPORT_ID (32)        (byte) 0x05, (byte) 0x01,        (byte) 0x09, (byte) 0x06,        (byte) 0xa1, (byte) 0x02,        (byte) 0x05, (byte) 0x06,                    // USAGE_PAGE (Generic Device Controls)        (byte) 0x09, (byte) 0x20,                    // USAGE (Battery Strength)        (byte) 0x15, (byte) 0x00,                    // LOGICAL_MINIMUM (0)        (byte) 0x26, (byte) 0xff, (byte) 0x00,      // LOGICAL_MAXIMUM (100)        (byte) 0x75, (byte) 0x08,                    // REPORT_SIZE (8)        (byte) 0x95, (byte) 0x01,                    // REPORT_COUNT (1)        (byte) 0x81, (byte) 0x02,                    // INPUT (Data,Var,Abs)        (byte) 0xc0,        (byte) 0xc0,        (byte) 0x05, (byte) 0x01,                    // USAGE_PAGE (Generic Desktop)        (byte) 0x09, (byte) 0x06,                    // USAGE (Keyboard)        (byte) 0xa1, (byte) 0x01,                    // COLLECTION (Application)        (byte) 0x85, (byte) 0x01,                    //   REPORT_ID (1)        (byte) 0x05, (byte) 0x07,                    //   USAGE_PAGE (Keyboard)        (byte) 0x19, (byte) 0xe0,                    //   USAGE_MINIMUM (Keyboard LeftControl)        (byte) 0x29, (byte) 0xe7,                    //   USAGE_MAXIMUM (Keyboard Right GUI)        (byte) 0x15, (byte) 0x00,                    //   LOGICAL_MINIMUM (0)        (byte) 0x25, (byte) 0x01,                    //   LOGICAL_MAXIMUM (1)        (byte) 0x75, (byte) 0x01,                    //   REPORT_SIZE (1)        (byte) 0x95, (byte) 0x08,                    //   REPORT_COUNT (8)        (byte) 0x81, (byte) 0x02,                    //   INPUT (Data,Var,Abs)        (byte) 0x05, (byte) 0x0c,                    //   USAGE_PAGE (Consumer Devices)        (byte) 0x15, (byte) 0x00,                    //   LOGICAL_MINIMUM (0)        (byte) 0x25, (byte) 0x01,                    //   LOGICAL_MAXIMUM (1)        (byte) 0x95, (byte) 0x07,                    //   REPORT_COUNT (7)        (byte) 0x75, (byte) 0x01,                    //   REPORT_SIZE (1)        (byte) 0x09, (byte) 0xb6,                    //   USAGE (Scan Previous Track)        (byte) 0x09, (byte) 0xb5,                    //   USAGE (Scan Next Track)        (byte) 0x09, (byte) 0xb7,                    //   USAGE (Stop)        (byte) 0x09, (byte) 0xcd,                    //   USAGE (Play/Pause)        (byte) 0x09, (byte) 0xe2,                    //   USAGE (Mute)        (byte) 0x09, (byte) 0xe9,                    //   USAGE (Volume Up)        (byte) 0x09, (byte) 0xea,                    //   USAGE (Volume Down)        (byte) 0x81, (byte) 0x02,                    //   INPUT (Data,Var,Abs)        (byte) 0x95, (byte) 0x01,                    //   REPORT_COUNT (1)        (byte) 0x75, (byte) 0x01,                    //   REPORT_SIZE (1)        (byte) 0x81, (byte) 0x03,                    //   INPUT (Constant,Var,Abs)        (byte) 0x05, (byte) 0x07,                    //   USAGE_PAGE (Keyboard)        (byte) 0x95, (byte) 0x05,                    //   REPORT_COUNT (5)        (byte) 0x75, (byte) 0x01,                    //   REPORT_SIZE (1)        (byte) 0x85, (byte) 0x01,                    //   REPORT_ID (1)        (byte) 0x05, (byte) 0x08,                    //   USAGE_PAGE (LEDs)        (byte) 0x19, (byte) 0x01,                    //   USAGE_MINIMUM (Num Lock)        (byte) 0x29, (byte) 0x05,                    //   USAGE_MAXIMUM (Kana)        (byte) 0x91, (byte) 0x02,                    //   OUTPUT (Data,Var,Abs)        (byte) 0x95, (byte) 0x01,                    //   REPORT_COUNT (1)        (byte) 0x75, (byte) 0x03,                    //   REPORT_SIZE (3)        (byte) 0x91, (byte) 0x03,                    //   OUTPUT (Cnst,Var,Abs)        (byte) 0x95, (byte) 0x06,                    //   REPORT_COUNT (6)        (byte) 0x75, (byte) 0x08,                    //   REPORT_SIZE (8)

连接很简单,直接调用connect方法就可以了。

public void connect() {        if (mHidDevice == null) return;        mHidDevice.connect();}

3.4 BluetoothHidDeviceCallback

BluetoothHidDeviceCallback这个抽象类有7个回调方法,

private byte[] mBuffer = new byte[1];
private final BluetoothHidDeviceCallback mCallback = new BluetoothHidDeviceCallback() {        @Override  public void onAppStatusChanged(BluetoothDevice pluggedDevice,                    BluetoothHidDeviceAppConfiguration config, boolean registered) {           // 一般在registerApp和unregisterApp方法之后回调              // registered 表示是否注册上              }        @Override        public void onConnectionStateChanged(BluetoothDevice device, int state) {            // device 远程蓝牙设备  state连接状态          mBuffer = (byte) 63           mHidDevice.sendReport(32, mBuffer);  // 不知道为啥子这样写?        }          // 其他5个方法就可以不管了。        @Override        public void onIntrData(byte reportId, byte[] data) {          Log.v(TAG, "intr data: reportId=" + reportId + " data=" + Arrays.toString(data));        }        @Override        public void onSetProtocol(byte protocol) {            Log.d(TAG, "protocol set to " + protocol);        }        @Override        public void onVirtualCableUnplug() {                    }        @Override        public void onGetReport(byte type, byte id, int bufferSize) {                    }        @Override        public void onSetReport(byte type, byte id, byte[] data) {                 }    };

BluetoothHidDeviceCallback7个方法都是C/C++等通过JNI机制的回调。

4,蓝牙鼠标

4.1 蓝牙鼠标滑动

实现鼠标在整个界面前后左右上下滑动

mTouchpad = view.findViewById(R.id.touchpad);        mTouchpad.setOnTouchListener(new OnTouchListener() {            private int mPrevX;             private int mPrevY;             @Override            public boolean onTouch(View v, MotionEvent event) {                switch (event.getAction()) {                    case MotionEvent.ACTION_DOWN:                        mPrevX = (int) (event.getX() * mSpeed);                        mPrevY = (int) (event.getY() * mSpeed);                        break;                    case MotionEvent.ACTION_MOVE:                        int x = (int) (event.getX() * mSpeed);                        int y = (int) (event.getY() * mSpeed);                        mouseMove((byte) (x – mPrevX), (byte) (y - mPrevY));                         mPrevX = x;                        mPrevY = y;                        break;                }                return true;            }        });


private int mSpeed = 3;

mSpeed的值控制鼠标移动的速度。

private byte[] mBuffer = new byte[4];byte id = 2;

public synchronized void move(byte dx, byte dy) {            // leave buttons state unchanged            mBuffer[1] = dx;            mBuffer[2] = dy;                        mHidDevice.sendReport(id, mBuffer);        }

4.2 蓝牙鼠标点击

将鼠标滑动到目标后,点击按钮可以选中目标。

button.setOnTouchListener(new OnTouchListener() {                    @Override                    public boolean onTouch(View v, MotionEvent event) {                        int which = 0;                        switch (event.getAction()) {                            case MotionEvent.ACTION_DOWN:                               mouseButtonDown(which);                                break;                            case MotionEvent.ACTION_UP:                                mouseButtonUp(which);                                break;                        }                        return false;                    }                });

Which的值有三种,分别是0,1,2 之间好像没什么差别。

public synchronized void buttonDown(int which) {            mBuffer[0] |= (1 << which);            mBuffer[1] = 0;            mBuffer[2] = 0;            mHidDevice.sendReport(id, mBuffer);        }  public synchronized void buttonUp(int which) {            mBuffer[0] &= ~(1 << which);            mBuffer[1] = 0;            mBuffer[2] = 0;              mHidDevice.sendReport(id, mBuffer);        }

4.3 蓝牙鼠标翻页

比如在手机中,有时候界面不止一页,这样就需要翻页来显示了。

private int mScrollSpeed = 3;   // 控制翻页的速度mScrollZone.setOnTouchListener(new OnTouchListener() {            private int mPrevY;            @Override            public boolean onTouch(View v, MotionEvent event) {                switch (event.getAction()) {                    case MotionEvent.ACTION_DOWN:                        mPrevY = (int) (event.getY() * mScrollSpeed);                        break;                    case MotionEvent.ACTION_MOVE:                        int y = (int) (event.getY() * mScrollSpeed);                        mouseScroll((byte) (mPrevY - y));                        mPrevY = y;                        break;                }                return true;            }        });public synchronized void scroll(byte delta) {            mBuffer[3] = delta;            mHidDevice.sendReport(id, mBuffer);            mBuffer[3] = 0x00;        }

5,蓝牙键盘

市面上的键盘类型较多,实现了3种蓝牙键盘,

                                           标准键盘

lable以及对应keyCode如下:

<Keyboard>    <Layout>        <Key keyLabel="Esc" keyCode="0x29"/>        <Key keyLabel="F1" keyCode="0x3A"/>        <Key keyLabel="F2" keyCode="0x3B"/>        <Key keyLabel="F3" keyCode="0x3C"/>        <Key keyLabel="F4" keyCode="0x3D"/>        <Key keyLabel="F5" keyCode="0x3E"/>        <Key keyLabel="F6" keyCode="0x3F"/>        <Key keyLabel="F7" keyCode="0x40"/>        <Key keyLabel="F8" keyCode="0x41"/>        <Key keyLabel="F9" keyCode="0x42"/>        <Key keyLabel="F10" keyCode="0x43"/>        <Key keyLabel="F11" keyCode="0x44"/>        <Key keyLabel="F12" keyCode="0x45"/>        <Key keyLabel="Del" keyCode="0x4C"/>    </Layout>    <Layout>        <Key keyLabel="'" shiftLabel="~" keyCode="0x35"/>        <Key keyLabel="1" shiftLabel="!" keyCode="0x1E"/>        <Key keyLabel="2" shiftLabel="\@" keyCode="0x1F"/>        <Key keyLabel="3" shiftLabel="\#" keyCode="0x20"/>        <Key keyLabel="4" shiftLabel="$" keyCode="0x21"/>        <Key keyLabel="5" shiftLabel="%" keyCode="0x22"/>        <Key keyLabel="6" shiftLabel="^" keyCode="0x23"/>        <Key keyLabel="7" shiftLabel="&" keyCode="0x24"/>        <Key keyLabel="8" shiftLabel="*" keyCode="0x25"/>        <Key keyLabel="9" shiftLabel="(" keyCode="0x26"/>        <Key keyLabel="0" shiftLabel=")" keyCode="0x27"/>        <Key keyLabel="-" shiftLabel="_" keyCode="0x2D"/>        <Key keyLabel="=" shiftLabel="+" keyCode="0x2E"/>        <Key keyLabel="Backspace ←" keyCode="0x2A" weight="1.5"/>    </Layout>    <Layout>        <Key keyLabel="Tab ↹" keyCode="0x2B" weight="1.5"/>        <Key keyLabel="Q" keyCode="0x14"/>        <Key keyLabel="W" keyCode="0x1A"/>        <Key keyLabel="E" keyCode="0x08"/>        <Key keyLabel="R" keyCode="0x15"/>        <Key keyLabel="T" keyCode="0x17"/>        <Key keyLabel="Y" keyCode="0x1C"/>        <Key keyLabel="U" keyCode="0x18"/>        <Key keyLabel="I" keyCode="0x0C"/>        <Key keyLabel="O" keyCode="0x12"/>        <Key keyLabel="P" keyCode="0x13"/>        <Key keyLabel="[" keyCode="0x2F" shiftLabel="{"/>        <Key keyLabel="]" keyCode="0x30" shiftLabel="}"/>        <Key keyLabel="\\" keyCode="0x31" shiftLabel="|"/>    </Layout>    <Layout>        <Key keyLabel="Caps Lock" keyCode="0x39" weight="1.5"/>        <Key keyLabel="A" keyCode="0x04"/>        <Key keyLabel="S" keyCode="0x16"/>        <Key keyLabel="D" keyCode="0x07"/>        <Key keyLabel="F" keyCode="0x09"/>        <Key keyLabel="G" keyCode="0x0A"/>        <Key keyLabel="H" keyCode="0x0B"/>        <Key keyLabel="J" keyCode="0x0D"/>        <Key keyLabel="K" keyCode="0x0E"/>        <Key keyLabel="L" keyCode="0x0F"/>        <Key keyLabel=";" keyCode="0x33" shiftLabel=":"/>        <Key keyLabel="'" keyCode="0x34" shiftLabel="""/>        <Key keyLabel="Enter ↵" keyCode="0x28" weight="3.0"/>    </Layout>    <Layout>        <Key keyLabel="Shift ⇧" keyCode="0xE1" keyFunc="Shift" weight="1.5"/>        <Key keyLabel="Z" keyCode="0x1D"/>        <Key keyLabel="X" keyCode="0x1B"/>        <Key keyLabel="C" keyCode="0x06"/>        <Key keyLabel="V" keyCode="0x19"/>        <Key keyLabel="B" keyCode="0x05"/>        <Key keyLabel="N" keyCode="0x11"/>        <Key keyLabel="M" keyCode="0x10"/>        <Key keyLabel="," keyCode="0x36" shiftLabel="<"/>        <Key keyLabel="." keyCode="0x37" shiftLabel=">"/>        <Key keyLabel="/" keyCode="0x38" shiftLabel="\?"/>        <Key keyLabel="Shift ⇧" keyCode="0xE5" keyFunc="Shift" weight="1.5"/>    </Layout>    <Layout>        <Key keyLabel="Ctrl" keyCode="0xE0" weight="1.5"/>        <Key keyLabel="Win" keyCode="0xE3"/>        <Key keyLabel="Alt" keyCode="0xE2"/>        <Key keyLabel=" " keyCode="0x2C" weight="10.0"/>        <Key keyLabel="Alt Gr" keyCode="0xE6"/>        <Key keyLabel="Win" keyCode="0xE7"/>        <Key keyLabel="Menu" keyCode="0x76"/>        <Key keyLabel="Ctrl" keyCode="0xE4" weight="1.5"/>    </Layout></Keyboard>

                                    左边是导航键盘  右边是数字键盘

导航键盘的lable以及对应keyCode如下:

<Keyboard>    <Layout>        <Key keyLabel="Vol Down ⇩" keyCode="0x86"/>        <Key keyLabel="Mute" keyCode="0x84"/>        <Key keyLabel="Vol Up ⇧" keyCode="0x85"/>    </Layout>    <Layout>        <Key keyLabel="Print Screen" keyCode="0x46"/>        <Key keyLabel="Scroll Lock" keyCode="0x47"/>        <Key keyLabel="Pause" keyCode="0x48"/>    </Layout>    <Layout>        <Key keyLabel="Insert" keyCode="0x49"/>        <Key keyLabel="Home" keyCode="0x4A"/>        <Key keyLabel="Page Up" keyCode="0x4B"/>    </Layout>    <Layout>        <Key keyLabel="Delete" keyCode="0x4C"/>        <Key keyLabel="End" keyCode="0x4D"/>        <Key keyLabel="Page Down" keyCode="0x4E"/>    </Layout>    <Layout>        <Key visible="false"/>        <Key keyLabel="↑" keyCode="0x52"/>        <Key visible="false"/>    </Layout>    <Layout>        <Key keyLabel="←" keyCode="0x50"/>        <Key keyLabel="↓" keyCode="0x51"/>        <Key keyLabel="→" keyCode="0x4F"/>    </Layout></Keyboard>

数字键盘的lable以及对应keyCode如下:

<Keyboard>    <Layout>        <Key keyLabel="Prev\n⇦" keyCode="0x80"/>        <Key keyLabel="Next\n⇨" keyCode="0x81"/>        <Key keyLabel="Stop" keyCode="0x82"/>        <Key keyLabel="Play\nPause" keyCode="0x83"/>        <Key visible="false"/>    </Layout>    <Layout>        <Key keyLabel="Num\nLock" keyCode="0x53"/>        <Key keyLabel="/" keyCode="0x54"/>        <Key keyLabel="*" keyCode="0x55"/>        <Key keyLabel="-" keyCode="0x56"/>    </Layout>    <Layout>        <Key keyLabel="7\nHome" keyCode="0x5F"/>        <Key keyLabel="8 ↑" keyCode="0x60"/>        <Key keyLabel="9\nPgUp" keyCode="0x61"/>        <Key keyLabel="+" keyCode="0x57"/>    </Layout>    <Layout>        <Key keyLabel="4\n←" keyCode="0x5C"/>        <Key keyLabel="5" keyCode="0x5D"/>        <Key keyLabel="6\n→" keyCode="0x5E"/>        <Key visible="false"/>    </Layout>    <Layout>        <Key keyLabel="1\nEnd" keyCode="0x59"/>        <Key keyLabel="2 ↓" keyCode="0x5A"/>        <Key keyLabel="3\nPgDn" keyCode="0x5B"/>        <Key visible="false"/>    </Layout>    <Layout>        <Key keyLabel="0\nIns" keyCode="0x62" weight="2.0"/>        <Key keyLabel=".\nDel" keyCode="0x63"/>        <Key keyLabel="Enter" keyCode="0x58"/>    </Layout></Keyboard>

按键事件都是一样的,主要就是keyCode不同,

@Override            public void onKeyUp(byte keyCode) {                keyboardKeyUp(keyCode);            }            @Override            public void onKeyDown(byte keyCode) {                keyboardKeyDown(keyCode);            }private final static byte MODIFIER_BASE = (byte) 0xe0;        private final static byte MODIFIER_COUNT = 8; /* left ctrl -> right gui */        private byte[] mBuffer = new byte[8];        byte id = 1;public synchronized void keyDown(byte key) {            if (key >= MODIFIER_BASE && key <= MODIFIER_BASE + MODIFIER_COUNT) {                mBuffer[0] |= (1 << (key - MODIFIER_BASE));            } else if ((key & 0x80) != 0) {                mBuffer[1] |= (1 << (key & 0x07));            } else {                for (int i = 2; i < 8; i++) {                    if (mBuffer[i] == 0x00) {                        mBuffer[i] = key;                        break;                    }                }            }            mHidDevice.sendReport(id, mBuffer);        }        public synchronized void keyUp(byte key) {            if (key >= MODIFIER_BASE && key <= MODIFIER_BASE + MODIFIER_COUNT) {                mBuffer[0] &= ~(1 << (key - MODIFIER_BASE));            } else if ((key & 0x80) != 0) {                mBuffer[1] &= ~(1 << (key & 0x07));            } else {                for (int i = 2; i < 8; i++) {                    if (mBuffer[i] == key) {                        mBuffer[i] = 0x00;                        break;                    }                }            }            mHidDevice.sendReport(id, mBuffer);        }

这样就可以了,很简单吧。

6,源码解析

客户端的BluetoothHidDevice和服务端的HidDevService都比较简单,很直接,完全没有拐弯抹角的地方, sendReport方法从客户端到服务端的过程如下,

回调的7个方法流程如下,以onAppStatusChanged回调为例,


7,小节

问题:1,回调的几个方法以及2个类还未弄清楚其作用。

2,客户端的BluetoothInputDevice以及客户端的HidService和HID协议的文件在一个文件夹下,那么这2个类的作用是什么呢?如何使用。

2 0
原创粉丝点击