13dc87e52SEdward Tomasz Napierala /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
33dc87e52SEdward Tomasz Napierala *
43dc87e52SEdward Tomasz Napierala * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
53dc87e52SEdward Tomasz Napierala * Copyright (c) 2018 The FreeBSD Foundation
63dc87e52SEdward Tomasz Napierala * All rights reserved.
73dc87e52SEdward Tomasz Napierala *
83dc87e52SEdward Tomasz Napierala * This software was developed by SRI International and the University of
93dc87e52SEdward Tomasz Napierala * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
103dc87e52SEdward Tomasz Napierala * ("CTSRD"), as part of the DARPA CRASH research programme.
113dc87e52SEdward Tomasz Napierala *
123dc87e52SEdward Tomasz Napierala * Portions of this software were developed by Edward Tomasz Napierala
133dc87e52SEdward Tomasz Napierala * under sponsorship from the FreeBSD Foundation.
143dc87e52SEdward Tomasz Napierala *
153dc87e52SEdward Tomasz Napierala * Redistribution and use in source and binary forms, with or without
163dc87e52SEdward Tomasz Napierala * modification, are permitted provided that the following conditions
173dc87e52SEdward Tomasz Napierala * are met:
183dc87e52SEdward Tomasz Napierala * 1. Redistributions of source code must retain the above copyright
193dc87e52SEdward Tomasz Napierala * notice, this list of conditions and the following disclaimer.
203dc87e52SEdward Tomasz Napierala * 2. Redistributions in binary form must reproduce the above copyright
213dc87e52SEdward Tomasz Napierala * notice, this list of conditions and the following disclaimer in the
223dc87e52SEdward Tomasz Napierala * documentation and/or other materials provided with the distribution.
233dc87e52SEdward Tomasz Napierala *
243dc87e52SEdward Tomasz Napierala * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
253dc87e52SEdward Tomasz Napierala * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
263dc87e52SEdward Tomasz Napierala * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
273dc87e52SEdward Tomasz Napierala * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
283dc87e52SEdward Tomasz Napierala * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
293dc87e52SEdward Tomasz Napierala * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
303dc87e52SEdward Tomasz Napierala * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
313dc87e52SEdward Tomasz Napierala * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
323dc87e52SEdward Tomasz Napierala * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
333dc87e52SEdward Tomasz Napierala * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
343dc87e52SEdward Tomasz Napierala * SUCH DAMAGE.
353dc87e52SEdward Tomasz Napierala */
363dc87e52SEdward Tomasz Napierala /*
373dc87e52SEdward Tomasz Napierala * USB template for CDC ACM (serial), CDC ECM (network), and CDC MSC (storage).
383dc87e52SEdward Tomasz Napierala */
393dc87e52SEdward Tomasz Napierala
403dc87e52SEdward Tomasz Napierala #ifdef USB_GLOBAL_INCLUDE_FILE
413dc87e52SEdward Tomasz Napierala #include USB_GLOBAL_INCLUDE_FILE
423dc87e52SEdward Tomasz Napierala #else
433dc87e52SEdward Tomasz Napierala #include <sys/stdint.h>
443dc87e52SEdward Tomasz Napierala #include <sys/stddef.h>
453dc87e52SEdward Tomasz Napierala #include <sys/param.h>
463dc87e52SEdward Tomasz Napierala #include <sys/queue.h>
473dc87e52SEdward Tomasz Napierala #include <sys/types.h>
483dc87e52SEdward Tomasz Napierala #include <sys/systm.h>
493dc87e52SEdward Tomasz Napierala #include <sys/kernel.h>
503dc87e52SEdward Tomasz Napierala #include <sys/bus.h>
513dc87e52SEdward Tomasz Napierala #include <sys/module.h>
523dc87e52SEdward Tomasz Napierala #include <sys/lock.h>
533dc87e52SEdward Tomasz Napierala #include <sys/mutex.h>
543dc87e52SEdward Tomasz Napierala #include <sys/condvar.h>
553dc87e52SEdward Tomasz Napierala #include <sys/sysctl.h>
563dc87e52SEdward Tomasz Napierala #include <sys/sx.h>
573dc87e52SEdward Tomasz Napierala #include <sys/unistd.h>
583dc87e52SEdward Tomasz Napierala #include <sys/callout.h>
593dc87e52SEdward Tomasz Napierala #include <sys/malloc.h>
603dc87e52SEdward Tomasz Napierala #include <sys/priv.h>
613dc87e52SEdward Tomasz Napierala
623dc87e52SEdward Tomasz Napierala #include <dev/usb/usb.h>
633dc87e52SEdward Tomasz Napierala #include <dev/usb/usbdi.h>
643dc87e52SEdward Tomasz Napierala #include <dev/usb/usb_core.h>
653dc87e52SEdward Tomasz Napierala #include <dev/usb/usb_cdc.h>
663dc87e52SEdward Tomasz Napierala #include <dev/usb/usb_ioctl.h>
673dc87e52SEdward Tomasz Napierala #include <dev/usb/usb_util.h>
683dc87e52SEdward Tomasz Napierala
693dc87e52SEdward Tomasz Napierala #include <dev/usb/template/usb_template.h>
703dc87e52SEdward Tomasz Napierala #endif /* USB_GLOBAL_INCLUDE_FILE */
713dc87e52SEdward Tomasz Napierala
723dc87e52SEdward Tomasz Napierala #define MODEM_IFACE_0 0
733dc87e52SEdward Tomasz Napierala #define MODEM_IFACE_1 1
743dc87e52SEdward Tomasz Napierala
753dc87e52SEdward Tomasz Napierala enum {
763dc87e52SEdward Tomasz Napierala MULTI_LANG_INDEX,
773dc87e52SEdward Tomasz Napierala MULTI_MODEM_INDEX,
783dc87e52SEdward Tomasz Napierala MULTI_ETH_MAC_INDEX,
793dc87e52SEdward Tomasz Napierala MULTI_ETH_CONTROL_INDEX,
803dc87e52SEdward Tomasz Napierala MULTI_ETH_DATA_INDEX,
813dc87e52SEdward Tomasz Napierala MULTI_STORAGE_INDEX,
823dc87e52SEdward Tomasz Napierala MULTI_CONFIGURATION_INDEX,
833dc87e52SEdward Tomasz Napierala MULTI_MANUFACTURER_INDEX,
843dc87e52SEdward Tomasz Napierala MULTI_PRODUCT_INDEX,
853dc87e52SEdward Tomasz Napierala MULTI_SERIAL_NUMBER_INDEX,
863dc87e52SEdward Tomasz Napierala MULTI_MAX_INDEX,
873dc87e52SEdward Tomasz Napierala };
883dc87e52SEdward Tomasz Napierala
891558eec6SEdward Tomasz Napierala #define MULTI_DEFAULT_VENDOR_ID USB_TEMPLATE_VENDOR
90d01c1c8bSEdward Tomasz Napierala #define MULTI_DEFAULT_PRODUCT_ID 0x05dc
91ac4a7f30SEdward Tomasz Napierala #define MULTI_DEFAULT_MODEM "Virtual serial port"
923dc87e52SEdward Tomasz Napierala #define MULTI_DEFAULT_ETH_MAC "2A02030405060789AB"
933dc87e52SEdward Tomasz Napierala #define MULTI_DEFAULT_ETH_CONTROL "Ethernet Comm Interface"
943dc87e52SEdward Tomasz Napierala #define MULTI_DEFAULT_ETH_DATA "Ethernet Data Interface"
953dc87e52SEdward Tomasz Napierala #define MULTI_DEFAULT_STORAGE "Mass Storage Interface"
963dc87e52SEdward Tomasz Napierala #define MULTI_DEFAULT_CONFIGURATION "Default configuration"
97d01c1c8bSEdward Tomasz Napierala #define MULTI_DEFAULT_MANUFACTURER USB_TEMPLATE_MANUFACTURER
983dc87e52SEdward Tomasz Napierala #define MULTI_DEFAULT_PRODUCT "Multifunction Device"
99733efc21SEdward Tomasz Napierala /*
100733efc21SEdward Tomasz Napierala * The reason for this being called like this is that OSX
101733efc21SEdward Tomasz Napierala * derives the device node name from it, resulting in a somewhat
102733efc21SEdward Tomasz Napierala * user-friendly "/dev/cu.usbmodemFreeBSD1". And yes, the "1"
103733efc21SEdward Tomasz Napierala * needs to be there, otherwise OSX will mangle it.
104733efc21SEdward Tomasz Napierala */
105733efc21SEdward Tomasz Napierala #define MULTI_DEFAULT_SERIAL_NUMBER "FreeBSD1"
1063dc87e52SEdward Tomasz Napierala
1073dc87e52SEdward Tomasz Napierala static struct usb_string_descriptor multi_modem;
1083dc87e52SEdward Tomasz Napierala static struct usb_string_descriptor multi_eth_mac;
1093dc87e52SEdward Tomasz Napierala static struct usb_string_descriptor multi_eth_control;
1103dc87e52SEdward Tomasz Napierala static struct usb_string_descriptor multi_eth_data;
1113dc87e52SEdward Tomasz Napierala static struct usb_string_descriptor multi_storage;
1123dc87e52SEdward Tomasz Napierala static struct usb_string_descriptor multi_configuration;
1133dc87e52SEdward Tomasz Napierala static struct usb_string_descriptor multi_manufacturer;
1143dc87e52SEdward Tomasz Napierala static struct usb_string_descriptor multi_product;
1153dc87e52SEdward Tomasz Napierala static struct usb_string_descriptor multi_serial_number;
1163dc87e52SEdward Tomasz Napierala
1173dc87e52SEdward Tomasz Napierala static struct sysctl_ctx_list multi_ctx_list;
1183dc87e52SEdward Tomasz Napierala
1193dc87e52SEdward Tomasz Napierala /* prototypes */
1203dc87e52SEdward Tomasz Napierala
1213dc87e52SEdward Tomasz Napierala static usb_temp_get_string_desc_t multi_get_string_desc;
1223dc87e52SEdward Tomasz Napierala
1233dc87e52SEdward Tomasz Napierala static const struct usb_cdc_union_descriptor eth_union_desc = {
1243dc87e52SEdward Tomasz Napierala .bLength = sizeof(eth_union_desc),
1253dc87e52SEdward Tomasz Napierala .bDescriptorType = UDESC_CS_INTERFACE,
1263dc87e52SEdward Tomasz Napierala .bDescriptorSubtype = UDESCSUB_CDC_UNION,
1273dc87e52SEdward Tomasz Napierala .bMasterInterface = 0, /* this is automatically updated */
1283dc87e52SEdward Tomasz Napierala .bSlaveInterface[0] = 1, /* this is automatically updated */
1293dc87e52SEdward Tomasz Napierala };
1303dc87e52SEdward Tomasz Napierala
1313dc87e52SEdward Tomasz Napierala static const struct usb_cdc_header_descriptor eth_header_desc = {
1323dc87e52SEdward Tomasz Napierala .bLength = sizeof(eth_header_desc),
1333dc87e52SEdward Tomasz Napierala .bDescriptorType = UDESC_CS_INTERFACE,
1343dc87e52SEdward Tomasz Napierala .bDescriptorSubtype = UDESCSUB_CDC_HEADER,
1353dc87e52SEdward Tomasz Napierala .bcdCDC[0] = 0x10,
1363dc87e52SEdward Tomasz Napierala .bcdCDC[1] = 0x01,
1373dc87e52SEdward Tomasz Napierala };
1383dc87e52SEdward Tomasz Napierala
1393dc87e52SEdward Tomasz Napierala static const struct usb_cdc_ethernet_descriptor eth_enf_desc = {
1403dc87e52SEdward Tomasz Napierala .bLength = sizeof(eth_enf_desc),
1413dc87e52SEdward Tomasz Napierala .bDescriptorType = UDESC_CS_INTERFACE,
1423dc87e52SEdward Tomasz Napierala .bDescriptorSubtype = UDESCSUB_CDC_ENF,
1433dc87e52SEdward Tomasz Napierala .iMacAddress = MULTI_ETH_MAC_INDEX,
1443dc87e52SEdward Tomasz Napierala .bmEthernetStatistics = {0, 0, 0, 0},
1453dc87e52SEdward Tomasz Napierala .wMaxSegmentSize = {0xEA, 0x05},/* 1514 bytes */
1463dc87e52SEdward Tomasz Napierala .wNumberMCFilters = {0, 0},
1473dc87e52SEdward Tomasz Napierala .bNumberPowerFilters = 0,
1483dc87e52SEdward Tomasz Napierala };
1493dc87e52SEdward Tomasz Napierala
1503dc87e52SEdward Tomasz Napierala static const void *eth_control_if_desc[] = {
1513dc87e52SEdward Tomasz Napierala ð_union_desc,
1523dc87e52SEdward Tomasz Napierala ð_header_desc,
1533dc87e52SEdward Tomasz Napierala ð_enf_desc,
1543dc87e52SEdward Tomasz Napierala NULL,
1553dc87e52SEdward Tomasz Napierala };
1563dc87e52SEdward Tomasz Napierala
1573dc87e52SEdward Tomasz Napierala static const struct usb_temp_packet_size bulk_mps = {
1583dc87e52SEdward Tomasz Napierala .mps[USB_SPEED_FULL] = 64,
1593dc87e52SEdward Tomasz Napierala .mps[USB_SPEED_HIGH] = 512,
1603dc87e52SEdward Tomasz Napierala };
1613dc87e52SEdward Tomasz Napierala
1623dc87e52SEdward Tomasz Napierala static const struct usb_temp_packet_size intr_mps = {
1633dc87e52SEdward Tomasz Napierala .mps[USB_SPEED_FULL] = 8,
1643dc87e52SEdward Tomasz Napierala .mps[USB_SPEED_HIGH] = 8,
1653dc87e52SEdward Tomasz Napierala };
1663dc87e52SEdward Tomasz Napierala
1673dc87e52SEdward Tomasz Napierala static const struct usb_temp_endpoint_desc bulk_in_ep = {
1683dc87e52SEdward Tomasz Napierala .pPacketSize = &bulk_mps,
1693dc87e52SEdward Tomasz Napierala #ifdef USB_HIP_IN_EP_0
1703dc87e52SEdward Tomasz Napierala .bEndpointAddress = USB_HIP_IN_EP_0,
1713dc87e52SEdward Tomasz Napierala #else
1723dc87e52SEdward Tomasz Napierala .bEndpointAddress = UE_DIR_IN,
1733dc87e52SEdward Tomasz Napierala #endif
1743dc87e52SEdward Tomasz Napierala .bmAttributes = UE_BULK,
1753dc87e52SEdward Tomasz Napierala };
1763dc87e52SEdward Tomasz Napierala
1773dc87e52SEdward Tomasz Napierala static const struct usb_temp_endpoint_desc bulk_out_ep = {
1783dc87e52SEdward Tomasz Napierala .pPacketSize = &bulk_mps,
1793dc87e52SEdward Tomasz Napierala #ifdef USB_HIP_OUT_EP_0
1803dc87e52SEdward Tomasz Napierala .bEndpointAddress = USB_HIP_OUT_EP_0,
1813dc87e52SEdward Tomasz Napierala #else
1823dc87e52SEdward Tomasz Napierala .bEndpointAddress = UE_DIR_OUT,
1833dc87e52SEdward Tomasz Napierala #endif
1843dc87e52SEdward Tomasz Napierala .bmAttributes = UE_BULK,
1853dc87e52SEdward Tomasz Napierala };
1863dc87e52SEdward Tomasz Napierala
1873dc87e52SEdward Tomasz Napierala static const struct usb_temp_endpoint_desc intr_in_ep = {
1883dc87e52SEdward Tomasz Napierala .pPacketSize = &intr_mps,
1893dc87e52SEdward Tomasz Napierala .bEndpointAddress = UE_DIR_IN,
1903dc87e52SEdward Tomasz Napierala .bmAttributes = UE_INTERRUPT,
1913dc87e52SEdward Tomasz Napierala };
1923dc87e52SEdward Tomasz Napierala
1933dc87e52SEdward Tomasz Napierala static const struct usb_temp_endpoint_desc *eth_intr_endpoints[] = {
1943dc87e52SEdward Tomasz Napierala &intr_in_ep,
1953dc87e52SEdward Tomasz Napierala NULL,
1963dc87e52SEdward Tomasz Napierala };
1973dc87e52SEdward Tomasz Napierala
1983dc87e52SEdward Tomasz Napierala static const struct usb_temp_interface_desc eth_control_interface = {
1993dc87e52SEdward Tomasz Napierala .ppEndpoints = eth_intr_endpoints,
2003dc87e52SEdward Tomasz Napierala .ppRawDesc = eth_control_if_desc,
2013dc87e52SEdward Tomasz Napierala .bInterfaceClass = UICLASS_CDC,
2023dc87e52SEdward Tomasz Napierala .bInterfaceSubClass = UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL,
2033dc87e52SEdward Tomasz Napierala .bInterfaceProtocol = UIPROTO_CDC_NONE,
2043dc87e52SEdward Tomasz Napierala .iInterface = MULTI_ETH_CONTROL_INDEX,
2053dc87e52SEdward Tomasz Napierala };
2063dc87e52SEdward Tomasz Napierala
2073dc87e52SEdward Tomasz Napierala static const struct usb_temp_endpoint_desc *eth_data_endpoints[] = {
2083dc87e52SEdward Tomasz Napierala &bulk_in_ep,
2093dc87e52SEdward Tomasz Napierala &bulk_out_ep,
2103dc87e52SEdward Tomasz Napierala NULL,
2113dc87e52SEdward Tomasz Napierala };
2123dc87e52SEdward Tomasz Napierala
2133dc87e52SEdward Tomasz Napierala static const struct usb_temp_interface_desc eth_data_null_interface = {
2143dc87e52SEdward Tomasz Napierala .ppEndpoints = NULL, /* no endpoints */
2153dc87e52SEdward Tomasz Napierala .bInterfaceClass = UICLASS_CDC_DATA,
2163dc87e52SEdward Tomasz Napierala .bInterfaceSubClass = UISUBCLASS_DATA,
2173dc87e52SEdward Tomasz Napierala .bInterfaceProtocol = 0,
2183dc87e52SEdward Tomasz Napierala .iInterface = MULTI_ETH_DATA_INDEX,
2193dc87e52SEdward Tomasz Napierala };
2203dc87e52SEdward Tomasz Napierala
2213dc87e52SEdward Tomasz Napierala static const struct usb_temp_interface_desc eth_data_interface = {
2223dc87e52SEdward Tomasz Napierala .ppEndpoints = eth_data_endpoints,
2233dc87e52SEdward Tomasz Napierala .bInterfaceClass = UICLASS_CDC_DATA,
2243dc87e52SEdward Tomasz Napierala .bInterfaceSubClass = UISUBCLASS_DATA,
2253dc87e52SEdward Tomasz Napierala .bInterfaceProtocol = 0,
2263dc87e52SEdward Tomasz Napierala .iInterface = MULTI_ETH_DATA_INDEX,
2273dc87e52SEdward Tomasz Napierala .isAltInterface = 1, /* this is an alternate setting */
2283dc87e52SEdward Tomasz Napierala };
2293dc87e52SEdward Tomasz Napierala
2303dc87e52SEdward Tomasz Napierala static const struct usb_temp_packet_size modem_bulk_mps = {
2313dc87e52SEdward Tomasz Napierala .mps[USB_SPEED_LOW] = 8,
2323dc87e52SEdward Tomasz Napierala .mps[USB_SPEED_FULL] = 64,
2333dc87e52SEdward Tomasz Napierala .mps[USB_SPEED_HIGH] = 512,
2343dc87e52SEdward Tomasz Napierala };
2353dc87e52SEdward Tomasz Napierala
2363dc87e52SEdward Tomasz Napierala static const struct usb_temp_packet_size modem_intr_mps = {
2373dc87e52SEdward Tomasz Napierala .mps[USB_SPEED_LOW] = 8,
2383dc87e52SEdward Tomasz Napierala .mps[USB_SPEED_FULL] = 8,
2393dc87e52SEdward Tomasz Napierala .mps[USB_SPEED_HIGH] = 8,
2403dc87e52SEdward Tomasz Napierala };
2413dc87e52SEdward Tomasz Napierala
2423dc87e52SEdward Tomasz Napierala static const struct usb_temp_interval modem_intr_interval = {
2433dc87e52SEdward Tomasz Napierala .bInterval[USB_SPEED_LOW] = 8, /* 8ms */
2443dc87e52SEdward Tomasz Napierala .bInterval[USB_SPEED_FULL] = 8, /* 8ms */
2453dc87e52SEdward Tomasz Napierala .bInterval[USB_SPEED_HIGH] = 7, /* 8ms */
2463dc87e52SEdward Tomasz Napierala };
2473dc87e52SEdward Tomasz Napierala
2483dc87e52SEdward Tomasz Napierala static const struct usb_temp_endpoint_desc modem_ep_0 = {
2493dc87e52SEdward Tomasz Napierala .pPacketSize = &modem_intr_mps,
2503dc87e52SEdward Tomasz Napierala .pIntervals = &modem_intr_interval,
2513dc87e52SEdward Tomasz Napierala .bEndpointAddress = UE_DIR_IN,
2523dc87e52SEdward Tomasz Napierala .bmAttributes = UE_INTERRUPT,
2533dc87e52SEdward Tomasz Napierala };
2543dc87e52SEdward Tomasz Napierala
2553dc87e52SEdward Tomasz Napierala static const struct usb_temp_endpoint_desc modem_ep_1 = {
2563dc87e52SEdward Tomasz Napierala .pPacketSize = &modem_bulk_mps,
2573dc87e52SEdward Tomasz Napierala .bEndpointAddress = UE_DIR_OUT,
2583dc87e52SEdward Tomasz Napierala .bmAttributes = UE_BULK,
2593dc87e52SEdward Tomasz Napierala };
2603dc87e52SEdward Tomasz Napierala
2613dc87e52SEdward Tomasz Napierala static const struct usb_temp_endpoint_desc modem_ep_2 = {
2623dc87e52SEdward Tomasz Napierala .pPacketSize = &modem_bulk_mps,
2633dc87e52SEdward Tomasz Napierala .bEndpointAddress = UE_DIR_IN,
2643dc87e52SEdward Tomasz Napierala .bmAttributes = UE_BULK,
2653dc87e52SEdward Tomasz Napierala };
2663dc87e52SEdward Tomasz Napierala
2673dc87e52SEdward Tomasz Napierala static const struct usb_temp_endpoint_desc *modem_iface_0_ep[] = {
2683dc87e52SEdward Tomasz Napierala &modem_ep_0,
2693dc87e52SEdward Tomasz Napierala NULL,
2703dc87e52SEdward Tomasz Napierala };
2713dc87e52SEdward Tomasz Napierala
2723dc87e52SEdward Tomasz Napierala static const struct usb_temp_endpoint_desc *modem_iface_1_ep[] = {
2733dc87e52SEdward Tomasz Napierala &modem_ep_1,
2743dc87e52SEdward Tomasz Napierala &modem_ep_2,
2753dc87e52SEdward Tomasz Napierala NULL,
2763dc87e52SEdward Tomasz Napierala };
2773dc87e52SEdward Tomasz Napierala
2783dc87e52SEdward Tomasz Napierala static const uint8_t modem_raw_desc_0[] = {
2793dc87e52SEdward Tomasz Napierala 0x05, 0x24, 0x00, 0x10, 0x01
2803dc87e52SEdward Tomasz Napierala };
2813dc87e52SEdward Tomasz Napierala
2823dc87e52SEdward Tomasz Napierala static const uint8_t modem_raw_desc_1[] = {
2833dc87e52SEdward Tomasz Napierala 0x05, 0x24, 0x06, MODEM_IFACE_0, MODEM_IFACE_1
2843dc87e52SEdward Tomasz Napierala };
2853dc87e52SEdward Tomasz Napierala
2863dc87e52SEdward Tomasz Napierala static const uint8_t modem_raw_desc_2[] = {
2873dc87e52SEdward Tomasz Napierala 0x05, 0x24, 0x01, 0x03, MODEM_IFACE_1
2883dc87e52SEdward Tomasz Napierala };
2893dc87e52SEdward Tomasz Napierala
2903dc87e52SEdward Tomasz Napierala static const uint8_t modem_raw_desc_3[] = {
2913dc87e52SEdward Tomasz Napierala 0x04, 0x24, 0x02, 0x07
2923dc87e52SEdward Tomasz Napierala };
2933dc87e52SEdward Tomasz Napierala
2943dc87e52SEdward Tomasz Napierala static const void *modem_iface_0_desc[] = {
2953dc87e52SEdward Tomasz Napierala &modem_raw_desc_0,
2963dc87e52SEdward Tomasz Napierala &modem_raw_desc_1,
2973dc87e52SEdward Tomasz Napierala &modem_raw_desc_2,
2983dc87e52SEdward Tomasz Napierala &modem_raw_desc_3,
2993dc87e52SEdward Tomasz Napierala NULL,
3003dc87e52SEdward Tomasz Napierala };
3013dc87e52SEdward Tomasz Napierala
3023dc87e52SEdward Tomasz Napierala static const struct usb_temp_interface_desc modem_iface_0 = {
3033dc87e52SEdward Tomasz Napierala .ppRawDesc = modem_iface_0_desc,
3043dc87e52SEdward Tomasz Napierala .ppEndpoints = modem_iface_0_ep,
3053dc87e52SEdward Tomasz Napierala .bInterfaceClass = UICLASS_CDC,
3063dc87e52SEdward Tomasz Napierala .bInterfaceSubClass = UISUBCLASS_ABSTRACT_CONTROL_MODEL,
3076b7e508cSEdward Tomasz Napierala .bInterfaceProtocol = UIPROTO_CDC_NONE,
3083dc87e52SEdward Tomasz Napierala .iInterface = MULTI_MODEM_INDEX,
3093dc87e52SEdward Tomasz Napierala };
3103dc87e52SEdward Tomasz Napierala
3113dc87e52SEdward Tomasz Napierala static const struct usb_temp_interface_desc modem_iface_1 = {
3123dc87e52SEdward Tomasz Napierala .ppEndpoints = modem_iface_1_ep,
3133dc87e52SEdward Tomasz Napierala .bInterfaceClass = UICLASS_CDC_DATA,
3143dc87e52SEdward Tomasz Napierala .bInterfaceSubClass = UISUBCLASS_DATA,
3153dc87e52SEdward Tomasz Napierala .bInterfaceProtocol = 0,
3163dc87e52SEdward Tomasz Napierala .iInterface = MULTI_MODEM_INDEX,
3173dc87e52SEdward Tomasz Napierala };
3183dc87e52SEdward Tomasz Napierala
3193dc87e52SEdward Tomasz Napierala static const struct usb_temp_packet_size msc_bulk_mps = {
3203dc87e52SEdward Tomasz Napierala .mps[USB_SPEED_FULL] = 64,
3213dc87e52SEdward Tomasz Napierala .mps[USB_SPEED_HIGH] = 512,
3223dc87e52SEdward Tomasz Napierala };
3233dc87e52SEdward Tomasz Napierala
3243dc87e52SEdward Tomasz Napierala static const struct usb_temp_endpoint_desc msc_bulk_in_ep = {
3253dc87e52SEdward Tomasz Napierala .pPacketSize = &msc_bulk_mps,
3263dc87e52SEdward Tomasz Napierala #ifdef USB_HIP_IN_EP_0
3273dc87e52SEdward Tomasz Napierala .bEndpointAddress = USB_HIP_IN_EP_0,
3283dc87e52SEdward Tomasz Napierala #else
3293dc87e52SEdward Tomasz Napierala .bEndpointAddress = UE_DIR_IN,
3303dc87e52SEdward Tomasz Napierala #endif
3313dc87e52SEdward Tomasz Napierala .bmAttributes = UE_BULK,
3323dc87e52SEdward Tomasz Napierala };
3333dc87e52SEdward Tomasz Napierala
3343dc87e52SEdward Tomasz Napierala static const struct usb_temp_endpoint_desc msc_bulk_out_ep = {
3353dc87e52SEdward Tomasz Napierala .pPacketSize = &msc_bulk_mps,
3363dc87e52SEdward Tomasz Napierala #ifdef USB_HIP_OUT_EP_0
3373dc87e52SEdward Tomasz Napierala .bEndpointAddress = USB_HIP_OUT_EP_0,
3383dc87e52SEdward Tomasz Napierala #else
3393dc87e52SEdward Tomasz Napierala .bEndpointAddress = UE_DIR_OUT,
3403dc87e52SEdward Tomasz Napierala #endif
3413dc87e52SEdward Tomasz Napierala .bmAttributes = UE_BULK,
3423dc87e52SEdward Tomasz Napierala };
3433dc87e52SEdward Tomasz Napierala
3443dc87e52SEdward Tomasz Napierala static const struct usb_temp_endpoint_desc *msc_data_endpoints[] = {
3453dc87e52SEdward Tomasz Napierala &msc_bulk_in_ep,
3463dc87e52SEdward Tomasz Napierala &msc_bulk_out_ep,
3473dc87e52SEdward Tomasz Napierala NULL,
3483dc87e52SEdward Tomasz Napierala };
3493dc87e52SEdward Tomasz Napierala
3503dc87e52SEdward Tomasz Napierala static const struct usb_temp_interface_desc msc_data_interface = {
3513dc87e52SEdward Tomasz Napierala .ppEndpoints = msc_data_endpoints,
3523dc87e52SEdward Tomasz Napierala .bInterfaceClass = UICLASS_MASS,
3533dc87e52SEdward Tomasz Napierala .bInterfaceSubClass = UISUBCLASS_SCSI,
3543dc87e52SEdward Tomasz Napierala .bInterfaceProtocol = UIPROTO_MASS_BBB,
3553dc87e52SEdward Tomasz Napierala .iInterface = MULTI_STORAGE_INDEX,
3563dc87e52SEdward Tomasz Napierala };
3573dc87e52SEdward Tomasz Napierala
3583dc87e52SEdward Tomasz Napierala static const struct usb_temp_interface_desc *multi_interfaces[] = {
3593dc87e52SEdward Tomasz Napierala &modem_iface_0,
3603dc87e52SEdward Tomasz Napierala &modem_iface_1,
3613dc87e52SEdward Tomasz Napierala ð_control_interface,
3623dc87e52SEdward Tomasz Napierala ð_data_null_interface,
3633dc87e52SEdward Tomasz Napierala ð_data_interface,
3643dc87e52SEdward Tomasz Napierala &msc_data_interface,
3653dc87e52SEdward Tomasz Napierala NULL,
3663dc87e52SEdward Tomasz Napierala };
3673dc87e52SEdward Tomasz Napierala
3683dc87e52SEdward Tomasz Napierala static const struct usb_temp_config_desc multi_config_desc = {
3693dc87e52SEdward Tomasz Napierala .ppIfaceDesc = multi_interfaces,
370d008c0d7SEdward Tomasz Napierala .bmAttributes = 0,
371d008c0d7SEdward Tomasz Napierala .bMaxPower = 0,
3723dc87e52SEdward Tomasz Napierala .iConfiguration = MULTI_CONFIGURATION_INDEX,
3733dc87e52SEdward Tomasz Napierala };
3743dc87e52SEdward Tomasz Napierala static const struct usb_temp_config_desc *multi_configs[] = {
3753dc87e52SEdward Tomasz Napierala &multi_config_desc,
3763dc87e52SEdward Tomasz Napierala NULL,
3773dc87e52SEdward Tomasz Napierala };
3783dc87e52SEdward Tomasz Napierala
3793dc87e52SEdward Tomasz Napierala struct usb_temp_device_desc usb_template_multi = {
3803dc87e52SEdward Tomasz Napierala .getStringDesc = &multi_get_string_desc,
3813dc87e52SEdward Tomasz Napierala .ppConfigDesc = multi_configs,
3821558eec6SEdward Tomasz Napierala .idVendor = MULTI_DEFAULT_VENDOR_ID,
3831558eec6SEdward Tomasz Napierala .idProduct = MULTI_DEFAULT_PRODUCT_ID,
3843dc87e52SEdward Tomasz Napierala .bcdDevice = 0x0100,
3853dc87e52SEdward Tomasz Napierala .bDeviceClass = UDCLASS_IN_INTERFACE,
3863dc87e52SEdward Tomasz Napierala .bDeviceSubClass = 0,
3873dc87e52SEdward Tomasz Napierala .bDeviceProtocol = 0,
3883dc87e52SEdward Tomasz Napierala .iManufacturer = MULTI_MANUFACTURER_INDEX,
3893dc87e52SEdward Tomasz Napierala .iProduct = MULTI_PRODUCT_INDEX,
3903dc87e52SEdward Tomasz Napierala .iSerialNumber = MULTI_SERIAL_NUMBER_INDEX,
3913dc87e52SEdward Tomasz Napierala };
3923dc87e52SEdward Tomasz Napierala
3933dc87e52SEdward Tomasz Napierala /*------------------------------------------------------------------------*
3943dc87e52SEdward Tomasz Napierala * multi_get_string_desc
3953dc87e52SEdward Tomasz Napierala *
3963dc87e52SEdward Tomasz Napierala * Return values:
3973dc87e52SEdward Tomasz Napierala * NULL: Failure. No such string.
3983dc87e52SEdward Tomasz Napierala * Else: Success. Pointer to string descriptor is returned.
3993dc87e52SEdward Tomasz Napierala *------------------------------------------------------------------------*/
4003dc87e52SEdward Tomasz Napierala static const void *
multi_get_string_desc(uint16_t lang_id,uint8_t string_index)4013dc87e52SEdward Tomasz Napierala multi_get_string_desc(uint16_t lang_id, uint8_t string_index)
4023dc87e52SEdward Tomasz Napierala {
4033dc87e52SEdward Tomasz Napierala static const void *ptr[MULTI_MAX_INDEX] = {
4043dc87e52SEdward Tomasz Napierala [MULTI_LANG_INDEX] = &usb_string_lang_en,
4053dc87e52SEdward Tomasz Napierala [MULTI_MODEM_INDEX] = &multi_modem,
4063dc87e52SEdward Tomasz Napierala [MULTI_ETH_MAC_INDEX] = &multi_eth_mac,
4073dc87e52SEdward Tomasz Napierala [MULTI_ETH_CONTROL_INDEX] = &multi_eth_control,
4083dc87e52SEdward Tomasz Napierala [MULTI_ETH_DATA_INDEX] = &multi_eth_data,
4093dc87e52SEdward Tomasz Napierala [MULTI_STORAGE_INDEX] = &multi_storage,
4103dc87e52SEdward Tomasz Napierala [MULTI_CONFIGURATION_INDEX] = &multi_configuration,
4113dc87e52SEdward Tomasz Napierala [MULTI_MANUFACTURER_INDEX] = &multi_manufacturer,
4123dc87e52SEdward Tomasz Napierala [MULTI_PRODUCT_INDEX] = &multi_product,
4133dc87e52SEdward Tomasz Napierala [MULTI_SERIAL_NUMBER_INDEX] = &multi_serial_number,
4143dc87e52SEdward Tomasz Napierala };
4153dc87e52SEdward Tomasz Napierala
4163dc87e52SEdward Tomasz Napierala if (string_index == 0) {
4173dc87e52SEdward Tomasz Napierala return (&usb_string_lang_en);
4183dc87e52SEdward Tomasz Napierala }
4193dc87e52SEdward Tomasz Napierala if (lang_id != 0x0409) {
4203dc87e52SEdward Tomasz Napierala return (NULL);
4213dc87e52SEdward Tomasz Napierala }
4223dc87e52SEdward Tomasz Napierala if (string_index < MULTI_MAX_INDEX) {
4233dc87e52SEdward Tomasz Napierala return (ptr[string_index]);
4243dc87e52SEdward Tomasz Napierala }
4253dc87e52SEdward Tomasz Napierala return (NULL);
4263dc87e52SEdward Tomasz Napierala }
4273dc87e52SEdward Tomasz Napierala
4283dc87e52SEdward Tomasz Napierala static void
multi_init(void * arg __unused)4293dc87e52SEdward Tomasz Napierala multi_init(void *arg __unused)
4303dc87e52SEdward Tomasz Napierala {
4313dc87e52SEdward Tomasz Napierala struct sysctl_oid *parent;
4323dc87e52SEdward Tomasz Napierala char parent_name[3];
4333dc87e52SEdward Tomasz Napierala
4343dc87e52SEdward Tomasz Napierala usb_make_str_desc(&multi_modem, sizeof(multi_modem),
4353dc87e52SEdward Tomasz Napierala MULTI_DEFAULT_MODEM);
4363dc87e52SEdward Tomasz Napierala usb_make_str_desc(&multi_eth_mac, sizeof(multi_eth_mac),
4373dc87e52SEdward Tomasz Napierala MULTI_DEFAULT_ETH_MAC);
4383dc87e52SEdward Tomasz Napierala usb_make_str_desc(&multi_eth_control, sizeof(multi_eth_control),
4393dc87e52SEdward Tomasz Napierala MULTI_DEFAULT_ETH_CONTROL);
4403dc87e52SEdward Tomasz Napierala usb_make_str_desc(&multi_eth_data, sizeof(multi_eth_data),
4413dc87e52SEdward Tomasz Napierala MULTI_DEFAULT_ETH_DATA);
4423dc87e52SEdward Tomasz Napierala usb_make_str_desc(&multi_storage, sizeof(multi_storage),
4433dc87e52SEdward Tomasz Napierala MULTI_DEFAULT_STORAGE);
4443dc87e52SEdward Tomasz Napierala usb_make_str_desc(&multi_configuration, sizeof(multi_configuration),
4453dc87e52SEdward Tomasz Napierala MULTI_DEFAULT_CONFIGURATION);
4463dc87e52SEdward Tomasz Napierala usb_make_str_desc(&multi_manufacturer, sizeof(multi_manufacturer),
4473dc87e52SEdward Tomasz Napierala MULTI_DEFAULT_MANUFACTURER);
4483dc87e52SEdward Tomasz Napierala usb_make_str_desc(&multi_product, sizeof(multi_product),
4493dc87e52SEdward Tomasz Napierala MULTI_DEFAULT_PRODUCT);
4503dc87e52SEdward Tomasz Napierala usb_make_str_desc(&multi_serial_number, sizeof(multi_serial_number),
4513dc87e52SEdward Tomasz Napierala MULTI_DEFAULT_SERIAL_NUMBER);
4523dc87e52SEdward Tomasz Napierala
4533dc87e52SEdward Tomasz Napierala snprintf(parent_name, sizeof(parent_name), "%d", USB_TEMP_MULTI);
4543dc87e52SEdward Tomasz Napierala sysctl_ctx_init(&multi_ctx_list);
4553dc87e52SEdward Tomasz Napierala
4563dc87e52SEdward Tomasz Napierala parent = SYSCTL_ADD_NODE(&multi_ctx_list,
4573dc87e52SEdward Tomasz Napierala SYSCTL_STATIC_CHILDREN(_hw_usb_templates), OID_AUTO,
458f8d2b1f3SPawel Biernacki parent_name, CTLFLAG_RW | CTLFLAG_MPSAFE,
4593dc87e52SEdward Tomasz Napierala 0, "USB Multifunction device side template");
4603dc87e52SEdward Tomasz Napierala SYSCTL_ADD_U16(&multi_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
4613dc87e52SEdward Tomasz Napierala "vendor_id", CTLFLAG_RWTUN,
4623dc87e52SEdward Tomasz Napierala &usb_template_multi.idVendor, 1, "Vendor identifier");
4633dc87e52SEdward Tomasz Napierala SYSCTL_ADD_U16(&multi_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
4643dc87e52SEdward Tomasz Napierala "product_id", CTLFLAG_RWTUN,
4653dc87e52SEdward Tomasz Napierala &usb_template_multi.idProduct, 1, "Product identifier");
4663dc87e52SEdward Tomasz Napierala SYSCTL_ADD_PROC(&multi_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
4673dc87e52SEdward Tomasz Napierala "eth_mac", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
4683dc87e52SEdward Tomasz Napierala &multi_eth_mac, sizeof(multi_eth_mac), usb_temp_sysctl,
4693dc87e52SEdward Tomasz Napierala "A", "Ethernet MAC address string");
4703dc87e52SEdward Tomasz Napierala #if 0
4713dc87e52SEdward Tomasz Napierala SYSCTL_ADD_PROC(&multi_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
4723dc87e52SEdward Tomasz Napierala "modem", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
4733dc87e52SEdward Tomasz Napierala &multi_modem, sizeof(multi_modem), usb_temp_sysctl,
4743dc87e52SEdward Tomasz Napierala "A", "Modem interface string");
4753dc87e52SEdward Tomasz Napierala SYSCTL_ADD_PROC(&multi_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
4763dc87e52SEdward Tomasz Napierala "eth_control", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
4773dc87e52SEdward Tomasz Napierala &multi_eth_control, sizeof(multi_eth_data), usb_temp_sysctl,
4783dc87e52SEdward Tomasz Napierala "A", "Ethernet control interface string");
4793dc87e52SEdward Tomasz Napierala SYSCTL_ADD_PROC(&multi_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
4803dc87e52SEdward Tomasz Napierala "eth_data", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
4813dc87e52SEdward Tomasz Napierala &multi_eth_data, sizeof(multi_eth_data), usb_temp_sysctl,
4823dc87e52SEdward Tomasz Napierala "A", "Ethernet data interface string");
4833dc87e52SEdward Tomasz Napierala SYSCTL_ADD_PROC(&multi_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
4843dc87e52SEdward Tomasz Napierala "interface", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
4853dc87e52SEdward Tomasz Napierala &multi_storage, sizeof(multi_storage), usb_temp_sysctl,
4863dc87e52SEdward Tomasz Napierala "A", "Storage interface string");
4873dc87e52SEdward Tomasz Napierala SYSCTL_ADD_PROC(&multi_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
4883dc87e52SEdward Tomasz Napierala "configuration", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
4893dc87e52SEdward Tomasz Napierala &multi_configuration, sizeof(multi_configuration), usb_temp_sysctl,
4903dc87e52SEdward Tomasz Napierala "A", "Configuration string");
4913dc87e52SEdward Tomasz Napierala #endif
4923dc87e52SEdward Tomasz Napierala SYSCTL_ADD_PROC(&multi_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
4933dc87e52SEdward Tomasz Napierala "manufacturer", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
4943dc87e52SEdward Tomasz Napierala &multi_manufacturer, sizeof(multi_manufacturer), usb_temp_sysctl,
4953dc87e52SEdward Tomasz Napierala "A", "Manufacturer string");
4963dc87e52SEdward Tomasz Napierala SYSCTL_ADD_PROC(&multi_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
4973dc87e52SEdward Tomasz Napierala "product", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
4983dc87e52SEdward Tomasz Napierala &multi_product, sizeof(multi_product), usb_temp_sysctl,
4993dc87e52SEdward Tomasz Napierala "A", "Product string");
5003dc87e52SEdward Tomasz Napierala SYSCTL_ADD_PROC(&multi_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
5013dc87e52SEdward Tomasz Napierala "serial_number", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
5023dc87e52SEdward Tomasz Napierala &multi_serial_number, sizeof(multi_serial_number), usb_temp_sysctl,
5033dc87e52SEdward Tomasz Napierala "A", "Serial number string");
5043dc87e52SEdward Tomasz Napierala }
5053dc87e52SEdward Tomasz Napierala
5063dc87e52SEdward Tomasz Napierala static void
multi_uninit(void * arg __unused)5073dc87e52SEdward Tomasz Napierala multi_uninit(void *arg __unused)
5083dc87e52SEdward Tomasz Napierala {
5093dc87e52SEdward Tomasz Napierala
5103dc87e52SEdward Tomasz Napierala sysctl_ctx_free(&multi_ctx_list);
5113dc87e52SEdward Tomasz Napierala }
5123dc87e52SEdward Tomasz Napierala
5133dc87e52SEdward Tomasz Napierala SYSINIT(multi_init, SI_SUB_LOCK, SI_ORDER_FIRST, multi_init, NULL);
5143dc87e52SEdward Tomasz Napierala SYSUNINIT(multi_uninit, SI_SUB_LOCK, SI_ORDER_FIRST, multi_uninit, NULL);
515