belkin_sa.c 16.9 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9
/*
 * Belkin USB Serial Adapter Driver
 *
 *  Copyright (C) 2000		William Greathouse (wgreathouse@smva.com)
 *  Copyright (C) 2000-2001 	Greg Kroah-Hartman (greg@kroah.com)
 *
 *  This program is largely derived from work by the linux-usb group
 *  and associated source files.  Please see the usb/serial files for
 *  individual credits and copyrights.
A
Alan Cox 已提交
10
 *
L
Linus Torvalds 已提交
11 12 13 14 15
 * 	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.
 *
A
Alan Cox 已提交
16 17
 * See Documentation/usb/usb-serial.txt for more information on using this
 * driver
L
Linus Torvalds 已提交
18 19 20 21 22 23 24 25 26 27 28 29 30 31
 *
 * TODO:
 * -- Add true modem contol line query capability.  Currently we track the
 *    states reported by the interrupt and the states we request.
 * -- Add error reporting back to application for UART error conditions.
 *    Just point me at how to implement this and I'll do it. I've put the
 *    framework in, but haven't analyzed the "tty_flip" interface yet.
 * -- Add support for flush commands
 * -- Add everything that is missing :)
 *
 * 27-Nov-2001 gkh
 * 	compressed all the differnent device entries into 1.
 *
 * 30-May-2001 gkh
A
Alan Cox 已提交
32 33
 *	switched from using spinlock to a semaphore, which fixes lots of
 *	problems.
L
Linus Torvalds 已提交
34 35 36 37 38 39 40 41 42 43 44 45
 *
 * 08-Apr-2001 gb
 *	- Identify version on module load.
 *
 * 12-Mar-2001 gkh
 *	- Added support for the GoHubs GO-COM232 device which is the same as the
 *	  Peracom device.
 *
 * 06-Nov-2000 gkh
 *	- Added support for the old Belkin and Peracom devices.
 *	- Made the port able to be opened multiple times.
 *	- Added some defaults incase the line settings are things these devices
A
Alan Cox 已提交
46
 *	  can't support.
L
Linus Torvalds 已提交
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
 *
 * 18-Oct-2000 William Greathouse
 *    Released into the wild (linux-usb-devel)
 *
 * 17-Oct-2000 William Greathouse
 *    Add code to recognize firmware version and set hardware flow control
 *    appropriately.  Belkin states that firmware prior to 3.05 does not
 *    operate correctly in hardware handshake mode.  I have verified this
 *    on firmware 2.05 -- for both RTS and DTR input flow control, the control
 *    line is not reset.  The test performed by the Belkin Win* driver is
 *    to enable hardware flow control for firmware 2.06 or greater and
 *    for 1.00 or prior.  I am only enabling for 2.06 or greater.
 *
 * 12-Oct-2000 William Greathouse
 *    First cut at supporting Belkin USB Serial Adapter F5U103
 *    I did not have a copy of the original work to support this
 *    adapter, so pardon any stupid mistakes.  All of the information
 *    I am using to write this driver was acquired by using a modified
 *    UsbSnoop on Windows2000 and from examining the other USB drivers.
 */

#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.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>
A
Alan Cox 已提交
77
#include <linux/uaccess.h>
L
Linus Torvalds 已提交
78
#include <linux/usb.h>
79
#include <linux/usb/serial.h>
L
Linus Torvalds 已提交
80 81 82 83 84 85 86 87 88 89 90 91
#include "belkin_sa.h"

static int debug;

/*
 * Version Information
 */
#define DRIVER_VERSION "v1.2"
#define DRIVER_AUTHOR "William Greathouse <wgreathouse@smva.com>"
#define DRIVER_DESC "USB Belkin Serial converter driver"

/* function prototypes for a Belkin USB Serial Adapter F5U103 */
A
Alan Cox 已提交
92 93 94 95 96 97 98 99 100 101 102 103 104
static int  belkin_sa_startup(struct usb_serial *serial);
static void belkin_sa_shutdown(struct usb_serial *serial);
static int  belkin_sa_open(struct tty_struct *tty,
			struct usb_serial_port *port, struct file *filp);
static void belkin_sa_close(struct tty_struct *tty,
			struct usb_serial_port *port, struct file *filp);
static void belkin_sa_read_int_callback(struct urb *urb);
static void belkin_sa_set_termios(struct tty_struct *tty,
			struct usb_serial_port *port, struct ktermios * old);
static void belkin_sa_break_ctl(struct tty_struct *tty, int break_state);
static int  belkin_sa_tiocmget(struct tty_struct *tty, struct file *file);
static int  belkin_sa_tiocmset(struct tty_struct *tty, struct file *file,
					unsigned int set, unsigned int clear);
L
Linus Torvalds 已提交
105 106 107 108 109 110 111 112 113


static struct usb_device_id id_table_combined [] = {
	{ USB_DEVICE(BELKIN_SA_VID, BELKIN_SA_PID) },
	{ USB_DEVICE(BELKIN_OLD_VID, BELKIN_OLD_PID) },
	{ USB_DEVICE(PERACOM_VID, PERACOM_PID) },
	{ USB_DEVICE(GOHUBS_VID, GOHUBS_PID) },
	{ USB_DEVICE(GOHUBS_VID, HANDYLINK_PID) },
	{ USB_DEVICE(BELKIN_DOCKSTATION_VID, BELKIN_DOCKSTATION_PID) },
A
Alan Cox 已提交
114
	{ }	/* Terminating entry */
L
Linus Torvalds 已提交
115 116
};

A
Alan Cox 已提交
117
MODULE_DEVICE_TABLE(usb, id_table_combined);
L
Linus Torvalds 已提交
118 119 120 121 122 123

static struct usb_driver belkin_driver = {
	.name =		"belkin",
	.probe =	usb_serial_probe,
	.disconnect =	usb_serial_disconnect,
	.id_table =	id_table_combined,
124
	.no_dynamic_id = 	1,
L
Linus Torvalds 已提交
125 126 127
};

/* All of the device info needed for the serial converters */
128
static struct usb_serial_driver belkin_device = {
129 130
	.driver = {
		.owner =	THIS_MODULE,
131
		.name =		"belkin",
132
	},
133
	.description =		"Belkin / Peracom / GoHubs USB Serial Adapter",
134
	.usb_driver =		&belkin_driver,
L
Linus Torvalds 已提交
135 136 137 138
	.id_table =		id_table_combined,
	.num_ports =		1,
	.open =			belkin_sa_open,
	.close =		belkin_sa_close,
A
Alan Cox 已提交
139 140
	.read_int_callback =	belkin_sa_read_int_callback,
					/* How we get the status info */
L
Linus Torvalds 已提交
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
	.set_termios =		belkin_sa_set_termios,
	.break_ctl =		belkin_sa_break_ctl,
	.tiocmget =		belkin_sa_tiocmget,
	.tiocmset =		belkin_sa_tiocmset,
	.attach =		belkin_sa_startup,
	.shutdown =		belkin_sa_shutdown,
};


struct belkin_sa_private {
	spinlock_t		lock;
	unsigned long		control_state;
	unsigned char		last_lsr;
	unsigned char		last_msr;
	int			bad_flow_control;
};


/*
 * ***************************************************************************
 * Belkin USB Serial Adapter F5U103 specific driver functions
 * ***************************************************************************
 */

#define WDR_TIMEOUT 5000 /* default urb timeout */

/* assumes that struct usb_serial *serial is available */
A
Alan Cox 已提交
168
#define BSA_USB_CMD(c, v) usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), \
L
Linus Torvalds 已提交
169 170 171 172
					    (c), BELKIN_SA_SET_REQUEST_TYPE, \
					    (v), 0, NULL, 0, WDR_TIMEOUT)

/* do some startup allocations not currently performed by usb_serial_probe() */
A
Alan Cox 已提交
173
static int belkin_sa_startup(struct usb_serial *serial)
L
Linus Torvalds 已提交
174 175 176 177 178 179 180
{
	struct usb_device *dev = serial->dev;
	struct belkin_sa_private *priv;

	/* allocate the private data structure */
	priv = kmalloc(sizeof(struct belkin_sa_private), GFP_KERNEL);
	if (!priv)
A
Alan Cox 已提交
181
		return -1; /* error */
L
Linus Torvalds 已提交
182 183 184 185 186 187
	/* set initial values for control structures */
	spin_lock_init(&priv->lock);
	priv->control_state = 0;
	priv->last_lsr = 0;
	priv->last_msr = 0;
	/* see comments at top of file */
A
Alan Cox 已提交
188 189 190 191 192
	priv->bad_flow_control =
		(le16_to_cpu(dev->descriptor.bcdDevice) <= 0x0206) ? 1 : 0;
	info("bcdDevice: %04x, bfc: %d",
					le16_to_cpu(dev->descriptor.bcdDevice),
					priv->bad_flow_control);
L
Linus Torvalds 已提交
193 194 195

	init_waitqueue_head(&serial->port[0]->write_wait);
	usb_set_serial_port_data(serial->port[0], priv);
A
Alan Cox 已提交
196 197

	return 0;
L
Linus Torvalds 已提交
198 199 200
}


A
Alan Cox 已提交
201
static void belkin_sa_shutdown(struct usb_serial *serial)
L
Linus Torvalds 已提交
202 203 204
{
	struct belkin_sa_private *priv;
	int i;
A
Alan Cox 已提交
205 206

	dbg("%s", __func__);
L
Linus Torvalds 已提交
207 208

	/* stop reads and writes on all ports */
A
Alan Cox 已提交
209
	for (i = 0; i < serial->num_ports; ++i) {
L
Linus Torvalds 已提交
210 211
		/* My special items, the standard routines free my urbs */
		priv = usb_get_serial_port_data(serial->port[i]);
212
		kfree(priv);
L
Linus Torvalds 已提交
213 214 215 216
	}
}


A
Alan Cox 已提交
217 218
static int  belkin_sa_open(struct tty_struct *tty,
			struct usb_serial_port *port, struct file *filp)
L
Linus Torvalds 已提交
219 220 221
{
	int retval = 0;

222
	dbg("%s port %d", __func__, port->number);
L
Linus Torvalds 已提交
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246

	/*Start reading from the device*/
	/* TODO: Look at possibility of submitting multiple URBs to device to
	 *       enhance buffering.  Win trace shows 16 initial read URBs.
	 */
	port->read_urb->dev = port->serial->dev;
	retval = usb_submit_urb(port->read_urb, GFP_KERNEL);
	if (retval) {
		err("usb_submit_urb(read bulk) failed");
		goto exit;
	}

	port->interrupt_in_urb->dev = port->serial->dev;
	retval = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
	if (retval) {
		usb_kill_urb(port->read_urb);
		err(" usb_submit_urb(read int) failed");
	}

exit:
	return retval;
} /* belkin_sa_open */


A
Alan Cox 已提交
247
static void belkin_sa_close(struct tty_struct *tty,
A
Alan Cox 已提交
248
			struct usb_serial_port *port, struct file *filp)
L
Linus Torvalds 已提交
249
{
250
	dbg("%s port %d", __func__, port->number);
L
Linus Torvalds 已提交
251 252 253 254 255 256 257 258

	/* shutdown our bulk reads and writes */
	usb_kill_urb(port->write_urb);
	usb_kill_urb(port->read_urb);
	usb_kill_urb(port->interrupt_in_urb);
} /* belkin_sa_close */


A
Alan Cox 已提交
259
static void belkin_sa_read_int_callback(struct urb *urb)
L
Linus Torvalds 已提交
260
{
261
	struct usb_serial_port *port = urb->context;
L
Linus Torvalds 已提交
262 263 264
	struct belkin_sa_private *priv;
	unsigned char *data = urb->transfer_buffer;
	int retval;
265
	int status = urb->status;
L
Linus Torvalds 已提交
266 267
	unsigned long flags;

268
	switch (status) {
L
Linus Torvalds 已提交
269 270 271 272 273 274 275
	case 0:
		/* success */
		break;
	case -ECONNRESET:
	case -ENOENT:
	case -ESHUTDOWN:
		/* this urb is terminated, clean up */
276
		dbg("%s - urb shutting down with status: %d",
277
		    __func__, status);
L
Linus Torvalds 已提交
278 279
		return;
	default:
280
		dbg("%s - nonzero urb status received: %d",
281
		    __func__, status);
L
Linus Torvalds 已提交
282 283 284
		goto exit;
	}

A
Alan Cox 已提交
285 286
	usb_serial_debug_data(debug, &port->dev, __func__,
					urb->actual_length, data);
L
Linus Torvalds 已提交
287 288 289 290 291 292 293

	/* Handle known interrupt data */
	/* ignore data[0] and data[1] */

	priv = usb_get_serial_port_data(port);
	spin_lock_irqsave(&priv->lock, flags);
	priv->last_msr = data[BELKIN_SA_MSR_INDEX];
A
Alan Cox 已提交
294

L
Linus Torvalds 已提交
295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324
	/* Record Control Line states */
	if (priv->last_msr & BELKIN_SA_MSR_DSR)
		priv->control_state |= TIOCM_DSR;
	else
		priv->control_state &= ~TIOCM_DSR;

	if (priv->last_msr & BELKIN_SA_MSR_CTS)
		priv->control_state |= TIOCM_CTS;
	else
		priv->control_state &= ~TIOCM_CTS;

	if (priv->last_msr & BELKIN_SA_MSR_RI)
		priv->control_state |= TIOCM_RI;
	else
		priv->control_state &= ~TIOCM_RI;

	if (priv->last_msr & BELKIN_SA_MSR_CD)
		priv->control_state |= TIOCM_CD;
	else
		priv->control_state &= ~TIOCM_CD;

	/* Now to report any errors */
	priv->last_lsr = data[BELKIN_SA_LSR_INDEX];
#if 0
	/*
	 * fill in the flip buffer here, but I do not know the relation
	 * to the current/next receive buffer or characters.  I need
	 * to look in to this before committing any code.
	 */
	if (priv->last_lsr & BELKIN_SA_LSR_ERR) {
A
Alan Cox 已提交
325
		tty = port->port.tty;
L
Linus Torvalds 已提交
326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341
		/* Overrun Error */
		if (priv->last_lsr & BELKIN_SA_LSR_OE) {
		}
		/* Parity Error */
		if (priv->last_lsr & BELKIN_SA_LSR_PE) {
		}
		/* Framing Error */
		if (priv->last_lsr & BELKIN_SA_LSR_FE) {
		}
		/* Break Indicator */
		if (priv->last_lsr & BELKIN_SA_LSR_BI) {
		}
	}
#endif
	spin_unlock_irqrestore(&priv->lock, flags);
exit:
A
Alan Cox 已提交
342
	retval = usb_submit_urb(urb, GFP_ATOMIC);
L
Linus Torvalds 已提交
343
	if (retval)
A
Alan Cox 已提交
344
		err("%s - usb_submit_urb failed with result %d",
345
		     __func__, retval);
L
Linus Torvalds 已提交
346 347
}

A
Alan Cox 已提交
348 349
static void belkin_sa_set_termios(struct tty_struct *tty,
		struct usb_serial_port *port, struct ktermios *old_termios)
L
Linus Torvalds 已提交
350 351 352 353 354 355 356 357 358 359 360
{
	struct usb_serial *serial = port->serial;
	struct belkin_sa_private *priv = usb_get_serial_port_data(port);
	unsigned int iflag;
	unsigned int cflag;
	unsigned int old_iflag = 0;
	unsigned int old_cflag = 0;
	__u16 urb_value = 0; /* Will hold the new flags */
	unsigned long flags;
	unsigned long control_state;
	int bad_flow_control;
361
	speed_t baud;
A
Alan Cox 已提交
362
	struct ktermios *termios = tty->termios;
A
Alan Cox 已提交
363

364 365
	iflag = termios->c_iflag;
	cflag = termios->c_cflag;
L
Linus Torvalds 已提交
366

367
	termios->c_cflag &= ~CMSPAR;
L
Linus Torvalds 已提交
368 369 370 371 372 373

	/* get a local copy of the current port settings */
	spin_lock_irqsave(&priv->lock, flags);
	control_state = priv->control_state;
	bad_flow_control = priv->bad_flow_control;
	spin_unlock_irqrestore(&priv->lock, flags);
A
Alan Cox 已提交
374

375 376
	old_iflag = old_termios->c_iflag;
	old_cflag = old_termios->c_cflag;
L
Linus Torvalds 已提交
377 378

	/* Set the baud rate */
379
	if ((cflag & CBAUD) != (old_cflag & CBAUD)) {
L
Linus Torvalds 已提交
380
		/* reassert DTR and (maybe) RTS on transition from B0 */
A
Alan Cox 已提交
381
		if ((old_cflag & CBAUD) == B0) {
L
Linus Torvalds 已提交
382 383 384 385
			control_state |= (TIOCM_DTR|TIOCM_RTS);
			if (BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, 1) < 0)
				err("Set DTR error");
			/* don't set RTS if using hardware flow control */
386
			if (!(old_cflag & CRTSCTS))
A
Alan Cox 已提交
387 388
				if (BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST
								, 1) < 0)
L
Linus Torvalds 已提交
389 390
					err("Set RTS error");
		}
391
	}
L
Linus Torvalds 已提交
392

A
Alan Cox 已提交
393
	baud = tty_get_baud_rate(tty);
394 395 396 397 398 399 400 401 402
	if (baud) {
		urb_value = BELKIN_SA_BAUD(baud);
		/* Clip to maximum speed */
		if (urb_value == 0)
			urb_value = 1;
		/* Turn it back into a resulting real baud rate */
		baud = BELKIN_SA_BAUD(urb_value);

		/* Report the actual baud rate back to the caller */
A
Alan Cox 已提交
403
		tty_encode_baud_rate(tty, baud, baud);
404 405 406 407
		if (BSA_USB_CMD(BELKIN_SA_SET_BAUDRATE_REQUEST, urb_value) < 0)
			err("Set baudrate error");
	} else {
		/* Disable flow control */
A
Alan Cox 已提交
408 409
		if (BSA_USB_CMD(BELKIN_SA_SET_FLOW_CTRL_REQUEST,
						BELKIN_SA_FLOW_NONE) < 0)
410 411 412 413 414 415 416
			err("Disable flowcontrol error");
		/* Drop RTS and DTR */
		control_state &= ~(TIOCM_DTR | TIOCM_RTS);
		if (BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, 0) < 0)
			err("DTR LOW error");
		if (BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, 0) < 0)
			err("RTS LOW error");
L
Linus Torvalds 已提交
417 418 419
	}

	/* set the parity */
A
Alan Cox 已提交
420
	if ((cflag ^ old_cflag) & (PARENB | PARODD)) {
L
Linus Torvalds 已提交
421
		if (cflag & PARENB)
A
Alan Cox 已提交
422 423
			urb_value = (cflag & PARODD) ?  BELKIN_SA_PARITY_ODD
						: BELKIN_SA_PARITY_EVEN;
L
Linus Torvalds 已提交
424 425 426 427 428 429 430
		else
			urb_value = BELKIN_SA_PARITY_NONE;
		if (BSA_USB_CMD(BELKIN_SA_SET_PARITY_REQUEST, urb_value) < 0)
			err("Set parity error");
	}

	/* set the number of data bits */
A
Alan Cox 已提交
431
	if ((cflag & CSIZE) != (old_cflag & CSIZE)) {
L
Linus Torvalds 已提交
432
		switch (cflag & CSIZE) {
A
Alan Cox 已提交
433 434 435 436 437 438 439 440 441 442 443 444 445 446 447
		case CS5:
			urb_value = BELKIN_SA_DATA_BITS(5);
			break;
		case CS6:
			urb_value = BELKIN_SA_DATA_BITS(6);
			break;
		case CS7:
			urb_value = BELKIN_SA_DATA_BITS(7);
			break;
		case CS8:
			urb_value = BELKIN_SA_DATA_BITS(8);
			break;
		default: dbg("CSIZE was not CS5-CS8, using default of 8");
			urb_value = BELKIN_SA_DATA_BITS(8);
			break;
L
Linus Torvalds 已提交
448 449 450 451 452 453
		}
		if (BSA_USB_CMD(BELKIN_SA_SET_DATA_BITS_REQUEST, urb_value) < 0)
			err("Set data bits error");
	}

	/* set the number of stop bits */
A
Alan Cox 已提交
454 455 456 457 458
	if ((cflag & CSTOPB) != (old_cflag & CSTOPB)) {
		urb_value = (cflag & CSTOPB) ? BELKIN_SA_STOP_BITS(2)
						: BELKIN_SA_STOP_BITS(1);
		if (BSA_USB_CMD(BELKIN_SA_SET_STOP_BITS_REQUEST,
							urb_value) < 0)
L
Linus Torvalds 已提交
459 460 461 462
			err("Set stop bits error");
	}

	/* Set flow control */
A
Alan Cox 已提交
463 464
	if (((iflag ^ old_iflag) & (IXOFF | IXON)) ||
		((cflag ^ old_cflag) & CRTSCTS)) {
L
Linus Torvalds 已提交
465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489
		urb_value = 0;
		if ((iflag & IXOFF) || (iflag & IXON))
			urb_value |= (BELKIN_SA_FLOW_OXON | BELKIN_SA_FLOW_IXON);
		else
			urb_value &= ~(BELKIN_SA_FLOW_OXON | BELKIN_SA_FLOW_IXON);

		if (cflag & CRTSCTS)
			urb_value |=  (BELKIN_SA_FLOW_OCTS | BELKIN_SA_FLOW_IRTS);
		else
			urb_value &= ~(BELKIN_SA_FLOW_OCTS | BELKIN_SA_FLOW_IRTS);

		if (bad_flow_control)
			urb_value &= ~(BELKIN_SA_FLOW_IRTS);

		if (BSA_USB_CMD(BELKIN_SA_SET_FLOW_CTRL_REQUEST, urb_value) < 0)
			err("Set flow control error");
	}

	/* save off the modified port settings */
	spin_lock_irqsave(&priv->lock, flags);
	priv->control_state = control_state;
	spin_unlock_irqrestore(&priv->lock, flags);
} /* belkin_sa_set_termios */


A
Alan Cox 已提交
490
static void belkin_sa_break_ctl(struct tty_struct *tty, int break_state)
L
Linus Torvalds 已提交
491
{
A
Alan Cox 已提交
492
	struct usb_serial_port *port = tty->driver_data;
L
Linus Torvalds 已提交
493 494 495 496 497 498 499
	struct usb_serial *serial = port->serial;

	if (BSA_USB_CMD(BELKIN_SA_SET_BREAK_REQUEST, break_state ? 1 : 0) < 0)
		err("Set break_ctl %d", break_state);
}


A
Alan Cox 已提交
500
static int belkin_sa_tiocmget(struct tty_struct *tty, struct file *file)
L
Linus Torvalds 已提交
501
{
A
Alan Cox 已提交
502
	struct usb_serial_port *port = tty->driver_data;
L
Linus Torvalds 已提交
503 504 505
	struct belkin_sa_private *priv = usb_get_serial_port_data(port);
	unsigned long control_state;
	unsigned long flags;
A
Alan Cox 已提交
506

507
	dbg("%s", __func__);
L
Linus Torvalds 已提交
508 509 510 511 512 513 514 515 516

	spin_lock_irqsave(&priv->lock, flags);
	control_state = priv->control_state;
	spin_unlock_irqrestore(&priv->lock, flags);

	return control_state;
}


A
Alan Cox 已提交
517
static int belkin_sa_tiocmset(struct tty_struct *tty, struct file *file,
L
Linus Torvalds 已提交
518 519
			       unsigned int set, unsigned int clear)
{
A
Alan Cox 已提交
520
	struct usb_serial_port *port = tty->driver_data;
L
Linus Torvalds 已提交
521 522 523 524 525 526 527
	struct usb_serial *serial = port->serial;
	struct belkin_sa_private *priv = usb_get_serial_port_data(port);
	unsigned long control_state;
	unsigned long flags;
	int retval;
	int rts = 0;
	int dtr = 0;
A
Alan Cox 已提交
528

529
	dbg("%s", __func__);
L
Linus Torvalds 已提交
530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569

	spin_lock_irqsave(&priv->lock, flags);
	control_state = priv->control_state;

	if (set & TIOCM_RTS) {
		control_state |= TIOCM_RTS;
		rts = 1;
	}
	if (set & TIOCM_DTR) {
		control_state |= TIOCM_DTR;
		dtr = 1;
	}
	if (clear & TIOCM_RTS) {
		control_state &= ~TIOCM_RTS;
		rts = 0;
	}
	if (clear & TIOCM_DTR) {
		control_state &= ~TIOCM_DTR;
		dtr = 0;
	}

	priv->control_state = control_state;
	spin_unlock_irqrestore(&priv->lock, flags);

	retval = BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, rts);
	if (retval < 0) {
		err("Set RTS error %d", retval);
		goto exit;
	}

	retval = BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, dtr);
	if (retval < 0) {
		err("Set DTR error %d", retval);
		goto exit;
	}
exit:
	return retval;
}


A
Alan Cox 已提交
570
static int __init belkin_sa_init(void)
L
Linus Torvalds 已提交
571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589
{
	int retval;
	retval = usb_serial_register(&belkin_device);
	if (retval)
		goto failed_usb_serial_register;
	retval = usb_register(&belkin_driver);
	if (retval)
		goto failed_usb_register;
	info(DRIVER_DESC " " DRIVER_VERSION);
	return 0;
failed_usb_register:
	usb_serial_deregister(&belkin_device);
failed_usb_serial_register:
	return retval;
}


static void __exit belkin_sa_exit (void)
{
A
Alan Cox 已提交
590
	usb_deregister(&belkin_driver);
A
Alan Cox 已提交
591
	usb_serial_deregister(&belkin_device);
L
Linus Torvalds 已提交
592 593 594
}


A
Alan Cox 已提交
595 596
module_init(belkin_sa_init);
module_exit(belkin_sa_exit);
L
Linus Torvalds 已提交
597

A
Alan Cox 已提交
598 599 600
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_VERSION(DRIVER_VERSION);
L
Linus Torvalds 已提交
601 602 603 604
MODULE_LICENSE("GPL");

module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debug enabled or not");