/* "avrstick USBdisk example" */ /* */ /* This demo implements an USB */ /* virtual COM port and an USB */ /* MassStorage device. */ /* (without virtual filesystem) */ #include <avr/io.h> #include <avr/wdt.h> #include <avr/power.h> #include <avr/interrupt.h> #include <avr/pgmspace.h> #include <string.h> #include <stdio.h> #include <stdbool.h> #include <stdint.h> #if (F_CPU != 32000000) #warning clock should better be 32MHz - USB needs it #endif /* initialize all the USB (terminal + disk) * - also switches to 32MHz * - enables medium priority interrupts * - also enables global interrupts */ extern void USBInit(void); /* process the USB */ extern void USBPoll(void); /* the I/O steam of the USB terminal */ extern FILE *USBtty0; #define USBdisk_sectorSize 512 /* Global number of 512 byte sectors the MassStorage * disk should identify itself with * Best initialized before "USBInit()". */ extern uint32_t USBdisk_sectorCount; /* Global information about the type of the media * Best initialized before "USBInit()". */ extern bool USBdisk_readOnly; static volatile unsigned long abstinent_reads = 0; static volatile unsigned long abstinent_writes = 0; int main(void) { USBdisk_sectorCount = 256; /* = 128 KiB */ USBdisk_readOnly = true; /* forbid write */ /* Init the USB (and clock + interrupts) */ USBInit(); for (;;) { /* Must throw away unused bytes from the host */ int c = fgetc(USBtty0); /* simple demo: implement an echo */ if (!(c<0)) { fprintf_P(USBtty0, PSTR("%3lu sectors read, %3lu writes ignored, key pressed: %c\r\n"), abstinent_reads, abstinent_writes, c); abstinent_reads=0; abstinent_writes=0; } USBPoll(); } } /* "USBdisk_CALLBACK_readSector" is called internally by the USB/SCSI stack. * Its purpose is to: * (1) read a sector "in_sectorNumber" (starting at 0), * (2) put the secotors content into "out_sectordata" * (3) return the number of bytes read - usually 512 (USBdisk_sectorSize). */ int16_t USBdisk_CALLBACK_readSector(uint8_t out_sectordata[USBdisk_sectorSize], const uint32_t in_sectorNumber) { /* increase the read counter */ abstinent_reads++; /* "fill" the sector with some data, make it depend on "in_sectorNumber" to see the different sectors */ memset(&out_sectordata[0], ~(in_sectorNumber & 0xff), USBdisk_sectorSize); return USBdisk_sectorSize; } /* "USBdisk_CALLBACK_writeSector" is called internally by the USB/SCSI stack. * Its purpose is to: * (1) put the content "in_sectordata" on the media at sector "in_sectorNumber" * (2) return the number of bytes written - usually 512 (USBdisk_sectorSize). */ int16_t USBdisk_CALLBACK_writeSector(uint8_t in_sectordata[USBdisk_sectorSize], const uint32_t in_sectorNumber) { /* increase the write counter */ abstinent_writes++; /* at the moment simply ignore the write - in case of readOnly it shouldn't be called anyway */ return USBdisk_sectorSize; }