xref: /freebsd-src/sys/dev/usb/usb_lookup.c (revision 71625ec9ad2a9bc8c09784fbd23b759830e0ee5f)
102ac6454SAndrew Thompson /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3718cf2ccSPedro F. Giffuni  *
402ac6454SAndrew Thompson  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
502ac6454SAndrew Thompson  *
602ac6454SAndrew Thompson  * Redistribution and use in source and binary forms, with or without
702ac6454SAndrew Thompson  * modification, are permitted provided that the following conditions
802ac6454SAndrew Thompson  * are met:
902ac6454SAndrew Thompson  * 1. Redistributions of source code must retain the above copyright
1002ac6454SAndrew Thompson  *    notice, this list of conditions and the following disclaimer.
1102ac6454SAndrew Thompson  * 2. Redistributions in binary form must reproduce the above copyright
1202ac6454SAndrew Thompson  *    notice, this list of conditions and the following disclaimer in the
1302ac6454SAndrew Thompson  *    documentation and/or other materials provided with the distribution.
1402ac6454SAndrew Thompson  *
1502ac6454SAndrew Thompson  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1602ac6454SAndrew Thompson  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1702ac6454SAndrew Thompson  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1802ac6454SAndrew Thompson  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1902ac6454SAndrew Thompson  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2002ac6454SAndrew Thompson  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2102ac6454SAndrew Thompson  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2202ac6454SAndrew Thompson  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2302ac6454SAndrew Thompson  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2402ac6454SAndrew Thompson  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2502ac6454SAndrew Thompson  * SUCH DAMAGE.
2602ac6454SAndrew Thompson  */
2702ac6454SAndrew Thompson 
28d2b99310SHans Petter Selasky #ifdef USB_GLOBAL_INCLUDE_FILE
29d2b99310SHans Petter Selasky #include USB_GLOBAL_INCLUDE_FILE
30d2b99310SHans Petter Selasky #else
31ed6d949aSAndrew Thompson #include <sys/stdint.h>
32ed6d949aSAndrew Thompson #include <sys/stddef.h>
33ed6d949aSAndrew Thompson #include <sys/param.h>
34ed6d949aSAndrew Thompson #include <sys/queue.h>
35ed6d949aSAndrew Thompson #include <sys/types.h>
36ed6d949aSAndrew Thompson #include <sys/systm.h>
37ed6d949aSAndrew Thompson #include <sys/kernel.h>
38ed6d949aSAndrew Thompson #include <sys/bus.h>
39ed6d949aSAndrew Thompson #include <sys/module.h>
40ed6d949aSAndrew Thompson #include <sys/lock.h>
41ed6d949aSAndrew Thompson #include <sys/mutex.h>
42ed6d949aSAndrew Thompson #include <sys/condvar.h>
43ed6d949aSAndrew Thompson #include <sys/sysctl.h>
44ed6d949aSAndrew Thompson #include <sys/sx.h>
45ed6d949aSAndrew Thompson #include <sys/unistd.h>
46ed6d949aSAndrew Thompson #include <sys/callout.h>
47ed6d949aSAndrew Thompson #include <sys/malloc.h>
48ed6d949aSAndrew Thompson #include <sys/priv.h>
491d63770bSHans Petter Selasky #include <sys/limits.h>
501d63770bSHans Petter Selasky #include <sys/endian.h>
51ed6d949aSAndrew Thompson 
52ed6d949aSAndrew Thompson #include <dev/usb/usb.h>
53ed6d949aSAndrew Thompson #include <dev/usb/usbdi.h>
54d2b99310SHans Petter Selasky #endif			/* USB_GLOBAL_INCLUDE_FILE */
5502ac6454SAndrew Thompson 
5602ac6454SAndrew Thompson /*------------------------------------------------------------------------*
57a593f6b8SAndrew Thompson  *	usbd_lookup_id_by_info
5802ac6454SAndrew Thompson  *
59760bc48eSAndrew Thompson  * This functions takes an array of "struct usb_device_id" and tries
60a593f6b8SAndrew Thompson  * to match the entries with the information in "struct usbd_lookup_info".
6102ac6454SAndrew Thompson  *
6202ac6454SAndrew Thompson  * NOTE: The "sizeof_id" parameter must be a multiple of the
63760bc48eSAndrew Thompson  * usb_device_id structure size. Else the behaviour of this function
6402ac6454SAndrew Thompson  * is undefined.
6502ac6454SAndrew Thompson  *
6602ac6454SAndrew Thompson  * Return values:
6702ac6454SAndrew Thompson  * NULL: No match found.
6802ac6454SAndrew Thompson  * Else: Pointer to matching entry.
6902ac6454SAndrew Thompson  *------------------------------------------------------------------------*/
70760bc48eSAndrew Thompson const struct usb_device_id *
usbd_lookup_id_by_info(const struct usb_device_id * id,usb_size_t sizeof_id,const struct usbd_lookup_info * info)71a593f6b8SAndrew Thompson usbd_lookup_id_by_info(const struct usb_device_id *id, usb_size_t sizeof_id,
72a593f6b8SAndrew Thompson     const struct usbd_lookup_info *info)
7302ac6454SAndrew Thompson {
74760bc48eSAndrew Thompson 	const struct usb_device_id *id_end;
7502ac6454SAndrew Thompson 
7602ac6454SAndrew Thompson 	if (id == NULL) {
7702ac6454SAndrew Thompson 		goto done;
7802ac6454SAndrew Thompson 	}
7902ac6454SAndrew Thompson 	id_end = (const void *)(((const uint8_t *)id) + sizeof_id);
8002ac6454SAndrew Thompson 
8102ac6454SAndrew Thompson 	/*
8202ac6454SAndrew Thompson 	 * Keep on matching array entries until we find a match or
8302ac6454SAndrew Thompson 	 * until we reach the end of the matching array:
8402ac6454SAndrew Thompson 	 */
8502ac6454SAndrew Thompson 	for (; id != id_end; id++) {
8602ac6454SAndrew Thompson 		if ((id->match_flag_vendor) &&
8702ac6454SAndrew Thompson 		    (id->idVendor != info->idVendor)) {
8802ac6454SAndrew Thompson 			continue;
8902ac6454SAndrew Thompson 		}
9002ac6454SAndrew Thompson 		if ((id->match_flag_product) &&
9102ac6454SAndrew Thompson 		    (id->idProduct != info->idProduct)) {
9202ac6454SAndrew Thompson 			continue;
9302ac6454SAndrew Thompson 		}
9402ac6454SAndrew Thompson 		if ((id->match_flag_dev_lo) &&
9502ac6454SAndrew Thompson 		    (id->bcdDevice_lo > info->bcdDevice)) {
9602ac6454SAndrew Thompson 			continue;
9702ac6454SAndrew Thompson 		}
9802ac6454SAndrew Thompson 		if ((id->match_flag_dev_hi) &&
9902ac6454SAndrew Thompson 		    (id->bcdDevice_hi < info->bcdDevice)) {
10002ac6454SAndrew Thompson 			continue;
10102ac6454SAndrew Thompson 		}
10202ac6454SAndrew Thompson 		if ((id->match_flag_dev_class) &&
10302ac6454SAndrew Thompson 		    (id->bDeviceClass != info->bDeviceClass)) {
10402ac6454SAndrew Thompson 			continue;
10502ac6454SAndrew Thompson 		}
10602ac6454SAndrew Thompson 		if ((id->match_flag_dev_subclass) &&
10702ac6454SAndrew Thompson 		    (id->bDeviceSubClass != info->bDeviceSubClass)) {
10802ac6454SAndrew Thompson 			continue;
10902ac6454SAndrew Thompson 		}
11002ac6454SAndrew Thompson 		if ((id->match_flag_dev_protocol) &&
11102ac6454SAndrew Thompson 		    (id->bDeviceProtocol != info->bDeviceProtocol)) {
11202ac6454SAndrew Thompson 			continue;
11302ac6454SAndrew Thompson 		}
11402ac6454SAndrew Thompson 		if ((id->match_flag_int_class) &&
11502ac6454SAndrew Thompson 		    (id->bInterfaceClass != info->bInterfaceClass)) {
11602ac6454SAndrew Thompson 			continue;
11702ac6454SAndrew Thompson 		}
11802ac6454SAndrew Thompson 		if ((id->match_flag_int_subclass) &&
11902ac6454SAndrew Thompson 		    (id->bInterfaceSubClass != info->bInterfaceSubClass)) {
12002ac6454SAndrew Thompson 			continue;
12102ac6454SAndrew Thompson 		}
12202ac6454SAndrew Thompson 		if ((id->match_flag_int_protocol) &&
12302ac6454SAndrew Thompson 		    (id->bInterfaceProtocol != info->bInterfaceProtocol)) {
12402ac6454SAndrew Thompson 			continue;
12502ac6454SAndrew Thompson 		}
12602ac6454SAndrew Thompson 		/* We found a match! */
12702ac6454SAndrew Thompson 		return (id);
12802ac6454SAndrew Thompson 	}
12902ac6454SAndrew Thompson 
13002ac6454SAndrew Thompson done:
13102ac6454SAndrew Thompson 	return (NULL);
13202ac6454SAndrew Thompson }
13302ac6454SAndrew Thompson 
13402ac6454SAndrew Thompson /*------------------------------------------------------------------------*
135a593f6b8SAndrew Thompson  *	usbd_lookup_id_by_uaa - factored out code
13602ac6454SAndrew Thompson  *
13702ac6454SAndrew Thompson  * Return values:
13802ac6454SAndrew Thompson  *    0: Success
13902ac6454SAndrew Thompson  * Else: Failure
14002ac6454SAndrew Thompson  *------------------------------------------------------------------------*/
14102ac6454SAndrew Thompson int
usbd_lookup_id_by_uaa(const struct usb_device_id * id,usb_size_t sizeof_id,struct usb_attach_arg * uaa)142a593f6b8SAndrew Thompson usbd_lookup_id_by_uaa(const struct usb_device_id *id, usb_size_t sizeof_id,
143760bc48eSAndrew Thompson     struct usb_attach_arg *uaa)
14402ac6454SAndrew Thompson {
145a593f6b8SAndrew Thompson 	id = usbd_lookup_id_by_info(id, sizeof_id, &uaa->info);
14602ac6454SAndrew Thompson 	if (id) {
14702ac6454SAndrew Thompson 		/* copy driver info */
14802ac6454SAndrew Thompson 		uaa->driver_info = id->driver_info;
14902ac6454SAndrew Thompson 		return (0);
15002ac6454SAndrew Thompson 	}
15102ac6454SAndrew Thompson 	return (ENXIO);
15202ac6454SAndrew Thompson }
153