net/bluetooth/sco.c

Source file repositories/reference/linux-study-clean/net/bluetooth/sco.c

File Facts

System
Linux kernel
Corpus path
net/bluetooth/sco.c
Extension
.c
Size
33053 bytes
Lines
1661
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: operation-table or driver-model contract
Status
pattern implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

static const struct proto_ops sco_sock_ops;

static struct bt_sock_list sco_sk_list = {
	.lock = __RW_LOCK_UNLOCKED(sco_sk_list.lock)
};

/* ---- SCO connections ---- */
struct sco_conn {
	struct hci_conn	*hcon;

	spinlock_t	lock;
	struct sock	*sk;

	struct delayed_work	timeout_work;

	unsigned int    mtu;
	struct kref	ref;
};

#define sco_conn_lock(c)	spin_lock(&c->lock)
#define sco_conn_unlock(c)	spin_unlock(&c->lock)

static void sco_sock_close(struct sock *sk);
static void sco_sock_kill(struct sock *sk);

/* ----- SCO socket info ----- */
#define sco_pi(sk) ((struct sco_pinfo *) sk)

struct sco_pinfo {
	struct bt_sock	bt;
	bdaddr_t	src;
	bdaddr_t	dst;
	__u32		flags;
	__u16		setting;
	struct bt_codec codec;
	struct sco_conn	*conn;
};

/* ---- SCO timers ---- */
#define SCO_CONN_TIMEOUT	(HZ * 40)
#define SCO_DISCONN_TIMEOUT	(HZ * 2)

static void sco_conn_free(struct kref *ref)
{
	struct sco_conn *conn = container_of(ref, struct sco_conn, ref);

	BT_DBG("conn %p", conn);

	if (conn->sk)
		sco_pi(conn->sk)->conn = NULL;

	if (conn->hcon) {
		conn->hcon->sco_data = NULL;
		hci_conn_drop(conn->hcon);
	}

	/* Ensure no more work items will run since hci_conn has been dropped */
	disable_delayed_work_sync(&conn->timeout_work);

	kfree(conn);
}

static void sco_conn_put(struct sco_conn *conn)
{
	if (!conn)
		return;

	BT_DBG("conn %p refcnt %d", conn, kref_read(&conn->ref));

	kref_put(&conn->ref, sco_conn_free);
}

static struct sco_conn *sco_conn_hold(struct sco_conn *conn)
{
	BT_DBG("conn %p refcnt %u", conn, kref_read(&conn->ref));

	kref_get(&conn->ref);
	return conn;
}

static struct sco_conn *sco_conn_hold_unless_zero(struct sco_conn *conn)
{
	if (!conn)
		return NULL;

	BT_DBG("conn %p refcnt %u", conn, kref_read(&conn->ref));

	if (!kref_get_unless_zero(&conn->ref))
		return NULL;

Annotation

Implementation Notes