1184610Salfred/* $FreeBSD$ */ 2184610Salfred/*- 3184610Salfred * Copyright (c) 2008 Hans Petter Selasky. All rights reserved. 4184610Salfred * 5184610Salfred * Redistribution and use in source and binary forms, with or without 6184610Salfred * modification, are permitted provided that the following conditions 7184610Salfred * are met: 8184610Salfred * 1. Redistributions of source code must retain the above copyright 9184610Salfred * notice, this list of conditions and the following disclaimer. 10184610Salfred * 2. Redistributions in binary form must reproduce the above copyright 11184610Salfred * notice, this list of conditions and the following disclaimer in the 12184610Salfred * documentation and/or other materials provided with the distribution. 13184610Salfred * 14184610Salfred * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15184610Salfred * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16184610Salfred * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17184610Salfred * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18184610Salfred * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19184610Salfred * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20184610Salfred * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21184610Salfred * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22184610Salfred * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23184610Salfred * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24184610Salfred * SUCH DAMAGE. 25184610Salfred */ 26184610Salfred 27246122Shselasky#ifdef USB_GLOBAL_INCLUDE_FILE 28246122Shselasky#include USB_GLOBAL_INCLUDE_FILE 29246122Shselasky#else 30194677Sthompsa#include <sys/stdint.h> 31194677Sthompsa#include <sys/stddef.h> 32194677Sthompsa#include <sys/param.h> 33194677Sthompsa#include <sys/queue.h> 34194677Sthompsa#include <sys/types.h> 35194677Sthompsa#include <sys/systm.h> 36194677Sthompsa#include <sys/kernel.h> 37194677Sthompsa#include <sys/bus.h> 38194677Sthompsa#include <sys/module.h> 39194677Sthompsa#include <sys/lock.h> 40194677Sthompsa#include <sys/mutex.h> 41194677Sthompsa#include <sys/condvar.h> 42194677Sthompsa#include <sys/sysctl.h> 43194677Sthompsa#include <sys/sx.h> 44194677Sthompsa#include <sys/unistd.h> 45194677Sthompsa#include <sys/callout.h> 46194677Sthompsa#include <sys/malloc.h> 47194677Sthompsa#include <sys/priv.h> 48223538Shselasky#include <sys/limits.h> 49223538Shselasky#include <sys/endian.h> 50184610Salfred 51194677Sthompsa#include <dev/usb/usb.h> 52194677Sthompsa#include <dev/usb/usbdi.h> 53246122Shselasky#endif /* USB_GLOBAL_INCLUDE_FILE */ 54194677Sthompsa 55184610Salfred/*------------------------------------------------------------------------* 56194228Sthompsa * usbd_lookup_id_by_info 57184610Salfred * 58192984Sthompsa * This functions takes an array of "struct usb_device_id" and tries 59194228Sthompsa * to match the entries with the information in "struct usbd_lookup_info". 60184610Salfred * 61184610Salfred * NOTE: The "sizeof_id" parameter must be a multiple of the 62192984Sthompsa * usb_device_id structure size. Else the behaviour of this function 63184610Salfred * is undefined. 64184610Salfred * 65184610Salfred * Return values: 66184610Salfred * NULL: No match found. 67184610Salfred * Else: Pointer to matching entry. 68184610Salfred *------------------------------------------------------------------------*/ 69192984Sthompsaconst struct usb_device_id * 70194228Sthompsausbd_lookup_id_by_info(const struct usb_device_id *id, usb_size_t sizeof_id, 71194228Sthompsa const struct usbd_lookup_info *info) 72184610Salfred{ 73192984Sthompsa const struct usb_device_id *id_end; 74184610Salfred 75184610Salfred if (id == NULL) { 76184610Salfred goto done; 77184610Salfred } 78184610Salfred id_end = (const void *)(((const uint8_t *)id) + sizeof_id); 79184610Salfred 80184610Salfred /* 81184610Salfred * Keep on matching array entries until we find a match or 82184610Salfred * until we reach the end of the matching array: 83184610Salfred */ 84184610Salfred for (; id != id_end; id++) { 85184610Salfred 86184610Salfred if ((id->match_flag_vendor) && 87184610Salfred (id->idVendor != info->idVendor)) { 88184610Salfred continue; 89184610Salfred } 90184610Salfred if ((id->match_flag_product) && 91184610Salfred (id->idProduct != info->idProduct)) { 92184610Salfred continue; 93184610Salfred } 94184610Salfred if ((id->match_flag_dev_lo) && 95184610Salfred (id->bcdDevice_lo > info->bcdDevice)) { 96184610Salfred continue; 97184610Salfred } 98184610Salfred if ((id->match_flag_dev_hi) && 99184610Salfred (id->bcdDevice_hi < info->bcdDevice)) { 100184610Salfred continue; 101184610Salfred } 102184610Salfred if ((id->match_flag_dev_class) && 103184610Salfred (id->bDeviceClass != info->bDeviceClass)) { 104184610Salfred continue; 105184610Salfred } 106184610Salfred if ((id->match_flag_dev_subclass) && 107184610Salfred (id->bDeviceSubClass != info->bDeviceSubClass)) { 108184610Salfred continue; 109184610Salfred } 110184610Salfred if ((id->match_flag_dev_protocol) && 111184610Salfred (id->bDeviceProtocol != info->bDeviceProtocol)) { 112184610Salfred continue; 113184610Salfred } 114184610Salfred if ((id->match_flag_int_class) && 115184610Salfred (id->bInterfaceClass != info->bInterfaceClass)) { 116184610Salfred continue; 117184610Salfred } 118184610Salfred if ((id->match_flag_int_subclass) && 119184610Salfred (id->bInterfaceSubClass != info->bInterfaceSubClass)) { 120184610Salfred continue; 121184610Salfred } 122184610Salfred if ((id->match_flag_int_protocol) && 123184610Salfred (id->bInterfaceProtocol != info->bInterfaceProtocol)) { 124184610Salfred continue; 125184610Salfred } 126184610Salfred /* We found a match! */ 127184610Salfred return (id); 128184610Salfred } 129184610Salfred 130184610Salfreddone: 131184610Salfred return (NULL); 132184610Salfred} 133184610Salfred 134184610Salfred/*------------------------------------------------------------------------* 135194228Sthompsa * usbd_lookup_id_by_uaa - factored out code 136184610Salfred * 137184610Salfred * Return values: 138184610Salfred * 0: Success 139184610Salfred * Else: Failure 140184610Salfred *------------------------------------------------------------------------*/ 141184610Salfredint 142194228Sthompsausbd_lookup_id_by_uaa(const struct usb_device_id *id, usb_size_t sizeof_id, 143192984Sthompsa struct usb_attach_arg *uaa) 144184610Salfred{ 145194228Sthompsa id = usbd_lookup_id_by_info(id, sizeof_id, &uaa->info); 146184610Salfred if (id) { 147184610Salfred /* copy driver info */ 148184610Salfred uaa->driver_info = id->driver_info; 149184610Salfred return (0); 150184610Salfred } 151184610Salfred return (ENXIO); 152184610Salfred} 153223538Shselasky 154223538Shselasky/*------------------------------------------------------------------------* 155223538Shselasky * Export the USB device ID format we use to userspace tools. 156223538Shselasky *------------------------------------------------------------------------*/ 157223538Shselasky#if BYTE_ORDER == BIG_ENDIAN 158223538Shselasky#define U16_XOR "8" 159223538Shselasky#define U32_XOR "12" 160223538Shselasky#define U64_XOR "56" 161223538Shselasky#define U8_BITFIELD_XOR "7" 162223538Shselasky#define U16_BITFIELD_XOR "15" 163223538Shselasky#define U32_BITFIELD_XOR "31" 164223538Shselasky#define U64_BITFIELD_XOR "63" 165223538Shselasky#else 166223538Shselasky#define U16_XOR "0" 167223538Shselasky#define U32_XOR "0" 168223538Shselasky#define U64_XOR "0" 169223538Shselasky#define U8_BITFIELD_XOR "0" 170223538Shselasky#define U16_BITFIELD_XOR "0" 171223538Shselasky#define U32_BITFIELD_XOR "0" 172223538Shselasky#define U64_BITFIELD_XOR "0" 173223538Shselasky#endif 174223538Shselasky 175223538Shselasky#if USB_HAVE_COMPAT_LINUX 176223538Shselasky#define MFL_SIZE "1" 177223538Shselasky#else 178223538Shselasky#define MFL_SIZE "0" 179223538Shselasky#endif 180223538Shselasky 181246194Shselasky#if defined(KLD_MODULE) && (USB_HAVE_ID_SECTION != 0) 182223538Shselaskystatic const char __section("bus_autoconf_format") __used usb_id_format[] = { 183223538Shselasky 184223538Shselasky /* Declare that three different sections use the same format */ 185223538Shselasky 186223538Shselasky "usb_host_id{256,:}" 187223538Shselasky "usb_device_id{256,:}" 188223538Shselasky "usb_dual_id{256,:}" 189223538Shselasky 190223538Shselasky /* List size of fields in the usb_device_id structure */ 191223538Shselasky 192223538Shselasky#if ULONG_MAX >= 0xFFFFFFFFUL 193223538Shselasky "unused{0,8}" 194223538Shselasky "unused{0,8}" 195223538Shselasky "unused{0,8}" 196223538Shselasky "unused{0,8}" 197223538Shselasky#if ULONG_MAX >= 0xFFFFFFFFFFFFFFFFULL 198223538Shselasky "unused{0,8}" 199223538Shselasky "unused{0,8}" 200223538Shselasky "unused{0,8}" 201223538Shselasky "unused{0,8}" 202223538Shselasky#endif 203223538Shselasky#else 204223538Shselasky#error "Please update code." 205223538Shselasky#endif 206223538Shselasky 207223538Shselasky "idVendor[0]{" U16_XOR ",8}" 208223538Shselasky "idVendor[1]{" U16_XOR ",8}" 209223538Shselasky "idProduct[0]{" U16_XOR ",8}" 210223538Shselasky "idProduct[1]{" U16_XOR ",8}" 211223538Shselasky "bcdDevice_lo[0]{" U16_XOR ",8}" 212223538Shselasky "bcdDevice_lo[1]{" U16_XOR ",8}" 213223538Shselasky "bcdDevice_hi[0]{" U16_XOR ",8}" 214223538Shselasky "bcdDevice_hi[1]{" U16_XOR ",8}" 215223538Shselasky 216223538Shselasky "bDeviceClass{0,8}" 217223538Shselasky "bDeviceSubClass{0,8}" 218223538Shselasky "bDeviceProtocol{0,8}" 219223538Shselasky "bInterfaceClass{0,8}" 220223538Shselasky "bInterfaceSubClass{0,8}" 221223538Shselasky "bInterfaceProtocol{0,8}" 222223538Shselasky 223223538Shselasky "mf_vendor{" U8_BITFIELD_XOR ",1}" 224223538Shselasky "mf_product{" U8_BITFIELD_XOR ",1}" 225223538Shselasky "mf_dev_lo{" U8_BITFIELD_XOR ",1}" 226223538Shselasky "mf_dev_hi{" U8_BITFIELD_XOR ",1}" 227223538Shselasky 228223538Shselasky "mf_dev_class{" U8_BITFIELD_XOR ",1}" 229223538Shselasky "mf_dev_subclass{" U8_BITFIELD_XOR ",1}" 230223538Shselasky "mf_dev_protocol{" U8_BITFIELD_XOR ",1}" 231223538Shselasky "mf_int_class{" U8_BITFIELD_XOR ",1}" 232223538Shselasky 233223538Shselasky "mf_int_subclass{" U8_BITFIELD_XOR ",1}" 234223538Shselasky "mf_int_protocol{" U8_BITFIELD_XOR ",1}" 235223538Shselasky "unused{" U8_BITFIELD_XOR ",6}" 236223538Shselasky 237223538Shselasky "mfl_vendor{" U16_XOR "," MFL_SIZE "}" 238223538Shselasky "mfl_product{" U16_XOR "," MFL_SIZE "}" 239223538Shselasky "mfl_dev_lo{" U16_XOR "," MFL_SIZE "}" 240223538Shselasky "mfl_dev_hi{" U16_XOR "," MFL_SIZE "}" 241223538Shselasky 242223538Shselasky "mfl_dev_class{" U16_XOR "," MFL_SIZE "}" 243223538Shselasky "mfl_dev_subclass{" U16_XOR "," MFL_SIZE "}" 244223538Shselasky "mfl_dev_protocol{" U16_XOR "," MFL_SIZE "}" 245223538Shselasky "mfl_int_class{" U16_XOR "," MFL_SIZE "}" 246223538Shselasky 247223538Shselasky "mfl_int_subclass{" U16_XOR "," MFL_SIZE "}" 248223538Shselasky "mfl_int_protocol{" U16_XOR "," MFL_SIZE "}" 249223538Shselasky "unused{" U16_XOR "," MFL_SIZE "}" 250223538Shselasky "unused{" U16_XOR "," MFL_SIZE "}" 251223538Shselasky 252223538Shselasky "unused{" U16_XOR "," MFL_SIZE "}" 253223538Shselasky "unused{" U16_XOR "," MFL_SIZE "}" 254223538Shselasky "unused{" U16_XOR "," MFL_SIZE "}" 255223538Shselasky "unused{" U16_XOR "," MFL_SIZE "}" 256223538Shselasky}; 257223538Shselasky#endif 258