📄 hci.c
字号:
/* * * BlueZ - Bluetooth protocol stack for Linux * * Copyright (C) 2000-2001 Qualcomm Incorporated * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com> * Copyright (C) 2002-2008 Marcel Holtmann <marcel@holtmann.org> * * * This program 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 Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <stdio.h>#include <errno.h>#include <fcntl.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <sys/param.h>#include <sys/uio.h>#include <sys/poll.h>#include <sys/types.h>#include <sys/ioctl.h>#include <sys/socket.h>#include <bluetooth/bluetooth.h>#include <bluetooth/hci.h>#include <bluetooth/hci_lib.h>#ifndef MIN#define MIN(x, y) ((x) < (y) ? (x) : (y))#endiftypedef struct { char *str; unsigned int val;} hci_map;static char *hci_bit2str(hci_map *m, unsigned int val) { char *str = malloc(120); char *ptr = str; if (!str) return NULL; *ptr = 0; while (m->str) { if ((unsigned int) m->val & val) ptr += sprintf(ptr, "%s ", m->str); m++; } return str;}static int hci_str2bit(hci_map *map, char *str, unsigned int *val){ char *t, *ptr; hci_map *m; int set; if (!str || !(str = ptr = strdup(str))) return 0; *val = set = 0; while ((t = strsep(&ptr, ","))) { for (m = map; m->str; m++) { if (!strcasecmp(m->str, t)) { *val |= (unsigned int) m->val; set = 1; } } } free(str); return set;}static char *hci_uint2str(hci_map *m, unsigned int val) { char *str = malloc(50); char *ptr = str; if (!str) return NULL; *ptr = 0; while (m->str) { if ((unsigned int) m->val == val) { ptr += sprintf(ptr, "%s", m->str); break; } m++; } return str;}static int hci_str2uint(hci_map *map, char *str, unsigned int *val){ char *t, *ptr; hci_map *m; int set = 0; if (!str) return 0; str = ptr = strdup(str); while ((t = strsep(&ptr, ","))) { for (m = map; m->str; m++) { if (!strcasecmp(m->str,t)) { *val = (unsigned int) m->val; set = 1; break; } } } free(str); return set;}char *hci_dtypetostr(int type){ switch (type) { case HCI_VIRTUAL: return "VIRTUAL"; case HCI_USB: return "USB"; case HCI_PCCARD: return "PCCARD"; case HCI_UART: return "UART"; case HCI_RS232: return "RS232"; case HCI_PCI: return "PCI"; case HCI_SDIO: return "SDIO"; default: return "UNKNOWN"; }}/* HCI dev flags mapping */static hci_map dev_flags_map[] = { { "UP", HCI_UP }, { "INIT", HCI_INIT }, { "RUNNING", HCI_RUNNING }, { "RAW", HCI_RAW }, { "PSCAN", HCI_PSCAN }, { "ISCAN", HCI_ISCAN }, { "INQUIRY", HCI_INQUIRY }, { "AUTH", HCI_AUTH }, { "ENCRYPT", HCI_ENCRYPT }, { NULL }};char *hci_dflagstostr(uint32_t flags){ char *str = bt_malloc(50); char *ptr = str; hci_map *m = dev_flags_map; if (!str) return NULL; *ptr = 0; if (!hci_test_bit(HCI_UP, &flags)) ptr += sprintf(ptr, "DOWN "); while (m->str) { if (hci_test_bit(m->val, &flags)) ptr += sprintf(ptr, "%s ", m->str); m++; } return str;}/* HCI packet type mapping */static hci_map pkt_type_map[] = { { "DM1", HCI_DM1 }, { "DM3", HCI_DM3 }, { "DM5", HCI_DM5 }, { "DH1", HCI_DH1 }, { "DH3", HCI_DH3 }, { "DH5", HCI_DH5 }, { "HV1", HCI_HV1 }, { "HV2", HCI_HV2 }, { "HV3", HCI_HV3 }, { "2-DH1", HCI_2DH1 }, { "2-DH3", HCI_2DH3 }, { "2-DH5", HCI_2DH5 }, { "3-DH1", HCI_3DH1 }, { "3-DH3", HCI_3DH3 }, { "3-DH5", HCI_3DH5 }, { NULL }};static hci_map sco_ptype_map[] = { { "HV1", 0x0001 }, { "HV2", 0x0002 }, { "HV3", 0x0004 }, { "EV3", HCI_EV3 }, { "EV4", HCI_EV4 }, { "EV5", HCI_EV5 }, { "2-EV3", HCI_2EV3 }, { "2-EV5", HCI_2EV5 }, { "3-EV3", HCI_3EV3 }, { "3-EV5", HCI_3EV5 }, { NULL }};char *hci_ptypetostr(unsigned int ptype){ return hci_bit2str(pkt_type_map, ptype);}int hci_strtoptype(char *str, unsigned int *val){ return hci_str2bit(pkt_type_map, str, val);}char *hci_scoptypetostr(unsigned int ptype){ return hci_bit2str(sco_ptype_map, ptype);}int hci_strtoscoptype(char *str, unsigned int *val){ return hci_str2bit(sco_ptype_map, str, val);}/* Link policy mapping */static hci_map link_policy_map[] = { { "NONE", 0 }, { "RSWITCH", HCI_LP_RSWITCH }, { "HOLD", HCI_LP_HOLD }, { "SNIFF", HCI_LP_SNIFF }, { "PARK", HCI_LP_PARK }, { NULL }};char *hci_lptostr(unsigned int lp){ return hci_bit2str(link_policy_map, lp);}int hci_strtolp(char *str, unsigned int *val){ return hci_str2bit(link_policy_map, str, val);}/* Link mode mapping */static hci_map link_mode_map[] = { { "NONE", 0 }, { "ACCEPT", HCI_LM_ACCEPT }, { "MASTER", HCI_LM_MASTER }, { "AUTH", HCI_LM_AUTH }, { "ENCRYPT", HCI_LM_ENCRYPT }, { "TRUSTED", HCI_LM_TRUSTED }, { "RELIABLE", HCI_LM_RELIABLE }, { "SECURE", HCI_LM_SECURE }, { NULL }};char *hci_lmtostr(unsigned int lm){ char *s, *str = bt_malloc(50); if (!str) return NULL; *str = 0; if (!(lm & HCI_LM_MASTER)) strcpy(str, "SLAVE "); s = hci_bit2str(link_mode_map, lm); if (!s) { bt_free(str); return NULL; } strcat(str, s); free(s); return str;}int hci_strtolm(char *str, unsigned int *val){ return hci_str2bit(link_mode_map, str, val);}/* Command mapping */static hci_map commands_map[] = { { "Inquiry", 0 }, { "Inquiry Cancel", 1 }, { "Periodic Inquiry Mode", 2 }, { "Exit Periodic Inquiry Mode", 3 }, { "Create Connection", 4 }, { "Disconnect", 5 }, { "Add SCO Connection", 6 }, { "Cancel Create Connection", 7 }, { "Accept Connection Request", 8 }, { "Reject Connection Request", 9 }, { "Link Key Request Reply", 10 }, { "Link Key Request Negative Reply", 11 }, { "PIN Code Request Reply", 12 }, { "PIN Code Request Negative Reply", 13 }, { "Change Connection Packet Type", 14 }, { "Authentication Requested", 15 }, { "Set Connection Encryption", 16 }, { "Change Connection Link Key", 17 }, { "Master Link Key", 18 }, { "Remote Name Request", 19 }, { "Cancel Remote Name Request", 20 }, { "Read Remote Supported Features", 21 }, { "Read Remote Extended Features", 22 }, { "Read Remote Version Information", 23 }, { "Read Clock Offset", 24 }, { "Read LMP Handle", 25 }, { "Reserved", 26 }, { "Reserved", 27 }, { "Reserved", 28 }, { "Reserved", 29 }, { "Reserved", 30 }, { "Reserved", 31 }, { "Reserved", 32 }, { "Hold Mode", 33 }, { "Sniff Mode", 34 }, { "Exit Sniff Mode", 35 }, { "Park State", 36 }, { "Exit Park State", 37 }, { "QoS Setup", 38 }, { "Role Discovery", 39 }, { "Switch Role", 40 }, { "Read Link Policy Settings", 41 }, { "Write Link Policy Settings", 42 }, { "Read Default Link Policy Settings", 43 }, { "Write Default Link Policy Settings", 44 }, { "Flow Specification", 45 }, { "Set Event Mask", 46 }, { "Reset", 47 }, { "Set Event Filter", 48 }, { "Flush", 49 }, { "Read PIN Type", 50 }, { "Write PIN Type", 51 }, { "Create New Unit Key", 52 }, { "Read Stored Link Key", 53 }, { "Write Stored Link Key", 54 }, { "Delete Stored Link Key", 55 }, { "Write Local Name", 56 }, { "Read Local Name", 57 }, { "Read Connection Accept Timeout", 58 }, { "Write Connection Accept Timeout", 59 }, { "Read Page Timeout", 60 }, { "Write Page Timeout", 61 }, { "Read Scan Enable", 62 }, { "Write Scan Enable", 63 }, { "Read Page Scan Activity", 64 }, { "Write Page Scan Activity", 65 }, { "Read Inquiry Scan Activity", 66 }, { "Write Inquiry Scan Activity", 67 }, { "Read Authentication Enable", 68 }, { "Write Authentication Enable", 69 }, { "Read Encryption Mode", 70 }, { "Write Encryption Mode", 71 }, { "Read Class Of Device", 72 }, { "Write Class Of Device", 73 }, { "Read Voice Setting", 74 }, { "Write Voice Setting", 75 }, { "Read Automatic Flush Timeout", 76 }, { "Write Automatic Flush Timeout", 77 }, { "Read Num Broadcast Retransmissions", 78 }, { "Write Num Broadcast Retransmissions", 79 }, { "Read Hold Mode Activity", 80 }, { "Write Hold Mode Activity", 81 }, { "Read Transmit Power Level", 82 }, { "Read Synchronous Flow Control Enable", 83 }, { "Write Synchronous Flow Control Enable", 84 }, { "Set Host Controller To Host Flow Control", 85 }, { "Host Buffer Size", 86 }, { "Host Number Of Completed Packets", 87 }, { "Read Link Supervision Timeout", 88 }, { "Write Link Supervision Timeout", 89 }, { "Read Number of Supported IAC", 90 }, { "Read Current IAC LAP", 91 }, { "Write Current IAC LAP", 92 }, { "Read Page Scan Period Mode", 93 }, { "Write Page Scan Period Mode", 94 }, { "Read Page Scan Mode", 95 }, { "Write Page Scan Mode", 96 }, { "Set AFH Channel Classification", 97 }, { "Reserved", 98 }, { "Reserved", 99 }, { "Read Inquiry Scan Type", 100 }, { "Write Inquiry Scan Type", 101 }, { "Read Inquiry Mode", 102 }, { "Write Inquiry Mode", 103 }, { "Read Page Scan Type", 104 }, { "Write Page Scan Type", 105 }, { "Read AFH Channel Assessment Mode", 106 }, { "Write AFH Channel Assessment Mode", 107 }, { "Reserved", 108 }, { "Reserved", 109 }, { "Reserved", 110 }, { "Reserved", 111 }, { "Reserved", 112 }, { "Reserved", 113 }, { "Reserved", 114 }, { "Read Local Version Information", 115 }, { "Read Local Supported Commands", 116 }, { "Read Local Supported Features", 117 }, { "Read Local Extended Features", 118 }, { "Read Buffer Size", 119 }, { "Read Country Code", 120 }, { "Read BD ADDR", 121 }, { "Read Failed Contact Counter", 122 }, { "Reset Failed Contact Counter", 123 }, { "Get Link Quality", 124 }, { "Read RSSI", 125 }, { "Read AFH Channel Map", 126 }, { "Read BD Clock", 127 }, { "Read Loopback Mode", 128 }, { "Write Loopback Mode", 129 }, { "Enable Device Under Test Mode", 130 }, { "Setup Synchronous Connection", 131 }, { "Accept Synchronous Connection", 132 }, { "Reject Synchronous Connection", 133 }, { "Reserved", 134 }, { "Reserved", 135 }, { "Read Extended Inquiry Response", 136 }, { "Write Extended Inquiry Response", 137 }, { "Refresh Encryption Key", 138 }, { "Reserved", 139 }, { "Sniff Subrating", 140 }, { "Read Simple Pairing Mode", 141 }, { "Write Simple Pairing Mode", 142 }, { "Read Local OOB Data", 143 }, { "Read Inquiry Transmit Power Level", 144 }, { "Write Inquiry Transmit Power Level", 145 }, { "Read Default Erroneous Data Reporting", 146 }, { "Write Default Erroneous Data Reporting", 147 }, { "Reserved", 148 }, { "Reserved", 149 }, { "Reserved", 150 }, { "IO Capability Request Reply", 151 }, { "User Confirmation Request Reply", 152 }, { "User Confirmation Request Negative Reply", 153 }, { "User Passkey Request Reply", 154 }, { "User Passkey Request Negative Reply", 155 }, { "Remote OOB Data Request Reply", 156 }, { "Write Simple Pairing Debug Mode", 157 }, { "Enhanced Flush", 158 }, { "Remote OOB Data Request Negative Reply", 159 }, { "Reserved", 160 }, { "Reserved", 161 }, { "Send Keypress Notification", 162 }, { "IO Capabilities Response Negative Reply", 163 }, { "Reserved", 164 }, { "Reserved", 165 }, { "Reserved", 166 }, { "Reserved", 167 }, { NULL }};char *hci_cmdtostr(unsigned int cmd){ return hci_uint2str(commands_map, cmd);}char *hci_commandstostr(uint8_t *commands, char *pref, int width){ hci_map *m; char *off, *ptr, *str; int size = 10; m = commands_map; while (m->str) { if (commands[m->val / 8] & (1 << (m->val % 8))) size += strlen(m->str) + (pref ? strlen(pref) : 0) + 3; m++; } str = bt_malloc(size); if (!str) return NULL; ptr = str; *ptr = '\0'; if (pref) ptr += sprintf(ptr, "%s", pref); off = ptr; m = commands_map; while (m->str) { if (commands[m->val / 8] & (1 << (m->val % 8))) { if (strlen(off) + strlen(m->str) > width - 3) { ptr += sprintf(ptr, "\n%s", pref ? pref : ""); off = ptr; } ptr += sprintf(ptr, "'%s' ", m->str); } m++; } return str;}/* Version mapping */static hci_map ver_map[] = { { "1.0b", 0x00 }, { "1.1", 0x01 }, { "1.2", 0x02 }, { "2.0", 0x03 }, { "2.1", 0x04 }, { NULL }};char *hci_vertostr(unsigned int ver){ return hci_uint2str(ver_map, ver);}int hci_strtover(char *str, unsigned int *ver){ return hci_str2uint(ver_map, str, ver);}char *lmp_vertostr(unsigned int ver){ return hci_uint2str(ver_map, ver);}int lmp_strtover(char *str, unsigned int *ver){ return hci_str2uint(ver_map, str, ver);}/* LMP features mapping */static hci_map lmp_features_map[8][9] = { { /* Byte 0 */ { "<3-slot packets>", LMP_3SLOT }, /* Bit 0 */ { "<5-slot packets>", LMP_5SLOT }, /* Bit 1 */ { "<encryption>", LMP_ENCRYPT }, /* Bit 2 */ { "<slot offset>", LMP_SOFFSET }, /* Bit 3 */ { "<timing accuracy>", LMP_TACCURACY }, /* Bit 4 */ { "<role switch>", LMP_RSWITCH }, /* Bit 5 */ { "<hold mode>", LMP_HOLD }, /* Bit 6 */ { "<sniff mode>", LMP_SNIFF }, /* Bit 7 */ { NULL } }, { /* Byte 1 */ { "<park state>", LMP_PARK }, /* Bit 0 */ { "<RSSI>", LMP_RSSI }, /* Bit 1 */ { "<channel quality>", LMP_QUALITY }, /* Bit 2 */ { "<SCO link>", LMP_SCO }, /* Bit 3 */ { "<HV2 packets>", LMP_HV2 }, /* Bit 4 */ { "<HV3 packets>", LMP_HV3 }, /* Bit 5 */ { "<u-law log>", LMP_ULAW }, /* Bit 6 */ { "<A-law log>", LMP_ALAW }, /* Bit 7 */ { NULL } }, { /* Byte 2 */ { "<CVSD>", LMP_CVSD }, /* Bit 0 */ { "<paging scheme>", LMP_PSCHEME }, /* Bit 1 */ { "<power control>", LMP_PCONTROL }, /* Bit 2 */ { "<transparent SCO>", LMP_TRSP_SCO }, /* Bit 3 */ { "<broadcast encrypt>",LMP_BCAST_ENC }, /* Bit 7 */ { NULL } }, { /* Byte 3 */ { "<no. 24>", 0x01 }, /* Bit 0 */ { "<EDR ACL 2 Mbps>", LMP_EDR_ACL_2M }, /* Bit 1 */ { "<EDR ACL 3 Mbps>", LMP_EDR_ACL_3M }, /* Bit 2 */ { "<enhanced iscan>", LMP_ENH_ISCAN }, /* Bit 3 */ { "<interlaced iscan>", LMP_ILACE_ISCAN }, /* Bit 4 */ { "<interlaced pscan>", LMP_ILACE_PSCAN }, /* Bit 5 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -