Source file: /~heha/basteln/PC/Programmiergeräte/Wild GIF12/mtp2.zip/MTP.cpp

#include "MTP.h"
#include "usb.h"
#include <string.h>
#include <avr/eeprom.h>
#include <avr/pgmspace.h>

struct MTPHeader {
 union{
  byte lenL;  // 0
  word lenW;
  uint32_t lenD;
  byte lenB[4];
 };
 byte typeL,typeH; // 4
 byte opL,opH;   // 6
 uint32_t transid; // 8
};

static struct{
 MTPHeader h;
 uint32_t params[3];    // 12
}bulkcs;

namespace MTP {

static void outc(const byte*p,byte len) {
 usbSend(p,len);
}
static void out1(byte b) {
 outc(&b,1);
}
static void out2(word w) {
 out1(w);
 out1(w>>8);
}
static void out4(word w) {
 out2(w);
 out2(0);
}
static void out0(byte len) {
 usbSend(0,len);
}
static void out8(word w) {
 out2(w);
 out0(6);
}
static void outHeader(word len) {
 out4(len+12);
 out2(2);		// type
 outc(&bulkcs.h.opL,6);	// operation + transaction ID
}
static void outFlush() {
 usbFlush();
}

static void outDescriptor() {
 outHeader(35);
 out0(35);		// lot of garbage
 outFlush();
}

static void outStorageIDs() {
 outHeader(8);
 out4(1); // 1 entry
 out4(1); // 1 storage
 outFlush();
}

static void outStorageInfo() {
 outHeader(2+2+2+8+8+4+1+1);
 out2(1);	// storage type (fixed ROM)
 out2(1);	// filesystem type (generic flat)
 out2(1);	// access capability (read-only)
 out8(1024);	// max capacity (bytes)
 out8(0);	// free space (bytes)
 out4(0);	// free space (objects)
 out0(2);	// 2 identifier, jetzt kommt "Festspeicher"
 outFlush();
}

static void outObjectHandles() {
 outHeader(8);
 out4(1);
 out4(1);
 outFlush();
}

static void outObjectInfo(byte) {
 static const PROGMEM char name[]="eeprom";
 outHeader(4+4+4+40+1+(sizeof name<<1)+3);
 out4(1); // Logical Storage ID
 out4(0x3000);	// undefiniert, Text
 out4(1024); // size
 out0(40); // Info für Bilder
 out1(sizeof name);
 for (byte i=0;i<sizeof name;i++) out2(pgm_read_byte(name+i));
 out0(3);  // date captured, date modified, keywords: all undefined
 outFlush();
}

static void GetObject(byte) {
 outHeader(1024);
 for (word i=0; i<1024; i++) out1(eeprom_read_byte((byte*)i));
 outFlush();	// Short-Packet
}

static void handleCommand() {
 byte p1 = 0;
 byte retcode = 1;  // Ok
 if (bulkcs.h.opH!=0x10) retcode=5;
 else switch (bulkcs.h.opL) {
  case 1: outDescriptor();		break;	// GetDescription
  case 2: break;	// OpenSession
  case 3: break;	// CloseSession
  case 4: outStorageIDs();		break;	// GetStorageIDs
  case 5: outStorageInfo();		break;	// GetStorageInfo
  case 6: p1 = 1;			break;	// GetNumObjects
  case 7: outObjectHandles();		break;	// GetObjectHandles
  case 8: outObjectInfo(bulkcs.params[0]);break;// GetObjectInfo
  case 9: GetObject(bulkcs.params[0]);	break;	// GetObject
  default:
  retcode = 5;  // operation not supported
 }
 bulkcs.h.lenL = 16;	// Standard: Rückgabe 1 Parameter 
 bulkcs.params[0] = p1;
 bulkcs.h.typeL = 3;	// Antwort
 bulkcs.h.opL = retcode;
 bulkcs.h.opH = 0x20;
 usbSend(&bulkcs,bulkcs.h.lenL);
 usbFlush();
}

// Einzige exportierte Funktion
void pollUSB() {
 if (usbRecvPoll()) {
  PORTD&=~0x20;	// TX
  usbRecv(&bulkcs,8);
  if (bulkcs.h.typeL==1	// "command", alles andere: STALL (Protokollfehler)
//  && bulkcs.h.typeH==0x10
  && bulkcs.h.lenD<=sizeof bulkcs
  && bulkcs.h.lenL>=12) {
   usbRecv(&bulkcs.h.transid,bulkcs.h.lenL-8);	// Rest des Kommandos abholen
   handleCommand();
  }else{
//   eelog(&bulkcs,8);	// Murks!
   UEINTX=0;		// aufs nächste ganze USB-Paket synchronisieren
  }
  PORTD|= 0x20;
 }
}

}/*namespace*/
Detected encoding: UTF-80