summaryrefslogtreecommitdiff
path: root/drivers/hid/hid-u2fzero.c
diff options
context:
space:
mode:
authorAndrej Shadura <andrew.shadura@collabora.co.uk>2021-10-23 16:17:11 +0200
committerJiri Kosina <jkosina@suse.cz>2021-10-27 10:15:55 +0200
commit6748031a854dc016c02839aecbe267adc5fd0153 (patch)
treef54a11679db997d1e89020995d10217cc7d9b9bd /drivers/hid/hid-u2fzero.c
parent42d43c92fc577dca59ed74aec7868abec8d6ca6e (diff)
HID: u2fzero: Support NitroKey U2F revision of the device
NitroKey produced a clone of U2F Zero with a different firmware, which moved extra commands into the vendor range. Disambiguate hardware revisions and select the correct configuration in u2fzero_probe. Link: https://github.com/Nitrokey/nitrokey-fido-u2f-firmware/commit/a93c16b41f Signed-off-by: Andrej Shadura <andrew.shadura@collabora.co.uk> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/hid-u2fzero.c')
-rw-r--r--drivers/hid/hid-u2fzero.c45
1 files changed, 36 insertions, 9 deletions
diff --git a/drivers/hid/hid-u2fzero.c b/drivers/hid/hid-u2fzero.c
index d70cd3d7f583..7a7a17804247 100644
--- a/drivers/hid/hid-u2fzero.c
+++ b/drivers/hid/hid-u2fzero.c
@@ -26,6 +26,30 @@
#define HID_REPORT_SIZE 64
+enum hw_revision {
+ HW_U2FZERO,
+ HW_NITROKEY_U2F,
+};
+
+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
@@ -52,10 +76,6 @@ struct u2f_hid_report {
#define U2F_HID_MSG_LEN(f) (size_t)(((f).init.bcnth << 8) + (f).init.bcntl)
-/* Custom extensions to the U2FHID protocol */
-#define U2F_CUSTOM_GET_RNG 0x21
-#define U2F_CUSTOM_WINK 0x24
-
struct u2fzero_device {
struct hid_device *hdev;
struct urb *urb; /* URB for the RNG data */
@@ -67,6 +87,7 @@ struct u2fzero_device {
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)
@@ -154,7 +175,7 @@ static int u2fzero_blink(struct led_classdev *ldev)
.report_type = 0,
.msg.cid = CID_BROADCAST,
.msg.init = {
- .cmd = U2F_CUSTOM_WINK,
+ .cmd = hw_configs[dev->hw_revision].wink_cmd,
.bcnth = 0,
.bcntl = 0,
.data = {0},
@@ -182,7 +203,7 @@ static int u2fzero_rng_read(struct hwrng *rng, void *data,
.report_type = 0,
.msg.cid = CID_BROADCAST,
.msg.init = {
- .cmd = U2F_CUSTOM_GET_RNG,
+ .cmd = hw_configs[dev->hw_revision].rng_cmd,
.bcnth = 0,
.bcntl = 0,
.data = {0},
@@ -295,6 +316,8 @@ static int u2fzero_probe(struct hid_device *hdev,
if (dev == NULL)
return -ENOMEM;
+ dev->hw_revision = id->driver_data;
+
dev->buf_out = devm_kmalloc(&hdev->dev,
sizeof(struct u2f_hid_report), GFP_KERNEL);
if (dev->buf_out == NULL)
@@ -329,7 +352,7 @@ static int u2fzero_probe(struct hid_device *hdev,
return ret;
}
- hid_info(hdev, "U2F Zero LED initialised\n");
+ hid_info(hdev, "%s LED initialised\n", hw_configs[dev->hw_revision].name);
ret = u2fzero_init_hwrng(dev, minor);
if (ret) {
@@ -337,7 +360,7 @@ static int u2fzero_probe(struct hid_device *hdev,
return ret;
}
- hid_info(hdev, "U2F Zero RNG initialised\n");
+ hid_info(hdev, "%s RNG initialised\n", hw_configs[dev->hw_revision].name);
return 0;
}
@@ -357,7 +380,11 @@ static void u2fzero_remove(struct hid_device *hdev)
static const struct hid_device_id u2fzero_table[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL,
- USB_DEVICE_ID_U2F_ZERO) },
+ USB_DEVICE_ID_U2F_ZERO),
+ .driver_data = HW_U2FZERO },
+ { HID_USB_DEVICE(USB_VENDOR_ID_CLAY_LOGIC,
+ USB_DEVICE_ID_NITROKEY_U2F),
+ .driver_data = HW_NITROKEY_U2F },
{ }
};
MODULE_DEVICE_TABLE(hid, u2fzero_table);