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 918e06491aSEdward Tomasz Napierala #define SERIALNET_DEFAULT_MODEM "USB Modem Interface" 928e06491aSEdward Tomasz Napierala #define SERIALNET_DEFAULT_ETH_MAC "2A02030405060789AB" 938e06491aSEdward Tomasz Napierala #define SERIALNET_DEFAULT_ETH_CONTROL "USB Ethernet Comm Interface" 948e06491aSEdward Tomasz Napierala #define SERIALNET_DEFAULT_ETH_DATA "USB Ethernet Data Interface" 958e06491aSEdward Tomasz Napierala #define SERIALNET_DEFAULT_CONFIGURATION "Default configuration" 968e06491aSEdward Tomasz Napierala #define SERIALNET_DEFAULT_MANUFACTURER "The FreeBSD Project" 978e06491aSEdward Tomasz Napierala #define SERIALNET_DEFAULT_PRODUCT "SERIALNET" 988e06491aSEdward Tomasz Napierala #define SERIALNET_DEFAULT_SERIAL_NUMBER "January 2015" 993e420a3eSRuslan Bukin 1008e06491aSEdward Tomasz Napierala static struct usb_string_descriptor serialnet_modem; 1018e06491aSEdward Tomasz Napierala static struct usb_string_descriptor serialnet_eth_mac; 1028e06491aSEdward Tomasz Napierala static struct usb_string_descriptor serialnet_eth_control; 1038e06491aSEdward Tomasz Napierala static struct usb_string_descriptor serialnet_eth_data; 1048e06491aSEdward Tomasz Napierala static struct usb_string_descriptor serialnet_configuration; 1058e06491aSEdward Tomasz Napierala static struct usb_string_descriptor serialnet_manufacturer; 1068e06491aSEdward Tomasz Napierala static struct usb_string_descriptor serialnet_product; 1078e06491aSEdward Tomasz Napierala static struct usb_string_descriptor serialnet_serial_number; 1083e420a3eSRuslan Bukin 1098e06491aSEdward Tomasz Napierala static struct sysctl_ctx_list serialnet_ctx_list; 1103e420a3eSRuslan Bukin 1113e420a3eSRuslan Bukin /* prototypes */ 1123e420a3eSRuslan Bukin 1133e420a3eSRuslan Bukin static usb_temp_get_string_desc_t serialnet_get_string_desc; 1143e420a3eSRuslan Bukin 1153e420a3eSRuslan Bukin static const struct usb_cdc_union_descriptor eth_union_desc = { 1163e420a3eSRuslan Bukin .bLength = sizeof(eth_union_desc), 1173e420a3eSRuslan Bukin .bDescriptorType = UDESC_CS_INTERFACE, 1183e420a3eSRuslan Bukin .bDescriptorSubtype = UDESCSUB_CDC_UNION, 1193e420a3eSRuslan Bukin .bMasterInterface = 0, /* this is automatically updated */ 1203e420a3eSRuslan Bukin .bSlaveInterface[0] = 1, /* this is automatically updated */ 1213e420a3eSRuslan Bukin }; 1223e420a3eSRuslan Bukin 1233e420a3eSRuslan Bukin static const struct usb_cdc_header_descriptor eth_header_desc = { 1243e420a3eSRuslan Bukin .bLength = sizeof(eth_header_desc), 1253e420a3eSRuslan Bukin .bDescriptorType = UDESC_CS_INTERFACE, 1263e420a3eSRuslan Bukin .bDescriptorSubtype = UDESCSUB_CDC_HEADER, 1273e420a3eSRuslan Bukin .bcdCDC[0] = 0x10, 1283e420a3eSRuslan Bukin .bcdCDC[1] = 0x01, 1293e420a3eSRuslan Bukin }; 1303e420a3eSRuslan Bukin 1313e420a3eSRuslan Bukin static const struct usb_cdc_ethernet_descriptor eth_enf_desc = { 1323e420a3eSRuslan Bukin .bLength = sizeof(eth_enf_desc), 1333e420a3eSRuslan Bukin .bDescriptorType = UDESC_CS_INTERFACE, 1343e420a3eSRuslan Bukin .bDescriptorSubtype = UDESCSUB_CDC_ENF, 1358e06491aSEdward Tomasz Napierala .iMacAddress = SERIALNET_ETH_MAC_INDEX, 1363e420a3eSRuslan Bukin .bmEthernetStatistics = {0, 0, 0, 0}, 1373e420a3eSRuslan Bukin .wMaxSegmentSize = {0xEA, 0x05},/* 1514 bytes */ 1383e420a3eSRuslan Bukin .wNumberMCFilters = {0, 0}, 1393e420a3eSRuslan Bukin .bNumberPowerFilters = 0, 1403e420a3eSRuslan Bukin }; 1413e420a3eSRuslan Bukin 1423e420a3eSRuslan Bukin static const void *eth_control_if_desc[] = { 1433e420a3eSRuslan Bukin ð_union_desc, 1443e420a3eSRuslan Bukin ð_header_desc, 1453e420a3eSRuslan Bukin ð_enf_desc, 1463e420a3eSRuslan Bukin NULL, 1473e420a3eSRuslan Bukin }; 1483e420a3eSRuslan Bukin 1493e420a3eSRuslan Bukin static const struct usb_temp_packet_size bulk_mps = { 1503e420a3eSRuslan Bukin .mps[USB_SPEED_FULL] = 64, 1513e420a3eSRuslan Bukin .mps[USB_SPEED_HIGH] = 512, 1523e420a3eSRuslan Bukin }; 1533e420a3eSRuslan Bukin 1543e420a3eSRuslan Bukin static const struct usb_temp_packet_size intr_mps = { 1553e420a3eSRuslan Bukin .mps[USB_SPEED_FULL] = 8, 1563e420a3eSRuslan Bukin .mps[USB_SPEED_HIGH] = 8, 1573e420a3eSRuslan Bukin }; 1583e420a3eSRuslan Bukin 1593e420a3eSRuslan Bukin static const struct usb_temp_endpoint_desc bulk_in_ep = { 1603e420a3eSRuslan Bukin .pPacketSize = &bulk_mps, 1613e420a3eSRuslan Bukin #ifdef USB_HIP_IN_EP_0 1623e420a3eSRuslan Bukin .bEndpointAddress = USB_HIP_IN_EP_0, 1633e420a3eSRuslan Bukin #else 1643e420a3eSRuslan Bukin .bEndpointAddress = UE_DIR_IN, 1653e420a3eSRuslan Bukin #endif 1663e420a3eSRuslan Bukin .bmAttributes = UE_BULK, 1673e420a3eSRuslan Bukin }; 1683e420a3eSRuslan Bukin 1693e420a3eSRuslan Bukin static const struct usb_temp_endpoint_desc bulk_out_ep = { 1703e420a3eSRuslan Bukin .pPacketSize = &bulk_mps, 1713e420a3eSRuslan Bukin #ifdef USB_HIP_OUT_EP_0 1723e420a3eSRuslan Bukin .bEndpointAddress = USB_HIP_OUT_EP_0, 1733e420a3eSRuslan Bukin #else 1743e420a3eSRuslan Bukin .bEndpointAddress = UE_DIR_OUT, 1753e420a3eSRuslan Bukin #endif 1763e420a3eSRuslan Bukin .bmAttributes = UE_BULK, 1773e420a3eSRuslan Bukin }; 1783e420a3eSRuslan Bukin 1793e420a3eSRuslan Bukin static const struct usb_temp_endpoint_desc intr_in_ep = { 1803e420a3eSRuslan Bukin .pPacketSize = &intr_mps, 1813e420a3eSRuslan Bukin .bEndpointAddress = UE_DIR_IN, 1823e420a3eSRuslan Bukin .bmAttributes = UE_INTERRUPT, 1833e420a3eSRuslan Bukin }; 1843e420a3eSRuslan Bukin 1853e420a3eSRuslan Bukin static const struct usb_temp_endpoint_desc *eth_intr_endpoints[] = { 1863e420a3eSRuslan Bukin &intr_in_ep, 1873e420a3eSRuslan Bukin NULL, 1883e420a3eSRuslan Bukin }; 1893e420a3eSRuslan Bukin 1903e420a3eSRuslan Bukin static const struct usb_temp_interface_desc eth_control_interface = { 1913e420a3eSRuslan Bukin .ppEndpoints = eth_intr_endpoints, 1923e420a3eSRuslan Bukin .ppRawDesc = eth_control_if_desc, 1933e420a3eSRuslan Bukin .bInterfaceClass = UICLASS_CDC, 1943e420a3eSRuslan Bukin .bInterfaceSubClass = UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 1954ffeccf1SEdward Tomasz Napierala .bInterfaceProtocol = UIPROTO_CDC_NONE, 1968e06491aSEdward Tomasz Napierala .iInterface = SERIALNET_ETH_CONTROL_INDEX, 1973e420a3eSRuslan Bukin }; 1983e420a3eSRuslan Bukin 1993e420a3eSRuslan Bukin static const struct usb_temp_endpoint_desc *eth_data_endpoints[] = { 2003e420a3eSRuslan Bukin &bulk_in_ep, 2013e420a3eSRuslan Bukin &bulk_out_ep, 2023e420a3eSRuslan Bukin NULL, 2033e420a3eSRuslan Bukin }; 2043e420a3eSRuslan Bukin 2053e420a3eSRuslan Bukin static const struct usb_temp_interface_desc eth_data_null_interface = { 2063e420a3eSRuslan Bukin .ppEndpoints = NULL, /* no endpoints */ 2073e420a3eSRuslan Bukin .bInterfaceClass = UICLASS_CDC_DATA, 2084ffeccf1SEdward Tomasz Napierala .bInterfaceSubClass = UISUBCLASS_DATA, 2093e420a3eSRuslan Bukin .bInterfaceProtocol = 0, 2108e06491aSEdward Tomasz Napierala .iInterface = SERIALNET_ETH_DATA_INDEX, 2113e420a3eSRuslan Bukin }; 2123e420a3eSRuslan Bukin 2133e420a3eSRuslan Bukin static const struct usb_temp_interface_desc eth_data_interface = { 2143e420a3eSRuslan Bukin .ppEndpoints = eth_data_endpoints, 2153e420a3eSRuslan Bukin .bInterfaceClass = UICLASS_CDC_DATA, 2163e420a3eSRuslan Bukin .bInterfaceSubClass = UISUBCLASS_DATA, 2173e420a3eSRuslan Bukin .bInterfaceProtocol = 0, 2188e06491aSEdward Tomasz Napierala .iInterface = SERIALNET_ETH_DATA_INDEX, 2193e420a3eSRuslan Bukin .isAltInterface = 1, /* this is an alternate setting */ 2203e420a3eSRuslan Bukin }; 2213e420a3eSRuslan Bukin 2223e420a3eSRuslan Bukin static const struct usb_temp_packet_size modem_bulk_mps = { 2233e420a3eSRuslan Bukin .mps[USB_SPEED_LOW] = 8, 2243e420a3eSRuslan Bukin .mps[USB_SPEED_FULL] = 64, 2253e420a3eSRuslan Bukin .mps[USB_SPEED_HIGH] = 512, 2263e420a3eSRuslan Bukin }; 2273e420a3eSRuslan Bukin 2283e420a3eSRuslan Bukin static const struct usb_temp_packet_size modem_intr_mps = { 2293e420a3eSRuslan Bukin .mps[USB_SPEED_LOW] = 8, 2303e420a3eSRuslan Bukin .mps[USB_SPEED_FULL] = 8, 2313e420a3eSRuslan Bukin .mps[USB_SPEED_HIGH] = 8, 2323e420a3eSRuslan Bukin }; 2333e420a3eSRuslan Bukin 2343e420a3eSRuslan Bukin static const struct usb_temp_interval modem_intr_interval = { 2353e420a3eSRuslan Bukin .bInterval[USB_SPEED_LOW] = 8, /* 8ms */ 2363e420a3eSRuslan Bukin .bInterval[USB_SPEED_FULL] = 8, /* 8ms */ 2373e420a3eSRuslan Bukin .bInterval[USB_SPEED_HIGH] = 7, /* 8ms */ 2383e420a3eSRuslan Bukin }; 2393e420a3eSRuslan Bukin 2403e420a3eSRuslan Bukin static const struct usb_temp_endpoint_desc modem_ep_0 = { 2413e420a3eSRuslan Bukin .pPacketSize = &modem_intr_mps, 2423e420a3eSRuslan Bukin .pIntervals = &modem_intr_interval, 2433e420a3eSRuslan Bukin .bEndpointAddress = UE_DIR_IN, 2443e420a3eSRuslan Bukin .bmAttributes = UE_INTERRUPT, 2453e420a3eSRuslan Bukin }; 2463e420a3eSRuslan Bukin 2473e420a3eSRuslan Bukin static const struct usb_temp_endpoint_desc modem_ep_1 = { 2483e420a3eSRuslan Bukin .pPacketSize = &modem_bulk_mps, 2493e420a3eSRuslan Bukin .bEndpointAddress = UE_DIR_OUT, 2503e420a3eSRuslan Bukin .bmAttributes = UE_BULK, 2513e420a3eSRuslan Bukin }; 2523e420a3eSRuslan Bukin 2533e420a3eSRuslan Bukin static const struct usb_temp_endpoint_desc modem_ep_2 = { 2543e420a3eSRuslan Bukin .pPacketSize = &modem_bulk_mps, 2553e420a3eSRuslan Bukin .bEndpointAddress = UE_DIR_IN, 2563e420a3eSRuslan Bukin .bmAttributes = UE_BULK, 2573e420a3eSRuslan Bukin }; 2583e420a3eSRuslan Bukin 2593e420a3eSRuslan Bukin static const struct usb_temp_endpoint_desc *modem_iface_0_ep[] = { 2603e420a3eSRuslan Bukin &modem_ep_0, 2613e420a3eSRuslan Bukin NULL, 2623e420a3eSRuslan Bukin }; 2633e420a3eSRuslan Bukin 2643e420a3eSRuslan Bukin static const struct usb_temp_endpoint_desc *modem_iface_1_ep[] = { 2653e420a3eSRuslan Bukin &modem_ep_1, 2663e420a3eSRuslan Bukin &modem_ep_2, 2673e420a3eSRuslan Bukin NULL, 2683e420a3eSRuslan Bukin }; 2693e420a3eSRuslan Bukin 2703e420a3eSRuslan Bukin static const uint8_t modem_raw_desc_0[] = { 2713e420a3eSRuslan Bukin 0x05, 0x24, 0x00, 0x10, 0x01 2723e420a3eSRuslan Bukin }; 2733e420a3eSRuslan Bukin 2743e420a3eSRuslan Bukin static const uint8_t modem_raw_desc_1[] = { 2753e420a3eSRuslan Bukin 0x05, 0x24, 0x06, MODEM_IFACE_0, MODEM_IFACE_1 2763e420a3eSRuslan Bukin }; 2773e420a3eSRuslan Bukin 2783e420a3eSRuslan Bukin static const uint8_t modem_raw_desc_2[] = { 2793e420a3eSRuslan Bukin 0x05, 0x24, 0x01, 0x03, MODEM_IFACE_1 2803e420a3eSRuslan Bukin }; 2813e420a3eSRuslan Bukin 2823e420a3eSRuslan Bukin static const uint8_t modem_raw_desc_3[] = { 2833e420a3eSRuslan Bukin 0x04, 0x24, 0x02, 0x07 2843e420a3eSRuslan Bukin }; 2853e420a3eSRuslan Bukin 2863e420a3eSRuslan Bukin static const void *modem_iface_0_desc[] = { 2873e420a3eSRuslan Bukin &modem_raw_desc_0, 2883e420a3eSRuslan Bukin &modem_raw_desc_1, 2893e420a3eSRuslan Bukin &modem_raw_desc_2, 2903e420a3eSRuslan Bukin &modem_raw_desc_3, 2913e420a3eSRuslan Bukin NULL, 2923e420a3eSRuslan Bukin }; 2933e420a3eSRuslan Bukin 2943e420a3eSRuslan Bukin static const struct usb_temp_interface_desc modem_iface_0 = { 2953e420a3eSRuslan Bukin .ppRawDesc = modem_iface_0_desc, 2963e420a3eSRuslan Bukin .ppEndpoints = modem_iface_0_ep, 2974ffeccf1SEdward Tomasz Napierala .bInterfaceClass = UICLASS_CDC, 2984ffeccf1SEdward Tomasz Napierala .bInterfaceSubClass = UISUBCLASS_ABSTRACT_CONTROL_MODEL, 2994ffeccf1SEdward Tomasz Napierala .bInterfaceProtocol = UIPROTO_CDC_AT, 3008e06491aSEdward Tomasz Napierala .iInterface = SERIALNET_MODEM_INDEX, 3013e420a3eSRuslan Bukin }; 3023e420a3eSRuslan Bukin 3033e420a3eSRuslan Bukin static const struct usb_temp_interface_desc modem_iface_1 = { 3043e420a3eSRuslan Bukin .ppEndpoints = modem_iface_1_ep, 3054ffeccf1SEdward Tomasz Napierala .bInterfaceClass = UICLASS_CDC_DATA, 3064ffeccf1SEdward Tomasz Napierala .bInterfaceSubClass = UISUBCLASS_DATA, 3073e420a3eSRuslan Bukin .bInterfaceProtocol = 0, 3088e06491aSEdward Tomasz Napierala .iInterface = SERIALNET_MODEM_INDEX, 3093e420a3eSRuslan Bukin }; 3103e420a3eSRuslan Bukin 3113e420a3eSRuslan Bukin static const struct usb_temp_interface_desc *serialnet_interfaces[] = { 3123e420a3eSRuslan Bukin &modem_iface_0, 3133e420a3eSRuslan Bukin &modem_iface_1, 3143e420a3eSRuslan Bukin ð_control_interface, 3153e420a3eSRuslan Bukin ð_data_null_interface, 3163e420a3eSRuslan Bukin ð_data_interface, 3173e420a3eSRuslan Bukin NULL, 3183e420a3eSRuslan Bukin }; 3193e420a3eSRuslan Bukin 3203e420a3eSRuslan Bukin static const struct usb_temp_config_desc serialnet_config_desc = { 3213e420a3eSRuslan Bukin .ppIfaceDesc = serialnet_interfaces, 3223e420a3eSRuslan Bukin .bmAttributes = UC_BUS_POWERED, 3233e420a3eSRuslan Bukin .bMaxPower = 25, /* 50 mA */ 3248e06491aSEdward Tomasz Napierala .iConfiguration = SERIALNET_CONFIGURATION_INDEX, 3253e420a3eSRuslan Bukin }; 3263e420a3eSRuslan Bukin static const struct usb_temp_config_desc *serialnet_configs[] = { 3273e420a3eSRuslan Bukin &serialnet_config_desc, 3283e420a3eSRuslan Bukin NULL, 3293e420a3eSRuslan Bukin }; 3303e420a3eSRuslan Bukin 3318e06491aSEdward Tomasz Napierala struct usb_temp_device_desc usb_template_serialnet = { 3323e420a3eSRuslan Bukin .getStringDesc = &serialnet_get_string_desc, 3333e420a3eSRuslan Bukin .ppConfigDesc = serialnet_configs, 3343e420a3eSRuslan Bukin .idVendor = USB_TEMPLATE_VENDOR, 3353e420a3eSRuslan Bukin .idProduct = 0x0001, 3363e420a3eSRuslan Bukin .bcdDevice = 0x0100, 3373e420a3eSRuslan Bukin .bDeviceClass = UDCLASS_COMM, 3383e420a3eSRuslan Bukin .bDeviceSubClass = 0, 3393e420a3eSRuslan Bukin .bDeviceProtocol = 0, 3408e06491aSEdward Tomasz Napierala .iManufacturer = SERIALNET_MANUFACTURER_INDEX, 3418e06491aSEdward Tomasz Napierala .iProduct = SERIALNET_PRODUCT_INDEX, 3428e06491aSEdward Tomasz Napierala .iSerialNumber = SERIALNET_SERIAL_NUMBER_INDEX, 3433e420a3eSRuslan Bukin }; 3443e420a3eSRuslan Bukin 3453e420a3eSRuslan Bukin /*------------------------------------------------------------------------* 3463e420a3eSRuslan Bukin * serialnet_get_string_desc 3473e420a3eSRuslan Bukin * 3483e420a3eSRuslan Bukin * Return values: 3493e420a3eSRuslan Bukin * NULL: Failure. No such string. 3503e420a3eSRuslan Bukin * Else: Success. Pointer to string descriptor is returned. 3513e420a3eSRuslan Bukin *------------------------------------------------------------------------*/ 3523e420a3eSRuslan Bukin static const void * 3533e420a3eSRuslan Bukin serialnet_get_string_desc(uint16_t lang_id, uint8_t string_index) 3543e420a3eSRuslan Bukin { 3558e06491aSEdward Tomasz Napierala static const void *ptr[SERIALNET_MAX_INDEX] = { 3568e06491aSEdward Tomasz Napierala [SERIALNET_LANG_INDEX] = &usb_string_lang_en, 3578e06491aSEdward Tomasz Napierala [SERIALNET_MODEM_INDEX] = &serialnet_modem, 3588e06491aSEdward Tomasz Napierala [SERIALNET_ETH_MAC_INDEX] = &serialnet_eth_mac, 3598e06491aSEdward Tomasz Napierala [SERIALNET_ETH_CONTROL_INDEX] = &serialnet_eth_control, 3608e06491aSEdward Tomasz Napierala [SERIALNET_ETH_DATA_INDEX] = &serialnet_eth_data, 3618e06491aSEdward Tomasz Napierala [SERIALNET_CONFIGURATION_INDEX] = &serialnet_configuration, 3628e06491aSEdward Tomasz Napierala [SERIALNET_MANUFACTURER_INDEX] = &serialnet_manufacturer, 3638e06491aSEdward Tomasz Napierala [SERIALNET_PRODUCT_INDEX] = &serialnet_product, 3648e06491aSEdward Tomasz Napierala [SERIALNET_SERIAL_NUMBER_INDEX] = &serialnet_serial_number, 3653e420a3eSRuslan Bukin }; 3663e420a3eSRuslan Bukin 3673e420a3eSRuslan Bukin if (string_index == 0) { 3683e420a3eSRuslan Bukin return (&usb_string_lang_en); 3693e420a3eSRuslan Bukin } 3703e420a3eSRuslan Bukin if (lang_id != 0x0409) { 3713e420a3eSRuslan Bukin return (NULL); 3723e420a3eSRuslan Bukin } 3738e06491aSEdward Tomasz Napierala if (string_index < SERIALNET_MAX_INDEX) { 3743e420a3eSRuslan Bukin return (ptr[string_index]); 3753e420a3eSRuslan Bukin } 3763e420a3eSRuslan Bukin return (NULL); 3773e420a3eSRuslan Bukin } 3788e06491aSEdward Tomasz Napierala 3798e06491aSEdward Tomasz Napierala static void 3808e06491aSEdward Tomasz Napierala serialnet_init(void *arg __unused) 3818e06491aSEdward Tomasz Napierala { 3828e06491aSEdward Tomasz Napierala struct sysctl_oid *parent; 3838e06491aSEdward Tomasz Napierala char parent_name[3]; 3848e06491aSEdward Tomasz Napierala 3858e06491aSEdward Tomasz Napierala usb_make_str_desc(&serialnet_modem, sizeof(serialnet_modem), 3868e06491aSEdward Tomasz Napierala SERIALNET_DEFAULT_MODEM); 3878e06491aSEdward Tomasz Napierala usb_make_str_desc(&serialnet_eth_mac, sizeof(serialnet_eth_mac), 3888e06491aSEdward Tomasz Napierala SERIALNET_DEFAULT_ETH_MAC); 3898e06491aSEdward Tomasz Napierala usb_make_str_desc(&serialnet_eth_control, sizeof(serialnet_eth_control), 3908e06491aSEdward Tomasz Napierala SERIALNET_DEFAULT_ETH_CONTROL); 3918e06491aSEdward Tomasz Napierala usb_make_str_desc(&serialnet_eth_data, sizeof(serialnet_eth_data), 3928e06491aSEdward Tomasz Napierala SERIALNET_DEFAULT_ETH_DATA); 3938e06491aSEdward Tomasz Napierala usb_make_str_desc(&serialnet_configuration, sizeof(serialnet_configuration), 3948e06491aSEdward Tomasz Napierala SERIALNET_DEFAULT_CONFIGURATION); 3958e06491aSEdward Tomasz Napierala usb_make_str_desc(&serialnet_manufacturer, sizeof(serialnet_manufacturer), 3968e06491aSEdward Tomasz Napierala SERIALNET_DEFAULT_MANUFACTURER); 3978e06491aSEdward Tomasz Napierala usb_make_str_desc(&serialnet_product, sizeof(serialnet_product), 3988e06491aSEdward Tomasz Napierala SERIALNET_DEFAULT_PRODUCT); 3998e06491aSEdward Tomasz Napierala usb_make_str_desc(&serialnet_serial_number, sizeof(serialnet_serial_number), 4008e06491aSEdward Tomasz Napierala SERIALNET_DEFAULT_SERIAL_NUMBER); 4018e06491aSEdward Tomasz Napierala 4028e06491aSEdward Tomasz Napierala snprintf(parent_name, sizeof(parent_name), "%d", USB_TEMP_SERIALNET); 4038e06491aSEdward Tomasz Napierala sysctl_ctx_init(&serialnet_ctx_list); 4048e06491aSEdward Tomasz Napierala 4058e06491aSEdward Tomasz Napierala parent = SYSCTL_ADD_NODE(&serialnet_ctx_list, 4068e06491aSEdward Tomasz Napierala SYSCTL_STATIC_CHILDREN(_hw_usb_templates), OID_AUTO, 4078e06491aSEdward Tomasz Napierala parent_name, CTLFLAG_RW, 4088e06491aSEdward Tomasz Napierala 0, "USB Mass Storage device side template"); 4098e06491aSEdward Tomasz Napierala SYSCTL_ADD_U16(&serialnet_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 4108e06491aSEdward Tomasz Napierala "vendor_id", CTLFLAG_RWTUN, 4118e06491aSEdward Tomasz Napierala &usb_template_serialnet.idVendor, 1, "Vendor identifier"); 4128e06491aSEdward Tomasz Napierala SYSCTL_ADD_U16(&serialnet_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 4138e06491aSEdward Tomasz Napierala "product_id", CTLFLAG_RWTUN, 4148e06491aSEdward Tomasz Napierala &usb_template_serialnet.idProduct, 1, "Product identifier"); 4158e06491aSEdward Tomasz Napierala SYSCTL_ADD_PROC(&serialnet_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 4168e06491aSEdward Tomasz Napierala "eth_mac", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 4178e06491aSEdward Tomasz Napierala &serialnet_eth_mac, sizeof(serialnet_eth_mac), usb_temp_sysctl, 4188e06491aSEdward Tomasz Napierala "A", "Ethernet MAC address string"); 4198e06491aSEdward Tomasz Napierala #if 0 4208e06491aSEdward Tomasz Napierala SYSCTL_ADD_PROC(&serialnet_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 4218e06491aSEdward Tomasz Napierala "modem", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 4228e06491aSEdward Tomasz Napierala &serialnet_modem, sizeof(serialnet_modem), usb_temp_sysctl, 4238e06491aSEdward Tomasz Napierala "A", "Modem interface string"); 4248e06491aSEdward Tomasz Napierala SYSCTL_ADD_PROC(&serialnet_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 4258e06491aSEdward Tomasz Napierala "eth_control", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 4268e06491aSEdward Tomasz Napierala &serialnet_eth_control, sizeof(serialnet_eth_data), usb_temp_sysctl, 4278e06491aSEdward Tomasz Napierala "A", "Ethernet control interface string"); 4288e06491aSEdward Tomasz Napierala SYSCTL_ADD_PROC(&serialnet_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 4298e06491aSEdward Tomasz Napierala "eth_data", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 4308e06491aSEdward Tomasz Napierala &serialnet_eth_data, sizeof(serialnet_eth_data), usb_temp_sysctl, 4318e06491aSEdward Tomasz Napierala "A", "Ethernet data interface string"); 4328e06491aSEdward Tomasz Napierala SYSCTL_ADD_PROC(&serialnet_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 4338e06491aSEdward Tomasz Napierala "configuration", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 4348e06491aSEdward Tomasz Napierala &serialnet_configuration, sizeof(serialnet_configuration), usb_temp_sysctl, 4358e06491aSEdward Tomasz Napierala "A", "Configuration string"); 4368e06491aSEdward Tomasz Napierala #endif 4378e06491aSEdward Tomasz Napierala SYSCTL_ADD_PROC(&serialnet_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 4388e06491aSEdward Tomasz Napierala "manufacturer", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 4398e06491aSEdward Tomasz Napierala &serialnet_manufacturer, sizeof(serialnet_manufacturer), usb_temp_sysctl, 4408e06491aSEdward Tomasz Napierala "A", "Manufacturer string"); 4418e06491aSEdward Tomasz Napierala SYSCTL_ADD_PROC(&serialnet_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 4428e06491aSEdward Tomasz Napierala "product", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 4438e06491aSEdward Tomasz Napierala &serialnet_product, sizeof(serialnet_product), usb_temp_sysctl, 4448e06491aSEdward Tomasz Napierala "A", "Product string"); 4458e06491aSEdward Tomasz Napierala SYSCTL_ADD_PROC(&serialnet_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 4468e06491aSEdward Tomasz Napierala "serial_number", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 4478e06491aSEdward Tomasz Napierala &serialnet_serial_number, sizeof(serialnet_serial_number), usb_temp_sysctl, 4488e06491aSEdward Tomasz Napierala "A", "Serial number string"); 4498e06491aSEdward Tomasz Napierala } 4508e06491aSEdward Tomasz Napierala 4518e06491aSEdward Tomasz Napierala static void 4528e06491aSEdward Tomasz Napierala serialnet_uninit(void *arg __unused) 4538e06491aSEdward Tomasz Napierala { 4548e06491aSEdward Tomasz Napierala 4558e06491aSEdward Tomasz Napierala sysctl_ctx_free(&serialnet_ctx_list); 4568e06491aSEdward Tomasz Napierala } 4578e06491aSEdward Tomasz Napierala 4588e06491aSEdward Tomasz Napierala SYSINIT(serialnet_init, SI_SUB_LOCK, SI_ORDER_FIRST, serialnet_init, NULL); 459*c70e38e4SHans Petter Selasky SYSUNINIT(serialnet_uninit, SI_SUB_LOCK, SI_ORDER_FIRST, serialnet_uninit, NULL); 460