summaryrefslogtreecommitdiff
path: root/src/hid_openbsd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/hid_openbsd.c')
-rw-r--r--src/hid_openbsd.c91
1 files changed, 24 insertions, 67 deletions
diff --git a/src/hid_openbsd.c b/src/hid_openbsd.c
index 2b31dba..319f7b8 100644
--- a/src/hid_openbsd.c
+++ b/src/hid_openbsd.c
@@ -8,19 +8,16 @@
8 8
9#include <sys/ioctl.h> 9#include <sys/ioctl.h>
10#include <dev/usb/usb.h> 10#include <dev/usb/usb.h>
11#include <dev/usb/usbhid.h>
12 11
13#include <errno.h> 12#include <errno.h>
14#include <fcntl.h> 13#include <fcntl.h>
15#include <string.h> 14#include <string.h>
16#include <unistd.h> 15#include <unistd.h>
17#include <usbhid.h>
18#include <poll.h> 16#include <poll.h>
19 17
20#include "fido.h" 18#include "fido.h"
21 19
22#define MAX_UHID 64 20#define MAX_UHID 64
23#define MAX_REPORT_LEN (sizeof(((struct usb_ctl_report *)(NULL))->ucr_data))
24 21
25struct hid_openbsd { 22struct hid_openbsd {
26 int fd; 23 int fd;
@@ -33,11 +30,8 @@ fido_hid_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen)
33{ 30{
34 size_t i; 31 size_t i;
35 char path[64]; 32 char path[64];
36 int is_fido, fd; 33 int fd;
37 struct usb_device_info udi; 34 struct usb_device_info udi;
38 report_desc_t rdesc = NULL;
39 hid_data_t hdata = NULL;
40 hid_item_t hitem;
41 fido_dev_info_t *di; 35 fido_dev_info_t *di;
42 36
43 if (ilen == 0) 37 if (ilen == 0)
@@ -47,7 +41,7 @@ fido_hid_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen)
47 return (FIDO_ERR_INVALID_ARGUMENT); 41 return (FIDO_ERR_INVALID_ARGUMENT);
48 42
49 for (i = *olen = 0; i < MAX_UHID && *olen < ilen; i++) { 43 for (i = *olen = 0; i < MAX_UHID && *olen < ilen; i++) {
50 snprintf(path, sizeof(path), "/dev/uhid%zu", i); 44 snprintf(path, sizeof(path), "/dev/fido/%zu", i);
51 if ((fd = open(path, O_RDWR)) == -1) { 45 if ((fd = open(path, O_RDWR)) == -1) {
52 if (errno != ENOENT && errno != ENXIO) { 46 if (errno != ENOENT && errno != ENXIO) {
53 fido_log_debug("%s: open %s: %s", __func__, 47 fido_log_debug("%s: open %s: %s", __func__,
@@ -55,6 +49,7 @@ fido_hid_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen)
55 } 49 }
56 continue; 50 continue;
57 } 51 }
52
58 memset(&udi, 0, sizeof(udi)); 53 memset(&udi, 0, sizeof(udi));
59 if (ioctl(fd, USB_GET_DEVICEINFO, &udi) != 0) { 54 if (ioctl(fd, USB_GET_DEVICEINFO, &udi) != 0) {
60 fido_log_debug("%s: get device info %s: %s", __func__, 55 fido_log_debug("%s: get device info %s: %s", __func__,
@@ -62,35 +57,8 @@ fido_hid_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen)
62 close(fd); 57 close(fd);
63 continue; 58 continue;
64 } 59 }
65 if ((rdesc = hid_get_report_desc(fd)) == NULL) {
66 fido_log_debug("%s: failed to get report descriptor: %s",
67 __func__, path);
68 close(fd);
69 continue;
70 }
71 if ((hdata = hid_start_parse(rdesc,
72 1<<hid_collection, -1)) == NULL) {
73 fido_log_debug("%s: failed to parse report descriptor: %s",
74 __func__, path);
75 hid_dispose_report_desc(rdesc);
76 close(fd);
77 continue;
78 }
79 is_fido = 0;
80 for (is_fido = 0; !is_fido;) {
81 memset(&hitem, 0, sizeof(hitem));
82 if (hid_get_item(hdata, &hitem) <= 0)
83 break;
84 if ((hitem._usage_page & 0xFFFF0000) == 0xf1d00000)
85 is_fido = 1;
86 }
87 hid_end_parse(hdata);
88 hid_dispose_report_desc(rdesc);
89 close(fd); 60 close(fd);
90 61
91 if (!is_fido)
92 continue;
93
94 fido_log_debug("%s: %s: bus = 0x%02x, addr = 0x%02x", 62 fido_log_debug("%s: %s: bus = 0x%02x, addr = 0x%02x",
95 __func__, path, udi.udi_bus, udi.udi_addr); 63 __func__, path, udi.udi_bus, udi.udi_addr);
96 fido_log_debug("%s: %s: vendor = \"%s\", product = \"%s\"", 64 fido_log_debug("%s: %s: vendor = \"%s\", product = \"%s\"",
@@ -116,8 +84,8 @@ fido_hid_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen)
116 explicit_bzero(di, sizeof(*di)); 84 explicit_bzero(di, sizeof(*di));
117 return FIDO_ERR_INTERNAL; 85 return FIDO_ERR_INTERNAL;
118 } 86 }
119 di->vendor_id = udi.udi_vendorNo; 87 di->vendor_id = (int16_t)udi.udi_vendorNo;
120 di->product_id = udi.udi_productNo; 88 di->product_id = (int16_t)udi.udi_productNo;
121 (*olen)++; 89 (*olen)++;
122 } 90 }
123 91
@@ -184,42 +152,15 @@ void *
184fido_hid_open(const char *path) 152fido_hid_open(const char *path)
185{ 153{
186 struct hid_openbsd *ret = NULL; 154 struct hid_openbsd *ret = NULL;
187 report_desc_t rdesc = NULL;
188 int len, usb_report_id = 0;
189 155
190 if ((ret = calloc(1, sizeof(*ret))) == NULL || 156 if ((ret = calloc(1, sizeof(*ret))) == NULL ||
191 (ret->fd = open(path, O_RDWR)) < 0) { 157 (ret->fd = open(path, O_RDWR)) < 0) {
192 free(ret); 158 free(ret);
193 return (NULL); 159 return (NULL);
194 } 160 }
195 if (ioctl(ret->fd, USB_GET_REPORT_ID, &usb_report_id) != 0) { 161 ret->report_in_len = ret->report_out_len = CTAP_MAX_REPORT_LEN;
196 fido_log_debug("%s: failed to get report ID: %s", __func__, 162 fido_log_debug("%s: inlen = %zu outlen = %zu", __func__,
197 strerror(errno)); 163 ret->report_in_len, ret->report_out_len);
198 goto fail;
199 }
200 if ((rdesc = hid_get_report_desc(ret->fd)) == NULL) {
201 fido_log_debug("%s: failed to get report descriptor", __func__);
202 goto fail;
203 }
204 if ((len = hid_report_size(rdesc, hid_input, usb_report_id)) <= 0 ||
205 (size_t)len > MAX_REPORT_LEN) {
206 fido_log_debug("%s: bad input report size %d", __func__, len);
207 goto fail;
208 }
209 ret->report_in_len = (size_t)len;
210 if ((len = hid_report_size(rdesc, hid_output, usb_report_id)) <= 0 ||
211 (size_t)len > MAX_REPORT_LEN) {
212 fido_log_debug("%s: bad output report size %d", __func__, len);
213 fail:
214 hid_dispose_report_desc(rdesc);
215 close(ret->fd);
216 free(ret);
217 return NULL;
218 }
219 ret->report_out_len = (size_t)len;
220 hid_dispose_report_desc(rdesc);
221 fido_log_debug("%s: USB report ID %d, inlen = %zu outlen = %zu",
222 __func__, usb_report_id, ret->report_in_len, ret->report_out_len);
223 164
224 /* 165 /*
225 * OpenBSD (as of 201910) has a bug that causes it to lose 166 * OpenBSD (as of 201910) has a bug that causes it to lose
@@ -281,3 +222,19 @@ fido_hid_write(void *handle, const unsigned char *buf, size_t len)
281 } 222 }
282 return ((int)len); 223 return ((int)len);
283} 224}
225
226size_t
227fido_hid_report_in_len(void *handle)
228{
229 struct hid_openbsd *ctx = handle;
230
231 return (ctx->report_in_len);
232}
233
234size_t
235fido_hid_report_out_len(void *handle)
236{
237 struct hid_openbsd *ctx = handle;
238
239 return (ctx->report_out_len);
240}