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