• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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