diff options
-rw-r--r-- | drivers/usb/serial/spcp8x5.c | 407 |
1 files changed, 29 insertions, 378 deletions
diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index 2ea32c561d02..329d311a35d9 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c | |||
@@ -1,6 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * spcp8x5 USB to serial adaptor driver | 2 | * spcp8x5 USB to serial adaptor driver |
3 | * | 3 | * |
4 | * Copyright (C) 2010 Johan Hovold (jhovold@gmail.com) | ||
4 | * Copyright (C) 2006 Linxb (xubin.lin@worldplus.com.cn) | 5 | * Copyright (C) 2006 Linxb (xubin.lin@worldplus.com.cn) |
5 | * Copyright (C) 2006 S1 Corp. | 6 | * Copyright (C) 2006 S1 Corp. |
6 | * | 7 | * |
@@ -29,7 +30,7 @@ | |||
29 | 30 | ||
30 | 31 | ||
31 | /* Version Information */ | 32 | /* Version Information */ |
32 | #define DRIVER_VERSION "v0.04" | 33 | #define DRIVER_VERSION "v0.10" |
33 | #define DRIVER_DESC "SPCP8x5 USB to serial adaptor driver" | 34 | #define DRIVER_DESC "SPCP8x5 USB to serial adaptor driver" |
34 | 35 | ||
35 | static int debug; | 36 | static int debug; |
@@ -64,11 +65,6 @@ struct spcp8x5_usb_ctrl_arg { | |||
64 | u16 length; | 65 | u16 length; |
65 | }; | 66 | }; |
66 | 67 | ||
67 | /* wait 30s before close */ | ||
68 | #define SPCP8x5_CLOSING_WAIT (30*HZ) | ||
69 | |||
70 | #define SPCP8x5_BUF_SIZE 1024 | ||
71 | |||
72 | 68 | ||
73 | /* spcp8x5 spec register define */ | 69 | /* spcp8x5 spec register define */ |
74 | #define MCR_CONTROL_LINE_RTS 0x02 | 70 | #define MCR_CONTROL_LINE_RTS 0x02 |
@@ -155,133 +151,6 @@ enum spcp8x5_type { | |||
155 | SPCP835_TYPE, | 151 | SPCP835_TYPE, |
156 | }; | 152 | }; |
157 | 153 | ||
158 | /* 1st in 1st out buffer 4 driver */ | ||
159 | struct ringbuf { | ||
160 | unsigned int buf_size; | ||
161 | char *buf_buf; | ||
162 | char *buf_get; | ||
163 | char *buf_put; | ||
164 | }; | ||
165 | |||
166 | /* alloc the ring buf and alloc the buffer itself */ | ||
167 | static inline struct ringbuf *alloc_ringbuf(unsigned int size) | ||
168 | { | ||
169 | struct ringbuf *pb; | ||
170 | |||
171 | if (size == 0) | ||
172 | return NULL; | ||
173 | |||
174 | pb = kmalloc(sizeof(*pb), GFP_KERNEL); | ||
175 | if (pb == NULL) | ||
176 | return NULL; | ||
177 | |||
178 | pb->buf_buf = kmalloc(size, GFP_KERNEL); | ||
179 | if (pb->buf_buf == NULL) { | ||
180 | kfree(pb); | ||
181 | return NULL; | ||
182 | } | ||
183 | |||
184 | pb->buf_size = size; | ||
185 | pb->buf_get = pb->buf_put = pb->buf_buf; | ||
186 | |||
187 | return pb; | ||
188 | } | ||
189 | |||
190 | /* free the ring buf and the buffer itself */ | ||
191 | static inline void free_ringbuf(struct ringbuf *pb) | ||
192 | { | ||
193 | if (pb != NULL) { | ||
194 | kfree(pb->buf_buf); | ||
195 | kfree(pb); | ||
196 | } | ||
197 | } | ||
198 | |||
199 | /* clear pipo , juest repoint the pointer here */ | ||
200 | static inline void clear_ringbuf(struct ringbuf *pb) | ||
201 | { | ||
202 | if (pb != NULL) | ||
203 | pb->buf_get = pb->buf_put; | ||
204 | } | ||
205 | |||
206 | /* get the number of data in the pipo */ | ||
207 | static inline unsigned int ringbuf_avail_data(struct ringbuf *pb) | ||
208 | { | ||
209 | if (pb == NULL) | ||
210 | return 0; | ||
211 | return (pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size; | ||
212 | } | ||
213 | |||
214 | /* get the number of space in the pipo */ | ||
215 | static inline unsigned int ringbuf_avail_space(struct ringbuf *pb) | ||
216 | { | ||
217 | if (pb == NULL) | ||
218 | return 0; | ||
219 | return (pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size; | ||
220 | } | ||
221 | |||
222 | /* put count data into pipo */ | ||
223 | static unsigned int put_ringbuf(struct ringbuf *pb, const char *buf, | ||
224 | unsigned int count) | ||
225 | { | ||
226 | unsigned int len; | ||
227 | |||
228 | if (pb == NULL) | ||
229 | return 0; | ||
230 | |||
231 | len = ringbuf_avail_space(pb); | ||
232 | if (count > len) | ||
233 | count = len; | ||
234 | |||
235 | if (count == 0) | ||
236 | return 0; | ||
237 | |||
238 | len = pb->buf_buf + pb->buf_size - pb->buf_put; | ||
239 | if (count > len) { | ||
240 | memcpy(pb->buf_put, buf, len); | ||
241 | memcpy(pb->buf_buf, buf+len, count - len); | ||
242 | pb->buf_put = pb->buf_buf + count - len; | ||
243 | } else { | ||
244 | memcpy(pb->buf_put, buf, count); | ||
245 | if (count < len) | ||
246 | pb->buf_put += count; | ||
247 | else /* count == len */ | ||
248 | pb->buf_put = pb->buf_buf; | ||
249 | } | ||
250 | return count; | ||
251 | } | ||
252 | |||
253 | /* get count data from pipo */ | ||
254 | static unsigned int get_ringbuf(struct ringbuf *pb, char *buf, | ||
255 | unsigned int count) | ||
256 | { | ||
257 | unsigned int len; | ||
258 | |||
259 | if (pb == NULL || buf == NULL) | ||
260 | return 0; | ||
261 | |||
262 | len = ringbuf_avail_data(pb); | ||
263 | if (count > len) | ||
264 | count = len; | ||
265 | |||
266 | if (count == 0) | ||
267 | return 0; | ||
268 | |||
269 | len = pb->buf_buf + pb->buf_size - pb->buf_get; | ||
270 | if (count > len) { | ||
271 | memcpy(buf, pb->buf_get, len); | ||
272 | memcpy(buf+len, pb->buf_buf, count - len); | ||
273 | pb->buf_get = pb->buf_buf + count - len; | ||
274 | } else { | ||
275 | memcpy(buf, pb->buf_get, count); | ||
276 | if (count < len) | ||
277 | pb->buf_get += count; | ||
278 | else /* count == len */ | ||
279 | pb->buf_get = pb->buf_buf; | ||
280 | } | ||
281 | |||
282 | return count; | ||
283 | } | ||
284 | |||
285 | static struct usb_driver spcp8x5_driver = { | 154 | static struct usb_driver spcp8x5_driver = { |
286 | .name = "spcp8x5", | 155 | .name = "spcp8x5", |
287 | .probe = usb_serial_probe, | 156 | .probe = usb_serial_probe, |
@@ -293,8 +162,6 @@ static struct usb_driver spcp8x5_driver = { | |||
293 | 162 | ||
294 | struct spcp8x5_private { | 163 | struct spcp8x5_private { |
295 | spinlock_t lock; | 164 | spinlock_t lock; |
296 | struct ringbuf *buf; | ||
297 | int write_urb_in_use; | ||
298 | enum spcp8x5_type type; | 165 | enum spcp8x5_type type; |
299 | wait_queue_head_t delta_msr_wait; | 166 | wait_queue_head_t delta_msr_wait; |
300 | u8 line_control; | 167 | u8 line_control; |
@@ -330,24 +197,15 @@ static int spcp8x5_startup(struct usb_serial *serial) | |||
330 | goto cleanup; | 197 | goto cleanup; |
331 | 198 | ||
332 | spin_lock_init(&priv->lock); | 199 | spin_lock_init(&priv->lock); |
333 | priv->buf = alloc_ringbuf(SPCP8x5_BUF_SIZE); | ||
334 | if (priv->buf == NULL) | ||
335 | goto cleanup2; | ||
336 | |||
337 | init_waitqueue_head(&priv->delta_msr_wait); | 200 | init_waitqueue_head(&priv->delta_msr_wait); |
338 | priv->type = type; | 201 | priv->type = type; |
339 | usb_set_serial_port_data(serial->port[i] , priv); | 202 | usb_set_serial_port_data(serial->port[i] , priv); |
340 | |||
341 | } | 203 | } |
342 | 204 | ||
343 | return 0; | 205 | return 0; |
344 | |||
345 | cleanup2: | ||
346 | kfree(priv); | ||
347 | cleanup: | 206 | cleanup: |
348 | for (--i; i >= 0; --i) { | 207 | for (--i; i >= 0; --i) { |
349 | priv = usb_get_serial_port_data(serial->port[i]); | 208 | priv = usb_get_serial_port_data(serial->port[i]); |
350 | free_ringbuf(priv->buf); | ||
351 | kfree(priv); | 209 | kfree(priv); |
352 | usb_set_serial_port_data(serial->port[i] , NULL); | 210 | usb_set_serial_port_data(serial->port[i] , NULL); |
353 | } | 211 | } |
@@ -358,15 +216,9 @@ cleanup: | |||
358 | static void spcp8x5_release(struct usb_serial *serial) | 216 | static void spcp8x5_release(struct usb_serial *serial) |
359 | { | 217 | { |
360 | int i; | 218 | int i; |
361 | struct spcp8x5_private *priv; | ||
362 | 219 | ||
363 | for (i = 0; i < serial->num_ports; i++) { | 220 | for (i = 0; i < serial->num_ports; i++) |
364 | priv = usb_get_serial_port_data(serial->port[i]); | 221 | kfree(usb_get_serial_port_data(serial->port[i])); |
365 | if (priv) { | ||
366 | free_ringbuf(priv->buf); | ||
367 | kfree(priv); | ||
368 | } | ||
369 | } | ||
370 | } | 222 | } |
371 | 223 | ||
372 | /* set the modem control line of the device. | 224 | /* set the modem control line of the device. |
@@ -470,33 +322,6 @@ static void spcp8x5_dtr_rts(struct usb_serial_port *port, int on) | |||
470 | spcp8x5_set_ctrlLine(port->serial->dev, control , priv->type); | 322 | spcp8x5_set_ctrlLine(port->serial->dev, control , priv->type); |
471 | } | 323 | } |
472 | 324 | ||
473 | /* close the serial port. We should wait for data sending to device 1st and | ||
474 | * then kill all urb. */ | ||
475 | static void spcp8x5_close(struct usb_serial_port *port) | ||
476 | { | ||
477 | struct spcp8x5_private *priv = usb_get_serial_port_data(port); | ||
478 | unsigned long flags; | ||
479 | int result; | ||
480 | |||
481 | dbg("%s - port %d", __func__, port->number); | ||
482 | |||
483 | spin_lock_irqsave(&priv->lock, flags); | ||
484 | /* clear out any remaining data in the buffer */ | ||
485 | clear_ringbuf(priv->buf); | ||
486 | spin_unlock_irqrestore(&priv->lock, flags); | ||
487 | |||
488 | /* kill urb */ | ||
489 | if (port->write_urb != NULL) { | ||
490 | result = usb_unlink_urb(port->write_urb); | ||
491 | if (result) | ||
492 | dev_dbg(&port->dev, | ||
493 | "usb_unlink_urb(write_urb) = %d\n", result); | ||
494 | } | ||
495 | result = usb_unlink_urb(port->read_urb); | ||
496 | if (result) | ||
497 | dev_dbg(&port->dev, "usb_unlink_urb(read_urb) = %d\n", result); | ||
498 | } | ||
499 | |||
500 | static void spcp8x5_init_termios(struct tty_struct *tty) | 325 | static void spcp8x5_init_termios(struct tty_struct *tty) |
501 | { | 326 | { |
502 | /* for the 1st time call this function */ | 327 | /* for the 1st time call this function */ |
@@ -620,7 +445,7 @@ static void spcp8x5_set_termios(struct tty_struct *tty, | |||
620 | } | 445 | } |
621 | 446 | ||
622 | /* open the serial port. do some usb system call. set termios and get the line | 447 | /* open the serial port. do some usb system call. set termios and get the line |
623 | * status of the device. then submit the read urb */ | 448 | * status of the device. */ |
624 | static int spcp8x5_open(struct tty_struct *tty, struct usb_serial_port *port) | 449 | static int spcp8x5_open(struct tty_struct *tty, struct usb_serial_port *port) |
625 | { | 450 | { |
626 | struct ktermios tmp_termios; | 451 | struct ktermios tmp_termios; |
@@ -655,52 +480,21 @@ static int spcp8x5_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
655 | priv->line_status = status & 0xf0 ; | 480 | priv->line_status = status & 0xf0 ; |
656 | spin_unlock_irqrestore(&priv->lock, flags); | 481 | spin_unlock_irqrestore(&priv->lock, flags); |
657 | 482 | ||
658 | dbg("%s - submitting read urb", __func__); | ||
659 | port->read_urb->dev = serial->dev; | ||
660 | ret = usb_submit_urb(port->read_urb, GFP_KERNEL); | ||
661 | if (ret) { | ||
662 | spcp8x5_close(port); | ||
663 | return -EPROTO; | ||
664 | } | ||
665 | port->port.drain_delay = 256; | 483 | port->port.drain_delay = 256; |
666 | return 0; | 484 | |
485 | return usb_serial_generic_open(tty, port); | ||
667 | } | 486 | } |
668 | 487 | ||
669 | /* bulk read call back function. check the status of the urb. if transfer | 488 | static void spcp8x5_process_read_urb(struct urb *urb) |
670 | * failed return. then update the status and the tty send data to tty subsys. | ||
671 | * submit urb again. | ||
672 | */ | ||
673 | static void spcp8x5_read_bulk_callback(struct urb *urb) | ||
674 | { | 489 | { |
675 | struct usb_serial_port *port = urb->context; | 490 | struct usb_serial_port *port = urb->context; |
676 | struct spcp8x5_private *priv = usb_get_serial_port_data(port); | 491 | struct spcp8x5_private *priv = usb_get_serial_port_data(port); |
677 | struct tty_struct *tty; | 492 | struct tty_struct *tty; |
678 | unsigned char *data = urb->transfer_buffer; | 493 | unsigned char *data = urb->transfer_buffer; |
679 | unsigned long flags; | 494 | unsigned long flags; |
680 | int result = urb->status; | ||
681 | u8 status; | 495 | u8 status; |
682 | char tty_flag; | 496 | char tty_flag; |
683 | 497 | ||
684 | dev_dbg(&port->dev, "start, result = %d, urb->actual_length = %d\n,", | ||
685 | result, urb->actual_length); | ||
686 | |||
687 | /* check the urb status */ | ||
688 | if (result) { | ||
689 | if (result == -EPROTO) { | ||
690 | /* spcp8x5 mysteriously fails with -EPROTO */ | ||
691 | /* reschedule the read */ | ||
692 | urb->dev = port->serial->dev; | ||
693 | result = usb_submit_urb(urb , GFP_ATOMIC); | ||
694 | if (result) | ||
695 | dev_dbg(&port->dev, | ||
696 | "failed submitting read urb %d\n", | ||
697 | result); | ||
698 | return; | ||
699 | } | ||
700 | dev_dbg(&port->dev, "unable to handle the error, exiting.\n"); | ||
701 | return; | ||
702 | } | ||
703 | |||
704 | /* get tty_flag from status */ | 498 | /* get tty_flag from status */ |
705 | tty_flag = TTY_NORMAL; | 499 | tty_flag = TTY_NORMAL; |
706 | 500 | ||
@@ -711,141 +505,33 @@ static void spcp8x5_read_bulk_callback(struct urb *urb) | |||
711 | /* wake up the wait for termios */ | 505 | /* wake up the wait for termios */ |
712 | wake_up_interruptible(&priv->delta_msr_wait); | 506 | wake_up_interruptible(&priv->delta_msr_wait); |
713 | 507 | ||
714 | /* break takes precedence over parity, which takes precedence over | 508 | if (!urb->actual_length) |
715 | * framing errors */ | ||
716 | if (status & UART_BREAK_ERROR) | ||
717 | tty_flag = TTY_BREAK; | ||
718 | else if (status & UART_PARITY_ERROR) | ||
719 | tty_flag = TTY_PARITY; | ||
720 | else if (status & UART_FRAME_ERROR) | ||
721 | tty_flag = TTY_FRAME; | ||
722 | dev_dbg(&port->dev, "tty_flag = %d\n", tty_flag); | ||
723 | |||
724 | tty = tty_port_tty_get(&port->port); | ||
725 | if (tty && urb->actual_length) { | ||
726 | /* overrun is special, not associated with a char */ | ||
727 | if (status & UART_OVERRUN_ERROR) | ||
728 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); | ||
729 | tty_insert_flip_string_fixed_flag(tty, data, tty_flag, | ||
730 | urb->actual_length); | ||
731 | tty_flip_buffer_push(tty); | ||
732 | } | ||
733 | tty_kref_put(tty); | ||
734 | |||
735 | /* Schedule the next read */ | ||
736 | urb->dev = port->serial->dev; | ||
737 | result = usb_submit_urb(urb , GFP_ATOMIC); | ||
738 | if (result) | ||
739 | dev_dbg(&port->dev, "failed submitting read urb %d\n", result); | ||
740 | } | ||
741 | |||
742 | /* get data from ring buffer and then write to usb bus */ | ||
743 | static void spcp8x5_send(struct usb_serial_port *port) | ||
744 | { | ||
745 | int count, result; | ||
746 | struct spcp8x5_private *priv = usb_get_serial_port_data(port); | ||
747 | unsigned long flags; | ||
748 | |||
749 | spin_lock_irqsave(&priv->lock, flags); | ||
750 | |||
751 | if (priv->write_urb_in_use) { | ||
752 | dev_dbg(&port->dev, "write urb still used\n"); | ||
753 | spin_unlock_irqrestore(&priv->lock, flags); | ||
754 | return; | 509 | return; |
755 | } | ||
756 | |||
757 | /* send the 1st urb for writting */ | ||
758 | memset(port->write_urb->transfer_buffer , 0x00 , port->bulk_out_size); | ||
759 | count = get_ringbuf(priv->buf, port->write_urb->transfer_buffer, | ||
760 | port->bulk_out_size); | ||
761 | 510 | ||
762 | if (count == 0) { | 511 | tty = tty_port_tty_get(&port->port); |
763 | spin_unlock_irqrestore(&priv->lock, flags); | 512 | if (!tty) |
764 | return; | 513 | return; |
765 | } | ||
766 | |||
767 | /* update the urb status */ | ||
768 | priv->write_urb_in_use = 1; | ||
769 | |||
770 | spin_unlock_irqrestore(&priv->lock, flags); | ||
771 | |||
772 | port->write_urb->transfer_buffer_length = count; | ||
773 | port->write_urb->dev = port->serial->dev; | ||
774 | |||
775 | result = usb_submit_urb(port->write_urb, GFP_ATOMIC); | ||
776 | if (result) { | ||
777 | dev_dbg(&port->dev, "failed submitting write urb, error %d\n", | ||
778 | result); | ||
779 | priv->write_urb_in_use = 0; | ||
780 | /* TODO: reschedule spcp8x5_send */ | ||
781 | } | ||
782 | |||
783 | |||
784 | schedule_work(&port->work); | ||
785 | } | ||
786 | 514 | ||
787 | /* this is the call back function for write urb. NOTE we should not sleep in | 515 | if (status & UART_STATE_TRANSIENT_MASK) { |
788 | * this routine. check the urb return code and then submit the write urb again | 516 | /* break takes precedence over parity, which takes precedence |
789 | * to hold the write loop */ | 517 | * over framing errors */ |
790 | static void spcp8x5_write_bulk_callback(struct urb *urb) | 518 | if (status & UART_BREAK_ERROR) |
791 | { | 519 | tty_flag = TTY_BREAK; |
792 | struct usb_serial_port *port = urb->context; | 520 | else if (status & UART_PARITY_ERROR) |
793 | struct spcp8x5_private *priv = usb_get_serial_port_data(port); | 521 | tty_flag = TTY_PARITY; |
794 | int result; | 522 | else if (status & UART_FRAME_ERROR) |
795 | int status = urb->status; | 523 | tty_flag = TTY_FRAME; |
524 | dev_dbg(&port->dev, "tty_flag = %d\n", tty_flag); | ||
796 | 525 | ||
797 | switch (status) { | 526 | /* overrun is special, not associated with a char */ |
798 | case 0: | 527 | if (status & UART_OVERRUN_ERROR) |
799 | /* success */ | 528 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); |
800 | break; | ||
801 | case -ECONNRESET: | ||
802 | case -ENOENT: | ||
803 | case -ESHUTDOWN: | ||
804 | /* this urb is terminated, clean up */ | ||
805 | dev_dbg(&port->dev, "urb shutting down with status: %d\n", | ||
806 | status); | ||
807 | priv->write_urb_in_use = 0; | ||
808 | return; | ||
809 | default: | ||
810 | /* error in the urb, so we have to resubmit it */ | ||
811 | dbg("%s - Overflow in write", __func__); | ||
812 | dbg("%s - nonzero write bulk status received: %d", | ||
813 | __func__, status); | ||
814 | port->write_urb->transfer_buffer_length = 1; | ||
815 | port->write_urb->dev = port->serial->dev; | ||
816 | result = usb_submit_urb(port->write_urb, GFP_ATOMIC); | ||
817 | if (result) | ||
818 | dev_dbg(&port->dev, | ||
819 | "failed resubmitting write urb %d\n", result); | ||
820 | else | ||
821 | return; | ||
822 | } | 529 | } |
823 | 530 | ||
824 | priv->write_urb_in_use = 0; | 531 | tty_insert_flip_string_fixed_flag(tty, data, tty_flag, |
825 | 532 | urb->actual_length); | |
826 | /* send any buffered data */ | 533 | tty_flip_buffer_push(tty); |
827 | spcp8x5_send(port); | 534 | tty_kref_put(tty); |
828 | } | ||
829 | |||
830 | /* write data to ring buffer. and then start the write transfer */ | ||
831 | static int spcp8x5_write(struct tty_struct *tty, struct usb_serial_port *port, | ||
832 | const unsigned char *buf, int count) | ||
833 | { | ||
834 | struct spcp8x5_private *priv = usb_get_serial_port_data(port); | ||
835 | unsigned long flags; | ||
836 | |||
837 | dev_dbg(&port->dev, "%d bytes\n", count); | ||
838 | |||
839 | if (!count) | ||
840 | return count; | ||
841 | |||
842 | spin_lock_irqsave(&priv->lock, flags); | ||
843 | count = put_ringbuf(priv->buf, buf, count); | ||
844 | spin_unlock_irqrestore(&priv->lock, flags); | ||
845 | |||
846 | spcp8x5_send(port); | ||
847 | |||
848 | return count; | ||
849 | } | 535 | } |
850 | 536 | ||
851 | static int spcp8x5_wait_modem_info(struct usb_serial_port *port, | 537 | static int spcp8x5_wait_modem_info(struct usb_serial_port *port, |
@@ -953,36 +639,6 @@ static int spcp8x5_tiocmget(struct tty_struct *tty, struct file *file) | |||
953 | return result; | 639 | return result; |
954 | } | 640 | } |
955 | 641 | ||
956 | /* get the avail space room in ring buffer */ | ||
957 | static int spcp8x5_write_room(struct tty_struct *tty) | ||
958 | { | ||
959 | struct usb_serial_port *port = tty->driver_data; | ||
960 | struct spcp8x5_private *priv = usb_get_serial_port_data(port); | ||
961 | int room = 0; | ||
962 | unsigned long flags; | ||
963 | |||
964 | spin_lock_irqsave(&priv->lock, flags); | ||
965 | room = ringbuf_avail_space(priv->buf); | ||
966 | spin_unlock_irqrestore(&priv->lock, flags); | ||
967 | |||
968 | return room; | ||
969 | } | ||
970 | |||
971 | /* get the number of avail data in write ring buffer */ | ||
972 | static int spcp8x5_chars_in_buffer(struct tty_struct *tty) | ||
973 | { | ||
974 | struct usb_serial_port *port = tty->driver_data; | ||
975 | struct spcp8x5_private *priv = usb_get_serial_port_data(port); | ||
976 | int chars = 0; | ||
977 | unsigned long flags; | ||
978 | |||
979 | spin_lock_irqsave(&priv->lock, flags); | ||
980 | chars = ringbuf_avail_data(priv->buf); | ||
981 | spin_unlock_irqrestore(&priv->lock, flags); | ||
982 | |||
983 | return chars; | ||
984 | } | ||
985 | |||
986 | /* All of the device info needed for the spcp8x5 SIO serial converter */ | 642 | /* All of the device info needed for the spcp8x5 SIO serial converter */ |
987 | static struct usb_serial_driver spcp8x5_device = { | 643 | static struct usb_serial_driver spcp8x5_device = { |
988 | .driver = { | 644 | .driver = { |
@@ -992,21 +648,16 @@ static struct usb_serial_driver spcp8x5_device = { | |||
992 | .id_table = id_table, | 648 | .id_table = id_table, |
993 | .num_ports = 1, | 649 | .num_ports = 1, |
994 | .open = spcp8x5_open, | 650 | .open = spcp8x5_open, |
995 | .close = spcp8x5_close, | ||
996 | .dtr_rts = spcp8x5_dtr_rts, | 651 | .dtr_rts = spcp8x5_dtr_rts, |
997 | .carrier_raised = spcp8x5_carrier_raised, | 652 | .carrier_raised = spcp8x5_carrier_raised, |
998 | .write = spcp8x5_write, | ||
999 | .set_termios = spcp8x5_set_termios, | 653 | .set_termios = spcp8x5_set_termios, |
1000 | .init_termios = spcp8x5_init_termios, | 654 | .init_termios = spcp8x5_init_termios, |
1001 | .ioctl = spcp8x5_ioctl, | 655 | .ioctl = spcp8x5_ioctl, |
1002 | .tiocmget = spcp8x5_tiocmget, | 656 | .tiocmget = spcp8x5_tiocmget, |
1003 | .tiocmset = spcp8x5_tiocmset, | 657 | .tiocmset = spcp8x5_tiocmset, |
1004 | .write_room = spcp8x5_write_room, | ||
1005 | .read_bulk_callback = spcp8x5_read_bulk_callback, | ||
1006 | .write_bulk_callback = spcp8x5_write_bulk_callback, | ||
1007 | .chars_in_buffer = spcp8x5_chars_in_buffer, | ||
1008 | .attach = spcp8x5_startup, | 658 | .attach = spcp8x5_startup, |
1009 | .release = spcp8x5_release, | 659 | .release = spcp8x5_release, |
660 | .process_read_urb = spcp8x5_process_read_urb, | ||
1010 | }; | 661 | }; |
1011 | 662 | ||
1012 | static int __init spcp8x5_init(void) | 663 | static int __init spcp8x5_init(void) |