xref: /freebsd/sys/dev/usb/template/usb_template_mtp.c (revision 8e06491a4e5709cf821dc010f349062f7b34c2f4)
1d2b99310SHans Petter Selasky /* $FreeBSD$ */
202ac6454SAndrew Thompson /*-
3718cf2ccSPedro F. Giffuni  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4718cf2ccSPedro F. Giffuni  *
55d38a4d4SEd Schouten  * Copyright (c) 2008 Hans Petter Selasky <hselasky@FreeBSD.org>
6*8e06491aSEdward Tomasz Napierala  * Copyright (c) 2018 The FreeBSD Foundation
702ac6454SAndrew Thompson  * All rights reserved.
802ac6454SAndrew Thompson  *
9*8e06491aSEdward Tomasz Napierala  * Portions of this software were developed by Edward Tomasz Napierala
10*8e06491aSEdward Tomasz Napierala  * under sponsorship from the FreeBSD Foundation.
11*8e06491aSEdward Tomasz Napierala  *
1202ac6454SAndrew Thompson  * Redistribution and use in source and binary forms, with or without
1302ac6454SAndrew Thompson  * modification, are permitted provided that the following conditions
1402ac6454SAndrew Thompson  * are met:
1502ac6454SAndrew Thompson  * 1. Redistributions of source code must retain the above copyright
1602ac6454SAndrew Thompson  *    notice, this list of conditions and the following disclaimer.
1702ac6454SAndrew Thompson  * 2. Redistributions in binary form must reproduce the above copyright
1802ac6454SAndrew Thompson  *    notice, this list of conditions and the following disclaimer in the
1902ac6454SAndrew Thompson  *    documentation and/or other materials provided with the distribution.
2002ac6454SAndrew Thompson  *
2102ac6454SAndrew Thompson  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2202ac6454SAndrew Thompson  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2302ac6454SAndrew Thompson  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2402ac6454SAndrew Thompson  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2502ac6454SAndrew Thompson  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2602ac6454SAndrew Thompson  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2702ac6454SAndrew Thompson  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2802ac6454SAndrew Thompson  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2902ac6454SAndrew Thompson  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3002ac6454SAndrew Thompson  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3102ac6454SAndrew Thompson  * SUCH DAMAGE.
3202ac6454SAndrew Thompson  */
3302ac6454SAndrew Thompson 
3402ac6454SAndrew Thompson /*
355a92ac1dSEdward Tomasz Napierala  * This file contains the USB templates for an USB Media Transfer
3602ac6454SAndrew Thompson  * Protocol device.
3702ac6454SAndrew Thompson  *
3802ac6454SAndrew Thompson  * NOTE: It is common practice that MTP devices use some dummy
3902ac6454SAndrew Thompson  * descriptor cludges to be automatically detected by the host
4002ac6454SAndrew Thompson  * operating system. These descriptors are documented in the LibMTP
4102ac6454SAndrew Thompson  * library at sourceforge.net. The alternative is to supply the host
4202ac6454SAndrew Thompson  * operating system the VID and PID of your device.
4302ac6454SAndrew Thompson  */
4402ac6454SAndrew Thompson 
45d2b99310SHans Petter Selasky #ifdef USB_GLOBAL_INCLUDE_FILE
46d2b99310SHans Petter Selasky #include USB_GLOBAL_INCLUDE_FILE
47d2b99310SHans Petter Selasky #else
48ed6d949aSAndrew Thompson #include <sys/stdint.h>
49ed6d949aSAndrew Thompson #include <sys/stddef.h>
50ed6d949aSAndrew Thompson #include <sys/param.h>
51ed6d949aSAndrew Thompson #include <sys/queue.h>
52ed6d949aSAndrew Thompson #include <sys/types.h>
53ed6d949aSAndrew Thompson #include <sys/systm.h>
54ed6d949aSAndrew Thompson #include <sys/kernel.h>
55ed6d949aSAndrew Thompson #include <sys/bus.h>
56ed6d949aSAndrew Thompson #include <sys/module.h>
57ed6d949aSAndrew Thompson #include <sys/lock.h>
58ed6d949aSAndrew Thompson #include <sys/mutex.h>
59ed6d949aSAndrew Thompson #include <sys/condvar.h>
60ed6d949aSAndrew Thompson #include <sys/sysctl.h>
61ed6d949aSAndrew Thompson #include <sys/sx.h>
62ed6d949aSAndrew Thompson #include <sys/unistd.h>
63ed6d949aSAndrew Thompson #include <sys/callout.h>
64ed6d949aSAndrew Thompson #include <sys/malloc.h>
65ed6d949aSAndrew Thompson #include <sys/priv.h>
66ed6d949aSAndrew Thompson 
6702ac6454SAndrew Thompson #include <dev/usb/usb.h>
68ed6d949aSAndrew Thompson #include <dev/usb/usbdi.h>
6923ab0871SHans Petter Selasky #include <dev/usb/usb_core.h>
70*8e06491aSEdward Tomasz Napierala #include <dev/usb/usb_ioctl.h>
71*8e06491aSEdward Tomasz Napierala #include <dev/usb/usb_util.h>
7223ab0871SHans Petter Selasky 
7302ac6454SAndrew Thompson #include <dev/usb/template/usb_template.h>
74d2b99310SHans Petter Selasky #endif			/* USB_GLOBAL_INCLUDE_FILE */
7502ac6454SAndrew Thompson 
7602ac6454SAndrew Thompson #define	MTP_BREQUEST 0x08
7702ac6454SAndrew Thompson 
7802ac6454SAndrew Thompson enum {
79*8e06491aSEdward Tomasz Napierala 	MTP_LANG_INDEX,
80*8e06491aSEdward Tomasz Napierala 	MTP_INTERFACE_INDEX,
81*8e06491aSEdward Tomasz Napierala 	MTP_CONFIGURATION_INDEX,
82*8e06491aSEdward Tomasz Napierala 	MTP_MANUFACTURER_INDEX,
83*8e06491aSEdward Tomasz Napierala 	MTP_PRODUCT_INDEX,
84*8e06491aSEdward Tomasz Napierala 	MTP_SERIAL_NUMBER_INDEX,
85*8e06491aSEdward Tomasz Napierala 	MTP_MAX_INDEX,
8602ac6454SAndrew Thompson };
8702ac6454SAndrew Thompson 
88*8e06491aSEdward Tomasz Napierala #define	MTP_DEFAULT_INTERFACE		"USB MTP Interface"
89*8e06491aSEdward Tomasz Napierala #define	MTP_DEFAULT_CONFIGURATION	"Default Config"
90*8e06491aSEdward Tomasz Napierala #define	MTP_DEFAULT_MANUFACTURER	"FreeBSD foundation"
91*8e06491aSEdward Tomasz Napierala #define	MTP_DEFAULT_PRODUCT		"USB MTP"
92*8e06491aSEdward Tomasz Napierala #define	MTP_DEFAULT_SERIAL_NUMBER	"June 2008"
9302ac6454SAndrew Thompson 
94*8e06491aSEdward Tomasz Napierala static struct usb_string_descriptor	mtp_interface;
95*8e06491aSEdward Tomasz Napierala static struct usb_string_descriptor	mtp_configuration;
96*8e06491aSEdward Tomasz Napierala static struct usb_string_descriptor	mtp_manufacturer;
97*8e06491aSEdward Tomasz Napierala static struct usb_string_descriptor	mtp_product;
98*8e06491aSEdward Tomasz Napierala static struct usb_string_descriptor	mtp_serial_number;
9902ac6454SAndrew Thompson 
100*8e06491aSEdward Tomasz Napierala static struct sysctl_ctx_list		mtp_ctx_list;
10102ac6454SAndrew Thompson 
10202ac6454SAndrew Thompson /* prototypes */
10302ac6454SAndrew Thompson 
104a593f6b8SAndrew Thompson static usb_temp_get_string_desc_t mtp_get_string_desc;
105a593f6b8SAndrew Thompson static usb_temp_get_vendor_desc_t mtp_get_vendor_desc;
10602ac6454SAndrew Thompson 
107760bc48eSAndrew Thompson static const struct usb_temp_packet_size bulk_mps = {
10802ac6454SAndrew Thompson 	.mps[USB_SPEED_FULL] = 64,
10902ac6454SAndrew Thompson 	.mps[USB_SPEED_HIGH] = 512,
11002ac6454SAndrew Thompson };
11102ac6454SAndrew Thompson 
112760bc48eSAndrew Thompson static const struct usb_temp_packet_size intr_mps = {
11302ac6454SAndrew Thompson 	.mps[USB_SPEED_FULL] = 64,
11402ac6454SAndrew Thompson 	.mps[USB_SPEED_HIGH] = 64,
11502ac6454SAndrew Thompson };
11602ac6454SAndrew Thompson 
117760bc48eSAndrew Thompson static const struct usb_temp_endpoint_desc bulk_out_ep = {
11802ac6454SAndrew Thompson 	.pPacketSize = &bulk_mps,
11902ac6454SAndrew Thompson #ifdef USB_HIP_OUT_EP_0
12002ac6454SAndrew Thompson 	.bEndpointAddress = USB_HIP_OUT_EP_0,
12102ac6454SAndrew Thompson #else
12202ac6454SAndrew Thompson 	.bEndpointAddress = UE_DIR_OUT,
12302ac6454SAndrew Thompson #endif
12402ac6454SAndrew Thompson 	.bmAttributes = UE_BULK,
12502ac6454SAndrew Thompson };
12602ac6454SAndrew Thompson 
127760bc48eSAndrew Thompson static const struct usb_temp_endpoint_desc intr_in_ep = {
12802ac6454SAndrew Thompson 	.pPacketSize = &intr_mps,
12902ac6454SAndrew Thompson 	.bEndpointAddress = UE_DIR_IN,
13002ac6454SAndrew Thompson 	.bmAttributes = UE_INTERRUPT,
13102ac6454SAndrew Thompson };
13202ac6454SAndrew Thompson 
133760bc48eSAndrew Thompson static const struct usb_temp_endpoint_desc bulk_in_ep = {
13402ac6454SAndrew Thompson 	.pPacketSize = &bulk_mps,
13502ac6454SAndrew Thompson #ifdef USB_HIP_IN_EP_0
13602ac6454SAndrew Thompson 	.bEndpointAddress = USB_HIP_IN_EP_0,
13702ac6454SAndrew Thompson #else
13802ac6454SAndrew Thompson 	.bEndpointAddress = UE_DIR_IN,
13902ac6454SAndrew Thompson #endif
14002ac6454SAndrew Thompson 	.bmAttributes = UE_BULK,
14102ac6454SAndrew Thompson };
14202ac6454SAndrew Thompson 
143760bc48eSAndrew Thompson static const struct usb_temp_endpoint_desc *mtp_data_endpoints[] = {
14402ac6454SAndrew Thompson 	&bulk_in_ep,
14502ac6454SAndrew Thompson 	&bulk_out_ep,
14602ac6454SAndrew Thompson 	&intr_in_ep,
14702ac6454SAndrew Thompson 	NULL,
14802ac6454SAndrew Thompson };
14902ac6454SAndrew Thompson 
150760bc48eSAndrew Thompson static const struct usb_temp_interface_desc mtp_data_interface = {
15102ac6454SAndrew Thompson 	.ppEndpoints = mtp_data_endpoints,
15202ac6454SAndrew Thompson 	.bInterfaceClass = UICLASS_IMAGE,
15302ac6454SAndrew Thompson 	.bInterfaceSubClass = UISUBCLASS_SIC,	/* Still Image Class */
15402ac6454SAndrew Thompson 	.bInterfaceProtocol = 1,	/* PIMA 15740 */
155*8e06491aSEdward Tomasz Napierala 	.iInterface = MTP_INTERFACE_INDEX,
15602ac6454SAndrew Thompson };
15702ac6454SAndrew Thompson 
158760bc48eSAndrew Thompson static const struct usb_temp_interface_desc *mtp_interfaces[] = {
15902ac6454SAndrew Thompson 	&mtp_data_interface,
16002ac6454SAndrew Thompson 	NULL,
16102ac6454SAndrew Thompson };
16202ac6454SAndrew Thompson 
163760bc48eSAndrew Thompson static const struct usb_temp_config_desc mtp_config_desc = {
16402ac6454SAndrew Thompson 	.ppIfaceDesc = mtp_interfaces,
16502ac6454SAndrew Thompson 	.bmAttributes = UC_BUS_POWERED,
16602ac6454SAndrew Thompson 	.bMaxPower = 25,		/* 50 mA */
167*8e06491aSEdward Tomasz Napierala 	.iConfiguration = MTP_CONFIGURATION_INDEX,
16802ac6454SAndrew Thompson };
16902ac6454SAndrew Thompson 
170760bc48eSAndrew Thompson static const struct usb_temp_config_desc *mtp_configs[] = {
17102ac6454SAndrew Thompson 	&mtp_config_desc,
17202ac6454SAndrew Thompson 	NULL,
17302ac6454SAndrew Thompson };
17402ac6454SAndrew Thompson 
175*8e06491aSEdward Tomasz Napierala struct usb_temp_device_desc usb_template_mtp = {
17602ac6454SAndrew Thompson 	.getStringDesc = &mtp_get_string_desc,
17702ac6454SAndrew Thompson 	.getVendorDesc = &mtp_get_vendor_desc,
17802ac6454SAndrew Thompson 	.ppConfigDesc = mtp_configs,
179399e6543SHans Petter Selasky 	.idVendor = USB_TEMPLATE_VENDOR,
180399e6543SHans Petter Selasky 	.idProduct = 0x0011,
18102ac6454SAndrew Thompson 	.bcdDevice = 0x0100,
18202ac6454SAndrew Thompson 	.bDeviceClass = 0,
18302ac6454SAndrew Thompson 	.bDeviceSubClass = 0,
18402ac6454SAndrew Thompson 	.bDeviceProtocol = 0,
185*8e06491aSEdward Tomasz Napierala 	.iManufacturer = MTP_MANUFACTURER_INDEX,
186*8e06491aSEdward Tomasz Napierala 	.iProduct = MTP_PRODUCT_INDEX,
187*8e06491aSEdward Tomasz Napierala 	.iSerialNumber = MTP_SERIAL_NUMBER_INDEX,
18802ac6454SAndrew Thompson };
18902ac6454SAndrew Thompson 
19002ac6454SAndrew Thompson /*------------------------------------------------------------------------*
19102ac6454SAndrew Thompson  *	mtp_get_vendor_desc
19202ac6454SAndrew Thompson  *
19302ac6454SAndrew Thompson  * Return values:
19402ac6454SAndrew Thompson  * NULL: Failure. No such vendor descriptor.
19502ac6454SAndrew Thompson  * Else: Success. Pointer to vendor descriptor is returned.
19602ac6454SAndrew Thompson  *------------------------------------------------------------------------*/
19702ac6454SAndrew Thompson static const void *
1989a8e0122SAndrew Thompson mtp_get_vendor_desc(const struct usb_device_request *req, uint16_t *plen)
19902ac6454SAndrew Thompson {
20002ac6454SAndrew Thompson 	static const uint8_t dummy_desc[0x28] = {
20102ac6454SAndrew Thompson 		0x28, 0, 0, 0, 0, 1, 4, 0,
20202ac6454SAndrew Thompson 		1, 0, 0, 0, 0, 0, 0, 0,
20302ac6454SAndrew Thompson 		0, 1, 0x4D, 0x54, 0x50, 0, 0, 0,
20402ac6454SAndrew Thompson 		0, 0, 0, 0, 0, 0, 0, 0,
20502ac6454SAndrew Thompson 		0, 0, 0, 0, 0, 0, 0, 0,
20602ac6454SAndrew Thompson 	};
20702ac6454SAndrew Thompson 
20802ac6454SAndrew Thompson 	if ((req->bmRequestType == UT_READ_VENDOR_DEVICE) &&
20902ac6454SAndrew Thompson 	    (req->bRequest == MTP_BREQUEST) && (req->wValue[0] == 0) &&
21002ac6454SAndrew Thompson 	    (req->wValue[1] == 0) && (req->wIndex[1] == 0) &&
21102ac6454SAndrew Thompson 	    ((req->wIndex[0] == 4) || (req->wIndex[0] == 5))) {
21202ac6454SAndrew Thompson 		/*
21302ac6454SAndrew Thompson 		 * By returning this descriptor LibMTP will
21402ac6454SAndrew Thompson 		 * automatically pickup our device.
21502ac6454SAndrew Thompson 		 */
21602ac6454SAndrew Thompson 		return (dummy_desc);
21702ac6454SAndrew Thompson 	}
21802ac6454SAndrew Thompson 	return (NULL);
21902ac6454SAndrew Thompson }
22002ac6454SAndrew Thompson 
22102ac6454SAndrew Thompson /*------------------------------------------------------------------------*
22202ac6454SAndrew Thompson  *	mtp_get_string_desc
22302ac6454SAndrew Thompson  *
22402ac6454SAndrew Thompson  * Return values:
22502ac6454SAndrew Thompson  * NULL: Failure. No such string.
22602ac6454SAndrew Thompson  * Else: Success. Pointer to string descriptor is returned.
22702ac6454SAndrew Thompson  *------------------------------------------------------------------------*/
22802ac6454SAndrew Thompson static const void *
22902ac6454SAndrew Thompson mtp_get_string_desc(uint16_t lang_id, uint8_t string_index)
23002ac6454SAndrew Thompson {
231*8e06491aSEdward Tomasz Napierala 	static const void *ptr[MTP_MAX_INDEX] = {
232*8e06491aSEdward Tomasz Napierala 		[MTP_LANG_INDEX] = &usb_string_lang_en,
233*8e06491aSEdward Tomasz Napierala 		[MTP_INTERFACE_INDEX] = &mtp_interface,
234*8e06491aSEdward Tomasz Napierala 		[MTP_CONFIGURATION_INDEX] = &mtp_configuration,
235*8e06491aSEdward Tomasz Napierala 		[MTP_MANUFACTURER_INDEX] = &mtp_manufacturer,
236*8e06491aSEdward Tomasz Napierala 		[MTP_PRODUCT_INDEX] = &mtp_product,
237*8e06491aSEdward Tomasz Napierala 		[MTP_SERIAL_NUMBER_INDEX] = &mtp_serial_number,
23802ac6454SAndrew Thompson 	};
23902ac6454SAndrew Thompson 
24002ac6454SAndrew Thompson 	static const uint8_t dummy_desc[0x12] = {
24102ac6454SAndrew Thompson 		0x12, 0x03, 0x4D, 0x00, 0x53, 0x00, 0x46, 0x00,
24202ac6454SAndrew Thompson 		0x54, 0x00, 0x31, 0x00, 0x30, 0x00, 0x30, 0x00,
24302ac6454SAndrew Thompson 		MTP_BREQUEST, 0x00,
24402ac6454SAndrew Thompson 	};
24502ac6454SAndrew Thompson 
24602ac6454SAndrew Thompson 	if (string_index == 0xEE) {
24702ac6454SAndrew Thompson 		/*
24802ac6454SAndrew Thompson 		 * By returning this string LibMTP will automatically
24902ac6454SAndrew Thompson 		 * pickup our device.
25002ac6454SAndrew Thompson 		 */
25102ac6454SAndrew Thompson 		return (dummy_desc);
25202ac6454SAndrew Thompson 	}
25302ac6454SAndrew Thompson 	if (string_index == 0) {
25423ab0871SHans Petter Selasky 		return (&usb_string_lang_en);
25502ac6454SAndrew Thompson 	}
25602ac6454SAndrew Thompson 	if (lang_id != 0x0409) {
25702ac6454SAndrew Thompson 		return (NULL);
25802ac6454SAndrew Thompson 	}
259*8e06491aSEdward Tomasz Napierala 	if (string_index < MTP_MAX_INDEX) {
26002ac6454SAndrew Thompson 		return (ptr[string_index]);
26102ac6454SAndrew Thompson 	}
26202ac6454SAndrew Thompson 	return (NULL);
26302ac6454SAndrew Thompson }
264*8e06491aSEdward Tomasz Napierala 
265*8e06491aSEdward Tomasz Napierala static void
266*8e06491aSEdward Tomasz Napierala mtp_init(void *arg __unused)
267*8e06491aSEdward Tomasz Napierala {
268*8e06491aSEdward Tomasz Napierala 	struct sysctl_oid *parent;
269*8e06491aSEdward Tomasz Napierala 	char parent_name[3];
270*8e06491aSEdward Tomasz Napierala 
271*8e06491aSEdward Tomasz Napierala 	usb_make_str_desc(&mtp_interface, sizeof(mtp_interface),
272*8e06491aSEdward Tomasz Napierala 	    MTP_DEFAULT_INTERFACE);
273*8e06491aSEdward Tomasz Napierala 	usb_make_str_desc(&mtp_configuration, sizeof(mtp_configuration),
274*8e06491aSEdward Tomasz Napierala 	    MTP_DEFAULT_CONFIGURATION);
275*8e06491aSEdward Tomasz Napierala 	usb_make_str_desc(&mtp_manufacturer, sizeof(mtp_manufacturer),
276*8e06491aSEdward Tomasz Napierala 	    MTP_DEFAULT_MANUFACTURER);
277*8e06491aSEdward Tomasz Napierala 	usb_make_str_desc(&mtp_product, sizeof(mtp_product),
278*8e06491aSEdward Tomasz Napierala 	    MTP_DEFAULT_PRODUCT);
279*8e06491aSEdward Tomasz Napierala 	usb_make_str_desc(&mtp_serial_number, sizeof(mtp_serial_number),
280*8e06491aSEdward Tomasz Napierala 	    MTP_DEFAULT_SERIAL_NUMBER);
281*8e06491aSEdward Tomasz Napierala 
282*8e06491aSEdward Tomasz Napierala 	snprintf(parent_name, sizeof(parent_name), "%d", USB_TEMP_MTP);
283*8e06491aSEdward Tomasz Napierala 	sysctl_ctx_init(&mtp_ctx_list);
284*8e06491aSEdward Tomasz Napierala 
285*8e06491aSEdward Tomasz Napierala 	parent = SYSCTL_ADD_NODE(&mtp_ctx_list,
286*8e06491aSEdward Tomasz Napierala 	    SYSCTL_STATIC_CHILDREN(_hw_usb_templates), OID_AUTO,
287*8e06491aSEdward Tomasz Napierala 	    parent_name, CTLFLAG_RW,
288*8e06491aSEdward Tomasz Napierala 	    0, "USB Media Transfer Protocol device side template");
289*8e06491aSEdward Tomasz Napierala 	SYSCTL_ADD_U16(&mtp_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
290*8e06491aSEdward Tomasz Napierala 	    "vendor_id", CTLFLAG_RWTUN,
291*8e06491aSEdward Tomasz Napierala 	    &usb_template_mtp.idVendor, 1, "Vendor identifier");
292*8e06491aSEdward Tomasz Napierala 	SYSCTL_ADD_U16(&mtp_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
293*8e06491aSEdward Tomasz Napierala 	    "product_id", CTLFLAG_RWTUN,
294*8e06491aSEdward Tomasz Napierala 	    &usb_template_mtp.idProduct, 1, "Product identifier");
295*8e06491aSEdward Tomasz Napierala #if 0
296*8e06491aSEdward Tomasz Napierala 	SYSCTL_ADD_PROC(&mtp_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
297*8e06491aSEdward Tomasz Napierala 	    "interface", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
298*8e06491aSEdward Tomasz Napierala 	    &mtp_interface, sizeof(mtp_interface), usb_temp_sysctl,
299*8e06491aSEdward Tomasz Napierala 	    "A", "Interface string");
300*8e06491aSEdward Tomasz Napierala 	SYSCTL_ADD_PROC(&mtp_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
301*8e06491aSEdward Tomasz Napierala 	    "configuration", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
302*8e06491aSEdward Tomasz Napierala 	    &mtp_configuration, sizeof(mtp_configuration), usb_temp_sysctl,
303*8e06491aSEdward Tomasz Napierala 	    "A", "Configuration string");
304*8e06491aSEdward Tomasz Napierala #endif
305*8e06491aSEdward Tomasz Napierala 	SYSCTL_ADD_PROC(&mtp_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
306*8e06491aSEdward Tomasz Napierala 	    "manufacturer", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
307*8e06491aSEdward Tomasz Napierala 	    &mtp_manufacturer, sizeof(mtp_manufacturer), usb_temp_sysctl,
308*8e06491aSEdward Tomasz Napierala 	    "A", "Manufacturer string");
309*8e06491aSEdward Tomasz Napierala 	SYSCTL_ADD_PROC(&mtp_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
310*8e06491aSEdward Tomasz Napierala 	    "product", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
311*8e06491aSEdward Tomasz Napierala 	    &mtp_product, sizeof(mtp_product), usb_temp_sysctl,
312*8e06491aSEdward Tomasz Napierala 	    "A", "Product string");
313*8e06491aSEdward Tomasz Napierala 	SYSCTL_ADD_PROC(&mtp_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
314*8e06491aSEdward Tomasz Napierala 	    "serial_number", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
315*8e06491aSEdward Tomasz Napierala 	    &mtp_serial_number, sizeof(mtp_serial_number), usb_temp_sysctl,
316*8e06491aSEdward Tomasz Napierala 	    "A", "Serial number string");
317*8e06491aSEdward Tomasz Napierala }
318*8e06491aSEdward Tomasz Napierala 
319*8e06491aSEdward Tomasz Napierala static void
320*8e06491aSEdward Tomasz Napierala mtp_uninit(void *arg __unused)
321*8e06491aSEdward Tomasz Napierala {
322*8e06491aSEdward Tomasz Napierala 
323*8e06491aSEdward Tomasz Napierala 	sysctl_ctx_free(&mtp_ctx_list);
324*8e06491aSEdward Tomasz Napierala }
325*8e06491aSEdward Tomasz Napierala 
326*8e06491aSEdward Tomasz Napierala SYSINIT(mtp_init, SI_SUB_LOCK, SI_ORDER_FIRST, mtp_init, NULL);
327*8e06491aSEdward Tomasz Napierala SYSUNINIT(mtp_init, SI_SUB_LOCK, SI_ORDER_FIRST, mtp_uninit, NULL);
328