[Spice-devel] [PATCH 5/6] usbclerk: add usbredirfilter & stdint.h

Arnon Gilboa agilboa at redhat.com
Mon Jul 23 02:23:07 PDT 2012


until switching to mingw build
---
 stdint.h         |  256 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 usbredirfilter.c |  260 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 usbredirfilter.h |  127 ++++++++++++++++++++++++++
 3 files changed, 643 insertions(+), 0 deletions(-)
 create mode 100644 stdint.h
 create mode 100644 usbredirfilter.c
 create mode 100644 usbredirfilter.h

diff --git a/stdint.h b/stdint.h
new file mode 100644
index 0000000..00988d9
--- /dev/null
+++ b/stdint.h
@@ -0,0 +1,256 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file was originally part of the w64 mingw-runtime package.
+ */
+
+/* ISO C9x  7.18  Integer types <stdint.h>
+ * Based on ISO/IEC SC22/WG14 9899 Committee draft (SC22 N2794)
+ *
+ *  THIS SOFTWARE IS NOT COPYRIGHTED
+ *
+ *  Contributor: Danny Smith <danny_r_smith_2001 at yahoo.co.nz>
+ *  Modified for libusb/MSVC: Pete Batard <pbatard at gmail.com>
+ *
+ *  This source code is offered for use in the public domain. You may
+ *  use, modify or distribute it freely.
+ *
+ *  This code is distributed in the hope that it will be useful but
+ *  WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
+ *  DISCLAIMED. This includes but is not limited to warranties of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *  Date: 2010-04-02
+ */
+
+#ifndef _MSC_VER
+#error This header should only be used with Microsoft compilers
+#endif
+
+#ifndef _STDINT_H
+#define _STDINT_H
+
+#ifndef _INTPTR_T_DEFINED
+#define _INTPTR_T_DEFINED
+#ifndef __intptr_t_defined
+#define __intptr_t_defined
+#undef intptr_t
+#ifdef _WIN64
+  typedef __int64 intptr_t;
+#else
+  typedef int intptr_t;
+#endif /* _WIN64 */
+#endif /* __intptr_t_defined */
+#endif /* _INTPTR_T_DEFINED */
+
+#ifndef _UINTPTR_T_DEFINED
+#define _UINTPTR_T_DEFINED
+#ifndef __uintptr_t_defined
+#define __uintptr_t_defined
+#undef uintptr_t
+#ifdef _WIN64
+  typedef unsigned __int64 uintptr_t;
+#else
+  typedef unsigned int uintptr_t;
+#endif /* _WIN64 */
+#endif /* __uintptr_t_defined */
+#endif /* _UINTPTR_T_DEFINED */
+
+#ifndef _PTRDIFF_T_DEFINED
+#define _PTRDIFF_T_DEFINED
+#ifndef _PTRDIFF_T_
+#define _PTRDIFF_T_
+#undef ptrdiff_t
+#ifdef _WIN64
+  typedef __int64 ptrdiff_t;
+#else
+  typedef int ptrdiff_t;
+#endif /* _WIN64 */
+#endif /* _PTRDIFF_T_ */
+#endif /* _PTRDIFF_T_DEFINED */
+
+#ifndef _WCHAR_T_DEFINED
+#define _WCHAR_T_DEFINED
+#ifndef __cplusplus
+  typedef unsigned short wchar_t;
+#endif /* C++ */
+#endif /* _WCHAR_T_DEFINED */
+
+#ifndef _WCTYPE_T_DEFINED
+#define _WCTYPE_T_DEFINED
+#ifndef _WINT_T
+#define _WINT_T
+  typedef unsigned short wint_t;
+  typedef unsigned short wctype_t;
+#endif /* _WINT_T */
+#endif /* _WCTYPE_T_DEFINED */
+
+/* 7.18.1.1  Exact-width integer types */
+typedef __int8 int8_t;
+typedef unsigned __int8   uint8_t;
+typedef __int16  int16_t;
+typedef unsigned __int16  uint16_t;
+typedef __int32  int32_t;
+typedef unsigned __int32  uint32_t;
+typedef __int64  int64_t;
+typedef unsigned __int64   uint64_t;
+
+/* 7.18.1.2  Minimum-width integer types */
+typedef signed char int_least8_t;
+typedef unsigned char   uint_least8_t;
+typedef short  int_least16_t;
+typedef unsigned short  uint_least16_t;
+typedef int  int_least32_t;
+typedef unsigned   uint_least32_t;
+typedef __int64  int_least64_t;
+typedef unsigned __int64   uint_least64_t;
+
+/*  7.18.1.3  Fastest minimum-width integer types
+ *  Not actually guaranteed to be fastest for all purposes
+ *  Here we use the exact-width types for 8 and 16-bit ints.
+ */
+typedef __int8 int_fast8_t;
+typedef unsigned __int8 uint_fast8_t;
+typedef __int16  int_fast16_t;
+typedef unsigned __int16  uint_fast16_t;
+typedef __int32  int_fast32_t;
+typedef unsigned  __int32  uint_fast32_t;
+typedef __int64  int_fast64_t;
+typedef unsigned __int64   uint_fast64_t;
+
+/* 7.18.1.5  Greatest-width integer types */
+typedef __int64  intmax_t;
+typedef unsigned __int64   uintmax_t;
+
+/* 7.18.2  Limits of specified-width integer types */
+
+/* 7.18.2.1  Limits of exact-width integer types */
+#define INT8_MIN (-128)
+#define INT16_MIN (-32768)
+#define INT32_MIN (-2147483647 - 1)
+#define INT64_MIN  (-9223372036854775807LL - 1)
+
+#define INT8_MAX 127
+#define INT16_MAX 32767
+#define INT32_MAX 2147483647
+#define INT64_MAX 9223372036854775807LL
+
+#define UINT8_MAX 255
+#define UINT16_MAX 65535
+#define UINT32_MAX 0xffffffffU  /* 4294967295U */
+#define UINT64_MAX 0xffffffffffffffffULL /* 18446744073709551615ULL */
+
+/* 7.18.2.2  Limits of minimum-width integer types */
+#define INT_LEAST8_MIN INT8_MIN
+#define INT_LEAST16_MIN INT16_MIN
+#define INT_LEAST32_MIN INT32_MIN
+#define INT_LEAST64_MIN INT64_MIN
+
+#define INT_LEAST8_MAX INT8_MAX
+#define INT_LEAST16_MAX INT16_MAX
+#define INT_LEAST32_MAX INT32_MAX
+#define INT_LEAST64_MAX INT64_MAX
+
+#define UINT_LEAST8_MAX UINT8_MAX
+#define UINT_LEAST16_MAX UINT16_MAX
+#define UINT_LEAST32_MAX UINT32_MAX
+#define UINT_LEAST64_MAX UINT64_MAX
+
+/* 7.18.2.3  Limits of fastest minimum-width integer types */
+#define INT_FAST8_MIN INT8_MIN
+#define INT_FAST16_MIN INT16_MIN
+#define INT_FAST32_MIN INT32_MIN
+#define INT_FAST64_MIN INT64_MIN
+
+#define INT_FAST8_MAX INT8_MAX
+#define INT_FAST16_MAX INT16_MAX
+#define INT_FAST32_MAX INT32_MAX
+#define INT_FAST64_MAX INT64_MAX
+
+#define UINT_FAST8_MAX UINT8_MAX
+#define UINT_FAST16_MAX UINT16_MAX
+#define UINT_FAST32_MAX UINT32_MAX
+#define UINT_FAST64_MAX UINT64_MAX
+
+/* 7.18.2.4  Limits of integer types capable of holding
+    object pointers */
+#ifdef _WIN64
+#define INTPTR_MIN INT64_MIN
+#define INTPTR_MAX INT64_MAX
+#define UINTPTR_MAX UINT64_MAX
+#else
+#define INTPTR_MIN INT32_MIN
+#define INTPTR_MAX INT32_MAX
+#define UINTPTR_MAX UINT32_MAX
+#endif
+
+/* 7.18.2.5  Limits of greatest-width integer types */
+#define INTMAX_MIN INT64_MIN
+#define INTMAX_MAX INT64_MAX
+#define UINTMAX_MAX UINT64_MAX
+
+/* 7.18.3  Limits of other integer types */
+#ifdef _WIN64
+#define PTRDIFF_MIN INT64_MIN
+#define PTRDIFF_MAX INT64_MAX
+#else
+#define PTRDIFF_MIN INT32_MIN
+#define PTRDIFF_MAX INT32_MAX
+#endif
+
+#define SIG_ATOMIC_MIN INT32_MIN
+#define SIG_ATOMIC_MAX INT32_MAX
+
+#ifndef SIZE_MAX
+#ifdef _WIN64
+#define SIZE_MAX UINT64_MAX
+#else
+#define SIZE_MAX UINT32_MAX
+#endif
+#endif
+
+#ifndef WCHAR_MIN  /* also in wchar.h */
+#define WCHAR_MIN 0U
+#define WCHAR_MAX 0xffffU
+#endif
+
+/*
+ * wint_t is unsigned short for compatibility with MS runtime
+ */
+#define WINT_MIN 0U
+#define WINT_MAX 0xffffU
+
+
+/* 7.18.4  Macros for integer constants */
+
+/* 7.18.4.1  Macros for minimum-width integer constants
+
+    Accoding to Douglas Gwyn <gwyn at arl.mil>:
+	"This spec was changed in ISO/IEC 9899:1999 TC1; in ISO/IEC
+	9899:1999 as initially published, the expansion was required
+	to be an integer constant of precisely matching type, which
+	is impossible to accomplish for the shorter types on most
+	platforms, because C99 provides no standard way to designate
+	an integer constant with width less than that of type int.
+	TC1 changed this to require just an integer constant
+	*expression* with *promoted* type."
+
+	The trick used here is from Clive D W Feather.
+*/
+
+#define INT8_C(val) (INT_LEAST8_MAX-INT_LEAST8_MAX+(val))
+#define INT16_C(val) (INT_LEAST16_MAX-INT_LEAST16_MAX+(val))
+#define INT32_C(val) (INT_LEAST32_MAX-INT_LEAST32_MAX+(val))
+/*  The 'trick' doesn't work in C89 for long long because, without
+    suffix, (val) will be evaluated as int, not intmax_t */
+#define INT64_C(val) val##i64
+
+#define UINT8_C(val) (val)
+#define UINT16_C(val) (val)
+#define UINT32_C(val) (val##i32)
+#define UINT64_C(val) val##ui64
+
+/* 7.18.4.2  Macros for greatest-width integer constants */
+#define INTMAX_C(val) val##i64
+#define UINTMAX_C(val) val##ui64
+
+#endif
diff --git a/usbredirfilter.c b/usbredirfilter.c
new file mode 100644
index 0000000..b55b2bf
--- /dev/null
+++ b/usbredirfilter.c
@@ -0,0 +1,260 @@
+/* usbredirfilter.h usb redirection filter header
+
+   Copyright 2012 Red Hat, Inc.
+
+   Red Hat Authors:
+   Hans de Goede <hdegoede at redhat.com>
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "usbredirfilter.h"
+
+int usbredirfilter_string_to_rules(
+    const char *filter_str, const char *token_sep, const char *rule_sep,
+    struct usbredirfilter_rule **rules_ret, int *rules_count_ret)
+{
+    char *rule, *token, *ep, *buf_end, *rule_end;
+    struct usbredirfilter_rule *rules = NULL;
+    int i, rules_count, *values, ret = 0;
+    char *buf = NULL;
+    const char *r;
+
+    *rules_ret = NULL;
+    *rules_count_ret = 0;
+
+    /* Figure out how much rules there are in the file, so we know how
+       much memory we must allocate for the rules array.
+       Note this will come up with a slightly too large number if there are
+       empty rule strings in the set. */
+    r = filter_str;
+    rules_count = 0;
+    while (r) {
+        r = strchr(r, rule_sep[0]);
+        if (r)
+            r++;
+        rules_count++;
+    }
+
+    rules = (struct usbredirfilter_rule *)calloc(rules_count, sizeof(struct usbredirfilter_rule));
+    if (!rules)
+        return -ENOMEM;
+
+    /* Make a copy since strtok mangles the string */
+    buf = strdup(filter_str);
+    if (!buf) {
+        ret = -ENOMEM;
+        goto leave;
+    }
+
+    /* And actually parse the string */
+    buf_end = buf + strlen(buf);
+    rules_count = 0;
+    rule = strtok(buf, rule_sep);
+    while (rule) {
+        rule_end = rule + strlen(rule);
+        /* We treat the filter rule as an array of ints for easier parsing */
+        values = (int *)&rules[rules_count];
+        token = strtok(rule, token_sep);
+        for (i = 0; i < 5 && token; i++) {
+            values[i] = strtol(token, &ep, 0);
+            if (*ep)
+                break;
+            token = strtok(NULL, token_sep);
+        }
+        if (i != 5 || token != NULL ||
+                usbredirfilter_verify(&rules[rules_count], 1)) {
+            ret = -EINVAL;
+            goto leave;
+        }
+        rules_count++;
+        if (rule_end < buf_end) {
+            rule = strtok(rule_end + 1, rule_sep);
+        } else {
+            rule = NULL;
+        }
+    }
+
+    *rules_ret = rules;
+    *rules_count_ret = rules_count;
+
+leave:
+    if (ret)
+        free(rules);
+    free(buf);
+    return ret;
+}
+
+char *usbredirfilter_rules_to_string(const struct usbredirfilter_rule *rules,
+    int rules_count, const char *token_sep, const char *rule_sep)
+{
+    int i;
+    char *str, *p;
+
+    if (usbredirfilter_verify(rules, rules_count))
+        return NULL;
+
+    /* We need 28 bytes per rule in the worst case */
+    str = (char *)malloc(28 * rules_count + 1);
+    if (!str)
+        return NULL;
+
+    p = str;
+    for (i = 0; i < rules_count; i++) {
+        if (rules[i].device_class != -1)
+            p += sprintf(p, "0x%02x%c", rules[i].device_class, *token_sep);
+        else
+            p += sprintf(p, "-1%c", *token_sep);
+
+        if (rules[i].vendor_id != -1)
+            p += sprintf(p, "0x%04x%c", rules[i].vendor_id, *token_sep);
+        else
+            p += sprintf(p, "-1%c", *token_sep);
+
+        if (rules[i].product_id != -1)
+            p += sprintf(p, "0x%04x%c", rules[i].product_id, *token_sep);
+        else
+            p += sprintf(p, "-1%c", *token_sep);
+
+        if (rules[i].device_version_bcd != -1)
+            p += sprintf(p, "0x%04x%c", rules[i].device_version_bcd, *token_sep);
+        else
+            p += sprintf(p, "-1%c", *token_sep);
+
+        p += sprintf(p, "%d%c", rules[i].allow ? 1:0, *rule_sep);
+    }
+
+    return str;
+}
+
+static int usbredirfilter_check1(const struct usbredirfilter_rule *rules,
+    int rules_count, uint8_t device_class, uint16_t vendor_id,
+    uint16_t product_id, uint16_t device_version_bcd, int default_allow)
+{
+    int i;
+
+    for (i = 0; i < rules_count; i++) {
+        if ((rules[i].device_class == -1 ||
+                rules[i].device_class == device_class) &&
+            (rules[i].vendor_id == -1 ||
+                rules[i].vendor_id == vendor_id) &&
+            (rules[i].product_id == -1 ||
+                rules[i].product_id == product_id) &&
+            (rules[i].device_version_bcd == -1 ||
+                rules[i].device_version_bcd == device_version_bcd)) {
+            /* Found a match ! */
+            return rules[i].allow ? 0 : -EPERM;
+        }
+    }
+
+    return default_allow ? 0 : -EPERM;
+}
+
+int usbredirfilter_check(
+    const struct usbredirfilter_rule *rules, int rules_count,
+    uint8_t device_class, uint8_t device_subclass, uint8_t device_protocol,
+    uint8_t *interface_class, uint8_t *interface_subclass,
+    uint8_t *interface_protocol, int interface_count,
+    uint16_t vendor_id, uint16_t product_id, uint16_t device_version_bcd,
+    int flags)
+{
+    int i, rc;
+
+    if (usbredirfilter_verify(rules, rules_count))
+        return -EINVAL;
+
+    /* Check the device_class */
+    if (device_class != 0x00 && device_class != 0xef) {
+        rc = usbredirfilter_check1(rules, rules_count, device_class,
+                                   vendor_id, product_id, device_version_bcd,
+                                   flags & usbredirfilter_fl_default_allow);
+        if (rc)
+            return rc;
+    }
+
+    /* Check the interface classes */
+    for (i = 0; i < interface_count; i++) {
+        if (!(flags & usbredirfilter_fl_dont_skip_non_boot_hid) &&
+                interface_count > 1 && interface_class[i] == 0x03 &&
+                interface_subclass[i] == 0x00 && interface_protocol[i] == 0x00)
+            continue;
+
+        rc = usbredirfilter_check1(rules, rules_count, interface_class[i],
+                                   vendor_id, product_id, device_version_bcd,
+                                   flags & usbredirfilter_fl_default_allow);
+        if (rc)
+            return rc;
+    }
+
+    return 0;
+}
+
+int usbredirfilter_verify(
+    const struct usbredirfilter_rule *rules, int rules_count)
+{
+    int i;
+
+    for (i = 0; i < rules_count; i++) {
+        if (rules[i].device_class < -1 || rules[i].device_class > 255)
+            return -EINVAL;
+        if (rules[i].vendor_id < -1 || rules[i].vendor_id > 65535)
+            return -EINVAL;
+        if (rules[i].product_id < -1 || rules[i].product_id > 65535)
+            return -EINVAL;
+        if (rules[i].device_version_bcd < -1 ||
+                rules[i].device_version_bcd > 65535)
+            return -EINVAL;
+    }
+    return 0;
+}
+
+void usbredirfilter_print(
+    const struct usbredirfilter_rule *rules, int rules_count, FILE *out)
+{
+    int i;
+    char device_class[16], vendor[16], product[16], version[16];
+
+    for (i = 0; i < rules_count; i++) {
+        if (rules[i].device_class != -1)
+            sprintf(device_class, " %02x", rules[i].device_class);
+        else
+            strcpy(device_class, "ANY");
+
+        if (rules[i].vendor_id != -1)
+            sprintf(vendor, "%04x", rules[i].vendor_id);
+        else
+            strcpy(vendor, " ANY");
+
+        if (rules[i].product_id != -1)
+            sprintf(product, "%04x", rules[i].product_id);
+        else
+            strcpy(product, " ANY");
+
+        if (rules[i].device_version_bcd != -1)
+            sprintf(version, "%2d.%02d",
+                    ((rules[i].device_version_bcd & 0xf000) >> 12) * 10 +
+                    ((rules[i].device_version_bcd & 0x0f00) >>  8),
+                    ((rules[i].device_version_bcd & 0x00f0) >>  4) * 10 +
+                    ((rules[i].device_version_bcd & 0x000f)));
+        else
+            strcpy(version, "  ANY");
+
+        fprintf(out, "Class %s ID %s:%s Version %s %s\n", device_class, vendor,
+                product, version, rules[i].allow ? "Allow":"Block");
+    }
+}
diff --git a/usbredirfilter.h b/usbredirfilter.h
new file mode 100644
index 0000000..9574d56
--- /dev/null
+++ b/usbredirfilter.h
@@ -0,0 +1,127 @@
+/* usbredirfilter.h usb redirection filter header
+
+   Copyright 2012 Red Hat, Inc.
+
+   Red Hat Authors:
+   Hans de Goede <hdegoede at redhat.com>
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef __USBREDIRFILTER_H
+#define __USBREDIRFILTER_H
+
+#include <stdio.h>
+
+#pragma warning(disable : 4996)
+#include "stdint.h"
+
+struct usbredirfilter_rule {
+    int device_class;       /* 0-255, -1 to match any class */
+    int vendor_id;          /* 0-65535, -1 to match any id */
+    int product_id;         /* 0-65535, -1 to match any id */
+    int device_version_bcd; /* 0-255, -1 to match any version */
+    int allow;              /* 0: deny redir for this device, non 0: allow */
+};
+
+/* Read a filter string and parse it into an array of usbredirfilter_rule-s.
+
+   Where each rule has the form of:
+   <class>,<vendor>,<product>,<version>,<allow>
+   Assuming "," as the specified token_sep character.
+
+   And the rules are themselves are separated by the rule_sep character, ie:
+   <rule1>|<rule2>|<rule3>
+
+   Assuming "|" as the rule_sep character. Note that with the seperator used
+   in this example the format matches the format as written by the RHEV-M USB
+   filter editor tool.
+
+   Note that the seperators must be single character strings!
+
+   On success the rules get returned in rules_ret and rules_count_ret, the
+   returned rules array should be freed with free() when the caller is done
+   with it.
+
+   Return value: 0 on success, -ENOMEM when allocating the rules array fails,
+       or -EINVAL when there is on parsing error.
+*/
+int usbredirfilter_string_to_rules(
+    const char *filter_str, const char *token_sep, const char *rule_sep,
+    struct usbredirfilter_rule **rules_ret, int *rules_count_ret);
+
+/* Convert a set of rules back to a string suitable for passing to
+   usbredirfilter_string_to_rules(); The returned string must be free()-ed
+   by the caller when it is done with it.
+
+   Return value: The string on sucess, or NULL if the rules fail verification,
+      or when allocating the string fails.
+*/
+char *usbredirfilter_rules_to_string(const struct usbredirfilter_rule *rules,
+    int rules_count, const char *token_sep, const char *rule_sep);
+
+/* Check if redirection of a device with the passed in device info is allowed
+   by the passed set of filter rules.
+
+   Since a device has class info at both the device level and the interface
+   level, this function does multiple passes.
+
+   First the rules are checked one by one against the given device info using
+   the device class info, if a matching rule is found, the result of the check
+   is that of that rule. If the result is deny, -EPERM will be returned.
+
+   Then the same is done substituting the device class info with the class info
+   from the interfaces. If any of the interfaces class checks result in a deny,
+   then -EPERM will be returned.
+
+   Note that under certain circumstances some passes are skipped:
+   - For devices with a device class of 0x00 or 0xef, the pass which checks the
+     device class is skipped.
+   - If the usbredirfilter_fl_dont_skip_non_boot_hid flag is not passed then
+     for devices with more then 1 interface and an interface with an interface
+     class of 0x03, an interface subclass of 0x00 and an interface protocol
+     of 0x00. the check is skipped for that interface. This allows to skip ie
+     checking the interface for volume buttons one some usbaudio class devices.
+
+   If the result of all (not skipped) passes is allow, then 0 will be returned,
+   which indicates that redirection should be allowed.
+
+   If a given pass does not match any rules the result of that pass will be
+   deny. This behavior can be changed with the usbredirfilter_fl_default_allow
+   flag, if this flas is set the result on no matching rules will be allow.
+
+   Return value: 0 when redirection is allowed, -EINVAL for invalid parameters,
+      -EPERM when redirection is blocked by the filter rules.
+*/
+enum {
+    usbredirfilter_fl_default_allow = 0x01,
+    usbredirfilter_fl_dont_skip_non_boot_hid = 0x02,
+};
+int usbredirfilter_check(
+    const struct usbredirfilter_rule *rules, int rules_count,
+    uint8_t device_class, uint8_t device_subclass, uint8_t device_protocol,
+    uint8_t *interface_class, uint8_t *interface_subclass,
+    uint8_t *interface_protocol, int interface_count,
+    uint16_t vendor_id, uint16_t product_id, uint16_t device_version_bcd,
+    int flags);
+
+/* Sanity check the passed in rules
+
+   Return value: 0 on success, -EINVAL when some values are out of bound. */
+int usbredirfilter_verify(
+    const struct usbredirfilter_rule *rules, int rules_count);
+
+/* Print the passed in rules to FILE out in human readable format */
+void usbredirfilter_print(
+    const struct usbredirfilter_rule *rules, int rules_count, FILE *out);
+#endif
-- 
1.7.4.1



More information about the Spice-devel mailing list