/* Send Read_Local_Version_Information command to the unit */ static int hci_read_local_version_information(int s, int argc, char **argv) { ng_hci_read_local_ver_rp rp; int n; n = sizeof(rp); if (hci_simple_request(s, NG_HCI_OPCODE(NG_HCI_OGF_INFO, NG_HCI_OCF_READ_LOCAL_VER), (char *) &rp, &n) == ERROR) return (ERROR); if (rp.status != 0x00) { fprintf(stdout, "Status: %s [%#02x]\n", hci_status2str(rp.status), rp.status); return (FAILED); } rp.manufacturer = le16toh(rp.manufacturer); fprintf(stdout, "HCI version: %s [%#02x]\n", hci_ver2str(rp.hci_version), rp.hci_version); fprintf(stdout, "HCI revision: %#04x\n", le16toh(rp.hci_revision)); fprintf(stdout, "LMP version: %s [%#02x]\n", hci_lmpver2str(rp.lmp_version), rp.lmp_version); fprintf(stdout, "LMP sub-version: %#04x\n", le16toh(rp.lmp_subversion)); fprintf(stdout, "Manufacturer: %s [%#04x]\n", hci_manufacturer2str(rp.manufacturer), rp.manufacturer); return (OK); } /* hci_read_local_version_information */
/* Send Read_Local_Supported_Features command to the unit */ static int hci_read_local_supported_features(int s, int argc, char **argv) { ng_hci_read_local_features_rp rp; int n; char buffer[1024]; n = sizeof(rp); if (hci_simple_request(s, NG_HCI_OPCODE(NG_HCI_OGF_INFO, NG_HCI_OCF_READ_LOCAL_FEATURES), (char *) &rp, &n) == ERROR) return (ERROR); if (rp.status != 0x00) { fprintf(stdout, "Status: %s [%#02x]\n", hci_status2str(rp.status), rp.status); return (FAILED); } fprintf(stdout, "Features: "); for (n = 0; n < sizeof(rp.features); n++) fprintf(stdout, "%#02x ", rp.features[n]); fprintf(stdout, "\n%s\n", hci_features2str(rp.features, buffer, sizeof(buffer))); return (OK); } /* hci_read_local_supported_features */
/* Sent Read_Buffer_Size command to the unit */ static int hci_read_buffer_size(int s, int argc, char **argv) { ng_hci_read_buffer_size_rp rp; int n; n = sizeof(rp); if (hci_simple_request(s, NG_HCI_OPCODE(NG_HCI_OGF_INFO, NG_HCI_OCF_READ_BUFFER_SIZE), (char *) &rp, &n) == ERROR) return (ERROR); if (rp.status != 0x00) { fprintf(stdout, "Status: %s [%#02x]\n", hci_status2str(rp.status), rp.status); return (FAILED); } fprintf(stdout, "Max. ACL packet size: %d bytes\n", le16toh(rp.max_acl_size)); fprintf(stdout, "Number of ACL packets: %d\n", le16toh(rp.num_acl_pkt)); fprintf(stdout, "Max. SCO packet size: %d bytes\n", rp.max_sco_size); fprintf(stdout, "Number of SCO packets: %d\n", le16toh(rp.num_sco_pkt)); return (OK); } /* hci_read_buffer_size */
/* Send Write_Link_Policy_Settings command to the unit */ static int hci_write_link_policy_settings(int s, int argc, char **argv) { ng_hci_write_link_policy_settings_cp cp; ng_hci_write_link_policy_settings_rp rp; int n; /* parse command parameters */ switch (argc) { case 2: /* connection handle */ if (sscanf(argv[0], "%d", &n) != 1 || n <= 0 || n > 0x0eff) return (USAGE); cp.con_handle = (uint16_t) (n & 0x0fff); cp.con_handle = htole16(cp.con_handle); /* link policy settings */ if (sscanf(argv[1], "%x", &n) != 1) return (USAGE); cp.settings = (uint16_t) (n & 0x0ffff); cp.settings = htole16(cp.settings); break; default: return (USAGE); } /* send request */ n = sizeof(rp); if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_LINK_POLICY, NG_HCI_OCF_WRITE_LINK_POLICY_SETTINGS), (char const *) &cp, sizeof(cp), (char *) &rp, &n) == ERROR) return (ERROR); if (rp.status != 0x00) { fprintf(stdout, "Status: %s [%#02x]\n", hci_status2str(rp.status), rp.status); return (FAILED); } return (OK); } /* hci_write_link_policy_settings */
/* Send Role Discovery to the unit */ static int hci_role_discovery(int s, int argc, char **argv) { ng_hci_role_discovery_cp cp; ng_hci_role_discovery_rp rp; int n; /* parse command parameters */ switch (argc) { case 1: /* connection handle */ if (sscanf(argv[0], "%d", &n) != 1 || n <= 0 || n > 0x0eff) return (USAGE); cp.con_handle = (uint16_t) (n & 0x0fff); cp.con_handle = htole16(cp.con_handle); break; default: return (USAGE); } /* send request */ n = sizeof(rp); if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_LINK_POLICY, NG_HCI_OCF_ROLE_DISCOVERY), (char const *) &cp, sizeof(cp), (char *) &rp, &n) == ERROR) return (ERROR); if (rp.status != 0x00) { fprintf(stdout, "Status: %s [%#02x]\n", hci_status2str(rp.status), rp.status); return (FAILED); } fprintf(stdout, "Connection handle: %d\n", le16toh(rp.con_handle)); fprintf(stdout, "Role: %s [%#x]\n", (rp.role == NG_HCI_ROLE_MASTER)? "Master" : "Slave", rp.role); return (OK); } /* hci_role_discovery */
/* Send Read_BD_ADDR command to the unit */ static int hci_read_bd_addr(int s, int argc, char **argv) { ng_hci_read_bdaddr_rp rp; int n; n = sizeof(rp); if (hci_simple_request(s, NG_HCI_OPCODE(NG_HCI_OGF_INFO, NG_HCI_OCF_READ_BDADDR), (char *) &rp, &n) == ERROR) return (ERROR); if (rp.status != 0x00) { fprintf(stdout, "Status: %s [%#02x]\n", hci_status2str(rp.status), rp.status); return (FAILED); } fprintf(stdout, "BD_ADDR: %s\n", bt_ntoa(&rp.bdaddr, NULL)); return (OK); } /* hci_read_bd_addr */
/* Send Read_Failed_Contact_Counter command to the unit */ static int hci_read_failed_contact_counter(int s, int argc, char **argv) { ng_hci_read_failed_contact_cntr_cp cp; ng_hci_read_failed_contact_cntr_rp rp; int n; switch (argc) { case 1: /* connection handle */ if (sscanf(argv[0], "%d", &n) != 1 || n <= 0 || n > 0x0eff) return (USAGE); cp.con_handle = (uint16_t) (n & 0x0fff); cp.con_handle = htole16(cp.con_handle); break; default: return (USAGE); } /* send command */ n = sizeof(rp); if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_STATUS, NG_HCI_OCF_READ_FAILED_CONTACT_CNTR), (char const *) &cp, sizeof(cp), (char *) &rp, &n) == ERROR) return (ERROR); if (rp.status != 0x00) { fprintf(stdout, "Status: %s [%#02x]\n", hci_status2str(rp.status), rp.status); return (FAILED); } fprintf(stdout, "Connection handle: %d\n", le16toh(rp.con_handle)); fprintf(stdout, "Failed contact counter: %d\n", le16toh(rp.counter)); return (OK); } /* hci_read_failed_contact_counter */
/* Sent Get_Link_Quality command to the unit */ static int hci_get_link_quality(int s, int argc, char **argv) { ng_hci_get_link_quality_cp cp; ng_hci_get_link_quality_rp rp; int n; switch (argc) { case 1: /* connection handle */ if (sscanf(argv[0], "%d", &n) != 1 || n <= 0 || n > 0x0eff) return (USAGE); cp.con_handle = (uint16_t) (n & 0x0fff); cp.con_handle = htole16(cp.con_handle); break; default: return (USAGE); } /* send command */ n = sizeof(rp); if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_STATUS, NG_HCI_OCF_GET_LINK_QUALITY), (char const *) &cp, sizeof(cp), (char *) &rp, &n) == ERROR) return (ERROR); if (rp.status != 0x00) { fprintf(stdout, "Status: %s [%#02x]\n", hci_status2str(rp.status), rp.status); return (FAILED); } fprintf(stdout, "Connection handle: %d\n", le16toh(rp.con_handle)); fprintf(stdout, "Link quality: %d\n", le16toh(rp.quality)); return (OK); } /* hci_get_link_quality */
/* Send Read_Country_Code command to the unit */ static int hci_read_country_code(int s, int argc, char **argv) { ng_hci_read_country_code_rp rp; int n; n = sizeof(rp); if (hci_simple_request(s, NG_HCI_OPCODE(NG_HCI_OGF_INFO, NG_HCI_OCF_READ_COUNTRY_CODE), (char *) &rp, &n) == ERROR) return (ERROR); if (rp.status != 0x00) { fprintf(stdout, "Status: %s [%#02x]\n", hci_status2str(rp.status), rp.status); return (FAILED); } fprintf(stdout, "Country code: %s [%#02x]\n", hci_cc2str(rp.country_code), rp.country_code); return (OK); } /* hci_read_country_code */
/* Send Create_Connection command to the unit */ static int hci_create_connection(int s, int argc, char **argv) { int n0; char b[512]; ng_hci_create_con_cp cp; ng_hci_event_pkt_t *e = (ng_hci_event_pkt_t *) b; /* Set defaults */ memset(&cp, 0, sizeof(cp)); cp.pkt_type = htole16( NG_HCI_PKT_DM1 | NG_HCI_PKT_DH1 | NG_HCI_PKT_DM3 | NG_HCI_PKT_DH3 | NG_HCI_PKT_DM5); cp.page_scan_rep_mode = NG_HCI_SCAN_REP_MODE0; cp.page_scan_mode = NG_HCI_MANDATORY_PAGE_SCAN_MODE; cp.clock_offset = 0; cp.accept_role_switch = 1; /* parse command parameters */ switch (argc) { case 6: /* accept role switch */ if (sscanf(argv[5], "%d", &n0) != 1) return (USAGE); cp.accept_role_switch = n0 ? 1 : 0; case 5: /* clock offset */ if (sscanf(argv[4], "%d", &n0) != 1) return (USAGE); cp.clock_offset = (n0 & 0xffff); cp.clock_offset = htole16(cp.clock_offset); case 4: /* page scan mode */ if (sscanf(argv[3], "%d", &n0) != 1 || n0 < 0 || n0 > 3) return (USAGE); cp.page_scan_mode = (n0 & 0xff); case 3: /* page scan rep mode */ if (sscanf(argv[2], "%d", &n0) != 1 || n0 < 0 || n0 > 2) return (USAGE); cp.page_scan_rep_mode = (n0 & 0xff); case 2: /* packet type */ if (sscanf(argv[1], "%x", &n0) != 1) return (USAGE); n0 &= ( NG_HCI_PKT_DM1 | NG_HCI_PKT_DH1 | NG_HCI_PKT_DM3 | NG_HCI_PKT_DH3 | NG_HCI_PKT_DM5); if (n0 == 0) return (USAGE); cp.pkt_type = (n0 & 0xffff); cp.pkt_type = htole16(cp.pkt_type); case 1: /* BD_ADDR */ if (!bt_aton(argv[0], &cp.bdaddr)) { struct hostent *he = NULL; if ((he = bt_gethostbyname(argv[0])) == NULL) return (USAGE); memcpy(&cp.bdaddr, he->h_addr, sizeof(cp.bdaddr)); } break; default: return (USAGE); } /* send request and expect status response */ n0 = sizeof(b); if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL, NG_HCI_OCF_CREATE_CON), (char const *) &cp, sizeof(cp), b, &n0) == ERROR) return (ERROR); if (*b != 0x00) return (FAILED); /* wait for event */ again: n0 = sizeof(b); if (hci_recv(s, b, &n0) == ERROR) return (ERROR); if (n0 < sizeof(*e)) { errno = EIO; return (ERROR); } if (e->event == NG_HCI_EVENT_CON_COMPL) { ng_hci_con_compl_ep *ep = (ng_hci_con_compl_ep *)(e + 1); if (ep->status != 0x00) { fprintf(stdout, "Status: %s [%#02x]\n", hci_status2str(ep->status), ep->status); return (FAILED); } fprintf(stdout, "BD_ADDR: %s\n", hci_bdaddr2str(&ep->bdaddr)); fprintf(stdout, "Connection handle: %d\n", le16toh(ep->con_handle)); fprintf(stdout, "Encryption mode: %s [%d]\n", hci_encrypt2str(ep->encryption_mode, 0), ep->encryption_mode); } else goto again; return (OK); } /* hci_create_connection */
/* Send Swith Role to the unit */ static int hci_switch_role(int s, int argc, char **argv) { int n0; char b[512]; ng_hci_switch_role_cp cp; ng_hci_event_pkt_t *e = (ng_hci_event_pkt_t *) b; /* parse command parameters */ switch (argc) { case 2: /* bdaddr */ if (!bt_aton(argv[0], &cp.bdaddr)) { struct hostent *he = NULL; if ((he = bt_gethostbyname(argv[0])) == NULL) return (USAGE); memcpy(&cp.bdaddr, he->h_addr, sizeof(cp.bdaddr)); } /* role */ if (sscanf(argv[1], "%d", &n0) != 1) return (USAGE); cp.role = n0? NG_HCI_ROLE_SLAVE : NG_HCI_ROLE_MASTER; break; default: return (USAGE); } /* send request and expect status response */ n0 = sizeof(b); if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_LINK_POLICY, NG_HCI_OCF_SWITCH_ROLE), (char const *) &cp, sizeof(cp), b, &n0) == ERROR) return (ERROR); if (*b != 0x00) return (FAILED); /* wait for event */ again: n0 = sizeof(b); if (hci_recv(s, b, &n0) == ERROR) return (ERROR); if (n0 < sizeof(*e)) { errno = EIO; return (ERROR); } if (e->event == NG_HCI_EVENT_ROLE_CHANGE) { ng_hci_role_change_ep *ep = (ng_hci_role_change_ep *)(e + 1); if (ep->status != 0x00) { fprintf(stdout, "Status: %s [%#02x]\n", hci_status2str(ep->status), ep->status); return (FAILED); } fprintf(stdout, "BD_ADDR: %s\n", hci_bdaddr2str(&ep->bdaddr)); fprintf(stdout, "Role: %s [%#x]\n", (ep->role == NG_HCI_ROLE_MASTER)? "Master" : "Slave", ep->role); } else goto again; return (OK); } /* hci_switch_role */
/* Send Add_SCO_Connection command to the unit */ static int hci_add_sco_connection(int s, int argc, char **argv) { int n; char b[512]; ng_hci_add_sco_con_cp cp; ng_hci_event_pkt_t *e = (ng_hci_event_pkt_t *) b; /* Set defaults */ memset(&cp, 0, sizeof(cp)); cp.pkt_type = htole16(NG_HCI_PKT_HV1 | NG_HCI_PKT_HV2 | NG_HCI_PKT_HV3); /* parse command parameters */ switch (argc) { case 2: /* packet type */ if (sscanf(argv[1], "%x", &n) != 1) return (USAGE); n &= (NG_HCI_PKT_HV1 | NG_HCI_PKT_HV2 | NG_HCI_PKT_HV3); if (n == 0) return (USAGE); cp.pkt_type = (uint16_t) (n & 0x0fff); cp.pkt_type = htole16(cp.pkt_type); case 1: /* acl connection handle */ if (sscanf(argv[0], "%d", &n) != 1 || n <= 0 || n > 0x0eff) return (USAGE); cp.con_handle = (uint16_t) (n & 0x0fff); cp.con_handle = htole16(cp.con_handle); break; default: return (USAGE); } /* send request and expect status response */ n = sizeof(b); if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL, NG_HCI_OCF_ADD_SCO_CON), (char const *) &cp, sizeof(cp), b, &n) == ERROR) return (ERROR); if (*b != 0x00) return (FAILED); /* wait for event */ again: n = sizeof(b); if (hci_recv(s, b, &n) == ERROR) return (ERROR); if (n < sizeof(*e)) { errno = EIO; return (ERROR); } if (e->event == NG_HCI_EVENT_CON_COMPL) { ng_hci_con_compl_ep *ep = (ng_hci_con_compl_ep *)(e + 1); if (ep->status != 0x00) { fprintf(stdout, "Status: %s [%#02x]\n", hci_status2str(ep->status), ep->status); return (FAILED); } fprintf(stdout, "BD_ADDR: %s\n", hci_bdaddr2str(&ep->bdaddr)); fprintf(stdout, "Connection handle: %d\n", le16toh(ep->con_handle)); fprintf(stdout, "Encryption mode: %s [%d]\n", hci_encrypt2str(ep->encryption_mode, 0), ep->encryption_mode); } else goto again; return (OK); } /* Add_SCO_Connection */
/* Send Inquiry command to the unit */ static int hci_inquiry(int s, int argc, char **argv) { int n0, n1, n2, timo; char b[512]; ng_hci_inquiry_cp cp; ng_hci_event_pkt_t *e = (ng_hci_event_pkt_t *) b; /* set defaults */ cp.lap[2] = 0x9e; cp.lap[1] = 0x8b; cp.lap[0] = 0x33; cp.inquiry_length = 5; cp.num_responses = 8; /* parse command parameters */ switch (argc) { case 3: /* number of responses, range 0x00 - 0xff */ if (sscanf(argv[2], "%d", &n0) != 1 || n0 < 0 || n0 > 0xff) return (USAGE); cp.num_responses = (n0 & 0xff); case 2: /* inquiry length (N * 1.28) sec, range 0x01 - 0x30 */ if (sscanf(argv[1], "%d", &n0) != 1 || n0 < 0x1 || n0 > 0x30) return (USAGE); cp.inquiry_length = (n0 & 0xff); case 1: /* LAP */ if (sscanf(argv[0], "%x:%x:%x", &n2, &n1, &n0) != 3) return (USAGE); cp.lap[0] = (n0 & 0xff); cp.lap[1] = (n1 & 0xff); cp.lap[2] = (n2 & 0xff); case 0: /* use defaults */ break; default: return (USAGE); } /* send request and expect status back */ n0 = sizeof(b); if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL, NG_HCI_OCF_INQUIRY), (char const *) &cp, sizeof(cp), b, &n0) == ERROR) return (ERROR); if (*b != 0x00) return (FAILED); timo = timeout; timeout = cp.inquiry_length * 1.28 + 1; wait_for_more: /* wait for inquiry events */ n0 = sizeof(b); if (hci_recv(s, b, &n0) == ERROR) { timeout = timo; return (ERROR); } if (n0 < sizeof(*e)) { timeout = timo; errno = EIO; return (ERROR); } switch (e->event) { case NG_HCI_EVENT_INQUIRY_RESULT: { ng_hci_inquiry_result_ep *ir = (ng_hci_inquiry_result_ep *)(e + 1); uint8_t *r = (uint8_t *)(ir + 1); fprintf(stdout, "Inquiry result, num_responses=%d\n", ir->num_responses); for (n0 = 0; n0 < ir->num_responses; n0++) hci_inquiry_response(n0, &r); goto wait_for_more; } case NG_HCI_EVENT_INQUIRY_COMPL: fprintf(stdout, "Inquiry complete. Status: %s [%#02x]\n", hci_status2str(*(b + sizeof(*e))), *(b + sizeof(*e))); break; default: goto wait_for_more; } timeout = timo; return (OK); } /* hci_inquiry */
/* Send Change_Connection_Packet_Type command to the unit */ static int hci_change_connection_packet_type(int s, int argc, char **argv) { int n; char b[512]; ng_hci_change_con_pkt_type_cp cp; ng_hci_event_pkt_t *e = (ng_hci_event_pkt_t *) b; switch (argc) { case 2: /* connection handle */ if (sscanf(argv[0], "%d", &n) != 1 || n <= 0 || n > 0x0eff) return (USAGE); cp.con_handle = (uint16_t) (n & 0x0fff); cp.con_handle = htole16(cp.con_handle); /* packet type */ if (sscanf(argv[1], "%x", &n) != 1) return (USAGE); cp.pkt_type = (uint16_t) (n & 0xffff); cp.pkt_type = htole16(cp.pkt_type); break; default: return (USAGE); } /* send request and expect status response */ n = sizeof(b); if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL, NG_HCI_OCF_CHANGE_CON_PKT_TYPE), (char const *) &cp, sizeof(cp), b, &n) == ERROR) return (ERROR); if (*b != 0x00) return (FAILED); /* wait for event */ again: n = sizeof(b); if (hci_recv(s, b, &n) == ERROR) return (ERROR); if (n < sizeof(*e)) { errno = EIO; return (ERROR); } if (e->event == NG_HCI_EVENT_CON_PKT_TYPE_CHANGED) { ng_hci_con_pkt_type_changed_ep *ep = (ng_hci_con_pkt_type_changed_ep *)(e + 1); if (ep->status != 0x00) { fprintf(stdout, "Status: %s [%#02x]\n", hci_status2str(ep->status), ep->status); return (FAILED); } fprintf(stdout, "Connection handle: %d\n", le16toh(ep->con_handle)); fprintf(stdout, "Packet type: %#04x\n", le16toh(ep->pkt_type)); } else goto again; return (OK); } /* hci_change_connection_packet_type */
/* Send Remote_Name_Request command to the unit */ static int hci_remote_name_request(int s, int argc, char **argv) { int n0; char b[512]; ng_hci_remote_name_req_cp cp; ng_hci_event_pkt_t *e = (ng_hci_event_pkt_t *) b; memset(&cp, 0, sizeof(cp)); cp.page_scan_rep_mode = NG_HCI_SCAN_REP_MODE0; cp.page_scan_mode = NG_HCI_MANDATORY_PAGE_SCAN_MODE; /* parse command parameters */ switch (argc) { case 4: /* clock_offset */ if (sscanf(argv[3], "%x", &n0) != 1) return (USAGE); cp.clock_offset = (n0 & 0xffff); cp.clock_offset = htole16(cp.clock_offset); case 3: /* page_scan_mode */ if (sscanf(argv[2], "%d", &n0) != 1 || n0 < 0x00 || n0 > 0x03) return (USAGE); cp.page_scan_mode = (n0 & 0xff); case 2: /* page_scan_rep_mode */ if (sscanf(argv[1], "%d", &n0) != 1 || n0 < 0x00 || n0 > 0x02) return (USAGE); cp.page_scan_rep_mode = (n0 & 0xff); case 1: /* BD_ADDR */ if (!bt_aton(argv[0], &cp.bdaddr)) { struct hostent *he = NULL; if ((he = bt_gethostbyname(argv[0])) == NULL) return (USAGE); memcpy(&cp.bdaddr, he->h_addr, sizeof(cp.bdaddr)); } break; default: return (USAGE); } /* send request and expect status response */ n0 = sizeof(b); if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL, NG_HCI_OCF_REMOTE_NAME_REQ), (char const *) &cp, sizeof(cp), b, &n0) == ERROR) return (ERROR); if (*b != 0x00) return (FAILED); /* wait for event */ again: n0 = sizeof(b); if (hci_recv(s, b, &n0) == ERROR) return (ERROR); if (n0 < sizeof(*e)) { errno = EIO; return (ERROR); } if (e->event == NG_HCI_EVENT_REMOTE_NAME_REQ_COMPL) { ng_hci_remote_name_req_compl_ep *ep = (ng_hci_remote_name_req_compl_ep *)(e + 1); if (ep->status != 0x00) { fprintf(stdout, "Status: %s [%#02x]\n", hci_status2str(ep->status), ep->status); return (FAILED); } fprintf(stdout, "BD_ADDR: %s\n", hci_bdaddr2str(&ep->bdaddr)); fprintf(stdout, "Name: %s\n", ep->name); } else goto again; return (OK); } /* hci_remote_name_request */
/* Send Read_Remote_Supported_Features command to the unit */ static int hci_read_remote_supported_features(int s, int argc, char **argv) { int n; char b[512]; ng_hci_read_remote_features_cp cp; ng_hci_event_pkt_t *e = (ng_hci_event_pkt_t *) b; char buffer[1024]; /* parse command parameters */ switch (argc) { case 1: /* connecton handle */ if (sscanf(argv[0], "%d", &n) != 1 || n < 0 || n > 0x0eff) return (USAGE); cp.con_handle = (n & 0x0fff); cp.con_handle = htole16(cp.con_handle); break; default: return (USAGE); } /* send request and expect status response */ n = sizeof(b); if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL, NG_HCI_OCF_READ_REMOTE_FEATURES), (char const *) &cp, sizeof(cp), b, &n) == ERROR) return (ERROR); if (*b != 0x00) return (FAILED); /* wait for event */ again: n = sizeof(b); if (hci_recv(s, b, &n) == ERROR) return (ERROR); if (n < sizeof(*e)) { errno = EIO; return (ERROR); } if (e->event == NG_HCI_EVENT_READ_REMOTE_FEATURES_COMPL) { ng_hci_read_remote_features_compl_ep *ep = (ng_hci_read_remote_features_compl_ep *)(e + 1); if (ep->status != 0x00) { fprintf(stdout, "Status: %s [%#02x]\n", hci_status2str(ep->status), ep->status); return (FAILED); } fprintf(stdout, "Connection handle: %d\n", le16toh(ep->con_handle)); fprintf(stdout, "Features: "); for (n = 0; n < sizeof(ep->features); n++) fprintf(stdout, "%#02x ", ep->features[n]); fprintf(stdout, "\n%s\n", hci_features2str(ep->features, buffer, sizeof(buffer))); } else goto again; return (OK); } /* hci_read_remote_supported_features */
/* Send Disconnect command to the unit */ static int hci_disconnect(int s, int argc, char **argv) { int n; char b[512]; ng_hci_discon_cp cp; ng_hci_event_pkt_t *e = (ng_hci_event_pkt_t *) b; /* Set defaults */ memset(&cp, 0, sizeof(cp)); cp.reason = 0x13; /* parse command parameters */ switch (argc) { case 2: /* reason */ if (sscanf(argv[1], "%d", &n) != 1 || n <= 0x00 || n > 0xff) return (USAGE); cp.reason = (uint8_t) (n & 0xff); case 1: /* connection handle */ if (sscanf(argv[0], "%d", &n) != 1 || n <= 0 || n > 0x0eff) return (USAGE); cp.con_handle = (uint16_t) (n & 0x0fff); cp.con_handle = htole16(cp.con_handle); break; default: return (USAGE); } /* send request and expect status response */ n = sizeof(b); if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL, NG_HCI_OCF_DISCON), (char const *) &cp, sizeof(cp), b, &n) == ERROR) return (ERROR); if (*b != 0x00) return (FAILED); /* wait for event */ again: n = sizeof(b); if (hci_recv(s, b, &n) == ERROR) return (ERROR); if (n < sizeof(*e)) { errno = EIO; return (ERROR); } if (e->event == NG_HCI_EVENT_DISCON_COMPL) { ng_hci_discon_compl_ep *ep = (ng_hci_discon_compl_ep *)(e + 1); if (ep->status != 0x00) { fprintf(stdout, "Status: %s [%#02x]\n", hci_status2str(ep->status), ep->status); return (FAILED); } fprintf(stdout, "Connection handle: %d\n", le16toh(ep->con_handle)); fprintf(stdout, "Reason: %s [%#02x]\n", hci_status2str(ep->reason), ep->reason); } else goto again; return (OK); } /* hci_disconnect */
/* Send Read_Clock_Offset command to the unit */ static int hci_read_clock_offset(int s, int argc, char **argv) { int n; char b[512]; ng_hci_read_clock_offset_cp cp; ng_hci_event_pkt_t *e = (ng_hci_event_pkt_t *) b; /* parse command parameters */ switch (argc) { case 1: /* connecton handle */ if (sscanf(argv[0], "%d", &n) != 1 || n < 0 || n > 0x0eff) return (USAGE); cp.con_handle = (n & 0x0fff); cp.con_handle = htole16(cp.con_handle); break; default: return (USAGE); } /* send request and expect status response */ n = sizeof(b); if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL, NG_HCI_OCF_READ_CLOCK_OFFSET), (char const *) &cp, sizeof(cp), b, &n) == ERROR) return (ERROR); if (*b != 0x00) return (FAILED); /* wait for event */ again: n = sizeof(b); if (hci_recv(s, b, &n) == ERROR) return (ERROR); if (n < sizeof(*e)) { errno = EIO; return (ERROR); } if (e->event == NG_HCI_EVENT_READ_CLOCK_OFFSET_COMPL) { ng_hci_read_clock_offset_compl_ep *ep = (ng_hci_read_clock_offset_compl_ep *)(e + 1); if (ep->status != 0x00) { fprintf(stdout, "Status: %s [%#02x]\n", hci_status2str(ep->status), ep->status); return (FAILED); } fprintf(stdout, "Connection handle: %d\n", le16toh(ep->con_handle)); fprintf(stdout, "Clock offset: %#04x\n", le16toh(ep->clock_offset)); } else goto again; return (OK); } /* hci_read_clock_offset */
/* Send Read_Remote_Version_Information command to the unit */ static int hci_read_remote_version_information(int s, int argc, char **argv) { int n; char b[512]; ng_hci_read_remote_ver_info_cp cp; ng_hci_event_pkt_t *e = (ng_hci_event_pkt_t *) b; /* parse command parameters */ switch (argc) { case 1: /* connecton handle */ if (sscanf(argv[0], "%d", &n) != 1 || n < 0 || n > 0x0eff) return (USAGE); cp.con_handle = (n & 0x0fff); cp.con_handle = htole16(cp.con_handle); break; default: return (USAGE); } /* send request and expect status response */ n = sizeof(b); if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL, NG_HCI_OCF_READ_REMOTE_VER_INFO), (char const *) &cp, sizeof(cp), b, &n) == ERROR) return (ERROR); if (*b != 0x00) return (FAILED); /* wait for event */ again: n = sizeof(b); if (hci_recv(s, b, &n) == ERROR) return (ERROR); if (n < sizeof(*e)) { errno = EIO; return (ERROR); } if (e->event == NG_HCI_EVENT_READ_REMOTE_VER_INFO_COMPL) { ng_hci_read_remote_ver_info_compl_ep *ep = (ng_hci_read_remote_ver_info_compl_ep *)(e + 1); if (ep->status != 0x00) { fprintf(stdout, "Status: %s [%#02x]\n", hci_status2str(ep->status), ep->status); return (FAILED); } ep->manufacturer = le16toh(ep->manufacturer); fprintf(stdout, "Connection handle: %d\n", le16toh(ep->con_handle)); fprintf(stdout, "LMP version: %s [%#02x]\n", hci_lmpver2str(ep->lmp_version), ep->lmp_version); fprintf(stdout, "LMP sub-version: %#04x\n", le16toh(ep->lmp_subversion)); fprintf(stdout, "Manufacturer: %s [%#04x]\n", hci_manufacturer2str(ep->manufacturer), ep->manufacturer); } else goto again; return (OK); } /* hci_read_remote_version_information */