]> err.no Git - yubikey-personalization/commitdiff
Add native Windows backend.
authorSimon Josefsson <simon@josefsson.org>
Sat, 9 Apr 2011 06:47:47 +0000 (08:47 +0200)
committerSimon Josefsson <simon@josefsson.org>
Sat, 9 Apr 2011 06:48:39 +0000 (08:48 +0200)
configure.ac
ykcore/Makefile.am
ykcore/ykcore_win32.c [deleted file]
ykcore/ykcore_windows.c [new file with mode: 0644]

index c0ecc7c0702ab4ae7434821ab7410953dd2936cf..18e32d7a10f9a8675f378c860e15cf2ffd5b3a58 100644 (file)
@@ -62,7 +62,7 @@ fi
 
 AC_ARG_WITH([backend],
   [AS_HELP_STRING([--with-backend=ARG],
-    [use specific backend; 'libusb-1.0', 'libusb' or 'osx'])],
+    [use specific backend; 'libusb-1.0', 'libusb', 'osx' or 'windows'])],
     [],
     [with_backend=check])
 
@@ -71,6 +71,7 @@ if test "x$with_backend" = xcheck; then
    AC_MSG_CHECKING([for backend])
    case "$host" in
     *-darwin*) with_backend=osx ;;
+    *-mingw*) with_backend=windows ;;
     *) PKG_CHECK_EXISTS([libusb-1.0], 
                                   [with_backend=libusb-1.0],
                           [with_backend=libusb])
@@ -110,9 +111,14 @@ if test x$with_backend = xosx; then
   LDFLAGS="$LDFLAGS -framework IOKit -framework CoreFoundation"
 fi
 
+if test x$with_backend = xwindows; then
+  LDFLAGS="$LDFLAGS -luuid -lsetupapi -lhid"
+fi
+
 AM_CONDITIONAL([BACKEND_LIBUSB], test x$with_backend = xlibusb)
 AM_CONDITIONAL([BACKEND_LIBUSB_1_0], test x$with_backend = xlibusb-1.0)
 AM_CONDITIONAL([BACKEND_OSX], test x$with_backend = xosx)
+AM_CONDITIONAL([BACKEND_WINDOWS], test x$with_backend = xwindows)
 
 gl_LD_VERSION_SCRIPT
 
index c21e8c81070a46360b10373570b97d372a6f5201..03ac1e4a23f89f82807f2eb56e2f0298e2725cb7 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (c) 2008, 2009, Yubico AB
+# Copyright (c) 2008, 2009, 2011, Yubico AB
 # All rights reserved.
 # 
 # Redistribution and use in source and binary forms, with or without
@@ -43,4 +43,8 @@ if BACKEND_OSX
 libykcore_la_SOURCES += ykcore_osx.c
 endif
 
-EXTRA_DIST = ykcore_stub.c ykcore_win32.c
+if BACKEND_WINDOWS
+libykcore_la_SOURCES += ykcore_windows.c
+endif
+
+EXTRA_DIST = ykcore_stub.c
diff --git a/ykcore/ykcore_win32.c b/ykcore/ykcore_win32.c
deleted file mode 100644 (file)
index 2a92c1c..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-/* -*- mode:C; c-file-style: "bsd" -*- */
-/* Please implement this.  Have a look at ykcore_libusb.c or some other
-   already implemented backend for inspiration. */
-#include "ykcore_stub.c"
diff --git a/ykcore/ykcore_windows.c b/ykcore/ykcore_windows.c
new file mode 100644 (file)
index 0000000..e87da7b
--- /dev/null
@@ -0,0 +1,193 @@
+/* -*- mode:C; c-file-style: "bsd" -*- */
+/*
+ * Copyright (c) 2008, 2011, Yubico AB
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "ykcore.h"
+#include "ykdef.h"
+#include "ykcore_backend.h"
+
+#include <stdio.h>
+#include <windows.h>
+#include <setupapi.h>
+#include <ntddkbd.h>
+typedef LONG NTSTATUS;
+#include <hidpi.h>
+
+BOOLEAN __stdcall HidD_GetAttributes(
+       HANDLE HidDeviceObject,
+       PHIDD_ATTRIBUTES Attributes
+       );
+BOOLEAN __stdcall HidD_GetFeature(
+       HANDLE HidDeviceObject,
+       PVOID ReportBuffer,
+       ULONG ReportBufferLength
+       );
+BOOLEAN __stdcall HidD_SetFeature(
+       HANDLE HidDeviceObject,
+       PVOID ReportBuffer,
+       ULONG ReportBufferLength
+       );
+
+int _ykusb_start(void)
+{
+       return 1;
+}
+
+int _ykusb_stop(void)
+{
+       return 1;
+}
+
+void * _ykusb_open_device(int vendor_id, int product_id)
+{
+       HDEVINFO hi;
+       SP_DEVICE_INTERFACE_DATA di;
+       PSP_DEVICE_INTERFACE_DETAIL_DATA pi;
+       int i, numDev = 0;
+       LPTSTR path = 0;
+       DWORD len, rc;
+       HANDLE ret_handle = NULL;
+
+       yk_errno = YK_EUSBERR;
+
+       hi = SetupDiGetClassDevs(&GUID_DEVINTERFACE_KEYBOARD, 0, 0,
+                                DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
+       if (hi == INVALID_HANDLE_VALUE)
+               return NULL;
+
+       di.cbSize = sizeof (SP_DEVICE_INTERFACE_DATA);
+
+       for (i = 0; i < 1000; i++) {
+               if (!SetupDiEnumDeviceInterfaces(hi, 0, &GUID_DEVINTERFACE_KEYBOARD, i, &di))
+                       break;
+
+               if (SetupDiGetDeviceInterfaceDetail(hi, &di, 0, 0, &len, 0) || GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+                       break;
+
+               pi = malloc (len);
+               if (!pi) {
+                       yk_errno = YK_ENOMEM;
+                       goto done;
+               }
+               pi->cbSize = sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA);
+
+               rc = SetupDiGetDeviceInterfaceDetail(hi, &di, pi, len, &len, 0);
+               if (rc) {
+                       HANDLE m_handle;
+
+                       m_handle = CreateFile(pi->DevicePath, GENERIC_WRITE,
+                                             FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
+                       if (m_handle != INVALID_HANDLE_VALUE) {
+                               HIDD_ATTRIBUTES devInfo;
+
+                               if (HidD_GetAttributes(m_handle, &devInfo)) {
+                                       if (devInfo.VendorID == vendor_id && devInfo.ProductID == product_id) {
+                                               ret_handle = m_handle;
+                                               free (pi);
+                                               goto done;
+                                       }
+                               }
+                       }
+                       CloseHandle (m_handle);
+               }
+
+               free (pi);
+
+               if (!rc)
+                       break;
+       }
+
+       yk_errno = YK_ENOKEY;
+
+done:
+       SetupDiDestroyDeviceInfoList(hi);
+       return ret_handle;
+}
+
+int _ykusb_close_device(void *yk)
+{
+       HANDLE h = yk;
+
+       CloseHandle(h);
+
+       return 1;
+}
+
+#define EXPECT_SIZE 8
+#define FEATURE_BUF_SIZE 9
+
+int _ykusb_read(void *dev, int report_type, int report_number,
+               char *buffer, int buffer_size)
+{
+       HANDLE h = dev;
+       BYTE buf[FEATURE_BUF_SIZE];
+
+       if (buffer_size != EXPECT_SIZE) {
+               yk_errno = YK_EUSBERR;
+               return 0;
+       }
+
+       memset(buf, 0, sizeof(buf));
+
+       if (!HidD_GetFeature(h, buf, sizeof (buf))) {
+               yk_errno = YK_EUSBERR;
+               return 0;
+       }
+
+       memcpy (buffer, buf + 1, buffer_size);
+
+       return buffer_size;
+}
+
+int _ykusb_write(void *dev, int report_type, int report_number,
+                char *buffer, int buffer_size)
+{
+       HANDLE h = dev;
+       BYTE buf[FEATURE_BUF_SIZE];
+
+       if (buffer_size != EXPECT_SIZE) {
+               yk_errno = YK_EUSBERR;
+               return 0;
+       }
+
+       buf[0] = 0;
+       memcpy (buf + 1, buffer, buffer_size);
+
+       if (!HidD_SetFeature(h, buf, sizeof (buf))) {
+               yk_errno = YK_EUSBERR;
+               return 0;
+       }
+
+       return 1;
+}
+
+const char *_ykusb_strerror(void)
+{
+       return "USB error\n";
+}