#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-8 | 0
|