xref: /freebsd/sys/dev/usb/template/usb_template_modem.c (revision 71625ec9ad2a9bc8c09784fbd23b759830e0ee5f)
1399e6543SHans Petter Selasky /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3718cf2ccSPedro F. Giffuni  *
48e06491aSEdward Tomasz Napierala  * Copyright (c) 2010 Hans Petter Selasky
58e06491aSEdward Tomasz Napierala  * Copyright (c) 2018 The FreeBSD Foundation
68e06491aSEdward Tomasz Napierala  * All rights reserved.
78e06491aSEdward Tomasz Napierala  *
88e06491aSEdward Tomasz Napierala  * Portions of this software were developed by Edward Tomasz Napierala
98e06491aSEdward Tomasz Napierala  * under sponsorship from the FreeBSD Foundation.
10399e6543SHans Petter Selasky  *
11399e6543SHans Petter Selasky  * Redistribution and use in source and binary forms, with or without
12399e6543SHans Petter Selasky  * modification, are permitted provided that the following conditions
13399e6543SHans Petter Selasky  * are met:
14399e6543SHans Petter Selasky  * 1. Redistributions of source code must retain the above copyright
15399e6543SHans Petter Selasky  *    notice, this list of conditions and the following disclaimer.
16399e6543SHans Petter Selasky  * 2. Redistributions in binary form must reproduce the above copyright
17399e6543SHans Petter Selasky  *    notice, this list of conditions and the following disclaimer in the
18399e6543SHans Petter Selasky  *    documentation and/or other materials provided with the distribution.
19399e6543SHans Petter Selasky  *
20399e6543SHans Petter Selasky  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21399e6543SHans Petter Selasky  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22399e6543SHans Petter Selasky  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23399e6543SHans Petter Selasky  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24399e6543SHans Petter Selasky  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25399e6543SHans Petter Selasky  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26399e6543SHans Petter Selasky  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27399e6543SHans Petter Selasky  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28399e6543SHans Petter Selasky  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29399e6543SHans Petter Selasky  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30399e6543SHans Petter Selasky  * SUCH DAMAGE.
31399e6543SHans Petter Selasky  */
32399e6543SHans Petter Selasky 
33399e6543SHans Petter Selasky /*
34399e6543SHans Petter Selasky  * This file contains the USB template for an USB Modem Device.
35399e6543SHans Petter Selasky  */
36399e6543SHans Petter Selasky 
37d2b99310SHans Petter Selasky #ifdef USB_GLOBAL_INCLUDE_FILE
38d2b99310SHans Petter Selasky #include USB_GLOBAL_INCLUDE_FILE
39d2b99310SHans Petter Selasky #else
40399e6543SHans Petter Selasky #include <sys/stdint.h>
41399e6543SHans Petter Selasky #include <sys/stddef.h>
42399e6543SHans Petter Selasky #include <sys/param.h>
43399e6543SHans Petter Selasky #include <sys/queue.h>
44399e6543SHans Petter Selasky #include <sys/types.h>
45399e6543SHans Petter Selasky #include <sys/systm.h>
46399e6543SHans Petter Selasky #include <sys/kernel.h>
47399e6543SHans Petter Selasky #include <sys/bus.h>
48399e6543SHans Petter Selasky #include <sys/module.h>
49399e6543SHans Petter Selasky #include <sys/lock.h>
50399e6543SHans Petter Selasky #include <sys/mutex.h>
51399e6543SHans Petter Selasky #include <sys/condvar.h>
52399e6543SHans Petter Selasky #include <sys/sysctl.h>
53399e6543SHans Petter Selasky #include <sys/sx.h>
54399e6543SHans Petter Selasky #include <sys/unistd.h>
55399e6543SHans Petter Selasky #include <sys/callout.h>
56399e6543SHans Petter Selasky #include <sys/malloc.h>
57399e6543SHans Petter Selasky #include <sys/priv.h>
58399e6543SHans Petter Selasky 
59399e6543SHans Petter Selasky #include <dev/usb/usb.h>
60399e6543SHans Petter Selasky #include <dev/usb/usbdi.h>
6123ab0871SHans Petter Selasky #include <dev/usb/usb_core.h>
62399e6543SHans Petter Selasky #include <dev/usb/usb_cdc.h>
638e06491aSEdward Tomasz Napierala #include <dev/usb/usb_ioctl.h>
648e06491aSEdward Tomasz Napierala #include <dev/usb/usb_util.h>
65399e6543SHans Petter Selasky 
66399e6543SHans Petter Selasky #include <dev/usb/template/usb_template.h>
67d2b99310SHans Petter Selasky #endif			/* USB_GLOBAL_INCLUDE_FILE */
68399e6543SHans Petter Selasky 
69399e6543SHans Petter Selasky enum {
708e06491aSEdward Tomasz Napierala 	MODEM_LANG_INDEX,
718e06491aSEdward Tomasz Napierala 	MODEM_INTERFACE_INDEX,
721ee5bed7SEdward Tomasz Napierala 	MODEM_MANUFACTURER_INDEX,
738e06491aSEdward Tomasz Napierala 	MODEM_PRODUCT_INDEX,
741ee5bed7SEdward Tomasz Napierala 	MODEM_SERIAL_NUMBER_INDEX,
758e06491aSEdward Tomasz Napierala 	MODEM_MAX_INDEX,
76399e6543SHans Petter Selasky };
77399e6543SHans Petter Selasky 
781558eec6SEdward Tomasz Napierala #define	MODEM_DEFAULT_VENDOR_ID		USB_TEMPLATE_VENDOR
79d01c1c8bSEdward Tomasz Napierala #define	MODEM_DEFAULT_PRODUCT_ID	0x27dd
80ac4a7f30SEdward Tomasz Napierala #define	MODEM_DEFAULT_INTERFACE		"Virtual serial port"
81d01c1c8bSEdward Tomasz Napierala #define	MODEM_DEFAULT_MANUFACTURER	USB_TEMPLATE_MANUFACTURER
82ac4a7f30SEdward Tomasz Napierala #define	MODEM_DEFAULT_PRODUCT		"Virtual serial port"
83733efc21SEdward Tomasz Napierala /*
84733efc21SEdward Tomasz Napierala  * The reason for this being called like this is that OSX
85733efc21SEdward Tomasz Napierala  * derives the device node name from it, resulting in a somewhat
86733efc21SEdward Tomasz Napierala  * user-friendly "/dev/cu.usbmodemFreeBSD1".  And yes, the "1"
87733efc21SEdward Tomasz Napierala  * needs to be there, otherwise OSX will mangle it.
88733efc21SEdward Tomasz Napierala  */
89733efc21SEdward Tomasz Napierala #define	MODEM_DEFAULT_SERIAL_NUMBER	"FreeBSD1"
90399e6543SHans Petter Selasky 
918e06491aSEdward Tomasz Napierala static struct usb_string_descriptor	modem_interface;
921ee5bed7SEdward Tomasz Napierala static struct usb_string_descriptor	modem_manufacturer;
938e06491aSEdward Tomasz Napierala static struct usb_string_descriptor	modem_product;
941ee5bed7SEdward Tomasz Napierala static struct usb_string_descriptor	modem_serial_number;
95399e6543SHans Petter Selasky 
968e06491aSEdward Tomasz Napierala static struct sysctl_ctx_list		modem_ctx_list;
97399e6543SHans Petter Selasky 
98399e6543SHans Petter Selasky #define	MODEM_IFACE_0 0
99399e6543SHans Petter Selasky #define	MODEM_IFACE_1 1
100399e6543SHans Petter Selasky 
101399e6543SHans Petter Selasky /* prototypes */
102399e6543SHans Petter Selasky 
103399e6543SHans Petter Selasky static const struct usb_temp_packet_size modem_bulk_mps = {
104399e6543SHans Petter Selasky 	.mps[USB_SPEED_LOW] = 8,
105399e6543SHans Petter Selasky 	.mps[USB_SPEED_FULL] = 64,
106399e6543SHans Petter Selasky 	.mps[USB_SPEED_HIGH] = 512,
107399e6543SHans Petter Selasky };
108399e6543SHans Petter Selasky 
109399e6543SHans Petter Selasky static const struct usb_temp_packet_size modem_intr_mps = {
110399e6543SHans Petter Selasky 	.mps[USB_SPEED_LOW] = 8,
111399e6543SHans Petter Selasky 	.mps[USB_SPEED_FULL] = 8,
112399e6543SHans Petter Selasky 	.mps[USB_SPEED_HIGH] = 8,
113399e6543SHans Petter Selasky };
114399e6543SHans Petter Selasky 
115399e6543SHans Petter Selasky static const struct usb_temp_interval modem_intr_interval = {
116e6ee4f7dSHans Petter Selasky 	.bInterval[USB_SPEED_LOW] = 8,	/* 8ms */
117e6ee4f7dSHans Petter Selasky 	.bInterval[USB_SPEED_FULL] = 8,	/* 8ms */
118e6ee4f7dSHans Petter Selasky 	.bInterval[USB_SPEED_HIGH] = 7,	/* 8ms */
119399e6543SHans Petter Selasky };
120399e6543SHans Petter Selasky 
121399e6543SHans Petter Selasky static const struct usb_temp_endpoint_desc modem_ep_0 = {
122399e6543SHans Petter Selasky 	.pPacketSize = &modem_intr_mps,
123399e6543SHans Petter Selasky 	.pIntervals = &modem_intr_interval,
124399e6543SHans Petter Selasky 	.bEndpointAddress = UE_DIR_IN,
125399e6543SHans Petter Selasky 	.bmAttributes = UE_INTERRUPT,
126399e6543SHans Petter Selasky };
127399e6543SHans Petter Selasky 
128399e6543SHans Petter Selasky static const struct usb_temp_endpoint_desc modem_ep_1 = {
129399e6543SHans Petter Selasky 	.pPacketSize = &modem_bulk_mps,
130399e6543SHans Petter Selasky 	.bEndpointAddress = UE_DIR_OUT,
131399e6543SHans Petter Selasky 	.bmAttributes = UE_BULK,
132399e6543SHans Petter Selasky };
133399e6543SHans Petter Selasky 
134399e6543SHans Petter Selasky static const struct usb_temp_endpoint_desc modem_ep_2 = {
135399e6543SHans Petter Selasky 	.pPacketSize = &modem_bulk_mps,
136399e6543SHans Petter Selasky 	.bEndpointAddress = UE_DIR_IN,
137399e6543SHans Petter Selasky 	.bmAttributes = UE_BULK,
138399e6543SHans Petter Selasky };
139399e6543SHans Petter Selasky 
140399e6543SHans Petter Selasky static const struct usb_temp_endpoint_desc *modem_iface_0_ep[] = {
141399e6543SHans Petter Selasky 	&modem_ep_0,
142399e6543SHans Petter Selasky 	NULL,
143399e6543SHans Petter Selasky };
144399e6543SHans Petter Selasky 
145399e6543SHans Petter Selasky static const struct usb_temp_endpoint_desc *modem_iface_1_ep[] = {
146399e6543SHans Petter Selasky 	&modem_ep_1,
147399e6543SHans Petter Selasky 	&modem_ep_2,
148399e6543SHans Petter Selasky 	NULL,
149399e6543SHans Petter Selasky };
150399e6543SHans Petter Selasky 
151399e6543SHans Petter Selasky static const uint8_t modem_raw_desc_0[] = {
152399e6543SHans Petter Selasky 	0x05, 0x24, 0x00, 0x10, 0x01
153399e6543SHans Petter Selasky };
154399e6543SHans Petter Selasky 
155399e6543SHans Petter Selasky static const uint8_t modem_raw_desc_1[] = {
156399e6543SHans Petter Selasky 	0x05, 0x24, 0x06, MODEM_IFACE_0, MODEM_IFACE_1
157399e6543SHans Petter Selasky };
158399e6543SHans Petter Selasky 
159399e6543SHans Petter Selasky static const uint8_t modem_raw_desc_2[] = {
160399e6543SHans Petter Selasky 	0x05, 0x24, 0x01, 0x03, MODEM_IFACE_1
161399e6543SHans Petter Selasky };
162399e6543SHans Petter Selasky 
163399e6543SHans Petter Selasky static const uint8_t modem_raw_desc_3[] = {
164399e6543SHans Petter Selasky 	0x04, 0x24, 0x02, 0x07
165399e6543SHans Petter Selasky };
166399e6543SHans Petter Selasky 
167399e6543SHans Petter Selasky static const void *modem_iface_0_desc[] = {
168399e6543SHans Petter Selasky 	&modem_raw_desc_0,
169399e6543SHans Petter Selasky 	&modem_raw_desc_1,
170399e6543SHans Petter Selasky 	&modem_raw_desc_2,
171399e6543SHans Petter Selasky 	&modem_raw_desc_3,
172399e6543SHans Petter Selasky 	NULL,
173399e6543SHans Petter Selasky };
174399e6543SHans Petter Selasky 
175399e6543SHans Petter Selasky static const struct usb_temp_interface_desc modem_iface_0 = {
176399e6543SHans Petter Selasky 	.ppRawDesc = modem_iface_0_desc,
177399e6543SHans Petter Selasky 	.ppEndpoints = modem_iface_0_ep,
1784ffeccf1SEdward Tomasz Napierala 	.bInterfaceClass = UICLASS_CDC,
1794ffeccf1SEdward Tomasz Napierala 	.bInterfaceSubClass = UISUBCLASS_ABSTRACT_CONTROL_MODEL,
1806b7e508cSEdward Tomasz Napierala 	.bInterfaceProtocol = UIPROTO_CDC_NONE,
1818e06491aSEdward Tomasz Napierala 	.iInterface = MODEM_INTERFACE_INDEX,
182399e6543SHans Petter Selasky };
183399e6543SHans Petter Selasky 
184399e6543SHans Petter Selasky static const struct usb_temp_interface_desc modem_iface_1 = {
185399e6543SHans Petter Selasky 	.ppEndpoints = modem_iface_1_ep,
1864ffeccf1SEdward Tomasz Napierala 	.bInterfaceClass = UICLASS_CDC_DATA,
1874ffeccf1SEdward Tomasz Napierala 	.bInterfaceSubClass = UISUBCLASS_DATA,
1884ffeccf1SEdward Tomasz Napierala 	.bInterfaceProtocol = UIPROTO_CDC_NONE,
1898e06491aSEdward Tomasz Napierala 	.iInterface = MODEM_INTERFACE_INDEX,
190399e6543SHans Petter Selasky };
191399e6543SHans Petter Selasky 
192399e6543SHans Petter Selasky static const struct usb_temp_interface_desc *modem_interfaces[] = {
193399e6543SHans Petter Selasky 	&modem_iface_0,
194399e6543SHans Petter Selasky 	&modem_iface_1,
195399e6543SHans Petter Selasky 	NULL,
196399e6543SHans Petter Selasky };
197399e6543SHans Petter Selasky 
198399e6543SHans Petter Selasky static const struct usb_temp_config_desc modem_config_desc = {
199399e6543SHans Petter Selasky 	.ppIfaceDesc = modem_interfaces,
200d008c0d7SEdward Tomasz Napierala 	.bmAttributes = 0,
201d008c0d7SEdward Tomasz Napierala 	.bMaxPower = 0,
2028e06491aSEdward Tomasz Napierala 	.iConfiguration = MODEM_PRODUCT_INDEX,
203399e6543SHans Petter Selasky };
204399e6543SHans Petter Selasky 
205399e6543SHans Petter Selasky static const struct usb_temp_config_desc *modem_configs[] = {
206399e6543SHans Petter Selasky 	&modem_config_desc,
207399e6543SHans Petter Selasky 	NULL,
208399e6543SHans Petter Selasky };
209399e6543SHans Petter Selasky 
210399e6543SHans Petter Selasky static usb_temp_get_string_desc_t modem_get_string_desc;
211399e6543SHans Petter Selasky static usb_temp_get_vendor_desc_t modem_get_vendor_desc;
212399e6543SHans Petter Selasky 
2138e06491aSEdward Tomasz Napierala struct usb_temp_device_desc usb_template_modem = {
214399e6543SHans Petter Selasky 	.getStringDesc = &modem_get_string_desc,
215399e6543SHans Petter Selasky 	.getVendorDesc = &modem_get_vendor_desc,
216399e6543SHans Petter Selasky 	.ppConfigDesc = modem_configs,
2171558eec6SEdward Tomasz Napierala 	.idVendor = MODEM_DEFAULT_VENDOR_ID,
2181558eec6SEdward Tomasz Napierala 	.idProduct = MODEM_DEFAULT_PRODUCT_ID,
219399e6543SHans Petter Selasky 	.bcdDevice = 0x0100,
220399e6543SHans Petter Selasky 	.bDeviceClass = UDCLASS_COMM,
221399e6543SHans Petter Selasky 	.bDeviceSubClass = 0,
222399e6543SHans Petter Selasky 	.bDeviceProtocol = 0,
2231ee5bed7SEdward Tomasz Napierala 	.iManufacturer = MODEM_MANUFACTURER_INDEX,
2248e06491aSEdward Tomasz Napierala 	.iProduct = MODEM_PRODUCT_INDEX,
2251ee5bed7SEdward Tomasz Napierala 	.iSerialNumber = MODEM_SERIAL_NUMBER_INDEX,
226399e6543SHans Petter Selasky };
227399e6543SHans Petter Selasky 
228399e6543SHans Petter Selasky /*------------------------------------------------------------------------*
229399e6543SHans Petter Selasky  *      modem_get_vendor_desc
230399e6543SHans Petter Selasky  *
231399e6543SHans Petter Selasky  * Return values:
232399e6543SHans Petter Selasky  * NULL: Failure. No such vendor descriptor.
233399e6543SHans Petter Selasky  * Else: Success. Pointer to vendor descriptor is returned.
234399e6543SHans Petter Selasky  *------------------------------------------------------------------------*/
235399e6543SHans Petter Selasky static const void *
modem_get_vendor_desc(const struct usb_device_request * req,uint16_t * plen)236399e6543SHans Petter Selasky modem_get_vendor_desc(const struct usb_device_request *req, uint16_t *plen)
237399e6543SHans Petter Selasky {
238399e6543SHans Petter Selasky 	return (NULL);
239399e6543SHans Petter Selasky }
240399e6543SHans Petter Selasky 
241399e6543SHans Petter Selasky /*------------------------------------------------------------------------*
242399e6543SHans Petter Selasky  *	modem_get_string_desc
243399e6543SHans Petter Selasky  *
244399e6543SHans Petter Selasky  * Return values:
245399e6543SHans Petter Selasky  * NULL: Failure. No such string.
246399e6543SHans Petter Selasky  * Else: Success. Pointer to string descriptor is returned.
247399e6543SHans Petter Selasky  *------------------------------------------------------------------------*/
248399e6543SHans Petter Selasky static const void *
modem_get_string_desc(uint16_t lang_id,uint8_t string_index)249399e6543SHans Petter Selasky modem_get_string_desc(uint16_t lang_id, uint8_t string_index)
250399e6543SHans Petter Selasky {
2518e06491aSEdward Tomasz Napierala 	static const void *ptr[MODEM_MAX_INDEX] = {
2528e06491aSEdward Tomasz Napierala 		[MODEM_LANG_INDEX] = &usb_string_lang_en,
2538e06491aSEdward Tomasz Napierala 		[MODEM_INTERFACE_INDEX] = &modem_interface,
2541ee5bed7SEdward Tomasz Napierala 		[MODEM_MANUFACTURER_INDEX] = &modem_manufacturer,
2558e06491aSEdward Tomasz Napierala 		[MODEM_PRODUCT_INDEX] = &modem_product,
2561ee5bed7SEdward Tomasz Napierala 		[MODEM_SERIAL_NUMBER_INDEX] = &modem_serial_number,
257399e6543SHans Petter Selasky 	};
258399e6543SHans Petter Selasky 
259399e6543SHans Petter Selasky 	if (string_index == 0) {
26023ab0871SHans Petter Selasky 		return (&usb_string_lang_en);
261399e6543SHans Petter Selasky 	}
262399e6543SHans Petter Selasky 	if (lang_id != 0x0409) {
263399e6543SHans Petter Selasky 		return (NULL);
264399e6543SHans Petter Selasky 	}
2658e06491aSEdward Tomasz Napierala 	if (string_index < MODEM_MAX_INDEX) {
266399e6543SHans Petter Selasky 		return (ptr[string_index]);
267399e6543SHans Petter Selasky 	}
268399e6543SHans Petter Selasky 	return (NULL);
269399e6543SHans Petter Selasky }
2708e06491aSEdward Tomasz Napierala 
2718e06491aSEdward Tomasz Napierala static void
modem_init(void * arg __unused)2728e06491aSEdward Tomasz Napierala modem_init(void *arg __unused)
2738e06491aSEdward Tomasz Napierala {
2748e06491aSEdward Tomasz Napierala 	struct sysctl_oid *parent;
2758e06491aSEdward Tomasz Napierala 	char parent_name[3];
2768e06491aSEdward Tomasz Napierala 
2778e06491aSEdward Tomasz Napierala 	usb_make_str_desc(&modem_interface, sizeof(modem_interface),
2788e06491aSEdward Tomasz Napierala 	    MODEM_DEFAULT_INTERFACE);
2791ee5bed7SEdward Tomasz Napierala 	usb_make_str_desc(&modem_manufacturer, sizeof(modem_manufacturer),
2801ee5bed7SEdward Tomasz Napierala 	    MODEM_DEFAULT_MANUFACTURER);
2818e06491aSEdward Tomasz Napierala 	usb_make_str_desc(&modem_product, sizeof(modem_product),
2828e06491aSEdward Tomasz Napierala 	    MODEM_DEFAULT_PRODUCT);
2831ee5bed7SEdward Tomasz Napierala 	usb_make_str_desc(&modem_serial_number, sizeof(modem_serial_number),
2841ee5bed7SEdward Tomasz Napierala 	    MODEM_DEFAULT_SERIAL_NUMBER);
2858e06491aSEdward Tomasz Napierala 
2868e06491aSEdward Tomasz Napierala 	snprintf(parent_name, sizeof(parent_name), "%d", USB_TEMP_MODEM);
2878e06491aSEdward Tomasz Napierala 	sysctl_ctx_init(&modem_ctx_list);
2888e06491aSEdward Tomasz Napierala 
2898e06491aSEdward Tomasz Napierala 	parent = SYSCTL_ADD_NODE(&modem_ctx_list,
2908e06491aSEdward Tomasz Napierala 	    SYSCTL_STATIC_CHILDREN(_hw_usb_templates), OID_AUTO,
291f8d2b1f3SPawel Biernacki 	    parent_name, CTLFLAG_RW | CTLFLAG_MPSAFE,
292ac4a7f30SEdward Tomasz Napierala 	    0, "Virtual serial port device side template");
2938e06491aSEdward Tomasz Napierala 	SYSCTL_ADD_U16(&modem_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
2948e06491aSEdward Tomasz Napierala 	    "vendor_id", CTLFLAG_RWTUN,
2958e06491aSEdward Tomasz Napierala 	    &usb_template_modem.idVendor, 1, "Vendor identifier");
2968e06491aSEdward Tomasz Napierala 	SYSCTL_ADD_U16(&modem_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
2978e06491aSEdward Tomasz Napierala 	    "product_id", CTLFLAG_RWTUN,
2988e06491aSEdward Tomasz Napierala 	    &usb_template_modem.idProduct, 1, "Product identifier");
2998e06491aSEdward Tomasz Napierala #if 0
3008e06491aSEdward Tomasz Napierala 	SYSCTL_ADD_PROC(&modem_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
3018e06491aSEdward Tomasz Napierala 	    "keyboard", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
3028e06491aSEdward Tomasz Napierala 	    &modem_interface, sizeof(modem_interface), usb_temp_sysctl,
3038e06491aSEdward Tomasz Napierala 	    "A", "Interface string");
3048e06491aSEdward Tomasz Napierala #endif
3058e06491aSEdward Tomasz Napierala 	SYSCTL_ADD_PROC(&modem_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
3061ee5bed7SEdward Tomasz Napierala 	    "manufacturer", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
3071ee5bed7SEdward Tomasz Napierala 	    &modem_manufacturer, sizeof(modem_manufacturer), usb_temp_sysctl,
3081ee5bed7SEdward Tomasz Napierala 	    "A", "Manufacturer string");
3091ee5bed7SEdward Tomasz Napierala 	SYSCTL_ADD_PROC(&modem_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
3108e06491aSEdward Tomasz Napierala 	    "product", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
3118e06491aSEdward Tomasz Napierala 	    &modem_product, sizeof(modem_product), usb_temp_sysctl,
3128e06491aSEdward Tomasz Napierala 	    "A", "Product string");
3131ee5bed7SEdward Tomasz Napierala 	SYSCTL_ADD_PROC(&modem_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
3141ee5bed7SEdward Tomasz Napierala 	    "serial_number", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
3151ee5bed7SEdward Tomasz Napierala 	    &modem_serial_number, sizeof(modem_serial_number), usb_temp_sysctl,
3161ee5bed7SEdward Tomasz Napierala 	    "A", "Serial number string");
3178e06491aSEdward Tomasz Napierala }
3188e06491aSEdward Tomasz Napierala 
3198e06491aSEdward Tomasz Napierala static void
modem_uninit(void * arg __unused)3208e06491aSEdward Tomasz Napierala modem_uninit(void *arg __unused)
3218e06491aSEdward Tomasz Napierala {
3228e06491aSEdward Tomasz Napierala 
3238e06491aSEdward Tomasz Napierala 	sysctl_ctx_free(&modem_ctx_list);
3248e06491aSEdward Tomasz Napierala }
3258e06491aSEdward Tomasz Napierala 
3268e06491aSEdward Tomasz Napierala SYSINIT(modem_init, SI_SUB_LOCK, SI_ORDER_FIRST, modem_init, NULL);
327c70e38e4SHans Petter Selasky SYSUNINIT(modem_uninit, SI_SUB_LOCK, SI_ORDER_FIRST, modem_uninit, NULL);
328