1 #include <sys/cdefs.h> 2 __FBSDID("$FreeBSD$"); 3 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 #include <dev/usb/usb.h> 35 #include <dev/usb/usb_mfunc.h> 36 37 #include <dev/usb/usb_core.h> 38 39 #include <dev/usb/template/usb_template.h> 40 41 enum { 42 STRING_LANG_INDEX, 43 STRING_MSC_DATA_INDEX, 44 STRING_MSC_CONFIG_INDEX, 45 STRING_MSC_VENDOR_INDEX, 46 STRING_MSC_PRODUCT_INDEX, 47 STRING_MSC_SERIAL_INDEX, 48 STRING_MSC_MAX, 49 }; 50 51 #define STRING_LANG \ 52 0x09, 0x04, /* American English */ 53 54 #define STRING_MSC_DATA \ 55 'U', 0, 'S', 0, 'B', 0, ' ', 0, \ 56 'M', 0, 'a', 0, 's', 0, 's', 0, \ 57 ' ', 0, 'S', 0, 't', 0, 'o', 0, \ 58 'r', 0, 'a', 0, 'g', 0, 'e', 0, \ 59 ' ', 0, 'I', 0, 'n', 0, 't', 0, \ 60 'e', 0, 'r', 0, 'f', 0, 'a', 0, \ 61 'c', 0, 'e', 0, 62 63 #define STRING_MSC_CONFIG \ 64 'D', 0, 'e', 0, 'f', 0, 'a', 0, \ 65 'u', 0, 'l', 0, 't', 0, ' ', 0, \ 66 'c', 0, 'o', 0, 'n', 0, 'f', 0, \ 67 'i', 0, 'g', 0, 68 69 #define STRING_MSC_VENDOR \ 70 'F', 0, 'r', 0, 'e', 0, 'e', 0, \ 71 'B', 0, 'S', 0, 'D', 0, ' ', 0, \ 72 'f', 0, 'o', 0, 'u', 0, 'n', 0, \ 73 'd', 0, 'a', 0, 't', 0, 'i', 0, \ 74 'o', 0, 'n', 0, 75 76 #define STRING_MSC_PRODUCT \ 77 'U', 0, 'S', 0, 'B', 0, ' ', 0, \ 78 'M', 0, 'e', 0, 'm', 0, 'o', 0, \ 79 'r', 0, 'y', 0, ' ', 0, 'S', 0, \ 80 't', 0, 'i', 0, 'c', 0, 'k', 0 81 82 #define STRING_MSC_SERIAL \ 83 'M', 0, 'a', 0, 'r', 0, 'c', 0, \ 84 'h', 0, ' ', 0, '2', 0, '0', 0, \ 85 '0', 0, '8', 0, 86 87 /* make the real string descriptors */ 88 89 USB_MAKE_STRING_DESC(STRING_LANG, string_lang); 90 USB_MAKE_STRING_DESC(STRING_MSC_DATA, string_msc_data); 91 USB_MAKE_STRING_DESC(STRING_MSC_CONFIG, string_msc_config); 92 USB_MAKE_STRING_DESC(STRING_MSC_VENDOR, string_msc_vendor); 93 USB_MAKE_STRING_DESC(STRING_MSC_PRODUCT, string_msc_product); 94 USB_MAKE_STRING_DESC(STRING_MSC_SERIAL, string_msc_serial); 95 96 /* prototypes */ 97 98 static usb2_temp_get_string_desc_t msc_get_string_desc; 99 100 static const struct usb2_temp_packet_size bulk_mps = { 101 .mps[USB_SPEED_FULL] = 64, 102 .mps[USB_SPEED_HIGH] = 512, 103 }; 104 105 static const struct usb2_temp_endpoint_desc bulk_in_ep = { 106 .pPacketSize = &bulk_mps, 107 #ifdef USB_HIP_IN_EP_0 108 .bEndpointAddress = USB_HIP_IN_EP_0, 109 #else 110 .bEndpointAddress = UE_DIR_IN, 111 #endif 112 .bmAttributes = UE_BULK, 113 }; 114 115 static const struct usb2_temp_endpoint_desc bulk_out_ep = { 116 .pPacketSize = &bulk_mps, 117 #ifdef USB_HIP_OUT_EP_0 118 .bEndpointAddress = USB_HIP_OUT_EP_0, 119 #else 120 .bEndpointAddress = UE_DIR_OUT, 121 #endif 122 .bmAttributes = UE_BULK, 123 }; 124 125 static const struct usb2_temp_endpoint_desc *msc_data_endpoints[] = { 126 &bulk_in_ep, 127 &bulk_out_ep, 128 NULL, 129 }; 130 131 static const struct usb2_temp_interface_desc msc_data_interface = { 132 .ppEndpoints = msc_data_endpoints, 133 .bInterfaceClass = UICLASS_MASS, 134 .bInterfaceSubClass = UISUBCLASS_SCSI, 135 .bInterfaceProtocol = UIPROTO_MASS_BBB, 136 .iInterface = STRING_MSC_DATA_INDEX, 137 }; 138 139 static const struct usb2_temp_interface_desc *msc_interfaces[] = { 140 &msc_data_interface, 141 NULL, 142 }; 143 144 static const struct usb2_temp_config_desc msc_config_desc = { 145 .ppIfaceDesc = msc_interfaces, 146 .bmAttributes = UC_BUS_POWERED, 147 .bMaxPower = 25, /* 50 mA */ 148 .iConfiguration = STRING_MSC_CONFIG_INDEX, 149 }; 150 151 static const struct usb2_temp_config_desc *msc_configs[] = { 152 &msc_config_desc, 153 NULL, 154 }; 155 156 const struct usb2_temp_device_desc usb2_template_msc = { 157 .getStringDesc = &msc_get_string_desc, 158 .ppConfigDesc = msc_configs, 159 .idVendor = 0x0001, 160 .idProduct = 0x0001, 161 .bcdDevice = 0x0100, 162 .bDeviceClass = UDCLASS_COMM, 163 .bDeviceSubClass = 0, 164 .bDeviceProtocol = 0, 165 .iManufacturer = STRING_MSC_VENDOR_INDEX, 166 .iProduct = STRING_MSC_PRODUCT_INDEX, 167 .iSerialNumber = STRING_MSC_SERIAL_INDEX, 168 }; 169 170 /*------------------------------------------------------------------------* 171 * msc_get_string_desc 172 * 173 * Return values: 174 * NULL: Failure. No such string. 175 * Else: Success. Pointer to string descriptor is returned. 176 *------------------------------------------------------------------------*/ 177 static const void * 178 msc_get_string_desc(uint16_t lang_id, uint8_t string_index) 179 { 180 static const void *ptr[STRING_MSC_MAX] = { 181 [STRING_LANG_INDEX] = &string_lang, 182 [STRING_MSC_DATA_INDEX] = &string_msc_data, 183 [STRING_MSC_CONFIG_INDEX] = &string_msc_config, 184 [STRING_MSC_VENDOR_INDEX] = &string_msc_vendor, 185 [STRING_MSC_PRODUCT_INDEX] = &string_msc_product, 186 [STRING_MSC_SERIAL_INDEX] = &string_msc_serial, 187 }; 188 189 if (string_index == 0) { 190 return (&string_lang); 191 } 192 if (lang_id != 0x0409) { 193 return (NULL); 194 } 195 if (string_index < STRING_MSC_MAX) { 196 return (ptr[string_index]); 197 } 198 return (NULL); 199 } 200