Bluetooth fixes by Iain Hibbert:

- Update bthidev(4) to use property lists for configuration.
This commit is contained in:
tron 2006-07-26 10:40:50 +00:00
parent 4241fec1bf
commit 5d67049004
6 changed files with 157 additions and 102 deletions

View File

@ -1,4 +1,4 @@
.\" $NetBSD: bthidev.4,v 1.1 2006/06/19 15:44:36 gdamore Exp $
.\" $NetBSD: bthidev.4,v 1.2 2006/07/26 10:40:50 tron Exp $
.\"
.\" Copyright (c) 2006 Itronix Inc.
.\" All rights reserved.
@ -36,7 +36,7 @@
.Nm bthidev
.Nd Bluetooth Human Interface Device support
.Sh SYNOPSIS
.Cd "bthidev* at bthub?"
.Cd "bthidev* at btdev?"
.Pp
.Cd "btkbd* at bthidev? reportid ?"
.Cd "btms* at bthidev? reportid ?"
@ -48,18 +48,51 @@ device can have several components, e.g., a keyboard and a mouse.
These components use different report identifiers to
distinguish which component data is coming from. The
.Nm
driver has other drivers attached that handle particular
kinds of devices and
.Nm
only dispatches data to them based on the report id.
driver may have several children attached that handle particular
components and dispatches data to them based on the report id.
.Pp
Normally, Bluetooth HIDs will be attached using the
.Xr btcontrol 8
program.
program. The following properties are used by the
.Nm
driver during autoconfiguration:
.Bl -tag -width interrupt_psmXX
.It local-bdaddr
Local device address.
.It remote-bdaddr
Remote device address.
.It device-type
Should be
.Sq bthidev ,
indicating a Human Interface Device.
.It control-psm
This, if set, will indicate the PSM to use for the Control channel. If not set,
.Dv L2CAP_PSM_HID_CNTL
will be used.
.It interrupt-psm
This, if set, will indicate the PSM to use for the Interrupt channel. If not set,
.Dv L2CAP_PSM_HID_INTR
will be used.
.It descriptor
This required binary blob is the HID descriptor containing information about
reports the device will produce, and obtained via SDP.
.It reconnect
If this boolean value is set, and is true, then the
.Nm
driver will initiate reconnections to the remote device when no connection is
present.
.El
.Pp
When the
.Nm
driver has configured its children, it will initate a connection to the remote
device. If this fails and the reconnect flag is not set, it will then wait for
the device to initiate the connection.
.Pp
.Sh SEE ALSO
.Xr bluetooth 4 ,
.Xr btcontrol 8 ,
.Xr bthub 4 ,
.Xr btdev 4 ,
.Xr btkbd 4 ,
.Xr btms 4
.Sh HISTORY

View File

@ -1,4 +1,4 @@
/* $NetBSD: bthidev.c,v 1.1 2006/06/19 15:44:45 gdamore Exp $ */
/* $NetBSD: bthidev.c,v 1.2 2006/07/26 10:40:50 tron Exp $ */
/*-
* Copyright (c) 2006 Itronix Inc.
@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: bthidev.c,v 1.1 2006/06/19 15:44:45 gdamore Exp $");
__KERNEL_RCSID(0, "$NetBSD: bthidev.c,v 1.2 2006/07/26 10:40:50 tron Exp $");
#include <sys/param.h>
#include <sys/conf.h>
@ -45,6 +45,8 @@ __KERNEL_RCSID(0, "$NetBSD: bthidev.c,v 1.1 2006/06/19 15:44:45 gdamore Exp $");
#include <sys/proc.h>
#include <sys/systm.h>
#include <prop/proplib.h>
#include <netbt/bluetooth.h>
#include <netbt/l2cap.h>
@ -60,22 +62,17 @@ __KERNEL_RCSID(0, "$NetBSD: bthidev.c,v 1.1 2006/06/19 15:44:45 gdamore Exp $");
* Bluetooth HID device
*/
MALLOC_DEFINE(M_BTHIDEV, "bthidev", "Bluetooth HID Memory");
#define MAX_DESCRIPTOR_LEN 1024 /* sanity check */
/* bthidev softc */
struct bthidev_softc {
struct btdev sc_btdev; /* device+ */
struct device sc_dev;
uint16_t sc_state;
uint16_t sc_flags;
bdaddr_t sc_laddr; /* local address */
bdaddr_t sc_raddr; /* remote address */
void *sc_desc; /* HID descriptor */
int sc_dlen; /* descriptor length */
uint16_t sc_ctlpsm; /* control PSM */
struct l2cap_channel *sc_ctl; /* control channel */
struct l2cap_channel *sc_ctl_l; /* control listen */
@ -90,6 +87,10 @@ struct bthidev_softc {
int sc_attempts; /* connection attempts */
};
/* sc_flags */
#define BTHID_RECONNECT (1 << 0) /* reconnect on link loss */
#define BTHID_CONNECTING (1 << 1) /* we are connecting */
/* device state */
#define BTHID_CLOSED 0
#define BTHID_WAIT_CTL 1
@ -152,30 +153,26 @@ static const struct btproto bthidev_int_proto = {
static int
bthidev_match(struct device *self, struct cfdata *cfdata, void *aux)
{
struct btdev_attach_args *bda = (struct btdev_attach_args *)aux;
prop_dictionary_t dict = aux;
prop_object_t obj;
if (bda->bd_type != BTDEV_HID
|| L2CAP_PSM_INVALID(bda->bd_hid.hid_ctl)
|| L2CAP_PSM_INVALID(bda->bd_hid.hid_int)
|| bda->bd_hid.hid_desc == NULL
|| bda->bd_hid.hid_dlen == 0
|| bda->bd_hid.hid_dlen > MAX_DESCRIPTOR_LEN)
return 0;
return 1;
obj = prop_dictionary_get(dict, "device-type");
return prop_string_equals_cstring(obj, "bthidev");
}
static void
bthidev_attach(struct device *parent, struct device *self, void *aux)
{
struct bthidev_softc *sc = (struct bthidev_softc *)self;
struct btdev_attach_args *bda = (struct btdev_attach_args *)aux;
prop_dictionary_t dict = aux;
prop_object_t obj;
struct bthidev_attach_args bha;
struct bthidev *dev;
struct hid_data *d;
struct hid_item h;
const void *desc;
int locs[BTHIDBUSCF_NLOCS];
int maxid, rep, s;
int maxid, rep, s, dlen;
/*
* Init softc
@ -184,34 +181,57 @@ bthidev_attach(struct device *parent, struct device *self, void *aux)
callout_init(&sc->sc_reconnect);
callout_setfunc(&sc->sc_reconnect, bthidev_timeout, sc);
sc->sc_state = BTHID_CLOSED;
sc->sc_flags = BTHID_CONNECTING;
sc->sc_ctlpsm = L2CAP_PSM_HID_CNTL;
sc->sc_intpsm = L2CAP_PSM_HID_INTR;
/*
* copy in our configuration info
* extract config from proplist
*/
bdaddr_copy(&sc->sc_laddr, &bda->bd_laddr);
bdaddr_copy(&sc->sc_raddr, &bda->bd_raddr);
obj = prop_dictionary_get(dict, "local-bdaddr");
bdaddr_copy(&sc->sc_laddr, prop_data_data_nocopy(obj));
sc->sc_ctlpsm = bda->bd_hid.hid_ctl;
sc->sc_intpsm = bda->bd_hid.hid_int;
obj = prop_dictionary_get(dict, "remote-bdaddr");
bdaddr_copy(&sc->sc_raddr, prop_data_data_nocopy(obj));
sc->sc_flags = bda->bd_hid.hid_flags;
if (sc->sc_flags & BTHID_INITIATE)
sc->sc_flags |= BTHID_CONNECT;
obj = prop_dictionary_get(dict, "control-psm");
if (obj && prop_object_type(obj) == PROP_TYPE_NUMBER) {
sc->sc_ctlpsm = prop_number_integer_value(obj);
if (L2CAP_PSM_INVALID(sc->sc_ctlpsm)) {
aprint_error(" invalid control_psm\n");
return;
}
}
sc->sc_dlen = bda->bd_hid.hid_dlen;
sc->sc_desc = malloc(bda->bd_hid.hid_dlen, M_BTHIDEV, M_WAITOK);
if (sc->sc_desc == NULL) {
aprint_error(" no memory\n");
obj = prop_dictionary_get(dict, "interrupt-psm");
if (obj && prop_object_type(obj) == PROP_TYPE_NUMBER) {
sc->sc_intpsm = prop_number_integer_value(obj);
if (L2CAP_PSM_INVALID(sc->sc_intpsm)) {
aprint_error(" invalid interrupt_psm\n");
return;
}
}
obj = prop_dictionary_get(dict, "descriptor");
if (obj && prop_object_type(obj) == PROP_TYPE_DATA) {
dlen = prop_data_size(obj);
desc = prop_data_data_nocopy(obj);
} else {
aprint_error(" no HID descriptor\n");
return;
}
copyin(bda->bd_hid.hid_desc, sc->sc_desc, bda->bd_hid.hid_dlen);
obj = prop_dictionary_get(dict, "reconnect");
if (obj && prop_object_type(obj) == PROP_TYPE_BOOL
&& !prop_bool_true(obj))
sc->sc_flags |= BTHID_RECONNECT;
/*
* Parse the descriptor and attach child devices, one per report.
*/
maxid = -1;
h.report_ID = 0;
d = hid_start_parse(sc->sc_desc, sc->sc_dlen, hid_none);
d = hid_start_parse(desc, dlen, hid_none);
while (hid_get_item(d, &h)) {
if (h.report_ID > maxid)
maxid = h.report_ID;
@ -226,13 +246,13 @@ bthidev_attach(struct device *parent, struct device *self, void *aux)
aprint_normal("\n");
for (rep = 0 ; rep <= maxid ; rep++) {
if (hid_report_size(sc->sc_desc, sc->sc_dlen, hid_feature, rep) == 0
&& hid_report_size(sc->sc_desc, sc->sc_dlen, hid_input, rep) == 0
&& hid_report_size(sc->sc_desc, sc->sc_dlen, hid_output, rep) == 0)
if (hid_report_size(desc, dlen, hid_feature, rep) == 0
&& hid_report_size(desc, dlen, hid_input, rep) == 0
&& hid_report_size(desc, dlen, hid_output, rep) == 0)
continue;
bha.ba_desc = sc->sc_desc;
bha.ba_dlen = sc->sc_dlen;
bha.ba_desc = desc;
bha.ba_dlen = dlen;
bha.ba_input = bthidev_null;
bha.ba_feature = bthidev_null;
bha.ba_output = bthidev_output;
@ -243,7 +263,7 @@ bthidev_attach(struct device *parent, struct device *self, void *aux)
dev = (struct bthidev *)config_found_sm_loc((struct device *)sc, "bthidbus",
locs, &bha, bthidev_print, config_stdsubmatch);
if (dev != NULL) {
dev->sc_parent = &sc->sc_btdev;
dev->sc_parent = &sc->sc_dev;
dev->sc_id = rep;
dev->sc_input = bha.ba_input;
dev->sc_feature = bha.ba_feature;
@ -255,10 +275,10 @@ bthidev_attach(struct device *parent, struct device *self, void *aux)
* start bluetooth connections
*/
s = splsoftnet();
if ((sc->sc_flags & BTHID_INITIATE) == 0)
if ((sc->sc_flags & BTHID_RECONNECT) == 0)
bthidev_listen(sc);
if (sc->sc_flags & BTHID_CONNECT)
if (sc->sc_flags & BTHID_CONNECTING)
bthidev_connect(sc);
splx(s);
}
@ -313,11 +333,6 @@ bthidev_detach(struct device *self, int flags)
config_detach(&dev->sc_dev, flags);
}
/* release descriptor */
if (sc->sc_desc != NULL) {
free(sc->sc_desc, M_BTHIDEV);
sc->sc_desc = NULL;
}
return 0;
}
@ -359,11 +374,11 @@ bthidev_timeout(void *arg)
switch (sc->sc_state) {
case BTHID_CLOSED:
sc->sc_flags |= BTHID_CONNECT;
sc->sc_flags |= BTHID_CONNECTING;
err = bthidev_connect(sc);
if (err)
printf("%s: connect failed (%d)\n",
btdev_name(sc), err);
sc->sc_dev.dv_xname, err);
break;
case BTHID_WAIT_CTL:
@ -445,7 +460,7 @@ bthidev_connect(struct bthidev_softc *sc)
int err;
if (sc->sc_attempts++ > 0)
printf("%s: connect (#%d)\n", btdev_name(sc), sc->sc_attempts);
printf("%s: connect (#%d)\n", sc->sc_dev.dv_xname, sc->sc_attempts);
memset(&sa, 0, sizeof(sa));
sa.bt_len = sizeof(sa);
@ -453,14 +468,14 @@ bthidev_connect(struct bthidev_softc *sc)
err = l2cap_attach(&sc->sc_ctl, &bthidev_ctl_proto, sc);
if (err) {
printf("%s: l2cap_attach failed (%d)\n", btdev_name(sc), err);
printf("%s: l2cap_attach failed (%d)\n", sc->sc_dev.dv_xname, err);
return err;
}
bdaddr_copy(&sa.bt_bdaddr, &sc->sc_laddr);
err = l2cap_bind(sc->sc_ctl, &sa);
if (err) {
printf("%s: l2cap_bind failed (%d)\n", btdev_name(sc), err);
printf("%s: l2cap_bind failed (%d)\n", sc->sc_dev.dv_xname, err);
return err;
}
@ -468,7 +483,7 @@ bthidev_connect(struct bthidev_softc *sc)
bdaddr_copy(&sa.bt_bdaddr, &sc->sc_raddr);
err = l2cap_connect(sc->sc_ctl, &sa);
if (err) {
printf("%s: l2cap_connect failed (%d)\n", btdev_name(sc), err);
printf("%s: l2cap_connect failed (%d)\n", sc->sc_dev.dv_xname, err);
return err;
}
@ -504,7 +519,7 @@ bthidev_ctl_connected(void *arg)
KASSERT(sc->sc_ctl != NULL);
KASSERT(sc->sc_int == NULL);
if (sc->sc_flags & BTHID_CONNECT) {
if (sc->sc_flags & BTHID_CONNECTING) {
/* initiate connect on interrupt PSM */
err = l2cap_attach(&sc->sc_int, &bthidev_int_proto, sc);
if (err)
@ -532,7 +547,7 @@ bthidev_ctl_connected(void *arg)
fail:
l2cap_detach(&sc->sc_ctl);
sc->sc_ctl = NULL;
printf("%s: connect failed (%d)\n", btdev_name(sc), err);
printf("%s: connect failed (%d)\n", sc->sc_dev.dv_xname, err);
}
static void
@ -547,17 +562,18 @@ bthidev_int_connected(void *arg)
KASSERT(sc->sc_int != NULL);
sc->sc_attempts = 0;
sc->sc_flags &= ~BTHID_CONNECT;
sc->sc_flags &= ~BTHID_CONNECTING;
sc->sc_state = BTHID_OPEN;
printf("%s: connected\n", btdev_name(sc));
printf("%s: connected\n", sc->sc_dev.dv_xname);
}
/*
* Disconnected
*
* Depending on our state, this could mean several things, but essentially
* we are lost.
* we are lost. If both channels are closed, and we are marked to reconnect,
* schedule another try otherwise just give up. They will contact us.
*/
static void
bthidev_ctl_disconnected(void *arg, int err)
@ -572,13 +588,20 @@ bthidev_ctl_disconnected(void *arg, int err)
sc->sc_state = BTHID_CLOSED;
if (sc->sc_int == NULL) {
printf("%s: disconnected\n", btdev_name(sc));
printf("%s: disconnected\n", sc->sc_dev.dv_xname);
sc->sc_flags &= ~BTHID_CONNECTING;
if (sc->sc_flags & BTHID_INITIATE)
if (sc->sc_flags & BTHID_RECONNECT)
callout_schedule(&sc->sc_reconnect,
BTHID_RETRY_INTERVAL * hz);
else
sc->sc_state = BTHID_WAIT_CTL;
} else {
/*
* The interrupt channel should have been closed first,
* so if its still up then kick it along..
*/
l2cap_disconnect(sc->sc_int, 0);
}
}
@ -595,9 +618,10 @@ bthidev_int_disconnected(void *arg, int err)
sc->sc_state = BTHID_CLOSED;
if (sc->sc_ctl == NULL) {
printf("%s: disconnected\n", btdev_name(sc));
printf("%s: disconnected\n", sc->sc_dev.dv_xname);
sc->sc_flags &= ~BTHID_CONNECTING;
if (sc->sc_flags & BTHID_INITIATE)
if (sc->sc_flags & BTHID_RECONNECT)
callout_schedule(&sc->sc_reconnect,
BTHID_RETRY_INTERVAL * hz);
else
@ -618,7 +642,7 @@ bthidev_ctl_newconn(void *arg, struct sockaddr_bt *laddr, struct sockaddr_bt *ra
struct bthidev_softc *sc = arg;
if (bdaddr_same(&raddr->bt_bdaddr, &sc->sc_raddr) == 0
|| (sc->sc_flags & BTHID_INITIATE)
|| (sc->sc_flags & BTHID_CONNECTING)
|| sc->sc_state != BTHID_WAIT_CTL
|| sc->sc_ctl != NULL
|| sc->sc_int != NULL)
@ -634,7 +658,7 @@ bthidev_int_newconn(void *arg, struct sockaddr_bt *laddr, struct sockaddr_bt *ra
struct bthidev_softc *sc = arg;
if (bdaddr_same(&raddr->bt_bdaddr, &sc->sc_raddr) == 0
|| (sc->sc_flags & BTHID_INITIATE)
|| (sc->sc_flags & BTHID_CONNECTING)
|| sc->sc_state != BTHID_WAIT_INT
|| sc->sc_ctl == NULL
|| sc->sc_int != NULL)
@ -666,7 +690,7 @@ bthidev_input(void *arg, struct mbuf *m)
goto release;
if (m->m_pkthdr.len > m->m_len)
printf("%s: truncating HID report\n", btdev_name(sc));
printf("%s: truncating HID report\n", sc->sc_dev.dv_xname);
len = m->m_len;
data = mtod(m, uint8_t *);
@ -699,7 +723,7 @@ bthidev_input(void *arg, struct mbuf *m)
}
}
printf("%s: report id %d, len = %d ignored\n",
btdev_name(sc), data[1], len - 2);
sc->sc_dev.dv_xname, data[1], len - 2);
goto release;
}
@ -709,7 +733,7 @@ bthidev_input(void *arg, struct mbuf *m)
goto release;
if (BTHID_DATA_PARAM(data[0]) == BTHID_CONTROL_UNPLUG) {
printf("%s: unplugged\n", btdev_name(sc));
printf("%s: unplugged\n", sc->sc_dev.dv_xname);
/* close interrupt channel */
if (sc->sc_int != NULL) {
@ -766,7 +790,7 @@ bthidev_output(struct bthidev *dev, uint8_t *report, int rlen)
if (rlen > MHLEN - 2) {
printf("%s: output report too long (%d)!\n",
btdev_name(sc), rlen);
sc->sc_dev.dv_xname, rlen);
return EMSGSIZE;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: bthidev.h,v 1.1 2006/06/19 15:44:45 gdamore Exp $ */
/* $NetBSD: bthidev.h,v 1.2 2006/07/26 10:40:50 tron Exp $ */
/*-
* Copyright (c) 2006 Itronix Inc.
@ -37,7 +37,7 @@
/* HID device header */
struct bthidev {
struct device sc_dev;
struct btdev *sc_parent;
struct device *sc_parent;
int sc_id; /* report id */
int sc_len; /* report len */
@ -53,7 +53,7 @@ struct bthidev {
/* HID device attach arguments */
struct bthidev_attach_args {
void *ba_desc; /* descriptor */
const void *ba_desc; /* descriptor */
int ba_dlen; /* descriptor length */
int ba_id; /* report id */
@ -65,6 +65,4 @@ struct bthidev_attach_args {
(struct bthidev *, uint8_t *, int);
};
MALLOC_DECLARE(M_BTHIDEV);
#endif /* _DEV_BLUETOOTH_BTHIDEV_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: btkbd.c,v 1.1 2006/06/19 15:44:45 gdamore Exp $ */
/* $NetBSD: btkbd.c,v 1.2 2006/07/26 10:40:50 tron Exp $ */
/*-
* Copyright (c) 2006 Itronix Inc.
@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: btkbd.c,v 1.1 2006/06/19 15:44:45 gdamore Exp $");
__KERNEL_RCSID(0, "$NetBSD: btkbd.c,v 1.2 2006/07/26 10:40:50 tron Exp $");
#include <sys/param.h>
#include <sys/callout.h>
@ -150,7 +150,7 @@ const struct wskbd_mapdata btkbd_keymapdata = {
static void btkbd_input(struct bthidev *, uint8_t *, int);
/* internal prototypes */
static const char *btkbd_parse_desc(struct btkbd_softc *, int, void *, int);
static const char *btkbd_parse_desc(struct btkbd_softc *, int, const void *, int);
#ifdef WSDISPLAY_COMPAT_RAWKBD
#ifdef BTKBD_REPEAT
@ -224,7 +224,7 @@ btkbd_detach(struct device *self, int flags)
}
static const char *
btkbd_parse_desc(struct btkbd_softc *sc, int id, void *desc, int dlen)
btkbd_parse_desc(struct btkbd_softc *sc, int id, const void *desc, int dlen)
{
struct hid_data *d;
struct hid_item h;

View File

@ -1,4 +1,4 @@
/* $NetBSD: hid.c,v 1.25 2006/06/19 15:44:45 gdamore Exp $ */
/* $NetBSD: hid.c,v 1.26 2006/07/26 10:40:50 tron Exp $ */
/* $FreeBSD: src/sys/dev/usb/hid.c,v 1.11 1999/11/17 22:33:39 n_hibma Exp $ */
/*
@ -39,7 +39,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: hid.c,v 1.25 2006/06/19 15:44:45 gdamore Exp $");
__KERNEL_RCSID(0, "$NetBSD: hid.c,v 1.26 2006/07/26 10:40:50 tron Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -66,9 +66,9 @@ Static void hid_clear_local(struct hid_item *);
#define MAXUSAGE 256
struct hid_data {
u_char *start;
u_char *end;
u_char *p;
const u_char *start;
const u_char *end;
const u_char *p;
struct hid_item cur;
int32_t usages[MAXUSAGE];
int nu;
@ -96,13 +96,13 @@ hid_clear_local(struct hid_item *c)
}
struct hid_data *
hid_start_parse(void *d, int len, enum hid_kind kind)
hid_start_parse(const void *d, int len, enum hid_kind kind)
{
struct hid_data *s;
s = malloc(sizeof *s, M_TEMP, M_WAITOK|M_ZERO);
s->start = s->p = d;
s->end = (char *)d + len;
s->end = (const char *)d + len;
s->kind = kind;
return (s);
}
@ -125,9 +125,9 @@ hid_get_item(struct hid_data *s, struct hid_item *h)
struct hid_item *c = &s->cur;
unsigned int bTag, bType, bSize;
u_int32_t oldpos;
u_char *data;
const u_char *data;
int32_t dval;
u_char *p;
const u_char *p;
struct hid_item *hi;
int i;
enum hid_kind retkind;
@ -376,7 +376,7 @@ hid_get_item(struct hid_data *s, struct hid_item *h)
}
int
hid_report_size(void *buf, int len, enum hid_kind k, u_int8_t id)
hid_report_size(const void *buf, int len, enum hid_kind k, u_int8_t id)
{
struct hid_data *d;
struct hid_item h;
@ -408,7 +408,7 @@ hid_report_size(void *buf, int len, enum hid_kind k, u_int8_t id)
}
int
hid_locate(void *desc, int size, u_int32_t u, u_int8_t id, enum hid_kind k,
hid_locate(const void *desc, int size, u_int32_t u, u_int8_t id, enum hid_kind k,
struct hid_location *loc, u_int32_t *flags)
{
struct hid_data *d;
@ -481,7 +481,7 @@ hid_get_data(u_char *buf, struct hid_location *loc)
* Needs some thought.
*/
int
hid_is_collection(void *desc, int size, u_int8_t id, u_int32_t usage)
hid_is_collection(const void *desc, int size, u_int8_t id, u_int32_t usage)
{
struct hid_data *hd;
struct hid_item hi;

View File

@ -1,4 +1,4 @@
/* $NetBSD: hid.h,v 1.10 2005/12/11 12:24:00 christos Exp $ */
/* $NetBSD: hid.h,v 1.11 2006/07/26 10:40:50 tron Exp $ */
/* $FreeBSD: src/sys/dev/usb/hid.h,v 1.7 1999/11/17 22:33:40 n_hibma Exp $ */
/*
@ -85,11 +85,11 @@ struct hid_item {
struct hid_item *next;
};
struct hid_data *hid_start_parse(void *, int, enum hid_kind);
struct hid_data *hid_start_parse(const void *, int, enum hid_kind);
void hid_end_parse(struct hid_data *);
int hid_get_item(struct hid_data *, struct hid_item *);
int hid_report_size(void *, int, enum hid_kind, u_int8_t);
int hid_locate(void *, int, u_int32_t, u_int8_t, enum hid_kind,
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 *);
int hid_is_collection(void *, int, u_int8_t, u_int32_t);
int hid_is_collection(const void *, int, u_int8_t, u_int32_t);