drivers/nfc/s3fwrn5/firmware.c

Source file repositories/reference/linux-study-clean/drivers/nfc/s3fwrn5/firmware.c

File Facts

System
Linux kernel
Corpus path
drivers/nfc/s3fwrn5/firmware.c
Extension
.c
Size
10648 bytes
Lines
482
Domain
Driver Families
Bucket
drivers/nfc
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 s3fwrn5_fw_version {
	__u8 major;
	__u8 build1;
	__u8 build2;
	__u8 target;
};

static int s3fwrn5_fw_send_msg(struct s3fwrn5_fw_info *fw_info,
	struct sk_buff *msg, struct sk_buff **rsp)
{
	struct s3fwrn5_info *info =
		container_of(fw_info, struct s3fwrn5_info, fw_info);
	long ret;

	reinit_completion(&fw_info->completion);

	ret = s3fwrn5_write(info, msg);
	if (ret < 0)
		return ret;

	ret = wait_for_completion_interruptible_timeout(
		&fw_info->completion, msecs_to_jiffies(1000));
	if (ret < 0)
		return ret;
	else if (ret == 0)
		return -ENXIO;

	if (!fw_info->rsp)
		return -EINVAL;

	*rsp = fw_info->rsp;
	fw_info->rsp = NULL;

	return 0;
}

static int s3fwrn5_fw_prep_msg(struct s3fwrn5_fw_info *fw_info,
	struct sk_buff **msg, u8 type, u8 code, const void *data, u16 len)
{
	struct s3fwrn5_fw_header hdr;
	struct sk_buff *skb;

	hdr.type = type | fw_info->parity;
	fw_info->parity ^= 0x80;
	hdr.code = code;
	hdr.len = len;

	skb = alloc_skb(S3FWRN5_FW_HDR_SIZE + len, GFP_KERNEL);
	if (!skb)
		return -ENOMEM;

	skb_put_data(skb, &hdr, S3FWRN5_FW_HDR_SIZE);
	if (len)
		skb_put_data(skb, data, len);

	*msg = skb;

	return 0;
}

static int s3fwrn5_fw_get_bootinfo(struct s3fwrn5_fw_info *fw_info,
	struct s3fwrn5_fw_cmd_get_bootinfo_rsp *bootinfo)
{
	struct sk_buff *msg, *rsp = NULL;
	struct s3fwrn5_fw_header *hdr;
	int ret;

	/* Send GET_BOOTINFO command */

	ret = s3fwrn5_fw_prep_msg(fw_info, &msg, S3FWRN5_FW_MSG_CMD,
		S3FWRN5_FW_CMD_GET_BOOTINFO, NULL, 0);
	if (ret < 0)
		return ret;

	ret = s3fwrn5_fw_send_msg(fw_info, msg, &rsp);
	kfree_skb(msg);
	if (ret < 0)
		return ret;

	hdr = (struct s3fwrn5_fw_header *) rsp->data;
	if (hdr->code != S3FWRN5_FW_RET_SUCCESS) {
		ret = -EINVAL;
		goto out;
	}

	memcpy(bootinfo, rsp->data + S3FWRN5_FW_HDR_SIZE, 10);

out:
	kfree_skb(rsp);
	return ret;

Annotation

Implementation Notes