Index: V-USB_Dev/firmwares/herePic/driver/Makefile
===================================================================
--- V-USB_Dev/firmwares/herePic/driver/Makefile	(revision f0689d3a1e1bf30ce45d26144d3c39df6aef5f8d)
+++ V-USB_Dev/firmwares/herePic/driver/Makefile	(revision 8659a17d82009218714a4bff86869e6804388262)
@@ -1,2 +1,2 @@
-herepic: herepic.cpp
-	g++ -o $@ $^ -Os -Wall -ldevice
+herepic: herepic.cpp icsp.h ../shared.h
+	g++ -o $@ $< -Os -Wall -ldevice
Index: V-USB_Dev/firmwares/herePic/driver/herepic.cpp
===================================================================
--- V-USB_Dev/firmwares/herePic/driver/herepic.cpp	(revision f0689d3a1e1bf30ce45d26144d3c39df6aef5f8d)
+++ V-USB_Dev/firmwares/herePic/driver/herepic.cpp	(revision 8659a17d82009218714a4bff86869e6804388262)
@@ -15,9 +15,9 @@
 #include <USBKit.h>
 
+#include "../shared.h"
+#include "icsp.h"
 
-// We need a subclass of USBRoster to enumerate devices. The Deviceadded hook
-// will be called for all plugged devices. If we don't find the correct one,
-// it will also be called later, as devices are plugged. So we can wait for the
-// right device to come in !
+
+// We need a subclass of USBRoster to enumerate devices.
 class MyUSBRoster: public BUSBRoster {
 	public:
@@ -35,4 +35,8 @@
 		}
 
+		/* The DeviceAdded hook will be called for all plugged devices.
+		If we don't find the correct one, the method will also be called later,
+		as devices are plugged. So we can wait for the right device to come in!
+		*/
 		status_t DeviceAdded(BUSBDevice* device)
 		{
@@ -41,7 +45,6 @@
 				&& strcmp(device->ProductString(), "HerePic") == 0)
 			{
-				std::cout << "Programmer found !" << std::endl;
-				// TODO send message to main app to tell it we're ready to go.
 				fDevice = device;
+				// Notify main thread it's ok to continue
 				sem_post(&fDeviceLock);
 			}
@@ -121,11 +124,13 @@
 	} while(nextopt != -1);
 
-	if (action <= 0)
+	// If we found no valid action request, print usage and exit
+	if (action <= 0 || action == 'h')
 	{
 		usage(argv[0]);
-		exit(action);
+		// Exit code is EXIT_SUCCESS if we reach this by -h option. Otherwise
+		// the arguments are incorrect
+		exit(action < 0 ? action : 0);
 	}
 
-	// TODO take action depending on command request in CLI
 	// TODO handle the boring usb stuff... (might be nice to abstract it so we
 	// can use both libusb and haiku usb kit)
@@ -140,19 +145,35 @@
 
 	int deviceAvailable;
+	// TODO we rely on the initial device scan being done when we get here. Is
+	// that always true ? If not, we may print this message in cases where it
+	// is not needed.
 	sem_getvalue(&deviceLock, &deviceAvailable);
 	if(deviceAvailable == 0)
 	{
-		std::cout << "Programmer not connected. Waiting for it..." << std::endl;
+		std::cout << "Programmer hardware not detected. Please connect it now..." << std::endl;
 	}
 
+	// Wait for the device
 	sem_wait(&deviceLock);
 
-	// Here, perform the programming cycle !
+	ICSP icsp(*theDevice);
+
+	// take action depending on command request in CLI
 	switch(action)
 	{
 		case 'r':
+			// read the chip
+			icsp.Read(filename);
+			break;
 		case 'w':
+			icsp.Write(filename);
+			// Here, perform the programming cycle !
+			break;
 		case 'e':
-			;
+			icsp.Erase();
+			// erase the chip
+			break;
 	}
+
+	exit(0);
 }
Index: V-USB_Dev/firmwares/herePic/driver/icsp.h
===================================================================
--- V-USB_Dev/firmwares/herePic/driver/icsp.h	(revision 8659a17d82009218714a4bff86869e6804388262)
+++ V-USB_Dev/firmwares/herePic/driver/icsp.h	(revision 8659a17d82009218714a4bff86869e6804388262)
@@ -0,0 +1,75 @@
+/* HEREPIC - AVR-based ICSP programmer for microchip PIC16F6xx and 16F8xx devices
+ * Copyright 2012, Adrien Destugues <pulkomandy@pulkomandy.tk>
+ *
+ * This file is distributed under the terms of the MIT licence.
+ */
+
+#include <string.h>
+
+class ICSP
+{
+	public:
+		ICSP(BUSBDevice& device)
+			: fDevice(device)
+		{
+		}
+
+		uint16_t Execute(ICSPCommands command, uint16_t param = 0)
+		{
+			// TODO send the command to the device
+			uint16 length;
+			uint8 reqType = USB_REQTYPE_VENDOR;
+			if(command == ReadCodeWord || command == ReadDataWord)
+			{
+				length = 2;
+				reqType |= USB_REQTYPE_DEVICE_OUT;
+			} else {
+				length = 0;
+				reqType |= USB_REQTYPE_DEVICE_IN;
+			}
+
+			ssize_t result = fDevice.ControlTransfer(reqType, command, param, 0,
+				length, &param);
+			if (result == length) {
+				// We transferred as much bytes as we wanted.
+				// Everyone is happy !
+				return param;
+			} else {
+				// Not enough bytes transferred, or the result is an error code
+				std::cerr << "USB communication error " << result
+					<< "(" << strerror(result) << ")" << std::endl;;
+				return result;
+			}
+		}
+
+		void Write(const char* filename)
+		{
+			std::cerr << "Sorry, this doesn't work yet !" << std::endl;
+			exit(-4);
+		}
+
+		void Read(const char* filename)
+		{
+			std::cerr << "Sorry, this doesn't work yet !" << std::endl;
+			exit(-4);
+		}
+
+		void Erase()
+		{
+			// Let's test some stuff...
+			std::cout << std::hex;
+
+			Execute(LoadConfigWord); // sets PC to 0x2000 to read CFG words
+			for(int i = 8; --i >= 0;)
+			{
+				uint16_t word = Execute(ReadCodeWord);
+				Execute(NextAddress);
+
+				std::cout << word << " ";
+			}
+			std::cout << std::endl;
+		}
+
+	private:
+		BUSBDevice& fDevice;
+};
Index: V-USB_Dev/firmwares/herePic/main.c
===================================================================
--- V-USB_Dev/firmwares/herePic/main.c	(revision f0689d3a1e1bf30ce45d26144d3c39df6aef5f8d)
+++ V-USB_Dev/firmwares/herePic/main.c	(revision 8659a17d82009218714a4bff86869e6804388262)
@@ -1,7 +1,2 @@
-/* HEREPIC - AVR-based ICSP programmer for microchip PIC16F6xx and 16F8xx devices
- * Copyright 2012, Adrien Destugues <pulkomandy@pulkomandy.tk>
- *
- * This file is distributed under the terms of the MIT licence.
- */
 
 /* This project is targetted at the VUSBDev hacking board. */
@@ -17,4 +12,5 @@
 
 #include "usbdrv/usbdrv.h"
+#include "shared.h"
 
 // IO pins:
@@ -39,32 +35,4 @@
 // Timers may make it easier to do that in parallel with the USB handling, since
 // timings are in the nanosecond range.
-
-
-// ICSP commands are 6-bit wide, for most of them (but not all) the 2 MSb are
-// ignored.
-// We also use these as USB commands for now, but we may do otherwise, since
-// transferring only 14 data bytes in an USB frame is quite a bit of waste.
-// We need some custom commands on USB side as well, to reset the PIC and such
-// things.
-typedef enum
-{
-	// HOST to DEVICE
-	LoadConfigWord 		=   0b0000,
-	LoadCodeWord 		=   0b0010,
-	LoadDataWord 		=   0b0011,
-
-	// Configuration
-	NextAddress			=   0b0110,
-	BeginEraseProgram 	= 0b001000,
-	BeginProgramOnly 	= 0b011000,
-	BulkEraseCode		=   0b1001,
-	BulkEraseData		=   0b1011,
-	BulkEraseConfig1	= 0b000001,
-	BulkEraseConfig2	= 0b000111,
-
-	// DEVICE to HOST
-	ReadCodeWord 		=   0b0100,
-	ReadDataWord		=   0b0101,
-} ICSPCommands;
 
 
Index: V-USB_Dev/firmwares/herePic/shared.h
===================================================================
--- V-USB_Dev/firmwares/herePic/shared.h	(revision 8659a17d82009218714a4bff86869e6804388262)
+++ V-USB_Dev/firmwares/herePic/shared.h	(revision 8659a17d82009218714a4bff86869e6804388262)
@@ -0,0 +1,32 @@
+/* HEREPIC - AVR-based ICSP programmer for microchip PIC16F6xx and 16F8xx devices
+ * Copyright 2012, Adrien Destugues <pulkomandy@pulkomandy.tk>
+ *
+ * This file is distributed under the terms of the MIT licence.
+ */
+
+// ICSP commands are 6-bit wide, for most of them (but not all) the 2 MSb are
+// ignored.
+// We also use these as USB commands for now, but we may do otherwise, since
+// transferring only 14 data bytes in an USB frame is quite a bit of waste.
+// We need some custom commands on USB side as well, to reset the PIC, blink
+// leds, and such things.
+typedef enum
+{
+	// HOST to DEVICE
+	LoadConfigWord 		=  0x0,
+	LoadCodeWord 		=  0x2,
+	LoadDataWord 		=  0x3,
+
+	// Configuration
+	NextAddress			=  0x6,
+	BeginEraseProgram 	= 0x08,
+	BeginProgramOnly 	= 0x18,
+	BulkEraseCode		=  0x9,
+	BulkEraseData		=  0xB,
+	BulkEraseConfig1	= 0x01,
+	BulkEraseConfig2	= 0x07,
+
+	// DEVICE to HOST
+	ReadCodeWord 		=  0x4,
+	ReadDataWord		=  0x5,
+} ICSPCommands;
