mirror of
git://projects.qi-hardware.com/iris.git
synced 2025-04-21 12:27:27 +03:00
use usb server for communication
This commit is contained in:
30
mips/nanonote/server/Makefile.am
Normal file
30
mips/nanonote/server/Makefile.am
Normal file
@@ -0,0 +1,30 @@
|
||||
# Iris: micro-kernel for a capability-based operating system.
|
||||
# mips/nanonote/server/Makefile.am: build rules
|
||||
# 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/>.
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
|
||||
bin_PROGRAMS = usb-server
|
||||
|
||||
usb_server_SOURCES = usb-server.cc
|
||||
usb_server_CPPFLAGS = $(SHEVEK_CFLAGS) -DSTAGE1_FILE=\"mips/nanonote/sdram-setup.raw\" -DSTAGE2_FILE=\"iris.raw\"
|
||||
usb_server_LDFLAGS = $(SHEVEK_LIBS) -lusb
|
||||
|
||||
PYPP = /usr/bin/pypp
|
||||
%.cc: %.ccp
|
||||
$(PYPP) --name $< < $< > $@
|
||||
|
||||
BUILT_SOURCES = usb-server.cc
|
||||
9
mips/nanonote/server/configure.ac
Normal file
9
mips/nanonote/server/configure.ac
Normal file
@@ -0,0 +1,9 @@
|
||||
AC_INIT(usb-server, 1.0, wijnen@debian.org)
|
||||
AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION)
|
||||
|
||||
AC_PROG_CXX
|
||||
|
||||
PKG_CHECK_MODULES(SHEVEK, shevek,, AC_MSG_ERROR(You need libshevek to compile AC_PACKAGE_NAME))
|
||||
|
||||
AC_CONFIG_FILES(Makefile)
|
||||
AC_OUTPUT
|
||||
179
mips/nanonote/server/usb-server.ccp
Normal file
179
mips/nanonote/server/usb-server.ccp
Normal file
@@ -0,0 +1,179 @@
|
||||
#pypp 0
|
||||
// Iris: micro-kernel for a capability-based operating system.
|
||||
// mips/nanonote/server/usb-server.ccp: Host-side helper for USB.
|
||||
// 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 <unistd.h>
|
||||
#include <usb.h>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <shevek/mainloop.hh>
|
||||
#include <shevek/server.hh>
|
||||
#include <shevek/args.hh>
|
||||
|
||||
struct client
|
||||
|
||||
struct data:
|
||||
Glib::RefPtr <shevek::server <client, data *> > server
|
||||
usb_dev_handle *handle
|
||||
static int const boot_vendor = 0x601a
|
||||
static int const boot_product = 0x4740
|
||||
static int const run_vendor = 0xfffe
|
||||
static int const run_product = 0x0002
|
||||
static unsigned const timeout = 1000
|
||||
void boot (unsigned entry)
|
||||
data (std::string const &port):
|
||||
handle = NULL
|
||||
server = shevek::server <client, data *>::create ()
|
||||
server->data () = this
|
||||
server->open (port)
|
||||
|
||||
private:
|
||||
static unsigned const STAGE1_LOAD = 0x80002000
|
||||
static unsigned const STAGE2_LOAD = 0x80000000
|
||||
static unsigned const STAGE1_ENTRY = STAGE1_LOAD
|
||||
enum requests:
|
||||
VR_GET_CPU_INFO = 0
|
||||
VR_SET_DATA_ADDRESS = 1
|
||||
VR_SET_DATA_LENGTH = 2
|
||||
VR_FLUSH_CACHES = 3
|
||||
VR_PROGRAM_START1 = 4
|
||||
VR_PROGRAM_START2 = 5
|
||||
void request (requests num, unsigned data = 0)
|
||||
void send_file (unsigned address, unsigned size, char const *data)
|
||||
void reboot ():
|
||||
// This always fails, because the device doesn't answer. However, that means there's nothing wrong, so don't complain.
|
||||
usb_control_msg (handle, USB_ENDPOINT_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, VR_GET_CPU_INFO, 0, 0, NULL, 8, timeout)
|
||||
usb_release_interface (handle, 0)
|
||||
usb_close (handle)
|
||||
handle = NULL
|
||||
void get_device (unsigned vendor, unsigned product, unsigned tries)
|
||||
|
||||
struct client : public shevek::server <client, data *>::connection:
|
||||
static Glib::RefPtr <client> create ():
|
||||
return Glib::RefPtr <client> (new client ())
|
||||
bool keep
|
||||
void pickup (bool is_stdio):
|
||||
keep = is_stdio
|
||||
void read (std::string const &line):
|
||||
shevek::istring l (line)
|
||||
unsigned entry
|
||||
if l ("reboot %x%", entry):
|
||||
get_server ()->data ()->boot (entry)
|
||||
else:
|
||||
out->write ("invalid command\n")
|
||||
if !keep:
|
||||
out->write_block ()
|
||||
disconnect ()
|
||||
|
||||
void data::request (requests r, unsigned data):
|
||||
if usb_control_msg (handle, USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, r, (data >> 16) & 0xffff, data & 0xffff, NULL, 0, timeout) < 0:
|
||||
std::cerr << "unable to send control message to NanoNote: " << usb_strerror () << ".\n"
|
||||
usb_release_interface (handle, 0)
|
||||
usb_close (handle)
|
||||
handle = NULL
|
||||
|
||||
void data::send_file (unsigned address, unsigned size, char const *data):
|
||||
request (VR_SET_DATA_ADDRESS, address)
|
||||
char const *ptr = data
|
||||
while ptr - data < size:
|
||||
int ret = usb_bulk_write (handle, 1, ptr, size - (ptr - data), timeout)
|
||||
if ret <= 0:
|
||||
std::cerr << "failed to write to NanoNote.\n"
|
||||
usb_release_interface (handle, 0)
|
||||
usb_close (handle)
|
||||
handle = NULL
|
||||
return
|
||||
ptr += ret
|
||||
|
||||
void data::get_device (unsigned vendor, unsigned product, unsigned tries):
|
||||
for unsigned i = 0; i < tries; ++i:
|
||||
usb_find_busses ()
|
||||
usb_find_devices ()
|
||||
for struct usb_bus *bus = usb_busses; bus; bus = bus->next:
|
||||
for struct usb_device *dev = bus->devices; dev; dev = dev->next:
|
||||
if dev->descriptor.idProduct != product || dev->descriptor.idVendor != vendor:
|
||||
//std::cerr << shevek::ostring ("Not using %04x:%04x when looking for %04x:%04x\n", dev->descriptor.idVendor, dev->descriptor.idProduct, vendor, product)
|
||||
continue
|
||||
handle = usb_open (dev)
|
||||
if usb_claim_interface (handle, 0) < 0:
|
||||
std::cerr << "unable to claim interface\n"
|
||||
usb_close (handle)
|
||||
handle = NULL
|
||||
continue
|
||||
return
|
||||
if i + 1 < tries:
|
||||
//std::cerr << "failed to find device, still trying...\n"
|
||||
sleep (1)
|
||||
std::cerr << shevek::ostring ("giving up finding device %04x:%04x\n", vendor, product)
|
||||
|
||||
void data::boot (unsigned entry):
|
||||
std::cerr << "booting " << shevek::ostring ("%x", entry) << "\n"
|
||||
if handle:
|
||||
usb_release_interface (handle, 0)
|
||||
usb_close (handle)
|
||||
handle = NULL
|
||||
get_device (boot_vendor, boot_product, 1)
|
||||
if !handle:
|
||||
get_device (run_vendor, run_product, 1)
|
||||
if !handle:
|
||||
std::cerr << "unable to find device\n"
|
||||
return
|
||||
reboot ()
|
||||
get_device (boot_vendor, boot_product, 5)
|
||||
if !handle:
|
||||
std::cerr << "unable to reboot device\n"
|
||||
return
|
||||
std::cerr << "sending stage 1\n"
|
||||
std::ifstream file (STAGE1_FILE)
|
||||
std::ostringstream stage1
|
||||
stage1 << file.rdbuf ()
|
||||
send_file (STAGE1_LOAD, stage1.str ().size (), stage1.str ().data ())
|
||||
std::cerr << "running stage 1\n"
|
||||
request (VR_PROGRAM_START1, STAGE1_ENTRY)
|
||||
usleep (100)
|
||||
std::ostringstream stage2
|
||||
usb_release_interface (handle, 0)
|
||||
file.close ()
|
||||
file.open (STAGE2_FILE)
|
||||
stage2 << file.rdbuf ()
|
||||
std::cerr << "sending Iris\n"
|
||||
send_file (STAGE2_LOAD, stage2.str ().size (), stage2.str ().data ())
|
||||
std::cerr << "flushing caches\n"
|
||||
request (VR_FLUSH_CACHES)
|
||||
std::cerr << "running Iris\n"
|
||||
request (VR_PROGRAM_START2, entry)
|
||||
usb_release_interface (handle, 0)
|
||||
usb_close (handle)
|
||||
handle = NULL
|
||||
get_device (run_vendor, run_product, 5)
|
||||
if !handle:
|
||||
std::cerr << "unable to open booted device\n"
|
||||
return
|
||||
std::cerr << "(re)booted NanoNote\n"
|
||||
|
||||
int main (int argc, char **argv):
|
||||
usb_init ()
|
||||
std::string port ("5050")
|
||||
shevek::args::option opts[] = {
|
||||
shevek::args::option ('p', "port", "port to listen for commands", true, port)
|
||||
}
|
||||
shevek::args args (argc, argv, opts, 0, 0, "device server for testing Iris on NanoNote", "2009")
|
||||
data d (port)
|
||||
shevek::loop ()
|
||||
return 0
|
||||
Reference in New Issue
Block a user