1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2014 Hans Petter Selasky 5 * Copyright (c) 2018 The FreeBSD Foundation 6 * All rights reserved. 7 * 8 * Portions of this software were developed by Edward Tomasz Napierala 9 * under sponsorship from the FreeBSD Foundation. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 /* 34 * This file contains the USB template for an USB phone device. 35 */ 36 37 #ifdef USB_GLOBAL_INCLUDE_FILE 38 #include USB_GLOBAL_INCLUDE_FILE 39 #else 40 #include <sys/stdint.h> 41 #include <sys/stddef.h> 42 #include <sys/param.h> 43 #include <sys/queue.h> 44 #include <sys/types.h> 45 #include <sys/systm.h> 46 #include <sys/kernel.h> 47 #include <sys/bus.h> 48 #include <sys/module.h> 49 #include <sys/lock.h> 50 #include <sys/mutex.h> 51 #include <sys/condvar.h> 52 #include <sys/sysctl.h> 53 #include <sys/sx.h> 54 #include <sys/unistd.h> 55 #include <sys/callout.h> 56 #include <sys/malloc.h> 57 #include <sys/priv.h> 58 59 #include <dev/usb/usb.h> 60 #include <dev/usb/usbdi.h> 61 #include <dev/usb/usb_core.h> 62 #include <dev/usb/usb_cdc.h> 63 #include <dev/usb/usb_ioctl.h> 64 #include <dev/usb/usb_util.h> 65 66 #include <dev/usb/template/usb_template.h> 67 #endif /* USB_GLOBAL_INCLUDE_FILE */ 68 69 enum { 70 PHONE_LANG_INDEX, 71 PHONE_MIXER_INDEX, 72 PHONE_RECORD_INDEX, 73 PHONE_PLAYBACK_INDEX, 74 PHONE_HID_INDEX, 75 PHONE_MANUFACTURER_INDEX, 76 PHONE_PRODUCT_INDEX, 77 PHONE_SERIAL_NUMBER_INDEX, 78 PHONE_MAX_INDEX, 79 }; 80 81 #define PHONE_DEFAULT_VENDOR_ID USB_TEMPLATE_VENDOR 82 #define PHONE_DEFAULT_PRODUCT_ID 0x05dc 83 #define PHONE_DEFAULT_MIXER "Mixer interface" 84 #define PHONE_DEFAULT_RECORD "Record interface" 85 #define PHONE_DEFAULT_PLAYBACK "Playback interface" 86 #define PHONE_DEFAULT_HID "HID interface" 87 #define PHONE_DEFAULT_MANUFACTURER USB_TEMPLATE_MANUFACTURER 88 #define PHONE_DEFAULT_PRODUCT "USB Phone Device" 89 #define PHONE_DEFAULT_SERIAL_NUMBER "March 2008" 90 91 static struct usb_string_descriptor phone_mixer; 92 static struct usb_string_descriptor phone_record; 93 static struct usb_string_descriptor phone_playback; 94 static struct usb_string_descriptor phone_hid; 95 static struct usb_string_descriptor phone_manufacturer; 96 static struct usb_string_descriptor phone_product; 97 static struct usb_string_descriptor phone_serial_number; 98 99 static struct sysctl_ctx_list phone_ctx_list; 100 101 /* prototypes */ 102 103 /* 104 * Phone Mixer description structures 105 * 106 * Some of the phone descriptors were dumped from no longer in 107 * production Yealink VOIP USB phone adapter: 108 */ 109 static uint8_t phone_hid_descriptor[] = { 110 0x05, 0x0b, 0x09, 0x01, 0xa1, 0x01, 0x05, 0x09, 111 0x19, 0x01, 0x29, 0x3f, 0x15, 0x00, 0x25, 0x01, 112 0x75, 0x01, 0x95, 0x80, 0x81, 0x00, 0x05, 0x08, 113 0x19, 0x01, 0x29, 0x10, 0x15, 0x00, 0x25, 0x01, 114 0x75, 0x01, 0x95, 0x80, 0x91, 0x00, 0xc0 115 }; 116 117 static const uint8_t phone_raw_desc_0[] = { 118 0x0a, 0x24, 0x01, 0x00, 0x01, 0x4a, 0x00, 0x02, 119 0x01, 0x02 120 }; 121 122 static const uint8_t phone_raw_desc_1[] = { 123 0x0c, 0x24, 0x02, 0x01, 0x01, 0x02, 0x00, 0x01, 124 0x00, 0x00, 0x00, 0x00 125 }; 126 127 static const uint8_t phone_raw_desc_2[] = { 128 0x0c, 0x24, 0x02, 0x02, 0x01, 0x01, 0x00, 0x01, 129 0x00, 0x00, 0x00, 0x00 130 }; 131 132 static const uint8_t phone_raw_desc_3[] = { 133 0x09, 0x24, 0x03, 0x03, 0x01, 0x03, 0x00, 0x06, 134 0x00 135 }; 136 137 static const uint8_t phone_raw_desc_4[] = { 138 0x09, 0x24, 0x03, 0x04, 0x01, 0x01, 0x00, 0x05, 139 0x00 140 }; 141 142 static const uint8_t phone_raw_desc_5[] = { 143 0x0b, 0x24, 0x06, 0x05, 0x01, 0x02, 0x03, 0x00, 144 0x03, 0x00, 0x00 145 }; 146 147 static const uint8_t phone_raw_desc_6[] = { 148 0x0b, 0x24, 0x06, 0x06, 0x02, 0x02, 0x03, 0x00, 149 0x03, 0x00, 0x00 150 }; 151 152 static const void *phone_raw_iface_0_desc[] = { 153 phone_raw_desc_0, 154 phone_raw_desc_1, 155 phone_raw_desc_2, 156 phone_raw_desc_3, 157 phone_raw_desc_4, 158 phone_raw_desc_5, 159 phone_raw_desc_6, 160 NULL, 161 }; 162 163 static const struct usb_temp_interface_desc phone_iface_0 = { 164 .ppEndpoints = NULL, /* no endpoints */ 165 .ppRawDesc = phone_raw_iface_0_desc, 166 .bInterfaceClass = UICLASS_AUDIO, 167 .bInterfaceSubClass = UISUBCLASS_AUDIOCONTROL, 168 .bInterfaceProtocol = 0, 169 .iInterface = PHONE_MIXER_INDEX, 170 }; 171 172 static const uint8_t phone_raw_desc_20[] = { 173 0x07, 0x24, 0x01, 0x04, 0x01, 0x01, 0x00 174 }; 175 176 static const uint8_t phone_raw_desc_21[] = { 177 0x0b, 0x24, 0x02, 0x01, 0x01, 0x02, 0x10, 0x01, 178 /* 8kHz */ 179 0x40, 0x1f, 0x00 180 }; 181 182 static const uint8_t phone_raw_desc_22[] = { 183 0x07, 0x25, 0x01, 0x00, 0x00, 0x00, 0x00 184 }; 185 186 static const void *phone_raw_iface_1_desc[] = { 187 phone_raw_desc_20, 188 phone_raw_desc_21, 189 NULL, 190 }; 191 192 static const void *phone_raw_ep_1_desc[] = { 193 phone_raw_desc_22, 194 NULL, 195 }; 196 197 static const struct usb_temp_packet_size phone_isoc_mps = { 198 .mps[USB_SPEED_FULL] = 0x10, 199 .mps[USB_SPEED_HIGH] = 0x10, 200 }; 201 202 static const struct usb_temp_interval phone_isoc_interval = { 203 .bInterval[USB_SPEED_FULL] = 1, /* 1:1 */ 204 .bInterval[USB_SPEED_HIGH] = 4, /* 1:8 */ 205 }; 206 207 static const struct usb_temp_endpoint_desc phone_isoc_in_ep = { 208 .ppRawDesc = phone_raw_ep_1_desc, 209 .pPacketSize = &phone_isoc_mps, 210 .pIntervals = &phone_isoc_interval, 211 .bEndpointAddress = UE_DIR_IN, 212 .bmAttributes = UE_ISOCHRONOUS, 213 }; 214 215 static const struct usb_temp_endpoint_desc *phone_iface_1_ep[] = { 216 &phone_isoc_in_ep, 217 NULL, 218 }; 219 220 static const struct usb_temp_interface_desc phone_iface_1_alt_0 = { 221 .ppEndpoints = NULL, /* no endpoints */ 222 .ppRawDesc = NULL, /* no raw descriptors */ 223 .bInterfaceClass = UICLASS_AUDIO, 224 .bInterfaceSubClass = UISUBCLASS_AUDIOSTREAM, 225 .bInterfaceProtocol = 0, 226 .iInterface = PHONE_PLAYBACK_INDEX, 227 }; 228 229 static const struct usb_temp_interface_desc phone_iface_1_alt_1 = { 230 .ppEndpoints = phone_iface_1_ep, 231 .ppRawDesc = phone_raw_iface_1_desc, 232 .bInterfaceClass = UICLASS_AUDIO, 233 .bInterfaceSubClass = UISUBCLASS_AUDIOSTREAM, 234 .bInterfaceProtocol = 0, 235 .iInterface = PHONE_PLAYBACK_INDEX, 236 .isAltInterface = 1, /* this is an alternate setting */ 237 }; 238 239 static const uint8_t phone_raw_desc_30[] = { 240 0x07, 0x24, 0x01, 0x02, 0x01, 0x01, 0x00 241 }; 242 243 static const uint8_t phone_raw_desc_31[] = { 244 0x0b, 0x24, 0x02, 0x01, 0x01, 0x02, 0x10, 0x01, 245 /* 8kHz */ 246 0x40, 0x1f, 0x00 247 }; 248 249 static const uint8_t phone_raw_desc_32[] = { 250 0x07, 0x25, 0x01, 0x00, 0x00, 0x00, 0x00 251 }; 252 253 static const void *phone_raw_iface_2_desc[] = { 254 phone_raw_desc_30, 255 phone_raw_desc_31, 256 NULL, 257 }; 258 259 static const void *phone_raw_ep_2_desc[] = { 260 phone_raw_desc_32, 261 NULL, 262 }; 263 264 static const struct usb_temp_endpoint_desc phone_isoc_out_ep = { 265 .ppRawDesc = phone_raw_ep_2_desc, 266 .pPacketSize = &phone_isoc_mps, 267 .pIntervals = &phone_isoc_interval, 268 .bEndpointAddress = UE_DIR_OUT, 269 .bmAttributes = UE_ISOCHRONOUS, 270 }; 271 272 static const struct usb_temp_endpoint_desc *phone_iface_2_ep[] = { 273 &phone_isoc_out_ep, 274 NULL, 275 }; 276 277 static const struct usb_temp_interface_desc phone_iface_2_alt_0 = { 278 .ppEndpoints = NULL, /* no endpoints */ 279 .ppRawDesc = NULL, /* no raw descriptors */ 280 .bInterfaceClass = UICLASS_AUDIO, 281 .bInterfaceSubClass = UISUBCLASS_AUDIOSTREAM, 282 .bInterfaceProtocol = 0, 283 .iInterface = PHONE_RECORD_INDEX, 284 }; 285 286 static const struct usb_temp_interface_desc phone_iface_2_alt_1 = { 287 .ppEndpoints = phone_iface_2_ep, 288 .ppRawDesc = phone_raw_iface_2_desc, 289 .bInterfaceClass = UICLASS_AUDIO, 290 .bInterfaceSubClass = UISUBCLASS_AUDIOSTREAM, 291 .bInterfaceProtocol = 0, 292 .iInterface = PHONE_RECORD_INDEX, 293 .isAltInterface = 1, /* this is an alternate setting */ 294 }; 295 296 static const uint8_t phone_hid_raw_desc_0[] = { 297 0x09, 0x21, 0x00, 0x01, 0x00, 0x01, 0x22, sizeof(phone_hid_descriptor), 298 0x00 299 }; 300 301 static const void *phone_hid_desc_0[] = { 302 phone_hid_raw_desc_0, 303 NULL, 304 }; 305 306 static const struct usb_temp_packet_size phone_hid_mps = { 307 .mps[USB_SPEED_FULL] = 0x10, 308 .mps[USB_SPEED_HIGH] = 0x10, 309 }; 310 311 static const struct usb_temp_interval phone_hid_interval = { 312 .bInterval[USB_SPEED_FULL] = 2, /* 2ms */ 313 .bInterval[USB_SPEED_HIGH] = 2, /* 2ms */ 314 }; 315 316 static const struct usb_temp_endpoint_desc phone_hid_in_ep = { 317 .pPacketSize = &phone_hid_mps, 318 .pIntervals = &phone_hid_interval, 319 .bEndpointAddress = UE_DIR_IN, 320 .bmAttributes = UE_INTERRUPT, 321 }; 322 323 static const struct usb_temp_endpoint_desc *phone_iface_3_ep[] = { 324 &phone_hid_in_ep, 325 NULL, 326 }; 327 328 static const struct usb_temp_interface_desc phone_iface_3 = { 329 .ppEndpoints = phone_iface_3_ep, 330 .ppRawDesc = phone_hid_desc_0, 331 .bInterfaceClass = UICLASS_HID, 332 .bInterfaceSubClass = 0, 333 .bInterfaceProtocol = 0, 334 .iInterface = PHONE_HID_INDEX, 335 }; 336 337 static const struct usb_temp_interface_desc *phone_interfaces[] = { 338 &phone_iface_0, 339 &phone_iface_1_alt_0, 340 &phone_iface_1_alt_1, 341 &phone_iface_2_alt_0, 342 &phone_iface_2_alt_1, 343 &phone_iface_3, 344 NULL, 345 }; 346 347 static const struct usb_temp_config_desc phone_config_desc = { 348 .ppIfaceDesc = phone_interfaces, 349 .bmAttributes = 0, 350 .bMaxPower = 0, 351 .iConfiguration = PHONE_PRODUCT_INDEX, 352 }; 353 354 static const struct usb_temp_config_desc *phone_configs[] = { 355 &phone_config_desc, 356 NULL, 357 }; 358 359 static usb_temp_get_string_desc_t phone_get_string_desc; 360 static usb_temp_get_vendor_desc_t phone_get_vendor_desc; 361 362 struct usb_temp_device_desc usb_template_phone = { 363 .getStringDesc = &phone_get_string_desc, 364 .getVendorDesc = &phone_get_vendor_desc, 365 .ppConfigDesc = phone_configs, 366 .idVendor = PHONE_DEFAULT_VENDOR_ID, 367 .idProduct = PHONE_DEFAULT_PRODUCT_ID, 368 .bcdDevice = 0x0100, 369 .bDeviceClass = UDCLASS_IN_INTERFACE, 370 .bDeviceSubClass = 0, 371 .bDeviceProtocol = 0, 372 .iManufacturer = PHONE_MANUFACTURER_INDEX, 373 .iProduct = PHONE_PRODUCT_INDEX, 374 .iSerialNumber = PHONE_SERIAL_NUMBER_INDEX, 375 }; 376 377 /*------------------------------------------------------------------------* 378 * phone_get_vendor_desc 379 * 380 * Return values: 381 * NULL: Failure. No such vendor descriptor. 382 * Else: Success. Pointer to vendor descriptor is returned. 383 *------------------------------------------------------------------------*/ 384 static const void * 385 phone_get_vendor_desc(const struct usb_device_request *req, uint16_t *plen) 386 { 387 if ((req->bmRequestType == 0x81) && (req->bRequest == 0x06) && 388 (req->wValue[0] == 0x00) && (req->wValue[1] == 0x22) && 389 (req->wIndex[1] == 0) && (req->wIndex[0] == 3 /* iface */)) { 390 *plen = sizeof(phone_hid_descriptor); 391 return (phone_hid_descriptor); 392 } 393 return (NULL); 394 } 395 396 /*------------------------------------------------------------------------* 397 * phone_get_string_desc 398 * 399 * Return values: 400 * NULL: Failure. No such string. 401 * Else: Success. Pointer to string descriptor is returned. 402 *------------------------------------------------------------------------*/ 403 static const void * 404 phone_get_string_desc(uint16_t lang_id, uint8_t string_index) 405 { 406 static const void *ptr[PHONE_MAX_INDEX] = { 407 [PHONE_LANG_INDEX] = &usb_string_lang_en, 408 [PHONE_MIXER_INDEX] = &phone_mixer, 409 [PHONE_RECORD_INDEX] = &phone_record, 410 [PHONE_PLAYBACK_INDEX] = &phone_playback, 411 [PHONE_HID_INDEX] = &phone_hid, 412 [PHONE_MANUFACTURER_INDEX] = &phone_manufacturer, 413 [PHONE_PRODUCT_INDEX] = &phone_product, 414 [PHONE_SERIAL_NUMBER_INDEX] = &phone_serial_number, 415 }; 416 417 if (string_index == 0) { 418 return (&usb_string_lang_en); 419 } 420 if (lang_id != 0x0409) { 421 return (NULL); 422 } 423 if (string_index < PHONE_MAX_INDEX) { 424 return (ptr[string_index]); 425 } 426 return (NULL); 427 } 428 429 static void 430 phone_init(void *arg __unused) 431 { 432 struct sysctl_oid *parent; 433 char parent_name[3]; 434 435 usb_make_str_desc(&phone_mixer, sizeof(phone_mixer), 436 PHONE_DEFAULT_MIXER); 437 usb_make_str_desc(&phone_record, sizeof(phone_record), 438 PHONE_DEFAULT_RECORD); 439 usb_make_str_desc(&phone_playback, sizeof(phone_playback), 440 PHONE_DEFAULT_PLAYBACK); 441 usb_make_str_desc(&phone_hid, sizeof(phone_hid), 442 PHONE_DEFAULT_HID); 443 usb_make_str_desc(&phone_manufacturer, sizeof(phone_manufacturer), 444 PHONE_DEFAULT_MANUFACTURER); 445 usb_make_str_desc(&phone_product, sizeof(phone_product), 446 PHONE_DEFAULT_PRODUCT); 447 usb_make_str_desc(&phone_serial_number, sizeof(phone_serial_number), 448 PHONE_DEFAULT_SERIAL_NUMBER); 449 450 snprintf(parent_name, sizeof(parent_name), "%d", USB_TEMP_PHONE); 451 sysctl_ctx_init(&phone_ctx_list); 452 453 parent = SYSCTL_ADD_NODE(&phone_ctx_list, 454 SYSCTL_STATIC_CHILDREN(_hw_usb_templates), OID_AUTO, 455 parent_name, CTLFLAG_RW | CTLFLAG_MPSAFE, 456 0, "USB Phone device side template"); 457 SYSCTL_ADD_U16(&phone_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 458 "vendor_id", CTLFLAG_RWTUN, 459 &usb_template_cdce.idVendor, 1, "Vendor identifier"); 460 SYSCTL_ADD_U16(&phone_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 461 "product_id", CTLFLAG_RWTUN, 462 &usb_template_cdce.idProduct, 1, "Product identifier"); 463 #if 0 464 SYSCTL_ADD_PROC(&phone_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 465 "mixer", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 466 &phone_mixer, sizeof(phone_mixer), usb_temp_sysctl, 467 "A", "Mixer interface string"); 468 SYSCTL_ADD_PROC(&phone_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 469 "record", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 470 &phone_record, sizeof(phone_record), usb_temp_sysctl, 471 "A", "Record interface string"); 472 SYSCTL_ADD_PROC(&phone_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 473 "playback", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 474 &phone_playback, sizeof(phone_playback), usb_temp_sysctl, 475 "A", "Playback interface string"); 476 SYSCTL_ADD_PROC(&phone_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 477 "hid", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 478 &phone_hid, sizeof(phone_hid), usb_temp_sysctl, 479 "A", "HID interface string"); 480 #endif 481 SYSCTL_ADD_PROC(&phone_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 482 "manufacturer", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 483 &phone_manufacturer, sizeof(phone_manufacturer), usb_temp_sysctl, 484 "A", "Manufacturer string"); 485 SYSCTL_ADD_PROC(&phone_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 486 "product", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 487 &phone_product, sizeof(phone_product), usb_temp_sysctl, 488 "A", "Product string"); 489 SYSCTL_ADD_PROC(&phone_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 490 "serial_number", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 491 &phone_serial_number, sizeof(phone_serial_number), usb_temp_sysctl, 492 "A", "Serial number string"); 493 } 494 495 static void 496 phone_uninit(void *arg __unused) 497 { 498 499 sysctl_ctx_free(&phone_ctx_list); 500 } 501 502 SYSINIT(phone_init, SI_SUB_LOCK, SI_ORDER_FIRST, phone_init, NULL); 503 SYSUNINIT(phone_uninit, SI_SUB_LOCK, SI_ORDER_FIRST, phone_uninit, NULL); 504