Index: EPRoxygen/27c020.cpp
===================================================================
--- EPRoxygen/27c020.cpp	(revision 16cf6ff42d66a47a7a2d124a848f884c47a59690)
+++ EPRoxygen/27c020.cpp	(revision 16cf6ff42d66a47a7a2d124a848f884c47a59690)
@@ -0,0 +1,55 @@
+#include "27c020.h"
+
+#include <stdio.h>
+#include <unistd.h>
+
+
+x27C020::x27C020()
+	: Device()
+{
+}
+
+void x27C020::power()
+{
+	Device::write(CTRL, 0b10011111 | CTRLmask);
+	Device::write(VOLT, 0b11001000 | VOLTmask);
+	outb(port + 2, NONE);
+}
+
+void x27C020::read(const char* filename)
+{
+	for (int address = 0; address < 256*1024; address++)
+	{
+		Device::write(VOLT, DOE | VOLTmask);
+		Device::write(CTRL, CE | OE | WE | A17 | CTRLmask);
+			usleep(1000);
+		
+		Device::write(ADR0, address);
+			usleep(1000);
+		Device::write(ADR1, address >> 8);
+			usleep(1000);
+		// TODO A16, A17
+		Device::write(CTRL, WE | A17 | CTRLmask);
+			usleep(1000);
+		uint8_t val = Device::read();
+		Device::write(CTRL, CE | OE | WE | A17 | CTRLmask);
+
+		// TODO write to file, or stdout if file is null
+		putc(val, stdout);
+		// TODO flush every 512 bytes or so
+		fflush(stdout);
+	}
+}
+
+void x27C020::write(const char* filename)
+{
+	// TODO support it !
+	puts("Writing not supported");
+}
+
+void x27C020::erase(void)
+{
+	// TODO return error
+	puts("Erasing not supported");
+}
+
Index: EPRoxygen/27c020.h
===================================================================
--- EPRoxygen/27c020.h	(revision 16cf6ff42d66a47a7a2d124a848f884c47a59690)
+++ EPRoxygen/27c020.h	(revision 16cf6ff42d66a47a7a2d124a848f884c47a59690)
@@ -0,0 +1,18 @@
+#include "device.h"
+
+class x27C020: public Device
+{
+	public:
+		x27C020();
+
+		void power(void);
+		void shutdown(void);
+		void read(const char* filename);
+		void write(const char* filename);
+		void erase(void);
+	private:
+
+		static const uint8_t CTRLmask = 0b01100000;
+		static const uint8_t VOLTmask = 0b10110011;
+};
+
Index: EPRoxygen/Makefile
===================================================================
--- EPRoxygen/Makefile	(revision a6ae6ac6192a2c27497f1540f985610601159c41)
+++ EPRoxygen/Makefile	(revision 16cf6ff42d66a47a7a2d124a848f884c47a59690)
@@ -1,3 +1,3 @@
-eproxygen: main.o at29c040.o
+eproxygen: main.o at29c040.o 27c020.o
 	g++ -Wall -g -O3 -fno-rtti -fno-exceptions $^ -o $@
 
Index: EPRoxygen/device.h
===================================================================
--- EPRoxygen/device.h	(revision a6ae6ac6192a2c27497f1540f985610601159c41)
+++ EPRoxygen/device.h	(revision 16cf6ff42d66a47a7a2d124a848f884c47a59690)
@@ -20,4 +20,8 @@
 		{};
 
+		virtual ~Device() {
+			shutdown();
+		};
+
 		void shutdown();
 		virtual void power() = 0;
@@ -38,7 +42,4 @@
 			return 0;
 		}
-
-		virtual ~Device() {};
-	
 	protected:
 		typedef enum {
@@ -131,6 +132,4 @@
 			usleep(1000);
 			byte |= inb(port + 1) >> 4;
-printf("R %X", byte ^ 0x88);
-getchar();
 			outb(port+2, NYBLE ^ 4); 
 			usleep(1000);
Index: EPRoxygen/main.cpp
===================================================================
--- EPRoxygen/main.cpp	(revision a6ae6ac6192a2c27497f1540f985610601159c41)
+++ EPRoxygen/main.cpp	(revision 16cf6ff42d66a47a7a2d124a848f884c47a59690)
@@ -10,4 +10,5 @@
 
 #include "device.h"
+#include "27c020.h"
 #include "at29c040.h"
 
@@ -22,5 +23,5 @@
 	int error = 0;
 
-	puts("EPRoxygen - UNIX driver for SEEIT EPR-02 ROM programmer\n"
+	fprintf(stderr, "EPRoxygen - UNIX driver for SEEIT EPR-02 ROM programmer\n"
 		"Copyright 2012, Adrien Destugues <pulkomandy@pulkomandy.tk>\n"
 		"Distributed under the terms of the MIT licence\n"
@@ -48,11 +49,15 @@
 			case 'd':
 				// TODO Set device
-				if (strcmp(optarg, "AT29C040"))
+				if (strcmp(optarg, "AT29C040") == 0)
 				{
+					device = new AT29C040();
+				} else if(strcmp(optarg, "27C020") == 0)
+				{
+					device = new x27C020();
+				} else {
 					fprintf(stderr,"Unknown device (only AT29C040 is supported)\n");
 					error = -3;
 					goto abort;
 				}
-				device = new AT29C040();
 				break;
 			case 'r':
@@ -71,4 +76,11 @@
 				opcode = c;
 		}
+	}
+
+	if (optind < argc)
+	{
+		fprintf(stderr, "Error parsing the command line before \"%s\"\n", argv[optind]);
+		error = -7;
+		goto abort;
 	}
 
@@ -94,6 +106,5 @@
 	}
 
-	// TODO Ask user to put ROM on socket
-	puts("Now insert chip into socket, then press any key...");
+	fprintf(stderr,"Now insert chip into socket, then press any key...\n");
 	getchar();
 
@@ -117,5 +128,5 @@
 
 abort:
-	device->shutdown();
+	// TODO in case ioperm failed, delete will try to shutdown() and give a bus error...
 	delete device;
 
