diff options
Diffstat (limited to 'drivers/usb/serial/ssu100.c')
-rw-r--r-- | drivers/usb/serial/ssu100.c | 258 |
1 files changed, 167 insertions, 91 deletions
diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c index 6e82d4f54bc8..e986002b3844 100644 --- a/drivers/usb/serial/ssu100.c +++ b/drivers/usb/serial/ssu100.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/serial.h> | 15 | #include <linux/serial.h> |
16 | #include <linux/usb.h> | 16 | #include <linux/usb.h> |
17 | #include <linux/usb/serial.h> | 17 | #include <linux/usb/serial.h> |
18 | #include <linux/serial_reg.h> | ||
18 | #include <linux/uaccess.h> | 19 | #include <linux/uaccess.h> |
19 | 20 | ||
20 | #define QT_OPEN_CLOSE_CHANNEL 0xca | 21 | #define QT_OPEN_CLOSE_CHANNEL 0xca |
@@ -27,36 +28,11 @@ | |||
27 | #define QT_HW_FLOW_CONTROL_MASK 0xc5 | 28 | #define QT_HW_FLOW_CONTROL_MASK 0xc5 |
28 | #define QT_SW_FLOW_CONTROL_MASK 0xc6 | 29 | #define QT_SW_FLOW_CONTROL_MASK 0xc6 |
29 | 30 | ||
30 | #define MODEM_CTL_REGISTER 0x04 | ||
31 | #define MODEM_STATUS_REGISTER 0x06 | ||
32 | |||
33 | |||
34 | #define SERIAL_LSR_OE 0x02 | ||
35 | #define SERIAL_LSR_PE 0x04 | ||
36 | #define SERIAL_LSR_FE 0x08 | ||
37 | #define SERIAL_LSR_BI 0x10 | ||
38 | |||
39 | #define SERIAL_LSR_TEMT 0x40 | ||
40 | |||
41 | #define SERIAL_MCR_DTR 0x01 | ||
42 | #define SERIAL_MCR_RTS 0x02 | ||
43 | #define SERIAL_MCR_LOOP 0x10 | ||
44 | |||
45 | #define SERIAL_MSR_CTS 0x10 | ||
46 | #define SERIAL_MSR_CD 0x80 | ||
47 | #define SERIAL_MSR_RI 0x40 | ||
48 | #define SERIAL_MSR_DSR 0x20 | ||
49 | #define SERIAL_MSR_MASK 0xf0 | 31 | #define SERIAL_MSR_MASK 0xf0 |
50 | 32 | ||
51 | #define SERIAL_CRTSCTS ((SERIAL_MCR_RTS << 8) | SERIAL_MSR_CTS) | 33 | #define SERIAL_CRTSCTS ((UART_MCR_RTS << 8) | UART_MSR_CTS) |
52 | 34 | ||
53 | #define SERIAL_8_DATA 0x03 | 35 | #define SERIAL_EVEN_PARITY (UART_LCR_PARITY | UART_LCR_EPAR) |
54 | #define SERIAL_7_DATA 0x02 | ||
55 | #define SERIAL_6_DATA 0x01 | ||
56 | #define SERIAL_5_DATA 0x00 | ||
57 | |||
58 | #define SERIAL_ODD_PARITY 0X08 | ||
59 | #define SERIAL_EVEN_PARITY 0X18 | ||
60 | 36 | ||
61 | #define MAX_BAUD_RATE 460800 | 37 | #define MAX_BAUD_RATE 460800 |
62 | 38 | ||
@@ -70,7 +46,7 @@ | |||
70 | #define FULLPWRBIT 0x00000080 | 46 | #define FULLPWRBIT 0x00000080 |
71 | #define NEXT_BOARD_POWER_BIT 0x00000004 | 47 | #define NEXT_BOARD_POWER_BIT 0x00000004 |
72 | 48 | ||
73 | static int debug = 1; | 49 | static int debug; |
74 | 50 | ||
75 | /* Version Information */ | 51 | /* Version Information */ |
76 | #define DRIVER_VERSION "v0.1" | 52 | #define DRIVER_VERSION "v0.1" |
@@ -99,10 +75,12 @@ static struct usb_driver ssu100_driver = { | |||
99 | }; | 75 | }; |
100 | 76 | ||
101 | struct ssu100_port_private { | 77 | struct ssu100_port_private { |
78 | spinlock_t status_lock; | ||
102 | u8 shadowLSR; | 79 | u8 shadowLSR; |
103 | u8 shadowMSR; | 80 | u8 shadowMSR; |
104 | wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */ | 81 | wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */ |
105 | unsigned short max_packet_size; | 82 | unsigned short max_packet_size; |
83 | struct async_icount icount; | ||
106 | }; | 84 | }; |
107 | 85 | ||
108 | static void ssu100_release(struct usb_serial *serial) | 86 | static void ssu100_release(struct usb_serial *serial) |
@@ -150,9 +128,10 @@ static inline int ssu100_getregister(struct usb_device *dev, | |||
150 | 128 | ||
151 | static inline int ssu100_setregister(struct usb_device *dev, | 129 | static inline int ssu100_setregister(struct usb_device *dev, |
152 | unsigned short uart, | 130 | unsigned short uart, |
131 | unsigned short reg, | ||
153 | u16 data) | 132 | u16 data) |
154 | { | 133 | { |
155 | u16 value = (data << 8) | MODEM_CTL_REGISTER; | 134 | u16 value = (data << 8) | reg; |
156 | 135 | ||
157 | return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | 136 | return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), |
158 | QT_SET_GET_REGISTER, 0x40, value, uart, | 137 | QT_SET_GET_REGISTER, 0x40, value, uart, |
@@ -178,11 +157,11 @@ static inline int update_mctrl(struct usb_device *dev, unsigned int set, | |||
178 | clear &= ~set; /* 'set' takes precedence over 'clear' */ | 157 | clear &= ~set; /* 'set' takes precedence over 'clear' */ |
179 | urb_value = 0; | 158 | urb_value = 0; |
180 | if (set & TIOCM_DTR) | 159 | if (set & TIOCM_DTR) |
181 | urb_value |= SERIAL_MCR_DTR; | 160 | urb_value |= UART_MCR_DTR; |
182 | if (set & TIOCM_RTS) | 161 | if (set & TIOCM_RTS) |
183 | urb_value |= SERIAL_MCR_RTS; | 162 | urb_value |= UART_MCR_RTS; |
184 | 163 | ||
185 | result = ssu100_setregister(dev, 0, urb_value); | 164 | result = ssu100_setregister(dev, 0, UART_MCR, urb_value); |
186 | if (result < 0) | 165 | if (result < 0) |
187 | dbg("%s Error from MODEM_CTRL urb", __func__); | 166 | dbg("%s Error from MODEM_CTRL urb", __func__); |
188 | 167 | ||
@@ -264,24 +243,24 @@ static void ssu100_set_termios(struct tty_struct *tty, | |||
264 | 243 | ||
265 | if (cflag & PARENB) { | 244 | if (cflag & PARENB) { |
266 | if (cflag & PARODD) | 245 | if (cflag & PARODD) |
267 | urb_value |= SERIAL_ODD_PARITY; | 246 | urb_value |= UART_LCR_PARITY; |
268 | else | 247 | else |
269 | urb_value |= SERIAL_EVEN_PARITY; | 248 | urb_value |= SERIAL_EVEN_PARITY; |
270 | } | 249 | } |
271 | 250 | ||
272 | switch (cflag & CSIZE) { | 251 | switch (cflag & CSIZE) { |
273 | case CS5: | 252 | case CS5: |
274 | urb_value |= SERIAL_5_DATA; | 253 | urb_value |= UART_LCR_WLEN5; |
275 | break; | 254 | break; |
276 | case CS6: | 255 | case CS6: |
277 | urb_value |= SERIAL_6_DATA; | 256 | urb_value |= UART_LCR_WLEN6; |
278 | break; | 257 | break; |
279 | case CS7: | 258 | case CS7: |
280 | urb_value |= SERIAL_7_DATA; | 259 | urb_value |= UART_LCR_WLEN7; |
281 | break; | 260 | break; |
282 | default: | 261 | default: |
283 | case CS8: | 262 | case CS8: |
284 | urb_value |= SERIAL_8_DATA; | 263 | urb_value |= UART_LCR_WLEN8; |
285 | break; | 264 | break; |
286 | } | 265 | } |
287 | 266 | ||
@@ -333,6 +312,7 @@ static int ssu100_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
333 | struct ssu100_port_private *priv = usb_get_serial_port_data(port); | 312 | struct ssu100_port_private *priv = usb_get_serial_port_data(port); |
334 | u8 *data; | 313 | u8 *data; |
335 | int result; | 314 | int result; |
315 | unsigned long flags; | ||
336 | 316 | ||
337 | dbg("%s - port %d", __func__, port->number); | 317 | dbg("%s - port %d", __func__, port->number); |
338 | 318 | ||
@@ -350,11 +330,10 @@ static int ssu100_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
350 | return result; | 330 | return result; |
351 | } | 331 | } |
352 | 332 | ||
353 | priv->shadowLSR = data[0] & (SERIAL_LSR_OE | SERIAL_LSR_PE | | 333 | spin_lock_irqsave(&priv->status_lock, flags); |
354 | SERIAL_LSR_FE | SERIAL_LSR_BI); | 334 | priv->shadowLSR = data[0]; |
355 | 335 | priv->shadowMSR = data[1]; | |
356 | priv->shadowMSR = data[1] & (SERIAL_MSR_CTS | SERIAL_MSR_DSR | | 336 | spin_unlock_irqrestore(&priv->status_lock, flags); |
357 | SERIAL_MSR_RI | SERIAL_MSR_CD); | ||
358 | 337 | ||
359 | kfree(data); | 338 | kfree(data); |
360 | 339 | ||
@@ -398,11 +377,51 @@ static int get_serial_info(struct usb_serial_port *port, | |||
398 | return 0; | 377 | return 0; |
399 | } | 378 | } |
400 | 379 | ||
380 | static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) | ||
381 | { | ||
382 | struct ssu100_port_private *priv = usb_get_serial_port_data(port); | ||
383 | struct async_icount prev, cur; | ||
384 | unsigned long flags; | ||
385 | |||
386 | spin_lock_irqsave(&priv->status_lock, flags); | ||
387 | prev = priv->icount; | ||
388 | spin_unlock_irqrestore(&priv->status_lock, flags); | ||
389 | |||
390 | while (1) { | ||
391 | wait_event_interruptible(priv->delta_msr_wait, | ||
392 | ((priv->icount.rng != prev.rng) || | ||
393 | (priv->icount.dsr != prev.dsr) || | ||
394 | (priv->icount.dcd != prev.dcd) || | ||
395 | (priv->icount.cts != prev.cts))); | ||
396 | |||
397 | if (signal_pending(current)) | ||
398 | return -ERESTARTSYS; | ||
399 | |||
400 | spin_lock_irqsave(&priv->status_lock, flags); | ||
401 | cur = priv->icount; | ||
402 | spin_unlock_irqrestore(&priv->status_lock, flags); | ||
403 | |||
404 | if ((prev.rng == cur.rng) && | ||
405 | (prev.dsr == cur.dsr) && | ||
406 | (prev.dcd == cur.dcd) && | ||
407 | (prev.cts == cur.cts)) | ||
408 | return -EIO; | ||
409 | |||
410 | if ((arg & TIOCM_RNG && (prev.rng != cur.rng)) || | ||
411 | (arg & TIOCM_DSR && (prev.dsr != cur.dsr)) || | ||
412 | (arg & TIOCM_CD && (prev.dcd != cur.dcd)) || | ||
413 | (arg & TIOCM_CTS && (prev.cts != cur.cts))) | ||
414 | return 0; | ||
415 | } | ||
416 | return 0; | ||
417 | } | ||
418 | |||
401 | static int ssu100_ioctl(struct tty_struct *tty, struct file *file, | 419 | static int ssu100_ioctl(struct tty_struct *tty, struct file *file, |
402 | unsigned int cmd, unsigned long arg) | 420 | unsigned int cmd, unsigned long arg) |
403 | { | 421 | { |
404 | struct usb_serial_port *port = tty->driver_data; | 422 | struct usb_serial_port *port = tty->driver_data; |
405 | struct ssu100_port_private *priv = usb_get_serial_port_data(port); | 423 | struct ssu100_port_private *priv = usb_get_serial_port_data(port); |
424 | void __user *user_arg = (void __user *)arg; | ||
406 | 425 | ||
407 | dbg("%s cmd 0x%04x", __func__, cmd); | 426 | dbg("%s cmd 0x%04x", __func__, cmd); |
408 | 427 | ||
@@ -412,28 +431,28 @@ static int ssu100_ioctl(struct tty_struct *tty, struct file *file, | |||
412 | (struct serial_struct __user *) arg); | 431 | (struct serial_struct __user *) arg); |
413 | 432 | ||
414 | case TIOCMIWAIT: | 433 | case TIOCMIWAIT: |
415 | while (priv != NULL) { | 434 | return wait_modem_info(port, arg); |
416 | u8 prevMSR = priv->shadowMSR & SERIAL_MSR_MASK; | 435 | |
417 | interruptible_sleep_on(&priv->delta_msr_wait); | 436 | case TIOCGICOUNT: |
418 | /* see if a signal did it */ | 437 | { |
419 | if (signal_pending(current)) | 438 | struct serial_icounter_struct icount; |
420 | return -ERESTARTSYS; | 439 | struct async_icount cnow = priv->icount; |
421 | else { | 440 | memset(&icount, 0, sizeof(icount)); |
422 | u8 diff = (priv->shadowMSR & SERIAL_MSR_MASK) ^ prevMSR; | 441 | icount.cts = cnow.cts; |
423 | if (!diff) | 442 | icount.dsr = cnow.dsr; |
424 | return -EIO; /* no change => error */ | 443 | icount.rng = cnow.rng; |
425 | 444 | icount.dcd = cnow.dcd; | |
426 | /* Return 0 if caller wanted to know about | 445 | icount.rx = cnow.rx; |
427 | these bits */ | 446 | icount.tx = cnow.tx; |
428 | 447 | icount.frame = cnow.frame; | |
429 | if (((arg & TIOCM_RNG) && (diff & SERIAL_MSR_RI)) || | 448 | icount.overrun = cnow.overrun; |
430 | ((arg & TIOCM_DSR) && (diff & SERIAL_MSR_DSR)) || | 449 | icount.parity = cnow.parity; |
431 | ((arg & TIOCM_CD) && (diff & SERIAL_MSR_CD)) || | 450 | icount.brk = cnow.brk; |
432 | ((arg & TIOCM_CTS) && (diff & SERIAL_MSR_CTS))) | 451 | icount.buf_overrun = cnow.buf_overrun; |
433 | return 0; | 452 | if (copy_to_user(user_arg, &icount, sizeof(icount))) |
434 | } | 453 | return -EFAULT; |
435 | } | ||
436 | return 0; | 454 | return 0; |
455 | } | ||
437 | 456 | ||
438 | default: | 457 | default: |
439 | break; | 458 | break; |
@@ -455,6 +474,7 @@ static void ssu100_set_max_packet_size(struct usb_serial_port *port) | |||
455 | 474 | ||
456 | unsigned num_endpoints; | 475 | unsigned num_endpoints; |
457 | int i; | 476 | int i; |
477 | unsigned long flags; | ||
458 | 478 | ||
459 | num_endpoints = interface->cur_altsetting->desc.bNumEndpoints; | 479 | num_endpoints = interface->cur_altsetting->desc.bNumEndpoints; |
460 | dev_info(&udev->dev, "Number of endpoints %d\n", num_endpoints); | 480 | dev_info(&udev->dev, "Number of endpoints %d\n", num_endpoints); |
@@ -466,7 +486,9 @@ static void ssu100_set_max_packet_size(struct usb_serial_port *port) | |||
466 | } | 486 | } |
467 | 487 | ||
468 | /* set max packet size based on descriptor */ | 488 | /* set max packet size based on descriptor */ |
489 | spin_lock_irqsave(&priv->status_lock, flags); | ||
469 | priv->max_packet_size = ep_desc->wMaxPacketSize; | 490 | priv->max_packet_size = ep_desc->wMaxPacketSize; |
491 | spin_unlock_irqrestore(&priv->status_lock, flags); | ||
470 | 492 | ||
471 | dev_info(&udev->dev, "Setting MaxPacketSize %d\n", priv->max_packet_size); | 493 | dev_info(&udev->dev, "Setting MaxPacketSize %d\n", priv->max_packet_size); |
472 | } | 494 | } |
@@ -485,9 +507,9 @@ static int ssu100_attach(struct usb_serial *serial) | |||
485 | return -ENOMEM; | 507 | return -ENOMEM; |
486 | } | 508 | } |
487 | 509 | ||
510 | spin_lock_init(&priv->status_lock); | ||
488 | init_waitqueue_head(&priv->delta_msr_wait); | 511 | init_waitqueue_head(&priv->delta_msr_wait); |
489 | usb_set_serial_port_data(port, priv); | 512 | usb_set_serial_port_data(port, priv); |
490 | |||
491 | ssu100_set_max_packet_size(port); | 513 | ssu100_set_max_packet_size(port); |
492 | 514 | ||
493 | return ssu100_initdevice(serial->dev); | 515 | return ssu100_initdevice(serial->dev); |
@@ -506,20 +528,20 @@ static int ssu100_tiocmget(struct tty_struct *tty, struct file *file) | |||
506 | if (!d) | 528 | if (!d) |
507 | return -ENOMEM; | 529 | return -ENOMEM; |
508 | 530 | ||
509 | r = ssu100_getregister(dev, 0, MODEM_CTL_REGISTER, d); | 531 | r = ssu100_getregister(dev, 0, UART_MCR, d); |
510 | if (r < 0) | 532 | if (r < 0) |
511 | goto mget_out; | 533 | goto mget_out; |
512 | 534 | ||
513 | r = ssu100_getregister(dev, 0, MODEM_STATUS_REGISTER, d+1); | 535 | r = ssu100_getregister(dev, 0, UART_MSR, d+1); |
514 | if (r < 0) | 536 | if (r < 0) |
515 | goto mget_out; | 537 | goto mget_out; |
516 | 538 | ||
517 | r = (d[0] & SERIAL_MCR_DTR ? TIOCM_DTR : 0) | | 539 | r = (d[0] & UART_MCR_DTR ? TIOCM_DTR : 0) | |
518 | (d[0] & SERIAL_MCR_RTS ? TIOCM_RTS : 0) | | 540 | (d[0] & UART_MCR_RTS ? TIOCM_RTS : 0) | |
519 | (d[1] & SERIAL_MSR_CTS ? TIOCM_CTS : 0) | | 541 | (d[1] & UART_MSR_CTS ? TIOCM_CTS : 0) | |
520 | (d[1] & SERIAL_MSR_CD ? TIOCM_CAR : 0) | | 542 | (d[1] & UART_MSR_DCD ? TIOCM_CAR : 0) | |
521 | (d[1] & SERIAL_MSR_RI ? TIOCM_RI : 0) | | 543 | (d[1] & UART_MSR_RI ? TIOCM_RI : 0) | |
522 | (d[1] & SERIAL_MSR_DSR ? TIOCM_DSR : 0); | 544 | (d[1] & UART_MSR_DSR ? TIOCM_DSR : 0); |
523 | 545 | ||
524 | mget_out: | 546 | mget_out: |
525 | kfree(d); | 547 | kfree(d); |
@@ -546,7 +568,7 @@ static void ssu100_dtr_rts(struct usb_serial_port *port, int on) | |||
546 | if (!port->serial->disconnected) { | 568 | if (!port->serial->disconnected) { |
547 | /* Disable flow control */ | 569 | /* Disable flow control */ |
548 | if (!on && | 570 | if (!on && |
549 | ssu100_setregister(dev, 0, 0) < 0) | 571 | ssu100_setregister(dev, 0, UART_MCR, 0) < 0) |
550 | dev_err(&port->dev, "error from flowcontrol urb\n"); | 572 | dev_err(&port->dev, "error from flowcontrol urb\n"); |
551 | /* drop RTS and DTR */ | 573 | /* drop RTS and DTR */ |
552 | if (on) | 574 | if (on) |
@@ -557,34 +579,88 @@ static void ssu100_dtr_rts(struct usb_serial_port *port, int on) | |||
557 | mutex_unlock(&port->serial->disc_mutex); | 579 | mutex_unlock(&port->serial->disc_mutex); |
558 | } | 580 | } |
559 | 581 | ||
582 | static void ssu100_update_msr(struct usb_serial_port *port, u8 msr) | ||
583 | { | ||
584 | struct ssu100_port_private *priv = usb_get_serial_port_data(port); | ||
585 | unsigned long flags; | ||
586 | |||
587 | spin_lock_irqsave(&priv->status_lock, flags); | ||
588 | priv->shadowMSR = msr; | ||
589 | spin_unlock_irqrestore(&priv->status_lock, flags); | ||
590 | |||
591 | if (msr & UART_MSR_ANY_DELTA) { | ||
592 | /* update input line counters */ | ||
593 | if (msr & UART_MSR_DCTS) | ||
594 | priv->icount.cts++; | ||
595 | if (msr & UART_MSR_DDSR) | ||
596 | priv->icount.dsr++; | ||
597 | if (msr & UART_MSR_DDCD) | ||
598 | priv->icount.dcd++; | ||
599 | if (msr & UART_MSR_TERI) | ||
600 | priv->icount.rng++; | ||
601 | wake_up_interruptible(&priv->delta_msr_wait); | ||
602 | } | ||
603 | } | ||
604 | |||
605 | static void ssu100_update_lsr(struct usb_serial_port *port, u8 lsr, | ||
606 | char *tty_flag) | ||
607 | { | ||
608 | struct ssu100_port_private *priv = usb_get_serial_port_data(port); | ||
609 | unsigned long flags; | ||
610 | |||
611 | spin_lock_irqsave(&priv->status_lock, flags); | ||
612 | priv->shadowLSR = lsr; | ||
613 | spin_unlock_irqrestore(&priv->status_lock, flags); | ||
614 | |||
615 | *tty_flag = TTY_NORMAL; | ||
616 | if (lsr & UART_LSR_BRK_ERROR_BITS) { | ||
617 | /* we always want to update icount, but we only want to | ||
618 | * update tty_flag for one case */ | ||
619 | if (lsr & UART_LSR_BI) { | ||
620 | priv->icount.brk++; | ||
621 | *tty_flag = TTY_BREAK; | ||
622 | usb_serial_handle_break(port); | ||
623 | } | ||
624 | if (lsr & UART_LSR_PE) { | ||
625 | priv->icount.parity++; | ||
626 | if (*tty_flag == TTY_NORMAL) | ||
627 | *tty_flag = TTY_PARITY; | ||
628 | } | ||
629 | if (lsr & UART_LSR_FE) { | ||
630 | priv->icount.frame++; | ||
631 | if (*tty_flag == TTY_NORMAL) | ||
632 | *tty_flag = TTY_FRAME; | ||
633 | } | ||
634 | if (lsr & UART_LSR_OE){ | ||
635 | priv->icount.overrun++; | ||
636 | if (*tty_flag == TTY_NORMAL) | ||
637 | *tty_flag = TTY_OVERRUN; | ||
638 | } | ||
639 | } | ||
640 | |||
641 | } | ||
642 | |||
560 | static int ssu100_process_packet(struct tty_struct *tty, | 643 | static int ssu100_process_packet(struct tty_struct *tty, |
561 | struct usb_serial_port *port, | 644 | struct usb_serial_port *port, |
562 | struct ssu100_port_private *priv, | 645 | struct ssu100_port_private *priv, |
563 | char *packet, int len) | 646 | char *packet, int len) |
564 | { | 647 | { |
565 | int i; | 648 | int i; |
566 | char flag; | 649 | char flag = TTY_NORMAL; |
567 | char *ch; | 650 | char *ch; |
568 | 651 | ||
569 | dbg("%s - port %d", __func__, port->number); | 652 | dbg("%s - port %d", __func__, port->number); |
570 | 653 | ||
571 | if (len < 4) { | 654 | if ((len >= 4) && |
572 | dbg("%s - malformed packet", __func__); | 655 | (packet[0] == 0x1b) && (packet[1] == 0x1b) && |
573 | return 0; | ||
574 | } | ||
575 | |||
576 | if ((packet[0] == 0x1b) && (packet[1] == 0x1b) && | ||
577 | ((packet[2] == 0x00) || (packet[2] == 0x01))) { | 656 | ((packet[2] == 0x00) || (packet[2] == 0x01))) { |
578 | if (packet[2] == 0x00) | 657 | if (packet[2] == 0x00) { |
579 | priv->shadowLSR = packet[3] & (SERIAL_LSR_OE | | 658 | ssu100_update_lsr(port, packet[3], &flag); |
580 | SERIAL_LSR_PE | | 659 | if (flag == TTY_OVERRUN) |
581 | SERIAL_LSR_FE | | 660 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); |
582 | SERIAL_LSR_BI); | ||
583 | |||
584 | if (packet[2] == 0x01) { | ||
585 | priv->shadowMSR = packet[3]; | ||
586 | wake_up_interruptible(&priv->delta_msr_wait); | ||
587 | } | 661 | } |
662 | if (packet[2] == 0x01) | ||
663 | ssu100_update_msr(port, packet[3]); | ||
588 | 664 | ||
589 | len -= 4; | 665 | len -= 4; |
590 | ch = packet + 4; | 666 | ch = packet + 4; |
@@ -596,7 +672,7 @@ static int ssu100_process_packet(struct tty_struct *tty, | |||
596 | 672 | ||
597 | if (port->port.console && port->sysrq) { | 673 | if (port->port.console && port->sysrq) { |
598 | for (i = 0; i < len; i++, ch++) { | 674 | for (i = 0; i < len; i++, ch++) { |
599 | if (!usb_serial_handle_sysrq_char(tty, port, *ch)) | 675 | if (!usb_serial_handle_sysrq_char(port, *ch)) |
600 | tty_insert_flip_char(tty, *ch, flag); | 676 | tty_insert_flip_char(tty, *ch, flag); |
601 | } | 677 | } |
602 | } else | 678 | } else |
@@ -631,7 +707,6 @@ static void ssu100_process_read_urb(struct urb *urb) | |||
631 | tty_kref_put(tty); | 707 | tty_kref_put(tty); |
632 | } | 708 | } |
633 | 709 | ||
634 | |||
635 | static struct usb_serial_driver ssu100_device = { | 710 | static struct usb_serial_driver ssu100_device = { |
636 | .driver = { | 711 | .driver = { |
637 | .owner = THIS_MODULE, | 712 | .owner = THIS_MODULE, |
@@ -653,6 +728,7 @@ static struct usb_serial_driver ssu100_device = { | |||
653 | .tiocmset = ssu100_tiocmset, | 728 | .tiocmset = ssu100_tiocmset, |
654 | .ioctl = ssu100_ioctl, | 729 | .ioctl = ssu100_ioctl, |
655 | .set_termios = ssu100_set_termios, | 730 | .set_termios = ssu100_set_termios, |
731 | .disconnect = usb_serial_generic_disconnect, | ||
656 | }; | 732 | }; |
657 | 733 | ||
658 | static int __init ssu100_init(void) | 734 | static int __init ssu100_init(void) |