mirror of
git://projects.qi-hardware.com/iris.git
synced 2025-04-21 12:27:27 +03:00
fix bugs; work on userspace
This commit is contained in:
@@ -23,10 +23,9 @@
|
||||
class DevBuzzer:
|
||||
static unsigned const pwm = 4
|
||||
Kernel::Cap event
|
||||
bool is_active, is_beeping
|
||||
bool is_beeping
|
||||
public:
|
||||
DevBuzzer ():
|
||||
is_active = false
|
||||
is_beeping = false
|
||||
gpio_as_pwm4 ()
|
||||
tcu_stop_counter (pwm)
|
||||
@@ -38,8 +37,8 @@ class DevBuzzer:
|
||||
return
|
||||
tcu_stop_counter (pwm)
|
||||
event.invoke ()
|
||||
is_active = false
|
||||
Kernel::free_cap (event)
|
||||
is_beeping = false
|
||||
void beep (unsigned freq, unsigned ms, Kernel::Cap cb):
|
||||
stop ()
|
||||
event = cb
|
||||
@@ -115,12 +114,11 @@ Kernel::Num start ():
|
||||
break
|
||||
switch Kernel::recv.data[0].l:
|
||||
case Buzzer::BEEP:
|
||||
// Volume is not used for this buzzer.
|
||||
// Volume is not used by this buzzer.
|
||||
Kernel::Cap arg = Kernel::get_arg ()
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
buzzer.beep (Kernel::recv.data[1].l, Kernel::recv.data[1].h, arg)
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (arg)
|
||||
Kernel::free_cap (reply)
|
||||
break
|
||||
case Buzzer::STOP:
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "iris.hh"
|
||||
#include "devices.hh"
|
||||
|
||||
// For some unknown reason, gcc needs this to be defined.
|
||||
unsigned __gxx_personality_v0
|
||||
@@ -33,7 +34,7 @@ namespace Kernel:
|
||||
Thread my_thread
|
||||
Memory my_memory
|
||||
Cap my_call
|
||||
Cap my_parent
|
||||
Parent my_parent
|
||||
__recv_data_t recv
|
||||
|
||||
void print_caps ():
|
||||
|
||||
@@ -1,271 +0,0 @@
|
||||
#pypp 0
|
||||
// Iris: micro-kernel for a capability-based operating system.
|
||||
// boot-programs/devices.hhp: interfaces for core devices.
|
||||
// Copyright 2009 Bas Wijnen <wijnen@debian.org>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef __IRIS_DEVICES_HH
|
||||
#define __IRIS_DEVICES_HH
|
||||
|
||||
#include "iris.hh"
|
||||
|
||||
// List interface.
|
||||
template <typename _T> //
|
||||
struct List : public Kernel::Caps:
|
||||
List (Kernel::Caps c = Kernel::Cap ()) : Kernel::Caps (c):
|
||||
List <_T> create (unsigned size, Kernel::Memory mem = Kernel::my_memory):
|
||||
return List <_T> (mem.create_caps (size))
|
||||
void set (unsigned idx, _T value):
|
||||
return Kernel::Caps::set (idx, value)
|
||||
_T get (unsigned idx):
|
||||
return _T (Kernel::Caps::get (idx))
|
||||
|
||||
/// A block of data with a size and content. Any character can be stored in it (including '\0').
|
||||
struct String : public Kernel::Cap:
|
||||
String (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
|
||||
enum request:
|
||||
GET_SIZE = 0x2001
|
||||
GET_CHARS
|
||||
GET_PAGE
|
||||
ID
|
||||
/// Get the size of the string.
|
||||
Kernel::Num get_size ():
|
||||
return call (CAP_MASTER_DIRECT | GET_SIZE)
|
||||
/// Get exactly 16 characters. The index must be word-aligned.
|
||||
char *get_chars (Kernel::Num idx, char buffer[16]):
|
||||
call (CAP_MASTER_DIRECT | GET_CHARS, idx)
|
||||
unsigned *b = (unsigned *)buffer
|
||||
b[0] = Kernel::recv.data[0].l
|
||||
b[1] = Kernel::recv.data[0].h
|
||||
b[2] = Kernel::recv.data[1].l
|
||||
b[3] = Kernel::recv.data[1].h
|
||||
return buffer
|
||||
/// Get a page from the string. This need not be implemented for strings smaller than PAGE_SIZE. The index must be page-aligned.
|
||||
Cap get_page (Kernel::Num idx, Kernel::Page ret = Kernel::my_memory.create_page ()):
|
||||
ocall (ret, CAP_MASTER_DIRECT | GET_PAGE, idx)
|
||||
return ret
|
||||
|
||||
/// A writable String.
|
||||
struct WString : public String:
|
||||
WString (Kernel::Cap c = Kernel::Cap ()) : String (c):
|
||||
enum request:
|
||||
TRUNCATE = String::ID
|
||||
SET_CHARS
|
||||
SET_PAGE
|
||||
ID
|
||||
/// Set the size of the string. Strings may have a limit to this setting.
|
||||
void truncate (Kernel::Num size):
|
||||
call (CAP_MASTER_DIRECT | TRUNCATE, size)
|
||||
/// Set exactly 4 characters. The index must be word-aligned.
|
||||
void set_chars (Kernel::Num idx, char buffer[4]):
|
||||
call (Kernel::Num (CAP_MASTER_DIRECT | SET_CHARS, *(unsigned *)buffer), idx)
|
||||
/// Overwrite a page from the string. This need not be implemented for strings smaller than PAGE_SIZE. The index must be page-aligned. The caller may lose the frame in the transaction.
|
||||
void set_page (Kernel::Num idx, Kernel::Page page):
|
||||
ocall (page, CAP_MASTER_DIRECT | SET_PAGE, idx)
|
||||
|
||||
// Every process which wants to be switchable through a terminal must implement this interface.
|
||||
struct Device : public Kernel::Cap:
|
||||
Device (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
|
||||
enum request:
|
||||
CREATE_USER = WString::ID
|
||||
DESTROY_USER
|
||||
UNUSE
|
||||
USE
|
||||
ID
|
||||
// Create a new user for this device. It will not be the active user.
|
||||
// The provided storage must allow object creation; no other actions may be used by the terminal.
|
||||
Kernel::Cap create_user (Kernel::Memory storage):
|
||||
iocall (storage, CAP_MASTER_DIRECT | CREATE_USER)
|
||||
return Kernel::get_arg ()
|
||||
// Destroy a user. It must not be active.
|
||||
void destroy_user (Kernel::Cap user):
|
||||
ocall (user, CAP_MASTER_DIRECT | DESTROY_USER)
|
||||
// Make user inactive.
|
||||
void unuse (Kernel::Cap user):
|
||||
ocall (user, CAP_MASTER_DIRECT | UNUSE)
|
||||
// Make user active.
|
||||
void use (Kernel::Cap user):
|
||||
ocall (user, CAP_MASTER_DIRECT | USE)
|
||||
|
||||
// Keyboard interface.
|
||||
struct Keyboard : public Kernel::Cap:
|
||||
Keyboard (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
|
||||
enum request:
|
||||
SET_CB = Device::ID
|
||||
GET_KEYS
|
||||
ID
|
||||
// At event: the callback is called with a keycode. One bit defines if it's a press or release event.
|
||||
enum constant:
|
||||
RELEASE = 1 << 31
|
||||
// Set the event callback. Currently pressed keys emit a key press event to the new callback immediately.
|
||||
void set_cb (Kernel::Cap cb):
|
||||
ocall (cb, CAP_MASTER_DIRECT | SET_CB)
|
||||
// Get a list of keys on this keyboard. The key codes start at zero with no gaps.
|
||||
List <String> get_keys ():
|
||||
icall (CAP_MASTER_DIRECT | GET_KEYS)
|
||||
return List <String> (Kernel::get_arg ())
|
||||
|
||||
// Buzzer interface.
|
||||
struct Buzzer : public Kernel::Cap:
|
||||
Buzzer (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
|
||||
enum request:
|
||||
BEEP = Keyboard::ID
|
||||
STOP
|
||||
ID
|
||||
// Emit a beep of specified frequency, time and volume. Volume may not be supported.
|
||||
void beep (unsigned freq, unsigned ms, unsigned volume, Kernel::Cap cb = Kernel::Cap ()):
|
||||
ocall (cb, Kernel::Num (CAP_MASTER_DIRECT | BEEP, volume), Kernel::Num (freq, ms))
|
||||
// Abort current beep, if any.
|
||||
void stop ():
|
||||
call (CAP_MASTER_DIRECT | STOP)
|
||||
|
||||
// Display interface.
|
||||
struct Display : public Kernel::Cap:
|
||||
Display (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
|
||||
enum request:
|
||||
EOF_CB = Buzzer::ID
|
||||
CREATE_FB
|
||||
USE_FB
|
||||
GET_INFO
|
||||
ID
|
||||
// Register an end-of-frame callback.
|
||||
// At end of frame, the callback is invoked and forgotten. It must be reregistered to keep a stream of events.
|
||||
void set_eof_cb (Kernel::Cap cb):
|
||||
ocall (cb, CAP_MASTER_DIRECT | EOF_CB)
|
||||
// Create a framebuffer for the display. When not in use, it can be freed by the user.
|
||||
// The pages must be cappages holding Page capabilities. They are filled by the display.
|
||||
// The passed numbers must be 0 or match a mode that the device can use.
|
||||
// The returned number is the physical address of the framebuffer. It can be used with display_use_framebuffer.
|
||||
unsigned create_framebuffer (unsigned w = 0, unsigned h = 0, unsigned mode = 0):
|
||||
return icall (Kernel::Num (CAP_MASTER_DIRECT | CREATE_FB, 0), Kernel::Num ((w << 16) | h, mode)).l
|
||||
// Use a framebuffer. The address must have been returned from display_create_framebuffer.
|
||||
// w, h and mode must match the values given at creation time.
|
||||
// unuse_cb is called the next time this operation is requested for this display.
|
||||
void use_framebuffer (unsigned addr, Kernel::Cap unuse_cb = Kernel::Cap (), unsigned w = 0, unsigned h = 0, unsigned mode = 0):
|
||||
ocall (unuse_cb, Kernel::Num (CAP_MASTER_DIRECT | USE_FB, addr), Kernel::Num ((w << 16) | h, mode))
|
||||
// Get information about the display.
|
||||
void get_info ():
|
||||
// TODO: Interface is to be designed.
|
||||
|
||||
|
||||
|
||||
// File system interface.
|
||||
// filesystem-related interfaces: file, directory, stream, seekable, mappable.
|
||||
// Normal files implement at least stream or seekable file. Directories implement directory.
|
||||
struct File : public Kernel::Cap:
|
||||
File (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
|
||||
enum request:
|
||||
INFO = Display::ID
|
||||
CLOSE
|
||||
MAP_HANDLE
|
||||
ID
|
||||
// Get information about the file.
|
||||
Kernel::Num get_info (unsigned type):
|
||||
return icall (Kernel::Num (CAP_MASTER_DIRECT | INFO, type))
|
||||
// Close a file. If this is a directory, it implicitly closes all files opened from it.
|
||||
void close ():
|
||||
call (CAP_MASTER_DIRECT | CLOSE)
|
||||
// Map a file handle. This can be useful for closing all children at once. The new handle itself is a child of the original handle.
|
||||
File map_handle ():
|
||||
icall (CAP_MASTER_DIRECT | MAP_HANDLE)
|
||||
return Kernel::get_arg ()
|
||||
|
||||
// Directory interface.
|
||||
struct Directory : public File:
|
||||
Directory (Kernel::Cap c = Kernel::Cap ()) : File (c):
|
||||
enum request:
|
||||
GET_SIZE = File::ID
|
||||
GET_NAME
|
||||
GET_FILE
|
||||
GET_FILE_INFO
|
||||
CREATE_FILE
|
||||
DELETE_FILE
|
||||
ID
|
||||
// Get the number of entries in this directory.
|
||||
Kernel::Num get_size ():
|
||||
return call (CAP_MASTER_DIRECT | GET_SIZE)
|
||||
// Get the filename. The return value is the size of the string, the page is filled with the string itself.
|
||||
String get_name (Kernel::Num idx):
|
||||
icall (CAP_MASTER_DIRECT | GET_NAME, idx)
|
||||
return Kernel::get_arg ()
|
||||
// Get the file.
|
||||
File get_file (Kernel::Num idx):
|
||||
icall (CAP_MASTER_DIRECT | GET_FILE, idx)
|
||||
return Kernel::get_arg ()
|
||||
// Get file info. This returns the same information as file_get_info, without opening the file.
|
||||
Kernel::Num get_file_info (Kernel::Num idx, unsigned type):
|
||||
return icall (Kernel::Num (CAP_MASTER_DIRECT | GET_FILE_INFO, type), idx)
|
||||
// Create a new file. After this, any index may map to a different file.
|
||||
File create_file (String name):
|
||||
icall (CAP_MASTER_DIRECT | CREATE_FILE)
|
||||
return Kernel::get_arg ()
|
||||
// Delete a file. After this, any index may map to a different file.
|
||||
void delete_file (Kernel::Num idx):
|
||||
call (CAP_MASTER_DIRECT | DELETE_FILE, idx)
|
||||
|
||||
// Stream interface.
|
||||
struct Stream : public File:
|
||||
Stream (Kernel::Cap c = Kernel::Cap ()) : File (c):
|
||||
enum request:
|
||||
READ = Directory::ID
|
||||
WRITE
|
||||
ID
|
||||
// Try to read size bytes. Returns the number of bytes successfully read.
|
||||
Kernel::Num read (Kernel::Num size):
|
||||
return icall (CAP_MASTER_DIRECT | READ, size)
|
||||
// Try to write size bytes. Returns the number of bytes successfully written.
|
||||
Kernel::Num write (String s, Kernel::Num size):
|
||||
return ocall (s, CAP_MASTER_DIRECT | WRITE, size)
|
||||
|
||||
// Seekable file interface.
|
||||
struct Seekable : public File:
|
||||
Seekable (Kernel::Cap c = Kernel::Cap ()) : File (c):
|
||||
enum request:
|
||||
READ = Stream::ID
|
||||
WRITE
|
||||
TRUNCATE
|
||||
ID
|
||||
// Try to read size bytes from position idx. Returns the number of bytes successfully read.
|
||||
Kernel::Num read (Kernel::Num idx, unsigned size):
|
||||
return icall (Kernel::Num (CAP_MASTER_DIRECT | READ, size), idx)
|
||||
// Try to write size bytes at position idx; the file is extended with zeroes if the write is past the end. Returns the number of bytes successfully written.
|
||||
Kernel::Num write (Kernel::Num idx, String s):
|
||||
return ocall (s, CAP_MASTER_DIRECT | WRITE, idx)
|
||||
// Truncate file to size idx. The file is extended with zeroes if it gets longer.
|
||||
void truncate (Kernel::Num idx):
|
||||
call (CAP_MASTER_DIRECT | TRUNCATE, idx)
|
||||
|
||||
// Mappable file interface.
|
||||
struct Mappable : public Seekable:
|
||||
Mappable (Kernel::Cap c = Kernel::Cap ()) : Seekable (c):
|
||||
// TODO: to be designed.
|
||||
|
||||
|
||||
|
||||
// Block device interface.
|
||||
struct Block_device : public Mappable:
|
||||
Block_device (Kernel::Cap c = Kernel::Cap ()) : Mappable (c):
|
||||
// TODO: to be designed.
|
||||
|
||||
|
||||
// TODO.
|
||||
// Sound interface.
|
||||
// Usb interfaces (port, device).
|
||||
// Pointer interface. (Only movement; buttons follow keyboard interface.)
|
||||
// Network interface.
|
||||
// Camera interface.
|
||||
// Terminal interfaces.
|
||||
|
||||
#endif
|
||||
@@ -19,28 +19,50 @@
|
||||
#include "devices.hh"
|
||||
#include "iris.hh"
|
||||
|
||||
static Keyboard kbd, sysreq
|
||||
static Buzzer buzzer
|
||||
static Keyboard sysreq
|
||||
static Device kbd_dev, buz_dev
|
||||
static List <String> kbd_names
|
||||
static unsigned slot
|
||||
|
||||
// Event types.
|
||||
enum type:
|
||||
MEMORY
|
||||
KBDDEV
|
||||
KBD
|
||||
KEYNAMES
|
||||
SYSREQ
|
||||
KBDDEV
|
||||
BUZDEV
|
||||
BUZZER
|
||||
|
||||
static void user_reply (Kernel::Cap target, unsigned dev):
|
||||
switch dev:
|
||||
case Keyboard::ID:
|
||||
// keyboard user
|
||||
kdebug ("keyboard requested\n")
|
||||
Kernel::Cap kbd = kbd_dev.create_user (Kernel::Cap ())
|
||||
kbd_dev.use (kbd)
|
||||
target.invoke (0, 0, kbd.copy ())
|
||||
Kernel::free_cap (kbd)
|
||||
break
|
||||
case Buzzer::ID:
|
||||
// buzzer user
|
||||
kdebug ("buzzer requested\n")
|
||||
Kernel::Cap buzzer = buz_dev.create_user (Kernel::Cap ())
|
||||
buz_dev.use (buzzer)
|
||||
kdebug ("invoking reply: ")
|
||||
kdebug_num (target.code)
|
||||
kdebug ("\n")
|
||||
target.invoke (0, 0, buzzer.copy ())
|
||||
Kernel::free_cap (buzzer)
|
||||
break
|
||||
default:
|
||||
kdebug ("invalid id requested:")
|
||||
kdebug_num (dev)
|
||||
kdebug_char ('\n')
|
||||
break
|
||||
|
||||
static void setup ():
|
||||
unsigned state = 0
|
||||
Kernel::Caps caps = Kernel::my_memory.create_caps (32)
|
||||
slot = caps.use ()
|
||||
Kernel::set_recv_arg (Kernel::Cap (slot, MEMORY))
|
||||
Kernel::Cap driver_memory = Kernel::my_memory.create_memory ()
|
||||
Kernel::Caps slot0 = Kernel::my_thread.get_caps (0)
|
||||
Kernel::Cap user
|
||||
unsigned device
|
||||
while true:
|
||||
Kernel::wait ()
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
@@ -59,44 +81,38 @@ static void setup ():
|
||||
default:
|
||||
kdebug ("unexpected keyboard\n")
|
||||
break
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (reply)
|
||||
break
|
||||
case Buzzer::ID:
|
||||
caps.set (BUZDEV, arg.copy ())
|
||||
buz_dev = Kernel::Cap (slot, BUZDEV)
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (reply)
|
||||
break
|
||||
case Parent::GET_DEVICE:
|
||||
user = reply
|
||||
device = Kernel::recv.data[1].l
|
||||
slot0.print (reply.idx ())
|
||||
break
|
||||
default:
|
||||
kdebug ("unknown setup request for init\n")
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (reply)
|
||||
Kernel::free_cap (arg)
|
||||
kdebug ("unknown setup request for init\n")
|
||||
continue
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (reply)
|
||||
Kernel::free_cap (arg)
|
||||
if ++state == 3:
|
||||
if ++state == 4:
|
||||
break
|
||||
// sysreq
|
||||
kdebug ("using sysreq\n")
|
||||
Kernel::Cap cb = Kernel::my_receiver.create_capability (SYSREQ)
|
||||
sysreq.set_cb (cb.copy ())
|
||||
// keyboard user
|
||||
Kernel::set_recv_arg (Kernel::Cap (slot, KBD))
|
||||
kbd = kbd_dev.create_user (driver_memory)
|
||||
kbd_dev.use (kbd)
|
||||
// keyboard callback
|
||||
Kernel::set_recv_arg (cb)
|
||||
Kernel::my_receiver.create_capability (KBD)
|
||||
kbd.set_cb (cb.copy ())
|
||||
// keyboard name list
|
||||
Kernel::set_recv_arg (Kernel::Cap (slot, KEYNAMES))
|
||||
kbd_names = kbd.get_keys ()
|
||||
// buzzer user
|
||||
Kernel::set_recv_arg (Kernel::Cap (slot, BUZZER))
|
||||
buzzer = buz_dev.create_user (driver_memory)
|
||||
buz_dev.use (buzzer)
|
||||
// clean up.
|
||||
Kernel::free_cap (cb)
|
||||
|
||||
//char const *decode_kbd = "0123456789abcdefghijklmnopqrstuvwxyz!@#$%^&*() T\n[],.-=/\\;|`'UDLREIKBPFZMS{}CA\":"
|
||||
char const *decode_kbd = "0123456789abcdefghijklmnopqrstuvwxyz!@#$*T\nE& B=UDLR+-F^CA"
|
||||
// First user reply.
|
||||
kdebug ("sending first user reply\n")
|
||||
user_reply (user, device)
|
||||
Kernel::free_cap (user)
|
||||
|
||||
Kernel::Num start ():
|
||||
setup ()
|
||||
@@ -112,20 +128,11 @@ Kernel::Num start ():
|
||||
else:
|
||||
kdebug ("pressed.\n\n")
|
||||
break
|
||||
case KBD:
|
||||
unsigned code = Kernel::recv.data[0].l
|
||||
if code & Keyboard::RELEASE:
|
||||
kdebug_char ('-')
|
||||
else:
|
||||
kdebug_char ('+')
|
||||
buzzer.beep (2000, 100, 0)
|
||||
String name = kbd_names.get (code & ~Keyboard::RELEASE)
|
||||
unsigned size = name.get_size ().l
|
||||
char buffer[16]
|
||||
for unsigned i = 0; i < size; i += 16:
|
||||
name.get_chars (i, buffer)
|
||||
for unsigned k = 0; k < size - i && k < 16; ++k:
|
||||
kdebug_char (buffer[k])
|
||||
kdebug_char ('\n')
|
||||
Kernel::free_cap (name)
|
||||
default:
|
||||
if Kernel::recv.data[0].l != Parent::GET_DEVICE:
|
||||
kdebug ("invalid call from user\n")
|
||||
break
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
user_reply (reply, Kernel::recv.data[1].l)
|
||||
Kernel::free_cap (reply)
|
||||
break
|
||||
|
||||
@@ -27,9 +27,15 @@ extern unsigned char const charset[127-32][6]
|
||||
|
||||
#define assert(x) do { while (!(x)) kdebug ("assertion failed " #x); } while (0)
|
||||
|
||||
#if defined (TRENDTAC)
|
||||
// For now, support only 16 bpp.
|
||||
// Screen is 800x480 tft.
|
||||
static unsigned h = 800, v = 480, hs = 80, vs = 20, fps = 60, Bpp = 2
|
||||
#else if defined (NANONOTE)
|
||||
static unsigned h = 320, v = 240, fps = 70, Bpp = 3
|
||||
#else
|
||||
#error unknown board
|
||||
#endif
|
||||
#define frame_size (v * h * Bpp)
|
||||
|
||||
static unsigned physical_descriptor
|
||||
@@ -40,21 +46,49 @@ struct Descriptor:
|
||||
unsigned id
|
||||
unsigned cmd
|
||||
|
||||
#if defined (TRENDTAC)
|
||||
static void reset ():
|
||||
LCD_CTRL = LCD_CTRL_BPP_16 | LCD_CTRL_BST_16
|
||||
LCD_VSYNC = vs
|
||||
LCD_HSYNC = hs
|
||||
LCD_DAV = (vs << 16) | (vs + v)
|
||||
LCD_DAH = (hs << 16) | (hs + h)
|
||||
LCD_VAT = ((hs + h) << 16) | (vs + v)
|
||||
#if defined (TRENDTAC)
|
||||
unsigned fps = 60
|
||||
// Vertical timings.
|
||||
unsigned vps = 0, vpe = vps + 20, vds = vpe, vde = vds + v, vt = vde
|
||||
// Horizontal timings.
|
||||
unsigned hps = 0, hpe = hps + 80, hds = hpe, hde = hds + h, ht = hde
|
||||
unsigned extra = 0
|
||||
// Bits per pixel.
|
||||
unsigned bpp = LCD_CTRL_BPP_16
|
||||
// Configuration.
|
||||
#define MODE_TFT_GEN 0
|
||||
#define VSYNC_N (1 << 8)
|
||||
LCD_CFG = MODE_TFT_GEN | VSYNC_N
|
||||
unsigned cfg = MODE_TFT_GEN | VSYNC_N
|
||||
#elif defined (NANONOTE)
|
||||
unsigned fps = 70
|
||||
// Vertical timings.
|
||||
unsigned vps = 0, vpe = vps + 1, vds = vpe + 20, vde = vds + v, vt = vde + 1
|
||||
// Horizontal timings.
|
||||
unsigned hps = 0, hpe = hps + 1, hds = hpe + 140, hde = hds + h, ht = hde + 273
|
||||
// 3 bytes per pixel, so for the display area 2 extra clocks are sent.
|
||||
unsigned extra = 2
|
||||
// Bits per pixel.
|
||||
unsigned bpp = LCD_CTRL_BPP_18_24
|
||||
// Configuration.
|
||||
unsigned cfg = LCD_CFG_MODE_TFT_SERIAL_TFT | LCD_CFG_PCP | LCD_CFG_HSP | LCD_CFG_VSP
|
||||
#else
|
||||
#error unknown board
|
||||
#endif
|
||||
|
||||
LCD_CTRL = bpp | LCD_CTRL_BST_16
|
||||
LCD_VSYNC = (vps << 16) | vpe
|
||||
LCD_HSYNC = (hps << 16) | hpe
|
||||
LCD_DAV = (vds << 16) | vde
|
||||
LCD_DAH = (hds << 16) | hde
|
||||
LCD_VAT = (ht << 16) | vt
|
||||
LCD_CFG = cfg
|
||||
|
||||
cpm_stop_lcd ()
|
||||
|
||||
unsigned pixclock = fps * (hs + h) * (vs + v)
|
||||
unsigned pixclock = fps * (ht + extra * (hde - hds)) * vt
|
||||
|
||||
#if defined (TRENDTAC)
|
||||
unsigned pllout = cpm_get_pllout ()
|
||||
CPM_CFCR2 = pllout / pixclock - 1
|
||||
|
||||
@@ -63,18 +97,29 @@ static void reset ():
|
||||
assert (val <= 0xf)
|
||||
cpm_set_lcdclk_div (val)
|
||||
CPM_CFCR |= CPM_CFCR_UPE
|
||||
#elif defined (NANONOTE)
|
||||
unsigned val = cpm_get_pllout2 () / pclk - 1
|
||||
if val > 0x3ff:
|
||||
kdebug ("pixel clock too large\n")
|
||||
Kernel::panic ()
|
||||
return
|
||||
cpm_set_pixdiv (val);
|
||||
|
||||
val = cpm_get_pllout () / (pixclock * 3)
|
||||
if val > 0x1f:
|
||||
kdebug ("pixel divider too large\n")
|
||||
Kernel::panic ()
|
||||
return
|
||||
cpm_set_ldiv (val)
|
||||
// Update dividers.
|
||||
CPM_CPCCR |= CPM_CPCCR_CE
|
||||
#endif
|
||||
|
||||
cpm_start_lcd ()
|
||||
|
||||
LCD_DA0 = physical_descriptor
|
||||
lcd_set_ena ()
|
||||
lcd_enable_eof_intr ()
|
||||
#elif defined (NANONOTE)
|
||||
static void reset ():
|
||||
// TODO
|
||||
#else
|
||||
#error unknown board
|
||||
#endif
|
||||
|
||||
static void putchar (unsigned x, unsigned y, unsigned ch, unsigned fg = 0xffff, unsigned bg = 0x0000):
|
||||
if ch < 32 || ch > 126:
|
||||
@@ -83,19 +128,19 @@ static void putchar (unsigned x, unsigned y, unsigned ch, unsigned fg = 0xffff,
|
||||
unsigned lookup[2] = { bg, fg }
|
||||
for unsigned k = 0; k < 6; ++k:
|
||||
for unsigned r = 0; r < 8; ++r:
|
||||
LCD_FRAMEBUFFER_BASE[(y * 8 + r) * 800 + x * 6 + k] = lookup[charset[ch][k] & (1 << r) ? 1 : 0]
|
||||
LCD_FRAMEBUFFER_BASE[(y * 8 + r) * h + x * 6 + k] = lookup[charset[ch][k] & (1 << r) ? 1 : 0]
|
||||
|
||||
static unsigned log_x = 1, log_y = 1
|
||||
static void inc_logx ():
|
||||
if ++log_x >= 800 / 6:
|
||||
if ++log_x >= h / 6:
|
||||
log_x = 1
|
||||
if ++log_y >= 480 / 8:
|
||||
if ++log_y >= v / 8:
|
||||
log_y = 1
|
||||
|
||||
static void log_char (unsigned ch):
|
||||
switch ch:
|
||||
case '\n':
|
||||
while log_x < 800 / 6:
|
||||
while log_x < h / 6:
|
||||
putchar (log_x++, log_y, ' ')
|
||||
inc_logx ()
|
||||
break
|
||||
@@ -138,22 +183,22 @@ Kernel::Num start ():
|
||||
p.alloc_physical (physical + i * PAGE_SIZE, false, true)
|
||||
Kernel::my_memory.map (p, (unsigned)LCD_FRAMEBUFFER_BASE + i * PAGE_SIZE)
|
||||
Kernel::free_cap (p)
|
||||
for unsigned y = 0; y < 480; ++y:
|
||||
unsigned g = (y << 6) / 480
|
||||
unsigned olr = 0, ob = ((25 * y * y) << 5) / (9 * 800 * 800 + 25 * 480 * 480)
|
||||
for unsigned x = 0; x < 800; ++x:
|
||||
unsigned r = (x << 5) / 800
|
||||
unsigned b = ((9 * x * x + 25 * y * y) << 5) / (9 * 800 * 800 + 25 * 480 * 480)
|
||||
for unsigned y = 0; y < v; ++y:
|
||||
unsigned g = (y << 6) / v
|
||||
unsigned olr = 0, ob = ((25 * y * y) << 5) / (9 * h * h + 25 * v * v)
|
||||
for unsigned x = 0; x < h; ++x:
|
||||
unsigned r = (x << 5) / h
|
||||
unsigned b = ((9 * x * x + 25 * y * y) << 5) / (9 * h * h + 25 * v * v)
|
||||
if r != olr:
|
||||
olr = r
|
||||
r = 0x1f
|
||||
unsigned oyb = b
|
||||
if y > 0:
|
||||
oyb = ((9 * x * x + 25 * (y - 1) * (y - 1)) << 5) / (9 * 800 * 800 + 25 * 480 * 480)
|
||||
oyb = ((9 * x * x + 25 * (y - 1) * (y - 1)) << 5) / (9 * h * h + 25 * v * v)
|
||||
if b != ob || b != oyb:
|
||||
ob = b
|
||||
b = 0x1f
|
||||
LCD_FRAMEBUFFER_BASE[y * 800 + x] = (r << 11) | (g << 5) | (b)
|
||||
LCD_FRAMEBUFFER_BASE[y * h + x] = (r << 11) | (g << 5) | (b)
|
||||
Kernel::Page p = Kernel::my_memory.mapping (&descriptor)
|
||||
physical_descriptor = p.physical_address () + ((unsigned)&descriptor & ~PAGE_MASK)
|
||||
Kernel::free_cap (p)
|
||||
@@ -166,11 +211,12 @@ Kernel::Num start ():
|
||||
reset ()
|
||||
|
||||
Kernel::Cap logcap = Kernel::my_receiver.create_capability (Init::LCD_LOG)
|
||||
#if defined (TRENDTAC)
|
||||
__asm__ volatile ("li $a0, 1\nlw $a1, %0\nbreak" :: "m"(logcap.code): "a0", "a1", "memory")
|
||||
#endif
|
||||
|
||||
((Init)Kernel::my_parent).register_lcd ()
|
||||
|
||||
Kernel::Cap eof_cb = Kernel::alloc_cap ()
|
||||
Kernel::Cap eof_cb
|
||||
bool have_eof = false
|
||||
while true:
|
||||
Kernel::wait ()
|
||||
//log_msg ()
|
||||
@@ -180,11 +226,15 @@ Kernel::Num start ():
|
||||
eof_cb.invoke ()
|
||||
break
|
||||
case Init::LCD_SET_EOF_CB:
|
||||
Kernel::free_cap (eof_cb)
|
||||
eof_cb = Kernel::recv.arg
|
||||
Kernel::recv.arg = Kernel::alloc_cap ()
|
||||
Kernel::recv.reply.invoke ()
|
||||
if have_eof:
|
||||
Kernel::free_cap (eof_cb)
|
||||
else:
|
||||
have_eof = true
|
||||
eof_cb = Kernel::get_arg ()
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
Kernel::register_interrupt (IRQ_LCD)
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (reply)
|
||||
break
|
||||
case Init::LCD_LOG:
|
||||
log_char (Kernel::recv.data[0].l)
|
||||
|
||||
70
boot-programs/metronome.ccp
Normal file
70
boot-programs/metronome.ccp
Normal file
@@ -0,0 +1,70 @@
|
||||
#pypp 0
|
||||
// Iris: micro-kernel for a capability-based operating system.
|
||||
// boot-programs/metronome.ccp: Userspace program.
|
||||
// Copyright 2009 Bas Wijnen <wijnen@debian.org>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "devices.hh"
|
||||
#include "keys.hh"
|
||||
|
||||
Kernel::Num start ():
|
||||
kdebug ("metronome started\n")
|
||||
Buzzer buzzer = Kernel::my_parent.get_device <Buzzer> ()
|
||||
Keyboard kbd = Kernel::my_parent.get_device <Keyboard> ()
|
||||
Kernel::Cap key = Kernel::my_receiver.create_capability (0)
|
||||
kbd.set_cb (key)
|
||||
unsigned mHz = 1000
|
||||
unsigned freq = 1000
|
||||
Kernel::my_receiver.set_alarm (1)
|
||||
bool running (true)
|
||||
while true:
|
||||
Kernel::wait ()
|
||||
switch Kernel::recv.protected_data.l:
|
||||
case ~0:
|
||||
if running:
|
||||
buzzer.beep (freq, 10, ~0)
|
||||
Kernel::my_receiver.set_alarm (HZ * 1000 / mHz)
|
||||
break
|
||||
case 0:
|
||||
if Kernel::recv.data[0].l & Keyboard::RELEASE:
|
||||
break
|
||||
switch Kernel::recv.data[0].l:
|
||||
case Key::VOLUME_UP:
|
||||
freq = freq * 11 / 10
|
||||
break
|
||||
case Key::VOLUME_DOWN:
|
||||
freq = freq * 9 / 10
|
||||
break
|
||||
case Key::LEFT:
|
||||
mHz = mHz * 101 / 100
|
||||
break
|
||||
case Key::RIGHT:
|
||||
mHz = mHz * 99 / 100
|
||||
break
|
||||
case Key::UP:
|
||||
mHz = mHz * 11 / 10
|
||||
break
|
||||
case Key::DOWN:
|
||||
mHz = mHz * 9 / 10
|
||||
break
|
||||
case Key::P:
|
||||
running = !running
|
||||
if running:
|
||||
Kernel::my_receiver.set_alarm (1)
|
||||
break
|
||||
break
|
||||
default:
|
||||
kdebug ("huh?\n")
|
||||
break
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "devices.hh"
|
||||
#define ARCH
|
||||
#include "arch.hh"
|
||||
#include "keys.hh"
|
||||
|
||||
//#define QI
|
||||
#define SCAN_INTERVAL HZ / 50
|
||||
@@ -33,27 +34,8 @@ class DevKbd:
|
||||
static unsigned const COLS[NUM_COLS]
|
||||
static unsigned const ROWS[NUM_ROWS]
|
||||
static unsigned const encode[NUM_ROWS][NUM_COLS]
|
||||
enum Keys:
|
||||
#ifdef QI
|
||||
A, B, C, D, E, F, G, H, I, J, K, L, M
|
||||
N, O, P, Q, R, S, T, U, V, W, X, Y, Z
|
||||
F1, F2, F3, F4, F5, F6, F7, F8
|
||||
TAB, BACKSLASH, QUOTE, COMMA, PERIOD, SLASH, EQUAL, SPACE
|
||||
ESCAPE, ENTER, BACKSPACE
|
||||
UP, DOWN, LEFT, RIGHT
|
||||
CAPS, ARROW, QI, CTRL, VOLUP, VOLDOWN, SHIFT, ALT, FN
|
||||
#else
|
||||
N0, N1, N2, N3, N4, N5, N6, N7, N8, N9
|
||||
A, B, C, D, E, F, G, H, I, J, K, L, M
|
||||
N, O, P, Q, R, S, T, U, V, W, X, Y, Z
|
||||
F1, F2, F3, F4
|
||||
CAPS, TAB, ENTER, ESCAPE, MP3, SPACE, BACKSPACE, EQUALS
|
||||
UP, DOWN, LEFT, RIGHT
|
||||
VOLUP, VOLDOWN
|
||||
FN, SHIFT, CTRL, ALT
|
||||
#endif
|
||||
NUM_KEYS
|
||||
static char const *const names[NUM_KEYS]
|
||||
static unsigned const NUM_KEYS = 58
|
||||
static unsigned const keys[NUM_KEYS]
|
||||
unsigned state[NUM_COLS]
|
||||
Kernel::Cap event
|
||||
bool is_active
|
||||
@@ -61,27 +43,14 @@ class DevKbd:
|
||||
public:
|
||||
unsigned size ():
|
||||
return NUM_KEYS
|
||||
unsigned get_name_size (unsigned n):
|
||||
if n >= NUM_KEYS:
|
||||
return 0
|
||||
unsigned ret = 0
|
||||
for char const *p = names[n]; *p; ++p:
|
||||
++ret
|
||||
return ret
|
||||
void send_name (unsigned n, Kernel::Cap c, Kernel::Num offset):
|
||||
if n >= NUM_KEYS:
|
||||
c.invoke (0, 0)
|
||||
return
|
||||
unsigned data[4]
|
||||
char *d = (char *)data
|
||||
if offset.value () < get_name_size (n):
|
||||
unsigned o = offset.l & ~3;
|
||||
unsigned p
|
||||
for p = 0; p < 16 && names[n][p + o]; ++p:
|
||||
*d++ = names[n][p + o]
|
||||
for ; p < 16; ++p:
|
||||
*d++ = 0
|
||||
c.invoke (Kernel::Num (data[0], data[1]), Kernel::Num (data[2], data[3]))
|
||||
void send_keys (unsigned first, Kernel::Cap target):
|
||||
unsigned d[4]
|
||||
unsigned i
|
||||
for i = 0; first + i < NUM_KEYS && i < 4; ++i:
|
||||
d[i] = keys[first + i]
|
||||
for ; i < 4; ++i:
|
||||
d[i] = ~0
|
||||
target.invoke (Kernel::Num (d[0], d[1]), Kernel::Num (d[2], d[3]))
|
||||
bool scanning ():
|
||||
return is_scanning
|
||||
void inactive ():
|
||||
@@ -155,43 +124,44 @@ unsigned const DevKbd::COLS[NUM_COLS] = { 10, 11, 12, 13, 14, 15, 16, 17 }
|
||||
unsigned const DevKbd::ROWS[NUM_ROWS] = { 18, 19, 20, 21, 22, 23, 24, 26 }
|
||||
unsigned const DevKbd::encode[NUM_ROWS][NUM_COLS] = {
|
||||
#ifdef QI
|
||||
{ F1, F2, F3, F4, F5, F6, F7, ~0 },
|
||||
{ Q, W, E, R, T, Y, U, I },
|
||||
{ A, S, D, F, G, H, J, K },
|
||||
{ ESCAPE, Z, X, C, V, B, N, M },
|
||||
{ TAB, CAPS, BACKSLASH, QUOTE, COMMA, PERIOD, SLASH, UP },
|
||||
{ O, L, EQUAL, ARROW, SPACE, QI, CTRL, LEFT },
|
||||
{ F8, P, BACKSPACE, ENTER, VOLUP, VOLDOWN, DOWN, RIGHT },
|
||||
{ SHIFT, ALT, FN, ~0, ~0, ~0, ~0, ~0 }
|
||||
{ Key::F1, Key::F2, Key::F3, Key::F4, Key::F5, Key::F6, Key::F7, ~0 },
|
||||
{ Key::Q, Key::W, Key::E, Key::R, Key::T, Key::Y, Key::U, Key::I },
|
||||
{ Key::A, Key::S, Key::D, Key::F, Key::G, Key::H, Key::J, Key::K },
|
||||
{ Key::ESCAPE, Key::Z, Key::X, Key::C, Key::V, Key::B, Key::N, Key::M },
|
||||
{ Key::TAB, Key::CAPS, Key::BACKSLASH, Key::QUOTE, Key::COMMA, Key::PERIOD, Key::SLASH, Key::UP },
|
||||
{ Key::O, Key::L, Key::EQUAL, Key::ARROW, Key::SPACE, Key::QI, Key::CTRL, Key::LEFT },
|
||||
{ Key::F8, Key::P, Key::BACKSPACE, Key::ENTER, Key::VOLUME_UP, Key::VOLUME_DOWN, Key::DOWN, Key::RIGHT },
|
||||
{ Key::SHIFT, Key::ALT, Key::FN, ~0, ~0, ~0, ~0, ~0 }
|
||||
#else
|
||||
{ ESCAPE, TAB, F1, F2, F3, F4, MP3, ~0 },
|
||||
{ N1, N2, N3, N4, N5, N6, N7, N8 },
|
||||
{ Q, W, E, R, T, Y, U, I },
|
||||
{ A, S, D, F, G, H, J, K },
|
||||
{ Z, X, C, V, B, N, M, UP },
|
||||
{ N9, O, L, ALT, CAPS, SPACE, EQUALS, LEFT },
|
||||
{ BACKSPACE, N0, P, ENTER, VOLUP, VOLDOWN, DOWN, RIGHT },
|
||||
{ FN, SHIFT, CTRL, ~0, ~0, ~0, ~0, ~0 }
|
||||
{ Key::ESCAPE, Key::TAB, Key::F1, Key::F2, Key::F3, Key::F4, Key::SPECIAL + 0, ~0 },
|
||||
{ Key::N1, Key::N2, Key::N3, Key::N4, Key::N5, Key::N6, Key::N7, Key::N8 },
|
||||
{ Key::Q, Key::W, Key::E, Key::R, Key::T, Key::Y, Key::U, Key::I },
|
||||
{ Key::A, Key::S, Key::D, Key::F, Key::G, Key::H, Key::J, Key::K },
|
||||
{ Key::Z, Key::X, Key::C, Key::V, Key::B, Key::N, Key::M, Key::UP },
|
||||
{ Key::N9, Key::O, Key::L, Key::LEFT_ALT, Key::CAPS_LOCK, Key::SPACE, Key::EQUALS, Key::LEFT },
|
||||
{ Key::BACKSPACE, Key::N0, Key::P, Key::ENTER, Key::VOLUME_UP, Key::VOLUME_DOWN, Key::DOWN, Key::RIGHT },
|
||||
{ Key::FN, Key::LEFT_SHIFT, Key::LEFT_CONTROL, ~0, ~0, ~0, ~0, ~0 }
|
||||
#endif
|
||||
}
|
||||
char const *const DevKbd::names[NUM_KEYS] = {
|
||||
unsigned const DevKbd::keys[NUM_KEYS] = {
|
||||
#ifdef QI
|
||||
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
|
||||
"n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
|
||||
"f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8",
|
||||
"tab", "\\", "'", ",", ".", "/", "=", "space",
|
||||
"escape", "enter", "backspace",
|
||||
"up", "down", "left", "right",
|
||||
"caps lock", "arrow", "qi", "left control", "volume up", "volume down", "left shift", "left alt", "fn"
|
||||
Key::F1, Key::F2, Key::F3, Key::F4, Key::F5, Key::F6, Key::F7,
|
||||
Key::Q, Key::W, Key::E, Key::R, Key::T, Key::Y, Key::U, Key::I,
|
||||
Key::A, Key::S, Key::D, Key::F, Key::G, Key::H, Key::J, Key::K,
|
||||
Key::ESCAPE, Key::Z, Key::X, Key::C, Key::V, Key::B, Key::N, Key::M,
|
||||
Key::TAB, Key::CAPS, Key::BACKSLASH, Key::QUOTE, Key::COMMA, Key::PERIOD, Key::SLASH, Key::UP,
|
||||
Key::O, Key::L, Key::EQUAL, Key::ARROW, Key::SPACE, Key::QI, Key::CTRL, Key::LEFT,
|
||||
Key::F8, Key::P, Key::BACKSPACE, Key::ENTER, Key::VOLUME_UP, Key::VOLUME_DOWN, Key::DOWN, Key::RIGHT,
|
||||
Key::SHIFT, Key::ALT, Key::FN
|
||||
#else
|
||||
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
|
||||
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
|
||||
"n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
|
||||
"f1", "f2", "f3", "f4",
|
||||
"caps lock", "tab", "enter", "escape", "mp3", "space", "backspace", "=",
|
||||
"up", "down", "left", "right",
|
||||
"volume up", "volume down",
|
||||
"fn", "left shift", "left control", "left alt"
|
||||
Key::ESCAPE, Key::TAB, Key::F1, Key::F2, Key::F3, Key::F4, Key::SPECIAL + 0,
|
||||
Key::N1, Key::N2, Key::N3, Key::N4, Key::N5, Key::N6, Key::N7, Key::N8,
|
||||
Key::Q, Key::W, Key::E, Key::R, Key::T, Key::Y, Key::U, Key::I,
|
||||
Key::A, Key::S, Key::D, Key::F, Key::G, Key::H, Key::J, Key::K,
|
||||
Key::Z, Key::X, Key::C, Key::V, Key::B, Key::N, Key::M, Key::UP,
|
||||
Key::N9, Key::O, Key::L, Key::LEFT_ALT, Key::CAPS_LOCK, Key::SPACE, Key::EQUALS, Key::LEFT,
|
||||
Key::BACKSPACE, Key::N0, Key::P, Key::ENTER, Key::VOLUME_UP, Key::VOLUME_DOWN, Key::DOWN, Key::RIGHT,
|
||||
Key::FN, Key::LEFT_SHIFT, Key::LEFT_CONTROL
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -222,12 +192,10 @@ class PowerButton:
|
||||
|
||||
enum codes:
|
||||
KBD_DEV = 32
|
||||
KBD_LIST
|
||||
PWR
|
||||
|
||||
Kernel::Num start ():
|
||||
map_gpio ()
|
||||
map_tcu ()
|
||||
|
||||
DevKbd kbd
|
||||
PowerButton pwr
|
||||
@@ -242,7 +210,6 @@ Kernel::Num start ():
|
||||
Kernel::my_receiver.set_alarm (SCAN_INTERVAL)
|
||||
unsigned user (~0)
|
||||
unsigned next_user (0)
|
||||
List <String> list = List <String> (Kernel::my_receiver.create_capability (KBD_LIST))
|
||||
Kernel::register_interrupt (IRQ_GPIO3)
|
||||
while true:
|
||||
Kernel::wait ()
|
||||
@@ -307,24 +274,6 @@ Kernel::Num start ():
|
||||
kdebug ("\n")
|
||||
break
|
||||
break
|
||||
case KBD_LIST:
|
||||
// Keyboard name lookup.
|
||||
switch Kernel::recv.data[0].l:
|
||||
case Kernel::Caps::GET:
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
unsigned num = Kernel::recv.data[1].l
|
||||
Kernel::Cap name = Kernel::my_receiver.create_capability (Kernel::Num (num, KBD_LIST))
|
||||
reply.invoke (kbd.get_name_size (num), 0, name.copy ())
|
||||
Kernel::free_cap (name)
|
||||
Kernel::free_cap (reply)
|
||||
break
|
||||
case Kernel::Caps::GET_SIZE:
|
||||
Kernel::recv.reply.invoke (kbd.size ())
|
||||
break
|
||||
default:
|
||||
kdebug ("invalid list operation\n")
|
||||
break
|
||||
break
|
||||
default:
|
||||
break
|
||||
break
|
||||
@@ -337,29 +286,23 @@ Kernel::Num start ():
|
||||
switch Kernel::recv.data[0].l:
|
||||
case Keyboard::SET_CB:
|
||||
kdebug ("set cb\n")
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
kbd.active (Kernel::get_arg ())
|
||||
Kernel::recv.reply.invoke ()
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (reply)
|
||||
break
|
||||
case Keyboard::GET_NUM_KEYS:
|
||||
kdebug ("get #keys\n")
|
||||
Kernel::recv.reply.invoke (kbd.size ())
|
||||
break
|
||||
case Keyboard::GET_KEYS:
|
||||
kdebug ("get keys\n")
|
||||
Kernel::recv.reply.invoke (0, 0, list)
|
||||
kbd.send_keys (Kernel::recv.data[0].l, Kernel::recv.reply)
|
||||
break
|
||||
default:
|
||||
kdebug ("other\n")
|
||||
break
|
||||
break
|
||||
case KBD_LIST:
|
||||
switch Kernel::recv.data[0].l:
|
||||
case String::GET_SIZE:
|
||||
Kernel::recv.reply.invoke (kbd.get_name_size (Kernel::recv.protected_data.l))
|
||||
break
|
||||
case String::GET_CHARS:
|
||||
kbd.send_name (Kernel::recv.protected_data.l, Kernel::recv.reply, Kernel::recv.data[1])
|
||||
break
|
||||
default:
|
||||
kdebug ("invalid string operation\n")
|
||||
break
|
||||
break
|
||||
default:
|
||||
kdebug ("unknown num: ")
|
||||
kdebug_num (Kernel::recv.protected_data.h)
|
||||
|
||||
Reference in New Issue
Block a user