Re: [PATCH v3 2/3] vt: introduce unicode mode for /dev/vcs

2018-06-29 Thread Geert Uytterhoeven
Hi Nicolas,

On Wed, Jun 27, 2018 at 7:03 AM Nicolas Pitre  wrote:
> Now that the core vt code knows how to preserve unicode values for each
> displayed character, it is then possible to let user space access it via
> /dev/vcs*.
>
> Unicode characters are presented as 32 bit values in native endianity
> via the /dev/vcsu* devices, mimicking the simple /dev/vcs* devices.
> Unicode with attributes (similarly to /dev/vcsa*) is not supported at
> the moment.
>
> Data is available only as long as the console is in UTF-8 mode. ENODATA
> is returned otherwise.
>
> This was tested with the latest development version (to become
> version 5.7) of BRLTTY. Amongst other things, this allows ⠋⠕⠗ ⠞⠓⠊⠎
> ⠃⠗⠁⠊⠇⠇⠑⠀⠞⠑⠭⠞⠀to appear directly on braille displays regardless of the
> console font being used.
>
> Signed-off-by: Nicolas Pitre 

Thanks for your patch (which is now in tty-next).

> --- a/drivers/tty/vt/vc_screen.c
> +++ b/drivers/tty/vt/vc_screen.c

> @@ -51,6 +57,26 @@
>
>  #define CON_BUF_SIZE (CONFIG_BASE_SMALL ? 256 : PAGE_SIZE)
>
> +/*
> + * Our minor space:
> + *
> + *   0 ... 63  glyph mode without attributes
> + *  64 ... 127 unicode mode without attributes
> + * 128 ... 191 glyph mode with attributes
> + * 192 ... 255 unused (reserved for unicode with attributes)
> + *
> + * This relies on MAX_NR_CONSOLES being  <= 63, meaning 63 actual consoles
> + * with minors 0, 64, 128 and 192 being proxies for the foreground console.
> + */
> +#if MAX_NR_CONSOLES > 63
> +#warning "/dev/vcs* devices may not accommodate more than 63 consoles"
> +#endif

MAX_NR_CONSOLES is part of UAPI, so it cannot change.
It doesn't hurt to have an explicit check here, though.

However, looking into that I noticed include/uapi/linux/vt.h says:

#define MAX_NR_CONSOLES 63  /* serial lines start at 64 */

But that seems to apply to /dev/tty* (major 4), not /dev/vcs* (major 7),
so you're safe.

> +
> +#define console(inode) (iminor(inode) & 63)
> +#define use_unicode(inode) (iminor(inode) & 64)
> +#define use_attributes(inode)  (iminor(inode) & 128)

I guess you need to update Documentation/admin-guide/devices.txt, and
add /dev/vcsu*?

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds


[PATCH v3 2/3] vt: introduce unicode mode for /dev/vcs

2018-06-26 Thread Nicolas Pitre
Now that the core vt code knows how to preserve unicode values for each
displayed character, it is then possible to let user space access it via
/dev/vcs*.

Unicode characters are presented as 32 bit values in native endianity
via the /dev/vcsu* devices, mimicking the simple /dev/vcs* devices.
Unicode with attributes (similarly to /dev/vcsa*) is not supported at
the moment.

Data is available only as long as the console is in UTF-8 mode. ENODATA
is returned otherwise.

This was tested with the latest development version (to become
version 5.7) of BRLTTY. Amongst other things, this allows ⠋⠕⠗ ⠞⠓⠊⠎
⠃⠗⠁⠊⠇⠇⠑⠀⠞⠑⠭⠞⠀to appear directly on braille displays regardless of the
console font being used.

Signed-off-by: Nicolas Pitre 
Tested-by: Dave Mielke 
Acked-by: Adam Borowski 
---
 drivers/tty/vt/vc_screen.c | 89 --
 drivers/tty/vt/vt.c| 61 ++
 include/linux/selection.h  |  5 +++
 3 files changed, 141 insertions(+), 14 deletions(-)

diff --git a/drivers/tty/vt/vc_screen.c b/drivers/tty/vt/vc_screen.c
index e4a66e1fd0..9c44252e52 100644
--- a/drivers/tty/vt/vc_screen.c
+++ b/drivers/tty/vt/vc_screen.c
@@ -10,6 +10,12 @@
  * Attribute/character pair is in native endianity.
  *[minor: N+128]
  *
+ * /dev/vcsuN: similar to /dev/vcsaN but using 4-byte unicode values
+ * instead of 1-byte screen glyph values.
+ *[minor: N+64]
+ *
+ * /dev/vcsuaN: same idea as /dev/vcsaN for unicode (not yet implemented).
+ *
  * This replaces screendump and part of selection, so that the system
  * administrator can control access using file system permissions.
  *
@@ -51,6 +57,26 @@
 
 #define CON_BUF_SIZE (CONFIG_BASE_SMALL ? 256 : PAGE_SIZE)
 
+/*
+ * Our minor space:
+ *
+ *   0 ... 63  glyph mode without attributes
+ *  64 ... 127 unicode mode without attributes
+ * 128 ... 191 glyph mode with attributes
+ * 192 ... 255 unused (reserved for unicode with attributes)
+ *
+ * This relies on MAX_NR_CONSOLES being  <= 63, meaning 63 actual consoles
+ * with minors 0, 64, 128 and 192 being proxies for the foreground console.
+ */
+#if MAX_NR_CONSOLES > 63
+#warning "/dev/vcs* devices may not accommodate more than 63 consoles"
+#endif
+
+#define console(inode) (iminor(inode) & 63)
+#define use_unicode(inode) (iminor(inode) & 64)
+#define use_attributes(inode)  (iminor(inode) & 128)
+
+
 struct vcs_poll_data {
struct notifier_block notifier;
unsigned int cons_num;
@@ -102,7 +128,7 @@ vcs_poll_data_get(struct file *file)
poll = kzalloc(sizeof(*poll), GFP_KERNEL);
if (!poll)
return NULL;
-   poll->cons_num = iminor(file_inode(file)) & 127;
+   poll->cons_num = console(file_inode(file));
init_waitqueue_head(&poll->waitq);
poll->notifier.notifier_call = vcs_notifier;
if (register_vt_notifier(&poll->notifier) != 0) {
@@ -140,7 +166,7 @@ vcs_poll_data_get(struct file *file)
 static struct vc_data*
 vcs_vc(struct inode *inode, int *viewed)
 {
-   unsigned int currcons = iminor(inode) & 127;
+   unsigned int currcons = console(inode);
 
WARN_CONSOLE_UNLOCKED();
 
@@ -164,7 +190,6 @@ static int
 vcs_size(struct inode *inode)
 {
int size;
-   int minor = iminor(inode);
struct vc_data *vc;
 
WARN_CONSOLE_UNLOCKED();
@@ -175,8 +200,12 @@ vcs_size(struct inode *inode)
 
size = vc->vc_rows * vc->vc_cols;
 
-   if (minor & 128)
+   if (use_attributes(inode)) {
+   if (use_unicode(inode))
+   return -EOPNOTSUPP;
size = 2*size + HEADER_SIZE;
+   } else if (use_unicode(inode))
+   size *= 4;
return size;
 }
 
@@ -197,12 +226,10 @@ static ssize_t
 vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 {
struct inode *inode = file_inode(file);
-   unsigned int currcons = iminor(inode);
struct vc_data *vc;
struct vcs_poll_data *poll;
-   long pos;
-   long attr, read;
-   int col, maxcol, viewed;
+   long pos, read;
+   int attr, uni_mode, row, col, maxcol, viewed;
unsigned short *org = NULL;
ssize_t ret;
char *con_buf;
@@ -218,7 +245,8 @@ vcs_read(struct file *file, char __user *buf, size_t count, 
loff_t *ppos)
 */
console_lock();
 
-   attr = (currcons & 128);
+   uni_mode = use_unicode(inode);
+   attr = use_attributes(inode);
ret = -ENXIO;
vc = vcs_vc(inode, &viewed);
if (!vc)
@@ -227,6 +255,10 @@ vcs_read(struct file *file, char __user *buf, size_t 
count, loff_t *ppos)
ret = -EINVAL;
if (pos < 0)
goto unlock_out;
+   /* we enforce 32-bit alignment for pos and count in unicode mode */
+   if (uni_mode && (pos | count) & 3)
+   goto unlock_out;
+
poll = file->private_data;
if (count && poll)
poll->seen_last_update