~timchen119/+junk/bluez5-trusty

« back to all changes in this revision

Viewing changes to emulator/vhci.c

  • Committer: tim
  • Date: 2015-09-04 08:03:03 UTC
  • Revision ID: tim@tim-inspiron-5442-20150904080303-75u7z8bdsl17xz8q
* init

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *
 
3
 *  BlueZ - Bluetooth protocol stack for Linux
 
4
 *
 
5
 *  Copyright (C) 2011-2014  Intel Corporation
 
6
 *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
 
7
 *
 
8
 *
 
9
 *  This library is free software; you can redistribute it and/or
 
10
 *  modify it under the terms of the GNU Lesser General Public
 
11
 *  License as published by the Free Software Foundation; either
 
12
 *  version 2.1 of the License, or (at your option) any later version.
 
13
 *
 
14
 *  This library is distributed in the hope that it will be useful,
 
15
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
17
 *  Lesser General Public License for more details.
 
18
 *
 
19
 *  You should have received a copy of the GNU Lesser General Public
 
20
 *  License along with this library; if not, write to the Free Software
 
21
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
22
 *
 
23
 */
 
24
 
 
25
#ifdef HAVE_CONFIG_H
 
26
#include <config.h>
 
27
#endif
 
28
 
 
29
#include <stdio.h>
 
30
#include <errno.h>
 
31
#include <fcntl.h>
 
32
#include <unistd.h>
 
33
#include <stdlib.h>
 
34
#include <string.h>
 
35
#include <sys/uio.h>
 
36
 
 
37
#include "lib/bluetooth.h"
 
38
#include "lib/hci.h"
 
39
 
 
40
#include "src/shared/mainloop.h"
 
41
#include "monitor/bt.h"
 
42
#include "btdev.h"
 
43
#include "vhci.h"
 
44
 
 
45
#define uninitialized_var(x) x = x
 
46
 
 
47
struct vhci {
 
48
        enum vhci_type type;
 
49
        int fd;
 
50
        struct btdev *btdev;
 
51
};
 
52
 
 
53
static void vhci_destroy(void *user_data)
 
54
{
 
55
        struct vhci *vhci = user_data;
 
56
 
 
57
        btdev_destroy(vhci->btdev);
 
58
 
 
59
        close(vhci->fd);
 
60
 
 
61
        free(vhci);
 
62
}
 
63
 
 
64
static void vhci_write_callback(const struct iovec *iov, int iovlen,
 
65
                                                        void *user_data)
 
66
{
 
67
        struct vhci *vhci = user_data;
 
68
        ssize_t written;
 
69
 
 
70
        written = writev(vhci->fd, iov, iovlen);
 
71
        if (written < 0)
 
72
                return;
 
73
}
 
74
 
 
75
static void vhci_read_callback(int fd, uint32_t events, void *user_data)
 
76
{
 
77
        struct vhci *vhci = user_data;
 
78
        unsigned char buf[4096];
 
79
        ssize_t len;
 
80
 
 
81
        if (events & (EPOLLERR | EPOLLHUP))
 
82
                return;
 
83
 
 
84
        len = read(vhci->fd, buf, sizeof(buf));
 
85
        if (len < 1)
 
86
                return;
 
87
 
 
88
        switch (buf[0]) {
 
89
        case BT_H4_CMD_PKT:
 
90
        case BT_H4_ACL_PKT:
 
91
        case BT_H4_SCO_PKT:
 
92
                btdev_receive_h4(vhci->btdev, buf, len);
 
93
                break;
 
94
        }
 
95
}
 
96
 
 
97
struct vhci *vhci_open(enum vhci_type type)
 
98
{
 
99
        struct vhci *vhci;
 
100
        enum btdev_type uninitialized_var(btdev_type);
 
101
        unsigned char uninitialized_var(ctrl_type);
 
102
        unsigned char setup_cmd[2];
 
103
        static uint8_t id = 0x23;
 
104
 
 
105
        switch (type) {
 
106
        case VHCI_TYPE_BREDRLE:
 
107
                btdev_type = BTDEV_TYPE_BREDRLE;
 
108
                ctrl_type = HCI_BREDR;
 
109
                break;
 
110
        case VHCI_TYPE_BREDR:
 
111
                btdev_type = BTDEV_TYPE_BREDR;
 
112
                ctrl_type = HCI_BREDR;
 
113
                break;
 
114
        case VHCI_TYPE_LE:
 
115
                btdev_type = BTDEV_TYPE_LE;
 
116
                ctrl_type = HCI_BREDR;
 
117
                break;
 
118
        case VHCI_TYPE_AMP:
 
119
                btdev_type = BTDEV_TYPE_AMP;
 
120
                ctrl_type = HCI_AMP;
 
121
                break;
 
122
        }
 
123
 
 
124
        vhci = malloc(sizeof(*vhci));
 
125
        if (!vhci)
 
126
                return NULL;
 
127
 
 
128
        memset(vhci, 0, sizeof(*vhci));
 
129
        vhci->type = type;
 
130
 
 
131
        vhci->fd = open("/dev/vhci", O_RDWR | O_NONBLOCK);
 
132
        if (vhci->fd < 0) {
 
133
                free(vhci);
 
134
                return NULL;
 
135
        }
 
136
 
 
137
        setup_cmd[0] = HCI_VENDOR_PKT;
 
138
        setup_cmd[1] = ctrl_type;
 
139
 
 
140
        if (write(vhci->fd, setup_cmd, sizeof(setup_cmd)) < 0) {
 
141
                close(vhci->fd);
 
142
                free(vhci);
 
143
                return NULL;
 
144
        }
 
145
 
 
146
        vhci->btdev = btdev_create(btdev_type, id++);
 
147
        if (!vhci->btdev) {
 
148
                close(vhci->fd);
 
149
                free(vhci);
 
150
                return NULL;
 
151
        }
 
152
 
 
153
        btdev_set_send_handler(vhci->btdev, vhci_write_callback, vhci);
 
154
 
 
155
        if (mainloop_add_fd(vhci->fd, EPOLLIN, vhci_read_callback,
 
156
                                                vhci, vhci_destroy) < 0) {
 
157
                btdev_destroy(vhci->btdev);
 
158
                close(vhci->fd);
 
159
                free(vhci);
 
160
                return NULL;
 
161
        }
 
162
 
 
163
        return vhci;
 
164
}
 
165
 
 
166
void vhci_close(struct vhci *vhci)
 
167
{
 
168
        if (!vhci)
 
169
                return;
 
170
 
 
171
        mainloop_remove_fd(vhci->fd);
 
172
}