summaryrefslogtreecommitdiff
path: root/src/hid_hidapi.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/hid_hidapi.c')
-rw-r--r--src/hid_hidapi.c138
1 files changed, 138 insertions, 0 deletions
diff --git a/src/hid_hidapi.c b/src/hid_hidapi.c
new file mode 100644
index 0000000..915621f
--- /dev/null
+++ b/src/hid_hidapi.c
@@ -0,0 +1,138 @@
1/*
2 * Copyright (c) 2019 Google LLC. All rights reserved.
3 * Use of this source code is governed by a BSD-style
4 * license that can be found in the LICENSE file.
5 */
6
7#include <hidapi/hidapi.h>
8
9#include <stdlib.h>
10#include <string.h>
11#include <wchar.h>
12
13#include "fido.h"
14
15static size_t
16fido_wcslen(const wchar_t *wcs)
17{
18 size_t l = 0;
19 while (*wcs++ != L'\0')
20 l++;
21 return l;
22}
23
24static char *
25wcs_to_cs(const wchar_t *wcs)
26{
27 char *cs;
28 size_t i;
29
30 if (wcs == NULL || (cs = calloc(fido_wcslen(wcs) + 1, 1)) == NULL)
31 return NULL;
32
33 for (i = 0; i < fido_wcslen(wcs); i++) {
34 if (wcs[i] >= 128) {
35 /* give up on parsing non-ASCII text */
36 free(cs);
37 return strdup("hidapi device");
38 }
39 cs[i] = (char)wcs[i];
40 }
41
42 return cs;
43}
44
45static int
46copy_info(fido_dev_info_t *di, const struct hid_device_info *d)
47{
48 memset(di, 0, sizeof(*di));
49
50 if (d->path != NULL)
51 di->path = strdup(d->path);
52 else
53 di->path = strdup("");
54
55 if (d->manufacturer_string != NULL)
56 di->manufacturer = wcs_to_cs(d->manufacturer_string);
57 else
58 di->manufacturer = strdup("");
59
60 if (d->product_string != NULL)
61 di->product = wcs_to_cs(d->product_string);
62 else
63 di->product = strdup("");
64
65 if (di->path == NULL ||
66 di->manufacturer == NULL ||
67 di->product == NULL) {
68 free(di->path);
69 free(di->manufacturer);
70 free(di->product);
71 return -1;
72 }
73
74 di->product_id = d->product_id;
75 di->vendor_id = d->vendor_id;
76 di->io = (fido_dev_io_t) {
77 &fido_hid_open,
78 &fido_hid_close,
79 &fido_hid_read,
80 &fido_hid_write,
81 };
82
83 return 0;
84}
85
86void *
87fido_hid_open(const char *path)
88{
89 return hid_open_path(path);
90}
91
92void
93fido_hid_close(void *hid_dev_handle)
94{
95 hid_close(hid_dev_handle);
96}
97
98int
99fido_hid_read(void *hid_dev_handle, unsigned char *buf, size_t len, int ms)
100{
101 return hid_read_timeout(hid_dev_handle, buf, len, ms);
102}
103
104int
105fido_hid_write(void *hid_dev_handle, const unsigned char *buf, size_t len)
106{
107 return hid_write(hid_dev_handle, buf, len);
108}
109
110int
111fido_hid_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen)
112{
113 struct hid_device_info *hdi;
114
115 *olen = 0;
116
117 if (ilen == 0)
118 return FIDO_OK; /* nothing to do */
119 if (devlist == NULL)
120 return FIDO_ERR_INVALID_ARGUMENT;
121 if ((hdi = hid_enumerate(0, 0)) == NULL)
122 return FIDO_OK; /* nothing to do */
123
124 for (struct hid_device_info *d = hdi; d != NULL; d = d->next) {
125#if defined(_WIN32) || defined(__APPLE__)
126 if (d->usage_page != 0xf1d0)
127 continue;
128#endif
129 if (copy_info(&devlist[*olen], d) == 0) {
130 if (++(*olen) == ilen)
131 break;
132 }
133 }
134
135 hid_free_enumeration(hdi);
136
137 return FIDO_OK;
138}