167217Sn_hibma/* $NetBSD: descr.c,v 1.9 2000/09/24 02:13:24 augustss Exp $ */ 261560Sn_hibma 361560Sn_hibma/* 461560Sn_hibma * Copyright (c) 1999 Lennart Augustsson <augustss@netbsd.org> 561560Sn_hibma * All rights reserved. 661560Sn_hibma * 761560Sn_hibma * Redistribution and use in source and binary forms, with or without 861560Sn_hibma * modification, are permitted provided that the following conditions 961560Sn_hibma * are met: 1061560Sn_hibma * 1. Redistributions of source code must retain the above copyright 1161560Sn_hibma * notice, this list of conditions and the following disclaimer. 1261560Sn_hibma * 2. Redistributions in binary form must reproduce the above copyright 1361560Sn_hibma * notice, this list of conditions and the following disclaimer in the 1461560Sn_hibma * documentation and/or other materials provided with the distribution. 1561560Sn_hibma * 1661560Sn_hibma * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1761560Sn_hibma * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1861560Sn_hibma * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1961560Sn_hibma * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2061560Sn_hibma * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2161560Sn_hibma * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2261560Sn_hibma * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2361560Sn_hibma * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2461560Sn_hibma * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2561560Sn_hibma * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2661560Sn_hibma * SUCH DAMAGE. 2761560Sn_hibma */ 2861560Sn_hibma 2984224Sdillon#include <sys/cdefs.h> 3084224Sdillon__FBSDID("$FreeBSD$"); 3184224Sdillon 3261560Sn_hibma#include <sys/types.h> 3361560Sn_hibma 3461560Sn_hibma#include <assert.h> 3561560Sn_hibma#include <errno.h> 3661560Sn_hibma#include <stdlib.h> 3761560Sn_hibma#include <string.h> 3861560Sn_hibma#include <unistd.h> 3961560Sn_hibma#include <sys/time.h> 4061560Sn_hibma#include <sys/ioctl.h> 41188945Sthompsa#include <dev/usb/usb_ioctl.h> 4261560Sn_hibma 43113273Smdodd#include "usbhid.h" 4461560Sn_hibma#include "usbvar.h" 4561560Sn_hibma 46187994Salfredint 47187994Salfredhid_set_immed(int fd, int enable) 48187994Salfred{ 49187994Salfred int ret; 50187994Salfred ret = ioctl(fd, USB_SET_IMMED, &enable); 51188945Sthompsa#ifdef HID_COMPAT7 52187994Salfred if (ret < 0) 53187994Salfred ret = hid_set_immed_compat7(fd, enable); 54188945Sthompsa#endif 55187994Salfred return (ret); 56187994Salfred} 57187994Salfred 58187994Salfredint 59187994Salfredhid_get_report_id(int fd) 60187994Salfred{ 61205728Skaiw report_desc_t rep; 62205728Skaiw hid_data_t d; 63205728Skaiw hid_item_t h; 64205728Skaiw int kindset; 65187994Salfred int temp = -1; 66187994Salfred int ret; 67187994Salfred 68205728Skaiw if ((rep = hid_get_report_desc(fd)) == NULL) 69205728Skaiw goto use_ioctl; 70205728Skaiw kindset = 1 << hid_input | 1 << hid_output | 1 << hid_feature; 71240762Smav for (d = hid_start_parse(rep, kindset, -1); hid_get_item(d, &h); ) { 72205728Skaiw /* Return the first report ID we met. */ 73205728Skaiw if (h.report_ID != 0) { 74205728Skaiw temp = h.report_ID; 75205728Skaiw break; 76205728Skaiw } 77205728Skaiw } 78205728Skaiw hid_end_parse(d); 79205728Skaiw hid_dispose_report_desc(rep); 80205728Skaiw 81205728Skaiw if (temp > 0) 82205728Skaiw return (temp); 83205728Skaiw 84205728Skaiwuse_ioctl: 85187994Salfred ret = ioctl(fd, USB_GET_REPORT_ID, &temp); 86188945Sthompsa#ifdef HID_COMPAT7 87187994Salfred if (ret < 0) 88187994Salfred ret = hid_get_report_id_compat7(fd); 89187994Salfred else 90188945Sthompsa#endif 91187994Salfred ret = temp; 92187994Salfred 93187994Salfred return (ret); 94187994Salfred} 95187994Salfred 9661560Sn_hibmareport_desc_t 9767217Sn_hibmahid_get_report_desc(int fd) 9861560Sn_hibma{ 99192992Sthompsa struct usb_gen_descriptor ugd; 100187994Salfred report_desc_t rep; 101187994Salfred void *data; 10261560Sn_hibma 103187994Salfred memset(&ugd, 0, sizeof(ugd)); 104187994Salfred 105187994Salfred /* get actual length first */ 106213920Shselasky ugd.ugd_data = hid_pass_ptr(NULL); 107187994Salfred ugd.ugd_maxlen = 65535; 108189108Sthompsa if (ioctl(fd, USB_GET_REPORT_DESC, &ugd) < 0) { 109188945Sthompsa#ifdef HID_COMPAT7 110187994Salfred /* could not read descriptor */ 111187994Salfred /* try FreeBSD 7 compat code */ 112187994Salfred return (hid_get_report_desc_compat7(fd)); 113189108Sthompsa#else 114189108Sthompsa return (NULL); 115189108Sthompsa#endif 116187994Salfred } 117187994Salfred 118187994Salfred /* 119187994Salfred * NOTE: The kernel will return a failure if 120187994Salfred * "ugd_actlen" is zero. 121187994Salfred */ 122187994Salfred data = malloc(ugd.ugd_actlen); 123187994Salfred if (data == NULL) 12467217Sn_hibma return (NULL); 12567217Sn_hibma 126187994Salfred /* fetch actual descriptor */ 127213920Shselasky ugd.ugd_data = hid_pass_ptr(data); 128187994Salfred ugd.ugd_maxlen = ugd.ugd_actlen; 129187994Salfred if (ioctl(fd, USB_GET_REPORT_DESC, &ugd) < 0) { 130187994Salfred /* could not read descriptor */ 131187994Salfred free(data); 132187994Salfred return (NULL); 133187994Salfred } 134187994Salfred 135213920Shselasky /* sanity check */ 136213920Shselasky if (ugd.ugd_actlen < 1) { 137213920Shselasky /* invalid report descriptor */ 138213920Shselasky free(data); 139213920Shselasky return (NULL); 140213920Shselasky } 141213920Shselasky 142187994Salfred /* check END_COLLECTION */ 143213920Shselasky if (((unsigned char *)data)[ugd.ugd_actlen -1] != 0xC0) { 144187994Salfred /* invalid end byte */ 145187994Salfred free(data); 146187994Salfred return (NULL); 147187994Salfred } 148187994Salfred 149187994Salfred rep = hid_use_report_desc(data, ugd.ugd_actlen); 150187994Salfred 151187994Salfred free(data); 152187994Salfred 153187994Salfred return (rep); 15467217Sn_hibma} 15567217Sn_hibma 15667217Sn_hibmareport_desc_t 15767217Sn_hibmahid_use_report_desc(unsigned char *data, unsigned int size) 15867217Sn_hibma{ 15967217Sn_hibma report_desc_t r; 16067217Sn_hibma 16167217Sn_hibma r = malloc(sizeof(*r) + size); 16261560Sn_hibma if (r == 0) { 16361560Sn_hibma errno = ENOMEM; 16467217Sn_hibma return (NULL); 16561560Sn_hibma } 16667217Sn_hibma r->size = size; 16767217Sn_hibma memcpy(r->data, data, size); 16861560Sn_hibma return (r); 16961560Sn_hibma} 17061560Sn_hibma 17161560Sn_hibmavoid 17267217Sn_hibmahid_dispose_report_desc(report_desc_t r) 17361560Sn_hibma{ 17461560Sn_hibma 17561560Sn_hibma free(r); 17661560Sn_hibma} 177