usbserial basic support. Works in qemu
This commit is contained in:
parent
cbf41813b3
commit
34364df689
6 changed files with 189 additions and 181 deletions
|
@ -269,6 +269,9 @@ void grub_usb_device_attach (grub_usb_device_t dev)
|
||||||
case GRUB_USB_CLASS_HID:
|
case GRUB_USB_CLASS_HID:
|
||||||
grub_dl_load ("usb_keyboard");
|
grub_dl_load ("usb_keyboard");
|
||||||
break;
|
break;
|
||||||
|
case 0xff:
|
||||||
|
grub_dl_load ("usbserial");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -195,6 +195,12 @@ usb_mod_SOURCES = bus/usb/usb.c bus/usb/usbtrans.c bus/usb/usbhub.c
|
||||||
usb_mod_CFLAGS = $(COMMON_CFLAGS)
|
usb_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||||
usb_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
usb_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
||||||
|
|
||||||
|
# For serial.mod.
|
||||||
|
pkglib_MODULES += usbserial.mod
|
||||||
|
usbserial_mod_SOURCES = term/usbserial.c
|
||||||
|
usbserial_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||||
|
usbserial_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
||||||
|
|
||||||
# For usbtest.mod
|
# For usbtest.mod
|
||||||
usbtest_mod_SOURCES = commands/usbtest.c
|
usbtest_mod_SOURCES = commands/usbtest.c
|
||||||
usbtest_mod_CFLAGS = $(COMMON_CFLAGS)
|
usbtest_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||||
|
|
|
@ -47,6 +47,7 @@ struct grub_serial_port
|
||||||
unsigned int parity;
|
unsigned int parity;
|
||||||
unsigned short stop_bits;
|
unsigned short stop_bits;
|
||||||
struct grub_serial_driver *driver;
|
struct grub_serial_driver *driver;
|
||||||
|
int configured;
|
||||||
/* This should be void *data but since serial is useful as an early console
|
/* This should be void *data but since serial is useful as an early console
|
||||||
when malloc isn't available it's a union.
|
when malloc isn't available it's a union.
|
||||||
*/
|
*/
|
||||||
|
@ -55,9 +56,9 @@ struct grub_serial_port
|
||||||
grub_port_t port;
|
grub_port_t port;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
grub_usb_device_t dev;
|
grub_usb_device_t usbdev;
|
||||||
int in_endp;
|
struct grub_usb_desc_endp *in_endp;
|
||||||
int out_endp;
|
struct grub_usb_desc_endp *out_endp;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -81,18 +82,19 @@ void grub_serial_unregister (struct grub_serial_port *port);
|
||||||
#define UART_1_STOP_BIT 0x00
|
#define UART_1_STOP_BIT 0x00
|
||||||
#define UART_2_STOP_BITS 0x04
|
#define UART_2_STOP_BITS 0x04
|
||||||
|
|
||||||
static inline void
|
|
||||||
grub_serial_fill_defaults (struct grub_serial_port *port)
|
|
||||||
{
|
|
||||||
/* Set default settings. */
|
/* Set default settings. */
|
||||||
|
static inline grub_err_t
|
||||||
|
grub_serial_config_defaults (struct grub_serial_port *port)
|
||||||
|
{
|
||||||
|
return port->driver->configure (port,
|
||||||
|
|
||||||
#ifdef GRUB_MACHINE_MIPS_YEELOONG
|
#ifdef GRUB_MACHINE_MIPS_YEELOONG
|
||||||
port->speed = 115200;
|
115200,
|
||||||
#else
|
#else
|
||||||
port->speed = 9600;
|
9600,
|
||||||
#endif
|
#endif
|
||||||
port->word_len = UART_8BITS_WORD;
|
UART_8BITS_WORD, UART_NO_PARITY,
|
||||||
port->parity = UART_NO_PARITY;
|
UART_1_STOP_BIT);
|
||||||
port->stop_bits = UART_1_STOP_BIT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void grub_ns8250_init (void);
|
void grub_ns8250_init (void);
|
||||||
|
|
124
term/ns8250.c
124
term/ns8250.c
|
@ -34,33 +34,6 @@ static const grub_port_t serial_hw_io_addr[] = GRUB_MACHINE_SERIAL_PORTS;
|
||||||
#define GRUB_SERIAL_PORT_NUM (ARRAY_SIZE(serial_hw_io_addr))
|
#define GRUB_SERIAL_PORT_NUM (ARRAY_SIZE(serial_hw_io_addr))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Fetch a key. */
|
|
||||||
static int
|
|
||||||
serial_hw_fetch (struct grub_serial_port *port)
|
|
||||||
{
|
|
||||||
if (grub_inb (port->port + UART_LSR) & UART_DATA_READY)
|
|
||||||
return grub_inb (port->port + UART_RX);
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Put a character. */
|
|
||||||
static void
|
|
||||||
serial_hw_put (struct grub_serial_port *port, const int c)
|
|
||||||
{
|
|
||||||
unsigned int timeout = 100000;
|
|
||||||
|
|
||||||
/* Wait until the transmitter holding register is empty. */
|
|
||||||
while ((grub_inb (port->port + UART_LSR) & UART_EMPTY_TRANSMITTER) == 0)
|
|
||||||
{
|
|
||||||
if (--timeout == 0)
|
|
||||||
/* There is something wrong. But what can I do? */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
grub_outb (c, port->port + UART_TX);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Convert speed to divisor. */
|
/* Convert speed to divisor. */
|
||||||
static unsigned short
|
static unsigned short
|
||||||
serial_get_divisor (unsigned int speed)
|
serial_get_divisor (unsigned int speed)
|
||||||
|
@ -99,29 +72,19 @@ serial_get_divisor (unsigned int speed)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize a serial device. PORT is the port number for a serial device.
|
static void
|
||||||
SPEED is a DTE-DTE speed which must be one of these: 2400, 4800, 9600,
|
do_real_config (struct grub_serial_port *port)
|
||||||
19200, 38400, 57600 and 115200. WORD_LEN is the word length to be used
|
|
||||||
for the device. Likewise, PARITY is the type of the parity and
|
|
||||||
STOP_BIT_LEN is the length of the stop bit. The possible values for
|
|
||||||
WORD_LEN, PARITY and STOP_BIT_LEN are defined in the header file as
|
|
||||||
macros. */
|
|
||||||
static grub_err_t
|
|
||||||
serial_hw_configure (struct grub_serial_port *port,
|
|
||||||
unsigned speed, unsigned short word_len,
|
|
||||||
unsigned int parity, unsigned short stop_bits)
|
|
||||||
{
|
{
|
||||||
|
int divisor;
|
||||||
unsigned char status = 0;
|
unsigned char status = 0;
|
||||||
unsigned short divisor;
|
|
||||||
|
|
||||||
divisor = serial_get_divisor (speed);
|
if (port->configured)
|
||||||
|
return;
|
||||||
|
|
||||||
|
divisor = serial_get_divisor (port->speed);
|
||||||
|
/* Shouldn't happen. */
|
||||||
if (divisor == 0)
|
if (divisor == 0)
|
||||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad speed");
|
return;
|
||||||
|
|
||||||
port->speed = speed;
|
|
||||||
port->word_len = word_len;
|
|
||||||
port->parity = parity;
|
|
||||||
port->stop_bits = stop_bits;
|
|
||||||
|
|
||||||
/* Turn off the interrupt. */
|
/* Turn off the interrupt. */
|
||||||
grub_outb (0, port->port + UART_IER);
|
grub_outb (0, port->port + UART_IER);
|
||||||
|
@ -153,7 +116,66 @@ serial_hw_configure (struct grub_serial_port *port,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Drain the input buffer. */
|
/* Drain the input buffer. */
|
||||||
while (serial_hw_fetch (port) != -1);
|
while (grub_inb (port->port + UART_LSR) & UART_DATA_READY)
|
||||||
|
grub_inb (port->port + UART_RX);
|
||||||
|
|
||||||
|
port->configured = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fetch a key. */
|
||||||
|
static int
|
||||||
|
serial_hw_fetch (struct grub_serial_port *port)
|
||||||
|
{
|
||||||
|
do_real_config (port);
|
||||||
|
if (grub_inb (port->port + UART_LSR) & UART_DATA_READY)
|
||||||
|
return grub_inb (port->port + UART_RX);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Put a character. */
|
||||||
|
static void
|
||||||
|
serial_hw_put (struct grub_serial_port *port, const int c)
|
||||||
|
{
|
||||||
|
unsigned int timeout = 100000;
|
||||||
|
|
||||||
|
do_real_config (port);
|
||||||
|
|
||||||
|
/* Wait until the transmitter holding register is empty. */
|
||||||
|
while ((grub_inb (port->port + UART_LSR) & UART_EMPTY_TRANSMITTER) == 0)
|
||||||
|
{
|
||||||
|
if (--timeout == 0)
|
||||||
|
/* There is something wrong. But what can I do? */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_outb (c, port->port + UART_TX);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize a serial device. PORT is the port number for a serial device.
|
||||||
|
SPEED is a DTE-DTE speed which must be one of these: 2400, 4800, 9600,
|
||||||
|
19200, 38400, 57600 and 115200. WORD_LEN is the word length to be used
|
||||||
|
for the device. Likewise, PARITY is the type of the parity and
|
||||||
|
STOP_BIT_LEN is the length of the stop bit. The possible values for
|
||||||
|
WORD_LEN, PARITY and STOP_BIT_LEN are defined in the header file as
|
||||||
|
macros. */
|
||||||
|
static grub_err_t
|
||||||
|
serial_hw_configure (struct grub_serial_port *port,
|
||||||
|
unsigned speed, unsigned short word_len,
|
||||||
|
unsigned int parity, unsigned short stop_bits)
|
||||||
|
{
|
||||||
|
unsigned short divisor;
|
||||||
|
|
||||||
|
divisor = serial_get_divisor (speed);
|
||||||
|
if (divisor == 0)
|
||||||
|
return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad speed");
|
||||||
|
|
||||||
|
port->speed = speed;
|
||||||
|
port->word_len = word_len;
|
||||||
|
port->parity = parity;
|
||||||
|
port->stop_bits = stop_bits;
|
||||||
|
|
||||||
|
port->configured = 0;
|
||||||
|
|
||||||
/* FIXME: should check if the serial terminal was found. */
|
/* FIXME: should check if the serial terminal was found. */
|
||||||
|
|
||||||
|
@ -177,11 +199,15 @@ grub_ns8250_init (void)
|
||||||
for (i = 0; i < GRUB_SERIAL_PORT_NUM; i++)
|
for (i = 0; i < GRUB_SERIAL_PORT_NUM; i++)
|
||||||
if (serial_hw_io_addr[i])
|
if (serial_hw_io_addr[i])
|
||||||
{
|
{
|
||||||
|
grub_err_t err;
|
||||||
grub_snprintf (com_names[i], sizeof (com_names[i]), "com%d", i);
|
grub_snprintf (com_names[i], sizeof (com_names[i]), "com%d", i);
|
||||||
com_ports[i].name = com_names[i];
|
com_ports[i].name = com_names[i];
|
||||||
com_ports[i].driver = &grub_ns8250_driver;
|
com_ports[i].driver = &grub_ns8250_driver;
|
||||||
grub_serial_fill_defaults (&com_ports[i]);
|
|
||||||
com_ports[i].port = serial_hw_io_addr[i];
|
com_ports[i].port = serial_hw_io_addr[i];
|
||||||
|
err = grub_serial_config_defaults (&com_ports[i]);
|
||||||
|
if (err)
|
||||||
|
grub_print_error ();
|
||||||
|
|
||||||
grub_serial_register (&com_ports[i]);
|
grub_serial_register (&com_ports[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -204,7 +230,7 @@ grub_serial_ns8250_add_port (grub_port_t port)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
p->driver = &grub_ns8250_driver;
|
p->driver = &grub_ns8250_driver;
|
||||||
grub_serial_fill_defaults (p);
|
grub_serial_config_defaults (p);
|
||||||
p->port = port;
|
p->port = port;
|
||||||
grub_serial_register (p);
|
grub_serial_register (p);
|
||||||
|
|
||||||
|
|
|
@ -315,7 +315,6 @@ grub_serial_unregister (struct grub_serial_port *port)
|
||||||
/* FIXME */
|
/* FIXME */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static grub_extcmd_t cmd;
|
static grub_extcmd_t cmd;
|
||||||
|
|
||||||
GRUB_MOD_INIT(serial)
|
GRUB_MOD_INIT(serial)
|
||||||
|
|
212
term/usbserial.c
212
term/usbserial.c
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* GRUB -- GRand Unified Bootloader
|
* GRUB -- GRand Unified Bootloader
|
||||||
* Copyright (C) 2000,2001,2002,2003,2004,2005,2007,2008,2009 Free Software Foundation, Inc.
|
* Copyright (C) 2000,2001,2002,2003,2004,2005,2007,2008,2009,2010 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* GRUB is free software: you can redistribute it and/or modify
|
* GRUB is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -16,150 +16,122 @@
|
||||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <grub/machine/memory.h>
|
|
||||||
#include <grub/serial.h>
|
#include <grub/serial.h>
|
||||||
#include <grub/term.h>
|
|
||||||
#include <grub/types.h>
|
#include <grub/types.h>
|
||||||
#include <grub/dl.h>
|
#include <grub/dl.h>
|
||||||
#include <grub/misc.h>
|
#include <grub/misc.h>
|
||||||
#include <grub/terminfo.h>
|
#include <grub/mm.h>
|
||||||
#include <grub/cpu/io.h>
|
#include <grub/usb.h>
|
||||||
#include <grub/extcmd.h>
|
|
||||||
#include <grub/i18n.h>
|
|
||||||
|
|
||||||
static unsigned int registered = 0;
|
|
||||||
|
|
||||||
/* Argument options. */
|
|
||||||
static const struct grub_arg_option options[] =
|
|
||||||
{
|
|
||||||
{"unit", 'u', 0, N_("Set the serial unit."), 0, ARG_TYPE_INT},
|
|
||||||
{"speed", 's', 0, N_("Set the serial port speed."), 0, ARG_TYPE_INT},
|
|
||||||
{"word", 'w', 0, N_("Set the serial port word length."), 0, ARG_TYPE_INT},
|
|
||||||
{"parity", 'r', 0, N_("Set the serial port parity."), 0, ARG_TYPE_STRING},
|
|
||||||
{"stop", 't', 0, N_("Set the serial port stop bits."), 0, ARG_TYPE_INT},
|
|
||||||
{0, 0, 0, 0, 0, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Serial port settings. */
|
|
||||||
struct usbserial_port
|
|
||||||
{
|
|
||||||
grub_usb_device_t usbdev;
|
|
||||||
int in_endp;
|
|
||||||
int out_endp;
|
|
||||||
unsigned short divisor;
|
|
||||||
unsigned short word_len;
|
|
||||||
unsigned int parity;
|
|
||||||
unsigned short stop_bits;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Serial port settings. */
|
|
||||||
static struct serial_port serial_settings;
|
|
||||||
|
|
||||||
/* Fetch a key. */
|
/* Fetch a key. */
|
||||||
static int
|
static int
|
||||||
serial_hw_fetch (void)
|
usbserial_hw_fetch (struct grub_serial_port *port)
|
||||||
{
|
{
|
||||||
/* FIXME */
|
char cc[3];
|
||||||
return -1;
|
grub_usb_err_t err;
|
||||||
|
err = grub_usb_bulk_read (port->usbdev, port->in_endp->endp_addr, 2, cc);
|
||||||
|
if (err != GRUB_USB_ERR_NAK)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
err = grub_usb_bulk_read (port->usbdev, port->in_endp->endp_addr, 3, cc);
|
||||||
|
if (err != GRUB_USB_ERR_NONE)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return cc[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Put a character. */
|
/* Put a character. */
|
||||||
static void
|
static void
|
||||||
usbserial_hw_put (struct usbserial_port *port, const int c)
|
usbserial_hw_put (struct grub_serial_port *port, const int c)
|
||||||
{
|
{
|
||||||
char cc = c;
|
char cc = c;
|
||||||
grub_usb_bulk_write (port->usbdev, port->out_endp, 1, &cc);
|
grub_usb_bulk_write (port->usbdev, port->out_endp->endp_addr, 1, &cc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_uint16_t
|
/* FIXME */
|
||||||
grub_serial_getwh (struct grub_term_output *term __attribute__ ((unused)))
|
static grub_err_t
|
||||||
|
usbserial_hw_configure (struct grub_serial_port *port,
|
||||||
|
unsigned speed, unsigned short word_len,
|
||||||
|
unsigned int parity, unsigned short stop_bits)
|
||||||
{
|
{
|
||||||
const grub_uint8_t TEXT_WIDTH = 80;
|
port->speed = speed;
|
||||||
const grub_uint8_t TEXT_HEIGHT = 24;
|
port->word_len = word_len;
|
||||||
return (TEXT_WIDTH << 8) | TEXT_HEIGHT;
|
port->parity = parity;
|
||||||
|
port->stop_bits = stop_bits;
|
||||||
|
|
||||||
|
port->configured = 0;
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct grub_terminfo_input_state grub_serial_terminfo_input =
|
static struct grub_serial_driver grub_usbserial_driver =
|
||||||
{
|
|
||||||
.readkey = serial_hw_fetch
|
|
||||||
};
|
|
||||||
|
|
||||||
struct grub_terminfo_output_state grub_serial_terminfo_output =
|
|
||||||
{
|
{
|
||||||
|
.configure = usbserial_hw_configure,
|
||||||
|
.fetch = usbserial_hw_fetch,
|
||||||
.put = usbserial_hw_put
|
.put = usbserial_hw_put
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct grub_term_input grub_serial_term_input =
|
static int
|
||||||
|
grub_usbserial_attach (grub_usb_device_t usbdev, int configno, int interfno)
|
||||||
{
|
{
|
||||||
.name = "usbserial",
|
static struct grub_serial_port *port;
|
||||||
.init = grub_terminfo_input_init,
|
int j;
|
||||||
.checkkey = grub_terminfo_checkkey,
|
struct grub_usb_desc_if *interf
|
||||||
.getkey = grub_terminfo_getkey,
|
= usbdev->config[configno].interf[interfno].descif;
|
||||||
.data = &grub_serial_terminfo_input
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct grub_term_output grub_serial_term_output =
|
port = grub_malloc (sizeof (*port));
|
||||||
{
|
if (!port)
|
||||||
.name = "usbserial",
|
|
||||||
.putchar = grub_terminfo_putchar,
|
|
||||||
.getwh = grub_serial_getwh,
|
|
||||||
.getxy = grub_terminfo_getxy,
|
|
||||||
.gotoxy = grub_terminfo_gotoxy,
|
|
||||||
.cls = grub_terminfo_cls,
|
|
||||||
.setcolorstate = grub_terminfo_setcolorstate,
|
|
||||||
.setcursor = grub_terminfo_setcursor,
|
|
||||||
.flags = GRUB_TERM_CODE_TYPE_ASCII,
|
|
||||||
.data = &grub_serial_terminfo_output,
|
|
||||||
.normal_color = GRUB_TERM_DEFAULT_NORMAL_COLOR,
|
|
||||||
.highlight_color = GRUB_TERM_DEFAULT_HIGHLIGHT_COLOR,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static grub_extcmd_t cmd;
|
|
||||||
|
|
||||||
GRUB_MOD_INIT(serial)
|
|
||||||
{
|
|
||||||
cmd = grub_register_extcmd ("serial", grub_cmd_serial,
|
|
||||||
GRUB_COMMAND_FLAG_BOTH,
|
|
||||||
N_("[OPTIONS...]"),
|
|
||||||
N_("Configure serial port."), options);
|
|
||||||
|
|
||||||
/* Set default settings. */
|
|
||||||
serial_settings.port = serial_hw_get_port (0);
|
|
||||||
#ifdef GRUB_MACHINE_MIPS_YEELOONG
|
|
||||||
serial_settings.divisor = serial_get_divisor (115200);
|
|
||||||
#else
|
|
||||||
serial_settings.divisor = serial_get_divisor (9600);
|
|
||||||
#endif
|
|
||||||
serial_settings.word_len = UART_8BITS_WORD;
|
|
||||||
serial_settings.parity = UART_NO_PARITY;
|
|
||||||
serial_settings.stop_bits = UART_1_STOP_BIT;
|
|
||||||
|
|
||||||
#ifdef GRUB_MACHINE_MIPS_YEELOONG
|
|
||||||
{
|
|
||||||
grub_err_t hwiniterr;
|
|
||||||
hwiniterr = serial_hw_init ();
|
|
||||||
|
|
||||||
if (hwiniterr == GRUB_ERR_NONE)
|
|
||||||
{
|
|
||||||
grub_term_register_input_active ("serial", &grub_serial_term_input);
|
|
||||||
grub_term_register_output_active ("serial", &grub_serial_term_output);
|
|
||||||
|
|
||||||
registered = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
GRUB_MOD_FINI(serial)
|
|
||||||
{
|
|
||||||
grub_unregister_extcmd (cmd);
|
|
||||||
if (registered == 1) /* Unregister terminal only if registered. */
|
|
||||||
{
|
{
|
||||||
grub_term_unregister_input (&grub_serial_term_input);
|
grub_print_error ();
|
||||||
grub_term_unregister_output (&grub_serial_term_output);
|
return 0;
|
||||||
grub_terminfo_output_unregister (&grub_serial_term_output);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
port->name = grub_xasprintf ("usb%d", usbdev->addr);
|
||||||
|
if (!port->name)
|
||||||
|
{
|
||||||
|
grub_free (port);
|
||||||
|
grub_print_error ();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
port->usbdev = usbdev;
|
||||||
|
port->driver = &grub_usbserial_driver;
|
||||||
|
for (j = 0; j < interf->endpointcnt; j++)
|
||||||
|
{
|
||||||
|
struct grub_usb_desc_endp *endp;
|
||||||
|
endp = &usbdev->config[0].interf[interfno].descendp[j];
|
||||||
|
|
||||||
|
if ((endp->endp_addr & 128) && (endp->attrib & 3) == 2)
|
||||||
|
{
|
||||||
|
/* Bulk IN endpoint. */
|
||||||
|
port->in_endp = endp;
|
||||||
|
}
|
||||||
|
else if (!(endp->endp_addr & 128) && (endp->attrib & 3) == 2)
|
||||||
|
{
|
||||||
|
/* Bulk OUT endpoint. */
|
||||||
|
port->out_endp = endp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!port->out_endp || !port->in_endp)
|
||||||
|
{
|
||||||
|
grub_free (port->name);
|
||||||
|
grub_free (port);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_serial_config_defaults (port);
|
||||||
|
grub_serial_register (port);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct grub_usb_attach_desc attach_hook =
|
||||||
|
{
|
||||||
|
.class = 0xff,
|
||||||
|
.hook = grub_usbserial_attach
|
||||||
|
};
|
||||||
|
|
||||||
|
GRUB_MOD_INIT(usbserial)
|
||||||
|
{
|
||||||
|
grub_usb_register_attach_hook_class (&attach_hook);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue