Coverage Report

Created: 2026-07-25 06:35

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/bluez/lib/bluetooth/hci.c
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
 *
4
 *  BlueZ - Bluetooth protocol stack for Linux
5
 *
6
 *  Copyright (C) 2000-2001  Qualcomm Incorporated
7
 *  Copyright (C) 2002-2003  Maxim Krasnyansky <maxk@qualcomm.com>
8
 *  Copyright (C) 2002-2010  Marcel Holtmann <marcel@holtmann.org>
9
 *
10
 *
11
 */
12
13
#ifdef HAVE_CONFIG_H
14
#include <config.h>
15
#endif
16
17
#define _GNU_SOURCE
18
#include <stdio.h>
19
#include <errno.h>
20
#include <fcntl.h>
21
#include <unistd.h>
22
#include <stdlib.h>
23
#include <string.h>
24
#include <poll.h>
25
26
#include <sys/param.h>
27
#include <sys/uio.h>
28
#include <sys/types.h>
29
#include <sys/ioctl.h>
30
#include <sys/socket.h>
31
32
#include "bluetooth.h"
33
#include "hci.h"
34
#include "hci_lib.h"
35
36
typedef struct {
37
  char *str;
38
  unsigned int val;
39
} hci_map;
40
41
static char *hci_bit2str(const hci_map *m, unsigned int val)
42
0
{
43
0
  char *str = malloc(120);
44
0
  char *ptr = str;
45
46
0
  if (!str)
47
0
    return NULL;
48
49
0
  *ptr = 0;
50
0
  while (m->str) {
51
0
    if ((unsigned int) m->val & val)
52
0
      ptr += sprintf(ptr, "%s ", m->str);
53
0
    m++;
54
0
  }
55
0
  return str;
56
0
}
57
58
static int hci_str2bit(const hci_map *map, char *str, unsigned int *val)
59
0
{
60
0
  char *t, *ptr;
61
0
  const hci_map *m;
62
0
  int set;
63
64
0
  if (!str || !(str = ptr = strdup(str)))
65
0
    return 0;
66
67
0
  *val = set = 0;
68
69
0
  while ((t = strsep(&ptr, ","))) {
70
0
    for (m = map; m->str; m++) {
71
0
      if (!strcasecmp(m->str, t)) {
72
0
        *val |= (unsigned int) m->val;
73
0
        set = 1;
74
0
      }
75
0
    }
76
0
  }
77
0
  free(str);
78
79
0
  return set;
80
0
}
81
82
static char *hci_uint2str(const hci_map *m, unsigned int val)
83
0
{
84
0
  char *str = malloc(50);
85
0
  char *ptr = str;
86
87
0
  if (!str)
88
0
    return NULL;
89
90
0
  *ptr = 0;
91
0
  while (m->str) {
92
0
    if ((unsigned int) m->val == val) {
93
0
      ptr += sprintf(ptr, "%s", m->str);
94
0
      break;
95
0
    }
96
0
    m++;
97
0
  }
98
0
  return str;
99
0
}
100
101
static int hci_str2uint(const hci_map *map, char *str, unsigned int *val)
102
0
{
103
0
  char *t, *ptr;
104
0
  const hci_map *m;
105
0
  int set = 0;
106
107
0
  if (!str)
108
0
    return 0;
109
110
0
  str = ptr = strdup(str);
111
112
0
  while ((t = strsep(&ptr, ","))) {
113
0
    for (m = map; m->str; m++) {
114
0
      if (!strcasecmp(m->str,t)) {
115
0
        *val = (unsigned int) m->val;
116
0
        set = 1;
117
0
        break;
118
0
      }
119
0
    }
120
0
  }
121
0
  free(str);
122
123
0
  return set;
124
0
}
125
126
const char *hci_bustostr(int bus)
127
0
{
128
0
  switch (bus) {
129
0
  case HCI_VIRTUAL:
130
0
    return "Virtual";
131
0
  case HCI_USB:
132
0
    return "USB";
133
0
  case HCI_PCCARD:
134
0
    return "PCCARD";
135
0
  case HCI_UART:
136
0
    return "UART";
137
0
  case HCI_RS232:
138
0
    return "RS232";
139
0
  case HCI_PCI:
140
0
    return "PCI";
141
0
  case HCI_SDIO:
142
0
    return "SDIO";
143
0
  case HCI_SPI:
144
0
    return "SPI";
145
0
  case HCI_I2C:
146
0
    return "I2C";
147
0
  case HCI_SMD:
148
0
    return "SMD";
149
0
  case HCI_VIRTIO:
150
0
    return "VIRTIO";
151
0
  case HCI_IPC:
152
0
    return "IPC";
153
0
  default:
154
0
    return "Unknown";
155
0
  }
156
0
}
157
158
const char *hci_dtypetostr(int type)
159
0
{
160
0
  return hci_bustostr(type & 0x0f);
161
0
}
162
163
char *hci_typetostr(int type)
164
0
{
165
0
  switch (type) {
166
0
  case HCI_PRIMARY:
167
0
    return "Primary";
168
0
  case HCI_AMP:
169
0
    return "AMP";
170
0
  default:
171
0
    return "Unknown";
172
0
  }
173
0
}
174
175
/* HCI dev flags mapping */
176
static const hci_map dev_flags_map[] = {
177
  { "UP",      HCI_UP      },
178
  { "INIT",    HCI_INIT    },
179
  { "RUNNING", HCI_RUNNING },
180
  { "RAW",     HCI_RAW     },
181
  { "PSCAN",   HCI_PSCAN   },
182
  { "ISCAN",   HCI_ISCAN   },
183
  { "INQUIRY", HCI_INQUIRY },
184
  { "AUTH",    HCI_AUTH    },
185
  { "ENCRYPT", HCI_ENCRYPT },
186
  { NULL }
187
};
188
189
char *hci_dflagstostr(uint32_t flags)
190
0
{
191
0
  char *str = bt_malloc(50);
192
0
  char *ptr = str;
193
0
  const hci_map *m = dev_flags_map;
194
195
0
  if (!str)
196
0
    return NULL;
197
198
0
  *ptr = 0;
199
200
0
  if (!hci_test_bit(HCI_UP, &flags))
201
0
    ptr += sprintf(ptr, "DOWN ");
202
203
0
  while (m->str) {
204
0
    if (hci_test_bit(m->val, &flags))
205
0
      ptr += sprintf(ptr, "%s ", m->str);
206
0
    m++;
207
0
  }
208
0
  return str;
209
0
}
210
211
/* HCI packet type mapping */
212
static const hci_map pkt_type_map[] = {
213
  { "DM1",   HCI_DM1  },
214
  { "DM3",   HCI_DM3  },
215
  { "DM5",   HCI_DM5  },
216
  { "DH1",   HCI_DH1  },
217
  { "DH3",   HCI_DH3  },
218
  { "DH5",   HCI_DH5  },
219
  { "HV1",   HCI_HV1  },
220
  { "HV2",   HCI_HV2  },
221
  { "HV3",   HCI_HV3  },
222
  { "2-DH1", HCI_2DH1 },
223
  { "2-DH3", HCI_2DH3 },
224
  { "2-DH5", HCI_2DH5 },
225
  { "3-DH1", HCI_3DH1 },
226
  { "3-DH3", HCI_3DH3 },
227
  { "3-DH5", HCI_3DH5 },
228
  { NULL }
229
};
230
231
static const hci_map sco_ptype_map[] = {
232
  { "HV1",   0x0001   },
233
  { "HV2",   0x0002   },
234
  { "HV3",   0x0004   },
235
  { "EV3",   HCI_EV3  },
236
  { "EV4",   HCI_EV4  },
237
  { "EV5",   HCI_EV5  },
238
  { "2-EV3", HCI_2EV3 },
239
  { "2-EV5", HCI_2EV5 },
240
  { "3-EV3", HCI_3EV3 },
241
  { "3-EV5", HCI_3EV5 },
242
  { NULL }
243
};
244
245
char *hci_ptypetostr(unsigned int ptype)
246
0
{
247
0
  return hci_bit2str(pkt_type_map, ptype);
248
0
}
249
250
int hci_strtoptype(char *str, unsigned int *val)
251
0
{
252
0
  return hci_str2bit(pkt_type_map, str, val);
253
0
}
254
255
char *hci_scoptypetostr(unsigned int ptype)
256
0
{
257
0
  return hci_bit2str(sco_ptype_map, ptype);
258
0
}
259
260
int hci_strtoscoptype(char *str, unsigned int *val)
261
0
{
262
0
  return hci_str2bit(sco_ptype_map, str, val);
263
0
}
264
265
/* Link policy mapping */
266
static const hci_map link_policy_map[] = {
267
  { "NONE", 0   },
268
  { "RSWITCH",  HCI_LP_RSWITCH  },
269
  { "HOLD", HCI_LP_HOLD },
270
  { "SNIFF",  HCI_LP_SNIFF  },
271
  { "PARK", HCI_LP_PARK },
272
  { NULL }
273
};
274
275
char *hci_lptostr(unsigned int lp)
276
0
{
277
0
  return hci_bit2str(link_policy_map, lp);
278
0
}
279
280
int hci_strtolp(char *str, unsigned int *val)
281
0
{
282
0
  return hci_str2bit(link_policy_map, str, val);
283
0
}
284
285
/* Link mode mapping */
286
static const hci_map link_mode_map[] = {
287
  { "NONE", 0   },
288
  { "ACCEPT", HCI_LM_ACCEPT },
289
  { "CENTRAL",  HCI_LM_MASTER },
290
  { "AUTH", HCI_LM_AUTH },
291
  { "ENCRYPT",  HCI_LM_ENCRYPT  },
292
  { "TRUSTED",  HCI_LM_TRUSTED  },
293
  { "RELIABLE", HCI_LM_RELIABLE },
294
  { "SECURE", HCI_LM_SECURE },
295
  { NULL }
296
};
297
298
char *hci_lmtostr(unsigned int lm)
299
0
{
300
0
  char *s, *str = bt_malloc(50);
301
0
  if (!str)
302
0
    return NULL;
303
304
0
  *str = 0;
305
0
  if (!(lm & HCI_LM_MASTER))
306
0
    strcpy(str, "PERIPHERAL ");
307
308
0
  s = hci_bit2str(link_mode_map, lm);
309
0
  if (!s) {
310
0
    bt_free(str);
311
0
    return NULL;
312
0
  }
313
314
0
  strcat(str, s);
315
0
  free(s);
316
0
  return str;
317
0
}
318
319
int hci_strtolm(char *str, unsigned int *val)
320
0
{
321
0
  int ret = hci_str2bit(link_mode_map, str, val);
322
323
  /* Deprecated name. Kept for compatibility. */
324
0
  if (!!str && strcasestr(str, "MASTER")) {
325
0
    ret = 1;
326
0
    *val |= HCI_LM_MASTER;
327
0
  }
328
329
0
  return ret;
330
0
}
331
332
/* Command mapping */
333
static const hci_map commands_map[] = {
334
  { "Inquiry",          0   },
335
  { "Inquiry Cancel",       1   },
336
  { "Periodic Inquiry Mode",      2   },
337
  { "Exit Periodic Inquiry Mode",     3   },
338
  { "Create Connection",        4   },
339
  { "Disconnect",         5   },
340
  { "Add SCO Connection",       6   },
341
  { "Cancel Create Connection",     7   },
342
343
  { "Accept Connection Request",      8   },
344
  { "Reject Connection Request",      9   },
345
  { "Link Key Request Reply",     10  },
346
  { "Link Key Request Negative Reply",    11  },
347
  { "PIN Code Request Reply",     12  },
348
  { "PIN Code Request Negative Reply",    13  },
349
  { "Change Connection Packet Type",    14  },
350
  { "Authentication Requested",     15  },
351
352
  { "Set Connection Encryption",      16  },
353
  { "Change Connection Link Key",     17  },
354
  { "Temporary Link Key",       18  },
355
  { "Remote Name Request",      19  },
356
  { "Cancel Remote Name Request",     20  },
357
  { "Read Remote Supported Features",   21  },
358
  { "Read Remote Extended Features",    22  },
359
  { "Read Remote Version Information",    23  },
360
361
  { "Read Clock Offset",        24  },
362
  { "Read LMP Handle",        25  },
363
  { "Reserved",         26  },
364
  { "Reserved",         27  },
365
  { "Reserved",         28  },
366
  { "Reserved",         29  },
367
  { "Reserved",         30  },
368
  { "Reserved",         31  },
369
370
  { "Reserved",         32  },
371
  { "Hold Mode",          33  },
372
  { "Sniff Mode",         34  },
373
  { "Exit Sniff Mode",        35  },
374
  { "Park State",         36  },
375
  { "Exit Park State",        37  },
376
  { "QoS Setup",          38  },
377
  { "Role Discovery",       39  },
378
379
  { "Switch Role",        40  },
380
  { "Read Link Policy Settings",      41  },
381
  { "Write Link Policy Settings",     42  },
382
  { "Read Default Link Policy Settings",    43  },
383
  { "Write Default Link Policy Settings",   44  },
384
  { "Flow Specification",       45  },
385
  { "Set Event Mask",       46  },
386
  { "Reset",          47  },
387
388
  { "Set Event Filter",       48  },
389
  { "Flush",          49  },
390
  { "Read PIN Type",        50  },
391
  { "Write PIN Type",       51  },
392
  { "Create New Unit Key",      52  },
393
  { "Read Stored Link Key",     53  },
394
  { "Write Stored Link Key",      54  },
395
  { "Delete Stored Link Key",     55  },
396
397
  { "Write Local Name",       56  },
398
  { "Read Local Name",        57  },
399
  { "Read Connection Accept Timeout",   58  },
400
  { "Write Connection Accept Timeout",    59  },
401
  { "Read Page Timeout",        60  },
402
  { "Write Page Timeout",       61  },
403
  { "Read Scan Enable",       62  },
404
  { "Write Scan Enable",        63  },
405
406
  { "Read Page Scan Activity",      64  },
407
  { "Write Page Scan Activity",     65  },
408
  { "Read Inquiry Scan Activity",     66  },
409
  { "Write Inquiry Scan Activity",    67  },
410
  { "Read Authentication Enable",     68  },
411
  { "Write Authentication Enable",    69  },
412
  { "Read Encryption Mode",     70  },
413
  { "Write Encryption Mode",      71  },
414
415
  { "Read Class Of Device",     72  },
416
  { "Write Class Of Device",      73  },
417
  { "Read Voice Setting",       74  },
418
  { "Write Voice Setting",      75  },
419
  { "Read Automatic Flush Timeout",   76  },
420
  { "Write Automatic Flush Timeout",    77  },
421
  { "Read Num Broadcast Retransmissions",   78  },
422
  { "Write Num Broadcast Retransmissions",  79  },
423
424
  { "Read Hold Mode Activity",      80  },
425
  { "Write Hold Mode Activity",     81  },
426
  { "Read Transmit Power Level",      82  },
427
  { "Read Synchronous Flow Control Enable", 83  },
428
  { "Write Synchronous Flow Control Enable",  84  },
429
  { "Set Host Controller To Host Flow Control", 85  },
430
  { "Host Buffer Size",       86  },
431
  { "Host Number Of Completed Packets",   87  },
432
433
  { "Read Link Supervision Timeout",    88  },
434
  { "Write Link Supervision Timeout",   89  },
435
  { "Read Number of Supported IAC",   90  },
436
  { "Read Current IAC LAP",     91  },
437
  { "Write Current IAC LAP",      92  },
438
  { "Read Page Scan Period Mode",     93  },
439
  { "Write Page Scan Period Mode",    94  },
440
  { "Read Page Scan Mode",      95  },
441
442
  { "Write Page Scan Mode",     96  },
443
  { "Set AFH Channel Classification",   97  },
444
  { "Reserved",         98  },
445
  { "Reserved",         99  },
446
  { "Read Inquiry Scan Type",     100 },
447
  { "Write Inquiry Scan Type",      101 },
448
  { "Read Inquiry Mode",        102 },
449
  { "Write Inquiry Mode",       103 },
450
451
  { "Read Page Scan Type",      104 },
452
  { "Write Page Scan Type",     105 },
453
  { "Read AFH Channel Assessment Mode",   106 },
454
  { "Write AFH Channel Assessment Mode",    107 },
455
  { "Reserved",         108 },
456
  { "Reserved",         109 },
457
  { "Reserved",         110 },
458
  { "Reserved",         111 },
459
460
  { "Reserved",         112 },
461
  { "Reserved",         113 },
462
  { "Reserved",         114 },
463
  { "Read Local Version Information",   115 },
464
  { "Read Local Supported Commands",    116 },
465
  { "Read Local Supported Features",    117 },
466
  { "Read Local Extended Features",   118 },
467
  { "Read Buffer Size",       119 },
468
469
  { "Read Country Code",        120 },
470
  { "Read BD ADDR",       121 },
471
  { "Read Failed Contact Counter",    122 },
472
  { "Reset Failed Contact Counter",   123 },
473
  { "Get Link Quality",       124 },
474
  { "Read RSSI",          125 },
475
  { "Read AFH Channel Map",     126 },
476
  { "Read BD Clock",        127 },
477
478
  { "Read Loopback Mode",       128 },
479
  { "Write Loopback Mode",      129 },
480
  { "Enable Device Under Test Mode",    130 },
481
  { "Setup Synchronous Connection",   131 },
482
  { "Accept Synchronous Connection",    132 },
483
  { "Reject Synchronous Connection",    133 },
484
  { "Reserved",         134 },
485
  { "Reserved",         135 },
486
487
  { "Read Extended Inquiry Response",   136 },
488
  { "Write Extended Inquiry Response",    137 },
489
  { "Refresh Encryption Key",     138 },
490
  { "Reserved",         139 },
491
  { "Sniff Subrating",        140 },
492
  { "Read Simple Pairing Mode",     141 },
493
  { "Write Simple Pairing Mode",      142 },
494
  { "Read Local OOB Data",      143 },
495
496
  { "Read Inquiry Response Transmit Power Level", 144 },
497
  { "Write Inquiry Transmit Power Level",   145 },
498
  { "Read Default Erroneous Data Reporting",  146 },
499
  { "Write Default Erroneous Data Reporting", 147 },
500
  { "Reserved",         148 },
501
  { "Reserved",         149 },
502
  { "Reserved",         150 },
503
  { "IO Capability Request Reply",    151 },
504
505
  { "User Confirmation Request Reply",    152 },
506
  { "User Confirmation Request Negative Reply", 153 },
507
  { "User Passkey Request Reply",     154 },
508
  { "User Passkey Request Negative Reply",  155 },
509
  { "Remote OOB Data Request Reply",    156 },
510
  { "Write Simple Pairing Debug Mode",    157 },
511
  { "Enhanced Flush",       158 },
512
  { "Remote OOB Data Request Negative Reply", 159 },
513
514
  { "Reserved",         160 },
515
  { "Reserved",         161 },
516
  { "Send Keypress Notification",     162 },
517
  { "IO Capability Request Negative Reply", 163 },
518
  { "Read Encryption Key Size",     164 },
519
  { "Reserved",         165 },
520
  { "Reserved",         166 },
521
  { "Reserved",         167 },
522
523
  { "Create Physical Link",     168 },
524
  { "Accept Physical Link",     169 },
525
  { "Disconnect Physical Link",     170 },
526
  { "Create Logical Link",      171 },
527
  { "Accept Logical Link",      172 },
528
  { "Disconnect Logical Link",      173 },
529
  { "Logical Link Cancel",      174 },
530
  { "Flow Specification Modify",      175 },
531
532
  { "Read Logical Link Accept Timeout",   176 },
533
  { "Write Logical Link Accept Timeout",    177 },
534
  { "Set Event Mask Page 2",      178 },
535
  { "Read Location Data",       179 },
536
  { "Write Location Data",      180 },
537
  { "Read Local AMP Info",      181 },
538
  { "Read Local AMP_ASSOC",     182 },
539
  { "Write Remote AMP_ASSOC",     183 },
540
541
  { "Read Flow Control Mode",     184 },
542
  { "Write Flow Control Mode",      185 },
543
  { "Read Data Block Size",     186 },
544
  { "Reserved",         187 },
545
  { "Reserved",         188 },
546
  { "Enable AMP Receiver Reports",    189 },
547
  { "AMP Test End",       190 },
548
  { "AMP Test Command",       191 },
549
550
  { "Read Enhanced Transmit Power Level",   192 },
551
  { "Reserved",         193 },
552
  { "Read Best Effort Flush Timeout",   194 },
553
  { "Write Best Effort Flush Timeout",    195 },
554
  { "Short Range Mode",       196 },
555
  { "Read LE Host Support",     197 },
556
  { "Write LE Host Support",      198 },
557
  { "Reserved",         199 },
558
559
  { "LE Set Event Mask",        200 },
560
  { "LE Read Buffer Size",      201 },
561
  { "LE Read Local Supported Features",   202 },
562
  { "Reserved",         203 },
563
  { "LE Set Random Address",      204 },
564
  { "LE Set Advertising Parameters",    205 },
565
  { "LE Read Advertising Channel TX Power", 206 },
566
  { "LE Set Advertising Data",      207 },
567
568
  { "LE Set Scan Response Data",      208 },
569
  { "LE Set Advertise Enable",      209 },
570
  { "LE Set Scan Parameters",     210 },
571
  { "LE Set Scan Enable",       211 },
572
  { "LE Create Connection",     212 },
573
  { "LE Create Connection Cancel",    213 },
574
  { "LE Read Accept List Size",     214 },
575
  { "LE Clear Accept List",     215 },
576
577
  { "LE Add Device To Accept List",   216 },
578
  { "LE Remove Device From Accept List",    217 },
579
  { "LE Connection Update",     218 },
580
  { "LE Set Host Channel Classification",   219 },
581
  { "LE Read Channel Map",      220 },
582
  { "LE Read Remote Used Features",   221 },
583
  { "LE Encrypt",         222 },
584
  { "LE Rand",          223 },
585
586
  { "LE Start Encryption",      224 },
587
  { "LE Long Term Key Request Reply",   225 },
588
  { "LE Long Term Key Request Negative Reply",  226 },
589
  { "LE Read Supported States",     227 },
590
  { "LE Receiver Test",       228 },
591
  { "LE Transmitter Test",      229 },
592
  { "LE Test End",        230 },
593
  { "Reserved",         231 },
594
595
  { NULL }
596
};
597
598
char *hci_cmdtostr(unsigned int cmd)
599
0
{
600
0
  return hci_uint2str(commands_map, cmd);
601
0
}
602
603
char *hci_commandstostr(const uint8_t *commands, const char *pref, int width)
604
0
{
605
0
  unsigned int maxwidth = width - 3;
606
0
  const hci_map *m;
607
0
  char *off, *ptr, *str;
608
0
  int size = 1;
609
0
  int pref_len;
610
611
0
  if (pref) {
612
0
    pref_len = strlen(pref);
613
0
  } else {
614
0
    pref_len = 0;
615
0
    pref = "";
616
0
  }
617
618
0
  m = commands_map;
619
620
0
  while (m->str) {
621
0
    if (commands[m->val / 8] & (1 << (m->val % 8)))
622
0
      size += pref_len + strlen(m->str) + 3;
623
0
    m++;
624
0
  }
625
626
0
  str = bt_malloc(size);
627
0
  if (!str)
628
0
    return NULL;
629
630
0
  ptr = str; *ptr = '\0';
631
632
0
  ptr += sprintf(ptr, "%s", pref);
633
0
  off = ptr;
634
635
0
  m = commands_map;
636
637
0
  while (m->str) {
638
0
    if (commands[m->val / 8] & (1 << (m->val % 8))) {
639
0
      if (ptr != str &&
640
0
        strlen(off) + strlen(m->str) > maxwidth) {
641
0
        ptr = ptr - 1;
642
0
        ptr += sprintf(ptr, "\n%s", pref);
643
0
        off = ptr;
644
0
      }
645
0
      ptr += sprintf(ptr, "'%s' ", m->str);
646
0
    }
647
0
    m++;
648
0
  }
649
650
0
  if (ptr != str)
651
    /* Trim trailing space. */
652
0
    ptr[-1] = '\0';
653
654
0
  return str;
655
0
}
656
657
/* Version mapping */
658
static const hci_map ver_map[] = {
659
  { "1.0b", 0x00 },
660
  { "1.1",  0x01 },
661
  { "1.2",  0x02 },
662
  { "2.0",  0x03 },
663
  { "2.1",  0x04 },
664
  { "3.0",  0x05 },
665
  { "4.0",  0x06 },
666
  { "4.1",  0x07 },
667
  { "4.2",  0x08 },
668
  { "5.0",  0x09 },
669
  { "5.1",  0x0a },
670
  { "5.2",  0x0b },
671
  { "5.3",  0x0c },
672
  { "5.4",  0x0d },
673
  { NULL }
674
};
675
676
char *hci_vertostr(unsigned int ver)
677
0
{
678
0
  return hci_uint2str(ver_map, ver);
679
0
}
680
681
int hci_strtover(char *str, unsigned int *ver)
682
0
{
683
0
  return hci_str2uint(ver_map, str, ver);
684
0
}
685
686
char *lmp_vertostr(unsigned int ver)
687
0
{
688
0
  return hci_uint2str(ver_map, ver);
689
0
}
690
691
int lmp_strtover(char *str, unsigned int *ver)
692
0
{
693
0
  return hci_str2uint(ver_map, str, ver);
694
0
}
695
696
static const hci_map pal_map[] = {
697
  { "3.0",  0x01 },
698
  { NULL }
699
};
700
701
char *pal_vertostr(unsigned int ver)
702
0
{
703
0
  return hci_uint2str(pal_map, ver);
704
0
}
705
706
int pal_strtover(char *str, unsigned int *ver)
707
0
{
708
0
  return hci_str2uint(pal_map, str, ver);
709
0
}
710
711
/* LMP features mapping */
712
static const hci_map lmp_features_map[8][9] = {
713
  { /* Byte 0 */
714
    { "<3-slot packets>", LMP_3SLOT },  /* Bit 0 */
715
    { "<5-slot packets>", LMP_5SLOT },  /* Bit 1 */
716
    { "<encryption>", LMP_ENCRYPT },  /* Bit 2 */
717
    { "<slot offset>",  LMP_SOFFSET },  /* Bit 3 */
718
    { "<timing accuracy>",  LMP_TACCURACY },  /* Bit 4 */
719
    { "<role switch>",  LMP_RSWITCH },  /* Bit 5 */
720
    { "<hold mode>",  LMP_HOLD  },  /* Bit 6 */
721
    { "<sniff mode>", LMP_SNIFF },  /* Bit 7 */
722
    { NULL }
723
  },
724
  { /* Byte 1 */
725
    { "<park state>", LMP_PARK  },  /* Bit 0 */
726
    { "<RSSI>",   LMP_RSSI  },  /* Bit 1 */
727
    { "<channel quality>",  LMP_QUALITY },  /* Bit 2 */
728
    { "<SCO link>",   LMP_SCO   },  /* Bit 3 */
729
    { "<HV2 packets>",  LMP_HV2   },  /* Bit 4 */
730
    { "<HV3 packets>",  LMP_HV3   },  /* Bit 5 */
731
    { "<u-law log>",  LMP_ULAW  },  /* Bit 6 */
732
    { "<A-law log>",  LMP_ALAW  },  /* Bit 7 */
733
    { NULL }
734
  },
735
  { /* Byte 2 */
736
    { "<CVSD>",   LMP_CVSD  },  /* Bit 0 */
737
    { "<paging scheme>",  LMP_PSCHEME },  /* Bit 1 */
738
    { "<power control>",  LMP_PCONTROL  },  /* Bit 2 */
739
    { "<transparent SCO>",  LMP_TRSP_SCO  },  /* Bit 3 */
740
    { "<broadcast encrypt>",LMP_BCAST_ENC },  /* Bit 7 */
741
    { NULL }
742
  },
743
  { /* Byte 3 */
744
    { "<no. 24>",   0x01    },  /* Bit 0 */
745
    { "<EDR ACL 2 Mbps>", LMP_EDR_ACL_2M  },  /* Bit 1 */
746
    { "<EDR ACL 3 Mbps>", LMP_EDR_ACL_3M  },  /* Bit 2 */
747
    { "<enhanced iscan>", LMP_ENH_ISCAN },  /* Bit 3 */
748
    { "<interlaced iscan>", LMP_ILACE_ISCAN },  /* Bit 4 */
749
    { "<interlaced pscan>", LMP_ILACE_PSCAN },  /* Bit 5 */
750
    { "<inquiry with RSSI>",LMP_RSSI_INQ  },  /* Bit 6 */
751
    { "<extended SCO>", LMP_ESCO  },  /* Bit 7 */
752
    { NULL }
753
  },
754
  { /* Byte 4 */
755
    { "<EV4 packets>",  LMP_EV4   },  /* Bit 0 */
756
    { "<EV5 packets>",  LMP_EV5   },  /* Bit 1 */
757
    { "<no. 34>",   0x04    },  /* Bit 2 */
758
    { "<AFH cap. perip.>",  LMP_AFH_CAP_SLV },  /* Bit 3 */
759
    { "<AFH cls. perip.>",  LMP_AFH_CLS_SLV },  /* Bit 4 */
760
    { "<BR/EDR not supp.>", LMP_NO_BREDR  },  /* Bit 5 */
761
    { "<LE support>", LMP_LE    },  /* Bit 6 */
762
    { "<3-slot EDR ACL>", LMP_EDR_3SLOT },  /* Bit 7 */
763
    { NULL }
764
  },
765
  { /* Byte 5 */
766
    { "<5-slot EDR ACL>", LMP_EDR_5SLOT },  /* Bit 0 */
767
    { "<sniff subrating>",  LMP_SNIFF_SUBR  },  /* Bit 1 */
768
    { "<pause encryption>", LMP_PAUSE_ENC },  /* Bit 2 */
769
    { "<AFH cap. central>", LMP_AFH_CAP_MST },  /* Bit 3 */
770
    { "<AFH cls. central>", LMP_AFH_CLS_MST },  /* Bit 4 */
771
    { "<EDR eSCO 2 Mbps>",  LMP_EDR_ESCO_2M },  /* Bit 5 */
772
    { "<EDR eSCO 3 Mbps>",  LMP_EDR_ESCO_3M },  /* Bit 6 */
773
    { "<3-slot EDR eSCO>",  LMP_EDR_3S_ESCO },  /* Bit 7 */
774
    { NULL }
775
  },
776
  { /* Byte 6 */
777
    { "<extended inquiry>", LMP_EXT_INQ },  /* Bit 0 */
778
    { "<LE and BR/EDR>",  LMP_LE_BREDR  },  /* Bit 1 */
779
    { "<no. 50>",   0x04    },  /* Bit 2 */
780
    { "<simple pairing>", LMP_SIMPLE_PAIR },  /* Bit 3 */
781
    { "<encapsulated PDU>", LMP_ENCAPS_PDU  },  /* Bit 4 */
782
    { "<err. data report>", LMP_ERR_DAT_REP },  /* Bit 5 */
783
    { "<non-flush flag>", LMP_NFLUSH_PKTS },  /* Bit 6 */
784
    { "<no. 55>",   0x80    },  /* Bit 7 */
785
    { NULL }
786
  },
787
  { /* Byte 7 */
788
    { "<LSTO>",   LMP_LSTO  },  /* Bit 1 */
789
    { "<inquiry TX power>", LMP_INQ_TX_PWR  },  /* Bit 1 */
790
    { "<EPC>",    LMP_EPC   },  /* Bit 2 */
791
    { "<no. 59>",   0x08    },  /* Bit 3 */
792
    { "<no. 60>",   0x10    },  /* Bit 4 */
793
    { "<no. 61>",   0x20    },  /* Bit 5 */
794
    { "<no. 62>",   0x40    },  /* Bit 6 */
795
    { "<extended features>",LMP_EXT_FEAT  },  /* Bit 7 */
796
    { NULL }
797
  },
798
};
799
800
char *lmp_featurestostr(uint8_t *features, char *pref, int width)
801
0
{
802
0
  unsigned int maxwidth = width - 1;
803
0
  char *off, *ptr, *str;
804
0
  int i, size = 10;
805
806
0
  for (i = 0; i < 8; i++) {
807
0
    const hci_map *m = lmp_features_map[i];
808
809
0
    while (m->str) {
810
0
      if (m->val & features[i])
811
0
        size += strlen(m->str) +
812
0
            (pref ? strlen(pref) : 0) + 1;
813
0
      m++;
814
0
    }
815
0
  }
816
817
0
  str = bt_malloc(size);
818
0
  if (!str)
819
0
    return NULL;
820
821
0
  ptr = str; *ptr = '\0';
822
823
0
  if (pref)
824
0
    ptr += sprintf(ptr, "%s", pref);
825
826
0
  off = ptr;
827
828
0
  for (i = 0; i < 8; i++) {
829
0
    const hci_map *m = lmp_features_map[i];
830
831
0
    while (m->str) {
832
0
      if (m->val & features[i]) {
833
0
        if (strlen(off) + strlen(m->str) > maxwidth) {
834
0
          ptr += sprintf(ptr, "\n%s",
835
0
              pref ? pref : "");
836
0
          off = ptr;
837
0
        }
838
0
        ptr += sprintf(ptr, "%s ", m->str);
839
0
      }
840
0
      m++;
841
0
    }
842
0
  }
843
844
0
  return str;
845
0
}
846
847
/* HCI functions that do not require open device */
848
int hci_for_each_dev(int flag, int (*func)(int dd, int dev_id, long arg),
849
      long arg)
850
0
{
851
0
  struct hci_dev_list_req *dl;
852
0
  struct hci_dev_req *dr;
853
0
  int dev_id = -1;
854
0
  int i, sk, err = 0;
855
856
0
  sk = socket(AF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC, BTPROTO_HCI);
857
0
  if (sk < 0)
858
0
    return -1;
859
860
0
  dl = malloc(HCI_MAX_DEV * sizeof(*dr) + sizeof(*dl));
861
0
  if (!dl) {
862
0
    err = errno;
863
0
    goto done;
864
0
  }
865
866
0
  memset(dl, 0, HCI_MAX_DEV * sizeof(*dr) + sizeof(*dl));
867
868
0
  dl->dev_num = HCI_MAX_DEV;
869
0
  dr = dl->dev_req;
870
871
0
  if (ioctl(sk, HCIGETDEVLIST, (void *) dl) < 0) {
872
0
    err = errno;
873
0
    goto free;
874
0
  }
875
876
0
  for (i = 0; i < dl->dev_num; i++, dr++) {
877
0
    if (hci_test_bit(flag, &dr->dev_opt))
878
0
      if (!func || func(sk, dr->dev_id, arg)) {
879
0
        dev_id = dr->dev_id;
880
0
        break;
881
0
      }
882
0
  }
883
884
0
  if (dev_id < 0)
885
0
    err = ENODEV;
886
887
0
free:
888
0
  free(dl);
889
890
0
done:
891
0
  close(sk);
892
0
  errno = err;
893
894
0
  return dev_id;
895
0
}
896
897
static int __other_bdaddr(int dd, int dev_id, long arg)
898
0
{
899
0
  struct hci_dev_info di = { .dev_id = dev_id };
900
901
0
  if (ioctl(dd, HCIGETDEVINFO, (void *) &di))
902
0
    return 0;
903
904
0
  if (hci_test_bit(HCI_RAW, &di.flags))
905
0
    return 0;
906
907
0
  return bacmp((bdaddr_t *) arg, &di.bdaddr);
908
0
}
909
910
static int __same_bdaddr(int dd, int dev_id, long arg)
911
0
{
912
0
  struct hci_dev_info di = { .dev_id = dev_id };
913
914
0
  if (ioctl(dd, HCIGETDEVINFO, (void *) &di))
915
0
    return 0;
916
917
0
  return !bacmp((bdaddr_t *) arg, &di.bdaddr);
918
0
}
919
920
int hci_get_route(bdaddr_t *bdaddr)
921
0
{
922
0
  int dev_id;
923
924
0
  dev_id = hci_for_each_dev(HCI_UP, __other_bdaddr,
925
0
        (long) (bdaddr ? bdaddr : BDADDR_ANY));
926
0
  if (dev_id < 0)
927
0
    dev_id = hci_for_each_dev(HCI_UP, __same_bdaddr,
928
0
        (long) (bdaddr ? bdaddr : BDADDR_ANY));
929
930
0
  return dev_id;
931
0
}
932
933
int hci_devid(const char *str)
934
0
{
935
0
  bdaddr_t ba;
936
0
  int id = -1;
937
938
0
  if (!strncmp(str, "hci", 3) && strlen(str) >= 4) {
939
0
    id = atoi(str + 3);
940
0
    if (hci_devba(id, &ba) < 0)
941
0
      return -1;
942
0
  } else {
943
0
    errno = ENODEV;
944
0
    str2ba(str, &ba);
945
0
    id = hci_for_each_dev(HCI_UP, __same_bdaddr, (long) &ba);
946
0
  }
947
948
0
  return id;
949
0
}
950
951
int hci_devinfo(int dev_id, struct hci_dev_info *di)
952
0
{
953
0
  int dd, err, ret;
954
955
0
  dd = socket(AF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC, BTPROTO_HCI);
956
0
  if (dd < 0)
957
0
    return dd;
958
959
0
  memset(di, 0, sizeof(struct hci_dev_info));
960
961
0
  di->dev_id = dev_id;
962
0
  ret = ioctl(dd, HCIGETDEVINFO, (void *) di);
963
964
0
  err = errno;
965
0
  close(dd);
966
0
  errno = err;
967
968
0
  return ret;
969
0
}
970
971
int hci_devba(int dev_id, bdaddr_t *bdaddr)
972
0
{
973
0
  struct hci_dev_info di;
974
975
0
  memset(&di, 0, sizeof(di));
976
977
0
  if (hci_devinfo(dev_id, &di))
978
0
    return -1;
979
980
0
  if (!hci_test_bit(HCI_UP, &di.flags)) {
981
0
    errno = ENETDOWN;
982
0
    return -1;
983
0
  }
984
985
0
  bacpy(bdaddr, &di.bdaddr);
986
987
0
  return 0;
988
0
}
989
990
int hci_inquiry(int dev_id, int len, int nrsp, const uint8_t *lap,
991
    inquiry_info **ii, long flags)
992
0
{
993
0
  struct hci_inquiry_req *ir;
994
0
  uint8_t num_rsp = nrsp;
995
0
  void *buf;
996
0
  int dd, size, err, ret = -1;
997
998
0
  if (nrsp <= 0) {
999
0
    num_rsp = 0;
1000
0
    nrsp = 255;
1001
0
  }
1002
1003
0
  if (dev_id < 0) {
1004
0
    dev_id = hci_get_route(NULL);
1005
0
    if (dev_id < 0) {
1006
0
      errno = ENODEV;
1007
0
      return -1;
1008
0
    }
1009
0
  }
1010
1011
0
  dd = socket(AF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC, BTPROTO_HCI);
1012
0
  if (dd < 0)
1013
0
    return dd;
1014
1015
0
  buf = malloc(sizeof(*ir) + (sizeof(inquiry_info) * (nrsp)));
1016
0
  if (!buf)
1017
0
    goto done;
1018
1019
0
  ir = buf;
1020
0
  ir->dev_id  = dev_id;
1021
0
  ir->num_rsp = num_rsp;
1022
0
  ir->length  = len;
1023
0
  ir->flags   = flags;
1024
1025
0
  if (lap) {
1026
0
    memcpy(ir->lap, lap, 3);
1027
0
  } else {
1028
0
    ir->lap[0] = 0x33;
1029
0
    ir->lap[1] = 0x8b;
1030
0
    ir->lap[2] = 0x9e;
1031
0
  }
1032
1033
0
  ret = ioctl(dd, HCIINQUIRY, (unsigned long) buf);
1034
0
  if (ret < 0)
1035
0
    goto free;
1036
1037
0
  size = sizeof(inquiry_info) * ir->num_rsp;
1038
1039
0
  if (!*ii)
1040
0
    *ii = malloc(size);
1041
1042
0
  if (*ii) {
1043
0
    memcpy((void *) *ii, buf + sizeof(*ir), size);
1044
0
    ret = ir->num_rsp;
1045
0
  } else
1046
0
    ret = -1;
1047
1048
0
free:
1049
0
  free(buf);
1050
1051
0
done:
1052
0
  err = errno;
1053
0
  close(dd);
1054
0
  errno = err;
1055
1056
0
  return ret;
1057
0
}
1058
1059
/* Open HCI device.
1060
 * Returns device descriptor (dd). */
1061
int hci_open_dev(int dev_id)
1062
0
{
1063
0
  struct sockaddr_hci a;
1064
0
  int dd, err;
1065
1066
  /* Check for valid device id */
1067
0
  if (dev_id < 0) {
1068
0
    errno = ENODEV;
1069
0
    return -1;
1070
0
  }
1071
1072
  /* Create HCI socket */
1073
0
  dd = socket(AF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC, BTPROTO_HCI);
1074
0
  if (dd < 0)
1075
0
    return dd;
1076
1077
  /* Bind socket to the HCI device */
1078
0
  memset(&a, 0, sizeof(a));
1079
0
  a.hci_family = AF_BLUETOOTH;
1080
0
  a.hci_dev = dev_id;
1081
0
  if (bind(dd, (struct sockaddr *) &a, sizeof(a)) < 0)
1082
0
    goto failed;
1083
1084
0
  return dd;
1085
1086
0
failed:
1087
0
  err = errno;
1088
0
  close(dd);
1089
0
  errno = err;
1090
1091
0
  return -1;
1092
0
}
1093
1094
int hci_close_dev(int dd)
1095
0
{
1096
0
  return close(dd);
1097
0
}
1098
1099
/* HCI functions that require open device
1100
 * dd - Device descriptor returned by hci_open_dev. */
1101
1102
int hci_send_cmd(int dd, uint16_t ogf, uint16_t ocf, uint8_t plen, void *param)
1103
0
{
1104
0
  uint8_t type = HCI_COMMAND_PKT;
1105
0
  hci_command_hdr hc;
1106
0
  struct iovec iv[3];
1107
0
  int ivn;
1108
1109
0
  hc.opcode = htobs(cmd_opcode_pack(ogf, ocf));
1110
0
  hc.plen= plen;
1111
1112
0
  iv[0].iov_base = &type;
1113
0
  iv[0].iov_len  = 1;
1114
0
  iv[1].iov_base = &hc;
1115
0
  iv[1].iov_len  = HCI_COMMAND_HDR_SIZE;
1116
0
  ivn = 2;
1117
1118
0
  if (plen) {
1119
0
    iv[2].iov_base = param;
1120
0
    iv[2].iov_len  = plen;
1121
0
    ivn = 3;
1122
0
  }
1123
1124
0
  while (writev(dd, iv, ivn) < 0) {
1125
0
    if (errno == EAGAIN || errno == EINTR)
1126
0
      continue;
1127
0
    return -1;
1128
0
  }
1129
0
  return 0;
1130
0
}
1131
1132
int hci_send_req(int dd, struct hci_request *r, int to)
1133
0
{
1134
0
  unsigned char buf[HCI_MAX_EVENT_SIZE], *ptr;
1135
0
  uint16_t opcode = htobs(cmd_opcode_pack(r->ogf, r->ocf));
1136
0
  struct hci_filter nf, of;
1137
0
  socklen_t olen;
1138
0
  hci_event_hdr *hdr;
1139
0
  int err, try;
1140
1141
0
  olen = sizeof(of);
1142
0
  if (getsockopt(dd, SOL_HCI, HCI_FILTER, &of, &olen) < 0)
1143
0
    return -1;
1144
1145
0
  hci_filter_clear(&nf);
1146
0
  hci_filter_set_ptype(HCI_EVENT_PKT,  &nf);
1147
0
  hci_filter_set_event(EVT_CMD_STATUS, &nf);
1148
0
  hci_filter_set_event(EVT_CMD_COMPLETE, &nf);
1149
0
  hci_filter_set_event(EVT_LE_META_EVENT, &nf);
1150
0
  hci_filter_set_event(r->event, &nf);
1151
0
  hci_filter_set_opcode(opcode, &nf);
1152
0
  if (setsockopt(dd, SOL_HCI, HCI_FILTER, &nf, sizeof(nf)) < 0)
1153
0
    return -1;
1154
1155
0
  if (hci_send_cmd(dd, r->ogf, r->ocf, r->clen, r->cparam) < 0)
1156
0
    goto failed;
1157
1158
0
  try = 10;
1159
0
  while (try--) {
1160
0
    evt_cmd_complete *cc;
1161
0
    evt_cmd_status *cs;
1162
0
    evt_remote_name_req_complete *rn;
1163
0
    evt_le_meta_event *me;
1164
0
    remote_name_req_cp *cp;
1165
0
    int len;
1166
1167
0
    if (to) {
1168
0
      struct pollfd p;
1169
0
      int n;
1170
1171
0
      p.fd = dd; p.events = POLLIN;
1172
0
      while ((n = poll(&p, 1, to)) < 0) {
1173
0
        if (errno == EAGAIN || errno == EINTR)
1174
0
          continue;
1175
0
        goto failed;
1176
0
      }
1177
1178
0
      if (!n) {
1179
0
        errno = ETIMEDOUT;
1180
0
        goto failed;
1181
0
      }
1182
1183
0
      to -= 10;
1184
0
      if (to < 0)
1185
0
        to = 0;
1186
1187
0
    }
1188
1189
0
    while ((len = read(dd, buf, sizeof(buf))) < 0) {
1190
0
      if (errno == EAGAIN || errno == EINTR)
1191
0
        continue;
1192
0
      goto failed;
1193
0
    }
1194
1195
0
    hdr = (void *) (buf + 1);
1196
0
    ptr = buf + (1 + HCI_EVENT_HDR_SIZE);
1197
0
    len -= (1 + HCI_EVENT_HDR_SIZE);
1198
1199
0
    switch (hdr->evt) {
1200
0
    case EVT_CMD_STATUS:
1201
0
      cs = (void *) ptr;
1202
1203
0
      if (cs->opcode != opcode)
1204
0
        continue;
1205
1206
0
      if (r->event != EVT_CMD_STATUS) {
1207
0
        if (cs->status) {
1208
0
          errno = EIO;
1209
0
          goto failed;
1210
0
        }
1211
0
        break;
1212
0
      }
1213
1214
0
      r->rlen = MIN(len, r->rlen);
1215
0
      memcpy(r->rparam, ptr, r->rlen);
1216
0
      goto done;
1217
1218
0
    case EVT_CMD_COMPLETE:
1219
0
      cc = (void *) ptr;
1220
1221
0
      if (cc->opcode != opcode)
1222
0
        continue;
1223
1224
0
      ptr += EVT_CMD_COMPLETE_SIZE;
1225
0
      len -= EVT_CMD_COMPLETE_SIZE;
1226
1227
0
      r->rlen = MIN(len, r->rlen);
1228
0
      memcpy(r->rparam, ptr, r->rlen);
1229
0
      goto done;
1230
1231
0
    case EVT_REMOTE_NAME_REQ_COMPLETE:
1232
0
      if (hdr->evt != r->event)
1233
0
        break;
1234
1235
0
      rn = (void *) ptr;
1236
0
      cp = r->cparam;
1237
1238
0
      if (bacmp(&rn->bdaddr, &cp->bdaddr))
1239
0
        continue;
1240
1241
0
      r->rlen = MIN(len, r->rlen);
1242
0
      memcpy(r->rparam, ptr, r->rlen);
1243
0
      goto done;
1244
1245
0
    case EVT_LE_META_EVENT:
1246
0
      me = (void *) ptr;
1247
1248
0
      if (me->subevent != r->event)
1249
0
        continue;
1250
1251
0
      len -= 1;
1252
0
      r->rlen = MIN(len, r->rlen);
1253
0
      memcpy(r->rparam, me->data, r->rlen);
1254
0
      goto done;
1255
1256
0
    default:
1257
0
      if (hdr->evt != r->event)
1258
0
        break;
1259
1260
0
      r->rlen = MIN(len, r->rlen);
1261
0
      memcpy(r->rparam, ptr, r->rlen);
1262
0
      goto done;
1263
0
    }
1264
0
  }
1265
0
  errno = ETIMEDOUT;
1266
1267
0
failed:
1268
0
  err = errno;
1269
0
  if (setsockopt(dd, SOL_HCI, HCI_FILTER, &of, sizeof(of)) < 0)
1270
0
    err = errno;
1271
0
  errno = err;
1272
0
  return -1;
1273
1274
0
done:
1275
0
  if (setsockopt(dd, SOL_HCI, HCI_FILTER, &of, sizeof(of)) < 0)
1276
0
    return -1;
1277
0
  return 0;
1278
0
}
1279
1280
int hci_create_connection(int dd, const bdaddr_t *bdaddr, uint16_t ptype,
1281
        uint16_t clkoffset, uint8_t rswitch,
1282
        uint16_t *handle, int to)
1283
0
{
1284
0
  evt_conn_complete rp;
1285
0
  create_conn_cp cp;
1286
0
  struct hci_request rq;
1287
1288
0
  memset(&cp, 0, sizeof(cp));
1289
0
  bacpy(&cp.bdaddr, bdaddr);
1290
0
  cp.pkt_type       = ptype;
1291
0
  cp.pscan_rep_mode = 0x02;
1292
0
  cp.clock_offset   = clkoffset;
1293
0
  cp.role_switch    = rswitch;
1294
1295
0
  memset(&rq, 0, sizeof(rq));
1296
0
  rq.ogf    = OGF_LINK_CTL;
1297
0
  rq.ocf    = OCF_CREATE_CONN;
1298
0
  rq.event  = EVT_CONN_COMPLETE;
1299
0
  rq.cparam = &cp;
1300
0
  rq.clen   = CREATE_CONN_CP_SIZE;
1301
0
  rq.rparam = &rp;
1302
0
  rq.rlen   = EVT_CONN_COMPLETE_SIZE;
1303
1304
0
  if (hci_send_req(dd, &rq, to) < 0)
1305
0
    return -1;
1306
1307
0
  if (rp.status) {
1308
0
    errno = EIO;
1309
0
    return -1;
1310
0
  }
1311
1312
0
  *handle = rp.handle;
1313
0
  return 0;
1314
0
}
1315
1316
int hci_disconnect(int dd, uint16_t handle, uint8_t reason, int to)
1317
0
{
1318
0
  evt_disconn_complete rp;
1319
0
  disconnect_cp cp;
1320
0
  struct hci_request rq;
1321
1322
0
  memset(&cp, 0, sizeof(cp));
1323
0
  cp.handle = handle;
1324
0
  cp.reason = reason;
1325
1326
0
  memset(&rq, 0, sizeof(rq));
1327
0
  rq.ogf    = OGF_LINK_CTL;
1328
0
  rq.ocf    = OCF_DISCONNECT;
1329
0
  rq.event  = EVT_DISCONN_COMPLETE;
1330
0
  rq.cparam = &cp;
1331
0
  rq.clen   = DISCONNECT_CP_SIZE;
1332
0
  rq.rparam = &rp;
1333
0
  rq.rlen   = EVT_DISCONN_COMPLETE_SIZE;
1334
1335
0
  if (hci_send_req(dd, &rq, to) < 0)
1336
0
    return -1;
1337
1338
0
  if (rp.status) {
1339
0
    errno = EIO;
1340
0
    return -1;
1341
0
  }
1342
0
  return 0;
1343
0
}
1344
1345
int hci_le_add_white_list(int dd, const bdaddr_t *bdaddr, uint8_t type, int to)
1346
0
{
1347
0
  struct hci_request rq;
1348
0
  le_add_device_to_white_list_cp cp;
1349
0
  uint8_t status;
1350
1351
0
  memset(&cp, 0, sizeof(cp));
1352
0
  cp.bdaddr_type = type;
1353
0
  bacpy(&cp.bdaddr, bdaddr);
1354
1355
0
  memset(&rq, 0, sizeof(rq));
1356
0
  rq.ogf = OGF_LE_CTL;
1357
0
  rq.ocf = OCF_LE_ADD_DEVICE_TO_WHITE_LIST;
1358
0
  rq.cparam = &cp;
1359
0
  rq.clen = LE_ADD_DEVICE_TO_WHITE_LIST_CP_SIZE;
1360
0
  rq.rparam = &status;
1361
0
  rq.rlen = 1;
1362
1363
0
  if (hci_send_req(dd, &rq, to) < 0)
1364
0
    return -1;
1365
1366
0
  if (status) {
1367
0
    errno = EIO;
1368
0
    return -1;
1369
0
  }
1370
1371
0
  return 0;
1372
0
}
1373
1374
int hci_le_rm_white_list(int dd, const bdaddr_t *bdaddr, uint8_t type, int to)
1375
0
{
1376
0
  struct hci_request rq;
1377
0
  le_remove_device_from_white_list_cp cp;
1378
0
  uint8_t status;
1379
1380
0
  memset(&cp, 0, sizeof(cp));
1381
0
  cp.bdaddr_type = type;
1382
0
  bacpy(&cp.bdaddr, bdaddr);
1383
1384
0
  memset(&rq, 0, sizeof(rq));
1385
0
  rq.ogf = OGF_LE_CTL;
1386
0
  rq.ocf = OCF_LE_REMOVE_DEVICE_FROM_WHITE_LIST;
1387
0
  rq.cparam = &cp;
1388
0
  rq.clen = LE_REMOVE_DEVICE_FROM_WHITE_LIST_CP_SIZE;
1389
0
  rq.rparam = &status;
1390
0
  rq.rlen = 1;
1391
1392
0
  if (hci_send_req(dd, &rq, to) < 0)
1393
0
    return -1;
1394
1395
0
  if (status) {
1396
0
    errno = EIO;
1397
0
    return -1;
1398
0
  }
1399
1400
0
  return 0;
1401
0
}
1402
1403
int hci_le_read_white_list_size(int dd, uint8_t *size, int to)
1404
0
{
1405
0
  struct hci_request rq;
1406
0
  le_read_white_list_size_rp rp;
1407
1408
0
  memset(&rp, 0, sizeof(rp));
1409
0
  memset(&rq, 0, sizeof(rq));
1410
1411
0
  rq.ogf = OGF_LE_CTL;
1412
0
  rq.ocf = OCF_LE_READ_WHITE_LIST_SIZE;
1413
0
  rq.rparam = &rp;
1414
0
  rq.rlen = LE_READ_WHITE_LIST_SIZE_RP_SIZE;
1415
1416
0
  if (hci_send_req(dd, &rq, to) < 0)
1417
0
    return -1;
1418
1419
0
  if (rp.status) {
1420
0
    errno = EIO;
1421
0
    return -1;
1422
0
  }
1423
1424
0
  if (size)
1425
0
    *size = rp.size;
1426
1427
0
  return 0;
1428
0
}
1429
1430
int hci_le_clear_white_list(int dd, int to)
1431
0
{
1432
0
  struct hci_request rq;
1433
0
  uint8_t status;
1434
1435
0
  memset(&rq, 0, sizeof(rq));
1436
0
  rq.ogf = OGF_LE_CTL;
1437
0
  rq.ocf = OCF_LE_CLEAR_WHITE_LIST;
1438
0
  rq.rparam = &status;
1439
0
  rq.rlen = 1;
1440
1441
0
  if (hci_send_req(dd, &rq, to) < 0)
1442
0
    return -1;
1443
1444
0
  if (status) {
1445
0
    errno = EIO;
1446
0
    return -1;
1447
0
  }
1448
1449
0
  return 0;
1450
0
}
1451
1452
int hci_le_add_resolving_list(int dd, const bdaddr_t *bdaddr, uint8_t type,
1453
        uint8_t *peer_irk, uint8_t *local_irk, int to)
1454
0
{
1455
0
  struct hci_request rq;
1456
0
  le_add_device_to_resolv_list_cp cp;
1457
0
  uint8_t status;
1458
1459
0
  memset(&cp, 0, sizeof(cp));
1460
0
  cp.bdaddr_type = type;
1461
0
  bacpy(&cp.bdaddr, bdaddr);
1462
0
  if (peer_irk)
1463
0
    memcpy(cp.peer_irk, peer_irk, 16);
1464
0
  if (local_irk)
1465
0
    memcpy(cp.local_irk, local_irk, 16);
1466
1467
0
  memset(&rq, 0, sizeof(rq));
1468
0
  rq.ogf = OGF_LE_CTL;
1469
0
  rq.ocf = OCF_LE_ADD_DEVICE_TO_RESOLV_LIST;
1470
0
  rq.cparam = &cp;
1471
0
  rq.clen = LE_ADD_DEVICE_TO_RESOLV_LIST_CP_SIZE;
1472
0
  rq.rparam = &status;
1473
0
  rq.rlen = 1;
1474
1475
0
  if (hci_send_req(dd, &rq, to) < 0)
1476
0
    return -1;
1477
1478
0
  if (status) {
1479
0
    errno = EIO;
1480
0
    return -1;
1481
0
  }
1482
1483
0
  return 0;
1484
0
}
1485
1486
int hci_le_rm_resolving_list(int dd, const bdaddr_t *bdaddr, uint8_t type, int to)
1487
0
{
1488
0
  struct hci_request rq;
1489
0
  le_remove_device_from_resolv_list_cp cp;
1490
0
  uint8_t status;
1491
1492
0
  memset(&cp, 0, sizeof(cp));
1493
0
  cp.bdaddr_type = type;
1494
0
  bacpy(&cp.bdaddr, bdaddr);
1495
1496
0
  memset(&rq, 0, sizeof(rq));
1497
0
  rq.ogf = OGF_LE_CTL;
1498
0
  rq.ocf = OCF_LE_REMOVE_DEVICE_FROM_RESOLV_LIST;
1499
0
  rq.cparam = &cp;
1500
0
  rq.clen = LE_REMOVE_DEVICE_FROM_RESOLV_LIST_CP_SIZE;
1501
0
  rq.rparam = &status;
1502
0
  rq.rlen = 1;
1503
1504
0
  if (hci_send_req(dd, &rq, to) < 0)
1505
0
    return -1;
1506
1507
0
  if (status) {
1508
0
    errno = EIO;
1509
0
    return -1;
1510
0
  }
1511
1512
0
  return 0;
1513
0
}
1514
1515
int hci_le_clear_resolving_list(int dd, int to)
1516
0
{
1517
0
  struct hci_request rq;
1518
0
  uint8_t status;
1519
1520
0
  memset(&rq, 0, sizeof(rq));
1521
0
  rq.ogf = OGF_LE_CTL;
1522
0
  rq.ocf = OCF_LE_CLEAR_RESOLV_LIST;
1523
0
  rq.rparam = &status;
1524
0
  rq.rlen = 1;
1525
1526
0
  if (hci_send_req(dd, &rq, to) < 0)
1527
0
    return -1;
1528
1529
0
  if (status) {
1530
0
    errno = EIO;
1531
0
    return -1;
1532
0
  }
1533
1534
0
  return 0;
1535
0
}
1536
1537
int hci_le_read_resolving_list_size(int dd, uint8_t *size, int to)
1538
0
{
1539
0
  struct hci_request rq;
1540
0
  le_read_resolv_list_size_rp rp;
1541
1542
0
  memset(&rp, 0, sizeof(rp));
1543
0
  memset(&rq, 0, sizeof(rq));
1544
1545
0
  rq.ogf = OGF_LE_CTL;
1546
0
  rq.ocf = OCF_LE_READ_RESOLV_LIST_SIZE;
1547
0
  rq.rparam = &rp;
1548
0
  rq.rlen = LE_READ_RESOLV_LIST_SIZE_RP_SIZE;
1549
1550
0
  if (hci_send_req(dd, &rq, to) < 0)
1551
0
    return -1;
1552
1553
0
  if (rp.status) {
1554
0
    errno = EIO;
1555
0
    return -1;
1556
0
  }
1557
1558
0
  if (size)
1559
0
    *size = rp.size;
1560
1561
0
  return 0;
1562
0
}
1563
1564
int hci_le_set_address_resolution_enable(int dd, uint8_t enable, int to)
1565
0
{
1566
0
  struct hci_request rq;
1567
0
  le_set_address_resolution_enable_cp cp;
1568
0
  uint8_t status;
1569
1570
0
  memset(&cp, 0, sizeof(cp));
1571
0
  cp.enable = enable;
1572
1573
0
  memset(&rq, 0, sizeof(rq));
1574
0
  rq.ogf = OGF_LE_CTL;
1575
0
  rq.ocf = OCF_LE_SET_ADDRESS_RESOLUTION_ENABLE;
1576
0
  rq.cparam = &cp;
1577
0
  rq.clen = LE_SET_ADDRESS_RESOLUTION_ENABLE_CP_SIZE;
1578
0
  rq.rparam = &status;
1579
0
  rq.rlen = 1;
1580
1581
0
  if (hci_send_req(dd, &rq, to) < 0)
1582
0
    return -1;
1583
1584
0
  if (status) {
1585
0
    errno = EIO;
1586
0
    return -1;
1587
0
  }
1588
1589
0
  return 0;
1590
0
}
1591
1592
int hci_read_local_name(int dd, int len, char *name, int to)
1593
0
{
1594
0
  read_local_name_rp rp;
1595
0
  struct hci_request rq;
1596
1597
0
  memset(&rq, 0, sizeof(rq));
1598
0
  rq.ogf    = OGF_HOST_CTL;
1599
0
  rq.ocf    = OCF_READ_LOCAL_NAME;
1600
0
  rq.rparam = &rp;
1601
0
  rq.rlen   = READ_LOCAL_NAME_RP_SIZE;
1602
1603
0
  if (hci_send_req(dd, &rq, to) < 0)
1604
0
    return -1;
1605
1606
0
  if (rp.status) {
1607
0
    errno = EIO;
1608
0
    return -1;
1609
0
  }
1610
1611
0
  rp.name[247] = '\0';
1612
0
  strncpy(name, (char *) rp.name, len);
1613
0
  return 0;
1614
0
}
1615
1616
int hci_write_local_name(int dd, const char *name, int to)
1617
0
{
1618
0
  change_local_name_cp cp;
1619
0
  struct hci_request rq;
1620
1621
0
  memset(&cp, 0, sizeof(cp));
1622
0
  strncpy((char *) cp.name, name, sizeof(cp.name) - 1);
1623
1624
0
  memset(&rq, 0, sizeof(rq));
1625
0
  rq.ogf    = OGF_HOST_CTL;
1626
0
  rq.ocf    = OCF_CHANGE_LOCAL_NAME;
1627
0
  rq.cparam = &cp;
1628
0
  rq.clen   = CHANGE_LOCAL_NAME_CP_SIZE;
1629
1630
0
  if (hci_send_req(dd, &rq, to) < 0)
1631
0
    return -1;
1632
1633
0
  return 0;
1634
0
}
1635
1636
int hci_read_remote_name_with_clock_offset(int dd, const bdaddr_t *bdaddr,
1637
            uint8_t pscan_rep_mode,
1638
            uint16_t clkoffset,
1639
            int len, char *name, int to)
1640
0
{
1641
0
  evt_remote_name_req_complete rn;
1642
0
  remote_name_req_cp cp;
1643
0
  struct hci_request rq;
1644
1645
0
  memset(&cp, 0, sizeof(cp));
1646
0
  bacpy(&cp.bdaddr, bdaddr);
1647
0
  cp.pscan_rep_mode = pscan_rep_mode;
1648
0
  cp.clock_offset   = clkoffset;
1649
1650
0
  memset(&rq, 0, sizeof(rq));
1651
0
  rq.ogf    = OGF_LINK_CTL;
1652
0
  rq.ocf    = OCF_REMOTE_NAME_REQ;
1653
0
  rq.cparam = &cp;
1654
0
  rq.clen   = REMOTE_NAME_REQ_CP_SIZE;
1655
0
  rq.event  = EVT_REMOTE_NAME_REQ_COMPLETE;
1656
0
  rq.rparam = &rn;
1657
0
  rq.rlen   = EVT_REMOTE_NAME_REQ_COMPLETE_SIZE;
1658
1659
0
  if (hci_send_req(dd, &rq, to) < 0)
1660
0
    return -1;
1661
1662
0
  if (rn.status) {
1663
0
    errno = EIO;
1664
0
    return -1;
1665
0
  }
1666
1667
0
  rn.name[247] = '\0';
1668
0
  strncpy(name, (char *) rn.name, len);
1669
0
  return 0;
1670
0
}
1671
1672
int hci_read_remote_name(int dd, const bdaddr_t *bdaddr, int len, char *name,
1673
        int to)
1674
0
{
1675
0
  return hci_read_remote_name_with_clock_offset(dd, bdaddr, 0x02, 0x0000,
1676
0
              len, name, to);
1677
0
}
1678
1679
int hci_read_remote_name_cancel(int dd, const bdaddr_t *bdaddr, int to)
1680
0
{
1681
0
  remote_name_req_cancel_cp cp;
1682
0
  struct hci_request rq;
1683
1684
0
  memset(&cp, 0, sizeof(cp));
1685
0
  bacpy(&cp.bdaddr, bdaddr);
1686
1687
0
  memset(&rq, 0, sizeof(rq));
1688
0
  rq.ogf    = OGF_LINK_CTL;
1689
0
  rq.ocf    = OCF_REMOTE_NAME_REQ_CANCEL;
1690
0
  rq.cparam = &cp;
1691
0
  rq.clen   = REMOTE_NAME_REQ_CANCEL_CP_SIZE;
1692
1693
0
  if (hci_send_req(dd, &rq, to) < 0)
1694
0
    return -1;
1695
1696
0
  return 0;
1697
0
}
1698
1699
int hci_read_remote_version(int dd, uint16_t handle, struct hci_version *ver,
1700
        int to)
1701
0
{
1702
0
  evt_read_remote_version_complete rp;
1703
0
  read_remote_version_cp cp;
1704
0
  struct hci_request rq;
1705
1706
0
  memset(&cp, 0, sizeof(cp));
1707
0
  cp.handle = handle;
1708
1709
0
  memset(&rq, 0, sizeof(rq));
1710
0
  rq.ogf    = OGF_LINK_CTL;
1711
0
  rq.ocf    = OCF_READ_REMOTE_VERSION;
1712
0
  rq.event  = EVT_READ_REMOTE_VERSION_COMPLETE;
1713
0
  rq.cparam = &cp;
1714
0
  rq.clen   = READ_REMOTE_VERSION_CP_SIZE;
1715
0
  rq.rparam = &rp;
1716
0
  rq.rlen   = EVT_READ_REMOTE_VERSION_COMPLETE_SIZE;
1717
1718
0
  if (hci_send_req(dd, &rq, to) < 0)
1719
0
    return -1;
1720
1721
0
  if (rp.status) {
1722
0
    errno = EIO;
1723
0
    return -1;
1724
0
  }
1725
1726
0
  ver->manufacturer = btohs(rp.manufacturer);
1727
0
  ver->lmp_ver      = rp.lmp_ver;
1728
0
  ver->lmp_subver   = btohs(rp.lmp_subver);
1729
0
  return 0;
1730
0
}
1731
1732
int hci_read_remote_features(int dd, uint16_t handle, uint8_t *features, int to)
1733
0
{
1734
0
  evt_read_remote_features_complete rp;
1735
0
  read_remote_features_cp cp;
1736
0
  struct hci_request rq;
1737
1738
0
  memset(&cp, 0, sizeof(cp));
1739
0
  cp.handle = handle;
1740
1741
0
  memset(&rq, 0, sizeof(rq));
1742
0
  rq.ogf    = OGF_LINK_CTL;
1743
0
  rq.ocf    = OCF_READ_REMOTE_FEATURES;
1744
0
  rq.event  = EVT_READ_REMOTE_FEATURES_COMPLETE;
1745
0
  rq.cparam = &cp;
1746
0
  rq.clen   = READ_REMOTE_FEATURES_CP_SIZE;
1747
0
  rq.rparam = &rp;
1748
0
  rq.rlen   = EVT_READ_REMOTE_FEATURES_COMPLETE_SIZE;
1749
1750
0
  if (hci_send_req(dd, &rq, to) < 0)
1751
0
    return -1;
1752
1753
0
  if (rp.status) {
1754
0
    errno = EIO;
1755
0
    return -1;
1756
0
  }
1757
1758
0
  if (features)
1759
0
    memcpy(features, rp.features, 8);
1760
1761
0
  return 0;
1762
0
}
1763
1764
int hci_read_remote_ext_features(int dd, uint16_t handle, uint8_t page,
1765
          uint8_t *max_page, uint8_t *features,
1766
          int to)
1767
0
{
1768
0
  evt_read_remote_ext_features_complete rp;
1769
0
  read_remote_ext_features_cp cp;
1770
0
  struct hci_request rq;
1771
1772
0
  memset(&cp, 0, sizeof(cp));
1773
0
  cp.handle   = handle;
1774
0
  cp.page_num = page;
1775
1776
0
  memset(&rq, 0, sizeof(rq));
1777
0
  rq.ogf    = OGF_LINK_CTL;
1778
0
  rq.ocf    = OCF_READ_REMOTE_EXT_FEATURES;
1779
0
  rq.event  = EVT_READ_REMOTE_EXT_FEATURES_COMPLETE;
1780
0
  rq.cparam = &cp;
1781
0
  rq.clen   = READ_REMOTE_EXT_FEATURES_CP_SIZE;
1782
0
  rq.rparam = &rp;
1783
0
  rq.rlen   = EVT_READ_REMOTE_EXT_FEATURES_COMPLETE_SIZE;
1784
1785
0
  if (hci_send_req(dd, &rq, to) < 0)
1786
0
    return -1;
1787
1788
0
  if (rp.status) {
1789
0
    errno = EIO;
1790
0
    return -1;
1791
0
  }
1792
1793
0
  if (max_page)
1794
0
    *max_page = rp.max_page_num;
1795
1796
0
  if (features)
1797
0
    memcpy(features, rp.features, 8);
1798
1799
0
  return 0;
1800
0
}
1801
1802
int hci_read_clock_offset(int dd, uint16_t handle, uint16_t *clkoffset, int to)
1803
0
{
1804
0
  evt_read_clock_offset_complete rp;
1805
0
  read_clock_offset_cp cp;
1806
0
  struct hci_request rq;
1807
1808
0
  memset(&cp, 0, sizeof(cp));
1809
0
  cp.handle = handle;
1810
1811
0
  memset(&rq, 0, sizeof(rq));
1812
0
  rq.ogf    = OGF_LINK_CTL;
1813
0
  rq.ocf    = OCF_READ_CLOCK_OFFSET;
1814
0
  rq.event  = EVT_READ_CLOCK_OFFSET_COMPLETE;
1815
0
  rq.cparam = &cp;
1816
0
  rq.clen   = READ_CLOCK_OFFSET_CP_SIZE;
1817
0
  rq.rparam = &rp;
1818
0
  rq.rlen   = EVT_READ_CLOCK_OFFSET_COMPLETE_SIZE;
1819
1820
0
  if (hci_send_req(dd, &rq, to) < 0)
1821
0
    return -1;
1822
1823
0
  if (rp.status) {
1824
0
    errno = EIO;
1825
0
    return -1;
1826
0
  }
1827
1828
0
  *clkoffset = rp.clock_offset;
1829
0
  return 0;
1830
0
}
1831
1832
int hci_read_local_version(int dd, struct hci_version *ver, int to)
1833
0
{
1834
0
  read_local_version_rp rp;
1835
0
  struct hci_request rq;
1836
1837
0
  memset(&rq, 0, sizeof(rq));
1838
0
  rq.ogf    = OGF_INFO_PARAM;
1839
0
  rq.ocf    = OCF_READ_LOCAL_VERSION;
1840
0
  rq.rparam = &rp;
1841
0
  rq.rlen   = READ_LOCAL_VERSION_RP_SIZE;
1842
1843
0
  if (hci_send_req(dd, &rq, to) < 0)
1844
0
    return -1;
1845
1846
0
  if (rp.status) {
1847
0
    errno = EIO;
1848
0
    return -1;
1849
0
  }
1850
1851
0
  ver->manufacturer = btohs(rp.manufacturer);
1852
0
  ver->hci_ver      = rp.hci_ver;
1853
0
  ver->hci_rev      = btohs(rp.hci_rev);
1854
0
  ver->lmp_ver      = rp.lmp_ver;
1855
0
  ver->lmp_subver   = btohs(rp.lmp_subver);
1856
0
  return 0;
1857
0
}
1858
1859
int hci_read_local_commands(int dd, uint8_t *commands, int to)
1860
0
{
1861
0
  read_local_commands_rp rp;
1862
0
  struct hci_request rq;
1863
1864
0
  memset(&rq, 0, sizeof(rq));
1865
0
  rq.ogf    = OGF_INFO_PARAM;
1866
0
  rq.ocf    = OCF_READ_LOCAL_COMMANDS;
1867
0
  rq.rparam = &rp;
1868
0
  rq.rlen   = READ_LOCAL_COMMANDS_RP_SIZE;
1869
1870
0
  if (hci_send_req(dd, &rq, to) < 0)
1871
0
    return -1;
1872
1873
0
  if (rp.status) {
1874
0
    errno = EIO;
1875
0
    return -1;
1876
0
  }
1877
1878
0
  if (commands)
1879
0
    memcpy(commands, rp.commands, 64);
1880
1881
0
  return 0;
1882
0
}
1883
1884
int hci_read_local_features(int dd, uint8_t *features, int to)
1885
0
{
1886
0
  read_local_features_rp rp;
1887
0
  struct hci_request rq;
1888
1889
0
  memset(&rq, 0, sizeof(rq));
1890
0
  rq.ogf    = OGF_INFO_PARAM;
1891
0
  rq.ocf    = OCF_READ_LOCAL_FEATURES;
1892
0
  rq.rparam = &rp;
1893
0
  rq.rlen   = READ_LOCAL_FEATURES_RP_SIZE;
1894
1895
0
  if (hci_send_req(dd, &rq, to) < 0)
1896
0
    return -1;
1897
1898
0
  if (rp.status) {
1899
0
    errno = EIO;
1900
0
    return -1;
1901
0
  }
1902
1903
0
  if (features)
1904
0
    memcpy(features, rp.features, 8);
1905
1906
0
  return 0;
1907
0
}
1908
1909
int hci_read_local_ext_features(int dd, uint8_t page, uint8_t *max_page,
1910
        uint8_t *features, int to)
1911
0
{
1912
0
  read_local_ext_features_cp cp;
1913
0
  read_local_ext_features_rp rp;
1914
0
  struct hci_request rq;
1915
1916
0
  cp.page_num = page;
1917
1918
0
  memset(&rq, 0, sizeof(rq));
1919
0
  rq.ogf    = OGF_INFO_PARAM;
1920
0
  rq.ocf    = OCF_READ_LOCAL_EXT_FEATURES;
1921
0
  rq.cparam = &cp;
1922
0
  rq.clen   = READ_LOCAL_EXT_FEATURES_CP_SIZE;
1923
0
  rq.rparam = &rp;
1924
0
  rq.rlen   = READ_LOCAL_EXT_FEATURES_RP_SIZE;
1925
1926
0
  if (hci_send_req(dd, &rq, to) < 0)
1927
0
    return -1;
1928
1929
0
  if (rp.status) {
1930
0
    errno = EIO;
1931
0
    return -1;
1932
0
  }
1933
1934
0
  if (max_page)
1935
0
    *max_page = rp.max_page_num;
1936
1937
0
  if (features)
1938
0
    memcpy(features, rp.features, 8);
1939
1940
0
  return 0;
1941
0
}
1942
1943
int hci_read_bd_addr(int dd, bdaddr_t *bdaddr, int to)
1944
0
{
1945
0
  read_bd_addr_rp rp;
1946
0
  struct hci_request rq;
1947
1948
0
  memset(&rq, 0, sizeof(rq));
1949
0
  rq.ogf    = OGF_INFO_PARAM;
1950
0
  rq.ocf    = OCF_READ_BD_ADDR;
1951
0
  rq.rparam = &rp;
1952
0
  rq.rlen   = READ_BD_ADDR_RP_SIZE;
1953
1954
0
  if (hci_send_req(dd, &rq, to) < 0)
1955
0
    return -1;
1956
1957
0
  if (rp.status) {
1958
0
    errno = EIO;
1959
0
    return -1;
1960
0
  }
1961
1962
0
  if (bdaddr)
1963
0
    bacpy(bdaddr, &rp.bdaddr);
1964
1965
0
  return 0;
1966
0
}
1967
1968
int hci_read_class_of_dev(int dd, uint8_t *cls, int to)
1969
0
{
1970
0
  read_class_of_dev_rp rp;
1971
0
  struct hci_request rq;
1972
1973
0
  memset(&rq, 0, sizeof(rq));
1974
0
  rq.ogf    = OGF_HOST_CTL;
1975
0
  rq.ocf    = OCF_READ_CLASS_OF_DEV;
1976
0
  rq.rparam = &rp;
1977
0
  rq.rlen   = READ_CLASS_OF_DEV_RP_SIZE;
1978
1979
0
  if (hci_send_req(dd, &rq, to) < 0)
1980
0
    return -1;
1981
1982
0
  if (rp.status) {
1983
0
    errno = EIO;
1984
0
    return -1;
1985
0
  }
1986
1987
0
  memcpy(cls, rp.dev_class, 3);
1988
0
  return 0;
1989
0
}
1990
1991
int hci_write_class_of_dev(int dd, uint32_t cls, int to)
1992
0
{
1993
0
  write_class_of_dev_cp cp;
1994
0
  struct hci_request rq;
1995
1996
0
  memset(&rq, 0, sizeof(rq));
1997
0
  cp.dev_class[0] = cls & 0xff;
1998
0
  cp.dev_class[1] = (cls >> 8) & 0xff;
1999
0
  cp.dev_class[2] = (cls >> 16) & 0xff;
2000
0
  rq.ogf    = OGF_HOST_CTL;
2001
0
  rq.ocf    = OCF_WRITE_CLASS_OF_DEV;
2002
0
  rq.cparam = &cp;
2003
0
  rq.clen   = WRITE_CLASS_OF_DEV_CP_SIZE;
2004
0
  return hci_send_req(dd, &rq, to);
2005
0
}
2006
2007
int hci_read_voice_setting(int dd, uint16_t *vs, int to)
2008
0
{
2009
0
  read_voice_setting_rp rp;
2010
0
  struct hci_request rq;
2011
2012
0
  memset(&rq, 0, sizeof(rq));
2013
0
  rq.ogf    = OGF_HOST_CTL;
2014
0
  rq.ocf    = OCF_READ_VOICE_SETTING;
2015
0
  rq.rparam = &rp;
2016
0
  rq.rlen   = READ_VOICE_SETTING_RP_SIZE;
2017
2018
0
  if (hci_send_req(dd, &rq, to) < 0)
2019
0
    return -1;
2020
2021
0
  if (rp.status) {
2022
0
    errno = EIO;
2023
0
    return -1;
2024
0
  }
2025
2026
0
  *vs = rp.voice_setting;
2027
0
  return 0;
2028
0
}
2029
2030
int hci_write_voice_setting(int dd, uint16_t vs, int to)
2031
0
{
2032
0
  write_voice_setting_cp cp;
2033
0
  struct hci_request rq;
2034
2035
0
  memset(&rq, 0, sizeof(rq));
2036
0
  cp.voice_setting = vs;
2037
0
  rq.ogf    = OGF_HOST_CTL;
2038
0
  rq.ocf    = OCF_WRITE_VOICE_SETTING;
2039
0
  rq.cparam = &cp;
2040
0
  rq.clen   = WRITE_VOICE_SETTING_CP_SIZE;
2041
2042
0
  return hci_send_req(dd, &rq, to);
2043
0
}
2044
2045
int hci_read_current_iac_lap(int dd, uint8_t *num_iac, uint8_t *lap, int to)
2046
0
{
2047
0
  read_current_iac_lap_rp rp;
2048
0
  struct hci_request rq;
2049
2050
0
  memset(&rq, 0, sizeof(rq));
2051
0
  rq.ogf    = OGF_HOST_CTL;
2052
0
  rq.ocf    = OCF_READ_CURRENT_IAC_LAP;
2053
0
  rq.rparam = &rp;
2054
0
  rq.rlen   = READ_CURRENT_IAC_LAP_RP_SIZE;
2055
2056
0
  if (hci_send_req(dd, &rq, to) < 0)
2057
0
    return -1;
2058
2059
0
  if (rp.status) {
2060
0
    errno = EIO;
2061
0
    return -1;
2062
0
  }
2063
2064
0
  *num_iac = rp.num_current_iac;
2065
0
  memcpy(lap, rp.lap, rp.num_current_iac * 3);
2066
0
  return 0;
2067
0
}
2068
2069
int hci_write_current_iac_lap(int dd, uint8_t num_iac, uint8_t *lap, int to)
2070
0
{
2071
0
  write_current_iac_lap_cp cp;
2072
0
  struct hci_request rq;
2073
2074
0
  memset(&cp, 0, sizeof(cp));
2075
0
  cp.num_current_iac = num_iac;
2076
0
  memcpy(&cp.lap, lap, num_iac * 3);
2077
2078
0
  memset(&rq, 0, sizeof(rq));
2079
0
  rq.ogf    = OGF_HOST_CTL;
2080
0
  rq.ocf    = OCF_WRITE_CURRENT_IAC_LAP;
2081
0
  rq.cparam = &cp;
2082
0
  rq.clen   = num_iac * 3 + 1;
2083
2084
0
  return hci_send_req(dd, &rq, to);
2085
0
}
2086
2087
int hci_read_stored_link_key(int dd, bdaddr_t *bdaddr, uint8_t all, int to)
2088
0
{
2089
0
  read_stored_link_key_cp cp;
2090
0
  struct hci_request rq;
2091
2092
0
  memset(&cp, 0, sizeof(cp));
2093
0
  bacpy(&cp.bdaddr, bdaddr);
2094
0
  cp.read_all = all;
2095
2096
0
  memset(&rq, 0, sizeof(rq));
2097
0
  rq.ogf    = OGF_HOST_CTL;
2098
0
  rq.ocf    = OCF_READ_STORED_LINK_KEY;
2099
0
  rq.cparam = &cp;
2100
0
  rq.clen   = READ_STORED_LINK_KEY_CP_SIZE;
2101
2102
0
  return hci_send_req(dd, &rq, to);
2103
0
}
2104
2105
int hci_write_stored_link_key(int dd, bdaddr_t *bdaddr, uint8_t *key, int to)
2106
0
{
2107
0
  unsigned char cp[WRITE_STORED_LINK_KEY_CP_SIZE + 6 + 16];
2108
0
  struct hci_request rq;
2109
2110
0
  memset(&cp, 0, sizeof(cp));
2111
0
  cp[0] = 1;
2112
0
  bacpy((bdaddr_t *) (cp + 1), bdaddr);
2113
0
  memcpy(cp + 7, key, 16);
2114
2115
0
  memset(&rq, 0, sizeof(rq));
2116
0
  rq.ogf    = OGF_HOST_CTL;
2117
0
  rq.ocf    = OCF_WRITE_STORED_LINK_KEY;
2118
0
  rq.cparam = &cp;
2119
0
  rq.clen   = WRITE_STORED_LINK_KEY_CP_SIZE + 6 + 16;
2120
2121
0
  return hci_send_req(dd, &rq, to);
2122
0
}
2123
2124
int hci_delete_stored_link_key(int dd, bdaddr_t *bdaddr, uint8_t all, int to)
2125
0
{
2126
0
  delete_stored_link_key_cp cp;
2127
0
  struct hci_request rq;
2128
2129
0
  memset(&cp, 0, sizeof(cp));
2130
0
  bacpy(&cp.bdaddr, bdaddr);
2131
0
  cp.delete_all = all;
2132
2133
0
  memset(&rq, 0, sizeof(rq));
2134
0
  rq.ogf    = OGF_HOST_CTL;
2135
0
  rq.ocf    = OCF_DELETE_STORED_LINK_KEY;
2136
0
  rq.cparam = &cp;
2137
0
  rq.clen   = DELETE_STORED_LINK_KEY_CP_SIZE;
2138
2139
0
  return hci_send_req(dd, &rq, to);
2140
0
}
2141
2142
int hci_authenticate_link(int dd, uint16_t handle, int to)
2143
0
{
2144
0
  auth_requested_cp cp;
2145
0
  evt_auth_complete rp;
2146
0
  struct hci_request rq;
2147
2148
0
  cp.handle = handle;
2149
2150
0
  rq.ogf    = OGF_LINK_CTL;
2151
0
  rq.ocf    = OCF_AUTH_REQUESTED;
2152
0
  rq.event  = EVT_AUTH_COMPLETE;
2153
0
  rq.cparam = &cp;
2154
0
  rq.clen   = AUTH_REQUESTED_CP_SIZE;
2155
0
  rq.rparam = &rp;
2156
0
  rq.rlen   = EVT_AUTH_COMPLETE_SIZE;
2157
2158
0
  if (hci_send_req(dd, &rq, to) < 0)
2159
0
    return -1;
2160
2161
0
  if (rp.status) {
2162
0
    errno = EIO;
2163
0
    return -1;
2164
0
  }
2165
2166
0
  return 0;
2167
0
}
2168
2169
int hci_encrypt_link(int dd, uint16_t handle, uint8_t encrypt, int to)
2170
0
{
2171
0
  set_conn_encrypt_cp cp;
2172
0
  evt_encrypt_change rp;
2173
0
  struct hci_request rq;
2174
2175
0
  cp.handle  = handle;
2176
0
  cp.encrypt = encrypt;
2177
2178
0
  rq.ogf     = OGF_LINK_CTL;
2179
0
  rq.ocf     = OCF_SET_CONN_ENCRYPT;
2180
0
  rq.event   = EVT_ENCRYPT_CHANGE;
2181
0
  rq.cparam  = &cp;
2182
0
  rq.clen    = SET_CONN_ENCRYPT_CP_SIZE;
2183
0
  rq.rparam  = &rp;
2184
0
  rq.rlen    = EVT_ENCRYPT_CHANGE_SIZE;
2185
2186
0
  if (hci_send_req(dd, &rq, to) < 0)
2187
0
    return -1;
2188
2189
0
  if (rp.status) {
2190
0
    errno = EIO;
2191
0
    return -1;
2192
0
  }
2193
2194
0
  return 0;
2195
0
}
2196
2197
int hci_change_link_key(int dd, uint16_t handle, int to)
2198
0
{
2199
0
  change_conn_link_key_cp cp;
2200
0
  evt_change_conn_link_key_complete rp;
2201
0
  struct hci_request rq;
2202
2203
0
  cp.handle = handle;
2204
2205
0
  rq.ogf    = OGF_LINK_CTL;
2206
0
  rq.ocf    = OCF_CHANGE_CONN_LINK_KEY;
2207
0
  rq.event  = EVT_CHANGE_CONN_LINK_KEY_COMPLETE;
2208
0
  rq.cparam = &cp;
2209
0
  rq.clen   = CHANGE_CONN_LINK_KEY_CP_SIZE;
2210
0
  rq.rparam = &rp;
2211
0
  rq.rlen   = EVT_CHANGE_CONN_LINK_KEY_COMPLETE_SIZE;
2212
2213
0
  if (hci_send_req(dd, &rq, to) < 0)
2214
0
    return -1;
2215
2216
0
  if (rp.status) {
2217
0
    errno = EIO;
2218
0
    return -1;
2219
0
  }
2220
2221
0
  return 0;
2222
0
}
2223
2224
int hci_switch_role(int dd, bdaddr_t *bdaddr, uint8_t role, int to)
2225
0
{
2226
0
  switch_role_cp cp;
2227
0
  evt_role_change rp;
2228
0
  struct hci_request rq;
2229
2230
0
  bacpy(&cp.bdaddr, bdaddr);
2231
0
  cp.role   = role;
2232
0
  rq.ogf    = OGF_LINK_POLICY;
2233
0
  rq.ocf    = OCF_SWITCH_ROLE;
2234
0
  rq.cparam = &cp;
2235
0
  rq.clen   = SWITCH_ROLE_CP_SIZE;
2236
0
  rq.rparam = &rp;
2237
0
  rq.rlen   = EVT_ROLE_CHANGE_SIZE;
2238
0
  rq.event  = EVT_ROLE_CHANGE;
2239
2240
0
  if (hci_send_req(dd, &rq, to) < 0)
2241
0
    return -1;
2242
2243
0
  if (rp.status) {
2244
0
    errno = EIO;
2245
0
    return -1;
2246
0
  }
2247
2248
0
  return 0;
2249
0
}
2250
2251
int hci_park_mode(int dd, uint16_t handle, uint16_t max_interval,
2252
      uint16_t min_interval, int to)
2253
0
{
2254
0
  park_mode_cp cp;
2255
0
  evt_mode_change rp;
2256
0
  struct hci_request rq;
2257
2258
0
  memset(&cp, 0, sizeof (cp));
2259
0
  cp.handle       = handle;
2260
0
  cp.max_interval = max_interval;
2261
0
  cp.min_interval = min_interval;
2262
2263
0
  memset(&rq, 0, sizeof (rq));
2264
0
  rq.ogf    = OGF_LINK_POLICY;
2265
0
  rq.ocf    = OCF_PARK_MODE;
2266
0
  rq.event  = EVT_MODE_CHANGE;
2267
0
  rq.cparam = &cp;
2268
0
  rq.clen   = PARK_MODE_CP_SIZE;
2269
0
  rq.rparam = &rp;
2270
0
  rq.rlen   = EVT_MODE_CHANGE_SIZE;
2271
2272
0
  if (hci_send_req(dd, &rq, to) < 0)
2273
0
    return -1;
2274
2275
0
  if (rp.status) {
2276
0
    errno = EIO;
2277
0
    return -1;
2278
0
  }
2279
2280
0
  return 0;
2281
0
}
2282
2283
int hci_exit_park_mode(int dd, uint16_t handle, int to)
2284
0
{
2285
0
  exit_park_mode_cp cp;
2286
0
  evt_mode_change rp;
2287
0
  struct hci_request rq;
2288
2289
0
  memset(&cp, 0, sizeof (cp));
2290
0
  cp.handle = handle;
2291
2292
0
  memset (&rq, 0, sizeof (rq));
2293
0
  rq.ogf    = OGF_LINK_POLICY;
2294
0
  rq.ocf    = OCF_EXIT_PARK_MODE;
2295
0
  rq.event  = EVT_MODE_CHANGE;
2296
0
  rq.cparam = &cp;
2297
0
  rq.clen   = EXIT_PARK_MODE_CP_SIZE;
2298
0
  rq.rparam = &rp;
2299
0
  rq.rlen   = EVT_MODE_CHANGE_SIZE;
2300
2301
0
  if (hci_send_req(dd, &rq, to) < 0)
2302
0
    return -1;
2303
2304
0
  if (rp.status) {
2305
0
    errno = EIO;
2306
0
    return -1;
2307
0
  }
2308
2309
0
  return 0;
2310
0
}
2311
2312
int hci_read_inquiry_scan_type(int dd, uint8_t *type, int to)
2313
0
{
2314
0
  read_inquiry_scan_type_rp rp;
2315
0
  struct hci_request rq;
2316
2317
0
  memset(&rq, 0, sizeof(rq));
2318
0
  rq.ogf    = OGF_HOST_CTL;
2319
0
  rq.ocf    = OCF_READ_INQUIRY_SCAN_TYPE;
2320
0
  rq.rparam = &rp;
2321
0
  rq.rlen   = READ_INQUIRY_SCAN_TYPE_RP_SIZE;
2322
2323
0
  if (hci_send_req(dd, &rq, to) < 0)
2324
0
    return -1;
2325
2326
0
  if (rp.status) {
2327
0
    errno = EIO;
2328
0
    return -1;
2329
0
  }
2330
2331
0
  *type = rp.type;
2332
0
  return 0;
2333
0
}
2334
2335
int hci_write_inquiry_scan_type(int dd, uint8_t type, int to)
2336
0
{
2337
0
  write_inquiry_scan_type_cp cp;
2338
0
  write_inquiry_scan_type_rp rp;
2339
0
  struct hci_request rq;
2340
2341
0
  memset(&cp, 0, sizeof(cp));
2342
0
  cp.type = type;
2343
2344
0
  memset(&rq, 0, sizeof(rq));
2345
0
  rq.ogf    = OGF_HOST_CTL;
2346
0
  rq.ocf    = OCF_WRITE_INQUIRY_SCAN_TYPE;
2347
0
  rq.cparam = &cp;
2348
0
  rq.clen   = WRITE_INQUIRY_SCAN_TYPE_CP_SIZE;
2349
0
  rq.rparam = &rp;
2350
0
  rq.rlen   = WRITE_INQUIRY_SCAN_TYPE_RP_SIZE;
2351
2352
0
  if (hci_send_req(dd, &rq, to) < 0)
2353
0
    return -1;
2354
2355
0
  if (rp.status) {
2356
0
    errno = EIO;
2357
0
    return -1;
2358
0
  }
2359
2360
0
  return 0;
2361
0
}
2362
2363
int hci_read_inquiry_mode(int dd, uint8_t *mode, int to)
2364
0
{
2365
0
  read_inquiry_mode_rp rp;
2366
0
  struct hci_request rq;
2367
2368
0
  memset(&rq, 0, sizeof(rq));
2369
0
  rq.ogf    = OGF_HOST_CTL;
2370
0
  rq.ocf    = OCF_READ_INQUIRY_MODE;
2371
0
  rq.rparam = &rp;
2372
0
  rq.rlen   = READ_INQUIRY_MODE_RP_SIZE;
2373
2374
0
  if (hci_send_req(dd, &rq, to) < 0)
2375
0
    return -1;
2376
2377
0
  if (rp.status) {
2378
0
    errno = EIO;
2379
0
    return -1;
2380
0
  }
2381
2382
0
  *mode = rp.mode;
2383
0
  return 0;
2384
0
}
2385
2386
int hci_write_inquiry_mode(int dd, uint8_t mode, int to)
2387
0
{
2388
0
  write_inquiry_mode_cp cp;
2389
0
  write_inquiry_mode_rp rp;
2390
0
  struct hci_request rq;
2391
2392
0
  memset(&cp, 0, sizeof(cp));
2393
0
  cp.mode = mode;
2394
2395
0
  memset(&rq, 0, sizeof(rq));
2396
0
  rq.ogf    = OGF_HOST_CTL;
2397
0
  rq.ocf    = OCF_WRITE_INQUIRY_MODE;
2398
0
  rq.cparam = &cp;
2399
0
  rq.clen   = WRITE_INQUIRY_MODE_CP_SIZE;
2400
0
  rq.rparam = &rp;
2401
0
  rq.rlen   = WRITE_INQUIRY_MODE_RP_SIZE;
2402
2403
0
  if (hci_send_req(dd, &rq, to) < 0)
2404
0
    return -1;
2405
2406
0
  if (rp.status) {
2407
0
    errno = EIO;
2408
0
    return -1;
2409
0
  }
2410
2411
0
  return 0;
2412
0
}
2413
2414
int hci_read_afh_mode(int dd, uint8_t *mode, int to)
2415
0
{
2416
0
  read_afh_mode_rp rp;
2417
0
  struct hci_request rq;
2418
2419
0
  memset(&rq, 0, sizeof(rq));
2420
0
  rq.ogf    = OGF_HOST_CTL;
2421
0
  rq.ocf    = OCF_READ_AFH_MODE;
2422
0
  rq.rparam = &rp;
2423
0
  rq.rlen   = READ_AFH_MODE_RP_SIZE;
2424
2425
0
  if (hci_send_req(dd, &rq, to) < 0)
2426
0
    return -1;
2427
2428
0
  if (rp.status) {
2429
0
    errno = EIO;
2430
0
    return -1;
2431
0
  }
2432
2433
0
  *mode = rp.mode;
2434
0
  return 0;
2435
0
}
2436
2437
int hci_write_afh_mode(int dd, uint8_t mode, int to)
2438
0
{
2439
0
  write_afh_mode_cp cp;
2440
0
  write_afh_mode_rp rp;
2441
0
  struct hci_request rq;
2442
2443
0
  memset(&cp, 0, sizeof(cp));
2444
0
  cp.mode = mode;
2445
2446
0
  memset(&rq, 0, sizeof(rq));
2447
0
  rq.ogf    = OGF_HOST_CTL;
2448
0
  rq.ocf    = OCF_WRITE_AFH_MODE;
2449
0
  rq.cparam = &cp;
2450
0
  rq.clen   = WRITE_AFH_MODE_CP_SIZE;
2451
0
  rq.rparam = &rp;
2452
0
  rq.rlen   = WRITE_AFH_MODE_RP_SIZE;
2453
2454
0
  if (hci_send_req(dd, &rq, to) < 0)
2455
0
    return -1;
2456
2457
0
  if (rp.status) {
2458
0
    errno = EIO;
2459
0
    return -1;
2460
0
  }
2461
2462
0
  return 0;
2463
0
}
2464
2465
int hci_read_ext_inquiry_response(int dd, uint8_t *fec, uint8_t *data, int to)
2466
0
{
2467
0
  read_ext_inquiry_response_rp rp;
2468
0
  struct hci_request rq;
2469
2470
0
  memset(&rq, 0, sizeof(rq));
2471
0
  rq.ogf    = OGF_HOST_CTL;
2472
0
  rq.ocf    = OCF_READ_EXT_INQUIRY_RESPONSE;
2473
0
  rq.rparam = &rp;
2474
0
  rq.rlen   = READ_EXT_INQUIRY_RESPONSE_RP_SIZE;
2475
2476
0
  if (hci_send_req(dd, &rq, to) < 0)
2477
0
    return -1;
2478
2479
0
  if (rp.status) {
2480
0
    errno = EIO;
2481
0
    return -1;
2482
0
  }
2483
2484
0
  *fec = rp.fec;
2485
0
  memcpy(data, rp.data, HCI_MAX_EIR_LENGTH);
2486
2487
0
  return 0;
2488
0
}
2489
2490
int hci_write_ext_inquiry_response(int dd, uint8_t fec, uint8_t *data, int to)
2491
0
{
2492
0
  write_ext_inquiry_response_cp cp;
2493
0
  write_ext_inquiry_response_rp rp;
2494
0
  struct hci_request rq;
2495
2496
0
  memset(&cp, 0, sizeof(cp));
2497
0
  cp.fec = fec;
2498
0
  memcpy(cp.data, data, HCI_MAX_EIR_LENGTH);
2499
2500
0
  memset(&rq, 0, sizeof(rq));
2501
0
  rq.ogf    = OGF_HOST_CTL;
2502
0
  rq.ocf    = OCF_WRITE_EXT_INQUIRY_RESPONSE;
2503
0
  rq.cparam = &cp;
2504
0
  rq.clen   = WRITE_EXT_INQUIRY_RESPONSE_CP_SIZE;
2505
0
  rq.rparam = &rp;
2506
0
  rq.rlen   = WRITE_EXT_INQUIRY_RESPONSE_RP_SIZE;
2507
2508
0
  if (hci_send_req(dd, &rq, to) < 0)
2509
0
    return -1;
2510
2511
0
  if (rp.status) {
2512
0
    errno = EIO;
2513
0
    return -1;
2514
0
  }
2515
2516
0
  return 0;
2517
0
}
2518
2519
int hci_read_simple_pairing_mode(int dd, uint8_t *mode, int to)
2520
0
{
2521
0
  read_simple_pairing_mode_rp rp;
2522
0
  struct hci_request rq;
2523
2524
0
  memset(&rq, 0, sizeof(rq));
2525
0
  rq.ogf    = OGF_HOST_CTL;
2526
0
  rq.ocf    = OCF_READ_SIMPLE_PAIRING_MODE;
2527
0
  rq.rparam = &rp;
2528
0
  rq.rlen   = READ_SIMPLE_PAIRING_MODE_RP_SIZE;
2529
2530
0
  if (hci_send_req(dd, &rq, to) < 0)
2531
0
    return -1;
2532
2533
0
  if (rp.status) {
2534
0
    errno = EIO;
2535
0
    return -1;
2536
0
  }
2537
2538
0
  *mode = rp.mode;
2539
0
  return 0;
2540
0
}
2541
2542
int hci_write_simple_pairing_mode(int dd, uint8_t mode, int to)
2543
0
{
2544
0
  write_simple_pairing_mode_cp cp;
2545
0
  write_simple_pairing_mode_rp rp;
2546
0
  struct hci_request rq;
2547
2548
0
  memset(&cp, 0, sizeof(cp));
2549
0
  cp.mode = mode;
2550
2551
0
  memset(&rq, 0, sizeof(rq));
2552
0
  rq.ogf    = OGF_HOST_CTL;
2553
0
  rq.ocf    = OCF_WRITE_SIMPLE_PAIRING_MODE;
2554
0
  rq.cparam = &cp;
2555
0
  rq.clen   = WRITE_SIMPLE_PAIRING_MODE_CP_SIZE;
2556
0
  rq.rparam = &rp;
2557
0
  rq.rlen   = WRITE_SIMPLE_PAIRING_MODE_RP_SIZE;
2558
2559
0
  if (hci_send_req(dd, &rq, to) < 0)
2560
0
    return -1;
2561
2562
0
  if (rp.status) {
2563
0
    errno = EIO;
2564
0
    return -1;
2565
0
  }
2566
2567
0
  return 0;
2568
0
}
2569
2570
int hci_read_local_oob_data(int dd, uint8_t *hash, uint8_t *randomizer, int to)
2571
0
{
2572
0
  read_local_oob_data_rp rp;
2573
0
  struct hci_request rq;
2574
2575
0
  memset(&rq, 0, sizeof(rq));
2576
0
  rq.ogf    = OGF_HOST_CTL;
2577
0
  rq.ocf    = OCF_READ_LOCAL_OOB_DATA;
2578
0
  rq.rparam = &rp;
2579
0
  rq.rlen   = READ_LOCAL_OOB_DATA_RP_SIZE;
2580
2581
0
  if (hci_send_req(dd, &rq, to) < 0)
2582
0
    return -1;
2583
2584
0
  if (rp.status) {
2585
0
    errno = EIO;
2586
0
    return -1;
2587
0
  }
2588
2589
0
  memcpy(hash, rp.hash, 16);
2590
0
  memcpy(randomizer, rp.randomizer, 16);
2591
0
  return 0;
2592
0
}
2593
2594
int hci_read_inq_response_tx_power_level(int dd, int8_t *level, int to)
2595
0
{
2596
0
  read_inq_response_tx_power_level_rp rp;
2597
0
  struct hci_request rq;
2598
2599
0
  memset(&rq, 0, sizeof(rq));
2600
0
  rq.ogf    = OGF_HOST_CTL;
2601
0
  rq.ocf    = OCF_READ_INQ_RESPONSE_TX_POWER_LEVEL;
2602
0
  rq.rparam = &rp;
2603
0
  rq.rlen   = READ_INQ_RESPONSE_TX_POWER_LEVEL_RP_SIZE;
2604
2605
0
  if (hci_send_req(dd, &rq, to) < 0)
2606
0
    return -1;
2607
2608
0
  if (rp.status) {
2609
0
    errno = EIO;
2610
0
    return -1;
2611
0
  }
2612
2613
0
  *level = rp.level;
2614
0
  return 0;
2615
0
}
2616
2617
int hci_read_inquiry_transmit_power_level(int dd, int8_t *level, int to)
2618
0
{
2619
0
  return hci_read_inq_response_tx_power_level(dd, level, to);
2620
0
}
2621
2622
int hci_write_inquiry_transmit_power_level(int dd, int8_t level, int to)
2623
0
{
2624
0
  write_inquiry_transmit_power_level_cp cp;
2625
0
  write_inquiry_transmit_power_level_rp rp;
2626
0
  struct hci_request rq;
2627
2628
0
  memset(&cp, 0, sizeof(cp));
2629
0
  cp.level = level;
2630
2631
0
  memset(&rq, 0, sizeof(rq));
2632
0
  rq.ogf    = OGF_HOST_CTL;
2633
0
  rq.ocf    = OCF_WRITE_INQUIRY_TRANSMIT_POWER_LEVEL;
2634
0
  rq.cparam = &cp;
2635
0
  rq.clen   = WRITE_INQUIRY_TRANSMIT_POWER_LEVEL_CP_SIZE;
2636
0
  rq.rparam = &rp;
2637
0
  rq.rlen   = WRITE_INQUIRY_TRANSMIT_POWER_LEVEL_RP_SIZE;
2638
2639
0
  if (hci_send_req(dd, &rq, to) < 0)
2640
0
    return -1;
2641
2642
0
  if (rp.status) {
2643
0
    errno = EIO;
2644
0
    return -1;
2645
0
  }
2646
2647
0
  return 0;
2648
0
}
2649
2650
int hci_read_transmit_power_level(int dd, uint16_t handle, uint8_t type,
2651
          int8_t *level, int to)
2652
0
{
2653
0
  read_transmit_power_level_cp cp;
2654
0
  read_transmit_power_level_rp rp;
2655
0
  struct hci_request rq;
2656
2657
0
  memset(&cp, 0, sizeof(cp));
2658
0
  cp.handle = handle;
2659
0
  cp.type   = type;
2660
2661
0
  memset(&rq, 0, sizeof(rq));
2662
0
  rq.ogf    = OGF_HOST_CTL;
2663
0
  rq.ocf    = OCF_READ_TRANSMIT_POWER_LEVEL;
2664
0
  rq.cparam = &cp;
2665
0
  rq.clen   = READ_TRANSMIT_POWER_LEVEL_CP_SIZE;
2666
0
  rq.rparam = &rp;
2667
0
  rq.rlen   = READ_TRANSMIT_POWER_LEVEL_RP_SIZE;
2668
2669
0
  if (hci_send_req(dd, &rq, to) < 0)
2670
0
    return -1;
2671
2672
0
  if (rp.status) {
2673
0
    errno = EIO;
2674
0
    return -1;
2675
0
  }
2676
2677
0
  *level = rp.level;
2678
0
  return 0;
2679
0
}
2680
2681
int hci_read_link_policy(int dd, uint16_t handle, uint16_t *policy, int to)
2682
0
{
2683
0
  read_link_policy_rp rp;
2684
0
  struct hci_request rq;
2685
2686
0
  memset(&rq, 0, sizeof(rq));
2687
0
  rq.ogf    = OGF_LINK_POLICY;
2688
0
  rq.ocf    = OCF_READ_LINK_POLICY;
2689
0
  rq.cparam = &handle;
2690
0
  rq.clen   = 2;
2691
0
  rq.rparam = &rp;
2692
0
  rq.rlen   = READ_LINK_POLICY_RP_SIZE;
2693
2694
0
  if (hci_send_req(dd, &rq, to) < 0)
2695
0
    return -1;
2696
2697
0
  if (rp.status) {
2698
0
    errno = EIO;
2699
0
    return -1;
2700
0
  }
2701
2702
0
  *policy = rp.policy;
2703
0
  return 0;
2704
0
}
2705
2706
int hci_write_link_policy(int dd, uint16_t handle, uint16_t policy, int to)
2707
0
{
2708
0
  write_link_policy_cp cp;
2709
0
  write_link_policy_rp rp;
2710
0
  struct hci_request rq;
2711
2712
0
  memset(&cp, 0, sizeof(cp));
2713
0
  cp.handle = handle;
2714
0
  cp.policy = policy;
2715
2716
0
  memset(&rq, 0, sizeof(rq));
2717
0
  rq.ogf    = OGF_LINK_POLICY;
2718
0
  rq.ocf    = OCF_WRITE_LINK_POLICY;
2719
0
  rq.cparam = &cp;
2720
0
  rq.clen   = WRITE_LINK_POLICY_CP_SIZE;
2721
0
  rq.rparam = &rp;
2722
0
  rq.rlen   = WRITE_LINK_POLICY_RP_SIZE;
2723
2724
0
  if (hci_send_req(dd, &rq, to) < 0)
2725
0
    return -1;
2726
2727
0
  if (rp.status) {
2728
0
    errno = EIO;
2729
0
    return -1;
2730
0
  }
2731
2732
0
  return 0;
2733
0
}
2734
2735
int hci_read_link_supervision_timeout(int dd, uint16_t handle,
2736
          uint16_t *timeout, int to)
2737
0
{
2738
0
  read_link_supervision_timeout_rp rp;
2739
0
  struct hci_request rq;
2740
2741
0
  memset(&rq, 0, sizeof(rq));
2742
0
  rq.ogf    = OGF_HOST_CTL;
2743
0
  rq.ocf    = OCF_READ_LINK_SUPERVISION_TIMEOUT;
2744
0
  rq.cparam = &handle;
2745
0
  rq.clen   = 2;
2746
0
  rq.rparam = &rp;
2747
0
  rq.rlen   = READ_LINK_SUPERVISION_TIMEOUT_RP_SIZE;
2748
2749
0
  if (hci_send_req(dd, &rq, to) < 0)
2750
0
    return -1;
2751
2752
0
  if (rp.status) {
2753
0
    errno = EIO;
2754
0
    return -1;
2755
0
  }
2756
2757
0
  *timeout = rp.timeout;
2758
0
  return 0;
2759
0
}
2760
2761
int hci_write_link_supervision_timeout(int dd, uint16_t handle,
2762
          uint16_t timeout, int to)
2763
0
{
2764
0
  write_link_supervision_timeout_cp cp;
2765
0
  write_link_supervision_timeout_rp rp;
2766
0
  struct hci_request rq;
2767
2768
0
  memset(&cp, 0, sizeof(cp));
2769
0
  cp.handle  = handle;
2770
0
  cp.timeout = timeout;
2771
2772
0
  memset(&rq, 0, sizeof(rq));
2773
0
  rq.ogf    = OGF_HOST_CTL;
2774
0
  rq.ocf    = OCF_WRITE_LINK_SUPERVISION_TIMEOUT;
2775
0
  rq.cparam = &cp;
2776
0
  rq.clen   = WRITE_LINK_SUPERVISION_TIMEOUT_CP_SIZE;
2777
0
  rq.rparam = &rp;
2778
0
  rq.rlen   = WRITE_LINK_SUPERVISION_TIMEOUT_RP_SIZE;
2779
2780
0
  if (hci_send_req(dd, &rq, to) < 0)
2781
0
    return -1;
2782
2783
0
  if (rp.status) {
2784
0
    errno = EIO;
2785
0
    return -1;
2786
0
  }
2787
2788
0
  return 0;
2789
0
}
2790
2791
int hci_set_afh_classification(int dd, uint8_t *map, int to)
2792
0
{
2793
0
  set_afh_classification_cp cp;
2794
0
  set_afh_classification_rp rp;
2795
0
  struct hci_request rq;
2796
2797
0
  memset(&cp, 0, sizeof(cp));
2798
0
  memcpy(cp.map, map, 10);
2799
2800
0
  memset(&rq, 0, sizeof(rq));
2801
0
  rq.ogf    = OGF_HOST_CTL;
2802
0
  rq.ocf    = OCF_SET_AFH_CLASSIFICATION;
2803
0
  rq.cparam = &cp;
2804
0
  rq.clen   = SET_AFH_CLASSIFICATION_CP_SIZE;
2805
0
  rq.rparam = &rp;
2806
0
  rq.rlen   = SET_AFH_CLASSIFICATION_RP_SIZE;
2807
2808
0
  if (hci_send_req(dd, &rq, to) < 0)
2809
0
    return -1;
2810
2811
0
  if (rp.status) {
2812
0
    errno = EIO;
2813
0
    return -1;
2814
0
  }
2815
2816
0
  return 0;
2817
0
}
2818
2819
int hci_read_link_quality(int dd, uint16_t handle, uint8_t *link_quality,
2820
        int to)
2821
0
{
2822
0
  read_link_quality_rp rp;
2823
0
  struct hci_request rq;
2824
2825
0
  memset(&rq, 0, sizeof(rq));
2826
0
  rq.ogf    = OGF_STATUS_PARAM;
2827
0
  rq.ocf    = OCF_READ_LINK_QUALITY;
2828
0
  rq.cparam = &handle;
2829
0
  rq.clen   = 2;
2830
0
  rq.rparam = &rp;
2831
0
  rq.rlen   = READ_LINK_QUALITY_RP_SIZE;
2832
2833
0
  if (hci_send_req(dd, &rq, to) < 0)
2834
0
    return -1;
2835
2836
0
  if (rp.status) {
2837
0
    errno = EIO;
2838
0
    return -1;
2839
0
  }
2840
2841
0
  *link_quality = rp.link_quality;
2842
0
  return 0;
2843
0
}
2844
2845
int hci_read_rssi(int dd, uint16_t handle, int8_t *rssi, int to)
2846
0
{
2847
0
  read_rssi_rp rp;
2848
0
  struct hci_request rq;
2849
2850
0
  memset(&rq, 0, sizeof(rq));
2851
0
  rq.ogf    = OGF_STATUS_PARAM;
2852
0
  rq.ocf    = OCF_READ_RSSI;
2853
0
  rq.cparam = &handle;
2854
0
  rq.clen   = 2;
2855
0
  rq.rparam = &rp;
2856
0
  rq.rlen   = READ_RSSI_RP_SIZE;
2857
2858
0
  if (hci_send_req(dd, &rq, to) < 0)
2859
0
    return -1;
2860
2861
0
  if (rp.status) {
2862
0
    errno = EIO;
2863
0
    return -1;
2864
0
  }
2865
2866
0
  *rssi = rp.rssi;
2867
0
  return 0;
2868
0
}
2869
2870
int hci_read_afh_map(int dd, uint16_t handle, uint8_t *mode, uint8_t *map,
2871
      int to)
2872
0
{
2873
0
  read_afh_map_rp rp;
2874
0
  struct hci_request rq;
2875
2876
0
  memset(&rq, 0, sizeof(rq));
2877
0
  rq.ogf    = OGF_STATUS_PARAM;
2878
0
  rq.ocf    = OCF_READ_AFH_MAP;
2879
0
  rq.cparam = &handle;
2880
0
  rq.clen   = 2;
2881
0
  rq.rparam = &rp;
2882
0
  rq.rlen   = READ_AFH_MAP_RP_SIZE;
2883
2884
0
  if (hci_send_req(dd, &rq, to) < 0)
2885
0
    return -1;
2886
2887
0
  if (rp.status) {
2888
0
    errno = EIO;
2889
0
    return -1;
2890
0
  }
2891
2892
0
  *mode = rp.mode;
2893
0
  memcpy(map, rp.map, 10);
2894
0
  return 0;
2895
0
}
2896
2897
int hci_read_clock(int dd, uint16_t handle, uint8_t which, uint32_t *clock,
2898
      uint16_t *accuracy, int to)
2899
0
{
2900
0
  read_clock_cp cp;
2901
0
  read_clock_rp rp;
2902
0
  struct hci_request rq;
2903
2904
0
  memset(&cp, 0, sizeof(cp));
2905
0
  cp.handle      = handle;
2906
0
  cp.which_clock = which;
2907
2908
0
  memset(&rq, 0, sizeof(rq));
2909
0
  rq.ogf    = OGF_STATUS_PARAM;
2910
0
  rq.ocf    = OCF_READ_CLOCK;
2911
0
  rq.cparam = &cp;
2912
0
  rq.clen   = READ_CLOCK_CP_SIZE;
2913
0
  rq.rparam = &rp;
2914
0
  rq.rlen   = READ_CLOCK_RP_SIZE;
2915
2916
0
  if (hci_send_req(dd, &rq, to) < 0)
2917
0
    return -1;
2918
2919
0
  if (rp.status) {
2920
0
    errno = EIO;
2921
0
    return -1;
2922
0
  }
2923
2924
0
  *clock    = rp.clock;
2925
0
  *accuracy = rp.accuracy;
2926
0
  return 0;
2927
0
}
2928
2929
int hci_le_set_scan_enable(int dd, uint8_t enable, uint8_t filter_dup, int to)
2930
0
{
2931
0
  struct hci_request rq;
2932
0
  le_set_scan_enable_cp scan_cp;
2933
0
  uint8_t status;
2934
2935
0
  memset(&scan_cp, 0, sizeof(scan_cp));
2936
0
  scan_cp.enable = enable;
2937
0
  scan_cp.filter_dup = filter_dup;
2938
2939
0
  memset(&rq, 0, sizeof(rq));
2940
0
  rq.ogf = OGF_LE_CTL;
2941
0
  rq.ocf = OCF_LE_SET_SCAN_ENABLE;
2942
0
  rq.cparam = &scan_cp;
2943
0
  rq.clen = LE_SET_SCAN_ENABLE_CP_SIZE;
2944
0
  rq.rparam = &status;
2945
0
  rq.rlen = 1;
2946
2947
0
  if (hci_send_req(dd, &rq, to) < 0)
2948
0
    return -1;
2949
2950
0
  if (status) {
2951
0
    errno = EIO;
2952
0
    return -1;
2953
0
  }
2954
2955
0
  return 0;
2956
0
}
2957
2958
int hci_le_set_scan_parameters(int dd, uint8_t type,
2959
          uint16_t interval, uint16_t window,
2960
          uint8_t own_type, uint8_t filter, int to)
2961
0
{
2962
0
  struct hci_request rq;
2963
0
  le_set_scan_parameters_cp param_cp;
2964
0
  uint8_t status;
2965
2966
0
  memset(&param_cp, 0, sizeof(param_cp));
2967
0
  param_cp.type = type;
2968
0
  param_cp.interval = interval;
2969
0
  param_cp.window = window;
2970
0
  param_cp.own_bdaddr_type = own_type;
2971
0
  param_cp.filter = filter;
2972
2973
0
  memset(&rq, 0, sizeof(rq));
2974
0
  rq.ogf = OGF_LE_CTL;
2975
0
  rq.ocf = OCF_LE_SET_SCAN_PARAMETERS;
2976
0
  rq.cparam = &param_cp;
2977
0
  rq.clen = LE_SET_SCAN_PARAMETERS_CP_SIZE;
2978
0
  rq.rparam = &status;
2979
0
  rq.rlen = 1;
2980
2981
0
  if (hci_send_req(dd, &rq, to) < 0)
2982
0
    return -1;
2983
2984
0
  if (status) {
2985
0
    errno = EIO;
2986
0
    return -1;
2987
0
  }
2988
2989
0
  return 0;
2990
0
}
2991
2992
int hci_le_set_advertise_enable(int dd, uint8_t enable, int to)
2993
0
{
2994
0
  struct hci_request rq;
2995
0
  le_set_advertise_enable_cp adv_cp;
2996
0
  uint8_t status;
2997
2998
0
  memset(&adv_cp, 0, sizeof(adv_cp));
2999
0
  adv_cp.enable = enable;
3000
3001
0
  memset(&rq, 0, sizeof(rq));
3002
0
  rq.ogf = OGF_LE_CTL;
3003
0
  rq.ocf = OCF_LE_SET_ADVERTISE_ENABLE;
3004
0
  rq.cparam = &adv_cp;
3005
0
  rq.clen = LE_SET_ADVERTISE_ENABLE_CP_SIZE;
3006
0
  rq.rparam = &status;
3007
0
  rq.rlen = 1;
3008
3009
0
  if (hci_send_req(dd, &rq, to) < 0)
3010
0
    return -1;
3011
3012
0
  if (status) {
3013
0
    errno = EIO;
3014
0
    return -1;
3015
0
  }
3016
3017
0
  return 0;
3018
0
}
3019
3020
int hci_le_create_conn(int dd, uint16_t interval, uint16_t window,
3021
    uint8_t initiator_filter, uint8_t peer_bdaddr_type,
3022
    bdaddr_t peer_bdaddr, uint8_t own_bdaddr_type,
3023
    uint16_t min_interval, uint16_t max_interval,
3024
    uint16_t latency, uint16_t supervision_timeout,
3025
    uint16_t min_ce_length, uint16_t max_ce_length,
3026
    uint16_t *handle, int to)
3027
0
{
3028
0
  struct hci_request rq;
3029
0
  le_create_connection_cp create_conn_cp;
3030
0
  evt_le_connection_complete conn_complete_rp;
3031
3032
0
  memset(&create_conn_cp, 0, sizeof(create_conn_cp));
3033
0
  create_conn_cp.interval = interval;
3034
0
  create_conn_cp.window = window;
3035
0
  create_conn_cp.initiator_filter = initiator_filter;
3036
0
  create_conn_cp.peer_bdaddr_type = peer_bdaddr_type;
3037
0
  create_conn_cp.peer_bdaddr = peer_bdaddr;
3038
0
  create_conn_cp.own_bdaddr_type = own_bdaddr_type;
3039
0
  create_conn_cp.min_interval = min_interval;
3040
0
  create_conn_cp.max_interval = max_interval;
3041
0
  create_conn_cp.latency = latency;
3042
0
  create_conn_cp.supervision_timeout = supervision_timeout;
3043
0
  create_conn_cp.min_ce_length = min_ce_length;
3044
0
  create_conn_cp.max_ce_length = max_ce_length;
3045
3046
0
  memset(&rq, 0, sizeof(rq));
3047
0
  rq.ogf = OGF_LE_CTL;
3048
0
  rq.ocf = OCF_LE_CREATE_CONN;
3049
0
  rq.event = EVT_LE_CONN_COMPLETE;
3050
0
  rq.cparam = &create_conn_cp;
3051
0
  rq.clen = LE_CREATE_CONN_CP_SIZE;
3052
0
  rq.rparam = &conn_complete_rp;
3053
0
  rq.rlen = EVT_CONN_COMPLETE_SIZE;
3054
3055
0
  if (hci_send_req(dd, &rq, to) < 0)
3056
0
    return -1;
3057
3058
0
  if (conn_complete_rp.status) {
3059
0
    errno = EIO;
3060
0
    return -1;
3061
0
  }
3062
3063
0
  if (handle)
3064
0
    *handle = conn_complete_rp.handle;
3065
3066
0
  return 0;
3067
0
}
3068
3069
int hci_le_conn_update(int dd, uint16_t handle, uint16_t min_interval,
3070
      uint16_t max_interval, uint16_t latency,
3071
      uint16_t supervision_timeout, int to)
3072
0
{
3073
0
  evt_le_connection_update_complete evt;
3074
0
  le_connection_update_cp cp;
3075
0
  struct hci_request rq;
3076
3077
0
  memset(&cp, 0, sizeof(cp));
3078
0
  cp.handle = handle;
3079
0
  cp.min_interval = min_interval;
3080
0
  cp.max_interval = max_interval;
3081
0
  cp.latency = latency;
3082
0
  cp.supervision_timeout = supervision_timeout;
3083
0
  cp.min_ce_length = htobs(0x0001);
3084
0
  cp.max_ce_length = htobs(0x0001);
3085
3086
0
  memset(&rq, 0, sizeof(rq));
3087
0
  rq.ogf = OGF_LE_CTL;
3088
0
  rq.ocf = OCF_LE_CONN_UPDATE;
3089
0
  rq.cparam = &cp;
3090
0
  rq.clen = LE_CONN_UPDATE_CP_SIZE;
3091
0
  rq.event = EVT_LE_CONN_UPDATE_COMPLETE;
3092
0
  rq.rparam = &evt;
3093
0
  rq.rlen = sizeof(evt);
3094
3095
0
  if (hci_send_req(dd, &rq, to) < 0)
3096
0
    return -1;
3097
3098
0
  if (evt.status) {
3099
0
    errno = EIO;
3100
0
    return -1;
3101
0
  }
3102
3103
0
  return 0;
3104
0
}
3105
3106
int hci_le_read_remote_features(int dd, uint16_t handle, uint8_t *features, int to)
3107
0
{
3108
0
  evt_le_read_remote_used_features_complete rp;
3109
0
  le_read_remote_used_features_cp cp;
3110
0
  struct hci_request rq;
3111
3112
0
  memset(&cp, 0, sizeof(cp));
3113
0
  cp.handle = handle;
3114
3115
0
  memset(&rq, 0, sizeof(rq));
3116
0
  rq.ogf    = OGF_LE_CTL;
3117
0
  rq.ocf    = OCF_LE_READ_REMOTE_USED_FEATURES;
3118
0
  rq.event  = EVT_LE_READ_REMOTE_USED_FEATURES_COMPLETE;
3119
0
  rq.cparam = &cp;
3120
0
  rq.clen   = LE_READ_REMOTE_USED_FEATURES_CP_SIZE;
3121
0
  rq.rparam = &rp;
3122
0
  rq.rlen   = EVT_LE_READ_REMOTE_USED_FEATURES_COMPLETE_SIZE;
3123
3124
0
  if (hci_send_req(dd, &rq, to) < 0)
3125
0
    return -1;
3126
3127
0
  if (rp.status) {
3128
0
    errno = EIO;
3129
0
    return -1;
3130
0
  }
3131
3132
0
  if (features)
3133
0
    memcpy(features, rp.features, 8);
3134
3135
0
  return 0;
3136
0
}