diff options
author | Johan Hovold <jhovold@gmail.com> | 2010-05-13 15:02:03 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-05-20 16:21:46 -0400 |
commit | f4a4cbb2047ec6b0175a08e5bcd78a697773390d (patch) | |
tree | d0fcb5bf284dbfc82775524bbc7f8fc240429b10 /drivers/usb | |
parent | df66e8a2afef506e303f931741193c7cf8fe0794 (diff) |
USB: ir-usb: reimplement using generic framework
Compile-only tested.
Signed-off-by: Johan Hovold <jhovold@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/serial/ir-usb.c | 197 |
1 files changed, 38 insertions, 159 deletions
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c index d8490eaeb234..e7087f9fe479 100644 --- a/drivers/usb/serial/ir-usb.c +++ b/drivers/usb/serial/ir-usb.c | |||
@@ -3,6 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2001-2002 Greg Kroah-Hartman (greg@kroah.com) | 4 | * Copyright (C) 2001-2002 Greg Kroah-Hartman (greg@kroah.com) |
5 | * Copyright (C) 2002 Gary Brubaker (xavyer@ix.netcom.com) | 5 | * Copyright (C) 2002 Gary Brubaker (xavyer@ix.netcom.com) |
6 | * Copyright (C) 2010 Johan Hovold (jhovold@gmail.com) | ||
6 | * | 7 | * |
7 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
@@ -72,8 +73,8 @@ | |||
72 | /* | 73 | /* |
73 | * Version Information | 74 | * Version Information |
74 | */ | 75 | */ |
75 | #define DRIVER_VERSION "v0.4" | 76 | #define DRIVER_VERSION "v0.5" |
76 | #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>" | 77 | #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Johan Hovold <jhovold@gmail.com>" |
77 | #define DRIVER_DESC "USB IR Dongle driver" | 78 | #define DRIVER_DESC "USB IR Dongle driver" |
78 | 79 | ||
79 | static int debug; | 80 | static int debug; |
@@ -87,11 +88,9 @@ static int xbof = -1; | |||
87 | 88 | ||
88 | static int ir_startup (struct usb_serial *serial); | 89 | static int ir_startup (struct usb_serial *serial); |
89 | static int ir_open(struct tty_struct *tty, struct usb_serial_port *port); | 90 | static int ir_open(struct tty_struct *tty, struct usb_serial_port *port); |
90 | static void ir_close(struct usb_serial_port *port); | 91 | static int ir_prepare_write_buffer(struct usb_serial_port *port, |
91 | static int ir_write(struct tty_struct *tty, struct usb_serial_port *port, | 92 | void *dest, size_t size); |
92 | const unsigned char *buf, int count); | 93 | static void ir_process_read_urb(struct urb *urb); |
93 | static void ir_write_bulk_callback (struct urb *urb); | ||
94 | static void ir_read_bulk_callback (struct urb *urb); | ||
95 | static void ir_set_termios(struct tty_struct *tty, | 94 | static void ir_set_termios(struct tty_struct *tty, |
96 | struct usb_serial_port *port, struct ktermios *old_termios); | 95 | struct usb_serial_port *port, struct ktermios *old_termios); |
97 | 96 | ||
@@ -130,10 +129,8 @@ static struct usb_serial_driver ir_device = { | |||
130 | .set_termios = ir_set_termios, | 129 | .set_termios = ir_set_termios, |
131 | .attach = ir_startup, | 130 | .attach = ir_startup, |
132 | .open = ir_open, | 131 | .open = ir_open, |
133 | .close = ir_close, | 132 | .prepare_write_buffer = ir_prepare_write_buffer, |
134 | .write = ir_write, | 133 | .process_read_urb = ir_process_read_urb, |
135 | .write_bulk_callback = ir_write_bulk_callback, | ||
136 | .read_bulk_callback = ir_read_bulk_callback, | ||
137 | }; | 134 | }; |
138 | 135 | ||
139 | static inline void irda_usb_dump_class_desc(struct usb_irda_cs_descriptor *desc) | 136 | static inline void irda_usb_dump_class_desc(struct usb_irda_cs_descriptor *desc) |
@@ -198,7 +195,6 @@ error: | |||
198 | return NULL; | 195 | return NULL; |
199 | } | 196 | } |
200 | 197 | ||
201 | |||
202 | static u8 ir_xbof_change(u8 xbof) | 198 | static u8 ir_xbof_change(u8 xbof) |
203 | { | 199 | { |
204 | u8 result; | 200 | u8 result; |
@@ -237,7 +233,6 @@ static u8 ir_xbof_change(u8 xbof) | |||
237 | return(result); | 233 | return(result); |
238 | } | 234 | } |
239 | 235 | ||
240 | |||
241 | static int ir_startup(struct usb_serial *serial) | 236 | static int ir_startup(struct usb_serial *serial) |
242 | { | 237 | { |
243 | struct usb_irda_cs_descriptor *irda_desc; | 238 | struct usb_irda_cs_descriptor *irda_desc; |
@@ -297,60 +292,21 @@ static int ir_startup(struct usb_serial *serial) | |||
297 | 292 | ||
298 | static int ir_open(struct tty_struct *tty, struct usb_serial_port *port) | 293 | static int ir_open(struct tty_struct *tty, struct usb_serial_port *port) |
299 | { | 294 | { |
300 | int result = 0; | 295 | int i; |
301 | 296 | ||
302 | dbg("%s - port %d", __func__, port->number); | 297 | dbg("%s - port %d", __func__, port->number); |
303 | 298 | ||
304 | /* Start reading from the device */ | 299 | for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) |
305 | usb_fill_bulk_urb( | 300 | port->write_urbs[i]->transfer_flags = URB_ZERO_PACKET; |
306 | port->read_urb, | ||
307 | port->serial->dev, | ||
308 | usb_rcvbulkpipe(port->serial->dev, | ||
309 | port->bulk_in_endpointAddress), | ||
310 | port->read_urb->transfer_buffer, | ||
311 | port->read_urb->transfer_buffer_length, | ||
312 | ir_read_bulk_callback, | ||
313 | port); | ||
314 | result = usb_submit_urb(port->read_urb, GFP_KERNEL); | ||
315 | if (result) | ||
316 | dev_err(&port->dev, | ||
317 | "%s - failed submitting read urb, error %d\n", | ||
318 | __func__, result); | ||
319 | |||
320 | return result; | ||
321 | } | ||
322 | |||
323 | static void ir_close(struct usb_serial_port *port) | ||
324 | { | ||
325 | dbg("%s - port %d", __func__, port->number); | ||
326 | 301 | ||
327 | /* shutdown our bulk read */ | 302 | /* Start reading from the device */ |
328 | usb_kill_urb(port->read_urb); | 303 | return usb_serial_generic_open(tty, port); |
329 | } | 304 | } |
330 | 305 | ||
331 | static int ir_write(struct tty_struct *tty, struct usb_serial_port *port, | 306 | static int ir_prepare_write_buffer(struct usb_serial_port *port, |
332 | const unsigned char *buf, int count) | 307 | void *dest, size_t size) |
333 | { | 308 | { |
334 | unsigned char *transfer_buffer; | 309 | unsigned char *buf = dest; |
335 | int result; | ||
336 | int transfer_size; | ||
337 | |||
338 | dbg("%s - port = %d, count = %d", __func__, port->number, count); | ||
339 | |||
340 | if (count == 0) | ||
341 | return 0; | ||
342 | |||
343 | spin_lock_bh(&port->lock); | ||
344 | if (port->write_urb_busy) { | ||
345 | spin_unlock_bh(&port->lock); | ||
346 | dbg("%s - already writing", __func__); | ||
347 | return 0; | ||
348 | } | ||
349 | port->write_urb_busy = 1; | ||
350 | spin_unlock_bh(&port->lock); | ||
351 | |||
352 | transfer_buffer = port->write_urb->transfer_buffer; | ||
353 | transfer_size = min(count, port->bulk_out_size - 1); | ||
354 | 310 | ||
355 | /* | 311 | /* |
356 | * The first byte of the packet we send to the device contains an | 312 | * The first byte of the packet we send to the device contains an |
@@ -359,114 +315,37 @@ static int ir_write(struct tty_struct *tty, struct usb_serial_port *port, | |||
359 | * | 315 | * |
360 | * See section 5.4.2.2 of the USB IrDA spec. | 316 | * See section 5.4.2.2 of the USB IrDA spec. |
361 | */ | 317 | */ |
362 | *transfer_buffer = ir_xbof | ir_baud; | 318 | *buf = ir_xbof | ir_baud; |
363 | ++transfer_buffer; | ||
364 | |||
365 | memcpy(transfer_buffer, buf, transfer_size); | ||
366 | |||
367 | usb_fill_bulk_urb( | ||
368 | port->write_urb, | ||
369 | port->serial->dev, | ||
370 | usb_sndbulkpipe(port->serial->dev, | ||
371 | port->bulk_out_endpointAddress), | ||
372 | port->write_urb->transfer_buffer, | ||
373 | transfer_size + 1, | ||
374 | ir_write_bulk_callback, | ||
375 | port); | ||
376 | 319 | ||
377 | port->write_urb->transfer_flags = URB_ZERO_PACKET; | 320 | return kfifo_out_locked(&port->write_fifo, buf + 1, size - 1, |
378 | 321 | &port->lock); | |
379 | result = usb_submit_urb(port->write_urb, GFP_ATOMIC); | ||
380 | if (result) { | ||
381 | port->write_urb_busy = 0; | ||
382 | dev_err(&port->dev, | ||
383 | "%s - failed submitting write urb, error %d\n", | ||
384 | __func__, result); | ||
385 | } else | ||
386 | result = transfer_size; | ||
387 | |||
388 | return result; | ||
389 | } | 322 | } |
390 | 323 | ||
391 | static void ir_write_bulk_callback(struct urb *urb) | 324 | static void ir_process_read_urb(struct urb *urb) |
392 | { | 325 | { |
393 | struct usb_serial_port *port = urb->context; | 326 | struct usb_serial_port *port = urb->context; |
394 | int status = urb->status; | 327 | unsigned char *data = urb->transfer_buffer; |
395 | 328 | struct tty_struct *tty; | |
396 | dbg("%s - port %d", __func__, port->number); | ||
397 | 329 | ||
398 | port->write_urb_busy = 0; | 330 | if (!urb->actual_length) |
399 | if (status) { | ||
400 | dbg("%s - nonzero write bulk status received: %d", | ||
401 | __func__, status); | ||
402 | return; | 331 | return; |
403 | } | 332 | /* |
404 | 333 | * The first byte of the packet we get from the device | |
405 | usb_serial_debug_data( | 334 | * contains a busy indicator and baud rate change. |
406 | debug, | 335 | * See section 5.4.1.2 of the USB IrDA spec. |
407 | &port->dev, | 336 | */ |
408 | __func__, | 337 | if (*data & 0x0f) |
409 | urb->actual_length, | 338 | ir_baud = *data & 0x0f; |
410 | urb->transfer_buffer); | ||
411 | |||
412 | usb_serial_port_softint(port); | ||
413 | } | ||
414 | |||
415 | static void ir_read_bulk_callback(struct urb *urb) | ||
416 | { | ||
417 | struct usb_serial_port *port = urb->context; | ||
418 | struct tty_struct *tty; | ||
419 | unsigned char *data = urb->transfer_buffer; | ||
420 | int result; | ||
421 | int status = urb->status; | ||
422 | 339 | ||
423 | dbg("%s - port %d", __func__, port->number); | 340 | if (urb->actual_length == 1) |
341 | return; | ||
424 | 342 | ||
425 | switch (status) { | 343 | tty = tty_port_tty_get(&port->port); |
426 | case 0: /* Successful */ | 344 | if (!tty) |
427 | /* | 345 | return; |
428 | * The first byte of the packet we get from the device | 346 | tty_insert_flip_string(tty, data + 1, urb->actual_length - 1); |
429 | * contains a busy indicator and baud rate change. | 347 | tty_flip_buffer_push(tty); |
430 | * See section 5.4.1.2 of the USB IrDA spec. | 348 | tty_kref_put(tty); |
431 | */ | ||
432 | if ((*data & 0x0f) > 0) | ||
433 | ir_baud = *data & 0x0f; | ||
434 | usb_serial_debug_data(debug, &port->dev, __func__, | ||
435 | urb->actual_length, data); | ||
436 | tty = tty_port_tty_get(&port->port); | ||
437 | tty_insert_flip_string(tty, data+1, urb->actual_length - 1); | ||
438 | tty_flip_buffer_push(tty); | ||
439 | tty_kref_put(tty); | ||
440 | |||
441 | /* | ||
442 | * No break here. | ||
443 | * We want to resubmit the urb so we can read | ||
444 | * again. | ||
445 | */ | ||
446 | |||
447 | case -EPROTO: /* taking inspiration from pl2303.c */ | ||
448 | /* Continue trying to always read */ | ||
449 | usb_fill_bulk_urb( | ||
450 | port->read_urb, | ||
451 | port->serial->dev, | ||
452 | usb_rcvbulkpipe(port->serial->dev, | ||
453 | port->bulk_in_endpointAddress), | ||
454 | port->read_urb->transfer_buffer, | ||
455 | port->read_urb->transfer_buffer_length, | ||
456 | ir_read_bulk_callback, | ||
457 | port); | ||
458 | |||
459 | result = usb_submit_urb(port->read_urb, GFP_ATOMIC); | ||
460 | if (result) | ||
461 | dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", | ||
462 | __func__, result); | ||
463 | break ; | ||
464 | default: | ||
465 | dbg("%s - nonzero read bulk status received: %d", | ||
466 | __func__, status); | ||
467 | break ; | ||
468 | } | ||
469 | return; | ||
470 | } | 349 | } |
471 | 350 | ||
472 | static void ir_set_termios_callback(struct urb *urb) | 351 | static void ir_set_termios_callback(struct urb *urb) |