Lines 1-13
Link Here
|
1 |
/* |
1 |
/* |
2 |
* Copyright (c) 2020 Yubico AB. All rights reserved. |
2 |
* Copyright (c) 2020-2022 Yubico AB. All rights reserved. |
3 |
* Use of this source code is governed by a BSD-style |
3 |
* Use of this source code is governed by a BSD-style |
4 |
* license that can be found in the LICENSE file. |
4 |
* license that can be found in the LICENSE file. |
5 |
*/ |
5 |
*/ |
6 |
|
6 |
|
7 |
#include <sys/types.h> |
7 |
#include <sys/param.h> |
8 |
|
8 |
|
9 |
#include <dev/usb/usb_ioctl.h> |
9 |
#include <dev/usb/usb_ioctl.h> |
10 |
#include <dev/usb/usbhid.h> |
10 |
#include <dev/usb/usbhid.h> |
|
|
11 |
#if __FreeBSD_version >= 1300500 |
12 |
#include <dev/hid/hidraw.h> |
13 |
#define USE_HIDRAW /* see usbhid(4) and hidraw(4) on FreeBSD 13+ */ |
14 |
#endif |
11 |
|
15 |
|
12 |
#include <errno.h> |
16 |
#include <errno.h> |
13 |
#include <unistd.h> |
17 |
#include <unistd.h> |
Lines 57-64
is_fido(int fd)
Link Here
|
57 |
return (usage_page == 0xf1d0); |
61 |
return (usage_page == 0xf1d0); |
58 |
} |
62 |
} |
59 |
|
63 |
|
|
|
64 |
#ifdef USE_HIDRAW |
65 |
static int |
66 |
copy_info_hidraw(fido_dev_info_t *di, const char *path) |
67 |
{ |
68 |
int fd = -1; |
69 |
int ok = -1; |
70 |
struct usb_device_info udi; |
71 |
struct hidraw_devinfo devinfo; |
72 |
char rawname[129]; |
73 |
|
74 |
memset(di, 0, sizeof(*di)); |
75 |
memset(&udi, 0, sizeof(udi)); |
76 |
memset(&devinfo, 0, sizeof(devinfo)); |
77 |
memset(rawname, 0, sizeof(rawname)); |
78 |
|
79 |
if ((fd = fido_hid_unix_open(path)) == -1 || is_fido(fd) == 0) |
80 |
goto fail; |
81 |
|
82 |
if (ioctl(fd, IOCTL_REQ(USB_GET_DEVICEINFO), &udi) == -1) { |
83 |
if (ioctl(fd, IOCTL_REQ(HIDIOCGRAWINFO), &devinfo) == -1 || |
84 |
ioctl(fd, IOCTL_REQ(HIDIOCGRAWNAME(128)), rawname) == -1 || |
85 |
(di->path = strdup(path)) == NULL || |
86 |
(di->manufacturer = strdup(UHID_VENDOR)) == NULL || |
87 |
(di->product = strdup(rawname)) == NULL) |
88 |
goto fail; |
89 |
di->vendor_id = devinfo.vendor; |
90 |
di->product_id = devinfo.product; |
91 |
} else { |
92 |
if ((di->path = strdup(path)) == NULL || |
93 |
(di->manufacturer = strdup(udi.udi_vendor)) == NULL || |
94 |
(di->product = strdup(udi.udi_product)) == NULL) |
95 |
goto fail; |
96 |
di->vendor_id = (int16_t)udi.udi_vendorNo; |
97 |
di->product_id = (int16_t)udi.udi_productNo; |
98 |
} |
99 |
|
100 |
ok = 0; |
101 |
fail: |
102 |
if (fd != -1 && close(fd) == -1) |
103 |
fido_log_error(errno, "%s: close %s", __func__, path); |
104 |
|
105 |
if (ok < 0) { |
106 |
free(di->path); |
107 |
free(di->manufacturer); |
108 |
free(di->product); |
109 |
explicit_bzero(di, sizeof(*di)); |
110 |
} |
111 |
|
112 |
return (ok); |
113 |
} |
114 |
#endif /* USE_HIDRAW */ |
115 |
|
60 |
static int |
116 |
static int |
61 |
copy_info(fido_dev_info_t *di, const char *path) |
117 |
copy_info_uhid(fido_dev_info_t *di, const char *path) |
62 |
{ |
118 |
{ |
63 |
int fd = -1; |
119 |
int fd = -1; |
64 |
int ok = -1; |
120 |
int ok = -1; |
Lines 81-94
copy_info(fido_dev_info_t *di, const char *path)
Link Here
|
81 |
(di->manufacturer = strdup(udi.udi_vendor)) == NULL || |
137 |
(di->manufacturer = strdup(udi.udi_vendor)) == NULL || |
82 |
(di->product = strdup(udi.udi_product)) == NULL) |
138 |
(di->product = strdup(udi.udi_product)) == NULL) |
83 |
goto fail; |
139 |
goto fail; |
84 |
|
|
|
85 |
di->vendor_id = (int16_t)udi.udi_vendorNo; |
140 |
di->vendor_id = (int16_t)udi.udi_vendorNo; |
86 |
di->product_id = (int16_t)udi.udi_productNo; |
141 |
di->product_id = (int16_t)udi.udi_productNo; |
87 |
|
142 |
|
88 |
ok = 0; |
143 |
ok = 0; |
89 |
fail: |
144 |
fail: |
90 |
if (fd != -1) |
145 |
if (fd != -1 && close(fd) == -1) |
91 |
close(fd); |
146 |
fido_log_error(errno, "%s: close %s", __func__, path); |
92 |
|
147 |
|
93 |
if (ok < 0) { |
148 |
if (ok < 0) { |
94 |
free(di->path); |
149 |
free(di->path); |
Lines 106-122
fido_hid_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen)
Link Here
|
106 |
char path[64]; |
161 |
char path[64]; |
107 |
size_t i; |
162 |
size_t i; |
108 |
|
163 |
|
109 |
*olen = 0; |
|
|
110 |
|
111 |
if (ilen == 0) |
164 |
if (ilen == 0) |
112 |
return (FIDO_OK); /* nothing to do */ |
165 |
return (FIDO_OK); /* nothing to do */ |
113 |
|
166 |
|
114 |
if (devlist == NULL || olen == NULL) |
167 |
if (devlist == NULL || olen == NULL) |
115 |
return (FIDO_ERR_INVALID_ARGUMENT); |
168 |
return (FIDO_ERR_INVALID_ARGUMENT); |
116 |
|
169 |
|
117 |
for (i = *olen = 0; i < MAX_UHID && *olen < ilen; i++) { |
170 |
*olen = 0; |
|
|
171 |
|
172 |
#ifdef USE_HIDRAW |
173 |
for (i = 0; i < MAX_UHID && *olen < ilen; i++) { |
174 |
snprintf(path, sizeof(path), "/dev/hidraw%zu", i); |
175 |
if (copy_info_hidraw(&devlist[*olen], path) == 0) { |
176 |
devlist[*olen].io = (fido_dev_io_t) { |
177 |
fido_hid_open, |
178 |
fido_hid_close, |
179 |
fido_hid_read, |
180 |
fido_hid_write, |
181 |
}; |
182 |
++(*olen); |
183 |
} |
184 |
} |
185 |
/* hidraw(4) is preferred over uhid(4) */ |
186 |
if (*olen != 0) |
187 |
return (FIDO_OK); |
188 |
#endif /* USE_HIDRAW */ |
189 |
|
190 |
for (i = 0; i < MAX_UHID && *olen < ilen; i++) { |
118 |
snprintf(path, sizeof(path), "/dev/uhid%zu", i); |
191 |
snprintf(path, sizeof(path), "/dev/uhid%zu", i); |
119 |
if (copy_info(&devlist[*olen], path) == 0) { |
192 |
if (copy_info_uhid(&devlist[*olen], path) == 0) { |
120 |
devlist[*olen].io = (fido_dev_io_t) { |
193 |
devlist[*olen].io = (fido_dev_io_t) { |
121 |
fido_hid_open, |
194 |
fido_hid_open, |
122 |
fido_hid_close, |
195 |
fido_hid_close, |
Lines 153-158
fido_hid_open(const char *path)
Link Here
|
153 |
ugd.ugd_data = buf; |
226 |
ugd.ugd_data = buf; |
154 |
ugd.ugd_maxlen = sizeof(buf); |
227 |
ugd.ugd_maxlen = sizeof(buf); |
155 |
|
228 |
|
|
|
229 |
/* |
230 |
* N.B. if ctx->fd is an hidraw(4) device, the ioctl() below puts it in |
231 |
* uhid(4) compat mode, which we need to keep fido_hid_write() as-is. |
232 |
*/ |
156 |
if ((r = ioctl(ctx->fd, IOCTL_REQ(USB_GET_REPORT_DESC), &ugd) == -1) || |
233 |
if ((r = ioctl(ctx->fd, IOCTL_REQ(USB_GET_REPORT_DESC), &ugd) == -1) || |
157 |
ugd.ugd_actlen > sizeof(buf) || |
234 |
ugd.ugd_actlen > sizeof(buf) || |
158 |
fido_hid_get_report_len(ugd.ugd_data, ugd.ugd_actlen, |
235 |
fido_hid_get_report_len(ugd.ugd_data, ugd.ugd_actlen, |