Library to use Arduino USB host shield on mbed

Dependents:   USBHOST_PS5

ArduinoのUSB Host Shield 2.0をmbedで使えるようにしたライブラリです。
大体のコードがArduinoからそのまま移植可能です。

Arduino UNOやMega用のホストシールド以外にもミニサイズのホストシールドでも使用可能です https://os.mbed.com/media/uploads/kotakku/dffgfddswa.png

シールドについて

3.3VのI/O用にシールドの改造が必要になりますがネット上に記事がたくさんあるのでそちらを参考にしてください

接続例

https://os.mbed.com/media/uploads/kotakku/esgsvfvhjrekldkcjxvb.png

使い方

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");
        }
    }
}
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?

UserRevisionLine numberNew contents of line
kotakku 0:b1ce54272580 1 /* Copyright (C) 2012 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 "BTD.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
kotakku 0:b1ce54272580 22 const uint8_t BTD::BTD_CONTROL_PIPE = 0;
kotakku 0:b1ce54272580 23 const uint8_t BTD::BTD_EVENT_PIPE = 1;
kotakku 0:b1ce54272580 24 const uint8_t BTD::BTD_DATAIN_PIPE = 2;
kotakku 0:b1ce54272580 25 const uint8_t BTD::BTD_DATAOUT_PIPE = 3;
kotakku 0:b1ce54272580 26
kotakku 0:b1ce54272580 27 BTD::BTD(USB *p) :
kotakku 0:b1ce54272580 28 connectToWii(false),
kotakku 0:b1ce54272580 29 pairWithWii(false),
kotakku 0:b1ce54272580 30 connectToHIDDevice(false),
kotakku 0:b1ce54272580 31 pairWithHIDDevice(false),
kotakku 0:b1ce54272580 32 pUsb(p), // Pointer to USB class instance - mandatory
kotakku 0:b1ce54272580 33 bAddress(0), // Device address - mandatory
kotakku 0:b1ce54272580 34 bNumEP(1), // If config descriptor needs to be parsed
kotakku 0:b1ce54272580 35 qNextPollTime(0), // Reset NextPollTime
kotakku 0:b1ce54272580 36 pollInterval(0),
kotakku 0:b1ce54272580 37 bPollEnable(false) // Don't start polling before dongle is connected
kotakku 0:b1ce54272580 38 {
kotakku 0:b1ce54272580 39 for(uint8_t i = 0; i < BTD_NUM_SERVICES; i++)
kotakku 0:b1ce54272580 40 btService[i] = NULL;
kotakku 0:b1ce54272580 41
kotakku 0:b1ce54272580 42 Initialize(); // Set all variables, endpoint structs etc. to default values
kotakku 0:b1ce54272580 43
kotakku 0:b1ce54272580 44 if(pUsb) // Register in USB subsystem
kotakku 0:b1ce54272580 45 pUsb->RegisterDeviceClass(this); // Set devConfig[] entry
kotakku 0:b1ce54272580 46 }
kotakku 0:b1ce54272580 47
kotakku 0:b1ce54272580 48 uint8_t BTD::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) {
kotakku 0:b1ce54272580 49 const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);
kotakku 0:b1ce54272580 50 uint8_t buf[constBufSize];
kotakku 0:b1ce54272580 51 USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
kotakku 0:b1ce54272580 52 uint8_t rcode;
kotakku 0:b1ce54272580 53 UsbDevice *p = NULL;
kotakku 0:b1ce54272580 54 EpInfo *oldep_ptr = NULL;
kotakku 0:b1ce54272580 55
kotakku 0:b1ce54272580 56 Initialize(); // Set all variables, endpoint structs etc. to default values
kotakku 0:b1ce54272580 57
kotakku 0:b1ce54272580 58 AddressPool &addrPool = pUsb->GetAddressPool(); // Get memory address of USB device address pool
kotakku 0:b1ce54272580 59 #ifdef EXTRADEBUG
kotakku 0:b1ce54272580 60 Notify(PSTR("\r\nBTD ConfigureDevice"), 0x80);
kotakku 0:b1ce54272580 61 #endif
kotakku 0:b1ce54272580 62
kotakku 0:b1ce54272580 63 if(bAddress) { // Check if address has already been assigned to an instance
kotakku 0:b1ce54272580 64 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 65 Notify(PSTR("\r\nAddress in use"), 0x80);
kotakku 0:b1ce54272580 66 #endif
kotakku 0:b1ce54272580 67 return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
kotakku 0:b1ce54272580 68 }
kotakku 0:b1ce54272580 69
kotakku 0:b1ce54272580 70 p = addrPool.GetUsbDevicePtr(0); // Get pointer to pseudo device with address 0 assigned
kotakku 0:b1ce54272580 71 if(!p) {
kotakku 0:b1ce54272580 72 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 73 Notify(PSTR("\r\nAddress not found"), 0x80);
kotakku 0:b1ce54272580 74 #endif
kotakku 0:b1ce54272580 75 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
kotakku 0:b1ce54272580 76 }
kotakku 0:b1ce54272580 77
kotakku 0:b1ce54272580 78 if(!p->epinfo) {
kotakku 0:b1ce54272580 79 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 80 Notify(PSTR("\r\nepinfo is null"), 0x80);
kotakku 0:b1ce54272580 81 #endif
kotakku 0:b1ce54272580 82 return USB_ERROR_EPINFO_IS_NULL;
kotakku 0:b1ce54272580 83 }
kotakku 0:b1ce54272580 84
kotakku 0:b1ce54272580 85 oldep_ptr = p->epinfo; // Save old pointer to EP_RECORD of address 0
kotakku 0:b1ce54272580 86 p->epinfo = epInfo; // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
kotakku 0:b1ce54272580 87 p->lowspeed = lowspeed;
kotakku 0:b1ce54272580 88 rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data
kotakku 0:b1ce54272580 89
kotakku 0:b1ce54272580 90 p->epinfo = oldep_ptr; // Restore p->epinfo
kotakku 0:b1ce54272580 91
kotakku 0:b1ce54272580 92 if(rcode)
kotakku 0:b1ce54272580 93 goto FailGetDevDescr;
kotakku 0:b1ce54272580 94
kotakku 0:b1ce54272580 95 bAddress = addrPool.AllocAddress(parent, false, port); // Allocate new address according to device class
kotakku 0:b1ce54272580 96
kotakku 0:b1ce54272580 97 if(!bAddress) {
kotakku 0:b1ce54272580 98 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 99 Notify(PSTR("\r\nOut of address space"), 0x80);
kotakku 0:b1ce54272580 100 #endif
kotakku 0:b1ce54272580 101 return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
kotakku 0:b1ce54272580 102 }
kotakku 0:b1ce54272580 103
kotakku 0:b1ce54272580 104 if (udd->bDeviceClass == 0x09) // Some dongles have an USB hub inside
kotakku 0:b1ce54272580 105 goto FailHub;
kotakku 0:b1ce54272580 106
kotakku 0:b1ce54272580 107 epInfo[0].maxPktSize = udd->bMaxPacketSize0; // Extract Max Packet Size from device descriptor
kotakku 0:b1ce54272580 108 epInfo[1].epAddr = udd->bNumConfigurations; // Steal and abuse from epInfo structure to save memory
kotakku 0:b1ce54272580 109
kotakku 0:b1ce54272580 110 VID = udd->idVendor;
kotakku 0:b1ce54272580 111 PID = udd->idProduct;
kotakku 0:b1ce54272580 112
kotakku 0:b1ce54272580 113 return USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET;
kotakku 0:b1ce54272580 114
kotakku 0:b1ce54272580 115 FailHub:
kotakku 0:b1ce54272580 116 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 117 Notify(PSTR("\r\nPlease create a hub instance in your code: \"USBHub Hub1(&Usb);\""), 0x80);
kotakku 0:b1ce54272580 118 #endif
kotakku 0:b1ce54272580 119 pUsb->setAddr(bAddress, 0, 0); // Reset address
kotakku 0:b1ce54272580 120 rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
kotakku 0:b1ce54272580 121 Release();
kotakku 0:b1ce54272580 122 return rcode;
kotakku 0:b1ce54272580 123
kotakku 0:b1ce54272580 124 FailGetDevDescr:
kotakku 0:b1ce54272580 125 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 126 NotifyFailGetDevDescr(rcode);
kotakku 0:b1ce54272580 127 #endif
kotakku 0:b1ce54272580 128 if(rcode != hrJERR)
kotakku 0:b1ce54272580 129 rcode = USB_ERROR_FailGetDevDescr;
kotakku 0:b1ce54272580 130 Release();
kotakku 0:b1ce54272580 131 return rcode;
kotakku 0:b1ce54272580 132 };
kotakku 0:b1ce54272580 133
kotakku 0:b1ce54272580 134 uint8_t BTD::Init(uint8_t parent __attribute__((unused)), uint8_t port __attribute__((unused)), bool lowspeed) {
kotakku 0:b1ce54272580 135 uint8_t rcode;
kotakku 0:b1ce54272580 136 uint8_t num_of_conf = epInfo[1].epAddr; // Number of configurations
kotakku 0:b1ce54272580 137 epInfo[1].epAddr = 0;
kotakku 0:b1ce54272580 138
kotakku 0:b1ce54272580 139 AddressPool &addrPool = pUsb->GetAddressPool();
kotakku 0:b1ce54272580 140 #ifdef EXTRADEBUG
kotakku 0:b1ce54272580 141 Notify(PSTR("\r\nBTD Init"), 0x80);
kotakku 0:b1ce54272580 142 #endif
kotakku 0:b1ce54272580 143 UsbDevice *p = addrPool.GetUsbDevicePtr(bAddress); // Get pointer to assigned address record
kotakku 0:b1ce54272580 144
kotakku 0:b1ce54272580 145 if(!p) {
kotakku 0:b1ce54272580 146 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 147 Notify(PSTR("\r\nAddress not found"), 0x80);
kotakku 0:b1ce54272580 148 #endif
kotakku 0:b1ce54272580 149 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
kotakku 0:b1ce54272580 150 }
kotakku 0:b1ce54272580 151
kotakku 0:b1ce54272580 152 delay(300); // Assign new address to the device
kotakku 0:b1ce54272580 153
kotakku 0:b1ce54272580 154 rcode = pUsb->setAddr(0, 0, bAddress); // Assign new address to the device
kotakku 0:b1ce54272580 155 if(rcode) {
kotakku 0:b1ce54272580 156 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 157 Notify(PSTR("\r\nsetAddr: "), 0x80);
kotakku 0:b1ce54272580 158 D_PrintHex<uint8_t > (rcode, 0x80);
kotakku 0:b1ce54272580 159 #endif
kotakku 0:b1ce54272580 160 p->lowspeed = false;
kotakku 0:b1ce54272580 161 goto Fail;
kotakku 0:b1ce54272580 162 }
kotakku 0:b1ce54272580 163 #ifdef EXTRADEBUG
kotakku 0:b1ce54272580 164 Notify(PSTR("\r\nAddr: "), 0x80);
kotakku 0:b1ce54272580 165 D_PrintHex<uint8_t > (bAddress, 0x80);
kotakku 0:b1ce54272580 166 #endif
kotakku 0:b1ce54272580 167
kotakku 0:b1ce54272580 168 p->lowspeed = false;
kotakku 0:b1ce54272580 169
kotakku 0:b1ce54272580 170 p = addrPool.GetUsbDevicePtr(bAddress); // Get pointer to assigned address record
kotakku 0:b1ce54272580 171 if(!p) {
kotakku 0:b1ce54272580 172 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 173 Notify(PSTR("\r\nAddress not found"), 0x80);
kotakku 0:b1ce54272580 174 #endif
kotakku 0:b1ce54272580 175 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
kotakku 0:b1ce54272580 176 }
kotakku 0:b1ce54272580 177
kotakku 0:b1ce54272580 178 p->lowspeed = lowspeed;
kotakku 0:b1ce54272580 179
kotakku 0:b1ce54272580 180 rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); // Assign epInfo to epinfo pointer - only EP0 is known
kotakku 0:b1ce54272580 181 if(rcode)
kotakku 0:b1ce54272580 182 goto FailSetDevTblEntry;
kotakku 0:b1ce54272580 183
kotakku 0:b1ce54272580 184 if(VID == PS3_VID && (PID == PS3_PID || PID == PS3NAVIGATION_PID || PID == PS3MOVE_PID)) {
kotakku 0:b1ce54272580 185 delay(100);
kotakku 0:b1ce54272580 186 rcode = pUsb->setConf(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, 1); // We only need the Control endpoint, so we don't have to initialize the other endpoints of device
kotakku 0:b1ce54272580 187 if(rcode)
kotakku 0:b1ce54272580 188 goto FailSetConfDescr;
kotakku 0:b1ce54272580 189
kotakku 0:b1ce54272580 190 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 191 if(PID == PS3_PID || PID == PS3NAVIGATION_PID) {
kotakku 0:b1ce54272580 192 if(PID == PS3_PID)
kotakku 0:b1ce54272580 193 Notify(PSTR("\r\nDualshock 3 Controller Connected"), 0x80);
kotakku 0:b1ce54272580 194 else // It must be a navigation controller
kotakku 0:b1ce54272580 195 Notify(PSTR("\r\nNavigation Controller Connected"), 0x80);
kotakku 0:b1ce54272580 196 } else // It must be a Motion controller
kotakku 0:b1ce54272580 197 Notify(PSTR("\r\nMotion Controller Connected"), 0x80);
kotakku 0:b1ce54272580 198 #endif
kotakku 0:b1ce54272580 199
kotakku 0:b1ce54272580 200 if(my_bdaddr[0] == 0x00 && my_bdaddr[1] == 0x00 && my_bdaddr[2] == 0x00 && my_bdaddr[3] == 0x00 && my_bdaddr[4] == 0x00 && my_bdaddr[5] == 0x00) {
kotakku 0:b1ce54272580 201 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 202 Notify(PSTR("\r\nPlease plug in the dongle before trying to pair with the PS3 Controller\r\nor set the Bluetooth address in the constructor of the PS3BT class"), 0x80);
kotakku 0:b1ce54272580 203 #endif
kotakku 0:b1ce54272580 204 } else {
kotakku 0:b1ce54272580 205 if(PID == PS3_PID || PID == PS3NAVIGATION_PID)
kotakku 0:b1ce54272580 206 setBdaddr(my_bdaddr); // Set internal Bluetooth address
kotakku 0:b1ce54272580 207 else
kotakku 0:b1ce54272580 208 setMoveBdaddr(my_bdaddr); // Set internal Bluetooth address
kotakku 0:b1ce54272580 209 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 210 Notify(PSTR("\r\nBluetooth Address was set to: "), 0x80);
kotakku 0:b1ce54272580 211 for(int8_t i = 5; i > 0; i--) {
kotakku 0:b1ce54272580 212 D_PrintHex<uint8_t > (my_bdaddr[i], 0x80);
kotakku 0:b1ce54272580 213 Notify(PSTR(":"), 0x80);
kotakku 0:b1ce54272580 214 }
kotakku 0:b1ce54272580 215 D_PrintHex<uint8_t > (my_bdaddr[0], 0x80);
kotakku 0:b1ce54272580 216 #endif
kotakku 0:b1ce54272580 217 }
kotakku 0:b1ce54272580 218
kotakku 0:b1ce54272580 219 pUsb->setConf(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, 0); // Reset configuration value
kotakku 0:b1ce54272580 220 pUsb->setAddr(bAddress, 0, 0); // Reset address
kotakku 0:b1ce54272580 221 Release(); // Release device
kotakku 0:b1ce54272580 222 return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; // Return
kotakku 0:b1ce54272580 223 } else {
kotakku 0:b1ce54272580 224 // Check if attached device is a Bluetooth dongle and fill endpoint data structure
kotakku 0:b1ce54272580 225 // First interface in the configuration must have Bluetooth assigned Class/Subclass/Protocol
kotakku 0:b1ce54272580 226 // And 3 endpoints - interrupt-IN, bulk-IN, bulk-OUT, not necessarily in this order
kotakku 0:b1ce54272580 227 for(uint8_t i = 0; i < num_of_conf; i++) {
kotakku 0:b1ce54272580 228 if((VID == IOGEAR_GBU521_VID && PID == IOGEAR_GBU521_PID) || (VID == BELKIN_F8T065BF_VID && PID == BELKIN_F8T065BF_PID)) {
kotakku 0:b1ce54272580 229 ConfigDescParser<USB_CLASS_VENDOR_SPECIFIC, WI_SUBCLASS_RF, WI_PROTOCOL_BT, CP_MASK_COMPARE_ALL> confDescrParser(this); // Workaround issue with some dongles
kotakku 0:b1ce54272580 230 rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
kotakku 0:b1ce54272580 231 } else {
kotakku 0:b1ce54272580 232 ConfigDescParser<USB_CLASS_WIRELESS_CTRL, WI_SUBCLASS_RF, WI_PROTOCOL_BT, CP_MASK_COMPARE_ALL> confDescrParser(this); // Set class id according to the specification
kotakku 0:b1ce54272580 233 rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
kotakku 0:b1ce54272580 234 }
kotakku 0:b1ce54272580 235 if(rcode) // Check error code
kotakku 0:b1ce54272580 236 goto FailGetConfDescr;
kotakku 0:b1ce54272580 237 if(bNumEP >= BTD_MAX_ENDPOINTS) // All endpoints extracted
kotakku 0:b1ce54272580 238 break;
kotakku 0:b1ce54272580 239 }
kotakku 0:b1ce54272580 240
kotakku 0:b1ce54272580 241 if(bNumEP < BTD_MAX_ENDPOINTS)
kotakku 0:b1ce54272580 242 goto FailUnknownDevice;
kotakku 0:b1ce54272580 243
kotakku 0:b1ce54272580 244 // Assign epInfo to epinfo pointer - this time all 3 endpoins
kotakku 0:b1ce54272580 245 rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);
kotakku 0:b1ce54272580 246 if(rcode)
kotakku 0:b1ce54272580 247 goto FailSetDevTblEntry;
kotakku 0:b1ce54272580 248
kotakku 0:b1ce54272580 249 // Set Configuration Value
kotakku 0:b1ce54272580 250 rcode = pUsb->setConf(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, bConfNum);
kotakku 0:b1ce54272580 251 if(rcode)
kotakku 0:b1ce54272580 252 goto FailSetConfDescr;
kotakku 0:b1ce54272580 253
kotakku 0:b1ce54272580 254 hci_num_reset_loops = 100; // only loop 100 times before trying to send the hci reset command
kotakku 0:b1ce54272580 255 hci_counter = 0;
kotakku 0:b1ce54272580 256 hci_state = HCI_INIT_STATE;
kotakku 0:b1ce54272580 257 waitingForConnection = false;
kotakku 0:b1ce54272580 258 bPollEnable = true;
kotakku 0:b1ce54272580 259
kotakku 0:b1ce54272580 260 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 261 Notify(PSTR("\r\nBluetooth Dongle Initialized"), 0x80);
kotakku 0:b1ce54272580 262 #endif
kotakku 0:b1ce54272580 263 }
kotakku 0:b1ce54272580 264 return 0; // Successful configuration
kotakku 0:b1ce54272580 265
kotakku 0:b1ce54272580 266 /* Diagnostic messages */
kotakku 0:b1ce54272580 267 FailSetDevTblEntry:
kotakku 0:b1ce54272580 268 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 269 NotifyFailSetDevTblEntry();
kotakku 0:b1ce54272580 270 goto Fail;
kotakku 0:b1ce54272580 271 #endif
kotakku 0:b1ce54272580 272
kotakku 0:b1ce54272580 273 FailGetConfDescr:
kotakku 0:b1ce54272580 274 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 275 NotifyFailGetConfDescr();
kotakku 0:b1ce54272580 276 goto Fail;
kotakku 0:b1ce54272580 277 #endif
kotakku 0:b1ce54272580 278
kotakku 0:b1ce54272580 279 FailSetConfDescr:
kotakku 0:b1ce54272580 280 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 281 NotifyFailSetConfDescr();
kotakku 0:b1ce54272580 282 #endif
kotakku 0:b1ce54272580 283 goto Fail;
kotakku 0:b1ce54272580 284
kotakku 0:b1ce54272580 285 FailUnknownDevice:
kotakku 0:b1ce54272580 286 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 287 NotifyFailUnknownDevice(VID, PID);
kotakku 0:b1ce54272580 288 #endif
kotakku 0:b1ce54272580 289 pUsb->setAddr(bAddress, 0, 0); // Reset address
kotakku 0:b1ce54272580 290 rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
kotakku 0:b1ce54272580 291 Fail:
kotakku 0:b1ce54272580 292 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 293 Notify(PSTR("\r\nBTD Init Failed, error code: "), 0x80);
kotakku 0:b1ce54272580 294 NotifyFail(rcode);
kotakku 0:b1ce54272580 295 #endif
kotakku 0:b1ce54272580 296 Release();
kotakku 0:b1ce54272580 297 return rcode;
kotakku 0:b1ce54272580 298 }
kotakku 0:b1ce54272580 299
kotakku 0:b1ce54272580 300 void BTD::Initialize() {
kotakku 0:b1ce54272580 301 uint8_t i;
kotakku 0:b1ce54272580 302 for(i = 0; i < BTD_MAX_ENDPOINTS; i++) {
kotakku 0:b1ce54272580 303 epInfo[i].epAddr = 0;
kotakku 0:b1ce54272580 304 epInfo[i].maxPktSize = (i) ? 0 : 8;
kotakku 0:b1ce54272580 305 epInfo[i].bmSndToggle = 0;
kotakku 0:b1ce54272580 306 epInfo[i].bmRcvToggle = 0;
kotakku 0:b1ce54272580 307 epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
kotakku 0:b1ce54272580 308 }
kotakku 0:b1ce54272580 309 for(i = 0; i < BTD_NUM_SERVICES; i++) {
kotakku 0:b1ce54272580 310 if(btService[i])
kotakku 0:b1ce54272580 311 btService[i]->Reset(); // Reset all Bluetooth services
kotakku 0:b1ce54272580 312 }
kotakku 0:b1ce54272580 313
kotakku 0:b1ce54272580 314 connectToWii = false;
kotakku 0:b1ce54272580 315 incomingWii = false;
kotakku 0:b1ce54272580 316 connectToHIDDevice = false;
kotakku 0:b1ce54272580 317 incomingHIDDevice = false;
kotakku 0:b1ce54272580 318 incomingPS4 = false;
kotakku 0:b1ce54272580 319 bAddress = 0; // Clear device address
kotakku 0:b1ce54272580 320 bNumEP = 1; // Must have to be reset to 1
kotakku 0:b1ce54272580 321 qNextPollTime = 0; // Reset next poll time
kotakku 0:b1ce54272580 322 pollInterval = 0;
kotakku 0:b1ce54272580 323 bPollEnable = false; // Don't start polling before dongle is connected
kotakku 0:b1ce54272580 324 }
kotakku 0:b1ce54272580 325
kotakku 0:b1ce54272580 326 /* Extracts interrupt-IN, bulk-IN, bulk-OUT endpoint information from config descriptor */
kotakku 0:b1ce54272580 327 void BTD::EndpointXtract(uint8_t conf, uint8_t iface __attribute__((unused)), uint8_t alt, uint8_t proto __attribute__((unused)), const USB_ENDPOINT_DESCRIPTOR *pep) {
kotakku 0:b1ce54272580 328 //ErrorMessage<uint8_t>(PSTR("Conf.Val"),conf);
kotakku 0:b1ce54272580 329 //ErrorMessage<uint8_t>(PSTR("Iface Num"),iface);
kotakku 0:b1ce54272580 330 //ErrorMessage<uint8_t>(PSTR("Alt.Set"),alt);
kotakku 0:b1ce54272580 331
kotakku 0:b1ce54272580 332 if(alt) // Wrong interface - by BT spec, no alt setting
kotakku 0:b1ce54272580 333 return;
kotakku 0:b1ce54272580 334
kotakku 0:b1ce54272580 335 bConfNum = conf;
kotakku 0:b1ce54272580 336 uint8_t index;
kotakku 0:b1ce54272580 337
kotakku 0:b1ce54272580 338 if((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_INTERRUPT && (pep->bEndpointAddress & 0x80) == 0x80) { // Interrupt In endpoint found
kotakku 0:b1ce54272580 339 index = BTD_EVENT_PIPE;
kotakku 0:b1ce54272580 340 epInfo[index].bmNakPower = USB_NAK_NOWAIT;
kotakku 0:b1ce54272580 341 } else if((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_BULK) // Bulk endpoint found
kotakku 0:b1ce54272580 342 index = ((pep->bEndpointAddress & 0x80) == 0x80) ? BTD_DATAIN_PIPE : BTD_DATAOUT_PIPE;
kotakku 0:b1ce54272580 343 else
kotakku 0:b1ce54272580 344 return;
kotakku 0:b1ce54272580 345
kotakku 0:b1ce54272580 346 // Fill the rest of endpoint data structure
kotakku 0:b1ce54272580 347 epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
kotakku 0:b1ce54272580 348 epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
kotakku 0:b1ce54272580 349 #ifdef EXTRADEBUG
kotakku 0:b1ce54272580 350 PrintEndpointDescriptor(pep);
kotakku 0:b1ce54272580 351 #endif
kotakku 0:b1ce54272580 352 if(pollInterval < pep->bInterval) // Set the polling interval as the largest polling interval obtained from endpoints
kotakku 0:b1ce54272580 353 pollInterval = pep->bInterval;
kotakku 0:b1ce54272580 354 bNumEP++;
kotakku 0:b1ce54272580 355 }
kotakku 0:b1ce54272580 356
kotakku 0:b1ce54272580 357 void BTD::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr __attribute__((unused))) {
kotakku 0:b1ce54272580 358 #ifdef EXTRADEBUG
kotakku 0:b1ce54272580 359 Notify(PSTR("\r\nEndpoint descriptor:"), 0x80);
kotakku 0:b1ce54272580 360 Notify(PSTR("\r\nLength:\t\t"), 0x80);
kotakku 0:b1ce54272580 361 D_PrintHex<uint8_t > (ep_ptr->bLength, 0x80);
kotakku 0:b1ce54272580 362 Notify(PSTR("\r\nType:\t\t"), 0x80);
kotakku 0:b1ce54272580 363 D_PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);
kotakku 0:b1ce54272580 364 Notify(PSTR("\r\nAddress:\t"), 0x80);
kotakku 0:b1ce54272580 365 D_PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);
kotakku 0:b1ce54272580 366 Notify(PSTR("\r\nAttributes:\t"), 0x80);
kotakku 0:b1ce54272580 367 D_PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);
kotakku 0:b1ce54272580 368 Notify(PSTR("\r\nMaxPktSize:\t"), 0x80);
kotakku 0:b1ce54272580 369 D_PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);
kotakku 0:b1ce54272580 370 Notify(PSTR("\r\nPoll Intrv:\t"), 0x80);
kotakku 0:b1ce54272580 371 D_PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);
kotakku 0:b1ce54272580 372 #endif
kotakku 0:b1ce54272580 373 }
kotakku 0:b1ce54272580 374
kotakku 0:b1ce54272580 375 /* Performs a cleanup after failed Init() attempt */
kotakku 0:b1ce54272580 376 uint8_t BTD::Release() {
kotakku 0:b1ce54272580 377 Initialize(); // Set all variables, endpoint structs etc. to default values
kotakku 0:b1ce54272580 378 pUsb->GetAddressPool().FreeAddress(bAddress);
kotakku 0:b1ce54272580 379 return 0;
kotakku 0:b1ce54272580 380 }
kotakku 0:b1ce54272580 381
kotakku 0:b1ce54272580 382 uint8_t BTD::Poll() {
kotakku 0:b1ce54272580 383 if(!bPollEnable)
kotakku 0:b1ce54272580 384 return 0;
kotakku 0:b1ce54272580 385 if((int32_t)((uint32_t)millis() - qNextPollTime) >= 0L) { // Don't poll if shorter than polling interval
kotakku 0:b1ce54272580 386 qNextPollTime = (uint32_t)millis() + pollInterval; // Set new poll time
kotakku 0:b1ce54272580 387 HCI_event_task(); // Poll the HCI event pipe
kotakku 0:b1ce54272580 388 HCI_task(); // HCI state machine
kotakku 0:b1ce54272580 389 ACL_event_task(); // Poll the ACL input pipe too
kotakku 0:b1ce54272580 390 }
kotakku 0:b1ce54272580 391 return 0;
kotakku 0:b1ce54272580 392 }
kotakku 0:b1ce54272580 393
kotakku 0:b1ce54272580 394 void BTD::disconnect() {
kotakku 0:b1ce54272580 395 for(uint8_t i = 0; i < BTD_NUM_SERVICES; i++)
kotakku 0:b1ce54272580 396 if(btService[i])
kotakku 0:b1ce54272580 397 btService[i]->disconnect();
kotakku 0:b1ce54272580 398 };
kotakku 0:b1ce54272580 399
kotakku 0:b1ce54272580 400 void BTD::HCI_event_task() {
kotakku 0:b1ce54272580 401 uint16_t length = BULK_MAXPKTSIZE; // Request more than 16 bytes anyway, the inTransfer routine will take care of this
kotakku 0:b1ce54272580 402 uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[ BTD_EVENT_PIPE ].epAddr, &length, hcibuf, pollInterval); // Input on endpoint 1
kotakku 0:b1ce54272580 403
kotakku 0:b1ce54272580 404 if(!rcode || rcode == hrNAK) { // Check for errors
kotakku 0:b1ce54272580 405 switch(hcibuf[0]) { // Switch on event type
kotakku 0:b1ce54272580 406 case EV_COMMAND_COMPLETE:
kotakku 0:b1ce54272580 407 if(!hcibuf[5]) { // Check if command succeeded
kotakku 0:b1ce54272580 408 hci_set_flag(HCI_FLAG_CMD_COMPLETE); // Set command complete flag
kotakku 0:b1ce54272580 409 if((hcibuf[3] == 0x01) && (hcibuf[4] == 0x10)) { // Parameters from read local version information
kotakku 0:b1ce54272580 410 hci_version = hcibuf[6]; // Used to check if it supports 2.0+EDR - see http://www.bluetooth.org/Technical/AssignedNumbers/hci.htm
kotakku 0:b1ce54272580 411 hci_set_flag(HCI_FLAG_READ_VERSION);
kotakku 0:b1ce54272580 412 } else if((hcibuf[3] == 0x09) && (hcibuf[4] == 0x10)) { // Parameters from read local bluetooth address
kotakku 0:b1ce54272580 413 for(uint8_t i = 0; i < 6; i++)
kotakku 0:b1ce54272580 414 my_bdaddr[i] = hcibuf[6 + i];
kotakku 0:b1ce54272580 415 hci_set_flag(HCI_FLAG_READ_BDADDR);
kotakku 0:b1ce54272580 416 }
kotakku 0:b1ce54272580 417 }
kotakku 0:b1ce54272580 418 break;
kotakku 0:b1ce54272580 419
kotakku 0:b1ce54272580 420 case EV_COMMAND_STATUS:
kotakku 0:b1ce54272580 421 if(hcibuf[2]) { // Show status on serial if not OK
kotakku 0:b1ce54272580 422 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 423 Notify(PSTR("\r\nHCI Command Failed: "), 0x80);
kotakku 0:b1ce54272580 424 D_PrintHex<uint8_t > (hcibuf[2], 0x80);
kotakku 0:b1ce54272580 425 #endif
kotakku 0:b1ce54272580 426 }
kotakku 0:b1ce54272580 427 break;
kotakku 0:b1ce54272580 428
kotakku 0:b1ce54272580 429 case EV_INQUIRY_COMPLETE:
kotakku 0:b1ce54272580 430 if(inquiry_counter >= 5 && (pairWithWii || pairWithHIDDevice)) {
kotakku 0:b1ce54272580 431 inquiry_counter = 0;
kotakku 0:b1ce54272580 432 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 433 if(pairWithWii)
kotakku 0:b1ce54272580 434 Notify(PSTR("\r\nCouldn't find Wiimote"), 0x80);
kotakku 0:b1ce54272580 435 else
kotakku 0:b1ce54272580 436 Notify(PSTR("\r\nCouldn't find HID device"), 0x80);
kotakku 0:b1ce54272580 437 #endif
kotakku 0:b1ce54272580 438 connectToWii = false;
kotakku 0:b1ce54272580 439 pairWithWii = false;
kotakku 0:b1ce54272580 440 connectToHIDDevice = false;
kotakku 0:b1ce54272580 441 pairWithHIDDevice = false;
kotakku 0:b1ce54272580 442 hci_state = HCI_SCANNING_STATE;
kotakku 0:b1ce54272580 443 }
kotakku 0:b1ce54272580 444 inquiry_counter++;
kotakku 0:b1ce54272580 445 break;
kotakku 0:b1ce54272580 446
kotakku 0:b1ce54272580 447 case EV_INQUIRY_RESULT:
kotakku 0:b1ce54272580 448 if(hcibuf[2]) { // Check that there is more than zero responses
kotakku 0:b1ce54272580 449 #ifdef EXTRADEBUG
kotakku 0:b1ce54272580 450 Notify(PSTR("\r\nNumber of responses: "), 0x80);
kotakku 0:b1ce54272580 451 Notify(hcibuf[2], 0x80);
kotakku 0:b1ce54272580 452 #endif
kotakku 0:b1ce54272580 453 for(uint8_t i = 0; i < hcibuf[2]; i++) {
kotakku 0:b1ce54272580 454 uint8_t offset = 8 * hcibuf[2] + 3 * i;
kotakku 0:b1ce54272580 455
kotakku 0:b1ce54272580 456 for(uint8_t j = 0; j < 3; j++)
kotakku 0:b1ce54272580 457 classOfDevice[j] = hcibuf[j + 4 + offset];
kotakku 0:b1ce54272580 458
kotakku 0:b1ce54272580 459 #ifdef EXTRADEBUG
kotakku 0:b1ce54272580 460 Notify(PSTR("\r\nClass of device: "), 0x80);
kotakku 0:b1ce54272580 461 D_PrintHex<uint8_t > (classOfDevice[2], 0x80);
kotakku 0:b1ce54272580 462 Notify(PSTR(" "), 0x80);
kotakku 0:b1ce54272580 463 D_PrintHex<uint8_t > (classOfDevice[1], 0x80);
kotakku 0:b1ce54272580 464 Notify(PSTR(" "), 0x80);
kotakku 0:b1ce54272580 465 D_PrintHex<uint8_t > (classOfDevice[0], 0x80);
kotakku 0:b1ce54272580 466 #endif
kotakku 0:b1ce54272580 467
kotakku 0:b1ce54272580 468 if(pairWithWii && classOfDevice[2] == 0x00 && (classOfDevice[1] & 0x05) && (classOfDevice[0] & 0x0C)) { // See http://wiibrew.org/wiki/Wiimote#SDP_information
kotakku 0:b1ce54272580 469 checkRemoteName = true; // Check remote name to distinguish between the different controllers
kotakku 0:b1ce54272580 470
kotakku 0:b1ce54272580 471 for(uint8_t j = 0; j < 6; j++)
kotakku 0:b1ce54272580 472 disc_bdaddr[j] = hcibuf[j + 3 + 6 * i];
kotakku 0:b1ce54272580 473
kotakku 0:b1ce54272580 474 hci_set_flag(HCI_FLAG_DEVICE_FOUND);
kotakku 0:b1ce54272580 475 break;
kotakku 0:b1ce54272580 476 } else if(pairWithHIDDevice && (classOfDevice[1] & 0x05) && (classOfDevice[0] & 0xC8)) { // Check if it is a mouse, keyboard or a gamepad - see: http://bluetooth-pentest.narod.ru/software/bluetooth_class_of_device-service_generator.html
kotakku 0:b1ce54272580 477 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 478 if(classOfDevice[0] & 0x80)
kotakku 0:b1ce54272580 479 Notify(PSTR("\r\nMouse found"), 0x80);
kotakku 0:b1ce54272580 480 if(classOfDevice[0] & 0x40)
kotakku 0:b1ce54272580 481 Notify(PSTR("\r\nKeyboard found"), 0x80);
kotakku 0:b1ce54272580 482 if(classOfDevice[0] & 0x08)
kotakku 0:b1ce54272580 483 Notify(PSTR("\r\nGamepad found"), 0x80);
kotakku 0:b1ce54272580 484 #endif
kotakku 0:b1ce54272580 485
kotakku 0:b1ce54272580 486 for(uint8_t j = 0; j < 6; j++)
kotakku 0:b1ce54272580 487 disc_bdaddr[j] = hcibuf[j + 3 + 6 * i];
kotakku 0:b1ce54272580 488
kotakku 0:b1ce54272580 489 hci_set_flag(HCI_FLAG_DEVICE_FOUND);
kotakku 0:b1ce54272580 490 break;
kotakku 0:b1ce54272580 491 }
kotakku 0:b1ce54272580 492 }
kotakku 0:b1ce54272580 493 }
kotakku 0:b1ce54272580 494 break;
kotakku 0:b1ce54272580 495
kotakku 0:b1ce54272580 496 case EV_CONNECT_COMPLETE:
kotakku 0:b1ce54272580 497 hci_set_flag(HCI_FLAG_CONNECT_EVENT);
kotakku 0:b1ce54272580 498 if(!hcibuf[2]) { // Check if connected OK
kotakku 0:b1ce54272580 499 #ifdef EXTRADEBUG
kotakku 0:b1ce54272580 500 Notify(PSTR("\r\nConnection established"), 0x80);
kotakku 0:b1ce54272580 501 #endif
kotakku 0:b1ce54272580 502 hci_handle = hcibuf[3] | ((hcibuf[4] & 0x0F) << 8); // Store the handle for the ACL connection
kotakku 0:b1ce54272580 503 hci_set_flag(HCI_FLAG_CONNECT_COMPLETE); // Set connection complete flag
kotakku 0:b1ce54272580 504 } else {
kotakku 0:b1ce54272580 505 hci_state = HCI_CHECK_DEVICE_SERVICE;
kotakku 0:b1ce54272580 506 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 507 Notify(PSTR("\r\nConnection Failed: "), 0x80);
kotakku 0:b1ce54272580 508 D_PrintHex<uint8_t > (hcibuf[2], 0x80);
kotakku 0:b1ce54272580 509 #endif
kotakku 0:b1ce54272580 510 }
kotakku 0:b1ce54272580 511 break;
kotakku 0:b1ce54272580 512
kotakku 0:b1ce54272580 513 case EV_DISCONNECT_COMPLETE:
kotakku 0:b1ce54272580 514 if(!hcibuf[2]) { // Check if disconnected OK
kotakku 0:b1ce54272580 515 hci_set_flag(HCI_FLAG_DISCONNECT_COMPLETE); // Set disconnect command complete flag
kotakku 0:b1ce54272580 516 hci_clear_flag(HCI_FLAG_CONNECT_COMPLETE); // Clear connection complete flag
kotakku 0:b1ce54272580 517 }
kotakku 0:b1ce54272580 518 break;
kotakku 0:b1ce54272580 519
kotakku 0:b1ce54272580 520 case EV_REMOTE_NAME_COMPLETE:
kotakku 0:b1ce54272580 521 if(!hcibuf[2]) { // Check if reading is OK
kotakku 0:b1ce54272580 522 for(uint8_t i = 0; i < min(sizeof (remote_name), sizeof (hcibuf) - 9); i++) {
kotakku 0:b1ce54272580 523 remote_name[i] = hcibuf[9 + i];
kotakku 0:b1ce54272580 524 if(remote_name[i] == '\0') // End of string
kotakku 0:b1ce54272580 525 break;
kotakku 0:b1ce54272580 526 }
kotakku 0:b1ce54272580 527 // TODO: Altid sæt '\0' i remote name!
kotakku 0:b1ce54272580 528 hci_set_flag(HCI_FLAG_REMOTE_NAME_COMPLETE);
kotakku 0:b1ce54272580 529 }
kotakku 0:b1ce54272580 530 break;
kotakku 0:b1ce54272580 531
kotakku 0:b1ce54272580 532 case EV_INCOMING_CONNECT:
kotakku 0:b1ce54272580 533 for(uint8_t i = 0; i < 6; i++)
kotakku 0:b1ce54272580 534 disc_bdaddr[i] = hcibuf[i + 2];
kotakku 0:b1ce54272580 535
kotakku 0:b1ce54272580 536 for(uint8_t i = 0; i < 3; i++)
kotakku 0:b1ce54272580 537 classOfDevice[i] = hcibuf[i + 8];
kotakku 0:b1ce54272580 538
kotakku 0:b1ce54272580 539 if((classOfDevice[1] & 0x05) && (classOfDevice[0] & 0xC8)) { // Check if it is a mouse, keyboard or a gamepad
kotakku 0:b1ce54272580 540 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 541 if(classOfDevice[0] & 0x80)
kotakku 0:b1ce54272580 542 Notify(PSTR("\r\nMouse is connecting"), 0x80);
kotakku 0:b1ce54272580 543 if(classOfDevice[0] & 0x40)
kotakku 0:b1ce54272580 544 Notify(PSTR("\r\nKeyboard is connecting"), 0x80);
kotakku 0:b1ce54272580 545 if(classOfDevice[0] & 0x08)
kotakku 0:b1ce54272580 546 Notify(PSTR("\r\nGamepad is connecting"), 0x80);
kotakku 0:b1ce54272580 547 #endif
kotakku 0:b1ce54272580 548 incomingHIDDevice = true;
kotakku 0:b1ce54272580 549 }
kotakku 0:b1ce54272580 550
kotakku 0:b1ce54272580 551 #ifdef EXTRADEBUG
kotakku 0:b1ce54272580 552 Notify(PSTR("\r\nClass of device: "), 0x80);
kotakku 0:b1ce54272580 553 D_PrintHex<uint8_t > (classOfDevice[2], 0x80);
kotakku 0:b1ce54272580 554 Notify(PSTR(" "), 0x80);
kotakku 0:b1ce54272580 555 D_PrintHex<uint8_t > (classOfDevice[1], 0x80);
kotakku 0:b1ce54272580 556 Notify(PSTR(" "), 0x80);
kotakku 0:b1ce54272580 557 D_PrintHex<uint8_t > (classOfDevice[0], 0x80);
kotakku 0:b1ce54272580 558 #endif
kotakku 0:b1ce54272580 559 hci_set_flag(HCI_FLAG_INCOMING_REQUEST);
kotakku 0:b1ce54272580 560 break;
kotakku 0:b1ce54272580 561
kotakku 0:b1ce54272580 562 case EV_PIN_CODE_REQUEST:
kotakku 0:b1ce54272580 563 if(pairWithWii) {
kotakku 0:b1ce54272580 564 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 565 Notify(PSTR("\r\nPairing with Wiimote"), 0x80);
kotakku 0:b1ce54272580 566 #endif
kotakku 0:b1ce54272580 567 hci_pin_code_request_reply();
kotakku 0:b1ce54272580 568 } else if(btdPin != NULL) {
kotakku 0:b1ce54272580 569 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 570 Notify(PSTR("\r\nBluetooth pin is set too: "), 0x80);
kotakku 0:b1ce54272580 571 NotifyStr(btdPin, 0x80);
kotakku 0:b1ce54272580 572 #endif
kotakku 0:b1ce54272580 573 hci_pin_code_request_reply();
kotakku 0:b1ce54272580 574 } else {
kotakku 0:b1ce54272580 575 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 576 Notify(PSTR("\r\nNo pin was set"), 0x80);
kotakku 0:b1ce54272580 577 #endif
kotakku 0:b1ce54272580 578 hci_pin_code_negative_request_reply();
kotakku 0:b1ce54272580 579 }
kotakku 0:b1ce54272580 580 break;
kotakku 0:b1ce54272580 581
kotakku 0:b1ce54272580 582 case EV_LINK_KEY_REQUEST:
kotakku 0:b1ce54272580 583 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 584 Notify(PSTR("\r\nReceived Key Request"), 0x80);
kotakku 0:b1ce54272580 585 #endif
kotakku 0:b1ce54272580 586 hci_link_key_request_negative_reply();
kotakku 0:b1ce54272580 587 break;
kotakku 0:b1ce54272580 588
kotakku 0:b1ce54272580 589 case EV_AUTHENTICATION_COMPLETE:
kotakku 0:b1ce54272580 590 if(!hcibuf[2]) { // Check if pairing was successful
kotakku 0:b1ce54272580 591 if(pairWithWii && !connectToWii) {
kotakku 0:b1ce54272580 592 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 593 Notify(PSTR("\r\nPairing successful with Wiimote"), 0x80);
kotakku 0:b1ce54272580 594 #endif
kotakku 0:b1ce54272580 595 connectToWii = true; // Used to indicate to the Wii service, that it should connect to this device
kotakku 0:b1ce54272580 596 } else if(pairWithHIDDevice && !connectToHIDDevice) {
kotakku 0:b1ce54272580 597 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 598 Notify(PSTR("\r\nPairing successful with HID device"), 0x80);
kotakku 0:b1ce54272580 599 #endif
kotakku 0:b1ce54272580 600 connectToHIDDevice = true; // Used to indicate to the BTHID service, that it should connect to this device
kotakku 0:b1ce54272580 601 }
kotakku 0:b1ce54272580 602 } else {
kotakku 0:b1ce54272580 603 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 604 Notify(PSTR("\r\nPairing Failed: "), 0x80);
kotakku 0:b1ce54272580 605 D_PrintHex<uint8_t > (hcibuf[2], 0x80);
kotakku 0:b1ce54272580 606 #endif
kotakku 0:b1ce54272580 607 hci_disconnect(hci_handle);
kotakku 0:b1ce54272580 608 hci_state = HCI_DISCONNECT_STATE;
kotakku 0:b1ce54272580 609 }
kotakku 0:b1ce54272580 610 break;
kotakku 0:b1ce54272580 611 /* We will just ignore the following events */
kotakku 0:b1ce54272580 612 case EV_NUM_COMPLETE_PKT:
kotakku 0:b1ce54272580 613 case EV_ROLE_CHANGED:
kotakku 0:b1ce54272580 614 case EV_PAGE_SCAN_REP_MODE:
kotakku 0:b1ce54272580 615 case EV_LOOPBACK_COMMAND:
kotakku 0:b1ce54272580 616 case EV_DATA_BUFFER_OVERFLOW:
kotakku 0:b1ce54272580 617 case EV_CHANGE_CONNECTION_LINK:
kotakku 0:b1ce54272580 618 case EV_MAX_SLOTS_CHANGE:
kotakku 0:b1ce54272580 619 case EV_QOS_SETUP_COMPLETE:
kotakku 0:b1ce54272580 620 case EV_LINK_KEY_NOTIFICATION:
kotakku 0:b1ce54272580 621 case EV_ENCRYPTION_CHANGE:
kotakku 0:b1ce54272580 622 case EV_READ_REMOTE_VERSION_INFORMATION_COMPLETE:
kotakku 0:b1ce54272580 623 break;
kotakku 0:b1ce54272580 624 #ifdef EXTRADEBUG
kotakku 0:b1ce54272580 625 default:
kotakku 0:b1ce54272580 626 if(hcibuf[0] != 0x00) {
kotakku 0:b1ce54272580 627 Notify(PSTR("\r\nUnmanaged HCI Event: "), 0x80);
kotakku 0:b1ce54272580 628 D_PrintHex<uint8_t > (hcibuf[0], 0x80);
kotakku 0:b1ce54272580 629 }
kotakku 0:b1ce54272580 630 break;
kotakku 0:b1ce54272580 631 #endif
kotakku 0:b1ce54272580 632 } // Switch
kotakku 0:b1ce54272580 633 }
kotakku 0:b1ce54272580 634 #ifdef EXTRADEBUG
kotakku 0:b1ce54272580 635 else {
kotakku 0:b1ce54272580 636 Notify(PSTR("\r\nHCI event error: "), 0x80);
kotakku 0:b1ce54272580 637 D_PrintHex<uint8_t > (rcode, 0x80);
kotakku 0:b1ce54272580 638 }
kotakku 0:b1ce54272580 639 #endif
kotakku 0:b1ce54272580 640 }
kotakku 0:b1ce54272580 641
kotakku 0:b1ce54272580 642 /* Poll Bluetooth and print result */
kotakku 0:b1ce54272580 643 void BTD::HCI_task() {
kotakku 0:b1ce54272580 644 switch(hci_state) {
kotakku 0:b1ce54272580 645 case HCI_INIT_STATE:
kotakku 0:b1ce54272580 646 hci_counter++;
kotakku 0:b1ce54272580 647 if(hci_counter > hci_num_reset_loops) { // wait until we have looped x times to clear any old events
kotakku 0:b1ce54272580 648 hci_reset();
kotakku 0:b1ce54272580 649 hci_state = HCI_RESET_STATE;
kotakku 0:b1ce54272580 650 hci_counter = 0;
kotakku 0:b1ce54272580 651 }
kotakku 0:b1ce54272580 652 break;
kotakku 0:b1ce54272580 653
kotakku 0:b1ce54272580 654 case HCI_RESET_STATE:
kotakku 0:b1ce54272580 655 hci_counter++;
kotakku 0:b1ce54272580 656 if(hci_check_flag(HCI_FLAG_CMD_COMPLETE)) {
kotakku 0:b1ce54272580 657 hci_counter = 0;
kotakku 0:b1ce54272580 658 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 659 Notify(PSTR("\r\nHCI Reset complete"), 0x80);
kotakku 0:b1ce54272580 660 #endif
kotakku 0:b1ce54272580 661 hci_state = HCI_CLASS_STATE;
kotakku 0:b1ce54272580 662 hci_write_class_of_device();
kotakku 0:b1ce54272580 663 } else if(hci_counter > hci_num_reset_loops) {
kotakku 0:b1ce54272580 664 hci_num_reset_loops *= 10;
kotakku 0:b1ce54272580 665 if(hci_num_reset_loops > 2000)
kotakku 0:b1ce54272580 666 hci_num_reset_loops = 2000;
kotakku 0:b1ce54272580 667 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 668 Notify(PSTR("\r\nNo response to HCI Reset"), 0x80);
kotakku 0:b1ce54272580 669 #endif
kotakku 0:b1ce54272580 670 hci_state = HCI_INIT_STATE;
kotakku 0:b1ce54272580 671 hci_counter = 0;
kotakku 0:b1ce54272580 672 }
kotakku 0:b1ce54272580 673 break;
kotakku 0:b1ce54272580 674
kotakku 0:b1ce54272580 675 case HCI_CLASS_STATE:
kotakku 0:b1ce54272580 676 if(hci_check_flag(HCI_FLAG_CMD_COMPLETE)) {
kotakku 0:b1ce54272580 677 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 678 Notify(PSTR("\r\nWrite class of device"), 0x80);
kotakku 0:b1ce54272580 679 #endif
kotakku 0:b1ce54272580 680 hci_state = HCI_BDADDR_STATE;
kotakku 0:b1ce54272580 681 hci_read_bdaddr();
kotakku 0:b1ce54272580 682 }
kotakku 0:b1ce54272580 683 break;
kotakku 0:b1ce54272580 684
kotakku 0:b1ce54272580 685 case HCI_BDADDR_STATE:
kotakku 0:b1ce54272580 686 if(hci_check_flag(HCI_FLAG_READ_BDADDR)) {
kotakku 0:b1ce54272580 687 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 688 Notify(PSTR("\r\nLocal Bluetooth Address: "), 0x80);
kotakku 0:b1ce54272580 689 for(int8_t i = 5; i > 0; i--) {
kotakku 0:b1ce54272580 690 D_PrintHex<uint8_t > (my_bdaddr[i], 0x80);
kotakku 0:b1ce54272580 691 Notify(PSTR(":"), 0x80);
kotakku 0:b1ce54272580 692 }
kotakku 0:b1ce54272580 693 D_PrintHex<uint8_t > (my_bdaddr[0], 0x80);
kotakku 0:b1ce54272580 694 #endif
kotakku 0:b1ce54272580 695 hci_read_local_version_information();
kotakku 0:b1ce54272580 696 hci_state = HCI_LOCAL_VERSION_STATE;
kotakku 0:b1ce54272580 697 }
kotakku 0:b1ce54272580 698 break;
kotakku 0:b1ce54272580 699
kotakku 0:b1ce54272580 700 case HCI_LOCAL_VERSION_STATE: // The local version is used by the PS3BT class
kotakku 0:b1ce54272580 701 if(hci_check_flag(HCI_FLAG_READ_VERSION)) {
kotakku 0:b1ce54272580 702 if(btdName != NULL) {
kotakku 0:b1ce54272580 703 hci_set_local_name(btdName);
kotakku 0:b1ce54272580 704 hci_state = HCI_SET_NAME_STATE;
kotakku 0:b1ce54272580 705 } else
kotakku 0:b1ce54272580 706 hci_state = HCI_CHECK_DEVICE_SERVICE;
kotakku 0:b1ce54272580 707 }
kotakku 0:b1ce54272580 708 break;
kotakku 0:b1ce54272580 709
kotakku 0:b1ce54272580 710 case HCI_SET_NAME_STATE:
kotakku 0:b1ce54272580 711 if(hci_check_flag(HCI_FLAG_CMD_COMPLETE)) {
kotakku 0:b1ce54272580 712 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 713 Notify(PSTR("\r\nThe name is set to: "), 0x80);
kotakku 0:b1ce54272580 714 NotifyStr(btdName, 0x80);
kotakku 0:b1ce54272580 715 #endif
kotakku 0:b1ce54272580 716 hci_state = HCI_CHECK_DEVICE_SERVICE;
kotakku 0:b1ce54272580 717 }
kotakku 0:b1ce54272580 718 break;
kotakku 0:b1ce54272580 719
kotakku 0:b1ce54272580 720 case HCI_CHECK_DEVICE_SERVICE:
kotakku 0:b1ce54272580 721 if(pairWithHIDDevice || pairWithWii) { // Check if it should try to connect to a Wiimote
kotakku 0:b1ce54272580 722 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 723 if(pairWithWii)
kotakku 0:b1ce54272580 724 Notify(PSTR("\r\nStarting inquiry\r\nPress 1 & 2 on the Wiimote\r\nOr press the SYNC button if you are using a Wii U Pro Controller or a Wii Balance Board"), 0x80);
kotakku 0:b1ce54272580 725 else
kotakku 0:b1ce54272580 726 Notify(PSTR("\r\nPlease enable discovery of your device"), 0x80);
kotakku 0:b1ce54272580 727 #endif
kotakku 0:b1ce54272580 728 hci_inquiry();
kotakku 0:b1ce54272580 729 hci_state = HCI_INQUIRY_STATE;
kotakku 0:b1ce54272580 730 } else
kotakku 0:b1ce54272580 731 hci_state = HCI_SCANNING_STATE; // Don't try to connect to a Wiimote
kotakku 0:b1ce54272580 732 break;
kotakku 0:b1ce54272580 733
kotakku 0:b1ce54272580 734 case HCI_INQUIRY_STATE:
kotakku 0:b1ce54272580 735 if(hci_check_flag(HCI_FLAG_DEVICE_FOUND)) {
kotakku 0:b1ce54272580 736 hci_inquiry_cancel(); // Stop inquiry
kotakku 0:b1ce54272580 737 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 738 if(pairWithWii)
kotakku 0:b1ce54272580 739 Notify(PSTR("\r\nWiimote found"), 0x80);
kotakku 0:b1ce54272580 740 else
kotakku 0:b1ce54272580 741 Notify(PSTR("\r\nHID device found"), 0x80);
kotakku 0:b1ce54272580 742
kotakku 0:b1ce54272580 743 Notify(PSTR("\r\nNow just create the instance like so:"), 0x80);
kotakku 0:b1ce54272580 744 if(pairWithWii)
kotakku 0:b1ce54272580 745 Notify(PSTR("\r\nWII Wii(&Btd);"), 0x80);
kotakku 0:b1ce54272580 746 else
kotakku 0:b1ce54272580 747 Notify(PSTR("\r\nBTHID bthid(&Btd);"), 0x80);
kotakku 0:b1ce54272580 748
kotakku 0:b1ce54272580 749 Notify(PSTR("\r\nAnd then press any button on the "), 0x80);
kotakku 0:b1ce54272580 750 if(pairWithWii)
kotakku 0:b1ce54272580 751 Notify(PSTR("Wiimote"), 0x80);
kotakku 0:b1ce54272580 752 else
kotakku 0:b1ce54272580 753 Notify(PSTR("device"), 0x80);
kotakku 0:b1ce54272580 754 #endif
kotakku 0:b1ce54272580 755 if(checkRemoteName) {
kotakku 0:b1ce54272580 756 hci_remote_name(); // We need to know the name to distinguish between the Wiimote, the new Wiimote with Motion Plus inside, a Wii U Pro Controller and a Wii Balance Board
kotakku 0:b1ce54272580 757 hci_state = HCI_REMOTE_NAME_STATE;
kotakku 0:b1ce54272580 758 } else
kotakku 0:b1ce54272580 759 hci_state = HCI_CONNECT_DEVICE_STATE;
kotakku 0:b1ce54272580 760 }
kotakku 0:b1ce54272580 761 break;
kotakku 0:b1ce54272580 762
kotakku 0:b1ce54272580 763 case HCI_CONNECT_DEVICE_STATE:
kotakku 0:b1ce54272580 764 if(hci_check_flag(HCI_FLAG_CMD_COMPLETE)) {
kotakku 0:b1ce54272580 765 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 766 if(pairWithWii)
kotakku 0:b1ce54272580 767 Notify(PSTR("\r\nConnecting to Wiimote"), 0x80);
kotakku 0:b1ce54272580 768 else
kotakku 0:b1ce54272580 769 Notify(PSTR("\r\nConnecting to HID device"), 0x80);
kotakku 0:b1ce54272580 770 #endif
kotakku 0:b1ce54272580 771 checkRemoteName = false;
kotakku 0:b1ce54272580 772 hci_connect();
kotakku 0:b1ce54272580 773 hci_state = HCI_CONNECTED_DEVICE_STATE;
kotakku 0:b1ce54272580 774 }
kotakku 0:b1ce54272580 775 break;
kotakku 0:b1ce54272580 776
kotakku 0:b1ce54272580 777 case HCI_CONNECTED_DEVICE_STATE:
kotakku 0:b1ce54272580 778 if(hci_check_flag(HCI_FLAG_CONNECT_EVENT)) {
kotakku 0:b1ce54272580 779 if(hci_check_flag(HCI_FLAG_CONNECT_COMPLETE)) {
kotakku 0:b1ce54272580 780 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 781 if(pairWithWii)
kotakku 0:b1ce54272580 782 Notify(PSTR("\r\nConnected to Wiimote"), 0x80);
kotakku 0:b1ce54272580 783 else
kotakku 0:b1ce54272580 784 Notify(PSTR("\r\nConnected to HID device"), 0x80);
kotakku 0:b1ce54272580 785 #endif
kotakku 0:b1ce54272580 786 hci_authentication_request(); // This will start the pairing with the Wiimote
kotakku 0:b1ce54272580 787 hci_state = HCI_SCANNING_STATE;
kotakku 0:b1ce54272580 788 } else {
kotakku 0:b1ce54272580 789 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 790 Notify(PSTR("\r\nTrying to connect one more time..."), 0x80);
kotakku 0:b1ce54272580 791 #endif
kotakku 0:b1ce54272580 792 hci_connect(); // Try to connect one more time
kotakku 0:b1ce54272580 793 }
kotakku 0:b1ce54272580 794 }
kotakku 0:b1ce54272580 795 break;
kotakku 0:b1ce54272580 796
kotakku 0:b1ce54272580 797 case HCI_SCANNING_STATE:
kotakku 0:b1ce54272580 798 if(!connectToWii && !pairWithWii && !connectToHIDDevice && !pairWithHIDDevice) {
kotakku 0:b1ce54272580 799 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 800 Notify(PSTR("\r\nWait For Incoming Connection Request"), 0x80);
kotakku 0:b1ce54272580 801 #endif
kotakku 0:b1ce54272580 802 hci_write_scan_enable();
kotakku 0:b1ce54272580 803 waitingForConnection = true;
kotakku 0:b1ce54272580 804 hci_state = HCI_CONNECT_IN_STATE;
kotakku 0:b1ce54272580 805 }
kotakku 0:b1ce54272580 806 break;
kotakku 0:b1ce54272580 807
kotakku 0:b1ce54272580 808 case HCI_CONNECT_IN_STATE:
kotakku 0:b1ce54272580 809 if(hci_check_flag(HCI_FLAG_INCOMING_REQUEST)) {
kotakku 0:b1ce54272580 810 waitingForConnection = false;
kotakku 0:b1ce54272580 811 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 812 Notify(PSTR("\r\nIncoming Connection Request"), 0x80);
kotakku 0:b1ce54272580 813 #endif
kotakku 0:b1ce54272580 814 hci_remote_name();
kotakku 0:b1ce54272580 815 hci_state = HCI_REMOTE_NAME_STATE;
kotakku 0:b1ce54272580 816 } else if(hci_check_flag(HCI_FLAG_DISCONNECT_COMPLETE))
kotakku 0:b1ce54272580 817 hci_state = HCI_DISCONNECT_STATE;
kotakku 0:b1ce54272580 818 break;
kotakku 0:b1ce54272580 819
kotakku 0:b1ce54272580 820 case HCI_REMOTE_NAME_STATE:
kotakku 0:b1ce54272580 821 if(hci_check_flag(HCI_FLAG_REMOTE_NAME_COMPLETE)) {
kotakku 0:b1ce54272580 822 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 823 Notify(PSTR("\r\nRemote Name: "), 0x80);
kotakku 0:b1ce54272580 824 for(uint8_t i = 0; i < strlen(remote_name); i++)
kotakku 0:b1ce54272580 825 Notifyc(remote_name[i], 0x80);
kotakku 0:b1ce54272580 826 #endif
kotakku 0:b1ce54272580 827 if(strncmp((const char*)remote_name, "Nintendo", 8) == 0) {
kotakku 0:b1ce54272580 828 incomingWii = true;
kotakku 0:b1ce54272580 829 motionPlusInside = false;
kotakku 0:b1ce54272580 830 wiiUProController = false;
kotakku 0:b1ce54272580 831 pairWiiUsingSync = false;
kotakku 0:b1ce54272580 832 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 833 Notify(PSTR("\r\nWiimote is connecting"), 0x80);
kotakku 0:b1ce54272580 834 #endif
kotakku 0:b1ce54272580 835 if(strncmp((const char*)remote_name, "Nintendo RVL-CNT-01-TR", 22) == 0) {
kotakku 0:b1ce54272580 836 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 837 Notify(PSTR(" with Motion Plus Inside"), 0x80);
kotakku 0:b1ce54272580 838 #endif
kotakku 0:b1ce54272580 839 motionPlusInside = true;
kotakku 0:b1ce54272580 840 } else if(strncmp((const char*)remote_name, "Nintendo RVL-CNT-01-UC", 22) == 0) {
kotakku 0:b1ce54272580 841 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 842 Notify(PSTR(" - Wii U Pro Controller"), 0x80);
kotakku 0:b1ce54272580 843 #endif
kotakku 0:b1ce54272580 844 wiiUProController = motionPlusInside = pairWiiUsingSync = true;
kotakku 0:b1ce54272580 845 } else if(strncmp((const char*)remote_name, "Nintendo RVL-WBC-01", 19) == 0) {
kotakku 0:b1ce54272580 846 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 847 Notify(PSTR(" - Wii Balance Board"), 0x80);
kotakku 0:b1ce54272580 848 #endif
kotakku 0:b1ce54272580 849 pairWiiUsingSync = true;
kotakku 0:b1ce54272580 850 }
kotakku 0:b1ce54272580 851 }
kotakku 0:b1ce54272580 852 if(classOfDevice[2] == 0 && classOfDevice[1] == 0x25 && classOfDevice[0] == 0x08 && strncmp((const char*)remote_name, "Wireless Controller", 19) == 0) {
kotakku 0:b1ce54272580 853 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 854 Notify(PSTR("\r\nPS4 controller is connecting"), 0x80);
kotakku 0:b1ce54272580 855 #endif
kotakku 0:b1ce54272580 856 incomingPS4 = true;
kotakku 0:b1ce54272580 857 }
kotakku 0:b1ce54272580 858 if(pairWithWii && checkRemoteName)
kotakku 0:b1ce54272580 859 hci_state = HCI_CONNECT_DEVICE_STATE;
kotakku 0:b1ce54272580 860 else {
kotakku 0:b1ce54272580 861 hci_accept_connection();
kotakku 0:b1ce54272580 862 hci_state = HCI_CONNECTED_STATE;
kotakku 0:b1ce54272580 863 }
kotakku 0:b1ce54272580 864 }
kotakku 0:b1ce54272580 865 break;
kotakku 0:b1ce54272580 866
kotakku 0:b1ce54272580 867 case HCI_CONNECTED_STATE:
kotakku 0:b1ce54272580 868 if(hci_check_flag(HCI_FLAG_CONNECT_COMPLETE)) {
kotakku 0:b1ce54272580 869 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 870 Notify(PSTR("\r\nConnected to Device: "), 0x80);
kotakku 0:b1ce54272580 871 for(int8_t i = 5; i > 0; i--) {
kotakku 0:b1ce54272580 872 D_PrintHex<uint8_t > (disc_bdaddr[i], 0x80);
kotakku 0:b1ce54272580 873 Notify(PSTR(":"), 0x80);
kotakku 0:b1ce54272580 874 }
kotakku 0:b1ce54272580 875 D_PrintHex<uint8_t > (disc_bdaddr[0], 0x80);
kotakku 0:b1ce54272580 876 #endif
kotakku 0:b1ce54272580 877 if(incomingPS4)
kotakku 0:b1ce54272580 878 connectToHIDDevice = true; // We should always connect to the PS4 controller
kotakku 0:b1ce54272580 879
kotakku 0:b1ce54272580 880 // Clear these flags for a new connection
kotakku 0:b1ce54272580 881 l2capConnectionClaimed = false;
kotakku 0:b1ce54272580 882 sdpConnectionClaimed = false;
kotakku 0:b1ce54272580 883 rfcommConnectionClaimed = false;
kotakku 0:b1ce54272580 884
kotakku 0:b1ce54272580 885 hci_event_flag = 0;
kotakku 0:b1ce54272580 886 hci_state = HCI_DONE_STATE;
kotakku 0:b1ce54272580 887 }
kotakku 0:b1ce54272580 888 break;
kotakku 0:b1ce54272580 889
kotakku 0:b1ce54272580 890 case HCI_DONE_STATE:
kotakku 0:b1ce54272580 891 hci_counter++;
kotakku 0:b1ce54272580 892 if(hci_counter > 1000) { // Wait until we have looped 1000 times to make sure that the L2CAP connection has been started
kotakku 0:b1ce54272580 893 hci_counter = 0;
kotakku 0:b1ce54272580 894 hci_state = HCI_SCANNING_STATE;
kotakku 0:b1ce54272580 895 }
kotakku 0:b1ce54272580 896 break;
kotakku 0:b1ce54272580 897
kotakku 0:b1ce54272580 898 case HCI_DISCONNECT_STATE:
kotakku 0:b1ce54272580 899 if(hci_check_flag(HCI_FLAG_DISCONNECT_COMPLETE)) {
kotakku 0:b1ce54272580 900 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 901 Notify(PSTR("\r\nHCI Disconnected from Device"), 0x80);
kotakku 0:b1ce54272580 902 #endif
kotakku 0:b1ce54272580 903 hci_event_flag = 0; // Clear all flags
kotakku 0:b1ce54272580 904
kotakku 0:b1ce54272580 905 // Reset all buffers
kotakku 0:b1ce54272580 906 memset(hcibuf, 0, BULK_MAXPKTSIZE);
kotakku 0:b1ce54272580 907 memset(l2capinbuf, 0, BULK_MAXPKTSIZE);
kotakku 0:b1ce54272580 908
kotakku 0:b1ce54272580 909 connectToWii = incomingWii = pairWithWii = false;
kotakku 0:b1ce54272580 910 connectToHIDDevice = incomingHIDDevice = pairWithHIDDevice = checkRemoteName = false;
kotakku 0:b1ce54272580 911 incomingPS4 = false;
kotakku 0:b1ce54272580 912
kotakku 0:b1ce54272580 913 hci_state = HCI_SCANNING_STATE;
kotakku 0:b1ce54272580 914 }
kotakku 0:b1ce54272580 915 break;
kotakku 0:b1ce54272580 916 default:
kotakku 0:b1ce54272580 917 break;
kotakku 0:b1ce54272580 918 }
kotakku 0:b1ce54272580 919 }
kotakku 0:b1ce54272580 920
kotakku 0:b1ce54272580 921 void BTD::ACL_event_task() {
kotakku 0:b1ce54272580 922 uint16_t length = BULK_MAXPKTSIZE;
kotakku 0:b1ce54272580 923 uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[ BTD_DATAIN_PIPE ].epAddr, &length, l2capinbuf, pollInterval); // Input on endpoint 2
kotakku 0:b1ce54272580 924
kotakku 0:b1ce54272580 925 if(!rcode) { // Check for errors
kotakku 0:b1ce54272580 926 if(length > 0) { // Check if any data was read
kotakku 0:b1ce54272580 927 for(uint8_t i = 0; i < BTD_NUM_SERVICES; i++) {
kotakku 0:b1ce54272580 928 if(btService[i])
kotakku 0:b1ce54272580 929 btService[i]->ACLData(l2capinbuf);
kotakku 0:b1ce54272580 930 }
kotakku 0:b1ce54272580 931 }
kotakku 0:b1ce54272580 932 }
kotakku 0:b1ce54272580 933 #ifdef EXTRADEBUG
kotakku 0:b1ce54272580 934 else if(rcode != hrNAK) {
kotakku 0:b1ce54272580 935 Notify(PSTR("\r\nACL data in error: "), 0x80);
kotakku 0:b1ce54272580 936 D_PrintHex<uint8_t > (rcode, 0x80);
kotakku 0:b1ce54272580 937 }
kotakku 0:b1ce54272580 938 #endif
kotakku 0:b1ce54272580 939 for(uint8_t i = 0; i < BTD_NUM_SERVICES; i++)
kotakku 0:b1ce54272580 940 if(btService[i])
kotakku 0:b1ce54272580 941 btService[i]->Run();
kotakku 0:b1ce54272580 942 }
kotakku 0:b1ce54272580 943
kotakku 0:b1ce54272580 944 /************************************************************/
kotakku 0:b1ce54272580 945 /* HCI Commands */
kotakku 0:b1ce54272580 946
kotakku 0:b1ce54272580 947 /************************************************************/
kotakku 0:b1ce54272580 948 void BTD::HCI_Command(uint8_t* data, uint16_t nbytes) {
kotakku 0:b1ce54272580 949 hci_clear_flag(HCI_FLAG_CMD_COMPLETE);
kotakku 0:b1ce54272580 950 pUsb->ctrlReq(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, bmREQ_HCI_OUT, 0x00, 0x00, 0x00, 0x00, nbytes, nbytes, data, NULL);
kotakku 0:b1ce54272580 951 }
kotakku 0:b1ce54272580 952
kotakku 0:b1ce54272580 953 void BTD::hci_reset() {
kotakku 0:b1ce54272580 954 hci_event_flag = 0; // Clear all the flags
kotakku 0:b1ce54272580 955 hcibuf[0] = 0x03; // HCI OCF = 3
kotakku 0:b1ce54272580 956 hcibuf[1] = 0x03 << 2; // HCI OGF = 3
kotakku 0:b1ce54272580 957 hcibuf[2] = 0x00;
kotakku 0:b1ce54272580 958
kotakku 0:b1ce54272580 959 HCI_Command(hcibuf, 3);
kotakku 0:b1ce54272580 960 }
kotakku 0:b1ce54272580 961
kotakku 0:b1ce54272580 962 void BTD::hci_write_scan_enable() {
kotakku 0:b1ce54272580 963 hci_clear_flag(HCI_FLAG_INCOMING_REQUEST);
kotakku 0:b1ce54272580 964 hcibuf[0] = 0x1A; // HCI OCF = 1A
kotakku 0:b1ce54272580 965 hcibuf[1] = 0x03 << 2; // HCI OGF = 3
kotakku 0:b1ce54272580 966 hcibuf[2] = 0x01; // parameter length = 1
kotakku 0:b1ce54272580 967 if(btdName != NULL)
kotakku 0:b1ce54272580 968 hcibuf[3] = 0x03; // Inquiry Scan enabled. Page Scan enabled.
kotakku 0:b1ce54272580 969 else
kotakku 0:b1ce54272580 970 hcibuf[3] = 0x02; // Inquiry Scan disabled. Page Scan enabled.
kotakku 0:b1ce54272580 971
kotakku 0:b1ce54272580 972 HCI_Command(hcibuf, 4);
kotakku 0:b1ce54272580 973 }
kotakku 0:b1ce54272580 974
kotakku 0:b1ce54272580 975 void BTD::hci_write_scan_disable() {
kotakku 0:b1ce54272580 976 hcibuf[0] = 0x1A; // HCI OCF = 1A
kotakku 0:b1ce54272580 977 hcibuf[1] = 0x03 << 2; // HCI OGF = 3
kotakku 0:b1ce54272580 978 hcibuf[2] = 0x01; // parameter length = 1
kotakku 0:b1ce54272580 979 hcibuf[3] = 0x00; // Inquiry Scan disabled. Page Scan disabled.
kotakku 0:b1ce54272580 980
kotakku 0:b1ce54272580 981 HCI_Command(hcibuf, 4);
kotakku 0:b1ce54272580 982 }
kotakku 0:b1ce54272580 983
kotakku 0:b1ce54272580 984 void BTD::hci_read_bdaddr() {
kotakku 0:b1ce54272580 985 hci_clear_flag(HCI_FLAG_READ_BDADDR);
kotakku 0:b1ce54272580 986 hcibuf[0] = 0x09; // HCI OCF = 9
kotakku 0:b1ce54272580 987 hcibuf[1] = 0x04 << 2; // HCI OGF = 4
kotakku 0:b1ce54272580 988 hcibuf[2] = 0x00;
kotakku 0:b1ce54272580 989
kotakku 0:b1ce54272580 990 HCI_Command(hcibuf, 3);
kotakku 0:b1ce54272580 991 }
kotakku 0:b1ce54272580 992
kotakku 0:b1ce54272580 993 void BTD::hci_read_local_version_information() {
kotakku 0:b1ce54272580 994 hci_clear_flag(HCI_FLAG_READ_VERSION);
kotakku 0:b1ce54272580 995 hcibuf[0] = 0x01; // HCI OCF = 1
kotakku 0:b1ce54272580 996 hcibuf[1] = 0x04 << 2; // HCI OGF = 4
kotakku 0:b1ce54272580 997 hcibuf[2] = 0x00;
kotakku 0:b1ce54272580 998
kotakku 0:b1ce54272580 999 HCI_Command(hcibuf, 3);
kotakku 0:b1ce54272580 1000 }
kotakku 0:b1ce54272580 1001
kotakku 0:b1ce54272580 1002 void BTD::hci_accept_connection() {
kotakku 0:b1ce54272580 1003 hci_clear_flag(HCI_FLAG_CONNECT_COMPLETE);
kotakku 0:b1ce54272580 1004 hcibuf[0] = 0x09; // HCI OCF = 9
kotakku 0:b1ce54272580 1005 hcibuf[1] = 0x01 << 2; // HCI OGF = 1
kotakku 0:b1ce54272580 1006 hcibuf[2] = 0x07; // parameter length 7
kotakku 0:b1ce54272580 1007 hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr
kotakku 0:b1ce54272580 1008 hcibuf[4] = disc_bdaddr[1];
kotakku 0:b1ce54272580 1009 hcibuf[5] = disc_bdaddr[2];
kotakku 0:b1ce54272580 1010 hcibuf[6] = disc_bdaddr[3];
kotakku 0:b1ce54272580 1011 hcibuf[7] = disc_bdaddr[4];
kotakku 0:b1ce54272580 1012 hcibuf[8] = disc_bdaddr[5];
kotakku 0:b1ce54272580 1013 hcibuf[9] = 0x00; // Switch role to master
kotakku 0:b1ce54272580 1014
kotakku 0:b1ce54272580 1015 HCI_Command(hcibuf, 10);
kotakku 0:b1ce54272580 1016 }
kotakku 0:b1ce54272580 1017
kotakku 0:b1ce54272580 1018 void BTD::hci_remote_name() {
kotakku 0:b1ce54272580 1019 hci_clear_flag(HCI_FLAG_REMOTE_NAME_COMPLETE);
kotakku 0:b1ce54272580 1020 hcibuf[0] = 0x19; // HCI OCF = 19
kotakku 0:b1ce54272580 1021 hcibuf[1] = 0x01 << 2; // HCI OGF = 1
kotakku 0:b1ce54272580 1022 hcibuf[2] = 0x0A; // parameter length = 10
kotakku 0:b1ce54272580 1023 hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr
kotakku 0:b1ce54272580 1024 hcibuf[4] = disc_bdaddr[1];
kotakku 0:b1ce54272580 1025 hcibuf[5] = disc_bdaddr[2];
kotakku 0:b1ce54272580 1026 hcibuf[6] = disc_bdaddr[3];
kotakku 0:b1ce54272580 1027 hcibuf[7] = disc_bdaddr[4];
kotakku 0:b1ce54272580 1028 hcibuf[8] = disc_bdaddr[5];
kotakku 0:b1ce54272580 1029 hcibuf[9] = 0x01; // Page Scan Repetition Mode
kotakku 0:b1ce54272580 1030 hcibuf[10] = 0x00; // Reserved
kotakku 0:b1ce54272580 1031 hcibuf[11] = 0x00; // Clock offset - low byte
kotakku 0:b1ce54272580 1032 hcibuf[12] = 0x00; // Clock offset - high byte
kotakku 0:b1ce54272580 1033
kotakku 0:b1ce54272580 1034 HCI_Command(hcibuf, 13);
kotakku 0:b1ce54272580 1035 }
kotakku 0:b1ce54272580 1036
kotakku 0:b1ce54272580 1037 void BTD::hci_set_local_name(const char* name) {
kotakku 0:b1ce54272580 1038 hcibuf[0] = 0x13; // HCI OCF = 13
kotakku 0:b1ce54272580 1039 hcibuf[1] = 0x03 << 2; // HCI OGF = 3
kotakku 0:b1ce54272580 1040 hcibuf[2] = strlen(name) + 1; // parameter length = the length of the string + end byte
kotakku 0:b1ce54272580 1041 uint8_t i;
kotakku 0:b1ce54272580 1042 for(i = 0; i < strlen(name); i++)
kotakku 0:b1ce54272580 1043 hcibuf[i + 3] = name[i];
kotakku 0:b1ce54272580 1044 hcibuf[i + 3] = 0x00; // End of string
kotakku 0:b1ce54272580 1045
kotakku 0:b1ce54272580 1046 HCI_Command(hcibuf, 4 + strlen(name));
kotakku 0:b1ce54272580 1047 }
kotakku 0:b1ce54272580 1048
kotakku 0:b1ce54272580 1049 void BTD::hci_inquiry() {
kotakku 0:b1ce54272580 1050 hci_clear_flag(HCI_FLAG_DEVICE_FOUND);
kotakku 0:b1ce54272580 1051 hcibuf[0] = 0x01;
kotakku 0:b1ce54272580 1052 hcibuf[1] = 0x01 << 2; // HCI OGF = 1
kotakku 0:b1ce54272580 1053 hcibuf[2] = 0x05; // Parameter Total Length = 5
kotakku 0:b1ce54272580 1054 hcibuf[3] = 0x33; // LAP: Genera/Unlimited Inquiry Access Code (GIAC = 0x9E8B33) - see https://www.bluetooth.org/Technical/AssignedNumbers/baseband.htm
kotakku 0:b1ce54272580 1055 hcibuf[4] = 0x8B;
kotakku 0:b1ce54272580 1056 hcibuf[5] = 0x9E;
kotakku 0:b1ce54272580 1057 hcibuf[6] = 0x30; // Inquiry time = 61.44 sec (maximum)
kotakku 0:b1ce54272580 1058 hcibuf[7] = 0x0A; // 10 number of responses
kotakku 0:b1ce54272580 1059
kotakku 0:b1ce54272580 1060 HCI_Command(hcibuf, 8);
kotakku 0:b1ce54272580 1061 }
kotakku 0:b1ce54272580 1062
kotakku 0:b1ce54272580 1063 void BTD::hci_inquiry_cancel() {
kotakku 0:b1ce54272580 1064 hcibuf[0] = 0x02;
kotakku 0:b1ce54272580 1065 hcibuf[1] = 0x01 << 2; // HCI OGF = 1
kotakku 0:b1ce54272580 1066 hcibuf[2] = 0x00; // Parameter Total Length = 0
kotakku 0:b1ce54272580 1067
kotakku 0:b1ce54272580 1068 HCI_Command(hcibuf, 3);
kotakku 0:b1ce54272580 1069 }
kotakku 0:b1ce54272580 1070
kotakku 0:b1ce54272580 1071 void BTD::hci_connect() {
kotakku 0:b1ce54272580 1072 hci_connect(disc_bdaddr); // Use last discovered device
kotakku 0:b1ce54272580 1073 }
kotakku 0:b1ce54272580 1074
kotakku 0:b1ce54272580 1075 void BTD::hci_connect(uint8_t *bdaddr) {
kotakku 0:b1ce54272580 1076 hci_clear_flag(HCI_FLAG_CONNECT_COMPLETE | HCI_FLAG_CONNECT_EVENT);
kotakku 0:b1ce54272580 1077 hcibuf[0] = 0x05;
kotakku 0:b1ce54272580 1078 hcibuf[1] = 0x01 << 2; // HCI OGF = 1
kotakku 0:b1ce54272580 1079 hcibuf[2] = 0x0D; // parameter Total Length = 13
kotakku 0:b1ce54272580 1080 hcibuf[3] = bdaddr[0]; // 6 octet bdaddr (LSB)
kotakku 0:b1ce54272580 1081 hcibuf[4] = bdaddr[1];
kotakku 0:b1ce54272580 1082 hcibuf[5] = bdaddr[2];
kotakku 0:b1ce54272580 1083 hcibuf[6] = bdaddr[3];
kotakku 0:b1ce54272580 1084 hcibuf[7] = bdaddr[4];
kotakku 0:b1ce54272580 1085 hcibuf[8] = bdaddr[5];
kotakku 0:b1ce54272580 1086 hcibuf[9] = 0x18; // DM1 or DH1 may be used
kotakku 0:b1ce54272580 1087 hcibuf[10] = 0xCC; // DM3, DH3, DM5, DH5 may be used
kotakku 0:b1ce54272580 1088 hcibuf[11] = 0x01; // Page repetition mode R1
kotakku 0:b1ce54272580 1089 hcibuf[12] = 0x00; // Reserved
kotakku 0:b1ce54272580 1090 hcibuf[13] = 0x00; // Clock offset
kotakku 0:b1ce54272580 1091 hcibuf[14] = 0x00; // Invalid clock offset
kotakku 0:b1ce54272580 1092 hcibuf[15] = 0x00; // Do not allow role switch
kotakku 0:b1ce54272580 1093
kotakku 0:b1ce54272580 1094 HCI_Command(hcibuf, 16);
kotakku 0:b1ce54272580 1095 }
kotakku 0:b1ce54272580 1096
kotakku 0:b1ce54272580 1097 void BTD::hci_pin_code_request_reply() {
kotakku 0:b1ce54272580 1098 hcibuf[0] = 0x0D; // HCI OCF = 0D
kotakku 0:b1ce54272580 1099 hcibuf[1] = 0x01 << 2; // HCI OGF = 1
kotakku 0:b1ce54272580 1100 hcibuf[2] = 0x17; // parameter length 23
kotakku 0:b1ce54272580 1101 hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr
kotakku 0:b1ce54272580 1102 hcibuf[4] = disc_bdaddr[1];
kotakku 0:b1ce54272580 1103 hcibuf[5] = disc_bdaddr[2];
kotakku 0:b1ce54272580 1104 hcibuf[6] = disc_bdaddr[3];
kotakku 0:b1ce54272580 1105 hcibuf[7] = disc_bdaddr[4];
kotakku 0:b1ce54272580 1106 hcibuf[8] = disc_bdaddr[5];
kotakku 0:b1ce54272580 1107 if(pairWithWii) {
kotakku 0:b1ce54272580 1108 hcibuf[9] = 6; // Pin length is the length of the Bluetooth address
kotakku 0:b1ce54272580 1109 if(pairWiiUsingSync) {
kotakku 0:b1ce54272580 1110 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 1111 Notify(PSTR("\r\nPairing with Wii controller via SYNC"), 0x80);
kotakku 0:b1ce54272580 1112 #endif
kotakku 0:b1ce54272580 1113 for(uint8_t i = 0; i < 6; i++)
kotakku 0:b1ce54272580 1114 hcibuf[10 + i] = my_bdaddr[i]; // The pin is the Bluetooth dongles Bluetooth address backwards
kotakku 0:b1ce54272580 1115 } else {
kotakku 0:b1ce54272580 1116 for(uint8_t i = 0; i < 6; i++)
kotakku 0:b1ce54272580 1117 hcibuf[10 + i] = disc_bdaddr[i]; // The pin is the Wiimote's Bluetooth address backwards
kotakku 0:b1ce54272580 1118 }
kotakku 0:b1ce54272580 1119 for(uint8_t i = 16; i < 26; i++)
kotakku 0:b1ce54272580 1120 hcibuf[i] = 0x00; // The rest should be 0
kotakku 0:b1ce54272580 1121 } else {
kotakku 0:b1ce54272580 1122 hcibuf[9] = strlen(btdPin); // Length of pin
kotakku 0:b1ce54272580 1123 uint8_t i;
kotakku 0:b1ce54272580 1124 for(i = 0; i < strlen(btdPin); i++) // The maximum size of the pin is 16
kotakku 0:b1ce54272580 1125 hcibuf[i + 10] = btdPin[i];
kotakku 0:b1ce54272580 1126 for(; i < 16; i++)
kotakku 0:b1ce54272580 1127 hcibuf[i + 10] = 0x00; // The rest should be 0
kotakku 0:b1ce54272580 1128 }
kotakku 0:b1ce54272580 1129
kotakku 0:b1ce54272580 1130 HCI_Command(hcibuf, 26);
kotakku 0:b1ce54272580 1131 }
kotakku 0:b1ce54272580 1132
kotakku 0:b1ce54272580 1133 void BTD::hci_pin_code_negative_request_reply() {
kotakku 0:b1ce54272580 1134 hcibuf[0] = 0x0E; // HCI OCF = 0E
kotakku 0:b1ce54272580 1135 hcibuf[1] = 0x01 << 2; // HCI OGF = 1
kotakku 0:b1ce54272580 1136 hcibuf[2] = 0x06; // parameter length 6
kotakku 0:b1ce54272580 1137 hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr
kotakku 0:b1ce54272580 1138 hcibuf[4] = disc_bdaddr[1];
kotakku 0:b1ce54272580 1139 hcibuf[5] = disc_bdaddr[2];
kotakku 0:b1ce54272580 1140 hcibuf[6] = disc_bdaddr[3];
kotakku 0:b1ce54272580 1141 hcibuf[7] = disc_bdaddr[4];
kotakku 0:b1ce54272580 1142 hcibuf[8] = disc_bdaddr[5];
kotakku 0:b1ce54272580 1143
kotakku 0:b1ce54272580 1144 HCI_Command(hcibuf, 9);
kotakku 0:b1ce54272580 1145 }
kotakku 0:b1ce54272580 1146
kotakku 0:b1ce54272580 1147 void BTD::hci_link_key_request_negative_reply() {
kotakku 0:b1ce54272580 1148 hcibuf[0] = 0x0C; // HCI OCF = 0C
kotakku 0:b1ce54272580 1149 hcibuf[1] = 0x01 << 2; // HCI OGF = 1
kotakku 0:b1ce54272580 1150 hcibuf[2] = 0x06; // parameter length 6
kotakku 0:b1ce54272580 1151 hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr
kotakku 0:b1ce54272580 1152 hcibuf[4] = disc_bdaddr[1];
kotakku 0:b1ce54272580 1153 hcibuf[5] = disc_bdaddr[2];
kotakku 0:b1ce54272580 1154 hcibuf[6] = disc_bdaddr[3];
kotakku 0:b1ce54272580 1155 hcibuf[7] = disc_bdaddr[4];
kotakku 0:b1ce54272580 1156 hcibuf[8] = disc_bdaddr[5];
kotakku 0:b1ce54272580 1157
kotakku 0:b1ce54272580 1158 HCI_Command(hcibuf, 9);
kotakku 0:b1ce54272580 1159 }
kotakku 0:b1ce54272580 1160
kotakku 0:b1ce54272580 1161 void BTD::hci_authentication_request() {
kotakku 0:b1ce54272580 1162 hcibuf[0] = 0x11; // HCI OCF = 11
kotakku 0:b1ce54272580 1163 hcibuf[1] = 0x01 << 2; // HCI OGF = 1
kotakku 0:b1ce54272580 1164 hcibuf[2] = 0x02; // parameter length = 2
kotakku 0:b1ce54272580 1165 hcibuf[3] = (uint8_t)(hci_handle & 0xFF); //connection handle - low byte
kotakku 0:b1ce54272580 1166 hcibuf[4] = (uint8_t)((hci_handle >> 8) & 0x0F); //connection handle - high byte
kotakku 0:b1ce54272580 1167
kotakku 0:b1ce54272580 1168 HCI_Command(hcibuf, 5);
kotakku 0:b1ce54272580 1169 }
kotakku 0:b1ce54272580 1170
kotakku 0:b1ce54272580 1171 void BTD::hci_disconnect(uint16_t handle) { // This is called by the different services
kotakku 0:b1ce54272580 1172 hci_clear_flag(HCI_FLAG_DISCONNECT_COMPLETE);
kotakku 0:b1ce54272580 1173 hcibuf[0] = 0x06; // HCI OCF = 6
kotakku 0:b1ce54272580 1174 hcibuf[1] = 0x01 << 2; // HCI OGF = 1
kotakku 0:b1ce54272580 1175 hcibuf[2] = 0x03; // parameter length = 3
kotakku 0:b1ce54272580 1176 hcibuf[3] = (uint8_t)(handle & 0xFF); //connection handle - low byte
kotakku 0:b1ce54272580 1177 hcibuf[4] = (uint8_t)((handle >> 8) & 0x0F); //connection handle - high byte
kotakku 0:b1ce54272580 1178 hcibuf[5] = 0x13; // reason
kotakku 0:b1ce54272580 1179
kotakku 0:b1ce54272580 1180 HCI_Command(hcibuf, 6);
kotakku 0:b1ce54272580 1181 }
kotakku 0:b1ce54272580 1182
kotakku 0:b1ce54272580 1183 void BTD::hci_write_class_of_device() { // See http://bluetooth-pentest.narod.ru/software/bluetooth_class_of_device-service_generator.html
kotakku 0:b1ce54272580 1184 hcibuf[0] = 0x24; // HCI OCF = 24
kotakku 0:b1ce54272580 1185 hcibuf[1] = 0x03 << 2; // HCI OGF = 3
kotakku 0:b1ce54272580 1186 hcibuf[2] = 0x03; // parameter length = 3
kotakku 0:b1ce54272580 1187 hcibuf[3] = 0x04; // Robot
kotakku 0:b1ce54272580 1188 hcibuf[4] = 0x08; // Toy
kotakku 0:b1ce54272580 1189 hcibuf[5] = 0x00;
kotakku 0:b1ce54272580 1190
kotakku 0:b1ce54272580 1191 HCI_Command(hcibuf, 6);
kotakku 0:b1ce54272580 1192 }
kotakku 0:b1ce54272580 1193 /*******************************************************************
kotakku 0:b1ce54272580 1194 * *
kotakku 0:b1ce54272580 1195 * HCI ACL Data Packet *
kotakku 0:b1ce54272580 1196 * *
kotakku 0:b1ce54272580 1197 * buf[0] buf[1] buf[2] buf[3]
kotakku 0:b1ce54272580 1198 * 0 4 8 11 12 16 24 31 MSB
kotakku 0:b1ce54272580 1199 * .-+-+-+-+-+-+-+-|-+-+-+-|-+-|-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-.
kotakku 0:b1ce54272580 1200 * | HCI Handle |PB |BC | Data Total Length | HCI ACL Data Packet
kotakku 0:b1ce54272580 1201 * .-+-+-+-+-+-+-+-|-+-+-+-|-+-|-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-.
kotakku 0:b1ce54272580 1202 *
kotakku 0:b1ce54272580 1203 * buf[4] buf[5] buf[6] buf[7]
kotakku 0:b1ce54272580 1204 * 0 8 16 31 MSB
kotakku 0:b1ce54272580 1205 * .-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-.
kotakku 0:b1ce54272580 1206 * | Length | Channel ID | Basic L2CAP header
kotakku 0:b1ce54272580 1207 * .-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-.
kotakku 0:b1ce54272580 1208 *
kotakku 0:b1ce54272580 1209 * buf[8] buf[9] buf[10] buf[11]
kotakku 0:b1ce54272580 1210 * 0 8 16 31 MSB
kotakku 0:b1ce54272580 1211 * .-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-.
kotakku 0:b1ce54272580 1212 * | Code | Identifier | Length | Control frame (C-frame)
kotakku 0:b1ce54272580 1213 * .-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-. (signaling packet format)
kotakku 0:b1ce54272580 1214 */
kotakku 0:b1ce54272580 1215 /************************************************************/
kotakku 0:b1ce54272580 1216 /* L2CAP Commands */
kotakku 0:b1ce54272580 1217
kotakku 0:b1ce54272580 1218 /************************************************************/
kotakku 0:b1ce54272580 1219 void BTD::L2CAP_Command(uint16_t handle, uint8_t* data, uint8_t nbytes, uint8_t channelLow, uint8_t channelHigh) {
kotakku 0:b1ce54272580 1220 uint8_t buf[8 + nbytes];
kotakku 0:b1ce54272580 1221 buf[0] = (uint8_t)(handle & 0xff); // HCI handle with PB,BC flag
kotakku 0:b1ce54272580 1222 buf[1] = (uint8_t)(((handle >> 8) & 0x0f) | 0x20);
kotakku 0:b1ce54272580 1223 buf[2] = (uint8_t)((4 + nbytes) & 0xff); // HCI ACL total data length
kotakku 0:b1ce54272580 1224 buf[3] = (uint8_t)((4 + nbytes) >> 8);
kotakku 0:b1ce54272580 1225 buf[4] = (uint8_t)(nbytes & 0xff); // L2CAP header: Length
kotakku 0:b1ce54272580 1226 buf[5] = (uint8_t)(nbytes >> 8);
kotakku 0:b1ce54272580 1227 buf[6] = channelLow;
kotakku 0:b1ce54272580 1228 buf[7] = channelHigh;
kotakku 0:b1ce54272580 1229
kotakku 0:b1ce54272580 1230 for(uint16_t i = 0; i < nbytes; i++) // L2CAP C-frame
kotakku 0:b1ce54272580 1231 buf[8 + i] = data[i];
kotakku 0:b1ce54272580 1232
kotakku 0:b1ce54272580 1233 uint8_t rcode = pUsb->outTransfer(bAddress, epInfo[ BTD_DATAOUT_PIPE ].epAddr, (8 + nbytes), buf);
kotakku 0:b1ce54272580 1234 if(rcode) {
kotakku 0:b1ce54272580 1235 delay(100); // This small delay prevents it from overflowing if it fails
kotakku 0:b1ce54272580 1236 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 1237 Notify(PSTR("\r\nError sending L2CAP message: 0x"), 0x80);
kotakku 0:b1ce54272580 1238 D_PrintHex<uint8_t > (rcode, 0x80);
kotakku 0:b1ce54272580 1239 Notify(PSTR(" - Channel ID: "), 0x80);
kotakku 0:b1ce54272580 1240 D_PrintHex<uint8_t > (channelHigh, 0x80);
kotakku 0:b1ce54272580 1241 Notify(PSTR(" "), 0x80);
kotakku 0:b1ce54272580 1242 D_PrintHex<uint8_t > (channelLow, 0x80);
kotakku 0:b1ce54272580 1243 #endif
kotakku 0:b1ce54272580 1244 }
kotakku 0:b1ce54272580 1245 }
kotakku 0:b1ce54272580 1246
kotakku 0:b1ce54272580 1247 void BTD::l2cap_connection_request(uint16_t handle, uint8_t rxid, uint8_t* scid, uint16_t psm) {
kotakku 0:b1ce54272580 1248 l2capoutbuf[0] = L2CAP_CMD_CONNECTION_REQUEST; // Code
kotakku 0:b1ce54272580 1249 l2capoutbuf[1] = rxid; // Identifier
kotakku 0:b1ce54272580 1250 l2capoutbuf[2] = 0x04; // Length
kotakku 0:b1ce54272580 1251 l2capoutbuf[3] = 0x00;
kotakku 0:b1ce54272580 1252 l2capoutbuf[4] = (uint8_t)(psm & 0xff); // PSM
kotakku 0:b1ce54272580 1253 l2capoutbuf[5] = (uint8_t)(psm >> 8);
kotakku 0:b1ce54272580 1254 l2capoutbuf[6] = scid[0]; // Source CID
kotakku 0:b1ce54272580 1255 l2capoutbuf[7] = scid[1];
kotakku 0:b1ce54272580 1256
kotakku 0:b1ce54272580 1257 L2CAP_Command(handle, l2capoutbuf, 8);
kotakku 0:b1ce54272580 1258 }
kotakku 0:b1ce54272580 1259
kotakku 0:b1ce54272580 1260 void BTD::l2cap_connection_response(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid, uint8_t result) {
kotakku 0:b1ce54272580 1261 l2capoutbuf[0] = L2CAP_CMD_CONNECTION_RESPONSE; // Code
kotakku 0:b1ce54272580 1262 l2capoutbuf[1] = rxid; // Identifier
kotakku 0:b1ce54272580 1263 l2capoutbuf[2] = 0x08; // Length
kotakku 0:b1ce54272580 1264 l2capoutbuf[3] = 0x00;
kotakku 0:b1ce54272580 1265 l2capoutbuf[4] = dcid[0]; // Destination CID
kotakku 0:b1ce54272580 1266 l2capoutbuf[5] = dcid[1];
kotakku 0:b1ce54272580 1267 l2capoutbuf[6] = scid[0]; // Source CID
kotakku 0:b1ce54272580 1268 l2capoutbuf[7] = scid[1];
kotakku 0:b1ce54272580 1269 l2capoutbuf[8] = result; // Result: Pending or Success
kotakku 0:b1ce54272580 1270 l2capoutbuf[9] = 0x00;
kotakku 0:b1ce54272580 1271 l2capoutbuf[10] = 0x00; // No further information
kotakku 0:b1ce54272580 1272 l2capoutbuf[11] = 0x00;
kotakku 0:b1ce54272580 1273
kotakku 0:b1ce54272580 1274 L2CAP_Command(handle, l2capoutbuf, 12);
kotakku 0:b1ce54272580 1275 }
kotakku 0:b1ce54272580 1276
kotakku 0:b1ce54272580 1277 void BTD::l2cap_config_request(uint16_t handle, uint8_t rxid, uint8_t* dcid) {
kotakku 0:b1ce54272580 1278 l2capoutbuf[0] = L2CAP_CMD_CONFIG_REQUEST; // Code
kotakku 0:b1ce54272580 1279 l2capoutbuf[1] = rxid; // Identifier
kotakku 0:b1ce54272580 1280 l2capoutbuf[2] = 0x08; // Length
kotakku 0:b1ce54272580 1281 l2capoutbuf[3] = 0x00;
kotakku 0:b1ce54272580 1282 l2capoutbuf[4] = dcid[0]; // Destination CID
kotakku 0:b1ce54272580 1283 l2capoutbuf[5] = dcid[1];
kotakku 0:b1ce54272580 1284 l2capoutbuf[6] = 0x00; // Flags
kotakku 0:b1ce54272580 1285 l2capoutbuf[7] = 0x00;
kotakku 0:b1ce54272580 1286 l2capoutbuf[8] = 0x01; // Config Opt: type = MTU (Maximum Transmission Unit) - Hint
kotakku 0:b1ce54272580 1287 l2capoutbuf[9] = 0x02; // Config Opt: length
kotakku 0:b1ce54272580 1288 l2capoutbuf[10] = 0xFF; // MTU
kotakku 0:b1ce54272580 1289 l2capoutbuf[11] = 0xFF;
kotakku 0:b1ce54272580 1290
kotakku 0:b1ce54272580 1291 L2CAP_Command(handle, l2capoutbuf, 12);
kotakku 0:b1ce54272580 1292 }
kotakku 0:b1ce54272580 1293
kotakku 0:b1ce54272580 1294 void BTD::l2cap_config_response(uint16_t handle, uint8_t rxid, uint8_t* scid) {
kotakku 0:b1ce54272580 1295 l2capoutbuf[0] = L2CAP_CMD_CONFIG_RESPONSE; // Code
kotakku 0:b1ce54272580 1296 l2capoutbuf[1] = rxid; // Identifier
kotakku 0:b1ce54272580 1297 l2capoutbuf[2] = 0x0A; // Length
kotakku 0:b1ce54272580 1298 l2capoutbuf[3] = 0x00;
kotakku 0:b1ce54272580 1299 l2capoutbuf[4] = scid[0]; // Source CID
kotakku 0:b1ce54272580 1300 l2capoutbuf[5] = scid[1];
kotakku 0:b1ce54272580 1301 l2capoutbuf[6] = 0x00; // Flag
kotakku 0:b1ce54272580 1302 l2capoutbuf[7] = 0x00;
kotakku 0:b1ce54272580 1303 l2capoutbuf[8] = 0x00; // Result
kotakku 0:b1ce54272580 1304 l2capoutbuf[9] = 0x00;
kotakku 0:b1ce54272580 1305 l2capoutbuf[10] = 0x01; // Config
kotakku 0:b1ce54272580 1306 l2capoutbuf[11] = 0x02;
kotakku 0:b1ce54272580 1307 l2capoutbuf[12] = 0xA0;
kotakku 0:b1ce54272580 1308 l2capoutbuf[13] = 0x02;
kotakku 0:b1ce54272580 1309
kotakku 0:b1ce54272580 1310 L2CAP_Command(handle, l2capoutbuf, 14);
kotakku 0:b1ce54272580 1311 }
kotakku 0:b1ce54272580 1312
kotakku 0:b1ce54272580 1313 void BTD::l2cap_disconnection_request(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid) {
kotakku 0:b1ce54272580 1314 l2capoutbuf[0] = L2CAP_CMD_DISCONNECT_REQUEST; // Code
kotakku 0:b1ce54272580 1315 l2capoutbuf[1] = rxid; // Identifier
kotakku 0:b1ce54272580 1316 l2capoutbuf[2] = 0x04; // Length
kotakku 0:b1ce54272580 1317 l2capoutbuf[3] = 0x00;
kotakku 0:b1ce54272580 1318 l2capoutbuf[4] = dcid[0];
kotakku 0:b1ce54272580 1319 l2capoutbuf[5] = dcid[1];
kotakku 0:b1ce54272580 1320 l2capoutbuf[6] = scid[0];
kotakku 0:b1ce54272580 1321 l2capoutbuf[7] = scid[1];
kotakku 0:b1ce54272580 1322
kotakku 0:b1ce54272580 1323 L2CAP_Command(handle, l2capoutbuf, 8);
kotakku 0:b1ce54272580 1324 }
kotakku 0:b1ce54272580 1325
kotakku 0:b1ce54272580 1326 void BTD::l2cap_disconnection_response(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid) {
kotakku 0:b1ce54272580 1327 l2capoutbuf[0] = L2CAP_CMD_DISCONNECT_RESPONSE; // Code
kotakku 0:b1ce54272580 1328 l2capoutbuf[1] = rxid; // Identifier
kotakku 0:b1ce54272580 1329 l2capoutbuf[2] = 0x04; // Length
kotakku 0:b1ce54272580 1330 l2capoutbuf[3] = 0x00;
kotakku 0:b1ce54272580 1331 l2capoutbuf[4] = dcid[0];
kotakku 0:b1ce54272580 1332 l2capoutbuf[5] = dcid[1];
kotakku 0:b1ce54272580 1333 l2capoutbuf[6] = scid[0];
kotakku 0:b1ce54272580 1334 l2capoutbuf[7] = scid[1];
kotakku 0:b1ce54272580 1335
kotakku 0:b1ce54272580 1336 L2CAP_Command(handle, l2capoutbuf, 8);
kotakku 0:b1ce54272580 1337 }
kotakku 0:b1ce54272580 1338
kotakku 0:b1ce54272580 1339 void BTD::l2cap_information_response(uint16_t handle, uint8_t rxid, uint8_t infoTypeLow, uint8_t infoTypeHigh) {
kotakku 0:b1ce54272580 1340 l2capoutbuf[0] = L2CAP_CMD_INFORMATION_RESPONSE; // Code
kotakku 0:b1ce54272580 1341 l2capoutbuf[1] = rxid; // Identifier
kotakku 0:b1ce54272580 1342 l2capoutbuf[2] = 0x08; // Length
kotakku 0:b1ce54272580 1343 l2capoutbuf[3] = 0x00;
kotakku 0:b1ce54272580 1344 l2capoutbuf[4] = infoTypeLow;
kotakku 0:b1ce54272580 1345 l2capoutbuf[5] = infoTypeHigh;
kotakku 0:b1ce54272580 1346 l2capoutbuf[6] = 0x00; // Result = success
kotakku 0:b1ce54272580 1347 l2capoutbuf[7] = 0x00; // Result = success
kotakku 0:b1ce54272580 1348 l2capoutbuf[8] = 0x00;
kotakku 0:b1ce54272580 1349 l2capoutbuf[9] = 0x00;
kotakku 0:b1ce54272580 1350 l2capoutbuf[10] = 0x00;
kotakku 0:b1ce54272580 1351 l2capoutbuf[11] = 0x00;
kotakku 0:b1ce54272580 1352
kotakku 0:b1ce54272580 1353 L2CAP_Command(handle, l2capoutbuf, 12);
kotakku 0:b1ce54272580 1354 }
kotakku 0:b1ce54272580 1355
kotakku 0:b1ce54272580 1356 /* PS3 Commands - only set Bluetooth address is implemented in this library */
kotakku 0:b1ce54272580 1357 void BTD::setBdaddr(uint8_t* bdaddr) {
kotakku 0:b1ce54272580 1358 /* Set the internal Bluetooth address */
kotakku 0:b1ce54272580 1359 uint8_t buf[8];
kotakku 0:b1ce54272580 1360 buf[0] = 0x01;
kotakku 0:b1ce54272580 1361 buf[1] = 0x00;
kotakku 0:b1ce54272580 1362
kotakku 0:b1ce54272580 1363 for(uint8_t i = 0; i < 6; i++)
kotakku 0:b1ce54272580 1364 buf[i + 2] = bdaddr[5 - i]; // Copy into buffer, has to be written reversed, so it is MSB first
kotakku 0:b1ce54272580 1365
kotakku 0:b1ce54272580 1366 // bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0xF5), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data
kotakku 0:b1ce54272580 1367 pUsb->ctrlReq(bAddress, epInfo[BTD_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0xF5, 0x03, 0x00, 8, 8, buf, NULL);
kotakku 0:b1ce54272580 1368 }
kotakku 0:b1ce54272580 1369
kotakku 0:b1ce54272580 1370 void BTD::setMoveBdaddr(uint8_t* bdaddr) {
kotakku 0:b1ce54272580 1371 /* Set the internal Bluetooth address */
kotakku 0:b1ce54272580 1372 uint8_t buf[11];
kotakku 0:b1ce54272580 1373 buf[0] = 0x05;
kotakku 0:b1ce54272580 1374 buf[7] = 0x10;
kotakku 0:b1ce54272580 1375 buf[8] = 0x01;
kotakku 0:b1ce54272580 1376 buf[9] = 0x02;
kotakku 0:b1ce54272580 1377 buf[10] = 0x12;
kotakku 0:b1ce54272580 1378
kotakku 0:b1ce54272580 1379 for(uint8_t i = 0; i < 6; i++)
kotakku 0:b1ce54272580 1380 buf[i + 1] = bdaddr[i];
kotakku 0:b1ce54272580 1381
kotakku 0:b1ce54272580 1382 // bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x05), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data
kotakku 0:b1ce54272580 1383 pUsb->ctrlReq(bAddress, epInfo[BTD_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x05, 0x03, 0x00, 11, 11, buf, NULL);
kotakku 0:b1ce54272580 1384 }
kotakku 0:b1ce54272580 1385