mirror of
https://github.com/apache/nuttx.git
synced 2026-05-19 03:03:37 +08:00
wireless/bluetooth: add interrupt_context hander for netsnoop
Signed-off-by: chengkai <chengkai@xiaomi.com>
This commit is contained in:
@@ -424,17 +424,14 @@ static int bt_bridge_send(FAR struct bt_driver_s *drv,
|
||||
flags = enter_critical_section();
|
||||
if (bt_filter_can_send(&device->filter, type, data, len))
|
||||
{
|
||||
int ret;
|
||||
|
||||
leave_critical_section(flags);
|
||||
ret = driver->send(driver, type, data, len);
|
||||
|
||||
#ifdef CONFIG_BLUETOOTH_BRIDGE_BTSNOOP
|
||||
snoop_dump(bridge->snoop, data - drv->head_reserve,
|
||||
len + drv->head_reserve, 0,
|
||||
SNOOP_DIRECTION_FLAG_SENT);
|
||||
#endif /* CONFIG_BLUETOOTH_BRIDGE_BTSNOOP */
|
||||
return ret;
|
||||
|
||||
return driver->send(driver, type, data, len);
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
|
||||
@@ -27,6 +27,9 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <nuttx/mutex.h>
|
||||
#include <nuttx/wqueue.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
@@ -81,11 +84,18 @@
|
||||
#define SNOOP_DIRECTION_FLAG_SENT 0 /* Direction flag 0 = Sent */
|
||||
#define SNOOP_DIRECTION_FLAG_RECV 1 /* Direction flag 1 = Received */
|
||||
|
||||
#ifndef CONFIG_NET_SNOOP_BUFSIZE
|
||||
# define CONFIG_NET_SNOOP_BUFSIZE 4096
|
||||
#endif
|
||||
struct snoop_s
|
||||
{
|
||||
bool autosync;
|
||||
uint32_t datalink;
|
||||
struct file filep;
|
||||
bool autosync;
|
||||
uint32_t datalink;
|
||||
struct file filep;
|
||||
mutex_t mutex;
|
||||
struct work_s work;
|
||||
uint8_t buf[CONFIG_NET_SNOOP_BUFSIZE];
|
||||
size_t next;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
@@ -106,6 +116,17 @@ extern "C"
|
||||
* Description:
|
||||
* This function open snoop file by datalink.
|
||||
*
|
||||
* Input Parameters:
|
||||
* snoop The snoop driver struct
|
||||
* filename Snoop file name
|
||||
* datalink Snoop datalink type, such as SNOOP_DATALINK_TYPE_XX
|
||||
* autosync whether do file_sync when snoop_dump
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on success; Negated errno on failure.
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int snoop_open(FAR struct snoop_s *snoop, FAR const char *filename,
|
||||
@@ -117,6 +138,18 @@ int snoop_open(FAR struct snoop_s *snoop, FAR const char *filename,
|
||||
* Description:
|
||||
* This function dump nbytes buf data into snoop file.
|
||||
*
|
||||
* Input Parameters:
|
||||
* snoop The snoop driver struct
|
||||
* buf Snoop buffer
|
||||
* nbytes Snoop buffer size
|
||||
* drops cumulative number of dropped packets
|
||||
* flags Packet Flags: 1 hci cmd , eg: btsnoop
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on success; Negated errno on failure.
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int snoop_dump(FAR struct snoop_s *snoop, FAR const void *buf,
|
||||
@@ -128,6 +161,14 @@ int snoop_dump(FAR struct snoop_s *snoop, FAR const void *buf,
|
||||
* Description:
|
||||
* This function sync snoop buffer.
|
||||
*
|
||||
* Input Parameters:
|
||||
* snoop The snoop driver struct
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on success; Negated errno on failure.
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int snoop_sync(FAR struct snoop_s *snoop);
|
||||
@@ -138,6 +179,14 @@ int snoop_sync(FAR struct snoop_s *snoop);
|
||||
* Description:
|
||||
* This function close snoop file.
|
||||
*
|
||||
* Input Parameters:
|
||||
* snoop The snoop driver struct
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on success; Negated errno on failure.
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int snoop_close(FAR struct snoop_s *snoop);
|
||||
|
||||
@@ -24,3 +24,7 @@ config NET_ARCH_CHKSUM
|
||||
uint16_t ipv4_chksum(FAR struct ipv4_hdr_s *ipv4)
|
||||
uint16_t ipv4_upperlayer_chksum(FAR struct net_driver_s *dev, uint8_t proto)
|
||||
uint16_t ipv6_upperlayer_chksum(FAR struct net_driver_s *dev, uint8_t proto, unsigned int iplen)
|
||||
|
||||
config NET_SNOOP_BUFSIZE
|
||||
int "Snoop buffer size for interrupt"
|
||||
default 4096
|
||||
|
||||
+209
-70
@@ -161,76 +161,128 @@ begin_packed_struct struct snoop_packet_header_s
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: snoop_dump_packet_header
|
||||
* Name: snoop_fill_packet_header
|
||||
*
|
||||
* Description:
|
||||
* This function fill snoop headr info.
|
||||
* This function fill snoop packet header info.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int snoop_dump_packet_header(FAR struct snoop_s *snoop,
|
||||
uint32_t bytes, uint32_t drops,
|
||||
uint32_t flags)
|
||||
static void snoop_fill_packet_header(FAR struct snoop_s *snoop,
|
||||
uint32_t bytes, uint32_t drops,
|
||||
uint32_t flags, FAR struct
|
||||
snoop_packet_header_s *header)
|
||||
{
|
||||
struct snoop_packet_header_s header;
|
||||
int ret;
|
||||
|
||||
if (!snoop)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
struct timeval tv;
|
||||
|
||||
switch (snoop->datalink)
|
||||
{
|
||||
case SNOOP_DATALINK_HCI_UNENCAP:
|
||||
case SNOOP_DATALINK_HCI_UART:
|
||||
case SNOOP_DATALINK_HCI_BSCP:
|
||||
case SNOOP_DATALINK_HCI_SERIAL:
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
case SNOOP_DATALINK_HCI_UNENCAP:
|
||||
case SNOOP_DATALINK_HCI_UART:
|
||||
case SNOOP_DATALINK_HCI_BSCP:
|
||||
case SNOOP_DATALINK_HCI_SERIAL:
|
||||
gettimeofday(&tv, NULL);
|
||||
header.ts_usec = htobe64(SNOOP_EPOCH_USEC(tv));
|
||||
header.flags = htobe32(flags);
|
||||
header->ts_usec = htobe64(SNOOP_EPOCH_USEC(tv));
|
||||
header->flags = htobe32(flags);
|
||||
break;
|
||||
}
|
||||
|
||||
case SNOOP_DATALINK_TYPE_TOKENBUS:
|
||||
case SNOOP_DATALINK_TYPE_TOKERING:
|
||||
case SNOOP_DATALINK_TYPE_METRONET:
|
||||
case SNOOP_DATALINK_TYPE_ETHERNET:
|
||||
case SNOOP_DATALINK_TYPE_HDLC:
|
||||
case SNOOP_DATALINK_TYPE_CHARSYNC:
|
||||
case SNOOP_DATALINK_TYPE_IBMC2C:
|
||||
case SNOOP_DATALINK_TYPE_FDDI:
|
||||
case SNOOP_DATALINK_TYPE_OTHER:
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
case SNOOP_DATALINK_TYPE_TOKENBUS:
|
||||
case SNOOP_DATALINK_TYPE_TOKERING:
|
||||
case SNOOP_DATALINK_TYPE_METRONET:
|
||||
case SNOOP_DATALINK_TYPE_ETHERNET:
|
||||
case SNOOP_DATALINK_TYPE_HDLC:
|
||||
case SNOOP_DATALINK_TYPE_CHARSYNC:
|
||||
case SNOOP_DATALINK_TYPE_IBMC2C:
|
||||
case SNOOP_DATALINK_TYPE_FDDI:
|
||||
case SNOOP_DATALINK_TYPE_OTHER:
|
||||
gettimeofday(&tv, NULL);
|
||||
header.ts.ts_sec = htobe32(tv.tv_sec);
|
||||
header.ts.ts_usec = htobe32(tv.tv_usec);
|
||||
header.rec_len = htobe32(flags);
|
||||
header->ts.ts_sec = htobe32(tv.tv_sec);
|
||||
header->ts.ts_usec = htobe32(tv.tv_usec);
|
||||
header->rec_len = htobe32(flags);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
default:
|
||||
DEBUGASSERT(false);
|
||||
}
|
||||
|
||||
header.orig_len = htobe32(bytes);
|
||||
header.incl_len = htobe32(bytes);
|
||||
header.cum_drops = htobe32(drops);
|
||||
header->orig_len = htobe32(bytes);
|
||||
header->incl_len = htobe32(bytes);
|
||||
header->cum_drops = htobe32(drops);
|
||||
}
|
||||
|
||||
ret = file_write(&snoop->filep, &header, sizeof(header));
|
||||
if (ret != sizeof(header))
|
||||
/****************************************************************************
|
||||
* Name: snoop_flush
|
||||
*
|
||||
* Description:
|
||||
* This function could flush snoop buf into file.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int snoop_flush(FAR struct snoop_s *snoop)
|
||||
{
|
||||
ssize_t ret;
|
||||
|
||||
if (snoop->next == 0)
|
||||
{
|
||||
return ret < 0 ? ret : -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return OK;
|
||||
do
|
||||
{
|
||||
ret = file_write(&snoop->filep, snoop->buf, snoop->next);
|
||||
if (ret < 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
snoop->next -= ret;
|
||||
memmove(snoop->buf, snoop->buf + ret, snoop->next);
|
||||
}
|
||||
while (snoop->next > 0);
|
||||
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
if (snoop->autosync)
|
||||
{
|
||||
ret = file_fsync(&snoop->filep);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: snoop_flush_lock
|
||||
*
|
||||
* Description:
|
||||
* Snoop flush atomic
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int snoop_flush_lock(FAR struct snoop_s *snoop)
|
||||
{
|
||||
irqstate_t flags;
|
||||
int ret;
|
||||
|
||||
flags = enter_critical_section();
|
||||
nxmutex_lock(&snoop->mutex);
|
||||
ret = snoop_flush(snoop);
|
||||
nxmutex_unlock(&snoop->mutex);
|
||||
leave_critical_section(flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: snoop_flush_work
|
||||
*
|
||||
* Description:
|
||||
* Do snoop flush work.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void snoop_flush_work(FAR void *arg)
|
||||
{
|
||||
snoop_flush_lock((FAR struct snoop_s *)arg);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -243,6 +295,17 @@ static int snoop_dump_packet_header(FAR struct snoop_s *snoop,
|
||||
* Description:
|
||||
* This function open snoop file by datalink.
|
||||
*
|
||||
* Input Parameters:
|
||||
* snoop The snoop driver struct
|
||||
* filename Snoop file name
|
||||
* datalink Snoop datalink type, such as SNOOP_DATALINK_TYPE_XX
|
||||
* autosync whether do file_sync when snoop_dump
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on success; Negated errno on failure.
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int snoop_open(FAR struct snoop_s *snoop, FAR const char *filename,
|
||||
@@ -268,7 +331,7 @@ int snoop_open(FAR struct snoop_s *snoop, FAR const char *filename,
|
||||
case SNOOP_DATALINK_TYPE_FDDI:
|
||||
case SNOOP_DATALINK_TYPE_OTHER:
|
||||
{
|
||||
uint8_t snoop_magic[] =
|
||||
static const uint8_t snoop_magic[] =
|
||||
{
|
||||
's', 'n', 'o', 'o', 'p', '\0', '\0', '\0'
|
||||
};
|
||||
@@ -283,7 +346,7 @@ int snoop_open(FAR struct snoop_s *snoop, FAR const char *filename,
|
||||
case SNOOP_DATALINK_HCI_BSCP:
|
||||
case SNOOP_DATALINK_HCI_SERIAL:
|
||||
{
|
||||
uint8_t btsnoop_magic[] =
|
||||
static const uint8_t btsnoop_magic[] =
|
||||
{
|
||||
'b', 't', 's', 'n', 'o', 'o', 'p', '\0'
|
||||
};
|
||||
@@ -307,8 +370,9 @@ int snoop_open(FAR struct snoop_s *snoop, FAR const char *filename,
|
||||
|
||||
snoop->datalink = datalink;
|
||||
snoop->autosync = autosync;
|
||||
header.datalink = htobe32(datalink);
|
||||
snoop->next = 0;
|
||||
|
||||
header.datalink = htobe32(datalink);
|
||||
ret = file_write(&snoop->filep, &header, sizeof(header));
|
||||
if (ret != sizeof(header))
|
||||
{
|
||||
@@ -316,10 +380,11 @@ int snoop_open(FAR struct snoop_s *snoop, FAR const char *filename,
|
||||
goto error;
|
||||
}
|
||||
|
||||
nxmutex_init(&snoop->mutex);
|
||||
return OK;
|
||||
|
||||
error:
|
||||
file_close(&snoop->filep);
|
||||
snoop_close(snoop);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -329,31 +394,93 @@ error:
|
||||
* Description:
|
||||
* This function dump nbytes buf data into snoop file.
|
||||
*
|
||||
* Input Parameters:
|
||||
* snoop The snoop driver struct
|
||||
* buf Snoop buffer
|
||||
* nbytes Snoop buffer size
|
||||
* drops cumulative number of dropped packets
|
||||
* flags Packet Flags: 1 hci cmd , eg: btsnoop
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on success; Negated errno on failure.
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int snoop_dump(FAR struct snoop_s *snoop, FAR const void *buf,
|
||||
uint32_t nbytes, uint32_t drops, uint32_t flags)
|
||||
{
|
||||
int ret;
|
||||
struct snoop_packet_header_s header;
|
||||
irqstate_t irqflags;
|
||||
int ret = 0;
|
||||
|
||||
if (!snoop)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = snoop_dump_packet_header(snoop, nbytes, drops, flags);
|
||||
if (ret != OK)
|
||||
snoop_fill_packet_header(snoop, nbytes, drops, flags, &header);
|
||||
|
||||
irqflags = enter_critical_section();
|
||||
if (up_interrupt_context())
|
||||
{
|
||||
return ret;
|
||||
if (sizeof(snoop->buf) - snoop->next <
|
||||
nbytes + sizeof(struct snoop_packet_header_s))
|
||||
{
|
||||
ret = -ENOMEM;
|
||||
goto out_leave;
|
||||
}
|
||||
|
||||
memcpy(snoop->buf + snoop->next, &header, sizeof(header));
|
||||
snoop->next += sizeof(header);
|
||||
memcpy(snoop->buf + snoop->next, buf, nbytes);
|
||||
snoop->next += nbytes;
|
||||
|
||||
if (work_available(&snoop->work))
|
||||
{
|
||||
work_queue(HPWORK, &snoop->work, snoop_flush_work, snoop, 0);
|
||||
}
|
||||
|
||||
goto out_leave;
|
||||
}
|
||||
else
|
||||
{
|
||||
nxmutex_lock(&snoop->mutex);
|
||||
ret = snoop_flush(snoop);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
ret = file_write(&snoop->filep, &header, sizeof(header));
|
||||
if (ret < 0)
|
||||
{
|
||||
goto out_unlock;
|
||||
}
|
||||
else if (ret != sizeof(header))
|
||||
{
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
ret = file_write(&snoop->filep, buf, nbytes);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto out_unlock;
|
||||
}
|
||||
else if (ret != nbytes)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
}
|
||||
|
||||
ret = file_write(&snoop->filep, buf, nbytes);
|
||||
if (ret != nbytes)
|
||||
{
|
||||
return ret < 0 ? ret : -EINVAL;
|
||||
}
|
||||
|
||||
return snoop->autosync ? snoop_sync(snoop) : OK;
|
||||
out_unlock:
|
||||
nxmutex_unlock(&snoop->mutex);
|
||||
out_leave:
|
||||
leave_critical_section(irqflags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -362,21 +489,24 @@ int snoop_dump(FAR struct snoop_s *snoop, FAR const void *buf,
|
||||
* Description:
|
||||
* This function sync snoop buffer.
|
||||
*
|
||||
* Input Parameters:
|
||||
* snoop The snoop driver struct
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on success; Negated errno on failure.
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int snoop_sync(FAR struct snoop_s *snoop)
|
||||
{
|
||||
int ret = OK;
|
||||
|
||||
if (!snoop)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
ret = file_fsync(&snoop->filep);
|
||||
#endif
|
||||
return ret;
|
||||
return snoop_flush_lock(snoop);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -385,6 +515,14 @@ int snoop_sync(FAR struct snoop_s *snoop)
|
||||
* Description:
|
||||
* This function close snoop file.
|
||||
*
|
||||
* Input Parameters:
|
||||
* snoop The snoop driver struct
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on success; Negated errno on failure.
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int snoop_close(FAR struct snoop_s *snoop)
|
||||
@@ -394,5 +532,6 @@ int snoop_close(FAR struct snoop_s *snoop)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
nxmutex_destroy(&snoop->mutex);
|
||||
return file_close(&snoop->filep);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user