13e420a3eSRuslan Bukin /*- 242e42a9aSEdward Tomasz Napierala * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 342e42a9aSEdward Tomasz Napierala * 43e420a3eSRuslan Bukin * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com> 58e06491aSEdward Tomasz Napierala * Copyright (c) 2018 The FreeBSD Foundation 63e420a3eSRuslan Bukin * All rights reserved. 73e420a3eSRuslan Bukin * 83e420a3eSRuslan Bukin * This software was developed by SRI International and the University of 93e420a3eSRuslan Bukin * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) 103e420a3eSRuslan Bukin * ("CTSRD"), as part of the DARPA CRASH research programme. 113e420a3eSRuslan Bukin * 128e06491aSEdward Tomasz Napierala * Portions of this software were developed by Edward Tomasz Napierala 138e06491aSEdward Tomasz Napierala * under sponsorship from the FreeBSD Foundation. 148e06491aSEdward Tomasz Napierala * 153e420a3eSRuslan Bukin * Redistribution and use in source and binary forms, with or without 163e420a3eSRuslan Bukin * modification, are permitted provided that the following conditions 173e420a3eSRuslan Bukin * are met: 183e420a3eSRuslan Bukin * 1. Redistributions of source code must retain the above copyright 193e420a3eSRuslan Bukin * notice, this list of conditions and the following disclaimer. 203e420a3eSRuslan Bukin * 2. Redistributions in binary form must reproduce the above copyright 213e420a3eSRuslan Bukin * notice, this list of conditions and the following disclaimer in the 223e420a3eSRuslan Bukin * documentation and/or other materials provided with the distribution. 233e420a3eSRuslan Bukin * 243e420a3eSRuslan Bukin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 253e420a3eSRuslan Bukin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 263e420a3eSRuslan Bukin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 273e420a3eSRuslan Bukin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 283e420a3eSRuslan Bukin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 293e420a3eSRuslan Bukin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 303e420a3eSRuslan Bukin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 313e420a3eSRuslan Bukin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 323e420a3eSRuslan Bukin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 333e420a3eSRuslan Bukin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 343e420a3eSRuslan Bukin * SUCH DAMAGE. 353e420a3eSRuslan Bukin */ 363e420a3eSRuslan Bukin /* 373e420a3eSRuslan Bukin * This file contains the USB template for USB Networking and Serial 383e420a3eSRuslan Bukin */ 393e420a3eSRuslan Bukin 403e420a3eSRuslan Bukin #include <sys/cdefs.h> 413e420a3eSRuslan Bukin __FBSDID("$FreeBSD$"); 423e420a3eSRuslan Bukin 433e420a3eSRuslan Bukin #ifdef USB_GLOBAL_INCLUDE_FILE 443e420a3eSRuslan Bukin #include USB_GLOBAL_INCLUDE_FILE 453e420a3eSRuslan Bukin #else 463e420a3eSRuslan Bukin #include <sys/stdint.h> 473e420a3eSRuslan Bukin #include <sys/stddef.h> 483e420a3eSRuslan Bukin #include <sys/param.h> 493e420a3eSRuslan Bukin #include <sys/queue.h> 503e420a3eSRuslan Bukin #include <sys/types.h> 513e420a3eSRuslan Bukin #include <sys/systm.h> 523e420a3eSRuslan Bukin #include <sys/kernel.h> 533e420a3eSRuslan Bukin #include <sys/bus.h> 543e420a3eSRuslan Bukin #include <sys/module.h> 553e420a3eSRuslan Bukin #include <sys/lock.h> 563e420a3eSRuslan Bukin #include <sys/mutex.h> 573e420a3eSRuslan Bukin #include <sys/condvar.h> 583e420a3eSRuslan Bukin #include <sys/sysctl.h> 593e420a3eSRuslan Bukin #include <sys/sx.h> 603e420a3eSRuslan Bukin #include <sys/unistd.h> 613e420a3eSRuslan Bukin #include <sys/callout.h> 623e420a3eSRuslan Bukin #include <sys/malloc.h> 633e420a3eSRuslan Bukin #include <sys/priv.h> 643e420a3eSRuslan Bukin 653e420a3eSRuslan Bukin #include <dev/usb/usb.h> 663e420a3eSRuslan Bukin #include <dev/usb/usbdi.h> 673e420a3eSRuslan Bukin #include <dev/usb/usb_core.h> 683e420a3eSRuslan Bukin #include <dev/usb/usb_cdc.h> 698e06491aSEdward Tomasz Napierala #include <dev/usb/usb_ioctl.h> 708e06491aSEdward Tomasz Napierala #include <dev/usb/usb_util.h> 713e420a3eSRuslan Bukin 723e420a3eSRuslan Bukin #include <dev/usb/template/usb_template.h> 733e420a3eSRuslan Bukin #endif /* USB_GLOBAL_INCLUDE_FILE */ 743e420a3eSRuslan Bukin 753e420a3eSRuslan Bukin #define MODEM_IFACE_0 0 763e420a3eSRuslan Bukin #define MODEM_IFACE_1 1 773e420a3eSRuslan Bukin 783e420a3eSRuslan Bukin enum { 798e06491aSEdward Tomasz Napierala SERIALNET_LANG_INDEX, 808e06491aSEdward Tomasz Napierala SERIALNET_MODEM_INDEX, 818e06491aSEdward Tomasz Napierala SERIALNET_ETH_MAC_INDEX, 828e06491aSEdward Tomasz Napierala SERIALNET_ETH_CONTROL_INDEX, 838e06491aSEdward Tomasz Napierala SERIALNET_ETH_DATA_INDEX, 848e06491aSEdward Tomasz Napierala SERIALNET_CONFIGURATION_INDEX, 858e06491aSEdward Tomasz Napierala SERIALNET_MANUFACTURER_INDEX, 868e06491aSEdward Tomasz Napierala SERIALNET_PRODUCT_INDEX, 878e06491aSEdward Tomasz Napierala SERIALNET_SERIAL_NUMBER_INDEX, 888e06491aSEdward Tomasz Napierala SERIALNET_MAX_INDEX, 893e420a3eSRuslan Bukin }; 903e420a3eSRuslan Bukin 911558eec6SEdward Tomasz Napierala #define SERIALNET_DEFAULT_VENDOR_ID USB_TEMPLATE_VENDOR 92d01c1c8bSEdward Tomasz Napierala #define SERIALNET_DEFAULT_PRODUCT_ID 0x05dc 93ac4a7f30SEdward Tomasz Napierala #define SERIALNET_DEFAULT_MODEM "Virtual serial port" 948e06491aSEdward Tomasz Napierala #define SERIALNET_DEFAULT_ETH_MAC "2A02030405060789AB" 958e06491aSEdward Tomasz Napierala #define SERIALNET_DEFAULT_ETH_CONTROL "USB Ethernet Comm Interface" 968e06491aSEdward Tomasz Napierala #define SERIALNET_DEFAULT_ETH_DATA "USB Ethernet Data Interface" 978e06491aSEdward Tomasz Napierala #define SERIALNET_DEFAULT_CONFIGURATION "Default configuration" 98d01c1c8bSEdward Tomasz Napierala #define SERIALNET_DEFAULT_MANUFACTURER USB_TEMPLATE_MANUFACTURER 99ac4a7f30SEdward Tomasz Napierala #define SERIALNET_DEFAULT_PRODUCT "Serial/Ethernet device" 100733efc21SEdward Tomasz Napierala /* 101733efc21SEdward Tomasz Napierala * The reason for this being called like this is that OSX 102733efc21SEdward Tomasz Napierala * derives the device node name from it, resulting in a somewhat 103733efc21SEdward Tomasz Napierala * user-friendly "/dev/cu.usbmodemFreeBSD1". And yes, the "1" 104733efc21SEdward Tomasz Napierala * needs to be there, otherwise OSX will mangle it. 105733efc21SEdward Tomasz Napierala */ 106733efc21SEdward Tomasz Napierala #define SERIALNET_DEFAULT_SERIAL_NUMBER "FreeBSD1" 1073e420a3eSRuslan Bukin 1088e06491aSEdward Tomasz Napierala static struct usb_string_descriptor serialnet_modem; 1098e06491aSEdward Tomasz Napierala static struct usb_string_descriptor serialnet_eth_mac; 1108e06491aSEdward Tomasz Napierala static struct usb_string_descriptor serialnet_eth_control; 1118e06491aSEdward Tomasz Napierala static struct usb_string_descriptor serialnet_eth_data; 1128e06491aSEdward Tomasz Napierala static struct usb_string_descriptor serialnet_configuration; 1138e06491aSEdward Tomasz Napierala static struct usb_string_descriptor serialnet_manufacturer; 1148e06491aSEdward Tomasz Napierala static struct usb_string_descriptor serialnet_product; 1158e06491aSEdward Tomasz Napierala static struct usb_string_descriptor serialnet_serial_number; 1163e420a3eSRuslan Bukin 1178e06491aSEdward Tomasz Napierala static struct sysctl_ctx_list serialnet_ctx_list; 1183e420a3eSRuslan Bukin 1193e420a3eSRuslan Bukin /* prototypes */ 1203e420a3eSRuslan Bukin 1213e420a3eSRuslan Bukin static usb_temp_get_string_desc_t serialnet_get_string_desc; 1223e420a3eSRuslan Bukin 1233e420a3eSRuslan Bukin static const struct usb_cdc_union_descriptor eth_union_desc = { 1243e420a3eSRuslan Bukin .bLength = sizeof(eth_union_desc), 1253e420a3eSRuslan Bukin .bDescriptorType = UDESC_CS_INTERFACE, 1263e420a3eSRuslan Bukin .bDescriptorSubtype = UDESCSUB_CDC_UNION, 1273e420a3eSRuslan Bukin .bMasterInterface = 0, /* this is automatically updated */ 1283e420a3eSRuslan Bukin .bSlaveInterface[0] = 1, /* this is automatically updated */ 1293e420a3eSRuslan Bukin }; 1303e420a3eSRuslan Bukin 1313e420a3eSRuslan Bukin static const struct usb_cdc_header_descriptor eth_header_desc = { 1323e420a3eSRuslan Bukin .bLength = sizeof(eth_header_desc), 1333e420a3eSRuslan Bukin .bDescriptorType = UDESC_CS_INTERFACE, 1343e420a3eSRuslan Bukin .bDescriptorSubtype = UDESCSUB_CDC_HEADER, 1353e420a3eSRuslan Bukin .bcdCDC[0] = 0x10, 1363e420a3eSRuslan Bukin .bcdCDC[1] = 0x01, 1373e420a3eSRuslan Bukin }; 1383e420a3eSRuslan Bukin 1393e420a3eSRuslan Bukin static const struct usb_cdc_ethernet_descriptor eth_enf_desc = { 1403e420a3eSRuslan Bukin .bLength = sizeof(eth_enf_desc), 1413e420a3eSRuslan Bukin .bDescriptorType = UDESC_CS_INTERFACE, 1423e420a3eSRuslan Bukin .bDescriptorSubtype = UDESCSUB_CDC_ENF, 1438e06491aSEdward Tomasz Napierala .iMacAddress = SERIALNET_ETH_MAC_INDEX, 1443e420a3eSRuslan Bukin .bmEthernetStatistics = {0, 0, 0, 0}, 1453e420a3eSRuslan Bukin .wMaxSegmentSize = {0xEA, 0x05},/* 1514 bytes */ 1463e420a3eSRuslan Bukin .wNumberMCFilters = {0, 0}, 1473e420a3eSRuslan Bukin .bNumberPowerFilters = 0, 1483e420a3eSRuslan Bukin }; 1493e420a3eSRuslan Bukin 1503e420a3eSRuslan Bukin static const void *eth_control_if_desc[] = { 1513e420a3eSRuslan Bukin ð_union_desc, 1523e420a3eSRuslan Bukin ð_header_desc, 1533e420a3eSRuslan Bukin ð_enf_desc, 1543e420a3eSRuslan Bukin NULL, 1553e420a3eSRuslan Bukin }; 1563e420a3eSRuslan Bukin 1573e420a3eSRuslan Bukin static const struct usb_temp_packet_size bulk_mps = { 1583e420a3eSRuslan Bukin .mps[USB_SPEED_FULL] = 64, 1593e420a3eSRuslan Bukin .mps[USB_SPEED_HIGH] = 512, 1603e420a3eSRuslan Bukin }; 1613e420a3eSRuslan Bukin 1623e420a3eSRuslan Bukin static const struct usb_temp_packet_size intr_mps = { 1633e420a3eSRuslan Bukin .mps[USB_SPEED_FULL] = 8, 1643e420a3eSRuslan Bukin .mps[USB_SPEED_HIGH] = 8, 1653e420a3eSRuslan Bukin }; 1663e420a3eSRuslan Bukin 1673e420a3eSRuslan Bukin static const struct usb_temp_endpoint_desc bulk_in_ep = { 1683e420a3eSRuslan Bukin .pPacketSize = &bulk_mps, 1693e420a3eSRuslan Bukin #ifdef USB_HIP_IN_EP_0 1703e420a3eSRuslan Bukin .bEndpointAddress = USB_HIP_IN_EP_0, 1713e420a3eSRuslan Bukin #else 1723e420a3eSRuslan Bukin .bEndpointAddress = UE_DIR_IN, 1733e420a3eSRuslan Bukin #endif 1743e420a3eSRuslan Bukin .bmAttributes = UE_BULK, 1753e420a3eSRuslan Bukin }; 1763e420a3eSRuslan Bukin 1773e420a3eSRuslan Bukin static const struct usb_temp_endpoint_desc bulk_out_ep = { 1783e420a3eSRuslan Bukin .pPacketSize = &bulk_mps, 1793e420a3eSRuslan Bukin #ifdef USB_HIP_OUT_EP_0 1803e420a3eSRuslan Bukin .bEndpointAddress = USB_HIP_OUT_EP_0, 1813e420a3eSRuslan Bukin #else 1823e420a3eSRuslan Bukin .bEndpointAddress = UE_DIR_OUT, 1833e420a3eSRuslan Bukin #endif 1843e420a3eSRuslan Bukin .bmAttributes = UE_BULK, 1853e420a3eSRuslan Bukin }; 1863e420a3eSRuslan Bukin 1873e420a3eSRuslan Bukin static const struct usb_temp_endpoint_desc intr_in_ep = { 1883e420a3eSRuslan Bukin .pPacketSize = &intr_mps, 1893e420a3eSRuslan Bukin .bEndpointAddress = UE_DIR_IN, 1903e420a3eSRuslan Bukin .bmAttributes = UE_INTERRUPT, 1913e420a3eSRuslan Bukin }; 1923e420a3eSRuslan Bukin 1933e420a3eSRuslan Bukin static const struct usb_temp_endpoint_desc *eth_intr_endpoints[] = { 1943e420a3eSRuslan Bukin &intr_in_ep, 1953e420a3eSRuslan Bukin NULL, 1963e420a3eSRuslan Bukin }; 1973e420a3eSRuslan Bukin 1983e420a3eSRuslan Bukin static const struct usb_temp_interface_desc eth_control_interface = { 1993e420a3eSRuslan Bukin .ppEndpoints = eth_intr_endpoints, 2003e420a3eSRuslan Bukin .ppRawDesc = eth_control_if_desc, 2013e420a3eSRuslan Bukin .bInterfaceClass = UICLASS_CDC, 2023e420a3eSRuslan Bukin .bInterfaceSubClass = UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 2034ffeccf1SEdward Tomasz Napierala .bInterfaceProtocol = UIPROTO_CDC_NONE, 2048e06491aSEdward Tomasz Napierala .iInterface = SERIALNET_ETH_CONTROL_INDEX, 2053e420a3eSRuslan Bukin }; 2063e420a3eSRuslan Bukin 2073e420a3eSRuslan Bukin static const struct usb_temp_endpoint_desc *eth_data_endpoints[] = { 2083e420a3eSRuslan Bukin &bulk_in_ep, 2093e420a3eSRuslan Bukin &bulk_out_ep, 2103e420a3eSRuslan Bukin NULL, 2113e420a3eSRuslan Bukin }; 2123e420a3eSRuslan Bukin 2133e420a3eSRuslan Bukin static const struct usb_temp_interface_desc eth_data_null_interface = { 2143e420a3eSRuslan Bukin .ppEndpoints = NULL, /* no endpoints */ 2153e420a3eSRuslan Bukin .bInterfaceClass = UICLASS_CDC_DATA, 2164ffeccf1SEdward Tomasz Napierala .bInterfaceSubClass = UISUBCLASS_DATA, 2173e420a3eSRuslan Bukin .bInterfaceProtocol = 0, 2188e06491aSEdward Tomasz Napierala .iInterface = SERIALNET_ETH_DATA_INDEX, 2193e420a3eSRuslan Bukin }; 2203e420a3eSRuslan Bukin 2213e420a3eSRuslan Bukin static const struct usb_temp_interface_desc eth_data_interface = { 2223e420a3eSRuslan Bukin .ppEndpoints = eth_data_endpoints, 2233e420a3eSRuslan Bukin .bInterfaceClass = UICLASS_CDC_DATA, 2243e420a3eSRuslan Bukin .bInterfaceSubClass = UISUBCLASS_DATA, 2253e420a3eSRuslan Bukin .bInterfaceProtocol = 0, 2268e06491aSEdward Tomasz Napierala .iInterface = SERIALNET_ETH_DATA_INDEX, 2273e420a3eSRuslan Bukin .isAltInterface = 1, /* this is an alternate setting */ 2283e420a3eSRuslan Bukin }; 2293e420a3eSRuslan Bukin 2303e420a3eSRuslan Bukin static const struct usb_temp_packet_size modem_bulk_mps = { 2313e420a3eSRuslan Bukin .mps[USB_SPEED_LOW] = 8, 2323e420a3eSRuslan Bukin .mps[USB_SPEED_FULL] = 64, 2333e420a3eSRuslan Bukin .mps[USB_SPEED_HIGH] = 512, 2343e420a3eSRuslan Bukin }; 2353e420a3eSRuslan Bukin 2363e420a3eSRuslan Bukin static const struct usb_temp_packet_size modem_intr_mps = { 2373e420a3eSRuslan Bukin .mps[USB_SPEED_LOW] = 8, 2383e420a3eSRuslan Bukin .mps[USB_SPEED_FULL] = 8, 2393e420a3eSRuslan Bukin .mps[USB_SPEED_HIGH] = 8, 2403e420a3eSRuslan Bukin }; 2413e420a3eSRuslan Bukin 2423e420a3eSRuslan Bukin static const struct usb_temp_interval modem_intr_interval = { 2433e420a3eSRuslan Bukin .bInterval[USB_SPEED_LOW] = 8, /* 8ms */ 2443e420a3eSRuslan Bukin .bInterval[USB_SPEED_FULL] = 8, /* 8ms */ 2453e420a3eSRuslan Bukin .bInterval[USB_SPEED_HIGH] = 7, /* 8ms */ 2463e420a3eSRuslan Bukin }; 2473e420a3eSRuslan Bukin 2483e420a3eSRuslan Bukin static const struct usb_temp_endpoint_desc modem_ep_0 = { 2493e420a3eSRuslan Bukin .pPacketSize = &modem_intr_mps, 2503e420a3eSRuslan Bukin .pIntervals = &modem_intr_interval, 2513e420a3eSRuslan Bukin .bEndpointAddress = UE_DIR_IN, 2523e420a3eSRuslan Bukin .bmAttributes = UE_INTERRUPT, 2533e420a3eSRuslan Bukin }; 2543e420a3eSRuslan Bukin 2553e420a3eSRuslan Bukin static const struct usb_temp_endpoint_desc modem_ep_1 = { 2563e420a3eSRuslan Bukin .pPacketSize = &modem_bulk_mps, 2573e420a3eSRuslan Bukin .bEndpointAddress = UE_DIR_OUT, 2583e420a3eSRuslan Bukin .bmAttributes = UE_BULK, 2593e420a3eSRuslan Bukin }; 2603e420a3eSRuslan Bukin 2613e420a3eSRuslan Bukin static const struct usb_temp_endpoint_desc modem_ep_2 = { 2623e420a3eSRuslan Bukin .pPacketSize = &modem_bulk_mps, 2633e420a3eSRuslan Bukin .bEndpointAddress = UE_DIR_IN, 2643e420a3eSRuslan Bukin .bmAttributes = UE_BULK, 2653e420a3eSRuslan Bukin }; 2663e420a3eSRuslan Bukin 2673e420a3eSRuslan Bukin static const struct usb_temp_endpoint_desc *modem_iface_0_ep[] = { 2683e420a3eSRuslan Bukin &modem_ep_0, 2693e420a3eSRuslan Bukin NULL, 2703e420a3eSRuslan Bukin }; 2713e420a3eSRuslan Bukin 2723e420a3eSRuslan Bukin static const struct usb_temp_endpoint_desc *modem_iface_1_ep[] = { 2733e420a3eSRuslan Bukin &modem_ep_1, 2743e420a3eSRuslan Bukin &modem_ep_2, 2753e420a3eSRuslan Bukin NULL, 2763e420a3eSRuslan Bukin }; 2773e420a3eSRuslan Bukin 2783e420a3eSRuslan Bukin static const uint8_t modem_raw_desc_0[] = { 2793e420a3eSRuslan Bukin 0x05, 0x24, 0x00, 0x10, 0x01 2803e420a3eSRuslan Bukin }; 2813e420a3eSRuslan Bukin 2823e420a3eSRuslan Bukin static const uint8_t modem_raw_desc_1[] = { 2833e420a3eSRuslan Bukin 0x05, 0x24, 0x06, MODEM_IFACE_0, MODEM_IFACE_1 2843e420a3eSRuslan Bukin }; 2853e420a3eSRuslan Bukin 2863e420a3eSRuslan Bukin static const uint8_t modem_raw_desc_2[] = { 2873e420a3eSRuslan Bukin 0x05, 0x24, 0x01, 0x03, MODEM_IFACE_1 2883e420a3eSRuslan Bukin }; 2893e420a3eSRuslan Bukin 2903e420a3eSRuslan Bukin static const uint8_t modem_raw_desc_3[] = { 2913e420a3eSRuslan Bukin 0x04, 0x24, 0x02, 0x07 2923e420a3eSRuslan Bukin }; 2933e420a3eSRuslan Bukin 2943e420a3eSRuslan Bukin static const void *modem_iface_0_desc[] = { 2953e420a3eSRuslan Bukin &modem_raw_desc_0, 2963e420a3eSRuslan Bukin &modem_raw_desc_1, 2973e420a3eSRuslan Bukin &modem_raw_desc_2, 2983e420a3eSRuslan Bukin &modem_raw_desc_3, 2993e420a3eSRuslan Bukin NULL, 3003e420a3eSRuslan Bukin }; 3013e420a3eSRuslan Bukin 3023e420a3eSRuslan Bukin static const struct usb_temp_interface_desc modem_iface_0 = { 3033e420a3eSRuslan Bukin .ppRawDesc = modem_iface_0_desc, 3043e420a3eSRuslan Bukin .ppEndpoints = modem_iface_0_ep, 3054ffeccf1SEdward Tomasz Napierala .bInterfaceClass = UICLASS_CDC, 3064ffeccf1SEdward Tomasz Napierala .bInterfaceSubClass = UISUBCLASS_ABSTRACT_CONTROL_MODEL, 3076b7e508cSEdward Tomasz Napierala .bInterfaceProtocol = UIPROTO_CDC_NONE, 3088e06491aSEdward Tomasz Napierala .iInterface = SERIALNET_MODEM_INDEX, 3093e420a3eSRuslan Bukin }; 3103e420a3eSRuslan Bukin 3113e420a3eSRuslan Bukin static const struct usb_temp_interface_desc modem_iface_1 = { 3123e420a3eSRuslan Bukin .ppEndpoints = modem_iface_1_ep, 3134ffeccf1SEdward Tomasz Napierala .bInterfaceClass = UICLASS_CDC_DATA, 3144ffeccf1SEdward Tomasz Napierala .bInterfaceSubClass = UISUBCLASS_DATA, 3153e420a3eSRuslan Bukin .bInterfaceProtocol = 0, 3168e06491aSEdward Tomasz Napierala .iInterface = SERIALNET_MODEM_INDEX, 3173e420a3eSRuslan Bukin }; 3183e420a3eSRuslan Bukin 3193e420a3eSRuslan Bukin static const struct usb_temp_interface_desc *serialnet_interfaces[] = { 3203e420a3eSRuslan Bukin &modem_iface_0, 3213e420a3eSRuslan Bukin &modem_iface_1, 3223e420a3eSRuslan Bukin ð_control_interface, 3233e420a3eSRuslan Bukin ð_data_null_interface, 3243e420a3eSRuslan Bukin ð_data_interface, 3253e420a3eSRuslan Bukin NULL, 3263e420a3eSRuslan Bukin }; 3273e420a3eSRuslan Bukin 3283e420a3eSRuslan Bukin static const struct usb_temp_config_desc serialnet_config_desc = { 3293e420a3eSRuslan Bukin .ppIfaceDesc = serialnet_interfaces, 330*d008c0d7SEdward Tomasz Napierala .bmAttributes = 0, 331*d008c0d7SEdward Tomasz Napierala .bMaxPower = 0, 3328e06491aSEdward Tomasz Napierala .iConfiguration = SERIALNET_CONFIGURATION_INDEX, 3333e420a3eSRuslan Bukin }; 3343e420a3eSRuslan Bukin static const struct usb_temp_config_desc *serialnet_configs[] = { 3353e420a3eSRuslan Bukin &serialnet_config_desc, 3363e420a3eSRuslan Bukin NULL, 3373e420a3eSRuslan Bukin }; 3383e420a3eSRuslan Bukin 3398e06491aSEdward Tomasz Napierala struct usb_temp_device_desc usb_template_serialnet = { 3403e420a3eSRuslan Bukin .getStringDesc = &serialnet_get_string_desc, 3413e420a3eSRuslan Bukin .ppConfigDesc = serialnet_configs, 3421558eec6SEdward Tomasz Napierala .idVendor = SERIALNET_DEFAULT_VENDOR_ID, 3431558eec6SEdward Tomasz Napierala .idProduct = SERIALNET_DEFAULT_PRODUCT_ID, 3443e420a3eSRuslan Bukin .bcdDevice = 0x0100, 3453e420a3eSRuslan Bukin .bDeviceClass = UDCLASS_COMM, 3463e420a3eSRuslan Bukin .bDeviceSubClass = 0, 3473e420a3eSRuslan Bukin .bDeviceProtocol = 0, 3488e06491aSEdward Tomasz Napierala .iManufacturer = SERIALNET_MANUFACTURER_INDEX, 3498e06491aSEdward Tomasz Napierala .iProduct = SERIALNET_PRODUCT_INDEX, 3508e06491aSEdward Tomasz Napierala .iSerialNumber = SERIALNET_SERIAL_NUMBER_INDEX, 3513e420a3eSRuslan Bukin }; 3523e420a3eSRuslan Bukin 3533e420a3eSRuslan Bukin /*------------------------------------------------------------------------* 3543e420a3eSRuslan Bukin * serialnet_get_string_desc 3553e420a3eSRuslan Bukin * 3563e420a3eSRuslan Bukin * Return values: 3573e420a3eSRuslan Bukin * NULL: Failure. No such string. 3583e420a3eSRuslan Bukin * Else: Success. Pointer to string descriptor is returned. 3593e420a3eSRuslan Bukin *------------------------------------------------------------------------*/ 3603e420a3eSRuslan Bukin static const void * 3613e420a3eSRuslan Bukin serialnet_get_string_desc(uint16_t lang_id, uint8_t string_index) 3623e420a3eSRuslan Bukin { 3638e06491aSEdward Tomasz Napierala static const void *ptr[SERIALNET_MAX_INDEX] = { 3648e06491aSEdward Tomasz Napierala [SERIALNET_LANG_INDEX] = &usb_string_lang_en, 3658e06491aSEdward Tomasz Napierala [SERIALNET_MODEM_INDEX] = &serialnet_modem, 3668e06491aSEdward Tomasz Napierala [SERIALNET_ETH_MAC_INDEX] = &serialnet_eth_mac, 3678e06491aSEdward Tomasz Napierala [SERIALNET_ETH_CONTROL_INDEX] = &serialnet_eth_control, 3688e06491aSEdward Tomasz Napierala [SERIALNET_ETH_DATA_INDEX] = &serialnet_eth_data, 3698e06491aSEdward Tomasz Napierala [SERIALNET_CONFIGURATION_INDEX] = &serialnet_configuration, 3708e06491aSEdward Tomasz Napierala [SERIALNET_MANUFACTURER_INDEX] = &serialnet_manufacturer, 3718e06491aSEdward Tomasz Napierala [SERIALNET_PRODUCT_INDEX] = &serialnet_product, 3728e06491aSEdward Tomasz Napierala [SERIALNET_SERIAL_NUMBER_INDEX] = &serialnet_serial_number, 3733e420a3eSRuslan Bukin }; 3743e420a3eSRuslan Bukin 3753e420a3eSRuslan Bukin if (string_index == 0) { 3763e420a3eSRuslan Bukin return (&usb_string_lang_en); 3773e420a3eSRuslan Bukin } 3783e420a3eSRuslan Bukin if (lang_id != 0x0409) { 3793e420a3eSRuslan Bukin return (NULL); 3803e420a3eSRuslan Bukin } 3818e06491aSEdward Tomasz Napierala if (string_index < SERIALNET_MAX_INDEX) { 3823e420a3eSRuslan Bukin return (ptr[string_index]); 3833e420a3eSRuslan Bukin } 3843e420a3eSRuslan Bukin return (NULL); 3853e420a3eSRuslan Bukin } 3868e06491aSEdward Tomasz Napierala 3878e06491aSEdward Tomasz Napierala static void 3888e06491aSEdward Tomasz Napierala serialnet_init(void *arg __unused) 3898e06491aSEdward Tomasz Napierala { 3908e06491aSEdward Tomasz Napierala struct sysctl_oid *parent; 3918e06491aSEdward Tomasz Napierala char parent_name[3]; 3928e06491aSEdward Tomasz Napierala 3938e06491aSEdward Tomasz Napierala usb_make_str_desc(&serialnet_modem, sizeof(serialnet_modem), 3948e06491aSEdward Tomasz Napierala SERIALNET_DEFAULT_MODEM); 3958e06491aSEdward Tomasz Napierala usb_make_str_desc(&serialnet_eth_mac, sizeof(serialnet_eth_mac), 3968e06491aSEdward Tomasz Napierala SERIALNET_DEFAULT_ETH_MAC); 3978e06491aSEdward Tomasz Napierala usb_make_str_desc(&serialnet_eth_control, sizeof(serialnet_eth_control), 3988e06491aSEdward Tomasz Napierala SERIALNET_DEFAULT_ETH_CONTROL); 3998e06491aSEdward Tomasz Napierala usb_make_str_desc(&serialnet_eth_data, sizeof(serialnet_eth_data), 4008e06491aSEdward Tomasz Napierala SERIALNET_DEFAULT_ETH_DATA); 4018e06491aSEdward Tomasz Napierala usb_make_str_desc(&serialnet_configuration, sizeof(serialnet_configuration), 4028e06491aSEdward Tomasz Napierala SERIALNET_DEFAULT_CONFIGURATION); 4038e06491aSEdward Tomasz Napierala usb_make_str_desc(&serialnet_manufacturer, sizeof(serialnet_manufacturer), 4048e06491aSEdward Tomasz Napierala SERIALNET_DEFAULT_MANUFACTURER); 4058e06491aSEdward Tomasz Napierala usb_make_str_desc(&serialnet_product, sizeof(serialnet_product), 4068e06491aSEdward Tomasz Napierala SERIALNET_DEFAULT_PRODUCT); 4078e06491aSEdward Tomasz Napierala usb_make_str_desc(&serialnet_serial_number, sizeof(serialnet_serial_number), 4088e06491aSEdward Tomasz Napierala SERIALNET_DEFAULT_SERIAL_NUMBER); 4098e06491aSEdward Tomasz Napierala 4108e06491aSEdward Tomasz Napierala snprintf(parent_name, sizeof(parent_name), "%d", USB_TEMP_SERIALNET); 4118e06491aSEdward Tomasz Napierala sysctl_ctx_init(&serialnet_ctx_list); 4128e06491aSEdward Tomasz Napierala 4138e06491aSEdward Tomasz Napierala parent = SYSCTL_ADD_NODE(&serialnet_ctx_list, 4148e06491aSEdward Tomasz Napierala SYSCTL_STATIC_CHILDREN(_hw_usb_templates), OID_AUTO, 4158e06491aSEdward Tomasz Napierala parent_name, CTLFLAG_RW, 4164e6e77b7SEdward Tomasz Napierala 0, "USB CDC Serial/Ethernet device side template"); 4178e06491aSEdward Tomasz Napierala SYSCTL_ADD_U16(&serialnet_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 4188e06491aSEdward Tomasz Napierala "vendor_id", CTLFLAG_RWTUN, 4198e06491aSEdward Tomasz Napierala &usb_template_serialnet.idVendor, 1, "Vendor identifier"); 4208e06491aSEdward Tomasz Napierala SYSCTL_ADD_U16(&serialnet_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 4218e06491aSEdward Tomasz Napierala "product_id", CTLFLAG_RWTUN, 4228e06491aSEdward Tomasz Napierala &usb_template_serialnet.idProduct, 1, "Product identifier"); 4238e06491aSEdward Tomasz Napierala SYSCTL_ADD_PROC(&serialnet_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 4248e06491aSEdward Tomasz Napierala "eth_mac", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 4258e06491aSEdward Tomasz Napierala &serialnet_eth_mac, sizeof(serialnet_eth_mac), usb_temp_sysctl, 4268e06491aSEdward Tomasz Napierala "A", "Ethernet MAC address string"); 4278e06491aSEdward Tomasz Napierala #if 0 4288e06491aSEdward Tomasz Napierala SYSCTL_ADD_PROC(&serialnet_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 4298e06491aSEdward Tomasz Napierala "modem", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 4308e06491aSEdward Tomasz Napierala &serialnet_modem, sizeof(serialnet_modem), usb_temp_sysctl, 4318e06491aSEdward Tomasz Napierala "A", "Modem interface string"); 4328e06491aSEdward Tomasz Napierala SYSCTL_ADD_PROC(&serialnet_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 4338e06491aSEdward Tomasz Napierala "eth_control", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 4348e06491aSEdward Tomasz Napierala &serialnet_eth_control, sizeof(serialnet_eth_data), usb_temp_sysctl, 4358e06491aSEdward Tomasz Napierala "A", "Ethernet control interface string"); 4368e06491aSEdward Tomasz Napierala SYSCTL_ADD_PROC(&serialnet_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 4378e06491aSEdward Tomasz Napierala "eth_data", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 4388e06491aSEdward Tomasz Napierala &serialnet_eth_data, sizeof(serialnet_eth_data), usb_temp_sysctl, 4398e06491aSEdward Tomasz Napierala "A", "Ethernet data interface string"); 4408e06491aSEdward Tomasz Napierala SYSCTL_ADD_PROC(&serialnet_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 4418e06491aSEdward Tomasz Napierala "configuration", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 4428e06491aSEdward Tomasz Napierala &serialnet_configuration, sizeof(serialnet_configuration), usb_temp_sysctl, 4438e06491aSEdward Tomasz Napierala "A", "Configuration string"); 4448e06491aSEdward Tomasz Napierala #endif 4458e06491aSEdward Tomasz Napierala SYSCTL_ADD_PROC(&serialnet_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 4468e06491aSEdward Tomasz Napierala "manufacturer", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 4478e06491aSEdward Tomasz Napierala &serialnet_manufacturer, sizeof(serialnet_manufacturer), usb_temp_sysctl, 4488e06491aSEdward Tomasz Napierala "A", "Manufacturer string"); 4498e06491aSEdward Tomasz Napierala SYSCTL_ADD_PROC(&serialnet_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 4508e06491aSEdward Tomasz Napierala "product", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 4518e06491aSEdward Tomasz Napierala &serialnet_product, sizeof(serialnet_product), usb_temp_sysctl, 4528e06491aSEdward Tomasz Napierala "A", "Product string"); 4538e06491aSEdward Tomasz Napierala SYSCTL_ADD_PROC(&serialnet_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 4548e06491aSEdward Tomasz Napierala "serial_number", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 4558e06491aSEdward Tomasz Napierala &serialnet_serial_number, sizeof(serialnet_serial_number), usb_temp_sysctl, 4568e06491aSEdward Tomasz Napierala "A", "Serial number string"); 4578e06491aSEdward Tomasz Napierala } 4588e06491aSEdward Tomasz Napierala 4598e06491aSEdward Tomasz Napierala static void 4608e06491aSEdward Tomasz Napierala serialnet_uninit(void *arg __unused) 4618e06491aSEdward Tomasz Napierala { 4628e06491aSEdward Tomasz Napierala 4638e06491aSEdward Tomasz Napierala sysctl_ctx_free(&serialnet_ctx_list); 4648e06491aSEdward Tomasz Napierala } 4658e06491aSEdward Tomasz Napierala 4668e06491aSEdward Tomasz Napierala SYSINIT(serialnet_init, SI_SUB_LOCK, SI_ORDER_FIRST, serialnet_init, NULL); 467c70e38e4SHans Petter Selasky SYSUNINIT(serialnet_uninit, SI_SUB_LOCK, SI_ORDER_FIRST, serialnet_uninit, NULL); 468