Landfall

Annotated pkg/landfall-examples/letux400_keypad_driver/letux400_keypad_driver.cc

0:89a1bc19c1fc
2018-05-13 Paul Boddie Added device libraries and programs, configuration files and examples. Also added an installation script and copyright and licensing information.
paul@0 1
/*
paul@0 2
 * Access the keypad on the configured device using an input driver.
paul@0 3
 *
paul@0 4
 * (c) 2018 Paul Boddie <paul@boddie.org.uk>
paul@0 5
 *
paul@0 6
 * This program is free software; you can redistribute it and/or
paul@0 7
 * modify it under the terms of the GNU General Public License as
paul@0 8
 * published by the Free Software Foundation; either version 2 of
paul@0 9
 * the License, or (at your option) any later version.
paul@0 10
 *
paul@0 11
 * This program is distributed in the hope that it will be useful,
paul@0 12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
paul@0 13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
paul@0 14
 * GNU General Public License for more details.
paul@0 15
 *
paul@0 16
 * You should have received a copy of the GNU General Public License
paul@0 17
 * along with this program; if not, write to the Free Software
paul@0 18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
paul@0 19
 * Boston, MA  02110-1301, USA
paul@0 20
 *
paul@0 21
 *
paul@0 22
 * Font definitions and licence (see unifont.tff for bitmap data derived from
paul@0 23
 * GNU Unifont's unifont.hex file):
paul@0 24
 *
paul@0 25
 * Copyright (C) 1998-2003 Roman Czyborra (http://czyborra.com/)
paul@0 26
 *
paul@0 27
 *   All glyphs are released under the GNU General Public License
paul@0 28
 *   (GPL) version 2 or (at your option) a later version, with the
paul@0 29
 *   GNU font embedding exception:
paul@0 30
 *
paul@0 31
 *        ** GPL v2.0 license with font embedding exception:
paul@0 32
 *
paul@0 33
 *        As a special exception, if you create a document which
paul@0 34
 *        uses this font, and embed this font or unaltered portions
paul@0 35
 *        of this font into the document, this font does not by
paul@0 36
 *        itself cause the resulting document to be covered by
paul@0 37
 *        the GNU General Public License. This exception does not
paul@0 38
 *        however invalidate any other reasons why the document
paul@0 39
 *        might be covered by the GNU General Public License.
paul@0 40
 *        If you modify this font, you may extend this exception
paul@0 41
 *        to your version of the font, but you are not obligated
paul@0 42
 *        to do so. If you do not wish to do so, delete this
paul@0 43
 *        exception statement from your version.
paul@0 44
 */
paul@0 45
paul@0 46
#include <l4/devices/input-keypad-client.h>
paul@0 47
paul@0 48
#include <l4/re/c/util/video/goos_fb.h>
paul@0 49
#include <l4/re/c/video/view.h>
paul@0 50
#include <l4/util/util.h>
paul@0 51
paul@0 52
#include <l4/mag-gfx/canvas>
paul@0 53
#include <l4/mag-gfx/font>
paul@0 54
#include <l4/mag-gfx/geometry>
paul@0 55
#include <l4/mag-gfx/gfx_colors>
paul@0 56
#include <l4/mag-gfx/mem_factory>
paul@0 57
paul@0 58
#include <stdint.h>
paul@0 59
#include <string.h>
paul@0 60
paul@0 61
/* Video abstractions. */
paul@0 62
paul@0 63
static l4re_util_video_goos_fb_t gfb;
paul@0 64
static l4re_video_view_info_t view_info;
paul@0 65
static void *fb = 0;
paul@0 66
paul@0 67
/* Bundled font data. */
paul@0 68
paul@0 69
extern char const _binary_unifont_tff_start[];
paul@0 70
paul@0 71
/* Screen abstractions. */
paul@0 72
paul@0 73
using namespace Mag_gfx;
paul@0 74
paul@0 75
static Font *_font = 0;
paul@0 76
static Canvas *_screen = 0;
paul@0 77
paul@0 78
paul@0 79
paul@0 80
/* Factories for certain pixel formats. */
paul@0 81
paul@0 82
static Mem::Factory<Rgb16> _rgb16;
paul@0 83
static Mem::Factory<Rgb32> _rgb32;
paul@0 84
paul@0 85
paul@0 86
paul@0 87
/* Key to character conversion function. */
paul@0 88
paul@0 89
static const char *keys_to_strings[] = {
paul@0 90
paul@0 91
  0, "Escape", "1", "2", "3", "4", "5", "6", "7", "8",
paul@0 92
paul@0 93
  "9", "0", "-", "=", "Backspace", "Tab", "Q", "W", "E", "R",
paul@0 94
paul@0 95
  "T", "Y", "U", "I", "O", "P", "[", "]", "Enter", "Left Ctrl",
paul@0 96
paul@0 97
  "A", "S", "D", "F", "G", "H", "J", "K", "L", ";",
paul@0 98
paul@0 99
  "'", "`", "Left Shift", "\\", "Z", "X", "C", "V", "B", "N",
paul@0 100
paul@0 101
  "M", ",", ".", "/", "Right Shift", "Keypad *", "Left Alt", "Space",
paul@0 102
    "Caps Lock", "F1",
paul@0 103
paul@0 104
  "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "Num Lock",
paul@0 105
paul@0 106
  "Scroll Lock", "Keypad 7", "Keypad 8", "Keypad 9", "Keypad -", "Keypad 4",
paul@0 107
    "Keypad 5", "Keypad 6", "Keypad +", "Keypad 1",
paul@0 108
paul@0 109
  "Keypad 2", "Keypad 3", "Keypad 0", "Keypad .", 0, 0, "#102", "F11", "F12", 0,
paul@0 110
paul@0 111
  0, 0, 0, 0, 0, 0, "Keypad Enter", "Right Ctrl", "Keypad /", "SysRq",
paul@0 112
paul@0 113
  "Right Alt", "Line Feed", "Home", "Up", "Page Up", "Left", "Right", "End",
paul@0 114
    "Down", "Page Down",
paul@0 115
paul@0 116
  "Insert", "Delete", "Macro", "Mute", "Volume Down", "Volume Up", "Power",
paul@0 117
    "Keypad =", "Keypad +-", "Pause",
paul@0 118
};
paul@0 119
paul@0 120
static const char null_string[] = "Unknown";
paul@0 121
paul@0 122
const int keys_to_strings_length = 120;
paul@0 123
paul@0 124
static const char *key_to_string(int key)
paul@0 125
{
paul@0 126
  return key < keys_to_strings_length ? keys_to_strings[key] : 0;
paul@0 127
}
paul@0 128
paul@0 129
/* Show the keypad event status on the display. */
paul@0 130
paul@0 131
static uint8_t row = 0;
paul@0 132
static uint32_t text_x = 0, text_y = 0, next_y = 0;
paul@0 133
paul@0 134
static void handler(Input_event event, void *priv)
paul@0 135
{
paul@0 136
  uint32_t colsize = view_info.width / 10,
paul@0 137
           rowsize = view_info.height / 20;
paul@0 138
  uint8_t column;
paul@0 139
  uint16_t mask;
paul@0 140
paul@0 141
  /* Convert the key code into a bit pattern. */
paul@0 142
paul@0 143
  if (!priv)
paul@0 144
  {
paul@0 145
    for (column = 0, mask = (1 << 9); column < 10; column++, mask >>= 1)
paul@0 146
      _screen->draw_box(Rect(Point(column * colsize, row * rowsize), Area(colsize, rowsize)),
paul@0 147
                        event.code & mask ? event.value ? Rgb32::Color(0, 255, 0) : Rgb32::Color(255, 0, 0)
paul@0 148
                                          : Rgb32::Color(0, 0, 0));
paul@0 149
paul@0 150
    /* Advance to the next row, wrapping around. */
paul@0 151
paul@0 152
    row = (row + 1) % 20;
paul@0 153
  }
paul@0 154
paul@0 155
  /* Or produce a string. */
paul@0 156
paul@0 157
  else if (event.value)
paul@0 158
  {
paul@0 159
    const char *s = ((const char *(*)(int)) priv)(event.code);
paul@0 160
    Rgba32::Color col;
paul@0 161
paul@0 162
    if (!s)
paul@0 163
    {
paul@0 164
      s = null_string;
paul@0 165
      col = Rgba32::Color(255, 0, 0, Rgba32::Color::Amax);
paul@0 166
    }
paul@0 167
    else
paul@0 168
      col = Rgba32::Color(255, 255, 255, Rgba32::Color::Amax);
paul@0 169
paul@0 170
    Area box = _font->str_sz(s, strlen(s));
paul@0 171
paul@0 172
    /* Test for enough space horizontally. */
paul@0 173
paul@0 174
    if (text_x + box.w() > view_info.width)
paul@0 175
    {
paul@0 176
      text_x = 0;
paul@0 177
      text_y = next_y;
paul@0 178
      next_y = text_y + box.h();
paul@0 179
    }
paul@0 180
paul@0 181
    /* Expand the line height, if appropriate. */
paul@0 182
paul@0 183
    else if (text_y + box.h() > next_y)
paul@0 184
      next_y += box.h();
paul@0 185
paul@0 186
    /* Test for enough space vertically. */
paul@0 187
paul@0 188
    if (next_y > view_info.height)
paul@0 189
    {
paul@0 190
      text_x = 0;
paul@0 191
      text_y = 0;
paul@0 192
      next_y = box.h();
paul@0 193
    }
paul@0 194
paul@0 195
    Point p(text_x, text_y);
paul@0 196
paul@0 197
    _screen->draw_box(Rect(p, box), Rgb32::Color(0, 0, 0));
paul@0 198
    _screen->draw_string(p, _font, col, s, strlen(s));
paul@0 199
paul@0 200
    /* Move to the next position. */
paul@0 201
paul@0 202
    text_x += box.w();
paul@0 203
  }
paul@0 204
paul@0 205
  /* Refresh the display. */
paul@0 206
paul@0 207
  l4re_util_video_goos_fb_refresh(&gfb, 0, 0, view_info.width, view_info.height);
paul@0 208
}
paul@0 209
paul@0 210
/* Arguments: [ chars ] */
paul@0 211
paul@0 212
int main(int argc, char *argv[])
paul@0 213
{
paul@0 214
  Keypad *keypad = Keypad::get_keypad();
paul@0 215
  Input_keypad_client client(keypad);
paul@0 216
paul@0 217
  if (l4re_util_video_goos_fb_setup_name(&gfb, "fb"))
paul@0 218
    return 1;
paul@0 219
paul@0 220
  if (l4re_util_video_goos_fb_view_info(&gfb, &view_info))
paul@0 221
    return 1;
paul@0 222
paul@0 223
  if (!(fb = l4re_util_video_goos_fb_attach_buffer(&gfb)))
paul@0 224
    return 1;
paul@0 225
paul@0 226
  /* Obtain a canvas for the framebuffer. */
paul@0 227
paul@0 228
  Factory *factory;
paul@0 229
paul@0 230
  if (view_info.pixel_info.bytes_per_pixel == 2)
paul@0 231
    factory = &_rgb16;
paul@0 232
  else
paul@0 233
    factory = &_rgb32;
paul@0 234
paul@0 235
  Canvas *screen = factory->create_canvas((void *) ((unsigned long) fb + view_info.buffer_offset),
paul@0 236
      Area(view_info.width, view_info.height),
paul@0 237
      view_info.bytes_per_line);
paul@0 238
paul@0 239
  Font font(&_binary_unifont_tff_start[0]);
paul@0 240
paul@0 241
  _screen = screen;
paul@0 242
  _font = &font;
paul@0 243
paul@0 244
  /* Attach the event handler and wait for events. */
paul@0 245
paul@0 246
  client.attach(handler, (argc > 1) && (!strcmp(argv[1], "chars")) ? (void *) key_to_string : 0);
paul@0 247
paul@0 248
  l4_sleep_forever();
paul@0 249
paul@0 250
  return 0;
paul@0 251
}