Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/netgraph/bluetooth/hci/ng_hci_cmds.c
34814 views
1
/*
2
* ng_hci_cmds.c
3
*/
4
5
/*-
6
* SPDX-License-Identifier: BSD-2-Clause
7
*
8
* Copyright (c) Maksim Yevmenkin <[email protected]>
9
* All rights reserved.
10
*
11
* Redistribution and use in source and binary forms, with or without
12
* modification, are permitted provided that the following conditions
13
* are met:
14
* 1. Redistributions of source code must retain the above copyright
15
* notice, this list of conditions and the following disclaimer.
16
* 2. Redistributions in binary form must reproduce the above copyright
17
* notice, this list of conditions and the following disclaimer in the
18
* documentation and/or other materials provided with the distribution.
19
*
20
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
* SUCH DAMAGE.
31
*
32
* $Id: ng_hci_cmds.c,v 1.4 2003/09/08 18:57:51 max Exp $
33
*/
34
35
#include <sys/param.h>
36
#include <sys/systm.h>
37
#include <sys/kernel.h>
38
#include <sys/endian.h>
39
#include <sys/malloc.h>
40
#include <sys/mbuf.h>
41
#include <sys/queue.h>
42
#include <netgraph/ng_message.h>
43
#include <netgraph/netgraph.h>
44
#include <netgraph/bluetooth/include/ng_bluetooth.h>
45
#include <netgraph/bluetooth/include/ng_hci.h>
46
#include <netgraph/bluetooth/hci/ng_hci_var.h>
47
#include <netgraph/bluetooth/hci/ng_hci_cmds.h>
48
#include <netgraph/bluetooth/hci/ng_hci_evnt.h>
49
#include <netgraph/bluetooth/hci/ng_hci_ulpi.h>
50
#include <netgraph/bluetooth/hci/ng_hci_misc.h>
51
52
/******************************************************************************
53
******************************************************************************
54
** HCI commands processing module
55
******************************************************************************
56
******************************************************************************/
57
58
#undef min
59
#define min(a, b) ((a) < (b))? (a) : (b)
60
61
static int complete_command (ng_hci_unit_p, int, struct mbuf **);
62
63
static int process_link_control_params
64
(ng_hci_unit_p, u_int16_t, struct mbuf *, struct mbuf *);
65
static int process_link_policy_params
66
(ng_hci_unit_p, u_int16_t, struct mbuf *, struct mbuf *);
67
static int process_hc_baseband_params
68
(ng_hci_unit_p, u_int16_t, struct mbuf *, struct mbuf *);
69
static int process_info_params
70
(ng_hci_unit_p, u_int16_t, struct mbuf *, struct mbuf *);
71
static int process_status_params
72
(ng_hci_unit_p, u_int16_t, struct mbuf *, struct mbuf *);
73
static int process_testing_params
74
(ng_hci_unit_p, u_int16_t, struct mbuf *, struct mbuf *);
75
static int process_le_params
76
(ng_hci_unit_p, u_int16_t, struct mbuf *, struct mbuf *);
77
78
static int process_link_control_status
79
(ng_hci_unit_p, ng_hci_command_status_ep *, struct mbuf *);
80
static int process_link_policy_status
81
(ng_hci_unit_p, ng_hci_command_status_ep *, struct mbuf *);
82
static int process_le_status
83
(ng_hci_unit_p, ng_hci_command_status_ep *, struct mbuf *);
84
85
/*
86
* Send HCI command to the driver.
87
*/
88
89
int
90
ng_hci_send_command(ng_hci_unit_p unit)
91
{
92
struct mbuf *m0 = NULL, *m = NULL;
93
int free, error = 0;
94
95
/* Check if other command is pending */
96
if (unit->state & NG_HCI_UNIT_COMMAND_PENDING)
97
return (0);
98
99
/* Check if unit can accept our command */
100
NG_HCI_BUFF_CMD_GET(unit->buffer, free);
101
if (free == 0)
102
return (0);
103
104
/* Check if driver hook is still ok */
105
if (unit->drv == NULL || NG_HOOK_NOT_VALID(unit->drv)) {
106
NG_HCI_WARN(
107
"%s: %s - hook \"%s\" is not connected or valid\n",
108
__func__, NG_NODE_NAME(unit->node), NG_HCI_HOOK_DRV);
109
110
NG_BT_MBUFQ_DRAIN(&unit->cmdq);
111
112
return (ENOTCONN);
113
}
114
115
/*
116
* Get first command from queue, give it to RAW hook then
117
* make copy of it and send it to the driver
118
*/
119
120
m0 = NG_BT_MBUFQ_FIRST(&unit->cmdq);
121
if (m0 == NULL)
122
return (0);
123
124
ng_hci_mtap(unit, m0);
125
126
m = m_dup(m0, M_NOWAIT);
127
if (m != NULL)
128
NG_SEND_DATA_ONLY(error, unit->drv, m);
129
else
130
error = ENOBUFS;
131
132
if (error != 0)
133
NG_HCI_ERR(
134
"%s: %s - could not send HCI command, error=%d\n",
135
__func__, NG_NODE_NAME(unit->node), error);
136
137
/*
138
* Even if we were not able to send command we still pretend
139
* that everything is OK and let timeout handle that.
140
*/
141
142
NG_HCI_BUFF_CMD_USE(unit->buffer, 1);
143
NG_HCI_STAT_CMD_SENT(unit->stat);
144
NG_HCI_STAT_BYTES_SENT(unit->stat, m0->m_pkthdr.len);
145
146
/*
147
* Note: ng_hci_command_timeout() will set
148
* NG_HCI_UNIT_COMMAND_PENDING flag
149
*/
150
151
ng_hci_command_timeout(unit);
152
153
return (0);
154
} /* ng_hci_send_command */
155
156
/*
157
* Process HCI Command_Compete event. Complete HCI command, and do post
158
* processing on the command parameters (cp) and command return parameters
159
* (e) if required (for example adjust state).
160
*/
161
162
int
163
ng_hci_process_command_complete(ng_hci_unit_p unit, struct mbuf *e)
164
{
165
ng_hci_command_compl_ep *ep = NULL;
166
struct mbuf *cp = NULL;
167
int error = 0;
168
169
/* Get event packet and update command buffer info */
170
NG_HCI_M_PULLUP(e, sizeof(*ep));
171
if (e == NULL)
172
return (ENOBUFS); /* XXX this is bad */
173
174
ep = mtod(e, ng_hci_command_compl_ep *);
175
NG_HCI_BUFF_CMD_SET(unit->buffer, ep->num_cmd_pkts);
176
177
/* Check for special NOOP command */
178
if (ep->opcode == 0x0000) {
179
NG_FREE_M(e);
180
goto out;
181
}
182
183
/* Try to match first command item in the queue */
184
error = complete_command(unit, ep->opcode, &cp);
185
if (error != 0) {
186
NG_FREE_M(e);
187
goto out;
188
}
189
190
/*
191
* Perform post processing on command parameters and return parameters
192
* do it only if status is OK (status == 0). Status is the first byte
193
* of any command return parameters.
194
*/
195
196
ep->opcode = le16toh(ep->opcode);
197
m_adj(e, sizeof(*ep));
198
199
if (*mtod(e, u_int8_t *) == 0) { /* XXX m_pullup here? */
200
switch (NG_HCI_OGF(ep->opcode)) {
201
case NG_HCI_OGF_LINK_CONTROL:
202
error = process_link_control_params(unit,
203
NG_HCI_OCF(ep->opcode), cp, e);
204
break;
205
206
case NG_HCI_OGF_LINK_POLICY:
207
error = process_link_policy_params(unit,
208
NG_HCI_OCF(ep->opcode), cp, e);
209
break;
210
211
case NG_HCI_OGF_HC_BASEBAND:
212
error = process_hc_baseband_params(unit,
213
NG_HCI_OCF(ep->opcode), cp, e);
214
break;
215
216
case NG_HCI_OGF_INFO:
217
error = process_info_params(unit,
218
NG_HCI_OCF(ep->opcode), cp, e);
219
break;
220
221
case NG_HCI_OGF_STATUS:
222
error = process_status_params(unit,
223
NG_HCI_OCF(ep->opcode), cp, e);
224
break;
225
226
case NG_HCI_OGF_TESTING:
227
error = process_testing_params(unit,
228
NG_HCI_OCF(ep->opcode), cp, e);
229
break;
230
case NG_HCI_OGF_LE:
231
error = process_le_params(unit,
232
NG_HCI_OCF(ep->opcode), cp, e);
233
break;
234
case NG_HCI_OGF_BT_LOGO:
235
case NG_HCI_OGF_VENDOR:
236
NG_FREE_M(cp);
237
NG_FREE_M(e);
238
break;
239
240
default:
241
NG_FREE_M(cp);
242
NG_FREE_M(e);
243
error = EINVAL;
244
break;
245
}
246
} else {
247
NG_HCI_ERR(
248
"%s: %s - HCI command failed, OGF=%#x, OCF=%#x, status=%#x\n",
249
__func__, NG_NODE_NAME(unit->node),
250
NG_HCI_OGF(ep->opcode), NG_HCI_OCF(ep->opcode),
251
*mtod(e, u_int8_t *));
252
253
NG_FREE_M(cp);
254
NG_FREE_M(e);
255
}
256
out:
257
ng_hci_send_command(unit);
258
259
return (error);
260
} /* ng_hci_process_command_complete */
261
262
/*
263
* Process HCI Command_Status event. Check the status (mst) and do post
264
* processing (if required).
265
*/
266
267
int
268
ng_hci_process_command_status(ng_hci_unit_p unit, struct mbuf *e)
269
{
270
ng_hci_command_status_ep *ep = NULL;
271
struct mbuf *cp = NULL;
272
int error = 0;
273
274
/* Update command buffer info */
275
NG_HCI_M_PULLUP(e, sizeof(*ep));
276
if (e == NULL)
277
return (ENOBUFS); /* XXX this is bad */
278
279
ep = mtod(e, ng_hci_command_status_ep *);
280
NG_HCI_BUFF_CMD_SET(unit->buffer, ep->num_cmd_pkts);
281
282
/* Check for special NOOP command */
283
if (ep->opcode == 0x0000)
284
goto out;
285
286
/* Try to match first command item in the queue */
287
error = complete_command(unit, ep->opcode, &cp);
288
if (error != 0)
289
goto out;
290
291
/*
292
* Perform post processing on HCI Command_Status event
293
*/
294
295
ep->opcode = le16toh(ep->opcode);
296
297
switch (NG_HCI_OGF(ep->opcode)) {
298
case NG_HCI_OGF_LINK_CONTROL:
299
error = process_link_control_status(unit, ep, cp);
300
break;
301
302
case NG_HCI_OGF_LINK_POLICY:
303
error = process_link_policy_status(unit, ep, cp);
304
break;
305
case NG_HCI_OGF_LE:
306
error = process_le_status(unit, ep, cp);
307
break;
308
case NG_HCI_OGF_BT_LOGO:
309
case NG_HCI_OGF_VENDOR:
310
NG_FREE_M(cp);
311
break;
312
313
case NG_HCI_OGF_HC_BASEBAND:
314
case NG_HCI_OGF_INFO:
315
case NG_HCI_OGF_STATUS:
316
case NG_HCI_OGF_TESTING:
317
default:
318
NG_FREE_M(cp);
319
error = EINVAL;
320
break;
321
}
322
out:
323
NG_FREE_M(e);
324
ng_hci_send_command(unit);
325
326
return (error);
327
} /* ng_hci_process_command_status */
328
329
/*
330
* Complete queued HCI command.
331
*/
332
333
static int
334
complete_command(ng_hci_unit_p unit, int opcode, struct mbuf **cp)
335
{
336
struct mbuf *m = NULL;
337
338
/* Check unit state */
339
if (!(unit->state & NG_HCI_UNIT_COMMAND_PENDING)) {
340
NG_HCI_ALERT(
341
"%s: %s - no pending command, state=%#x\n",
342
__func__, NG_NODE_NAME(unit->node), unit->state);
343
344
return (EINVAL);
345
}
346
347
/* Get first command in the queue */
348
m = NG_BT_MBUFQ_FIRST(&unit->cmdq);
349
if (m == NULL) {
350
NG_HCI_ALERT(
351
"%s: %s - empty command queue?!\n", __func__, NG_NODE_NAME(unit->node));
352
353
return (EINVAL);
354
}
355
356
/*
357
* Match command opcode, if does not match - do nothing and
358
* let timeout handle that.
359
*/
360
361
if (mtod(m, ng_hci_cmd_pkt_t *)->opcode != opcode) {
362
NG_HCI_ALERT(
363
"%s: %s - command queue is out of sync\n", __func__, NG_NODE_NAME(unit->node));
364
365
return (EINVAL);
366
}
367
368
/*
369
* Now we can remove command timeout, dequeue completed command
370
* and return command parameters. ng_hci_command_untimeout will
371
* drop NG_HCI_UNIT_COMMAND_PENDING flag.
372
* Note: if ng_hci_command_untimeout() fails (returns non-zero)
373
* then timeout already happened and timeout message went info node
374
* queue. In this case we ignore command completion and pretend
375
* there is a timeout.
376
*/
377
378
if (ng_hci_command_untimeout(unit) != 0)
379
return (ETIMEDOUT);
380
381
NG_BT_MBUFQ_DEQUEUE(&unit->cmdq, *cp);
382
m_adj(*cp, sizeof(ng_hci_cmd_pkt_t));
383
384
return (0);
385
} /* complete_command */
386
387
/*
388
* Process HCI command timeout
389
*/
390
391
void
392
ng_hci_process_command_timeout(node_p node, hook_p hook, void *arg1, int arg2)
393
{
394
ng_hci_unit_p unit = NULL;
395
struct mbuf *m = NULL;
396
u_int16_t opcode;
397
398
if (NG_NODE_NOT_VALID(node)) {
399
printf("%s: Netgraph node is not valid\n", __func__);
400
return;
401
}
402
403
unit = (ng_hci_unit_p) NG_NODE_PRIVATE(node);
404
405
if (unit->state & NG_HCI_UNIT_COMMAND_PENDING) {
406
unit->state &= ~NG_HCI_UNIT_COMMAND_PENDING;
407
408
NG_BT_MBUFQ_DEQUEUE(&unit->cmdq, m);
409
if (m == NULL) {
410
NG_HCI_ALERT(
411
"%s: %s - command queue is out of sync!\n", __func__, NG_NODE_NAME(unit->node));
412
413
return;
414
}
415
416
opcode = le16toh(mtod(m, ng_hci_cmd_pkt_t *)->opcode);
417
NG_FREE_M(m);
418
419
NG_HCI_ERR(
420
"%s: %s - unable to complete HCI command OGF=%#x, OCF=%#x. Timeout\n",
421
__func__, NG_NODE_NAME(unit->node), NG_HCI_OGF(opcode),
422
NG_HCI_OCF(opcode));
423
424
/* Try to send more commands */
425
NG_HCI_BUFF_CMD_SET(unit->buffer, 1);
426
ng_hci_send_command(unit);
427
} else
428
NG_HCI_ALERT(
429
"%s: %s - no pending command\n", __func__, NG_NODE_NAME(unit->node));
430
} /* ng_hci_process_command_timeout */
431
432
/*
433
* Process link command return parameters
434
*/
435
436
static int
437
process_link_control_params(ng_hci_unit_p unit, u_int16_t ocf,
438
struct mbuf *mcp, struct mbuf *mrp)
439
{
440
int error = 0;
441
442
switch (ocf) {
443
case NG_HCI_OCF_INQUIRY_CANCEL:
444
case NG_HCI_OCF_PERIODIC_INQUIRY:
445
case NG_HCI_OCF_EXIT_PERIODIC_INQUIRY:
446
case NG_HCI_OCF_LINK_KEY_REP:
447
case NG_HCI_OCF_LINK_KEY_NEG_REP:
448
case NG_HCI_OCF_PIN_CODE_REP:
449
case NG_HCI_OCF_PIN_CODE_NEG_REP:
450
/* These do not need post processing */
451
break;
452
453
case NG_HCI_OCF_INQUIRY:
454
case NG_HCI_OCF_CREATE_CON:
455
case NG_HCI_OCF_DISCON:
456
case NG_HCI_OCF_ADD_SCO_CON:
457
case NG_HCI_OCF_ACCEPT_CON:
458
case NG_HCI_OCF_REJECT_CON:
459
case NG_HCI_OCF_CHANGE_CON_PKT_TYPE:
460
case NG_HCI_OCF_AUTH_REQ:
461
case NG_HCI_OCF_SET_CON_ENCRYPTION:
462
case NG_HCI_OCF_CHANGE_CON_LINK_KEY:
463
case NG_HCI_OCF_MASTER_LINK_KEY:
464
case NG_HCI_OCF_REMOTE_NAME_REQ:
465
case NG_HCI_OCF_READ_REMOTE_FEATURES:
466
case NG_HCI_OCF_READ_REMOTE_VER_INFO:
467
case NG_HCI_OCF_READ_CLOCK_OFFSET:
468
default:
469
470
/*
471
* None of these command was supposed to generate
472
* Command_Complete event. Instead Command_Status event
473
* should have been generated and then appropriate event
474
* should have been sent to indicate the final result.
475
*/
476
477
error = EINVAL;
478
break;
479
}
480
481
NG_FREE_M(mcp);
482
NG_FREE_M(mrp);
483
484
return (error);
485
} /* process_link_control_params */
486
487
/*
488
* Process link policy command return parameters
489
*/
490
491
static int
492
process_link_policy_params(ng_hci_unit_p unit, u_int16_t ocf,
493
struct mbuf *mcp, struct mbuf *mrp)
494
{
495
int error = 0;
496
497
switch (ocf){
498
case NG_HCI_OCF_ROLE_DISCOVERY: {
499
ng_hci_role_discovery_rp *rp = NULL;
500
ng_hci_unit_con_t *con = NULL;
501
u_int16_t h;
502
503
NG_HCI_M_PULLUP(mrp, sizeof(*rp));
504
if (mrp != NULL) {
505
rp = mtod(mrp, ng_hci_role_discovery_rp *);
506
507
h = NG_HCI_CON_HANDLE(le16toh(rp->con_handle));
508
con = ng_hci_con_by_handle(unit, h);
509
if (con == NULL) {
510
NG_HCI_ALERT(
511
"%s: %s - invalid connection handle=%d\n",
512
__func__, NG_NODE_NAME(unit->node), h);
513
error = ENOENT;
514
} else if (con->link_type != NG_HCI_LINK_ACL) {
515
NG_HCI_ALERT(
516
"%s: %s - invalid link type=%d\n", __func__, NG_NODE_NAME(unit->node),
517
con->link_type);
518
error = EINVAL;
519
} else
520
con->role = rp->role;
521
} else
522
error = ENOBUFS;
523
} break;
524
525
case NG_HCI_OCF_READ_LINK_POLICY_SETTINGS:
526
case NG_HCI_OCF_WRITE_LINK_POLICY_SETTINGS:
527
/* These do not need post processing */
528
break;
529
530
case NG_HCI_OCF_HOLD_MODE:
531
case NG_HCI_OCF_SNIFF_MODE:
532
case NG_HCI_OCF_EXIT_SNIFF_MODE:
533
case NG_HCI_OCF_PARK_MODE:
534
case NG_HCI_OCF_EXIT_PARK_MODE:
535
case NG_HCI_OCF_QOS_SETUP:
536
case NG_HCI_OCF_SWITCH_ROLE:
537
default:
538
539
/*
540
* None of these command was supposed to generate
541
* Command_Complete event. Instead Command_Status event
542
* should have been generated and then appropriate event
543
* should have been sent to indicate the final result.
544
*/
545
546
error = EINVAL;
547
break;
548
}
549
550
NG_FREE_M(mcp);
551
NG_FREE_M(mrp);
552
553
return (error);
554
} /* process_link_policy_params */
555
556
/*
557
* Process HC and baseband command return parameters
558
*/
559
560
int
561
process_hc_baseband_params(ng_hci_unit_p unit, u_int16_t ocf,
562
struct mbuf *mcp, struct mbuf *mrp)
563
{
564
int error = 0;
565
566
switch (ocf) {
567
case NG_HCI_OCF_SET_EVENT_MASK:
568
case NG_HCI_OCF_SET_EVENT_FILTER:
569
case NG_HCI_OCF_FLUSH: /* XXX Do we need to handle that? */
570
case NG_HCI_OCF_READ_PIN_TYPE:
571
case NG_HCI_OCF_WRITE_PIN_TYPE:
572
case NG_HCI_OCF_CREATE_NEW_UNIT_KEY:
573
case NG_HCI_OCF_WRITE_STORED_LINK_KEY:
574
case NG_HCI_OCF_WRITE_CON_ACCEPT_TIMO:
575
case NG_HCI_OCF_WRITE_PAGE_TIMO:
576
case NG_HCI_OCF_READ_SCAN_ENABLE:
577
case NG_HCI_OCF_WRITE_SCAN_ENABLE:
578
case NG_HCI_OCF_WRITE_PAGE_SCAN_ACTIVITY:
579
case NG_HCI_OCF_WRITE_INQUIRY_SCAN_ACTIVITY:
580
case NG_HCI_OCF_READ_AUTH_ENABLE:
581
case NG_HCI_OCF_WRITE_AUTH_ENABLE:
582
case NG_HCI_OCF_READ_ENCRYPTION_MODE:
583
case NG_HCI_OCF_WRITE_ENCRYPTION_MODE:
584
case NG_HCI_OCF_WRITE_VOICE_SETTINGS:
585
case NG_HCI_OCF_READ_NUM_BROADCAST_RETRANS:
586
case NG_HCI_OCF_WRITE_NUM_BROADCAST_RETRANS:
587
case NG_HCI_OCF_READ_HOLD_MODE_ACTIVITY:
588
case NG_HCI_OCF_WRITE_HOLD_MODE_ACTIVITY:
589
case NG_HCI_OCF_READ_SCO_FLOW_CONTROL:
590
case NG_HCI_OCF_WRITE_SCO_FLOW_CONTROL:
591
case NG_HCI_OCF_H2HC_FLOW_CONTROL: /* XXX Not supported this time */
592
case NG_HCI_OCF_HOST_BUFFER_SIZE:
593
case NG_HCI_OCF_READ_IAC_LAP:
594
case NG_HCI_OCF_WRITE_IAC_LAP:
595
case NG_HCI_OCF_READ_PAGE_SCAN_PERIOD:
596
case NG_HCI_OCF_WRITE_PAGE_SCAN_PERIOD:
597
case NG_HCI_OCF_READ_PAGE_SCAN:
598
case NG_HCI_OCF_WRITE_PAGE_SCAN:
599
case NG_HCI_OCF_READ_LINK_SUPERVISION_TIMO:
600
case NG_HCI_OCF_WRITE_LINK_SUPERVISION_TIMO:
601
case NG_HCI_OCF_READ_SUPPORTED_IAC_NUM:
602
case NG_HCI_OCF_READ_STORED_LINK_KEY:
603
case NG_HCI_OCF_DELETE_STORED_LINK_KEY:
604
case NG_HCI_OCF_READ_CON_ACCEPT_TIMO:
605
case NG_HCI_OCF_READ_PAGE_TIMO:
606
case NG_HCI_OCF_READ_PAGE_SCAN_ACTIVITY:
607
case NG_HCI_OCF_READ_INQUIRY_SCAN_ACTIVITY:
608
case NG_HCI_OCF_READ_VOICE_SETTINGS:
609
case NG_HCI_OCF_READ_AUTO_FLUSH_TIMO:
610
case NG_HCI_OCF_WRITE_AUTO_FLUSH_TIMO:
611
case NG_HCI_OCF_READ_XMIT_LEVEL:
612
case NG_HCI_OCF_HOST_NUM_COMPL_PKTS: /* XXX Can get here? */
613
case NG_HCI_OCF_CHANGE_LOCAL_NAME:
614
case NG_HCI_OCF_READ_LOCAL_NAME:
615
case NG_HCI_OCF_READ_UNIT_CLASS:
616
case NG_HCI_OCF_WRITE_UNIT_CLASS:
617
case NG_HCI_OCF_WRITE_SIMPLE_PAIRING:
618
case NG_HCI_OCF_READ_LE_HOST_SUPPORTED:
619
case NG_HCI_OCF_WRITE_LE_HOST_SUPPORTED:
620
case NG_HCI_OCF_WRITE_SECURE_CONNECTIONS_HOST_SUPPORT:
621
/* These do not need post processing */
622
break;
623
624
case NG_HCI_OCF_RESET: {
625
ng_hci_unit_con_p con = NULL;
626
int size;
627
628
/*
629
* XXX
630
*
631
* After RESET command unit goes into standby mode
632
* and all operational state is lost. Host controller
633
* will revert to default values for all parameters.
634
*
635
* For now we shall terminate all connections and drop
636
* inited bit. After RESET unit must be re-initialized.
637
*/
638
639
while (!LIST_EMPTY(&unit->con_list)) {
640
con = LIST_FIRST(&unit->con_list);
641
642
/* Remove all timeouts (if any) */
643
if (con->flags & NG_HCI_CON_TIMEOUT_PENDING)
644
ng_hci_con_untimeout(con);
645
646
/* Connection terminated by local host */
647
ng_hci_lp_discon_ind(con, 0x16);
648
ng_hci_free_con(con);
649
}
650
651
NG_HCI_BUFF_ACL_TOTAL(unit->buffer, size);
652
NG_HCI_BUFF_ACL_FREE(unit->buffer, size);
653
654
NG_HCI_BUFF_SCO_TOTAL(unit->buffer, size);
655
NG_HCI_BUFF_SCO_FREE(unit->buffer, size);
656
657
unit->state &= ~NG_HCI_UNIT_INITED;
658
} break;
659
660
default:
661
error = EINVAL;
662
break;
663
}
664
665
NG_FREE_M(mcp);
666
NG_FREE_M(mrp);
667
668
return (error);
669
} /* process_hc_baseband_params */
670
671
/*
672
* Process info command return parameters
673
*/
674
675
static int
676
process_info_params(ng_hci_unit_p unit, u_int16_t ocf, struct mbuf *mcp,
677
struct mbuf *mrp)
678
{
679
int error = 0, len;
680
681
switch (ocf) {
682
case NG_HCI_OCF_READ_LOCAL_VER:
683
case NG_HCI_OCF_READ_COUNTRY_CODE:
684
break;
685
686
case NG_HCI_OCF_READ_LOCAL_FEATURES:
687
m_adj(mrp, sizeof(u_int8_t));
688
len = min(mrp->m_pkthdr.len, sizeof(unit->features));
689
m_copydata(mrp, 0, len, (caddr_t) unit->features);
690
break;
691
692
case NG_HCI_OCF_READ_BUFFER_SIZE: {
693
ng_hci_read_buffer_size_rp *rp = NULL;
694
695
/* Do not update buffer descriptor if node was initialized */
696
if ((unit->state & NG_HCI_UNIT_READY) == NG_HCI_UNIT_READY)
697
break;
698
699
NG_HCI_M_PULLUP(mrp, sizeof(*rp));
700
if (mrp != NULL) {
701
rp = mtod(mrp, ng_hci_read_buffer_size_rp *);
702
703
NG_HCI_BUFF_ACL_SET(
704
unit->buffer,
705
le16toh(rp->num_acl_pkt), /* number */
706
le16toh(rp->max_acl_size), /* size */
707
le16toh(rp->num_acl_pkt) /* free */
708
);
709
710
NG_HCI_BUFF_SCO_SET(
711
unit->buffer,
712
le16toh(rp->num_sco_pkt), /* number */
713
rp->max_sco_size, /* size */
714
le16toh(rp->num_sco_pkt) /* free */
715
);
716
717
/* Let upper layers know */
718
ng_hci_node_is_up(unit->node, unit->acl, NULL, 0);
719
ng_hci_node_is_up(unit->node, unit->sco, NULL, 0);
720
} else
721
error = ENOBUFS;
722
} break;
723
724
case NG_HCI_OCF_READ_BDADDR:
725
/* Do not update BD_ADDR if node was initialized */
726
if ((unit->state & NG_HCI_UNIT_READY) == NG_HCI_UNIT_READY)
727
break;
728
729
m_adj(mrp, sizeof(u_int8_t));
730
len = min(mrp->m_pkthdr.len, sizeof(unit->bdaddr));
731
m_copydata(mrp, 0, len, (caddr_t) &unit->bdaddr);
732
733
/* Let upper layers know */
734
ng_hci_node_is_up(unit->node, unit->acl, NULL, 0);
735
ng_hci_node_is_up(unit->node, unit->sco, NULL, 0);
736
break;
737
738
default:
739
error = EINVAL;
740
break;
741
}
742
743
NG_FREE_M(mcp);
744
NG_FREE_M(mrp);
745
746
return (error);
747
} /* process_info_params */
748
749
/*
750
* Process status command return parameters
751
*/
752
753
static int
754
process_status_params(ng_hci_unit_p unit, u_int16_t ocf, struct mbuf *mcp,
755
struct mbuf *mrp)
756
{
757
int error = 0;
758
759
switch (ocf) {
760
case NG_HCI_OCF_READ_FAILED_CONTACT_CNTR:
761
case NG_HCI_OCF_RESET_FAILED_CONTACT_CNTR:
762
case NG_HCI_OCF_GET_LINK_QUALITY:
763
case NG_HCI_OCF_READ_RSSI:
764
/* These do not need post processing */
765
break;
766
767
default:
768
error = EINVAL;
769
break;
770
}
771
772
NG_FREE_M(mcp);
773
NG_FREE_M(mrp);
774
775
return (error);
776
} /* process_status_params */
777
778
/*
779
* Process testing command return parameters
780
*/
781
782
int
783
process_testing_params(ng_hci_unit_p unit, u_int16_t ocf, struct mbuf *mcp,
784
struct mbuf *mrp)
785
{
786
int error = 0;
787
788
switch (ocf) {
789
/*
790
* XXX FIXME
791
* We do not support these features at this time. However,
792
* HCI node could support this and do something smart. At least
793
* node can change unit state.
794
*/
795
796
case NG_HCI_OCF_READ_LOOPBACK_MODE:
797
case NG_HCI_OCF_WRITE_LOOPBACK_MODE:
798
case NG_HCI_OCF_ENABLE_UNIT_UNDER_TEST:
799
break;
800
801
default:
802
error = EINVAL;
803
break;
804
}
805
806
NG_FREE_M(mcp);
807
NG_FREE_M(mrp);
808
809
return (error);
810
} /* process_testing_params */
811
812
/*
813
* Process LE command return parameters
814
*/
815
816
static int
817
process_le_params(ng_hci_unit_p unit, u_int16_t ocf,
818
struct mbuf *mcp, struct mbuf *mrp)
819
{
820
int error = 0;
821
822
switch (ocf){
823
case NG_HCI_OCF_LE_SET_EVENT_MASK:
824
case NG_HCI_OCF_LE_READ_BUFFER_SIZE:
825
case NG_HCI_OCF_LE_READ_LOCAL_SUPPORTED_FEATURES:
826
case NG_HCI_OCF_LE_SET_RANDOM_ADDRESS:
827
case NG_HCI_OCF_LE_SET_ADVERTISING_PARAMETERS:
828
case NG_HCI_OCF_LE_READ_ADVERTISING_CHANNEL_TX_POWER:
829
case NG_HCI_OCF_LE_SET_ADVERTISING_DATA:
830
case NG_HCI_OCF_LE_SET_SCAN_RESPONSE_DATA:
831
case NG_HCI_OCF_LE_SET_ADVERTISE_ENABLE:
832
case NG_HCI_OCF_LE_SET_SCAN_PARAMETERS:
833
case NG_HCI_OCF_LE_SET_SCAN_ENABLE:
834
case NG_HCI_OCF_LE_CREATE_CONNECTION_CANCEL:
835
case NG_HCI_OCF_LE_CLEAR_WHITE_LIST:
836
case NG_HCI_OCF_LE_READ_WHITE_LIST_SIZE:
837
case NG_HCI_OCF_LE_ADD_DEVICE_TO_WHITE_LIST:
838
case NG_HCI_OCF_LE_REMOVE_DEVICE_FROM_WHITE_LIST:
839
case NG_HCI_OCF_LE_SET_HOST_CHANNEL_CLASSIFICATION:
840
case NG_HCI_OCF_LE_READ_CHANNEL_MAP:
841
case NG_HCI_OCF_LE_ENCRYPT:
842
case NG_HCI_OCF_LE_RAND:
843
case NG_HCI_OCF_LE_LONG_TERM_KEY_REQUEST_REPLY:
844
case NG_HCI_OCF_LE_LONG_TERM_KEY_REQUEST_NEGATIVE_REPLY:
845
case NG_HCI_OCF_LE_READ_SUPPORTED_STATES:
846
case NG_HCI_OCF_LE_RECEIVER_TEST:
847
case NG_HCI_OCF_LE_TRANSMITTER_TEST:
848
case NG_HCI_OCF_LE_TEST_END:
849
850
/* These do not need post processing */
851
break;
852
case NG_HCI_OCF_LE_CREATE_CONNECTION:
853
case NG_HCI_OCF_LE_CONNECTION_UPDATE:
854
case NG_HCI_OCF_LE_READ_REMOTE_USED_FEATURES:
855
case NG_HCI_OCF_LE_START_ENCRYPTION:
856
857
default:
858
/*
859
* None of these command was supposed to generate
860
* Command_Complete event. Instead Command_Status event
861
* should have been generated and then appropriate event
862
* should have been sent to indicate the final result.
863
*/
864
865
error = EINVAL;
866
break;
867
}
868
869
NG_FREE_M(mcp);
870
NG_FREE_M(mrp);
871
872
return (error);
873
874
}
875
876
static int
877
process_le_status(ng_hci_unit_p unit,ng_hci_command_status_ep *ep,
878
struct mbuf *mcp)
879
{
880
int error = 0;
881
882
switch (NG_HCI_OCF(ep->opcode)){
883
case NG_HCI_OCF_LE_CREATE_CONNECTION:
884
case NG_HCI_OCF_LE_CONNECTION_UPDATE:
885
case NG_HCI_OCF_LE_READ_REMOTE_USED_FEATURES:
886
case NG_HCI_OCF_LE_START_ENCRYPTION:
887
888
/* These do not need post processing */
889
break;
890
891
case NG_HCI_OCF_LE_SET_EVENT_MASK:
892
case NG_HCI_OCF_LE_READ_BUFFER_SIZE:
893
case NG_HCI_OCF_LE_READ_LOCAL_SUPPORTED_FEATURES:
894
case NG_HCI_OCF_LE_SET_RANDOM_ADDRESS:
895
case NG_HCI_OCF_LE_SET_ADVERTISING_PARAMETERS:
896
case NG_HCI_OCF_LE_READ_ADVERTISING_CHANNEL_TX_POWER:
897
case NG_HCI_OCF_LE_SET_ADVERTISING_DATA:
898
case NG_HCI_OCF_LE_SET_SCAN_RESPONSE_DATA:
899
case NG_HCI_OCF_LE_SET_ADVERTISE_ENABLE:
900
case NG_HCI_OCF_LE_SET_SCAN_PARAMETERS:
901
case NG_HCI_OCF_LE_SET_SCAN_ENABLE:
902
case NG_HCI_OCF_LE_CREATE_CONNECTION_CANCEL:
903
case NG_HCI_OCF_LE_CLEAR_WHITE_LIST:
904
case NG_HCI_OCF_LE_READ_WHITE_LIST_SIZE:
905
case NG_HCI_OCF_LE_ADD_DEVICE_TO_WHITE_LIST:
906
case NG_HCI_OCF_LE_REMOVE_DEVICE_FROM_WHITE_LIST:
907
case NG_HCI_OCF_LE_SET_HOST_CHANNEL_CLASSIFICATION:
908
case NG_HCI_OCF_LE_READ_CHANNEL_MAP:
909
case NG_HCI_OCF_LE_ENCRYPT:
910
case NG_HCI_OCF_LE_RAND:
911
case NG_HCI_OCF_LE_LONG_TERM_KEY_REQUEST_REPLY:
912
case NG_HCI_OCF_LE_LONG_TERM_KEY_REQUEST_NEGATIVE_REPLY:
913
case NG_HCI_OCF_LE_READ_SUPPORTED_STATES:
914
case NG_HCI_OCF_LE_RECEIVER_TEST:
915
case NG_HCI_OCF_LE_TRANSMITTER_TEST:
916
case NG_HCI_OCF_LE_TEST_END:
917
918
default:
919
/*
920
* None of these command was supposed to generate
921
* Command_Stutus event. Command Complete instead.
922
*/
923
924
error = EINVAL;
925
break;
926
}
927
928
NG_FREE_M(mcp);
929
930
return (error);
931
932
}
933
934
/*
935
* Process link control command status
936
*/
937
938
static int
939
process_link_control_status(ng_hci_unit_p unit, ng_hci_command_status_ep *ep,
940
struct mbuf *mcp)
941
{
942
int error = 0;
943
944
switch (NG_HCI_OCF(ep->opcode)) {
945
case NG_HCI_OCF_INQUIRY:
946
case NG_HCI_OCF_DISCON: /* XXX */
947
case NG_HCI_OCF_REJECT_CON: /* XXX */
948
case NG_HCI_OCF_CHANGE_CON_PKT_TYPE:
949
case NG_HCI_OCF_AUTH_REQ:
950
case NG_HCI_OCF_SET_CON_ENCRYPTION:
951
case NG_HCI_OCF_CHANGE_CON_LINK_KEY:
952
case NG_HCI_OCF_MASTER_LINK_KEY:
953
case NG_HCI_OCF_REMOTE_NAME_REQ:
954
case NG_HCI_OCF_READ_REMOTE_FEATURES:
955
case NG_HCI_OCF_READ_REMOTE_VER_INFO:
956
case NG_HCI_OCF_READ_CLOCK_OFFSET:
957
/* These do not need post processing */
958
break;
959
960
case NG_HCI_OCF_CREATE_CON:
961
break;
962
963
case NG_HCI_OCF_ADD_SCO_CON:
964
break;
965
966
case NG_HCI_OCF_ACCEPT_CON:
967
break;
968
969
case NG_HCI_OCF_INQUIRY_CANCEL:
970
case NG_HCI_OCF_PERIODIC_INQUIRY:
971
case NG_HCI_OCF_EXIT_PERIODIC_INQUIRY:
972
case NG_HCI_OCF_LINK_KEY_REP:
973
case NG_HCI_OCF_LINK_KEY_NEG_REP:
974
case NG_HCI_OCF_PIN_CODE_REP:
975
case NG_HCI_OCF_PIN_CODE_NEG_REP:
976
default:
977
978
/*
979
* None of these command was supposed to generate
980
* Command_Status event. Instead Command_Complete event
981
* should have been sent.
982
*/
983
984
error = EINVAL;
985
break;
986
}
987
988
NG_FREE_M(mcp);
989
990
return (error);
991
} /* process_link_control_status */
992
993
/*
994
* Process link policy command status
995
*/
996
997
static int
998
process_link_policy_status(ng_hci_unit_p unit, ng_hci_command_status_ep *ep,
999
struct mbuf *mcp)
1000
{
1001
int error = 0;
1002
1003
switch (NG_HCI_OCF(ep->opcode)) {
1004
case NG_HCI_OCF_HOLD_MODE:
1005
case NG_HCI_OCF_SNIFF_MODE:
1006
case NG_HCI_OCF_EXIT_SNIFF_MODE:
1007
case NG_HCI_OCF_PARK_MODE:
1008
case NG_HCI_OCF_EXIT_PARK_MODE:
1009
case NG_HCI_OCF_SWITCH_ROLE:
1010
/* These do not need post processing */
1011
break;
1012
1013
case NG_HCI_OCF_QOS_SETUP:
1014
break;
1015
1016
case NG_HCI_OCF_ROLE_DISCOVERY:
1017
case NG_HCI_OCF_READ_LINK_POLICY_SETTINGS:
1018
case NG_HCI_OCF_WRITE_LINK_POLICY_SETTINGS:
1019
default:
1020
1021
/*
1022
* None of these command was supposed to generate
1023
* Command_Status event. Instead Command_Complete event
1024
* should have been sent.
1025
*/
1026
1027
error = EINVAL;
1028
break;
1029
}
1030
1031
NG_FREE_M(mcp);
1032
1033
return (error);
1034
} /* process_link_policy_status */
1035
1036