Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/usb hid_get_data() does not work if the size of data...



details:   https://anonhg.NetBSD.org/src/rev/bc9364facfc4
branches:  trunk
changeset: 754793:bc9364facfc4
user:      plunky <plunky%NetBSD.org@localhost>
date:      Wed May 12 18:44:48 2010 +0000

description:
hid_get_data() does not work if the size of data is less than
a byte and crosses a byte boundary, and it always returns a
sign-extended value.

fix this by using the algorithm from libusbhid to read bytes,
and provide a hid_get_udata() function to return unsigned data
values.

while here, const args

diffstat:

 sys/dev/usb/hid.c |  43 ++++++++++++++++++++++++++++---------------
 sys/dev/usb/hid.h |   5 +++--
 2 files changed, 31 insertions(+), 17 deletions(-)

diffs (92 lines):

diff -r 2953429595a5 -r bc9364facfc4 sys/dev/usb/hid.c
--- a/sys/dev/usb/hid.c Wed May 12 18:37:56 2010 +0000
+++ b/sys/dev/usb/hid.c Wed May 12 18:44:48 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: hid.c,v 1.28 2008/04/28 20:23:59 martin Exp $  */
+/*     $NetBSD: hid.c,v 1.29 2010/05/12 18:44:48 plunky Exp $  */
 /*     $FreeBSD: src/sys/dev/usb/hid.c,v 1.11 1999/11/17 22:33:39 n_hibma Exp $ */
 
 /*
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: hid.c,v 1.28 2008/04/28 20:23:59 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: hid.c,v 1.29 2010/05/12 18:44:48 plunky Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -427,30 +427,43 @@
        return (0);
 }
 
+long
+hid_get_data(const u_char *buf, const struct hid_location *loc)
+{
+       u_int hsize = loc->size;
+       u_long data;
+
+       if (hsize == 0)
+               return (0);
+
+       data = hid_get_udata(buf, loc);
+       if (data < (1 << (hsize - 1)))
+               return (data);
+       return data - (1 << hsize);
+}
+
 u_long
-hid_get_data(u_char *buf, struct hid_location *loc)
+hid_get_udata(const u_char *buf, const struct hid_location *loc)
 {
        u_int hpos = loc->pos;
        u_int hsize = loc->size;
-       u_int32_t data;
-       int i, s;
-
-       DPRINTFN(10, ("hid_get_data: loc %d/%d\n", hpos, hsize));
+       u_int i, num, off;
+       u_long data;
 
        if (hsize == 0)
                return (0);
 
        data = 0;
-       s = hpos / 8;
-       for (i = hpos; i < hpos+hsize; i += 8)
-               data |= buf[i / 8] << ((i / 8 - s) * 8);
+       off = hpos / 8;
+       num = (hpos + hsize + 7) / 8 - off;
+
+       for (i = 0; i < num; i++)
+               data |= buf[off + i] << (i * 8);
+
        data >>= hpos % 8;
        data &= (1 << hsize) - 1;
-       hsize = 32 - hsize;
-       /* Sign extend */
-       data = ((int32_t)data << hsize) >> hsize;
-       DPRINTFN(10,("hid_get_data: loc %d/%d = %lu\n",
-                   loc->pos, loc->size, (long)data));
+
+       DPRINTFN(10,("hid_get_data: loc %d/%d = %lu\n", hpos, hsize, data));
        return (data);
 }
 
diff -r 2953429595a5 -r bc9364facfc4 sys/dev/usb/hid.h
--- a/sys/dev/usb/hid.h Wed May 12 18:37:56 2010 +0000
+++ b/sys/dev/usb/hid.h Wed May 12 18:44:48 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: hid.h,v 1.12 2008/04/28 20:23:59 martin Exp $  */
+/*     $NetBSD: hid.h,v 1.13 2010/05/12 18:44:49 plunky Exp $  */
 /*     $FreeBSD: src/sys/dev/usb/hid.h,v 1.7 1999/11/17 22:33:40 n_hibma Exp $ */
 
 /*
@@ -84,5 +84,6 @@
 int hid_report_size(const void *, int, enum hid_kind, u_int8_t);
 int hid_locate(const void *, int, u_int32_t, u_int8_t, enum hid_kind,
     struct hid_location *, u_int32_t *);
-u_long hid_get_data(u_char *, struct hid_location *);
+long hid_get_data(const u_char *, const struct hid_location *);
+u_long hid_get_udata(const u_char *, const struct hid_location *);
 int hid_is_collection(const void *, int, u_int8_t, u_int32_t);



Home | Main Index | Thread Index | Old Index