19 #define DEBUG // Uncomment to print data for debugging
45 uint8_t
BTD::Init(uint8_t parent, uint8_t port,
bool lowspeed) {
57 Notify(PSTR(
"\r\nBTD Init"), 0x80);
62 Notify(PSTR(
"\r\nAddress in use"), 0x80);
72 Notify(PSTR(
"\r\nAddress not found"), 0x80);
79 Notify(PSTR(
"\r\nepinfo is null"), 0x80);
117 Notify(PSTR(
"\r\nsetAddr: "), 0x80);
119 PrintHex<uint8_t > (rcode, 0x80);
123 Notify(PSTR(
"\r\nAddr: "), 0x80);
124 PrintHex<uint8_t > (
bAddress, 0x80);
138 goto FailSetDevTblEntry;
146 goto FailSetConfDescr;
151 Notify(PSTR(
"\r\nDualshock 3 Controller Connected"), 0x80);
153 Notify(PSTR(
"\r\nNavigation Controller Connected"), 0x80);
159 Notify(PSTR(
"\r\nMotion Controller Connected"), 0x80);
164 Notify(PSTR(
"\r\nBluetooth Address was set to: "), 0x80);
165 for (int8_t i = 5; i > 0; i--) {
182 for (uint8_t i = 0; i < num_of_conf; i++) {
186 goto FailGetConfDescr;
192 goto FailUnknownDevice;
197 goto FailSetDevTblEntry;
204 goto FailSetConfDescr;
206 hci_num_reset_loops = 100;
213 Notify(PSTR(
"\r\nBluetooth Dongle Initialized"), 0x80);
241 Notify(PSTR(
"\r\nBTD Init Failed, error code: "), 0x80);
276 if (pollInterval < pep->bInterval)
283 Notify(PSTR(
"\r\nEndpoint descriptor:"), 0x80);
284 Notify(PSTR(
"\r\nLength:\t\t"), 0x80);
285 PrintHex<uint8_t > (ep_ptr->
bLength, 0x80);
286 Notify(PSTR(
"\r\nType:\t\t"), 0x80);
288 Notify(PSTR(
"\r\nAddress:\t"), 0x80);
290 Notify(PSTR(
"\r\nAttributes:\t"), 0x80);
292 Notify(PSTR(
"\r\nMaxPktSize:\t"), 0x80);
294 Notify(PSTR(
"\r\nPoll Intrv:\t"), 0x80);
295 PrintHex<uint8_t > (ep_ptr->
bInterval, 0x80);
303 btService[i]->
Reset();
324 void BTD::HCI_event_task() {
335 if ((hcibuf[3] == 0x01) && (hcibuf[4] == 0x10)) {
338 }
else if ((hcibuf[3] == 0x09) && (hcibuf[4] == 0x10)) {
339 for (uint8_t i = 0; i < 6; i++)
349 Notify(PSTR(
"\r\nHCI Command Failed: "), 0x80);
350 PrintHex<uint8_t > (hcibuf[2], 0x80);
352 PrintHex<uint8_t > (hcibuf[4], 0x80);
354 PrintHex<uint8_t > (hcibuf[5], 0x80);
360 if (inquiry_counter >= 5) {
363 Notify(PSTR(
"\r\nCouldn't find Wiimote"), 0x80);
375 Notify(PSTR(
"\r\nNumber of responses: "), 0x80);
378 for (uint8_t i = 0; i < hcibuf[2]; i++) {
379 if ((hcibuf[4 + 8 * hcibuf[2] + 3 * i] == 0x04 && hcibuf[5 + 8 * hcibuf[2] + 3 * i] == 0x25 && hcibuf[6 + 8 * hcibuf[2] + 3 * i] == 0x00) || (hcibuf[4 + 8 * hcibuf[2] + 3 * i] == 0x08 && hcibuf[5 + 8 * hcibuf[2] + 3 * i] == 0x05 && hcibuf[6 + 8 * hcibuf[2] + 3 * i] == 0x00)) {
380 if (hcibuf[4 + 8 * hcibuf[2] + 3 * i] == 0x08)
395 Notify(PSTR(
"\r\nClass of device: "), 0x80);
396 PrintHex<uint8_t > (hcibuf[6 + 8 * hcibuf[2] + 3 * i], 0x80);
398 PrintHex<uint8_t > (hcibuf[5 + 8 * hcibuf[2] + 3 * i], 0x80);
400 PrintHex<uint8_t > (hcibuf[4 + 8 * hcibuf[2] + 3 * i], 0x80);
410 hci_handle = hcibuf[3] | ((hcibuf[4] & 0x0F) << 8);
415 Notify(PSTR(
"\r\nConnection Failed"), 0x80);
430 for (uint8_t i = 0; i < min(
sizeof(
remote_name),
sizeof(hcibuf)-9); i++)
444 Notify(PSTR(
"\r\nClass of device: "), 0x80);
445 PrintHex<uint8_t > (hcibuf[10], 0x80);
447 PrintHex<uint8_t > (hcibuf[9], 0x80);
449 PrintHex<uint8_t > (hcibuf[8], 0x80);
457 Notify(PSTR(
"\r\nPairing with wiimote"), 0x80);
460 }
else if (
btdPin != NULL) {
462 Notify(PSTR(
"\r\nBluetooth pin is set too: "), 0x80);
468 Notify(PSTR(
"\r\nNo pin was set"), 0x80);
476 Notify(PSTR(
"\r\nReceived Key Request"), 0x80);
484 Notify(PSTR(
"\r\nPairing successful"), 0x80);
504 if (hcibuf[0] != 0x00) {
505 Notify(PSTR(
"\r\nUnmanaged HCI Event: "), 0x80);
506 PrintHex<uint8_t > (hcibuf[0], 0x80);
513 else if (rcode !=
hrNAK) {
514 Notify(PSTR(
"\r\nHCI event error: "), 0x80);
515 PrintHex<uint8_t > (rcode, 0x80);
522 void BTD::HCI_task() {
526 if (hci_counter > hci_num_reset_loops) {
538 Notify(PSTR(
"\r\nHCI Reset complete"), 0x80);
542 }
else if (hci_counter > hci_num_reset_loops) {
543 hci_num_reset_loops *= 10;
544 if (hci_num_reset_loops > 2000)
545 hci_num_reset_loops = 2000;
547 Notify(PSTR(
"\r\nNo response to HCI Reset"), 0x80);
557 Notify(PSTR(
"\r\nWrite class of device"), 0x80);
567 Notify(PSTR(
"\r\nLocal Bluetooth Address: "), 0x80);
568 for (int8_t i = 5; i > 0; i--) {
572 PrintHex<uint8_t > (my_bdaddr[0], 0x80);
592 Notify(PSTR(
"\r\nThe name is set to: "), 0x80);
602 Notify(PSTR(
"\r\nStarting inquiry\r\nPress 1 & 2 on the Wiimote\r\nOr press sync if you are using a Wii U Pro Controller"), 0x80);
614 Notify(PSTR(
"\r\nWiimote found"), 0x80);
615 Notify(PSTR(
"\r\nNow just create the instance like so:"), 0x80);
616 Notify(PSTR(
"\r\nWII Wii(&Btd);"), 0x80);
617 Notify(PSTR(
"\r\nAnd then press any button on the Wiimote"), 0x80);
630 Notify(PSTR(
"\r\nConnecting to Wiimote"), 0x80);
641 Notify(PSTR(
"\r\nConnected to Wiimote"), 0x80);
647 Notify(PSTR(
"\r\nTrying to connect one more time..."), 0x80);
657 Notify(PSTR(
"\r\nWait For Incoming Connection Request"), 0x80);
669 Notify(PSTR(
"\r\nIncoming Connection Request"), 0x80);
680 Notify(PSTR(
"\r\nRemote Name: "), 0x80);
681 for (uint8_t i = 0; i < 30; i++) {
687 if (strncmp((
const char*)
remote_name,
"Nintendo", 8) == 0) {
690 Notify(PSTR(
"\r\nWiimote is connecting"), 0x80);
692 if (strncmp((
const char*)
remote_name,
"Nintendo RVL-CNT-01-TR", 22) == 0) {
694 Notify(PSTR(
" with Motion Plus Inside"), 0x80);
697 }
else if (strncmp((
const char*)
remote_name,
"Nintendo RVL-CNT-01-UC", 22) == 0) {
699 Notify(PSTR(
" - Wii U Pro Controller"), 0x80);
720 Notify(PSTR(
"\r\nConnected to Device: "), 0x80);
721 for (int8_t i = 5; i > 0; i--) {
725 PrintHex<uint8_t > (disc_bdaddr[0], 0x80);
739 if (hci_counter > 1000) {
748 Notify(PSTR(
"\r\nHCI Disconnected from Device"), 0x80);
766 void BTD::ACL_event_task() {
772 btService[i]->
ACLData(l2capinbuf);
775 else if (rcode !=
hrNAK) {
776 Notify(PSTR(
"\r\nACL data in error: "), 0x80);
777 PrintHex<uint8_t > (rcode, 0x80);
791 pUsb->
ctrlReq(
bAddress,
epInfo[
BTD_CONTROL_PIPE ].epAddr,
bmREQ_HCI_OUT, 0x00, 0x00, 0x00, 0x00, nbytes, nbytes, data, NULL);
797 hcibuf[1] = 0x03 << 2;
806 hcibuf[1] = 0x03 << 2;
818 hcibuf[1] = 0x03 << 2;
827 hcibuf[1] = 0x04 << 2;
835 hcibuf[1] = 0x04 << 2;
844 hcibuf[1] = 0x01 << 2;
860 hcibuf[1] = 0x01 << 2;
878 hcibuf[1] = 0x03 << 2;
879 hcibuf[2] = strlen(name) + 1;
881 for (i = 0; i < strlen(name); i++)
882 hcibuf[i + 3] = name[i];
883 hcibuf[i + 3] = 0x00;
891 hcibuf[1] = 0x01 << 2;
904 hcibuf[1] = 0x01 << 2;
913 hcibuf[1] = 0x01 << 2;
934 hcibuf[1] = 0x01 << 2;
946 Notify(PSTR(
"\r\nParing with Wii U Pro Controller"), 0x80);
948 for(uint8_t i = 0; i < 6; i++)
952 for(uint8_t i = 0; i < 6; i++)
955 for (uint8_t i = 16; i < 26; i++)
958 hcibuf[9] = strlen(
btdPin);
960 for (i = 0; i < strlen(
btdPin); i++)
961 hcibuf[i + 10] =
btdPin[i];
963 hcibuf[i + 10] = 0x00;
971 hcibuf[1] = 0x01 << 2;
985 hcibuf[1] = 0x01 << 2;
999 hcibuf[1] = 0x01 << 2;
1002 hcibuf[4] = (uint8_t)((
hci_handle >> 8) & 0x0F);
1010 hcibuf[1] = 0x01 << 2;
1012 hcibuf[3] = (uint8_t)(handle & 0xFF);
1013 hcibuf[4] = (uint8_t)((handle >> 8) & 0x0F);
1021 hcibuf[1] = 0x03 << 2;
1055 void BTD::L2CAP_Command(uint16_t handle, uint8_t* data, uint8_t nbytes, uint8_t channelLow, uint8_t channelHigh) {
1056 uint8_t buf[8 + nbytes];
1057 buf[0] = (uint8_t)(handle & 0xff);
1058 buf[1] = (uint8_t)(((handle >> 8) & 0x0f) | 0x20);
1059 buf[2] = (uint8_t)((4 + nbytes) & 0xff);
1060 buf[3] = (uint8_t)((4 + nbytes) >> 8);
1061 buf[4] = (uint8_t)(nbytes & 0xff);
1062 buf[5] = (uint8_t)(nbytes >> 8);
1063 buf[6] = channelLow;
1064 buf[7] = channelHigh;
1066 for (uint16_t i = 0; i < nbytes; i++)
1067 buf[8 + i] = data[i];
1073 Notify(PSTR(
"\r\nError sending L2CAP message: 0x"), 0x80);
1074 PrintHex<uint8_t > (rcode, 0x80);
1075 Notify(PSTR(
" - Channel ID: "), 0x80);
1076 PrintHex<uint8_t > (channelHigh, 0x80);
1078 PrintHex<uint8_t > (channelLow, 0x80);
1085 l2capoutbuf[1] = rxid;
1086 l2capoutbuf[2] = 0x04;
1087 l2capoutbuf[3] = 0x00;
1088 l2capoutbuf[4] = (uint8_t)(psm & 0xff);
1089 l2capoutbuf[5] = (uint8_t)(psm >> 8);
1090 l2capoutbuf[6] = scid[0];
1091 l2capoutbuf[7] = scid[1];
1098 l2capoutbuf[1] = rxid;
1099 l2capoutbuf[2] = 0x08;
1100 l2capoutbuf[3] = 0x00;
1101 l2capoutbuf[4] = dcid[0];
1102 l2capoutbuf[5] = dcid[1];
1103 l2capoutbuf[6] = scid[0];
1104 l2capoutbuf[7] = scid[1];
1105 l2capoutbuf[8] = result;
1106 l2capoutbuf[9] = 0x00;
1107 l2capoutbuf[10] = 0x00;
1108 l2capoutbuf[11] = 0x00;
1115 l2capoutbuf[1] = rxid;
1116 l2capoutbuf[2] = 0x08;
1117 l2capoutbuf[3] = 0x00;
1118 l2capoutbuf[4] = dcid[0];
1119 l2capoutbuf[5] = dcid[1];
1120 l2capoutbuf[6] = 0x00;
1121 l2capoutbuf[7] = 0x00;
1122 l2capoutbuf[8] = 0x01;
1123 l2capoutbuf[9] = 0x02;
1124 l2capoutbuf[10] = 0xFF;
1125 l2capoutbuf[11] = 0xFF;
1132 l2capoutbuf[1] = rxid;
1133 l2capoutbuf[2] = 0x0A;
1134 l2capoutbuf[3] = 0x00;
1135 l2capoutbuf[4] = scid[0];
1136 l2capoutbuf[5] = scid[1];
1137 l2capoutbuf[6] = 0x00;
1138 l2capoutbuf[7] = 0x00;
1139 l2capoutbuf[8] = 0x00;
1140 l2capoutbuf[9] = 0x00;
1141 l2capoutbuf[10] = 0x01;
1142 l2capoutbuf[11] = 0x02;
1143 l2capoutbuf[12] = 0xA0;
1144 l2capoutbuf[13] = 0x02;
1151 l2capoutbuf[1] = rxid;
1152 l2capoutbuf[2] = 0x04;
1153 l2capoutbuf[3] = 0x00;
1154 l2capoutbuf[4] = dcid[0];
1155 l2capoutbuf[5] = dcid[1];
1156 l2capoutbuf[6] = scid[0];
1157 l2capoutbuf[7] = scid[1];
1164 l2capoutbuf[1] = rxid;
1165 l2capoutbuf[2] = 0x04;
1166 l2capoutbuf[3] = 0x00;
1167 l2capoutbuf[4] = dcid[0];
1168 l2capoutbuf[5] = dcid[1];
1169 l2capoutbuf[6] = scid[0];
1170 l2capoutbuf[7] = scid[1];
1177 l2capoutbuf[1] = rxid;
1178 l2capoutbuf[2] = 0x08;
1179 l2capoutbuf[3] = 0x00;
1180 l2capoutbuf[4] = infoTypeLow;
1181 l2capoutbuf[5] = infoTypeHigh;
1182 l2capoutbuf[6] = 0x00;
1183 l2capoutbuf[7] = 0x00;
1184 l2capoutbuf[8] = 0x00;
1185 l2capoutbuf[9] = 0x00;
1186 l2capoutbuf[10] = 0x00;
1187 l2capoutbuf[11] = 0x00;
1193 void BTD::setBdaddr(uint8_t* bdaddr) {
1199 for (uint8_t i = 0; i < 6; i++)
1200 buf[i + 2] = bdaddr[5 - i];
1203 pUsb->
ctrlReq(
bAddress,
epInfo[
BTD_CONTROL_PIPE].epAddr,
bmREQ_HID_OUT,
HID_REQUEST_SET_REPORT, 0xF5, 0x03, 0x00, 8, 8, buf, NULL);
1206 void BTD::setMoveBdaddr(uint8_t* bdaddr) {
1215 for (uint8_t i = 0; i < 6; i++)
1216 buf[i + 1] = bdaddr[i];
1219 pUsb->
ctrlReq(
bAddress,
epInfo[
BTD_CONTROL_PIPE].epAddr,
bmREQ_HID_OUT,
HID_REQUEST_SET_REPORT, 0x05, 0x03, 0x00, 11, 11, buf, NULL);