1 /* $FreeBSD$ */ 2 /*- 3 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 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_MIXER "Mixer interface" 83 #define PHONE_DEFAULT_RECORD "Record interface" 84 #define PHONE_DEFAULT_PLAYBACK "Playback interface" 85 #define PHONE_DEFAULT_HID "HID interface" 86 #define PHONE_DEFAULT_MANUFACTURER "FreeBSD foundation" 87 #define PHONE_DEFAULT_PRODUCT "USB Phone Device" 88 #define PHONE_DEFAULT_SERIAL_NUMBER "March 2008" 89 90 static struct usb_string_descriptor phone_mixer; 91 static struct usb_string_descriptor phone_record; 92 static struct usb_string_descriptor phone_playback; 93 static struct usb_string_descriptor phone_hid; 94 static struct usb_string_descriptor phone_manufacturer; 95 static struct usb_string_descriptor phone_product; 96 static struct usb_string_descriptor phone_serial_number; 97 98 static struct sysctl_ctx_list phone_ctx_list; 99 100 /* prototypes */ 101 102 /* 103 * Phone Mixer description structures 104 * 105 * Some of the phone descriptors were dumped from no longer in 106 * production Yealink VOIP USB phone adapter: 107 */ 108 static uint8_t phone_hid_descriptor[] = { 109 0x05, 0x0b, 0x09, 0x01, 0xa1, 0x01, 0x05, 0x09, 110 0x19, 0x01, 0x29, 0x3f, 0x15, 0x00, 0x25, 0x01, 111 0x75, 0x01, 0x95, 0x80, 0x81, 0x00, 0x05, 0x08, 112 0x19, 0x01, 0x29, 0x10, 0x15, 0x00, 0x25, 0x01, 113 0x75, 0x01, 0x95, 0x80, 0x91, 0x00, 0xc0 114 }; 115 116 static const uint8_t phone_raw_desc_0[] = { 117 0x0a, 0x24, 0x01, 0x00, 0x01, 0x4a, 0x00, 0x02, 118 0x01, 0x02 119 }; 120 121 static const uint8_t phone_raw_desc_1[] = { 122 0x0c, 0x24, 0x02, 0x01, 0x01, 0x02, 0x00, 0x01, 123 0x00, 0x00, 0x00, 0x00 124 }; 125 126 static const uint8_t phone_raw_desc_2[] = { 127 0x0c, 0x24, 0x02, 0x02, 0x01, 0x01, 0x00, 0x01, 128 0x00, 0x00, 0x00, 0x00 129 }; 130 131 static const uint8_t phone_raw_desc_3[] = { 132 0x09, 0x24, 0x03, 0x03, 0x01, 0x03, 0x00, 0x06, 133 0x00 134 }; 135 136 static const uint8_t phone_raw_desc_4[] = { 137 0x09, 0x24, 0x03, 0x04, 0x01, 0x01, 0x00, 0x05, 138 0x00 139 }; 140 141 static const uint8_t phone_raw_desc_5[] = { 142 0x0b, 0x24, 0x06, 0x05, 0x01, 0x02, 0x03, 0x00, 143 0x03, 0x00, 0x00 144 }; 145 146 static const uint8_t phone_raw_desc_6[] = { 147 0x0b, 0x24, 0x06, 0x06, 0x02, 0x02, 0x03, 0x00, 148 0x03, 0x00, 0x00 149 }; 150 151 static const void *phone_raw_iface_0_desc[] = { 152 phone_raw_desc_0, 153 phone_raw_desc_1, 154 phone_raw_desc_2, 155 phone_raw_desc_3, 156 phone_raw_desc_4, 157 phone_raw_desc_5, 158 phone_raw_desc_6, 159 NULL, 160 }; 161 162 static const struct usb_temp_interface_desc phone_iface_0 = { 163 .ppEndpoints = NULL, /* no endpoints */ 164 .ppRawDesc = phone_raw_iface_0_desc, 165 .bInterfaceClass = UICLASS_AUDIO, 166 .bInterfaceSubClass = UISUBCLASS_AUDIOCONTROL, 167 .bInterfaceProtocol = 0, 168 .iInterface = PHONE_MIXER_INDEX, 169 }; 170 171 static const uint8_t phone_raw_desc_20[] = { 172 0x07, 0x24, 0x01, 0x04, 0x01, 0x01, 0x00 173 }; 174 175 static const uint8_t phone_raw_desc_21[] = { 176 0x0b, 0x24, 0x02, 0x01, 0x01, 0x02, 0x10, 0x01, 177 /* 8kHz */ 178 0x40, 0x1f, 0x00 179 }; 180 181 static const uint8_t phone_raw_desc_22[] = { 182 0x07, 0x25, 0x01, 0x00, 0x00, 0x00, 0x00 183 }; 184 185 static const void *phone_raw_iface_1_desc[] = { 186 phone_raw_desc_20, 187 phone_raw_desc_21, 188 NULL, 189 }; 190 191 static const void *phone_raw_ep_1_desc[] = { 192 phone_raw_desc_22, 193 NULL, 194 }; 195 196 static const struct usb_temp_packet_size phone_isoc_mps = { 197 .mps[USB_SPEED_FULL] = 0x10, 198 .mps[USB_SPEED_HIGH] = 0x10, 199 }; 200 201 static const struct usb_temp_interval phone_isoc_interval = { 202 .bInterval[USB_SPEED_FULL] = 1, /* 1:1 */ 203 .bInterval[USB_SPEED_HIGH] = 4, /* 1:8 */ 204 }; 205 206 static const struct usb_temp_endpoint_desc phone_isoc_in_ep = { 207 .ppRawDesc = phone_raw_ep_1_desc, 208 .pPacketSize = &phone_isoc_mps, 209 .pIntervals = &phone_isoc_interval, 210 .bEndpointAddress = UE_DIR_IN, 211 .bmAttributes = UE_ISOCHRONOUS, 212 }; 213 214 static const struct usb_temp_endpoint_desc *phone_iface_1_ep[] = { 215 &phone_isoc_in_ep, 216 NULL, 217 }; 218 219 static const struct usb_temp_interface_desc phone_iface_1_alt_0 = { 220 .ppEndpoints = NULL, /* no endpoints */ 221 .ppRawDesc = NULL, /* no raw descriptors */ 222 .bInterfaceClass = UICLASS_AUDIO, 223 .bInterfaceSubClass = UISUBCLASS_AUDIOSTREAM, 224 .bInterfaceProtocol = 0, 225 .iInterface = PHONE_PLAYBACK_INDEX, 226 }; 227 228 static const struct usb_temp_interface_desc phone_iface_1_alt_1 = { 229 .ppEndpoints = phone_iface_1_ep, 230 .ppRawDesc = phone_raw_iface_1_desc, 231 .bInterfaceClass = UICLASS_AUDIO, 232 .bInterfaceSubClass = UISUBCLASS_AUDIOSTREAM, 233 .bInterfaceProtocol = 0, 234 .iInterface = PHONE_PLAYBACK_INDEX, 235 .isAltInterface = 1, /* this is an alternate setting */ 236 }; 237 238 static const uint8_t phone_raw_desc_30[] = { 239 0x07, 0x24, 0x01, 0x02, 0x01, 0x01, 0x00 240 }; 241 242 static const uint8_t phone_raw_desc_31[] = { 243 0x0b, 0x24, 0x02, 0x01, 0x01, 0x02, 0x10, 0x01, 244 /* 8kHz */ 245 0x40, 0x1f, 0x00 246 }; 247 248 static const uint8_t phone_raw_desc_32[] = { 249 0x07, 0x25, 0x01, 0x00, 0x00, 0x00, 0x00 250 }; 251 252 static const void *phone_raw_iface_2_desc[] = { 253 phone_raw_desc_30, 254 phone_raw_desc_31, 255 NULL, 256 }; 257 258 static const void *phone_raw_ep_2_desc[] = { 259 phone_raw_desc_32, 260 NULL, 261 }; 262 263 static const struct usb_temp_endpoint_desc phone_isoc_out_ep = { 264 .ppRawDesc = phone_raw_ep_2_desc, 265 .pPacketSize = &phone_isoc_mps, 266 .pIntervals = &phone_isoc_interval, 267 .bEndpointAddress = UE_DIR_OUT, 268 .bmAttributes = UE_ISOCHRONOUS, 269 }; 270 271 static const struct usb_temp_endpoint_desc *phone_iface_2_ep[] = { 272 &phone_isoc_out_ep, 273 NULL, 274 }; 275 276 static const struct usb_temp_interface_desc phone_iface_2_alt_0 = { 277 .ppEndpoints = NULL, /* no endpoints */ 278 .ppRawDesc = NULL, /* no raw descriptors */ 279 .bInterfaceClass = UICLASS_AUDIO, 280 .bInterfaceSubClass = UISUBCLASS_AUDIOSTREAM, 281 .bInterfaceProtocol = 0, 282 .iInterface = PHONE_RECORD_INDEX, 283 }; 284 285 static const struct usb_temp_interface_desc phone_iface_2_alt_1 = { 286 .ppEndpoints = phone_iface_2_ep, 287 .ppRawDesc = phone_raw_iface_2_desc, 288 .bInterfaceClass = UICLASS_AUDIO, 289 .bInterfaceSubClass = UISUBCLASS_AUDIOSTREAM, 290 .bInterfaceProtocol = 0, 291 .iInterface = PHONE_RECORD_INDEX, 292 .isAltInterface = 1, /* this is an alternate setting */ 293 }; 294 295 static const uint8_t phone_hid_raw_desc_0[] = { 296 0x09, 0x21, 0x00, 0x01, 0x00, 0x01, 0x22, sizeof(phone_hid_descriptor), 297 0x00 298 }; 299 300 static const void *phone_hid_desc_0[] = { 301 phone_hid_raw_desc_0, 302 NULL, 303 }; 304 305 static const struct usb_temp_packet_size phone_hid_mps = { 306 .mps[USB_SPEED_FULL] = 0x10, 307 .mps[USB_SPEED_HIGH] = 0x10, 308 }; 309 310 static const struct usb_temp_interval phone_hid_interval = { 311 .bInterval[USB_SPEED_FULL] = 2, /* 2ms */ 312 .bInterval[USB_SPEED_HIGH] = 2, /* 2ms */ 313 }; 314 315 static const struct usb_temp_endpoint_desc phone_hid_in_ep = { 316 .pPacketSize = &phone_hid_mps, 317 .pIntervals = &phone_hid_interval, 318 .bEndpointAddress = UE_DIR_IN, 319 .bmAttributes = UE_INTERRUPT, 320 }; 321 322 static const struct usb_temp_endpoint_desc *phone_iface_3_ep[] = { 323 &phone_hid_in_ep, 324 NULL, 325 }; 326 327 static const struct usb_temp_interface_desc phone_iface_3 = { 328 .ppEndpoints = phone_iface_3_ep, 329 .ppRawDesc = phone_hid_desc_0, 330 .bInterfaceClass = UICLASS_HID, 331 .bInterfaceSubClass = 0, 332 .bInterfaceProtocol = 0, 333 .iInterface = PHONE_HID_INDEX, 334 }; 335 336 static const struct usb_temp_interface_desc *phone_interfaces[] = { 337 &phone_iface_0, 338 &phone_iface_1_alt_0, 339 &phone_iface_1_alt_1, 340 &phone_iface_2_alt_0, 341 &phone_iface_2_alt_1, 342 &phone_iface_3, 343 NULL, 344 }; 345 346 static const struct usb_temp_config_desc phone_config_desc = { 347 .ppIfaceDesc = phone_interfaces, 348 .bmAttributes = UC_BUS_POWERED, 349 .bMaxPower = 25, /* 50 mA */ 350 .iConfiguration = PHONE_PRODUCT_INDEX, 351 }; 352 353 static const struct usb_temp_config_desc *phone_configs[] = { 354 &phone_config_desc, 355 NULL, 356 }; 357 358 static usb_temp_get_string_desc_t phone_get_string_desc; 359 static usb_temp_get_vendor_desc_t phone_get_vendor_desc; 360 361 struct usb_temp_device_desc usb_template_phone = { 362 .getStringDesc = &phone_get_string_desc, 363 .getVendorDesc = &phone_get_vendor_desc, 364 .ppConfigDesc = phone_configs, 365 .idVendor = USB_TEMPLATE_VENDOR, 366 .idProduct = 0xb001, 367 .bcdDevice = 0x0100, 368 .bDeviceClass = UDCLASS_IN_INTERFACE, 369 .bDeviceSubClass = 0, 370 .bDeviceProtocol = 0, 371 .iManufacturer = PHONE_MANUFACTURER_INDEX, 372 .iProduct = PHONE_PRODUCT_INDEX, 373 .iSerialNumber = PHONE_SERIAL_NUMBER_INDEX, 374 }; 375 376 /*------------------------------------------------------------------------* 377 * phone_get_vendor_desc 378 * 379 * Return values: 380 * NULL: Failure. No such vendor descriptor. 381 * Else: Success. Pointer to vendor descriptor is returned. 382 *------------------------------------------------------------------------*/ 383 static const void * 384 phone_get_vendor_desc(const struct usb_device_request *req, uint16_t *plen) 385 { 386 if ((req->bmRequestType == 0x81) && (req->bRequest == 0x06) && 387 (req->wValue[0] == 0x00) && (req->wValue[1] == 0x22) && 388 (req->wIndex[1] == 0) && (req->wIndex[0] == 3 /* iface */)) { 389 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, 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