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