more firmware tweaks
diff --git a/32blit-stm32/CMakeLists.txt b/32blit-stm32/CMakeLists.txt
index be85e23..a654e69 100644
--- a/32blit-stm32/CMakeLists.txt
+++ b/32blit-stm32/CMakeLists.txt
@@ -74,6 +74,8 @@
 	Src/32blit.c
 	Src/CDCLogging.c
 	startup_stm32h750xx.s
+	Src/usb-cdc.cpp
+	Src/core-debug.cpp
 	Src/CDCDataStream.cpp 
 	Src/CDCCommandStream.cpp 
 	Src/CDCCommandHandler.cpp 
diff --git a/32blit-stm32/Inc/32blit.h b/32blit-stm32/Inc/32blit.h
index 902601b..1d8895b 100644
--- a/32blit-stm32/Inc/32blit.h
+++ b/32blit-stm32/Inc/32blit.h
@@ -41,5 +41,6 @@
 void blit_menu_render(uint32_t time);

 void blit_menu();

 

+

 extern void blit_enable_ADC();

 extern void blit_disable_ADC();

diff --git a/32blit-stm32/Inc/core-debug.hpp b/32blit-stm32/Inc/core-debug.hpp
new file mode 100644
index 0000000..11677a9
--- /dev/null
+++ b/32blit-stm32/Inc/core-debug.hpp
@@ -0,0 +1,11 @@
+#pragma once

+

+#include <string>

+#include <vector>

+

+namespace debug {

+

+  extern std::vector<std::string> messages;

+  extern void debug(const char *p);

+  extern void render();

+}
\ No newline at end of file
diff --git a/32blit-stm32/Inc/usb-cdc.hpp b/32blit-stm32/Inc/usb-cdc.hpp
new file mode 100644
index 0000000..b06d625
--- /dev/null
+++ b/32blit-stm32/Inc/usb-cdc.hpp
@@ -0,0 +1,17 @@
+#pragma once

+

+#include <stdint.h>

+#include <map>

+

+namespace cdc {

+

+  typedef bool (*CommandHandler)(char *data, uint32_t length);

+

+  extern std::map<std::string, CommandHandler> handlers;

+

+  void reset_rx_buffer();

+  void data_received(uint32_t length);  

+  void parse_command();

+  void register_command_handler(std::string command, CommandHandler handler);    

+

+}

diff --git a/32blit-stm32/Src/32blit.c b/32blit-stm32/Src/32blit.c
index 28acfa9..7cc2294 100644
--- a/32blit-stm32/Src/32blit.c
+++ b/32blit-stm32/Src/32blit.c
@@ -3,7 +3,7 @@
 

 #include "32blit.h"

 #include "main.h"

-

+#include "core-debug.hpp"

 #include "sound.hpp"

 #include "display.hpp"

 #include "gpio.hpp"

@@ -84,6 +84,7 @@
 void blit_tick() {

   if(display::needs_render) {

     blit::render(blit::now());

+    debug::render();

     display::enable_vblank_interrupt();

   }

 

diff --git a/32blit-stm32/Src/core-debug.cpp b/32blit-stm32/Src/core-debug.cpp
new file mode 100644
index 0000000..7501c92
--- /dev/null
+++ b/32blit-stm32/Src/core-debug.cpp
@@ -0,0 +1,35 @@
+

+#include "core-debug.hpp"

+

+#include "32blit.h"

+

+using namespace blit;

+

+namespace debug {

+

+  std::vector<std::string> messages;

+

+  void debug(const char *p) {

+    std::string message = p;

+

+    if(messages.size() > 20) {

+      messages.erase(messages.begin());

+    }

+

+    messages.push_back(message);

+  }

+

+  void render() {

+    if(messages.size() > 0) {

+      screen.pen = Pen(0, 0, 0, 200);

+      screen.rectangle(Rect(10, 10, 300, 220));

+      screen.pen = Pen(255, 255, 255, 200);

+      uint8_t i = 0;

+      for(auto message : messages) {

+        screen.text(message, minimal_font, Point(12, 12 + i * 10));

+        i++;

+      }

+    }

+  }

+

+}
\ No newline at end of file
diff --git a/32blit-stm32/Src/main.c b/32blit-stm32/Src/main.c
index 21b2d66..1c7c622 100644
--- a/32blit-stm32/Src/main.c
+++ b/32blit-stm32/Src/main.c
@@ -31,6 +31,7 @@
 #include "spi.h"

 #include "tim.h"

 #include "usb_device.h"

+#include "core-debug.hpp"

 

 #include "gpio.hpp"

 #include "display.hpp"

@@ -41,6 +42,7 @@
 #include "32blit.h"

 #include "32blit.hpp"

 #include "graphics/color.hpp"

+#include "usb-cdc.hpp"

 #include "CDCResetHandler.h"

 #include "CDCInfoHandler.h"

 #include "CDCCommandStream.h"

@@ -171,9 +173,13 @@
     blit_tick();

     //HAL_Delay(1000);

     // handle CDC input

-    g_commandStream.Stream();

+    //g_commandStream.Stream();

+    cdc::parse_command();

 

     uint32_t t_elapsed = blit::now() - t_start;

+

+    

+

 //    uint32_t uTimeElapsed = (DWT->CYCCNT - uTimeStart)/uTicksPerUs;

 //    printf("%lu, %lu\n\r", t_elapsed, uTimeElapsed);

     /* USER CODE END WHILE */

diff --git a/32blit-stm32/Src/usb-cdc.cpp b/32blit-stm32/Src/usb-cdc.cpp
new file mode 100644
index 0000000..323b04c
--- /dev/null
+++ b/32blit-stm32/Src/usb-cdc.cpp
@@ -0,0 +1,78 @@
+#include "32blit.h"

+#include "core-debug.hpp"

+#include "usbd_cdc.h"

+#include "usbd_core.h"

+#include "usb-cdc.hpp"

+

+#include <cstring>

+#include <string>

+

+extern USBD_HandleTypeDef hUsbDeviceHS;

+

+namespace cdc {

+

+  std::map<std::string, CommandHandler> handlers;

+

+  struct {

+    char data[64];

+    uint32_t length = 0;

+  } rx_buffer;

+

+  // register a function to handle a new USB serial command

+  void register_command_handler(std::string command, CommandHandler handler) {

+    handlers[command] = handler;

+  }

+

+  void data_received(uint32_t length) {

+    rx_buffer.length = length;

+  }

+

+  // stores the length of the current rx buffer and swaps to the other buffer if

+  // it is free for use returning a pointer to the data member (or null if not free)

+  void reset_rx_buffer() {      

+    rx_buffer.length = 0;

+

+    USBD_CDC_SetRxBuffer(&hUsbDeviceHS, rx_buffer.data);

+    USBD_CDC_ReceivePacket(&hUsbDeviceHS);

+  }

+

+  // check for the incoming command identifier and matches it to the 

+  // appropriate handler, then streams all incoming data directly to

+  // the handler until the command processing is complete

+  void parse_command() {

+    static CommandHandler handler = nullptr;

+    

+    if(rx_buffer.length > 0) {   

+     // debug::debug(std::to_string(rx_buffer.length).c_str());

+      uint32_t s = blit::now();

+      if(!handler) {                

+        // if no handler assigned yet then we're waiting for the command

+        // search through the handler list to see if we have a matching one

+        for(auto c : handlers) {

+          if(strcmp(c.first.c_str(), rx_buffer.data) == 0) {

+            // found the command so assign the handler and call it with the

+            // first packet of data

+            handler = c.second;

+            uint32_t command_length = strlen(rx_buffer.data) + 1;

+

+            bool done = handler(rx_buffer.data + command_length, rx_buffer.length - command_length);

+

+            if(done) {

+              handler = nullptr;

+            }

+          }

+        }

+      } else {

+        // the command handle must return true when it has finished processing

+        // the entire command (even if this is across multiple packets)

+        bool done = handler(rx_buffer.data, rx_buffer.length);

+

+        if(done) {

+          handler = nullptr;

+        }

+      }

+

+      reset_rx_buffer();

+    }    

+  }

+}
\ No newline at end of file
diff --git a/32blit-stm32/Src/usbd_cdc_if.c b/32blit-stm32/Src/usbd_cdc_if.c
index 85aef3b..e7a8189 100644
--- a/32blit-stm32/Src/usbd_cdc_if.c
+++ b/32blit-stm32/Src/usbd_cdc_if.c
@@ -19,6 +19,7 @@
   */

 /* USER CODE END Header */

 #include "CDCCommandStream.h"

+#include "usb-cdc.hpp"

 

 /* Includes ------------------------------------------------------------------*/

 #include "usbd_cdc_if.h"

@@ -160,7 +161,10 @@
   /* USER CODE BEGIN 8 */

   /* Set Application Buffers */

   USBD_CDC_SetTxBuffer(&hUsbDeviceHS, UserTxBufferHS, 0);

-  USBD_CDC_SetRxBuffer(&hUsbDeviceHS, g_commandStream.GetFifoWriteBuffer());

+  //USBD_CDC_SetRxBuffer(&hUsbDeviceHS, g_commandStream.GetFifoWriteBuffer());

+  //USBD_CDC_SetRxBuffer(&hUsbDeviceHS, cdc::swap_buffers(0));

+

+  cdc::reset_rx_buffer();

   return (USBD_OK);

   /* USER CODE END 8 */

 }

@@ -271,14 +275,21 @@
   /* USER CODE BEGIN 11 */

 

 	// release the old write buffer for reading and set length

-	g_commandStream.ReleaseFifoWriteBuffer(*Len);

+//	g_commandStream.ReleaseFifoWriteBuffer(*Len);

+

+

+  cdc::data_received(*Len);

+  

+  //g_commandStream.ReleaseFifoWriteBuffer(*Len);^M

+

+  // now supply a new rx buffer for reading into^M

 

 	// If a new writebuffer is available, set RxBuffer and requext next USB packet

-	if(uint8_t *pBuffer = g_commandStream.GetFifoWriteBuffer())

+/*	if(uint8_t *pBuffer = g_commandStream.GetFifoWriteBuffer())

 	{

 	  USBD_CDC_SetRxBuffer(&hUsbDeviceHS, pBuffer);

 		USBD_CDC_ReceivePacket(&hUsbDeviceHS);

-	}

+	}*/

 

 ////  g_commandStream.AddToFifo(Buf, *Len);

 //	if(*Len)

diff --git a/examples/flash b/examples/flash
index 3d0cd97..aaaeee6 100644
--- a/examples/flash
+++ b/examples/flash
@@ -60,7 +60,7 @@
 
 serial_port.reset_output_buffer()
 
-command = "32BLSAVE{0}\x00{1}\x00".format(file_name, file_size)
+command = "SAVE\x00{0}\x00{1}\x00".format(file_name, file_size)
 serial_port.write(bytes(command, "ascii"))
 
 #serial_port.write(b"32BL")
diff --git a/firmware/flash-loader/flash-loader.cpp b/firmware/flash-loader/flash-loader.cpp
index c3c51df..4903711 100644
--- a/firmware/flash-loader/flash-loader.cpp
+++ b/firmware/flash-loader/flash-loader.cpp
@@ -2,10 +2,14 @@
 #include "graphics/color.hpp"
 #include <cmath>
 #include "quadspi.h"
+#include "usbd_def.h"
+#include "usbd_cdc_if.h"
 #include "CDCCommandStream.h"
+#include "usb-cdc.hpp"
 #include <cstring>
 #include <stdio.h>
 #include <stdlib.h>
+
 using namespace blit;
  
 extern CDCCommandStream g_commandStream;
@@ -17,8 +21,7 @@
 
 FlashLoader flashLoader;
 
-inline bool ends_with(std::string const &value, std::string const &ending)
-{
+inline bool ends_with(std::string const &value, std::string const &ending) {
   if(ending.size() > value.size()) return false;
   return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
 }
@@ -34,7 +37,7 @@
 }
 
 void select_file(const char *filename) {
-  for(auto i = 0; i < files.size(); i++) {
+  for(size_t i = 0; i < files.size(); i++) {
     if(files[i].name == filename) {
       persist.selected_menu_item = i;
     }
@@ -43,18 +46,29 @@
 
 Vec2 list_offset(5.0f, 0.0f);
 
+bool usb_cdc_save_to_sd_card(char *data, uint32_t length);
+
+bool usb_cdc_reset(char *data, uint32_t length) {
+  NVIC_SystemReset();
+  return true;
+}
+
+bool usb_cdc_application_location(char *data, uint32_t length) {
+  while(USBD_BUSY == CDC_Transmit_HS((uint8_t *)"32BL_EXT", 8)) {};
+
+	HAL_Delay(250);
+	return true;
+}
+
 
 void init()
 {
   set_screen_mode(ScreenMode::hires);
   load_file_list();
 
-	// register PROG
-	g_commandStream.AddCommandHandler(CDCCommandHandler::CDCFourCCMake<'P', 'R', 'O', 'G'>::value, &flashLoader);
-	// register SAVE
-	g_commandStream.AddCommandHandler(CDCCommandHandler::CDCFourCCMake<'S', 'A', 'V', 'E'>::value, &flashLoader);
-	// register LS
-	g_commandStream.AddCommandHandler(CDCCommandHandler::CDCFourCCMake<'_', '_', 'L', 'S'>::value, &flashLoader);
+  cdc::register_command_handler("RESET", usb_cdc_reset);
+  cdc::register_command_handler("INFO", usb_cdc_application_location);
+  cdc::register_command_handler("SAVE", usb_cdc_save_to_sd_card);
 }
 
 void background(uint32_t time_ms) {  
@@ -62,22 +76,7 @@
   static Vec3 blobs[blob_count];
 
   static bool first = true;
-/*
-  for(int y = 0; y < 240; y++) {
-    screen.pen = Pen(y, 0, 0);
-    screen.rectangle(Rect(0, y, 80, 1));
-    screen.pen = Pen(0, y, 0);
-    screen.rectangle(Rect(80, y, 80, 1));
-    screen.pen = Pen(0, 0, y);
-    screen.rectangle(Rect(160, y, 80, 1));
-    screen.pen = Pen(y, y, y);
-    screen.rectangle(Rect(240, y, 80, 1));
-  }
 
-  screen.pen = Pen(0, 0, 0);
-  screen.rectangle(Rect(100, 100, 100, 100));
-  return;
-*/  
   for(uint16_t y = 0; y < 420; y++) {
     for(uint16_t x = 0; x < 320; x++) {
       screen.pen = Pen(x >> 1, y, 255 - (x >> 1));
@@ -181,8 +180,6 @@
 }
 
 
-/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
 
 
 bool flash_from_sd_to_qspi_flash(const std::string &filename)
@@ -240,128 +237,9 @@
 }
 
 
-/*
-// RenderSaveFile() Render file save progress %
-void FlashLoader::RenderSaveFile(uint32_t time)
-{
-	screen.pen = Pen(0,0,0);
-	screen.rectangle(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
-	screen.pen = Pen(255, 255, 255);
-	char buffer[128];
-	sprintf(buffer, "Saving %.2u%%", (uint16_t)m_fPercent);
-	screen.text(buffer, minimal_font, ROW(0));
-}
-
-
-// RenderFlashCDC() Render flashing progress %
-void FlashLoader::RenderFlashCDC(uint32_t time)
-{
-	screen.pen = Pen(0,0,0);
-	screen.rectangle(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
-	screen.pen = Pen(255, 255, 255);
-
-	char buffer[128];
-	sprintf(buffer, "Flashing %.2u%%", (uint16_t)m_fPercent);
-	screen.text(buffer, minimal_font, ROW(0));
-}
-*/
-
-/*
-void FlashLoader::Update(uint32_t time)
-{
-	if(m_state == stLS)
-	{
-		load_file_list();
-		m_state = stFlashFile;
-	}
-}
-*/
-
-
-
-//////////////////////////////////////////////////////////////////////
-// Streaming Code
-//  The streaming code works with a simple state machine,
-//  current state is in m_parseState, the states parse index is
-//  in m_uParseState
-//////////////////////////////////////////////////////////////////////
-
-// StreamInit() Initialise state machine
-bool FlashLoader::StreamInit(CDCFourCC uCommand)
-{
-	//printf("streamInit()\n\r");
-	m_fPercent = 0.0f;
-	bool bNeedStream = true;
-	switch(uCommand)
-	{
-		case CDCCommandHandler::CDCFourCCMake<'P', 'R', 'O', 'G'>::value:
-			m_state = stFlashCDC;
-			m_parseState = stFilename;
-			m_uParseIndex = 0;
-		break;
-
-		case CDCCommandHandler::CDCFourCCMake<'S', 'A', 'V', 'E'>::value:
-			m_state = stSaveFile;
-			m_parseState = stFilename;
-			m_uParseIndex = 0;
-		break;
-
-		case CDCCommandHandler::CDCFourCCMake<'_', '_', 'L', 'S'>::value:
-			m_state = stLS;
-			bNeedStream = false;
-		break;
-
-	}
-	return bNeedStream;
-}
-
-
-// FlashData() Flash data to the QSPI flash
-// Note: currently qspi_write_buffer only works for sizes of 256 max
-/*
-bool FlashLoader::FlashData(uint32_t uOffset, uint8_t *pBuffer, uint32_t uLen)
-{
-	bool bResult = false;
-	if(QSPI_OK == qspi_write_buffer(uOffset, pBuffer, uLen))
-	{
-		if(QSPI_OK == qspi_read_buffer(uOffset, m_verifyBuffer, uLen))
-		{
-			// compare buffers
-			bResult = true;
-
-			for(uint32_t uB = 0; bResult && uB < uLen; uB++)
-				bResult = pBuffer[uB] == m_verifyBuffer[uB];
-		}
-	}
-	return bResult;
-}
-*/
-
-// SaveData() Saves date to file on SDCard
-bool FlashLoader::SaveData(uint8_t *pBuffer, uint32_t uLen)
-{
-	UINT uWritten;
-	FRESULT res = f_write(&m_file, pBuffer, uLen, &uWritten);
-
-	return !res && (uWritten == uLen);
-
-}
-
-void copy_from_usb_to_sd_card() {
-
-}
-
-// StreamData() Handle streamed data
-// State machine has three states:
-// stFilename : Parse filename
-// stLength   : Parse length, this is sent as an ascii string
-// stData     : The binary data (.bin file)
-
-
 // when a command is issued (e.g. "PROG" or "SAVE") then this function is called
 // whenever new data is received to allow the firmware to process it.
-CDCCommandHandler::StreamResult FlashLoader::StreamData(CDCDataStream &stream)
-{
+bool usb_cdc_save_to_sd_card(char *data, uint32_t length) {
   enum class StreamState { NONE, NAME, LENGTH, DATA };
   static StreamState state = StreamState::NONE;
 
@@ -382,10 +260,14 @@
 
   // loop through all bytes in the input stream
   uint8_t byte;
-  while(stream.Get(byte)) {        
+  while(length--) {      
+    byte = *data++;
     *p++ = byte;
 
     switch(state) {
+      case StreamState::NONE:
+        break;
+
       // sending filename
       case StreamState::NAME:
         if(byte == '\0') {        
@@ -402,9 +284,8 @@
           bytes_total = atol(length_buffer);
           p = data_buffer;          
 
-          if(f_open(&file, name_buffer, FA_CREATE_ALWAYS | FA_WRITE) != FR_OK) {
-            progress.show(std::to_string(srError), 1);
-            return srError;
+          if(f_open(&file, name_buffer, FA_CREATE_ALWAYS | FA_WRITE) != FR_OK) {            
+            return true;
           }
 
           state = StreamState::DATA;
@@ -421,7 +302,7 @@
         if(bytes_read == bytes_total || p == (data_buffer + sizeof(data_buffer))) {
           UINT bytes_written;
           if(f_write(&file, data_buffer, p - data_buffer, &bytes_written) != FR_OK) {
-            return srError;
+            return true;
           }
           p = data_buffer;
           progress.update(bytes_read);
@@ -434,175 +315,12 @@
           progress.hide();
           load_file_list();
           select_file(name_buffer);
-          return srFinish;
+          return true;
         }
         
         break;
     }
   }
 
-  return srContinue;
-
-  /*
-	CDCCommandHandler::StreamResult result = srContinue;
-	uint8_t byte;
-	while(dataStream.GetStreamLength() && result == srContinue)
-	{
-		switch (m_parseState)
-		{
-			case stFilename:
-				if(m_uParseIndex < MAX_FILENAME)
-				{
-					while(result == srContinue && m_parseState == stFilename && dataStream.Get(byte))
-					{
-						m_sFilename[m_uParseIndex++] = byte;
-						if (byte == 0)
-						{
-							m_parseState = stLength;
-							m_uParseIndex = 0;
-						}
-					}
-				}
-				else
-				{
-					printf("Failed to read filename\n\r");
-					result =srError;
-				}
-			break;
-
-
-			case stLength:
-				if(m_uParseIndex < MAX_FILELEN)
-				{
-					while(result == srContinue && m_parseState == stLength && dataStream.Get(byte))
-					{
-						m_sFilelen[m_uParseIndex++] = byte;
-						if (byte == 0)
-						{
-							m_parseState = stData;
-							m_uParseIndex = 0;
-							char *pEndPtr;
-							m_uFilelen = strtoul(m_sFilelen, &pEndPtr, 10);
-							if(m_uFilelen)
-							{
-								// init file or flash
-								switch(m_state)
-								{
-									case stSaveFile:
-									{
-										FRESULT res = f_open(&m_file, m_sFilename, FA_CREATE_ALWAYS | FA_WRITE);
-										if(res)
-										{
-											printf("Failed to create file (%s)\n\r", m_sFilename);
-											result = srError;
-										}
-									}
-									break;
-
-									case stFlashCDC:
-										qspi_chip_erase();
-									break;
-
-									default:
-									break;
-								}
-							}
-							else
-							{
-								printf("Failed to parse filelen\n\r");
-								result =srError;
-							}
-						}
-					}
-				}
-				else
-				{
-					printf("Failed to read filelen\n\r");
-					result =srError;
-				}
-			break;
-
-			case stData:
-					while((result == srContinue) && (m_parseState == stData) && (m_uParseIndex <= m_uFilelen) && dataStream.Get(byte))
-					{
-						uint32_t uByteOffset = m_uParseIndex % PAGE_SIZE;
-						m_buffer[uByteOffset] = byte;
-
-						// check buffer needs writing
-						volatile uint32_t uWriteLen = 0;
-						bool bEOS = false;
-						if (m_uParseIndex == m_uFilelen-1)
-						{
-							uWriteLen = uByteOffset+1;
-							bEOS = true;
-						}
-						else
-							if(uByteOffset == PAGE_SIZE-1)
-								uWriteLen = PAGE_SIZE;
-
-						if(uWriteLen)
-						{
-							switch(m_state)
-							{
-								case stSaveFile:
-									// save data
-									if(!SaveData(m_buffer, uWriteLen))
-									{
-										printf("Failed to save to SDCard\n\r");
-										result = srError;
-									}
-
-									// end of stream close up
-									if(bEOS)
-									{
-										f_close(&m_file);
-										m_bFsInit = false;
-										m_state = stFlashFile;
-										if(result != srError)
-											result = srFinish;
-									}
-								break;
-
-								case stFlashCDC:
-								{
-									// save data
-									volatile uint32_t uPage = (m_uParseIndex / PAGE_SIZE);
-									if(!FlashData(uPage*PAGE_SIZE, m_buffer, uWriteLen))
-									{
-										printf("Failed to write to flash\n\r");
-										result = srError;
-									}
-
-									// end of stream close up
-									if(bEOS)
-									{
-										if(result != srError)
-										{
-											result = srFinish;
-											m_state = stSwitch;
-										}
-										else
-											m_state = stFlashFile;
-									}
-								}
-								break;
-
-								default:
-								break;
-							}
-						}
-
-						m_uParseIndex++;
-						m_uBytesHandled = m_uParseIndex;
-						m_fPercent = ((float)m_uParseIndex/(float)m_uFilelen)* 100.0f;
-					}
-			break;
-		}
-	}
-
-	if(result==srError)
-		m_state = stFlashFile;*/
-
-	//return result;
+  return false;
 }
-
diff --git a/firmware/flash-loader/flash-loader.hpp b/firmware/flash-loader/flash-loader.hpp
index dbde002..c6cc00b 100644
--- a/firmware/flash-loader/flash-loader.hpp
+++ b/firmware/flash-loader/flash-loader.hpp
@@ -64,8 +64,10 @@
 class FlashLoader : public CDCCommandHandler
 {
 public:
-	virtual StreamResult StreamData(CDCDataStream &dataStream);
-	virtual bool StreamInit(CDCFourCC uCommand);
+	virtual StreamResult StreamData(CDCDataStream &dataStream)  {
+return srContinue;
+ }
+	virtual bool StreamInit(CDCFourCC uCommand) {}
 
 
 	void Init(void);