1 /* $FreeBSD$ */ 2 /*- 3 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 4 * 5 * Copyright (c) 2008 Hans Petter Selasky <hselasky@FreeBSD.org> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 /* 31 * This file contains the USB templates for an USB Mass Storage Device. 32 */ 33 34 #ifdef USB_GLOBAL_INCLUDE_FILE 35 #include USB_GLOBAL_INCLUDE_FILE 36 #else 37 #include <sys/stdint.h> 38 #include <sys/stddef.h> 39 #include <sys/param.h> 40 #include <sys/queue.h> 41 #include <sys/types.h> 42 #include <sys/systm.h> 43 #include <sys/kernel.h> 44 #include <sys/bus.h> 45 #include <sys/module.h> 46 #include <sys/lock.h> 47 #include <sys/mutex.h> 48 #include <sys/condvar.h> 49 #include <sys/sysctl.h> 50 #include <sys/sx.h> 51 #include <sys/unistd.h> 52 #include <sys/callout.h> 53 #include <sys/malloc.h> 54 #include <sys/priv.h> 55 56 #include <dev/usb/usb.h> 57 #include <dev/usb/usbdi.h> 58 #include <dev/usb/usb_core.h> 59 60 #include <dev/usb/template/usb_template.h> 61 #endif /* USB_GLOBAL_INCLUDE_FILE */ 62 63 enum { 64 STRING_LANG_INDEX, 65 STRING_MSC_DATA_INDEX, 66 STRING_MSC_CONFIG_INDEX, 67 STRING_MSC_VENDOR_INDEX, 68 STRING_MSC_PRODUCT_INDEX, 69 STRING_MSC_SERIAL_INDEX, 70 STRING_MSC_MAX, 71 }; 72 73 #define STRING_MSC_DATA \ 74 "U\0S\0B\0 \0M\0a\0s\0s\0 \0S\0t\0o\0r\0a\0g\0e\0 " \ 75 "\0I\0n\0t\0e\0r\0f\0a\0c\0e" 76 77 #define STRING_MSC_CONFIG \ 78 "D\0e\0f\0a\0u\0l\0t\0 \0c\0o\0n\0f\0i\0g" 79 80 #define STRING_MSC_VENDOR \ 81 "F\0r\0e\0e\0B\0S\0D\0 \0f\0o\0u\0n\0d\0a\0t\0i\0o\0n" 82 83 #define STRING_MSC_PRODUCT \ 84 "U\0S\0B\0 \0M\0e\0m\0o\0r\0y\0 \0S\0t\0i\0c\0k" 85 86 #define STRING_MSC_SERIAL \ 87 "M\0a\0r\0c\0h\0 \0002\0000\0000\08" 88 89 /* make the real string descriptors */ 90 91 USB_MAKE_STRING_DESC(STRING_MSC_DATA, string_msc_data); 92 USB_MAKE_STRING_DESC(STRING_MSC_CONFIG, string_msc_config); 93 USB_MAKE_STRING_DESC(STRING_MSC_VENDOR, string_msc_vendor); 94 USB_MAKE_STRING_DESC(STRING_MSC_PRODUCT, string_msc_product); 95 USB_MAKE_STRING_DESC(STRING_MSC_SERIAL, string_msc_serial); 96 97 /* prototypes */ 98 99 static usb_temp_get_string_desc_t msc_get_string_desc; 100 101 static const struct usb_temp_packet_size bulk_mps = { 102 .mps[USB_SPEED_FULL] = 64, 103 .mps[USB_SPEED_HIGH] = 512, 104 }; 105 106 static const struct usb_temp_endpoint_desc bulk_in_ep = { 107 .pPacketSize = &bulk_mps, 108 #ifdef USB_HIP_IN_EP_0 109 .bEndpointAddress = USB_HIP_IN_EP_0, 110 #else 111 .bEndpointAddress = UE_DIR_IN, 112 #endif 113 .bmAttributes = UE_BULK, 114 }; 115 116 static const struct usb_temp_endpoint_desc bulk_out_ep = { 117 .pPacketSize = &bulk_mps, 118 #ifdef USB_HIP_OUT_EP_0 119 .bEndpointAddress = USB_HIP_OUT_EP_0, 120 #else 121 .bEndpointAddress = UE_DIR_OUT, 122 #endif 123 .bmAttributes = UE_BULK, 124 }; 125 126 static const struct usb_temp_endpoint_desc *msc_data_endpoints[] = { 127 &bulk_in_ep, 128 &bulk_out_ep, 129 NULL, 130 }; 131 132 static const struct usb_temp_interface_desc msc_data_interface = { 133 .ppEndpoints = msc_data_endpoints, 134 .bInterfaceClass = UICLASS_MASS, 135 .bInterfaceSubClass = UISUBCLASS_SCSI, 136 .bInterfaceProtocol = UIPROTO_MASS_BBB, 137 .iInterface = STRING_MSC_DATA_INDEX, 138 }; 139 140 static const struct usb_temp_interface_desc *msc_interfaces[] = { 141 &msc_data_interface, 142 NULL, 143 }; 144 145 static const struct usb_temp_config_desc msc_config_desc = { 146 .ppIfaceDesc = msc_interfaces, 147 .bmAttributes = UC_BUS_POWERED, 148 .bMaxPower = 25, /* 50 mA */ 149 .iConfiguration = STRING_MSC_CONFIG_INDEX, 150 }; 151 152 static const struct usb_temp_config_desc *msc_configs[] = { 153 &msc_config_desc, 154 NULL, 155 }; 156 157 const struct usb_temp_device_desc usb_template_msc = { 158 .getStringDesc = &msc_get_string_desc, 159 .ppConfigDesc = msc_configs, 160 .idVendor = USB_TEMPLATE_VENDOR, 161 .idProduct = 0x0012, 162 .bcdDevice = 0x0100, 163 .bDeviceClass = UDCLASS_COMM, 164 .bDeviceSubClass = 0, 165 .bDeviceProtocol = 0, 166 .iManufacturer = STRING_MSC_VENDOR_INDEX, 167 .iProduct = STRING_MSC_PRODUCT_INDEX, 168 .iSerialNumber = STRING_MSC_SERIAL_INDEX, 169 }; 170 171 /*------------------------------------------------------------------------* 172 * msc_get_string_desc 173 * 174 * Return values: 175 * NULL: Failure. No such string. 176 * Else: Success. Pointer to string descriptor is returned. 177 *------------------------------------------------------------------------*/ 178 static const void * 179 msc_get_string_desc(uint16_t lang_id, uint8_t string_index) 180 { 181 static const void *ptr[STRING_MSC_MAX] = { 182 [STRING_LANG_INDEX] = &usb_string_lang_en, 183 [STRING_MSC_DATA_INDEX] = &string_msc_data, 184 [STRING_MSC_CONFIG_INDEX] = &string_msc_config, 185 [STRING_MSC_VENDOR_INDEX] = &string_msc_vendor, 186 [STRING_MSC_PRODUCT_INDEX] = &string_msc_product, 187 [STRING_MSC_SERIAL_INDEX] = &string_msc_serial, 188 }; 189 190 if (string_index == 0) { 191 return (&usb_string_lang_en); 192 } 193 if (lang_id != 0x0409) { 194 return (NULL); 195 } 196 if (string_index < STRING_MSC_MAX) { 197 return (ptr[string_index]); 198 } 199 return (NULL); 200 } 201