diff options
Diffstat (limited to 'drivers/usb/serial/ir-usb.c')
-rw-r--r-- | drivers/usb/serial/ir-usb.c | 272 |
1 files changed, 83 insertions, 189 deletions
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c index 4a0f51974232..ccbce4066d04 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,83 +292,22 @@ 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 | char *buffer; | 295 | int i; |
301 | int result = 0; | ||
302 | 296 | ||
303 | dbg("%s - port %d", __func__, port->number); | 297 | dbg("%s - port %d", __func__, port->number); |
304 | 298 | ||
305 | if (buffer_size) { | 299 | for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) |
306 | /* override the default buffer sizes */ | 300 | port->write_urbs[i]->transfer_flags = URB_ZERO_PACKET; |
307 | buffer = kmalloc(buffer_size, GFP_KERNEL); | ||
308 | if (!buffer) { | ||
309 | dev_err(&port->dev, "%s - out of memory.\n", __func__); | ||
310 | return -ENOMEM; | ||
311 | } | ||
312 | kfree(port->read_urb->transfer_buffer); | ||
313 | port->read_urb->transfer_buffer = buffer; | ||
314 | port->read_urb->transfer_buffer_length = buffer_size; | ||
315 | |||
316 | buffer = kmalloc(buffer_size, GFP_KERNEL); | ||
317 | if (!buffer) { | ||
318 | dev_err(&port->dev, "%s - out of memory.\n", __func__); | ||
319 | return -ENOMEM; | ||
320 | } | ||
321 | kfree(port->write_urb->transfer_buffer); | ||
322 | port->write_urb->transfer_buffer = buffer; | ||
323 | port->write_urb->transfer_buffer_length = buffer_size; | ||
324 | port->bulk_out_size = buffer_size; | ||
325 | } | ||
326 | 301 | ||
327 | /* Start reading from the device */ | 302 | /* Start reading from the device */ |
328 | usb_fill_bulk_urb( | 303 | return usb_serial_generic_open(tty, port); |
329 | port->read_urb, | ||
330 | port->serial->dev, | ||
331 | usb_rcvbulkpipe(port->serial->dev, | ||
332 | port->bulk_in_endpointAddress), | ||
333 | port->read_urb->transfer_buffer, | ||
334 | port->read_urb->transfer_buffer_length, | ||
335 | ir_read_bulk_callback, | ||
336 | port); | ||
337 | result = usb_submit_urb(port->read_urb, GFP_KERNEL); | ||
338 | if (result) | ||
339 | dev_err(&port->dev, | ||
340 | "%s - failed submitting read urb, error %d\n", | ||
341 | __func__, result); | ||
342 | |||
343 | return result; | ||
344 | } | 304 | } |
345 | 305 | ||
346 | static void ir_close(struct usb_serial_port *port) | 306 | static int ir_prepare_write_buffer(struct usb_serial_port *port, |
307 | void *dest, size_t size) | ||
347 | { | 308 | { |
348 | dbg("%s - port %d", __func__, port->number); | 309 | unsigned char *buf = dest; |
349 | 310 | int count; | |
350 | /* shutdown our bulk read */ | ||
351 | usb_kill_urb(port->read_urb); | ||
352 | } | ||
353 | |||
354 | static int ir_write(struct tty_struct *tty, struct usb_serial_port *port, | ||
355 | const unsigned char *buf, int count) | ||
356 | { | ||
357 | unsigned char *transfer_buffer; | ||
358 | int result; | ||
359 | int transfer_size; | ||
360 | |||
361 | dbg("%s - port = %d, count = %d", __func__, port->number, count); | ||
362 | |||
363 | if (count == 0) | ||
364 | return 0; | ||
365 | |||
366 | spin_lock_bh(&port->lock); | ||
367 | if (port->write_urb_busy) { | ||
368 | spin_unlock_bh(&port->lock); | ||
369 | dbg("%s - already writing", __func__); | ||
370 | return 0; | ||
371 | } | ||
372 | port->write_urb_busy = 1; | ||
373 | spin_unlock_bh(&port->lock); | ||
374 | |||
375 | transfer_buffer = port->write_urb->transfer_buffer; | ||
376 | transfer_size = min(count, port->bulk_out_size - 1); | ||
377 | 311 | ||
378 | /* | 312 | /* |
379 | * The first byte of the packet we send to the device contains an | 313 | * The first byte of the packet we send to the device contains an |
@@ -382,119 +316,57 @@ static int ir_write(struct tty_struct *tty, struct usb_serial_port *port, | |||
382 | * | 316 | * |
383 | * See section 5.4.2.2 of the USB IrDA spec. | 317 | * See section 5.4.2.2 of the USB IrDA spec. |
384 | */ | 318 | */ |
385 | *transfer_buffer = ir_xbof | ir_baud; | 319 | *buf = ir_xbof | ir_baud; |
386 | ++transfer_buffer; | ||
387 | |||
388 | memcpy(transfer_buffer, buf, transfer_size); | ||
389 | 320 | ||
390 | usb_fill_bulk_urb( | 321 | count = kfifo_out_locked(&port->write_fifo, buf + 1, size - 1, |
391 | port->write_urb, | 322 | &port->lock); |
392 | port->serial->dev, | 323 | return count + 1; |
393 | usb_sndbulkpipe(port->serial->dev, | ||
394 | port->bulk_out_endpointAddress), | ||
395 | port->write_urb->transfer_buffer, | ||
396 | transfer_size + 1, | ||
397 | ir_write_bulk_callback, | ||
398 | port); | ||
399 | |||
400 | port->write_urb->transfer_flags = URB_ZERO_PACKET; | ||
401 | |||
402 | result = usb_submit_urb(port->write_urb, GFP_ATOMIC); | ||
403 | if (result) { | ||
404 | port->write_urb_busy = 0; | ||
405 | dev_err(&port->dev, | ||
406 | "%s - failed submitting write urb, error %d\n", | ||
407 | __func__, result); | ||
408 | } else | ||
409 | result = transfer_size; | ||
410 | |||
411 | return result; | ||
412 | } | 324 | } |
413 | 325 | ||
414 | static void ir_write_bulk_callback(struct urb *urb) | 326 | static void ir_process_read_urb(struct urb *urb) |
415 | { | 327 | { |
416 | struct usb_serial_port *port = urb->context; | 328 | struct usb_serial_port *port = urb->context; |
417 | int status = urb->status; | 329 | unsigned char *data = urb->transfer_buffer; |
418 | 330 | struct tty_struct *tty; | |
419 | dbg("%s - port %d", __func__, port->number); | ||
420 | 331 | ||
421 | port->write_urb_busy = 0; | 332 | if (!urb->actual_length) |
422 | if (status) { | ||
423 | dbg("%s - nonzero write bulk status received: %d", | ||
424 | __func__, status); | ||
425 | return; | 333 | return; |
426 | } | 334 | /* |
335 | * The first byte of the packet we get from the device | ||
336 | * contains a busy indicator and baud rate change. | ||
337 | * See section 5.4.1.2 of the USB IrDA spec. | ||
338 | */ | ||
339 | if (*data & 0x0f) | ||
340 | ir_baud = *data & 0x0f; | ||
427 | 341 | ||
428 | usb_serial_debug_data( | 342 | if (urb->actual_length == 1) |
429 | debug, | 343 | return; |
430 | &port->dev, | ||
431 | __func__, | ||
432 | urb->actual_length, | ||
433 | urb->transfer_buffer); | ||
434 | 344 | ||
435 | usb_serial_port_softint(port); | 345 | tty = tty_port_tty_get(&port->port); |
346 | if (!tty) | ||
347 | return; | ||
348 | tty_insert_flip_string(tty, data + 1, urb->actual_length - 1); | ||
349 | tty_flip_buffer_push(tty); | ||
350 | tty_kref_put(tty); | ||
436 | } | 351 | } |
437 | 352 | ||
438 | static void ir_read_bulk_callback(struct urb *urb) | 353 | static void ir_set_termios_callback(struct urb *urb) |
439 | { | 354 | { |
440 | struct usb_serial_port *port = urb->context; | 355 | struct usb_serial_port *port = urb->context; |
441 | struct tty_struct *tty; | ||
442 | unsigned char *data = urb->transfer_buffer; | ||
443 | int result; | ||
444 | int status = urb->status; | 356 | int status = urb->status; |
445 | 357 | ||
446 | dbg("%s - port %d", __func__, port->number); | 358 | dbg("%s - port %d", __func__, port->number); |
447 | 359 | ||
448 | switch (status) { | 360 | kfree(urb->transfer_buffer); |
449 | case 0: /* Successful */ | 361 | |
450 | /* | 362 | if (status) |
451 | * The first byte of the packet we get from the device | 363 | dbg("%s - non-zero urb status: %d", __func__, status); |
452 | * contains a busy indicator and baud rate change. | ||
453 | * See section 5.4.1.2 of the USB IrDA spec. | ||
454 | */ | ||
455 | if ((*data & 0x0f) > 0) | ||
456 | ir_baud = *data & 0x0f; | ||
457 | usb_serial_debug_data(debug, &port->dev, __func__, | ||
458 | urb->actual_length, data); | ||
459 | tty = tty_port_tty_get(&port->port); | ||
460 | tty_insert_flip_string(tty, data+1, urb->actual_length - 1); | ||
461 | tty_flip_buffer_push(tty); | ||
462 | tty_kref_put(tty); | ||
463 | |||
464 | /* | ||
465 | * No break here. | ||
466 | * We want to resubmit the urb so we can read | ||
467 | * again. | ||
468 | */ | ||
469 | |||
470 | case -EPROTO: /* taking inspiration from pl2303.c */ | ||
471 | /* Continue trying to always read */ | ||
472 | usb_fill_bulk_urb( | ||
473 | port->read_urb, | ||
474 | port->serial->dev, | ||
475 | usb_rcvbulkpipe(port->serial->dev, | ||
476 | port->bulk_in_endpointAddress), | ||
477 | port->read_urb->transfer_buffer, | ||
478 | port->read_urb->transfer_buffer_length, | ||
479 | ir_read_bulk_callback, | ||
480 | port); | ||
481 | |||
482 | result = usb_submit_urb(port->read_urb, GFP_ATOMIC); | ||
483 | if (result) | ||
484 | dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", | ||
485 | __func__, result); | ||
486 | break ; | ||
487 | default: | ||
488 | dbg("%s - nonzero read bulk status received: %d", | ||
489 | __func__, status); | ||
490 | break ; | ||
491 | } | ||
492 | return; | ||
493 | } | 364 | } |
494 | 365 | ||
495 | static void ir_set_termios(struct tty_struct *tty, | 366 | static void ir_set_termios(struct tty_struct *tty, |
496 | struct usb_serial_port *port, struct ktermios *old_termios) | 367 | struct usb_serial_port *port, struct ktermios *old_termios) |
497 | { | 368 | { |
369 | struct urb *urb; | ||
498 | unsigned char *transfer_buffer; | 370 | unsigned char *transfer_buffer; |
499 | int result; | 371 | int result; |
500 | speed_t baud; | 372 | speed_t baud; |
@@ -548,41 +420,63 @@ static void ir_set_termios(struct tty_struct *tty, | |||
548 | else | 420 | else |
549 | ir_xbof = ir_xbof_change(xbof) ; | 421 | ir_xbof = ir_xbof_change(xbof) ; |
550 | 422 | ||
551 | /* FIXME need to check to see if our write urb is busy right | 423 | /* Only speed changes are supported */ |
552 | * now, or use a urb pool. | 424 | tty_termios_copy_hw(tty->termios, old_termios); |
553 | * | 425 | tty_encode_baud_rate(tty, baud, baud); |
426 | |||
427 | /* | ||
554 | * send the baud change out on an "empty" data packet | 428 | * send the baud change out on an "empty" data packet |
555 | */ | 429 | */ |
556 | transfer_buffer = port->write_urb->transfer_buffer; | 430 | urb = usb_alloc_urb(0, GFP_KERNEL); |
431 | if (!urb) { | ||
432 | dev_err(&port->dev, "%s - no more urbs\n", __func__); | ||
433 | return; | ||
434 | } | ||
435 | transfer_buffer = kmalloc(1, GFP_KERNEL); | ||
436 | if (!transfer_buffer) { | ||
437 | dev_err(&port->dev, "%s - out of memory\n", __func__); | ||
438 | goto err_buf; | ||
439 | } | ||
440 | |||
557 | *transfer_buffer = ir_xbof | ir_baud; | 441 | *transfer_buffer = ir_xbof | ir_baud; |
558 | 442 | ||
559 | usb_fill_bulk_urb( | 443 | usb_fill_bulk_urb( |
560 | port->write_urb, | 444 | urb, |
561 | port->serial->dev, | 445 | port->serial->dev, |
562 | usb_sndbulkpipe(port->serial->dev, | 446 | usb_sndbulkpipe(port->serial->dev, |
563 | port->bulk_out_endpointAddress), | 447 | port->bulk_out_endpointAddress), |
564 | port->write_urb->transfer_buffer, | 448 | transfer_buffer, |
565 | 1, | 449 | 1, |
566 | ir_write_bulk_callback, | 450 | ir_set_termios_callback, |
567 | port); | 451 | port); |
568 | 452 | ||
569 | port->write_urb->transfer_flags = URB_ZERO_PACKET; | 453 | urb->transfer_flags = URB_ZERO_PACKET; |
570 | 454 | ||
571 | result = usb_submit_urb(port->write_urb, GFP_KERNEL); | 455 | result = usb_submit_urb(urb, GFP_KERNEL); |
572 | if (result) | 456 | if (result) { |
573 | dev_err(&port->dev, | 457 | dev_err(&port->dev, "%s - failed to submit urb: %d\n", |
574 | "%s - failed submitting write urb, error %d\n", | 458 | __func__, result); |
575 | __func__, result); | 459 | goto err_subm; |
460 | } | ||
576 | 461 | ||
577 | /* Only speed changes are supported */ | 462 | usb_free_urb(urb); |
578 | tty_termios_copy_hw(tty->termios, old_termios); | 463 | |
579 | tty_encode_baud_rate(tty, baud, baud); | 464 | return; |
465 | err_subm: | ||
466 | kfree(transfer_buffer); | ||
467 | err_buf: | ||
468 | usb_free_urb(urb); | ||
580 | } | 469 | } |
581 | 470 | ||
582 | static int __init ir_init(void) | 471 | static int __init ir_init(void) |
583 | { | 472 | { |
584 | int retval; | 473 | int retval; |
585 | 474 | ||
475 | if (buffer_size) { | ||
476 | ir_device.bulk_in_size = buffer_size; | ||
477 | ir_device.bulk_out_size = buffer_size; | ||
478 | } | ||
479 | |||
586 | retval = usb_serial_register(&ir_device); | 480 | retval = usb_serial_register(&ir_device); |
587 | if (retval) | 481 | if (retval) |
588 | goto failed_usb_serial_register; | 482 | goto failed_usb_serial_register; |