diff options
-rw-r--r-- | drivers/usb/serial/pl2303.c | 570 |
1 files changed, 269 insertions, 301 deletions
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 0cd42bf4c6c8..e2d8f9b94eed 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c | |||
@@ -127,65 +127,6 @@ static struct usb_driver pl2303_driver = { | |||
127 | #define UART_OVERRUN_ERROR 0x40 | 127 | #define UART_OVERRUN_ERROR 0x40 |
128 | #define UART_CTS 0x80 | 128 | #define UART_CTS 0x80 |
129 | 129 | ||
130 | /* function prototypes for a PL2303 serial converter */ | ||
131 | static int pl2303_open (struct usb_serial_port *port, struct file *filp); | ||
132 | static void pl2303_close (struct usb_serial_port *port, struct file *filp); | ||
133 | static void pl2303_set_termios (struct usb_serial_port *port, | ||
134 | struct termios *old); | ||
135 | static int pl2303_ioctl (struct usb_serial_port *port, struct file *file, | ||
136 | unsigned int cmd, unsigned long arg); | ||
137 | static void pl2303_read_int_callback (struct urb *urb, struct pt_regs *regs); | ||
138 | static void pl2303_read_bulk_callback (struct urb *urb, struct pt_regs *regs); | ||
139 | static void pl2303_write_bulk_callback (struct urb *urb, struct pt_regs *regs); | ||
140 | static int pl2303_write (struct usb_serial_port *port, | ||
141 | const unsigned char *buf, int count); | ||
142 | static void pl2303_send (struct usb_serial_port *port); | ||
143 | static int pl2303_write_room(struct usb_serial_port *port); | ||
144 | static int pl2303_chars_in_buffer(struct usb_serial_port *port); | ||
145 | static void pl2303_break_ctl(struct usb_serial_port *port,int break_state); | ||
146 | static int pl2303_tiocmget (struct usb_serial_port *port, struct file *file); | ||
147 | static int pl2303_tiocmset (struct usb_serial_port *port, struct file *file, | ||
148 | unsigned int set, unsigned int clear); | ||
149 | static int pl2303_startup (struct usb_serial *serial); | ||
150 | static void pl2303_shutdown (struct usb_serial *serial); | ||
151 | static struct pl2303_buf *pl2303_buf_alloc(unsigned int size); | ||
152 | static void pl2303_buf_free(struct pl2303_buf *pb); | ||
153 | static void pl2303_buf_clear(struct pl2303_buf *pb); | ||
154 | static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb); | ||
155 | static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb); | ||
156 | static unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf, | ||
157 | unsigned int count); | ||
158 | static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf, | ||
159 | unsigned int count); | ||
160 | |||
161 | |||
162 | /* All of the device info needed for the PL2303 SIO serial converter */ | ||
163 | static struct usb_serial_driver pl2303_device = { | ||
164 | .driver = { | ||
165 | .owner = THIS_MODULE, | ||
166 | .name = "pl2303", | ||
167 | }, | ||
168 | .id_table = id_table, | ||
169 | .num_interrupt_in = NUM_DONT_CARE, | ||
170 | .num_bulk_in = 1, | ||
171 | .num_bulk_out = 1, | ||
172 | .num_ports = 1, | ||
173 | .open = pl2303_open, | ||
174 | .close = pl2303_close, | ||
175 | .write = pl2303_write, | ||
176 | .ioctl = pl2303_ioctl, | ||
177 | .break_ctl = pl2303_break_ctl, | ||
178 | .set_termios = pl2303_set_termios, | ||
179 | .tiocmget = pl2303_tiocmget, | ||
180 | .tiocmset = pl2303_tiocmset, | ||
181 | .read_bulk_callback = pl2303_read_bulk_callback, | ||
182 | .read_int_callback = pl2303_read_int_callback, | ||
183 | .write_bulk_callback = pl2303_write_bulk_callback, | ||
184 | .write_room = pl2303_write_room, | ||
185 | .chars_in_buffer = pl2303_chars_in_buffer, | ||
186 | .attach = pl2303_startup, | ||
187 | .shutdown = pl2303_shutdown, | ||
188 | }; | ||
189 | 130 | ||
190 | enum pl2303_type { | 131 | enum pl2303_type { |
191 | type_0, /* don't know the difference between type 0 and */ | 132 | type_0, /* don't know the difference between type 0 and */ |
@@ -204,6 +145,164 @@ struct pl2303_private { | |||
204 | enum pl2303_type type; | 145 | enum pl2303_type type; |
205 | }; | 146 | }; |
206 | 147 | ||
148 | /* | ||
149 | * pl2303_buf_alloc | ||
150 | * | ||
151 | * Allocate a circular buffer and all associated memory. | ||
152 | */ | ||
153 | static struct pl2303_buf *pl2303_buf_alloc(unsigned int size) | ||
154 | { | ||
155 | struct pl2303_buf *pb; | ||
156 | |||
157 | if (size == 0) | ||
158 | return NULL; | ||
159 | |||
160 | pb = (struct pl2303_buf *)kmalloc(sizeof(struct pl2303_buf), GFP_KERNEL); | ||
161 | if (pb == NULL) | ||
162 | return NULL; | ||
163 | |||
164 | pb->buf_buf = kmalloc(size, GFP_KERNEL); | ||
165 | if (pb->buf_buf == NULL) { | ||
166 | kfree(pb); | ||
167 | return NULL; | ||
168 | } | ||
169 | |||
170 | pb->buf_size = size; | ||
171 | pb->buf_get = pb->buf_put = pb->buf_buf; | ||
172 | |||
173 | return pb; | ||
174 | } | ||
175 | |||
176 | /* | ||
177 | * pl2303_buf_free | ||
178 | * | ||
179 | * Free the buffer and all associated memory. | ||
180 | */ | ||
181 | static void pl2303_buf_free(struct pl2303_buf *pb) | ||
182 | { | ||
183 | if (pb) { | ||
184 | kfree(pb->buf_buf); | ||
185 | kfree(pb); | ||
186 | } | ||
187 | } | ||
188 | |||
189 | /* | ||
190 | * pl2303_buf_clear | ||
191 | * | ||
192 | * Clear out all data in the circular buffer. | ||
193 | */ | ||
194 | static void pl2303_buf_clear(struct pl2303_buf *pb) | ||
195 | { | ||
196 | if (pb != NULL) | ||
197 | pb->buf_get = pb->buf_put; | ||
198 | /* equivalent to a get of all data available */ | ||
199 | } | ||
200 | |||
201 | /* | ||
202 | * pl2303_buf_data_avail | ||
203 | * | ||
204 | * Return the number of bytes of data available in the circular | ||
205 | * buffer. | ||
206 | */ | ||
207 | static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb) | ||
208 | { | ||
209 | if (pb == NULL) | ||
210 | return 0; | ||
211 | |||
212 | return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size); | ||
213 | } | ||
214 | |||
215 | /* | ||
216 | * pl2303_buf_space_avail | ||
217 | * | ||
218 | * Return the number of bytes of space available in the circular | ||
219 | * buffer. | ||
220 | */ | ||
221 | static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb) | ||
222 | { | ||
223 | if (pb == NULL) | ||
224 | return 0; | ||
225 | |||
226 | return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size); | ||
227 | } | ||
228 | |||
229 | /* | ||
230 | * pl2303_buf_put | ||
231 | * | ||
232 | * Copy data data from a user buffer and put it into the circular buffer. | ||
233 | * Restrict to the amount of space available. | ||
234 | * | ||
235 | * Return the number of bytes copied. | ||
236 | */ | ||
237 | static unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf, | ||
238 | unsigned int count) | ||
239 | { | ||
240 | unsigned int len; | ||
241 | |||
242 | if (pb == NULL) | ||
243 | return 0; | ||
244 | |||
245 | len = pl2303_buf_space_avail(pb); | ||
246 | if (count > len) | ||
247 | count = len; | ||
248 | |||
249 | if (count == 0) | ||
250 | return 0; | ||
251 | |||
252 | len = pb->buf_buf + pb->buf_size - pb->buf_put; | ||
253 | if (count > len) { | ||
254 | memcpy(pb->buf_put, buf, len); | ||
255 | memcpy(pb->buf_buf, buf+len, count - len); | ||
256 | pb->buf_put = pb->buf_buf + count - len; | ||
257 | } else { | ||
258 | memcpy(pb->buf_put, buf, count); | ||
259 | if (count < len) | ||
260 | pb->buf_put += count; | ||
261 | else /* count == len */ | ||
262 | pb->buf_put = pb->buf_buf; | ||
263 | } | ||
264 | |||
265 | return count; | ||
266 | } | ||
267 | |||
268 | /* | ||
269 | * pl2303_buf_get | ||
270 | * | ||
271 | * Get data from the circular buffer and copy to the given buffer. | ||
272 | * Restrict to the amount of data available. | ||
273 | * | ||
274 | * Return the number of bytes copied. | ||
275 | */ | ||
276 | static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf, | ||
277 | unsigned int count) | ||
278 | { | ||
279 | unsigned int len; | ||
280 | |||
281 | if (pb == NULL) | ||
282 | return 0; | ||
283 | |||
284 | len = pl2303_buf_data_avail(pb); | ||
285 | if (count > len) | ||
286 | count = len; | ||
287 | |||
288 | if (count == 0) | ||
289 | return 0; | ||
290 | |||
291 | len = pb->buf_buf + pb->buf_size - pb->buf_get; | ||
292 | if (count > len) { | ||
293 | memcpy(buf, pb->buf_get, len); | ||
294 | memcpy(buf+len, pb->buf_buf, count - len); | ||
295 | pb->buf_get = pb->buf_buf + count - len; | ||
296 | } else { | ||
297 | memcpy(buf, pb->buf_get, count); | ||
298 | if (count < len) | ||
299 | pb->buf_get += count; | ||
300 | else /* count == len */ | ||
301 | pb->buf_get = pb->buf_buf; | ||
302 | } | ||
303 | |||
304 | return count; | ||
305 | } | ||
207 | 306 | ||
208 | static int pl2303_startup(struct usb_serial *serial) | 307 | static int pl2303_startup(struct usb_serial *serial) |
209 | { | 308 | { |
@@ -258,26 +357,6 @@ static int set_control_lines(struct usb_device *dev, u8 value) | |||
258 | return retval; | 357 | return retval; |
259 | } | 358 | } |
260 | 359 | ||
261 | static int pl2303_write(struct usb_serial_port *port, const unsigned char *buf, | ||
262 | int count) | ||
263 | { | ||
264 | struct pl2303_private *priv = usb_get_serial_port_data(port); | ||
265 | unsigned long flags; | ||
266 | |||
267 | dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count); | ||
268 | |||
269 | if (!count) | ||
270 | return count; | ||
271 | |||
272 | spin_lock_irqsave(&priv->lock, flags); | ||
273 | count = pl2303_buf_put(priv->buf, buf, count); | ||
274 | spin_unlock_irqrestore(&priv->lock, flags); | ||
275 | |||
276 | pl2303_send(port); | ||
277 | |||
278 | return count; | ||
279 | } | ||
280 | |||
281 | static void pl2303_send(struct usb_serial_port *port) | 360 | static void pl2303_send(struct usb_serial_port *port) |
282 | { | 361 | { |
283 | int count, result; | 362 | int count, result; |
@@ -321,6 +400,26 @@ static void pl2303_send(struct usb_serial_port *port) | |||
321 | usb_serial_port_softint(port); | 400 | usb_serial_port_softint(port); |
322 | } | 401 | } |
323 | 402 | ||
403 | static int pl2303_write(struct usb_serial_port *port, const unsigned char *buf, | ||
404 | int count) | ||
405 | { | ||
406 | struct pl2303_private *priv = usb_get_serial_port_data(port); | ||
407 | unsigned long flags; | ||
408 | |||
409 | dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count); | ||
410 | |||
411 | if (!count) | ||
412 | return count; | ||
413 | |||
414 | spin_lock_irqsave(&priv->lock, flags); | ||
415 | count = pl2303_buf_put(priv->buf, buf, count); | ||
416 | spin_unlock_irqrestore(&priv->lock, flags); | ||
417 | |||
418 | pl2303_send(port); | ||
419 | |||
420 | return count; | ||
421 | } | ||
422 | |||
324 | static int pl2303_write_room(struct usb_serial_port *port) | 423 | static int pl2303_write_room(struct usb_serial_port *port) |
325 | { | 424 | { |
326 | struct pl2303_private *priv = usb_get_serial_port_data(port); | 425 | struct pl2303_private *priv = usb_get_serial_port_data(port); |
@@ -520,6 +619,70 @@ static void pl2303_set_termios(struct usb_serial_port *port, | |||
520 | kfree(buf); | 619 | kfree(buf); |
521 | } | 620 | } |
522 | 621 | ||
622 | static void pl2303_close(struct usb_serial_port *port, struct file *filp) | ||
623 | { | ||
624 | struct pl2303_private *priv = usb_get_serial_port_data(port); | ||
625 | unsigned long flags; | ||
626 | unsigned int c_cflag; | ||
627 | int bps; | ||
628 | long timeout; | ||
629 | wait_queue_t wait; | ||
630 | |||
631 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
632 | |||
633 | /* wait for data to drain from the buffer */ | ||
634 | spin_lock_irqsave(&priv->lock, flags); | ||
635 | timeout = PL2303_CLOSING_WAIT; | ||
636 | init_waitqueue_entry(&wait, current); | ||
637 | add_wait_queue(&port->tty->write_wait, &wait); | ||
638 | for (;;) { | ||
639 | set_current_state(TASK_INTERRUPTIBLE); | ||
640 | if (pl2303_buf_data_avail(priv->buf) == 0 || | ||
641 | timeout == 0 || signal_pending(current) || | ||
642 | !usb_get_intfdata(port->serial->interface)) /* disconnect */ | ||
643 | break; | ||
644 | spin_unlock_irqrestore(&priv->lock, flags); | ||
645 | timeout = schedule_timeout(timeout); | ||
646 | spin_lock_irqsave(&priv->lock, flags); | ||
647 | } | ||
648 | set_current_state(TASK_RUNNING); | ||
649 | remove_wait_queue(&port->tty->write_wait, &wait); | ||
650 | /* clear out any remaining data in the buffer */ | ||
651 | pl2303_buf_clear(priv->buf); | ||
652 | spin_unlock_irqrestore(&priv->lock, flags); | ||
653 | |||
654 | /* wait for characters to drain from the device */ | ||
655 | /* (this is long enough for the entire 256 byte */ | ||
656 | /* pl2303 hardware buffer to drain with no flow */ | ||
657 | /* control for data rates of 1200 bps or more, */ | ||
658 | /* for lower rates we should really know how much */ | ||
659 | /* data is in the buffer to compute a delay */ | ||
660 | /* that is not unnecessarily long) */ | ||
661 | bps = tty_get_baud_rate(port->tty); | ||
662 | if (bps > 1200) | ||
663 | timeout = max((HZ*2560)/bps,HZ/10); | ||
664 | else | ||
665 | timeout = 2*HZ; | ||
666 | schedule_timeout_interruptible(timeout); | ||
667 | |||
668 | /* shutdown our urbs */ | ||
669 | dbg("%s - shutting down urbs", __FUNCTION__); | ||
670 | usb_kill_urb(port->write_urb); | ||
671 | usb_kill_urb(port->read_urb); | ||
672 | usb_kill_urb(port->interrupt_in_urb); | ||
673 | |||
674 | if (port->tty) { | ||
675 | c_cflag = port->tty->termios->c_cflag; | ||
676 | if (c_cflag & HUPCL) { | ||
677 | /* drop DTR and RTS */ | ||
678 | spin_lock_irqsave(&priv->lock, flags); | ||
679 | priv->line_control = 0; | ||
680 | spin_unlock_irqrestore(&priv->lock, flags); | ||
681 | set_control_lines(port->serial->dev, 0); | ||
682 | } | ||
683 | } | ||
684 | } | ||
685 | |||
523 | static int pl2303_open(struct usb_serial_port *port, struct file *filp) | 686 | static int pl2303_open(struct usb_serial_port *port, struct file *filp) |
524 | { | 687 | { |
525 | struct termios tmp_termios; | 688 | struct termios tmp_termios; |
@@ -601,70 +764,6 @@ static int pl2303_open(struct usb_serial_port *port, struct file *filp) | |||
601 | return 0; | 764 | return 0; |
602 | } | 765 | } |
603 | 766 | ||
604 | static void pl2303_close(struct usb_serial_port *port, struct file *filp) | ||
605 | { | ||
606 | struct pl2303_private *priv = usb_get_serial_port_data(port); | ||
607 | unsigned long flags; | ||
608 | unsigned int c_cflag; | ||
609 | int bps; | ||
610 | long timeout; | ||
611 | wait_queue_t wait; | ||
612 | |||
613 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
614 | |||
615 | /* wait for data to drain from the buffer */ | ||
616 | spin_lock_irqsave(&priv->lock, flags); | ||
617 | timeout = PL2303_CLOSING_WAIT; | ||
618 | init_waitqueue_entry(&wait, current); | ||
619 | add_wait_queue(&port->tty->write_wait, &wait); | ||
620 | for (;;) { | ||
621 | set_current_state(TASK_INTERRUPTIBLE); | ||
622 | if (pl2303_buf_data_avail(priv->buf) == 0 || | ||
623 | timeout == 0 || signal_pending(current) || | ||
624 | !usb_get_intfdata(port->serial->interface)) /* disconnect */ | ||
625 | break; | ||
626 | spin_unlock_irqrestore(&priv->lock, flags); | ||
627 | timeout = schedule_timeout(timeout); | ||
628 | spin_lock_irqsave(&priv->lock, flags); | ||
629 | } | ||
630 | set_current_state(TASK_RUNNING); | ||
631 | remove_wait_queue(&port->tty->write_wait, &wait); | ||
632 | /* clear out any remaining data in the buffer */ | ||
633 | pl2303_buf_clear(priv->buf); | ||
634 | spin_unlock_irqrestore(&priv->lock, flags); | ||
635 | |||
636 | /* wait for characters to drain from the device */ | ||
637 | /* (this is long enough for the entire 256 byte */ | ||
638 | /* pl2303 hardware buffer to drain with no flow */ | ||
639 | /* control for data rates of 1200 bps or more, */ | ||
640 | /* for lower rates we should really know how much */ | ||
641 | /* data is in the buffer to compute a delay */ | ||
642 | /* that is not unnecessarily long) */ | ||
643 | bps = tty_get_baud_rate(port->tty); | ||
644 | if (bps > 1200) | ||
645 | timeout = max((HZ*2560)/bps,HZ/10); | ||
646 | else | ||
647 | timeout = 2*HZ; | ||
648 | schedule_timeout_interruptible(timeout); | ||
649 | |||
650 | /* shutdown our urbs */ | ||
651 | dbg("%s - shutting down urbs", __FUNCTION__); | ||
652 | usb_kill_urb(port->write_urb); | ||
653 | usb_kill_urb(port->read_urb); | ||
654 | usb_kill_urb(port->interrupt_in_urb); | ||
655 | |||
656 | if (port->tty) { | ||
657 | c_cflag = port->tty->termios->c_cflag; | ||
658 | if (c_cflag & HUPCL) { | ||
659 | /* drop DTR and RTS */ | ||
660 | spin_lock_irqsave(&priv->lock, flags); | ||
661 | priv->line_control = 0; | ||
662 | spin_unlock_irqrestore(&priv->lock, flags); | ||
663 | set_control_lines(port->serial->dev, 0); | ||
664 | } | ||
665 | } | ||
666 | } | ||
667 | |||
668 | static int pl2303_tiocmset(struct usb_serial_port *port, struct file *file, | 767 | static int pl2303_tiocmset(struct usb_serial_port *port, struct file *file, |
669 | unsigned int set, unsigned int clear) | 768 | unsigned int set, unsigned int clear) |
670 | { | 769 | { |
@@ -1003,164 +1102,33 @@ static void pl2303_write_bulk_callback(struct urb *urb, struct pt_regs *regs) | |||
1003 | pl2303_send(port); | 1102 | pl2303_send(port); |
1004 | } | 1103 | } |
1005 | 1104 | ||
1006 | /* | 1105 | /* All of the device info needed for the PL2303 SIO serial converter */ |
1007 | * pl2303_buf_alloc | 1106 | static struct usb_serial_driver pl2303_device = { |
1008 | * | 1107 | .driver = { |
1009 | * Allocate a circular buffer and all associated memory. | 1108 | .owner = THIS_MODULE, |
1010 | */ | 1109 | .name = "pl2303", |
1011 | static struct pl2303_buf *pl2303_buf_alloc(unsigned int size) | 1110 | }, |
1012 | { | 1111 | .id_table = id_table, |
1013 | struct pl2303_buf *pb; | 1112 | .num_interrupt_in = NUM_DONT_CARE, |
1014 | 1113 | .num_bulk_in = 1, | |
1015 | if (size == 0) | 1114 | .num_bulk_out = 1, |
1016 | return NULL; | 1115 | .num_ports = 1, |
1017 | 1116 | .open = pl2303_open, | |
1018 | pb = (struct pl2303_buf *)kmalloc(sizeof(struct pl2303_buf), GFP_KERNEL); | 1117 | .close = pl2303_close, |
1019 | if (pb == NULL) | 1118 | .write = pl2303_write, |
1020 | return NULL; | 1119 | .ioctl = pl2303_ioctl, |
1021 | 1120 | .break_ctl = pl2303_break_ctl, | |
1022 | pb->buf_buf = kmalloc(size, GFP_KERNEL); | 1121 | .set_termios = pl2303_set_termios, |
1023 | if (pb->buf_buf == NULL) { | 1122 | .tiocmget = pl2303_tiocmget, |
1024 | kfree(pb); | 1123 | .tiocmset = pl2303_tiocmset, |
1025 | return NULL; | 1124 | .read_bulk_callback = pl2303_read_bulk_callback, |
1026 | } | 1125 | .read_int_callback = pl2303_read_int_callback, |
1027 | 1126 | .write_bulk_callback = pl2303_write_bulk_callback, | |
1028 | pb->buf_size = size; | 1127 | .write_room = pl2303_write_room, |
1029 | pb->buf_get = pb->buf_put = pb->buf_buf; | 1128 | .chars_in_buffer = pl2303_chars_in_buffer, |
1030 | 1129 | .attach = pl2303_startup, | |
1031 | return pb; | 1130 | .shutdown = pl2303_shutdown, |
1032 | } | 1131 | }; |
1033 | |||
1034 | /* | ||
1035 | * pl2303_buf_free | ||
1036 | * | ||
1037 | * Free the buffer and all associated memory. | ||
1038 | */ | ||
1039 | static void pl2303_buf_free(struct pl2303_buf *pb) | ||
1040 | { | ||
1041 | if (pb) { | ||
1042 | kfree(pb->buf_buf); | ||
1043 | kfree(pb); | ||
1044 | } | ||
1045 | } | ||
1046 | |||
1047 | /* | ||
1048 | * pl2303_buf_clear | ||
1049 | * | ||
1050 | * Clear out all data in the circular buffer. | ||
1051 | */ | ||
1052 | static void pl2303_buf_clear(struct pl2303_buf *pb) | ||
1053 | { | ||
1054 | if (pb != NULL) | ||
1055 | pb->buf_get = pb->buf_put; | ||
1056 | /* equivalent to a get of all data available */ | ||
1057 | } | ||
1058 | |||
1059 | /* | ||
1060 | * pl2303_buf_data_avail | ||
1061 | * | ||
1062 | * Return the number of bytes of data available in the circular | ||
1063 | * buffer. | ||
1064 | */ | ||
1065 | static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb) | ||
1066 | { | ||
1067 | if (pb == NULL) | ||
1068 | return 0; | ||
1069 | |||
1070 | return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size); | ||
1071 | } | ||
1072 | |||
1073 | /* | ||
1074 | * pl2303_buf_space_avail | ||
1075 | * | ||
1076 | * Return the number of bytes of space available in the circular | ||
1077 | * buffer. | ||
1078 | */ | ||
1079 | static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb) | ||
1080 | { | ||
1081 | if (pb == NULL) | ||
1082 | return 0; | ||
1083 | |||
1084 | return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size); | ||
1085 | } | ||
1086 | |||
1087 | /* | ||
1088 | * pl2303_buf_put | ||
1089 | * | ||
1090 | * Copy data data from a user buffer and put it into the circular buffer. | ||
1091 | * Restrict to the amount of space available. | ||
1092 | * | ||
1093 | * Return the number of bytes copied. | ||
1094 | */ | ||
1095 | static unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf, | ||
1096 | unsigned int count) | ||
1097 | { | ||
1098 | unsigned int len; | ||
1099 | |||
1100 | if (pb == NULL) | ||
1101 | return 0; | ||
1102 | |||
1103 | len = pl2303_buf_space_avail(pb); | ||
1104 | if (count > len) | ||
1105 | count = len; | ||
1106 | |||
1107 | if (count == 0) | ||
1108 | return 0; | ||
1109 | |||
1110 | len = pb->buf_buf + pb->buf_size - pb->buf_put; | ||
1111 | if (count > len) { | ||
1112 | memcpy(pb->buf_put, buf, len); | ||
1113 | memcpy(pb->buf_buf, buf+len, count - len); | ||
1114 | pb->buf_put = pb->buf_buf + count - len; | ||
1115 | } else { | ||
1116 | memcpy(pb->buf_put, buf, count); | ||
1117 | if (count < len) | ||
1118 | pb->buf_put += count; | ||
1119 | else /* count == len */ | ||
1120 | pb->buf_put = pb->buf_buf; | ||
1121 | } | ||
1122 | |||
1123 | return count; | ||
1124 | } | ||
1125 | |||
1126 | /* | ||
1127 | * pl2303_buf_get | ||
1128 | * | ||
1129 | * Get data from the circular buffer and copy to the given buffer. | ||
1130 | * Restrict to the amount of data available. | ||
1131 | * | ||
1132 | * Return the number of bytes copied. | ||
1133 | */ | ||
1134 | static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf, | ||
1135 | unsigned int count) | ||
1136 | { | ||
1137 | unsigned int len; | ||
1138 | |||
1139 | if (pb == NULL) | ||
1140 | return 0; | ||
1141 | |||
1142 | len = pl2303_buf_data_avail(pb); | ||
1143 | if (count > len) | ||
1144 | count = len; | ||
1145 | |||
1146 | if (count == 0) | ||
1147 | return 0; | ||
1148 | |||
1149 | len = pb->buf_buf + pb->buf_size - pb->buf_get; | ||
1150 | if (count > len) { | ||
1151 | memcpy(buf, pb->buf_get, len); | ||
1152 | memcpy(buf+len, pb->buf_buf, count - len); | ||
1153 | pb->buf_get = pb->buf_buf + count - len; | ||
1154 | } else { | ||
1155 | memcpy(buf, pb->buf_get, count); | ||
1156 | if (count < len) | ||
1157 | pb->buf_get += count; | ||
1158 | else /* count == len */ | ||
1159 | pb->buf_get = pb->buf_buf; | ||
1160 | } | ||
1161 | |||
1162 | return count; | ||
1163 | } | ||
1164 | 1132 | ||
1165 | static int __init pl2303_init(void) | 1133 | static int __init pl2303_init(void) |
1166 | { | 1134 | { |