belkin_sa.c 17.2 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
static int  belkin_sa_startup(struct usb_serial *serial);
93
static void belkin_sa_release(struct usb_serial *serial);
A
Alan Cox 已提交
94 95
static int  belkin_sa_open(struct tty_struct *tty,
			struct usb_serial_port *port, struct file *filp);
96
static void belkin_sa_close(struct usb_serial_port *port);
A
Alan Cox 已提交
97 98 99 100 101 102 103
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 已提交
104 105 106 107 108 109 110 111 112


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 已提交
113
	{ }	/* Terminating entry */
L
Linus Torvalds 已提交
114 115
};

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

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

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


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 已提交
167
#define BSA_USB_CMD(c, v) usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), \
L
Linus Torvalds 已提交
168 169 170 171
					    (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 已提交
172
static int belkin_sa_startup(struct usb_serial *serial)
L
Linus Torvalds 已提交
173 174 175 176 177 178 179
{
	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 已提交
180
		return -1; /* error */
L
Linus Torvalds 已提交
181 182 183 184 185 186
	/* 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 已提交
187 188
	priv->bad_flow_control =
		(le16_to_cpu(dev->descriptor.bcdDevice) <= 0x0206) ? 1 : 0;
189
	dev_info(&dev->dev, "bcdDevice: %04x, bfc: %d\n",
A
Alan Cox 已提交
190 191
					le16_to_cpu(dev->descriptor.bcdDevice),
					priv->bad_flow_control);
L
Linus Torvalds 已提交
192 193 194

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

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


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

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

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


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

220
	dbg("%s port %d", __func__, port->number);
L
Linus Torvalds 已提交
221 222 223 224 225 226 227 228

	/*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) {
229
		dev_err(&port->dev, "usb_submit_urb(read bulk) failed\n");
L
Linus Torvalds 已提交
230 231 232 233 234 235 236
		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);
237
		dev_err(&port->dev, "usb_submit_urb(read int) failed\n");
L
Linus Torvalds 已提交
238 239 240 241 242 243 244
	}

exit:
	return retval;
} /* belkin_sa_open */


245
static void belkin_sa_close(struct usb_serial_port *port)
L
Linus Torvalds 已提交
246
{
247
	dbg("%s port %d", __func__, port->number);
L
Linus Torvalds 已提交
248 249 250 251 252 253 254 255

	/* 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 已提交
256
static void belkin_sa_read_int_callback(struct urb *urb)
L
Linus Torvalds 已提交
257
{
258
	struct usb_serial_port *port = urb->context;
L
Linus Torvalds 已提交
259 260 261
	struct belkin_sa_private *priv;
	unsigned char *data = urb->transfer_buffer;
	int retval;
262
	int status = urb->status;
L
Linus Torvalds 已提交
263 264
	unsigned long flags;

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

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

	/* 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 已提交
291

L
Linus Torvalds 已提交
292 293 294 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
	/* 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 已提交
322
		tty = tty_port_tty_get(&port->port);
L
Linus Torvalds 已提交
323 324 325 326 327 328 329 330 331 332 333 334
		/* 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) {
		}
A
Alan Cox 已提交
335
		tty_kref_put(tty);
L
Linus Torvalds 已提交
336 337 338 339
	}
#endif
	spin_unlock_irqrestore(&priv->lock, flags);
exit:
A
Alan Cox 已提交
340
	retval = usb_submit_urb(urb, GFP_ATOMIC);
L
Linus Torvalds 已提交
341
	if (retval)
342 343
		dev_err(&port->dev, "%s - usb_submit_urb failed with "
			"result %d\n", __func__, retval);
L
Linus Torvalds 已提交
344 345
}

A
Alan Cox 已提交
346 347
static void belkin_sa_set_termios(struct tty_struct *tty,
		struct usb_serial_port *port, struct ktermios *old_termios)
L
Linus Torvalds 已提交
348 349 350 351 352 353 354 355 356 357 358
{
	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;
359
	speed_t baud;
A
Alan Cox 已提交
360
	struct ktermios *termios = tty->termios;
A
Alan Cox 已提交
361

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

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

	/* 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 已提交
372

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

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

A
Alan Cox 已提交
391
	baud = tty_get_baud_rate(tty);
392 393 394 395 396 397 398 399 400
	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 已提交
401
		tty_encode_baud_rate(tty, baud, baud);
402
		if (BSA_USB_CMD(BELKIN_SA_SET_BAUDRATE_REQUEST, urb_value) < 0)
403
			dev_err(&port->dev, "Set baudrate error\n");
404 405
	} else {
		/* Disable flow control */
A
Alan Cox 已提交
406 407
		if (BSA_USB_CMD(BELKIN_SA_SET_FLOW_CTRL_REQUEST,
						BELKIN_SA_FLOW_NONE) < 0)
408
			dev_err(&port->dev, "Disable flowcontrol error\n");
409 410 411
		/* Drop RTS and DTR */
		control_state &= ~(TIOCM_DTR | TIOCM_RTS);
		if (BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, 0) < 0)
412
			dev_err(&port->dev, "DTR LOW error\n");
413
		if (BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, 0) < 0)
414
			dev_err(&port->dev, "RTS LOW error\n");
L
Linus Torvalds 已提交
415 416 417
	}

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

	/* set the number of data bits */
A
Alan Cox 已提交
429
	if ((cflag & CSIZE) != (old_cflag & CSIZE)) {
L
Linus Torvalds 已提交
430
		switch (cflag & CSIZE) {
A
Alan Cox 已提交
431 432 433 434 435 436 437 438 439 440 441 442 443 444 445
		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 已提交
446 447
		}
		if (BSA_USB_CMD(BELKIN_SA_SET_DATA_BITS_REQUEST, urb_value) < 0)
448
			dev_err(&port->dev, "Set data bits error\n");
L
Linus Torvalds 已提交
449 450 451
	}

	/* set the number of stop bits */
A
Alan Cox 已提交
452 453 454 455 456
	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)
457
			dev_err(&port->dev, "Set stop bits error\n");
L
Linus Torvalds 已提交
458 459 460
	}

	/* Set flow control */
A
Alan Cox 已提交
461 462
	if (((iflag ^ old_iflag) & (IXOFF | IXON)) ||
		((cflag ^ old_cflag) & CRTSCTS)) {
L
Linus Torvalds 已提交
463 464 465 466 467 468 469 470 471 472 473 474 475 476 477
		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)
478
			dev_err(&port->dev, "Set flow control error\n");
L
Linus Torvalds 已提交
479 480 481 482 483 484 485 486 487
	}

	/* 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 已提交
488
static void belkin_sa_break_ctl(struct tty_struct *tty, int break_state)
L
Linus Torvalds 已提交
489
{
A
Alan Cox 已提交
490
	struct usb_serial_port *port = tty->driver_data;
L
Linus Torvalds 已提交
491 492 493
	struct usb_serial *serial = port->serial;

	if (BSA_USB_CMD(BELKIN_SA_SET_BREAK_REQUEST, break_state ? 1 : 0) < 0)
494
		dev_err(&port->dev, "Set break_ctl %d\n", break_state);
L
Linus Torvalds 已提交
495 496 497
}


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

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

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

	return control_state;
}


A
Alan Cox 已提交
515
static int belkin_sa_tiocmset(struct tty_struct *tty, struct file *file,
L
Linus Torvalds 已提交
516 517
			       unsigned int set, unsigned int clear)
{
A
Alan Cox 已提交
518
	struct usb_serial_port *port = tty->driver_data;
L
Linus Torvalds 已提交
519 520 521 522 523 524 525
	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 已提交
526

527
	dbg("%s", __func__);
L
Linus Torvalds 已提交
528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553

	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) {
554
		dev_err(&port->dev, "Set RTS error %d\n", retval);
L
Linus Torvalds 已提交
555 556 557 558 559
		goto exit;
	}

	retval = BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, dtr);
	if (retval < 0) {
560
		dev_err(&port->dev, "Set DTR error %d\n", retval);
L
Linus Torvalds 已提交
561 562 563 564 565 566 567
		goto exit;
	}
exit:
	return retval;
}


A
Alan Cox 已提交
568
static int __init belkin_sa_init(void)
L
Linus Torvalds 已提交
569 570 571 572 573 574 575 576
{
	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;
577 578
	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
	       DRIVER_DESC "\n");
L
Linus Torvalds 已提交
579 580 581 582 583 584 585 586 587 588
	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 已提交
589
	usb_deregister(&belkin_driver);
A
Alan Cox 已提交
590
	usb_serial_deregister(&belkin_device);
L
Linus Torvalds 已提交
591 592 593
}


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

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

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