aboutsummaryrefslogtreecommitdiff
path: root/libmpio
diff options
context:
space:
mode:
Diffstat (limited to 'libmpio')
-rw-r--r--libmpio/Makefile.am24
-rw-r--r--libmpio/Makefile.in372
-rw-r--r--libmpio/debug.c293
-rw-r--r--libmpio/debug.h102
-rw-r--r--libmpio/defs.h192
-rw-r--r--libmpio/directory.c509
-rw-r--r--libmpio/directory.h50
-rw-r--r--libmpio/ecc.c203
-rw-r--r--libmpio/ecc.h36
-rw-r--r--libmpio/fat.c414
-rw-r--r--libmpio/fat.h47
-rw-r--r--libmpio/io.c618
-rw-r--r--libmpio/io.h58
-rw-r--r--libmpio/mpio.c769
-rw-r--r--libmpio/mpio.h97
-rw-r--r--libmpio/smartmedia.c153
-rw-r--r--libmpio/smartmedia.h39
17 files changed, 3976 insertions, 0 deletions
diff --git a/libmpio/Makefile.am b/libmpio/Makefile.am
new file mode 100644
index 0000000..0517b3a
--- /dev/null
+++ b/libmpio/Makefile.am
@@ -0,0 +1,24 @@
+INCLUDES=
+
+lib_LTLIBRARIES=libmpio.la
+
+libmpio_la_SOURCES= \
+ mpio.c \
+ io.c \
+ debug.c \
+ smartmedia.c \
+ directory.c \
+ fat.c \
+ ecc.c
+
+pkginclude_HEADERS= \
+ mpio.h \
+ defs.h
+
+noinst_HEADERS= \
+ io.h \
+ debug.h \
+ smartmedia.h \
+ directory.h \
+ fat.h \
+ ecc.h
diff --git a/libmpio/Makefile.in b/libmpio/Makefile.in
new file mode 100644
index 0000000..b555d58
--- /dev/null
+++ b/libmpio/Makefile.in
@@ -0,0 +1,372 @@
+# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_alias = @build_alias@
+build_triplet = @build@
+host_alias = @host_alias@
+host_triplet = @host@
+target_alias = @target_alias@
+target_triplet = @target@
+AS = @AS@
+CC = @CC@
+DLLTOOL = @DLLTOOL@
+ECHO = @ECHO@
+EXEEXT = @EXEEXT@
+HAVE_GETOPT_H = @HAVE_GETOPT_H@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+MAKEINFO = @MAKEINFO@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+RANLIB = @RANLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+
+INCLUDES =
+
+lib_LTLIBRARIES = libmpio.la
+
+libmpio_la_SOURCES = \
+ mpio.c \
+ io.c \
+ debug.c \
+ smartmedia.c \
+ directory.c \
+ fat.c \
+ ecc.c
+
+
+pkginclude_HEADERS = \
+ mpio.h \
+ defs.h
+
+
+noinst_HEADERS = \
+ io.h \
+ debug.h \
+ smartmedia.h \
+ directory.h \
+ fat.h \
+ ecc.h
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_CLEAN_FILES =
+LTLIBRARIES = $(lib_LTLIBRARIES)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir)
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+libmpio_la_LDFLAGS =
+libmpio_la_LIBADD =
+libmpio_la_OBJECTS = mpio.lo io.lo debug.lo smartmedia.lo directory.lo \
+fat.lo ecc.lo
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+HEADERS = $(noinst_HEADERS) $(pkginclude_HEADERS)
+
+DIST_COMMON = Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = gtar
+GZIP_ENV = --best
+SOURCES = $(libmpio_la_SOURCES)
+OBJECTS = $(libmpio_la_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .lo .o .obj .s
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps libmpio/Makefile
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-libLTLIBRARIES:
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+
+distclean-libLTLIBRARIES:
+
+maintainer-clean-libLTLIBRARIES:
+
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ $(mkinstalldirs) $(DESTDIR)$(libdir)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo "$(LIBTOOL) --mode=install $(INSTALL) $$p $(DESTDIR)$(libdir)/$$p"; \
+ $(LIBTOOL) --mode=install $(INSTALL) $$p $(DESTDIR)$(libdir)/$$p; \
+ else :; fi; \
+ done
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/$$p; \
+ done
+
+.c.o:
+ $(COMPILE) -c $<
+
+# FIXME: We should only use cygpath when building on Windows,
+# and only if it is available.
+.c.obj:
+ $(COMPILE) -c `cygpath -w $<`
+
+.s.o:
+ $(COMPILE) -c $<
+
+.S.o:
+ $(COMPILE) -c $<
+
+mostlyclean-compile:
+ -rm -f *.o core *.core
+ -rm -f *.$(OBJEXT)
+
+clean-compile:
+
+distclean-compile:
+ -rm -f *.tab.c
+
+maintainer-clean-compile:
+
+.c.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.s.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.S.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+
+maintainer-clean-libtool:
+
+libmpio.la: $(libmpio_la_OBJECTS) $(libmpio_la_DEPENDENCIES)
+ $(LINK) -rpath $(libdir) $(libmpio_la_LDFLAGS) $(libmpio_la_OBJECTS) $(libmpio_la_LIBADD) $(LIBS)
+
+install-pkgincludeHEADERS: $(pkginclude_HEADERS)
+ @$(NORMAL_INSTALL)
+ $(mkinstalldirs) $(DESTDIR)$(pkgincludedir)
+ @list='$(pkginclude_HEADERS)'; for p in $$list; do \
+ if test -f "$$p"; then d= ; else d="$(srcdir)/"; fi; \
+ echo " $(INSTALL_DATA) $$d$$p $(DESTDIR)$(pkgincludedir)/$$p"; \
+ $(INSTALL_DATA) $$d$$p $(DESTDIR)$(pkgincludedir)/$$p; \
+ done
+
+uninstall-pkgincludeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ list='$(pkginclude_HEADERS)'; for p in $$list; do \
+ rm -f $(DESTDIR)$(pkgincludedir)/$$p; \
+ done
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ here=`pwd` && cd $(srcdir) \
+ && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+ || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+ -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = libmpio
+
+distdir: $(DISTFILES)
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+ cp -pr $$d/$$file $(distdir)/$$file; \
+ else \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file || :; \
+ fi; \
+ done
+debug.lo debug.o : debug.c debug.h
+directory.lo directory.o : directory.c debug.h io.h defs.h mpio.h \
+ directory.h
+ecc.lo ecc.o : ecc.c ecc.h defs.h debug.h
+fat.lo fat.o : fat.c fat.h defs.h io.h debug.h
+io.lo io.o : io.c io.h defs.h debug.h ecc.h
+mpio.lo mpio.o : mpio.c defs.h debug.h directory.h io.h mpio.h \
+ smartmedia.h fat.h
+mpio_io.lo mpio_io.o : mpio_io.c mpio_io.h mpio_defs.h
+smartmedia.lo smartmedia.o : smartmedia.c smartmedia.h defs.h debug.h
+
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am: install-libLTLIBRARIES
+install-exec: install-exec-am
+
+install-data-am: install-pkgincludeHEADERS
+install-data: install-data-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am: uninstall-libLTLIBRARIES uninstall-pkgincludeHEADERS
+uninstall: uninstall-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+all-redirect: all-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs:
+ $(mkinstalldirs) $(DESTDIR)$(libdir) $(DESTDIR)$(pkgincludedir)
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -rm -f Makefile $(CONFIG_CLEAN_FILES)
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am: mostlyclean-libLTLIBRARIES mostlyclean-compile \
+ mostlyclean-libtool mostlyclean-tags \
+ mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am: clean-libLTLIBRARIES clean-compile clean-libtool clean-tags \
+ clean-generic mostlyclean-am
+
+clean: clean-am
+
+distclean-am: distclean-libLTLIBRARIES distclean-compile \
+ distclean-libtool distclean-tags distclean-generic \
+ clean-am
+ -rm -f libtool
+
+distclean: distclean-am
+
+maintainer-clean-am: maintainer-clean-libLTLIBRARIES \
+ maintainer-clean-compile maintainer-clean-libtool \
+ maintainer-clean-tags maintainer-clean-generic \
+ distclean-am
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-libLTLIBRARIES distclean-libLTLIBRARIES \
+clean-libLTLIBRARIES maintainer-clean-libLTLIBRARIES \
+uninstall-libLTLIBRARIES install-libLTLIBRARIES mostlyclean-compile \
+distclean-compile clean-compile maintainer-clean-compile \
+mostlyclean-libtool distclean-libtool clean-libtool \
+maintainer-clean-libtool uninstall-pkgincludeHEADERS \
+install-pkgincludeHEADERS tags mostlyclean-tags distclean-tags \
+clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \
+check-am installcheck-am installcheck install-exec-am install-exec \
+install-data-am install-data install-am install uninstall-am uninstall \
+all-redirect all-am all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/libmpio/debug.c b/libmpio/debug.c
new file mode 100644
index 0000000..2de85eb
--- /dev/null
+++ b/libmpio/debug.c
@@ -0,0 +1,293 @@
+/*
+ * debug.c
+ *
+ * Authors: Dirk Meyer <dmeyer@tzi.de>
+ * Andreas Büsching <crunchy@tzi.de>
+ *
+ * $Id: debug.c,v 1.1 2002/08/28 16:10:51 salmoon Exp $
+ */
+
+#include "debug.h"
+
+#include <ctype.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+#define DCOLOR "_color"
+#define DFILE "_file"
+#define DSUFFIX "_debug"
+#define LEVEL_HEXDUMP 5
+
+char *__debug_color = NULL;
+int __debug_level = 0;
+FILE *__debug_fd;
+
+void
+debug_init(void) {
+ char *env_var = malloc(strlen(DPACKAGE) + strlen(DFILE) + 1);
+ const char *env;
+
+ /* check debug output file */
+ strcpy(env_var, DPACKAGE);
+ strcat(env_var, DFILE);
+
+ if ((env = getenv(env_var))) {
+ if (__debug_fd && fileno(__debug_fd) != -1) {
+ fclose(__debug_fd);
+ }
+
+ __debug_fd = fopen(env, "a");
+ if (!__debug_fd) {
+ __debug_fd = stderr;
+ }
+ } else {
+ __debug_fd = stderr;
+ }
+
+ free(env_var);
+
+ /* check debug level */
+ env_var = malloc(strlen(DPACKAGE) + strlen(DSUFFIX) + 1);
+ strcpy(env_var, DPACKAGE);
+ strcat(env_var, DSUFFIX);
+
+ if ((env = getenv(env_var)))
+ if (isdigit(env[0]))
+ __debug_level = strtol(env, NULL, 10);
+ else
+ __debug_level = 1;
+ else
+ __debug_level = -1;
+
+ free(env_var);
+
+ /* check debug color */
+ env_var = malloc(strlen(DPACKAGE) + strlen(DCOLOR) + 1);
+
+ strcpy(env_var, DPACKAGE);
+ strcat(env_var, DCOLOR);
+
+ if (__debug_color) free(__debug_color);
+ __debug_color = NULL;
+
+ if ((env = getenv(env_var))) {
+ if (env[0] != '\0') {
+ __debug_color = malloc(4 + strlen(env));
+ sprintf(__debug_color, "\033[%sm", env);
+ } else
+ __debug_color = malloc(6);
+ strcpy(__debug_color, "\033[32m");
+ } else {
+ __debug_color = NULL;
+ }
+
+ free(env_var);
+}
+
+int
+debug_file(char *filename)
+{
+ if (__debug_fd && fileno(__debug_fd) != -1) {
+ fclose(__debug_fd);
+ }
+
+ __debug_fd = fopen(filename, "a");
+ if (!__debug_fd) {
+ perror("fopen:");
+ __debug_fd = stderr;
+ return 0;
+ }
+
+ return 1;
+}
+
+int
+debug_level(int level)
+{
+ int tmp = __debug_level;
+
+ __debug_level = level;
+
+ return tmp;
+}
+
+int
+debug_level_get(void)
+{
+ return __debug_level;
+}
+
+
+void
+_hexdump (const char *package, const char* file, int line,
+ const char* function, const char* data, int len)
+{
+ char buf[17];
+ int i;
+
+ if (_use_debug(LEVEL_HEXDUMP)) {
+ fprintf (__debug_fd, "%s%s:\033[m %s(%d): %s: data=%p len=%d\n",
+ __debug_color, package, file, line, function, data, len);
+ for (i = 0; data != NULL && i < len; i++) {
+ if (i % 16 == 0)
+ fprintf(__debug_fd, "\033[30m%s:\033[m %04x: ", package, i);
+ fprintf(__debug_fd, "%02x ", (unsigned int)(unsigned char)data[i]);
+ buf[i % 16] = (data[i] >= 32 && data[i] <= 126) ? data[i] : '.';
+ buf[i % 16 + 1] = '\0';
+ if (i % 4 == 3) fprintf(__debug_fd, " ");
+ if (i % 16 == 15) fprintf(__debug_fd, "%s\n", buf);
+ }
+ if (i % 16 != 0) {
+ for (; i % 16 != 0; i++)
+ fprintf (__debug_fd, (i % 4 == 3) ? " " : " ");
+ fprintf(__debug_fd, "%s\n", buf);
+ }
+ }
+}
+
+void
+_hexdump_n (const char *package, const int n, const char* file, int line,
+ const char* function, const char* data, int len)
+{
+ char buf[17];
+ int i;
+
+ if (_use_debug(n)) {
+ fprintf (__debug_fd, "%s%s:\033[m %s(%d): %s: data=%p len=%d\n",
+ __debug_color, package, file, line, function, data, len);
+ for (i = 0; data != NULL && i < len; i++) {
+ if (i % 16 == 0)
+ fprintf(__debug_fd, "\033[30m%s:\033[m %04x: ", package, i);
+ fprintf(__debug_fd, "%02x ", (unsigned int)(unsigned char)data[i]);
+ buf[i % 16] = (data[i] >= 32 && data[i] <= 126) ? data[i] : '.';
+ buf[i % 16 + 1] = '\0';
+ if (i % 4 == 3) fprintf(__debug_fd, " ");
+ if (i % 16 == 15) fprintf(__debug_fd, "%s\n", buf);
+ }
+ if (i % 16 != 0) {
+ for (; i % 16 != 0; i++)
+ fprintf (__debug_fd, (i % 4 == 3) ? " " : " ");
+ fprintf(__debug_fd, "%s\n", buf);
+ }
+ }
+}
+
+
+void
+_hexdump_text (const char *text,
+ const char *package, const char *file, int line,
+ const char *function, const char *data, int len)
+{
+ if (_use_debug(LEVEL_HEXDUMP)) {
+ fprintf(__debug_fd, "%s%s: %s(%d): %s: %s\033[m", __debug_color,
+ package, file, line, function, text);
+ _hexdump(package, file, line, function, data, len);
+ }
+}
+
+
+
+void
+_error(const char *package, const char *file, int line,
+ const char *function, int fatal, const char *format, ...)
+{
+ char foo[2048];
+ va_list ap;
+ va_start(ap, format);
+
+ vsnprintf(foo, sizeof(foo) - strlen(format) - 1, format, ap);
+ if (_use_debug(0))
+ fprintf(__debug_fd, "\033[31m%s: %s(%d): %s: %s\033[m",
+ package, file, line, function, foo);
+ else
+ fprintf(__debug_fd, "%s: %s(%d): %s: %s",
+ package, file, line, function, foo);
+ fflush(__debug_fd);
+
+ if (fatal) {
+ fprintf(__debug_fd, "\033[31mfatal error -- exit programm\033[m\n");
+ exit(1);
+ }
+
+ va_end(ap);
+}
+
+void
+_debug(const char *package, const char *file, int line,
+ const char *function, const char *format, ...)
+{
+ char foo[2048];
+ va_list ap;
+ va_start(ap, format);
+
+ vsnprintf(foo, sizeof(foo) - strlen(format) - 1, format, ap);
+
+ if (_use_debug(0)) {
+ fprintf(__debug_fd, "%s%s: %s(%d): %s: %s\033[m",
+ ( __debug_color ? __debug_color : ""),
+ package, file, line, function, foo);
+ fflush(__debug_fd);
+ }
+
+ va_end(ap);
+}
+
+void
+_debug_n(const char *package, const int n, const char *file,
+ int line, const char *function, const char *format, ...)
+{
+ char foo[2048];
+ va_list ap;
+ va_start(ap, format);
+
+ vsnprintf(foo, sizeof(foo) - strlen(format) - 1, format, ap);
+
+ if (_use_debug(n)) {
+ fprintf(__debug_fd, "%s%s: %s(%d): %s: %s\033[m",
+ ( __debug_color ? __debug_color : ""),
+ package, file, line, function, foo);
+ fflush(__debug_fd);
+ }
+
+ va_end(ap);
+}
+
+void
+_octetstr(const char *package, const char *file, int line,
+ const char *function, const uint8_t *str,
+ const unsigned int len, const char *what)
+{
+ if (_use_debug(LEVEL_HEXDUMP)) {
+ unsigned int i;
+
+ fprintf(__debug_fd, "%s%s: %s(%d): %s: ",
+ package, file, function, line, (what?what:""));
+ for (i = 0; i < len; i++) {
+ if (i < (len - 1))
+ fprintf(__debug_fd, "%03d.", str [i]);
+ else
+ fprintf(__debug_fd, "%03d", str [i]);
+ }
+ }
+}
+
+int
+_use_debug(int level)
+{
+ if (__debug_level == -1) return 0;
+
+ if (level <= __debug_level) {
+ return 1;
+ }
+
+ return 0;
+}
+
+/* end of debug.c */
+
+
+
+
+
diff --git a/libmpio/debug.h b/libmpio/debug.h
new file mode 100644
index 0000000..4c7df21
--- /dev/null
+++ b/libmpio/debug.h
@@ -0,0 +1,102 @@
+/*
+ * debug.h
+ *
+ * Author: Dirk Meyer <dmeyer@tzi.de>
+ * Andreas Büsching <crunchy@tzi.de>
+ *
+ * $Id: debug.h,v 1.1 2002/08/28 16:10:51 salmoon Exp $
+ */
+
+#ifndef _MPIO_DEBUG_H_
+#define _MPIO_DEBUG_H_
+
+// if DPACKAGE is not definied use PACKAGE or "unknown"
+
+#ifndef DPACKAGE
+
+#ifdef PACKAGE
+#define DPACKAGE PACKAGE
+#else
+#define DPACKAGE unknown
+#endif
+
+#endif
+
+#include <stdio.h>
+
+#ifdef sun
+#include <sys/int_types.h>
+#else
+#include <stdint.h>
+#endif
+
+#ifndef PBOOL
+#define PBOOL(x) (x)?"True":"False"
+#endif
+
+#define UNUSED(x) (x = x)
+
+#define debugn(n,args...) \
+ _debug_n(DPACKAGE, n, __FILE__, __LINE__, __FUNCTION__, args)
+
+#define debug(args...) \
+ _debug(DPACKAGE, __FILE__, __LINE__, __FUNCTION__, args)
+
+#define debug_error(fatal,args...) \
+ _error(DPACKAGE, __FILE__, __LINE__, __FUNCTION__, fatal, args)
+
+#define hexdump(data,len) \
+ _hexdump(DPACKAGE, __FILE__, __LINE__, __FUNCTION__, data, len)
+
+#define hexdumpn(n,data,len) \
+ _hexdump_n(DPACKAGE, n, __FILE__, __LINE__, __FUNCTION__, data, len)
+
+#define hexdump_text(text,data,len) \
+ _hexdump_text(text, DPACKAGE, __FILE__, __LINE__, __FUNCTION__, data, len)
+
+#define octetstrdump(data,len) \
+ _octetstr(DPACKAGE, __FILE__, __LINE__, __FUNCTION__, data, len)
+
+#define ipadr_dump(data,len,text) \
+ _octetstr(DPACKAGE, __FILE__, __LINE__, __FUNCTION__, data, len, text)
+
+#define use_debug() \
+ use_debug(DPACKAGE)
+
+
+#define with_special_debug(what) \
+ _use_debug(DPACKAGE, what)
+
+void debug_init(void);
+int debug_file(char *filename);
+int debug_level(int level);
+int debug_level_get(void);
+
+void _debug(const char *package, const char* file, int line,
+ const char* function, const char *format, ...);
+
+void _debug_n(const char *package, const int n, const char* file,
+ int line, const char* function, const char *format, ...);
+
+void _hexdump (const char *package, const char* file, int line,
+ const char* function, const char* data, int len);
+
+void _hexdump_n (const char *package, const int n, const char* file, int line,
+ const char* function, const char* data, int len);
+
+void _hexdump_text (const char *text,
+ const char *package, const char* file, int line,
+ const char* function, const char* data, int len);
+
+void _error(const char *package, const char* file, int line,
+ const char* function, int fatal, const char *format, ...);
+
+void _octetstr(const char *package, const char* file, int line,
+ const char* function, const uint8_t *str,
+ const unsigned int len, const char *what);
+
+int _use_debug(int level);
+
+#endif /* _MPIO_DEBUG_H_ */
+
+/* end of debug.h */
diff --git a/libmpio/defs.h b/libmpio/defs.h
new file mode 100644
index 0000000..8498f22
--- /dev/null
+++ b/libmpio/defs.h
@@ -0,0 +1,192 @@
+/* -*- linux-c -*- */
+
+/*
+ * $Id: defs.h,v 1.1 2002/08/28 16:10:51 salmoon Exp $
+ *
+ * Library for USB MPIO-*
+ *
+ * Markus Germeier (mager@tzi.de)
+ *
+ * uses code from mpio_stat.c by
+ * Yuji Touya (salmoon@users.sourceforge.net)
+ *
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+#ifndef _MPIO_DEFS_H_
+#define _MPIO_DEFS_H_
+
+typedef unsigned char BYTE;
+typedef unsigned short WORD;
+typedef unsigned int DWORD;
+
+/* Memory selection */
+typedef enum { MPIO_INTERNAL_MEM = 0x01,
+ MPIO_EXTERNAL_MEM = 0x10 } mpio_mem_t;
+
+/* USB commands */
+typedef enum { GET_VERSION = 0x01,
+ GET_BLOCK = 0x02,
+ PUT_SECTOR = 0x03,
+ DEL_BLOCK = 0x04,
+ GET_SECTOR = 0x06,
+ GET_SPARE_AREA = 0x07,
+ PUT_BLOCK = 0x08 } mpio_cmd_t;
+
+/* file types on internal memory */
+/* found in the code of salmoon, are these needed? -mager */
+typedef enum { FTYPE_CONF = 'C',
+ FTYPE_FONT = 'F',
+ FTYPE_OTHER = 'H',
+ FTYPE_ENTRY = 'R' } mpio_file_t;
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#define MPIO_DEVICE "/dev/usb/mpio"
+
+#define SECTOR_SIZE 0x200
+#define SECTOR_ECC 0x040
+#define SECTOR_TRANS (SECTOR_SIZE + SECTOR_ECC)
+
+#define BLOCK_SECTORS 0x20
+#define BLOCK_SIZE (SECTOR_SIZE * BLOCK_SECTORS)
+#define BLOCK_TRANS (BLOCK_SIZE + (SECTOR_ECC * BLOCK_SECTORS))
+
+#define DIR_NUM 0x10
+#define DIR_SIZE (SECTOR_SIZE*DIR_NUM)
+#define DIR_ENTRY_SIZE 0x20
+
+#define SMALL_MEM 0x02
+
+#define CMD_SIZE 0x40
+
+#define OFFSET_CIS 0x20
+#define OFFSET_MBR 0x40
+
+#define INFO_LINE 81
+
+/* get formatted information, about the MPIO player */
+
+typedef struct {
+ BYTE firmware_id[INFO_LINE];
+ BYTE firmware_version[INFO_LINE];
+ BYTE firmware_date[INFO_LINE];
+
+ BYTE firmware_mem_internal[INFO_LINE];
+ BYTE firmware_mem_external[INFO_LINE];
+
+} mpio_info_t;
+
+/* view of the MPIO firmware */
+typedef struct {
+ /* everything we get from GET_VERSION */
+ BYTE id[12];
+ BYTE major[3];
+ BYTE minor[3];
+ BYTE year[5];
+ BYTE month[3];
+ BYTE day[3];
+} mpio_firmware_t;
+
+/* */
+typedef struct {
+ DWORD NumCylinder;
+ DWORD NumHead;
+ DWORD NumSector;
+ DWORD SumSector;
+} mpio_disk_phy_t;
+
+/* view of a SmartMedia(tm) card */
+typedef struct {
+ BYTE id;
+ BYTE manufacturer;
+ BYTE size; /* MB */
+ BYTE chips; /* this is the hack for
+ MPIO internal representation, because
+ there might be two chips involved */
+
+ /* only needed for external SmartMedia cards */
+ mpio_disk_phy_t geo;
+
+ BYTE cis[SECTOR_SIZE];
+ BYTE mbr[SECTOR_SIZE]; /* Master Boot Record */
+ BYTE pbr[SECTOR_SIZE]; /* Partition Boot Record */
+
+ int pbr_offset; /* sector offset for the PBR */
+ int fat_offset; /* sector offset for the FAT */
+ int dir_offset;
+
+ /* these are needed for internal and external cards */
+ int max_cluster; /* # of clusters actually available */
+ int fat_size; /* # sectors for FAT */
+ int fat_nums; /* # of FATs */
+ BYTE * fat; /* *real FAT (like in block allocation :-) */
+
+ /* seems to be a fixed size according to the
+ Samsung documentation */
+ BYTE dir[DIR_SIZE]; /* file index */
+} mpio_smartmedia_t;
+
+
+/* view of the MPIO-* */
+typedef struct {
+ BYTE version[CMD_SIZE];
+
+ int fd;
+
+ mpio_firmware_t firmware;
+
+ mpio_smartmedia_t internal;
+ mpio_smartmedia_t external;
+} mpio_t;
+
+/* these are copied from:
+ * http://www.linuxhq.com/kernel/v2.4/doc/filesystems/vfat.txt.html
+ *
+ */
+
+typedef struct { // Short 8.3 names
+ unsigned char name[8]; // file name
+ unsigned char ext[3]; // file extension
+ unsigned char attr; // attribute byte
+ unsigned char lcase; // Case for base and extension
+ unsigned char ctime_ms; // Creation time, milliseconds
+ unsigned char ctime[2]; // Creation time
+ unsigned char cdate[2]; // Creation date
+ unsigned char adate[2]; // Last access date
+ unsigned char reserved[2]; // reserved values (ignored)
+ unsigned char time[2]; // time stamp
+ unsigned char date[2]; // date stamp
+ unsigned char start[2]; // starting cluster number
+ unsigned char size[4]; // size of the file
+} mpio_dir_entry_t;
+
+typedef struct { // Up to 13 characters of a long name
+ unsigned char id; // sequence number for slot
+ unsigned char name0_4[10]; // first 5 characters in name
+ unsigned char attr; // attribute byte
+ unsigned char reserved; // always 0
+ unsigned char alias_checksum; // checksum for 8.3 alias
+ unsigned char name5_10[12]; // 6 more characters in name
+ unsigned char start[2]; // starting cluster number
+ unsigned char name11_12[4]; // last 2 characters in name
+} mpio_dir_slot_t;
+
+#endif /* _MPIO_DEFS_H_ */
+
diff --git a/libmpio/directory.c b/libmpio/directory.c
new file mode 100644
index 0000000..b14dd6d
--- /dev/null
+++ b/libmpio/directory.c
@@ -0,0 +1,509 @@
+/*
+ *
+ * $Id: directory.c,v 1.1 2002/08/28 16:10:51 salmoon Exp $
+ *
+ * Library for USB MPIO-*
+ *
+ * Markus Germeier (mager@tzi.de)
+ *
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+#include <unistd.h>
+#include <iconv.h>
+
+#include "debug.h"
+#include "io.h"
+#include "mpio.h"
+#include "directory.h"
+
+/* directory operations */
+BYTE *
+mpio_directory_open(mpio_t *m, BYTE mem)
+{
+ BYTE *out;
+ if (mem == MPIO_EXTERNAL_MEM) {
+ if (m->external.id) {
+ out = m->external.dir;
+ } else {
+ return NULL;
+ }
+ } else {
+ out = m->internal.dir;
+ }
+
+ if (out[0] == 0x00)
+ return NULL;
+
+ return out;
+}
+
+int
+mpio_dentry_get_size(mpio_t *m, BYTE *buffer)
+{
+ mpio_dir_entry_t *dentry;
+
+ if (!buffer)
+ return -1;
+
+ UNUSED(m);
+
+ dentry = (mpio_dir_entry_t *)buffer;
+
+ if ((dentry->name[0] & 0x40) &&
+ (dentry->attr == 0x0f) &&
+ (dentry->start[0] == 0x00) &&
+ (dentry->start[1] == 0x00)) {
+ dentry++;
+ while ((dentry->attr == 0x0f) &&
+ (dentry->start[0] == 0x00) &&
+ (dentry->start[1] == 0x00)) {
+ /* this/these are vfat slots */
+ dentry++;
+ }
+ }
+ dentry++;
+
+ return(((BYTE *)dentry) - buffer);
+}
+
+BYTE*
+mpio_dentry_next(mpio_t *m, BYTE *buffer)
+{
+ int size;
+ BYTE *out;
+
+ size = mpio_dentry_get_size(m, buffer);
+ if (size<0)
+ return NULL;
+
+ out = buffer + size;
+
+ if (*out == 0x00)
+ return NULL;
+
+ return out;
+}
+
+int
+mpio_dentry_get_raw(mpio_t *m, BYTE *dentry, BYTE *buffer, int bufsize)
+{
+ int size;
+
+ size = mpio_dentry_get_size(m, buffer);
+
+ if (size < 0)
+ return size;
+
+ if (size > bufsize)
+ return -2;
+
+ memcpy(buffer, dentry, size);
+
+ return size;
+}
+
+void
+mpio_dentry_copy_from_slot(BYTE *buffer, mpio_dir_slot_t *slot)
+{
+ memcpy(buffer, slot->name0_4, 10);
+ memcpy(buffer + 10, slot->name5_10, 12);
+ memcpy(buffer + 22, slot->name11_12, 4);
+}
+
+void
+mpio_dentry_copy_to_slot(BYTE *buffer, mpio_dir_slot_t *slot)
+{
+ memcpy(slot->name0_4, buffer, 10);
+ memcpy(slot->name5_10, buffer + 10, 12);
+ memcpy(slot->name11_12, buffer + 22, 4);
+}
+
+int
+mpio_dentry_get(mpio_t *m, BYTE *buffer,
+ BYTE *filename, int filename_size,
+ WORD *year, BYTE *month, BYTE *day,
+ BYTE *hour, BYTE *minute, DWORD *fsize)
+{
+ BYTE filename_8_3[12];
+
+ return mpio_dentry_get_real(m, buffer, filename, filename_size,
+ filename_8_3,
+ year, month, day, hour, minute, fsize);
+}
+
+/* TODO: please clean me up !!! */
+int
+mpio_dentry_get_real(mpio_t *m, BYTE *buffer,
+ BYTE *filename, int filename_size,
+ BYTE filename_8_3[12],
+ WORD *year, BYTE *month, BYTE *day,
+ BYTE *hour, BYTE *minute, DWORD *fsize)
+{
+ int date, time;
+ int vfat = 0;
+ int num_slots = 0;
+ int slots = 0;
+ int in = 0, out = 0;
+ mpio_dir_entry_t *dentry;
+ mpio_dir_slot_t *slot;
+ BYTE *unicode = 0;
+ BYTE *uc;
+ BYTE *fname = 0;
+ iconv_t ic;
+
+ if (buffer == NULL)
+ return -1;
+
+ dentry = (mpio_dir_entry_t *)buffer;
+
+ if ((dentry->name[0] & 0x40) &&
+ (dentry->attr == 0x0f) &&
+ (dentry->start[0] == 0x00) &&
+ (dentry->start[1] == 0x00)) {
+ num_slots = (mpio_dentry_get_size(m, buffer) / 0x20) - 1;
+ slots = num_slots - 1;
+ dentry++;
+ vfat++;
+ unicode = malloc(256);
+ uc = unicode;
+ fname = filename;
+ slot = (mpio_dir_slot_t *)buffer;
+ mpio_dentry_copy_from_slot(unicode + (26 * slots), slot);
+ slots--;
+
+ while ((dentry->attr == 0x0f) &&
+ (dentry->start[0] == 0x00) &&
+ (dentry->start[1] == 0x00)) {
+ /* this/these are vfat slots */
+ slot = (mpio_dir_slot_t *)dentry;
+ mpio_dentry_copy_from_slot((unicode + (26 * slots)), slot);
+ dentry++;
+ slots--;
+ }
+ }
+
+ if (vfat) {
+ ic = iconv_open("ASCII", "UNICODE");
+ in = num_slots * 26;
+ out = num_slots * 13;
+ memset(fname, 0, filename_size);
+ iconv(ic, (char **)&uc, &in, (char **)&fname, &out);
+ iconv_close(ic);
+ free(unicode);
+ } else {
+ memcpy(filename_8_3, dentry->name, 8);
+ filename_8_3[0x08] = '.';
+ memcpy(filename_8_3 + 0x09, dentry->ext, 3);
+ filename_8_3[0x0c] = 0;
+
+ if (filename_size >= 12) {
+ snprintf(filename, 13, "%s", filename_8_3);
+ } else {
+ snprintf(filename, 12, "%s", "ERROR");
+ }
+
+ }
+
+ date = (dentry->date[1] * 0x100) + dentry->date[0];
+ *year = date / 512 + 1980;
+ *month = (date / 32) & 0xf;
+ *day = date & 0x1f;
+
+ time = (dentry->time[1] * 0x100) + dentry->time[0];
+ *hour = time / 2048;
+ *minute= (time / 32) & 0x3f;
+
+ *fsize = dentry->size[3];
+ *fsize *= 0x100;
+ *fsize += dentry->size[2];
+ *fsize *= 0x100;
+ *fsize += dentry->size[1];
+ *fsize *= 0x100;
+ *fsize += dentry->size[0];
+
+ return(((BYTE *)dentry) - buffer);
+}
+
+/* read "size" sectors of fat into the provided buffer */
+int
+mpio_rootdir_read (mpio_t *m, mpio_mem_t mem)
+{
+ mpio_smartmedia_t *sm;
+ BYTE recvbuff[SECTOR_SIZE];
+ int i;
+
+ if (mem == MPIO_INTERNAL_MEM) sm = &m->internal;
+ if (mem == MPIO_EXTERNAL_MEM) sm = &m->external;
+
+ for (i = 0; i < DIR_NUM; i++) {
+ if (mpio_io_sector_read(m, mem,
+ (sm->dir_offset + i), sm->size, 0, recvbuff))
+ return 1;
+
+ memcpy(sm->dir + (i * SECTOR_SIZE), recvbuff, SECTOR_SIZE);
+ }
+
+ return (0);
+}
+
+int
+mpio_rootdir_clear (mpio_t *m, mpio_mem_t mem)
+{
+ mpio_smartmedia_t *sm;
+
+ if (mem == MPIO_INTERNAL_MEM) sm=&m->internal;
+ if (mem==MPIO_EXTERNAL_MEM) sm=&m->external;
+
+ memset(sm->dir, 0x00, DIR_SIZE);
+
+ return 0;
+}
+
+WORD
+mpio_dentry_get_startsector(mpio_t *m, BYTE *p)
+{
+ int s;
+ int sektor;
+ mpio_dir_slot_t *dentry;
+
+ s = mpio_dentry_get_size(m, p);
+ s -= DIR_ENTRY_SIZE ;
+
+ dentry = (mpio_dir_slot_t *)p;
+
+ while (s != 0) {
+ dentry++;
+ s -= DIR_ENTRY_SIZE ;
+ }
+
+ sektor = dentry->start[1] * 0x100 + dentry->start[0];
+
+ return sektor;
+}
+
+int
+mpio_dentry_put(mpio_t *m, BYTE mem,
+ BYTE *filename, int filename_size,
+ WORD year, BYTE month, BYTE day,
+ BYTE hour, BYTE minute, DWORD fsize, WORD ssector)
+{
+ BYTE *unicode = 0;
+ BYTE *back, *fback;
+ BYTE *fname = 0;
+ iconv_t ic;
+ int in = 0, out = 0;
+ int fin = 0, fout = 0;
+ int count = 0;
+ BYTE index;
+
+ BYTE *p;
+ mpio_dir_entry_t *dentry;
+ mpio_dir_slot_t *slot;
+
+ p = mpio_directory_open(m, mem);
+ if (p) {
+ while (*p != 0x00)
+ p += 0x20;
+ } else {
+ if (mem == MPIO_EXTERNAL_MEM)
+ p = m->external.dir;
+ if (mem == MPIO_INTERNAL_MEM)
+ p = m->internal.dir;
+ }
+
+ /* generate vfat filename in UNICODE */
+ ic = iconv_open("UNICODE", "ASCII");
+ fin = in = filename_size + 1;
+ fout = out = filename_size * 2 + 2 + 26;
+ fname = malloc(in);
+ fback = fname;
+ unicode = malloc(out);
+ back = unicode;
+
+ memset(fname, 0, in);
+ snprintf(fname, in, "%s", filename);
+ memset(unicode, 0xff, out);
+ iconv(ic, (char **)&fback, &fin, (char **)&back, &fout);
+ iconv_close(ic);
+ hexdump(fname, in);
+ hexdump(unicode, out);
+
+ back = unicode + 2;
+
+ count = filename_size / 13;
+ if (filename_size % 13)
+ count++;
+
+ slot = (mpio_dir_slot_t *)p;
+
+ index = 0x40 + count;
+ while (count > 0) {
+ mpio_dentry_copy_to_slot(back + ((count - 1) * 26), slot);
+ hexdump((char *)back + ((count - 1) * 26), 0x20);
+ slot->id = index;
+ slot->attr = 0x0f;
+ slot->reserved = 0x00;
+ slot->start[0] = 0x00;
+ slot->start[1] = 0x00;
+ /* FIXME: */
+ slot->alias_checksum = 0x00; // checksum for 8.3 alias
+
+ hexdump((char *)slot, 0x20);
+
+ slot++;
+ count--;
+ index = count;
+ }
+
+/* memcpy(p, m->internal.dir+0x220, 0x20); */
+
+/* p+=0x20; */
+ dentry = (mpio_dir_entry_t *)slot;
+ memcpy(dentry->name,"AAAAAAAA",8);
+ memcpy(dentry->ext,"MP3",3);
+ dentry->attr = 0x20;
+ dentry->lcase = 0x00;
+ dentry->ctime_ms = 0x00;
+ dentry->ctime[0] = 0x37;
+ dentry->ctime[1] = 0x7b;
+ dentry->cdate[0] = 0xfb;
+ dentry->cdate[1] = 0x2c;
+ dentry->adate[0] = 0xfd;
+ dentry->adate[1] = 0x2c;
+ dentry->reserved[0] = 0x00;
+ dentry->reserved[1] = 0x00;
+ dentry->time[0] = 0x38;
+ dentry->time[1] = 0x7b;
+ dentry->date[0] = 0xfb;
+ dentry->date[1] = 0x2c;
+ dentry->size[0] = fsize & 0xff;
+ dentry->size[1] = (fsize / 0x100) & 0xff;
+ dentry->size[2] = (fsize / 0x10000) & 0xff;
+ dentry->size[3] = (fsize / 0x1000000) & 0xff;
+ dentry->start[0] = ssector & 0xff;
+ dentry->start[1] = ssector / 0x100;
+
+ free(unicode);
+ free(fname);
+
+ /* what do we want to return? */
+ return 0;
+}
+
+BYTE *
+mpio_dentry_find_name_8_3(mpio_t *m, BYTE mem, BYTE *filename)
+{
+ BYTE *p;
+ BYTE bdummy;
+ WORD wdummy;
+ BYTE fname[129];
+ BYTE fname_8_3[13];
+ DWORD ddummy;
+ BYTE *found = 0;
+
+ p = mpio_directory_open(m, mem);
+ while ((p) && (!found)) {
+ mpio_dentry_get_real (m, p,
+ fname, 128,
+ fname_8_3,
+ &wdummy, &bdummy, &bdummy,
+ &bdummy, &bdummy, &ddummy);
+ if ((strcmp(fname_8_3, filename) == 0) &&
+ (strcmp(filename,fname_8_3) == 0)) {
+ found = p;
+ p = NULL;
+ }
+
+ p = mpio_dentry_next(m, p);
+ }
+
+ return found;
+}
+
+BYTE *
+mpio_dentry_find_name(mpio_t *m, BYTE mem, BYTE *filename)
+{
+ BYTE *p;
+ BYTE bdummy;
+ WORD wdummy;
+ BYTE fname[129];
+ DWORD ddummy;
+ BYTE *found = 0;
+
+ p = mpio_directory_open(m, mem);
+ while ((p) && (!found)) {
+ mpio_dentry_get (m, p,
+ fname, 128,
+ &wdummy, &bdummy, &bdummy,
+ &bdummy, &bdummy, &ddummy);
+ if ((strcmp(fname,filename) == 0) && (strcmp(filename,fname) == 0)) {
+ found = p;
+ p = NULL;
+ }
+
+ p = mpio_dentry_next(m, p);
+ }
+
+ return found;
+}
+
+
+int
+mpio_dentry_delete(mpio_t *m, BYTE mem, BYTE *filename)
+{
+ mpio_smartmedia_t *sm;
+ BYTE *start;
+ int size;
+ BYTE tmp[DIR_SIZE];
+
+ if (mem == MPIO_INTERNAL_MEM) sm = &m->internal;
+ if (mem==MPIO_EXTERNAL_MEM) sm = &m->external;
+
+ start = mpio_dentry_find_name(m, mem, filename);
+
+ /* second try */
+ if (!start)
+ start = mpio_dentry_find_name_8_3(m, mem, filename);
+
+ if (!start) {
+ debug("could not find file: %s\n", filename);
+ return 0;
+ }
+
+ size = mpio_dentry_get_size(m, start);
+
+ if (size <= 0) {
+ debug("fatal error in mpio_dentry_delete\n");
+ return 0;
+ }
+
+ debugn(5, "size: %2x\n", size);
+
+ /* clear new buffer */
+ memset(tmp, 0, DIR_SIZE);
+ /* copy before delete */
+ if (start != sm->dir)
+ memcpy(tmp, sm->dir, (start - (sm->dir)));
+ /* copy after delete */
+ memcpy(tmp + (start - (sm->dir)), (start + size),
+ (sm->dir + DIR_SIZE - (start + size)));
+
+ memcpy(sm->dir, tmp, DIR_SIZE);
+
+ return 0;
+}
diff --git a/libmpio/directory.h b/libmpio/directory.h
new file mode 100644
index 0000000..ddce24c
--- /dev/null
+++ b/libmpio/directory.h
@@ -0,0 +1,50 @@
+/*
+ *
+ * $Id: directory.h,v 1.1 2002/08/28 16:10:51 salmoon Exp $
+ *
+ * Library for USB MPIO-*
+ *
+ * Markus Germeier (mager@tzi.de)
+ *
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+#ifndef _MPIO_DIRECTORY_H_
+#define _MPIO_DIRECTORY_H_
+
+/* root directory operations */
+int mpio_rootdir_read (mpio_t *, mpio_mem_t);
+int mpio_rootdir_clear (mpio_t *, mpio_mem_t);
+int mpio_rootdir_format(mpio_t *, mpio_mem_t);
+
+/* operations on a single directory entry */
+int mpio_dentry_get_size(mpio_t *, BYTE *);
+int mpio_dentry_get_raw(mpio_t *, BYTE *, BYTE *, int);
+WORD mpio_dentry_get_startsector(mpio_t *, BYTE *);
+int mpio_dentry_put(mpio_t *, BYTE, BYTE *, int,
+ WORD, BYTE, BYTE, BYTE, BYTE, DWORD, WORD);
+BYTE * mpio_dentry_find_name_8_3(mpio_t *, BYTE, BYTE *);
+BYTE * mpio_dentry_find_name(mpio_t *, BYTE, BYTE *);
+int mpio_dentry_delete(mpio_t *, BYTE, BYTE *);
+
+/* helper functions */
+void mpio_dentry_copy_from_slot(BYTE *, mpio_dir_slot_t *);
+void mpio_dentry_copy_to_slot(BYTE *, mpio_dir_slot_t *);
+int mpio_dentry_get_real(mpio_t *, BYTE *, BYTE *, int, BYTE[12],
+ WORD *, BYTE *, BYTE *, BYTE *, BYTE *, DWORD *);
+
+#endif /* _MPIO_DIRECTORY_H_ */
diff --git a/libmpio/ecc.c b/libmpio/ecc.c
new file mode 100644
index 0000000..e7429a5
--- /dev/null
+++ b/libmpio/ecc.c
@@ -0,0 +1,203 @@
+/*
+ *
+ * $Id: ecc.c,v 1.1 2002/08/28 16:10:51 salmoon Exp $
+ *
+ * Library for USB MPIO-*
+ *
+ * Markus Germeier (mager@tzi.de)
+ *
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+#include "ecc.h"
+#include "debug.h"
+
+BYTE get_bit(BYTE, int);
+
+/* TODO: fix correctable errors */
+
+inline BYTE
+get_bit(BYTE d, int offset)
+{
+ return ((d >> offset) & 0x01 );
+}
+
+int
+mpio_ecc_256_gen(BYTE *data, BYTE *ecc)
+{
+ BYTE p1, p1_;
+ BYTE p2, p2_;
+ BYTE p4, p4_;
+
+ BYTE p08, p08_;
+ BYTE p16, p16_;
+ BYTE p32, p32_;
+ BYTE p64, p64_;
+
+ BYTE p0128, p0128_;
+ BYTE p0256, p0256_;
+ BYTE p0512, p0512_;
+ BYTE p1024, p1024_;
+
+ int i, j;
+
+ /* init */
+ p1=p1_=0;
+ p2=p2_=0;
+ p4=p4_=0;
+
+ p08=p08_=0;
+ p16=p16_=0;
+ p32=p32_=0;
+ p64=p64_=0;
+
+ p0128=p0128_=0;
+ p0256=p0256_=0;
+ p0512=p0512_=0;
+ p1024=p1024_=0;
+
+ /* vertical */
+ for (i=0; i<256; i++) {
+
+ /* p1, p1_ */
+ p1 ^= (get_bit(data[i], 7) ^
+ get_bit(data[i], 5) ^
+ get_bit(data[i], 3) ^
+ get_bit(data[i], 1));
+ p1_^= (get_bit(data[i], 6) ^
+ get_bit(data[i], 4) ^
+ get_bit(data[i], 2) ^
+ get_bit(data[i], 0));
+
+ /* p2, p2_ */
+ p2 ^= (get_bit(data[i], 7) ^
+ get_bit(data[i], 6) ^
+ get_bit(data[i], 3) ^
+ get_bit(data[i], 2));
+ p2_^= (get_bit(data[i], 5) ^
+ get_bit(data[i], 4) ^
+ get_bit(data[i], 1) ^
+ get_bit(data[i], 0));
+
+ /* p4, p4_ */
+ p4 ^= (get_bit(data[i], 7) ^
+ get_bit(data[i], 6) ^
+ get_bit(data[i], 5) ^
+ get_bit(data[i], 4));
+ p4_^= (get_bit(data[i], 3) ^
+ get_bit(data[i], 2) ^
+ get_bit(data[i], 1) ^
+ get_bit(data[i], 0));
+ }
+
+ /* horizontal */
+ for (i=0; i<8; i++) {
+
+ for (j=0; j<256; j++) {
+
+ /* p08, p08_ */
+ if ((j & 0x01) == 0)
+ p08_^= get_bit(data[j], i);
+ if ((j & 0x01) == 1)
+ p08 ^= get_bit(data[j], i);
+
+ /* p16, p16_ */
+ if (((j/2) & 0x01) == 0)
+ p16_^= get_bit(data[j], i);
+ if (((j/2) & 0x01) == 1)
+ p16^= get_bit(data[j], i);
+
+ /* p32, p32_ */
+ if (((j/4) & 0x01) == 0)
+ p32_^= get_bit(data[j], i);
+ if (((j/4) & 0x01) == 1)
+ p32^= get_bit(data[j], i);
+
+ /* p64, p64_ */
+ if (((j/8) & 0x01) == 0)
+ p64_^= get_bit(data[j], i);
+ if (((j/8) & 0x01) == 1)
+ p64^= get_bit(data[j], i);
+
+
+ /* p0128, p0128_ */
+ if (((j/16) & 0x01) == 0)
+ p0128_^= get_bit(data[j], i);
+ if (((j/16) & 0x01) == 1)
+ p0128 ^= get_bit(data[j], i);
+
+ /* p0256, p0256_ */
+ if (((j/32) & 0x01) == 0)
+ p0256_^= get_bit(data[j], i);
+ if (((j/32) & 0x01) == 1)
+ p0256^= get_bit(data[j], i);
+
+ /* p0512, p0512_ */
+ if (((j/64) & 0x01) == 0)
+ p0512_^= get_bit(data[j], i);
+ if (((j/64) & 0x01) == 1)
+ p0512^= get_bit(data[j], i);
+
+ /* p1024, p1024_ */
+ if (((j/128) & 0x01) == 0)
+ p1024_^= get_bit(data[j], i);
+ if (((j/128) & 0x01) == 1)
+ p1024^= get_bit(data[j], i);
+
+ }
+ }
+
+ ecc[0]=~((p64 << 7) | (p64_ << 6) |
+ (p32 << 5) | (p32_ << 4) |
+ (p16 << 3) | (p16_ << 2) |
+ (p08 << 1) | (p08_ << 0));
+
+ ecc[1]=~((p1024 << 7) | (p1024_ << 6) |
+ (p0512 << 5) | (p0512_ << 4) |
+ (p0256 << 3) | (p0256_ << 2) |
+ (p0128 << 1) | (p0128_ << 0));
+
+ ecc[2]=~((p4 << 7) | (p4_ << 6) |
+ (p2 << 5) | (p2_ << 4) |
+ (p1 << 3) | (p1_ << 2));
+
+ return 0;
+}
+
+
+int
+mpio_ecc_256_check(BYTE *data, BYTE *ecc)
+{
+ BYTE own_ecc[3];
+ mpio_ecc_256_gen(data, own_ecc);
+ if ((own_ecc[0]^ecc[0])|
+ (own_ecc[1]^ecc[1])|
+ (own_ecc[2]^ecc[2])) {
+ debug("ECC %2x %2x %2x vs. %2x %2x %2x\n",
+ ecc[0], ecc[1], ecc[2], own_ecc[0], own_ecc[1], own_ecc[2]);
+ debugn(2, "ECC Error detected\n");
+ debugn(2, "ECC Correction code not in place yet, Sorry\n");
+ debugn(3, "got ECC: %2x %2x %2x\n", ecc[0], ecc[1], ecc[2]);
+ debugn(3, "calc. ECC: %2x %2x %2x\n", own_ecc[0], own_ecc[1], own_ecc[2]);
+ }
+
+ return 0;
+}
+
+
+
+
diff --git a/libmpio/ecc.h b/libmpio/ecc.h
new file mode 100644
index 0000000..8ac98ad
--- /dev/null
+++ b/libmpio/ecc.h
@@ -0,0 +1,36 @@
+/*
+ *
+ * $Id: ecc.h,v 1.1 2002/08/28 16:10:51 salmoon Exp $
+ *
+ * Library for USB MPIO-*
+ *
+ * Markus Germeier (mager@tzi.de)
+ *
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+#ifndef _MPIO_ECC_H_
+#define _MPIO_ECC_H_
+
+#include "defs.h"
+
+/* 256 Bytes Data, 3 Byte ECC to generate */
+int mpio_ecc_256_gen(BYTE *, BYTE *);
+/* 256 Bytes Data, 3 Bytes ECC to check and possibly correct */
+int mpio_ecc_256_check(BYTE *, BYTE*);
+
+#endif
diff --git a/libmpio/fat.c b/libmpio/fat.c
new file mode 100644
index 0000000..c978b2b
--- /dev/null
+++ b/libmpio/fat.c
@@ -0,0 +1,414 @@
+/*
+ *
+ * $Id: fat.c,v 1.1 2002/08/28 16:10:51 salmoon Exp $
+ *
+ * Library for USB MPIO-*
+ *
+ * Markus Germeier (mager@tzi.de)
+ *
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+#include "fat.h"
+#include "io.h"
+#include "debug.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+int
+mpio_bootblocks_read (mpio_t *m, mpio_mem_t mem)
+{
+ BYTE *pe; /* partition entry */
+ BYTE *bpb; /* BIOS Parameter Block */
+
+ mpio_smartmedia_t *sm;
+
+ int sector, head, cylinder, total_sector;
+ long temp;
+
+ if (mem == MPIO_INTERNAL_MEM) sm = &m->internal;
+ if (mem == MPIO_EXTERNAL_MEM) sm = &m->external;
+
+ /* TODO: check a few things more, just to be sure */
+
+ /* read CIS (just in case it might me usefull) */
+ /* fixed @ offset 0x20 */
+ if (mpio_io_sector_read(m, mem, 0x20, sm->size, 0, sm->cis)) {
+ debug("error reading CIS\n");
+ return 1;
+ }
+
+ /* read MBR */
+ /* fixed @ offset 0x40 */
+ if (mpio_io_sector_read(m, mem, 0x40, sm->size, 0, sm->mbr)) {
+ debug("error reading MBR\n");
+ return 1;
+ }
+
+ if ((sm->mbr[0x1fe] != 0x55) || (sm->mbr[0x1ff] != 0xaa)) {
+ debug("This is not the MBR!\n");
+ return 1;
+ }
+
+ /* always use the first partition */
+ /* we probably don't need to support others */
+ pe = sm->mbr + 0x1be;
+
+ head = (int)(*(pe+0x01) & 0xff);
+ sector = (int)(*(pe+0x02) & 0x3f);
+ cylinder = (int)((*(pe+0x02) >> 6) * 0x100 + *(pe + 0x03));
+
+ sm->pbr_offset=(cylinder * sm->geo.NumHead + head ) *
+ sm->geo.NumSector + sector - 1 + OFFSET_MBR;
+
+ /* read PBR */
+ if (mpio_io_sector_read(m, mem, sm->pbr_offset, sm->size, 0, sm->pbr))
+ return 1;
+
+ if ((sm->pbr[0x1fe] != 0x55) || (sm->pbr[0x1ff] != 0xaa)) {
+ debug("This is not the PBR!\n");
+ return 1;
+ }
+
+ if (strncmp((sm->pbr+0x36),"FAT", 3) != 0) {
+ debug("Did not find an FAT signature, *not* good!, aborting!\n");
+ exit (1);
+ }
+
+ bpb = sm->pbr + 0x0b;
+
+ total_sector = (*(sm->pbr+0x14) * 0x100 + *(sm->pbr + 0x13));
+ if (!total_sector)
+ total_sector = (*(sm->pbr+0x23) * 0x1000000 +
+ *(sm->pbr+0x22) * 0x10000 +
+ *(sm->pbr+0x21) * 0x100 +
+ *(sm->pbr+0x20));
+
+ /* 128 MB need 2 Bytes instead of 1.5 */
+ if (sm->size != 128)
+ temp = ((total_sector / 0x20 * 0x03 / 0x02 / 0x200) + 0x01);
+ else
+ temp = ((total_sector / 0x20 * 0x02 / 0x200) + 0x01);
+
+ sm->max_cluster = (total_sector / BLOCK_SECTORS);
+ debugn(2,"max_cluster: %d\n", sm->max_cluster);
+ sm->fat_offset = sm->pbr_offset + 0x01;
+ sm->fat_size = temp;
+ sm->fat_nums = *(sm->pbr + 0x10);
+ sm->dir_offset = sm->pbr_offset + 0x01 + temp * 2;
+
+ return 0;
+}
+
+/* read "fat_size" sectors of fat into the provided buffer */
+int
+mpio_fat_read (mpio_t *m, mpio_mem_t mem)
+{
+ mpio_smartmedia_t *sm;
+ BYTE recvbuff[SECTOR_SIZE];
+ int i;
+
+ if (mem == MPIO_INTERNAL_MEM) {
+ sm = &m->internal;
+ if (mpio_io_spare_read(m, mem, 0, (sm->size / sm->chips), 0, sm->fat,
+ (sm->fat_size * SECTOR_SIZE)))
+ return 1;
+ return 0;
+ }
+
+ if (mem == MPIO_EXTERNAL_MEM) sm = &m->external;
+
+ for (i = 0; i < sm->fat_size; i++) {
+ if (mpio_io_sector_read(m, mem, (sm->fat_offset + i),
+ sm->size, 0, recvbuff))
+ return 1;
+
+ memcpy(sm->fat + (i * SECTOR_SIZE), recvbuff, SECTOR_SIZE);
+ }
+
+ return (0);
+}
+
+int
+mpio_fat_entry_free(mpio_t *m, mpio_mem_t mem, int entry )
+{
+ int e;
+ mpio_smartmedia_t *sm;
+
+ if (mem == MPIO_INTERNAL_MEM) {
+ sm = &m->internal;
+ e = entry * 0x10;
+
+ if((sm->fat[e+0] == 0xff) &&
+ (sm->fat[e+1] == 0xff) &&
+ (sm->fat[e+2] == 0xff))
+ return 1;
+ }
+
+ if (mem == MPIO_EXTERNAL_MEM) {
+ sm = &m->internal;
+ if (mpio_fat_entry_read(m, mem, entry) == 0)
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+mpio_fat_entry_read(mpio_t *m, mpio_mem_t mem, int entry )
+{
+ mpio_smartmedia_t *sm;
+ int e;
+ int v;
+
+ if (mem == MPIO_INTERNAL_MEM) {
+ sm = &m->internal;
+ e = entry;
+ e = e * 0x10 + 7;
+ if((sm->fat[e+0] == 0xff) &&
+ (sm->fat[e+1] == 0xff) &&
+ (sm->fat[e+2] == 0xff) &&
+ (sm->fat[e+3] == 0xff))
+ return 0xffffffff;
+
+ v = (sm->fat[e+1] * 0x10000 +
+ sm->fat[e+2] * 0x100 +
+ sm->fat[e+3]) / 0x20 + sm->fat[e+0] * 0x1000000;
+
+ return v;
+ }
+
+ if (mem == MPIO_EXTERNAL_MEM) sm = &m->external;
+
+ if (sm->size == 128) {
+ /* 2 Byte per entry */
+ e = entry * 2;
+ v = sm->fat[e + 1] * 0x100 + sm->fat[e];
+ } else {
+ /* 1.5 Byte per entry */
+ /* Nibble order: x321 */
+ e = (entry * 3 / 2);
+/* printf("mager: byte (%d/%d)\n", e, e+1); */
+ if ((entry & 0x01) == 0) {
+ /* LLxH */
+ /* 21x3 */
+ v = (sm->fat[e + 1] & 0x0f) * 0x100 + sm->fat[e];
+ } else {
+ /* 1x32 */
+ v = (sm->fat[e + 1] * 0x10) + (sm->fat[e] >> 4);
+ }
+ }
+
+ return v;
+}
+
+int
+mpio_fat_entry_write(mpio_t *m, mpio_mem_t mem, int entry, WORD value)
+{
+ mpio_smartmedia_t *sm;
+ int e;
+ BYTE backup;
+
+ if (mem == MPIO_INTERNAL_MEM) {
+ sm = &m->internal;
+ }
+
+ if (mem == MPIO_EXTERNAL_MEM) {
+ sm = &m->external;
+ }
+ if (sm->size == 128) {
+ /* 2 Byte per entry */
+ e = entry * 2;
+ sm->fat[e] = value & 0xff;
+ sm->fat[e + 1] = (value >> 8 ) & 0xff;
+
+ } else {
+ /* 1.5 Byte per entry */
+ e = (entry * 3 / 2);
+ if ((entry & 0x01) == 0) {
+ /* 21x3 */
+ sm->fat[e] = value & 0xff;
+ backup = sm->fat[e + 1] & 0xf0;
+ sm->fat[e + 1] = backup | (( value / 0x100 ) & 0x0f);
+ } else {
+ /* 1x32 */
+ sm->fat[e + 1] = (value / 0x10) & 0xff;
+ backup = sm->fat[e] & 0x0f;
+ sm->fat[e] = backup | ( (value * 0x10) & 0xf0 );
+ }
+
+ }
+
+ return 0;
+}
+
+int
+mpio_fat_internal_find_startsector(mpio_t *m, BYTE start)
+{
+ int i = 0;
+ int found = 0;
+ mpio_smartmedia_t *sm = &m->internal;
+
+ while ((i < sm->max_cluster) && (!found)) {
+ if ((sm->fat[i * 0x10] == 0xaa) &&
+ (sm->fat[i * 0x10 + 1] == start)) {
+ found = i;
+ }
+ i++;
+ }
+
+ return found;
+}
+
+int
+mpio_fat_free_clusters(mpio_t *m, mpio_mem_t mem)
+{
+ mpio_smartmedia_t *sm;
+ int i;
+ int e = 0;
+ int fsize;
+ if (mem == MPIO_INTERNAL_MEM) {
+ sm = &m->internal;
+
+ for (i = 0; i < sm->max_cluster; i++)
+ if (mpio_fat_entry_free(m, mem, i)) e++;
+ }
+
+ if (mem == MPIO_EXTERNAL_MEM) {
+ sm = &m->external;
+ fsize = sm->fat_size * SECTOR_SIZE;
+
+ if (sm->size == 128) {
+ fsize /= 2;
+ } else {
+ fsize *= 2;
+ fsize /= 3;
+ }
+ for (i = 0; i < (sm->max_cluster - 1); i++)
+ if (mpio_fat_entry_read(m, mem, i) == 0) e++;
+ }
+
+ return (e * 16);
+}
+
+int
+mpio_fat_find_free(mpio_t *m, mpio_mem_t mem)
+{
+ mpio_smartmedia_t *sm;
+ int i;
+ int fsize;
+ int found = 0;
+
+ if (mem == MPIO_INTERNAL_MEM) {
+ sm = &m->internal;
+
+ for (i = 2; ((i < sm->max_cluster) && (!found)); i++)
+ if (mpio_fat_entry_free(m, mem, i)) found = i;
+ }
+
+ if (mem == MPIO_EXTERNAL_MEM) {
+ sm = &m->external;
+ fsize = sm->fat_size * SECTOR_SIZE;
+
+ if (sm->size == 128) {
+ fsize /= 2;
+ } else {
+ fsize *= 2;
+ fsize /= 3;
+ }
+ for (i = 2; ((i < (sm->max_cluster-1)) && (!found)); i++)
+ if (mpio_fat_entry_read(m, mem, i)==0) found = i;
+ }
+
+ return found;
+}
+
+int
+mpio_fat_clear(mpio_t *m, mpio_mem_t mem)
+{
+ mpio_smartmedia_t *sm;
+
+ if (mem == MPIO_INTERNAL_MEM) {
+ sm = &m->internal;
+ debug("clearing of the internal FAT not yet supported , sorry\n");
+ return 0;
+ }
+
+ if (mem == MPIO_EXTERNAL_MEM) {
+ sm = &m->external;
+ memset(sm->fat, 0x00, (sm->fat_size * SECTOR_SIZE));
+ sm->fat[0] = 0xf8;
+ sm->fat[1] = 0xff;
+ sm->fat[2] = 0xff;
+ /* for FAT 16 */
+ if (sm->size == 128)
+ sm->fat[3] = 0xff;
+ }
+
+ return 0;
+}
+
+/*
+ * This function acutally writes both,
+ * the FAT _and_ the root directory
+ *
+ */
+
+int
+mpio_fat_write(mpio_t *m, mpio_mem_t mem)
+{
+ mpio_smartmedia_t *sm;
+ BYTE dummy[BLOCK_SIZE];
+ WORD i;
+
+ if (mem == MPIO_INTERNAL_MEM) {
+ sm = &m->internal;
+ debug("writing of the internal FAT is not yet supported, sorry\n");
+ return 0;
+ }
+
+ if (mem == MPIO_EXTERNAL_MEM) sm=&m->external;
+
+ memset(dummy, 0xff, BLOCK_SIZE);
+
+ for (i = 0x40; i < (sm->dir_offset + DIR_NUM) ; i++) {
+ if (((i / 0x20) * 0x20) == i) {
+/* debug("formatting: %2x\n", i); */
+ mpio_io_block_delete(m, mem, i, sm->size);
+ }
+
+ if (i == 0x40)
+ mpio_io_sector_write(m, mem, 0x40, sm->size, 0, sm->mbr);
+ if ((i > 0x40) && (i < sm->pbr_offset))
+ mpio_io_sector_write(m, mem, i, sm->size, 0, dummy);
+
+ if (i == sm->pbr_offset)
+ mpio_io_sector_write(m, mem, sm->pbr_offset, sm->size, 0, sm->pbr);
+
+ if ((i >= sm->fat_offset) && (i < (sm->fat_offset + (2 * sm->fat_size))))
+ mpio_io_sector_write(m, mem, i, sm->size, 0,
+ (sm->fat + SECTOR_SIZE *
+ ((i - sm->fat_offset) % sm->fat_size)));
+
+ if (i>=sm->dir_offset)
+ mpio_io_sector_write(m, mem, i, sm->size, 0,
+ (sm->dir + (i - sm->dir_offset) * SECTOR_SIZE));
+ }
+
+ return 0;
+}
diff --git a/libmpio/fat.h b/libmpio/fat.h
new file mode 100644
index 0000000..dc6c6d0
--- /dev/null
+++ b/libmpio/fat.h
@@ -0,0 +1,47 @@
+/*
+ *
+ * $Id: fat.h,v 1.1 2002/08/28 16:10:51 salmoon Exp $
+ *
+ * Library for USB MPIO-*
+ *
+ * Markus Germeier (mager@tzi.de)
+ *
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+#ifndef _MPIO_FAT_H_
+#define _MPIO_FAT_H_
+
+#include "defs.h"
+
+
+int mpio_bootblocks_read(mpio_t *, mpio_mem_t);
+
+int mpio_fat_read(mpio_t *, mpio_mem_t);
+int mpio_fat_write(mpio_t *, mpio_mem_t);
+int mpio_fat_clear(mpio_t *, mpio_mem_t);
+
+int mpio_fat_entry_read(mpio_t *, mpio_mem_t, int);
+int mpio_fat_entry_write(mpio_t *, mpio_mem_t, int, WORD);
+int mpio_fat_entry_free(mpio_t *, mpio_mem_t, int);
+
+int mpio_fat_free_clusters(mpio_t *, mpio_mem_t);
+int mpio_fat_find_free(mpio_t *, mpio_mem_t);
+
+int mpio_fat_internal_find_startsector(mpio_t *, BYTE);
+
+#endif /* _MPIO_FAT_H_ */
diff --git a/libmpio/io.c b/libmpio/io.c
new file mode 100644
index 0000000..1e49a27
--- /dev/null
+++ b/libmpio/io.c
@@ -0,0 +1,618 @@
+/* -*- linux-c -*- */
+
+/*
+ *
+ * $Id: io.c,v 1.1 2002/08/28 16:10:50 salmoon Exp $
+ *
+ * Library for USB MPIO-*
+ *
+ * Markus Germeier (mager@tzi.de)
+ *
+ * uses code from mpio_stat.c by
+ * Yuji Touya (salmoon@users.sourceforge.net)
+ *
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+/*
+ *
+ * low level I/O
+ *
+ *
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "io.h"
+#include "debug.h"
+#include "ecc.h"
+
+WORD index2blockaddress(WORD);
+
+WORD index2blockaddress(WORD ba)
+{
+ WORD addr;
+ BYTE p = 0, c = 0;
+ BYTE high, low;
+
+ high = 0x10 | ((ba / 0x80) & 0x07);
+ low = (ba * 2) & 0xff;
+
+ c = high;
+ while (c) {
+ if (c & 0x01)
+ p ^= 1;
+ c /= 2;
+ }
+
+ c = low;
+ while (c) {
+ if (c & 0x01)
+ p ^= 0x01;
+ c /= 2;
+ }
+
+ addr = (high * 0x100) + low + p;
+
+ return addr;
+}
+
+/*
+ * low-low level functions
+ */
+
+/*
+ * Set command packet
+ *
+ * parameter:
+ *
+ * cmd: commando code
+ * mem: internal/external
+ * index: sector/block
+ * small: FAT with less or equal 32MB
+ * wsize: write size, only for PUT_BLOCK
+ *
+ *
+ */
+
+int
+mpio_io_set_cmdpacket(mpio_cmd_t cmd, mpio_mem_t mem, DWORD index,
+ BYTE small, BYTE wsize, BYTE *buffer)
+{
+
+ /* clear cmdpacket*/
+ memset(buffer, 0, 0x40);
+
+ *buffer = cmd;
+ *(buffer + 0x01) = mem;
+ *(buffer + 0x03) = (BYTE) (index & 0x00ff);
+ *(buffer + 0x04) = (BYTE)((index & 0xff00) >> 8);
+ /* SM cards with less or equal 32 MB only need 2 Bytes
+ * to address sectors or blocks.
+ * The highest byte has to be 0xff in that case!
+ */
+ if (small <= 32) {
+ *(buffer + 0x05) = 0xff;
+ } else {
+ *(buffer + 0x05) = (BYTE) (index >> 16);
+ }
+ *(buffer + 0x06) = wsize; /* is this always 0x48 in case of a write ?? */
+
+ memcpy((buffer + 0x3b), "jykim", 5);
+
+
+ return (0);
+}
+
+/*
+ * write chunk of data to MPIO filedescriptor
+ *
+ * parameter:
+ *
+ * fd: filedescriptor
+ * block: data buffer (has to be num_bytes)
+ * num_bytes: size of data buffer
+ *
+ */
+int
+mpio_io_bulk_write(int fd, BYTE *block, int num_bytes)
+{
+ BYTE *p;
+ int count, bytes_left, bytes_written;
+
+ bytes_left = num_bytes;
+ bytes_written = 0;
+ p = block;
+
+ do
+ {
+ count = write (fd, p, bytes_left);
+ if (count > 0)
+ {
+ p += count;
+ bytes_written += count;
+ bytes_left -= count;
+ }
+ } while (bytes_left > 0 && count > 0);
+
+ return bytes_written;
+}
+
+/*
+ * read chunk of data from MPIO filedescriptor
+ *
+ * parameter:
+ *
+ * fd: filedescriptor
+ * block: return buffer (has to be num_bytes)
+ * num_bytes: size of return buffer
+ *
+ */
+int
+mpio_io_bulk_read (int fd, BYTE *block, int num_bytes)
+{
+ int total_read, count, bytes_left;
+ BYTE *p;
+
+ total_read = 0;
+ bytes_left = num_bytes;
+ p = block;
+
+ do
+ {
+ count = read (fd, p, bytes_left);
+
+ if (count > 0)
+ {
+ total_read += count;
+ bytes_left -= count;
+ p += count;
+ }
+ } while (total_read < num_bytes && count > 0);
+
+ return total_read;
+}
+
+/*
+ * low level functions
+ */
+
+/*
+ * read version block from MPIO
+ *
+ * parameter:
+ *
+ * m: mpio context
+ * buffer: return buffer (has to be CMD_SIZE)
+ *
+ */
+int
+mpio_io_version_read(mpio_t *m, BYTE *buffer)
+{
+ int nwrite, nread;
+ BYTE cmdpacket[CMD_SIZE], status[CMD_SIZE];
+
+ /* Send command packet to MPIO */
+ mpio_io_set_cmdpacket (GET_VERSION, 0, 0, 0xff, 0, cmdpacket);
+
+ debugn (5, ">>> MPIO\n");
+ hexdump (cmdpacket, sizeof(cmdpacket));
+
+ nwrite = mpio_io_bulk_write (m->fd, cmdpacket, 0x40);
+
+ if (nwrite != CMD_SIZE) {
+ debug ("Failed to send command.\n\n");
+ close (m->fd);
+ return 0;
+ }
+
+ /* Receive packet from MPIO */
+ nread = mpio_io_bulk_read (m->fd, status, 0x40);
+
+ if (nread == -1 || nread != 0x40) {
+ debug ("Failed to read Sector.\n%x\n",nread);
+ close (m->fd);
+ return 0;
+ }
+
+ debugn (5, "<<< MPIO\n");
+ hexdump (status, 0x40);
+
+ memcpy(buffer, status, 0x40);
+
+ return CMD_SIZE;
+}
+
+/*
+ * read sector from SmartMedia
+ *
+ * parameter:
+ *
+ * m: mpio context
+ * area: MPIO_{INTERNAL,EXTERNAL}_MEM
+ * index: index number of sector to read
+ * small: size of memory chip to read from
+ * wsize: dummy
+ * output: return buffer (has to be SECTOR_SIZE)
+ *
+ */
+int
+mpio_io_sector_read(mpio_t *m, BYTE area, DWORD index, BYTE small,
+ BYTE wsize, BYTE *output)
+{
+ int nwrite, nread;
+ BYTE cmdpacket[CMD_SIZE], recvbuff[SECTOR_TRANS];
+
+ mpio_io_set_cmdpacket (GET_SECTOR, area, index, small, wsize, cmdpacket);
+
+ debugn (5, "\n>>> MPIO\n");
+ hexdump (cmdpacket, sizeof(cmdpacket));
+
+ nwrite = mpio_io_bulk_write (m->fd, cmdpacket, 0x40);
+
+ if(nwrite != CMD_SIZE) {
+ debug ("\nFailed to send command.\n\n");
+ close (m->fd);
+ return 1;
+ }
+
+ /* Receive packet from MPIO */
+ nread = mpio_io_bulk_read (m->fd, recvbuff, SECTOR_TRANS);
+
+ if(nread != SECTOR_TRANS) {
+ debug ("\nFailed to read Sector.\n%x\n", nread);
+ close (m->fd);
+ return 1;
+ }
+
+ /* check ECC Area information */
+ if (area==MPIO_EXTERNAL_MEM) {
+ mpio_ecc_256_check (recvbuff,
+ (recvbuff + SECTOR_SIZE + 13));
+ mpio_ecc_256_check ((recvbuff + (SECTOR_SIZE / 2)),
+ (recvbuff + SECTOR_SIZE + 8));
+ }
+
+ debugn (5, "\n<<< MPIO\n");
+ hexdump (recvbuff, SECTOR_TRANS);
+
+ memcpy(output, recvbuff, SECTOR_SIZE);
+
+ return 0;
+}
+
+/*
+ * write sector to SmartMedia
+ *
+ * parameter:
+ *
+ * m: mpio context
+ * area: MPIO_{INTERNAL,EXTERNAL}_MEM
+ * index: index number of sector to read
+ * small: size of memory chip to read from
+ * wsize: dummy
+ * input: data buffer (has to be SECTOR_SIZE)
+ *
+ */
+int
+mpio_io_sector_write(mpio_t *m, BYTE area, DWORD index, BYTE small,
+ BYTE wsize, BYTE *input)
+{
+ DWORD block_address, ba;
+ int nwrite;
+ BYTE cmdpacket[CMD_SIZE], sendbuff[SECTOR_TRANS];
+
+ mpio_io_set_cmdpacket(PUT_SECTOR, area, index, small, wsize, cmdpacket);
+
+ debugn (5, "\n>>> MPIO\n");
+ hexdump (cmdpacket, sizeof(cmdpacket));
+
+ nwrite = mpio_io_bulk_write(m->fd, cmdpacket, 0x40);
+
+ if(nwrite != CMD_SIZE) {
+ debug ("\nFailed to send command.\n\n");
+ close (m->fd);
+ return 1;
+ }
+
+ memset(sendbuff, 0, SECTOR_TRANS);
+ memset(sendbuff + SECTOR_SIZE, 0xff, 0x10);
+ memcpy(sendbuff, input, SECTOR_SIZE);
+
+ if (index<0x40) {
+ block_address=0;
+ } else {
+ ba= (index /0x20) - 2;
+ debugn(2, "foobar: %4x\n", ba);
+ block_address= index2blockaddress(ba);
+ debugn(2, "foobar: %4x\n", block_address);
+ }
+
+ /* generate ECC information for spare area ! */
+ mpio_ecc_256_gen(sendbuff,
+ sendbuff + SECTOR_SIZE + 0x0d);
+ mpio_ecc_256_gen(sendbuff + (SECTOR_SIZE / 2),
+ sendbuff + SECTOR_SIZE + 0x08);
+
+ ba = (block_address / 0x100) & 0xff;
+ sendbuff[SECTOR_SIZE + 0x06] = ba;
+ sendbuff[SECTOR_SIZE + 0x0b] = ba;
+
+ ba = block_address & 0xff;
+ sendbuff[SECTOR_SIZE + 0x07] = ba;
+ sendbuff[SECTOR_SIZE + 0x0c] = ba;
+
+ debugn (5, "\n>>> MPIO\n");
+ hexdump(sendbuff, SECTOR_TRANS);
+
+ /* write sector MPIO */
+ nwrite = mpio_io_bulk_write(m->fd, sendbuff, SECTOR_TRANS);
+
+ if(nwrite != SECTOR_TRANS) {
+ debug ("\nFailed to read Sector.\n%x\n", nwrite);
+ close (m->fd);
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * read/write of blocks
+ */
+int
+mpio_io_block_read(mpio_t *m, BYTE area, DWORD index, BYTE small,
+ BYTE wsize, BYTE *output)
+{
+ int i=0;
+ int nwrite, nread;
+ DWORD rarea=0;
+ BYTE cmdpacket[CMD_SIZE], recvbuff[BLOCK_TRANS];
+
+ if (area == MPIO_INTERNAL_MEM) {
+ rarea = index / 0x1000000;
+ index &= 0xffffff;
+ }
+ if (area == MPIO_EXTERNAL_MEM) {
+ rarea = area;
+ }
+
+ index *= BLOCK_SECTORS;
+
+ mpio_io_set_cmdpacket(GET_BLOCK, rarea, index, small, wsize, cmdpacket);
+
+ debugn(5, "\n>>> MPIO\n");
+ hexdump(cmdpacket, sizeof(cmdpacket));
+
+ nwrite = mpio_io_bulk_write(m->fd, cmdpacket, CMD_SIZE);
+
+ if(nwrite != CMD_SIZE) {
+ debug ("\nFailed to send command.\n\n");
+ close (m->fd);
+ return 1;
+ }
+
+ /* Receive packet from MPIO */
+ nread = mpio_io_bulk_read(m->fd, recvbuff, BLOCK_TRANS);
+
+ if(nread != BLOCK_TRANS) {
+ debug ("\nFailed to read Block.\n%x\n",nread);
+ close (m->fd);
+ return 1;
+ }
+
+ debugn(5, "\n<<< MPIO\n");
+ hexdump(recvbuff, BLOCK_TRANS);
+
+ for (i = 0; i < BLOCK_SECTORS; i++) {
+ /* check ECC Area information */
+ if (area==MPIO_EXTERNAL_MEM) {
+ mpio_ecc_256_check ((recvbuff + (i * SECTOR_TRANS)),
+ ((recvbuff + (i * SECTOR_TRANS) + SECTOR_SIZE + 13)));
+ mpio_ecc_256_check ((recvbuff + (i * SECTOR_TRANS) + (SECTOR_SIZE / 2)),
+ ((recvbuff + (i * SECTOR_TRANS) + SECTOR_SIZE + 8)));
+ }
+
+ memcpy(output + (i * SECTOR_SIZE),
+ recvbuff + (i * SECTOR_TRANS),
+ SECTOR_SIZE);
+ }
+
+ return 0;
+}
+
+/* Read spare is only usefull for the internal memory,
+ * the FAT lies there.
+ *
+ * For external SmartMedia cards we get and write the
+ * informatione during {read,write}_{sector,block}
+ *
+ */
+
+int
+mpio_io_spare_read(mpio_t *m, BYTE area, DWORD index, BYTE small,
+ BYTE wsize, BYTE *output, int toread)
+{
+ int i;
+ int nwrite, nread;
+ int chip = 0;
+ int chips = 0;
+ BYTE cmdpacket[CMD_SIZE];
+
+ if (area != MPIO_INTERNAL_MEM) {
+ debug("Something fishy happened, aborting!n");
+ exit(1);
+ }
+
+ chips = m->internal.chips;
+
+ for (chip = 1; chip <= chips; chip++) {
+ mpio_io_set_cmdpacket(GET_SPARE_AREA, chip, index, small,
+ wsize, cmdpacket);
+ debugn(5, "\n>>> MPIO\n");
+ hexdump(cmdpacket, sizeof(cmdpacket));
+
+ nwrite = mpio_io_bulk_write(m->fd, cmdpacket, CMD_SIZE);
+
+ if(nwrite != CMD_SIZE) {
+ debug ("\nFailed to send command.\n\n");
+ close (m->fd);
+ return 1;
+ }
+
+ /* Receive packet from MPIO */
+ for (i = 0; i < (toread / chips / CMD_SIZE); i++) {
+
+ nread = mpio_io_bulk_read (m->fd,
+ output + (i * CMD_SIZE) +
+ (toread / chips * (chip - 1)),
+ CMD_SIZE);
+
+ if(nread != CMD_SIZE) {
+ debug ("\nFailed to read Block.\n%x\n",nread);
+ close (m->fd);
+ return 1;
+ }
+ debugn(5, "\n<<< MPIO\n");
+ hexdump(output + (i * CMD_SIZE) + (toread / chips * (chip - 1)),
+ CMD_SIZE);
+ }
+ }
+
+ return 0;
+}
+
+int
+mpio_io_block_delete(mpio_t *m, BYTE mem, DWORD index, BYTE small)
+{
+ int nwrite, nread;
+ BYTE cmdpacket[CMD_SIZE], status[CMD_SIZE];
+
+/* Send command packet to MPIO */
+
+ mpio_io_set_cmdpacket(DEL_BLOCK, mem, index, small, 0, cmdpacket);
+
+ debugn (5, ">>> MPIO\n");
+ hexdump (cmdpacket, sizeof(cmdpacket));
+
+ nwrite = mpio_io_bulk_write(m->fd, cmdpacket, 0x40);
+
+ if (nwrite != CMD_SIZE) {
+ debug ("Failed to send command.\n\n");
+ close (m->fd);
+ return 0;
+ }
+
+/* Receive packet from MPIO */
+ nread = mpio_io_bulk_read (m->fd, status, CMD_SIZE);
+
+ if ((nread == -1) || (nread != CMD_SIZE)) {
+ debug ("Failed to read Sector.\n%x\n",nread);
+ close (m->fd);
+ return 0;
+ }
+
+ if (status[0] != 0xc0) debug ("error formatting Block %04x\n", index);
+ debugn(5, "<<< MPIO\n");
+ hexdump(status, CMD_SIZE);
+
+ return CMD_SIZE;
+}
+
+int
+mpio_io_block_write(mpio_t *m, BYTE area, DWORD index, BYTE small,
+ BYTE wsize, BYTE *data)
+{
+ int i = 0;
+ int nwrite;
+ DWORD block_address, ba;
+ DWORD rarea = 0;
+ BYTE cmdpacket[CMD_SIZE], sendbuff[BLOCK_TRANS];
+
+ if (area == MPIO_INTERNAL_MEM) {
+ rarea = index / 0x1000000;
+ index &= 0xffffff;
+ }
+ if (area == MPIO_EXTERNAL_MEM) {
+ rarea = area;
+ }
+
+ index *= BLOCK_SECTORS;
+
+ /* build block for transfer to MPIO */
+ for (i = 0; i < BLOCK_SECTORS; i++) {
+ memcpy(sendbuff + (i * SECTOR_TRANS),
+ data + (i * SECTOR_SIZE),
+ SECTOR_SIZE);
+ memset(sendbuff + (i * SECTOR_TRANS) + SECTOR_SIZE,
+ 0xff, CMD_SIZE);
+ /* fill in block information */
+ if (index < 0x40) {
+ block_address = 0;
+ } else {
+ ba = (index / 0x20) - 2;
+/* debugn(2, "foobar: %4x\n", ba); */
+ block_address = index2blockaddress(ba);
+/* debugn(2, "foobar: %4x\n", block_address); */
+ }
+
+ ba = (block_address / 0x100) & 0xff;
+ sendbuff[(i * SECTOR_TRANS) + SECTOR_SIZE + 0x06] = ba;
+ sendbuff[(i * SECTOR_TRANS) + SECTOR_SIZE + 0x0b] = ba;
+
+ ba = block_address & 0xff;
+ sendbuff[(i * SECTOR_TRANS) + SECTOR_SIZE + 0x07] = ba;
+ sendbuff[(i * SECTOR_TRANS) + SECTOR_SIZE + 0x0c] = ba;
+
+ /* generate ECC Area information */
+ if (area == MPIO_EXTERNAL_MEM) {
+ mpio_ecc_256_gen ((sendbuff + (i * SECTOR_TRANS)),
+ ((sendbuff + (i * SECTOR_TRANS) + SECTOR_SIZE + 13)));
+ mpio_ecc_256_gen ((sendbuff + (i * SECTOR_TRANS) + (SECTOR_SIZE / 2)),
+ ((sendbuff + (i * SECTOR_TRANS) + SECTOR_SIZE + 8)));
+ }
+ }
+
+ mpio_io_set_cmdpacket(PUT_BLOCK, rarea, index, small, wsize, cmdpacket);
+
+ debugn(5, "\n>>> MPIO\n");
+ hexdump(cmdpacket, sizeof(cmdpacket));
+
+ nwrite = mpio_io_bulk_write(m->fd, cmdpacket, CMD_SIZE);
+
+ if(nwrite != CMD_SIZE) {
+ debug ("\nFailed to send command.\n\n");
+ close (m->fd);
+ return 1;
+ }
+
+ /* send packet to MPIO */
+ debugn(5, "\n<<< MPIO\n");
+ hexdump(sendbuff, BLOCK_TRANS);
+ nwrite = mpio_io_bulk_write (m->fd, sendbuff, BLOCK_TRANS);
+
+ if(nwrite != BLOCK_TRANS) {
+ debug ("\nFailed to read Block.\n%x\n",nwrite);
+ close (m->fd);
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/libmpio/io.h b/libmpio/io.h
new file mode 100644
index 0000000..d682967
--- /dev/null
+++ b/libmpio/io.h
@@ -0,0 +1,58 @@
+/* -*- linux-c -*- */
+
+/*
+ *
+ * $Id: io.h,v 1.1 2002/08/28 16:10:51 salmoon Exp $
+ *
+ * Library for USB MPIO-*
+ *
+ * Markus Germeier (mager@tzi.de)
+ *
+ * uses code from mpio_stat.c by
+ * Yuji Touya (salmoon@users.sourceforge.net)
+ *
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+#ifndef _MPIO_IO_H_
+#define _MPIO_IO_H_
+
+#include "defs.h"
+
+/* real I/O */
+int mpio_io_set_cmdpacket(mpio_cmd_t, mpio_mem_t,
+ DWORD, BYTE, BYTE, BYTE *);
+
+int mpio_io_bulk_read(int, BYTE *, int);
+int mpio_io_bulk_write(int, BYTE *, int);
+
+/* read version block into memory */
+int mpio_io_version_read(mpio_t *, BYTE *);
+
+/* */
+int mpio_io_sector_read(mpio_t *, BYTE, DWORD, BYTE, BYTE, BYTE *);
+int mpio_io_sector_write(mpio_t *, BYTE, DWORD, BYTE, BYTE, BYTE *);
+
+/* */
+int mpio_io_block_read(mpio_t *, BYTE, DWORD, BYTE, BYTE, BYTE *);
+int mpio_io_block_write(mpio_t *, BYTE, DWORD, BYTE, BYTE, BYTE *);
+int mpio_io_block_delete(mpio_t *, BYTE, DWORD, BYTE);
+
+/* */
+int mpio_io_spare_read (mpio_t *, BYTE, DWORD, BYTE, BYTE, BYTE *, int);
+
+#endif /* _MPIO_IO_H_ */
diff --git a/libmpio/mpio.c b/libmpio/mpio.c
new file mode 100644
index 0000000..ce16963
--- /dev/null
+++ b/libmpio/mpio.c
@@ -0,0 +1,769 @@
+/*
+ *
+ * $Id: mpio.c,v 1.1 2002/08/28 16:10:50 salmoon Exp $
+ *
+ * Library for USB MPIO-*
+ *
+ * Markus Germeier (mager@tzi.de)
+ *
+ * uses code from mpio_stat.c by
+ * Yuji Touya (salmoon@users.sourceforge.net)
+ *
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "defs.h"
+#include "debug.h"
+#include "directory.h"
+#include "io.h"
+#include "mpio.h"
+#include "smartmedia.h"
+#include "fat.h"
+
+#define DSTRING 100
+
+int sector_hack(int mem, int sector);
+void mpio_init_internal(mpio_t *);
+void mpio_init_external(mpio_t *);
+
+void
+mpio_init_internal(mpio_t *m)
+{
+ BYTE i_offset = 0x18;
+ /* init main memory parameters */
+ m->internal.manufacturer = m->version[i_offset];
+ m->internal.id = m->version[i_offset+1];
+ m->internal.size = mpio_id2mem(m->internal.id);
+ m->internal.max_cluster = m->internal.size/16*1024;
+ m->internal.chips = 1;
+
+ /* look for a second installed memory chip */
+ if (mpio_id_valid(m->version[i_offset+2]))
+ {
+ if(mpio_id2mem(m->internal.id) != mpio_id2mem(m->version[i_offset+3]))
+ {
+ printf("Found a MPIO with two chips with different size!");
+ printf("I'm utterly confused and aborting now, sorry!");
+ printf("Please report this to: mpio-devel@lists.sourceforge.net\n");
+ exit(1);
+ }
+ m->internal.size = 2 * mpio_id2mem(m->internal.id);
+ m->internal.chips = 2;
+ }
+
+ mpio_id2geo(m->internal.id, &m->internal.geo);
+
+ /* read FAT information from spare area */
+ m->internal.fat_size=m->internal.size*2;
+ m->internal.fat=malloc(m->internal.fat_size*SECTOR_SIZE);
+ mpio_fat_read(m, MPIO_INTERNAL_MEM);
+
+ /* Read directory from internal memory */
+ m->internal.dir_offset=0;
+ mpio_rootdir_read(m, MPIO_INTERNAL_MEM);
+}
+
+void
+mpio_init_external(mpio_t *m)
+{
+ BYTE e_offset=0x20;
+
+ /* heuristic to find the right offset for the external memory */
+ while((e_offset<0x3a) && !(mpio_id_valid(m->version[e_offset])))
+ e_offset++;
+
+ if (mpio_id_valid(m->version[e_offset]))
+ {
+ m->external.manufacturer=m->version[e_offset];
+ m->external.id=m->version[e_offset+1];
+ } else {
+ m->external.manufacturer=0;
+ m->external.id=0;
+ }
+
+ if (m->external.id!=0) {
+
+ m->external.fat=0;
+ /* Read things from external memory (if available) */
+ m->external.size = mpio_id2mem(m->external.id);
+ m->external.chips = 1; /* external is always _one_ chip !! */
+ mpio_id2geo(m->external.id, &m->external.geo);
+
+ if (m->external.size < 16) {
+ printf("Sorry, I don't believe this software works with "
+ "SmartMedia Cards less than 16MB\n"
+ "Proceed with care and send any findings to: "
+ "mpio-devel@lists.sourceforge.net\n");
+ }
+
+ mpio_bootblocks_read(m, MPIO_EXTERNAL_MEM);
+ m->external.fat = malloc(SECTOR_SIZE*m->external.fat_size);
+ mpio_fat_read(m, MPIO_EXTERNAL_MEM);
+ mpio_rootdir_read(m, MPIO_EXTERNAL_MEM);
+ }
+
+
+
+}
+
+mpio_t *
+mpio_init(void)
+{
+ mpio_t *new_mpio;
+
+ new_mpio = malloc(sizeof(mpio_t));
+ if (!new_mpio) {
+ debug ("Error allocating memory for mpio_t");
+ return NULL;
+ }
+
+ new_mpio->fd = open(MPIO_DEVICE, O_RDWR);
+
+ if (new_mpio->fd < 0) {
+
+ debug ("Could not open %s\n"
+ "Verify that the mpio module is loaded and "
+ "your MPIO is\nconnected and powered up.\n\n" , MPIO_DEVICE);
+
+ return NULL;
+ }
+
+ /* Read Version Information */
+ mpio_io_version_read(new_mpio, new_mpio->version);
+
+ /* fill in values */
+ /* TODO: check for different versions !! */
+ snprintf(new_mpio->firmware.id, 12, "%s", new_mpio->version);
+ snprintf(new_mpio->firmware.major, 3, "%s", new_mpio->version + 0x0c);
+ snprintf(new_mpio->firmware.minor, 3, "%s", new_mpio->version + 0x0e);
+ snprintf(new_mpio->firmware.year, 5, "%s", new_mpio->version + 0x10);
+ snprintf(new_mpio->firmware.month, 3, "%s", new_mpio->version + 0x14);
+ snprintf(new_mpio->firmware.day, 3, "%s", new_mpio->version + 0x16);
+
+ /* internal init */
+ mpio_init_internal(new_mpio);
+
+ /* external init */
+ mpio_init_external(new_mpio);
+
+ return new_mpio;
+}
+
+/*
+ * returns available memory
+ *
+ * free: give back free memory size
+ *
+ */
+int
+mpio_memory_free(mpio_t *m, mpio_mem_t mem, int *free)
+{
+ *free=mpio_fat_free_clusters(m, mem);
+ if (mem==MPIO_INTERNAL_MEM) {
+ return (m->internal.geo.SumSector * SECTOR_SIZE / 1000);
+ }
+
+ if (mem==MPIO_EXTERNAL_MEM) {
+ return (m->external.geo.SumSector * SECTOR_SIZE / 1000);
+ }
+
+ return 0;
+}
+
+void
+mpio_close(mpio_t *m)
+{
+ close(m->fd);
+
+ if(m->internal.fat)
+ free(m->internal.fat);
+ if(m->external.fat)
+ free(m->external.fat);
+
+ free(m);
+
+}
+
+void
+mpio_get_info(mpio_t *m, mpio_info_t *info)
+{
+ int max=INFO_LINE-1;
+ snprintf(info->firmware_id, max, "\"%s\"", m->firmware.id);
+ snprintf(info->firmware_version, max, "%s.%s",
+ m->firmware.major, m->firmware.minor);
+ snprintf(info->firmware_date, max, "%s.%s.%s",
+ m->firmware.day, m->firmware.month, m->firmware.year);
+
+ if (m->internal.chips == 1) {
+ snprintf(info->firmware_mem_internal, max, "%3dMB (%s)",
+ mpio_id2mem(m->internal.id),
+ mpio_id2manufacturer(m->internal.manufacturer));
+ } else {
+ snprintf(info->firmware_mem_internal, max, "%3dMB (%s) - %d chips",
+ mpio_id2mem(m->internal.id),
+ mpio_id2manufacturer(m->internal.manufacturer),
+ m->internal.chips);
+ }
+
+ snprintf(info->firmware_mem_external, max, "%3dMB (%s)",
+ mpio_id2mem(m->external.id),
+ mpio_id2manufacturer(m->external.manufacturer));
+}
+
+/* void */
+/* mpio_print_version(mpio_t *m) */
+/* { */
+/* printf("Firmware Id: \"%s\"\n", m->firmware.id); */
+/* printf("Firmware Version: %s.%s\n", m->firmware.major, */
+/* m->firmware.minor); */
+/* printf("Firmware Date: %s.%s.%s\n", m->firmware.day, */
+/* m->firmware.month, */
+/* m->firmware.year); */
+
+/* printf("internal Memory: %3dMB (%s)\n", */
+/* mpio_id2mem(m->internal.id), */
+/* mpio_id2manufacturer(m->internal.manufacturer)); */
+/* if (m->external.id!=0) { */
+/* printf("external Memory: %3dMB (%s)\n", */
+/* mpio_id2mem(m->external.id), */
+/* mpio_id2manufacturer(m->external.manufacturer)); */
+/* } else { */
+/* printf("external Memory: %3dMB (%s)\n", 0, "not available"); */
+/* } */
+/* } */
+
+/*
+ *
+ * foo
+ *
+ */
+
+/*
+ * HELP!
+ *
+ * somebody explain me these values!!!
+ *
+ */
+
+int
+sector_hack(int mem, int sector)
+{
+ int a = sector;
+
+ /* No Zone-based block management for SmartMedia below 32MB !!*/
+
+ if (mem == 64) {
+ /* I'm so large in *not* knowing! */
+ if (sector >= 89)
+ a++;
+ if (a >= 1000)
+ a += 21;
+ if (a >= 2021)
+ a += 24;
+ if (a >= 3045)
+ a += 24;
+ /* WHAT? */
+ if (a >= 3755)
+ a++;
+
+ }
+ if ((mem == 128) || (mem == 32)) {
+ /* two blocks are already spent elsewhere */
+ /* question is: where (CIS and ??) */
+ if (sector >= 998)
+ a += 22;
+ /* ... and then add 24 empty blocks every 1000 sectors */
+ a += ((sector - 998) / 1000 * 24);
+/* if (a>=2020) */
+/* a+=24; */
+/* if (a>=3044) */
+/* a+=24; */
+/* if (a>=4068) */
+/* a+=24; */
+/* if (a>=5092) */
+/* a+=24; */
+/* if (a>=6116) */
+/* a+=24; */
+/* if (a>=7140) */
+/* a+=24; */
+ }
+
+ return a;
+}
+
+int
+mpio_file_get(mpio_t *m, mpio_mem_t mem, BYTE *filename,
+ BYTE (*progress_callback)(int, int))
+{
+ BYTE *p;
+ BYTE bdummy;
+ WORD wdummy;
+
+ mpio_smartmedia_t *sm;
+ int data_offset;
+ BYTE fname[129];
+ BYTE block[BLOCK_SIZE];
+ DWORD startsector = 0, sector;
+ DWORD realsector = 0;
+ int fd, towrite;
+
+ DWORD filesize, fsize;
+ DWORD fat_and;
+ DWORD fat_end;
+ BYTE abort = 0;
+
+ /* please fix me sometime */
+ /* the system entry are kind of special ! */
+ if (strncmp("sysdum", filename, 6) == 0)
+ return 0;
+
+ if (mem == MPIO_INTERNAL_MEM) {
+ sm = &m->internal;
+ data_offset = 0x00;
+ fat_and = 0xffffffff;
+ fat_end = 0xffffffff;
+ }
+
+ if (mem == MPIO_EXTERNAL_MEM) {
+ sm = &m->external;
+ data_offset = sm->dir_offset + DIR_NUM - (2 * BLOCK_SECTORS);
+ /* FAT 16 vs. FAT 12 */
+ if (sm->size==128) {
+ fat_and = 0xffff;
+ fat_end = 0xfff8;
+ } else {
+ fat_and = 0xfff;
+ fat_end = 0xff8;
+ }
+ }
+
+ p = mpio_directory_open(m, mem);
+ while (p) {
+ mpio_dentry_get (m, p,
+ fname, 128,
+ &wdummy, &bdummy, &bdummy,
+ &bdummy, &bdummy, &filesize);
+ fsize = filesize;
+ if ((strcmp(fname,filename) == 0) && (strcmp(filename,fname) == 0)) {
+ startsector = mpio_dentry_get_startsector(m, p);
+ p = NULL;
+ }
+
+ p = mpio_dentry_next(m, p);
+ }
+
+ /* grr, of curse these are clusters not sectors */
+ /* must code while awake, must ... */
+ if (startsector) {
+ fd = open(filename, (O_RDWR | O_CREAT), (S_IRWXU | S_IRGRP | S_IROTH));
+ debugn(2, "startsector: %4x\n", startsector);
+ sector = startsector;
+ if (mem == MPIO_INTERNAL_MEM) {
+ realsector = mpio_fat_internal_find_startsector(m, sector);
+ realsector = realsector+ /* chose the right bank */
+ (0x01000000 * ((realsector / (sm->size / 16 * 1000 / sm->chips)) + 1));
+ sector=realsector;
+ debugn(2, "startsector (real): %4x\n", sector);
+ } else {
+ realsector=sector_hack(sm->size, sector);
+ }
+
+ mpio_io_block_read(m, mem, realsector + (data_offset / BLOCK_SECTORS),
+ sm->size, 0, block);
+
+ if (filesize > BLOCK_SIZE) {
+ towrite = BLOCK_SIZE;
+ } else {
+ towrite = filesize;
+ }
+
+ if (write(fd, block, towrite) != towrite) {
+ debug("error writing file data\n");
+ close(fd);
+ return -1;
+ }
+
+ filesize -= towrite;
+
+ debugn(5, "sector: (%6x) %4x\n",
+ (sector&0xffffff), mpio_fat_entry_read(m, mem, sector&0xffffff));
+
+
+
+ while((((mpio_fat_entry_read(m, mem, (sector & 0xffffff)) & fat_and)
+ < fat_end)) && (filesize > 0) && (!abort)) {
+ sector=mpio_fat_entry_read(m, mem, sector & 0xffffff);
+ debugn(2,"next sector: %4x\n", sector);
+ if (mem == MPIO_INTERNAL_MEM) {
+ realsector = sector;
+ } else {
+ realsector = sector_hack(sm->size, sector);
+ }
+
+ debugn(2," realsector: %4x\n", realsector);
+
+ mpio_io_block_read(m, mem,
+ (realsector + (data_offset / BLOCK_SECTORS)),
+ sm->size, 0, block);
+ if (filesize > BLOCK_SIZE) {
+ towrite=BLOCK_SIZE;
+ } else {
+ towrite=filesize;
+ }
+
+ if (write(fd, block, towrite)!=towrite) {
+ debug("error writing file data\n");
+ close(fd);
+ return -1;
+ }
+ filesize-=towrite;
+
+ if (progress_callback)
+ abort=(*progress_callback)((fsize-filesize), fsize);
+
+ }
+
+ close (fd);
+ } else {
+ debug("unable to locate the file: %s\n", filename);
+ }
+
+ return (fsize-filesize);
+}
+
+int
+mpio_file_put(mpio_t *m, mpio_mem_t mem, BYTE *filename,
+ BYTE (*progress_callback)(int, int))
+{
+ mpio_smartmedia_t *sm;
+ int data_offset;
+ BYTE block[BLOCK_SIZE];
+ DWORD startsector=0, sector, nextsector;
+ DWORD realsector=0;
+ int fd, toread;
+ struct stat file_stat;
+
+ DWORD filesize, fsize;
+ DWORD fat_and;
+ DWORD fat_end;
+ BYTE abort=0;
+
+
+ if (mem==MPIO_INTERNAL_MEM) {
+ sm=&m->internal;
+ data_offset=0x00;
+ fat_and=0xffffffff;
+ fat_end=0xffffffff;
+ debug("writing to internal memory is not yet supported, sorry\n");
+ return 0;
+ }
+
+ if (mem==MPIO_EXTERNAL_MEM) {
+ sm=&m->external;
+ data_offset=sm->dir_offset+DIR_NUM-(2*BLOCK_SECTORS);
+ /* FAT 16 vs. FAT 12 */
+ if (sm->size==128) {
+ fat_and=0xffff;
+ fat_end=0xfff8;
+ } else {
+ fat_and=0xfff;
+ fat_end=0xff8;
+ }
+ }
+
+ if (stat((const char *)filename, &file_stat)!=0) {
+ debug("could not find file: %s\n", filename);
+ return 0;
+ }
+
+ fsize=filesize=file_stat.st_size;
+ debugn(2, "filesize: %d\n", fsize);
+
+ fd = open(filename, O_RDONLY);
+ if (fd==-1) {
+ debug("could not find file: %s\n", filename);
+ return 0;
+ }
+
+ while ((filesize>0) & (!abort)) {
+
+ if (filesize>=BLOCK_SIZE) {
+ toread=BLOCK_SIZE;
+ } else {
+ toread=filesize;
+ }
+
+ if (read(fd, block, toread)!=toread) {
+ debug("error reading file data\n");
+ close(fd);
+ return -1;
+ }
+
+ if (!startsector) {
+ startsector=mpio_fat_find_free(m, mem);
+ if (!startsector) {
+ debug("could not find startsector for file!\n");
+ close(fd);
+ return 0;
+ }
+ sector=startsector;
+ debugn(2, "startsector: %d\n", startsector);
+ /* evil hacks are us ;-) */
+ mpio_fat_entry_write(m, mem, startsector, fat_and);
+ } else {
+ nextsector=mpio_fat_find_free(m, mem);
+ if (!nextsector){
+ debug("no more free blocks, short write!\n");
+ close(fd);
+ return (fsize-filesize);
+ }
+ debugn(2, " nextsector: %d\n", nextsector);
+
+ mpio_fat_entry_write(m, mem, sector, nextsector);
+ sector=nextsector;
+ /* evil hacks are us ;-) */
+ mpio_fat_entry_write(m, mem, sector, fat_and);
+
+ }
+
+ if (mem==MPIO_INTERNAL_MEM) {
+/* realsector=fat_internal_find_startsector(m, sector); */
+/* realsector=realsector+ /\* chose the right bank *\/ */
+/* (0x01000000*((realsector/(sm->size/16*1000/sm->chips))+1)); */
+/* sector=realsector; */
+/* debugn(2, "startsector (real): %4x\n", sector); */
+ } else {
+ realsector=sector_hack(sm->size, sector);
+ }
+
+/* debug("mager: %04x : %3d\n", realsector*BLOCK_SECTORS, realsector); */
+ mpio_io_block_delete(m, mem, ((realsector*BLOCK_SECTORS) + data_offset),
+ sm->size);
+ mpio_io_block_write(m, mem, realsector + (data_offset/BLOCK_SECTORS),
+ sm->size, 0x48, block);
+
+ filesize -= toread;
+
+ if (progress_callback)
+ abort=(*progress_callback)((fsize-filesize), fsize);
+ }
+
+ close(fd);
+
+ /* FIXEME: add real values here!!! */
+ mpio_dentry_put(m, mem,
+ filename, strlen(filename),
+ 2002, 8, 13,
+ 2, 12, fsize, startsector);
+
+ mpio_fat_write(m, mem);
+
+ return fsize-filesize;
+}
+
+int
+mpio_memory_format(mpio_t *m, mpio_mem_t mem,
+ BYTE (*progress_callback)(int, int))
+{
+ int data_offset;
+ mpio_smartmedia_t *sm;
+ DWORD clusters;
+ DWORD i;
+
+ if (mem == MPIO_INTERNAL_MEM) {
+ sm=&m->internal;
+ data_offset=0x00;
+ debug("formatting of internal memory is not yet supported, sorry\n");
+ return 0;
+ }
+
+ if (mem == MPIO_EXTERNAL_MEM) {
+ sm = &m->external;
+ data_offset = sm->dir_offset+DIR_NUM;
+ }
+/* debug("mager: %2x\n", data_offset); */
+
+ clusters = sm->size*128;
+
+/* debug("Clusters: %4x\n", sm->size*128); */
+
+ for (i = data_offset; i < clusters; i += 0x20) {
+ mpio_io_block_delete(m, mem, i, sm->size);
+ if (progress_callback)
+ (*progress_callback)(i, clusters + 1);
+ }
+
+ /* format CIS area */
+ mpio_io_block_delete(m, mem, 0x20, sm->size);
+ mpio_io_sector_write(m, mem, 0x20, sm->size, 0, sm->cis);
+ mpio_io_sector_write(m, mem, 0x21, sm->size, 0, sm->cis);
+
+ mpio_fat_clear(m, mem);
+ mpio_rootdir_clear(m, mem);
+ mpio_fat_write(m, mem);
+
+ if (progress_callback)
+ (*progress_callback)(clusters+1, clusters+1);
+
+ return 0;
+}
+
+
+/* can we share code with mpio_file_get ??? */
+int
+mpio_file_del(mpio_t *m, mpio_mem_t mem, BYTE *filename,
+ BYTE (*progress_callback)(int, int))
+{
+ BYTE *p;
+ BYTE bdummy;
+ WORD wdummy;
+
+ mpio_smartmedia_t *sm;
+ int data_offset;
+ BYTE fname[129];
+ DWORD startsector=0, sector;
+ DWORD realsector=0, oldsector=0;
+ int towrite;
+
+ DWORD filesize, fsize;
+ DWORD fat_and;
+ DWORD fat_end;
+ BYTE abort=0;
+
+ /* please fix me sometime */
+ /* the system entry are kind of special ! */
+ if (strncmp("sysdum", filename, 6)==0)
+ return 0;
+
+ if (mem==MPIO_INTERNAL_MEM) {
+ sm=&m->internal;
+ data_offset=0x00;
+ fat_and=0xffffffff;
+ fat_end=0xffffffff;
+ debug("deleting from files of internal memory"
+ " is not yet supported, sorry\n");
+ return 0;
+ }
+
+ if (mem==MPIO_EXTERNAL_MEM) {
+ sm=&m->external;
+ data_offset=sm->dir_offset+DIR_NUM-(2*BLOCK_SECTORS);
+ /* FAT 16 vs. FAT 12 */
+ if (sm->size==128) {
+ fat_and=0xffff;
+ fat_end=0xfff8;
+ } else {
+ fat_and=0xfff;
+ fat_end=0xff8;
+ }
+ }
+
+
+ p=mpio_directory_open(m, mem);
+ while (p) {
+
+ mpio_dentry_get (m, p,
+ fname, 128,
+ &wdummy, &bdummy, &bdummy,
+ &bdummy, &bdummy, &filesize);
+ fsize=filesize;
+ if ((strcmp(fname,filename)==0) && (strcmp(filename,fname)==0)) {
+ startsector=mpio_dentry_get_startsector(m, p);
+ p=NULL;
+ }
+
+ p=mpio_dentry_next(m, p);
+ }
+
+ /* grr, of curse these are clusters not sectors */
+ /* must code while awake, must ... */
+ if (startsector) {
+ debugn(2, "startsector: %4x\n", startsector);
+ sector = startsector;
+ if (mem == MPIO_INTERNAL_MEM) {
+ realsector = mpio_fat_internal_find_startsector(m, sector);
+ realsector = realsector+ /* chose the right bank */
+ (0x01000000*((realsector / (sm->size / 16 * 1000 / sm->chips)) + 1));
+ sector = realsector;
+ debugn(2, "startsector (real): %4x\n", sector);
+ } else {
+ realsector = sector_hack(sm->size, sector);
+ }
+
+ mpio_io_block_delete(m, mem, (realsector * BLOCK_SECTORS) + data_offset,
+ sm->size);
+
+ if (filesize > BLOCK_SIZE) {
+ towrite = BLOCK_SIZE;
+ } else {
+ towrite = filesize;
+ }
+
+ filesize -= towrite;
+
+ debugn(5, "sector: (%6x) %4x\n",
+ (sector&0xffffff), mpio_fat_entry_read(m, mem, sector&0xffffff));
+
+ while((((mpio_fat_entry_read(m, mem, (sector & 0xffffff)) & fat_and)
+ < fat_end)) && (filesize>0) && (!abort)) {
+ oldsector = sector;
+ sector = mpio_fat_entry_read(m, mem, sector & 0xffffff);
+ mpio_fat_entry_write(m, mem, oldsector, 0);
+ debugn(2,"next sector: %4x\n", sector);
+ if (mem == MPIO_INTERNAL_MEM) {
+ realsector = sector;
+ } else {
+ realsector = sector_hack(sm->size, sector);
+ }
+
+ debugn(2," realsector: %4x\n", realsector);
+
+ mpio_io_block_delete(m, mem,
+ ((realsector * BLOCK_SECTORS) + data_offset),
+ sm->size);
+ if (filesize > BLOCK_SIZE) {
+ towrite = BLOCK_SIZE;
+ } else {
+ towrite = filesize;
+ }
+
+ filesize -= towrite;
+
+ if (progress_callback)
+ abort=(*progress_callback)((fsize-filesize), fsize);
+ }
+ mpio_fat_entry_write(m, mem, sector, 0);
+
+ } else {
+ debug("unable to locate the file: %s\n", filename);
+ }
+
+ /* TODO: delete directory entry */
+ mpio_dentry_delete(m, mem, filename);
+
+ mpio_fat_write(m, mem);
+
+ return (fsize-filesize);
+}
+
+
+
diff --git a/libmpio/mpio.h b/libmpio/mpio.h
new file mode 100644
index 0000000..c373ce2
--- /dev/null
+++ b/libmpio/mpio.h
@@ -0,0 +1,97 @@
+/* -*- linux-c -*- */
+
+/*
+ * $Id: mpio.h,v 1.1 2002/08/28 16:10:51 salmoon Exp $
+ *
+ * Library for USB MPIO-*
+ *
+ * Markus Germeier (mager@tzi.de)
+ *
+ * uses code from mpio_stat.c by
+ * Yuji Touya (salmoon@users.sourceforge.net)
+ *
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+#ifndef _MPIO_H_
+#define _MPIO_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+
+#include "defs.h"
+
+/*
+ *init and shutdown
+ */
+
+mpio_t *mpio_init(void);
+void mpio_close(mpio_t *);
+
+/*
+ * request information
+ */
+
+/* get version */
+void mpio_get_info(mpio_t *, mpio_info_t *);
+/* print version: deprecated */
+//void mpio_print_version(mpio_t *);
+/* retrieves free memory in bytes */
+int mpio_memory_free(mpio_t *, mpio_mem_t, int *free);
+
+/*
+ * directory operations
+ */
+
+/* context, memory bank */
+BYTE* mpio_directory_open(mpio_t *, BYTE);
+/* context, dir context */
+BYTE* mpio_dentry_next(mpio_t *, BYTE *);
+/* context, dir context */
+int mpio_dentry_get(mpio_t *, BYTE *, BYTE *, int,WORD *, BYTE *, BYTE *,
+ BYTE *, BYTE *, DWORD *);
+
+/* context, memory bank, filename, callback */
+int mpio_file_get(mpio_t *, mpio_mem_t, BYTE *, BYTE (*)(int, int));
+
+/* context, memory bank, filename, callback */
+int mpio_file_put(mpio_t *, mpio_mem_t, BYTE *, BYTE (*)(int, int));
+
+/* context, memory bank, filename, callback */
+int mpio_file_del(mpio_t *, mpio_mem_t, BYTE *, BYTE (*)(int, int));
+
+
+/* context, memory bank, callback */
+int mpio_memory_format(mpio_t *, mpio_mem_t, BYTE (*)(int, int));
+
+
+/*
+ * timeline:
+ * ---------
+ * 2004: some functions to change the order of files
+ * 2005: read mp3 tags of the files
+ */
+
+#endif /* _MPIO_H_ */
+
+
diff --git a/libmpio/smartmedia.c b/libmpio/smartmedia.c
new file mode 100644
index 0000000..64e89b1
--- /dev/null
+++ b/libmpio/smartmedia.c
@@ -0,0 +1,153 @@
+/* -*- linux-c -*- */
+
+/*
+ *
+ * $Id: smartmedia.c,v 1.1 2002/08/28 16:10:51 salmoon Exp $
+ *
+ * Library for USB MPIO-*
+ *
+ * Markus Germeier (mager@tzi.de)
+ *
+ *
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "smartmedia.h"
+#include "debug.h"
+
+mpio_disk_phy_t MPIO_DISK_GEO_002={ 125, 4, 8, 4000 };
+mpio_disk_phy_t MPIO_DISK_GEO_004={ 250, 4, 8, 8000 };
+mpio_disk_phy_t MPIO_DISK_GEO_008={ 250, 4, 16, 16000 };
+mpio_disk_phy_t MPIO_DISK_GEO_016={ 500, 4, 16, 32000 };
+mpio_disk_phy_t MPIO_DISK_GEO_032={ 500, 4, 16, 64000 };
+mpio_disk_phy_t MPIO_DISK_GEO_064={ 500, 4, 32, 128000 };
+mpio_disk_phy_t MPIO_DISK_GEO_128={ 500, 4, 32, 256000 };
+
+/* This comes from the Samsung documentation files */
+
+/* a small warning: only use this function (mpio_id2mem) in the very
+ * beginning of MPIO model detection. After that use the values
+ * of size and chips! -mager
+ */
+
+int
+mpio_id2mem(BYTE id)
+{
+ int i=0;
+
+ switch(id)
+ {
+ case 0xea:
+ i=2;
+ break;
+ case 0xe3: /* Samsung */
+ case 0xe5: /* Toshiba */
+ i=4;
+ break;
+ case 0xe6:
+ i=8;
+ break;
+ case 0x73:
+ i=16;
+ break;
+ case 0x75:
+ i=32;
+ break;
+ case 0x76:
+ i=64;
+ break;
+ case 0x79:
+ i=128;
+ break;
+ default:
+ debug("This should never happen (id2mem)!\n");
+ exit (1);
+ }
+ return i;
+}
+
+BYTE *
+mpio_id2manufacturer(BYTE id)
+{
+ BYTE *m;
+ switch(id)
+ {
+ case 0xec:
+ m="Samsung";
+ break;
+ case 0x98:
+ m="Toshiba";
+ break;
+ default:
+ m="unknown";
+ }
+ return m;
+}
+
+BYTE
+mpio_id_valid(BYTE id)
+{
+ switch(id) {
+ case 0xec: /* Samsung */
+ case 0x98: /* Toshiba */
+ return 1;
+ default:
+ ;
+ }
+
+ return 0;
+}
+
+void
+mpio_id2geo(BYTE id, mpio_disk_phy_t *geo)
+{
+ switch(id) {
+ case 0xea:
+ *geo = MPIO_DISK_GEO_002;
+ break;
+ case 0xe3: /* Samsung */
+ case 0xe5: /* Toshiba */
+ *geo = MPIO_DISK_GEO_004;
+ break;
+ case 0xe6:
+ *geo = MPIO_DISK_GEO_008;
+ break;
+ case 0x73:
+ *geo = MPIO_DISK_GEO_016;
+ break;
+ case 0x75:
+ *geo = MPIO_DISK_GEO_032;
+ break;
+ case 0x76:
+ *geo = MPIO_DISK_GEO_064;
+ break;
+ case 0x79:
+ *geo = MPIO_DISK_GEO_128;
+ break;
+ default:
+ debug("This should never happen!\n");
+ exit (1);
+ }
+
+ return;
+}
+
+
+
diff --git a/libmpio/smartmedia.h b/libmpio/smartmedia.h
new file mode 100644
index 0000000..1d01a07
--- /dev/null
+++ b/libmpio/smartmedia.h
@@ -0,0 +1,39 @@
+/* -*- linux-c -*- */
+
+/*
+ *
+ * $Id: smartmedia.h,v 1.1 2002/08/28 16:10:51 salmoon Exp $
+ *
+ * Library for USB MPIO-*
+ *
+ * Markus Germeier (mager@tzi.de)
+ *
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+#ifndef _MPIO_SMARTMEDIA_H_
+#define _MPIO_SMARTMEDIA_H_
+
+#include "defs.h"
+
+/* get our configuration for SmartMedia cards right */
+int mpio_id2mem (BYTE);
+BYTE * mpio_id2manufacturer(BYTE);
+void mpio_id2geo(BYTE, mpio_disk_phy_t *);
+BYTE mpio_id_valid(BYTE);
+
+#endif /* _MPIO_SMARTMEDIA_H_ */