drivers/hid/hid-u2fzero.c

Source file repositories/reference/linux-study-clean/drivers/hid/hid-u2fzero.c

File Facts

System
Linux kernel
Corpus path
drivers/hid/hid-u2fzero.c
Extension
.c
Size
8798 bytes
Lines
409
Domain
Driver Families
Bucket
drivers/hid
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 hw_revision_config {
	u8 rng_cmd;
	u8 wink_cmd;
	const char *name;
};

static const struct hw_revision_config hw_configs[] = {
	[HW_U2FZERO] = {
		.rng_cmd  = 0x21,
		.wink_cmd = 0x24,
		.name = "U2F Zero",
	},
	[HW_NITROKEY_U2F] = {
		.rng_cmd  = 0xc0,
		.wink_cmd = 0xc2,
		.name = "NitroKey U2F",
	},
};

/* We only use broadcast (CID-less) messages */
#define CID_BROADCAST		0xffffffff

struct u2f_hid_msg {
	u32 cid;
	union {
		struct {
			u8 cmd;
			u8 bcnth;
			u8 bcntl;
			u8 data[HID_REPORT_SIZE - 7];
		} init;
		struct {
			u8 seq;
			u8 data[HID_REPORT_SIZE - 5];
		} cont;
	};
} __packed;

struct u2f_hid_report {
	u8 report_type;
	struct u2f_hid_msg msg;
} __packed;

#define U2F_HID_MSG_LEN(f)	(size_t)(((f).init.bcnth << 8) + (f).init.bcntl)

struct u2fzero_device {
	struct hid_device	*hdev;
	struct urb		*urb;	    /* URB for the RNG data */
	struct led_classdev	ldev;	    /* Embedded struct for led */
	struct hwrng		hwrng;	    /* Embedded struct for hwrng */
	char			*led_name;
	char			*rng_name;
	u8			*buf_out;
	u8			*buf_in;
	struct mutex		lock;
	bool			present;
	kernel_ulong_t		hw_revision;
};

static int u2fzero_send(struct u2fzero_device *dev, struct u2f_hid_report *req)
{
	int ret;

	mutex_lock(&dev->lock);

	memcpy(dev->buf_out, req, sizeof(struct u2f_hid_report));

	ret = hid_hw_output_report(dev->hdev, dev->buf_out,
				   sizeof(struct u2f_hid_msg));

	mutex_unlock(&dev->lock);

	if (ret < 0)
		return ret;

	return ret == sizeof(struct u2f_hid_msg) ? 0 : -EMSGSIZE;
}

struct u2fzero_transfer_context {
	struct completion done;
	int status;
};

static void u2fzero_read_callback(struct urb *urb)
{
	struct u2fzero_transfer_context *ctx = urb->context;

	ctx->status = urb->status;
	complete(&ctx->done);
}

Annotation

Implementation Notes