drivers/bluetooth/btqcomsmd.c

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

File Facts

System
Linux kernel
Corpus path
drivers/bluetooth/btqcomsmd.c
Extension
.c
Size
4990 bytes
Lines
231
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 btqcomsmd {
	struct hci_dev *hdev;

	struct rpmsg_endpoint *acl_channel;
	struct rpmsg_endpoint *cmd_channel;
};

static int btqcomsmd_recv(struct hci_dev *hdev, unsigned int type,
			   const void *data, size_t count)
{
	struct sk_buff *skb;

	/* Use GFP_ATOMIC as we're in IRQ context */
	skb = bt_skb_alloc(count, GFP_ATOMIC);
	if (!skb) {
		hdev->stat.err_rx++;
		return -ENOMEM;
	}

	hci_skb_pkt_type(skb) = type;
	skb_put_data(skb, data, count);

	return hci_recv_frame(hdev, skb);
}

static int btqcomsmd_acl_callback(struct rpmsg_device *rpdev, void *data,
				  int count, void *priv, u32 addr)
{
	struct btqcomsmd *btq = priv;

	btq->hdev->stat.byte_rx += count;
	return btqcomsmd_recv(btq->hdev, HCI_ACLDATA_PKT, data, count);
}

static int btqcomsmd_cmd_callback(struct rpmsg_device *rpdev, void *data,
				  int count, void *priv, u32 addr)
{
	struct btqcomsmd *btq = priv;

	btq->hdev->stat.byte_rx += count;
	return btqcomsmd_recv(btq->hdev, HCI_EVENT_PKT, data, count);
}

static int btqcomsmd_send(struct hci_dev *hdev, struct sk_buff *skb)
{
	struct btqcomsmd *btq = hci_get_drvdata(hdev);
	int ret;

	switch (hci_skb_pkt_type(skb)) {
	case HCI_ACLDATA_PKT:
		ret = rpmsg_send(btq->acl_channel, skb->data, skb->len);
		if (ret) {
			hdev->stat.err_tx++;
			break;
		}
		hdev->stat.acl_tx++;
		hdev->stat.byte_tx += skb->len;
		break;
	case HCI_COMMAND_PKT:
		ret = rpmsg_send(btq->cmd_channel, skb->data, skb->len);
		if (ret) {
			hdev->stat.err_tx++;
			break;
		}
		hdev->stat.cmd_tx++;
		hdev->stat.byte_tx += skb->len;
		break;
	default:
		ret = -EILSEQ;
		break;
	}

	if (!ret)
		kfree_skb(skb);

	return ret;
}

static int btqcomsmd_open(struct hci_dev *hdev)
{
	return 0;
}

static int btqcomsmd_close(struct hci_dev *hdev)
{
	return 0;
}

static int btqcomsmd_setup(struct hci_dev *hdev)
{

Annotation

Implementation Notes