descr.c revision 187994
11553Srgrimes/*	$NetBSD: descr.c,v 1.9 2000/09/24 02:13:24 augustss Exp $	*/
21553Srgrimes
31553Srgrimes/*
41553Srgrimes * Copyright (c) 1999 Lennart Augustsson <augustss@netbsd.org>
51553Srgrimes * All rights reserved.
61553Srgrimes *
71553Srgrimes * Redistribution and use in source and binary forms, with or without
81553Srgrimes * modification, are permitted provided that the following conditions
91553Srgrimes * are met:
101553Srgrimes * 1. Redistributions of source code must retain the above copyright
111553Srgrimes *    notice, this list of conditions and the following disclaimer.
121553Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
131553Srgrimes *    notice, this list of conditions and the following disclaimer in the
141553Srgrimes *    documentation and/or other materials provided with the distribution.
151553Srgrimes *
161553Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
171553Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
181553Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
191553Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
201553Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
211553Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
221553Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
231553Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
241553Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
251553Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
261553Srgrimes * SUCH DAMAGE.
271553Srgrimes */
281553Srgrimes
291553Srgrimes#include <sys/cdefs.h>
301553Srgrimes__FBSDID("$FreeBSD: head/lib/libusbhid/descr.c 187994 2009-02-02 00:49:39Z alfred $");
311553Srgrimes
321553Srgrimes#include <sys/types.h>
331553Srgrimes
341553Srgrimes#include <assert.h>
3529602Scharnier#include <errno.h>
361553Srgrimes#include <stdlib.h>
371553Srgrimes#include <string.h>
381553Srgrimes#include <unistd.h>
391553Srgrimes#include <sys/time.h>
401553Srgrimes#include <sys/ioctl.h>
4129602Scharnier
4229602Scharnier#include <dev/usb2/include/usb2_ioctl.h>
4329602Scharnier
4429602Scharnier#include "usbhid.h"
4545588Smarkm#include "usbvar.h"
461553Srgrimes
471553Srgrimesint
481553Srgrimeshid_set_immed(int fd, int enable)
491553Srgrimes{
501553Srgrimes	int ret;
511553Srgrimes	ret = ioctl(fd, USB_SET_IMMED, &enable);
521553Srgrimes	if (ret < 0)
531553Srgrimes		ret = hid_set_immed_compat7(fd, enable);
541553Srgrimes	return (ret);
551553Srgrimes}
561553Srgrimes
571553Srgrimesint
581553Srgrimeshid_get_report_id(int fd)
591553Srgrimes{
601553Srgrimes	int temp = -1;
611553Srgrimes	int ret;
621553Srgrimes
638857Srgrimes	ret = ioctl(fd, USB_GET_REPORT_ID, &temp);
641553Srgrimes	if (ret < 0)
651553Srgrimes		ret = hid_get_report_id_compat7(fd);
661553Srgrimes	else
671553Srgrimes		ret = temp;
681553Srgrimes
691553Srgrimes	return (ret);
701553Srgrimes}
711553Srgrimes
721553Srgrimesreport_desc_t
731553Srgrimeshid_get_report_desc(int fd)
741553Srgrimes{
751553Srgrimes	struct usb2_gen_descriptor ugd;
761553Srgrimes	report_desc_t rep;
771553Srgrimes	void *data;
781553Srgrimes
791553Srgrimes	memset(&ugd, 0, sizeof(ugd));
801553Srgrimes
811553Srgrimes	/* get actual length first */
821553Srgrimes	ugd.ugd_data = NULL;
831553Srgrimes	ugd.ugd_maxlen = 65535;
841553Srgrimes	if (ioctl(fd, USB_GET_REPORT_DESC, &ugd) < 0) {
851553Srgrimes		/* could not read descriptor */
861553Srgrimes		/* try FreeBSD 7 compat code */
871553Srgrimes		return (hid_get_report_desc_compat7(fd));
881553Srgrimes	}
891553Srgrimes
901553Srgrimes	/*
911553Srgrimes	 * NOTE: The kernel will return a failure if
921553Srgrimes	 * "ugd_actlen" is zero.
931553Srgrimes	 */
941553Srgrimes	data = malloc(ugd.ugd_actlen);
952657Scsgr	if (data == NULL)
962657Scsgr		return (NULL);
972657Scsgr
982657Scsgr	/* fetch actual descriptor */
992657Scsgr	ugd.ugd_data = data;
1002657Scsgr	ugd.ugd_maxlen = ugd.ugd_actlen;
1012657Scsgr	if (ioctl(fd, USB_GET_REPORT_DESC, &ugd) < 0) {
1022657Scsgr		/* could not read descriptor */
1032657Scsgr		free(data);
1041553Srgrimes		return (NULL);
1051553Srgrimes	}
1061553Srgrimes
1071553Srgrimes	/* check END_COLLECTION */
1081553Srgrimes	if (((unsigned char *)ugd.ugd_data)[ugd.ugd_actlen -1] != 0xC0) {
1091553Srgrimes		/* invalid end byte */
1101553Srgrimes		free(data);
1111553Srgrimes		return (NULL);
1121553Srgrimes	}
1131553Srgrimes
1141553Srgrimes	rep = hid_use_report_desc(data, ugd.ugd_actlen);
11536042Sguido
1161553Srgrimes	free(data);
1172657Scsgr
11819617Sjulian	return (rep);
1191553Srgrimes}
1201553Srgrimes
12129602Scharnierreport_desc_t
1221553Srgrimeshid_use_report_desc(unsigned char *data, unsigned int size)
12330807Sache{
1241553Srgrimes	report_desc_t r;
1251553Srgrimes
1261553Srgrimes	r = malloc(sizeof(*r) + size);
1271553Srgrimes	if (r == 0) {
1281553Srgrimes		errno = ENOMEM;
1291553Srgrimes		return (NULL);
1301553Srgrimes	}
1311553Srgrimes	r->size = size;
13213142Speter	memcpy(r->data, data, size);
13319617Sjulian	return (r);
1341553Srgrimes}
13545089Smarkm
13645089Smarkmvoid
13745089Smarkmhid_dispose_report_desc(report_desc_t r)
13845089Smarkm{
13945089Smarkm
14045089Smarkm	free(r);
14145089Smarkm}
14245089Smarkm