usb_lookup.c revision 194677
1184610Salfred/* $FreeBSD: head/sys/dev/usb/usb_lookup.c 194677 2009-06-23 02:19:59Z thompsa $ */ 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 27194677Sthompsa#include <sys/stdint.h> 28194677Sthompsa#include <sys/stddef.h> 29194677Sthompsa#include <sys/param.h> 30194677Sthompsa#include <sys/queue.h> 31194677Sthompsa#include <sys/types.h> 32194677Sthompsa#include <sys/systm.h> 33194677Sthompsa#include <sys/kernel.h> 34194677Sthompsa#include <sys/bus.h> 35194677Sthompsa#include <sys/linker_set.h> 36194677Sthompsa#include <sys/module.h> 37194677Sthompsa#include <sys/lock.h> 38194677Sthompsa#include <sys/mutex.h> 39194677Sthompsa#include <sys/condvar.h> 40194677Sthompsa#include <sys/sysctl.h> 41194677Sthompsa#include <sys/sx.h> 42194677Sthompsa#include <sys/unistd.h> 43194677Sthompsa#include <sys/callout.h> 44194677Sthompsa#include <sys/malloc.h> 45194677Sthompsa#include <sys/priv.h> 46184610Salfred 47194677Sthompsa#include <dev/usb/usb.h> 48194677Sthompsa#include <dev/usb/usbdi.h> 49194677Sthompsa 50184610Salfred/*------------------------------------------------------------------------* 51194228Sthompsa * usbd_lookup_id_by_info 52184610Salfred * 53192984Sthompsa * This functions takes an array of "struct usb_device_id" and tries 54194228Sthompsa * to match the entries with the information in "struct usbd_lookup_info". 55184610Salfred * 56184610Salfred * NOTE: The "sizeof_id" parameter must be a multiple of the 57192984Sthompsa * usb_device_id structure size. Else the behaviour of this function 58184610Salfred * is undefined. 59184610Salfred * 60184610Salfred * Return values: 61184610Salfred * NULL: No match found. 62184610Salfred * Else: Pointer to matching entry. 63184610Salfred *------------------------------------------------------------------------*/ 64192984Sthompsaconst struct usb_device_id * 65194228Sthompsausbd_lookup_id_by_info(const struct usb_device_id *id, usb_size_t sizeof_id, 66194228Sthompsa const struct usbd_lookup_info *info) 67184610Salfred{ 68192984Sthompsa const struct usb_device_id *id_end; 69184610Salfred 70184610Salfred if (id == NULL) { 71184610Salfred goto done; 72184610Salfred } 73184610Salfred id_end = (const void *)(((const uint8_t *)id) + sizeof_id); 74184610Salfred 75184610Salfred /* 76184610Salfred * Keep on matching array entries until we find a match or 77184610Salfred * until we reach the end of the matching array: 78184610Salfred */ 79184610Salfred for (; id != id_end; id++) { 80184610Salfred 81184610Salfred if ((id->match_flag_vendor) && 82184610Salfred (id->idVendor != info->idVendor)) { 83184610Salfred continue; 84184610Salfred } 85184610Salfred if ((id->match_flag_product) && 86184610Salfred (id->idProduct != info->idProduct)) { 87184610Salfred continue; 88184610Salfred } 89184610Salfred if ((id->match_flag_dev_lo) && 90184610Salfred (id->bcdDevice_lo > info->bcdDevice)) { 91184610Salfred continue; 92184610Salfred } 93184610Salfred if ((id->match_flag_dev_hi) && 94184610Salfred (id->bcdDevice_hi < info->bcdDevice)) { 95184610Salfred continue; 96184610Salfred } 97184610Salfred if ((id->match_flag_dev_class) && 98184610Salfred (id->bDeviceClass != info->bDeviceClass)) { 99184610Salfred continue; 100184610Salfred } 101184610Salfred if ((id->match_flag_dev_subclass) && 102184610Salfred (id->bDeviceSubClass != info->bDeviceSubClass)) { 103184610Salfred continue; 104184610Salfred } 105184610Salfred if ((id->match_flag_dev_protocol) && 106184610Salfred (id->bDeviceProtocol != info->bDeviceProtocol)) { 107184610Salfred continue; 108184610Salfred } 109184610Salfred if ((info->bDeviceClass == 0xFF) && 110184610Salfred (!(id->match_flag_vendor)) && 111184610Salfred ((id->match_flag_int_class) || 112184610Salfred (id->match_flag_int_subclass) || 113184610Salfred (id->match_flag_int_protocol))) { 114184610Salfred continue; 115184610Salfred } 116184610Salfred if ((id->match_flag_int_class) && 117184610Salfred (id->bInterfaceClass != info->bInterfaceClass)) { 118184610Salfred continue; 119184610Salfred } 120184610Salfred if ((id->match_flag_int_subclass) && 121184610Salfred (id->bInterfaceSubClass != info->bInterfaceSubClass)) { 122184610Salfred continue; 123184610Salfred } 124184610Salfred if ((id->match_flag_int_protocol) && 125184610Salfred (id->bInterfaceProtocol != info->bInterfaceProtocol)) { 126184610Salfred continue; 127184610Salfred } 128184610Salfred /* We found a match! */ 129184610Salfred return (id); 130184610Salfred } 131184610Salfred 132184610Salfreddone: 133184610Salfred return (NULL); 134184610Salfred} 135184610Salfred 136184610Salfred/*------------------------------------------------------------------------* 137194228Sthompsa * usbd_lookup_id_by_uaa - factored out code 138184610Salfred * 139184610Salfred * Return values: 140184610Salfred * 0: Success 141184610Salfred * Else: Failure 142184610Salfred *------------------------------------------------------------------------*/ 143184610Salfredint 144194228Sthompsausbd_lookup_id_by_uaa(const struct usb_device_id *id, usb_size_t sizeof_id, 145192984Sthompsa struct usb_attach_arg *uaa) 146184610Salfred{ 147194228Sthompsa id = usbd_lookup_id_by_info(id, sizeof_id, &uaa->info); 148184610Salfred if (id) { 149184610Salfred /* copy driver info */ 150184610Salfred uaa->driver_info = id->driver_info; 151184610Salfred return (0); 152184610Salfred } 153184610Salfred return (ENXIO); 154184610Salfred} 155