drivers/bluetooth/bpa10x.c

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

File Facts

System
Linux kernel
Corpus path
drivers/bluetooth/bpa10x.c
Extension
.c
Size
9070 bytes
Lines
448
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 bpa10x_data {
	struct hci_dev    *hdev;
	struct usb_device *udev;

	struct usb_anchor tx_anchor;
	struct usb_anchor rx_anchor;

	struct sk_buff *rx_skb[2];
	struct hci_uart hu;
};

static void bpa10x_tx_complete(struct urb *urb)
{
	struct sk_buff *skb = urb->context;
	struct hci_dev *hdev = (struct hci_dev *) skb->dev;

	BT_DBG("%s urb %p status %d count %d", hdev->name,
					urb, urb->status, urb->actual_length);

	if (!test_bit(HCI_RUNNING, &hdev->flags))
		goto done;

	if (!urb->status)
		hdev->stat.byte_tx += urb->transfer_buffer_length;
	else
		hdev->stat.err_tx++;

done:
	kfree(urb->setup_packet);

	kfree_skb(skb);
}

#define HCI_VENDOR_HDR_SIZE 5

#define HCI_RECV_VENDOR \
	.type = HCI_VENDOR_PKT, \
	.hlen = HCI_VENDOR_HDR_SIZE, \
	.loff = 3, \
	.lsize = 2, \
	.maxlen = HCI_MAX_FRAME_SIZE

static const struct h4_recv_pkt bpa10x_recv_pkts[] = {
	{ H4_RECV_ACL,     .recv = hci_recv_frame },
	{ H4_RECV_SCO,     .recv = hci_recv_frame },
	{ H4_RECV_EVENT,   .recv = hci_recv_frame },
	{ HCI_RECV_VENDOR, .recv = hci_recv_diag  },
};

static void bpa10x_rx_complete(struct urb *urb)
{
	struct hci_dev *hdev = urb->context;
	struct bpa10x_data *data = hci_get_drvdata(hdev);
	int err;

	BT_DBG("%s urb %p status %d count %d", hdev->name,
					urb, urb->status, urb->actual_length);

	if (!test_bit(HCI_RUNNING, &hdev->flags))
		return;

	if (urb->status == 0) {
		bool idx = usb_pipebulk(urb->pipe);

		data->rx_skb[idx] = h4_recv_buf(&data->hu, data->rx_skb[idx],
						urb->transfer_buffer,
						urb->actual_length,
						bpa10x_recv_pkts,
						ARRAY_SIZE(bpa10x_recv_pkts));
		if (IS_ERR(data->rx_skb[idx])) {
			bt_dev_err(hdev, "corrupted event packet");
			hdev->stat.err_rx++;
			data->rx_skb[idx] = NULL;
		}
	}

	usb_anchor_urb(urb, &data->rx_anchor);

	err = usb_submit_urb(urb, GFP_ATOMIC);
	if (err < 0) {
		bt_dev_err(hdev, "urb %p failed to resubmit (%d)", urb, -err);
		usb_unanchor_urb(urb);
	}
}

static inline int bpa10x_submit_intr_urb(struct hci_dev *hdev)
{
	struct bpa10x_data *data = hci_get_drvdata(hdev);
	struct urb *urb;
	unsigned char *buf;

Annotation

Implementation Notes