1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 /* 27 * Copyright 2019 Joyent, Inc. 28 */ 29 30 /* 31 * USB Serial CDC ACM driver 32 * 33 * 1. General Concepts 34 * ------------------- 35 * 36 * 1.1 Overview 37 * ------------ 38 * This driver supports devices that comply with the USB Communication 39 * Device Class Abstract Control Model (USB CDC ACM) specification, 40 * which is available at http://www.usb.org. Given the broad nature 41 * of communication equipment, this driver supports the following 42 * types of devices: 43 * + Telecommunications devices: analog modems, mobile phones; 44 * + Networking devices: cable modems; 45 * Except the above mentioned acm devices, this driver also supports 46 * some devices which provide modem-like function and have pairs of 47 * bulk in/out pipes. 48 * 49 * There are three classes that make up the definition for communication 50 * devices: the Communication Device Class, the Communication Interface 51 * Class and the Data Interface Class. The Communication Device Class 52 * is a device level definition and is used by the host to properly 53 * identify a communication device that may present several different 54 * types of interfaces. The Communication Interface Class defines a 55 * general-purpose mechanism that can be used to enable all types of 56 * communication services on the Universal Serial Bus (USB). The Data 57 * Interface Class defines a general-purpose mechanism to enable bulk 58 * transfer on the USB when the data does not meet the requirements 59 * for any other class. 60 * 61 * 1.2 Interface Definitions 62 * ------------------------- 63 * Communication Class Interface is used for device management and, 64 * optionally, call management. Device management includes the requests 65 * that manage the operational state of a device, the device responses, 66 * and event notifications. In Abstract Control Model, the device can 67 * provide an internal implementation of call management over the Data 68 * Class interface or the Communication Class interface. 69 * 70 * The Data Class defines a data interface as an interface with a class 71 * type of Data Class. Data transmission on a communication device is 72 * not restricted to interfaces using the Data Class. Rather, a data 73 * interface is used to transmit and/or receive data that is not 74 * defined by any other class. The data could be: 75 * + Some form of raw data from a communication line. 76 * + Legacy modem data. 77 * + Data using a proprietary format. 78 * 79 * 1.3 Endpoint Requirements 80 * ------------------------- 81 * The Communication Class interface requires one endpoint, the management 82 * element. Optionally, it can have an additional endpoint, the notification 83 * element. The management element uses the default endpoint for all 84 * standard and Communication Class-specific requests. The notification 85 * element normally uses an interrupt endpoint. 86 * 87 * The type of endpoints belonging to a Data Class interface are restricted 88 * to bulk, and are expected to exist in pairs of the same type (one In and 89 * one Out). 90 * 91 * 1.4 ACM Function Characteristics 92 * -------------------------------- 93 * With Abstract Control Model, the USB device understands standard 94 * V.25ter (AT) commands. The device contains a Datapump and micro- 95 * controller that handles the AT commands and relay controls. The 96 * device uses both a Data Class interface and a Communication Class. 97 * interface. 98 * 99 * A Communication Class interface of type Abstract Control Model will 100 * consist of a minimum of two pipes; one is used to implement the 101 * management element and the other to implement a notification element. 102 * In addition, the device can use two pipes to implement channels over 103 * which to carry unspecified data, typically over a Data Class interface. 104 * 105 * 1.5 ACM Serial Emulation 106 * ------------------------ 107 * The Abstract Control Model can bridge the gap between legacy modem 108 * devices and USB devices. To support certain types of legacy applications, 109 * two problems need to be addressed. The first is supporting specific 110 * legacy control signals and state variables which are addressed 111 * directly by the various carrier modulation standards. To support these 112 * requirement, additional requests and notifications have been created. 113 * Please refer to macro, beginning with USB_CDC_REQ_* and 114 * USB_CDC_NOTIFICATION_*. 115 * 116 * The second significant item which is needed to bridge the gap between 117 * legacy modem designs and the Abstract Control Model is a means to 118 * multiplex call control (AT commands) on the Data Class interface. 119 * Legacy modem designs are limited by only supporting one channel for 120 * both "AT" commands and the actual data. To allow this type of 121 * functionality, the device must have a means to specify this limitation 122 * to the host. 123 * 124 * When describing this type of device, the Communication Class interface 125 * would still specify a Abstract Control Model, but call control would 126 * actually occur over the Data Class interface. To describe this 127 * particular characteristic, the Call Management Functional Descriptor 128 * would have bit D1 of bmCapabilities set. 129 * 130 * 1.6 Other Bulk In/Out Devices 131 * ----------------------------- 132 * Some devices don't conform to USB CDC specification, but they provide 133 * modem-like function and have pairs of bulk in/out pipes. This driver 134 * supports this kind of device and exports term nodes by their pipes. 135 * 136 * 2. Implementation 137 * ----------------- 138 * 139 * 2.1 Overview 140 * ------------ 141 * It is a device-specific driver (DSD) working with USB generic serial 142 * driver (GSD). It implements the USB-to-serial device-specific driver 143 * interface (DSDI) which is offered by GSD. The interface is defined 144 * by ds_ops_t structure. 145 * 146 * 2.2 Port States 147 * --------------- 148 * For USB CDC ACM devices, this driver is attached to its interface, 149 * and exports one port for each interface. For other modem-like devices, 150 * this driver can dynamically find the ports in the current device, 151 * and export one port for each pair bulk in/out pipes. Each port can 152 * be operated independently. 153 * 154 * port_state: 155 * 156 * attach_ports 157 * | 158 * | 159 * | 160 * v 161 * USBSACM_PORT_CLOSED 162 * | ^ 163 * | | 164 * V | 165 * open_port close_port 166 * | ^ 167 * | | 168 * V | 169 * USBSACM_PORT_OPEN 170 * 171 * 172 * 2.3 Pipe States 173 * --------------- 174 * Each port has its own bulk in/out pipes and some ports could also have 175 * its own interrupt pipes (traced by usbsacm_port structure), which are 176 * opened during attach. The pipe status is as following: 177 * 178 * pipe_state: 179 * 180 * usbsacm_init_alloc_ports usbsacm_free_ports 181 * | ^ 182 * v | 183 * |---->------ USBSACM_PORT_CLOSED ------>------+ 184 * ^ | 185 * | reconnect/resume/open_port 186 * | | 187 * disconnect/suspend/close_port | 188 * | v 189 * +------<------ USBSACM_PIPE_IDLE ------<------| 190 * | | 191 * V ^ 192 * | | 193 * +-----------------+ +-----------+ 194 * | | 195 * V ^ 196 * | | 197 * rx_start/tx_start----->------failed------->---------| 198 * | | 199 * | bulkin_cb/bulkout_cb 200 * V | 201 * | ^ 202 * | | 203 * +----->----- USBSACM_PIPE_BUSY ---->------+ 204 * 205 * 206 * To get its status in a timely way, acm driver can get the status 207 * of the device by polling the interrupt pipe. 208 * 209 */ 210 211 #include <sys/types.h> 212 #include <sys/param.h> 213 #include <sys/conf.h> 214 #include <sys/stream.h> 215 #include <sys/strsun.h> 216 #include <sys/termio.h> 217 #include <sys/termiox.h> 218 #include <sys/ddi.h> 219 #include <sys/sunddi.h> 220 #include <sys/byteorder.h> 221 #define USBDRV_MAJOR_VER 2 222 #define USBDRV_MINOR_VER 0 223 #include <sys/usb/usba.h> 224 #include <sys/usb/usbdevs.h> 225 #include <sys/usb/usba/usba_types.h> 226 #include <sys/usb/clients/usbser/usbser.h> 227 #include <sys/usb/clients/usbser/usbser_dsdi.h> 228 #include <sys/usb/clients/usbcdc/usb_cdc.h> 229 #include <sys/usb/clients/usbser/usbsacm/usbsacm.h> 230 231 /* devops entry points */ 232 static int usbsacm_attach(dev_info_t *, ddi_attach_cmd_t); 233 static int usbsacm_detach(dev_info_t *, ddi_detach_cmd_t); 234 static int usbsacm_getinfo(dev_info_t *, ddi_info_cmd_t, void *, 235 void **); 236 static int usbsacm_open(queue_t *, dev_t *, int, int, cred_t *); 237 238 /* DSD operations */ 239 static int usbsacm_ds_attach(ds_attach_info_t *); 240 static void usbsacm_ds_detach(ds_hdl_t); 241 static int usbsacm_ds_register_cb(ds_hdl_t, uint_t, ds_cb_t *); 242 static void usbsacm_ds_unregister_cb(ds_hdl_t, uint_t); 243 static int usbsacm_ds_open_port(ds_hdl_t, uint_t); 244 static int usbsacm_ds_close_port(ds_hdl_t, uint_t); 245 246 /* standard UART operations */ 247 static int usbsacm_ds_set_port_params(ds_hdl_t, uint_t, 248 ds_port_params_t *); 249 static int usbsacm_ds_set_modem_ctl(ds_hdl_t, uint_t, int, int); 250 static int usbsacm_ds_get_modem_ctl(ds_hdl_t, uint_t, int, int *); 251 static int usbsacm_ds_break_ctl(ds_hdl_t, uint_t, int); 252 253 /* data xfer */ 254 static int usbsacm_ds_tx(ds_hdl_t, uint_t, mblk_t *); 255 static mblk_t *usbsacm_ds_rx(ds_hdl_t, uint_t); 256 static void usbsacm_ds_stop(ds_hdl_t, uint_t, int); 257 static void usbsacm_ds_start(ds_hdl_t, uint_t, int); 258 259 /* fifo operations */ 260 static int usbsacm_ds_fifo_flush(ds_hdl_t, uint_t, int); 261 static int usbsacm_ds_fifo_drain(ds_hdl_t, uint_t, int); 262 static int usbsacm_wait_tx_drain(usbsacm_port_t *, int); 263 static int usbsacm_fifo_flush_locked(usbsacm_state_t *, uint_t, int); 264 265 /* power management and CPR */ 266 static int usbsacm_ds_suspend(ds_hdl_t); 267 static int usbsacm_ds_resume(ds_hdl_t); 268 static int usbsacm_ds_disconnect(ds_hdl_t); 269 static int usbsacm_ds_reconnect(ds_hdl_t); 270 static int usbsacm_ds_usb_power(ds_hdl_t, int, int, int *); 271 static int usbsacm_create_pm_components(usbsacm_state_t *); 272 static void usbsacm_destroy_pm_components(usbsacm_state_t *); 273 static void usbsacm_pm_set_busy(usbsacm_state_t *); 274 static void usbsacm_pm_set_idle(usbsacm_state_t *); 275 static int usbsacm_pwrlvl0(usbsacm_state_t *); 276 static int usbsacm_pwrlvl1(usbsacm_state_t *); 277 static int usbsacm_pwrlvl2(usbsacm_state_t *); 278 static int usbsacm_pwrlvl3(usbsacm_state_t *); 279 280 /* event handling */ 281 /* pipe callbacks */ 282 static void usbsacm_bulkin_cb(usb_pipe_handle_t, usb_bulk_req_t *); 283 static void usbsacm_bulkout_cb(usb_pipe_handle_t, usb_bulk_req_t *); 284 285 /* interrupt pipe */ 286 static void usbsacm_pipe_start_polling(usbsacm_port_t *acmp); 287 static void usbsacm_intr_cb(usb_pipe_handle_t ph, usb_intr_req_t *req); 288 static void usbsacm_intr_ex_cb(usb_pipe_handle_t ph, usb_intr_req_t *req); 289 static void usbsacm_parse_intr_data(usbsacm_port_t *acmp, mblk_t *data); 290 291 /* Utility functions */ 292 /* data transfer routines */ 293 static int usbsacm_rx_start(usbsacm_port_t *); 294 static void usbsacm_tx_start(usbsacm_port_t *); 295 static int usbsacm_send_data(usbsacm_port_t *, mblk_t *); 296 297 /* Initialize or release resources */ 298 static int usbsacm_init_alloc_ports(usbsacm_state_t *); 299 static void usbsacm_free_ports(usbsacm_state_t *); 300 static void usbsacm_cleanup(usbsacm_state_t *); 301 302 /* analysis functional descriptors */ 303 static int usbsacm_get_descriptors(usbsacm_state_t *); 304 305 /* hotplug */ 306 static int usbsacm_restore_device_state(usbsacm_state_t *); 307 static int usbsacm_restore_port_state(usbsacm_state_t *); 308 309 /* pipe operations */ 310 static int usbsacm_open_port_pipes(usbsacm_port_t *); 311 static void usbsacm_close_port_pipes(usbsacm_port_t *); 312 static void usbsacm_close_pipes(usbsacm_state_t *); 313 static void usbsacm_disconnect_pipes(usbsacm_state_t *); 314 static int usbsacm_reconnect_pipes(usbsacm_state_t *); 315 316 /* vendor-specific commands */ 317 static int usbsacm_req_write(usbsacm_port_t *, uchar_t, uint16_t, 318 mblk_t **); 319 static int usbsacm_set_line_coding(usbsacm_port_t *, 320 usb_cdc_line_coding_t *); 321 static void usbsacm_mctl2reg(int mask, int val, uint8_t *); 322 static int usbsacm_reg2mctl(uint8_t); 323 324 /* misc */ 325 static void usbsacm_put_tail(mblk_t **, mblk_t *); 326 static void usbsacm_put_head(mblk_t **, mblk_t *); 327 328 329 /* 330 * Standard STREAMS driver definitions 331 */ 332 struct module_info usbsacm_modinfo = { 333 0, /* module id */ 334 "usbsacm", /* module name */ 335 USBSER_MIN_PKTSZ, /* min pkt size */ 336 USBSER_MAX_PKTSZ, /* max pkt size */ 337 USBSER_HIWAT, /* hi watermark */ 338 USBSER_LOWAT /* low watermark */ 339 }; 340 341 static struct qinit usbsacm_rinit = { 342 NULL, 343 usbser_rsrv, 344 usbsacm_open, 345 usbser_close, 346 NULL, 347 &usbsacm_modinfo, 348 NULL 349 }; 350 351 static struct qinit usbsacm_winit = { 352 usbser_wput, 353 usbser_wsrv, 354 NULL, 355 NULL, 356 NULL, 357 &usbsacm_modinfo, 358 NULL 359 }; 360 361 362 struct streamtab usbsacm_str_info = { 363 &usbsacm_rinit, &usbsacm_winit, NULL, NULL 364 }; 365 366 /* cb_ops structure */ 367 static struct cb_ops usbsacm_cb_ops = { 368 nodev, /* cb_open */ 369 nodev, /* cb_close */ 370 nodev, /* cb_strategy */ 371 nodev, /* cb_print */ 372 nodev, /* cb_dump */ 373 nodev, /* cb_read */ 374 nodev, /* cb_write */ 375 nodev, /* cb_ioctl */ 376 nodev, /* cb_devmap */ 377 nodev, /* cb_mmap */ 378 nodev, /* cb_segmap */ 379 nochpoll, /* cb_chpoll */ 380 ddi_prop_op, /* cb_prop_op */ 381 &usbsacm_str_info, /* cb_stream */ 382 (int)(D_64BIT | D_NEW | D_MP | D_HOTPLUG) /* cb_flag */ 383 }; 384 385 /* dev_ops structure */ 386 struct dev_ops usbsacm_ops = { 387 DEVO_REV, /* devo_rev */ 388 0, /* devo_refcnt */ 389 usbsacm_getinfo, /* devo_getinfo */ 390 nulldev, /* devo_identify */ 391 nulldev, /* devo_probe */ 392 usbsacm_attach, /* devo_attach */ 393 usbsacm_detach, /* devo_detach */ 394 nodev, /* devo_reset */ 395 &usbsacm_cb_ops, /* devo_cb_ops */ 396 (struct bus_ops *)NULL, /* devo_bus_ops */ 397 usbser_power, /* devo_power */ 398 ddi_quiesce_not_needed, /* devo_quiesce */ 399 }; 400 401 extern struct mod_ops mod_driverops; 402 /* modldrv structure */ 403 static struct modldrv modldrv = { 404 &mod_driverops, /* type of module - driver */ 405 "USB Serial CDC ACM driver", 406 &usbsacm_ops, 407 }; 408 409 /* modlinkage structure */ 410 static struct modlinkage modlinkage = { 411 MODREV_1, 412 &modldrv, 413 NULL 414 }; 415 416 static void *usbsacm_statep; /* soft state */ 417 418 /* 419 * DSD definitions 420 */ 421 static ds_ops_t usbsacm_ds_ops = { 422 DS_OPS_VERSION, 423 usbsacm_ds_attach, 424 usbsacm_ds_detach, 425 usbsacm_ds_register_cb, 426 usbsacm_ds_unregister_cb, 427 usbsacm_ds_open_port, 428 usbsacm_ds_close_port, 429 usbsacm_ds_usb_power, 430 usbsacm_ds_suspend, 431 usbsacm_ds_resume, 432 usbsacm_ds_disconnect, 433 usbsacm_ds_reconnect, 434 usbsacm_ds_set_port_params, 435 usbsacm_ds_set_modem_ctl, 436 usbsacm_ds_get_modem_ctl, 437 usbsacm_ds_break_ctl, 438 NULL, /* NULL if h/w doesn't support loopback */ 439 usbsacm_ds_tx, 440 usbsacm_ds_rx, 441 usbsacm_ds_stop, 442 usbsacm_ds_start, 443 usbsacm_ds_fifo_flush, 444 usbsacm_ds_fifo_drain 445 }; 446 447 /* 448 * baud code -> baud rate (0 means unsupported rate) 449 */ 450 static int usbsacm_speedtab[] = { 451 0, /* B0 */ 452 50, /* B50 */ 453 75, /* B75 */ 454 110, /* B110 */ 455 134, /* B134 */ 456 150, /* B150 */ 457 200, /* B200 */ 458 300, /* B300 */ 459 600, /* B600 */ 460 1200, /* B1200 */ 461 1800, /* B1800 */ 462 2400, /* B2400 */ 463 4800, /* B4800 */ 464 9600, /* B9600 */ 465 19200, /* B19200 */ 466 38400, /* B38400 */ 467 57600, /* B57600 */ 468 76800, /* B76800 */ 469 115200, /* B115200 */ 470 153600, /* B153600 */ 471 230400, /* B230400 */ 472 307200, /* B307200 */ 473 460800, /* B460800 */ 474 921600 /* B921600 */ 475 }; 476 477 478 static uint_t usbsacm_errlevel = USB_LOG_L4; 479 static uint_t usbsacm_errmask = 0xffffffff; 480 static uint_t usbsacm_instance_debug = (uint_t)-1; 481 482 483 /* 484 * usbsacm driver's entry points 485 * ----------------------------- 486 */ 487 /* 488 * Module-wide initialization routine. 489 */ 490 int 491 _init(void) 492 { 493 int error; 494 495 if ((error = mod_install(&modlinkage)) == 0) { 496 497 error = ddi_soft_state_init(&usbsacm_statep, 498 usbser_soft_state_size(), 1); 499 } 500 501 return (error); 502 } 503 504 505 /* 506 * Module-wide tear-down routine. 507 */ 508 int 509 _fini(void) 510 { 511 int error; 512 513 if ((error = mod_remove(&modlinkage)) == 0) { 514 ddi_soft_state_fini(&usbsacm_statep); 515 } 516 517 return (error); 518 } 519 520 521 int 522 _info(struct modinfo *modinfop) 523 { 524 return (mod_info(&modlinkage, modinfop)); 525 } 526 527 528 /* 529 * Device configuration entry points 530 */ 531 static int 532 usbsacm_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 533 { 534 return (usbser_attach(dip, cmd, usbsacm_statep, &usbsacm_ds_ops)); 535 } 536 537 538 static int 539 usbsacm_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 540 { 541 return (usbser_detach(dip, cmd, usbsacm_statep)); 542 } 543 544 545 int 546 usbsacm_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, 547 void **result) 548 { 549 return (usbser_getinfo(dip, infocmd, arg, result, usbsacm_statep)); 550 } 551 552 553 static int 554 usbsacm_open(queue_t *rq, dev_t *dev, int flag, int sflag, cred_t *cr) 555 { 556 return (usbser_open(rq, dev, flag, sflag, cr, usbsacm_statep)); 557 } 558 559 /* 560 * usbsacm_ds_detach: 561 * attach device instance, called from GSD attach 562 * initialize state and device, including: 563 * state variables, locks, device node 564 * device registration with system 565 * power management 566 */ 567 static int 568 usbsacm_ds_attach(ds_attach_info_t *aip) 569 { 570 usbsacm_state_t *acmp; 571 572 acmp = (usbsacm_state_t *)kmem_zalloc(sizeof (usbsacm_state_t), 573 KM_SLEEP); 574 acmp->acm_dip = aip->ai_dip; 575 acmp->acm_usb_events = aip->ai_usb_events; 576 acmp->acm_ports = NULL; 577 *aip->ai_hdl = (ds_hdl_t)acmp; 578 579 /* registers usbsacm with the USBA framework */ 580 if (usb_client_attach(acmp->acm_dip, USBDRV_VERSION, 581 0) != USB_SUCCESS) { 582 583 goto fail; 584 } 585 586 /* Get the configuration information of device */ 587 if (usb_get_dev_data(acmp->acm_dip, &acmp->acm_dev_data, 588 USB_PARSE_LVL_CFG, 0) != USB_SUCCESS) { 589 590 goto fail; 591 } 592 acmp->acm_def_ph = acmp->acm_dev_data->dev_default_ph; 593 acmp->acm_dev_state = USB_DEV_ONLINE; 594 mutex_init(&acmp->acm_mutex, NULL, MUTEX_DRIVER, 595 acmp->acm_dev_data->dev_iblock_cookie); 596 597 acmp->acm_lh = usb_alloc_log_hdl(acmp->acm_dip, "usbsacm", 598 &usbsacm_errlevel, &usbsacm_errmask, &usbsacm_instance_debug, 0); 599 600 /* Create power management components */ 601 if (usbsacm_create_pm_components(acmp) != USB_SUCCESS) { 602 USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh, 603 "usbsacm_ds_attach: create pm components failed."); 604 605 goto fail; 606 } 607 608 /* Register to get callbacks for USB events */ 609 if (usb_register_event_cbs(acmp->acm_dip, acmp->acm_usb_events, 0) 610 != USB_SUCCESS) { 611 USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh, 612 "usbsacm_ds_attach: register event callback failed."); 613 614 goto fail; 615 } 616 617 /* 618 * If devices conform to acm spec, driver will attach using class id; 619 * if not, using device id. 620 */ 621 if ((strcmp(DEVI(acmp->acm_dip)->devi_binding_name, 622 "usbif,class2.2") == 0) || 623 ((strcmp(DEVI(acmp->acm_dip)->devi_binding_name, 624 "usb,class2.2.0") == 0))) { 625 626 acmp->acm_compatibility = B_TRUE; 627 } else { 628 USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh, 629 "usbsacm_ds_attach: A nonstandard device is attaching to " 630 "usbsacm driver. This device doesn't conform to " 631 "usb cdc spec."); 632 633 acmp->acm_compatibility = B_FALSE; 634 } 635 636 /* initialize state variables */ 637 if (usbsacm_init_alloc_ports(acmp) != USB_SUCCESS) { 638 USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh, 639 "usbsacm_ds_attach: initialize port structure failed."); 640 641 goto fail; 642 } 643 *aip->ai_port_cnt = acmp->acm_port_cnt; 644 645 /* Get max data size of bulk transfer */ 646 if (usb_pipe_get_max_bulk_transfer_size(acmp->acm_dip, 647 &acmp->acm_xfer_sz) != USB_SUCCESS) { 648 USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh, 649 "usbsacm_ds_attach: get max size of transfer failed."); 650 651 goto fail; 652 } 653 654 return (USB_SUCCESS); 655 fail: 656 usbsacm_cleanup(acmp); 657 658 return (USB_FAILURE); 659 } 660 661 662 /* 663 * usbsacm_ds_detach: 664 * detach device instance, called from GSD detach 665 */ 666 static void 667 usbsacm_ds_detach(ds_hdl_t hdl) 668 { 669 usbsacm_state_t *acmp = (usbsacm_state_t *)hdl; 670 671 USB_DPRINTF_L4(PRINT_MASK_CLOSE, acmp->acm_lh, 672 "usbsacm_ds_detach:"); 673 674 usbsacm_close_pipes(acmp); 675 usbsacm_cleanup(acmp); 676 } 677 678 679 /* 680 * usbsacm_ds_register_cb: 681 * GSD routine call ds_register_cb to register interrupt callbacks 682 * for the given port 683 */ 684 /*ARGSUSED*/ 685 static int 686 usbsacm_ds_register_cb(ds_hdl_t hdl, uint_t port_num, ds_cb_t *cb) 687 { 688 usbsacm_state_t *acmp = (usbsacm_state_t *)hdl; 689 usbsacm_port_t *acm_port; 690 691 USB_DPRINTF_L4(PRINT_MASK_OPEN, acmp->acm_lh, 692 "usbsacm_ds_register_cb: acmp = 0x%p port_num = %d", 693 (void *)acmp, port_num); 694 695 /* Check if port number is greater than actual port number. */ 696 if (port_num >= acmp->acm_port_cnt) { 697 USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh, 698 "usbsacm_ds_register_cb: port number is wrong."); 699 700 return (USB_FAILURE); 701 } 702 acm_port = &acmp->acm_ports[port_num]; 703 acm_port->acm_cb = *cb; 704 705 return (USB_SUCCESS); 706 } 707 708 709 /* 710 * usbsacm_ds_unregister_cb: 711 * GSD routine call ds_unregister_cb to unregister 712 * interrupt callbacks for the given port 713 */ 714 /*ARGSUSED*/ 715 static void 716 usbsacm_ds_unregister_cb(ds_hdl_t hdl, uint_t port_num) 717 { 718 usbsacm_state_t *acmp = (usbsacm_state_t *)hdl; 719 usbsacm_port_t *acm_port; 720 721 USB_DPRINTF_L4(PRINT_MASK_CLOSE, acmp->acm_lh, 722 "usbsacm_ds_unregister_cb: "); 723 724 if (port_num < acmp->acm_port_cnt) { 725 /* Release callback function */ 726 acm_port = &acmp->acm_ports[port_num]; 727 bzero(&acm_port->acm_cb, sizeof (acm_port->acm_cb)); 728 } 729 } 730 731 732 /* 733 * usbsacm_ds_open_port: 734 * GSD routine call ds_open_port 735 * to open the given port 736 */ 737 /*ARGSUSED*/ 738 static int 739 usbsacm_ds_open_port(ds_hdl_t hdl, uint_t port_num) 740 { 741 usbsacm_state_t *acmp = (usbsacm_state_t *)hdl; 742 usbsacm_port_t *acm_port = &acmp->acm_ports[port_num]; 743 744 USB_DPRINTF_L4(PRINT_MASK_OPEN, acmp->acm_lh, 745 "usbsacm_ds_open_port: port_num = %d", port_num); 746 747 mutex_enter(&acm_port->acm_port_mutex); 748 /* Check the status of the given port and device */ 749 if ((acmp->acm_dev_state == USB_DEV_DISCONNECTED) || 750 (acm_port->acm_port_state != USBSACM_PORT_CLOSED)) { 751 mutex_exit(&acm_port->acm_port_mutex); 752 753 return (USB_FAILURE); 754 } 755 mutex_exit(&acm_port->acm_port_mutex); 756 757 usbsacm_pm_set_busy(acmp); 758 759 /* open pipes of port */ 760 if (usbsacm_open_port_pipes(acm_port) != USB_SUCCESS) { 761 USB_DPRINTF_L2(PRINT_MASK_OPEN, acmp->acm_lh, 762 "usbsacm_ds_open_port: open pipes failed."); 763 764 return (USB_FAILURE); 765 } 766 767 mutex_enter(&acm_port->acm_port_mutex); 768 /* data receipt */ 769 if (usbsacm_rx_start(acm_port) != USB_SUCCESS) { 770 USB_DPRINTF_L2(PRINT_MASK_OPEN, acmp->acm_lh, 771 "usbsacm_ds_open_port: start receive data failed."); 772 mutex_exit(&acm_port->acm_port_mutex); 773 774 return (USB_FAILURE); 775 } 776 acm_port->acm_port_state = USBSACM_PORT_OPEN; 777 778 mutex_exit(&acm_port->acm_port_mutex); 779 780 return (USB_SUCCESS); 781 } 782 783 784 /* 785 * usbsacm_ds_close_port: 786 * GSD routine call ds_close_port 787 * to close the given port 788 */ 789 /*ARGSUSED*/ 790 static int 791 usbsacm_ds_close_port(ds_hdl_t hdl, uint_t port_num) 792 { 793 usbsacm_state_t *acmp = (usbsacm_state_t *)hdl; 794 usbsacm_port_t *acm_port = &acmp->acm_ports[port_num]; 795 int rval = USB_SUCCESS; 796 797 USB_DPRINTF_L4(PRINT_MASK_CLOSE, acmp->acm_lh, 798 "usbsacm_ds_close_port: acmp = 0x%p", (void *)acmp); 799 800 mutex_enter(&acm_port->acm_port_mutex); 801 acm_port->acm_port_state = USBSACM_PORT_CLOSED; 802 mutex_exit(&acm_port->acm_port_mutex); 803 804 usbsacm_close_port_pipes(acm_port); 805 806 mutex_enter(&acm_port->acm_port_mutex); 807 rval = usbsacm_fifo_flush_locked(acmp, port_num, DS_TX | DS_RX); 808 mutex_exit(&acm_port->acm_port_mutex); 809 810 usbsacm_pm_set_idle(acmp); 811 812 return (rval); 813 } 814 815 816 /* 817 * usbsacm_ds_usb_power: 818 * GSD routine call ds_usb_power 819 * to set power level of the component 820 */ 821 /*ARGSUSED*/ 822 static int 823 usbsacm_ds_usb_power(ds_hdl_t hdl, int comp, int level, int *new_state) 824 { 825 usbsacm_state_t *acmp = (usbsacm_state_t *)hdl; 826 usbsacm_pm_t *pm = acmp->acm_pm; 827 int rval = USB_SUCCESS; 828 829 USB_DPRINTF_L4(PRINT_MASK_PM, acmp->acm_lh, 830 "usbsacm_ds_usb_power: "); 831 832 /* check if pm is NULL */ 833 if (pm == NULL) { 834 USB_DPRINTF_L2(PRINT_MASK_PM, acmp->acm_lh, 835 "usbsacm_ds_usb_power: pm is NULL."); 836 837 return (USB_FAILURE); 838 } 839 840 mutex_enter(&acmp->acm_mutex); 841 /* 842 * check if we are transitioning to a legal power level 843 */ 844 if (USB_DEV_PWRSTATE_OK(pm->pm_pwr_states, level)) { 845 USB_DPRINTF_L2(PRINT_MASK_PM, acmp->acm_lh, 846 "usbsacm_ds_usb_power: " 847 "illegal power level %d, pwr_states=%x", 848 level, pm->pm_pwr_states); 849 mutex_exit(&acmp->acm_mutex); 850 851 return (USB_FAILURE); 852 } 853 854 /* 855 * if we are about to raise power and asked to lower power, fail 856 */ 857 if (pm->pm_raise_power && (level < (int)pm->pm_cur_power)) { 858 USB_DPRINTF_L2(PRINT_MASK_PM, acmp->acm_lh, 859 "usbsacm_ds_usb_power: wrong condition."); 860 mutex_exit(&acmp->acm_mutex); 861 862 return (USB_FAILURE); 863 } 864 865 /* 866 * Set the power status of device by request level. 867 */ 868 switch (level) { 869 case USB_DEV_OS_PWR_OFF: 870 rval = usbsacm_pwrlvl0(acmp); 871 872 break; 873 case USB_DEV_OS_PWR_1: 874 rval = usbsacm_pwrlvl1(acmp); 875 876 break; 877 case USB_DEV_OS_PWR_2: 878 rval = usbsacm_pwrlvl2(acmp); 879 880 break; 881 case USB_DEV_OS_FULL_PWR: 882 rval = usbsacm_pwrlvl3(acmp); 883 /* 884 * If usbser dev_state is DISCONNECTED or SUSPENDED, it shows 885 * that the usb serial device is disconnected/suspended while it 886 * is under power down state, now the device is powered up 887 * before it is reconnected/resumed. xxx_pwrlvl3() will set dev 888 * state to ONLINE, we need to set the dev state back to 889 * DISCONNECTED/SUSPENDED. 890 */ 891 if ((rval == USB_SUCCESS) && 892 ((*new_state == USB_DEV_DISCONNECTED) || 893 (*new_state == USB_DEV_SUSPENDED))) { 894 acmp->acm_dev_state = *new_state; 895 } 896 897 break; 898 } 899 900 *new_state = acmp->acm_dev_state; 901 mutex_exit(&acmp->acm_mutex); 902 903 return (rval); 904 } 905 906 907 /* 908 * usbsacm_ds_suspend: 909 * GSD routine call ds_suspend 910 * during CPR suspend 911 */ 912 static int 913 usbsacm_ds_suspend(ds_hdl_t hdl) 914 { 915 usbsacm_state_t *acmp = (usbsacm_state_t *)hdl; 916 int state = USB_DEV_SUSPENDED; 917 918 USB_DPRINTF_L4(PRINT_MASK_PM, acmp->acm_lh, 919 "usbsacm_ds_suspend: "); 920 /* 921 * If the device is suspended while it is under PWRED_DOWN state, we 922 * need to keep the PWRED_DOWN state so that it could be powered up 923 * later. In the mean while, usbser dev state will be changed to 924 * SUSPENDED state. 925 */ 926 mutex_enter(&acmp->acm_mutex); 927 if (acmp->acm_dev_state != USB_DEV_PWRED_DOWN) { 928 /* set device status to suspend */ 929 acmp->acm_dev_state = USB_DEV_SUSPENDED; 930 } 931 mutex_exit(&acmp->acm_mutex); 932 933 usbsacm_disconnect_pipes(acmp); 934 935 return (state); 936 } 937 938 /* 939 * usbsacm_ds_resume: 940 * GSD routine call ds_resume 941 * during CPR resume 942 */ 943 /*ARGSUSED*/ 944 static int 945 usbsacm_ds_resume(ds_hdl_t hdl) 946 { 947 usbsacm_state_t *acmp = (usbsacm_state_t *)hdl; 948 int current_state; 949 int ret; 950 951 USB_DPRINTF_L4(PRINT_MASK_PM, acmp->acm_lh, 952 "usbsacm_ds_resume: "); 953 954 mutex_enter(&acmp->acm_mutex); 955 current_state = acmp->acm_dev_state; 956 mutex_exit(&acmp->acm_mutex); 957 958 /* restore the status of device */ 959 if (current_state != USB_DEV_ONLINE) { 960 ret = usbsacm_restore_device_state(acmp); 961 } else { 962 ret = USB_DEV_ONLINE; 963 } 964 965 return (ret); 966 } 967 968 /* 969 * usbsacm_ds_disconnect: 970 * GSD routine call ds_disconnect 971 * to disconnect USB device 972 */ 973 static int 974 usbsacm_ds_disconnect(ds_hdl_t hdl) 975 { 976 usbsacm_state_t *acmp = (usbsacm_state_t *)hdl; 977 int state = USB_DEV_DISCONNECTED; 978 979 USB_DPRINTF_L4(PRINT_MASK_CLOSE, acmp->acm_lh, 980 "usbsacm_ds_disconnect: "); 981 982 /* 983 * If the device is disconnected while it is under PWRED_DOWN state, we 984 * need to keep the PWRED_DOWN state so that it could be powered up 985 * later. In the mean while, usbser dev state will be changed to 986 * DISCONNECTED state. 987 */ 988 mutex_enter(&acmp->acm_mutex); 989 if (acmp->acm_dev_state != USB_DEV_PWRED_DOWN) { 990 /* set device status to disconnected */ 991 acmp->acm_dev_state = USB_DEV_DISCONNECTED; 992 } 993 mutex_exit(&acmp->acm_mutex); 994 995 usbsacm_disconnect_pipes(acmp); 996 997 return (state); 998 } 999 1000 1001 /* 1002 * usbsacm_ds_reconnect: 1003 * GSD routine call ds_reconnect 1004 * to reconnect USB device 1005 */ 1006 /*ARGSUSED*/ 1007 static int 1008 usbsacm_ds_reconnect(ds_hdl_t hdl) 1009 { 1010 usbsacm_state_t *acmp = (usbsacm_state_t *)hdl; 1011 1012 USB_DPRINTF_L4(PRINT_MASK_OPEN, acmp->acm_lh, 1013 "usbsacm_ds_reconnect: "); 1014 1015 return (usbsacm_restore_device_state(acmp)); 1016 } 1017 1018 1019 /* 1020 * usbsacm_ds_set_port_params: 1021 * GSD routine call ds_set_port_params 1022 * to set one or more port parameters 1023 */ 1024 /*ARGSUSED*/ 1025 static int 1026 usbsacm_ds_set_port_params(ds_hdl_t hdl, uint_t port_num, ds_port_params_t *tp) 1027 { 1028 usbsacm_state_t *acmp = (usbsacm_state_t *)hdl; 1029 usbsacm_port_t *acm_port = &acmp->acm_ports[port_num]; 1030 int i; 1031 uint_t ui; 1032 ds_port_param_entry_t *pe; 1033 usb_cdc_line_coding_t lc; 1034 int ret; 1035 1036 USB_DPRINTF_L4(PRINT_MASK_ALL, acmp->acm_lh, 1037 "usbsacm_ds_set_port_params: acmp = 0x%p", (void *)acmp); 1038 1039 mutex_enter(&acm_port->acm_port_mutex); 1040 /* 1041 * If device conform to acm spec, check if it support to set port param. 1042 */ 1043 if ((acm_port->acm_cap & USB_CDC_ACM_CAP_SERIAL_LINE) == 0 && 1044 acmp->acm_compatibility == B_TRUE) { 1045 1046 mutex_exit(&acm_port->acm_port_mutex); 1047 USB_DPRINTF_L2(PRINT_MASK_ALL, acmp->acm_lh, 1048 "usbsacm_ds_set_port_params: " 1049 "don't support Set_Line_Coding."); 1050 1051 return (USB_FAILURE); 1052 } 1053 1054 lc = acm_port->acm_line_coding; 1055 mutex_exit(&acm_port->acm_port_mutex); 1056 pe = tp->tp_entries; 1057 /* Get parameter information from ds_port_params_t */ 1058 for (i = 0; i < tp->tp_cnt; i++, pe++) { 1059 switch (pe->param) { 1060 case DS_PARAM_BAUD: 1061 /* Data terminal rate, in bits per second. */ 1062 ui = pe->val.ui; 1063 1064 /* if we don't support this speed, return USB_FAILURE */ 1065 if ((ui >= NELEM(usbsacm_speedtab)) || 1066 ((ui > 0) && (usbsacm_speedtab[ui] == 0))) { 1067 USB_DPRINTF_L2(PRINT_MASK_EVENTS, acmp->acm_lh, 1068 "usbsacm_ds_set_port_params: " 1069 " error baud rate"); 1070 1071 return (USB_FAILURE); 1072 } 1073 lc.dwDTERate = LE_32(usbsacm_speedtab[ui]); 1074 1075 break; 1076 case DS_PARAM_PARITY: 1077 /* Parity Type */ 1078 if (pe->val.ui & PARENB) { 1079 if (pe->val.ui & PARODD) { 1080 lc.bParityType = USB_CDC_PARITY_ODD; 1081 } else { 1082 lc.bParityType = USB_CDC_PARITY_EVEN; 1083 } 1084 } else { 1085 lc.bParityType = USB_CDC_PARITY_NO; 1086 } 1087 1088 break; 1089 case DS_PARAM_STOPB: 1090 /* Stop bit */ 1091 if (pe->val.ui & CSTOPB) { 1092 lc.bCharFormat = USB_CDC_STOP_BITS_2; 1093 } else { 1094 lc.bCharFormat = USB_CDC_STOP_BITS_1; 1095 } 1096 1097 break; 1098 case DS_PARAM_CHARSZ: 1099 /* Data Bits */ 1100 switch (pe->val.ui) { 1101 case CS5: 1102 lc.bDataBits = 5; 1103 break; 1104 case CS6: 1105 lc.bDataBits = 6; 1106 break; 1107 case CS7: 1108 lc.bDataBits = 7; 1109 break; 1110 case CS8: 1111 default: 1112 lc.bDataBits = 8; 1113 break; 1114 } 1115 1116 break; 1117 default: 1118 USB_DPRINTF_L2(PRINT_MASK_EVENTS, acmp->acm_lh, 1119 "usbsacm_ds_set_port_params: " 1120 "parameter 0x%x isn't supported", 1121 pe->param); 1122 1123 break; 1124 } 1125 } 1126 1127 if ((ret = usbsacm_set_line_coding(acm_port, &lc)) == USB_SUCCESS) { 1128 mutex_enter(&acm_port->acm_port_mutex); 1129 acm_port->acm_line_coding = lc; 1130 mutex_exit(&acm_port->acm_port_mutex); 1131 } 1132 1133 /* 1134 * If device don't conform to acm spec, return success directly. 1135 */ 1136 if (acmp->acm_compatibility != B_TRUE) { 1137 ret = USB_SUCCESS; 1138 } 1139 1140 return (ret); 1141 } 1142 1143 1144 /* 1145 * usbsacm_ds_set_modem_ctl: 1146 * GSD routine call ds_set_modem_ctl 1147 * to set modem control of the given port 1148 */ 1149 /*ARGSUSED*/ 1150 static int 1151 usbsacm_ds_set_modem_ctl(ds_hdl_t hdl, uint_t port_num, int mask, int val) 1152 { 1153 usbsacm_state_t *acmp = (usbsacm_state_t *)hdl; 1154 usbsacm_port_t *acm_port = &acmp->acm_ports[port_num]; 1155 uint8_t new_mctl; 1156 int ret; 1157 1158 USB_DPRINTF_L4(PRINT_MASK_ALL, acmp->acm_lh, 1159 "usbsacm_ds_set_modem_ctl: mask = 0x%x val = 0x%x", 1160 mask, val); 1161 1162 mutex_enter(&acm_port->acm_port_mutex); 1163 /* 1164 * If device conform to acm spec, check if it support to set modem 1165 * controls. 1166 */ 1167 if ((acm_port->acm_cap & USB_CDC_ACM_CAP_SERIAL_LINE) == 0 && 1168 acmp->acm_compatibility == B_TRUE) { 1169 1170 mutex_exit(&acm_port->acm_port_mutex); 1171 USB_DPRINTF_L2(PRINT_MASK_ALL, acmp->acm_lh, 1172 "usbsacm_ds_set_modem_ctl: " 1173 "don't support Set_Control_Line_State."); 1174 1175 return (USB_FAILURE); 1176 } 1177 1178 new_mctl = acm_port->acm_mctlout; 1179 mutex_exit(&acm_port->acm_port_mutex); 1180 1181 usbsacm_mctl2reg(mask, val, &new_mctl); 1182 1183 if ((acmp->acm_compatibility == B_FALSE) || ((ret = 1184 usbsacm_req_write(acm_port, USB_CDC_REQ_SET_CONTROL_LINE_STATE, 1185 new_mctl, NULL)) == USB_SUCCESS)) { 1186 mutex_enter(&acm_port->acm_port_mutex); 1187 acm_port->acm_mctlout = new_mctl; 1188 mutex_exit(&acm_port->acm_port_mutex); 1189 } 1190 1191 /* 1192 * If device don't conform to acm spec, return success directly. 1193 */ 1194 if (acmp->acm_compatibility != B_TRUE) { 1195 ret = USB_SUCCESS; 1196 } 1197 1198 return (ret); 1199 } 1200 1201 1202 /* 1203 * usbsacm_ds_get_modem_ctl: 1204 * GSD routine call ds_get_modem_ctl 1205 * to get modem control/status of the given port 1206 */ 1207 /*ARGSUSED*/ 1208 static int 1209 usbsacm_ds_get_modem_ctl(ds_hdl_t hdl, uint_t port_num, int mask, int *valp) 1210 { 1211 usbsacm_state_t *acmp = (usbsacm_state_t *)hdl; 1212 usbsacm_port_t *acm_port = &acmp->acm_ports[port_num]; 1213 1214 mutex_enter(&acm_port->acm_port_mutex); 1215 *valp = usbsacm_reg2mctl(acm_port->acm_mctlout) & mask; 1216 /* 1217 * If device conform to acm spec, polling function can modify the value 1218 * of acm_mctlin; else set to default value. 1219 */ 1220 if (acmp->acm_compatibility) { 1221 *valp |= usbsacm_reg2mctl(acm_port->acm_mctlin) & mask; 1222 *valp |= (mask & (TIOCM_CD | TIOCM_CTS)); 1223 } else { 1224 *valp |= (mask & (TIOCM_CD | TIOCM_CTS | TIOCM_DSR | TIOCM_RI)); 1225 } 1226 mutex_exit(&acm_port->acm_port_mutex); 1227 1228 USB_DPRINTF_L4(PRINT_MASK_ALL, acmp->acm_lh, 1229 "usbsacm_ds_get_modem_ctl: val = 0x%x", *valp); 1230 1231 return (USB_SUCCESS); 1232 } 1233 1234 1235 /* 1236 * usbsacm_ds_tx: 1237 * GSD routine call ds_break_ctl 1238 * to set/clear break 1239 */ 1240 /*ARGSUSED*/ 1241 static int 1242 usbsacm_ds_break_ctl(ds_hdl_t hdl, uint_t port_num, int ctl) 1243 { 1244 usbsacm_state_t *acmp = (usbsacm_state_t *)hdl; 1245 usbsacm_port_t *acm_port = &acmp->acm_ports[port_num]; 1246 1247 USB_DPRINTF_L4(PRINT_MASK_ALL, acmp->acm_lh, 1248 "usbsacm_ds_break_ctl: "); 1249 1250 mutex_enter(&acm_port->acm_port_mutex); 1251 /* 1252 * If device conform to acm spec, check if it support to send break. 1253 */ 1254 if ((acm_port->acm_cap & USB_CDC_ACM_CAP_SEND_BREAK) == 0 && 1255 acmp->acm_compatibility == B_TRUE) { 1256 1257 mutex_exit(&acm_port->acm_port_mutex); 1258 USB_DPRINTF_L2(PRINT_MASK_ALL, acmp->acm_lh, 1259 "usbsacm_ds_break_ctl: don't support send break."); 1260 1261 return (USB_FAILURE); 1262 } 1263 mutex_exit(&acm_port->acm_port_mutex); 1264 1265 return (usbsacm_req_write(acm_port, USB_CDC_REQ_SEND_BREAK, 1266 ((ctl == DS_ON) ? 0xffff : 0), NULL)); 1267 } 1268 1269 1270 /* 1271 * usbsacm_ds_tx: 1272 * GSD routine call ds_tx 1273 * to data transmit 1274 */ 1275 /*ARGSUSED*/ 1276 static int 1277 usbsacm_ds_tx(ds_hdl_t hdl, uint_t port_num, mblk_t *mp) 1278 { 1279 usbsacm_state_t *acmp = (usbsacm_state_t *)hdl; 1280 usbsacm_port_t *acm_port = &acmp->acm_ports[port_num]; 1281 1282 USB_DPRINTF_L4(PRINT_MASK_ALL, acmp->acm_lh, 1283 "usbsacm_ds_tx: mp = 0x%p acmp = 0x%p", (void *)mp, (void *)acmp); 1284 1285 /* sanity checks */ 1286 if (mp == NULL) { 1287 1288 return (USB_SUCCESS); 1289 } 1290 if (MBLKL(mp) < 1) { 1291 freemsg(mp); 1292 1293 return (USB_SUCCESS); 1294 } 1295 1296 mutex_enter(&acm_port->acm_port_mutex); 1297 /* put mblk to tail of mblk chain */ 1298 usbsacm_put_tail(&acm_port->acm_tx_mp, mp); 1299 usbsacm_tx_start(acm_port); 1300 mutex_exit(&acm_port->acm_port_mutex); 1301 1302 return (USB_SUCCESS); 1303 } 1304 1305 1306 /* 1307 * usbsacm_ds_rx: 1308 * GSD routine call ds_rx; 1309 * to data receipt 1310 */ 1311 /*ARGSUSED*/ 1312 static mblk_t * 1313 usbsacm_ds_rx(ds_hdl_t hdl, uint_t port_num) 1314 { 1315 usbsacm_state_t *acmp = (usbsacm_state_t *)hdl; 1316 usbsacm_port_t *acm_port = &acmp->acm_ports[port_num]; 1317 mblk_t *mp; 1318 1319 USB_DPRINTF_L4(PRINT_MASK_ALL, acmp->acm_lh, 1320 "usbsacm_ds_rx: acmp = 0x%p", (void *)acmp); 1321 1322 mutex_enter(&acm_port->acm_port_mutex); 1323 1324 mp = acm_port->acm_rx_mp; 1325 acm_port->acm_rx_mp = NULL; 1326 mutex_exit(&acm_port->acm_port_mutex); 1327 1328 return (mp); 1329 } 1330 1331 1332 /* 1333 * usbsacm_ds_stop: 1334 * GSD routine call ds_stop; 1335 * but acm spec don't define this function 1336 */ 1337 /*ARGSUSED*/ 1338 static void 1339 usbsacm_ds_stop(ds_hdl_t hdl, uint_t port_num, int dir) 1340 { 1341 usbsacm_state_t *acmp = (usbsacm_state_t *)hdl; 1342 1343 USB_DPRINTF_L2(PRINT_MASK_EVENTS, acmp->acm_lh, 1344 "usbsacm_ds_stop: don't support!"); 1345 } 1346 1347 1348 /* 1349 * usbsacm_ds_start: 1350 * GSD routine call ds_start; 1351 * but acm spec don't define this function 1352 */ 1353 /*ARGSUSED*/ 1354 static void 1355 usbsacm_ds_start(ds_hdl_t hdl, uint_t port_num, int dir) 1356 { 1357 usbsacm_state_t *acmp = (usbsacm_state_t *)hdl; 1358 1359 USB_DPRINTF_L2(PRINT_MASK_EVENTS, acmp->acm_lh, 1360 "usbsacm_ds_start: don't support!"); 1361 } 1362 1363 1364 /* 1365 * usbsacm_ds_fifo_flush: 1366 * GSD routine call ds_fifo_flush 1367 * to flush FIFOs 1368 */ 1369 /*ARGSUSED*/ 1370 static int 1371 usbsacm_ds_fifo_flush(ds_hdl_t hdl, uint_t port_num, int dir) 1372 { 1373 usbsacm_state_t *acmp = (usbsacm_state_t *)hdl; 1374 usbsacm_port_t *acm_port = &acmp->acm_ports[port_num]; 1375 int ret = USB_SUCCESS; 1376 1377 USB_DPRINTF_L4(PRINT_MASK_ALL, acmp->acm_lh, 1378 "usbsacm_ds_fifo_flush: "); 1379 1380 mutex_enter(&acm_port->acm_port_mutex); 1381 ret = usbsacm_fifo_flush_locked(acmp, port_num, dir); 1382 mutex_exit(&acm_port->acm_port_mutex); 1383 1384 return (ret); 1385 } 1386 1387 1388 /* 1389 * usbsacm_ds_fifo_drain: 1390 * GSD routine call ds_fifo_drain 1391 * to wait until empty output FIFO 1392 */ 1393 /*ARGSUSED*/ 1394 static int 1395 usbsacm_ds_fifo_drain(ds_hdl_t hdl, uint_t port_num, int timeout) 1396 { 1397 usbsacm_state_t *acmp = (usbsacm_state_t *)hdl; 1398 usbsacm_port_t *acm_port = &acmp->acm_ports[port_num]; 1399 int rval = USB_SUCCESS; 1400 1401 USB_DPRINTF_L4(PRINT_MASK_EVENTS, acmp->acm_lh, 1402 "usbsacm_ds_fifo_drain: "); 1403 1404 mutex_enter(&acm_port->acm_port_mutex); 1405 ASSERT(acm_port->acm_port_state == USBSACM_PORT_OPEN); 1406 1407 if (usbsacm_wait_tx_drain(acm_port, timeout) != USB_SUCCESS) { 1408 USB_DPRINTF_L2(PRINT_MASK_EVENTS, acmp->acm_lh, 1409 "usbsacm_ds_fifo_drain: fifo drain failed."); 1410 mutex_exit(&acm_port->acm_port_mutex); 1411 1412 return (USB_FAILURE); 1413 } 1414 1415 mutex_exit(&acm_port->acm_port_mutex); 1416 1417 return (rval); 1418 } 1419 1420 1421 /* 1422 * usbsacm_fifo_flush_locked: 1423 * flush FIFOs of the given ports 1424 */ 1425 /*ARGSUSED*/ 1426 static int 1427 usbsacm_fifo_flush_locked(usbsacm_state_t *acmp, uint_t port_num, int dir) 1428 { 1429 usbsacm_port_t *acm_port = &acmp->acm_ports[port_num]; 1430 1431 USB_DPRINTF_L4(PRINT_MASK_EVENTS, acmp->acm_lh, 1432 "usbsacm_fifo_flush_locked: "); 1433 1434 /* flush transmit FIFO if DS_TX is set */ 1435 if ((dir & DS_TX) && acm_port->acm_tx_mp) { 1436 freemsg(acm_port->acm_tx_mp); 1437 acm_port->acm_tx_mp = NULL; 1438 } 1439 /* flush received FIFO if DS_RX is set */ 1440 if ((dir & DS_RX) && acm_port->acm_rx_mp) { 1441 freemsg(acm_port->acm_rx_mp); 1442 acm_port->acm_rx_mp = NULL; 1443 } 1444 1445 return (USB_SUCCESS); 1446 } 1447 1448 1449 /* 1450 * usbsacm_get_bulk_pipe_number: 1451 * Calculate the number of bulk in or out pipes in current device. 1452 */ 1453 static int 1454 usbsacm_get_bulk_pipe_number(usbsacm_state_t *acmp, uint_t dir) 1455 { 1456 int count = 0; 1457 int i, skip; 1458 usb_if_data_t *cur_if; 1459 int ep_num; 1460 int if_num; 1461 1462 USB_DPRINTF_L4(PRINT_MASK_ATTA, acmp->acm_lh, 1463 "usbsacm_get_bulk_pipe_number: "); 1464 1465 cur_if = acmp->acm_dev_data->dev_curr_cfg->cfg_if; 1466 if_num = acmp->acm_dev_data->dev_curr_cfg->cfg_n_if; 1467 1468 /* search each interface which have bulk endpoint */ 1469 for (i = 0; i < if_num; i++) { 1470 ep_num = cur_if->if_alt->altif_n_ep; 1471 1472 /* 1473 * search endpoints in current interface, 1474 * which type is input parameter 'dir' 1475 */ 1476 for (skip = 0; skip < ep_num; skip++) { 1477 if (usb_lookup_ep_data(acmp->acm_dip, 1478 acmp->acm_dev_data, i, 0, skip, 1479 USB_EP_ATTR_BULK, dir) == NULL) { 1480 1481 /* 1482 * If not found, skip the internal loop 1483 * and search the next interface. 1484 */ 1485 break; 1486 } 1487 count++; 1488 } 1489 1490 cur_if++; 1491 } 1492 1493 return (count); 1494 } 1495 1496 1497 /* 1498 * port management 1499 * --------------- 1500 * initialize, release port. 1501 * 1502 * 1503 * usbsacm_init_ports_status: 1504 * Initialize the port status for the current device. 1505 */ 1506 static int 1507 usbsacm_init_ports_status(usbsacm_state_t *acmp) 1508 { 1509 usbsacm_port_t *cur_port; 1510 int i, skip; 1511 int if_num; 1512 int intr_if_no = 0; 1513 int ep_num; 1514 usb_if_data_t *cur_if; 1515 1516 USB_DPRINTF_L4(PRINT_MASK_OPEN, acmp->acm_lh, 1517 "usbsacm_init_ports_status: acmp = 0x%p", (void *)acmp); 1518 1519 /* Initialize the port status to default value */ 1520 for (i = 0; i < acmp->acm_port_cnt; i++) { 1521 cur_port = &acmp->acm_ports[i]; 1522 1523 cv_init(&cur_port->acm_tx_cv, NULL, CV_DRIVER, NULL); 1524 1525 cur_port->acm_port_state = USBSACM_PORT_CLOSED; 1526 1527 cur_port->acm_line_coding.dwDTERate = LE_32((uint32_t)9600); 1528 cur_port->acm_line_coding.bCharFormat = 0; 1529 cur_port->acm_line_coding.bParityType = USB_CDC_PARITY_NO; 1530 cur_port->acm_line_coding.bDataBits = 8; 1531 cur_port->acm_device = acmp; 1532 mutex_init(&cur_port->acm_port_mutex, NULL, MUTEX_DRIVER, 1533 acmp->acm_dev_data->dev_iblock_cookie); 1534 } 1535 1536 /* 1537 * If device conform to cdc acm spec, parse function descriptors. 1538 */ 1539 if (acmp->acm_compatibility == B_TRUE) { 1540 1541 if (usbsacm_get_descriptors(acmp) != USB_SUCCESS) { 1542 1543 return (USB_FAILURE); 1544 } 1545 1546 return (USB_SUCCESS); 1547 } 1548 1549 /* 1550 * If device don't conform to spec, search pairs of bulk in/out 1551 * endpoints and fill port structure. 1552 */ 1553 cur_if = acmp->acm_dev_data->dev_curr_cfg->cfg_if; 1554 if_num = acmp->acm_dev_data->dev_curr_cfg->cfg_n_if; 1555 cur_port = acmp->acm_ports; 1556 1557 /* search each interface which have bulk in and out */ 1558 for (i = 0; i < if_num; i++) { 1559 ep_num = cur_if->if_alt->altif_n_ep; 1560 1561 for (skip = 0; skip < ep_num; skip++) { 1562 1563 /* search interrupt pipe. */ 1564 if ((usb_lookup_ep_data(acmp->acm_dip, acmp->acm_dev_data, 1565 i, 0, skip, USB_EP_ATTR_INTR, USB_EP_DIR_IN) != NULL)) { 1566 1567 intr_if_no = i; 1568 } 1569 1570 /* search pair of bulk in/out endpoints. */ 1571 if ((usb_lookup_ep_data(acmp->acm_dip, acmp->acm_dev_data, 1572 i, 0, skip, USB_EP_ATTR_BULK, USB_EP_DIR_IN) == NULL) || 1573 (usb_lookup_ep_data(acmp->acm_dip, acmp->acm_dev_data, 1574 i, 0, skip, USB_EP_ATTR_BULK, USB_EP_DIR_OUT) == NULL)) { 1575 1576 continue; 1577 } 1578 1579 cur_port->acm_data_if_no = i; 1580 cur_port->acm_ctrl_if_no = intr_if_no; 1581 cur_port->acm_data_port_no = skip; 1582 cur_port++; 1583 intr_if_no = 0; 1584 } 1585 1586 cur_if++; 1587 } 1588 1589 return (USB_SUCCESS); 1590 } 1591 1592 1593 /* 1594 * usbsacm_init_alloc_ports: 1595 * Allocate memory and initialize the port state for the current device. 1596 */ 1597 static int 1598 usbsacm_init_alloc_ports(usbsacm_state_t *acmp) 1599 { 1600 int rval = USB_SUCCESS; 1601 int count_in = 0, count_out = 0; 1602 1603 if (acmp->acm_compatibility) { 1604 acmp->acm_port_cnt = 1; 1605 } else { 1606 /* Calculate the number of the bulk in/out endpoints */ 1607 count_in = usbsacm_get_bulk_pipe_number(acmp, USB_EP_DIR_IN); 1608 count_out = usbsacm_get_bulk_pipe_number(acmp, USB_EP_DIR_OUT); 1609 1610 USB_DPRINTF_L3(PRINT_MASK_OPEN, acmp->acm_lh, 1611 "usbsacm_init_alloc_ports: count_in = %d, count_out = %d", 1612 count_in, count_out); 1613 1614 acmp->acm_port_cnt = min(count_in, count_out); 1615 } 1616 1617 /* return if not found any pair of bulk in/out endpoint. */ 1618 if (acmp->acm_port_cnt == 0) { 1619 USB_DPRINTF_L2(PRINT_MASK_OPEN, acmp->acm_lh, 1620 "usbsacm_init_alloc_ports: port count is zero."); 1621 1622 return (USB_FAILURE); 1623 } 1624 1625 /* allocate memory for ports */ 1626 acmp->acm_ports = (usbsacm_port_t *)kmem_zalloc(acmp->acm_port_cnt * 1627 sizeof (usbsacm_port_t), KM_SLEEP); 1628 if (acmp->acm_ports == NULL) { 1629 USB_DPRINTF_L2(PRINT_MASK_OPEN, acmp->acm_lh, 1630 "usbsacm_init_alloc_ports: allocate memory failed."); 1631 1632 return (USB_FAILURE); 1633 } 1634 1635 /* fill the status of port structure. */ 1636 rval = usbsacm_init_ports_status(acmp); 1637 if (rval != USB_SUCCESS) { 1638 usbsacm_free_ports(acmp); 1639 } 1640 1641 return (rval); 1642 } 1643 1644 1645 /* 1646 * usbsacm_free_ports: 1647 * Release ports and deallocate memory. 1648 */ 1649 static void 1650 usbsacm_free_ports(usbsacm_state_t *acmp) 1651 { 1652 int i; 1653 1654 USB_DPRINTF_L4(PRINT_MASK_CLOSE, acmp->acm_lh, 1655 "usbsacm_free_ports: "); 1656 1657 /* Release memory and data structure for each port */ 1658 for (i = 0; i < acmp->acm_port_cnt; i++) { 1659 cv_destroy(&acmp->acm_ports[i].acm_tx_cv); 1660 mutex_destroy(&acmp->acm_ports[i].acm_port_mutex); 1661 } 1662 kmem_free((caddr_t)acmp->acm_ports, sizeof (usbsacm_port_t) * 1663 acmp->acm_port_cnt); 1664 acmp->acm_ports = NULL; 1665 } 1666 1667 1668 /* 1669 * usbsacm_get_descriptors: 1670 * analysis functional descriptors of acm device 1671 */ 1672 static int 1673 usbsacm_get_descriptors(usbsacm_state_t *acmp) 1674 { 1675 int i; 1676 usb_cfg_data_t *cfg; 1677 usb_alt_if_data_t *altif; 1678 usb_cvs_data_t *cvs; 1679 int mgmt_cap = 0; 1680 int master_if = -1, slave_if = -1; 1681 usbsacm_port_t *acm_port = acmp->acm_ports; 1682 usb_dev_descr_t *dd; 1683 1684 USB_DPRINTF_L4(PRINT_MASK_ATTA, acmp->acm_lh, 1685 "usbsacm_get_descriptors: "); 1686 1687 dd = acmp->acm_dev_data->dev_descr; 1688 cfg = acmp->acm_dev_data->dev_curr_cfg; 1689 /* set default control and data interface */ 1690 acm_port->acm_ctrl_if_no = acm_port->acm_data_if_no = 0; 1691 1692 /* get current interfaces */ 1693 acm_port->acm_ctrl_if_no = acmp->acm_dev_data->dev_curr_if; 1694 if (cfg->cfg_if[acm_port->acm_ctrl_if_no].if_n_alt == 0) { 1695 USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh, 1696 "usbsacm_get_descriptors: elements in if_alt is %d", 1697 cfg->cfg_if[acm_port->acm_ctrl_if_no].if_n_alt); 1698 1699 return (USB_FAILURE); 1700 } 1701 1702 altif = &cfg->cfg_if[acm_port->acm_ctrl_if_no].if_alt[0]; 1703 1704 /* 1705 * Based on CDC specification, ACM devices usually include the 1706 * following function descriptors: Header, ACM, Union and Call 1707 * Management function descriptors. This loop search tree data 1708 * structure for each acm class descriptor. 1709 */ 1710 for (i = 0; i < altif->altif_n_cvs; i++) { 1711 1712 cvs = &altif->altif_cvs[i]; 1713 1714 if ((cvs->cvs_buf == NULL) || 1715 (cvs->cvs_buf[1] != USB_CDC_CS_INTERFACE)) { 1716 continue; 1717 } 1718 1719 switch (cvs->cvs_buf[2]) { 1720 case USB_CDC_DESCR_TYPE_CALL_MANAGEMENT: 1721 /* parse call management functional descriptor. */ 1722 if (cvs->cvs_buf_len >= 5) { 1723 mgmt_cap = cvs->cvs_buf[3]; 1724 acm_port->acm_data_if_no = cvs->cvs_buf[4]; 1725 } 1726 break; 1727 case USB_CDC_DESCR_TYPE_ACM: 1728 /* parse ACM functional descriptor. */ 1729 if (cvs->cvs_buf_len >= 4) { 1730 acm_port->acm_cap = cvs->cvs_buf[3]; 1731 } 1732 1733 /* 1734 * The Sigma Designs, Inc. USB device does not report 1735 * itself as implementing the full ACM spec. However, 1736 * it does function as a usb serial modem, so we opt to 1737 * scribble in the reported functionality if we 1738 * determine the USB device matches this vendor 1739 * and product ID. 1740 */ 1741 if (dd->idVendor == USB_VENDOR_SIGMADESIGNS && 1742 dd->idProduct == USB_PRODUCT_SIGMADESIGNS_ZW090) { 1743 acm_port->acm_cap |= 1744 USB_CDC_ACM_CAP_SERIAL_LINE; 1745 } 1746 break; 1747 case USB_CDC_DESCR_TYPE_UNION: 1748 /* parse Union functional descriptor. */ 1749 if (cvs->cvs_buf_len >= 5) { 1750 master_if = cvs->cvs_buf[3]; 1751 slave_if = cvs->cvs_buf[4]; 1752 } 1753 break; 1754 default: 1755 break; 1756 } 1757 } 1758 1759 /* For usb acm devices, it must satisfy the following options. */ 1760 if (cfg->cfg_n_if < 2) { 1761 USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh, 1762 "usbsacm_get_descriptors: # of interfaces %d < 2", 1763 cfg->cfg_n_if); 1764 1765 return (USB_FAILURE); 1766 } 1767 1768 if (acm_port->acm_data_if_no == 0 && 1769 slave_if != acm_port->acm_data_if_no) { 1770 USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh, 1771 "usbsacm_get_descriptors: Device hasn't call management " 1772 "descriptor and use Union Descriptor."); 1773 1774 acm_port->acm_data_if_no = slave_if; 1775 } 1776 1777 if ((master_if != acm_port->acm_ctrl_if_no) || 1778 (slave_if != acm_port->acm_data_if_no)) { 1779 USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh, 1780 "usbsacm_get_descriptors: control interface or " 1781 "data interface don't match."); 1782 1783 return (USB_FAILURE); 1784 } 1785 1786 /* 1787 * We usually need both call and data capabilities, but 1788 * some devices, such as Nokia mobile phones, don't provide 1789 * call management descriptor, so we just give a warning 1790 * message. 1791 */ 1792 if (((mgmt_cap & USB_CDC_CALL_MGMT_CAP_CALL_MGMT) == 0) || 1793 ((mgmt_cap & USB_CDC_CALL_MGMT_CAP_DATA_INTERFACE) == 0)) { 1794 USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh, 1795 "usbsacm_get_descriptors: " 1796 "insufficient mgmt capabilities %x", 1797 mgmt_cap); 1798 } 1799 1800 if ((acm_port->acm_ctrl_if_no >= cfg->cfg_n_if) || 1801 (acm_port->acm_data_if_no >= cfg->cfg_n_if)) { 1802 USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh, 1803 "usbsacm_get_descriptors: control interface %d or " 1804 "data interface %d out of range.", 1805 acm_port->acm_ctrl_if_no, acm_port->acm_data_if_no); 1806 1807 return (USB_FAILURE); 1808 } 1809 1810 /* control interface must have interrupt endpoint */ 1811 if (usb_lookup_ep_data(acmp->acm_dip, acmp->acm_dev_data, 1812 acm_port->acm_ctrl_if_no, 0, 0, USB_EP_ATTR_INTR, 1813 USB_EP_DIR_IN) == NULL) { 1814 USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh, 1815 "usbsacm_get_descriptors: " 1816 "ctrl interface %d has no interrupt endpoint", 1817 acm_port->acm_data_if_no); 1818 1819 return (USB_FAILURE); 1820 } 1821 1822 /* data interface must have bulk in and out */ 1823 if (usb_lookup_ep_data(acmp->acm_dip, acmp->acm_dev_data, 1824 acm_port->acm_data_if_no, 0, 0, USB_EP_ATTR_BULK, 1825 USB_EP_DIR_IN) == NULL) { 1826 USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh, 1827 "usbsacm_get_descriptors: " 1828 "data interface %d has no bulk in endpoint", 1829 acm_port->acm_data_if_no); 1830 1831 return (USB_FAILURE); 1832 } 1833 if (usb_lookup_ep_data(acmp->acm_dip, acmp->acm_dev_data, 1834 acm_port->acm_data_if_no, 0, 0, USB_EP_ATTR_BULK, 1835 USB_EP_DIR_OUT) == NULL) { 1836 USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh, 1837 "usbsacm_get_descriptors: " 1838 "data interface %d has no bulk out endpoint", 1839 acm_port->acm_data_if_no); 1840 1841 return (USB_FAILURE); 1842 } 1843 1844 return (USB_SUCCESS); 1845 } 1846 1847 1848 /* 1849 * usbsacm_cleanup: 1850 * Release resources of current device during detach. 1851 */ 1852 static void 1853 usbsacm_cleanup(usbsacm_state_t *acmp) 1854 { 1855 USB_DPRINTF_L4(PRINT_MASK_CLOSE, acmp->acm_lh, 1856 "usbsacm_cleanup: "); 1857 1858 if (acmp != NULL) { 1859 /* free ports */ 1860 if (acmp->acm_ports != NULL) { 1861 usbsacm_free_ports(acmp); 1862 } 1863 1864 /* unregister callback function */ 1865 if (acmp->acm_usb_events != NULL) { 1866 usb_unregister_event_cbs(acmp->acm_dip, 1867 acmp->acm_usb_events); 1868 } 1869 1870 /* destroy power management components */ 1871 if (acmp->acm_pm != NULL) { 1872 usbsacm_destroy_pm_components(acmp); 1873 } 1874 1875 /* free description of device tree. */ 1876 if (acmp->acm_def_ph != NULL) { 1877 mutex_destroy(&acmp->acm_mutex); 1878 1879 usb_free_descr_tree(acmp->acm_dip, acmp->acm_dev_data); 1880 acmp->acm_def_ph = NULL; 1881 } 1882 1883 if (acmp->acm_lh != NULL) { 1884 usb_free_log_hdl(acmp->acm_lh); 1885 acmp->acm_lh = NULL; 1886 } 1887 1888 /* detach client device */ 1889 if (acmp->acm_dev_data != NULL) { 1890 usb_client_detach(acmp->acm_dip, acmp->acm_dev_data); 1891 } 1892 1893 kmem_free((caddr_t)acmp, sizeof (usbsacm_state_t)); 1894 } 1895 } 1896 1897 1898 /* 1899 * usbsacm_restore_device_state: 1900 * restore device state after CPR resume or reconnect 1901 */ 1902 static int 1903 usbsacm_restore_device_state(usbsacm_state_t *acmp) 1904 { 1905 int state; 1906 1907 USB_DPRINTF_L4(PRINT_MASK_ALL, acmp->acm_lh, 1908 "usbsacm_restore_device_state: "); 1909 1910 mutex_enter(&acmp->acm_mutex); 1911 state = acmp->acm_dev_state; 1912 mutex_exit(&acmp->acm_mutex); 1913 1914 /* Check device status */ 1915 if ((state != USB_DEV_DISCONNECTED) && (state != USB_DEV_SUSPENDED)) { 1916 1917 return (state); 1918 } 1919 1920 /* Check if we are talking to the same device */ 1921 if (usb_check_same_device(acmp->acm_dip, acmp->acm_lh, USB_LOG_L0, 1922 -1, USB_CHK_ALL, NULL) != USB_SUCCESS) { 1923 mutex_enter(&acmp->acm_mutex); 1924 state = acmp->acm_dev_state = USB_DEV_DISCONNECTED; 1925 mutex_exit(&acmp->acm_mutex); 1926 1927 return (state); 1928 } 1929 1930 if (state == USB_DEV_DISCONNECTED) { 1931 USB_DPRINTF_L1(PRINT_MASK_ALL, acmp->acm_lh, 1932 "usbsacm_restore_device_state: Device has been reconnected " 1933 "but data may have been lost"); 1934 } 1935 1936 /* reconnect pipes */ 1937 if (usbsacm_reconnect_pipes(acmp) != USB_SUCCESS) { 1938 1939 return (state); 1940 } 1941 1942 /* 1943 * init device state 1944 */ 1945 mutex_enter(&acmp->acm_mutex); 1946 state = acmp->acm_dev_state = USB_DEV_ONLINE; 1947 mutex_exit(&acmp->acm_mutex); 1948 1949 if ((usbsacm_restore_port_state(acmp) != USB_SUCCESS)) { 1950 USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh, 1951 "usbsacm_restore_device_state: failed"); 1952 } 1953 1954 return (state); 1955 } 1956 1957 1958 /* 1959 * usbsacm_restore_port_state: 1960 * restore ports state after CPR resume or reconnect 1961 */ 1962 static int 1963 usbsacm_restore_port_state(usbsacm_state_t *acmp) 1964 { 1965 int i, ret = USB_SUCCESS; 1966 usbsacm_port_t *cur_port; 1967 1968 USB_DPRINTF_L4(PRINT_MASK_ALL, acmp->acm_lh, 1969 "usbsacm_restore_port_state: "); 1970 1971 /* restore status of all ports */ 1972 for (i = 0; i < acmp->acm_port_cnt; i++) { 1973 cur_port = &acmp->acm_ports[i]; 1974 mutex_enter(&cur_port->acm_port_mutex); 1975 if (cur_port->acm_port_state != USBSACM_PORT_OPEN) { 1976 mutex_exit(&cur_port->acm_port_mutex); 1977 1978 continue; 1979 } 1980 mutex_exit(&cur_port->acm_port_mutex); 1981 1982 if ((ret = usbsacm_set_line_coding(cur_port, 1983 &cur_port->acm_line_coding)) != USB_SUCCESS) { 1984 USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh, 1985 "usbsacm_restore_port_state: failed."); 1986 } 1987 } 1988 1989 return (ret); 1990 } 1991 1992 1993 /* 1994 * pipe management 1995 * --------------- 1996 * 1997 * 1998 * usbsacm_open_port_pipes: 1999 * Open pipes of one port and set port structure; 2000 * Each port includes three pipes: bulk in, bulk out and interrupt. 2001 */ 2002 static int 2003 usbsacm_open_port_pipes(usbsacm_port_t *acm_port) 2004 { 2005 int rval = USB_SUCCESS; 2006 usbsacm_state_t *acmp = acm_port->acm_device; 2007 usb_ep_data_t *in_data, *out_data, *intr_pipe; 2008 usb_pipe_policy_t policy; 2009 2010 USB_DPRINTF_L4(PRINT_MASK_OPEN, acmp->acm_lh, 2011 "usbsacm_open_port_pipes: acmp = 0x%p", (void *)acmp); 2012 2013 /* Get bulk and interrupt endpoint data */ 2014 intr_pipe = usb_lookup_ep_data(acmp->acm_dip, acmp->acm_dev_data, 2015 acm_port->acm_ctrl_if_no, 0, 0, 2016 USB_EP_ATTR_INTR, USB_EP_DIR_IN); 2017 in_data = usb_lookup_ep_data(acmp->acm_dip, acmp->acm_dev_data, 2018 acm_port->acm_data_if_no, 0, acm_port->acm_data_port_no, 2019 USB_EP_ATTR_BULK, USB_EP_DIR_IN); 2020 out_data = usb_lookup_ep_data(acmp->acm_dip, acmp->acm_dev_data, 2021 acm_port->acm_data_if_no, 0, acm_port->acm_data_port_no, 2022 USB_EP_ATTR_BULK, USB_EP_DIR_OUT); 2023 2024 /* Bulk in and out must exist meanwhile. */ 2025 if ((in_data == NULL) || (out_data == NULL)) { 2026 USB_DPRINTF_L2(PRINT_MASK_OPEN, acmp->acm_lh, 2027 "usbsacm_open_port_pipes: look up bulk pipe failed in " 2028 "interface %d port %d", 2029 acm_port->acm_data_if_no, acm_port->acm_data_port_no); 2030 2031 return (USB_FAILURE); 2032 } 2033 2034 /* 2035 * If device conform to acm spec, it must have an interrupt pipe 2036 * for this port. 2037 */ 2038 if (acmp->acm_compatibility == B_TRUE && intr_pipe == NULL) { 2039 USB_DPRINTF_L2(PRINT_MASK_OPEN, acmp->acm_lh, 2040 "usbsacm_open_port_pipes: look up interrupt pipe failed in " 2041 "interface %d", acm_port->acm_ctrl_if_no); 2042 2043 return (USB_FAILURE); 2044 } 2045 2046 policy.pp_max_async_reqs = 2; 2047 2048 /* Open bulk in endpoint */ 2049 if (usb_pipe_open(acmp->acm_dip, &in_data->ep_descr, &policy, 2050 USB_FLAGS_SLEEP, &acm_port->acm_bulkin_ph) != USB_SUCCESS) { 2051 USB_DPRINTF_L2(PRINT_MASK_OPEN, acmp->acm_lh, 2052 "usbsacm_open_port_pipes: open bulkin pipe failed!"); 2053 2054 return (USB_FAILURE); 2055 } 2056 2057 /* Open bulk out endpoint */ 2058 if (usb_pipe_open(acmp->acm_dip, &out_data->ep_descr, &policy, 2059 USB_FLAGS_SLEEP, &acm_port->acm_bulkout_ph) != USB_SUCCESS) { 2060 USB_DPRINTF_L2(PRINT_MASK_OPEN, acmp->acm_lh, 2061 "usbsacm_open_port_pipes: open bulkout pipe failed!"); 2062 2063 usb_pipe_close(acmp->acm_dip, acm_port->acm_bulkin_ph, 2064 USB_FLAGS_SLEEP, NULL, NULL); 2065 2066 return (USB_FAILURE); 2067 } 2068 2069 /* Open interrupt endpoint if found. */ 2070 if (intr_pipe != NULL) { 2071 2072 if (usb_pipe_open(acmp->acm_dip, &intr_pipe->ep_descr, &policy, 2073 USB_FLAGS_SLEEP, &acm_port->acm_intr_ph) != USB_SUCCESS) { 2074 USB_DPRINTF_L2(PRINT_MASK_OPEN, acmp->acm_lh, 2075 "usbsacm_open_port_pipes: " 2076 "open control pipe failed"); 2077 2078 usb_pipe_close(acmp->acm_dip, acm_port->acm_bulkin_ph, 2079 USB_FLAGS_SLEEP, NULL, NULL); 2080 usb_pipe_close(acmp->acm_dip, acm_port->acm_bulkout_ph, 2081 USB_FLAGS_SLEEP, NULL, NULL); 2082 2083 return (USB_FAILURE); 2084 } 2085 } 2086 2087 /* initialize the port structure. */ 2088 mutex_enter(&acm_port->acm_port_mutex); 2089 acm_port->acm_bulkin_size = in_data->ep_descr.wMaxPacketSize; 2090 acm_port->acm_bulkin_state = USBSACM_PIPE_IDLE; 2091 acm_port->acm_bulkout_state = USBSACM_PIPE_IDLE; 2092 if (acm_port->acm_intr_ph != NULL) { 2093 acm_port->acm_intr_state = USBSACM_PIPE_IDLE; 2094 acm_port->acm_intr_ep_descr = intr_pipe->ep_descr; 2095 } 2096 mutex_exit(&acm_port->acm_port_mutex); 2097 2098 if (acm_port->acm_intr_ph != NULL) { 2099 2100 usbsacm_pipe_start_polling(acm_port); 2101 } 2102 2103 return (rval); 2104 } 2105 2106 2107 /* 2108 * usbsacm_close_port_pipes: 2109 * Close pipes of one port and reset port structure to closed; 2110 * Each port includes three pipes: bulk in, bulk out and interrupt. 2111 */ 2112 static void 2113 usbsacm_close_port_pipes(usbsacm_port_t *acm_port) 2114 { 2115 usbsacm_state_t *acmp = acm_port->acm_device; 2116 2117 mutex_enter(&acm_port->acm_port_mutex); 2118 USB_DPRINTF_L4(PRINT_MASK_CLOSE, acmp->acm_lh, 2119 "usbsacm_close_port_pipes: acm_bulkin_state = %d", 2120 acm_port->acm_bulkin_state); 2121 2122 /* 2123 * Check the status of the given port. If port is closing or closed, 2124 * return directly. 2125 */ 2126 if ((acm_port->acm_bulkin_state == USBSACM_PIPE_CLOSED) || 2127 (acm_port->acm_bulkin_state == USBSACM_PIPE_CLOSING)) { 2128 USB_DPRINTF_L2(PRINT_MASK_CLOSE, acmp->acm_lh, 2129 "usbsacm_close_port_pipes: port is closing or has closed"); 2130 mutex_exit(&acm_port->acm_port_mutex); 2131 2132 return; 2133 } 2134 2135 acm_port->acm_bulkin_state = USBSACM_PIPE_CLOSING; 2136 mutex_exit(&acm_port->acm_port_mutex); 2137 2138 /* Close pipes */ 2139 usb_pipe_reset(acmp->acm_dip, acm_port->acm_bulkin_ph, 2140 USB_FLAGS_SLEEP, 0, 0); 2141 usb_pipe_close(acmp->acm_dip, acm_port->acm_bulkin_ph, 2142 USB_FLAGS_SLEEP, 0, 0); 2143 usb_pipe_close(acmp->acm_dip, acm_port->acm_bulkout_ph, 2144 USB_FLAGS_SLEEP, 0, 0); 2145 if (acm_port->acm_intr_ph != NULL) { 2146 usb_pipe_stop_intr_polling(acm_port->acm_intr_ph, 2147 USB_FLAGS_SLEEP); 2148 usb_pipe_close(acmp->acm_dip, acm_port->acm_intr_ph, 2149 USB_FLAGS_SLEEP, 0, 0); 2150 } 2151 2152 mutex_enter(&acm_port->acm_port_mutex); 2153 /* Reset the status of pipes to closed */ 2154 acm_port->acm_bulkin_state = USBSACM_PIPE_CLOSED; 2155 acm_port->acm_bulkin_ph = NULL; 2156 acm_port->acm_bulkout_state = USBSACM_PIPE_CLOSED; 2157 acm_port->acm_bulkout_ph = NULL; 2158 if (acm_port->acm_intr_ph != NULL) { 2159 acm_port->acm_intr_state = USBSACM_PIPE_CLOSED; 2160 acm_port->acm_intr_ph = NULL; 2161 } 2162 2163 mutex_exit(&acm_port->acm_port_mutex); 2164 2165 USB_DPRINTF_L4(PRINT_MASK_CLOSE, acmp->acm_lh, 2166 "usbsacm_close_port_pipes: port has been closed."); 2167 } 2168 2169 2170 /* 2171 * usbsacm_close_pipes: 2172 * close all opened pipes of current devices. 2173 */ 2174 static void 2175 usbsacm_close_pipes(usbsacm_state_t *acmp) 2176 { 2177 int i; 2178 2179 USB_DPRINTF_L4(PRINT_MASK_CLOSE, acmp->acm_lh, 2180 "usbsacm_close_pipes: "); 2181 2182 /* Close all ports */ 2183 for (i = 0; i < acmp->acm_port_cnt; i++) { 2184 usbsacm_close_port_pipes(&acmp->acm_ports[i]); 2185 } 2186 } 2187 2188 2189 /* 2190 * usbsacm_disconnect_pipes: 2191 * this function just call usbsacm_close_pipes. 2192 */ 2193 static void 2194 usbsacm_disconnect_pipes(usbsacm_state_t *acmp) 2195 { 2196 USB_DPRINTF_L4(PRINT_MASK_CLOSE, acmp->acm_lh, 2197 "usbsacm_disconnect_pipes: "); 2198 2199 usbsacm_close_pipes(acmp); 2200 } 2201 2202 2203 /* 2204 * usbsacm_reconnect_pipes: 2205 * reconnect pipes in CPR resume or reconnect 2206 */ 2207 static int 2208 usbsacm_reconnect_pipes(usbsacm_state_t *acmp) 2209 { 2210 usbsacm_port_t *cur_port = acmp->acm_ports; 2211 int i; 2212 2213 USB_DPRINTF_L4(PRINT_MASK_OPEN, acmp->acm_lh, 2214 "usbsacm_reconnect_pipes: "); 2215 2216 /* reopen all ports of current device. */ 2217 for (i = 0; i < acmp->acm_port_cnt; i++) { 2218 cur_port = &acmp->acm_ports[i]; 2219 2220 mutex_enter(&cur_port->acm_port_mutex); 2221 /* 2222 * If port status is open, reopen it; 2223 * else retain the current status. 2224 */ 2225 if (cur_port->acm_port_state == USBSACM_PORT_OPEN) { 2226 2227 mutex_exit(&cur_port->acm_port_mutex); 2228 if (usbsacm_open_port_pipes(cur_port) != USB_SUCCESS) { 2229 USB_DPRINTF_L4(PRINT_MASK_OPEN, acmp->acm_lh, 2230 "usbsacm_reconnect_pipes: " 2231 "open port %d failed.", i); 2232 2233 return (USB_FAILURE); 2234 } 2235 mutex_enter(&cur_port->acm_port_mutex); 2236 } 2237 mutex_exit(&cur_port->acm_port_mutex); 2238 } 2239 2240 return (USB_SUCCESS); 2241 } 2242 2243 /* 2244 * usbsacm_bulkin_cb: 2245 * Bulk In regular and exeception callback; 2246 * USBA framework will call this callback 2247 * after deal with bulkin request. 2248 */ 2249 /*ARGSUSED*/ 2250 static void 2251 usbsacm_bulkin_cb(usb_pipe_handle_t pipe, usb_bulk_req_t *req) 2252 { 2253 usbsacm_port_t *acm_port = (usbsacm_port_t *)req->bulk_client_private; 2254 usbsacm_state_t *acmp = acm_port->acm_device; 2255 mblk_t *data; 2256 int data_len; 2257 2258 data = req->bulk_data; 2259 data_len = (data) ? MBLKL(data) : 0; 2260 2261 mutex_enter(&acm_port->acm_port_mutex); 2262 USB_DPRINTF_L4(PRINT_MASK_EVENTS, acmp->acm_lh, 2263 "usbsacm_bulkin_cb: " 2264 "acm_bulkin_state = %d acm_port_state = %d data_len = %d", 2265 acm_port->acm_bulkin_state, acm_port->acm_port_state, data_len); 2266 2267 if ((acm_port->acm_port_state == USBSACM_PORT_OPEN) && (data_len) && 2268 (req->bulk_completion_reason == USB_CR_OK)) { 2269 mutex_exit(&acm_port->acm_port_mutex); 2270 /* prevent USBA from freeing data along with the request */ 2271 req->bulk_data = NULL; 2272 2273 /* save data on the receive list */ 2274 usbsacm_put_tail(&acm_port->acm_rx_mp, data); 2275 2276 /* invoke GSD receive callback */ 2277 if (acm_port->acm_cb.cb_rx) { 2278 acm_port->acm_cb.cb_rx(acm_port->acm_cb.cb_arg); 2279 } 2280 mutex_enter(&acm_port->acm_port_mutex); 2281 } 2282 mutex_exit(&acm_port->acm_port_mutex); 2283 2284 usb_free_bulk_req(req); 2285 2286 /* receive more */ 2287 mutex_enter(&acm_port->acm_port_mutex); 2288 if (((acm_port->acm_bulkin_state == USBSACM_PIPE_BUSY) || 2289 (acm_port->acm_bulkin_state == USBSACM_PIPE_IDLE)) && 2290 (acm_port->acm_port_state == USBSACM_PORT_OPEN) && 2291 (acmp->acm_dev_state == USB_DEV_ONLINE)) { 2292 if (usbsacm_rx_start(acm_port) != USB_SUCCESS) { 2293 USB_DPRINTF_L2(PRINT_MASK_EVENTS, acmp->acm_lh, 2294 "usbsacm_bulkin_cb: restart rx fail " 2295 "acm_port_state = %d", acm_port->acm_port_state); 2296 } 2297 } else if (acm_port->acm_bulkin_state == USBSACM_PIPE_BUSY) { 2298 acm_port->acm_bulkin_state = USBSACM_PIPE_IDLE; 2299 } 2300 mutex_exit(&acm_port->acm_port_mutex); 2301 } 2302 2303 2304 /* 2305 * usbsacm_bulkout_cb: 2306 * Bulk Out regular and exeception callback; 2307 * USBA framework will call this callback function 2308 * after deal with bulkout request. 2309 */ 2310 /*ARGSUSED*/ 2311 static void 2312 usbsacm_bulkout_cb(usb_pipe_handle_t pipe, usb_bulk_req_t *req) 2313 { 2314 usbsacm_port_t *acm_port = (usbsacm_port_t *)req->bulk_client_private; 2315 usbsacm_state_t *acmp = acm_port->acm_device; 2316 int data_len; 2317 mblk_t *data = req->bulk_data; 2318 2319 USB_DPRINTF_L4(PRINT_MASK_EVENTS, acmp->acm_lh, 2320 "usbsacm_bulkout_cb: acmp = 0x%p", (void *)acmp); 2321 2322 data_len = (req->bulk_data) ? MBLKL(req->bulk_data) : 0; 2323 2324 /* put untransferred residue back on the transfer list */ 2325 if (req->bulk_completion_reason && (data_len > 0)) { 2326 usbsacm_put_head(&acm_port->acm_tx_mp, data); 2327 req->bulk_data = NULL; 2328 } 2329 2330 usb_free_bulk_req(req); 2331 2332 /* invoke GSD transmit callback */ 2333 if (acm_port->acm_cb.cb_tx) { 2334 acm_port->acm_cb.cb_tx(acm_port->acm_cb.cb_arg); 2335 } 2336 2337 /* send more */ 2338 mutex_enter(&acm_port->acm_port_mutex); 2339 acm_port->acm_bulkout_state = USBSACM_PIPE_IDLE; 2340 if (acm_port->acm_tx_mp == NULL) { 2341 cv_broadcast(&acm_port->acm_tx_cv); 2342 } else { 2343 usbsacm_tx_start(acm_port); 2344 } 2345 mutex_exit(&acm_port->acm_port_mutex); 2346 } 2347 2348 2349 /* 2350 * usbsacm_rx_start: 2351 * start data receipt 2352 */ 2353 static int 2354 usbsacm_rx_start(usbsacm_port_t *acm_port) 2355 { 2356 usbsacm_state_t *acmp = acm_port->acm_device; 2357 usb_bulk_req_t *br; 2358 int rval = USB_FAILURE; 2359 int data_len; 2360 2361 USB_DPRINTF_L4(PRINT_MASK_EVENTS, acmp->acm_lh, 2362 "usbsacm_rx_start: acm_xfer_sz = 0x%lx acm_bulkin_size = 0x%lx", 2363 acmp->acm_xfer_sz, acm_port->acm_bulkin_size); 2364 2365 acm_port->acm_bulkin_state = USBSACM_PIPE_BUSY; 2366 /* 2367 * Qualcomm CDMA card won't response the first request, 2368 * if the following code don't multiply by 2. 2369 */ 2370 data_len = min(acmp->acm_xfer_sz, acm_port->acm_bulkin_size * 2); 2371 mutex_exit(&acm_port->acm_port_mutex); 2372 2373 br = usb_alloc_bulk_req(acmp->acm_dip, data_len, USB_FLAGS_SLEEP); 2374 if (br == NULL) { 2375 USB_DPRINTF_L2(PRINT_MASK_EVENTS, acmp->acm_lh, 2376 "usbsacm_rx_start: allocate bulk request failed"); 2377 2378 mutex_enter(&acm_port->acm_port_mutex); 2379 2380 return (USB_FAILURE); 2381 } 2382 /* initialize bulk in request. */ 2383 br->bulk_len = data_len; 2384 br->bulk_timeout = USBSACM_BULKIN_TIMEOUT; 2385 br->bulk_cb = usbsacm_bulkin_cb; 2386 br->bulk_exc_cb = usbsacm_bulkin_cb; 2387 br->bulk_client_private = (usb_opaque_t)acm_port; 2388 br->bulk_attributes = USB_ATTRS_AUTOCLEARING 2389 | USB_ATTRS_SHORT_XFER_OK; 2390 2391 rval = usb_pipe_bulk_xfer(acm_port->acm_bulkin_ph, br, 0); 2392 2393 mutex_enter(&acm_port->acm_port_mutex); 2394 if (rval != USB_SUCCESS) { 2395 USB_DPRINTF_L2(PRINT_MASK_EVENTS, acmp->acm_lh, 2396 "usbsacm_rx_start: bulk transfer failed %d", rval); 2397 usb_free_bulk_req(br); 2398 acm_port->acm_bulkin_state = USBSACM_PIPE_IDLE; 2399 } 2400 2401 return (rval); 2402 } 2403 2404 2405 /* 2406 * usbsacm_tx_start: 2407 * start data transmit 2408 */ 2409 static void 2410 usbsacm_tx_start(usbsacm_port_t *acm_port) 2411 { 2412 int len; /* bytes we can transmit */ 2413 mblk_t *data; /* data to be transmitted */ 2414 int data_len; /* bytes in 'data' */ 2415 mblk_t *mp; /* current msgblk */ 2416 int copylen; /* bytes copy from 'mp' to 'data' */ 2417 int rval; 2418 usbsacm_state_t *acmp = acm_port->acm_device; 2419 2420 USB_DPRINTF_L4(PRINT_MASK_ALL, acmp->acm_lh, 2421 "usbsacm_tx_start: "); 2422 2423 /* check the transmitted data. */ 2424 if (acm_port->acm_tx_mp == NULL) { 2425 USB_DPRINTF_L2(PRINT_MASK_EVENTS, acmp->acm_lh, 2426 "usbsacm_tx_start: acm_tx_mp is NULL"); 2427 2428 return; 2429 } 2430 2431 /* check pipe status */ 2432 if (acm_port->acm_bulkout_state != USBSACM_PIPE_IDLE) { 2433 2434 USB_DPRINTF_L2(PRINT_MASK_EVENTS, acmp->acm_lh, 2435 "usbsacm_tx_start: error state in bulkout endpoint"); 2436 2437 return; 2438 } 2439 ASSERT(MBLKL(acm_port->acm_tx_mp) > 0); 2440 2441 /* send as much data as port can receive */ 2442 len = min(msgdsize(acm_port->acm_tx_mp), acmp->acm_xfer_sz); 2443 2444 if (len == 0) { 2445 USB_DPRINTF_L2(PRINT_MASK_EVENTS, acmp->acm_lh, 2446 "usbsacm_tx_start: data len is 0"); 2447 2448 return; 2449 } 2450 2451 /* allocate memory for sending data. */ 2452 if ((data = allocb(len, BPRI_LO)) == NULL) { 2453 USB_DPRINTF_L2(PRINT_MASK_EVENTS, acmp->acm_lh, 2454 "usbsacm_tx_start: failure in allocate memory"); 2455 2456 return; 2457 } 2458 2459 /* 2460 * copy no more than 'len' bytes from mblk chain to transmit mblk 'data' 2461 */ 2462 data_len = 0; 2463 while ((data_len < len) && acm_port->acm_tx_mp) { 2464 /* Get the first mblk from chain. */ 2465 mp = acm_port->acm_tx_mp; 2466 copylen = min(MBLKL(mp), len - data_len); 2467 bcopy(mp->b_rptr, data->b_wptr, copylen); 2468 mp->b_rptr += copylen; 2469 data->b_wptr += copylen; 2470 data_len += copylen; 2471 2472 if (MBLKL(mp) < 1) { 2473 acm_port->acm_tx_mp = unlinkb(mp); 2474 freeb(mp); 2475 } else { 2476 ASSERT(data_len == len); 2477 } 2478 } 2479 2480 if (data_len <= 0) { 2481 freeb(data); 2482 2483 return; 2484 } 2485 2486 acm_port->acm_bulkout_state = USBSACM_PIPE_BUSY; 2487 2488 mutex_exit(&acm_port->acm_port_mutex); 2489 /* send request. */ 2490 rval = usbsacm_send_data(acm_port, data); 2491 mutex_enter(&acm_port->acm_port_mutex); 2492 2493 /* 2494 * If send failed, retransmit data when acm_tx_mp is null. 2495 */ 2496 if (rval != USB_SUCCESS) { 2497 acm_port->acm_bulkout_state = USBSACM_PIPE_IDLE; 2498 if (acm_port->acm_tx_mp == NULL) { 2499 usbsacm_put_head(&acm_port->acm_tx_mp, data); 2500 } 2501 } 2502 } 2503 2504 2505 /* 2506 * usbsacm_send_data: 2507 * data transfer 2508 */ 2509 static int 2510 usbsacm_send_data(usbsacm_port_t *acm_port, mblk_t *data) 2511 { 2512 usbsacm_state_t *acmp = acm_port->acm_device; 2513 usb_bulk_req_t *br; 2514 int rval; 2515 int data_len = MBLKL(data); 2516 2517 USB_DPRINTF_L4(PRINT_MASK_EVENTS, acmp->acm_lh, 2518 "usbsacm_send_data: data address is 0x%p, length = %d", 2519 (void *)data, data_len); 2520 2521 br = usb_alloc_bulk_req(acmp->acm_dip, 0, USB_FLAGS_SLEEP); 2522 if (br == NULL) { 2523 USB_DPRINTF_L2(PRINT_MASK_OPEN, acmp->acm_lh, 2524 "usbsacm_send_data: alloc req failed."); 2525 2526 return (USB_FAILURE); 2527 } 2528 2529 /* initialize the bulk out request */ 2530 br->bulk_data = data; 2531 br->bulk_len = data_len; 2532 br->bulk_timeout = USBSACM_BULKOUT_TIMEOUT; 2533 br->bulk_cb = usbsacm_bulkout_cb; 2534 br->bulk_exc_cb = usbsacm_bulkout_cb; 2535 br->bulk_client_private = (usb_opaque_t)acm_port; 2536 br->bulk_attributes = USB_ATTRS_AUTOCLEARING; 2537 2538 rval = usb_pipe_bulk_xfer(acm_port->acm_bulkout_ph, br, 0); 2539 2540 if (rval != USB_SUCCESS) { 2541 USB_DPRINTF_L2(PRINT_MASK_EVENTS, acmp->acm_lh, 2542 "usbsacm_send_data: Send Data failed."); 2543 2544 /* 2545 * Don't free it in usb_free_bulk_req because it will 2546 * be linked in usbsacm_put_head 2547 */ 2548 br->bulk_data = NULL; 2549 2550 usb_free_bulk_req(br); 2551 } 2552 2553 return (rval); 2554 } 2555 2556 /* 2557 * usbsacm_wait_tx_drain: 2558 * wait until local tx buffer drains. 2559 * 'timeout' is in seconds, zero means wait forever 2560 */ 2561 static int 2562 usbsacm_wait_tx_drain(usbsacm_port_t *acm_port, int timeout) 2563 { 2564 clock_t until; 2565 int over = 0; 2566 2567 until = ddi_get_lbolt() + drv_usectohz(1000 * 1000 * timeout); 2568 2569 while (acm_port->acm_tx_mp && !over) { 2570 if (timeout > 0) { 2571 over = (cv_timedwait_sig(&acm_port->acm_tx_cv, 2572 &acm_port->acm_port_mutex, until) <= 0); 2573 } else { 2574 over = (cv_wait_sig(&acm_port->acm_tx_cv, 2575 &acm_port->acm_port_mutex) == 0); 2576 } 2577 } 2578 2579 return ((acm_port->acm_tx_mp == NULL) ? USB_SUCCESS : USB_FAILURE); 2580 } 2581 2582 2583 /* 2584 * usbsacm_req_write: 2585 * send command over control pipe 2586 */ 2587 static int 2588 usbsacm_req_write(usbsacm_port_t *acm_port, uchar_t request, uint16_t value, 2589 mblk_t **data) 2590 { 2591 usbsacm_state_t *acmp = acm_port->acm_device; 2592 usb_ctrl_setup_t setup; 2593 usb_cb_flags_t cb_flags; 2594 usb_cr_t cr; 2595 2596 USB_DPRINTF_L4(PRINT_MASK_ALL, acmp->acm_lh, 2597 "usbsacm_req_write: "); 2598 2599 /* initialize the control request. */ 2600 setup.bmRequestType = USBSACM_REQ_WRITE_IF; 2601 setup.bRequest = request; 2602 setup.wValue = value; 2603 setup.wIndex = acm_port->acm_ctrl_if_no; 2604 setup.wLength = ((data != NULL) && (*data != NULL)) ? MBLKL(*data) : 0; 2605 setup.attrs = 0; 2606 2607 return (usb_pipe_ctrl_xfer_wait(acmp->acm_def_ph, &setup, data, 2608 &cr, &cb_flags, 0)); 2609 } 2610 2611 2612 /* 2613 * usbsacm_set_line_coding: 2614 * Send USB_CDC_REQ_SET_LINE_CODING request 2615 */ 2616 static int 2617 usbsacm_set_line_coding(usbsacm_port_t *acm_port, usb_cdc_line_coding_t *lc) 2618 { 2619 mblk_t *bp; 2620 int ret; 2621 2622 /* allocate mblk and copy supplied structure into it */ 2623 if ((bp = allocb(USB_CDC_LINE_CODING_LEN, BPRI_HI)) == NULL) { 2624 2625 return (USB_NO_RESOURCES); 2626 } 2627 2628 #ifndef __lock_lint /* warlock gets confused here */ 2629 /* LINTED E_BAD_PTR_CAST_ALIGN */ 2630 *((usb_cdc_line_coding_t *)bp->b_wptr) = *lc; 2631 bp->b_wptr += USB_CDC_LINE_CODING_LEN; 2632 #endif 2633 2634 ret = usbsacm_req_write(acm_port, USB_CDC_REQ_SET_LINE_CODING, 0, &bp); 2635 2636 if (bp != NULL) { 2637 freeb(bp); 2638 } 2639 2640 return (ret); 2641 } 2642 2643 2644 2645 /* 2646 * usbsacm_mctl2reg: 2647 * Set Modem control status 2648 */ 2649 static void 2650 usbsacm_mctl2reg(int mask, int val, uint8_t *line_ctl) 2651 { 2652 if (mask & TIOCM_RTS) { 2653 if (val & TIOCM_RTS) { 2654 *line_ctl |= USB_CDC_ACM_CONTROL_RTS; 2655 } else { 2656 *line_ctl &= ~USB_CDC_ACM_CONTROL_RTS; 2657 } 2658 } 2659 if (mask & TIOCM_DTR) { 2660 if (val & TIOCM_DTR) { 2661 *line_ctl |= USB_CDC_ACM_CONTROL_DTR; 2662 } else { 2663 *line_ctl &= ~USB_CDC_ACM_CONTROL_DTR; 2664 } 2665 } 2666 } 2667 2668 2669 /* 2670 * usbsacm_reg2mctl: 2671 * Get Modem control status 2672 */ 2673 static int 2674 usbsacm_reg2mctl(uint8_t line_ctl) 2675 { 2676 int val = 0; 2677 2678 if (line_ctl & USB_CDC_ACM_CONTROL_RTS) { 2679 val |= TIOCM_RTS; 2680 } 2681 if (line_ctl & USB_CDC_ACM_CONTROL_DTR) { 2682 val |= TIOCM_DTR; 2683 } 2684 if (line_ctl & USB_CDC_ACM_CONTROL_DSR) { 2685 val |= TIOCM_DSR; 2686 } 2687 if (line_ctl & USB_CDC_ACM_CONTROL_RNG) { 2688 val |= TIOCM_RI; 2689 } 2690 2691 return (val); 2692 } 2693 2694 2695 /* 2696 * misc routines 2697 * ------------- 2698 * 2699 */ 2700 2701 /* 2702 * usbsacm_put_tail: 2703 * link a message block to tail of message 2704 * account for the case when message is null 2705 */ 2706 static void 2707 usbsacm_put_tail(mblk_t **mpp, mblk_t *bp) 2708 { 2709 if (*mpp) { 2710 linkb(*mpp, bp); 2711 } else { 2712 *mpp = bp; 2713 } 2714 } 2715 2716 2717 /* 2718 * usbsacm_put_head: 2719 * put a message block at the head of the message 2720 * account for the case when message is null 2721 */ 2722 static void 2723 usbsacm_put_head(mblk_t **mpp, mblk_t *bp) 2724 { 2725 if (*mpp) { 2726 linkb(bp, *mpp); 2727 } 2728 *mpp = bp; 2729 } 2730 2731 2732 /* 2733 * power management 2734 * ---------------- 2735 * 2736 * usbsacm_create_pm_components: 2737 * create PM components 2738 */ 2739 static int 2740 usbsacm_create_pm_components(usbsacm_state_t *acmp) 2741 { 2742 dev_info_t *dip = acmp->acm_dip; 2743 usbsacm_pm_t *pm; 2744 uint_t pwr_states; 2745 usb_dev_descr_t *dev_descr; 2746 2747 USB_DPRINTF_L4(PRINT_MASK_PM, acmp->acm_lh, 2748 "usbsacm_create_pm_components: "); 2749 2750 if (usb_create_pm_components(dip, &pwr_states) != USB_SUCCESS) { 2751 USB_DPRINTF_L2(PRINT_MASK_PM, acmp->acm_lh, 2752 "usbsacm_create_pm_components: failed"); 2753 2754 return (USB_SUCCESS); 2755 } 2756 2757 pm = acmp->acm_pm = 2758 (usbsacm_pm_t *)kmem_zalloc(sizeof (usbsacm_pm_t), KM_SLEEP); 2759 2760 pm->pm_pwr_states = (uint8_t)pwr_states; 2761 pm->pm_cur_power = USB_DEV_OS_FULL_PWR; 2762 /* 2763 * Qualcomm CDMA card won't response the following control commands 2764 * after receive USB_REMOTE_WAKEUP_ENABLE. So we just set 2765 * pm_wakeup_enable to 0 for this specific device. 2766 */ 2767 dev_descr = acmp->acm_dev_data->dev_descr; 2768 if (dev_descr->idVendor == 0x5c6 && dev_descr->idProduct == 0x3100) { 2769 pm->pm_wakeup_enabled = 0; 2770 } else { 2771 pm->pm_wakeup_enabled = (usb_handle_remote_wakeup(dip, 2772 USB_REMOTE_WAKEUP_ENABLE) == USB_SUCCESS); 2773 } 2774 2775 (void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR); 2776 2777 return (USB_SUCCESS); 2778 } 2779 2780 2781 /* 2782 * usbsacm_destroy_pm_components: 2783 * destroy PM components 2784 */ 2785 static void 2786 usbsacm_destroy_pm_components(usbsacm_state_t *acmp) 2787 { 2788 usbsacm_pm_t *pm = acmp->acm_pm; 2789 dev_info_t *dip = acmp->acm_dip; 2790 int rval; 2791 2792 USB_DPRINTF_L4(PRINT_MASK_CLOSE, acmp->acm_lh, 2793 "usbsacm_destroy_pm_components: "); 2794 2795 if (acmp->acm_dev_state != USB_DEV_DISCONNECTED) { 2796 if (pm->pm_wakeup_enabled) { 2797 rval = pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR); 2798 if (rval != DDI_SUCCESS) { 2799 USB_DPRINTF_L2(PRINT_MASK_PM, acmp->acm_lh, 2800 "usbsacm_destroy_pm_components: " 2801 "raising power failed (%d)", rval); 2802 } 2803 2804 rval = usb_handle_remote_wakeup(dip, 2805 USB_REMOTE_WAKEUP_DISABLE); 2806 if (rval != USB_SUCCESS) { 2807 USB_DPRINTF_L2(PRINT_MASK_PM, acmp->acm_lh, 2808 "usbsacm_destroy_pm_components: " 2809 "disable remote wakeup failed (%d)", rval); 2810 } 2811 } 2812 2813 (void) pm_lower_power(dip, 0, USB_DEV_OS_PWR_OFF); 2814 } 2815 kmem_free((caddr_t)pm, sizeof (usbsacm_pm_t)); 2816 acmp->acm_pm = NULL; 2817 } 2818 2819 2820 /* 2821 * usbsacm_pm_set_busy: 2822 * mark device busy and raise power 2823 */ 2824 static void 2825 usbsacm_pm_set_busy(usbsacm_state_t *acmp) 2826 { 2827 usbsacm_pm_t *pm = acmp->acm_pm; 2828 dev_info_t *dip = acmp->acm_dip; 2829 int rval; 2830 2831 USB_DPRINTF_L4(PRINT_MASK_PM, acmp->acm_lh, 2832 "usbsacm_pm_set_busy: pm = 0x%p", (void *)pm); 2833 2834 if (pm == NULL) { 2835 2836 return; 2837 } 2838 2839 mutex_enter(&acmp->acm_mutex); 2840 /* if already marked busy, just increment the counter */ 2841 if (pm->pm_busy_cnt++ > 0) { 2842 mutex_exit(&acmp->acm_mutex); 2843 2844 return; 2845 } 2846 2847 (void) pm_busy_component(dip, 0); 2848 2849 if (pm->pm_cur_power == USB_DEV_OS_FULL_PWR) { 2850 mutex_exit(&acmp->acm_mutex); 2851 2852 return; 2853 } 2854 2855 /* need to raise power */ 2856 pm->pm_raise_power = B_TRUE; 2857 mutex_exit(&acmp->acm_mutex); 2858 2859 rval = pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR); 2860 if (rval != DDI_SUCCESS) { 2861 USB_DPRINTF_L2(PRINT_MASK_PM, acmp->acm_lh, 2862 "usbsacm_pm_set_busy: raising power failed"); 2863 } 2864 2865 mutex_enter(&acmp->acm_mutex); 2866 pm->pm_raise_power = B_FALSE; 2867 mutex_exit(&acmp->acm_mutex); 2868 } 2869 2870 2871 /* 2872 * usbsacm_pm_set_idle: 2873 * mark device idle 2874 */ 2875 static void 2876 usbsacm_pm_set_idle(usbsacm_state_t *acmp) 2877 { 2878 usbsacm_pm_t *pm = acmp->acm_pm; 2879 dev_info_t *dip = acmp->acm_dip; 2880 2881 USB_DPRINTF_L4(PRINT_MASK_PM, acmp->acm_lh, 2882 "usbsacm_pm_set_idle: "); 2883 2884 if (pm == NULL) { 2885 2886 return; 2887 } 2888 2889 /* 2890 * if more ports use the device, do not mark as yet 2891 */ 2892 mutex_enter(&acmp->acm_mutex); 2893 if (--pm->pm_busy_cnt > 0) { 2894 mutex_exit(&acmp->acm_mutex); 2895 2896 return; 2897 } 2898 2899 if (pm) { 2900 (void) pm_idle_component(dip, 0); 2901 } 2902 mutex_exit(&acmp->acm_mutex); 2903 } 2904 2905 2906 /* 2907 * usbsacm_pwrlvl0: 2908 * Functions to handle power transition for OS levels 0 -> 3 2909 * The same level as OS state, different from USB state 2910 */ 2911 static int 2912 usbsacm_pwrlvl0(usbsacm_state_t *acmp) 2913 { 2914 int rval; 2915 int i; 2916 usbsacm_port_t *cur_port = acmp->acm_ports; 2917 2918 USB_DPRINTF_L4(PRINT_MASK_PM, acmp->acm_lh, 2919 "usbsacm_pwrlvl0: "); 2920 2921 switch (acmp->acm_dev_state) { 2922 case USB_DEV_ONLINE: 2923 /* issue USB D3 command to the device */ 2924 rval = usb_set_device_pwrlvl3(acmp->acm_dip); 2925 ASSERT(rval == USB_SUCCESS); 2926 2927 if (cur_port != NULL) { 2928 for (i = 0; i < acmp->acm_port_cnt; i++) { 2929 cur_port = &acmp->acm_ports[i]; 2930 if (cur_port->acm_intr_ph != NULL && 2931 cur_port->acm_port_state != 2932 USBSACM_PORT_CLOSED) { 2933 2934 mutex_exit(&acmp->acm_mutex); 2935 usb_pipe_stop_intr_polling( 2936 cur_port->acm_intr_ph, 2937 USB_FLAGS_SLEEP); 2938 mutex_enter(&acmp->acm_mutex); 2939 2940 mutex_enter(&cur_port->acm_port_mutex); 2941 cur_port->acm_intr_state = 2942 USBSACM_PIPE_IDLE; 2943 mutex_exit(&cur_port->acm_port_mutex); 2944 } 2945 } 2946 } 2947 2948 acmp->acm_dev_state = USB_DEV_PWRED_DOWN; 2949 acmp->acm_pm->pm_cur_power = USB_DEV_OS_PWR_OFF; 2950 2951 /* FALLTHRU */ 2952 case USB_DEV_DISCONNECTED: 2953 case USB_DEV_SUSPENDED: 2954 /* allow a disconnect/cpr'ed device to go to lower power */ 2955 2956 return (USB_SUCCESS); 2957 case USB_DEV_PWRED_DOWN: 2958 default: 2959 USB_DPRINTF_L2(PRINT_MASK_PM, acmp->acm_lh, 2960 "usbsacm_pwrlvl0: illegal device state"); 2961 2962 return (USB_FAILURE); 2963 } 2964 } 2965 2966 2967 /* 2968 * usbsacm_pwrlvl1: 2969 * Functions to handle power transition for OS levels 1 -> 2 2970 */ 2971 static int 2972 usbsacm_pwrlvl1(usbsacm_state_t *acmp) 2973 { 2974 /* issue USB D2 command to the device */ 2975 (void) usb_set_device_pwrlvl2(acmp->acm_dip); 2976 2977 return (USB_FAILURE); 2978 } 2979 2980 2981 /* 2982 * usbsacm_pwrlvl2: 2983 * Functions to handle power transition for OS levels 2 -> 1 2984 */ 2985 static int 2986 usbsacm_pwrlvl2(usbsacm_state_t *acmp) 2987 { 2988 /* issue USB D1 command to the device */ 2989 (void) usb_set_device_pwrlvl1(acmp->acm_dip); 2990 2991 return (USB_FAILURE); 2992 } 2993 2994 2995 /* 2996 * usbsacm_pwrlvl3: 2997 * Functions to handle power transition for OS levels 3 -> 0 2998 * The same level as OS state, different from USB state 2999 */ 3000 static int 3001 usbsacm_pwrlvl3(usbsacm_state_t *acmp) 3002 { 3003 int rval; 3004 int i; 3005 usbsacm_port_t *cur_port = acmp->acm_ports; 3006 3007 USB_DPRINTF_L4(PRINT_MASK_PM, acmp->acm_lh, 3008 "usbsacm_pwrlvl3: "); 3009 3010 switch (acmp->acm_dev_state) { 3011 case USB_DEV_PWRED_DOWN: 3012 /* Issue USB D0 command to the device here */ 3013 rval = usb_set_device_pwrlvl0(acmp->acm_dip); 3014 ASSERT(rval == USB_SUCCESS); 3015 3016 if (cur_port != NULL) { 3017 for (i = 0; i < acmp->acm_port_cnt; i++) { 3018 cur_port = &acmp->acm_ports[i]; 3019 if (cur_port->acm_intr_ph != NULL && 3020 cur_port->acm_port_state != 3021 USBSACM_PORT_CLOSED) { 3022 3023 mutex_exit(&acmp->acm_mutex); 3024 usbsacm_pipe_start_polling(cur_port); 3025 mutex_enter(&acmp->acm_mutex); 3026 } 3027 } 3028 } 3029 3030 acmp->acm_dev_state = USB_DEV_ONLINE; 3031 acmp->acm_pm->pm_cur_power = USB_DEV_OS_FULL_PWR; 3032 3033 /* FALLTHRU */ 3034 case USB_DEV_ONLINE: 3035 /* we are already in full power */ 3036 3037 /* FALLTHRU */ 3038 case USB_DEV_DISCONNECTED: 3039 case USB_DEV_SUSPENDED: 3040 3041 return (USB_SUCCESS); 3042 default: 3043 USB_DPRINTF_L2(PRINT_MASK_PM, acmp->acm_lh, 3044 "usbsacm_pwrlvl3: illegal device state"); 3045 3046 return (USB_FAILURE); 3047 } 3048 } 3049 3050 3051 /* 3052 * usbsacm_pipe_start_polling: 3053 * start polling on the interrupt pipe 3054 */ 3055 static void 3056 usbsacm_pipe_start_polling(usbsacm_port_t *acm_port) 3057 { 3058 usb_intr_req_t *intr; 3059 int rval; 3060 usbsacm_state_t *acmp = acm_port->acm_device; 3061 3062 USB_DPRINTF_L4(PRINT_MASK_ATTA, acmp->acm_lh, 3063 "usbsacm_pipe_start_polling: "); 3064 3065 if (acm_port->acm_intr_ph == NULL) { 3066 3067 return; 3068 } 3069 3070 intr = usb_alloc_intr_req(acmp->acm_dip, 0, USB_FLAGS_SLEEP); 3071 3072 /* 3073 * If it is in interrupt context, usb_alloc_intr_req will return NULL if 3074 * called with SLEEP flag. 3075 */ 3076 if (!intr) { 3077 USB_DPRINTF_L2(PRINT_MASK_OPEN, acmp->acm_lh, 3078 "usbsacm_pipe_start_polling: alloc req failed."); 3079 3080 return; 3081 } 3082 3083 /* initialize the interrupt request. */ 3084 intr->intr_attributes = USB_ATTRS_SHORT_XFER_OK | 3085 USB_ATTRS_AUTOCLEARING; 3086 mutex_enter(&acm_port->acm_port_mutex); 3087 intr->intr_len = acm_port->acm_intr_ep_descr.wMaxPacketSize; 3088 mutex_exit(&acm_port->acm_port_mutex); 3089 intr->intr_client_private = (usb_opaque_t)acm_port; 3090 intr->intr_cb = usbsacm_intr_cb; 3091 intr->intr_exc_cb = usbsacm_intr_ex_cb; 3092 3093 rval = usb_pipe_intr_xfer(acm_port->acm_intr_ph, intr, USB_FLAGS_SLEEP); 3094 3095 mutex_enter(&acm_port->acm_port_mutex); 3096 if (rval == USB_SUCCESS) { 3097 acm_port->acm_intr_state = USBSACM_PIPE_BUSY; 3098 } else { 3099 usb_free_intr_req(intr); 3100 acm_port->acm_intr_state = USBSACM_PIPE_IDLE; 3101 USB_DPRINTF_L3(PRINT_MASK_OPEN, acmp->acm_lh, 3102 "usbsacm_pipe_start_polling: failed (%d)", rval); 3103 } 3104 mutex_exit(&acm_port->acm_port_mutex); 3105 } 3106 3107 3108 /* 3109 * usbsacm_intr_cb: 3110 * interrupt pipe normal callback 3111 */ 3112 /*ARGSUSED*/ 3113 static void 3114 usbsacm_intr_cb(usb_pipe_handle_t ph, usb_intr_req_t *req) 3115 { 3116 usbsacm_port_t *acm_port = (usbsacm_port_t *)req->intr_client_private; 3117 usbsacm_state_t *acmp = acm_port->acm_device; 3118 mblk_t *data = req->intr_data; 3119 int data_len; 3120 3121 USB_DPRINTF_L4(PRINT_MASK_CB, acmp->acm_lh, 3122 "usbsacm_intr_cb: "); 3123 3124 data_len = (data) ? MBLKL(data) : 0; 3125 3126 /* check data length */ 3127 if (data_len < 8) { 3128 USB_DPRINTF_L2(PRINT_MASK_CB, acmp->acm_lh, 3129 "usbsacm_intr_cb: %d packet too short", data_len); 3130 usb_free_intr_req(req); 3131 3132 return; 3133 } 3134 req->intr_data = NULL; 3135 usb_free_intr_req(req); 3136 3137 mutex_enter(&acm_port->acm_port_mutex); 3138 /* parse interrupt data. */ 3139 usbsacm_parse_intr_data(acm_port, data); 3140 mutex_exit(&acm_port->acm_port_mutex); 3141 } 3142 3143 3144 /* 3145 * usbsacm_intr_ex_cb: 3146 * interrupt pipe exception callback 3147 */ 3148 /*ARGSUSED*/ 3149 static void 3150 usbsacm_intr_ex_cb(usb_pipe_handle_t ph, usb_intr_req_t *req) 3151 { 3152 usbsacm_port_t *acm_port = (usbsacm_port_t *)req->intr_client_private; 3153 usbsacm_state_t *acmp = acm_port->acm_device; 3154 usb_cr_t cr = req->intr_completion_reason; 3155 3156 USB_DPRINTF_L4(PRINT_MASK_CB, acmp->acm_lh, 3157 "usbsacm_intr_ex_cb: "); 3158 3159 usb_free_intr_req(req); 3160 3161 /* 3162 * If completion reason isn't USB_CR_PIPE_CLOSING and 3163 * USB_CR_STOPPED_POLLING, restart polling. 3164 */ 3165 if ((cr != USB_CR_PIPE_CLOSING) && (cr != USB_CR_STOPPED_POLLING)) { 3166 mutex_enter(&acmp->acm_mutex); 3167 3168 if (acmp->acm_dev_state != USB_DEV_ONLINE) { 3169 3170 USB_DPRINTF_L3(PRINT_MASK_CB, acmp->acm_lh, 3171 "usbsacm_intr_ex_cb: state = %d", 3172 acmp->acm_dev_state); 3173 3174 mutex_exit(&acmp->acm_mutex); 3175 3176 return; 3177 } 3178 mutex_exit(&acmp->acm_mutex); 3179 3180 usbsacm_pipe_start_polling(acm_port); 3181 } 3182 } 3183 3184 3185 /* 3186 * usbsacm_parse_intr_data: 3187 * Parse data received from interrupt callback 3188 */ 3189 static void 3190 usbsacm_parse_intr_data(usbsacm_port_t *acm_port, mblk_t *data) 3191 { 3192 usbsacm_state_t *acmp = acm_port->acm_device; 3193 uint8_t bmRequestType; 3194 uint8_t bNotification; 3195 uint16_t wValue; 3196 uint16_t wLength; 3197 uint16_t wData; 3198 3199 USB_DPRINTF_L4(PRINT_MASK_ALL, acmp->acm_lh, 3200 "usbsacm_parse_intr_data: "); 3201 3202 bmRequestType = data->b_rptr[0]; 3203 bNotification = data->b_rptr[1]; 3204 /* 3205 * If Notification type is NETWORK_CONNECTION, wValue is 0 or 1, 3206 * mLength is 0. If Notification type is SERIAL_TYPE, mValue is 0, 3207 * mLength is 2. So we directly get the value from the byte. 3208 */ 3209 wValue = data->b_rptr[2]; 3210 wLength = data->b_rptr[6]; 3211 3212 if (bmRequestType != USB_CDC_NOTIFICATION_REQUEST_TYPE) { 3213 USB_DPRINTF_L2(PRINT_MASK_CB, acmp->acm_lh, 3214 "usbsacm_parse_intr_data: unknown request type - 0x%x", 3215 bmRequestType); 3216 3217 freemsg(data); 3218 3219 return; 3220 } 3221 3222 /* 3223 * Check the return value of device 3224 */ 3225 switch (bNotification) { 3226 case USB_CDC_NOTIFICATION_NETWORK_CONNECTION: 3227 USB_DPRINTF_L3(PRINT_MASK_CB, acmp->acm_lh, 3228 "usbsacm_parse_intr_data: %s network!", 3229 wValue ? "connected to" :"disconnected from"); 3230 3231 break; 3232 case USB_CDC_NOTIFICATION_RESPONSE_AVAILABLE: 3233 USB_DPRINTF_L3(PRINT_MASK_CB, acmp->acm_lh, 3234 "usbsacm_parse_intr_data: A response is a available."); 3235 3236 break; 3237 case USB_CDC_NOTIFICATION_SERIAL_STATE: 3238 /* check the parameter's length. */ 3239 if (wLength != 2) { 3240 3241 USB_DPRINTF_L3(PRINT_MASK_CB, acmp->acm_lh, 3242 "usbsacm_parse_intr_data: error data length."); 3243 } else { 3244 /* 3245 * The Data field is a bitmapped value that contains 3246 * the current state of carrier detect, transmission 3247 * carrier, break, ring signal and device overrun 3248 * error. 3249 */ 3250 wData = data->b_rptr[8]; 3251 /* 3252 * Check the serial state of the current port. 3253 */ 3254 if (wData & USB_CDC_ACM_CONTROL_DCD) { 3255 3256 USB_DPRINTF_L3(PRINT_MASK_CB, acmp->acm_lh, 3257 "usbsacm_parse_intr_data: " 3258 "receiver carrier is set."); 3259 } 3260 if (wData & USB_CDC_ACM_CONTROL_DSR) { 3261 3262 USB_DPRINTF_L3(PRINT_MASK_CB, acmp->acm_lh, 3263 "usbsacm_parse_intr_data: " 3264 "transmission carrier is set."); 3265 3266 acm_port->acm_mctlin |= USB_CDC_ACM_CONTROL_DSR; 3267 } 3268 if (wData & USB_CDC_ACM_CONTROL_BREAK) { 3269 3270 USB_DPRINTF_L3(PRINT_MASK_CB, acmp->acm_lh, 3271 "usbsacm_parse_intr_data: " 3272 "break detection mechanism is set."); 3273 } 3274 if (wData & USB_CDC_ACM_CONTROL_RNG) { 3275 3276 USB_DPRINTF_L3(PRINT_MASK_CB, acmp->acm_lh, 3277 "usbsacm_parse_intr_data: " 3278 "ring signal detection is set."); 3279 3280 acm_port->acm_mctlin |= USB_CDC_ACM_CONTROL_RNG; 3281 } 3282 if (wData & USB_CDC_ACM_CONTROL_FRAMING) { 3283 3284 USB_DPRINTF_L3(PRINT_MASK_CB, acmp->acm_lh, 3285 "usbsacm_parse_intr_data: " 3286 "A framing error has occurred."); 3287 } 3288 if (wData & USB_CDC_ACM_CONTROL_PARITY) { 3289 3290 USB_DPRINTF_L3(PRINT_MASK_CB, acmp->acm_lh, 3291 "usbsacm_parse_intr_data: " 3292 "A parity error has occurred."); 3293 } 3294 if (wData & USB_CDC_ACM_CONTROL_OVERRUN) { 3295 3296 USB_DPRINTF_L3(PRINT_MASK_CB, acmp->acm_lh, 3297 "usbsacm_parse_intr_data: " 3298 "Received data has been discarded " 3299 "due to overrun."); 3300 } 3301 } 3302 3303 break; 3304 default: 3305 USB_DPRINTF_L3(PRINT_MASK_CB, acmp->acm_lh, 3306 "usbsacm_parse_intr_data: unknown notification - 0x%x!", 3307 bNotification); 3308 3309 break; 3310 } 3311 3312 freemsg(data); 3313 } 3314