From 0d8d92cf4631f4a0a88fe04817d375f9e73408e4 Mon Sep 17 00:00:00 2001 From: salmoon Date: Wed, 28 Aug 2002 16:10:44 +0000 Subject: Initial revision --- libmpio/Makefile.am | 24 ++ libmpio/Makefile.in | 372 +++++++++++++++++++++++++ libmpio/debug.c | 293 ++++++++++++++++++++ libmpio/debug.h | 102 +++++++ libmpio/defs.h | 192 +++++++++++++ libmpio/directory.c | 509 ++++++++++++++++++++++++++++++++++ libmpio/directory.h | 50 ++++ libmpio/ecc.c | 203 ++++++++++++++ libmpio/ecc.h | 36 +++ libmpio/fat.c | 414 +++++++++++++++++++++++++++ libmpio/fat.h | 47 ++++ libmpio/io.c | 618 +++++++++++++++++++++++++++++++++++++++++ libmpio/io.h | 58 ++++ libmpio/mpio.c | 769 +++++++++++++++++++++++++++++++++++++++++++++++++++ libmpio/mpio.h | 97 +++++++ libmpio/smartmedia.c | 153 ++++++++++ libmpio/smartmedia.h | 39 +++ 17 files changed, 3976 insertions(+) create mode 100644 libmpio/Makefile.am create mode 100644 libmpio/Makefile.in create mode 100644 libmpio/debug.c create mode 100644 libmpio/debug.h create mode 100644 libmpio/defs.h create mode 100644 libmpio/directory.c create mode 100644 libmpio/directory.h create mode 100644 libmpio/ecc.c create mode 100644 libmpio/ecc.h create mode 100644 libmpio/fat.c create mode 100644 libmpio/fat.h create mode 100644 libmpio/io.c create mode 100644 libmpio/io.h create mode 100644 libmpio/mpio.c create mode 100644 libmpio/mpio.h create mode 100644 libmpio/smartmedia.c create mode 100644 libmpio/smartmedia.h (limited to 'libmpio') 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 + * Andreas Büsching + * + * $Id: debug.c,v 1.1 2002/08/28 16:10:51 salmoon Exp $ + */ + +#include "debug.h" + +#include +#include +#include +#include +#include + +#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 + * Andreas Büsching + * + * $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 + +#ifdef sun +#include +#else +#include +#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 +#include + +#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 +#include + +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 +#include +#include +#include + +#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 +#include +#include +#include + +#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 +#include +#include +#include +#include +#include +#include +#include + +#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 +#include + +#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_ */ -- cgit v1.2.3