1 /******************************************************************************
2 *
3 * Copyright (C) 2009-2012 Broadcom Corporation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19 /****************************************************************************
20 *
21 * Name: btsnoopdisp.c
22 *
23 * Function: this file contains functions to generate a BTSNOOP file
24 *
25 *
26 ****************************************************************************/
27 #include <stdio.h>
28 #include <dlfcn.h>
29 #include <stdlib.h>
30 #include <errno.h>
31 #include <string.h>
32 #include <pthread.h>
33 #include <sys/prctl.h>
34 #include <unistd.h>
35 #include <ctype.h>
36 #include <fcntl.h>
37
38 #include <arpa/inet.h>
39 #include <netinet/in.h>
40 #include <netdb.h>
41
42 /* for gettimeofday */
43 #include <sys/time.h>
44 /* for the S_* open parameters */
45 #include <sys/stat.h>
46 /* for write */
47 #include <unistd.h>
48 /* for O_* open parameters */
49 #include <fcntl.h>
50 /* defines the O_* open parameters */
51 #include <fcntl.h>
52
53 #define LOG_TAG "BTSNOOP-DISP"
54 #include <cutils/log.h>
55
56 #include "bt_hci_bdroid.h"
57 #include "utils.h"
58
59 #ifndef BTSNOOP_DBG
60 #define BTSNOOP_DBG FALSE
61 #endif
62
63 #if (BTSNOOP_DBG == TRUE)
64 #define SNOOPDBG(param, ...) {ALOGD(param, ## __VA_ARGS__);}
65 #else
66 #define SNOOPDBG(param, ...) {}
67 #endif
68
69 /* file descriptor of the BT snoop file (by default, -1 means disabled) */
70 int hci_btsnoop_fd = -1;
71
72 /* Macro to perform a multiplication of 2 unsigned 32bit values and store the result
73 * in an unsigned 64 bit value (as two 32 bit variables):
74 * u64 = u32In1 * u32In2
75 * u32OutLow = u64[31:0]
76 * u32OutHi = u64[63:32]
77 * basically the algorithm:
78 * (hi1*2^16 + lo1)*(hi2*2^16 + lo2) = lo1*lo2 + (hi1*hi2)*2^32 + (hi1*lo2 + hi2*lo1)*2^16
79 * and the carry is propagated 16 bit by 16 bit:
80 * result[15:0] = lo1*lo2 & 0xFFFF
81 * result[31:16] = ((lo1*lo2) >> 16) + (hi1*lo2 + hi2*lo1)
82 * and so on
83 */
84 #define HCIDISP_MULT_64(u32In1, u32In2, u32OutLo, u32OutHi) \
85 do { \
86 uint32_t u32In1Tmp = u32In1; \
87 uint32_t u32In2Tmp = u32In2; \
88 uint32_t u32Tmp, u32Carry; \
89 u32OutLo = (u32In1Tmp & 0xFFFF) * (u32In2Tmp & 0xFFFF); /*lo1*lo2*/ \
90 u32OutHi = ((u32In1Tmp >> 16) & 0xFFFF) * ((u32In2Tmp >> 16) & 0xFFFF); /*hi1*hi2*/ \
91 u32Tmp = (u32In1Tmp & 0xFFFF) * ((u32In2Tmp >> 16) & 0xFFFF); /*lo1*hi2*/ \
92 u32Carry = (uint32_t)((u32OutLo>>16)&0xFFFF); \
93 u32Carry += (u32Tmp&0xFFFF); \
94 u32OutLo += (u32Tmp << 16) ; \
95 u32OutHi += (u32Tmp >> 16); \
96 u32Tmp = ((u32In1Tmp >> 16) & 0xFFFF) * (u32In2Tmp & 0xFFFF); \
97 u32Carry += (u32Tmp)&0xFFFF; \
98 u32Carry>>=16; \
99 u32OutLo += (u32Tmp << 16); \
100 u32OutHi += (u32Tmp >> 16); \
101 u32OutHi += u32Carry; \
102 } while (0)
103
104 /* Macro to make an addition of 2 64 bit values:
105 * result = (u32OutHi & u32OutLo) + (u32InHi & u32InLo)
106 * u32OutHi = result[63:32]
107 * u32OutLo = result[31:0]
108 */
109 #define HCIDISP_ADD_64(u32InLo, u32InHi, u32OutLo, u32OutHi) \
110 do { \
111 (u32OutLo) += (u32InLo); \
112 if ((u32OutLo) < (u32InLo)) (u32OutHi)++; \
113 (u32OutHi) += (u32InHi); \
114 } while (0)
115
116 /* EPOCH in microseconds since 01/01/0000 : 0x00dcddb3.0f2f8000 */
117 #define BTSNOOP_EPOCH_HI 0x00dcddb3U
118 #define BTSNOOP_EPOCH_LO 0x0f2f8000U
119
120 /*******************************************************************************
121 **
122 ** Function tv_to_btsnoop_ts
123 **
124 ** Description This function generate a BT Snoop timestamp.
125 **
126 ** Returns void
127 **
128 ** NOTE
129 ** The return value is 64 bit as 2 32 bit variables out_lo and * out_hi.
130 ** A BT Snoop timestamp is the number of microseconds since 01/01/0000.
131 ** The timeval structure contains the number of microseconds since EPOCH
132 ** (01/01/1970) encoded as: tv.tv_sec, number of seconds since EPOCH and
133 ** tv_usec, number of microseconds in current second
134 **
135 ** Therefore the algorithm is:
136 ** result = tv.tv_sec * 1000000
137 ** result += tv.tv_usec
138 ** result += EPOCH_OFFSET
139 *******************************************************************************/
tv_to_btsnoop_ts(uint32_t * out_lo,uint32_t * out_hi,struct timeval * tv)140 static void tv_to_btsnoop_ts(uint32_t *out_lo, uint32_t *out_hi, struct timeval *tv)
141 {
142 /* multiply the seconds by 1000000 */
143 HCIDISP_MULT_64(tv->tv_sec, 0xf4240, *out_lo, *out_hi);
144
145 /* add the microseconds */
146 HCIDISP_ADD_64((uint32_t)tv->tv_usec, 0, *out_lo, *out_hi);
147
148 /* add the epoch */
149 HCIDISP_ADD_64(BTSNOOP_EPOCH_LO, BTSNOOP_EPOCH_HI, *out_lo, *out_hi);
150 }
151
152 /*******************************************************************************
153 **
154 ** Function l_to_be
155 **
156 ** Description Function to convert a 32 bit value into big endian format
157 **
158 ** Returns 32 bit value in big endian format
159 *******************************************************************************/
l_to_be(uint32_t x)160 static uint32_t l_to_be(uint32_t x)
161 {
162 #if __BIG_ENDIAN != TRUE
163 x = (x >> 24) |
164 ((x >> 8) & 0xFF00) |
165 ((x << 8) & 0xFF0000) |
166 (x << 24);
167 #endif
168 return x;
169 }
170
171 /*******************************************************************************
172 **
173 ** Function btsnoop_is_open
174 **
175 ** Description Function to check if BTSNOOP is open
176 **
177 ** Returns 1 if open otherwise 0
178 *******************************************************************************/
btsnoop_is_open(void)179 int btsnoop_is_open(void)
180 {
181 #if defined(BTSNOOPDISP_INCLUDED) && (BTSNOOPDISP_INCLUDED == TRUE)
182 SNOOPDBG("btsnoop_is_open: snoop fd = %d\n", hci_btsnoop_fd);
183
184 if (hci_btsnoop_fd != -1)
185 {
186 return 1;
187 }
188 return 0;
189 #else
190 return 2; /* Snoop not available */
191 #endif
192 }
193
194 /*******************************************************************************
195 **
196 ** Function btsnoop_log_open
197 **
198 ** Description Function to open the BTSNOOP file
199 **
200 ** Returns None
201 *******************************************************************************/
btsnoop_log_open(char * btsnoop_logfile)202 static int btsnoop_log_open(char *btsnoop_logfile)
203 {
204 #if defined(BTSNOOPDISP_INCLUDED) && (BTSNOOPDISP_INCLUDED == TRUE)
205 hci_btsnoop_fd = -1;
206
207 SNOOPDBG("btsnoop_log_open: snoop log file = %s\n", btsnoop_logfile);
208
209 /* write the BT snoop header */
210 if ((btsnoop_logfile != NULL) && (strlen(btsnoop_logfile) != 0))
211 {
212 hci_btsnoop_fd = open(btsnoop_logfile, \
213 O_WRONLY|O_CREAT|O_TRUNC, \
214 S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH);
215 if (hci_btsnoop_fd == -1)
216 {
217 perror("open");
218 SNOOPDBG("btsnoop_log_open: Unable to open snoop log file\n");
219 hci_btsnoop_fd = -1;
220 return 0;
221 }
222 write(hci_btsnoop_fd, "btsnoop\0\0\0\0\1\0\0\x3\xea", 16);
223 return 1;
224 }
225 #endif
226 return 2; /* Snoop not available */
227 }
228
229 /*******************************************************************************
230 **
231 ** Function btsnoop_log_close
232 **
233 ** Description Function to close the BTSNOOP file
234 **
235 ** Returns None
236 *******************************************************************************/
btsnoop_log_close(void)237 static int btsnoop_log_close(void)
238 {
239 #if defined(BTSNOOPDISP_INCLUDED) && (BTSNOOPDISP_INCLUDED == TRUE)
240 /* write the BT snoop header */
241 if (hci_btsnoop_fd != -1)
242 {
243 SNOOPDBG("btsnoop_log_close: Closing snoop log file\n");
244 close(hci_btsnoop_fd);
245 hci_btsnoop_fd = -1;
246 return 1;
247 }
248 return 0;
249 #else
250 return 2; /* Snoop not available */
251 #endif
252 }
253
254 /*******************************************************************************
255 **
256 ** Function btsnoop_hci_cmd
257 **
258 ** Description Function to add a command in the BTSNOOP file
259 **
260 ** Returns None
261 *******************************************************************************/
btsnoop_hci_cmd(uint8_t * p)262 void btsnoop_hci_cmd(uint8_t *p)
263 {
264 SNOOPDBG("btsnoop_hci_cmd: fd = %d", hci_btsnoop_fd);
265
266 if (hci_btsnoop_fd != -1)
267 {
268 uint32_t value, value_hi;
269 struct timeval tv;
270
271 /* since these display functions are called from different contexts */
272 utils_lock();
273
274 /* store the length in both original and included fields */
275 value = l_to_be(p[2] + 4);
276 write(hci_btsnoop_fd, &value, 4);
277 write(hci_btsnoop_fd, &value, 4);
278 /* flags: command sent from the host */
279 value = l_to_be(2);
280 write(hci_btsnoop_fd, &value, 4);
281 /* drops: none */
282 value = 0;
283 write(hci_btsnoop_fd, &value, 4);
284 /* time */
285 gettimeofday(&tv, NULL);
286 tv_to_btsnoop_ts(&value, &value_hi, &tv);
287 value_hi = l_to_be(value_hi);
288 value = l_to_be(value);
289 write(hci_btsnoop_fd, &value_hi, 4);
290 write(hci_btsnoop_fd, &value, 4);
291 /* data */
292 write(hci_btsnoop_fd, "\x1", 1);
293 write(hci_btsnoop_fd, p, p[2] + 3);
294
295 /* since these display functions are called from different contexts */
296 utils_unlock();
297 }
298 }
299
300 /*******************************************************************************
301 **
302 ** Function btsnoop_hci_evt
303 **
304 ** Description Function to add a event in the BTSNOOP file
305 **
306 ** Returns None
307 *******************************************************************************/
btsnoop_hci_evt(uint8_t * p)308 void btsnoop_hci_evt(uint8_t *p)
309 {
310 SNOOPDBG("btsnoop_hci_evt: fd = %d", hci_btsnoop_fd);
311
312 if (hci_btsnoop_fd != -1)
313 {
314 uint32_t value, value_hi;
315 struct timeval tv;
316
317 /* since these display functions are called from different contexts */
318 utils_lock();
319
320 /* store the length in both original and included fields */
321 value = l_to_be(p[1] + 3);
322 write(hci_btsnoop_fd, &value, 4);
323 write(hci_btsnoop_fd, &value, 4);
324 /* flags: event received in the host */
325 value = l_to_be(3);
326 write(hci_btsnoop_fd, &value, 4);
327 /* drops: none */
328 value = 0;
329 write(hci_btsnoop_fd, &value, 4);
330 /* time */
331 gettimeofday(&tv, NULL);
332 tv_to_btsnoop_ts(&value, &value_hi, &tv);
333 value_hi = l_to_be(value_hi);
334 value = l_to_be(value);
335 write(hci_btsnoop_fd, &value_hi, 4);
336 write(hci_btsnoop_fd, &value, 4);
337 /* data */
338 write(hci_btsnoop_fd, "\x4", 1);
339 write(hci_btsnoop_fd, p, p[1] + 2);
340
341 /* since these display functions are called from different contexts */
342 utils_unlock();
343 }
344 }
345
346 /*******************************************************************************
347 **
348 ** Function btsnoop_sco_data
349 **
350 ** Description Function to add a SCO data packet in the BTSNOOP file
351 **
352 ** Returns None
353 *******************************************************************************/
btsnoop_sco_data(uint8_t * p,uint8_t is_rcvd)354 void btsnoop_sco_data(uint8_t *p, uint8_t is_rcvd)
355 {
356 SNOOPDBG("btsnoop_sco_data: fd = %d", hci_btsnoop_fd);
357
358 if (hci_btsnoop_fd != -1)
359 {
360 uint32_t value, value_hi;
361 struct timeval tv;
362
363 /* since these display functions are called from different contexts */
364 utils_lock();
365
366 /* store the length in both original and included fields */
367 value = l_to_be(p[2] + 4);
368 write(hci_btsnoop_fd, &value, 4);
369 write(hci_btsnoop_fd, &value, 4);
370 /* flags: data can be sent or received */
371 value = l_to_be(is_rcvd?1:0);
372 write(hci_btsnoop_fd, &value, 4);
373 /* drops: none */
374 value = 0;
375 write(hci_btsnoop_fd, &value, 4);
376 /* time */
377 gettimeofday(&tv, NULL);
378 tv_to_btsnoop_ts(&value, &value_hi, &tv);
379 value_hi = l_to_be(value_hi);
380 value = l_to_be(value);
381 write(hci_btsnoop_fd, &value_hi, 4);
382 write(hci_btsnoop_fd, &value, 4);
383 /* data */
384 write(hci_btsnoop_fd, "\x3", 1);
385 write(hci_btsnoop_fd, p, p[2] + 3);
386
387 /* since these display functions are called from different contexts */
388 utils_unlock();
389 }
390 }
391
392 /*******************************************************************************
393 **
394 ** Function btsnoop_acl_data
395 **
396 ** Description Function to add an ACL data packet in the BTSNOOP file
397 **
398 ** Returns None
399 *******************************************************************************/
btsnoop_acl_data(uint8_t * p,uint8_t is_rcvd)400 void btsnoop_acl_data(uint8_t *p, uint8_t is_rcvd)
401 {
402 SNOOPDBG("btsnoop_acl_data: fd = %d", hci_btsnoop_fd);
403 if (hci_btsnoop_fd != -1)
404 {
405 uint32_t value, value_hi;
406 struct timeval tv;
407
408 /* since these display functions are called from different contexts */
409 utils_lock();
410
411 /* store the length in both original and included fields */
412 value = l_to_be((p[3]<<8) + p[2] + 5);
413 write(hci_btsnoop_fd, &value, 4);
414 write(hci_btsnoop_fd, &value, 4);
415 /* flags: data can be sent or received */
416 value = l_to_be(is_rcvd?1:0);
417 write(hci_btsnoop_fd, &value, 4);
418 /* drops: none */
419 value = 0;
420 write(hci_btsnoop_fd, &value, 4);
421 /* time */
422 gettimeofday(&tv, NULL);
423 tv_to_btsnoop_ts(&value, &value_hi, &tv);
424 value_hi = l_to_be(value_hi);
425 value = l_to_be(value);
426 write(hci_btsnoop_fd, &value_hi, 4);
427 write(hci_btsnoop_fd, &value, 4);
428 /* data */
429 write(hci_btsnoop_fd, "\x2", 1);
430 write(hci_btsnoop_fd, p, (p[3]<<8) + p[2] + 4);
431
432 /* since these display functions are called from different contexts */
433 utils_unlock();
434 }
435 }
436
437
438 /********************************************************************************
439 ** API allow external realtime parsing of output using e.g hcidump
440 *********************************************************************************/
441
442 #define EXT_PARSER_PORT 4330
443
444 static pthread_t thread_id;
445 static int s_listen = -1;
446 static int ext_parser_fd = -1;
447
448 static void ext_parser_detached(void);
449
ext_parser_accept(int port)450 static int ext_parser_accept(int port)
451 {
452 socklen_t clilen;
453 struct sockaddr_in cliaddr, servaddr;
454 int s, srvlen;
455 int n = 1;
456 int size_n;
457 int result = 0;
458
459 ALOGD("waiting for connection on port %d", port);
460
461 s_listen = socket(AF_INET, SOCK_STREAM, 0);
462
463 if (s_listen < 0)
464 {
465 ALOGE("listener not created: listen fd %d", s_listen);
466 return -1;
467 }
468
469 bzero(&servaddr, sizeof(servaddr));
470 servaddr.sin_family = AF_INET;
471 servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
472 servaddr.sin_port = htons(port);
473
474 srvlen = sizeof(servaddr);
475
476 /* allow reuse of sock addr upon bind */
477 result = setsockopt(s_listen, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n));
478
479 if (result<0)
480 {
481 perror("setsockopt");
482 }
483
484 result = bind(s_listen, (struct sockaddr *) &servaddr, srvlen);
485
486 if (result < 0)
487 perror("bind");
488
489 result = listen(s_listen, 1);
490
491 if (result < 0)
492 perror("listen");
493
494 clilen = sizeof(struct sockaddr_in);
495
496 s = accept(s_listen, (struct sockaddr *) &cliaddr, &clilen);
497
498 if (s < 0)
499 {
500 perror("accept");
501 return -1;
502 }
503
504 ALOGD("connected (%d)", s);
505
506 return s;
507 }
508
send_ext_parser(char * p,int len)509 static int send_ext_parser(char *p, int len)
510 {
511 int n;
512
513 /* check if io socket is connected */
514 if (ext_parser_fd == -1)
515 return 0;
516
517 SNOOPDBG("write %d to snoop socket\n", len);
518
519 n = write(ext_parser_fd, p, len);
520
521 if (n<=0)
522 {
523 ext_parser_detached();
524 }
525
526 return n;
527 }
528
ext_parser_detached(void)529 static void ext_parser_detached(void)
530 {
531 ALOGD("ext parser detached");
532
533 if (ext_parser_fd>0)
534 close(ext_parser_fd);
535
536 if (s_listen > 0)
537 close(s_listen);
538
539 ext_parser_fd = -1;
540 s_listen = -1;
541 }
542
interruptFn(int sig)543 static void interruptFn (int sig)
544 {
545 ALOGD("interruptFn");
546 pthread_exit(0);
547 }
548
ext_parser_thread(void * param)549 static void ext_parser_thread(void* param)
550 {
551 int fd;
552 int sig = SIGUSR2;
553 sigset_t sigSet;
554 sigemptyset (&sigSet);
555 sigaddset (&sigSet, sig);
556
557 ALOGD("ext_parser_thread");
558
559 prctl(PR_SET_NAME, (unsigned long)"BtsnoopExtParser", 0, 0, 0);
560
561 pthread_sigmask (SIG_UNBLOCK, &sigSet, NULL);
562
563 struct sigaction act;
564 act.sa_handler = interruptFn;
565 sigaction (sig, &act, NULL );
566
567 do
568 {
569 fd = ext_parser_accept(EXT_PARSER_PORT);
570
571 ext_parser_fd = fd;
572
573 ALOGD("ext parser attached on fd %d\n", ext_parser_fd);
574 } while (1);
575 }
576
btsnoop_stop_listener(void)577 void btsnoop_stop_listener(void)
578 {
579 ALOGD("btsnoop_init");
580 ext_parser_detached();
581 }
582
btsnoop_init(void)583 void btsnoop_init(void)
584 {
585 #if defined(BTSNOOP_EXT_PARSER_INCLUDED) && (BTSNOOP_EXT_PARSER_INCLUDED == TRUE)
586 ALOGD("btsnoop_init");
587
588 /* always setup ext listener port */
589 if (pthread_create(&thread_id, NULL,
590 (void*)ext_parser_thread,NULL)!=0)
591 perror("pthread_create");
592 #endif
593 }
594
btsnoop_open(char * p_path)595 void btsnoop_open(char *p_path)
596 {
597 #if defined(BTSNOOPDISP_INCLUDED) && (BTSNOOPDISP_INCLUDED == TRUE)
598 ALOGD("btsnoop_open");
599 btsnoop_log_open(p_path);
600 #endif // BTSNOOPDISP_INCLUDED
601 }
602
btsnoop_close(void)603 void btsnoop_close(void)
604 {
605 #if defined(BTSNOOPDISP_INCLUDED) && (BTSNOOPDISP_INCLUDED == TRUE)
606 ALOGD("btsnoop_close");
607 btsnoop_log_close();
608 #endif
609 }
610
btsnoop_cleanup(void)611 void btsnoop_cleanup (void)
612 {
613 #if defined(BTSNOOP_EXT_PARSER_INCLUDED) && (BTSNOOP_EXT_PARSER_INCLUDED == TRUE)
614 ALOGD("btsnoop_cleanup");
615 pthread_kill(thread_id, SIGUSR2);
616 pthread_join(thread_id, NULL);
617 ext_parser_detached();
618 #endif
619 }
620
621
622 #define HCIT_TYPE_COMMAND 1
623 #define HCIT_TYPE_ACL_DATA 2
624 #define HCIT_TYPE_SCO_DATA 3
625 #define HCIT_TYPE_EVENT 4
626
btsnoop_capture(HC_BT_HDR * p_buf,uint8_t is_rcvd)627 void btsnoop_capture(HC_BT_HDR *p_buf, uint8_t is_rcvd)
628 {
629 uint8_t *p = (uint8_t *)(p_buf + 1) + p_buf->offset;
630
631 SNOOPDBG("btsnoop_capture: fd = %d, type %x, rcvd %d, ext %d", \
632 hci_btsnoop_fd, p_buf->event, is_rcvd, ext_parser_fd);
633
634 #if defined(BTSNOOP_EXT_PARSER_INCLUDED) && (BTSNOOP_EXT_PARSER_INCLUDED == TRUE)
635 if (ext_parser_fd > 0)
636 {
637 uint8_t tmp = *p;
638
639 /* borrow one byte for H4 packet type indicator */
640 p--;
641
642 switch (p_buf->event & MSG_EVT_MASK)
643 {
644 case MSG_HC_TO_STACK_HCI_EVT:
645 *p = HCIT_TYPE_EVENT;
646 break;
647 case MSG_HC_TO_STACK_HCI_ACL:
648 case MSG_STACK_TO_HC_HCI_ACL:
649 *p = HCIT_TYPE_ACL_DATA;
650 break;
651 case MSG_HC_TO_STACK_HCI_SCO:
652 case MSG_STACK_TO_HC_HCI_SCO:
653 *p = HCIT_TYPE_SCO_DATA;
654 break;
655 case MSG_STACK_TO_HC_HCI_CMD:
656 *p = HCIT_TYPE_COMMAND;
657 break;
658 }
659
660 send_ext_parser((char*)p, p_buf->len+1);
661 *(++p) = tmp;
662 return;
663 }
664 #endif
665
666 #if defined(BTSNOOPDISP_INCLUDED) && (BTSNOOPDISP_INCLUDED == TRUE)
667 if (hci_btsnoop_fd == -1)
668 return;
669
670 switch (p_buf->event & MSG_EVT_MASK)
671 {
672 case MSG_HC_TO_STACK_HCI_EVT:
673 SNOOPDBG("TYPE : EVT");
674 btsnoop_hci_evt(p);
675 break;
676 case MSG_HC_TO_STACK_HCI_ACL:
677 case MSG_STACK_TO_HC_HCI_ACL:
678 SNOOPDBG("TYPE : ACL");
679 btsnoop_acl_data(p, is_rcvd);
680 break;
681 case MSG_HC_TO_STACK_HCI_SCO:
682 case MSG_STACK_TO_HC_HCI_SCO:
683 SNOOPDBG("TYPE : SCO");
684 btsnoop_sco_data(p, is_rcvd);
685 break;
686 case MSG_STACK_TO_HC_HCI_CMD:
687 SNOOPDBG("TYPE : CMD");
688 btsnoop_hci_cmd(p);
689 break;
690 }
691 #endif // BTSNOOPDISP_INCLUDED
692 }
693
694
695