drivers/bluetooth/hci_aml.c

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

File Facts

System
Linux kernel
Corpus path
drivers/bluetooth/hci_aml.c
Extension
.c
Size
17598 bytes
Lines
755
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 aml_fw_len {
	u32 iccm_len;
	u32 dccm_len;
};

struct aml_tci_rsp {
	u8 num_cmd_packet;
	u16 opcode;
	u8 status;
} __packed;

struct aml_device_data {
	int iccm_offset;
	int dccm_offset;
	bool is_coex;
};

struct aml_serdev {
	struct hci_uart serdev_hu;
	struct device *dev;
	struct gpio_desc *bt_en_gpio;
	struct regulator *bt_supply;
	struct clk *lpo_clk;
	const struct aml_device_data *aml_dev_data;
	const char *firmware_name;
};

struct aml_data {
	struct sk_buff *rx_skb;
	struct sk_buff_head txq;
};

static const struct h4_recv_pkt aml_recv_pkts[] = {
	{ H4_RECV_ACL, .recv = hci_recv_frame },
	{ H4_RECV_SCO, .recv = hci_recv_frame },
	{ H4_RECV_EVENT, .recv = hci_recv_frame },
	{ H4_RECV_ISO, .recv = hci_recv_frame },
};

/* The TCI command is a private command, which is for setting baud rate,
 * downloading firmware, initiating RAM.
 *
 * op_code |      op_len           | op_addr | parameter   |
 * --------|-----------------------|---------|-------------|
 *   2B    | 1B len(addr+param)    |    4B   |  len(param) |
 */
static int aml_send_tci_cmd(struct hci_dev *hdev, u16 op_code, u32 op_addr,
			    u32 *param, u32 param_len)
{
	struct aml_tci_rsp *rsp = NULL;
	struct sk_buff *skb = NULL;
	size_t buf_len = 0;
	u8 *buf = NULL;
	int err = 0;

	buf_len = sizeof(op_addr) + param_len;
	buf = kmalloc(buf_len, GFP_KERNEL);
	if (!buf)
		return -ENOMEM;

	memcpy(buf, &op_addr, sizeof(op_addr));
	if (param && param_len > 0)
		memcpy(buf + sizeof(op_addr), param, param_len);

	skb = __hci_cmd_sync_ev(hdev, op_code, buf_len, buf,
				HCI_EV_CMD_COMPLETE, HCI_INIT_TIMEOUT);
	if (IS_ERR(skb)) {
		err = PTR_ERR(skb);
		bt_dev_err(hdev, "Failed to send TCI cmd (error: %d)", err);
		goto exit;
	}

	rsp = skb_pull_data(skb, sizeof(struct aml_tci_rsp));
	if (!rsp)
		goto skb_free;

	if (rsp->opcode != op_code || rsp->status != 0x00) {
		bt_dev_err(hdev, "send TCI cmd (0x%04X), response (0x%04X):(%d)",
		       op_code, rsp->opcode, rsp->status);
		err = -EINVAL;
		goto skb_free;
	}

skb_free:
	kfree_skb(skb);

exit:
	kfree(buf);
	return err;
}

Annotation

Implementation Notes