⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 keyspan.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 3 页
字号:
static void	usa28_inack_callback(struct urb *urb){	dbg (__FUNCTION__);}static void	usa28_outcont_callback(struct urb *urb){	struct usb_serial_port *port;	struct keyspan_port_private *p_priv;	port = (struct usb_serial_port *) urb->context;	p_priv = (struct keyspan_port_private *)(port->private);	if (p_priv->resend_cont) {		dbg (__FUNCTION__ " sending setup");		keyspan_usa28_send_setup(port->serial, port);	}}static void	usa28_instat_callback(struct urb *urb){	int					err;	unsigned char 				*data = urb->transfer_buffer;	keyspan_usa28_portStatusMessage		*msg;	struct usb_serial			*serial;	struct usb_serial_port			*port;	struct keyspan_port_private	 	*p_priv;	int old_dcd_state;	serial = (struct usb_serial *) urb->context;	if (urb->status) {		dbg(__FUNCTION__ " nonzero status: %x", urb->status);		return;	}	if (urb->actual_length != sizeof(struct keyspan_usa28_portStatusMessage)) {		dbg(__FUNCTION__ " bad length %d", urb->actual_length);		goto exit;	}	/*dbg(__FUNCTION__ " %x %x %x %x %x %x %x %x %x %x %x %x",	    data[0], data[1], data[2], data[3], data[4], data[5],	    data[6], data[7], data[8], data[9], data[10], data[11]);*/			/* Now do something useful with the data */	msg = (keyspan_usa28_portStatusMessage *)data;		/* Check port number from message and retrieve private data */		if (msg->port >= serial->num_ports) {		dbg ("Unexpected port number %d", msg->port);		goto exit;	}	port = &serial->port[msg->port];	p_priv = (struct keyspan_port_private *)(port->private);		/* Update handshaking pin state information */	old_dcd_state = p_priv->dcd_state;	p_priv->cts_state = ((msg->cts) ? 1 : 0);	p_priv->dsr_state = ((msg->dsr) ? 1 : 0);	p_priv->dcd_state = ((msg->dcd) ? 1 : 0);	p_priv->ri_state = ((msg->ri) ? 1 : 0);	if (port->tty && !C_CLOCAL(port->tty)	    && old_dcd_state != p_priv->dcd_state) {		if (old_dcd_state)			tty_hangup(port->tty);		/*  else */		/*	wake_up_interruptible(&p_priv->open_wait); */	}exit:			/* Resubmit urb so we continue receiving */	urb->dev = serial->dev;	if ((err = usb_submit_urb(urb)) != 0) {		dbg(__FUNCTION__ "resubmit read urb failed. (%d)", err);	}}static void	usa28_glocont_callback(struct urb *urb){	dbg (__FUNCTION__);}static void	usa49_glocont_callback(struct urb *urb){	struct usb_serial *serial;	struct usb_serial_port *port;	struct keyspan_port_private *p_priv;	int i;	/*  dbg (__FUNCTION__); */	serial = (struct usb_serial *) urb->context;	for (i = 0; i < serial->num_ports; ++i) {		port = &serial->port[i];		p_priv = (struct keyspan_port_private *)(port->private);		if (p_priv->resend_cont) {			/*  dbg (__FUNCTION__ " sending setup"); */			keyspan_usa49_send_setup(serial, port);			break;		}	}}	/* This is actually called glostat in the Keyspan	   doco */static void	usa49_instat_callback(struct urb *urb){	int					err;	unsigned char 				*data = urb->transfer_buffer;	keyspan_usa49_portStatusMessage		*msg;	struct usb_serial			*serial;	struct usb_serial_port			*port;	struct keyspan_port_private	 	*p_priv;	int old_dcd_state;	/*  dbg (__FUNCTION__); */	serial = (struct usb_serial *) urb->context;	if (urb->status) {		dbg(__FUNCTION__ " nonzero status: %x", urb->status);		return;	}	if (urb->actual_length != sizeof(struct keyspan_usa49_portStatusMessage)) {		dbg(__FUNCTION__ " bad length %d", urb->actual_length);		goto exit;	}	/*dbg(__FUNCTION__ " %x %x %x %x %x %x %x %x %x %x %x",	    data[0], data[1], data[2], data[3], data[4], data[5],	    data[6], data[7], data[8], data[9], data[10]);*/			/* Now do something useful with the data */	msg = (keyspan_usa49_portStatusMessage *)data;		/* Check port number from message and retrieve private data */		if (msg->portNumber >= serial->num_ports) {		dbg ("Unexpected port number %d", msg->portNumber);		goto exit;	}	port = &serial->port[msg->portNumber];	p_priv = (struct keyspan_port_private *)(port->private);		/* Update handshaking pin state information */	old_dcd_state = p_priv->dcd_state;	p_priv->cts_state = ((msg->cts) ? 1 : 0);	p_priv->dsr_state = ((msg->dsr) ? 1 : 0);	p_priv->dcd_state = ((msg->dcd) ? 1 : 0);	p_priv->ri_state = ((msg->ri) ? 1 : 0);	if (port->tty && !C_CLOCAL(port->tty)	    && old_dcd_state != p_priv->dcd_state) {		if (old_dcd_state)			tty_hangup(port->tty);		/*  else */		/*	wake_up_interruptible(&p_priv->open_wait); */	}exit:			/* Resubmit urb so we continue receiving */	urb->dev = serial->dev;	if ((err = usb_submit_urb(urb)) != 0) {		dbg(__FUNCTION__ "resubmit read urb failed. (%d)", err);	}}static void	usa49_inack_callback(struct urb *urb){	dbg (__FUNCTION__);}static void	usa49_indat_callback(struct urb *urb){	int			i, err;	int			endpoint;	struct usb_serial_port	*port;	struct tty_struct	*tty;	unsigned char 		*data = urb->transfer_buffer;	/*  dbg (__FUNCTION__); */	endpoint = usb_pipeendpoint(urb->pipe);	if (urb->status) {		dbg(__FUNCTION__ "nonzero status: %x on endpoint %d.",			      		urb->status, endpoint);		return;	}	port = (struct usb_serial_port *) urb->context;	tty = port->tty;	if (urb->actual_length) {		if (data[0] == 0) {			/* no error on any byte */			for (i = 1; i < urb->actual_length ; ++i) {				tty_insert_flip_char(tty, data[i], 0);			}		} else {			/* some bytes had errors, every byte has status */			for (i = 0; i + 1 < urb->actual_length; i += 2) {				int stat = data[i], flag = 0;				if (stat & RXERROR_OVERRUN)					flag |= TTY_OVERRUN;				if (stat & RXERROR_FRAMING)					flag |= TTY_FRAME;				if (stat & RXERROR_PARITY)					flag |= TTY_PARITY;				/* XXX should handle break (0x10) */				tty_insert_flip_char(tty, data[i+1], flag);			}		}		tty_flip_buffer_push(tty);	}						/* Resubmit urb so we continue receiving */	urb->dev = port->serial->dev;	if ((err = usb_submit_urb(urb)) != 0) {		dbg(__FUNCTION__ "resubmit read urb failed. (%d)", err);	}}/* not used, usa-49 doesn't have per-port control endpoints */static void	usa49_outcont_callback(struct urb *urb){	dbg (__FUNCTION__);}static int keyspan_write_room (struct usb_serial_port *port){//	dbg("keyspan_write_room called");	return (32);}static int keyspan_chars_in_buffer (struct usb_serial_port *port){	return (0);}static int keyspan_open (struct usb_serial_port *port, struct file *filp){	struct keyspan_port_private 	*p_priv;	struct keyspan_serial_private 	*s_priv;	struct usb_serial 		*serial = port->serial;	const keyspan_device_details	*d_details;	int				i, already_active, err;	unsigned long flags;	urb_t *urb;	s_priv = (struct keyspan_serial_private *)(serial->private);	p_priv = (struct keyspan_port_private *)(port->private);	d_details = s_priv->device_details;		/*  dbg("keyspan_open called."); */	MOD_INC_USE_COUNT;	spin_lock_irqsave (&port->port_lock, flags);	++port->open_count;	already_active = port->active;	port->active = 1;	spin_unlock_irqrestore (&port->port_lock, flags);	if (already_active)		return 0;	p_priv = (struct keyspan_port_private *)(port->private);	/* Set some sane defaults */	p_priv->baud = 9600;	p_priv->cflag = CREAD | CLOCAL;	p_priv->flow_control = flow_none;	p_priv->rts_state = 1;	p_priv->dtr_state = 1;	/* Start reading from endpoints */	for (i = 0; i < 2; i++) {		if ((urb = p_priv->in_urbs[i]) == NULL)			continue;		urb->dev = serial->dev;		if ((err = usb_submit_urb(urb)) != 0) {			dbg(__FUNCTION__ " submit urb %d failed (%d)", i, err);		}	}/*    Now done in startup routine	if (atomic_inc_return(&s_priv->active_count) == 1) {		s_priv->instat_urb->dev = serial->dev;		if ((err = usb_submit_urb(s_priv->instat_urb)) != 0) {			dbg(__FUNCTION__ " submit instat urb failed %d", err);		}	}*/	keyspan_send_setup(port);	return (0);}static inline void stop_urb(urb_t *urb){	if (urb && urb->status == -EINPROGRESS) {		urb->transfer_flags &= ~USB_ASYNC_UNLINK;		usb_unlink_urb(urb);	}}static void keyspan_close(struct usb_serial_port *port, struct file *filp){	int			i;	struct usb_serial	*serial = port->serial; /* FIXME should so sanity check */	struct keyspan_serial_private 	*s_priv;	struct keyspan_port_private 	*p_priv;	unsigned long flags;	/*  dbg("keyspan_close called"); */	s_priv = (struct keyspan_serial_private *)(serial->private);	p_priv = (struct keyspan_port_private *)(port->private);	spin_lock_irqsave (&port->port_lock, flags);	if (--port->open_count <= 0) {		if (port->active) {			/* Stop reading/writing urbs */			stop_urb(p_priv->inack_urb);			stop_urb(p_priv->outcont_urb);			for (i = 0; i < 2; i++) {				stop_urb(p_priv->in_urbs[i]);				stop_urb(p_priv->out_urbs[i]);			}			/* Now done in shutdown 			if (atomic_dec_return(&s_priv->active_count) <= 0) {				stop_urb(s_priv->instat_urb);				stop_urb(s_priv->glocont_urb);			} */		}		port->active = 0;		port->open_count = 0;		port->tty = 0;	}	spin_unlock_irqrestore (&port->port_lock, flags);	MOD_DEC_USE_COUNT;}	/* download the firmware to a pre-renumeration device */static int keyspan_fake_startup (struct usb_serial *serial){	int 				response;	const struct ezusb_hex_record 	*record;	char				*fw_name;	dbg("Keyspan startup version %04x product %04x",	    serial->dev->descriptor.bcdDevice,	    serial->dev->descriptor.idProduct); 		if ((serial->dev->descriptor.bcdDevice & 0x8000) != 0x8000) {		dbg("Firmware already loaded.  Quitting.");		return(1);	}		/* Select firmware image on the basis of idProduct */	switch (serial->dev->descriptor.idProduct) {	case 0x0101:		record = &keyspan_usa28_firmware[0];		fw_name = "USA28";		break;	case 0x0102:		record = &keyspan_usa28x_firmware[0];		fw_name = "USA28X";		break;	case 0x0103:		record = &keyspan_usa19_firmware[0];		fw_name = "USA19";		break;			     	case 0x0105:		record = &keyspan_usa18x_firmware[0];		fw_name = "USA18X";		break;			     	case 0x0106:		record = &keyspan_usa19w_firmware[0];		fw_name = "USA19W";		break;			case 0x0109:		record = &keyspan_usa49w_firmware[0];		fw_name = "USA49W";		break;	default:		record = NULL;		fw_name = "Unknown";		break;	}	if (record == NULL) {		err("Required keyspan firmware image (%s) unavailable.", fw_name);		return(1);	}	dbg("Uploading Keyspan %s firmware.", fw_name);		/* download the firmware image */	response = ezusb_set_reset(serial, 1);	while(record->address != 0xffff) {		response = ezusb_writememory(serial, record->address,					     (unsigned char *)record->data,					     record->data_size, 0xa0);		if (response < 0) {			err("ezusb_writememory failed for Keyspan"			    "firmware (%d %04X %p %d)",			    response, 			    record->address, record->data, record->data_size);			break;		}		record++;	}		/* bring device out of reset. Renumeration will occur in a		   moment and the new device will bind to the real driver */	response = ezusb_set_reset(serial, 0);	/* we don't want this device to have a driver assigned to it. */	return (1);}/* Helper functions used by keyspan_setup_urbs */static urb_t *keyspan_setup_urb(struct usb_serial *serial, int endpoint,				int dir, void *ctx, char *buf, int len,				void (*callback)(urb_t *)){	urb_t *urb;	if (endpoint == -1)		return NULL;		/* endpoint not needed */	/*  dbg (__FUNCTION__ " alloc for endpoint %d.", endpoint); */	urb = usb_alloc_urb(0);		/* No ISO */	if (urb == NULL) {		dbg (__FUNCTION__ " alloc for endpoint %d failed.", endpoint);		return NULL;	}		/* Fill URB using supplied data. */	FILL_BULK_URB(urb, serial->dev,		      usb_sndbulkpipe(serial->dev, endpoint) | dir,		      buf, len, callback, ctx);	return urb;}struct callbacks {	void	(*instat_callback)(urb_t *);	void	(*glocont_callback)(urb_t *);	void	(*indat_callback)(urb_t *);	void	(*outdat_callback)(urb_t *);	void	(*inack_callback)(urb_t *);	void	(*outcont_callback)(urb_t *);} keyspan_callbacks[] = {	{		/* msg_usa26 callbacks */		instat_callback: usa26_instat_callback,		glocont_callback: usa26_glocont_callback,		indat_callback: usa26_indat_callback,		outdat_callback: usa2x_outdat_callback,		inack_callback: usa26_inack_callback,		outcont_callback: usa26_outcont_callback,	}, {		/* msg_usa28 callbacks */		instat_callback: usa28_instat_callback,		glocont_callback: usa28_glocont_callback,		indat_callback: usa28_indat_callback,		outdat_callback: usa2x_outdat_callback,		inack_callback: usa28_inack_callback,		outcont_callback: usa28_outcont_callback,	}, {		/* msg_usa49 callbacks */		instat_callback: usa49_instat_callback,		glocont_callback: usa49_glocont_callback,		indat_callback: usa49_indat_callback,		outdat_callback: usa2x_outdat_callback,		inack_callback: usa49_inack_callback,		outcont_callback: usa49_outcont_callback,	}};	/* Generic setup urbs function that uses	   data in device_details */static void keyspan_setup_urbs(struct usb_serial *serial){	int				i, j;	struct keyspan_serial_private 	*s_priv;	const keyspan_device_details	*d_details;	struct usb_serial_port		*port;	struct keyspan_port_private	*p_priv;	struct callbacks		*cback;	int				endp;	/*  dbg (__FUNCTION__); */	s_priv = (struct keyspan_serial_private *)(serial->private);	d_details = s_priv->device_details;		/* Setup values for the various callback routines */	cback = &keyspan_callbacks[d_details->msg_format];		/* Allocate and set up urbs for each one that is in use, 		   starting with instat endpoints */	s_priv->instat_urb = keyspan_setup_urb		(serial, d_details->instat_endpoint, USB_DIR_IN,		 serial, s_priv->instat_buf, INSTAT_BUFLEN,		 cback->instat_callback);	s_priv->glocont_urb = keyspan_setup_urb		(serial, d_details->glocont_endpoint, USB_DIR_OUT,		 serial, s_priv->glocont_buf, GLOCONT_BUFLEN,		 cback->glocont_callback);		/* Setup endpoints for each port specific thing */	for (i = 0; i < d_details->num_ports; i ++) {		port = &serial->port[i];		p_priv = (struct keyspan_port_private *)(port->private);		/* Do indat endpoints first, once for each flip */		endp = d_details->indat_endpoints[i];		for (j = 0; j <= d_details->indat_endp_flip; ++j, ++endp) {			p_priv->in_urbs[j] = keyspan_setup_urb				(serial, endp, USB_DIR_IN, port,				 p_priv->in_buffer[j], 64,				 cback->indat_callback);		}		for (; j < 2; ++j)			p_priv->in_urbs[j] = NULL;		/* outdat endpoints also have flip */		endp = d_details->outdat_endpoints[i];		for (j = 0; j <= d_details->outdat_endp_flip; ++j, ++endp) {			p_priv->out_urbs[j] = keyspan_setup_urb				(serial, endp, USB_DIR_OUT, port,				 p_priv->out_buffer[j], 64,				 cback->outdat_callback);		}		for (; j < 2; ++j)			p_priv->out_urbs[j] = NULL;		/* inack endpoint */		p_priv->inack_urb = keyspan_setup_urb			(serial, d_details->inack_endpoints[i], USB_DIR_IN,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -