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