Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/usr.sbin/bluetooth/hccontrol/send_recv.c
106138 views
1
/*-
2
* send_recv.c
3
*
4
* SPDX-License-Identifier: BSD-2-Clause
5
*
6
* Copyright (c) 2001-2002 Maksim Yevmenkin <[email protected]>
7
* All rights reserved.
8
*
9
* Redistribution and use in source and binary forms, with or without
10
* modification, are permitted provided that the following conditions
11
* are met:
12
* 1. Redistributions of source code must retain the above copyright
13
* notice, this list of conditions and the following disclaimer.
14
* 2. Redistributions in binary form must reproduce the above copyright
15
* notice, this list of conditions and the following disclaimer in the
16
* documentation and/or other materials provided with the distribution.
17
*
18
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
* SUCH DAMAGE.
29
*
30
* $Id: send_recv.c,v 1.2 2003/05/21 22:40:30 max Exp $
31
*/
32
33
#include <sys/types.h>
34
#include <sys/socket.h>
35
#include <sys/time.h>
36
#include <sys/endian.h>
37
#include <assert.h>
38
#include <errno.h>
39
#include <netgraph/bluetooth/include/ng_hci.h>
40
#include <string.h>
41
#include <unistd.h>
42
#include "hccontrol.h"
43
44
/* Send HCI request to the unit */
45
int
46
hci_request(int s, int opcode, char const *cp, int cp_size, char *rp, int *rp_size)
47
{
48
char buffer[512];
49
int n;
50
ng_hci_cmd_pkt_t *c = (ng_hci_cmd_pkt_t *) buffer;
51
ng_hci_event_pkt_t *e = (ng_hci_event_pkt_t *) buffer;
52
53
assert(rp != NULL);
54
assert(rp_size != NULL);
55
assert(*rp_size > 0);
56
57
c->type = NG_HCI_CMD_PKT;
58
c->opcode = (uint16_t) opcode;
59
c->opcode = htole16(c->opcode);
60
61
if (cp != NULL) {
62
assert(0 < cp_size && cp_size <= NG_HCI_CMD_PKT_SIZE);
63
64
c->length = (uint8_t) cp_size;
65
memcpy(buffer + sizeof(*c), cp, cp_size);
66
} else
67
c->length = 0;
68
69
if (hci_send(s, buffer, sizeof(*c) + cp_size) == ERROR)
70
return (ERROR);
71
72
again:
73
n = sizeof(buffer);
74
if (hci_recv(s, buffer, &n) == ERROR)
75
return (ERROR);
76
77
if (n < sizeof(*e)) {
78
errno = EMSGSIZE;
79
return (ERROR);
80
}
81
82
if (e->type != NG_HCI_EVENT_PKT) {
83
errno = EIO;
84
return (ERROR);
85
}
86
87
switch (e->event) {
88
case NG_HCI_EVENT_COMMAND_COMPL: {
89
ng_hci_command_compl_ep *cc =
90
(ng_hci_command_compl_ep *)(e + 1);
91
92
cc->opcode = le16toh(cc->opcode);
93
94
if (cc->opcode == 0x0000 || cc->opcode != opcode)
95
goto again;
96
97
n -= (sizeof(*e) + sizeof(*cc));
98
if (n < *rp_size)
99
*rp_size = n;
100
101
memcpy(rp, buffer + sizeof(*e) + sizeof(*cc), *rp_size);
102
} break;
103
104
case NG_HCI_EVENT_COMMAND_STATUS: {
105
ng_hci_command_status_ep *cs =
106
(ng_hci_command_status_ep *)(e + 1);
107
108
cs->opcode = le16toh(cs->opcode);
109
110
if (cs->opcode == 0x0000 || cs->opcode != opcode)
111
goto again;
112
113
*rp_size = 1;
114
*rp = cs->status;
115
} break;
116
117
default:
118
goto again;
119
}
120
121
return (OK);
122
} /* hci_request */
123
124
/* Send simple HCI request - Just HCI command packet (no parameters) */
125
int
126
hci_simple_request(int s, int opcode, char *rp, int *rp_size)
127
{
128
return (hci_request(s, opcode, NULL, 0, rp, rp_size));
129
} /* hci_simple_request */
130
131
/* Send HCI data to the unit */
132
int
133
hci_send(int s, char const *buffer, int size)
134
{
135
assert(buffer != NULL);
136
assert(size >= sizeof(ng_hci_cmd_pkt_t));
137
assert(size <= sizeof(ng_hci_cmd_pkt_t) + NG_HCI_CMD_PKT_SIZE);
138
139
if (send(s, buffer, size, 0) < 0)
140
return (ERROR);
141
142
return (OK);
143
} /* hci_send */
144
145
/* Receive HCI data from the unit */
146
int
147
hci_recv(int s, char *buffer, int *size)
148
{
149
struct timeval tv;
150
fd_set rfd;
151
int n;
152
153
assert(buffer != NULL);
154
assert(size != NULL);
155
assert(*size > sizeof(ng_hci_event_pkt_t));
156
157
again:
158
FD_ZERO(&rfd);
159
FD_SET(s, &rfd);
160
161
tv.tv_sec = timeout;
162
tv.tv_usec = 0;
163
164
n = select(s + 1, &rfd, NULL, NULL, &tv);
165
if (n <= 0) {
166
if (n < 0) {
167
if (errno == EINTR)
168
goto again;
169
} else
170
errno = ETIMEDOUT;
171
172
return (ERROR);
173
}
174
175
assert(FD_ISSET(s, &rfd));
176
177
n = recv(s, buffer, *size, 0);
178
if (n < 0)
179
return (ERROR);
180
181
*size = n;
182
183
return (OK);
184
} /* hci_recv */
185
186
187