Diff between 14f601a8058b843189801c9d0a9a21664491e7d7 and d6ed61a54cccd29c7c668bc8ff9006343a658a08

Changed Files

File Additions Deletions Status
.gitignore +0 -1 modified
Makefile.tools +1 -9 modified
test/hciemu.1 +0 -31 deleted
test/hciemu.c +0 -1294 deleted

Full Patch

diff --git a/.gitignore b/.gitignore
index 5391c85..487f2fd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -54,7 +54,6 @@ tools/sdptool
 tools/avtest
 test/agent
 test/bdaddr
-test/hciemu
 test/gaptest
 test/ipctest
 test/btiotest
diff --git a/Makefile.tools b/Makefile.tools
index 57801a2..a82a3f6 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -151,13 +151,9 @@ endif
 
 
 if TEST
-bin_PROGRAMS += test/hciemu
-
 noinst_PROGRAMS += test/gaptest test/bdaddr test/agent \
 					test/btiotest test/mpris-player
 
-test_hciemu_LDADD = lib/libbluetooth-private.la
-
 test_gaptest_LDADD = @DBUS_LIBS@
 
 test_bdaddr_SOURCES = test/bdaddr.c src/oui.h src/oui.c
@@ -170,13 +166,9 @@ test_btiotest_LDADD = @GLIB_LIBS@ lib/libbluetooth-private.la
 
 test_mpris_player_SOURCES = test/mpris-player.c
 test_mpris_player_LDADD = @DBUS_LIBS@ @GLIB_LIBS@
-
-dist_man_MANS += test/hciemu.1
+endif
 
 EXTRA_DIST += test/bdaddr.1
-else
-EXTRA_DIST += test/hciemu.1 test/bdaddr.1
-endif
 
 EXTRA_DIST += test/sap_client.py test/bluezutils.py \
 		test/dbusdef.py test/monitor-bluetooth test/list-devices \
diff --git a/test/hciemu.1 b/test/hciemu.1
deleted file mode 100644
index cecaeb7..0000000
--- a/test/hciemu.1
+++ /dev/null
@@ -1,31 +0,0 @@
-.TH HCIEMU 1 "Jul 6 2009" BlueZ ""
-.SH NAME
-hciemu \- HCI emulator
-.SH SYNOPSIS
-.B hciemu
-[\fIoptions\fR] \fIlocal_address\fR
-
-.SH DESCRIPTION
-.LP
-.B
-hciemu
-is used to emulate an HCI via \fBhci_vhci\fR kernel module
-
-.SH OPTIONS
-.TP
-.BI -d\  device
-use specified \fIdevice\fR
-.TP
-.BI -b\  bdaddr
-emulate \fIbdaddr\fR
-.TP
-.BI -s\  file
-create snoop file \fIfile\fR
-.TP
-.B -n
-do not detach
-
-.SH AUTHORS
-Written by Marcel Holtmann <marcel@holtmann.org> and Maxim Krasnyansky
-<maxk@qualcomm.com>, man page by Filippo Giunchedi <filippo@debian.org>
-.PP
diff --git a/test/hciemu.c b/test/hciemu.c
deleted file mode 100644
index a125cf4..0000000
--- a/test/hciemu.c
+++ /dev/null
@@ -1,1294 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2000-2002  Maxim Krasnyansky <maxk@qualcomm.com>
- *  Copyright (C) 2003-2010  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 <stdint.h>
-#include <string.h>
-#include <signal.h>
-#include <getopt.h>
-#include <syslog.h>
-#include <sys/time.h>
-#include <sys/epoll.h>
-#include <sys/socket.h>
-#include <sys/resource.h>
-#include <sys/stat.h>
-
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/hci.h>
-#include <bluetooth/hci_lib.h>
-#include <bluetooth/l2cap.h>
-
-#define VHCI_DEV		"/dev/vhci"
-
-#define VHCI_MAX_CONN		12
-
-#define VHCI_ACL_MTU		192
-#define VHCI_ACL_MAX_PKT	8
-
-struct vhci_device {
-	uint8_t		features[8];
-	uint8_t		name[248];
-	uint8_t		dev_class[3];
-	uint8_t		scan_enable;
-	uint8_t		ssp_mode;
-	uint8_t		inq_mode;
-	uint8_t		eir_fec;
-	uint8_t		eir_data[HCI_MAX_EIR_LENGTH];
-	uint8_t		le_mode;
-	uint8_t		le_simul;
-	uint16_t	acl_cnt;
-	bdaddr_t	bdaddr;
-	int		dev_fd;
-	int		scan_fd;
-	int		dd;
-};
-
-struct vhci_conn {
-	bdaddr_t	dest;
-	uint16_t	handle;
-	int		fd;
-};
-
-struct vhci_link_info {
-	bdaddr_t	bdaddr;
-	uint8_t		dev_class[3];
-	uint8_t		link_type;
-	uint8_t		role;
-} __attribute__ ((packed));
-
-static struct vhci_device vdev;
-static struct vhci_conn *vconn[VHCI_MAX_CONN];
-
-struct btsnoop_hdr {
-	uint8_t		id[8];		/* Identification Pattern */
-	uint32_t	version;	/* Version Number = 1 */
-	uint32_t	type;		/* Datalink Type */
-} __attribute__ ((packed));
-#define BTSNOOP_HDR_SIZE (sizeof(struct btsnoop_hdr))
-
-struct btsnoop_pkt {
-	uint32_t	size;		/* Original Length */
-	uint32_t	len;		/* Included Length */
-	uint32_t	flags;		/* Packet Flags */
-	uint32_t	drops;		/* Cumulative Drops */
-	uint64_t	ts;		/* Timestamp microseconds */
-	uint8_t		data[0];	/* Packet Data */
-} __attribute__ ((packed));
-#define BTSNOOP_PKT_SIZE (sizeof(struct btsnoop_pkt))
-
-static uint8_t btsnoop_id[] = { 0x62, 0x74, 0x73, 0x6e, 0x6f, 0x6f, 0x70, 0x00 };
-
-#define MAX_EPOLL_EVENTS 10
-
-static int epoll_fd;
-
-static volatile sig_atomic_t __io_canceled = 0;
-
-static void sig_term(int sig)
-{
-	__io_canceled = 1;
-}
-
-static inline int read_n(int fd, void *buf, int len)
-{
-	register int w, t = 0;
-
-	while (!__io_canceled && len > 0) {
-		if ((w = read(fd, buf, len)) < 0 ){
-			if( errno == EINTR || errno == EAGAIN )
-				continue;
-			return -1;
-		}
-		if (!w)
-			return 0;
-		len -= w; buf += w; t += w;
-	}
-	return t;
-}
-
-/* Write exactly len bytes (Signal safe)*/
-static inline int write_n(int fd, void *buf, int len)
-{
-	register int w, t = 0;
-
-	while (!__io_canceled && len > 0) {
-		if ((w = write(fd, buf, len)) < 0 ){
-			if( errno == EINTR || errno == EAGAIN )
-				continue;
-			return -1;
-		}
-		if (!w)
-			return 0;
-		len -= w; buf += w; t += w;
-	}
-	return t;
-}
-
-static int create_snoop(char *file)
-{
-	struct btsnoop_hdr hdr;
-	int fd, len;
-
-	fd = open(file, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
-	if (fd < 0)
-		return fd;
-
-	memcpy(hdr.id, btsnoop_id, sizeof(btsnoop_id));
-	hdr.version = htonl(1);
-	hdr.type = htonl(1002);
-
-	len = write(fd, &hdr, BTSNOOP_HDR_SIZE);
-	if (len < 0) {
-		close(fd);
-		return -EIO;
-	}
-
-	if (len != BTSNOOP_HDR_SIZE) {
-		close(fd);
-		return -1;
-	}
-
-	return fd;
-}
-
-static int write_snoop(int fd, int type, int incoming,
-				unsigned char *buf, int len)
-{
-	struct btsnoop_pkt pkt;
-	struct timeval tv;
-	uint32_t size = len;
-	uint64_t ts;
-
-	if (fd < 0)
-		return -1;
-
-	memset(&tv, 0, sizeof(tv));
-	gettimeofday(&tv, NULL);
-	ts = (tv.tv_sec - 946684800ll) * 1000000ll + tv.tv_usec;
-
-	pkt.size = htonl(size);
-	pkt.len  = pkt.size;
-	pkt.flags = ntohl(incoming & 0x01);
-	pkt.drops = htonl(0);
-	pkt.ts = hton64(ts + 0x00E03AB44A676000ll);
-
-	if (type == HCI_COMMAND_PKT || type == HCI_EVENT_PKT)
-		pkt.flags |= ntohl(0x02);
-
-	if (write(fd, &pkt, BTSNOOP_PKT_SIZE) < 0)
-		return -errno;
-
-	if (write(fd, buf, size) < 0)
-		return -errno;
-
-	return 0;
-}
-
-static struct vhci_conn *conn_get_by_bdaddr(bdaddr_t *ba)
-{
-	register int i;
-
-	for (i = 0; i < VHCI_MAX_CONN; i++)
-		if (!bacmp(&vconn[i]->dest, ba))
-			return vconn[i];
-
-	return NULL;
-}
-
-static void reset_vdev(void)
-{
-	/* Device settings */
-	vdev.features[0] = 0xff;
-	vdev.features[1] = 0xff;
-	vdev.features[2] = 0x8f;
-	vdev.features[3] = 0xfe;
-	vdev.features[4] = 0x9b;
-	vdev.features[5] = 0xf9;
-	vdev.features[6] = 0x00;
-	vdev.features[7] = 0x80;
-
-	vdev.features[4] |= 0x40;	/* LE Supported */
-	vdev.features[6] |= 0x01;	/* Extended Inquiry Response */
-	vdev.features[6] |= 0x02;	/* BR/EDR and LE */
-	vdev.features[6] |= 0x08;	/* Secure Simple Pairing */
-
-	memset(vdev.name, 0, sizeof(vdev.name));
-	strncpy((char *) vdev.name, "BlueZ (Virtual HCI)",
-							sizeof(vdev.name) - 1);
-
-	vdev.dev_class[0] = 0x00;
-	vdev.dev_class[1] = 0x00;
-	vdev.dev_class[2] = 0x00;
-
-	vdev.scan_enable = 0x00;
-	vdev.ssp_mode = 0x00;
-	vdev.inq_mode = 0x00;
-	vdev.eir_fec = 0x00;
-	memset(vdev.eir_data, 0, sizeof(vdev.eir_data));
-	vdev.le_mode = 0x00;
-	vdev.le_simul = 0x00;
-}
-
-static void command_status(uint16_t ogf, uint16_t ocf, uint8_t status)
-{
-	uint8_t buf[HCI_MAX_FRAME_SIZE], *ptr = buf;
-	evt_cmd_status *cs;
-	hci_event_hdr *he;
-
-	/* Packet type */
-	*ptr++ = HCI_EVENT_PKT;
-
-	/* Event header */
-	he = (void *) ptr; ptr += HCI_EVENT_HDR_SIZE;
-
-	he->evt  = EVT_CMD_STATUS;
-	he->plen = EVT_CMD_STATUS_SIZE;
-
-	cs = (void *) ptr; ptr += EVT_CMD_STATUS_SIZE;
-
-	cs->status = status;
-	cs->ncmd   = 1;
-	cs->opcode = htobs(cmd_opcode_pack(ogf, ocf));
-
-	write_snoop(vdev.dd, HCI_EVENT_PKT, 1, buf, ptr - buf);
-
-	if (write(vdev.dev_fd, buf, ptr - buf) < 0)
-		syslog(LOG_ERR, "Can't send event: %s(%d)",
-						strerror(errno), errno);
-}
-
-static void command_complete(uint16_t ogf, uint16_t ocf, int plen, void *data)
-{
-	uint8_t buf[HCI_MAX_FRAME_SIZE], *ptr = buf;
-	evt_cmd_complete *cc;
-	hci_event_hdr *he;
-
-	/* Packet type */
-	*ptr++ = HCI_EVENT_PKT;
-
-	/* Event header */
-	he = (void *) ptr; ptr += HCI_EVENT_HDR_SIZE;
-
-	he->evt  = EVT_CMD_COMPLETE;
-	he->plen = EVT_CMD_COMPLETE_SIZE + plen;
-
-	cc = (void *) ptr; ptr += EVT_CMD_COMPLETE_SIZE;
-
-	cc->ncmd = 1;
-	cc->opcode = htobs(cmd_opcode_pack(ogf, ocf));
-
-	if (plen) {
-		memcpy(ptr, data, plen);
-		ptr += plen;
-	}
-
-	write_snoop(vdev.dd, HCI_EVENT_PKT, 1, buf, ptr - buf);
-
-	if (write(vdev.dev_fd, buf, ptr - buf) < 0)
-		syslog(LOG_ERR, "Can't send event: %s(%d)",
-						strerror(errno), errno);
-}
-
-static void connect_request(struct vhci_conn *conn)
-{
-	uint8_t buf[HCI_MAX_FRAME_SIZE], *ptr = buf;
-	evt_conn_request *cr;
-	hci_event_hdr *he;
-
-	/* Packet type */
-	*ptr++ = HCI_EVENT_PKT;
-
-	/* Event header */
-	he = (void *) ptr; ptr += HCI_EVENT_HDR_SIZE;
-
-	he->evt  = EVT_CONN_REQUEST;
-	he->plen = EVT_CONN_REQUEST_SIZE;
-
-	cr = (void *) ptr; ptr += EVT_CONN_REQUEST_SIZE;
-
-	bacpy(&cr->bdaddr, &conn->dest);
-	memset(&cr->dev_class, 0, sizeof(cr->dev_class));
-	cr->link_type = ACL_LINK;
-
-	write_snoop(vdev.dd, HCI_EVENT_PKT, 1, buf, ptr - buf);
-
-	if (write(vdev.dev_fd, buf, ptr - buf) < 0)
-		syslog(LOG_ERR, "Can't send event: %s (%d)",
-						strerror(errno), errno);
-}
-
-static void connect_complete(struct vhci_conn *conn)
-{
-	uint8_t buf[HCI_MAX_FRAME_SIZE], *ptr = buf;
-	evt_conn_complete *cc;
-	hci_event_hdr *he;
-
-	/* Packet type */
-	*ptr++ = HCI_EVENT_PKT;
-
-	/* Event header */
-	he = (void *) ptr; ptr += HCI_EVENT_HDR_SIZE;
-
-	he->evt  = EVT_CONN_COMPLETE;
-	he->plen = EVT_CONN_COMPLETE_SIZE;
-
-	cc = (void *) ptr; ptr += EVT_CONN_COMPLETE_SIZE;
-
-	bacpy(&cc->bdaddr, &conn->dest);
-	cc->status = 0x00;
-	cc->handle = htobs(conn->handle);
-	cc->link_type = ACL_LINK;
-	cc->encr_mode = 0x00;
-
-	write_snoop(vdev.dd, HCI_EVENT_PKT, 1, buf, ptr - buf);
-
-	if (write(vdev.dev_fd, buf, ptr - buf) < 0)
-		syslog(LOG_ERR, "Can't send event: %s (%d)",
-						strerror(errno), errno);
-
-	/* TODO: Add io_acl_data() handling */
-}
-
-static void disconn_complete(struct vhci_conn *conn)
-{
-	uint8_t buf[HCI_MAX_FRAME_SIZE], *ptr = buf;
-	evt_disconn_complete *dc;
-	hci_event_hdr *he;
-
-	/* Packet type */
-	*ptr++ = HCI_EVENT_PKT;
-
-	/* Event header */
-	he = (void *) ptr; ptr += HCI_EVENT_HDR_SIZE;
-
-	he->evt  = EVT_DISCONN_COMPLETE;
-	he->plen = EVT_DISCONN_COMPLETE_SIZE;
-
-	dc = (void *) ptr; ptr += EVT_DISCONN_COMPLETE_SIZE;
-
-	dc->status = 0x00;
-	dc->handle = htobs(conn->handle);
-	dc->reason = 0x00;
-
-	write_snoop(vdev.dd, HCI_EVENT_PKT, 1, buf, ptr - buf);
-
-	if (write(vdev.dev_fd, buf, ptr - buf) < 0)
-		syslog(LOG_ERR, "Can't send event: %s (%d)",
-						strerror(errno), errno);
-
-	vdev.acl_cnt = 0;
-}
-
-static void num_completed_pkts(struct vhci_conn *conn)
-{
-	uint8_t buf[HCI_MAX_FRAME_SIZE], *ptr = buf;
-	evt_num_comp_pkts *np;
-	hci_event_hdr *he;
-
-	/* Packet type */
-	*ptr++ = HCI_EVENT_PKT;
-
-	/* Event header */
-	he = (void *) ptr; ptr += HCI_EVENT_HDR_SIZE;
-
-	he->evt  = EVT_NUM_COMP_PKTS;
-	he->plen = EVT_NUM_COMP_PKTS_SIZE;
-
-	np = (void *) ptr; ptr += EVT_NUM_COMP_PKTS_SIZE;
-	np->num_hndl = 1;
-
-	bt_put_le16(conn->handle, ptr);
-	ptr += 2;
-	bt_put_le16(vdev.acl_cnt, ptr);
-	ptr += 2;
-
-	write_snoop(vdev.dd, HCI_EVENT_PKT, 1, buf, ptr - buf);
-
-	if (write(vdev.dev_fd, buf, ptr - buf) < 0)
-		syslog(LOG_ERR, "Can't send event: %s (%d)",
-						strerror(errno), errno);
-}
-
-static uint8_t scan_enable(uint8_t *data)
-{
-#if 0
-	struct epoll_event scan_event;
-	struct sockaddr_in sa;
-	bdaddr_t ba;
-	int sk, opt;
-
-	if (!(*data & SCAN_PAGE)) {
-		if (vdev.scan_fd >= 0) {
-			close(vdev.scan_fd);
-			vdev.scan_fd = -1;
-		}
-		return 0;
-	}
-
-	if (vdev.scan_fd >= 0)
-		return 0;
-
-	if ((sk = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
-		syslog(LOG_ERR, "Can't create socket: %s (%d)",
-						strerror(errno), errno);
-		return 1;
-	}
-
-	opt = 1;
-	setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
-
-	baswap(&ba, &vdev.bdaddr);
-	sa.sin_family = AF_INET;
-	memcpy(&sa.sin_addr.s_addr, &ba, sizeof(sa.sin_addr.s_addr));
-	memcpy(&sa.sin_port, &ba.b[4], sizeof(sa.sin_port));
-	if (bind(sk, (struct sockaddr *) &sa, sizeof(sa))) {
-		syslog(LOG_ERR, "Can't bind socket: %s (%d)",
-						strerror(errno), errno);
-		goto failed;
-	}
-
-	if (listen(sk, 10)) {
-		syslog(LOG_ERR, "Can't listen on socket: %s (%d)",
-						strerror(errno), errno);
-		goto failed;
-	}
-
-	memset(&scan_event, 0, sizeof(scan_event));
-	scan_event.events = EPOLLIN;
-	scan_event.data.fd = sk;
-
-	if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, sk, &scan_event) < 0) {
-		syslog(LOG_ERR, "Failed to setup scan event watch");
-		goto failed;
-	}
-
-	vdev.scan_fd = sk;
-	return 0;
-
-failed:
-	close(sk);
-	return 1;
-#endif
-
-	return data[0];
-}
-
-static void accept_connection(uint8_t *data)
-{
-	accept_conn_req_cp *cp = (void *) data;
-	struct vhci_conn *conn;
-
-	if (!(conn = conn_get_by_bdaddr(&cp->bdaddr)))
-		return;
-
-	connect_complete(conn);
-}
-
-static void close_connection(struct vhci_conn *conn)
-{
-	char addr[18];
-
-	ba2str(&conn->dest, addr);
-	syslog(LOG_INFO, "Closing connection %s handle %d",
-					addr, conn->handle);
-
-	close(conn->fd);
-
-	vconn[conn->handle - 1] = NULL;
-	disconn_complete(conn);
-	free(conn);
-}
-
-static void disconnect(uint8_t *data)
-{
-	disconnect_cp *cp = (void *) data;
-	struct vhci_conn *conn;
-	uint16_t handle;
-
-	handle = btohs(cp->handle);
-
-	if (handle > VHCI_MAX_CONN)
-		return;
-
-	if (!(conn = vconn[handle-1]))
-		return;
-
-	close_connection(conn);
-}
-
-static void create_connection(uint8_t *data)
-{
-	create_conn_cp *cp = (void *) data;
-	struct vhci_link_info info;
-	struct vhci_conn *conn;
-	struct sockaddr_in sa;
-	int h, sk, opt;
-	bdaddr_t ba;
-
-	for (h = 0; h < VHCI_MAX_CONN; h++)
-		if (!vconn[h])
-			goto do_connect;
-
-	syslog(LOG_ERR, "Too many connections");
-	return;
-
-do_connect:
-	if ((sk = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
-		syslog(LOG_ERR, "Can't create socket: %s (%d)",
-						strerror(errno), errno);
-		return;
-	}
-
-	opt = 1;
-	setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
-
-	baswap(&ba, &vdev.bdaddr);
-	sa.sin_family = AF_INET;
-	sa.sin_addr.s_addr = INADDR_ANY;	// *(uint32_t *) &ba;
-	sa.sin_port = 0;			// *(uint16_t *) &ba.b[4];
-	if (bind(sk, (struct sockaddr *) &sa, sizeof(sa))) {
-		syslog(LOG_ERR, "Can't bind socket: %s (%d)",
-						strerror(errno), errno);
-		close(sk);
-		return;
-	}
-
-	baswap(&ba, &cp->bdaddr);
-	sa.sin_family = AF_INET;
-	memcpy(&sa.sin_addr.s_addr, &ba, sizeof(sa.sin_addr.s_addr));
-	memcpy(&sa.sin_port, &ba.b[4], sizeof(sa.sin_port));
-	if (connect(sk, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
-		syslog(LOG_ERR, "Can't connect: %s (%d)",
-						strerror(errno), errno);
-		close(sk);
-		return;
-	}
-
-	/* Send info */
-	memset(&info, 0, sizeof(info));
-	bacpy(&info.bdaddr, &vdev.bdaddr);
-	info.link_type = ACL_LINK;
-	info.role = 1;
-	write_n(sk, (void *) &info, sizeof(info));
-
-	if (!(conn = malloc(sizeof(*conn)))) {
-		syslog(LOG_ERR, "Can't alloc new connection: %s (%d)",
-						strerror(errno), errno);
-		close(sk);
-		return;
-	}
-
-	memcpy((uint8_t *) &ba, (uint8_t *) &sa.sin_addr, 4);
-	memcpy((uint8_t *) &ba.b[4], (uint8_t *) &sa.sin_port, 2);
-	baswap(&conn->dest, &ba);
-
-	vconn[h] = conn;
-	conn->handle = h + 1;
-	conn->fd = sk;
-
-	connect_complete(conn);
-}
-
-static void hci_link_control(uint16_t ocf, int plen, uint8_t *data)
-{
-	const uint16_t ogf = OGF_LINK_CTL;
-
-	switch (ocf) {
-	case OCF_CREATE_CONN:
-		command_status(ogf, ocf, 0x00);
-		create_connection(data);
-		break;
-
-	case OCF_ACCEPT_CONN_REQ:
-		command_status(ogf, ocf, 0x00);
-		accept_connection(data);
-		break;
-
-	case OCF_DISCONNECT:
-		command_status(ogf, ocf, 0x00);
-		disconnect(data);
-		break;
-
-	default:
-		command_status(ogf, ocf, 0x01);
-		break;
-	}
-}
-
-static void hci_link_policy(uint16_t ocf, int plen, uint8_t *data)
-{
-	const uint16_t ogf = OGF_INFO_PARAM;
-
-	switch (ocf) {
-	default:
-		command_status(ogf, ocf, 0x01);
-		break;
-	}
-}
-
-static void hci_host_control(uint16_t ocf, int plen, uint8_t *data)
-{
-	read_scan_enable_rp se;
-	read_local_name_rp ln;
-	read_class_of_dev_rp cd;
-	read_inquiry_mode_rp im;
-	read_ext_inquiry_response_rp ir;
-	read_simple_pairing_mode_rp pm;
-	read_le_host_supported_rp hs;
-	uint8_t status;
-
-	const uint16_t ogf = OGF_HOST_CTL;
-
-	switch (ocf) {
-	case OCF_RESET:
-		status = 0x00;
-		reset_vdev();
-		command_complete(ogf, ocf, 1, &status);
-		break;
-
-	case OCF_SET_EVENT_FLT:
-		status = 0x00;
-		command_complete(ogf, ocf, 1, &status);
-		break;
-
-	case OCF_CHANGE_LOCAL_NAME:
-		status = 0x00;
-		memcpy(vdev.name, data, sizeof(vdev.name));
-		command_complete(ogf, ocf, 1, &status);
-		break;
-
-	case OCF_READ_LOCAL_NAME:
-		ln.status = 0x00;
-		memcpy(ln.name, vdev.name, sizeof(ln.name));
-		command_complete(ogf, ocf, sizeof(ln), &ln);
-		break;
-
-	case OCF_WRITE_CONN_ACCEPT_TIMEOUT:
-	case OCF_WRITE_PAGE_TIMEOUT:
-		status = 0x00;
-		command_complete(ogf, ocf, 1, &status);
-		break;
-
-	case OCF_READ_SCAN_ENABLE:
-		se.status = 0x00;
-		se.enable = vdev.scan_enable;
-		command_complete(ogf, ocf, sizeof(se), &se);
-		break;
-
-	case OCF_WRITE_SCAN_ENABLE:
-		status = 0x00;
-		vdev.scan_enable = scan_enable(data);
-		command_complete(ogf, ocf, 1, &status);
-		break;
-
-	case OCF_WRITE_AUTH_ENABLE:
-		status = 0x00;
-		command_complete(ogf, ocf, 1, &status);
-		break;
-
-	case OCF_WRITE_ENCRYPT_MODE:
-		status = 0x00;
-		command_complete(ogf, ocf, 1, &status);
-		break;
-
-	case OCF_READ_CLASS_OF_DEV:
-		cd.status = 0x00;
-		memcpy(cd.dev_class, vdev.dev_class, 3);
-		command_complete(ogf, ocf, sizeof(cd), &cd);
-		break;
-
-	case OCF_WRITE_CLASS_OF_DEV:
-		status = 0x00;
-		memcpy(vdev.dev_class, data, 3);
-		command_complete(ogf, ocf, 1, &status);
-		break;
-
-	case OCF_READ_INQUIRY_MODE:
-		im.status = 0x00;
-		im.mode = vdev.inq_mode;
-		command_complete(ogf, ocf, sizeof(im), &im);
-		break;
-
-	case OCF_WRITE_INQUIRY_MODE:
-		status = 0x00;
-		vdev.inq_mode = data[0];
-		command_complete(ogf, ocf, 1, &status);
-		break;
-
-	case OCF_READ_EXT_INQUIRY_RESPONSE:
-		ir.status = 0x00;
-		ir.fec = vdev.eir_fec;
-		memcpy(ir.data, vdev.eir_data, HCI_MAX_EIR_LENGTH);
-		command_complete(ogf, ocf, sizeof(ir), &ir);
-		break;
-
-	case OCF_WRITE_EXT_INQUIRY_RESPONSE:
-		status = 0x00;
-		vdev.eir_fec = data[0];
-		memcpy(vdev.eir_data, data + 1, HCI_MAX_EIR_LENGTH);
-		command_complete(ogf, ocf, 1, &status);
-		break;
-
-	case OCF_READ_SIMPLE_PAIRING_MODE:
-		pm.status = 0x00;
-		pm.mode = vdev.ssp_mode;
-		command_complete(ogf, ocf, sizeof(pm), &pm);
-		break;
-
-	case OCF_WRITE_SIMPLE_PAIRING_MODE:
-		status = 0x00;
-		vdev.ssp_mode = data[0];
-		command_complete(ogf, ocf, 1, &status);
-		break;
-
-	case OCF_READ_LE_HOST_SUPPORTED:
-		hs.status = 0x00;
-		hs.le = vdev.le_mode;
-		hs.simul = vdev.le_simul;
-		command_complete(ogf, ocf, sizeof(hs), &hs);
-		break;
-
-	case OCF_WRITE_LE_HOST_SUPPORTED:
-		status = 0x00;
-		vdev.le_mode = data[0];
-		vdev.le_simul = data[1];
-		command_complete(ogf, ocf, 1, &status);
-		break;
-
-	default:
-		command_status(ogf, ocf, 0x01);
-		break;
-	}
-}
-
-static void hci_info_param(uint16_t ocf, int plen, uint8_t *data)
-{
-	read_local_version_rp lv;
-	read_local_features_rp lf;
-	read_local_ext_features_rp ef;
-	read_buffer_size_rp bs;
-	read_bd_addr_rp ba;
-
-	const uint16_t ogf = OGF_INFO_PARAM;
-
-	switch (ocf) {
-	case OCF_READ_LOCAL_VERSION:
-		lv.status = 0x00;
-		lv.hci_ver = 0x06;
-		lv.hci_rev = htobs(0x0000);
-		lv.lmp_ver = 0x06;
-		lv.manufacturer = htobs(63);
-		lv.lmp_subver = htobs(0x0000);
-		command_complete(ogf, ocf, sizeof(lv), &lv);
-		break;
-
-	case OCF_READ_LOCAL_FEATURES:
-		lf.status = 0x00;
-		memcpy(lf.features, vdev.features, 8);
-		command_complete(ogf, ocf, sizeof(lf), &lf);
-		break;
-
-	case OCF_READ_LOCAL_EXT_FEATURES:
-		ef.status = 0x00;
-		if (*data == 0) {
-			ef.page_num = 0;
-			ef.max_page_num = 1;
-			memcpy(ef.features, vdev.features, 8);
-		} else if (*data == 1) {
-			ef.page_num = 1;
-			ef.max_page_num = 1;
-			memset(ef.features, 0, 8);
-			ef.features[0] |= (!!vdev.ssp_mode << 0);
-			ef.features[0] |= (!!vdev.le_mode << 1);
-			ef.features[0] |= (!!vdev.le_simul << 2);
-		} else {
-			ef.page_num = *data;
-			ef.max_page_num = 0;
-			memset(ef.features, 0, 8);
-		}
-		command_complete(ogf, ocf, sizeof(ef), &ef);
-		break;
-
-	case OCF_READ_BUFFER_SIZE:
-		bs.status = 0x00;
-		bs.acl_mtu = htobs(VHCI_ACL_MTU);
-		bs.sco_mtu = 0;
-		bs.acl_max_pkt = htobs(VHCI_ACL_MAX_PKT);
-		bs.sco_max_pkt = htobs(0);
-		command_complete(ogf, ocf, sizeof(bs), &bs);
-		break;
-
-	case OCF_READ_BD_ADDR:
-		ba.status = 0x00;
-		bacpy(&ba.bdaddr, &vdev.bdaddr);
-		command_complete(ogf, ocf, sizeof(ba), &ba);
-		break;
-
-	default:
-		command_status(ogf, ocf, 0x01);
-		break;
-	}
-}
-
-static void hci_status_param(uint16_t ocf, int plen, uint8_t *data)
-{
-	read_local_amp_info_rp ai;
-
-	const uint16_t ogf = OGF_STATUS_PARAM;
-
-	switch (ocf) {
-	case OCF_READ_LOCAL_AMP_INFO:
-		memset(&ai, 0, sizeof(ai));
-
-		/* BT only */
-		ai.amp_status = 0x01;
-		ai.max_pdu_size = htobl(L2CAP_DEFAULT_MTU);
-		ai.controller_type = HCI_AMP;
-		ai.max_amp_assoc_length = htobl(HCI_MAX_ACL_SIZE);
-		/* No flushing at all */
-		ai.max_flush_timeout = 0xFFFFFFFF;
-		ai.best_effort_flush_timeout = 0xFFFFFFFF;
-
-		command_complete(ogf, ocf, sizeof(ai), &ai);
-		break;
-
-	default:
-		command_status(ogf, ocf, 0x01);
-		break;
-	}
-}
-
-static void hci_le_control(uint16_t ocf, int plen, uint8_t *data)
-{
-	le_read_buffer_size_rp bs;
-
-	const uint16_t ogf = OGF_LE_CTL;
-
-	switch (ocf) {
-	case OCF_LE_READ_BUFFER_SIZE:
-		bs.status = 0;
-		bs.pkt_len = htobs(VHCI_ACL_MTU);
-		bs.max_pkt = htobs(VHCI_ACL_MAX_PKT);
-		command_complete(ogf, ocf, sizeof(bs), &bs);
-		break;
-
-	default:
-		command_status(ogf, ocf, 0x01);
-		break;
-	}
-}
-
-static void hci_command(uint8_t *data)
-{
-	hci_command_hdr *ch;
-	uint8_t *ptr = data;
-	uint16_t ogf, ocf;
-
-	ch = (hci_command_hdr *) ptr;
-	ptr += HCI_COMMAND_HDR_SIZE;
-
-	ch->opcode = btohs(ch->opcode);
-	ogf = cmd_opcode_ogf(ch->opcode);
-	ocf = cmd_opcode_ocf(ch->opcode);
-
-	switch (ogf) {
-	case OGF_LINK_CTL:
-		hci_link_control(ocf, ch->plen, ptr);
-		break;
-
-	case OGF_LINK_POLICY:
-		hci_link_policy(ocf, ch->plen, ptr);
-		break;
-
-	case OGF_HOST_CTL:
-		hci_host_control(ocf, ch->plen, ptr);
-		break;
-
-	case OGF_INFO_PARAM:
-		hci_info_param(ocf, ch->plen, ptr);
-		break;
-
-	case OGF_STATUS_PARAM:
-		hci_status_param(ocf, ch->plen, ptr);
-		break;
-
-	case OGF_LE_CTL:
-		hci_le_control(ocf, ch->plen, ptr);
-		break;
-
-	default:
-		command_status(ogf, ocf, 0x01);
-		break;
-	}
-}
-
-static void hci_acl_data(uint8_t *data)
-{
-	hci_acl_hdr *ah = (void *) data;
-	struct vhci_conn *conn;
-	uint16_t handle;
-
-	handle = acl_handle(btohs(ah->handle));
-
-	if (handle > VHCI_MAX_CONN || !(conn = vconn[handle - 1])) {
-		syslog(LOG_ERR, "Bad connection handle %d", handle);
-		return;
-	}
-
-	if (write_n(conn->fd, data, btohs(ah->dlen) + HCI_ACL_HDR_SIZE) < 0) {
-		close_connection(conn);
-		return;
-	}
-
-	if (++vdev.acl_cnt > VHCI_ACL_MAX_PKT - 1) {
-		/* Send num of complete packets event */
-		num_completed_pkts(conn);
-		vdev.acl_cnt = 0;
-	}
-}
-
-#if 0
-static void io_acl_data(void *data)
-{
-	struct vhci_conn *conn = data;
-	unsigned char buf[HCI_MAX_FRAME_SIZE], *ptr;
-	hci_acl_hdr *ah;
-	uint16_t flags;
-	int len;
-
-	ptr = buf + 1;
-	if (read_n(conn->fd, ptr, HCI_ACL_HDR_SIZE) <= 0) {
-		close_connection(conn);
-		return;
-	}
-
-	ah = (void *) ptr;
-	ptr += HCI_ACL_HDR_SIZE;
-
-	len = btohs(ah->dlen);
-	if (read_n(conn->fd, ptr, len) <= 0) {
-		close_connection(conn);
-		return;
-	}
-
-	buf[0] = HCI_ACLDATA_PKT;
-
-	flags = acl_flags(btohs(ah->handle));
-	ah->handle = htobs(acl_handle_pack(conn->handle, flags));
-	len += HCI_ACL_HDR_SIZE + 1;
-
-	write_snoop(vdev.dd, HCI_ACLDATA_PKT, 1, buf, len);
-
-	if (write(vdev.dev_fd, buf, len) < 0)
-		syslog(LOG_ERR, "ACL data write error");
-}
-#endif
-
-static void io_conn_ind(void)
-{
-	struct vhci_link_info info;
-	struct vhci_conn *conn;
-	struct sockaddr_in sa;
-	socklen_t len;
-	int nsk, h;
-
-	len = sizeof(sa);
-	if ((nsk = accept(vdev.scan_fd, (struct sockaddr *) &sa, &len)) < 0)
-		return;
-
-	if (read_n(nsk, &info, sizeof(info)) < 0) {
-		syslog(LOG_ERR, "Can't read link info");
-		return;
-	}
-
-	if (!(conn = malloc(sizeof(*conn)))) {
-		syslog(LOG_ERR, "Can't alloc new connection");
-		close(nsk);
-		return;
-	}
-
-	bacpy(&conn->dest, &info.bdaddr);
-
-	for (h = 0; h < VHCI_MAX_CONN; h++)
-		if (!vconn[h])
-			goto accepted;
-
-	syslog(LOG_ERR, "Too many connections");
-	free(conn);
-	close(nsk);
-	return;
-
-accepted:
-	vconn[h] = conn;
-	conn->handle = h + 1;
-	conn->fd = nsk;
-	connect_request(conn);
-}
-
-static void io_hci_data(void)
-{
-	unsigned char buf[HCI_MAX_FRAME_SIZE], *ptr;
-	int type;
-	ssize_t len;
-
-	ptr = buf;
-
-	len = read(vdev.dev_fd, buf, sizeof(buf));
-	if (len < 0) {
-		if (errno == EAGAIN)
-			return;
-
-		syslog(LOG_ERR, "Read failed: %s (%d)", strerror(errno), errno);
-		__io_canceled = 1;
-		return;
-	}
-
-	type = *ptr++;
-
-	write_snoop(vdev.dd, type, 0, buf, len);
-
-	switch (type) {
-	case HCI_COMMAND_PKT:
-		hci_command(ptr);
-		break;
-
-	case HCI_ACLDATA_PKT:
-		hci_acl_data(ptr);
-		break;
-
-	default:
-		syslog(LOG_ERR, "Unknown packet type 0x%2.2x", type);
-		break;
-	}
-}
-
-static int getbdaddrbyname(char *str, bdaddr_t *ba)
-{
-	int i, n, len;
-
-	len = strlen(str);
-
-	/* Check address format */
-	for (i = 0, n = 0; i < len; i++)
-		if (str[i] == ':')
-			n++;
-
-	if (n == 5) {
-		/* BD address */
-		str2ba(str, ba);
-		return 0;
-	}
-
-	if (n == 0) {
-		/* loopback port */
-		in_addr_t addr = INADDR_LOOPBACK;
-		uint16_t be16 = htons(atoi(str));
-		bdaddr_t b;
-
-		memcpy(&b, &addr, 4);
-		memcpy(&b.b[4], &be16, sizeof(be16));
-		baswap(ba, &b);
-
-		return 0;
-	}
-
-	fprintf(stderr, "Invalid address format\n");
-
-	return -1;
-}
-
-static void usage(void)
-{
-	printf("hciemu - HCI emulator ver %s\n", VERSION);
-	printf("Usage: \n");
-	printf("\thciemu [options] port_number\n"
-		"Options:\n"
-		"\t[-d device] use specified device node\n"
-		"\t[-s file] create snoop file\n"
-		"\t[-n] do not detach\n"
-		"\t[-h] help, you are looking at it\n");
-}
-
-static const struct option options[] = {
-	{ "device",	1, 0, 'd' },
-	{ "bdaddr",	1, 0, 'b' },
-	{ "snoop",	1, 0, 's' },
-	{ "nodetach",	0, 0, 'n' },
-	{ "help",	0, 0, 'h' },
-	{ }
-};
-
-int main(int argc, char *argv[])
-{
-	int exitcode = EXIT_FAILURE;
-	struct sigaction sa;
-	char *device = NULL, *snoop = NULL;
-	int device_fd;
-	struct epoll_event device_event;
-	int dd, opt, detach = 1;
-
-	while ((opt=getopt_long(argc, argv, "d:s:nh", options, NULL)) != EOF) {
-		switch(opt) {
-		case 'd':
-			device = strdup(optarg);
-			break;
-		case 's':
-			snoop = strdup(optarg);
-			break;
-		case 'n':
-			detach = 0;
-			break;
-		case 'h':
-			usage();
-			exit(0);
-		default:
-			usage();
-			exit(1);
-		}
-	}
-
-	argc -= optind;
-	argv += optind;
-	optind = 0;
-
-	if (argc < 1) {
-		usage();
-		exit(1);
-	}
-
-	if (getbdaddrbyname(argv[0], &vdev.bdaddr) < 0)
-		exit(1);
-
-	if (detach) {
-		if (daemon(0, 0)) {
-			perror("Can't start daemon");
-			exit(1);
-		}
-	}
-
-	/* Start logging to syslog and stderr */
-	openlog("hciemu", LOG_PID | LOG_NDELAY | LOG_PERROR, LOG_DAEMON);
-	syslog(LOG_INFO, "HCI emulation daemon ver %s started", VERSION);
-
-	memset(&sa, 0, sizeof(sa));
-	sa.sa_flags   = SA_NOCLDSTOP;
-	sa.sa_handler = SIG_IGN;
-	sigaction(SIGCHLD, &sa, NULL);
-	sigaction(SIGPIPE, &sa, NULL);
-
-	sa.sa_handler = sig_term;
-	sigaction(SIGTERM, &sa, NULL);
-	sigaction(SIGINT,  &sa, NULL);
-
-	if (!device)
-		device = strdup(VHCI_DEV);
-
-	/* Open and create virtual HCI device */
-	device_fd = open(device, O_RDWR);
-	if (device_fd < 0) {
-		syslog(LOG_ERR, "Can't open device %s: %s (%d)",
-					device, strerror(errno), errno);
-		free(device);
-		return exitcode;
-	}
-
-	free(device);
-
-	/* Create snoop file */
-	if (snoop) {
-		dd = create_snoop(snoop);
-		if (dd < 0)
-			syslog(LOG_ERR, "Can't create snoop file %s: %s (%d)",
-						snoop, strerror(errno), errno);
-		free(snoop);
-	} else
-		dd = -1;
-
-	/* Create event loop */
-	epoll_fd = epoll_create1(EPOLL_CLOEXEC);
-	if (epoll_fd < 0) {
-		perror("Failed to create epoll descriptor");
-		goto close_device;
-	}
-
-	reset_vdev();
-
-	vdev.dev_fd = device_fd;
-	vdev.dd = dd;
-
-	memset(&device_event, 0, sizeof(device_event));
-	device_event.events = EPOLLIN;
-	device_event.data.fd = device_fd;
-
-	if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, device_fd, &device_event) < 0) {
-		perror("Failed to setup device event watch");
-		goto close_device;
-	}
-
-	setpriority(PRIO_PROCESS, 0, -19);
-
-	/* Start event processor */
-	for (;;) {
-		struct epoll_event events[MAX_EPOLL_EVENTS];
-		int n, nfds;
-
-		if (__io_canceled)
-			break;
-
-		nfds = epoll_wait(epoll_fd, events, MAX_EPOLL_EVENTS, -1);
-		if (nfds < 0)
-			continue;
-
-		for (n = 0; n < nfds; n++) {
-			if (events[n].data.fd == vdev.dev_fd)
-				io_hci_data();
-			else if (events[n].data.fd == vdev.scan_fd)
-				io_conn_ind();
-		}
-	}
-
-	exitcode = EXIT_SUCCESS;
-
-	epoll_ctl(epoll_fd, EPOLL_CTL_DEL, device_fd, NULL);
-
-close_device:
-	close(device_fd);
-
-	if (dd >= 0)
-		close(dd);
-
-	close(epoll_fd);
-
-	syslog(LOG_INFO, "Exit");
-
-	return exitcode;
-}