File: btstack_hid.c

package info (click to toggle)
retroarch 1.22.2%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 80,716 kB
  • sloc: ansic: 1,275,794; cpp: 115,470; objc: 9,973; asm: 6,624; python: 4,071; makefile: 2,867; sh: 2,828; xml: 1,408; perl: 393; java: 298; javascript: 196
file content (1488 lines) | stat: -rw-r--r-- 47,657 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
/*  RetroArch - A frontend for libretro.
 *  Copyright (C) 2013-2014 - Jason Fetters
 *  Copyright (C) 2011-2017 - Daniel De Matteis
 *
 *  RetroArch is free software: you can redistribute it and/or modify it under the terms
 *  of the GNU General Public License as published by the Free Software Found-
 *  ation, either version 3 of the License, or (at your option) any later version.
 *
 *  RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 *  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 *  PURPOSE.  See the GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along with RetroArch.
 *  If not, see <http://www.gnu.org/licenses/>.
 */

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <string.h>
#include <sys/time.h>

#ifdef __APPLE__
#include <CoreFoundation/CFRunLoop.h>
#endif

#include <boolean.h>
#include <retro_miscellaneous.h>
#include <rthreads/rthreads.h>
#ifdef HAVE_DYLIB
#include <dynamic/dylib.h>
#endif
#include <string/stdstring.h>

#include "../input_defines.h"
#include "../input_driver.h"
#define BUILDING_BTDYNAMIC
#include "../connect/joypad_connection.h"

/* Length of a Bluetooth device address. */
#define BD_ADDR_LEN        6
/* The link key type. */
#define LINK_KEY_LEN       16
/* The device name type. */
#define DEVICE_NAME_LEN    248

/* Type definitions. */
typedef uint16_t hci_con_handle_t;
typedef uint8_t bd_addr_t[BD_ADDR_LEN];
typedef uint8_t link_key_t[LINK_KEY_LEN];
typedef uint8_t device_name_t[DEVICE_NAME_LEN+1];

/* Packet handler. */
typedef void (*btstack_packet_handler_t) (uint8_t packet_type,
    uint16_t channel, uint8_t *packet, uint16_t size);

/* Hardware state of Bluetooth controller  */
typedef enum
{
   HCI_POWER_OFF = 0,
   HCI_POWER_ON,
   HCI_POWER_SLEEP
} HCI_POWER_MODE;

/* State of BTstack */
typedef enum
{
   HCI_STATE_OFF = 0,
   HCI_STATE_INITIALIZING,
   HCI_STATE_WORKING,
   HCI_STATE_HALTING,
   HCI_STATE_SLEEPING,
   HCI_STATE_FALLING_ASLEEP
} HCI_STATE;

typedef enum
{
   RUN_LOOP_POSIX = 1,
   RUN_LOOP_COCOA,
   RUN_LOOP_EMBEDDED
} RUN_LOOP_TYPE;

/* compact HCI Command packet description */
typedef struct
{
   uint16_t    opcode;
   const char *format;
} hci_cmd_t;

typedef struct linked_item
{
   struct linked_item *next; /* <-- next element in list, or NULL */
   void *user_data;          /* <-- pointer to struct base */
} linked_item_t;

typedef linked_item_t *linked_list_t;

typedef struct data_source
{
   linked_item_t item;

   /* File descriptor to watch or 0. */
   int  fd;

   int  (*process)(struct data_source *ds);
} data_source_t;

typedef struct timer
{
   linked_item_t item;
   /* Next timeout. */
   struct timeval timeout;
#ifdef HAVE_TICK
   /* Timeout in system ticks. */
   uint32_t timeout;
#endif
   void  (*process)(struct timer *ts);
} timer_source_t;

/* btdynamic.h */

#ifndef BUILDING_BTDYNAMIC
#define BTDIMPORT extern
#else
#define BTDIMPORT
#endif

BTDIMPORT int (*bt_open_ptr)(void);
BTDIMPORT void (*bt_close_ptr)(void);
BTDIMPORT void (*bt_flip_addr_ptr)(bd_addr_t dest, bd_addr_t src);
BTDIMPORT char* (*bd_addr_to_str_ptr)(bd_addr_t addr);
BTDIMPORT btstack_packet_handler_t (*bt_register_packet_handler_ptr)
   (btstack_packet_handler_t handler);
BTDIMPORT int (*bt_send_cmd_ptr)(const hci_cmd_t *cmd, ...);
BTDIMPORT void (*bt_send_l2cap_ptr)(uint16_t local_cid,
      uint8_t *data, uint16_t len);
BTDIMPORT void (*run_loop_init_ptr)(RUN_LOOP_TYPE type);
BTDIMPORT void (*run_loop_execute_ptr)(void);

BTDIMPORT const hci_cmd_t* btstack_set_power_mode_ptr;
BTDIMPORT const hci_cmd_t* hci_delete_stored_link_key_ptr;
BTDIMPORT const hci_cmd_t* hci_disconnect_ptr;
BTDIMPORT const hci_cmd_t* hci_read_bd_addr_ptr;
BTDIMPORT const hci_cmd_t* hci_inquiry_ptr;
BTDIMPORT const hci_cmd_t* hci_inquiry_cancel_ptr;
BTDIMPORT const hci_cmd_t* hci_pin_code_request_reply_ptr;
BTDIMPORT const hci_cmd_t* hci_pin_code_request_negative_reply_ptr;
BTDIMPORT const hci_cmd_t* hci_remote_name_request_ptr;
BTDIMPORT const hci_cmd_t* hci_remote_name_request_cancel_ptr;
BTDIMPORT const hci_cmd_t* hci_write_authentication_enable_ptr;
BTDIMPORT const hci_cmd_t* hci_write_inquiry_mode_ptr;
BTDIMPORT const hci_cmd_t* l2cap_create_channel_ptr;
BTDIMPORT const hci_cmd_t* l2cap_register_service_ptr;
BTDIMPORT const hci_cmd_t* l2cap_accept_connection_ptr;
BTDIMPORT const hci_cmd_t* l2cap_decline_connection_ptr;

/* hci_cmds.h */

/**
 * packet types - used in BTstack and over the H4 UART interface
 */
#define HCI_COMMAND_DATA_PACKET                             0x01
#define HCI_ACL_DATA_PACKET                                 0x02
#define HCI_SCO_DATA_PACKET                                 0x03
#define HCI_EVENT_PACKET                                    0x04

/* extension for client/server communication */
#define DAEMON_EVENT_PACKET                                 0x05

/* L2CAP data */
#define L2CAP_DATA_PACKET                                   0x06

/* RFCOMM data */
#define RFCOMM_DATA_PACKET                                  0x07

/* Attribute protocol data */
#define ATT_DATA_PACKET                                     0x08

/* Security Manager protocol data */
#define SM_DATA_PACKET                                      0x09

/* debug log messages */
#define LOG_MESSAGE_PACKET                                  0xFC

/* Fixed PSM numbers */
#define PSM_SDP                                             0x01
#define PSM_RFCOMM                                          0x03
#define PSM_HID_CONTROL                                     0x11
#define PSM_HID_INTERRUPT                                   0x13

/* Events from host controller to host */
#define HCI_EVENT_INQUIRY_COMPLETE                          0x01
#define HCI_EVENT_INQUIRY_RESULT                            0x02
#define HCI_EVENT_CONNECTION_COMPLETE                       0x03
#define HCI_EVENT_CONNECTION_REQUEST                        0x04
#define HCI_EVENT_DISCONNECTION_COMPLETE                    0x05
#define HCI_EVENT_AUTHENTICATION_COMPLETE_EVENT             0x06
#define HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE              0x07
#define HCI_EVENT_ENCRYPTION_CHANGE                         0x08
#define HCI_EVENT_CHANGE_CONNECTION_LINK_KEY_COMPLETE       0x09
#define HCI_EVENT_MASTER_LINK_KEY_COMPLETE                  0x0A
#define HCI_EVENT_READ_REMOTE_SUPPORTED_FEATURES_COMPLETE   0x0B
#define HCI_EVENT_READ_REMOTE_VERSION_INFORMATION_COMPLETE  0x0C
#define HCI_EVENT_QOS_SETUP_COMPLETE                        0x0D
#define HCI_EVENT_COMMAND_COMPLETE                          0x0E
#define HCI_EVENT_COMMAND_STATUS                            0x0F
#define HCI_EVENT_HARDWARE_ERROR                            0x10
#define HCI_EVENT_FLUSH_OCCURED                             0x11
#define HCI_EVENT_ROLE_CHANGE                               0x12
#define HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS               0x13
#define HCI_EVENT_MODE_CHANGE_EVENT                         0x14
#define HCI_EVENT_RETURN_LINK_KEYS                          0x15
#define HCI_EVENT_PIN_CODE_REQUEST                          0x16
#define HCI_EVENT_LINK_KEY_REQUEST                          0x17
#define HCI_EVENT_LINK_KEY_NOTIFICATION                     0x18
#define HCI_EVENT_DATA_BUFFER_OVERFLOW                      0x1A
#define HCI_EVENT_MAX_SLOTS_CHANGED                         0x1B
#define HCI_EVENT_READ_CLOCK_OFFSET_COMPLETE                0x1C
#define HCI_EVENT_PACKET_TYPE_CHANGED                       0x1D
#define HCI_EVENT_INQUIRY_RESULT_WITH_RSSI                  0x22
#define HCI_EVENT_EXTENDED_INQUIRY_RESPONSE                 0x2F
#define HCI_EVENT_LE_META                                   0x3E
#define HCI_EVENT_VENDOR_SPECIFIC                           0xFF

#define HCI_SUBEVENT_LE_CONNECTION_COMPLETE                 0x01
#define HCI_SUBEVENT_LE_ADVERTISING_REPORT                  0x02
#define HCI_SUBEVENT_LE_CONNECTION_UPDATE_COMPLETE          0x03
#define HCI_SUBEVENT_LE_READ_REMOTE_USED_FEATURES_COMPLETE  0x04
#define HCI_SUBEVENT_LE_LONG_TERM_KEY_REQUEST               0x05

/* last used HCI_EVENT in 2.1 is 0x3d */

/* events 0x50-0x5f are used internally */

/* BTSTACK DAEMON EVENTS */

/* events from BTstack for application/client lib */
#define BTSTACK_EVENT_STATE                                 0x60

/* data: event(8), len(8), nr hci connections */
#define BTSTACK_EVENT_NR_CONNECTIONS_CHANGED                0x61

/* data: none */
#define BTSTACK_EVENT_POWERON_FAILED                        0x62

/* data: major (8), minor (8), revision(16) */
#define BTSTACK_EVENT_VERSION                               0x63

/* data: system bluetooth on/off (bool) */
#define BTSTACK_EVENT_SYSTEM_BLUETOOTH_ENABLED              0x64

/* data: event (8), len(8), status (8) == 0, address (48), name (1984 bits = 248 bytes) */
#define BTSTACK_EVENT_REMOTE_NAME_CACHED                    0x65

/* data: discoverable enabled (bool) */
#define BTSTACK_EVENT_DISCOVERABLE_ENABLED                  0x66

/* L2CAP EVENTS */

/* data: event (8), len(8), status (8), address(48), handle (16), psm (16), local_cid(16), remote_cid (16), local_mtu(16), remote_mtu(16)  */
#define L2CAP_EVENT_CHANNEL_OPENED                          0x70

/* data: event (8), len(8), channel (16) */
#define L2CAP_EVENT_CHANNEL_CLOSED                          0x71

/* data: event (8), len(8), address(48), handle (16), psm (16), local_cid(16), remote_cid (16)  */
#define L2CAP_EVENT_INCOMING_CONNECTION                     0x72

/* data: event(8), len(8), handle(16) */
#define L2CAP_EVENT_TIMEOUT_CHECK                           0x73

/* data: event(8), len(8), local_cid(16), credits(8) */
#define L2CAP_EVENT_CREDITS                                 0x74

/* data: event(8), len(8), status (8), psm (16) */
#define L2CAP_EVENT_SERVICE_REGISTERED                      0x75

/* RFCOMM EVENTS */

/* data: event(8), len(8), status (8), address (48), handle (16), server channel(8), rfcomm_cid(16), max frame size(16) */
#define RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE                  0x80

/* data: event(8), len(8), rfcomm_cid(16) */
#define RFCOMM_EVENT_CHANNEL_CLOSED                         0x81

/* data: event (8), len(8), address(48), channel (8), rfcomm_cid (16) */
#define RFCOMM_EVENT_INCOMING_CONNECTION                    0x82

/* data: event (8), len(8), rfcommid (16), ... */
#define RFCOMM_EVENT_REMOTE_LINE_STATUS                     0x83

/* data: event(8), len(8), rfcomm_cid(16), credits(8) */
#define RFCOMM_EVENT_CREDITS                                0x84

/* data: event(8), len(8), status (8), rfcomm server channel id (8)  */
#define RFCOMM_EVENT_SERVICE_REGISTERED                     0x85

/* data: event(8), len(8), status (8), rfcomm server channel id (8)  */
#define RFCOMM_EVENT_PERSISTENT_CHANNEL                     0x86

/* data: event(8), len(8), status(8), service_record_handle(32) */
#define SDP_SERVICE_REGISTERED                              0x90

/* last error code in 2.1 is 0x38 - we start with 0x50 for BTstack errors */

#define BTSTACK_CONNECTION_TO_BTDAEMON_FAILED               0x50
#define BTSTACK_ACTIVATION_FAILED_SYSTEM_BLUETOOTH          0x51
#define BTSTACK_ACTIVATION_POWERON_FAILED                   0x52
#define BTSTACK_ACTIVATION_FAILED_UNKNOWN                   0x53
#define BTSTACK_NOT_ACTIVATED                               0x54
#define BTSTACK_BUSY                                        0x55
#define BTSTACK_MEMORY_ALLOC_FAILED                         0x56
#define BTSTACK_ACL_BUFFERS_FULL                            0x57

/* L2CAP errors - enumeration by the command that created them */
#define L2CAP_COMMAND_REJECT_REASON_COMMAND_NOT_UNDERSTOOD  0x60
#define L2CAP_COMMAND_REJECT_REASON_SIGNALING_MTU_EXCEEDED  0x61
#define L2CAP_COMMAND_REJECT_REASON_INVALID_CID_IN_REQUEST  0x62

#define L2CAP_CONNECTION_RESPONSE_RESULT_SUCCESSFUL         0x63
#define L2CAP_CONNECTION_RESPONSE_RESULT_PENDING            0x64
#define L2CAP_CONNECTION_RESPONSE_RESULT_REFUSED_PSM        0x65
#define L2CAP_CONNECTION_RESPONSE_RESULT_REFUSED_SECURITY   0x66
#define L2CAP_CONNECTION_RESPONSE_RESULT_REFUSED_RESOURCES  0x65

#define L2CAP_CONFIG_RESPONSE_RESULT_SUCCESSFUL             0x66
#define L2CAP_CONFIG_RESPONSE_RESULT_UNACCEPTABLE_PARAMS    0x67
#define L2CAP_CONFIG_RESPONSE_RESULT_REJECTED               0x68
#define L2CAP_CONFIG_RESPONSE_RESULT_UNKNOWN_OPTIONS        0x69
#define L2CAP_SERVICE_ALREADY_REGISTERED                    0x6a

#define RFCOMM_MULTIPLEXER_STOPPED                          0x70
#define RFCOMM_CHANNEL_ALREADY_REGISTERED                   0x71
#define RFCOMM_NO_OUTGOING_CREDITS                          0x72

#define SDP_HANDLE_ALREADY_REGISTERED                       0x80

/* Default INQ Mode
 * 0x9E8B33: General/Unlimited Inquiry Access Code (GIAC)
 **/
#define HCI_INQUIRY_LAP                                     0x9E8B33L

/* HCI Commands - see hci_cmds.c for info on parameters */
extern const hci_cmd_t btstack_get_state;
extern const hci_cmd_t btstack_set_power_mode;
extern const hci_cmd_t btstack_set_acl_capture_mode;
extern const hci_cmd_t btstack_get_version;
extern const hci_cmd_t btstack_get_system_bluetooth_enabled;
extern const hci_cmd_t btstack_set_system_bluetooth_enabled;
extern const hci_cmd_t btstack_set_discoverable;
extern const hci_cmd_t btstack_set_bluetooth_enabled;    /* only used by btstack config */

extern const hci_cmd_t hci_accept_connection_request;
extern const hci_cmd_t hci_authentication_requested;
extern const hci_cmd_t hci_change_connection_link_key;
extern const hci_cmd_t hci_create_connection;
extern const hci_cmd_t hci_create_connection_cancel;
extern const hci_cmd_t hci_delete_stored_link_key;
extern const hci_cmd_t hci_disconnect;
extern const hci_cmd_t hci_host_buffer_size;
extern const hci_cmd_t hci_inquiry;
extern const hci_cmd_t hci_inquiry_cancel;
extern const hci_cmd_t hci_link_key_request_negative_reply;
extern const hci_cmd_t hci_link_key_request_reply;
extern const hci_cmd_t hci_pin_code_request_reply;
extern const hci_cmd_t hci_pin_code_request_negative_reply;
extern const hci_cmd_t hci_qos_setup;
extern const hci_cmd_t hci_read_bd_addr;
extern const hci_cmd_t hci_read_buffer_size;
extern const hci_cmd_t hci_read_le_host_supported;
extern const hci_cmd_t hci_read_link_policy_settings;
extern const hci_cmd_t hci_read_link_supervision_timeout;
extern const hci_cmd_t hci_read_local_supported_features;
extern const hci_cmd_t hci_read_num_broadcast_retransmissions;
extern const hci_cmd_t hci_reject_connection_request;
extern const hci_cmd_t hci_remote_name_request;
extern const hci_cmd_t hci_remote_name_request_cancel;
extern const hci_cmd_t hci_reset;
extern const hci_cmd_t hci_role_discovery;
extern const hci_cmd_t hci_set_event_mask;
extern const hci_cmd_t hci_set_connection_encryption;
extern const hci_cmd_t hci_sniff_mode;
extern const hci_cmd_t hci_switch_role_command;
extern const hci_cmd_t hci_write_authentication_enable;
extern const hci_cmd_t hci_write_class_of_device;
extern const hci_cmd_t hci_write_extended_inquiry_response;
extern const hci_cmd_t hci_write_inquiry_mode;
extern const hci_cmd_t hci_write_le_host_supported;
extern const hci_cmd_t hci_write_link_policy_settings;
extern const hci_cmd_t hci_write_link_supervision_timeout;
extern const hci_cmd_t hci_write_local_name;
extern const hci_cmd_t hci_write_num_broadcast_retransmissions;
extern const hci_cmd_t hci_write_page_timeout;
extern const hci_cmd_t hci_write_scan_enable;
extern const hci_cmd_t hci_write_simple_pairing_mode;

extern const hci_cmd_t hci_le_add_device_to_whitelist;
extern const hci_cmd_t hci_le_clear_white_list;
extern const hci_cmd_t hci_le_connection_update;
extern const hci_cmd_t hci_le_create_connection;
extern const hci_cmd_t hci_le_create_connection_cancel;
extern const hci_cmd_t hci_le_encrypt;
extern const hci_cmd_t hci_le_long_term_key_negative_reply;
extern const hci_cmd_t hci_le_long_term_key_request_reply;
extern const hci_cmd_t hci_le_rand;
extern const hci_cmd_t hci_le_read_advertising_channel_tx_power;
extern const hci_cmd_t hci_le_read_buffer_size ;
extern const hci_cmd_t hci_le_read_channel_map;
extern const hci_cmd_t hci_le_read_remote_used_features;
extern const hci_cmd_t hci_le_read_supported_features;
extern const hci_cmd_t hci_le_read_supported_states;
extern const hci_cmd_t hci_le_read_white_list_size;
extern const hci_cmd_t hci_le_receiver_test;
extern const hci_cmd_t hci_le_remove_device_from_whitelist;
extern const hci_cmd_t hci_le_set_advertise_enable;
extern const hci_cmd_t hci_le_set_advertising_data;
extern const hci_cmd_t hci_le_set_advertising_parameters;
extern const hci_cmd_t hci_le_set_event_mask;
extern const hci_cmd_t hci_le_set_host_channel_classification;
extern const hci_cmd_t hci_le_set_random_address;
extern const hci_cmd_t hci_le_set_scan_enable;
extern const hci_cmd_t hci_le_set_scan_parameters;
extern const hci_cmd_t hci_le_set_scan_response_data;
extern const hci_cmd_t hci_le_start_encryption;
extern const hci_cmd_t hci_le_test_end;
extern const hci_cmd_t hci_le_transmitter_test;

extern const hci_cmd_t l2cap_accept_connection;
extern const hci_cmd_t l2cap_create_channel;
extern const hci_cmd_t l2cap_create_channel_mtu;
extern const hci_cmd_t l2cap_decline_connection;
extern const hci_cmd_t l2cap_disconnect;
extern const hci_cmd_t l2cap_register_service;
extern const hci_cmd_t l2cap_unregister_service;

extern const hci_cmd_t sdp_register_service_record;
extern const hci_cmd_t sdp_unregister_service_record;

/* accept connection @param bd_addr(48), rfcomm_cid (16) */
extern const hci_cmd_t rfcomm_accept_connection;
/* create rfcomm channel: @param bd_addr(48), channel (8) */
extern const hci_cmd_t rfcomm_create_channel;
/* create rfcomm channel: @param bd_addr(48), channel (8), mtu (16), credits (8) */
extern const hci_cmd_t rfcomm_create_channel_with_initial_credits;
/* decline rfcomm disconnect,@param bd_addr(48), rfcomm cid (16), reason(8) */
extern const hci_cmd_t rfcomm_decline_connection;
/* disconnect rfcomm disconnect, @param rfcomm_cid(8), reason(8) */
extern const hci_cmd_t rfcomm_disconnect;
/* register rfcomm service: @param channel(8), mtu (16) */
extern const hci_cmd_t rfcomm_register_service;
/* register rfcomm service: @param channel(8), mtu (16), initial credits (8) */
extern const hci_cmd_t rfcomm_register_service_with_initial_credits;
/* unregister rfcomm service, @param service_channel(16) */
extern const hci_cmd_t rfcomm_unregister_service;
/* request persistent rfcomm channel for service name: serive name (char*)  */
extern const hci_cmd_t rfcomm_persistent_channel_for_service;

/* linked_list.h */

void linked_item_set_user(linked_item_t *item, void *user_data);

void * linked_item_get_user(linked_item_t *item);

int  linked_list_empty(linked_list_t * list);

void linked_list_add(linked_list_t * list, linked_item_t *item);

void linked_list_add_tail(linked_list_t * list, linked_item_t *item);

int  linked_list_remove(linked_list_t * list, linked_item_t *item);

linked_item_t * linked_list_get_last_item(linked_list_t * list);

void test_linked_list(void);

/* run_loop.h */

/* Set timer based on current time in milliseconds. */
void run_loop_set_timer(timer_source_t *a, uint32_t timeout_in_ms);

/* Set callback that will be executed when timer expires. */
void run_loop_set_timer_handler(timer_source_t *ts,
      void (*process)(timer_source_t *_ts));

/* Add timer source. */
void run_loop_add_timer(timer_source_t *timer);

/* Remove timer source. */
int  run_loop_remove_timer(timer_source_t *timer);

/* Init must be called before any other run_loop call.
 * Use RUN_LOOP_EMBEDDED for embedded devices.
 */
void run_loop_init(RUN_LOOP_TYPE type);

/* Set data source callback. */
void run_loop_set_data_source_handler(data_source_t *ds,
      int (*process)(data_source_t *_ds));

/* Add data source. */
void run_loop_add_data_source(data_source_t *dataSource);

/* Remove data source. */
int  run_loop_remove_data_source(data_source_t *dataSource);

/* Execute configured run loop.
 * This function does not return. */
void run_loop_execute(void);

/* Hack to fix HCI timer handling. */
#ifdef HAVE_TICK
/* Sets how many milliseconds has one tick. */
uint32_t embedded_ticks_for_ms(uint32_t time_in_ms);

/* Queries the current time in ticks. */
uint32_t embedded_get_ticks(void);

#endif

/* utils.h */

/* Connection handle type. */

/* helper for BT little endian format. */
#define READ_BT_16( buffer, pos) ( ((uint16_t) buffer[pos]) | (((uint16_t)buffer[pos+1]) << 8))
#define READ_BT_24( buffer, pos) ( ((uint32_t) buffer[pos]) | (((uint32_t)buffer[pos+1]) << 8) | (((uint32_t)buffer[pos+2]) << 16))
#define READ_BT_32( buffer, pos) ( ((uint32_t) buffer[pos]) | (((uint32_t)buffer[pos+1]) << 8) | (((uint32_t)buffer[pos+2]) << 16) | (((uint32_t) buffer[pos+3])) << 24)

/* helper for SDP big endian format. */
#define READ_NET_16( buffer, pos) ( ((uint16_t) buffer[pos+1]) | (((uint16_t)buffer[pos  ]) << 8))
#define READ_NET_32( buffer, pos) ( ((uint32_t) buffer[pos+3]) | (((uint32_t)buffer[pos+2]) << 8) | (((uint32_t)buffer[pos+1]) << 16) | (((uint32_t) buffer[pos])) << 24)

/* HCI CMD OGF/OCF. */
#define READ_CMD_OGF(buffer) (buffer[1] >> 2)
#define READ_CMD_OCF(buffer) ((buffer[1] & 0x03) << 8 | buffer[0])

/* Check if command complete event for given command. */
#define COMMAND_COMPLETE_EVENT(event,cmd) ( event[0] == HCI_EVENT_COMMAND_COMPLETE && READ_BT_16(event,3) == cmd.opcode)
#define COMMAND_STATUS_EVENT(event,cmd) ( event[0] == HCI_EVENT_COMMAND_STATUS && READ_BT_16(event,4) == cmd.opcode)

/* Code+Len=2, Pkts+Opcode=3; total=5 */
#define OFFSET_OF_DATA_IN_COMMAND_COMPLETE 5

/* ACL Packet. */
#define READ_ACL_CONNECTION_HANDLE( buffer ) ( READ_BT_16(buffer,0) & 0x0fff)
#define READ_ACL_FLAGS( buffer )      ( buffer[1] >> 4 )
#define READ_ACL_LENGTH( buffer )     (READ_BT_16(buffer, 2))

/* L2CAP Packet. */
#define READ_L2CAP_LENGTH(buffer)     ( READ_BT_16(buffer, 4))
#define READ_L2CAP_CHANNEL_ID(buffer) ( READ_BT_16(buffer, 6))

#define BD_ADDR_CMP(a,b)               memcmp(a,b, BD_ADDR_LEN)
#define BD_ADDR_COPY(dest,src)         memcpy(dest,src,BD_ADDR_LEN)

void bt_store_16(uint8_t *buffer, uint16_t pos, uint16_t value);

void bt_store_32(uint8_t *buffer, uint16_t pos, uint32_t value);

void bt_flip_addr(bd_addr_t dest, bd_addr_t src);

void net_store_16(uint8_t *buffer, uint16_t pos, uint16_t value);

void net_store_32(uint8_t *buffer, uint16_t pos, uint32_t value);

void hexdump(void *data, int size);

void printUUID(uint8_t *uuid);

/* Deprecated - please use more convenient bd_addr_to_str. */
void print_bd_addr(bd_addr_t addr);

char * bd_addr_to_str(bd_addr_t addr);

int sscan_bd_addr(uint8_t * addr_string, bd_addr_t addr);

uint8_t crc8_check(uint8_t *data, uint16_t len, uint8_t check_sum);

uint8_t crc8_calc(uint8_t *data, uint16_t len);

/* btstack.h */

/* Default TCP port for BTstack daemon. */
#define BTSTACK_PORT            13333

/* UNIX domain socket for BTstack. */
#define BTSTACK_UNIX            "/tmp/BTstack"

/* Optional
 *
 * If called before bt_open, TCP socket is used
 * instead of local UNIX socket.
 *
 * note: Address is not copied and must be
 * valid during bt_open.
 */
void bt_use_tcp(const char * address, uint16_t port);

/* Init BTstack library. */
int bt_open(void);

/* Stop using BTstack library. */
int bt_close(void);

/* Send HCI cmd packet. */
int bt_send_cmd(const hci_cmd_t *cmd, ...);

/* Register packet handler -- channel only valid
 for L2CAP and RFCOMM packets.
 */
btstack_packet_handler_t bt_register_packet_handler(
      btstack_packet_handler_t handler);

void bt_send_acl(uint8_t * data, uint16_t len);

void bt_send_l2cap(uint16_t local_cid, uint8_t *data, uint16_t len);

void bt_send_rfcomm(uint16_t rfcom_cid, uint8_t *data, uint16_t len);

/* custom functions */

joypad_connection_t *slots;

typedef struct btstack_hid
{
   void *empty;
} btstack_hid_t;

enum btpad_state
{
   BTPAD_EMPTY = 0,
   BTPAD_CONNECTING,
   BTPAD_CONNECTED
};

struct btpad_queue_command
{
   const hci_cmd_t* command;

   union
   {
      struct
      {
         uint8_t on;
      }  btstack_set_power_mode;

      struct
      {
         uint16_t handle;
         uint8_t reason;
      }  hci_disconnect;

      struct
      {
         uint32_t lap;
         uint8_t length;
         uint8_t num_responses;
      }  hci_inquiry;

      struct
      {
         bd_addr_t bd_addr;
         uint8_t page_scan_repetition_mode;
         uint8_t reserved;
         uint16_t clock_offset;
      }  hci_remote_name_request;

      /* For wiimote only.
       * TODO - should we repurpose this so
       * that it's for more than just Wiimote?
       * */
      struct
      {
         bd_addr_t bd_addr;
         bd_addr_t pin;
      }  hci_pin_code_request_reply;
   };
};

struct btstack_hid_adapter
{
   uint32_t slot;

   enum btpad_state state;

   bool has_address;
   bd_addr_t address;

   uint16_t handle;

   /* 0: Control, 1: Interrupt */
   uint16_t channels[2];
};

#define GRAB(A) {#A, (void**)&A##_ptr}

static struct
{
   const char* name;
   void** target;
}  grabbers[] =
{
   GRAB(bt_open),
   GRAB(bt_close),
   GRAB(bt_flip_addr),
   GRAB(bd_addr_to_str),
   GRAB(bt_register_packet_handler),
   GRAB(bt_send_cmd),
   GRAB(bt_send_l2cap),
   GRAB(run_loop_init),
   GRAB(run_loop_execute),

   GRAB(btstack_set_power_mode),
   GRAB(hci_delete_stored_link_key),
   GRAB(hci_disconnect),
   GRAB(hci_read_bd_addr),
   GRAB(hci_inquiry),
   GRAB(hci_inquiry_cancel),
   GRAB(hci_pin_code_request_reply),
   GRAB(hci_pin_code_request_negative_reply),
   GRAB(hci_remote_name_request),
   GRAB(hci_remote_name_request_cancel),
   GRAB(hci_write_authentication_enable),
   GRAB(hci_write_inquiry_mode),
   GRAB(l2cap_create_channel),
   GRAB(l2cap_register_service),
   GRAB(l2cap_accept_connection),
   GRAB(l2cap_decline_connection),
   {0, 0}
};

static bool btstack_tested;
static bool btstack_loaded;

static bool inquiry_off;
static bool inquiry_running;
static struct btstack_hid_adapter g_connections[MAX_USERS];

struct btpad_queue_command commands[64];
static uint32_t insert_position;
static uint32_t read_position;
static uint32_t can_run;

static sthread_t *btstack_thread;

#ifdef __APPLE__
static CFRunLoopSourceRef btstack_quit_source;
#endif

static void *btstack_get_handle(void)
{
#ifdef HAVE_DYLIB
   void *handle = dylib_load("/usr/lib/libBTstack.dylib");

   if (handle)
      return handle;
#endif
   return NULL;
}

static void btpad_increment_position(uint32_t *ptr)
{
   *ptr = (*ptr + 1) % 64;
}

static void btpad_connection_send_control(void *data,
      uint8_t *s, size_t len)
{
   struct btstack_hid_adapter *connection = (struct btstack_hid_adapter*)data;
   if (connection)
      bt_send_l2cap_ptr(connection->channels[0], s, len);
}

static void btpad_queue_process_cmd(struct btpad_queue_command *cmd)
{
    if (!cmd)
        return;

    if (cmd->command == btstack_set_power_mode_ptr)
        bt_send_cmd_ptr(
                        cmd->command,
                        cmd->btstack_set_power_mode.on);
    else if (cmd->command == hci_read_bd_addr_ptr)
        bt_send_cmd_ptr(cmd->command);
    else if (cmd->command == hci_disconnect_ptr)
        bt_send_cmd_ptr(
                        cmd->command,
                        cmd->hci_disconnect.handle,
                        cmd->hci_disconnect.reason);
    else if (cmd->command == hci_inquiry_ptr)
        bt_send_cmd_ptr(
                        cmd->command,
                        cmd->hci_inquiry.lap,
                        cmd->hci_inquiry.length,
                        cmd->hci_inquiry.num_responses);
    else if (cmd->command == hci_remote_name_request_ptr)
        bt_send_cmd_ptr(
                        cmd->command,
                        cmd->hci_remote_name_request.bd_addr,
                        cmd->hci_remote_name_request.page_scan_repetition_mode,
                        cmd->hci_remote_name_request.reserved,
                        cmd->hci_remote_name_request.clock_offset);

    else if (cmd->command == hci_pin_code_request_reply_ptr)
        bt_send_cmd_ptr(
                        cmd->command,
                        cmd->hci_pin_code_request_reply.bd_addr,
                        6,
                        cmd->hci_pin_code_request_reply.pin);
}

static void btpad_queue_process(void)
{
   for (; can_run && (insert_position != read_position); can_run--)
   {
      struct btpad_queue_command* cmd = &commands[read_position];
      btpad_queue_process_cmd(cmd);
      btpad_increment_position(&read_position);
   }
}

static void btpad_queue_run(uint32_t count)
{
   can_run = count;

   btpad_queue_process();
}

static void btpad_queue_hci_read_bd_addr(
      struct btpad_queue_command *cmd)
{
   if (!cmd)
      return;

   cmd->command = hci_read_bd_addr_ptr;

   btpad_increment_position(&insert_position);
   btpad_queue_process();
}

static void btpad_queue_hci_disconnect(
      struct btpad_queue_command *cmd,
      uint16_t handle, uint8_t reason)
{
   if (!cmd)
      return;

   cmd->command               = hci_disconnect_ptr;
   cmd->hci_disconnect.handle = handle;
   cmd->hci_disconnect.reason = reason;

   btpad_increment_position(&insert_position);
   btpad_queue_process();
}

static void btpad_queue_hci_inquiry(
      struct btpad_queue_command *cmd,
      uint32_t lap,
      uint8_t length, uint8_t num_responses)
{
   if (!cmd)
      return;

   cmd->command                   = hci_inquiry_ptr;
   cmd->hci_inquiry.lap           = lap;
   cmd->hci_inquiry.length        = length;
   cmd->hci_inquiry.num_responses = num_responses;

   btpad_increment_position(&insert_position);
   btpad_queue_process();
}

static void btpad_queue_hci_remote_name_request(
      struct btpad_queue_command *cmd,
      bd_addr_t bd_addr,
      uint8_t page_scan_repetition_mode,
      uint8_t reserved, uint16_t clock_offset)
{
   if (!cmd)
      return;

   cmd->command = hci_remote_name_request_ptr;
   memcpy(cmd->hci_remote_name_request.bd_addr, bd_addr, sizeof(bd_addr_t));
   cmd->hci_remote_name_request.page_scan_repetition_mode =
      page_scan_repetition_mode;
   cmd->hci_remote_name_request.reserved     = reserved;
   cmd->hci_remote_name_request.clock_offset = clock_offset;

   btpad_increment_position(&insert_position);
   btpad_queue_process();
}

static void btpad_queue_hci_pin_code_request_reply(
      struct btpad_queue_command *cmd,
      bd_addr_t bd_addr, bd_addr_t pin)
{
   if (!cmd)
      return;

   cmd->command = hci_pin_code_request_reply_ptr;
   memcpy(cmd->hci_pin_code_request_reply.bd_addr, bd_addr, sizeof(bd_addr_t));
   memcpy(cmd->hci_pin_code_request_reply.pin, pin, sizeof(bd_addr_t));

   btpad_increment_position(&insert_position);
   btpad_queue_process();
}

static void btpad_close_connection(struct btstack_hid_adapter* connection)
{
   if (!connection)
      return;

   if (connection->handle)
      btpad_queue_hci_disconnect(&commands[insert_position],
            connection->handle, 0x15);

   memset(connection, 0, sizeof(struct btstack_hid_adapter));
}

static void btpad_close_all_connections(void)
{
   unsigned i;

   for (i = 0; i < MAX_USERS; i ++)
      btpad_close_connection(&g_connections[i]);

#ifdef __APPLE__
   CFRunLoopStop(CFRunLoopGetCurrent());
#endif
}

static struct btstack_hid_adapter *btpad_find_empty_connection(void)
{
   unsigned i;

   for (i = 0; i < MAX_USERS; i++)
   {
      if (g_connections[i].state == BTPAD_EMPTY)
         return &g_connections[i];
   }

   return 0;
}

static struct btstack_hid_adapter *btpad_find_connection_for(
      uint16_t handle, bd_addr_t address)
{
   unsigned i;

   for (i = 0; i < MAX_USERS; i++)
   {
      if (!g_connections[i].handle && !g_connections[i].has_address)
         continue;

      if (handle && g_connections[i].handle
            && handle != g_connections[i].handle)
         continue;

      if (address && g_connections[i].has_address
            && (BD_ADDR_CMP(address, g_connections[i].address)))
         continue;

      return &g_connections[i];
   }

   return 0;
}

static void btpad_queue_reset(void)
{
   insert_position = 0;
   read_position   = 0;
   can_run         = 1;
}

static void btpad_set_inquiry_state(bool on)
{
   inquiry_off = !on;

   if (!inquiry_off && !inquiry_running)
      btpad_queue_hci_inquiry(&commands[insert_position],
            HCI_INQUIRY_LAP, 3, 1);
}

static void btpad_packet_handler(uint8_t packet_type,
      uint16_t channel, uint8_t *packet, uint16_t size)
{
   unsigned i;
   bd_addr_t event_addr;
   struct btpad_queue_command* cmd = &commands[insert_position];

   switch (packet_type)
   {
      case L2CAP_DATA_PACKET:
         for (i = 0; i < MAX_USERS; i ++)
         {
            struct btstack_hid_adapter *connection = &g_connections[i];

            if (!connection || connection->state != BTPAD_CONNECTED)
               continue;

            if (     connection->channels[0] == channel
                  || connection->channels[1] == channel)
               pad_connection_packet(&slots[connection->slot], connection->slot, packet, size);
         }
         break;
      case HCI_EVENT_PACKET:
         switch (packet[0])
         {
            case BTSTACK_EVENT_STATE:
               RARCH_LOG("[BTstack] HCI State %d.\n", packet[2]);

               switch (packet[2])
               {
                  case HCI_STATE_WORKING:
                     btpad_queue_reset();
                     btpad_queue_hci_read_bd_addr(cmd);

                     /* TODO: Where did I get 672 for MTU? */

                     bt_send_cmd_ptr(l2cap_register_service_ptr, PSM_HID_CONTROL,   672);
                     bt_send_cmd_ptr(l2cap_register_service_ptr, PSM_HID_INTERRUPT, 672);
                     btpad_queue_hci_inquiry(cmd, HCI_INQUIRY_LAP, 3, 1);

                     btpad_queue_run(1);
                     break;

                  case HCI_STATE_HALTING:
                     btpad_close_all_connections();
                     break;
               }
               break;

            case HCI_EVENT_COMMAND_STATUS:
               btpad_queue_run(packet[3]);
               break;

            case HCI_EVENT_COMMAND_COMPLETE:
               btpad_queue_run(packet[2]);

               if (COMMAND_COMPLETE_EVENT(packet, (*hci_read_bd_addr_ptr)))
               {
                  bt_flip_addr_ptr(event_addr, &packet[6]);
                  if (!packet[5])
                     RARCH_LOG("[BTpad] Local address is %s.\n",
                           bd_addr_to_str_ptr(event_addr));
                  else
                     RARCH_LOG("[BTpad] Failed to get local address (Status: %02X).\n",
                           packet[5]);
               }
               break;

            case HCI_EVENT_INQUIRY_RESULT:
               if (packet[2])
               {
                  struct btstack_hid_adapter* connection = NULL;

                  bt_flip_addr_ptr(event_addr, &packet[3]);

                  connection = btpad_find_empty_connection();

                  if (!connection)
                     return;

                  RARCH_LOG("[BTpad] Inquiry found device\n");
                  memset(connection, 0, sizeof(struct btstack_hid_adapter));

                  memcpy(connection->address, event_addr, sizeof(bd_addr_t));
                  connection->has_address = true;
                  connection->state       = BTPAD_CONNECTING;

                  bt_send_cmd_ptr(l2cap_create_channel_ptr, connection->address, PSM_HID_CONTROL);
                  bt_send_cmd_ptr(l2cap_create_channel_ptr, connection->address, PSM_HID_INTERRUPT);
               }
               break;

            case HCI_EVENT_INQUIRY_COMPLETE:
               /* This must be turned off during gameplay
                * as it causes a ton of lag. */
               inquiry_running = !inquiry_off;

               if (inquiry_running)
                  btpad_queue_hci_inquiry(cmd, HCI_INQUIRY_LAP, 3, 1);
               break;

            case L2CAP_EVENT_CHANNEL_OPENED:
               {
                  uint16_t handle, psm, channel_id;
                  struct btstack_hid_adapter *connection = NULL;

                  bt_flip_addr_ptr(event_addr, &packet[3]);

                  handle             = READ_BT_16(packet, 9);
                  psm                = READ_BT_16(packet, 11);
                  channel_id         = READ_BT_16(packet, 13);
                  connection         = btpad_find_connection_for(handle, event_addr);

                  if (!packet[2])
                  {
                     if (!connection)
                     {
                        RARCH_LOG("[BTpad] Got L2CAP \"Channel Opened\" event for unrecognized device.\n");
                        break;
                     }

                     RARCH_LOG("[BTpad] L2CAP channel opened: (PSM: %02X).\n", psm);
                     connection->handle         = handle;

                     switch (psm)
                     {
                        case PSM_HID_CONTROL:
                           connection->channels[0] = channel_id;
                           break;
                        case PSM_HID_INTERRUPT:
                           connection->channels[1] = channel_id;
                           break;
                        default:
                           RARCH_LOG("[BTpad] Got unknown L2CAP PSM, ignoring (PSM: %02X).\n", psm);
                           break;
                     }

                     if (connection->channels[0] && connection->channels[1])
                     {
                        RARCH_LOG("[BTpad] Got both L2CAP channels, requesting name.\n");
                        btpad_queue_hci_remote_name_request(cmd, connection->address, 0, 0, 0);
                     }
                  }
                  else
                     RARCH_LOG("[BTpad] Got failed L2CAP \"Channel Opened\" event (PSM: %02X, Status: %02X).\n", psm, packet[2]);
               }
               break;

            case L2CAP_EVENT_INCOMING_CONNECTION:
               {
                  uint16_t handle, psm, channel_id;
                  struct btstack_hid_adapter* connection = NULL;

                  bt_flip_addr_ptr(event_addr, &packet[2]);

                  handle     = READ_BT_16(packet, 8);
                  psm        = READ_BT_16(packet, 10);
                  channel_id = READ_BT_16(packet, 12);

                  connection = btpad_find_connection_for(handle, event_addr);

                  if (!connection)
                  {
                     connection = btpad_find_empty_connection();
                     if (!connection)
                        break;

                     RARCH_LOG("[BTpad] Got new incoming connection...\n");

                     memset(connection, 0,
                           sizeof(struct btstack_hid_adapter));

                     memcpy(connection->address, event_addr,
                           sizeof(bd_addr_t));
                     connection->has_address = true;
                     connection->handle = handle;
                     connection->state = BTPAD_CONNECTING;
                  }

                  RARCH_LOG("[BTpad] Incoming L2CAP connection (PSM: %02X).\n",
                        psm);
                  bt_send_cmd_ptr(l2cap_accept_connection_ptr, channel_id);
               }
               break;

            case HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE:
               {
                  struct btstack_hid_adapter *connection = NULL;

                  bt_flip_addr_ptr(event_addr, &packet[3]);

                  connection = btpad_find_connection_for(0, event_addr);

                  if (!connection)
                  {
                     RARCH_LOG("[BTpad] Got unexpected remote name, ignoring.\n");
                     break;
                  }

                  RARCH_LOG("[BTpad] Got %.200s.\n", (char*)&packet[9]);

                  connection->slot  = pad_connection_pad_init(&slots[connection->slot],
                        (char*)packet + 9, 0, 0, connection, &btstack_hid);
                  connection->state = BTPAD_CONNECTED;
               }
               break;

            case HCI_EVENT_PIN_CODE_REQUEST:
               RARCH_LOG("[BTpad] Sending Wiimote PIN.\n");

               bt_flip_addr_ptr(event_addr, &packet[2]);
               btpad_queue_hci_pin_code_request_reply(cmd, event_addr, &packet[2]);
               break;

            case HCI_EVENT_DISCONNECTION_COMPLETE:
               {
                  const uint32_t handle = READ_BT_16(packet, 3);

                  if (!packet[2])
                  {
                     struct btstack_hid_adapter* connection = btpad_find_connection_for(handle, 0);

                     if (connection)
                     {
                        connection->handle = 0;

                        pad_connection_pad_deinit(&slots[connection->slot], connection->slot);
                        btpad_close_connection(connection);
                     }
                  }
                  else
                     RARCH_LOG("[BTpad] Got failed \"Disconnection Complete\" event (Status: %02X).\n", packet[2]);
               }
               break;

            case L2CAP_EVENT_SERVICE_REGISTERED:
               if (packet[2])
                  RARCH_LOG("[BTpad] Got failed \"Service Registered\" event (PSM: %02X, Status: %02X).\n",
                        READ_BT_16(packet, 3), packet[2]);
               break;
         }
         break;
   }
}

static bool btstack_try_load(void)
{
#ifdef HAVE_DYLIB
   unsigned i;
#endif
   void *handle   = NULL;

   if (btstack_tested)
      return btstack_loaded;

   btstack_tested = true;
   btstack_loaded = false;

   handle         = btstack_get_handle();

   if (!handle)
      return false;

#ifdef HAVE_DYLIB
   for (i = 0; grabbers[i].name; i ++)
   {
      *grabbers[i].target = dylib_proc(handle, grabbers[i].name);

      if (!*grabbers[i].target)
      {
         dylib_close(handle);
         return false;
      }
   }
#endif

#if defined(HAVE_COCOA) || defined(HAVE_COCOATOUCH) || defined(HAVE_COCOA_METAL)
   run_loop_init_ptr(RUN_LOOP_COCOA);
#else
   run_loop_init_ptr(RUN_LOOP_POSIX);
#endif
   bt_register_packet_handler_ptr(btpad_packet_handler);

   btstack_loaded = true;

   return true;
}

static void btstack_thread_stop(void *data)
{
   (void)data;
   bt_send_cmd_ptr(btstack_set_power_mode_ptr, HCI_POWER_OFF);
}

static void btstack_thread_func(void* data)
{
   RARCH_LOG("[BTstack] Thread started.\n");

   if (bt_open_ptr())
      return;

#ifdef __APPLE__
   CFRunLoopSourceContext ctx = { 0, 0, 0, 0, 0, 0, 0, 0, 0, btstack_thread_stop };
   btstack_quit_source = CFRunLoopSourceCreate(0, 0, &ctx);
   CFRunLoopAddSource(CFRunLoopGetCurrent(), btstack_quit_source, kCFRunLoopCommonModes);
#endif

   RARCH_LOG("[BTstack] Turning on...\n");
   bt_send_cmd_ptr(btstack_set_power_mode_ptr, HCI_POWER_ON);

   RARCH_LOG("[BTstack] Thread running...\n");
#ifdef __APPLE__
   CFRunLoopRun();
#endif

   RARCH_LOG("[BTstack] Thread done.\n");

#ifdef __APPLE__
   CFRunLoopSourceInvalidate(btstack_quit_source);
   CFRelease(btstack_quit_source);
#endif
}

static void btstack_set_poweron(bool on)
{
   if (!btstack_try_load())
      return;

   if (on && !btstack_thread)
      btstack_thread = sthread_create(btstack_thread_func, NULL);
   else if (!on && btstack_thread && btstack_quit_source)
   {
#ifdef __APPLE__
      CFRunLoopSourceSignal(btstack_quit_source);
#endif
      sthread_join(btstack_thread);
      btstack_thread = NULL;
   }
}

static bool btstack_hid_joypad_query(void *data, unsigned pad)
{
   return pad < MAX_USERS;
}

static const char *btstack_hid_joypad_name(void *data, unsigned pad)
{
   /* TODO/FIXME - implement properly */
   if (pad >= MAX_USERS)
      return NULL;

   return NULL;
}

static void btstack_hid_joypad_get_buttons(void *data, unsigned port,
      input_bits_t *state)
{
  btstack_hid_t        *hid   = (btstack_hid_t*)data;
  if (hid)
    pad_connection_get_buttons(&slots[port], port, state);
  else
    BIT256_CLEAR_ALL_PTR(state);
}

static int16_t btstack_hid_joypad_button(void *data,
      unsigned port, uint16_t joykey)
{
   input_bits_t buttons;
   btstack_hid_joypad_get_buttons(data, port, &buttons);

   /* Check hat. */
   if (GET_HAT_DIR(joykey))
      return 0;
   else if ((port < MAX_USERS) && (joykey < 32))
      return (BIT256_GET(buttons, joykey) != 0);
   return 0;
}

static int16_t btstack_hid_joypad_axis(void *data,
      unsigned port, uint32_t joyaxis)
{

   if (AXIS_NEG_GET(joyaxis) < 4)
   {
      int16_t val = pad_connection_get_axis(
            &slots[port], port, AXIS_NEG_GET(joyaxis));

      if (val < 0)
         return val;
   }
   else if (AXIS_POS_GET(joyaxis) < 4)
   {
      int16_t val = pad_connection_get_axis(
            &slots[port], port, AXIS_POS_GET(joyaxis));

      if (val > 0)
         return val;
   }
   return 0;
}


static int16_t btstack_hid_joypad_state(
      void *data,
      rarch_joypad_info_t *joypad_info,
      const void *binds_data,
      unsigned port)
{
   unsigned i;
   int16_t ret                          = 0;
   const struct retro_keybind *binds    = (const struct retro_keybind*)binds_data;
   uint16_t port_idx                     = joypad_info->joy_idx;
   joypad_connection_t              *pad = &slots[port_idx];

   if (!pad)
      return 0;

   for (i = 0; i < RARCH_FIRST_CUSTOM_BIND; i++)
   {
      /* Auto-binds are per joypad, not per user. */
      const uint64_t joykey  = (binds[i].joykey != NO_BTN)
         ? binds[i].joykey  : joypad_info->auto_binds[i].joykey;
      const uint32_t joyaxis = (binds[i].joyaxis != AXIS_NONE)
         ? binds[i].joyaxis : joypad_info->auto_binds[i].joyaxis;
      if (
               (uint16_t)joykey != NO_BTN
            && btstack_hid_joypad_button(data, port_idx, (uint16_t)joykey))
         ret |= ( 1 << i);
      else if (joyaxis != AXIS_NONE &&
            ((float)abs(btstack_hid_joypad_axis(data, port_idx, joyaxis))
             / 0x8000) > joypad_info->axis_threshold)
         ret |= (1 << i);
   }

   return ret;
}

static bool btstack_hid_joypad_rumble(void *data, unsigned pad,
      enum retro_rumble_effect effect, uint16_t strength)
{
   btstack_hid_t        *hid   = (btstack_hid_t*)data;
   if (!hid)
      return false;
   return pad_connection_rumble(&slots[pad], pad, effect, strength);
}

static void btstack_hid_free(const void *data)
{
   btstack_hid_t *hid = (btstack_hid_t*)data;

   if (!hid)
      return;

   pad_connection_destroy(slots);
   btpad_set_inquiry_state(true);
   btstack_set_poweron(false);

   if (hid)
      free(hid);
}

static void *btstack_hid_init(void)
{
   btstack_hid_t *hid = (btstack_hid_t*)calloc(1, sizeof(btstack_hid_t));

   if (!hid)
      goto error;

   slots = pad_connection_init(MAX_USERS);

   if (!slots)
      goto error;

   btstack_set_poweron(false);
   btpad_set_inquiry_state(false);

   return hid;

error:
   btstack_hid_free(hid);
   return NULL;
}

static void btstack_hid_poll(void *data)
{
   (void)data;
}

hid_driver_t btstack_hid = {
   btstack_hid_init,
   btstack_hid_joypad_query,
   btstack_hid_free,
   btstack_hid_joypad_button,
   btstack_hid_joypad_state,
   btstack_hid_joypad_get_buttons,
   btstack_hid_joypad_axis,
   btstack_hid_poll,
   btstack_hid_joypad_rumble,
   btstack_hid_joypad_name,
   "btstack",
   btpad_connection_send_control
};