Blame emulator/vhci.c

Packit Service 8264ee
/*
Packit Service 8264ee
 *
Packit Service 8264ee
 *  BlueZ - Bluetooth protocol stack for Linux
Packit Service 8264ee
 *
Packit Service 8264ee
 *  Copyright (C) 2011-2014  Intel Corporation
Packit Service 8264ee
 *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
Packit Service 8264ee
 *
Packit Service 8264ee
 *
Packit Service 8264ee
 *  This library is free software; you can redistribute it and/or
Packit Service 8264ee
 *  modify it under the terms of the GNU Lesser General Public
Packit Service 8264ee
 *  License as published by the Free Software Foundation; either
Packit Service 8264ee
 *  version 2.1 of the License, or (at your option) any later version.
Packit Service 8264ee
 *
Packit Service 8264ee
 *  This library is distributed in the hope that it will be useful,
Packit Service 8264ee
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 8264ee
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 8264ee
 *  Lesser General Public License for more details.
Packit Service 8264ee
 *
Packit Service 8264ee
 *  You should have received a copy of the GNU Lesser General Public
Packit Service 8264ee
 *  License along with this library; if not, write to the Free Software
Packit Service 8264ee
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
Packit Service 8264ee
 *
Packit Service 8264ee
 */
Packit Service 8264ee
Packit Service 8264ee
#ifdef HAVE_CONFIG_H
Packit Service 8264ee
#include <config.h>
Packit Service 8264ee
#endif
Packit Service 8264ee
Packit Service 8264ee
#include <stdio.h>
Packit Service 8264ee
#include <errno.h>
Packit Service 8264ee
#include <fcntl.h>
Packit Service 8264ee
#include <unistd.h>
Packit Service 8264ee
#include <stdlib.h>
Packit Service 8264ee
#include <string.h>
Packit Service 8264ee
#include <sys/uio.h>
Packit Service 8264ee
Packit Service 8264ee
#include "lib/bluetooth.h"
Packit Service 8264ee
#include "lib/hci.h"
Packit Service 8264ee
Packit Service 8264ee
#include "src/shared/mainloop.h"
Packit Service 8264ee
#include "monitor/bt.h"
Packit Service 8264ee
#include "btdev.h"
Packit Service 8264ee
#include "vhci.h"
Packit Service 8264ee
Packit Service 8264ee
#define uninitialized_var(x) x = x
Packit Service 8264ee
Packit Service 8264ee
struct vhci {
Packit Service 8264ee
	enum vhci_type type;
Packit Service 8264ee
	int fd;
Packit Service 8264ee
	struct btdev *btdev;
Packit Service 8264ee
};
Packit Service 8264ee
Packit Service 8264ee
static void vhci_destroy(void *user_data)
Packit Service 8264ee
{
Packit Service 8264ee
	struct vhci *vhci = user_data;
Packit Service 8264ee
Packit Service 8264ee
	btdev_destroy(vhci->btdev);
Packit Service 8264ee
Packit Service 8264ee
	close(vhci->fd);
Packit Service 8264ee
Packit Service 8264ee
	free(vhci);
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static void vhci_write_callback(const struct iovec *iov, int iovlen,
Packit Service 8264ee
							void *user_data)
Packit Service 8264ee
{
Packit Service 8264ee
	struct vhci *vhci = user_data;
Packit Service 8264ee
	ssize_t written;
Packit Service 8264ee
Packit Service 8264ee
	written = writev(vhci->fd, iov, iovlen);
Packit Service 8264ee
	if (written < 0)
Packit Service 8264ee
		return;
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static void vhci_read_callback(int fd, uint32_t events, void *user_data)
Packit Service 8264ee
{
Packit Service 8264ee
	struct vhci *vhci = user_data;
Packit Service 8264ee
	unsigned char buf[4096];
Packit Service 8264ee
	ssize_t len;
Packit Service 8264ee
Packit Service 8264ee
	if (events & (EPOLLERR | EPOLLHUP))
Packit Service 8264ee
		return;
Packit Service 8264ee
Packit Service 8264ee
	len = read(vhci->fd, buf, sizeof(buf));
Packit Service 8264ee
	if (len < 1)
Packit Service 8264ee
		return;
Packit Service 8264ee
Packit Service 8264ee
	switch (buf[0]) {
Packit Service 8264ee
	case BT_H4_CMD_PKT:
Packit Service 8264ee
	case BT_H4_ACL_PKT:
Packit Service 8264ee
	case BT_H4_SCO_PKT:
Packit Service 8264ee
		btdev_receive_h4(vhci->btdev, buf, len);
Packit Service 8264ee
		break;
Packit Service 8264ee
	}
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
struct vhci *vhci_open(enum vhci_type type)
Packit Service 8264ee
{
Packit Service 8264ee
	struct vhci *vhci;
Packit Service 8264ee
	enum btdev_type uninitialized_var(btdev_type);
Packit Service 8264ee
	unsigned char uninitialized_var(ctrl_type);
Packit Service 8264ee
	unsigned char setup_cmd[2];
Packit Service 8264ee
	static uint8_t id = 0x23;
Packit Service 8264ee
Packit Service 8264ee
	switch (type) {
Packit Service 8264ee
	case VHCI_TYPE_BREDRLE:
Packit Service 8264ee
		btdev_type = BTDEV_TYPE_BREDRLE;
Packit Service 8264ee
		ctrl_type = HCI_PRIMARY;
Packit Service 8264ee
		break;
Packit Service 8264ee
	case VHCI_TYPE_BREDR:
Packit Service 8264ee
		btdev_type = BTDEV_TYPE_BREDR;
Packit Service 8264ee
		ctrl_type = HCI_PRIMARY;
Packit Service 8264ee
		break;
Packit Service 8264ee
	case VHCI_TYPE_LE:
Packit Service 8264ee
		btdev_type = BTDEV_TYPE_LE;
Packit Service 8264ee
		ctrl_type = HCI_PRIMARY;
Packit Service 8264ee
		break;
Packit Service 8264ee
	case VHCI_TYPE_AMP:
Packit Service 8264ee
		btdev_type = BTDEV_TYPE_AMP;
Packit Service 8264ee
		ctrl_type = HCI_AMP;
Packit Service 8264ee
		break;
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	vhci = malloc(sizeof(*vhci));
Packit Service 8264ee
	if (!vhci)
Packit Service 8264ee
		return NULL;
Packit Service 8264ee
Packit Service 8264ee
	memset(vhci, 0, sizeof(*vhci));
Packit Service 8264ee
	vhci->type = type;
Packit Service 8264ee
Packit Service 8264ee
	vhci->fd = open("/dev/vhci", O_RDWR | O_NONBLOCK);
Packit Service 8264ee
	if (vhci->fd < 0) {
Packit Service 8264ee
		free(vhci);
Packit Service 8264ee
		return NULL;
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	setup_cmd[0] = HCI_VENDOR_PKT;
Packit Service 8264ee
	setup_cmd[1] = ctrl_type;
Packit Service 8264ee
Packit Service 8264ee
	if (write(vhci->fd, setup_cmd, sizeof(setup_cmd)) < 0) {
Packit Service 8264ee
		close(vhci->fd);
Packit Service 8264ee
		free(vhci);
Packit Service 8264ee
		return NULL;
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	vhci->btdev = btdev_create(btdev_type, id++);
Packit Service 8264ee
	if (!vhci->btdev) {
Packit Service 8264ee
		close(vhci->fd);
Packit Service 8264ee
		free(vhci);
Packit Service 8264ee
		return NULL;
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	btdev_set_send_handler(vhci->btdev, vhci_write_callback, vhci);
Packit Service 8264ee
Packit Service 8264ee
	if (mainloop_add_fd(vhci->fd, EPOLLIN, vhci_read_callback,
Packit Service 8264ee
						vhci, vhci_destroy) < 0) {
Packit Service 8264ee
		btdev_destroy(vhci->btdev);
Packit Service 8264ee
		close(vhci->fd);
Packit Service 8264ee
		free(vhci);
Packit Service 8264ee
		return NULL;
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	return vhci;
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
void vhci_close(struct vhci *vhci)
Packit Service 8264ee
{
Packit Service 8264ee
	if (!vhci)
Packit Service 8264ee
		return;
Packit Service 8264ee
Packit Service 8264ee
	mainloop_remove_fd(vhci->fd);
Packit Service 8264ee
}