161560Sn_hibma/* $NetBSD: data.c,v 1.8 2000/04/02 11:10:53 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 32205728Skaiw#include <sys/param.h> 3361560Sn_hibma#include <assert.h> 3461560Sn_hibma#include <stdlib.h> 35225839Smav#include <string.h> 36225839Smav#include <dev/usb/usb_ioctl.h> 37113273Smdodd#include "usbhid.h" 38225839Smav#include "usbvar.h" 3961560Sn_hibma 40208023Sthompsaint32_t 4161560Sn_hibmahid_get_data(const void *p, const hid_item_t *h) 4261560Sn_hibma{ 43205728Skaiw const uint8_t *buf; 44205728Skaiw uint32_t hpos; 45205728Skaiw uint32_t hsize; 46205728Skaiw uint32_t data; 4761560Sn_hibma int i, end, offs; 4861560Sn_hibma 4961560Sn_hibma buf = p; 50205728Skaiw 51205728Skaiw /* Skip report ID byte. */ 52205728Skaiw if (h->report_ID > 0) 53205728Skaiw buf++; 54205728Skaiw 5561560Sn_hibma hpos = h->pos; /* bit position of data */ 5661560Sn_hibma hsize = h->report_size; /* bit length of data */ 5761560Sn_hibma 58205728Skaiw /* Range check and limit */ 5961560Sn_hibma if (hsize == 0) 6061560Sn_hibma return (0); 61205728Skaiw if (hsize > 32) 62205728Skaiw hsize = 32; 63205728Skaiw 6461560Sn_hibma offs = hpos / 8; 6561560Sn_hibma end = (hpos + hsize) / 8 - offs; 6661560Sn_hibma data = 0; 6761560Sn_hibma for (i = 0; i <= end; i++) 6861560Sn_hibma data |= buf[offs + i] << (i*8); 69208012Sthompsa 70208012Sthompsa /* Correctly shift down data */ 7161560Sn_hibma data >>= hpos % 8; 72208012Sthompsa hsize = 32 - hsize; 73208012Sthompsa 74208012Sthompsa /* Mask and sign extend in one */ 75208012Sthompsa if ((h->logical_minimum < 0) || (h->logical_maximum < 0)) 76208012Sthompsa data = (int32_t)((int32_t)data << hsize) >> hsize; 77208012Sthompsa else 78208012Sthompsa data = (uint32_t)((uint32_t)data << hsize) >> hsize; 79208012Sthompsa 8061560Sn_hibma return (data); 8161560Sn_hibma} 8261560Sn_hibma 8361560Sn_hibmavoid 84208023Sthompsahid_set_data(void *p, const hid_item_t *h, int32_t data) 8561560Sn_hibma{ 86205728Skaiw uint8_t *buf; 87205728Skaiw uint32_t hpos; 88205728Skaiw uint32_t hsize; 89208023Sthompsa uint32_t mask; 90208023Sthompsa int i; 91208023Sthompsa int end; 92208023Sthompsa int offs; 9361560Sn_hibma 9461560Sn_hibma buf = p; 95205728Skaiw 96205728Skaiw /* Set report ID byte. */ 97205728Skaiw if (h->report_ID > 0) 98205728Skaiw *buf++ = h->report_ID & 0xff; 99205728Skaiw 10061560Sn_hibma hpos = h->pos; /* bit position of data */ 10161560Sn_hibma hsize = h->report_size; /* bit length of data */ 10261560Sn_hibma 10361560Sn_hibma if (hsize != 32) { 10461560Sn_hibma mask = (1 << hsize) - 1; 10561560Sn_hibma data &= mask; 10661560Sn_hibma } else 10761560Sn_hibma mask = ~0; 10861560Sn_hibma 10961560Sn_hibma data <<= (hpos % 8); 11061560Sn_hibma mask <<= (hpos % 8); 11161560Sn_hibma mask = ~mask; 11261560Sn_hibma 11361560Sn_hibma offs = hpos / 8; 11461560Sn_hibma end = (hpos + hsize) / 8 - offs; 11561560Sn_hibma 11661560Sn_hibma for (i = 0; i <= end; i++) 11761560Sn_hibma buf[offs + i] = (buf[offs + i] & (mask >> (i*8))) | 118205728Skaiw ((data >> (i*8)) & 0xff); 11961560Sn_hibma} 120225839Smav 121225839Smavint 122225839Smavhid_get_report(int fd, enum hid_kind k, unsigned char *data, unsigned int size) 123225839Smav{ 124225839Smav struct usb_gen_descriptor ugd; 125225839Smav 126225839Smav memset(&ugd, 0, sizeof(ugd)); 127225839Smav ugd.ugd_data = hid_pass_ptr(data); 128225839Smav ugd.ugd_maxlen = size; 129225839Smav ugd.ugd_report_type = k + 1; 130225839Smav return (ioctl(fd, USB_GET_REPORT, &ugd)); 131225839Smav} 132225839Smav 133225839Smavint 134225839Smavhid_set_report(int fd, enum hid_kind k, unsigned char *data, unsigned int size) 135225839Smav{ 136225839Smav struct usb_gen_descriptor ugd; 137225839Smav 138225839Smav memset(&ugd, 0, sizeof(ugd)); 139225839Smav ugd.ugd_data = hid_pass_ptr(data); 140225839Smav ugd.ugd_maxlen = size; 141225839Smav ugd.ugd_report_type = k + 1; 142225839Smav return (ioctl(fd, USB_SET_REPORT, &ugd)); 143225839Smav} 144