160b08185Syz147069 /* 260b08185Syz147069 * CDDL HEADER START 360b08185Syz147069 * 460b08185Syz147069 * The contents of this file are subject to the terms of the 560b08185Syz147069 * Common Development and Distribution License, Version 1.0 only 660b08185Syz147069 * (the "License"). You may not use this file except in compliance 760b08185Syz147069 * with the License. 860b08185Syz147069 * 960b08185Syz147069 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 1060b08185Syz147069 * or http://www.opensolaris.org/os/licensing. 1160b08185Syz147069 * See the License for the specific language governing permissions 1260b08185Syz147069 * and limitations under the License. 1360b08185Syz147069 * 1460b08185Syz147069 * When distributing Covered Code, include this CDDL HEADER in each 1560b08185Syz147069 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1660b08185Syz147069 * If applicable, add the following below this CDDL HEADER, with the 1760b08185Syz147069 * fields enclosed by brackets "[]" replaced with your own identifying 1860b08185Syz147069 * information: Portions Copyright [yyyy] [name of copyright owner] 1960b08185Syz147069 * 2060b08185Syz147069 * CDDL HEADER END 2160b08185Syz147069 */ 2260b08185Syz147069 /* 2360b08185Syz147069 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 2460b08185Syz147069 * Use is subject to license terms. 2560b08185Syz147069 */ 2660b08185Syz147069 2760b08185Syz147069 #pragma ident "%Z%%M% %I% %E% SMI" 2860b08185Syz147069 2960b08185Syz147069 /* 3060b08185Syz147069 * 3160b08185Syz147069 * keyspanport pipe routines (mostly device-neutral) 3260b08185Syz147069 * 3360b08185Syz147069 */ 3460b08185Syz147069 #include <sys/types.h> 3560b08185Syz147069 #include <sys/param.h> 3660b08185Syz147069 #include <sys/conf.h> 3760b08185Syz147069 #include <sys/stream.h> 3860b08185Syz147069 #include <sys/strsun.h> 3960b08185Syz147069 #include <sys/termio.h> 4060b08185Syz147069 #include <sys/ddi.h> 4160b08185Syz147069 #include <sys/sunddi.h> 4260b08185Syz147069 4360b08185Syz147069 #include <sys/usb/usba.h> 4460b08185Syz147069 #include <sys/usb/clients/usbser/usbser_keyspan/keyspan_var.h> 4560b08185Syz147069 #include <sys/usb/clients/usbser/usbser_keyspan/keyspan_pipe.h> 4660b08185Syz147069 4760b08185Syz147069 /* 4860b08185Syz147069 * initialize pipe structure with the given parameters 4960b08185Syz147069 */ 5060b08185Syz147069 static void 5160b08185Syz147069 keyspan_init_one_pipe(keyspan_state_t *ksp, keyspan_port_t *kp, 5260b08185Syz147069 keyspan_pipe_t *pipe) 5360b08185Syz147069 { 5460b08185Syz147069 usb_pipe_policy_t *policy; 5560b08185Syz147069 5660b08185Syz147069 USB_DPRINTF_L4(DPRINT_OPEN, ksp->ks_lh, "keyspan_init_one_pipe: " 5760b08185Syz147069 "pipe = %p, pipe_stat %x", (void *)pipe, pipe->pipe_state); 5860b08185Syz147069 5960b08185Syz147069 /* init sync primitives */ 6060b08185Syz147069 mutex_init(&pipe->pipe_mutex, NULL, MUTEX_DRIVER, (void *)NULL); 6160b08185Syz147069 6260b08185Syz147069 /* init pipe policy */ 6360b08185Syz147069 policy = &pipe->pipe_policy; 6460b08185Syz147069 policy->pp_max_async_reqs = 2; 6560b08185Syz147069 6660b08185Syz147069 pipe->pipe_ksp = ksp; 6760b08185Syz147069 if (kp == NULL) { 6860b08185Syz147069 /* globle pipes should have device log handle */ 6960b08185Syz147069 pipe->pipe_lh = ksp->ks_lh; 7060b08185Syz147069 } else { 7160b08185Syz147069 /* port pipes should have port log handle */ 7260b08185Syz147069 pipe->pipe_lh = kp->kp_lh; 7360b08185Syz147069 } 7460b08185Syz147069 7560b08185Syz147069 pipe->pipe_state = KEYSPAN_PIPE_CLOSED; 7660b08185Syz147069 } 7760b08185Syz147069 7860b08185Syz147069 7960b08185Syz147069 static void 8060b08185Syz147069 keyspan_fini_one_pipe(keyspan_pipe_t *pipe) 8160b08185Syz147069 { 8260b08185Syz147069 USB_DPRINTF_L4(DPRINT_OPEN, pipe->pipe_ksp->ks_lh, 8360b08185Syz147069 "keyspan_fini_one_pipe: pipe_stat %x", pipe->pipe_state); 8460b08185Syz147069 8560b08185Syz147069 if (pipe->pipe_state != KEYSPAN_PIPE_NOT_INIT) { 8660b08185Syz147069 mutex_destroy(&pipe->pipe_mutex); 8760b08185Syz147069 pipe->pipe_state = KEYSPAN_PIPE_NOT_INIT; 8860b08185Syz147069 } 8960b08185Syz147069 } 9060b08185Syz147069 9160b08185Syz147069 /* 9260b08185Syz147069 * Lookup the endpoints defined in the spec; 9360b08185Syz147069 * Allocate resources, initialize pipe structures. 9460b08185Syz147069 * All are bulk pipes, including data in/out, cmd/status pipes. 9560b08185Syz147069 */ 9660b08185Syz147069 int 9760b08185Syz147069 keyspan_init_pipes(keyspan_state_t *ksp) 9860b08185Syz147069 { 9960b08185Syz147069 usb_client_dev_data_t *dev_data = ksp->ks_dev_data; 10060b08185Syz147069 int ifc, alt, i, j, k = 0; 10160b08185Syz147069 uint8_t port_cnt = ksp->ks_dev_spec.port_cnt; 10260b08185Syz147069 uint8_t ep_addr, ep_cnt; 10360b08185Syz147069 usb_ep_data_t *dataout[KEYSPAN_MAX_PORT_NUM], 10460b08185Syz147069 *datain[KEYSPAN_MAX_PORT_NUM], 10560b08185Syz147069 *status = NULL, *ctrl = NULL, *tmp_ep; 10660b08185Syz147069 usb_alt_if_data_t *alt_data; 10760b08185Syz147069 usb_if_data_t *if_data; 10860b08185Syz147069 10960b08185Syz147069 11060b08185Syz147069 ifc = dev_data->dev_curr_if; 11160b08185Syz147069 alt = 0; 11260b08185Syz147069 if_data = &dev_data->dev_curr_cfg->cfg_if[ifc]; 11360b08185Syz147069 alt_data = &if_data->if_alt[alt]; 11460b08185Syz147069 11560b08185Syz147069 /* 11660b08185Syz147069 * The actual EP number (indicated by bNumEndpoints) is more than 11760b08185Syz147069 * those defined in spec. We have to match those we need according 11860b08185Syz147069 * to EP addresses. And we'll lookup In EPs and Out EPs separately. 11960b08185Syz147069 */ 12060b08185Syz147069 ep_cnt = (alt_data->altif_descr.bNumEndpoints + 1) / 2; 12160b08185Syz147069 12260b08185Syz147069 /* 12360b08185Syz147069 * get DIR_IN EP descriptors, and then match with EP addresses. 12460b08185Syz147069 * Different keyspan devices may has different EP addresses. 12560b08185Syz147069 */ 12660b08185Syz147069 for (i = 0; i < ep_cnt; i++) { 12760b08185Syz147069 tmp_ep = usb_lookup_ep_data(ksp->ks_dip, dev_data, ifc, alt, i, 12860b08185Syz147069 USB_EP_ATTR_BULK, USB_EP_DIR_IN); 12960b08185Syz147069 if (tmp_ep == NULL) { 13060b08185Syz147069 USB_DPRINTF_L3(DPRINT_ATTACH, ksp->ks_lh, 13160b08185Syz147069 "keyspan_init_pipes: can't find bulk in ep, i=%d," 13260b08185Syz147069 "ep_cnt=%d", i, ep_cnt); 13360b08185Syz147069 13460b08185Syz147069 continue; 13560b08185Syz147069 } 13660b08185Syz147069 ep_addr = tmp_ep->ep_descr.bEndpointAddress; 13760b08185Syz147069 13860b08185Syz147069 USB_DPRINTF_L3(DPRINT_ATTACH, ksp->ks_lh, "keyspan_init_pipes: " 13960b08185Syz147069 "ep_addr =%x, stat_ep_addr=%x, i=%d", ep_addr, 14060b08185Syz147069 ksp->ks_dev_spec.stat_ep_addr, i); 14160b08185Syz147069 14260b08185Syz147069 /* match the status EP */ 14360b08185Syz147069 if (ep_addr == ksp->ks_dev_spec.stat_ep_addr) { 14460b08185Syz147069 status = tmp_ep; 14560b08185Syz147069 14660b08185Syz147069 continue; 14760b08185Syz147069 } 14860b08185Syz147069 14960b08185Syz147069 /* match the EPs of the ports */ 15060b08185Syz147069 for (j = 0; j < port_cnt; j++) { 15160b08185Syz147069 USB_DPRINTF_L3(DPRINT_ATTACH, ksp->ks_lh, 15260b08185Syz147069 "keyspan_init_pipes: try to match bulk in data ep," 15360b08185Syz147069 " j=%d", j); 15460b08185Syz147069 if (ep_addr == ksp->ks_dev_spec.datain_ep_addr[j]) { 15560b08185Syz147069 datain[j] = tmp_ep; 15660b08185Syz147069 k++; 15760b08185Syz147069 USB_DPRINTF_L3(DPRINT_ATTACH, ksp->ks_lh, 15860b08185Syz147069 "keyspan_init_pipes: matched a bulk in" 15960b08185Syz147069 " data ep"); 16060b08185Syz147069 16160b08185Syz147069 break; 16260b08185Syz147069 } 16360b08185Syz147069 } 16460b08185Syz147069 16560b08185Syz147069 /* if have matched all the necessary endpoints, break out */ 16660b08185Syz147069 if (k >= port_cnt && status != NULL) { 16760b08185Syz147069 16860b08185Syz147069 break; 16960b08185Syz147069 } 17060b08185Syz147069 17160b08185Syz147069 USB_DPRINTF_L4(DPRINT_ATTACH, ksp->ks_lh, "keyspan_init_pipes: " 17260b08185Syz147069 "try to match bulk in data ep, j=%d", j); 17360b08185Syz147069 17460b08185Syz147069 if (j == port_cnt) { 17560b08185Syz147069 /* this ep can't be matched by any addr */ 17660b08185Syz147069 USB_DPRINTF_L4(DPRINT_ATTACH, ksp->ks_lh, 17760b08185Syz147069 "keyspan_init_pipes: can't match bulk in ep," 17860b08185Syz147069 " addr =%x,", ep_addr); 17960b08185Syz147069 } 18060b08185Syz147069 } 18160b08185Syz147069 18260b08185Syz147069 if (k != port_cnt || status == NULL) { 18360b08185Syz147069 18460b08185Syz147069 /* Some of the necessary IN endpoints are not matched */ 18560b08185Syz147069 USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh, 18660b08185Syz147069 "keyspan_init_pipes: matched %d data in endpoints," 18760b08185Syz147069 " not enough", k); 18860b08185Syz147069 18960b08185Syz147069 return (USB_FAILURE); 19060b08185Syz147069 } 19160b08185Syz147069 19260b08185Syz147069 k = 0; 19360b08185Syz147069 19460b08185Syz147069 /* 19560b08185Syz147069 * get DIR_OUT EP descriptors, and then match with ep addrs. 19660b08185Syz147069 * different keyspan devices may has different ep addresses. 19760b08185Syz147069 */ 19860b08185Syz147069 for (i = 0; i < ep_cnt; i++) { 19960b08185Syz147069 tmp_ep = usb_lookup_ep_data(ksp->ks_dip, dev_data, ifc, alt, i, 20060b08185Syz147069 USB_EP_ATTR_BULK, USB_EP_DIR_OUT); 20160b08185Syz147069 if (tmp_ep == NULL) { 20260b08185Syz147069 USB_DPRINTF_L3(DPRINT_ATTACH, ksp->ks_lh, 20360b08185Syz147069 "keyspan_init_pipes: can't find bulk out ep, i=%d," 20460b08185Syz147069 "ep_cnt=%d", i, ep_cnt); 20560b08185Syz147069 20660b08185Syz147069 continue; 20760b08185Syz147069 } 20860b08185Syz147069 ep_addr = tmp_ep->ep_descr.bEndpointAddress; 20960b08185Syz147069 21060b08185Syz147069 /* match the status ep */ 21160b08185Syz147069 if (ep_addr == ksp->ks_dev_spec.ctrl_ep_addr) { 21260b08185Syz147069 ctrl = tmp_ep; 21360b08185Syz147069 21460b08185Syz147069 continue; 21560b08185Syz147069 } 21660b08185Syz147069 21760b08185Syz147069 /* match the ep of the ports */ 21860b08185Syz147069 for (j = 0; j < port_cnt; j++) { 21960b08185Syz147069 if (ep_addr == ksp->ks_dev_spec.dataout_ep_addr[j]) { 22060b08185Syz147069 dataout[j] = tmp_ep; 22160b08185Syz147069 k++; 22260b08185Syz147069 22360b08185Syz147069 break; 22460b08185Syz147069 } 22560b08185Syz147069 } 22660b08185Syz147069 /* if have matched all the necessary endpoints, break out */ 22760b08185Syz147069 if (k >= port_cnt && ctrl != NULL) { 22860b08185Syz147069 22960b08185Syz147069 break; 23060b08185Syz147069 } 23160b08185Syz147069 23260b08185Syz147069 if (j == port_cnt) { 23360b08185Syz147069 23460b08185Syz147069 /* this ep can't be matched by any addr */ 23560b08185Syz147069 USB_DPRINTF_L4(DPRINT_ATTACH, ksp->ks_lh, 23660b08185Syz147069 "keyspan_init_pipes: can't match bulk out ep," 23760b08185Syz147069 " ep_addr =%x", ep_addr); 23860b08185Syz147069 23960b08185Syz147069 } 24060b08185Syz147069 } 24160b08185Syz147069 24260b08185Syz147069 if (k != port_cnt || ctrl == NULL) { 24360b08185Syz147069 /* Not all the necessary OUT endpoints are matched */ 24460b08185Syz147069 USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh, 24560b08185Syz147069 "keyspan_init_pipes: matched %d data in endpoints," 24660b08185Syz147069 " not enough", k); 24760b08185Syz147069 24860b08185Syz147069 return (USB_FAILURE); 24960b08185Syz147069 } 25060b08185Syz147069 25160b08185Syz147069 mutex_enter(&ksp->ks_mutex); 25260b08185Syz147069 25360b08185Syz147069 /* 25460b08185Syz147069 * Device globle pipes: a bulk in pipe for status and a bulk out 25560b08185Syz147069 * pipe for controle cmd. 25660b08185Syz147069 */ 25760b08185Syz147069 ksp->ks_statin_pipe.pipe_ep_descr = status->ep_descr; 25860b08185Syz147069 keyspan_init_one_pipe(ksp, NULL, &ksp->ks_statin_pipe); 25960b08185Syz147069 26060b08185Syz147069 ksp->ks_ctrlout_pipe.pipe_ep_descr = ctrl->ep_descr; 26160b08185Syz147069 keyspan_init_one_pipe(ksp, NULL, &ksp->ks_ctrlout_pipe); 26260b08185Syz147069 26360b08185Syz147069 /* for data in/out pipes of each port */ 26460b08185Syz147069 for (i = 0; i < port_cnt; i++) { 26560b08185Syz147069 26660b08185Syz147069 ksp->ks_ports[i].kp_datain_pipe.pipe_ep_descr = 26760b08185Syz147069 datain[i]->ep_descr; 26860b08185Syz147069 keyspan_init_one_pipe(ksp, &ksp->ks_ports[i], 26960b08185Syz147069 &ksp->ks_ports[i].kp_datain_pipe); 27060b08185Syz147069 27160b08185Syz147069 ksp->ks_ports[i].kp_dataout_pipe.pipe_ep_descr = 27260b08185Syz147069 dataout[i]->ep_descr; 27360b08185Syz147069 keyspan_init_one_pipe(ksp, &ksp->ks_ports[i], 27460b08185Syz147069 &ksp->ks_ports[i].kp_dataout_pipe); 27560b08185Syz147069 } 27660b08185Syz147069 27760b08185Syz147069 mutex_exit(&ksp->ks_mutex); 27860b08185Syz147069 27960b08185Syz147069 return (USB_SUCCESS); 28060b08185Syz147069 } 28160b08185Syz147069 28260b08185Syz147069 void 28360b08185Syz147069 keyspan_fini_pipes(keyspan_state_t *ksp) 28460b08185Syz147069 { 28560b08185Syz147069 keyspan_port_t *kp; 28660b08185Syz147069 int i; 28760b08185Syz147069 28860b08185Syz147069 for (i = 0; i < ksp->ks_dev_spec.port_cnt; i++) { 28960b08185Syz147069 kp = &ksp->ks_ports[i]; 29060b08185Syz147069 keyspan_fini_one_pipe(&kp->kp_datain_pipe); 29160b08185Syz147069 keyspan_fini_one_pipe(&kp->kp_dataout_pipe); 29260b08185Syz147069 } 29360b08185Syz147069 29460b08185Syz147069 /* fini global pipes */ 29560b08185Syz147069 keyspan_fini_one_pipe(&ksp->ks_statin_pipe); 29660b08185Syz147069 keyspan_fini_one_pipe(&ksp->ks_ctrlout_pipe); 29760b08185Syz147069 } 29860b08185Syz147069 29960b08185Syz147069 30060b08185Syz147069 static int 30160b08185Syz147069 keyspan_open_one_pipe(keyspan_state_t *ksp, keyspan_pipe_t *pipe) 30260b08185Syz147069 { 30360b08185Syz147069 int rval; 30460b08185Syz147069 30560b08185Syz147069 /* don't open for the second time */ 30660b08185Syz147069 mutex_enter(&pipe->pipe_mutex); 30760b08185Syz147069 ASSERT(pipe->pipe_state != KEYSPAN_PIPE_NOT_INIT); 30860b08185Syz147069 if (pipe->pipe_state != KEYSPAN_PIPE_CLOSED) { 30960b08185Syz147069 mutex_exit(&pipe->pipe_mutex); 31060b08185Syz147069 31160b08185Syz147069 return (USB_SUCCESS); 31260b08185Syz147069 } 31360b08185Syz147069 mutex_exit(&pipe->pipe_mutex); 31460b08185Syz147069 31560b08185Syz147069 rval = usb_pipe_open(ksp->ks_dip, &pipe->pipe_ep_descr, 31660b08185Syz147069 &pipe->pipe_policy, USB_FLAGS_SLEEP, &pipe->pipe_handle); 31760b08185Syz147069 31860b08185Syz147069 if (rval == USB_SUCCESS) { 31960b08185Syz147069 mutex_enter(&pipe->pipe_mutex); 32060b08185Syz147069 pipe->pipe_state = KEYSPAN_PIPE_OPEN; 32160b08185Syz147069 mutex_exit(&pipe->pipe_mutex); 32260b08185Syz147069 } 32360b08185Syz147069 32460b08185Syz147069 return (rval); 32560b08185Syz147069 } 32660b08185Syz147069 32760b08185Syz147069 32860b08185Syz147069 /* 32960b08185Syz147069 * close one pipe if open 33060b08185Syz147069 */ 33160b08185Syz147069 static void 33260b08185Syz147069 keyspan_close_one_pipe(keyspan_pipe_t *pipe) 33360b08185Syz147069 { 33460b08185Syz147069 /* 33560b08185Syz147069 * pipe may already be closed, e.g. if device has been physically 33660b08185Syz147069 * disconnected and the driver immediately detached 33760b08185Syz147069 */ 33860b08185Syz147069 if (pipe->pipe_handle != NULL) { 33960b08185Syz147069 usb_pipe_close(pipe->pipe_ksp->ks_dip, pipe->pipe_handle, 34060b08185Syz147069 USB_FLAGS_SLEEP, NULL, NULL); 34160b08185Syz147069 mutex_enter(&pipe->pipe_mutex); 34260b08185Syz147069 pipe->pipe_handle = NULL; 34360b08185Syz147069 pipe->pipe_state = KEYSPAN_PIPE_CLOSED; 34460b08185Syz147069 mutex_exit(&pipe->pipe_mutex); 34560b08185Syz147069 } 34660b08185Syz147069 } 34760b08185Syz147069 34860b08185Syz147069 /* 34960b08185Syz147069 * Open global pipes, a status pipe and a control pipe 35060b08185Syz147069 */ 35160b08185Syz147069 int 35260b08185Syz147069 keyspan_open_dev_pipes(keyspan_state_t *ksp) 35360b08185Syz147069 { 35460b08185Syz147069 int rval; 35560b08185Syz147069 35660b08185Syz147069 USB_DPRINTF_L4(DPRINT_OPEN, ksp->ks_lh, "keyspan_open_dev_pipes"); 35760b08185Syz147069 35860b08185Syz147069 rval = keyspan_open_one_pipe(ksp, &ksp->ks_ctrlout_pipe); 35960b08185Syz147069 if (rval != USB_SUCCESS) { 36060b08185Syz147069 USB_DPRINTF_L2(DPRINT_OPEN, ksp->ks_lh, 36160b08185Syz147069 "keyspan_open_dev_pipes: open ctrl pipe failed %d", rval); 36260b08185Syz147069 36360b08185Syz147069 return (rval); 36460b08185Syz147069 } 36560b08185Syz147069 36660b08185Syz147069 rval = keyspan_open_one_pipe(ksp, &ksp->ks_statin_pipe); 36760b08185Syz147069 if (rval != USB_SUCCESS) { 36860b08185Syz147069 USB_DPRINTF_L2(DPRINT_OPEN, ksp->ks_lh, 36960b08185Syz147069 "keyspan_open_dev_pipes: open status pipe failed %d", rval); 37060b08185Syz147069 37160b08185Syz147069 /* close the first opened pipe here */ 37260b08185Syz147069 keyspan_close_one_pipe(&ksp->ks_ctrlout_pipe); 37360b08185Syz147069 37460b08185Syz147069 return (rval); 37560b08185Syz147069 } 37660b08185Syz147069 37760b08185Syz147069 /* start receive device status */ 37860b08185Syz147069 rval = keyspan_receive_status(ksp); 37960b08185Syz147069 if (rval != USB_SUCCESS) { 38060b08185Syz147069 USB_DPRINTF_L2(DPRINT_OPEN, ksp->ks_lh, 38160b08185Syz147069 "keyspan_open_dev_pipes: receive device status failed %d", 38260b08185Syz147069 rval); 38360b08185Syz147069 38460b08185Syz147069 /* close opened pipes here */ 38560b08185Syz147069 keyspan_close_one_pipe(&ksp->ks_statin_pipe); 38660b08185Syz147069 keyspan_close_one_pipe(&ksp->ks_ctrlout_pipe); 38760b08185Syz147069 38860b08185Syz147069 return (rval); 38960b08185Syz147069 } 39060b08185Syz147069 39160b08185Syz147069 return (rval); 39260b08185Syz147069 } 39360b08185Syz147069 39460b08185Syz147069 39560b08185Syz147069 /* 39660b08185Syz147069 * Reopen all pipes if the port had them open 39760b08185Syz147069 */ 39860b08185Syz147069 int 39960b08185Syz147069 keyspan_reopen_pipes(keyspan_state_t *ksp) 40060b08185Syz147069 { 40160b08185Syz147069 keyspan_port_t *kp; 40260b08185Syz147069 int i; 40360b08185Syz147069 40460b08185Syz147069 USB_DPRINTF_L4(DPRINT_OPEN, ksp->ks_lh, "keyspan_reopen_pipes"); 40560b08185Syz147069 40660b08185Syz147069 if (keyspan_open_dev_pipes(ksp) != USB_SUCCESS) { 40760b08185Syz147069 40860b08185Syz147069 return (USB_FAILURE); 40960b08185Syz147069 } 41060b08185Syz147069 41160b08185Syz147069 for (i = 0; i < ksp->ks_dev_spec.port_cnt; i++) { 41260b08185Syz147069 kp = &ksp->ks_ports[i]; 41360b08185Syz147069 mutex_enter(&kp->kp_mutex); 41460b08185Syz147069 if (kp->kp_state == KEYSPAN_PORT_OPEN) { 41560b08185Syz147069 USB_DPRINTF_L4(DPRINT_OPEN, ksp->ks_lh, 41660b08185Syz147069 "keyspan_reopen_pipes() reopen pipe #%d", i); 41760b08185Syz147069 mutex_exit(&kp->kp_mutex); 41860b08185Syz147069 if (keyspan_open_port_pipes(kp) != USB_SUCCESS) { 41960b08185Syz147069 42060b08185Syz147069 return (USB_FAILURE); 42160b08185Syz147069 } 42260b08185Syz147069 mutex_enter(&kp->kp_mutex); 42360b08185Syz147069 kp->kp_no_more_reads = B_FALSE; 42460b08185Syz147069 } 42560b08185Syz147069 mutex_exit(&kp->kp_mutex); 42660b08185Syz147069 } 42760b08185Syz147069 42860b08185Syz147069 return (USB_SUCCESS); 42960b08185Syz147069 } 43060b08185Syz147069 43160b08185Syz147069 void 43260b08185Syz147069 keyspan_close_port_pipes(keyspan_port_t *kp) 43360b08185Syz147069 { 43460b08185Syz147069 USB_DPRINTF_L4(DPRINT_CLOSE, kp->kp_lh, "keyspan_close_port_pipes"); 43560b08185Syz147069 43660b08185Syz147069 keyspan_close_one_pipe(&kp->kp_dataout_pipe); 43760b08185Syz147069 keyspan_close_one_pipe(&kp->kp_datain_pipe); 43860b08185Syz147069 } 43960b08185Syz147069 44060b08185Syz147069 /* 44160b08185Syz147069 * Close IN and OUT bulk pipes of all ports 44260b08185Syz147069 */ 44360b08185Syz147069 void 44460b08185Syz147069 keyspan_close_open_pipes(keyspan_state_t *ksp) 44560b08185Syz147069 { 44660b08185Syz147069 keyspan_port_t *kp; 44760b08185Syz147069 int i; 44860b08185Syz147069 44960b08185Syz147069 USB_DPRINTF_L4(DPRINT_CLOSE, ksp->ks_lh, "keyspan_close_open_pipes"); 45060b08185Syz147069 45160b08185Syz147069 for (i = 0; i < ksp->ks_dev_spec.port_cnt; i++) { 45260b08185Syz147069 kp = &ksp->ks_ports[i]; 45360b08185Syz147069 mutex_enter(&kp->kp_mutex); 45460b08185Syz147069 if (kp->kp_state == KEYSPAN_PORT_OPEN) { 45560b08185Syz147069 kp->kp_no_more_reads = B_TRUE; 45660b08185Syz147069 mutex_exit(&kp->kp_mutex); 45760b08185Syz147069 usb_pipe_reset(ksp->ks_dip, 45860b08185Syz147069 kp->kp_datain_pipe.pipe_handle, USB_FLAGS_SLEEP, 45960b08185Syz147069 NULL, NULL); 46060b08185Syz147069 keyspan_close_port_pipes(kp); 46160b08185Syz147069 } else { 46260b08185Syz147069 mutex_exit(&kp->kp_mutex); 46360b08185Syz147069 } 46460b08185Syz147069 } 46560b08185Syz147069 } 46660b08185Syz147069 46760b08185Syz147069 46860b08185Syz147069 /* 46960b08185Syz147069 * Close global pipes 47060b08185Syz147069 */ 47160b08185Syz147069 void 47260b08185Syz147069 keyspan_close_dev_pipes(keyspan_state_t *ksp) 47360b08185Syz147069 { 47460b08185Syz147069 USB_DPRINTF_L4(DPRINT_CLOSE, ksp->ks_lh, "keyspan_close_dev_pipes"); 47560b08185Syz147069 47660b08185Syz147069 keyspan_close_one_pipe(&ksp->ks_statin_pipe); 47760b08185Syz147069 keyspan_close_one_pipe(&ksp->ks_ctrlout_pipe); 47860b08185Syz147069 } 47960b08185Syz147069 48060b08185Syz147069 48160b08185Syz147069 /* 48260b08185Syz147069 * Open bulk data IN and data OUT pipes for one port. 48360b08185Syz147069 * The status and control pipes are opened in attach because they are global. 48460b08185Syz147069 */ 48560b08185Syz147069 int 48660b08185Syz147069 keyspan_open_port_pipes(keyspan_port_t *kp) 48760b08185Syz147069 { 48860b08185Syz147069 keyspan_state_t *ksp = kp->kp_ksp; 48960b08185Syz147069 int rval; 49060b08185Syz147069 49160b08185Syz147069 USB_DPRINTF_L4(DPRINT_OPEN, kp->kp_lh, "keyspan_open_port_pipes"); 49260b08185Syz147069 49360b08185Syz147069 rval = keyspan_open_one_pipe(ksp, &kp->kp_datain_pipe); 49460b08185Syz147069 if (rval != USB_SUCCESS) { 49560b08185Syz147069 49660b08185Syz147069 goto fail; 49760b08185Syz147069 } 49860b08185Syz147069 49960b08185Syz147069 rval = keyspan_open_one_pipe(ksp, &kp->kp_dataout_pipe); 50060b08185Syz147069 if (rval != USB_SUCCESS) { 50160b08185Syz147069 50260b08185Syz147069 goto fail; 50360b08185Syz147069 } 50460b08185Syz147069 50560b08185Syz147069 return (rval); 50660b08185Syz147069 50760b08185Syz147069 fail: 50860b08185Syz147069 USB_DPRINTF_L2(DPRINT_OPEN, kp->kp_lh, 50960b08185Syz147069 "keyspan_open_port_pipes: failed %d", rval); 51060b08185Syz147069 keyspan_close_port_pipes(kp); 51160b08185Syz147069 51260b08185Syz147069 return (rval); 51360b08185Syz147069 } 51460b08185Syz147069 51560b08185Syz147069 void 51660b08185Syz147069 keyspan_close_pipes(keyspan_state_t *ksp) 51760b08185Syz147069 { 51860b08185Syz147069 USB_DPRINTF_L4(DPRINT_OPEN, ksp->ks_lh, "keyspan_close_pipes"); 51960b08185Syz147069 52060b08185Syz147069 /* close all ports' pipes first, and then device ctrl/status pipes. */ 52160b08185Syz147069 keyspan_close_open_pipes(ksp); 52260b08185Syz147069 keyspan_close_dev_pipes(ksp); 52360b08185Syz147069 52460b08185Syz147069 } 52560b08185Syz147069 52660b08185Syz147069 52760b08185Syz147069 /* 52860b08185Syz147069 * bulk out common callback 52960b08185Syz147069 */ 53060b08185Syz147069 /*ARGSUSED*/ 53160b08185Syz147069 void 53260b08185Syz147069 keyspan_bulkout_cb(usb_pipe_handle_t pipe, usb_bulk_req_t *req) 53360b08185Syz147069 { 53460b08185Syz147069 keyspan_port_t *kp = (keyspan_port_t *)req->bulk_client_private; 53560b08185Syz147069 keyspan_pipe_t *bulkout = &kp->kp_dataout_pipe; 53660b08185Syz147069 mblk_t *data = req->bulk_data; 53760b08185Syz147069 int data_len; 53860b08185Syz147069 53960b08185Syz147069 data_len = (data) ? MBLKL(data) : 0; 54060b08185Syz147069 54160b08185Syz147069 USB_DPRINTF_L4(DPRINT_OUT_PIPE, bulkout->pipe_lh, 54260b08185Syz147069 "keyspan_bulkout_cb: len=%d cr=%d cb_flags=%x", 54360b08185Syz147069 data_len, req->bulk_completion_reason, req->bulk_cb_flags); 54460b08185Syz147069 54560b08185Syz147069 if (req->bulk_completion_reason && (data_len > 0)) { 54660b08185Syz147069 54760b08185Syz147069 /* 54860b08185Syz147069 * Data wasn't transfered successfully. 54960b08185Syz147069 * Put data back on the queue. 55060b08185Syz147069 */ 55160b08185Syz147069 keyspan_put_head(&kp->kp_tx_mp, data, kp); 55260b08185Syz147069 55360b08185Syz147069 /* don't release mem in usb_free_bulk_req */ 55460b08185Syz147069 req->bulk_data = NULL; 55560b08185Syz147069 } 55660b08185Syz147069 55760b08185Syz147069 usb_free_bulk_req(req); 55860b08185Syz147069 55960b08185Syz147069 /* if more data available, kick off another transmit */ 56060b08185Syz147069 mutex_enter(&kp->kp_mutex); 56160b08185Syz147069 if (kp->kp_tx_mp == NULL) { 56260b08185Syz147069 56360b08185Syz147069 /* no more data, notify waiters */ 56460b08185Syz147069 cv_broadcast(&kp->kp_tx_cv); 56560b08185Syz147069 mutex_exit(&kp->kp_mutex); 56660b08185Syz147069 56760b08185Syz147069 /* tx callback for this port */ 56860b08185Syz147069 kp->kp_cb.cb_tx(kp->kp_cb.cb_arg); 56960b08185Syz147069 } else { 57060b08185Syz147069 keyspan_tx_start(kp, NULL); 57160b08185Syz147069 mutex_exit(&kp->kp_mutex); 57260b08185Syz147069 } 57360b08185Syz147069 } 57460b08185Syz147069 575*c138f478Syz147069 576*c138f478Syz147069 /* For incoming data only. Parse a status byte and return the err code */ 577*c138f478Syz147069 void 578*c138f478Syz147069 keyspan_parse_status(uchar_t *status, uchar_t *err) 579*c138f478Syz147069 { 580*c138f478Syz147069 if (*status & RXERROR_BREAK) { 581*c138f478Syz147069 /* 582*c138f478Syz147069 * Parity and Framing errors only count if they 583*c138f478Syz147069 * occur exclusive of a break being received. 584*c138f478Syz147069 */ 585*c138f478Syz147069 *status &= (uint8_t)(RXERROR_OVERRUN | RXERROR_BREAK); 586*c138f478Syz147069 } 587*c138f478Syz147069 *err |= (*status & RXERROR_OVERRUN) ? DS_OVERRUN_ERR : 0; 588*c138f478Syz147069 *err |= (*status & RXERROR_PARITY) ? DS_PARITY_ERR : 0; 589*c138f478Syz147069 *err |= (*status & RXERROR_FRAMING) ? DS_FRAMING_ERR : 0; 590*c138f478Syz147069 *err |= (*status & RXERROR_BREAK) ? DS_BREAK_ERR : 0; 591*c138f478Syz147069 } 592*c138f478Syz147069 593*c138f478Syz147069 59460b08185Syz147069 /* 59560b08185Syz147069 * pipe callbacks 59660b08185Syz147069 * -------------- 59760b08185Syz147069 * 59860b08185Syz147069 * bulk in common callback for usa19hs model 59960b08185Syz147069 */ 60060b08185Syz147069 /*ARGSUSED*/ 60160b08185Syz147069 int 60260b08185Syz147069 keyspan_bulkin_cb_usa19hs(usb_pipe_handle_t pipe, usb_bulk_req_t *req) 60360b08185Syz147069 { 60460b08185Syz147069 keyspan_port_t *kp = (keyspan_port_t *)req->bulk_client_private; 60560b08185Syz147069 keyspan_pipe_t *bulkin = &kp->kp_datain_pipe; 60660b08185Syz147069 mblk_t *data = req->bulk_data; 60760b08185Syz147069 uint_t cr = req->bulk_completion_reason; 60860b08185Syz147069 int data_len; 60960b08185Syz147069 61060b08185Syz147069 ASSERT(mutex_owned(&kp->kp_mutex)); 61160b08185Syz147069 61260b08185Syz147069 data_len = (data) ? MBLKL(data) : 0; 61360b08185Syz147069 61460b08185Syz147069 USB_DPRINTF_L4(DPRINT_IN_PIPE, bulkin->pipe_lh, 61560b08185Syz147069 "keyspan_bulkin_cb_usa19hs: len=%d" 61660b08185Syz147069 " cr=%d flags=%x baud=%x", 61760b08185Syz147069 data_len, cr, req->bulk_cb_flags, kp->kp_baud); 61860b08185Syz147069 61960b08185Syz147069 /* put data on the read queue */ 62060b08185Syz147069 if ((data_len > 0) && (kp->kp_state != KEYSPAN_PORT_CLOSED) && 62160b08185Syz147069 (cr == USB_CR_OK)) { 622*c138f478Syz147069 uchar_t status = data->b_rptr[0]; 623*c138f478Syz147069 uchar_t err = 0; 624*c138f478Syz147069 mblk_t *mp; 62560b08185Syz147069 /* 626*c138f478Syz147069 * According to Keyspan spec, if 0x80 bit is clear, there is 627*c138f478Syz147069 * only one status byte at the head of the data buf; if 0x80 bit 628*c138f478Syz147069 * set, then data buf contains alternate status and data bytes; 629*c138f478Syz147069 * In the first case, only OVERRUN err can exist; In the second 630*c138f478Syz147069 * case, there are four kinds of err bits may appear in status. 63160b08185Syz147069 */ 632*c138f478Syz147069 633*c138f478Syz147069 /* if 0x80 bit AND overrun bit are clear, just send up data */ 634*c138f478Syz147069 if (!(status & 0x80) && !(status & RXERROR_OVERRUN)) { 63560b08185Syz147069 USB_DPRINTF_L4(DPRINT_IN_PIPE, bulkin->pipe_lh, 63660b08185Syz147069 "keyspan_bulkin_cb_usa19hs: len=%d", 63760b08185Syz147069 data_len); 63860b08185Syz147069 639*c138f478Syz147069 /* Get rid of the first status byte and send up data */ 64060b08185Syz147069 data->b_rptr++; 64160b08185Syz147069 data_len--; 64260b08185Syz147069 if (data_len > 0) { 64360b08185Syz147069 keyspan_put_tail(&kp->kp_rx_mp, data); 64460b08185Syz147069 64560b08185Syz147069 /* 64660b08185Syz147069 * the data will not be freed and 64760b08185Syz147069 * will be sent up later. 64860b08185Syz147069 */ 64960b08185Syz147069 req->bulk_data = NULL; 65060b08185Syz147069 } 651*c138f478Syz147069 } else if (!(status & 0x80)) { 652*c138f478Syz147069 /* If 0x80 bit is clear and overrun bit is set */ 653*c138f478Syz147069 USB_DPRINTF_L2(DPRINT_IN_PIPE, bulkin->pipe_lh, 654*c138f478Syz147069 "keyspan_bulkin_cb_usa19hs: usb xfer is OK," 655*c138f478Syz147069 " but there is overrun err in serial xfer"); 65660b08185Syz147069 657*c138f478Syz147069 keyspan_parse_status(&status, &err); 658*c138f478Syz147069 mutex_exit(&kp->kp_mutex); 659*c138f478Syz147069 if ((mp = allocb(2, BPRI_HI)) == NULL) { 660*c138f478Syz147069 USB_DPRINTF_L2(DPRINT_IN_PIPE, kp->kp_lh, 661*c138f478Syz147069 "keyspan_bulkin_cb_usa19hs: allocb failed"); 662*c138f478Syz147069 mutex_enter(&kp->kp_mutex); 66360b08185Syz147069 664*c138f478Syz147069 return (0); 665*c138f478Syz147069 } 666*c138f478Syz147069 DB_TYPE(mp) = M_BREAK; 667*c138f478Syz147069 *mp->b_wptr++ = err; 668*c138f478Syz147069 *mp->b_wptr++ = status; 669*c138f478Syz147069 mutex_enter(&kp->kp_mutex); 670*c138f478Syz147069 671*c138f478Syz147069 /* Add to the received list; Send up the err code. */ 672*c138f478Syz147069 keyspan_put_tail(&kp->kp_rx_mp, mp); 673*c138f478Syz147069 674*c138f478Syz147069 /* 675*c138f478Syz147069 * Don't send up the first byte because 676*c138f478Syz147069 * it is a status byte. 677*c138f478Syz147069 */ 678*c138f478Syz147069 data->b_rptr++; 679*c138f478Syz147069 data_len--; 680*c138f478Syz147069 if (data_len > 0) { 681*c138f478Syz147069 keyspan_put_tail(&kp->kp_rx_mp, data); 682*c138f478Syz147069 683*c138f478Syz147069 /* 684*c138f478Syz147069 * the data will not be freed and 685*c138f478Syz147069 * will be sent up later. 686*c138f478Syz147069 */ 687*c138f478Syz147069 req->bulk_data = NULL; 688*c138f478Syz147069 } 689*c138f478Syz147069 } else { /* 0x80 bit set, there are some errs in the data */ 690*c138f478Syz147069 USB_DPRINTF_L2(DPRINT_IN_PIPE, bulkin->pipe_lh, 691*c138f478Syz147069 "keyspan_bulkin_cb_usa19hs: usb xfer is OK," 692*c138f478Syz147069 " but there are errs in serial xfer"); 693*c138f478Syz147069 /* 694*c138f478Syz147069 * Usually, there are at least two bytes, 695*c138f478Syz147069 * one status and one data. 696*c138f478Syz147069 */ 69760b08185Syz147069 if (data_len > 1) { 69860b08185Syz147069 int i = 0; 69960b08185Syz147069 int j = 1; 700*c138f478Syz147069 /* 701*c138f478Syz147069 * In this case, there might be multi status 702*c138f478Syz147069 * bytes. Parse each status byte and move the 703*c138f478Syz147069 * data bytes together. 704*c138f478Syz147069 */ 70560b08185Syz147069 for (j = 1; j < data_len; j += 2) { 706*c138f478Syz147069 status = data->b_rptr[j-1]; 707*c138f478Syz147069 keyspan_parse_status(&status, &err); 708*c138f478Syz147069 709*c138f478Syz147069 /* move the data togeter */ 71060b08185Syz147069 data->b_rptr[i] = data->b_rptr[j]; 71160b08185Syz147069 i++; 71260b08185Syz147069 } 71360b08185Syz147069 data->b_wptr = data->b_rptr + i; 714*c138f478Syz147069 } else { /* There are only one byte in incoming buf */ 715*c138f478Syz147069 keyspan_parse_status(&status, &err); 716*c138f478Syz147069 } 717*c138f478Syz147069 mutex_exit(&kp->kp_mutex); 718*c138f478Syz147069 if ((mp = allocb(2, BPRI_HI)) == NULL) { 719*c138f478Syz147069 USB_DPRINTF_L2(DPRINT_IN_PIPE, kp->kp_lh, 720*c138f478Syz147069 "keyspan_bulkin_cb_usa19hs: allocb failed"); 721*c138f478Syz147069 mutex_enter(&kp->kp_mutex); 72260b08185Syz147069 723*c138f478Syz147069 return (0); 724*c138f478Syz147069 } 725*c138f478Syz147069 DB_TYPE(mp) = M_BREAK; 726*c138f478Syz147069 *mp->b_wptr++ = err; 727*c138f478Syz147069 if (data_len > 2) { 728*c138f478Syz147069 /* 729*c138f478Syz147069 * There are multiple status bytes in this case. 730*c138f478Syz147069 * Use err as status character since err is got 731*c138f478Syz147069 * by or in all status bytes. 732*c138f478Syz147069 */ 733*c138f478Syz147069 *mp->b_wptr++ = err; 734*c138f478Syz147069 } else { 735*c138f478Syz147069 *mp->b_wptr++ = status; 736*c138f478Syz147069 } 737*c138f478Syz147069 mutex_enter(&kp->kp_mutex); 738*c138f478Syz147069 739*c138f478Syz147069 /* Add to the received list; Send up the err code. */ 740*c138f478Syz147069 keyspan_put_tail(&kp->kp_rx_mp, mp); 741*c138f478Syz147069 742*c138f478Syz147069 if (data_len > 1) { 743*c138f478Syz147069 data_len = data->b_wptr - data->b_rptr; 744*c138f478Syz147069 keyspan_put_tail(&kp->kp_rx_mp, data); 74560b08185Syz147069 /* 74660b08185Syz147069 * The data will not be freed and 74760b08185Syz147069 * will be sent up later. 74860b08185Syz147069 */ 74960b08185Syz147069 req->bulk_data = NULL; 750*c138f478Syz147069 } 751*c138f478Syz147069 } 752*c138f478Syz147069 } else { /* usb error happened, so don't send up data */ 75360b08185Syz147069 data_len = 0; 75460b08185Syz147069 USB_DPRINTF_L4(DPRINT_IN_PIPE, bulkin->pipe_lh, 75560b08185Syz147069 "keyspan_bulkin_cb_usa19hs: error happened, len=%d, " 75660b08185Syz147069 "cr=0x%x, cb_flags=0x%x", data_len, cr, req->bulk_cb_flags); 757*c138f478Syz147069 } 75860b08185Syz147069 if (kp->kp_state != KEYSPAN_PORT_OPEN) { 75960b08185Syz147069 kp->kp_no_more_reads = B_TRUE; 76060b08185Syz147069 } 76160b08185Syz147069 76260b08185Syz147069 return (data_len); 76360b08185Syz147069 } 76460b08185Syz147069 765*c138f478Syz147069 76660b08185Syz147069 /* 76760b08185Syz147069 * pipe callbacks 76860b08185Syz147069 * -------------- 76960b08185Syz147069 * 77060b08185Syz147069 * bulk in common callback for usa49 model 77160b08185Syz147069 */ 77260b08185Syz147069 /*ARGSUSED*/ 77360b08185Syz147069 int 77460b08185Syz147069 keyspan_bulkin_cb_usa49(usb_pipe_handle_t pipe, usb_bulk_req_t *req) 77560b08185Syz147069 { 77660b08185Syz147069 keyspan_port_t *kp = (keyspan_port_t *)req->bulk_client_private; 77760b08185Syz147069 keyspan_pipe_t *bulkin = &kp->kp_datain_pipe; 77860b08185Syz147069 mblk_t *data = req->bulk_data; 77960b08185Syz147069 uint_t cr = req->bulk_completion_reason; 78060b08185Syz147069 int data_len; 78160b08185Syz147069 78260b08185Syz147069 ASSERT(mutex_owned(&kp->kp_mutex)); 78360b08185Syz147069 78460b08185Syz147069 data_len = (data) ? MBLKL(data) : 0; 78560b08185Syz147069 78660b08185Syz147069 USB_DPRINTF_L4(DPRINT_IN_PIPE, bulkin->pipe_lh, 78760b08185Syz147069 "keyspan_bulkin_cb_usa49: len=%d" 78860b08185Syz147069 " cr=%d flags=%x", data_len, cr, req->bulk_cb_flags); 78960b08185Syz147069 79060b08185Syz147069 /* put data on the read queue */ 79160b08185Syz147069 if ((data_len > 0) && (kp->kp_state != KEYSPAN_PORT_CLOSED) && 79260b08185Syz147069 (cr == USB_CR_OK)) { 793*c138f478Syz147069 uchar_t status = data->b_rptr[0]; 794*c138f478Syz147069 uchar_t err = 0; 795*c138f478Syz147069 mblk_t *mp; 79660b08185Syz147069 /* 797*c138f478Syz147069 * According to Keyspan spec, if 0x80 bit is clear, there is 798*c138f478Syz147069 * only one status byte at the head of the data buf; if 0x80 bit 799*c138f478Syz147069 * set, then data buf contains alternate status and data bytes; 800*c138f478Syz147069 * In the first case, only OVERRUN err can exist; In the second 801*c138f478Syz147069 * case, there are four kinds of err bits may appear in status. 80260b08185Syz147069 */ 80360b08185Syz147069 804*c138f478Syz147069 /* if 0x80 bit AND overrun bit are clear, just send up data */ 805*c138f478Syz147069 if (!(status & 0x80) && !(status & RXERROR_OVERRUN)) { 806*c138f478Syz147069 USB_DPRINTF_L4(DPRINT_IN_PIPE, bulkin->pipe_lh, 807*c138f478Syz147069 "keyspan_bulkin_cb_usa49: len=%d", 808*c138f478Syz147069 data_len); 809*c138f478Syz147069 810*c138f478Syz147069 /* Get rid of the first status byte and send up data */ 81160b08185Syz147069 data->b_rptr++; 81260b08185Syz147069 data_len--; 81360b08185Syz147069 if (data_len > 0) { 81460b08185Syz147069 keyspan_put_tail(&kp->kp_rx_mp, data); 81560b08185Syz147069 81660b08185Syz147069 /* 817*c138f478Syz147069 * the data will not be freed and 81860b08185Syz147069 * will be sent up later. 81960b08185Syz147069 */ 82060b08185Syz147069 req->bulk_data = NULL; 82160b08185Syz147069 } 822*c138f478Syz147069 } else if (!(status & 0x80)) { 823*c138f478Syz147069 /* If 0x80 bit is clear and overrun bit is set */ 824*c138f478Syz147069 USB_DPRINTF_L2(DPRINT_IN_PIPE, bulkin->pipe_lh, 825*c138f478Syz147069 "keyspan_bulkin_cb_usa49: usb xfer is OK," 826*c138f478Syz147069 " but there is overrun err in serial xfer"); 827*c138f478Syz147069 828*c138f478Syz147069 keyspan_parse_status(&status, &err); 829*c138f478Syz147069 mutex_exit(&kp->kp_mutex); 830*c138f478Syz147069 if ((mp = allocb(2, BPRI_HI)) == NULL) { 831*c138f478Syz147069 USB_DPRINTF_L2(DPRINT_IN_PIPE, kp->kp_lh, 832*c138f478Syz147069 "keyspan_bulkin_cb_usa49: allocb failed"); 833*c138f478Syz147069 mutex_enter(&kp->kp_mutex); 834*c138f478Syz147069 835*c138f478Syz147069 return (0); 836*c138f478Syz147069 } 837*c138f478Syz147069 DB_TYPE(mp) = M_BREAK; 838*c138f478Syz147069 *mp->b_wptr++ = err; 839*c138f478Syz147069 *mp->b_wptr++ = status; 840*c138f478Syz147069 mutex_enter(&kp->kp_mutex); 841*c138f478Syz147069 842*c138f478Syz147069 /* Add to the received list; Send up the err code. */ 843*c138f478Syz147069 keyspan_put_tail(&kp->kp_rx_mp, mp); 844*c138f478Syz147069 845*c138f478Syz147069 /* 846*c138f478Syz147069 * Don't send up the first byte because 847*c138f478Syz147069 * it is a status byte. 848*c138f478Syz147069 */ 849*c138f478Syz147069 data->b_rptr++; 850*c138f478Syz147069 data_len--; 851*c138f478Syz147069 if (data_len > 0) { 852*c138f478Syz147069 keyspan_put_tail(&kp->kp_rx_mp, data); 853*c138f478Syz147069 854*c138f478Syz147069 /* 855*c138f478Syz147069 * the data will not be freed and 856*c138f478Syz147069 * will be sent up later. 857*c138f478Syz147069 */ 858*c138f478Syz147069 req->bulk_data = NULL; 859*c138f478Syz147069 } 860*c138f478Syz147069 } else { /* 0x80 bit set, there are some errs in the data */ 861*c138f478Syz147069 USB_DPRINTF_L2(DPRINT_IN_PIPE, bulkin->pipe_lh, 862*c138f478Syz147069 "keyspan_bulkin_cb_usa49: usb xfer is OK," 863*c138f478Syz147069 " but there are errs in serial xfer"); 864*c138f478Syz147069 /* 865*c138f478Syz147069 * Usually, there are at least two bytes, 866*c138f478Syz147069 * one status and one data. 867*c138f478Syz147069 */ 86860b08185Syz147069 if (data_len > 1) { 86960b08185Syz147069 int i = 0; 87060b08185Syz147069 int j = 1; 871*c138f478Syz147069 /* 872*c138f478Syz147069 * In this case, there might be multi status 873*c138f478Syz147069 * bytes. Parse each status byte and move the 874*c138f478Syz147069 * data bytes together. 875*c138f478Syz147069 */ 87660b08185Syz147069 for (j = 1; j < data_len; j += 2) { 877*c138f478Syz147069 status = data->b_rptr[j-1]; 878*c138f478Syz147069 keyspan_parse_status(&status, &err); 879*c138f478Syz147069 880*c138f478Syz147069 /* move the data togeter */ 88160b08185Syz147069 data->b_rptr[i] = data->b_rptr[j]; 88260b08185Syz147069 i++; 88360b08185Syz147069 } 88460b08185Syz147069 data->b_wptr = data->b_rptr + i; 885*c138f478Syz147069 } else { /* There are only one byte in incoming buf */ 886*c138f478Syz147069 keyspan_parse_status(&status, &err); 887*c138f478Syz147069 } 888*c138f478Syz147069 mutex_exit(&kp->kp_mutex); 889*c138f478Syz147069 if ((mp = allocb(2, BPRI_HI)) == NULL) { 890*c138f478Syz147069 USB_DPRINTF_L2(DPRINT_IN_PIPE, kp->kp_lh, 891*c138f478Syz147069 "keyspan_bulkin_cb_usa49: allocb failed"); 892*c138f478Syz147069 mutex_enter(&kp->kp_mutex); 89360b08185Syz147069 894*c138f478Syz147069 return (0); 895*c138f478Syz147069 } 896*c138f478Syz147069 DB_TYPE(mp) = M_BREAK; 897*c138f478Syz147069 *mp->b_wptr++ = err; 898*c138f478Syz147069 if (data_len > 2) { 899*c138f478Syz147069 /* 900*c138f478Syz147069 * There are multiple status bytes in this case. 901*c138f478Syz147069 * Use err as status character since err is got 902*c138f478Syz147069 * by or in all status bytes. 903*c138f478Syz147069 */ 904*c138f478Syz147069 *mp->b_wptr++ = err; 905*c138f478Syz147069 } else { 906*c138f478Syz147069 *mp->b_wptr++ = status; 907*c138f478Syz147069 } 908*c138f478Syz147069 mutex_enter(&kp->kp_mutex); 909*c138f478Syz147069 910*c138f478Syz147069 /* Add to the received list; Send up the err code. */ 911*c138f478Syz147069 keyspan_put_tail(&kp->kp_rx_mp, mp); 912*c138f478Syz147069 913*c138f478Syz147069 if (data_len > 1) { 914*c138f478Syz147069 data_len = data->b_wptr - data->b_rptr; 915*c138f478Syz147069 keyspan_put_tail(&kp->kp_rx_mp, data); 91660b08185Syz147069 /* 91760b08185Syz147069 * The data will not be freed and 91860b08185Syz147069 * will be sent up later. 91960b08185Syz147069 */ 92060b08185Syz147069 req->bulk_data = NULL; 92160b08185Syz147069 } 92260b08185Syz147069 } 92360b08185Syz147069 } else { 92460b08185Syz147069 /* usb error happened, so don't send up data */ 92560b08185Syz147069 data_len = 0; 92660b08185Syz147069 USB_DPRINTF_L2(DPRINT_IN_PIPE, bulkin->pipe_lh, 92760b08185Syz147069 "keyspan_bulkin_cb_usa49: port_state=%d" 92860b08185Syz147069 " b_rptr[0]=%c", kp->kp_state, data->b_rptr[0]); 929*c138f478Syz147069 } 93060b08185Syz147069 if (kp->kp_state != KEYSPAN_PORT_OPEN) { 93160b08185Syz147069 kp->kp_no_more_reads = B_TRUE; 93260b08185Syz147069 } 93360b08185Syz147069 93460b08185Syz147069 return (data_len); 93560b08185Syz147069 } 936*c138f478Syz147069 93760b08185Syz147069 93860b08185Syz147069 /* 93960b08185Syz147069 * pipe callbacks 94060b08185Syz147069 * -------------- 94160b08185Syz147069 * 94260b08185Syz147069 * bulk in common callback 94360b08185Syz147069 */ 94460b08185Syz147069 /*ARGSUSED*/ 94560b08185Syz147069 void 94660b08185Syz147069 keyspan_bulkin_cb(usb_pipe_handle_t pipe, usb_bulk_req_t *req) 94760b08185Syz147069 { 94860b08185Syz147069 keyspan_port_t *kp = (keyspan_port_t *)req->bulk_client_private; 94960b08185Syz147069 keyspan_state_t *ksp = kp->kp_ksp; 95060b08185Syz147069 int data_len; 95160b08185Syz147069 boolean_t no_more_reads = B_FALSE; 95260b08185Syz147069 95360b08185Syz147069 USB_DPRINTF_L4(DPRINT_IN_PIPE, (&kp->kp_datain_pipe)->pipe_lh, 95460b08185Syz147069 "keyspan_bulkin_cb"); 95560b08185Syz147069 95660b08185Syz147069 mutex_enter(&kp->kp_mutex); 95760b08185Syz147069 95860b08185Syz147069 /* put data on the read queue */ 95960b08185Syz147069 switch (ksp->ks_dev_spec.id_product) { 96060b08185Syz147069 case KEYSPAN_USA19HS_PID: 96160b08185Syz147069 data_len = keyspan_bulkin_cb_usa19hs(pipe, req); 96260b08185Syz147069 96360b08185Syz147069 break; 96460b08185Syz147069 965*c138f478Syz147069 96660b08185Syz147069 case KEYSPAN_USA49WLC_PID: 96760b08185Syz147069 data_len = keyspan_bulkin_cb_usa49(pipe, req); 96860b08185Syz147069 96960b08185Syz147069 break; 970*c138f478Syz147069 97160b08185Syz147069 default: 97260b08185Syz147069 USB_DPRINTF_L2(DPRINT_IN_PIPE, (&kp->kp_datain_pipe)->pipe_lh, 97360b08185Syz147069 "keyspan_bulkin_cb:" 97460b08185Syz147069 "the device's product id can't be recognized"); 97560b08185Syz147069 mutex_exit(&kp->kp_mutex); 97660b08185Syz147069 97760b08185Syz147069 return; 97860b08185Syz147069 } 97960b08185Syz147069 98060b08185Syz147069 no_more_reads = kp->kp_no_more_reads; 98160b08185Syz147069 98260b08185Syz147069 mutex_exit(&kp->kp_mutex); 98360b08185Syz147069 98460b08185Syz147069 usb_free_bulk_req(req); 98560b08185Syz147069 98660b08185Syz147069 /* kick off another read unless indicated otherwise */ 98760b08185Syz147069 if (!no_more_reads) { 98860b08185Syz147069 (void) keyspan_receive_data(&kp->kp_datain_pipe, 98960b08185Syz147069 kp->kp_read_len, kp); 99060b08185Syz147069 } 99160b08185Syz147069 99260b08185Syz147069 /* setup rx callback for this port */ 99360b08185Syz147069 if (data_len > 0) { 99460b08185Syz147069 kp->kp_cb.cb_rx(kp->kp_cb.cb_arg); 99560b08185Syz147069 } 99660b08185Syz147069 } 99760b08185Syz147069 99860b08185Syz147069 /* 99960b08185Syz147069 * pipe callbacks 100060b08185Syz147069 * -------------- 100160b08185Syz147069 * 100260b08185Syz147069 * bulk in status callback for usa19hs model 100360b08185Syz147069 */ 100460b08185Syz147069 /*ARGSUSED*/ 100560b08185Syz147069 void 100660b08185Syz147069 keyspan_status_cb_usa19hs(usb_pipe_handle_t pipe, usb_bulk_req_t *req) 100760b08185Syz147069 { 100860b08185Syz147069 keyspan_state_t *ksp = (keyspan_state_t *)req->bulk_client_private; 100960b08185Syz147069 keyspan_pipe_t *bulkin = &ksp->ks_statin_pipe; 101060b08185Syz147069 mblk_t *data = req->bulk_data; 101160b08185Syz147069 usb_cr_t cr = req->bulk_completion_reason; 101260b08185Syz147069 int data_len; 101360b08185Syz147069 101460b08185Syz147069 data_len = (data) ? MBLKL(data) : 0; 101560b08185Syz147069 101660b08185Syz147069 USB_DPRINTF_L4(DPRINT_IN_PIPE, bulkin->pipe_lh, 101760b08185Syz147069 "keyspan_status_cb_usa19hs: len=%d" 101860b08185Syz147069 " cr=%d flags=%x", data_len, cr, req->bulk_cb_flags); 101960b08185Syz147069 102060b08185Syz147069 /* put data on the read queue */ 102160b08185Syz147069 if ((data_len == 14) && (cr == USB_CR_OK)) { 102260b08185Syz147069 keyspan_port_t *kp = &ksp->ks_ports[0]; 102360b08185Syz147069 keyspan_usa19hs_port_status_msg_t *status_msg = 102460b08185Syz147069 &(kp->kp_status_msg.usa19hs); 102560b08185Syz147069 102660b08185Syz147069 mutex_enter(&kp->kp_mutex); 102760b08185Syz147069 bcopy(data->b_rptr, status_msg, data_len); 102860b08185Syz147069 102960b08185Syz147069 if (status_msg->controlResponse) { 103060b08185Syz147069 kp->kp_status_flag |= KEYSPAN_PORT_CTRLRESP; 103160b08185Syz147069 } else { 103260b08185Syz147069 kp->kp_status_flag &= ~KEYSPAN_PORT_CTRLRESP; 103360b08185Syz147069 } 103460b08185Syz147069 103560b08185Syz147069 if (status_msg->portState & PORTSTATE_ENABLED) { 103660b08185Syz147069 kp->kp_status_flag |= KEYSPAN_PORT_ENABLE; 103760b08185Syz147069 } else { 103860b08185Syz147069 kp->kp_status_flag &= ~KEYSPAN_PORT_ENABLE; 103960b08185Syz147069 } 104060b08185Syz147069 104160b08185Syz147069 if (status_msg->portState & PORTSTATE_TXBREAK) { 104260b08185Syz147069 kp->kp_status_flag |= KEYSPAN_PORT_TXBREAK; 104360b08185Syz147069 } else { 104460b08185Syz147069 kp->kp_status_flag &= ~KEYSPAN_PORT_TXBREAK; 104560b08185Syz147069 } 104660b08185Syz147069 104760b08185Syz147069 if (status_msg->rxBreak) { 104860b08185Syz147069 kp->kp_status_flag |= KEYSPAN_PORT_RXBREAK; 104960b08185Syz147069 } else { 105060b08185Syz147069 kp->kp_status_flag &= ~KEYSPAN_PORT_RXBREAK; 105160b08185Syz147069 } 105260b08185Syz147069 105360b08185Syz147069 if (status_msg->portState & PORTSTATE_LOOPBACK) { 105460b08185Syz147069 kp->kp_status_flag |= KEYSPAN_PORT_LOOPBACK; 105560b08185Syz147069 } else { 105660b08185Syz147069 kp->kp_status_flag &= ~KEYSPAN_PORT_LOOPBACK; 105760b08185Syz147069 } 105860b08185Syz147069 105960b08185Syz147069 /* if msr status changed, then invoke status callback */ 106060b08185Syz147069 if (status_msg->msr & USA_MSR_dCTS || 106160b08185Syz147069 status_msg->msr & USA_MSR_dDSR || 106260b08185Syz147069 status_msg->msr & USA_MSR_dRI || 106360b08185Syz147069 status_msg->msr & USA_MSR_dDCD) { 106460b08185Syz147069 106560b08185Syz147069 mutex_exit(&kp->kp_mutex); 106660b08185Syz147069 kp->kp_cb.cb_status(kp->kp_cb.cb_arg); 106760b08185Syz147069 } else { 106860b08185Syz147069 mutex_exit(&kp->kp_mutex); 106960b08185Syz147069 } 107060b08185Syz147069 } else { 107160b08185Syz147069 107260b08185Syz147069 USB_DPRINTF_L2(DPRINT_IN_PIPE, bulkin->pipe_lh, 107360b08185Syz147069 "keyspan_status_cb_usa19hs: get status failed, cr=%d" 107460b08185Syz147069 " data_len=%d", cr, data_len); 107560b08185Syz147069 } 107660b08185Syz147069 } 107760b08185Syz147069 1078*c138f478Syz147069 107960b08185Syz147069 /* 108060b08185Syz147069 * pipe callbacks 108160b08185Syz147069 * -------------- 108260b08185Syz147069 * 108360b08185Syz147069 * bulk in status callback for usa49 model 108460b08185Syz147069 */ 108560b08185Syz147069 /*ARGSUSED*/ 108660b08185Syz147069 void 108760b08185Syz147069 keyspan_status_cb_usa49(usb_pipe_handle_t pipe, usb_bulk_req_t *req) 108860b08185Syz147069 { 108960b08185Syz147069 keyspan_state_t *ksp = (keyspan_state_t *)req->bulk_client_private; 109060b08185Syz147069 keyspan_pipe_t *bulkin = &ksp->ks_statin_pipe; 109160b08185Syz147069 mblk_t *data = req->bulk_data; 109260b08185Syz147069 uint_t cr = req->bulk_completion_reason; 109360b08185Syz147069 int data_len; 109460b08185Syz147069 109560b08185Syz147069 data_len = (data) ? MBLKL(data) : 0; 109660b08185Syz147069 109760b08185Syz147069 USB_DPRINTF_L4(DPRINT_IN_PIPE, bulkin->pipe_lh, 109860b08185Syz147069 "keyspan_status_cb_usa49: len=%d" 109960b08185Syz147069 " cr=%d flags=%x", data_len, cr, req->bulk_cb_flags); 110060b08185Syz147069 110160b08185Syz147069 /* put data on the read queue */ 110260b08185Syz147069 if ((data_len == 11) && (cr == USB_CR_OK)) { 110360b08185Syz147069 keyspan_usa49_port_status_msg_t status_msg; 110460b08185Syz147069 keyspan_port_t *cur_kp; 110560b08185Syz147069 keyspan_usa49_port_status_msg_t *kp_status_msg; 110660b08185Syz147069 boolean_t need_cb = B_FALSE; 110760b08185Syz147069 110860b08185Syz147069 bcopy(data->b_rptr, &status_msg, data_len); 110960b08185Syz147069 if (status_msg.portNumber >= ksp->ks_dev_spec.port_cnt) { 111060b08185Syz147069 111160b08185Syz147069 return; 111260b08185Syz147069 } 111360b08185Syz147069 cur_kp = &ksp->ks_ports[status_msg.portNumber]; 111460b08185Syz147069 kp_status_msg = &(cur_kp->kp_status_msg.usa49); 111560b08185Syz147069 111660b08185Syz147069 mutex_enter(&cur_kp->kp_mutex); 111760b08185Syz147069 111860b08185Syz147069 /* if msr status changed, then need invoke status callback */ 111960b08185Syz147069 if (status_msg.cts != kp_status_msg->cts || 112060b08185Syz147069 status_msg.dsr != kp_status_msg->dsr || 112160b08185Syz147069 status_msg.ri != kp_status_msg->ri || 112260b08185Syz147069 status_msg.dcd != kp_status_msg->dcd) { 112360b08185Syz147069 112460b08185Syz147069 need_cb = B_TRUE; 112560b08185Syz147069 } 112660b08185Syz147069 112760b08185Syz147069 bcopy(&status_msg, kp_status_msg, data_len); 112860b08185Syz147069 112960b08185Syz147069 if (kp_status_msg->controlResponse) { 113060b08185Syz147069 cur_kp->kp_status_flag |= KEYSPAN_PORT_CTRLRESP; 113160b08185Syz147069 } else { 113260b08185Syz147069 cur_kp->kp_status_flag &= ~KEYSPAN_PORT_CTRLRESP; 113360b08185Syz147069 } 113460b08185Syz147069 113560b08185Syz147069 if (!kp_status_msg->rxEnabled) { 113660b08185Syz147069 cur_kp->kp_status_flag |= KEYSPAN_PORT_RXBREAK; 113760b08185Syz147069 } else { 113860b08185Syz147069 cur_kp->kp_status_flag &= ~KEYSPAN_PORT_RXBREAK; 113960b08185Syz147069 } 114060b08185Syz147069 114160b08185Syz147069 mutex_exit(&cur_kp->kp_mutex); 114260b08185Syz147069 114360b08185Syz147069 if (need_cb) { 114460b08185Syz147069 114560b08185Syz147069 cur_kp->kp_cb.cb_status(cur_kp->kp_cb.cb_arg); 114660b08185Syz147069 } 114760b08185Syz147069 } else { 114860b08185Syz147069 114960b08185Syz147069 USB_DPRINTF_L2(DPRINT_IN_PIPE, bulkin->pipe_lh, 115060b08185Syz147069 "keyspan_status_cb_usa49: get status failed, cr=%d" 115160b08185Syz147069 " data_len=%d", cr, data_len); 115260b08185Syz147069 } 115360b08185Syz147069 } 1154*c138f478Syz147069 115560b08185Syz147069 115660b08185Syz147069 /* 115760b08185Syz147069 * pipe callbacks 115860b08185Syz147069 * -------------- 115960b08185Syz147069 * 116060b08185Syz147069 * bulk in callback for status receiving 116160b08185Syz147069 */ 116260b08185Syz147069 /*ARGSUSED*/ 116360b08185Syz147069 void 116460b08185Syz147069 keyspan_status_cb(usb_pipe_handle_t pipe, usb_bulk_req_t *req) 116560b08185Syz147069 { 116660b08185Syz147069 keyspan_state_t *ksp = (keyspan_state_t *)req->bulk_client_private; 116760b08185Syz147069 usb_cr_t cr = req->bulk_completion_reason; 116860b08185Syz147069 116960b08185Syz147069 USB_DPRINTF_L4(DPRINT_IN_PIPE, (&ksp->ks_statin_pipe)->pipe_lh, 117060b08185Syz147069 "keyspan_status_cb"); 117160b08185Syz147069 117260b08185Syz147069 /* put data on the read queue */ 117360b08185Syz147069 switch (ksp->ks_dev_spec.id_product) { 117460b08185Syz147069 case KEYSPAN_USA19HS_PID: 117560b08185Syz147069 keyspan_status_cb_usa19hs(pipe, req); 117660b08185Syz147069 117760b08185Syz147069 break; 117860b08185Syz147069 1179*c138f478Syz147069 118060b08185Syz147069 case KEYSPAN_USA49WLC_PID: 118160b08185Syz147069 keyspan_status_cb_usa49(pipe, req); 118260b08185Syz147069 118360b08185Syz147069 break; 1184*c138f478Syz147069 118560b08185Syz147069 default: 118660b08185Syz147069 USB_DPRINTF_L2(DPRINT_IN_PIPE, 118760b08185Syz147069 (&ksp->ks_statin_pipe)->pipe_lh, "keyspan_status_cb:" 118860b08185Syz147069 "the device's product id can't be recognized"); 118960b08185Syz147069 119060b08185Syz147069 return; 119160b08185Syz147069 } 119260b08185Syz147069 119360b08185Syz147069 usb_free_bulk_req(req); 119460b08185Syz147069 119560b08185Syz147069 /* kick off another read to receive status */ 119660b08185Syz147069 if ((cr != USB_CR_FLUSHED) && (cr != USB_CR_DEV_NOT_RESP) && 119760b08185Syz147069 keyspan_dev_is_online(ksp)) { 119860b08185Syz147069 if (keyspan_receive_status(ksp) != USB_SUCCESS) { 119960b08185Syz147069 USB_DPRINTF_L2(DPRINT_IN_PIPE, 120060b08185Syz147069 (&ksp->ks_statin_pipe)->pipe_lh, 120160b08185Syz147069 "keyspan_status_cb:" 120260b08185Syz147069 "receive status can't be restarted."); 120360b08185Syz147069 } 120460b08185Syz147069 } else { 120560b08185Syz147069 USB_DPRINTF_L2(DPRINT_IN_PIPE, 120660b08185Syz147069 (&ksp->ks_statin_pipe)->pipe_lh, "keyspan_status_cb:" 120760b08185Syz147069 "get status failed: cr=%d", cr); 120860b08185Syz147069 } 120960b08185Syz147069 } 121060b08185Syz147069 121160b08185Syz147069 /* 121260b08185Syz147069 * Submit data read request (asynchronous). If this function returns 121360b08185Syz147069 * USB_SUCCESS, pipe is acquired and request is sent, otherwise req is free. 121460b08185Syz147069 */ 121560b08185Syz147069 int 121660b08185Syz147069 keyspan_receive_data(keyspan_pipe_t *bulkin, int len, void *cb_arg) 121760b08185Syz147069 { 121860b08185Syz147069 keyspan_state_t *ksp = bulkin->pipe_ksp; 121960b08185Syz147069 usb_bulk_req_t *br; 122060b08185Syz147069 int rval; 122160b08185Syz147069 122260b08185Syz147069 USB_DPRINTF_L4(DPRINT_IN_PIPE, bulkin->pipe_lh, "keyspan_receive_data:" 122360b08185Syz147069 "len=%d", len); 122460b08185Syz147069 122560b08185Syz147069 ASSERT(!mutex_owned(&bulkin->pipe_mutex)); 122660b08185Syz147069 122760b08185Syz147069 br = usb_alloc_bulk_req(ksp->ks_dip, len, USB_FLAGS_SLEEP); 122860b08185Syz147069 br->bulk_len = len; 122960b08185Syz147069 123060b08185Syz147069 /* No timeout, just wait for data */ 123160b08185Syz147069 br->bulk_timeout = 0; 123260b08185Syz147069 br->bulk_client_private = cb_arg; 123360b08185Syz147069 br->bulk_attributes = USB_ATTRS_SHORT_XFER_OK | USB_ATTRS_AUTOCLEARING; 123460b08185Syz147069 br->bulk_cb = keyspan_bulkin_cb; 123560b08185Syz147069 br->bulk_exc_cb = keyspan_bulkin_cb; 123660b08185Syz147069 123760b08185Syz147069 rval = usb_pipe_bulk_xfer(bulkin->pipe_handle, br, 0); 123860b08185Syz147069 if (rval != USB_SUCCESS) { 123960b08185Syz147069 usb_free_bulk_req(br); 124060b08185Syz147069 } 124160b08185Syz147069 USB_DPRINTF_L4(DPRINT_IN_PIPE, bulkin->pipe_lh, 124260b08185Syz147069 "keyspan_receive_data: rval = %d", rval); 124360b08185Syz147069 return (rval); 124460b08185Syz147069 } 124560b08185Syz147069 124660b08185Syz147069 /* 124760b08185Syz147069 * submit device status read request (asynchronous). 124860b08185Syz147069 */ 124960b08185Syz147069 int 125060b08185Syz147069 keyspan_receive_status(keyspan_state_t *ksp) 125160b08185Syz147069 { 125260b08185Syz147069 keyspan_pipe_t *bulkin = &ksp->ks_statin_pipe; 125360b08185Syz147069 usb_bulk_req_t *br; 125460b08185Syz147069 int rval; 125560b08185Syz147069 125660b08185Syz147069 USB_DPRINTF_L4(DPRINT_IN_PIPE, bulkin->pipe_lh, 125760b08185Syz147069 "keyspan_receive_status"); 125860b08185Syz147069 125960b08185Syz147069 ASSERT(!mutex_owned(&bulkin->pipe_mutex)); 126060b08185Syz147069 126160b08185Syz147069 br = usb_alloc_bulk_req(ksp->ks_dip, 32, USB_FLAGS_SLEEP); 126260b08185Syz147069 br->bulk_len = KEYSPAN_STATIN_MAX_LEN; 126360b08185Syz147069 126460b08185Syz147069 /* No timeout, just wait for data */ 126560b08185Syz147069 br->bulk_timeout = 0; 126660b08185Syz147069 br->bulk_client_private = (void *)ksp; 126760b08185Syz147069 br->bulk_attributes = USB_ATTRS_SHORT_XFER_OK | USB_ATTRS_AUTOCLEARING; 126860b08185Syz147069 br->bulk_cb = keyspan_status_cb; 126960b08185Syz147069 br->bulk_exc_cb = keyspan_status_cb; 127060b08185Syz147069 127160b08185Syz147069 rval = usb_pipe_bulk_xfer(bulkin->pipe_handle, br, 0); 127260b08185Syz147069 if (rval != USB_SUCCESS) { 127360b08185Syz147069 usb_free_bulk_req(br); 127460b08185Syz147069 } 127560b08185Syz147069 USB_DPRINTF_L4(DPRINT_IN_PIPE, bulkin->pipe_lh, 127660b08185Syz147069 "keyspan_receive_status: rval = %d", rval); 127760b08185Syz147069 return (rval); 127860b08185Syz147069 } 127960b08185Syz147069 128060b08185Syz147069 /* 128160b08185Syz147069 * submit data for transfer (asynchronous) 128260b08185Syz147069 * 128360b08185Syz147069 * if data was sent successfully, 'mpp' will be nulled to indicate 128460b08185Syz147069 * that mblk is consumed by USBA and no longer belongs to the caller. 128560b08185Syz147069 * 128660b08185Syz147069 * if this function returns USB_SUCCESS, pipe is acquired and request 128760b08185Syz147069 * is sent, otherwise pipe is free. 128860b08185Syz147069 */ 128960b08185Syz147069 int 129060b08185Syz147069 keyspan_send_data(keyspan_pipe_t *bulkout, mblk_t **mpp, void *cb_arg) 129160b08185Syz147069 { 129260b08185Syz147069 keyspan_state_t *ksp = bulkout->pipe_ksp; 129360b08185Syz147069 usb_bulk_req_t *br; 129460b08185Syz147069 int rval; 129560b08185Syz147069 129660b08185Syz147069 ASSERT(!mutex_owned(&bulkout->pipe_mutex)); 129760b08185Syz147069 USB_DPRINTF_L4(DPRINT_OUT_PIPE, bulkout->pipe_lh, 129860b08185Syz147069 "keyspan_send_data"); 129960b08185Syz147069 130060b08185Syz147069 br = usb_alloc_bulk_req(ksp->ks_dip, 0, USB_FLAGS_SLEEP); 130160b08185Syz147069 br->bulk_len = MBLKL(*mpp); 130260b08185Syz147069 br->bulk_data = *mpp; 130360b08185Syz147069 br->bulk_timeout = KEYSPAN_BULK_TIMEOUT; 130460b08185Syz147069 br->bulk_client_private = cb_arg; 130560b08185Syz147069 br->bulk_attributes = USB_ATTRS_AUTOCLEARING; 130660b08185Syz147069 br->bulk_cb = keyspan_bulkout_cb; 130760b08185Syz147069 br->bulk_exc_cb = keyspan_bulkout_cb; 130860b08185Syz147069 130960b08185Syz147069 USB_DPRINTF_L3(DPRINT_OUT_PIPE, bulkout->pipe_lh, "keyspan_send_data:" 131060b08185Syz147069 "bulk_len = %d", br->bulk_len); 131160b08185Syz147069 131260b08185Syz147069 rval = usb_pipe_bulk_xfer(bulkout->pipe_handle, br, 0); 131360b08185Syz147069 if (rval == USB_SUCCESS) { 131460b08185Syz147069 131560b08185Syz147069 /* data consumed. The mem will be released in bulkout_cb */ 131660b08185Syz147069 *mpp = NULL; 131760b08185Syz147069 } else { 131860b08185Syz147069 131960b08185Syz147069 /* 132060b08185Syz147069 * Don't free it in usb_free_bulk_req because it will 132160b08185Syz147069 * be linked in keyspan_put_head 132260b08185Syz147069 */ 132360b08185Syz147069 br->bulk_data = NULL; 132460b08185Syz147069 132560b08185Syz147069 usb_free_bulk_req(br); 132660b08185Syz147069 } 132760b08185Syz147069 USB_DPRINTF_L4(DPRINT_OUT_PIPE, bulkout->pipe_lh, 132860b08185Syz147069 "keyspan_send_data: rval = %d", rval); 132960b08185Syz147069 133060b08185Syz147069 return (rval); 133160b08185Syz147069 } 1332