diff mbox series

[v5,05/28] efi: serial: Support arrow keys

Message ID 20211204155657.2913911-2-sjg@chromium.org
State Changes Requested, archived
Delegated to: Heinrich Schuchardt
Headers show
Series efi: Improvements to U-Boot running on top of UEFI | expand

Commit Message

Simon Glass Dec. 4, 2021, 3:56 p.m. UTC
At present only the backspace key is supported in U-Boot, when running as
an EFI app. Add support for arrows, home and end as well, to make the CLI
more friendly.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 drivers/serial/serial_efi.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

Comments

Heinrich Schuchardt Dec. 9, 2021, 7:39 p.m. UTC | #1
On 12/4/21 07:56, Simon Glass wrote:
> At present only the backspace key is supported in U-Boot, when running as
> an EFI app. Add support for arrows, home and end as well, to make the CLI
> more friendly.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> (no changes since v1)
>
>   drivers/serial/serial_efi.c | 11 +++++++++--
>   1 file changed, 9 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/serial/serial_efi.c b/drivers/serial/serial_efi.c
> index 33ddbd6080c..0067576389d 100644
> --- a/drivers/serial/serial_efi.c
> +++ b/drivers/serial/serial_efi.c
> @@ -24,6 +24,9 @@ struct serial_efi_priv {
>   	bool have_key;
>   };
>
> +/* Convert a lower-case character to its ctrl-char equivalent */
> +#define CTL_CH(c)		((c) - 'a' + 1)
> +
>   int serial_efi_setbrg(struct udevice *dev, int baudrate)
>   {
>   	return 0;
> @@ -49,6 +52,7 @@ static int serial_efi_get_key(struct serial_efi_priv *priv)
>   static int serial_efi_getc(struct udevice *dev)
>   {
>   	struct serial_efi_priv *priv = dev_get_priv(dev);
> +	char conv_scan[10] = {0, 'p', 'n', 'f', 'b', 'a', 'e', 0, 8};
>   	int ret, ch;
>
>   	ret = serial_efi_get_key(priv);
> @@ -63,8 +67,11 @@ static int serial_efi_getc(struct udevice *dev)
>   	 * key scan code of 8. Handle this so that backspace works correctly
>   	 * in the U-Boot command line.
>   	 */
> -	if (!ch && priv->key.scan_code == 8)
> -		ch = 8;
> +	if (!ch && priv->key.scan_code < sizeof(conv_scan)) {
> +		ch = conv_scan[priv->key.scan_code];
> +		if (ch >= 'a')
> +			ch -= 'a' - 1;

This is not what a serial console would use in Linux. Just try U-Boot's
conitrace command. If you use the following, we get compatibility with
the rest of U-Boot:

1b 5b 32 7e - insert
1b 5b 33 7e - delete
1b 5b 35 7e - page up
1b 5b 36 7e - page down
1b 5b 41 - up
1b 5b 42 - down
1b 5b 43 - right
1b 5b 44 - left
1b 5b 46 - end
1b 5b 48 - home

Best regards

Heinrich

> +	}
>   	debug(" [%x %x %x] ", ch, priv->key.unicode_char, priv->key.scan_code);
>
>   	return ch;
>
Simon Glass Dec. 17, 2021, 4:37 p.m. UTC | #2
Hi Heinrich,

On Thu, 9 Dec 2021 at 12:44, Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
>
> On 12/4/21 07:56, Simon Glass wrote:
> > At present only the backspace key is supported in U-Boot, when running as
> > an EFI app. Add support for arrows, home and end as well, to make the CLI
> > more friendly.
> >
> > Signed-off-by: Simon Glass <sjg@chromium.org>
> > ---
> >
> > (no changes since v1)
> >
> >   drivers/serial/serial_efi.c | 11 +++++++++--
> >   1 file changed, 9 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/serial/serial_efi.c b/drivers/serial/serial_efi.c
> > index 33ddbd6080c..0067576389d 100644
> > --- a/drivers/serial/serial_efi.c
> > +++ b/drivers/serial/serial_efi.c
> > @@ -24,6 +24,9 @@ struct serial_efi_priv {
> >       bool have_key;
> >   };
> >
> > +/* Convert a lower-case character to its ctrl-char equivalent */
> > +#define CTL_CH(c)            ((c) - 'a' + 1)
> > +
> >   int serial_efi_setbrg(struct udevice *dev, int baudrate)
> >   {
> >       return 0;
> > @@ -49,6 +52,7 @@ static int serial_efi_get_key(struct serial_efi_priv *priv)
> >   static int serial_efi_getc(struct udevice *dev)
> >   {
> >       struct serial_efi_priv *priv = dev_get_priv(dev);
> > +     char conv_scan[10] = {0, 'p', 'n', 'f', 'b', 'a', 'e', 0, 8};
> >       int ret, ch;
> >
> >       ret = serial_efi_get_key(priv);
> > @@ -63,8 +67,11 @@ static int serial_efi_getc(struct udevice *dev)
> >        * key scan code of 8. Handle this so that backspace works correctly
> >        * in the U-Boot command line.
> >        */
> > -     if (!ch && priv->key.scan_code == 8)
> > -             ch = 8;
> > +     if (!ch && priv->key.scan_code < sizeof(conv_scan)) {
> > +             ch = conv_scan[priv->key.scan_code];
> > +             if (ch >= 'a')
> > +                     ch -= 'a' - 1;
>
> This is not what a serial console would use in Linux. Just try U-Boot's
> conitrace command. If you use the following, we get compatibility with
> the rest of U-Boot:
>
> 1b 5b 32 7e - insert
> 1b 5b 33 7e - delete
> 1b 5b 35 7e - page up
> 1b 5b 36 7e - page down
> 1b 5b 41 - up
> 1b 5b 42 - down
> 1b 5b 43 - right
> 1b 5b 44 - left
> 1b 5b 46 - end
> 1b 5b 48 - home

That's more complicated since it requires the serial driver to convert
one character into multiple. We can always add it later if needed. But
this does command-line history, etc. working in the app.

Regards,
Simon
Heinrich Schuchardt Dec. 17, 2021, 5:09 p.m. UTC | #3
On 12/17/21 17:37, Simon Glass wrote:
> Hi Heinrich,
>
> On Thu, 9 Dec 2021 at 12:44, Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
>>
>> On 12/4/21 07:56, Simon Glass wrote:
>>> At present only the backspace key is supported in U-Boot, when running as
>>> an EFI app. Add support for arrows, home and end as well, to make the CLI
>>> more friendly.
>>>
>>> Signed-off-by: Simon Glass <sjg@chromium.org>
>>> ---
>>>
>>> (no changes since v1)
>>>
>>>    drivers/serial/serial_efi.c | 11 +++++++++--
>>>    1 file changed, 9 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/drivers/serial/serial_efi.c b/drivers/serial/serial_efi.c
>>> index 33ddbd6080c..0067576389d 100644
>>> --- a/drivers/serial/serial_efi.c
>>> +++ b/drivers/serial/serial_efi.c
>>> @@ -24,6 +24,9 @@ struct serial_efi_priv {
>>>        bool have_key;
>>>    };
>>>
>>> +/* Convert a lower-case character to its ctrl-char equivalent */
>>> +#define CTL_CH(c)            ((c) - 'a' + 1)
>>> +
>>>    int serial_efi_setbrg(struct udevice *dev, int baudrate)
>>>    {
>>>        return 0;
>>> @@ -49,6 +52,7 @@ static int serial_efi_get_key(struct serial_efi_priv *priv)
>>>    static int serial_efi_getc(struct udevice *dev)
>>>    {
>>>        struct serial_efi_priv *priv = dev_get_priv(dev);
>>> +     char conv_scan[10] = {0, 'p', 'n', 'f', 'b', 'a', 'e', 0, 8};
>>>        int ret, ch;
>>>
>>>        ret = serial_efi_get_key(priv);
>>> @@ -63,8 +67,11 @@ static int serial_efi_getc(struct udevice *dev)
>>>         * key scan code of 8. Handle this so that backspace works correctly
>>>         * in the U-Boot command line.
>>>         */
>>> -     if (!ch && priv->key.scan_code == 8)
>>> -             ch = 8;
>>> +     if (!ch && priv->key.scan_code < sizeof(conv_scan)) {
>>> +             ch = conv_scan[priv->key.scan_code];
>>> +             if (ch >= 'a')
>>> +                     ch -= 'a' - 1;
>>
>> This is not what a serial console would use in Linux. Just try U-Boot's
>> conitrace command. If you use the following, we get compatibility with
>> the rest of U-Boot:
>>
>> 1b 5b 32 7e - insert
>> 1b 5b 33 7e - delete
>> 1b 5b 35 7e - page up
>> 1b 5b 36 7e - page down
>> 1b 5b 41 - up
>> 1b 5b 42 - down
>> 1b 5b 43 - right
>> 1b 5b 44 - left
>> 1b 5b 46 - end
>> 1b 5b 48 - home
>
> That's more complicated since it requires the serial driver to convert
> one character into multiple. We can always add it later if needed. But
> this does command-line history, etc. working in the app.

Yes you will need a ring buffer as in the USB keyboard driver.

lib/efi_loader/efi_console.c only understands the multi-byte sequences.
I do not know if there are other places which have the same limitation.

Best regards

Heinrich

>
> Regards,
> Simon
Simon Glass Dec. 17, 2021, 5:42 p.m. UTC | #4
Hi Heinrich,

On Fri, 17 Dec 2021 at 10:14, Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
>
> On 12/17/21 17:37, Simon Glass wrote:
> > Hi Heinrich,
> >
> > On Thu, 9 Dec 2021 at 12:44, Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
> >>
> >> On 12/4/21 07:56, Simon Glass wrote:
> >>> At present only the backspace key is supported in U-Boot, when running as
> >>> an EFI app. Add support for arrows, home and end as well, to make the CLI
> >>> more friendly.
> >>>
> >>> Signed-off-by: Simon Glass <sjg@chromium.org>
> >>> ---
> >>>
> >>> (no changes since v1)
> >>>
> >>>    drivers/serial/serial_efi.c | 11 +++++++++--
> >>>    1 file changed, 9 insertions(+), 2 deletions(-)
> >>>
> >>> diff --git a/drivers/serial/serial_efi.c b/drivers/serial/serial_efi.c
> >>> index 33ddbd6080c..0067576389d 100644
> >>> --- a/drivers/serial/serial_efi.c
> >>> +++ b/drivers/serial/serial_efi.c
> >>> @@ -24,6 +24,9 @@ struct serial_efi_priv {
> >>>        bool have_key;
> >>>    };
> >>>
> >>> +/* Convert a lower-case character to its ctrl-char equivalent */
> >>> +#define CTL_CH(c)            ((c) - 'a' + 1)
> >>> +
> >>>    int serial_efi_setbrg(struct udevice *dev, int baudrate)
> >>>    {
> >>>        return 0;
> >>> @@ -49,6 +52,7 @@ static int serial_efi_get_key(struct serial_efi_priv *priv)
> >>>    static int serial_efi_getc(struct udevice *dev)
> >>>    {
> >>>        struct serial_efi_priv *priv = dev_get_priv(dev);
> >>> +     char conv_scan[10] = {0, 'p', 'n', 'f', 'b', 'a', 'e', 0, 8};
> >>>        int ret, ch;
> >>>
> >>>        ret = serial_efi_get_key(priv);
> >>> @@ -63,8 +67,11 @@ static int serial_efi_getc(struct udevice *dev)
> >>>         * key scan code of 8. Handle this so that backspace works correctly
> >>>         * in the U-Boot command line.
> >>>         */
> >>> -     if (!ch && priv->key.scan_code == 8)
> >>> -             ch = 8;
> >>> +     if (!ch && priv->key.scan_code < sizeof(conv_scan)) {
> >>> +             ch = conv_scan[priv->key.scan_code];
> >>> +             if (ch >= 'a')
> >>> +                     ch -= 'a' - 1;
> >>
> >> This is not what a serial console would use in Linux. Just try U-Boot's
> >> conitrace command. If you use the following, we get compatibility with
> >> the rest of U-Boot:
> >>
> >> 1b 5b 32 7e - insert
> >> 1b 5b 33 7e - delete
> >> 1b 5b 35 7e - page up
> >> 1b 5b 36 7e - page down
> >> 1b 5b 41 - up
> >> 1b 5b 42 - down
> >> 1b 5b 43 - right
> >> 1b 5b 44 - left
> >> 1b 5b 46 - end
> >> 1b 5b 48 - home
> >
> > That's more complicated since it requires the serial driver to convert
> > one character into multiple. We can always add it later if needed. But
> > this does command-line history, etc. working in the app.
>
> Yes you will need a ring buffer as in the USB keyboard driver.
>
> lib/efi_loader/efi_console.c only understands the multi-byte sequences.
> I do not know if there are other places which have the same limitation.

The ones I am using here are the official U-Boot codes. Perhaps
EFI_LOADER should be fixed, but this doesn't matter for the EFI app.

In any case, this work can be done later if needed.

Regards,
Simon
diff mbox series

Patch

diff --git a/drivers/serial/serial_efi.c b/drivers/serial/serial_efi.c
index 33ddbd6080c..0067576389d 100644
--- a/drivers/serial/serial_efi.c
+++ b/drivers/serial/serial_efi.c
@@ -24,6 +24,9 @@  struct serial_efi_priv {
 	bool have_key;
 };
 
+/* Convert a lower-case character to its ctrl-char equivalent */
+#define CTL_CH(c)		((c) - 'a' + 1)
+
 int serial_efi_setbrg(struct udevice *dev, int baudrate)
 {
 	return 0;
@@ -49,6 +52,7 @@  static int serial_efi_get_key(struct serial_efi_priv *priv)
 static int serial_efi_getc(struct udevice *dev)
 {
 	struct serial_efi_priv *priv = dev_get_priv(dev);
+	char conv_scan[10] = {0, 'p', 'n', 'f', 'b', 'a', 'e', 0, 8};
 	int ret, ch;
 
 	ret = serial_efi_get_key(priv);
@@ -63,8 +67,11 @@  static int serial_efi_getc(struct udevice *dev)
 	 * key scan code of 8. Handle this so that backspace works correctly
 	 * in the U-Boot command line.
 	 */
-	if (!ch && priv->key.scan_code == 8)
-		ch = 8;
+	if (!ch && priv->key.scan_code < sizeof(conv_scan)) {
+		ch = conv_scan[priv->key.scan_code];
+		if (ch >= 'a')
+			ch -= 'a' - 1;
+	}
 	debug(" [%x %x %x] ", ch, priv->key.unicode_char, priv->key.scan_code);
 
 	return ch;