drivers/bluetooth/hci_ll.c

Source file repositories/reference/linux-study-clean/drivers/bluetooth/hci_ll.c

File Facts

System
Linux kernel
Corpus path
drivers/bluetooth/hci_ll.c
Extension
.c
Size
20102 bytes
Lines
835
Domain
Driver Families
Bucket
drivers/bluetooth
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct ll_device {
	struct hci_uart hu;
	struct serdev_device *serdev;
	struct gpio_desc *enable_gpio;
	struct clk *ext_clk;
	bdaddr_t bdaddr;
	bool broken_enhanced_setup;
};

struct ll_struct {
	struct sk_buff *rx_skb;
	struct sk_buff_head txq;
	spinlock_t hcill_lock;		/* HCILL state lock	*/
	unsigned long hcill_state;	/* HCILL power state	*/
	struct sk_buff_head tx_wait_q;	/* HCILL wait queue	*/
};

/*
 * Builds and sends an HCILL command packet.
 * These are very simple packets with only 1 cmd byte
 */
static int send_hcill_cmd(u8 cmd, struct hci_uart *hu)
{
	int err = 0;
	struct sk_buff *skb = NULL;
	struct ll_struct *ll = hu->priv;

	BT_DBG("hu %p cmd 0x%x", hu, cmd);

	/* allocate packet */
	skb = bt_skb_alloc(1, GFP_ATOMIC);
	if (!skb) {
		BT_ERR("cannot allocate memory for HCILL packet");
		err = -ENOMEM;
		goto out;
	}

	/* prepare packet */
	skb_put_u8(skb, cmd);

	/* send packet */
	skb_queue_tail(&ll->txq, skb);
out:
	return err;
}

/* Initialize protocol */
static int ll_open(struct hci_uart *hu)
{
	struct ll_struct *ll;

	BT_DBG("hu %p", hu);

	ll = kzalloc_obj(*ll);
	if (!ll)
		return -ENOMEM;

	skb_queue_head_init(&ll->txq);
	skb_queue_head_init(&ll->tx_wait_q);
	spin_lock_init(&ll->hcill_lock);

	ll->hcill_state = HCILL_AWAKE;

	hu->priv = ll;

	if (hu->serdev) {
		struct ll_device *lldev = serdev_device_get_drvdata(hu->serdev);

		if (!IS_ERR(lldev->ext_clk))
			clk_prepare_enable(lldev->ext_clk);
	}

	return 0;
}

/* Flush protocol data */
static int ll_flush(struct hci_uart *hu)
{
	struct ll_struct *ll = hu->priv;

	BT_DBG("hu %p", hu);

	skb_queue_purge(&ll->tx_wait_q);
	skb_queue_purge(&ll->txq);

	return 0;
}

/* Close protocol */
static int ll_close(struct hci_uart *hu)

Annotation

Implementation Notes