Library to use Arduino USB host shield on mbed
ArduinoのUSB Host Shield 2.0をmbedで使えるようにしたライブラリです。
大体のコードがArduinoからそのまま移植可能です。
Arduino UNOやMega用のホストシールド以外にもミニサイズのホストシールドでも使用可能です
シールドについて
3.3VのI/O用にシールドの改造が必要になりますがネット上に記事がたくさんあるのでそちらを参考にしてください
接続例
使い方
Arduinoのコードと違うのはUSBのインスタンスの宣言部分のみです。
ピンを自分で指定できるようにしたので使いやすくなりました。
仕様
- Arduinoのmillis関数、micros関数の移植のために内部でTimerクラスを使用しています。
main.cpp
#include "mbed.h" #include <PS3BT.h> #include <usbhub.h> Serial pc(USBTX, USBRX, 115200); //Nucleo f303k8用 USB Usb(A6, A5, A4, A3, A2); // mosi, miso, sclk, ssel, intr BTD Btd(&Usb); PS3BT PS3(&Btd); int main() { bool printAngle = false; if (Usb.Init() == -1) { pc.printf("\r\nOSC did not start"); while (1); // Halt } pc.printf("\r\nPS3 USB Library Started"); while (1) { Usb.Task(); if (PS3.PS3Connected || PS3.PS3NavigationConnected) { if (PS3.getAnalogHat(LeftHatX) > 137 || PS3.getAnalogHat(LeftHatX) < 117 || PS3.getAnalogHat(LeftHatY) > 137 || PS3.getAnalogHat(LeftHatY) < 117 || PS3.getAnalogHat(RightHatX) > 137 || PS3.getAnalogHat(RightHatX) < 117 || PS3.getAnalogHat(RightHatY) > 137 || PS3.getAnalogHat(RightHatY) < 117) { pc.printf("\r\nLeftHatX: %d", PS3.getAnalogHat(LeftHatX)); pc.printf("\tLeftHatY: %d", PS3.getAnalogHat(LeftHatY)); if (PS3.PS3Connected) { // The Navigation controller only have one joystick pc.printf("\tRightHatX: %d", PS3.getAnalogHat(RightHatX)); pc.printf("\tRightHatY: %d", PS3.getAnalogHat(RightHatY)); } } // Analog button values can be read from almost all buttons if (PS3.getAnalogButton(L2) || PS3.getAnalogButton(R2)) { pc.printf("\r\nL2: %d", PS3.getAnalogButton(L2)); if (!PS3.PS3NavigationConnected) { pc.printf("\tR2: %d", PS3.getAnalogButton(R2)); } } if (PS3.getButtonClick(PS)) { PS3.disconnect(); pc.printf("\r\nPS"); } if (PS3.getButtonClick(TRIANGLE)) pc.printf("\r\nTriangle"); if (PS3.getButtonClick(CIRCLE)) pc.printf("\r\nCircle"); if (PS3.getButtonClick(CROSS)) pc.printf("\r\nCross"); if (PS3.getButtonClick(SQUARE)) pc.printf("\r\nSquare"); if (PS3.getButtonClick(UP)) { pc.printf("\r\nUp"); PS3.setLedOff(); PS3.setLedOn(CONTROLLER_LED4); } if (PS3.getButtonClick(RIGHT)) { pc.printf("\r\nRight"); PS3.setLedOff(); PS3.setLedOn(CONTROLLER_LED1); } if (PS3.getButtonClick(DOWN)) { pc.printf("\r\nDown"); PS3.setLedOff(); PS3.setLedOn(CONTROLLER_LED2); } if (PS3.getButtonClick(LEFT)) { pc.printf("\r\nLeft"); PS3.setLedOff(); PS3.setLedOn(CONTROLLER_LED3); } if (PS3.getButtonClick(L1)) pc.printf("\r\nL1"); if (PS3.getButtonClick(L3)) pc.printf("\r\nL3"); if (PS3.getButtonClick(R1)) pc.printf("\r\nR1"); if (PS3.getButtonClick(R3)) pc.printf("\r\nR3"); if (PS3.getButtonClick(SELECT)) { pc.printf("\r\nSelect - "); PS3.printStatusString(); } if (PS3.getButtonClick(START)) { pc.printf("\r\nStart"); printAngle = !printAngle; } if (printAngle) { pc.printf("\r\nPitch: %.3lf", PS3.getAngle(Pitch)); pc.printf("\tRoll: %.3lf", PS3.getAngle(Roll)); } } else { pc.printf("not connect\n"); } } }
USB_Host/BTHID.cpp@1:da31140f2a1c, 2020-05-02 (annotated)
- Committer:
- robo_ichinoseki_a
- Date:
- Sat May 02 05:56:48 2020 +0000
- Revision:
- 1:da31140f2a1c
- Parent:
- 0:b1ce54272580
update
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
kotakku | 0:b1ce54272580 | 1 | /* Copyright (C) 2013 Kristian Lauszus, TKJ Electronics. All rights reserved. |
kotakku | 0:b1ce54272580 | 2 | |
kotakku | 0:b1ce54272580 | 3 | This software may be distributed and modified under the terms of the GNU |
kotakku | 0:b1ce54272580 | 4 | General Public License version 2 (GPL2) as published by the Free Software |
kotakku | 0:b1ce54272580 | 5 | Foundation and appearing in the file GPL2.TXT included in the packaging of |
kotakku | 0:b1ce54272580 | 6 | this file. Please note that GPL2 Section 2[b] requires that all works based |
kotakku | 0:b1ce54272580 | 7 | on this software must also be made publicly available under the terms of |
kotakku | 0:b1ce54272580 | 8 | the GPL2 ("Copyleft"). |
kotakku | 0:b1ce54272580 | 9 | |
kotakku | 0:b1ce54272580 | 10 | Contact information |
kotakku | 0:b1ce54272580 | 11 | ------------------- |
kotakku | 0:b1ce54272580 | 12 | |
kotakku | 0:b1ce54272580 | 13 | Kristian Lauszus, TKJ Electronics |
kotakku | 0:b1ce54272580 | 14 | Web : http://www.tkjelectronics.com |
kotakku | 0:b1ce54272580 | 15 | e-mail : kristianl@tkjelectronics.com |
kotakku | 0:b1ce54272580 | 16 | */ |
kotakku | 0:b1ce54272580 | 17 | |
kotakku | 0:b1ce54272580 | 18 | #include "BTHID.h" |
kotakku | 0:b1ce54272580 | 19 | // To enable serial debugging see "settings.h" |
kotakku | 0:b1ce54272580 | 20 | //#define EXTRADEBUG // Uncomment to get even more debugging data |
kotakku | 0:b1ce54272580 | 21 | //#define PRINTREPORT // Uncomment to print the report send by the HID device |
kotakku | 0:b1ce54272580 | 22 | |
kotakku | 0:b1ce54272580 | 23 | BTHID::BTHID(BTD *p, bool pair, const char *pin) : |
kotakku | 0:b1ce54272580 | 24 | BluetoothService(p), // Pointer to USB class instance - mandatory |
kotakku | 0:b1ce54272580 | 25 | protocolMode(USB_HID_BOOT_PROTOCOL) { |
kotakku | 0:b1ce54272580 | 26 | for(uint8_t i = 0; i < NUM_PARSERS; i++) |
kotakku | 0:b1ce54272580 | 27 | pRptParser[i] = NULL; |
kotakku | 0:b1ce54272580 | 28 | |
kotakku | 0:b1ce54272580 | 29 | pBtd->pairWithHIDDevice = pair; |
kotakku | 0:b1ce54272580 | 30 | pBtd->btdPin = pin; |
kotakku | 0:b1ce54272580 | 31 | |
kotakku | 0:b1ce54272580 | 32 | /* Set device cid for the control and intterrupt channelse - LSB */ |
kotakku | 0:b1ce54272580 | 33 | control_dcid[0] = 0x70; // 0x0070 |
kotakku | 0:b1ce54272580 | 34 | control_dcid[1] = 0x00; |
kotakku | 0:b1ce54272580 | 35 | interrupt_dcid[0] = 0x71; // 0x0071 |
kotakku | 0:b1ce54272580 | 36 | interrupt_dcid[1] = 0x00; |
kotakku | 0:b1ce54272580 | 37 | |
kotakku | 0:b1ce54272580 | 38 | Reset(); |
kotakku | 0:b1ce54272580 | 39 | } |
kotakku | 0:b1ce54272580 | 40 | |
kotakku | 0:b1ce54272580 | 41 | void BTHID::Reset() { |
kotakku | 0:b1ce54272580 | 42 | connected = false; |
kotakku | 0:b1ce54272580 | 43 | activeConnection = false; |
kotakku | 0:b1ce54272580 | 44 | l2cap_event_flag = 0; // Reset flags |
kotakku | 0:b1ce54272580 | 45 | l2cap_state = L2CAP_WAIT; |
kotakku | 0:b1ce54272580 | 46 | ResetBTHID(); |
kotakku | 0:b1ce54272580 | 47 | } |
kotakku | 0:b1ce54272580 | 48 | |
kotakku | 0:b1ce54272580 | 49 | void BTHID::disconnect() { // Use this void to disconnect the device |
kotakku | 0:b1ce54272580 | 50 | // First the HID interrupt channel has to be disconnected, then the HID control channel and finally the HCI connection |
kotakku | 0:b1ce54272580 | 51 | pBtd->l2cap_disconnection_request(hci_handle, ++identifier, interrupt_scid, interrupt_dcid); |
kotakku | 0:b1ce54272580 | 52 | Reset(); |
kotakku | 0:b1ce54272580 | 53 | l2cap_state = L2CAP_INTERRUPT_DISCONNECT; |
kotakku | 0:b1ce54272580 | 54 | } |
kotakku | 0:b1ce54272580 | 55 | |
kotakku | 0:b1ce54272580 | 56 | void BTHID::ACLData(uint8_t* l2capinbuf) { |
kotakku | 0:b1ce54272580 | 57 | if(!pBtd->l2capConnectionClaimed && pBtd->incomingHIDDevice && !connected && !activeConnection) { |
kotakku | 0:b1ce54272580 | 58 | if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { |
kotakku | 0:b1ce54272580 | 59 | if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) { |
kotakku | 0:b1ce54272580 | 60 | pBtd->incomingHIDDevice = false; |
kotakku | 0:b1ce54272580 | 61 | pBtd->l2capConnectionClaimed = true; // Claim that the incoming connection belongs to this service |
kotakku | 0:b1ce54272580 | 62 | activeConnection = true; |
kotakku | 0:b1ce54272580 | 63 | hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection |
kotakku | 0:b1ce54272580 | 64 | l2cap_state = L2CAP_WAIT; |
kotakku | 0:b1ce54272580 | 65 | } |
kotakku | 0:b1ce54272580 | 66 | } |
kotakku | 0:b1ce54272580 | 67 | } |
kotakku | 0:b1ce54272580 | 68 | |
kotakku | 0:b1ce54272580 | 69 | if(checkHciHandle(l2capinbuf, hci_handle)) { // acl_handle_ok |
kotakku | 0:b1ce54272580 | 70 | if((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001U) { // l2cap_control - Channel ID for ACL-U |
kotakku | 0:b1ce54272580 | 71 | if(l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) { |
kotakku | 0:b1ce54272580 | 72 | #ifdef DEBUG_USB_HOST |
kotakku | 0:b1ce54272580 | 73 | Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80); |
kotakku | 0:b1ce54272580 | 74 | D_PrintHex<uint8_t > (l2capinbuf[13], 0x80); |
kotakku | 0:b1ce54272580 | 75 | Notify(PSTR(" "), 0x80); |
kotakku | 0:b1ce54272580 | 76 | D_PrintHex<uint8_t > (l2capinbuf[12], 0x80); |
kotakku | 0:b1ce54272580 | 77 | Notify(PSTR(" "), 0x80); |
kotakku | 0:b1ce54272580 | 78 | D_PrintHex<uint8_t > (l2capinbuf[17], 0x80); |
kotakku | 0:b1ce54272580 | 79 | Notify(PSTR(" "), 0x80); |
kotakku | 0:b1ce54272580 | 80 | D_PrintHex<uint8_t > (l2capinbuf[16], 0x80); |
kotakku | 0:b1ce54272580 | 81 | Notify(PSTR(" "), 0x80); |
kotakku | 0:b1ce54272580 | 82 | D_PrintHex<uint8_t > (l2capinbuf[15], 0x80); |
kotakku | 0:b1ce54272580 | 83 | Notify(PSTR(" "), 0x80); |
kotakku | 0:b1ce54272580 | 84 | D_PrintHex<uint8_t > (l2capinbuf[14], 0x80); |
kotakku | 0:b1ce54272580 | 85 | #endif |
kotakku | 0:b1ce54272580 | 86 | } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_RESPONSE) { |
kotakku | 0:b1ce54272580 | 87 | if(((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) && ((l2capinbuf[18] | (l2capinbuf[19] << 8)) == SUCCESSFUL)) { // Success |
kotakku | 0:b1ce54272580 | 88 | if(l2capinbuf[14] == control_dcid[0] && l2capinbuf[15] == control_dcid[1]) { |
kotakku | 0:b1ce54272580 | 89 | //Notify(PSTR("\r\nHID Control Connection Complete"), 0x80); |
kotakku | 0:b1ce54272580 | 90 | identifier = l2capinbuf[9]; |
kotakku | 0:b1ce54272580 | 91 | control_scid[0] = l2capinbuf[12]; |
kotakku | 0:b1ce54272580 | 92 | control_scid[1] = l2capinbuf[13]; |
kotakku | 0:b1ce54272580 | 93 | l2cap_set_flag(L2CAP_FLAG_CONTROL_CONNECTED); |
kotakku | 0:b1ce54272580 | 94 | } else if(l2capinbuf[14] == interrupt_dcid[0] && l2capinbuf[15] == interrupt_dcid[1]) { |
kotakku | 0:b1ce54272580 | 95 | //Notify(PSTR("\r\nHID Interrupt Connection Complete"), 0x80); |
kotakku | 0:b1ce54272580 | 96 | identifier = l2capinbuf[9]; |
kotakku | 0:b1ce54272580 | 97 | interrupt_scid[0] = l2capinbuf[12]; |
kotakku | 0:b1ce54272580 | 98 | interrupt_scid[1] = l2capinbuf[13]; |
kotakku | 0:b1ce54272580 | 99 | l2cap_set_flag(L2CAP_FLAG_INTERRUPT_CONNECTED); |
kotakku | 0:b1ce54272580 | 100 | } |
kotakku | 0:b1ce54272580 | 101 | } |
kotakku | 0:b1ce54272580 | 102 | } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { |
kotakku | 0:b1ce54272580 | 103 | #ifdef EXTRADEBUG |
kotakku | 0:b1ce54272580 | 104 | Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80); |
kotakku | 0:b1ce54272580 | 105 | D_PrintHex<uint8_t > (l2capinbuf[13], 0x80); |
kotakku | 0:b1ce54272580 | 106 | Notify(PSTR(" "), 0x80); |
kotakku | 0:b1ce54272580 | 107 | D_PrintHex<uint8_t > (l2capinbuf[12], 0x80); |
kotakku | 0:b1ce54272580 | 108 | Notify(PSTR(" SCID: "), 0x80); |
kotakku | 0:b1ce54272580 | 109 | D_PrintHex<uint8_t > (l2capinbuf[15], 0x80); |
kotakku | 0:b1ce54272580 | 110 | Notify(PSTR(" "), 0x80); |
kotakku | 0:b1ce54272580 | 111 | D_PrintHex<uint8_t > (l2capinbuf[14], 0x80); |
kotakku | 0:b1ce54272580 | 112 | Notify(PSTR(" Identifier: "), 0x80); |
kotakku | 0:b1ce54272580 | 113 | D_PrintHex<uint8_t > (l2capinbuf[9], 0x80); |
kotakku | 0:b1ce54272580 | 114 | #endif |
kotakku | 0:b1ce54272580 | 115 | if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) { |
kotakku | 0:b1ce54272580 | 116 | identifier = l2capinbuf[9]; |
kotakku | 0:b1ce54272580 | 117 | control_scid[0] = l2capinbuf[14]; |
kotakku | 0:b1ce54272580 | 118 | control_scid[1] = l2capinbuf[15]; |
kotakku | 0:b1ce54272580 | 119 | l2cap_set_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST); |
kotakku | 0:b1ce54272580 | 120 | } else if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_INTR_PSM) { |
kotakku | 0:b1ce54272580 | 121 | identifier = l2capinbuf[9]; |
kotakku | 0:b1ce54272580 | 122 | interrupt_scid[0] = l2capinbuf[14]; |
kotakku | 0:b1ce54272580 | 123 | interrupt_scid[1] = l2capinbuf[15]; |
kotakku | 0:b1ce54272580 | 124 | l2cap_set_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST); |
kotakku | 0:b1ce54272580 | 125 | } |
kotakku | 0:b1ce54272580 | 126 | } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) { |
kotakku | 0:b1ce54272580 | 127 | if((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success |
kotakku | 0:b1ce54272580 | 128 | if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { |
kotakku | 0:b1ce54272580 | 129 | //Notify(PSTR("\r\nHID Control Configuration Complete"), 0x80); |
kotakku | 0:b1ce54272580 | 130 | identifier = l2capinbuf[9]; |
kotakku | 0:b1ce54272580 | 131 | l2cap_set_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS); |
kotakku | 0:b1ce54272580 | 132 | } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { |
kotakku | 0:b1ce54272580 | 133 | //Notify(PSTR("\r\nHID Interrupt Configuration Complete"), 0x80); |
kotakku | 0:b1ce54272580 | 134 | identifier = l2capinbuf[9]; |
kotakku | 0:b1ce54272580 | 135 | l2cap_set_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS); |
kotakku | 0:b1ce54272580 | 136 | } |
kotakku | 0:b1ce54272580 | 137 | } |
kotakku | 0:b1ce54272580 | 138 | } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) { |
kotakku | 0:b1ce54272580 | 139 | if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { |
kotakku | 0:b1ce54272580 | 140 | //Notify(PSTR("\r\nHID Control Configuration Request"), 0x80); |
kotakku | 0:b1ce54272580 | 141 | pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], control_scid); |
kotakku | 0:b1ce54272580 | 142 | } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { |
kotakku | 0:b1ce54272580 | 143 | //Notify(PSTR("\r\nHID Interrupt Configuration Request"), 0x80); |
kotakku | 0:b1ce54272580 | 144 | pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], interrupt_scid); |
kotakku | 0:b1ce54272580 | 145 | } |
kotakku | 0:b1ce54272580 | 146 | } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) { |
kotakku | 0:b1ce54272580 | 147 | if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { |
kotakku | 0:b1ce54272580 | 148 | #ifdef DEBUG_USB_HOST |
kotakku | 0:b1ce54272580 | 149 | Notify(PSTR("\r\nDisconnect Request: Control Channel"), 0x80); |
kotakku | 0:b1ce54272580 | 150 | #endif |
kotakku | 0:b1ce54272580 | 151 | identifier = l2capinbuf[9]; |
kotakku | 0:b1ce54272580 | 152 | pBtd->l2cap_disconnection_response(hci_handle, identifier, control_dcid, control_scid); |
kotakku | 0:b1ce54272580 | 153 | Reset(); |
kotakku | 0:b1ce54272580 | 154 | } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { |
kotakku | 0:b1ce54272580 | 155 | #ifdef DEBUG_USB_HOST |
kotakku | 0:b1ce54272580 | 156 | Notify(PSTR("\r\nDisconnect Request: Interrupt Channel"), 0x80); |
kotakku | 0:b1ce54272580 | 157 | #endif |
kotakku | 0:b1ce54272580 | 158 | identifier = l2capinbuf[9]; |
kotakku | 0:b1ce54272580 | 159 | pBtd->l2cap_disconnection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid); |
kotakku | 0:b1ce54272580 | 160 | Reset(); |
kotakku | 0:b1ce54272580 | 161 | } |
kotakku | 0:b1ce54272580 | 162 | } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) { |
kotakku | 0:b1ce54272580 | 163 | if(l2capinbuf[12] == control_scid[0] && l2capinbuf[13] == control_scid[1]) { |
kotakku | 0:b1ce54272580 | 164 | //Notify(PSTR("\r\nDisconnect Response: Control Channel"), 0x80); |
kotakku | 0:b1ce54272580 | 165 | identifier = l2capinbuf[9]; |
kotakku | 0:b1ce54272580 | 166 | l2cap_set_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE); |
kotakku | 0:b1ce54272580 | 167 | } else if(l2capinbuf[12] == interrupt_scid[0] && l2capinbuf[13] == interrupt_scid[1]) { |
kotakku | 0:b1ce54272580 | 168 | //Notify(PSTR("\r\nDisconnect Response: Interrupt Channel"), 0x80); |
kotakku | 0:b1ce54272580 | 169 | identifier = l2capinbuf[9]; |
kotakku | 0:b1ce54272580 | 170 | l2cap_set_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE); |
kotakku | 0:b1ce54272580 | 171 | } |
kotakku | 0:b1ce54272580 | 172 | } |
kotakku | 0:b1ce54272580 | 173 | #ifdef EXTRADEBUG |
kotakku | 0:b1ce54272580 | 174 | else { |
kotakku | 0:b1ce54272580 | 175 | identifier = l2capinbuf[9]; |
kotakku | 0:b1ce54272580 | 176 | Notify(PSTR("\r\nL2CAP Unknown Signaling Command: "), 0x80); |
kotakku | 0:b1ce54272580 | 177 | D_PrintHex<uint8_t > (l2capinbuf[8], 0x80); |
kotakku | 0:b1ce54272580 | 178 | } |
kotakku | 0:b1ce54272580 | 179 | #endif |
kotakku | 0:b1ce54272580 | 180 | } else if(l2capinbuf[6] == interrupt_dcid[0] && l2capinbuf[7] == interrupt_dcid[1]) { // l2cap_interrupt |
kotakku | 0:b1ce54272580 | 181 | #ifdef PRINTREPORT |
kotakku | 0:b1ce54272580 | 182 | Notify(PSTR("\r\nL2CAP Interrupt: "), 0x80); |
kotakku | 0:b1ce54272580 | 183 | for(uint16_t i = 0; i < ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); i++) { |
kotakku | 0:b1ce54272580 | 184 | D_PrintHex<uint8_t > (l2capinbuf[i + 8], 0x80); |
kotakku | 0:b1ce54272580 | 185 | Notify(PSTR(" "), 0x80); |
kotakku | 0:b1ce54272580 | 186 | } |
kotakku | 0:b1ce54272580 | 187 | #endif |
kotakku | 0:b1ce54272580 | 188 | if(l2capinbuf[8] == 0xA1) { // HID_THDR_DATA_INPUT |
kotakku | 0:b1ce54272580 | 189 | uint16_t length = ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); |
kotakku | 0:b1ce54272580 | 190 | ParseBTHIDData((uint8_t)(length - 1), &l2capinbuf[9]); |
kotakku | 0:b1ce54272580 | 191 | |
kotakku | 0:b1ce54272580 | 192 | switch(l2capinbuf[9]) { |
kotakku | 0:b1ce54272580 | 193 | case 0x01: // Keyboard or Joystick events |
kotakku | 0:b1ce54272580 | 194 | if(pRptParser[KEYBOARD_PARSER_ID]) |
kotakku | 0:b1ce54272580 | 195 | pRptParser[KEYBOARD_PARSER_ID]->Parse(reinterpret_cast<USBHID *>(this), 0, (uint8_t)(length - 2), &l2capinbuf[10]); // Use reinterpret_cast again to extract the instance |
kotakku | 0:b1ce54272580 | 196 | break; |
kotakku | 0:b1ce54272580 | 197 | |
kotakku | 0:b1ce54272580 | 198 | case 0x02: // Mouse events |
kotakku | 0:b1ce54272580 | 199 | if(pRptParser[MOUSE_PARSER_ID]) |
kotakku | 0:b1ce54272580 | 200 | pRptParser[MOUSE_PARSER_ID]->Parse(reinterpret_cast<USBHID *>(this), 0, (uint8_t)(length - 2), &l2capinbuf[10]); // Use reinterpret_cast again to extract the instance |
kotakku | 0:b1ce54272580 | 201 | break; |
kotakku | 0:b1ce54272580 | 202 | #ifdef EXTRADEBUG |
kotakku | 0:b1ce54272580 | 203 | default: |
kotakku | 0:b1ce54272580 | 204 | Notify(PSTR("\r\nUnknown Report type: "), 0x80); |
kotakku | 0:b1ce54272580 | 205 | D_PrintHex<uint8_t > (l2capinbuf[9], 0x80); |
kotakku | 0:b1ce54272580 | 206 | break; |
kotakku | 0:b1ce54272580 | 207 | #endif |
kotakku | 0:b1ce54272580 | 208 | } |
kotakku | 0:b1ce54272580 | 209 | } |
kotakku | 0:b1ce54272580 | 210 | } else if(l2capinbuf[6] == control_dcid[0] && l2capinbuf[7] == control_dcid[1]) { // l2cap_control |
kotakku | 0:b1ce54272580 | 211 | #ifdef PRINTREPORT |
kotakku | 0:b1ce54272580 | 212 | Notify(PSTR("\r\nL2CAP Control: "), 0x80); |
kotakku | 0:b1ce54272580 | 213 | for(uint16_t i = 0; i < ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); i++) { |
kotakku | 0:b1ce54272580 | 214 | D_PrintHex<uint8_t > (l2capinbuf[i + 8], 0x80); |
kotakku | 0:b1ce54272580 | 215 | Notify(PSTR(" "), 0x80); |
kotakku | 0:b1ce54272580 | 216 | } |
kotakku | 0:b1ce54272580 | 217 | #endif |
kotakku | 0:b1ce54272580 | 218 | } |
kotakku | 0:b1ce54272580 | 219 | #ifdef EXTRADEBUG |
kotakku | 0:b1ce54272580 | 220 | else { |
kotakku | 0:b1ce54272580 | 221 | Notify(PSTR("\r\nUnsupported L2CAP Data - Channel ID: "), 0x80); |
kotakku | 0:b1ce54272580 | 222 | D_PrintHex<uint8_t > (l2capinbuf[7], 0x80); |
kotakku | 0:b1ce54272580 | 223 | Notify(PSTR(" "), 0x80); |
kotakku | 0:b1ce54272580 | 224 | D_PrintHex<uint8_t > (l2capinbuf[6], 0x80); |
kotakku | 0:b1ce54272580 | 225 | |
kotakku | 0:b1ce54272580 | 226 | Notify(PSTR("\r\nData: "), 0x80); |
kotakku | 0:b1ce54272580 | 227 | Notify(PSTR("\r\n"), 0x80); |
kotakku | 0:b1ce54272580 | 228 | for(uint16_t i = 0; i < ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); i++) { |
kotakku | 0:b1ce54272580 | 229 | D_PrintHex<uint8_t > (l2capinbuf[i + 8], 0x80); |
kotakku | 0:b1ce54272580 | 230 | Notify(PSTR(" "), 0x80); |
kotakku | 0:b1ce54272580 | 231 | } |
kotakku | 0:b1ce54272580 | 232 | } |
kotakku | 0:b1ce54272580 | 233 | #endif |
kotakku | 0:b1ce54272580 | 234 | L2CAP_task(); |
kotakku | 0:b1ce54272580 | 235 | } |
kotakku | 0:b1ce54272580 | 236 | } |
kotakku | 0:b1ce54272580 | 237 | |
kotakku | 0:b1ce54272580 | 238 | void BTHID::L2CAP_task() { |
kotakku | 0:b1ce54272580 | 239 | switch(l2cap_state) { |
kotakku | 0:b1ce54272580 | 240 | /* These states are used if the HID device is the host */ |
kotakku | 0:b1ce54272580 | 241 | case L2CAP_CONTROL_SUCCESS: |
kotakku | 0:b1ce54272580 | 242 | if(l2cap_check_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS)) { |
kotakku | 0:b1ce54272580 | 243 | #ifdef DEBUG_USB_HOST |
kotakku | 0:b1ce54272580 | 244 | Notify(PSTR("\r\nHID Control Successfully Configured"), 0x80); |
kotakku | 0:b1ce54272580 | 245 | #endif |
kotakku | 0:b1ce54272580 | 246 | setProtocol(); // Set protocol before establishing HID interrupt channel |
kotakku | 0:b1ce54272580 | 247 | l2cap_state = L2CAP_INTERRUPT_SETUP; |
kotakku | 0:b1ce54272580 | 248 | } |
kotakku | 0:b1ce54272580 | 249 | break; |
kotakku | 0:b1ce54272580 | 250 | |
kotakku | 0:b1ce54272580 | 251 | case L2CAP_INTERRUPT_SETUP: |
kotakku | 0:b1ce54272580 | 252 | if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST)) { |
kotakku | 0:b1ce54272580 | 253 | #ifdef DEBUG_USB_HOST |
kotakku | 0:b1ce54272580 | 254 | Notify(PSTR("\r\nHID Interrupt Incoming Connection Request"), 0x80); |
kotakku | 0:b1ce54272580 | 255 | #endif |
kotakku | 0:b1ce54272580 | 256 | pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, PENDING); |
kotakku | 0:b1ce54272580 | 257 | delay(1); |
kotakku | 0:b1ce54272580 | 258 | pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, SUCCESSFUL); |
kotakku | 0:b1ce54272580 | 259 | identifier++; |
kotakku | 0:b1ce54272580 | 260 | delay(1); |
kotakku | 0:b1ce54272580 | 261 | pBtd->l2cap_config_request(hci_handle, identifier, interrupt_scid); |
kotakku | 0:b1ce54272580 | 262 | |
kotakku | 0:b1ce54272580 | 263 | l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST; |
kotakku | 0:b1ce54272580 | 264 | } |
kotakku | 0:b1ce54272580 | 265 | break; |
kotakku | 0:b1ce54272580 | 266 | |
kotakku | 0:b1ce54272580 | 267 | /* These states are used if the Arduino is the host */ |
kotakku | 0:b1ce54272580 | 268 | case L2CAP_CONTROL_CONNECT_REQUEST: |
kotakku | 0:b1ce54272580 | 269 | if(l2cap_check_flag(L2CAP_FLAG_CONTROL_CONNECTED)) { |
kotakku | 0:b1ce54272580 | 270 | #ifdef DEBUG_USB_HOST |
kotakku | 0:b1ce54272580 | 271 | Notify(PSTR("\r\nSend HID Control Config Request"), 0x80); |
kotakku | 0:b1ce54272580 | 272 | #endif |
kotakku | 0:b1ce54272580 | 273 | identifier++; |
kotakku | 0:b1ce54272580 | 274 | pBtd->l2cap_config_request(hci_handle, identifier, control_scid); |
kotakku | 0:b1ce54272580 | 275 | l2cap_state = L2CAP_CONTROL_CONFIG_REQUEST; |
kotakku | 0:b1ce54272580 | 276 | } |
kotakku | 0:b1ce54272580 | 277 | break; |
kotakku | 0:b1ce54272580 | 278 | |
kotakku | 0:b1ce54272580 | 279 | case L2CAP_CONTROL_CONFIG_REQUEST: |
kotakku | 0:b1ce54272580 | 280 | if(l2cap_check_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS)) { |
kotakku | 0:b1ce54272580 | 281 | setProtocol(); // Set protocol before establishing HID interrupt channel |
kotakku | 0:b1ce54272580 | 282 | delay(1); // Short delay between commands - just to be sure |
kotakku | 0:b1ce54272580 | 283 | #ifdef DEBUG_USB_HOST |
kotakku | 0:b1ce54272580 | 284 | Notify(PSTR("\r\nSend HID Interrupt Connection Request"), 0x80); |
kotakku | 0:b1ce54272580 | 285 | #endif |
kotakku | 0:b1ce54272580 | 286 | identifier++; |
kotakku | 0:b1ce54272580 | 287 | pBtd->l2cap_connection_request(hci_handle, identifier, interrupt_dcid, HID_INTR_PSM); |
kotakku | 0:b1ce54272580 | 288 | l2cap_state = L2CAP_INTERRUPT_CONNECT_REQUEST; |
kotakku | 0:b1ce54272580 | 289 | } |
kotakku | 0:b1ce54272580 | 290 | break; |
kotakku | 0:b1ce54272580 | 291 | |
kotakku | 0:b1ce54272580 | 292 | case L2CAP_INTERRUPT_CONNECT_REQUEST: |
kotakku | 0:b1ce54272580 | 293 | if(l2cap_check_flag(L2CAP_FLAG_INTERRUPT_CONNECTED)) { |
kotakku | 0:b1ce54272580 | 294 | #ifdef DEBUG_USB_HOST |
kotakku | 0:b1ce54272580 | 295 | Notify(PSTR("\r\nSend HID Interrupt Config Request"), 0x80); |
kotakku | 0:b1ce54272580 | 296 | #endif |
kotakku | 0:b1ce54272580 | 297 | identifier++; |
kotakku | 0:b1ce54272580 | 298 | pBtd->l2cap_config_request(hci_handle, identifier, interrupt_scid); |
kotakku | 0:b1ce54272580 | 299 | l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST; |
kotakku | 0:b1ce54272580 | 300 | } |
kotakku | 0:b1ce54272580 | 301 | break; |
kotakku | 0:b1ce54272580 | 302 | |
kotakku | 0:b1ce54272580 | 303 | case L2CAP_INTERRUPT_CONFIG_REQUEST: |
kotakku | 0:b1ce54272580 | 304 | if(l2cap_check_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS)) { // Now the HID channels is established |
kotakku | 0:b1ce54272580 | 305 | #ifdef DEBUG_USB_HOST |
kotakku | 0:b1ce54272580 | 306 | Notify(PSTR("\r\nHID Channels Established"), 0x80); |
kotakku | 0:b1ce54272580 | 307 | #endif |
kotakku | 0:b1ce54272580 | 308 | pBtd->connectToHIDDevice = false; |
kotakku | 0:b1ce54272580 | 309 | pBtd->pairWithHIDDevice = false; |
kotakku | 0:b1ce54272580 | 310 | connected = true; |
kotakku | 0:b1ce54272580 | 311 | onInit(); |
kotakku | 0:b1ce54272580 | 312 | l2cap_state = L2CAP_DONE; |
kotakku | 0:b1ce54272580 | 313 | } |
kotakku | 0:b1ce54272580 | 314 | break; |
kotakku | 0:b1ce54272580 | 315 | |
kotakku | 0:b1ce54272580 | 316 | case L2CAP_DONE: |
kotakku | 0:b1ce54272580 | 317 | break; |
kotakku | 0:b1ce54272580 | 318 | |
kotakku | 0:b1ce54272580 | 319 | case L2CAP_INTERRUPT_DISCONNECT: |
kotakku | 0:b1ce54272580 | 320 | if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE)) { |
kotakku | 0:b1ce54272580 | 321 | #ifdef DEBUG_USB_HOST |
kotakku | 0:b1ce54272580 | 322 | Notify(PSTR("\r\nDisconnected Interrupt Channel"), 0x80); |
kotakku | 0:b1ce54272580 | 323 | #endif |
kotakku | 0:b1ce54272580 | 324 | identifier++; |
kotakku | 0:b1ce54272580 | 325 | pBtd->l2cap_disconnection_request(hci_handle, identifier, control_scid, control_dcid); |
kotakku | 0:b1ce54272580 | 326 | l2cap_state = L2CAP_CONTROL_DISCONNECT; |
kotakku | 0:b1ce54272580 | 327 | } |
kotakku | 0:b1ce54272580 | 328 | break; |
kotakku | 0:b1ce54272580 | 329 | |
kotakku | 0:b1ce54272580 | 330 | case L2CAP_CONTROL_DISCONNECT: |
kotakku | 0:b1ce54272580 | 331 | if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE)) { |
kotakku | 0:b1ce54272580 | 332 | #ifdef DEBUG_USB_HOST |
kotakku | 0:b1ce54272580 | 333 | Notify(PSTR("\r\nDisconnected Control Channel"), 0x80); |
kotakku | 0:b1ce54272580 | 334 | #endif |
kotakku | 0:b1ce54272580 | 335 | pBtd->hci_disconnect(hci_handle); |
kotakku | 0:b1ce54272580 | 336 | hci_handle = -1; // Reset handle |
kotakku | 0:b1ce54272580 | 337 | l2cap_event_flag = 0; // Reset flags |
kotakku | 0:b1ce54272580 | 338 | l2cap_state = L2CAP_WAIT; |
kotakku | 0:b1ce54272580 | 339 | } |
kotakku | 0:b1ce54272580 | 340 | break; |
kotakku | 0:b1ce54272580 | 341 | } |
kotakku | 0:b1ce54272580 | 342 | } |
kotakku | 0:b1ce54272580 | 343 | |
kotakku | 0:b1ce54272580 | 344 | void BTHID::Run() { |
kotakku | 0:b1ce54272580 | 345 | switch(l2cap_state) { |
kotakku | 0:b1ce54272580 | 346 | case L2CAP_WAIT: |
kotakku | 0:b1ce54272580 | 347 | if(pBtd->connectToHIDDevice && !pBtd->l2capConnectionClaimed && !connected && !activeConnection) { |
kotakku | 0:b1ce54272580 | 348 | pBtd->l2capConnectionClaimed = true; |
kotakku | 0:b1ce54272580 | 349 | activeConnection = true; |
kotakku | 0:b1ce54272580 | 350 | #ifdef DEBUG_USB_HOST |
kotakku | 0:b1ce54272580 | 351 | Notify(PSTR("\r\nSend HID Control Connection Request"), 0x80); |
kotakku | 0:b1ce54272580 | 352 | #endif |
kotakku | 0:b1ce54272580 | 353 | hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection |
kotakku | 0:b1ce54272580 | 354 | l2cap_event_flag = 0; // Reset flags |
kotakku | 0:b1ce54272580 | 355 | identifier = 0; |
kotakku | 0:b1ce54272580 | 356 | pBtd->l2cap_connection_request(hci_handle, identifier, control_dcid, HID_CTRL_PSM); |
kotakku | 0:b1ce54272580 | 357 | l2cap_state = L2CAP_CONTROL_CONNECT_REQUEST; |
kotakku | 0:b1ce54272580 | 358 | } else if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST)) { |
kotakku | 0:b1ce54272580 | 359 | #ifdef DEBUG_USB_HOST |
kotakku | 0:b1ce54272580 | 360 | Notify(PSTR("\r\nHID Control Incoming Connection Request"), 0x80); |
kotakku | 0:b1ce54272580 | 361 | #endif |
kotakku | 0:b1ce54272580 | 362 | pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, PENDING); |
kotakku | 0:b1ce54272580 | 363 | delay(1); |
kotakku | 0:b1ce54272580 | 364 | pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, SUCCESSFUL); |
kotakku | 0:b1ce54272580 | 365 | identifier++; |
kotakku | 0:b1ce54272580 | 366 | delay(1); |
kotakku | 0:b1ce54272580 | 367 | pBtd->l2cap_config_request(hci_handle, identifier, control_scid); |
kotakku | 0:b1ce54272580 | 368 | l2cap_state = L2CAP_CONTROL_SUCCESS; |
kotakku | 0:b1ce54272580 | 369 | } |
kotakku | 0:b1ce54272580 | 370 | break; |
kotakku | 0:b1ce54272580 | 371 | } |
kotakku | 0:b1ce54272580 | 372 | } |
kotakku | 0:b1ce54272580 | 373 | |
kotakku | 0:b1ce54272580 | 374 | /************************************************************/ |
kotakku | 0:b1ce54272580 | 375 | /* HID Commands */ |
kotakku | 0:b1ce54272580 | 376 | |
kotakku | 0:b1ce54272580 | 377 | /************************************************************/ |
kotakku | 0:b1ce54272580 | 378 | void BTHID::setProtocol() { |
kotakku | 0:b1ce54272580 | 379 | #ifdef DEBUG_USB_HOST |
kotakku | 0:b1ce54272580 | 380 | Notify(PSTR("\r\nSet protocol mode: "), 0x80); |
kotakku | 0:b1ce54272580 | 381 | D_PrintHex<uint8_t > (protocolMode, 0x80); |
kotakku | 0:b1ce54272580 | 382 | #endif |
kotakku | 0:b1ce54272580 | 383 | if (protocolMode != USB_HID_BOOT_PROTOCOL && protocolMode != HID_RPT_PROTOCOL) { |
kotakku | 0:b1ce54272580 | 384 | #ifdef DEBUG_USB_HOST |
kotakku | 0:b1ce54272580 | 385 | Notify(PSTR("\r\nNot a valid protocol mode. Using Boot protocol instead."), 0x80); |
kotakku | 0:b1ce54272580 | 386 | #endif |
kotakku | 0:b1ce54272580 | 387 | protocolMode = USB_HID_BOOT_PROTOCOL; // Use Boot Protocol by default |
kotakku | 0:b1ce54272580 | 388 | } |
kotakku | 0:b1ce54272580 | 389 | uint8_t command = 0x70 | protocolMode; // Set Protocol, see Bluetooth HID specs page 33 |
kotakku | 0:b1ce54272580 | 390 | pBtd->L2CAP_Command(hci_handle, &command, 1, control_scid[0], control_scid[1]); |
kotakku | 0:b1ce54272580 | 391 | } |
kotakku | 0:b1ce54272580 | 392 | |
kotakku | 0:b1ce54272580 | 393 | void BTHID::setLeds(uint8_t data) { |
kotakku | 0:b1ce54272580 | 394 | uint8_t buf[3]; |
kotakku | 0:b1ce54272580 | 395 | buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) |
kotakku | 0:b1ce54272580 | 396 | buf[1] = 0x01; // Report ID |
kotakku | 0:b1ce54272580 | 397 | buf[2] = data; |
kotakku | 0:b1ce54272580 | 398 | pBtd->L2CAP_Command(hci_handle, buf, 3, interrupt_scid[0], interrupt_scid[1]); |
kotakku | 0:b1ce54272580 | 399 | } |
kotakku | 0:b1ce54272580 | 400 |