⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hcitool.c

📁 这是Linux环境下的蓝牙源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * *  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 <ctype.h>#include <fcntl.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <getopt.h>#include <sys/param.h>#include <sys/ioctl.h>#include <sys/socket.h>#include <bluetooth/bluetooth.h>#include <bluetooth/hci.h>#include <bluetooth/hci_lib.h>#include "textfile.h"#include "oui.h"#define for_each_opt(opt, long, short) while ((opt=getopt_long(argc, argv, short ? short:"+", long, NULL)) != -1)static void usage(void);static int dev_info(int s, int dev_id, long arg){	struct hci_dev_info di = { dev_id: dev_id };	char addr[18];	if (ioctl(s, HCIGETDEVINFO, (void *) &di))		return 0;	ba2str(&di.bdaddr, addr);	printf("\t%s\t%s\n", di.name, addr);	return 0;}static char *type2str(uint8_t type){	switch (type) {	case SCO_LINK:		return "SCO";	case ACL_LINK:		return "ACL";	case ESCO_LINK:		return "eSCO";	default:		return "Unknown";	}}static int conn_list(int s, int dev_id, long arg){	struct hci_conn_list_req *cl;	struct hci_conn_info *ci;	int id = arg;	int i;	if (id != -1 && dev_id != id)		return 0;	if (!(cl = malloc(10 * sizeof(*ci) + sizeof(*cl)))) {		perror("Can't allocate memory");		exit(1);	}	cl->dev_id = dev_id;	cl->conn_num = 10;	ci = cl->conn_info;	if (ioctl(s, HCIGETCONNLIST, (void *) cl)) {		perror("Can't get connection list");		exit(1);	}	for (i = 0; i < cl->conn_num; i++, ci++) {		char addr[18];		ba2str(&ci->bdaddr, addr);		printf("\t%s %s %s handle %d state %d lm %s\n",			ci->out ? "<" : ">", type2str(ci->type),			addr, ci->handle, ci->state,			hci_lmtostr(ci->link_mode));	}	return 0;}static int find_conn(int s, int dev_id, long arg){	struct hci_conn_list_req *cl;	struct hci_conn_info *ci;	int i;	if (!(cl = malloc(10 * sizeof(*ci) + sizeof(*cl)))) {		perror("Can't allocate memory");		exit(1);	}	cl->dev_id = dev_id;	cl->conn_num = 10;	ci = cl->conn_info;	if (ioctl(s, HCIGETCONNLIST, (void *) cl)) {		perror("Can't get connection list");		exit(1);	}	for (i = 0; i < cl->conn_num; i++, ci++)		if (!bacmp((bdaddr_t *) arg, &ci->bdaddr))			return 1;	return 0;}static void hex_dump(char *pref, int width, unsigned char *buf, int len){	register int i,n;	for (i = 0, n = 1; i < len; i++, n++) {		if (n == 1)			printf("%s", pref);		printf("%2.2X ", buf[i]);		if (n == width) {			printf("\n");			n = 0;		}	}	if (i && n!=1)		printf("\n");}static char *get_minor_device_name(int major, int minor){	switch (major) {	case 0:	/* misc */		return "";	case 1:	/* computer */		switch(minor) {		case 0:			return "Uncategorized";		case 1:			return "Desktop workstation";		case 2:			return "Server";		case 3:			return "Laptop";		case 4:			return "Handheld";		case 5:			return "Palm";		case 6:			return "Wearable";		}		break;	case 2:	/* phone */		switch(minor) {		case 0:			return "Uncategorized";		case 1:			return "Cellular";		case 2:			return "Cordless";		case 3:			return "Smart phone";		case 4:			return "Wired modem or voice gateway";		case 5:			return "Common ISDN Access";		case 6:			return "Sim Card Reader";		}		break;	case 3:	/* lan access */		if (minor == 0)			return "Uncategorized";		switch(minor / 8) {		case 0:			return "Fully available";		case 1:			return "1-17% utilized";		case 2:			return "17-33% utilized";		case 3:			return "33-50% utilized";		case 4:			return "50-67% utilized";		case 5:			return "67-83% utilized";		case 6:			return "83-99% utilized";		case 7:			return "No service available";		}		break;	case 4:	/* audio/video */		switch(minor) {		case 0:			return "Uncategorized";		case 1:			return "Device conforms to the Headset profile";		case 2:			return "Hands-free";			/* 3 is reserved */		case 4:			return "Microphone";		case 5:			return "Loudspeaker";		case 6:			return "Headphones";		case 7:			return "Portable Audio";		case 8:			return "Car Audio";		case 9:			return "Set-top box";		case 10:			return "HiFi Audio Device";		case 11:			return "VCR";		case 12:			return "Video Camera";		case 13:			return "Camcorder";		case 14:			return "Video Monitor";		case 15:			return "Video Display and Loudspeaker";		case 16:			return "Video Conferencing";			/* 17 is reserved */		case 18:			return "Gaming/Toy";		}		break;	case 5:	/* peripheral */ {		static char cls_str[48]; cls_str[0] = 0;		switch(minor & 48) {		case 16:			strncpy(cls_str, "Keyboard", sizeof(cls_str));			break;		case 32:			strncpy(cls_str, "Pointing device", sizeof(cls_str));			break;		case 48:			strncpy(cls_str, "Combo keyboard/pointing device", sizeof(cls_str));			break;		}		if((minor & 15) && (strlen(cls_str) > 0))			strcat(cls_str, "/");		switch(minor & 15) {		case 0:			break;		case 1:			strncat(cls_str, "Joystick", sizeof(cls_str) - strlen(cls_str));			break;		case 2:			strncat(cls_str, "Gamepad", sizeof(cls_str) - strlen(cls_str));			break;		case 3:			strncat(cls_str, "Remote control", sizeof(cls_str) - strlen(cls_str));			break;		case 4:			strncat(cls_str, "Sensing device", sizeof(cls_str) - strlen(cls_str));			break;		case 5:			strncat(cls_str, "Digitizer tablet", sizeof(cls_str) - strlen(cls_str));		break;		case 6:			strncat(cls_str, "Card reader", sizeof(cls_str) - strlen(cls_str));			break;		default:			strncat(cls_str, "(reserved)", sizeof(cls_str) - strlen(cls_str));			break;		}		if(strlen(cls_str) > 0)			return cls_str;	}	case 6:	/* imaging */		if (minor & 4)			return "Display";		if (minor & 8)			return "Camera";		if (minor & 16)			return "Scanner";		if (minor & 32)			return "Printer";		break;	case 7: /* wearable */		switch(minor) {		case 1:			return "Wrist Watch";		case 2:			return "Pager";		case 3:			return "Jacket";		case 4:			return "Helmet";		case 5:			return "Glasses";		}		break;	case 8: /* toy */		switch(minor) {		case 1:			return "Robot";		case 2:			return "Vehicle";		case 3:			return "Doll / Action Figure";		case 4:			return "Controller";		case 5:			return "Game";		}		break;	case 63:	/* uncategorised */		return "";	}	return "Unknown (reserved) minor device class";}static char *major_classes[] = {	"Miscellaneous", "Computer", "Phone", "LAN Access",	"Audio/Video", "Peripheral", "Imaging", "Uncategorized"};static char *get_device_name(const bdaddr_t *local, const bdaddr_t *peer){	char filename[PATH_MAX + 1], addr[18];	ba2str(local, addr);	create_name(filename, PATH_MAX, STORAGEDIR, addr, "names");	ba2str(peer, addr);	return textfile_get(filename, addr);}/* Display local devices */static struct option dev_options[] = {	{ "help",	0, 0, 'h' },	{0, 0, 0, 0 }};static char *dev_help =	"Usage:\n"	"\tdev\n";static void cmd_dev(int dev_id, int argc, char **argv){	int opt;	for_each_opt(opt, dev_options, NULL) {		switch (opt) {		default:			printf(dev_help);			return;		}	}	printf("Devices:\n");	hci_for_each_dev(HCI_UP, dev_info, 0);}/* Inquiry */static struct option inq_options[] = {	{ "help",	0, 0, 'h' },	{ "length",	1, 0, 'l' },	{ "numrsp",	1, 0, 'n' },	{ "iac",	1, 0, 'i' },	{ "flush",	0, 0, 'f' },	{ 0, 0, 0, 0 }};static char *inq_help =	"Usage:\n"	"\tinq [--length=N] maximum inquiry duration in 1.28 s units\n"	"\t    [--numrsp=N] specify maximum number of inquiry responses\n"	"\t    [--iac=lap]  specify the inquiry access code\n"	"\t    [--flush]    flush the inquiry cache\n";static void cmd_inq(int dev_id, int argc, char **argv){	inquiry_info *info = NULL;	uint8_t lap[3] = { 0x33, 0x8b, 0x9e };	int num_rsp, length, flags;	char addr[18];	int i, l, opt;	length  = 8;	/* ~10 seconds */	num_rsp = 0;	flags   = 0;	for_each_opt(opt, inq_options, NULL) {		switch (opt) {		case 'l':			length = atoi(optarg);			break;		case 'n':			num_rsp = atoi(optarg);			break;		case 'i':			l = strtoul(optarg, 0, 16);			if (!strcasecmp(optarg, "giac")) {				l = 0x9e8b33;			} else if (!strcasecmp(optarg, "liac")) {				l = 0x9e8b00;			} if (l < 0x9e8b00 || l > 0x9e8b3f) {				printf("Invalid access code 0x%x\n", l);				exit(1);			}			lap[0] = (l & 0xff);			lap[1] = (l >> 8) & 0xff;			lap[2] = (l >> 16) & 0xff;			break;		case 'f':			flags |= IREQ_CACHE_FLUSH;			break;		default:			printf(inq_help);			return;		}	}	printf("Inquiring ...\n");	num_rsp = hci_inquiry(dev_id, length, num_rsp, lap, &info, flags);	if (num_rsp < 0) {		perror("Inquiry failed.");		exit(1);	}	for (i = 0; i < num_rsp; i++) {		ba2str(&(info+i)->bdaddr, addr);		printf("\t%s\tclock offset: 0x%4.4x\tclass: 0x%2.2x%2.2x%2.2x\n",			addr, btohs((info+i)->clock_offset),			(info+i)->dev_class[2],			(info+i)->dev_class[1],			(info+i)->dev_class[0]);	}	bt_free(info);}/* Device scanning */static struct option scan_options[] = {	{ "help",	0, 0, 'h' },	{ "length",	1, 0, 'l' },	{ "numrsp",	1, 0, 'n' },	{ "iac",	1, 0, 'i' },	{ "flush",	0, 0, 'f' },	{ "refresh",	0, 0, 'r' },	{ "class",	0, 0, 'C' },	{ "info",	0, 0, 'I' },	{ "oui",	0, 0, 'O' },	{ "all",	0, 0, 'A' },	{ "ext",	0, 0, 'A' },	{ 0, 0, 0, 0 }};static char *scan_help =	"Usage:\n"	"\tscan [--length=N] [--numrsp=N] [--iac=lap] [--flush] [--class] [--info] [--oui] [--refresh]\n";static void cmd_scan(int dev_id, int argc, char **argv){	inquiry_info *info = NULL;	uint8_t lap[3] = { 0x33, 0x8b, 0x9e };	int num_rsp, length, flags;	uint8_t cls[3], features[8];	uint16_t handle;	char addr[18], name[249], oui[9], *comp, *tmp;	struct hci_version version;	struct hci_dev_info di;	struct hci_conn_info_req *cr;	int refresh = 0, extcls = 0, extinf = 0, extoui = 0;	int i, n, l, opt, dd, cc, nc;	length  = 8;	/* ~10 seconds */	num_rsp = 0;	flags   = 0;	for_each_opt(opt, scan_options, NULL) {		switch (opt) {		case 'l':			length = atoi(optarg);			break;		case 'n':			num_rsp = atoi(optarg);			break;		case 'i':			l = strtoul(optarg, 0, 16);			if (!strcasecmp(optarg, "giac")) {				l = 0x9e8b33;			} else if (!strcasecmp(optarg, "liac")) {				l = 0x9e8b00;			} else if (l < 0x9e8b00 || l > 0x9e8b3f) {				printf("Invalid access code 0x%x\n", l);				exit(1);			}			lap[0] = (l & 0xff);			lap[1] = (l >> 8) & 0xff;			lap[2] = (l >> 16) & 0xff;			break;		case 'f':			flags |= IREQ_CACHE_FLUSH;			break;		case 'r':			refresh = 1;			break;		case 'C':			extcls = 1;			break;		case 'I':			extinf = 1;			break;		case 'O':			extoui = 1;			break;		case 'A':			extcls = 1;			extinf = 1;			extoui = 1;			break;		default:			printf(scan_help);			return;		}	}	if (dev_id < 0) {		dev_id = hci_get_route(NULL);		if (dev_id < 0) {			perror("Device is not available");			exit(1);		}	}	if (hci_devinfo(dev_id, &di) < 0) {		perror("Can't get device info");		exit(1);	}	printf("Scanning ...\n");	num_rsp = hci_inquiry(dev_id, length, num_rsp, lap, &info, flags);	if (num_rsp < 0) {		perror("Inquiry failed");		exit(1);	}	dd = hci_open_dev(dev_id);	if (dd < 0) {		perror("HCI device open failed");		free(info);		exit(1);	}	if (extcls || extinf || extoui)		printf("\n");	for (i = 0; i < num_rsp; i++) {		if (!refresh) {			memset(name, 0, sizeof(name));			tmp = get_device_name(&di.bdaddr, &(info+i)->bdaddr);			if (tmp) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -