102ac6454SAndrew Thompson /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
3718cf2ccSPedro F. Giffuni *
45d38a4d4SEd Schouten * Copyright (c) 2008 Hans Petter Selasky <hselasky@FreeBSD.org>
58e06491aSEdward Tomasz Napierala * Copyright (c) 2018 The FreeBSD Foundation
602ac6454SAndrew Thompson * All rights reserved.
702ac6454SAndrew Thompson *
88e06491aSEdward Tomasz Napierala * Portions of this software were developed by Edward Tomasz Napierala
98e06491aSEdward Tomasz Napierala * under sponsorship from the FreeBSD Foundation.
108e06491aSEdward Tomasz Napierala *
1102ac6454SAndrew Thompson * Redistribution and use in source and binary forms, with or without
1202ac6454SAndrew Thompson * modification, are permitted provided that the following conditions
1302ac6454SAndrew Thompson * are met:
1402ac6454SAndrew Thompson * 1. Redistributions of source code must retain the above copyright
1502ac6454SAndrew Thompson * notice, this list of conditions and the following disclaimer.
1602ac6454SAndrew Thompson * 2. Redistributions in binary form must reproduce the above copyright
1702ac6454SAndrew Thompson * notice, this list of conditions and the following disclaimer in the
1802ac6454SAndrew Thompson * documentation and/or other materials provided with the distribution.
1902ac6454SAndrew Thompson *
2002ac6454SAndrew Thompson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2102ac6454SAndrew Thompson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2202ac6454SAndrew Thompson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2302ac6454SAndrew Thompson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2402ac6454SAndrew Thompson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2502ac6454SAndrew Thompson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2602ac6454SAndrew Thompson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2702ac6454SAndrew Thompson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2802ac6454SAndrew Thompson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2902ac6454SAndrew Thompson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3002ac6454SAndrew Thompson * SUCH DAMAGE.
3102ac6454SAndrew Thompson */
3202ac6454SAndrew Thompson
3302ac6454SAndrew Thompson /*
345a92ac1dSEdward Tomasz Napierala * This file contains the USB templates for an USB Media Transfer
3502ac6454SAndrew Thompson * Protocol device.
3602ac6454SAndrew Thompson *
3702ac6454SAndrew Thompson * NOTE: It is common practice that MTP devices use some dummy
3802ac6454SAndrew Thompson * descriptor cludges to be automatically detected by the host
3902ac6454SAndrew Thompson * operating system. These descriptors are documented in the LibMTP
4002ac6454SAndrew Thompson * library at sourceforge.net. The alternative is to supply the host
4102ac6454SAndrew Thompson * operating system the VID and PID of your device.
4202ac6454SAndrew Thompson */
4302ac6454SAndrew Thompson
44d2b99310SHans Petter Selasky #ifdef USB_GLOBAL_INCLUDE_FILE
45d2b99310SHans Petter Selasky #include USB_GLOBAL_INCLUDE_FILE
46d2b99310SHans Petter Selasky #else
47ed6d949aSAndrew Thompson #include <sys/stdint.h>
48ed6d949aSAndrew Thompson #include <sys/stddef.h>
49ed6d949aSAndrew Thompson #include <sys/param.h>
50ed6d949aSAndrew Thompson #include <sys/queue.h>
51ed6d949aSAndrew Thompson #include <sys/types.h>
52ed6d949aSAndrew Thompson #include <sys/systm.h>
53ed6d949aSAndrew Thompson #include <sys/kernel.h>
54ed6d949aSAndrew Thompson #include <sys/bus.h>
55ed6d949aSAndrew Thompson #include <sys/module.h>
56ed6d949aSAndrew Thompson #include <sys/lock.h>
57ed6d949aSAndrew Thompson #include <sys/mutex.h>
58ed6d949aSAndrew Thompson #include <sys/condvar.h>
59ed6d949aSAndrew Thompson #include <sys/sysctl.h>
60ed6d949aSAndrew Thompson #include <sys/sx.h>
61ed6d949aSAndrew Thompson #include <sys/unistd.h>
62ed6d949aSAndrew Thompson #include <sys/callout.h>
63ed6d949aSAndrew Thompson #include <sys/malloc.h>
64ed6d949aSAndrew Thompson #include <sys/priv.h>
65ed6d949aSAndrew Thompson
6602ac6454SAndrew Thompson #include <dev/usb/usb.h>
67ed6d949aSAndrew Thompson #include <dev/usb/usbdi.h>
6823ab0871SHans Petter Selasky #include <dev/usb/usb_core.h>
698e06491aSEdward Tomasz Napierala #include <dev/usb/usb_ioctl.h>
708e06491aSEdward Tomasz Napierala #include <dev/usb/usb_util.h>
7123ab0871SHans Petter Selasky
7202ac6454SAndrew Thompson #include <dev/usb/template/usb_template.h>
73d2b99310SHans Petter Selasky #endif /* USB_GLOBAL_INCLUDE_FILE */
7402ac6454SAndrew Thompson
7502ac6454SAndrew Thompson #define MTP_BREQUEST 0x08
7602ac6454SAndrew Thompson
7702ac6454SAndrew Thompson enum {
788e06491aSEdward Tomasz Napierala MTP_LANG_INDEX,
798e06491aSEdward Tomasz Napierala MTP_INTERFACE_INDEX,
808e06491aSEdward Tomasz Napierala MTP_CONFIGURATION_INDEX,
818e06491aSEdward Tomasz Napierala MTP_MANUFACTURER_INDEX,
828e06491aSEdward Tomasz Napierala MTP_PRODUCT_INDEX,
838e06491aSEdward Tomasz Napierala MTP_SERIAL_NUMBER_INDEX,
848e06491aSEdward Tomasz Napierala MTP_MAX_INDEX,
8502ac6454SAndrew Thompson };
8602ac6454SAndrew Thompson
871558eec6SEdward Tomasz Napierala #define MTP_DEFAULT_VENDOR_ID USB_TEMPLATE_VENDOR
88defd918dSEdward Tomasz Napierala #define MTP_DEFAULT_PRODUCT_ID 0x27e2
898e06491aSEdward Tomasz Napierala #define MTP_DEFAULT_INTERFACE "USB MTP Interface"
908e06491aSEdward Tomasz Napierala #define MTP_DEFAULT_CONFIGURATION "Default Config"
91d01c1c8bSEdward Tomasz Napierala #define MTP_DEFAULT_MANUFACTURER USB_TEMPLATE_MANUFACTURER
928e06491aSEdward Tomasz Napierala #define MTP_DEFAULT_PRODUCT "USB MTP"
938e06491aSEdward Tomasz Napierala #define MTP_DEFAULT_SERIAL_NUMBER "June 2008"
9402ac6454SAndrew Thompson
958e06491aSEdward Tomasz Napierala static struct usb_string_descriptor mtp_interface;
968e06491aSEdward Tomasz Napierala static struct usb_string_descriptor mtp_configuration;
978e06491aSEdward Tomasz Napierala static struct usb_string_descriptor mtp_manufacturer;
988e06491aSEdward Tomasz Napierala static struct usb_string_descriptor mtp_product;
998e06491aSEdward Tomasz Napierala static struct usb_string_descriptor mtp_serial_number;
10002ac6454SAndrew Thompson
1018e06491aSEdward Tomasz Napierala static struct sysctl_ctx_list mtp_ctx_list;
10202ac6454SAndrew Thompson
10302ac6454SAndrew Thompson /* prototypes */
10402ac6454SAndrew Thompson
105a593f6b8SAndrew Thompson static usb_temp_get_string_desc_t mtp_get_string_desc;
106a593f6b8SAndrew Thompson static usb_temp_get_vendor_desc_t mtp_get_vendor_desc;
10702ac6454SAndrew Thompson
108760bc48eSAndrew Thompson static const struct usb_temp_packet_size bulk_mps = {
10902ac6454SAndrew Thompson .mps[USB_SPEED_FULL] = 64,
11002ac6454SAndrew Thompson .mps[USB_SPEED_HIGH] = 512,
11102ac6454SAndrew Thompson };
11202ac6454SAndrew Thompson
113760bc48eSAndrew Thompson static const struct usb_temp_packet_size intr_mps = {
11402ac6454SAndrew Thompson .mps[USB_SPEED_FULL] = 64,
11502ac6454SAndrew Thompson .mps[USB_SPEED_HIGH] = 64,
11602ac6454SAndrew Thompson };
11702ac6454SAndrew Thompson
118760bc48eSAndrew Thompson static const struct usb_temp_endpoint_desc bulk_out_ep = {
11902ac6454SAndrew Thompson .pPacketSize = &bulk_mps,
12002ac6454SAndrew Thompson #ifdef USB_HIP_OUT_EP_0
12102ac6454SAndrew Thompson .bEndpointAddress = USB_HIP_OUT_EP_0,
12202ac6454SAndrew Thompson #else
12302ac6454SAndrew Thompson .bEndpointAddress = UE_DIR_OUT,
12402ac6454SAndrew Thompson #endif
12502ac6454SAndrew Thompson .bmAttributes = UE_BULK,
12602ac6454SAndrew Thompson };
12702ac6454SAndrew Thompson
128760bc48eSAndrew Thompson static const struct usb_temp_endpoint_desc intr_in_ep = {
12902ac6454SAndrew Thompson .pPacketSize = &intr_mps,
13002ac6454SAndrew Thompson .bEndpointAddress = UE_DIR_IN,
13102ac6454SAndrew Thompson .bmAttributes = UE_INTERRUPT,
13202ac6454SAndrew Thompson };
13302ac6454SAndrew Thompson
134760bc48eSAndrew Thompson static const struct usb_temp_endpoint_desc bulk_in_ep = {
13502ac6454SAndrew Thompson .pPacketSize = &bulk_mps,
13602ac6454SAndrew Thompson #ifdef USB_HIP_IN_EP_0
13702ac6454SAndrew Thompson .bEndpointAddress = USB_HIP_IN_EP_0,
13802ac6454SAndrew Thompson #else
13902ac6454SAndrew Thompson .bEndpointAddress = UE_DIR_IN,
14002ac6454SAndrew Thompson #endif
14102ac6454SAndrew Thompson .bmAttributes = UE_BULK,
14202ac6454SAndrew Thompson };
14302ac6454SAndrew Thompson
144760bc48eSAndrew Thompson static const struct usb_temp_endpoint_desc *mtp_data_endpoints[] = {
14502ac6454SAndrew Thompson &bulk_in_ep,
14602ac6454SAndrew Thompson &bulk_out_ep,
14702ac6454SAndrew Thompson &intr_in_ep,
14802ac6454SAndrew Thompson NULL,
14902ac6454SAndrew Thompson };
15002ac6454SAndrew Thompson
151760bc48eSAndrew Thompson static const struct usb_temp_interface_desc mtp_data_interface = {
15202ac6454SAndrew Thompson .ppEndpoints = mtp_data_endpoints,
15302ac6454SAndrew Thompson .bInterfaceClass = UICLASS_IMAGE,
15402ac6454SAndrew Thompson .bInterfaceSubClass = UISUBCLASS_SIC, /* Still Image Class */
15502ac6454SAndrew Thompson .bInterfaceProtocol = 1, /* PIMA 15740 */
1568e06491aSEdward Tomasz Napierala .iInterface = MTP_INTERFACE_INDEX,
15702ac6454SAndrew Thompson };
15802ac6454SAndrew Thompson
159760bc48eSAndrew Thompson static const struct usb_temp_interface_desc *mtp_interfaces[] = {
16002ac6454SAndrew Thompson &mtp_data_interface,
16102ac6454SAndrew Thompson NULL,
16202ac6454SAndrew Thompson };
16302ac6454SAndrew Thompson
164760bc48eSAndrew Thompson static const struct usb_temp_config_desc mtp_config_desc = {
16502ac6454SAndrew Thompson .ppIfaceDesc = mtp_interfaces,
166d008c0d7SEdward Tomasz Napierala .bmAttributes = 0,
167d008c0d7SEdward Tomasz Napierala .bMaxPower = 0,
1688e06491aSEdward Tomasz Napierala .iConfiguration = MTP_CONFIGURATION_INDEX,
16902ac6454SAndrew Thompson };
17002ac6454SAndrew Thompson
171760bc48eSAndrew Thompson static const struct usb_temp_config_desc *mtp_configs[] = {
17202ac6454SAndrew Thompson &mtp_config_desc,
17302ac6454SAndrew Thompson NULL,
17402ac6454SAndrew Thompson };
17502ac6454SAndrew Thompson
1768e06491aSEdward Tomasz Napierala struct usb_temp_device_desc usb_template_mtp = {
17702ac6454SAndrew Thompson .getStringDesc = &mtp_get_string_desc,
17802ac6454SAndrew Thompson .getVendorDesc = &mtp_get_vendor_desc,
17902ac6454SAndrew Thompson .ppConfigDesc = mtp_configs,
1801558eec6SEdward Tomasz Napierala .idVendor = MTP_DEFAULT_VENDOR_ID,
1811558eec6SEdward Tomasz Napierala .idProduct = MTP_DEFAULT_PRODUCT_ID,
18202ac6454SAndrew Thompson .bcdDevice = 0x0100,
18302ac6454SAndrew Thompson .bDeviceClass = 0,
18402ac6454SAndrew Thompson .bDeviceSubClass = 0,
18502ac6454SAndrew Thompson .bDeviceProtocol = 0,
1868e06491aSEdward Tomasz Napierala .iManufacturer = MTP_MANUFACTURER_INDEX,
1878e06491aSEdward Tomasz Napierala .iProduct = MTP_PRODUCT_INDEX,
1888e06491aSEdward Tomasz Napierala .iSerialNumber = MTP_SERIAL_NUMBER_INDEX,
18902ac6454SAndrew Thompson };
19002ac6454SAndrew Thompson
19102ac6454SAndrew Thompson /*------------------------------------------------------------------------*
19202ac6454SAndrew Thompson * mtp_get_vendor_desc
19302ac6454SAndrew Thompson *
19402ac6454SAndrew Thompson * Return values:
19502ac6454SAndrew Thompson * NULL: Failure. No such vendor descriptor.
19602ac6454SAndrew Thompson * Else: Success. Pointer to vendor descriptor is returned.
19702ac6454SAndrew Thompson *------------------------------------------------------------------------*/
19802ac6454SAndrew Thompson static const void *
mtp_get_vendor_desc(const struct usb_device_request * req,uint16_t * plen)1999a8e0122SAndrew Thompson mtp_get_vendor_desc(const struct usb_device_request *req, uint16_t *plen)
20002ac6454SAndrew Thompson {
20102ac6454SAndrew Thompson static const uint8_t dummy_desc[0x28] = {
20202ac6454SAndrew Thompson 0x28, 0, 0, 0, 0, 1, 4, 0,
20302ac6454SAndrew Thompson 1, 0, 0, 0, 0, 0, 0, 0,
20402ac6454SAndrew Thompson 0, 1, 0x4D, 0x54, 0x50, 0, 0, 0,
20502ac6454SAndrew Thompson 0, 0, 0, 0, 0, 0, 0, 0,
20602ac6454SAndrew Thompson 0, 0, 0, 0, 0, 0, 0, 0,
20702ac6454SAndrew Thompson };
20802ac6454SAndrew Thompson
20902ac6454SAndrew Thompson if ((req->bmRequestType == UT_READ_VENDOR_DEVICE) &&
21002ac6454SAndrew Thompson (req->bRequest == MTP_BREQUEST) && (req->wValue[0] == 0) &&
21102ac6454SAndrew Thompson (req->wValue[1] == 0) && (req->wIndex[1] == 0) &&
21202ac6454SAndrew Thompson ((req->wIndex[0] == 4) || (req->wIndex[0] == 5))) {
21302ac6454SAndrew Thompson /*
21402ac6454SAndrew Thompson * By returning this descriptor LibMTP will
21502ac6454SAndrew Thompson * automatically pickup our device.
21602ac6454SAndrew Thompson */
21702ac6454SAndrew Thompson return (dummy_desc);
21802ac6454SAndrew Thompson }
21902ac6454SAndrew Thompson return (NULL);
22002ac6454SAndrew Thompson }
22102ac6454SAndrew Thompson
22202ac6454SAndrew Thompson /*------------------------------------------------------------------------*
22302ac6454SAndrew Thompson * mtp_get_string_desc
22402ac6454SAndrew Thompson *
22502ac6454SAndrew Thompson * Return values:
22602ac6454SAndrew Thompson * NULL: Failure. No such string.
22702ac6454SAndrew Thompson * Else: Success. Pointer to string descriptor is returned.
22802ac6454SAndrew Thompson *------------------------------------------------------------------------*/
22902ac6454SAndrew Thompson static const void *
mtp_get_string_desc(uint16_t lang_id,uint8_t string_index)23002ac6454SAndrew Thompson mtp_get_string_desc(uint16_t lang_id, uint8_t string_index)
23102ac6454SAndrew Thompson {
2328e06491aSEdward Tomasz Napierala static const void *ptr[MTP_MAX_INDEX] = {
2338e06491aSEdward Tomasz Napierala [MTP_LANG_INDEX] = &usb_string_lang_en,
2348e06491aSEdward Tomasz Napierala [MTP_INTERFACE_INDEX] = &mtp_interface,
2358e06491aSEdward Tomasz Napierala [MTP_CONFIGURATION_INDEX] = &mtp_configuration,
2368e06491aSEdward Tomasz Napierala [MTP_MANUFACTURER_INDEX] = &mtp_manufacturer,
2378e06491aSEdward Tomasz Napierala [MTP_PRODUCT_INDEX] = &mtp_product,
2388e06491aSEdward Tomasz Napierala [MTP_SERIAL_NUMBER_INDEX] = &mtp_serial_number,
23902ac6454SAndrew Thompson };
24002ac6454SAndrew Thompson
24102ac6454SAndrew Thompson static const uint8_t dummy_desc[0x12] = {
24202ac6454SAndrew Thompson 0x12, 0x03, 0x4D, 0x00, 0x53, 0x00, 0x46, 0x00,
24302ac6454SAndrew Thompson 0x54, 0x00, 0x31, 0x00, 0x30, 0x00, 0x30, 0x00,
24402ac6454SAndrew Thompson MTP_BREQUEST, 0x00,
24502ac6454SAndrew Thompson };
24602ac6454SAndrew Thompson
24702ac6454SAndrew Thompson if (string_index == 0xEE) {
24802ac6454SAndrew Thompson /*
24902ac6454SAndrew Thompson * By returning this string LibMTP will automatically
25002ac6454SAndrew Thompson * pickup our device.
25102ac6454SAndrew Thompson */
25202ac6454SAndrew Thompson return (dummy_desc);
25302ac6454SAndrew Thompson }
25402ac6454SAndrew Thompson if (string_index == 0) {
25523ab0871SHans Petter Selasky return (&usb_string_lang_en);
25602ac6454SAndrew Thompson }
25702ac6454SAndrew Thompson if (lang_id != 0x0409) {
25802ac6454SAndrew Thompson return (NULL);
25902ac6454SAndrew Thompson }
2608e06491aSEdward Tomasz Napierala if (string_index < MTP_MAX_INDEX) {
26102ac6454SAndrew Thompson return (ptr[string_index]);
26202ac6454SAndrew Thompson }
26302ac6454SAndrew Thompson return (NULL);
26402ac6454SAndrew Thompson }
2658e06491aSEdward Tomasz Napierala
2668e06491aSEdward Tomasz Napierala static void
mtp_init(void * arg __unused)2678e06491aSEdward Tomasz Napierala mtp_init(void *arg __unused)
2688e06491aSEdward Tomasz Napierala {
2698e06491aSEdward Tomasz Napierala struct sysctl_oid *parent;
2708e06491aSEdward Tomasz Napierala char parent_name[3];
2718e06491aSEdward Tomasz Napierala
2728e06491aSEdward Tomasz Napierala usb_make_str_desc(&mtp_interface, sizeof(mtp_interface),
2738e06491aSEdward Tomasz Napierala MTP_DEFAULT_INTERFACE);
2748e06491aSEdward Tomasz Napierala usb_make_str_desc(&mtp_configuration, sizeof(mtp_configuration),
2758e06491aSEdward Tomasz Napierala MTP_DEFAULT_CONFIGURATION);
2768e06491aSEdward Tomasz Napierala usb_make_str_desc(&mtp_manufacturer, sizeof(mtp_manufacturer),
2778e06491aSEdward Tomasz Napierala MTP_DEFAULT_MANUFACTURER);
2788e06491aSEdward Tomasz Napierala usb_make_str_desc(&mtp_product, sizeof(mtp_product),
2798e06491aSEdward Tomasz Napierala MTP_DEFAULT_PRODUCT);
2808e06491aSEdward Tomasz Napierala usb_make_str_desc(&mtp_serial_number, sizeof(mtp_serial_number),
2818e06491aSEdward Tomasz Napierala MTP_DEFAULT_SERIAL_NUMBER);
2828e06491aSEdward Tomasz Napierala
2838e06491aSEdward Tomasz Napierala snprintf(parent_name, sizeof(parent_name), "%d", USB_TEMP_MTP);
2848e06491aSEdward Tomasz Napierala sysctl_ctx_init(&mtp_ctx_list);
2858e06491aSEdward Tomasz Napierala
2868e06491aSEdward Tomasz Napierala parent = SYSCTL_ADD_NODE(&mtp_ctx_list,
2878e06491aSEdward Tomasz Napierala SYSCTL_STATIC_CHILDREN(_hw_usb_templates), OID_AUTO,
288f8d2b1f3SPawel Biernacki parent_name, CTLFLAG_RW | CTLFLAG_MPSAFE,
2898e06491aSEdward Tomasz Napierala 0, "USB Media Transfer Protocol device side template");
2908e06491aSEdward Tomasz Napierala SYSCTL_ADD_U16(&mtp_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
2918e06491aSEdward Tomasz Napierala "vendor_id", CTLFLAG_RWTUN,
2928e06491aSEdward Tomasz Napierala &usb_template_mtp.idVendor, 1, "Vendor identifier");
2938e06491aSEdward Tomasz Napierala SYSCTL_ADD_U16(&mtp_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
2948e06491aSEdward Tomasz Napierala "product_id", CTLFLAG_RWTUN,
2958e06491aSEdward Tomasz Napierala &usb_template_mtp.idProduct, 1, "Product identifier");
2968e06491aSEdward Tomasz Napierala #if 0
2978e06491aSEdward Tomasz Napierala SYSCTL_ADD_PROC(&mtp_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
2988e06491aSEdward Tomasz Napierala "interface", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
2998e06491aSEdward Tomasz Napierala &mtp_interface, sizeof(mtp_interface), usb_temp_sysctl,
3008e06491aSEdward Tomasz Napierala "A", "Interface string");
3018e06491aSEdward Tomasz Napierala SYSCTL_ADD_PROC(&mtp_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
3028e06491aSEdward Tomasz Napierala "configuration", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
3038e06491aSEdward Tomasz Napierala &mtp_configuration, sizeof(mtp_configuration), usb_temp_sysctl,
3048e06491aSEdward Tomasz Napierala "A", "Configuration string");
3058e06491aSEdward Tomasz Napierala #endif
3068e06491aSEdward Tomasz Napierala SYSCTL_ADD_PROC(&mtp_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
3078e06491aSEdward Tomasz Napierala "manufacturer", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
3088e06491aSEdward Tomasz Napierala &mtp_manufacturer, sizeof(mtp_manufacturer), usb_temp_sysctl,
3098e06491aSEdward Tomasz Napierala "A", "Manufacturer string");
3108e06491aSEdward Tomasz Napierala SYSCTL_ADD_PROC(&mtp_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
3118e06491aSEdward Tomasz Napierala "product", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
3128e06491aSEdward Tomasz Napierala &mtp_product, sizeof(mtp_product), usb_temp_sysctl,
3138e06491aSEdward Tomasz Napierala "A", "Product string");
3148e06491aSEdward Tomasz Napierala SYSCTL_ADD_PROC(&mtp_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
3158e06491aSEdward Tomasz Napierala "serial_number", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
3168e06491aSEdward Tomasz Napierala &mtp_serial_number, sizeof(mtp_serial_number), usb_temp_sysctl,
3178e06491aSEdward Tomasz Napierala "A", "Serial number string");
3188e06491aSEdward Tomasz Napierala }
3198e06491aSEdward Tomasz Napierala
3208e06491aSEdward Tomasz Napierala static void
mtp_uninit(void * arg __unused)3218e06491aSEdward Tomasz Napierala mtp_uninit(void *arg __unused)
3228e06491aSEdward Tomasz Napierala {
3238e06491aSEdward Tomasz Napierala
3248e06491aSEdward Tomasz Napierala sysctl_ctx_free(&mtp_ctx_list);
3258e06491aSEdward Tomasz Napierala }
3268e06491aSEdward Tomasz Napierala
3278e06491aSEdward Tomasz Napierala SYSINIT(mtp_init, SI_SUB_LOCK, SI_ORDER_FIRST, mtp_init, NULL);
328c70e38e4SHans Petter Selasky SYSUNINIT(mtp_uninit, SI_SUB_LOCK, SI_ORDER_FIRST, mtp_uninit, NULL);
329