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
_init(void)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
_fini(void)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
_info(struct modinfo * modinfop)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
usbsacm_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)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
usbsacm_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)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
usbsacm_getinfo(dev_info_t * dip,ddi_info_cmd_t infocmd,void * arg,void ** result)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
usbsacm_open(queue_t * rq,dev_t * dev,int flag,int sflag,cred_t * cr)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
usbsacm_ds_attach(ds_attach_info_t * aip)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
usbsacm_ds_detach(ds_hdl_t hdl)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
usbsacm_ds_register_cb(ds_hdl_t hdl,uint_t port_num,ds_cb_t * cb)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
usbsacm_ds_unregister_cb(ds_hdl_t hdl,uint_t port_num)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
usbsacm_ds_open_port(ds_hdl_t hdl,uint_t port_num)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
usbsacm_ds_close_port(ds_hdl_t hdl,uint_t port_num)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
usbsacm_ds_usb_power(ds_hdl_t hdl,int comp,int level,int * new_state)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
usbsacm_ds_suspend(ds_hdl_t hdl)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
usbsacm_ds_resume(ds_hdl_t hdl)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
usbsacm_ds_disconnect(ds_hdl_t hdl)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
usbsacm_ds_reconnect(ds_hdl_t hdl)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
usbsacm_ds_set_port_params(ds_hdl_t hdl,uint_t port_num,ds_port_params_t * tp)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
usbsacm_ds_set_modem_ctl(ds_hdl_t hdl,uint_t port_num,int mask,int val)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
usbsacm_ds_get_modem_ctl(ds_hdl_t hdl,uint_t port_num,int mask,int * valp)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
usbsacm_ds_break_ctl(ds_hdl_t hdl,uint_t port_num,int ctl)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
usbsacm_ds_tx(ds_hdl_t hdl,uint_t port_num,mblk_t * mp)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 *
usbsacm_ds_rx(ds_hdl_t hdl,uint_t port_num)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
usbsacm_ds_stop(ds_hdl_t hdl,uint_t port_num,int dir)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
usbsacm_ds_start(ds_hdl_t hdl,uint_t port_num,int dir)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
usbsacm_ds_fifo_flush(ds_hdl_t hdl,uint_t port_num,int dir)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
usbsacm_ds_fifo_drain(ds_hdl_t hdl,uint_t port_num,int timeout)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
usbsacm_fifo_flush_locked(usbsacm_state_t * acmp,uint_t port_num,int dir)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
usbsacm_get_bulk_pipe_number(usbsacm_state_t * acmp,uint_t dir)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
usbsacm_init_ports_status(usbsacm_state_t * acmp)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
usbsacm_init_alloc_ports(usbsacm_state_t * acmp)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
usbsacm_free_ports(usbsacm_state_t * acmp)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
usbsacm_get_descriptors(usbsacm_state_t * acmp)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
usbsacm_cleanup(usbsacm_state_t * acmp)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
usbsacm_restore_device_state(usbsacm_state_t * acmp)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
usbsacm_restore_port_state(usbsacm_state_t * acmp)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
usbsacm_open_port_pipes(usbsacm_port_t * acm_port)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
usbsacm_close_port_pipes(usbsacm_port_t * acm_port)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
usbsacm_close_pipes(usbsacm_state_t * acmp)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
usbsacm_disconnect_pipes(usbsacm_state_t * acmp)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
usbsacm_reconnect_pipes(usbsacm_state_t * acmp)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
usbsacm_bulkin_cb(usb_pipe_handle_t pipe,usb_bulk_req_t * req)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
usbsacm_bulkout_cb(usb_pipe_handle_t pipe,usb_bulk_req_t * req)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
usbsacm_rx_start(usbsacm_port_t * acm_port)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
usbsacm_tx_start(usbsacm_port_t * acm_port)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
usbsacm_send_data(usbsacm_port_t * acm_port,mblk_t * data)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
usbsacm_wait_tx_drain(usbsacm_port_t * acm_port,int timeout)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
usbsacm_req_write(usbsacm_port_t * acm_port,uchar_t request,uint16_t value,mblk_t ** data)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
usbsacm_set_line_coding(usbsacm_port_t * acm_port,usb_cdc_line_coding_t * lc)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
usbsacm_mctl2reg(int mask,int val,uint8_t * line_ctl)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
usbsacm_reg2mctl(uint8_t line_ctl)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
usbsacm_put_tail(mblk_t ** mpp,mblk_t * bp)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
usbsacm_put_head(mblk_t ** mpp,mblk_t * bp)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
usbsacm_create_pm_components(usbsacm_state_t * acmp)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
usbsacm_destroy_pm_components(usbsacm_state_t * acmp)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
usbsacm_pm_set_busy(usbsacm_state_t * acmp)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
usbsacm_pm_set_idle(usbsacm_state_t * acmp)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
usbsacm_pwrlvl0(usbsacm_state_t * acmp)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
usbsacm_pwrlvl1(usbsacm_state_t * acmp)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
usbsacm_pwrlvl2(usbsacm_state_t * acmp)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
usbsacm_pwrlvl3(usbsacm_state_t * acmp)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
usbsacm_pipe_start_polling(usbsacm_port_t * acm_port)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
usbsacm_intr_cb(usb_pipe_handle_t ph,usb_intr_req_t * req)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
usbsacm_intr_ex_cb(usb_pipe_handle_t ph,usb_intr_req_t * req)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
usbsacm_parse_intr_data(usbsacm_port_t * acm_port,mblk_t * data)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