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

📄 whiteheat.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
		dbg("%s - bad reply from firmware", __FUNCTION__);	}		/* Continue trying to always read */	command_port->read_urb->dev = command_port->serial->dev;	result = usb_submit_urb(command_port->read_urb, GFP_ATOMIC);	spin_unlock_irqrestore(&command_info->lock, flags);	if (result)		dbg("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);}static void whiteheat_read_callback(struct urb *urb, struct pt_regs *regs){	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;	struct whiteheat_urb_wrap *wrap;	unsigned char *data = urb->transfer_buffer;	struct whiteheat_private *info = usb_get_serial_port_data(port);	dbg("%s - port %d", __FUNCTION__, port->number);	spin_lock(&info->lock);	wrap = urb_to_wrap(urb, &info->rx_urbs_submitted);	if (!wrap) {		spin_unlock(&info->lock);		err("%s - Not my urb!", __FUNCTION__);		return;	}	list_del(&wrap->list);	spin_unlock(&info->lock);	if (urb->status) {		dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);		spin_lock(&info->lock);		list_add(&wrap->list, &info->rx_urbs_free);		spin_unlock(&info->lock);		return;	}	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);	spin_lock(&info->lock);	list_add_tail(&wrap->list, &info->rx_urb_q);	if (info->flags & THROTTLED) {		info->flags |= ACTUALLY_THROTTLED;		spin_unlock(&info->lock);		return;	}	spin_unlock(&info->lock);	schedule_work(&info->rx_work);}static void whiteheat_write_callback(struct urb *urb, struct pt_regs *regs){	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;	struct whiteheat_private *info = usb_get_serial_port_data(port);	struct whiteheat_urb_wrap *wrap;	dbg("%s - port %d", __FUNCTION__, port->number);	spin_lock(&info->lock);	wrap = urb_to_wrap(urb, &info->tx_urbs_submitted);	if (!wrap) {		spin_unlock(&info->lock);		err("%s - Not my urb!", __FUNCTION__);		return;	}	list_del(&wrap->list);	list_add(&wrap->list, &info->tx_urbs_free);	spin_unlock(&info->lock);	if (urb->status) {		dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);		return;	}	usb_serial_port_softint((void *)port);	schedule_work(&port->work);}/***************************************************************************** * Connect Tech's White Heat firmware interface *****************************************************************************/static int firm_send_command (struct usb_serial_port *port, __u8 command, __u8 *data, __u8 datasize){	struct usb_serial_port *command_port;	struct whiteheat_command_private *command_info;	struct whiteheat_private *info;	__u8 *transfer_buffer;	int retval = 0;	unsigned long flags;	dbg("%s - command %d", __FUNCTION__, command);	command_port = port->serial->port[COMMAND_PORT];	command_info = usb_get_serial_port_data(command_port);	spin_lock_irqsave(&command_info->lock, flags);	command_info->command_finished = FALSE;		transfer_buffer = (__u8 *)command_port->write_urb->transfer_buffer;	transfer_buffer[0] = command;	memcpy (&transfer_buffer[1], data, datasize);	command_port->write_urb->transfer_buffer_length = datasize + 1;	command_port->write_urb->dev = port->serial->dev;	retval = usb_submit_urb (command_port->write_urb, GFP_KERNEL);	if (retval) {		dbg("%s - submit urb failed", __FUNCTION__);		goto exit;	}	spin_unlock_irqrestore(&command_info->lock, flags);	/* wait for the command to complete */	wait_event_interruptible_timeout(command_info->wait_command, 		(command_info->command_finished != FALSE), COMMAND_TIMEOUT);	spin_lock_irqsave(&command_info->lock, flags);	if (command_info->command_finished == FALSE) {		dbg("%s - command timed out.", __FUNCTION__);		retval = -ETIMEDOUT;		goto exit;	}	if (command_info->command_finished == WHITEHEAT_CMD_FAILURE) {		dbg("%s - command failed.", __FUNCTION__);		retval = -EIO;		goto exit;	}	if (command_info->command_finished == WHITEHEAT_CMD_COMPLETE) {		dbg("%s - command completed.", __FUNCTION__);		switch (command) {			case WHITEHEAT_GET_DTR_RTS:				info = usb_get_serial_port_data(port);				memcpy(&info->mcr, command_info->result_buffer, sizeof(struct whiteheat_dr_info));				break;		}	}exit:	spin_unlock_irqrestore(&command_info->lock, flags);	return retval;}static int firm_open(struct usb_serial_port *port) {	struct whiteheat_simple open_command;	open_command.port = port->number - port->serial->minor + 1;	return firm_send_command(port, WHITEHEAT_OPEN, (__u8 *)&open_command, sizeof(open_command));}static int firm_close(struct usb_serial_port *port) {	struct whiteheat_simple close_command;	close_command.port = port->number - port->serial->minor + 1;	return firm_send_command(port, WHITEHEAT_CLOSE, (__u8 *)&close_command, sizeof(close_command));}static int firm_setup_port(struct usb_serial_port *port) {	struct whiteheat_port_settings port_settings;	unsigned int cflag = port->tty->termios->c_cflag;	port_settings.port = port->number + 1;	/* get the byte size */	switch (cflag & CSIZE) {		case CS5:	port_settings.bits = 5;   break;		case CS6:	port_settings.bits = 6;   break;		case CS7:	port_settings.bits = 7;   break;		default:		case CS8:	port_settings.bits = 8;   break;	}	dbg("%s - data bits = %d", __FUNCTION__, port_settings.bits);		/* determine the parity */	if (cflag & PARENB)		if (cflag & CMSPAR)			if (cflag & PARODD)				port_settings.parity = WHITEHEAT_PAR_MARK;			else				port_settings.parity = WHITEHEAT_PAR_SPACE;		else			if (cflag & PARODD)				port_settings.parity = WHITEHEAT_PAR_ODD;			else				port_settings.parity = WHITEHEAT_PAR_EVEN;	else		port_settings.parity = WHITEHEAT_PAR_NONE;	dbg("%s - parity = %c", __FUNCTION__, port_settings.parity);	/* figure out the stop bits requested */	if (cflag & CSTOPB)		port_settings.stop = 2;	else		port_settings.stop = 1;	dbg("%s - stop bits = %d", __FUNCTION__, port_settings.stop);	/* figure out the flow control settings */	if (cflag & CRTSCTS)		port_settings.hflow = (WHITEHEAT_HFLOW_CTS | WHITEHEAT_HFLOW_RTS);	else		port_settings.hflow = WHITEHEAT_HFLOW_NONE;	dbg("%s - hardware flow control = %s %s %s %s", __FUNCTION__,	    (port_settings.hflow & WHITEHEAT_HFLOW_CTS) ? "CTS" : "",	    (port_settings.hflow & WHITEHEAT_HFLOW_RTS) ? "RTS" : "",	    (port_settings.hflow & WHITEHEAT_HFLOW_DSR) ? "DSR" : "",	    (port_settings.hflow & WHITEHEAT_HFLOW_DTR) ? "DTR" : "");		/* determine software flow control */	if (I_IXOFF(port->tty))		port_settings.sflow = WHITEHEAT_SFLOW_RXTX;	else		port_settings.sflow = WHITEHEAT_SFLOW_NONE;	dbg("%s - software flow control = %c", __FUNCTION__, port_settings.sflow);		port_settings.xon = START_CHAR(port->tty);	port_settings.xoff = STOP_CHAR(port->tty);	dbg("%s - XON = %2x, XOFF = %2x", __FUNCTION__, port_settings.xon, port_settings.xoff);	/* get the baud rate wanted */	port_settings.baud = tty_get_baud_rate(port->tty);	dbg("%s - baud rate = %d", __FUNCTION__, port_settings.baud);	/* handle any settings that aren't specified in the tty structure */	port_settings.lloop = 0;		/* now send the message to the device */	return firm_send_command(port, WHITEHEAT_SETUP_PORT, (__u8 *)&port_settings, sizeof(port_settings));}static int firm_set_rts(struct usb_serial_port *port, __u8 onoff) {	struct whiteheat_set_rdb rts_command;	rts_command.port = port->number - port->serial->minor + 1;	rts_command.state = onoff;	return firm_send_command(port, WHITEHEAT_SET_RTS, (__u8 *)&rts_command, sizeof(rts_command));}static int firm_set_dtr(struct usb_serial_port *port, __u8 onoff) {	struct whiteheat_set_rdb dtr_command;	dtr_command.port = port->number - port->serial->minor + 1;	dtr_command.state = onoff;	return firm_send_command(port, WHITEHEAT_SET_RTS, (__u8 *)&dtr_command, sizeof(dtr_command));}static int firm_set_break(struct usb_serial_port *port, __u8 onoff) {	struct whiteheat_set_rdb break_command;	break_command.port = port->number - port->serial->minor + 1;	break_command.state = onoff;	return firm_send_command(port, WHITEHEAT_SET_RTS, (__u8 *)&break_command, sizeof(break_command));}static int firm_purge(struct usb_serial_port *port, __u8 rxtx) {	struct whiteheat_purge purge_command;	purge_command.port = port->number - port->serial->minor + 1;	purge_command.what = rxtx;	return firm_send_command(port, WHITEHEAT_PURGE, (__u8 *)&purge_command, sizeof(purge_command));}static int firm_get_dtr_rts(struct usb_serial_port *port) {	struct whiteheat_simple get_dr_command;	get_dr_command.port = port->number - port->serial->minor + 1;	return firm_send_command(port, WHITEHEAT_GET_DTR_RTS, (__u8 *)&get_dr_command, sizeof(get_dr_command));}static int firm_report_tx_done(struct usb_serial_port *port) {	struct whiteheat_simple close_command;	close_command.port = port->number - port->serial->minor + 1;	return firm_send_command(port, WHITEHEAT_REPORT_TX_DONE, (__u8 *)&close_command, sizeof(close_command));}/***************************************************************************** * Connect Tech's White Heat utility functions *****************************************************************************/static int start_command_port(struct usb_serial *serial){	struct usb_serial_port *command_port;	struct whiteheat_command_private *command_info;	unsigned long flags;	int retval = 0;		command_port = serial->port[COMMAND_PORT];	command_info = usb_get_serial_port_data(command_port);	spin_lock_irqsave(&command_info->lock, flags);	if (!command_info->port_running) {		/* Work around HCD bugs */		usb_clear_halt(serial->dev, command_port->read_urb->pipe);		command_port->read_urb->dev = serial->dev;		retval = usb_submit_urb(command_port->read_urb, GFP_KERNEL);		if (retval) {			err("%s - failed submitting read urb, error %d", __FUNCTION__, retval);			goto exit;		}	}	command_info->port_running++;exit:	spin_unlock_irqrestore(&command_info->lock, flags);	return retval;}static void stop_command_port(struct usb_serial *serial){	struct usb_serial_port *command_port;	struct whiteheat_command_private *command_info;	unsigned long flags;	command_port = serial->port[COMMAND_PORT];	command_info = usb_get_serial_port_data(command_port);	spin_lock_irqsave(&command_info->lock, flags);	command_info->port_running--;	if (!command_info->port_running)		usb_kill_urb(command_port->read_urb);	spin_unlock_irqrestore(&command_info->lock, flags);}static int start_port_read(struct usb_serial_port *port){	struct whiteheat_private *info = usb_get_serial_port_data(port);	struct whiteheat_urb_wrap *wrap;	struct urb *urb;	int retval = 0;	unsigned long flags;	struct list_head *tmp;	struct list_head *tmp2;	spin_lock_irqsave(&info->lock, flags);	list_for_each_safe(tmp, tmp2, &info->rx_urbs_free) {		list_del(tmp);		wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);		urb = wrap->urb;		urb->dev = port->serial->dev;		retval = usb_submit_urb(urb, GFP_KERNEL);		if (retval) {			list_add(tmp, &info->rx_urbs_free);			list_for_each_safe(tmp, tmp2, &info->rx_urbs_submitted) {				wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);				urb = wrap->urb;				usb_kill_urb(urb);				list_del(tmp);				list_add(tmp, &info->rx_urbs_free);			}			break;		}		list_add(tmp, &info->rx_urbs_submitted);	}	spin_unlock_irqrestore(&info->lock, flags);	return retval;}static struct whiteheat_urb_wrap *urb_to_wrap(struct urb* urb, struct list_head *head){	struct whiteheat_urb_wrap *wrap;	struct list_head *tmp;	list_for_each(tmp, head) {		wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);		if (wrap->urb == urb)			return wrap;	}	return NULL;}static struct list_head *list_first(struct list_head *head){	return head->next;}static void rx_data_softint(void *private){	struct usb_serial_port *port = (struct usb_serial_port *)private;	struct whiteheat_private *info = usb_get_serial_port_data(port);	struct tty_struct *tty = port->tty;	struct whiteheat_urb_wrap *wrap;	struct urb *urb;	unsigned long flags;	struct list_head *tmp;	struct list_head *tmp2;	int result;	int sent = 0;	spin_lock_irqsave(&info->lock, flags);	if (info->flags & THROTTLED) {		spin_unlock_irqrestore(&info->lock, flags);		return;	}	list_for_each_safe(tmp, tmp2, &info->rx_urb_q) {		list_del(tmp);		spin_unlock_irqrestore(&info->lock, flags);		wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);		urb = wrap->urb;		if (tty && urb->actual_length) {			if (urb->actual_length > TTY_FLIPBUF_SIZE - tty->flip.count) {				spin_lock_irqsave(&info->lock, flags);				list_add(tmp, &info->rx_urb_q);				spin_unlock_irqrestore(&info->lock, flags);				tty_flip_buffer_push(tty);				schedule_work(&info->rx_work);				return;			}			memcpy(tty->flip.char_buf_ptr, urb->transfer_buffer, urb->actual_length);			tty->flip.char_buf_ptr += urb->actual_length;			tty->flip.count += urb->actual_length;			sent += urb->actual_length;		}		urb->dev = port->serial->dev;		result = usb_submit_urb(urb, GFP_ATOMIC);		if (result) {			err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);			spin_lock_irqsave(&info->lock, flags);			list_add(tmp, &info->rx_urbs_free);			continue;		}		spin_lock_irqsave(&info->lock, flags);		list_add(tmp, &info->rx_urbs_submitted);	}	spin_unlock_irqrestore(&info->lock, flags);	if (sent)		tty_flip_buffer_push(tty);}/***************************************************************************** * Connect Tech's White Heat module functions *****************************************************************************/static int __init whiteheat_init (void){	int retval;	retval = usb_serial_register(&whiteheat_fake_device);	if (retval)		goto failed_fake_register;	retval = usb_serial_register(&whiteheat_device);	if (retval)		goto failed_device_register;	retval = usb_register(&whiteheat_driver);	if (retval)		goto failed_usb_register;	info(DRIVER_DESC " " DRIVER_VERSION);	return 0;failed_usb_register:	usb_serial_deregister(&whiteheat_device);failed_device_register:	usb_serial_deregister(&whiteheat_fake_device);failed_fake_register:	return retval;}static void __exit whiteheat_exit (void){	usb_deregister (&whiteheat_driver);	usb_serial_deregister (&whiteheat_fake_device);	usb_serial_deregister (&whiteheat_device);}module_init(whiteheat_init);module_exit(whiteheat_exit);MODULE_AUTHOR( DRIVER_AUTHOR );MODULE_DESCRIPTION( DRIVER_DESC );MODULE_LICENSE("GPL");module_param(urb_pool_size, int, 0);MODULE_PARM_DESC(urb_pool_size, "Number of urbs to use for buffering");module_param(debug, bool, S_IRUGO | S_IWUSR);MODULE_PARM_DESC(debug, "Debug enabled or not");

⌨️ 快捷键说明

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