diff options
author | Jason Wessel <jason.wessel@windriver.com> | 2009-05-12 00:24:09 +0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-06-16 08:44:45 +0400 |
commit | 98fcb5f78165b8a3d93870ad7afd4d9ebbb8b43a (patch) | |
tree | ed64298e8b6bf47ba9c57db298e732429f7f669e /drivers/usb/serial/usb_debug.c | |
parent | 87c1edd217a6742e48028db6664d7763de0449f6 (diff) | |
download | linux-98fcb5f78165b8a3d93870ad7afd4d9ebbb8b43a.tar.xz |
USB: serial: usb_debug,usb_generic_serial: implement sysrq and serial break
The usb_debug driver was modified to implement serial break handling
by using a "magic" data packet comprised of the sequence:
0x00 0xff 0x01 0xfe 0x00 0xfe 0x01 0xff
When the tty layer requests a serial break the usb_debug driver sends
the magic packet. On the receiving side the magic packet is thrown
away or a sysrq is activated depending on what kernel .config options
have been set.
The generic serial driver was modified as well as the usb serial
headers to generically implement sysrq processing in the same way the
non usb uart based drivers implement the sysrq handling. This will
allow other usb serial devices to implement sysrq handling as desired.
The new usb serial functions are named similarly and implemented
similarly to the uart functions as follows:
usb_serial_handle_break <-> uart_handle_break
usb_serial_handle_sysrq_char <-> uart_handle_sysrq_char
Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/serial/usb_debug.c')
-rw-r--r-- | drivers/usb/serial/usb_debug.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c index a9427a8b8672..614800972dc3 100644 --- a/drivers/usb/serial/usb_debug.c +++ b/drivers/usb/serial/usb_debug.c @@ -17,6 +17,17 @@ #define URB_DEBUG_MAX_IN_FLIGHT_URBS 4000 #define USB_DEBUG_MAX_PACKET_SIZE 8 +#define USB_DEBUG_BRK_SIZE 8 +static char USB_DEBUG_BRK[USB_DEBUG_BRK_SIZE] = { + 0x00, + 0xff, + 0x01, + 0xfe, + 0x00, + 0xfe, + 0x01, + 0xff, +}; static struct usb_device_id id_table [] = { { USB_DEVICE(0x0525, 0x127a) }, @@ -39,6 +50,32 @@ static int usb_debug_open(struct tty_struct *tty, struct usb_serial_port *port, return usb_serial_generic_open(tty, port, filp); } +/* This HW really does not support a serial break, so one will be + * emulated when ever the break state is set to true. + */ +static void usb_debug_break_ctl(struct tty_struct *tty, int break_state) +{ + struct usb_serial_port *port = tty->driver_data; + if (!break_state) + return; + usb_serial_generic_write(tty, port, USB_DEBUG_BRK, USB_DEBUG_BRK_SIZE); +} + +static void usb_debug_read_bulk_callback(struct urb *urb) +{ + struct usb_serial_port *port = urb->context; + + if (urb->actual_length == USB_DEBUG_BRK_SIZE && + memcmp(urb->transfer_buffer, USB_DEBUG_BRK, + USB_DEBUG_BRK_SIZE) == 0) { + usb_serial_handle_break(port); + usb_serial_generic_resubmit_read_urb(port, GFP_ATOMIC); + return; + } + + usb_serial_generic_read_bulk_callback(urb); +} + static struct usb_serial_driver debug_device = { .driver = { .owner = THIS_MODULE, @@ -48,6 +85,8 @@ static struct usb_serial_driver debug_device = { .num_ports = 1, .open = usb_debug_open, .max_in_flight_urbs = URB_DEBUG_MAX_IN_FLIGHT_URBS, + .break_ctl = usb_debug_break_ctl, + .read_bulk_callback = usb_debug_read_bulk_callback, }; static int __init debug_init(void) |