The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/usb/template/usb_template_mtp.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* $FreeBSD$ */
    2 /*-
    3  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    4  *
    5  * Copyright (c) 2008 Hans Petter Selasky <hselasky@FreeBSD.org>
    6  * Copyright (c) 2018 The FreeBSD Foundation
    7  * All rights reserved.
    8  *
    9  * Portions of this software were developed by Edward Tomasz Napierala
   10  * under sponsorship from the FreeBSD Foundation.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   31  * SUCH DAMAGE.
   32  */
   33 
   34 /*
   35  * This file contains the USB templates for an USB Media Transfer
   36  * Protocol device.
   37  *
   38  * NOTE: It is common practice that MTP devices use some dummy
   39  * descriptor cludges to be automatically detected by the host
   40  * operating system. These descriptors are documented in the LibMTP
   41  * library at sourceforge.net. The alternative is to supply the host
   42  * operating system the VID and PID of your device.
   43  */
   44 
   45 #ifdef USB_GLOBAL_INCLUDE_FILE
   46 #include USB_GLOBAL_INCLUDE_FILE
   47 #else
   48 #include <sys/stdint.h>
   49 #include <sys/stddef.h>
   50 #include <sys/param.h>
   51 #include <sys/queue.h>
   52 #include <sys/types.h>
   53 #include <sys/systm.h>
   54 #include <sys/kernel.h>
   55 #include <sys/bus.h>
   56 #include <sys/module.h>
   57 #include <sys/lock.h>
   58 #include <sys/mutex.h>
   59 #include <sys/condvar.h>
   60 #include <sys/sysctl.h>
   61 #include <sys/sx.h>
   62 #include <sys/unistd.h>
   63 #include <sys/callout.h>
   64 #include <sys/malloc.h>
   65 #include <sys/priv.h>
   66 
   67 #include <dev/usb/usb.h>
   68 #include <dev/usb/usbdi.h>
   69 #include <dev/usb/usb_core.h>
   70 #include <dev/usb/usb_ioctl.h>
   71 #include <dev/usb/usb_util.h>
   72 
   73 #include <dev/usb/template/usb_template.h>
   74 #endif                  /* USB_GLOBAL_INCLUDE_FILE */
   75 
   76 #define MTP_BREQUEST 0x08
   77 
   78 enum {
   79         MTP_LANG_INDEX,
   80         MTP_INTERFACE_INDEX,
   81         MTP_CONFIGURATION_INDEX,
   82         MTP_MANUFACTURER_INDEX,
   83         MTP_PRODUCT_INDEX,
   84         MTP_SERIAL_NUMBER_INDEX,
   85         MTP_MAX_INDEX,
   86 };
   87 
   88 #define MTP_DEFAULT_VENDOR_ID           USB_TEMPLATE_VENDOR
   89 #define MTP_DEFAULT_PRODUCT_ID          0x27e2
   90 #define MTP_DEFAULT_INTERFACE           "USB MTP Interface"
   91 #define MTP_DEFAULT_CONFIGURATION       "Default Config"
   92 #define MTP_DEFAULT_MANUFACTURER        USB_TEMPLATE_MANUFACTURER
   93 #define MTP_DEFAULT_PRODUCT             "USB MTP"
   94 #define MTP_DEFAULT_SERIAL_NUMBER       "June 2008"
   95 
   96 static struct usb_string_descriptor     mtp_interface;
   97 static struct usb_string_descriptor     mtp_configuration;
   98 static struct usb_string_descriptor     mtp_manufacturer;
   99 static struct usb_string_descriptor     mtp_product;
  100 static struct usb_string_descriptor     mtp_serial_number;
  101 
  102 static struct sysctl_ctx_list           mtp_ctx_list;
  103 
  104 /* prototypes */
  105 
  106 static usb_temp_get_string_desc_t mtp_get_string_desc;
  107 static usb_temp_get_vendor_desc_t mtp_get_vendor_desc;
  108 
  109 static const struct usb_temp_packet_size bulk_mps = {
  110         .mps[USB_SPEED_FULL] = 64,
  111         .mps[USB_SPEED_HIGH] = 512,
  112 };
  113 
  114 static const struct usb_temp_packet_size intr_mps = {
  115         .mps[USB_SPEED_FULL] = 64,
  116         .mps[USB_SPEED_HIGH] = 64,
  117 };
  118 
  119 static const struct usb_temp_endpoint_desc bulk_out_ep = {
  120         .pPacketSize = &bulk_mps,
  121 #ifdef USB_HIP_OUT_EP_0
  122         .bEndpointAddress = USB_HIP_OUT_EP_0,
  123 #else
  124         .bEndpointAddress = UE_DIR_OUT,
  125 #endif
  126         .bmAttributes = UE_BULK,
  127 };
  128 
  129 static const struct usb_temp_endpoint_desc intr_in_ep = {
  130         .pPacketSize = &intr_mps,
  131         .bEndpointAddress = UE_DIR_IN,
  132         .bmAttributes = UE_INTERRUPT,
  133 };
  134 
  135 static const struct usb_temp_endpoint_desc bulk_in_ep = {
  136         .pPacketSize = &bulk_mps,
  137 #ifdef USB_HIP_IN_EP_0
  138         .bEndpointAddress = USB_HIP_IN_EP_0,
  139 #else
  140         .bEndpointAddress = UE_DIR_IN,
  141 #endif
  142         .bmAttributes = UE_BULK,
  143 };
  144 
  145 static const struct usb_temp_endpoint_desc *mtp_data_endpoints[] = {
  146         &bulk_in_ep,
  147         &bulk_out_ep,
  148         &intr_in_ep,
  149         NULL,
  150 };
  151 
  152 static const struct usb_temp_interface_desc mtp_data_interface = {
  153         .ppEndpoints = mtp_data_endpoints,
  154         .bInterfaceClass = UICLASS_IMAGE,
  155         .bInterfaceSubClass = UISUBCLASS_SIC,   /* Still Image Class */
  156         .bInterfaceProtocol = 1,        /* PIMA 15740 */
  157         .iInterface = MTP_INTERFACE_INDEX,
  158 };
  159 
  160 static const struct usb_temp_interface_desc *mtp_interfaces[] = {
  161         &mtp_data_interface,
  162         NULL,
  163 };
  164 
  165 static const struct usb_temp_config_desc mtp_config_desc = {
  166         .ppIfaceDesc = mtp_interfaces,
  167         .bmAttributes = 0,
  168         .bMaxPower = 0,
  169         .iConfiguration = MTP_CONFIGURATION_INDEX,
  170 };
  171 
  172 static const struct usb_temp_config_desc *mtp_configs[] = {
  173         &mtp_config_desc,
  174         NULL,
  175 };
  176 
  177 struct usb_temp_device_desc usb_template_mtp = {
  178         .getStringDesc = &mtp_get_string_desc,
  179         .getVendorDesc = &mtp_get_vendor_desc,
  180         .ppConfigDesc = mtp_configs,
  181         .idVendor = MTP_DEFAULT_VENDOR_ID,
  182         .idProduct = MTP_DEFAULT_PRODUCT_ID,
  183         .bcdDevice = 0x0100,
  184         .bDeviceClass = 0,
  185         .bDeviceSubClass = 0,
  186         .bDeviceProtocol = 0,
  187         .iManufacturer = MTP_MANUFACTURER_INDEX,
  188         .iProduct = MTP_PRODUCT_INDEX,
  189         .iSerialNumber = MTP_SERIAL_NUMBER_INDEX,
  190 };
  191 
  192 /*------------------------------------------------------------------------*
  193  *      mtp_get_vendor_desc
  194  *
  195  * Return values:
  196  * NULL: Failure. No such vendor descriptor.
  197  * Else: Success. Pointer to vendor descriptor is returned.
  198  *------------------------------------------------------------------------*/
  199 static const void *
  200 mtp_get_vendor_desc(const struct usb_device_request *req, uint16_t *plen)
  201 {
  202         static const uint8_t dummy_desc[0x28] = {
  203                 0x28, 0, 0, 0, 0, 1, 4, 0,
  204                 1, 0, 0, 0, 0, 0, 0, 0,
  205                 0, 1, 0x4D, 0x54, 0x50, 0, 0, 0,
  206                 0, 0, 0, 0, 0, 0, 0, 0,
  207                 0, 0, 0, 0, 0, 0, 0, 0,
  208         };
  209 
  210         if ((req->bmRequestType == UT_READ_VENDOR_DEVICE) &&
  211             (req->bRequest == MTP_BREQUEST) && (req->wValue[0] == 0) &&
  212             (req->wValue[1] == 0) && (req->wIndex[1] == 0) &&
  213             ((req->wIndex[0] == 4) || (req->wIndex[0] == 5))) {
  214                 /*
  215                  * By returning this descriptor LibMTP will
  216                  * automatically pickup our device.
  217                  */
  218                 return (dummy_desc);
  219         }
  220         return (NULL);
  221 }
  222 
  223 /*------------------------------------------------------------------------*
  224  *      mtp_get_string_desc
  225  *
  226  * Return values:
  227  * NULL: Failure. No such string.
  228  * Else: Success. Pointer to string descriptor is returned.
  229  *------------------------------------------------------------------------*/
  230 static const void *
  231 mtp_get_string_desc(uint16_t lang_id, uint8_t string_index)
  232 {
  233         static const void *ptr[MTP_MAX_INDEX] = {
  234                 [MTP_LANG_INDEX] = &usb_string_lang_en,
  235                 [MTP_INTERFACE_INDEX] = &mtp_interface,
  236                 [MTP_CONFIGURATION_INDEX] = &mtp_configuration,
  237                 [MTP_MANUFACTURER_INDEX] = &mtp_manufacturer,
  238                 [MTP_PRODUCT_INDEX] = &mtp_product,
  239                 [MTP_SERIAL_NUMBER_INDEX] = &mtp_serial_number,
  240         };
  241 
  242         static const uint8_t dummy_desc[0x12] = {
  243                 0x12, 0x03, 0x4D, 0x00, 0x53, 0x00, 0x46, 0x00,
  244                 0x54, 0x00, 0x31, 0x00, 0x30, 0x00, 0x30, 0x00,
  245                 MTP_BREQUEST, 0x00,
  246         };
  247 
  248         if (string_index == 0xEE) {
  249                 /*
  250                  * By returning this string LibMTP will automatically
  251                  * pickup our device.
  252                  */
  253                 return (dummy_desc);
  254         }
  255         if (string_index == 0) {
  256                 return (&usb_string_lang_en);
  257         }
  258         if (lang_id != 0x0409) {
  259                 return (NULL);
  260         }
  261         if (string_index < MTP_MAX_INDEX) {
  262                 return (ptr[string_index]);
  263         }
  264         return (NULL);
  265 }
  266 
  267 static void
  268 mtp_init(void *arg __unused)
  269 {
  270         struct sysctl_oid *parent;
  271         char parent_name[3];
  272 
  273         usb_make_str_desc(&mtp_interface, sizeof(mtp_interface),
  274             MTP_DEFAULT_INTERFACE);
  275         usb_make_str_desc(&mtp_configuration, sizeof(mtp_configuration),
  276             MTP_DEFAULT_CONFIGURATION);
  277         usb_make_str_desc(&mtp_manufacturer, sizeof(mtp_manufacturer),
  278             MTP_DEFAULT_MANUFACTURER);
  279         usb_make_str_desc(&mtp_product, sizeof(mtp_product),
  280             MTP_DEFAULT_PRODUCT);
  281         usb_make_str_desc(&mtp_serial_number, sizeof(mtp_serial_number),
  282             MTP_DEFAULT_SERIAL_NUMBER);
  283 
  284         snprintf(parent_name, sizeof(parent_name), "%d", USB_TEMP_MTP);
  285         sysctl_ctx_init(&mtp_ctx_list);
  286 
  287         parent = SYSCTL_ADD_NODE(&mtp_ctx_list,
  288             SYSCTL_STATIC_CHILDREN(_hw_usb_templates), OID_AUTO,
  289             parent_name, CTLFLAG_RW | CTLFLAG_MPSAFE,
  290             0, "USB Media Transfer Protocol device side template");
  291         SYSCTL_ADD_U16(&mtp_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
  292             "vendor_id", CTLFLAG_RWTUN,
  293             &usb_template_mtp.idVendor, 1, "Vendor identifier");
  294         SYSCTL_ADD_U16(&mtp_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
  295             "product_id", CTLFLAG_RWTUN,
  296             &usb_template_mtp.idProduct, 1, "Product identifier");
  297 #if 0
  298         SYSCTL_ADD_PROC(&mtp_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
  299             "interface", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
  300             &mtp_interface, sizeof(mtp_interface), usb_temp_sysctl,
  301             "A", "Interface string");
  302         SYSCTL_ADD_PROC(&mtp_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
  303             "configuration", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
  304             &mtp_configuration, sizeof(mtp_configuration), usb_temp_sysctl,
  305             "A", "Configuration string");
  306 #endif
  307         SYSCTL_ADD_PROC(&mtp_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
  308             "manufacturer", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
  309             &mtp_manufacturer, sizeof(mtp_manufacturer), usb_temp_sysctl,
  310             "A", "Manufacturer string");
  311         SYSCTL_ADD_PROC(&mtp_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
  312             "product", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
  313             &mtp_product, sizeof(mtp_product), usb_temp_sysctl,
  314             "A", "Product string");
  315         SYSCTL_ADD_PROC(&mtp_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
  316             "serial_number", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
  317             &mtp_serial_number, sizeof(mtp_serial_number), usb_temp_sysctl,
  318             "A", "Serial number string");
  319 }
  320 
  321 static void
  322 mtp_uninit(void *arg __unused)
  323 {
  324 
  325         sysctl_ctx_free(&mtp_ctx_list);
  326 }
  327 
  328 SYSINIT(mtp_init, SI_SUB_LOCK, SI_ORDER_FIRST, mtp_init, NULL);
  329 SYSUNINIT(mtp_uninit, SI_SUB_LOCK, SI_ORDER_FIRST, mtp_uninit, NULL);

Cache object: 246add0701a6de9d88e1354167972e05


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.