cregit-Linux how code gets into the kernel

Release 4.7 drivers/usb/serial/whiteheat.c

/*
 * USB ConnectTech WhiteHEAT driver
 *
 *      Copyright (C) 2002
 *          Connect Tech Inc.
 *
 *      Copyright (C) 1999 - 2001
 *          Greg Kroah-Hartman (greg@kroah.com)
 *
 *      This program is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation; either version 2 of the License, or
 *      (at your option) any later version.
 *
 * See Documentation/usb/usb-serial.txt for more information on using this
 * driver
 */

#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
#include <linux/tty_flip.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/mutex.h>
#include <linux/uaccess.h>
#include <asm/termbits.h>
#include <linux/usb.h>
#include <linux/serial_reg.h>
#include <linux/serial.h>
#include <linux/usb/serial.h>
#include <linux/usb/ezusb.h>
#include "whiteheat.h"			/* WhiteHEAT specific commands */

#ifndef CMSPAR

#define CMSPAR 0
#endif

/*
 * Version Information
 */

#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Stuart MacDonald <stuartm@connecttech.com>"

#define DRIVER_DESC "USB ConnectTech WhiteHEAT driver"


#define CONNECT_TECH_VENDOR_ID		0x0710

#define CONNECT_TECH_FAKE_WHITE_HEAT_ID	0x0001

#define CONNECT_TECH_WHITE_HEAT_ID	0x8001

/*
   ID tables for whiteheat are unusual, because we want to different
   things for different versions of the device.  Eventually, this
   will be doable from a single table.  But, for now, we define two
   separate ID tables, and then a third table that combines them
   just for the purpose of exporting the autoloading information.
*/

static const struct usb_device_id id_table_std[] = {
	{ USB_DEVICE(CONNECT_TECH_VENDOR_ID, CONNECT_TECH_WHITE_HEAT_ID) },
	{ }						/* Terminating entry */
};


static const struct usb_device_id id_table_prerenumeration[] = {
	{ USB_DEVICE(CONNECT_TECH_VENDOR_ID, CONNECT_TECH_FAKE_WHITE_HEAT_ID) },
	{ }						/* Terminating entry */
};


static const struct usb_device_id id_table_combined[] = {
	{ USB_DEVICE(CONNECT_TECH_VENDOR_ID, CONNECT_TECH_WHITE_HEAT_ID) },
	{ USB_DEVICE(CONNECT_TECH_VENDOR_ID, CONNECT_TECH_FAKE_WHITE_HEAT_ID) },
	{ }						/* Terminating entry */
};

MODULE_DEVICE_TABLE(usb, id_table_combined);


/* function prototypes for the Connect Tech WhiteHEAT prerenumeration device */
static int  whiteheat_firmware_download(struct usb_serial *serial,
					const struct usb_device_id *id);
static int  whiteheat_firmware_attach(struct usb_serial *serial);

/* function prototypes for the Connect Tech WhiteHEAT serial converter */
static int whiteheat_probe(struct usb_serial *serial,
				const struct usb_device_id *id);
static int  whiteheat_attach(struct usb_serial *serial);
static void whiteheat_release(struct usb_serial *serial);
static int  whiteheat_port_probe(struct usb_serial_port *port);
static int  whiteheat_port_remove(struct usb_serial_port *port);
static int  whiteheat_open(struct tty_struct *tty,
			struct usb_serial_port *port);
static void whiteheat_close(struct usb_serial_port *port);
static int  whiteheat_ioctl(struct tty_struct *tty,
			unsigned int cmd, unsigned long arg);
static void whiteheat_set_termios(struct tty_struct *tty,
			struct usb_serial_port *port, struct ktermios *old);
static int  whiteheat_tiocmget(struct tty_struct *tty);
static int  whiteheat_tiocmset(struct tty_struct *tty,
			unsigned int set, unsigned int clear);
static void whiteheat_break_ctl(struct tty_struct *tty, int break_state);


static struct usb_serial_driver whiteheat_fake_device = {
	.driver = {
		.owner =	THIS_MODULE,
		.name =		"whiteheatnofirm",
        },
	.description =		"Connect Tech - WhiteHEAT - (prerenumeration)",
	.id_table =		id_table_prerenumeration,
	.num_ports =		1,
	.probe =		whiteheat_firmware_download,
	.attach =		whiteheat_firmware_attach,
};


static struct usb_serial_driver whiteheat_device = {
	.driver = {
		.owner =	THIS_MODULE,
		.name =		"whiteheat",
        },
	.description =		"Connect Tech - WhiteHEAT",
	.id_table =		id_table_std,
	.num_ports =		4,
	.probe =		whiteheat_probe,
	.attach =		whiteheat_attach,
	.release =		whiteheat_release,
	.port_probe =		whiteheat_port_probe,
	.port_remove =		whiteheat_port_remove,
	.open =			whiteheat_open,
	.close =		whiteheat_close,
	.ioctl =		whiteheat_ioctl,
	.set_termios =		whiteheat_set_termios,
	.break_ctl =		whiteheat_break_ctl,
	.tiocmget =		whiteheat_tiocmget,
	.tiocmset =		whiteheat_tiocmset,
	.throttle =		usb_serial_generic_throttle,
	.unthrottle =		usb_serial_generic_unthrottle,
};


static struct usb_serial_driver * const serial_drivers[] = {
	&whiteheat_fake_device, &whiteheat_device, NULL
};


struct whiteheat_command_private {
	
struct mutex		mutex;
	
__u8			port_running;
	
__u8			command_finished;
	
wait_queue_head_t	wait_command; /* for handling sleeping whilst
                                                 waiting for a command to
                                                 finish */
	
__u8			result_buffer[64];
};


struct whiteheat_private {
	
__u8			mcr;		/* FIXME: no locking on mcr */
};


/* local function prototypes */
static int start_command_port(struct usb_serial *serial);
static void stop_command_port(struct usb_serial *serial);
static void command_port_write_callback(struct urb *urb);
static void command_port_read_callback(struct urb *urb);

static int firm_send_command(struct usb_serial_port *port, __u8 command,
						__u8 *data, __u8 datasize);
static int firm_open(struct usb_serial_port *port);
static int firm_close(struct usb_serial_port *port);
static void firm_setup_port(struct tty_struct *tty);
static int firm_set_rts(struct usb_serial_port *port, __u8 onoff);
static int firm_set_dtr(struct usb_serial_port *port, __u8 onoff);
static int firm_set_break(struct usb_serial_port *port, __u8 onoff);
static int firm_purge(struct usb_serial_port *port, __u8 rxtx);
static int firm_get_dtr_rts(struct usb_serial_port *port);
static int firm_report_tx_done(struct usb_serial_port *port);



#define COMMAND_PORT		4

#define COMMAND_TIMEOUT		(2*HZ)	
/* 2 second timeout for a command */

#define	COMMAND_TIMEOUT_MS	2000

#define CLOSING_DELAY		(30 * HZ)


/*****************************************************************************
 * Connect Tech's White Heat prerenumeration driver functions
 *****************************************************************************/

/* steps to download the firmware to the WhiteHEAT device:
 - hold the reset (by writing to the reset bit of the CPUCS register)
 - download the VEND_AX.HEX file to the chip using VENDOR_REQUEST-ANCHOR_LOAD
 - release the reset (by writing to the CPUCS register)
 - download the WH.HEX file for all addresses greater than 0x1b3f using
   VENDOR_REQUEST-ANCHOR_EXTERNAL_RAM_LOAD
 - hold the reset
 - download the WH.HEX file for all addresses less than 0x1b40 using
   VENDOR_REQUEST_ANCHOR_LOAD
 - release the reset
 - device renumerated itself and comes up as new device id with all
   firmware download completed.
*/

static int whiteheat_firmware_download(struct usb_serial *serial, const struct usb_device_id *id) { int response; response = ezusb_fx1_ihex_firmware_download(serial->dev, "whiteheat_loader.fw"); if (response >= 0) { response = ezusb_fx1_ihex_firmware_download(serial->dev, "whiteheat.fw"); if (response >= 0) return 0; } return -ENOENT; }

Contributors

PersonTokensPropCommitsCommitProp
stuart macdonaldstuart macdonald4266.67%116.67%
rene buergelrene buergel1117.46%233.33%
greg kroah-hartmangreg kroah-hartman914.29%233.33%
david woodhousedavid woodhouse11.59%116.67%
Total63100.00%6100.00%


static int whiteheat_firmware_attach(struct usb_serial *serial) { /* We want this device to fail to have a driver assigned to it */ return 1; }

Contributors

PersonTokensPropCommitsCommitProp
stuart macdonaldstuart macdonald15100.00%1100.00%
Total15100.00%1100.00%

/***************************************************************************** * Connect Tech's White Heat serial driver functions *****************************************************************************/
static int whiteheat_probe(struct usb_serial *serial, const struct usb_device_id *id) { struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; size_t num_bulk_in = 0; size_t num_bulk_out = 0; size_t min_num_bulk; unsigned int i; iface_desc = serial->interface->cur_altsetting; for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { endpoint = &iface_desc->endpoint[i].desc; if (usb_endpoint_is_bulk_in(endpoint)) ++num_bulk_in; if (usb_endpoint_is_bulk_out(endpoint)) ++num_bulk_out; } min_num_bulk = COMMAND_PORT + 1; if (num_bulk_in < min_num_bulk || num_bulk_out < min_num_bulk) return -ENODEV; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
johan hovoldjohan hovold126100.00%1100.00%
Total126100.00%1100.00%


static int whiteheat_attach(struct usb_serial *serial) { struct usb_serial_port *command_port; struct whiteheat_command_private *command_info; struct whiteheat_hw_info *hw_info; int pipe; int ret; int alen; __u8 *command; __u8 *result; command_port = serial->port[COMMAND_PORT]; pipe = usb_sndbulkpipe(serial->dev, command_port->bulk_out_endpointAddress); command = kmalloc(2, GFP_KERNEL); if (!command) goto no_command_buffer; command[0] = WHITEHEAT_GET_HW_INFO; command[1] = 0; result = kmalloc(sizeof(*hw_info) + 1, GFP_KERNEL); if (!result) goto no_result_buffer; /* * When the module is reloaded the firmware is still there and * the endpoints are still in the usb core unchanged. This is the * unlinking bug in disguise. Same for the call below. */ usb_clear_halt(serial->dev, pipe); ret = usb_bulk_msg(serial->dev, pipe, command, 2, &alen, COMMAND_TIMEOUT_MS); if (ret) { dev_err(&serial->dev->dev, "%s: Couldn't send command [%d]\n", serial->type->description, ret); goto no_firmware; } else if (alen != 2) { dev_err(&serial->dev->dev, "%s: Send command incomplete [%d]\n", serial->type->description, alen); goto no_firmware; } pipe = usb_rcvbulkpipe(serial->dev, command_port->bulk_in_endpointAddress); /* See the comment on the usb_clear_halt() above */ usb_clear_halt(serial->dev, pipe); ret = usb_bulk_msg(serial->dev, pipe, result, sizeof(*hw_info) + 1, &alen, COMMAND_TIMEOUT_MS); if (ret) { dev_err(&serial->dev->dev, "%s: Couldn't get results [%d]\n", serial->type->description, ret); goto no_firmware; } else if (alen != sizeof(*hw_info) + 1) { dev_err(&serial->dev->dev, "%s: Get results incomplete [%d]\n", serial->type->description, alen); goto no_firmware; } else if (result[0] != command[0]) { dev_err(&serial->dev->dev, "%s: Command failed [%d]\n", serial->type->description, result[0]); goto no_firmware; } hw_info = (struct whiteheat_hw_info *)&result[1]; dev_info(&serial->dev->dev, "%s: Firmware v%d.%02d\n", serial->type->description, hw_info->sw_major_rev, hw_info->sw_minor_rev); command_info = kmalloc(sizeof(struct whiteheat_command_private), GFP_KERNEL); if (!command_info) goto no_command_private; mutex_init(&command_info->mutex); command_info->port_running = 0; init_waitqueue_head(&command_info->wait_command); usb_set_serial_port_data(command_port, command_info); command_port->write_urb->complete = command_port_write_callback; command_port->read_urb->complete = command_port_read_callback; kfree(result); kfree(command); return 0; no_firmware: /* Firmware likely not running */ dev_err(&serial->dev->dev, "%s: Unable to retrieve firmware version, try replugging\n", serial->type->description); dev_err(&serial->dev->dev, "%s: If the firmware is not running (status led not blinking)\n", serial->type->description); dev_err(&serial->dev->dev, "%s: please contact support@connecttech.com\n", serial->type->description); kfree(result); kfree(command); return -ENODEV; no_command_private: kfree(result); no_result_buffer: kfree(command); no_command_buffer: return -ENOMEM; }

Contributors

PersonTokensPropCommitsCommitProp
stuart macdonaldstuart macdonald33457.99%425.00%
johan hovoldjohan hovold11019.10%425.00%
greg kroah-hartmangreg kroah-hartman6811.81%425.00%
oliver neukumoliver neukum6010.42%16.25%
nishanth aravamudannishanth aravamudan20.35%16.25%
alan coxalan cox10.17%16.25%
david howellsdavid howells10.17%16.25%
Total576100.00%16100.00%


static void whiteheat_release(struct usb_serial *serial) { struct usb_serial_port *command_port; /* free up our private data for our command port */ command_port = serial->port[COMMAND_PORT]; kfree(usb_get_serial_port_data(command_port)); }

Contributors

PersonTokensPropCommitsCommitProp
johan hovoldjohan hovold3294.12%266.67%
stuart macdonaldstuart macdonald25.88%133.33%
Total34100.00%3100.00%


static int whiteheat_port_probe(struct usb_serial_port *port) { struct whiteheat_private *info; info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; usb_set_serial_port_data(port, info); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
johan hovoldjohan hovold48100.00%2100.00%
Total48100.00%2100.00%


static int whiteheat_port_remove(struct usb_serial_port *port) { struct whiteheat_private *info; info = usb_get_serial_port_data(port); kfree(info); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
johan hovoldjohan hovold2890.32%240.00%
stuart macdonaldstuart macdonald39.68%360.00%
Total31100.00%5100.00%


static int whiteheat_open(struct tty_struct *tty, struct usb_serial_port *port) { int retval; retval = start_command_port(port->serial); if (retval) goto exit; /* send an open port command */ retval = firm_open(port); if (retval) { stop_command_port(port->serial); goto exit; } retval = firm_purge(port, WHITEHEAT_PURGE_RX | WHITEHEAT_PURGE_TX); if (retval) { firm_close(port); stop_command_port(port->serial); goto exit; } if (tty) firm_setup_port(tty); /* Work around HCD bugs */ usb_clear_halt(port->serial->dev, port->read_urb->pipe); usb_clear_halt(port->serial->dev, port->write_urb->pipe); retval = usb_serial_generic_open(tty, port); if (retval) { firm_close(port); stop_command_port(port->serial); goto exit; } exit: return retval; }

Contributors

PersonTokensPropCommitsCommitProp
johan hovoldjohan hovold10261.45%116.67%
stuart macdonaldstuart macdonald5331.93%350.00%
greg kroah-hartmangreg kroah-hartman116.63%233.33%
Total166100.00%6100.00%


static void whiteheat_close(struct usb_serial_port *port) { firm_report_tx_done(port); firm_close(port); usb_serial_generic_close(port); stop_command_port(port->serial); }

Contributors

PersonTokensPropCommitsCommitProp
johan hovoldjohan hovold1957.58%150.00%
stuart macdonaldstuart macdonald1442.42%150.00%
Total33100.00%2100.00%


static int whiteheat_tiocmget(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct whiteheat_private *info = usb_get_serial_port_data(port); unsigned int modem_signals = 0; firm_get_dtr_rts(port); if (info->mcr & UART_MCR_DTR) modem_signals |= TIOCM_DTR; if (info->mcr & UART_MCR_RTS) modem_signals |= TIOCM_RTS; return modem_signals; }

Contributors

PersonTokensPropCommitsCommitProp
johan hovoldjohan hovold4261.76%150.00%
stuart macdonaldstuart macdonald2638.24%150.00%
Total68100.00%2100.00%


static int whiteheat_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; struct whiteheat_private *info = usb_get_serial_port_data(port); if (set & TIOCM_RTS) info->mcr |= UART_MCR_RTS; if (set & TIOCM_DTR) info->mcr |= UART_MCR_DTR; if (clear & TIOCM_RTS) info->mcr &= ~UART_MCR_RTS; if (clear & TIOCM_DTR) info->mcr &= ~UART_MCR_DTR; firm_set_dtr(port, info->mcr & UART_MCR_DTR); firm_set_rts(port, info->mcr & UART_MCR_RTS); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
johan hovoldjohan hovold6153.98%125.00%
stuart macdonaldstuart macdonald4237.17%125.00%
alan coxalan cox97.96%125.00%
greg kroah-hartmangreg kroah-hartman10.88%125.00%
Total113100.00%4100.00%


static int whiteheat_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { struct usb_serial_port *port = tty->driver_data; struct serial_struct serstruct; void __user *user_arg = (void __user *)arg; switch (cmd) { case TIOCGSERIAL: memset(&serstruct, 0, sizeof(serstruct)); serstruct.type = PORT_16654; serstruct.line = port->minor; serstruct.port = port->port_number; serstruct.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; serstruct.xmit_fifo_size = kfifo_size(&port->write_fifo); serstruct.custom_divisor = 0; serstruct.baud_base = 460800; serstruct.close_delay = CLOSING_DELAY; serstruct.closing_wait = CLOSING_DELAY; if (copy_to_user(user_arg, &serstruct, sizeof(serstruct))) return -EFAULT; break; default: break; } return -ENOIOCTLCMD; }

Contributors

PersonTokensPropCommitsCommitProp
johan hovoldjohan hovold11270.89%120.00%
stuart macdonaldstuart macdonald3924.68%240.00%
oliver neukumoliver neukum63.80%120.00%
greg kroah-hartmangreg kroah-hartman10.63%120.00%
Total158100.00%5100.00%


static void whiteheat_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { firm_setup_port(tty); }

Contributors

PersonTokensPropCommitsCommitProp
johan hovoldjohan hovold1453.85%133.33%
stuart macdonaldstuart macdonald726.92%133.33%
alan coxalan cox519.23%133.33%
Total26100.00%3100.00%


static void whiteheat_break_ctl(struct tty_struct *tty, int break_state) { struct usb_serial_port *port = tty->driver_data; firm_set_break(port, break_state); }

Contributors

PersonTokensPropCommitsCommitProp
johan hovoldjohan hovold1963.33%125.00%
stuart macdonaldstuart macdonald930.00%250.00%
greg kroah-hartmangreg kroah-hartman26.67%125.00%
Total30100.00%4100.00%

/***************************************************************************** * Connect Tech's White Heat callback routines *****************************************************************************/
static void command_port_write_callback(struct urb *urb) { int status = urb->status; if (status) { dev_dbg(&urb->dev->dev, "nonzero urb status: %d\n", status); return; } }

Contributors

PersonTokensPropCommitsCommitProp
stuart macdonaldstuart macdonald1641.03%250.00%
johan hovoldjohan hovold1435.90%125.00%
greg kroah-hartmangreg kroah-hartman923.08%125.00%
Total39100.00%4100.00%


static void command_port_read_callback(struct urb *urb) { struct usb_serial_port *command_port = urb->context; struct whiteheat_command_private *command_info; int status = urb->status; unsigned char *data = urb->transfer_buffer; int result; command_info = usb_get_serial_port_data(command_port); if (!command_info) { dev_dbg(&urb->dev->dev, "%s - command_info is NULL, exiting.\n", __func__); return; } if (!urb->actual_length) { dev_dbg(&urb->dev->dev, "%s - empty response, exiting.\n", __func__); return; } if (status) { dev_dbg(&urb->dev->dev, "%s - nonzero urb status: %d\n", __func__, status); if (status != -ENOENT) command_info->command_finished = WHITEHEAT_CMD_FAILURE; wake_up(&command_info->wait_command); return; } usb_serial_debug_data(&command_port->dev, __func__, urb->actual_length, data); if (data[0] == WHITEHEAT_CMD_COMPLETE) { command_info->command_finished = WHITEHEAT_CMD_COMPLETE; wake_up(&command_info->wait_command); } else if (data[0] == WHITEHEAT_CMD_FAILURE) { command_info->command_finished = WHITEHEAT_CMD_FAILURE; wake_up(&command_info->wait_command); } else if (data[0] == WHITEHEAT_EVENT) { /* These are unsolicited reports from the firmware, hence no waiting command to wakeup */ dev_dbg(&urb->dev->dev, "%s - event received\n", __func__); } else if ((data[0] == WHITEHEAT_GET_DTR_RTS) && (urb->actual_length - 1 <= sizeof(command_info->result_buffer))) { memcpy(command_info->result_buffer, &data[1], urb->actual_length - 1); command_info->command_finished = WHITEHEAT_CMD_COMPLETE; wake_up(&command_info->wait_command); } else dev_dbg(&urb->dev->dev, "%s - bad reply from firmware\n", __func__); /* Continue trying to always read */ result = usb_submit_urb(command_port->read_urb, GFP_ATOMIC); if (result) dev_dbg(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result); }

Contributors

PersonTokensPropCommitsCommitProp
johan hovoldjohan hovold18453.49%114.29%
stuart macdonaldstuart macdonald7020.35%228.57%
greg kroah-hartmangreg kroah-hartman4813.95%228.57%
james forshawjames forshaw4111.92%114.29%
harvey harrisonharvey harrison10.29%114.29%
Total344100.00%7100.00%

/***************************************************************************** * 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; struct device *dev = &port->dev; __u8 *transfer_buffer; int retval = 0; int t; dev_dbg(dev, "%s - command %d\n", __func__, command); command_port = port->serial->port[COMMAND_PORT]; command_info = usb_get_serial_port_data(command_port); mutex_lock(&command_info->mutex); 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; retval = usb_submit_urb(command_port->write_urb, GFP_NOIO); if (retval) { dev_dbg(dev, "%s - submit urb failed\n", __func__); goto exit; } /* wait for the command to complete */ t = wait_event_timeout(command_info->wait_command, (bool)command_info->command_finished, COMMAND_TIMEOUT); if (!t) usb_kill_urb(command_port->write_urb); if (command_info->command_finished == false) { dev_dbg(dev, "%s - command timed out.\n", __func__); retval = -ETIMEDOUT; goto exit; } if (command_info->command_finished == WHITEHEAT_CMD_FAILURE) { dev_dbg(dev, "%s - command failed.\n", __func__); retval = -EIO; goto exit; } if (command_info->command_finished == WHITEHEAT_CMD_COMPLETE) { dev_dbg(dev, "%s - command completed.\n", __func__); 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: mutex_unlock(&command_info->mutex); return retval; }

Contributors

PersonTokensPropCommitsCommitProp
johan hovoldjohan hovold19961.42%114.29%
stuart macdonaldstuart macdonald8325.62%228.57%
greg kroah-hartmangreg kroah-hartman3510.80%228.57%
alan coxalan cox51.54%114.29%
harvey harrisonharvey harrison20.62%114.29%
Total324100.00%7100.00%


static int firm_open(struct usb_serial_port *port) { struct whiteheat_simple open_command; open_command.port = port->port_number + 1; return firm_send_command(port, WHITEHEAT_OPEN, (__u8 *)&open_command, sizeof(open_command)); }

Contributors

PersonTokensPropCommitsCommitProp
johan hovoldjohan hovold1942.22%120.00%
stuart macdonaldstuart macdonald1635.56%120.00%
greg kroah-hartmangreg kroah-hartman920.00%240.00%
alan coxalan cox12.22%120.00%
Total45100.00%5100.00%


static int firm_close(struct usb_serial_port *port) { struct whiteheat_simple close_command; close_command.port = port->port_number + 1; return firm_send_command(port, WHITEHEAT_CLOSE, (__u8 *)&close_command, sizeof(close_command)); }

Contributors

PersonTokensPropCommitsCommitProp
johan hovoldjohan hovold2862.22%125.00%
stuart macdonaldstuart macdonald1328.89%125.00%
alan coxalan cox36.67%125.00%
greg kroah-hartmangreg kroah-hartman12.22%125.00%
Total45100.00%4100.00%


static void firm_setup_port(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct device *dev = &port->dev; struct whiteheat_port_settings port_settings; unsigned int cflag = tty->termios.c_cflag; port_settings.port = 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; } dev_dbg(dev, "%s - data bits = %d\n", __func__, 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; dev_dbg(dev, "%s - parity = %c\n", __func__, port_settings.parity); /* figure out the stop bits requested */ if (cflag & CSTOPB) port_settings.stop = 2; else port_settings.stop = 1; dev_dbg(dev, "%s - stop bits = %d\n", __func__, 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; dev_dbg(dev, "%s - hardware flow control = %s %s %s %s\n", __func__, (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(tty)) port_settings.sflow = WHITEHEAT_SFLOW_RXTX; else port_settings.sflow = WHITEHEAT_SFLOW_NONE; dev_dbg(dev, "%s - software flow control = %c\n", __func__, port_settings.sflow); port_settings.xon = START_CHAR(tty); port_settings.xoff = STOP_CHAR(tty); dev_dbg(dev, "%s - XON = %2x, XOFF = %2x\n", __func__, port_settings.xon, port_settings.xoff); /* get the baud rate wanted */ port_settings.baud = tty_get_baud_rate(tty); dev_dbg(dev, "%s - baud rate = %d\n", __func__, port_settings.baud); /* fixme: should set validated settings */ tty_encode_baud_rate(tty, port_settings.baud, 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 */ firm_send_command(port, WHITEHEAT_SETUP_PORT, (__u8 *)&port_settings, sizeof(port_settings)); }

Contributors

PersonTokensPropCommitsCommitProp
johan hovoldjohan hovold25758.94%17.69%
stuart macdonaldstuart macdonald10223.39%215.38%
greg kroah-hartmangreg kroah-hartman429.63%430.77%
alan coxalan cox132.98%323.08%
pre-gitpre-git102.29%17.69%
linus torvaldslinus torvalds102.29%17.69%
harvey harrisonharvey harrison20.46%17.69%
Total436100.00%13100.00%


static int firm_set_rts(struct usb_serial_port *port, __u8 onoff) { struct whiteheat_set_rdb rts_command; rts_command.port = port->port_number + 1; rts_command.state = onoff; return firm_send_command(port, WHITEHEAT_SET_RTS, (__u8 *)&rts_command, sizeof(rts_command)); }

Contributors

PersonTokensPropCommitsCommitProp
johan hovoldjohan hovold3462.96%120.00%
stuart macdonaldstuart macdonald1222.22%240.00%
linus torvaldslinus torvalds712.96%120.00%
greg kroah-hartmangreg kroah-hartman11.85%120.00%
Total54100.00%5100.00%


static int firm_set_dtr(struct usb_serial_port *port, __u8 onoff) { struct whiteheat_set_rdb dtr_command; dtr_command.port = port->port_number + 1; dtr_command.state = onoff; return firm_send_command(port, WHITEHEAT_SET_DTR, (__u8 *)&dtr_command, sizeof(dtr_command)); }

Contributors

PersonTokensPropCommitsCommitProp
johan hovoldjohan hovold3055.56%116.67%
stuart macdonaldstuart macdonald1120.37%233.33%
pre-gitpre-git916.67%116.67%
oliver neukumoliver neukum35.56%116.67%
greg kroah-hartmangreg kroah-hartman11.85%116.67%
Total54100.00%6100.00%


static int firm_set_break(struct usb_serial_port *port, __u8 onoff) { struct whiteheat_set_rdb break_command; break_command.port = port->port_number + 1; break_command.state = onoff; return firm_send_command(port, WHITEHEAT_SET_BREAK, (__u8 *)&break_command, sizeof(break_command)); }

Contributors

PersonTokensPropCommitsCommitProp
johan hovoldjohan hovold3972.22%116.67%
stuart macdonaldstuart macdonald814.81%233.33%
oliver neukumoliver neukum47.41%116.67%
pre-gitpre-git23.70%116.67%
greg kroah-hartmangreg kroah-hartman11.85%116.67%
Total54100.00%6100.00%


static int firm_purge(struct usb_serial_port *port, __u8 rxtx) { struct whiteheat_purge purge_command; purge_command.port = port->port_number + 1; purge_command.what = rxtx; return firm_send_command(port, WHITEHEAT_PURGE, (__u8 *)&purge_command, sizeof(purge_command)); }

Contributors

PersonTokensPropCommitsCommitProp
johan hovoldjohan hovold3768.52%120.00%
pre-gitpre-git1120.37%120.00%
stuart macdonaldstuart macdonald59.26%240.00%
greg kroah-hartmangreg kroah-hartman11.85%120.00%
Total54100.00%5100.00%


static int firm_get_dtr_rts(struct usb_serial_port *port) { struct whiteheat_simple get_dr_command; get_dr_command.port = port->port_number + 1; return firm_send_command(port, WHITEHEAT_GET_DTR_RTS, (__u8 *)&get_dr_command, sizeof(get_dr_command)); }

Contributors

PersonTokensPropCommitsCommitProp
johan hovoldjohan hovold3680.00%125.00%
pre-gitpre-git715.56%125.00%
stuart macdonaldstuart macdonald12.22%125.00%
greg kroah-hartmangreg kroah-hartman12.22%125.00%
Total45100.00%4100.00%


static int firm_report_tx_done(struct usb_serial_port *port) { struct whiteheat_simple close_command; close_command.port = port->port_number + 1; return firm_send_command(port, WHITEHEAT_REPORT_TX_DONE, (__u8 *)&close_command, sizeof(close_command)); }

Contributors

PersonTokensPropCommitsCommitProp
johan hovoldjohan hovold3271.11%116.67%
stuart macdonaldstuart macdonald511.11%116.67%
david howellsdavid howells36.67%116.67%
pre-gitpre-git24.44%116.67%
alan coxalan cox24.44%116.67%
greg kroah-hartmangreg kroah-hartman12.22%116.67%
Total45100.00%6100.00%

/***************************************************************************** * 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; int retval = 0; command_port = serial->port[COMMAND_PORT]; command_info = usb_get_serial_port_data(command_port); mutex_lock(&command_info->mutex); if (!command_info->port_running) { /* Work around HCD bugs */ usb_clear_halt(serial->dev, command_port->read_urb->pipe); retval = usb_submit_urb(command_port->read_urb, GFP_KERNEL); if (retval) { dev_err(&serial->dev->dev, "%s - failed submitting read urb, error %d\n", __func__, retval); goto exit; } } command_info->port_running++; exit: mutex_unlock(&command_info->mutex); return retval; }

Contributors

PersonTokensPropCommitsCommitProp
johan hovoldjohan hovold6651.97%112.50%
stuart macdonaldstuart macdonald5140.16%337.50%
greg kroah-hartmangreg kroah-hartman53.94%112.50%
pre-gitpre-git32.36%112.50%
alan coxalan cox10.79%112.50%
harvey harrisonharvey harrison10.79%112.50%
Total127100.00%8100.00%


static void stop_command_port(struct usb_serial *serial) { struct usb_serial_port *command_port; struct whiteheat_command_private *command_info; command_port = serial->port[COMMAND_PORT]; command_info = usb_get_serial_port_data(command_port); mutex_lock(&command_info->mutex); command_info->port_running--; if (!command_info->port_running) usb_kill_urb(command_port->read_urb); mutex_unlock(&command_info->mutex); }

Contributors

PersonTokensPropCommitsCommitProp
johan hovoldjohan hovold5272.22%120.00%
stuart macdonaldstuart macdonald1419.44%240.00%
alan coxalan cox34.17%120.00%
pre-gitpre-git34.17%120.00%
Total72100.00%5100.00%

module_usb_serial_driver(serial_drivers, id_table_combined); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); MODULE_FIRMWARE("whiteheat.fw"); MODULE_FIRMWARE("whiteheat_loader.fw");

Overall Contributors

PersonTokensPropCommitsCommitProp
johan hovoldjohan hovold179744.92%79.72%
stuart macdonaldstuart macdonald123630.90%56.94%
greg kroah-hartmangreg kroah-hartman3298.22%2027.78%
pre-gitpre-git2957.38%79.72%
oliver neukumoliver neukum791.98%22.78%
alan coxalan cox681.70%912.50%
linus torvaldslinus torvalds501.25%811.11%
james forshawjames forshaw411.02%11.39%
rusty russellrusty russell290.72%11.39%
alan sternalan stern220.55%22.78%
rene buergelrene buergel120.30%34.17%
david woodhousedavid woodhouse110.28%11.39%
meelis roosmeelis roos90.23%11.39%
nishanth aravamudannishanth aravamudan60.15%11.39%
harvey harrisonharvey harrison60.15%11.39%
david howellsdavid howells40.10%11.39%
marton nemethmarton nemeth30.07%11.39%
marcel sebekmarcel sebek30.07%11.39%
Total4000100.00%72100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
{% endraw %}