Revision 0:1802fb31b938, committed 2010-01-21
- Comitter:
- iva2k
- Date:
- Thu Jan 21 01:15:42 2010 +0000
- Commit message:
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Fat/usbhost_fat.c Thu Jan 21 01:15:42 2010 +0000
@@ -0,0 +1,1043 @@
+/*
+**************************************************************************************************************
+* NXP USB Host Stack
+*
+* (c) Copyright 2008, NXP SemiConductors
+* (c) Copyright 2008, OnChip Technologies LLC
+* All Rights Reserved
+*
+* www.nxp.com
+* www.onchiptech.com
+*
+* File : usbhost_fat.c
+* Programmer(s) : Ravikanth.P
+* Version :
+*
+**************************************************************************************************************
+*/
+
+/*
+**************************************************************************************************************
+* INCLUDE HEADER FILES
+**************************************************************************************************************
+*/
+
+#include "usbhost_fat.h"
+
+/*
+**************************************************************************************************************
+* GLOBAL VARIABLES
+**************************************************************************************************************
+*/
+
+#define MAX_FILE_DESCRIPTORS 2
+static BOOT_SEC FAT_BootSec;
+static FILE_ENTRY FAT_FileEntry[MAX_FILE_DESCRIPTORS];
+
+/*
+**************************************************************************************************************
+* INITIALIZE THE FILE SYSTEM
+*
+* Description: This function initializes the FAT16 file system
+*
+* Arguments : None
+*
+* Returns : OK if Success
+* ERR_INVALID_BOOTSIG if Failed
+*
+**************************************************************************************************************
+*/
+
+USB_INT32S FAT_Init (void)
+{
+ USB_INT16U boot_sig;
+ USB_INT32S rc, i;
+ FILE_ENTRY *entry;
+
+ for (i=0;i<MAX_FILE_DESCRIPTORS;i++) {
+ entry = &FAT_FileEntry[i];
+ entry->CurrClus = 0;
+ entry->CurrClusOffset = 0;
+ entry->FileSize = 0;
+ entry->EntrySec = 0;
+ entry->EntrySecOffset = 0;
+ entry->FileStatus = 0;
+ }
+
+ MS_BulkRecv(0, 1, FATBuffer);
+ boot_sig = ReadLE16U(&FATBuffer[510]);
+ if (boot_sig != 0xAA55) {
+ rc = ERR_INVALID_BOOT_SIG;
+ } else {
+ if (FATBuffer[0] != 0xEB && FATBuffer[0] != 0xE9) {
+ FAT_BootSec.BootSecOffset = ReadLE32U(&FATBuffer[454]);
+ MS_BulkRecv(FAT_BootSec.BootSecOffset, 1, FATBuffer);
+ }
+ FAT_BootSec.BytsPerSec = ReadLE16U(&FATBuffer[11]); /* Bytes per cluster */
+ FAT_BootSec.SecPerClus = FATBuffer[13]; /* Sectors per cluster */
+ /* Reserved sector count */
+ FAT_BootSec.RsvdSecCnt = ReadLE16U(&FATBuffer[14]) + FAT_BootSec.BootSecOffset;
+ FAT_BootSec.NumFATs = FATBuffer[16]; /* Number of FAT copies */
+ FAT_BootSec.RootEntCnt = ReadLE16U(&FATBuffer[17]); /* Root entry count */
+ FAT_BootSec.TotSec16 = ReadLE16U(&FATBuffer[19]); /* Total FAT16 sectors */
+ FAT_BootSec.TotSec32 = ReadLE32U(&FATBuffer[32]); /* Total FAT32 sectors */
+ FAT_BootSec.FATSz16 = ReadLE16U(&FATBuffer[22]); /* Size of the FAT table */
+ /* Bytes per cluster */
+ FAT_BootSec.BytsPerClus = (FAT_BootSec.BytsPerSec * FAT_BootSec.SecPerClus);
+ /* Root directory starting sector */
+ FAT_BootSec.RootDirStartSec = FAT_BootSec.RsvdSecCnt + (FAT_BootSec.FATSz16 * FAT_BootSec.NumFATs);
+ /* Sectors occupied by root directory */
+ FAT_BootSec.RootDirSec = ((FAT_BootSec.RootEntCnt * 32) + (FAT_BootSec.BytsPerSec - 1)) /
+ (FAT_BootSec.BytsPerSec);
+ /* First data sector */
+ FAT_BootSec.FirstDataSec = FAT_BootSec.RootDirStartSec + FAT_BootSec.RootDirSec;
+ FAT_BootSec.FATType = FAT_GetFATType(); /* Type of FAT */
+ if (FAT_BootSec.FATType == FAT_16) {
+ rc = OK;
+ } else {
+ rc = ERR_FAT_NOT_SUPPORTED;
+ PRINT_Err(rc);
+ }
+ }
+ return (rc);
+}
+
+/*
+**************************************************************************************************************
+* GET FILE SYSTEM TYPE
+*
+* Description: This function returns the file system type with which the disk is formatted
+*
+* Arguments : None
+*
+* Returns : FAT16 On Success
+* ERR_FAT_TYPE On Failure
+*
+**************************************************************************************************************
+*/
+
+USB_INT08U FAT_GetFATType (void)
+{
+ USB_INT08U fat_type;
+ USB_INT32U tot_sec;
+ USB_INT32U tot_data_clus;
+
+
+ if (FAT_BootSec.TotSec16 != 0) { /* Get total sectors in the disk */
+ tot_sec = FAT_BootSec.TotSec16;
+ } else {
+ tot_sec = FAT_BootSec.TotSec32;
+ }
+
+ tot_data_clus = tot_sec / (FAT_BootSec.SecPerClus); /* Get total data clusters in the disk */
+ /* If total data clusters >= 4085 and */
+ /* < 65525, then it is FAT16 file system */
+ if (tot_data_clus >= 4085 && tot_data_clus < 65525) {
+ fat_type = FAT_16;
+ } else {
+ fat_type = 0;
+ }
+
+ return (fat_type);
+}
+
+/*
+**************************************************************************************************************
+* OPENING A FILE
+*
+* Description: This function stores the attributes of a file, such as starting cluster, file size,
+* sector where the file entry is stored and offset of the entry in that sector
+*
+* Arguments : file_name Name of the file. The file must be in root directory.
+*
+* Returns : pointer to the entry On Success
+* NULL On Failure
+*
+* Modifed 6/9/08 WCB returns a file descriptor which is the INDEX+1 to the entry.
+* returning the entry address itself could be interpreted as a negative number --
+* and thus an error -- for memory locations of 0x80000000 and above. We return
+* INDEX+1 instead of just the index to avoid returning a file descriptor of zero,
+* which could be potentially confused with an error.
+*
+**************************************************************************************************************
+*/
+
+USB_INT32S FILE_Open (USB_INT08U *file_name,
+ USB_INT08U flags)
+{
+ USB_INT32S rc;
+ FILE_ENTRY *entry = 0;
+ USB_INT32S fd = -1;
+
+ do {
+ if (FAT_FileEntry[++fd].FileStatus == 0)
+ entry = &FAT_FileEntry[fd];
+ } while ((entry == 0) && (fd < MAX_FILE_DESCRIPTORS-1));
+ if (entry == 0) {
+ return (ERR_OPEN_LIMIT_REACHED);
+ }
+ if (flags == RDONLY) { /* Search for a file. If it doesn't exist, don't create it */
+ rc = FAT_FindEntry(file_name, entry);
+ if (rc == MATCH_FOUND) {
+ entry->FileStatus = 1;
+ rc = fd+1;
+ }
+ } else { /* Search for a file. If it doesn't exist, create it */
+ rc = FAT_CreateEntry(file_name, entry);
+ if (rc == MATCH_FOUND) {
+ entry->FileStatus = 1;
+ rc = fd+1;
+ }
+ }
+ return (rc);
+}
+
+/*
+**************************************************************************************************************
+* FINDING AN ENTRY
+*
+* Description: This function searches for a file name in the root directory
+*
+* Arguments : ent_name_given Pointer to the file name to be searched.
+* entry Pointer to the entry structure. The attributes of the file are stored in this
+* structure if the file was found in the root directory.
+*
+* Returns : MATCH_FOUND if the file was found in the root directory.
+* MATCH_NOT_FOUND if the file was not found in the root directory.
+*
+**************************************************************************************************************
+*/
+
+USB_INT32S FAT_FindEntry (USB_INT08U *ent_name_given,
+ FILE_ENTRY *entry)
+{
+ USB_INT32U sec_num;
+ volatile USB_INT08U *buf;
+ USB_INT08U ent_type;
+ USB_INT08U ent_name_read[13];
+
+
+ for (sec_num = FAT_BootSec.RootDirStartSec; /* For all the sectors in root directory */
+ sec_num < (FAT_BootSec.RootDirStartSec + FAT_BootSec.RootDirSec);
+ sec_num++) {
+
+
+ MS_BulkRecv(sec_num, 1, FATBuffer); /* Read one sector */
+ buf = FATBuffer;
+ while (buf < (FATBuffer + FAT_BootSec.BytsPerSec)) {
+ ent_type = FAT_ChkEntType(buf); /* Check for the entry type */
+ if (ent_type == SFN_ENTRY) { /* If it is short entry get short file name */
+ FAT_GetSFN(buf, ent_name_read);
+ /* Compare given name with this name case insensitively */
+ if (FAT_StrCaseCmp(ent_name_given, ent_name_read) == MATCH_FOUND) {
+ entry->CurrClus = ReadLE16U(&buf[26]); /* If they are same, get starting cluster */
+ entry->FileSize = ReadLE32U(&buf[28]); /* Get file size */
+ entry->EntrySec = sec_num; /* Get sector number where the filename is located */
+ /* Get offset in this sector where the filename is located */
+ entry->EntrySecOffset = buf - FATBuffer;
+ return (MATCH_FOUND);
+ }
+ }
+ if (ent_type == LAST_ENTRY) { /* If it is the last entry, no more entries will exist. Return */
+ return (MATCH_NOT_FOUND);
+ }
+ buf = buf + 32; /* Move to the next entry */
+ }
+ }
+ return (MATCH_NOT_FOUND);
+}
+
+/*
+**************************************************************************************************************
+* GET SHORT FILE NAME AND EXTENSION OF A FILE
+*
+* Description: This function reads the short file name and extension corresponding to a file
+*
+* Arguments : ent_buf buffer which contains the 32 byte entry of a file
+* name buffer to store the file name and extension of a file
+*
+* Returns : None
+*
+**************************************************************************************************************
+*/
+
+void FAT_GetSFN (volatile USB_INT08U *entry,
+ USB_INT08U *name)
+{
+ USB_INT08U ext[4]; /* Buffer to store the extension of a file */
+ USB_INT08U *ext_ptr;
+
+
+ ext_ptr = ext;
+
+ FAT_GetSfnName(entry, name); /* Get file name into "name" buffer */
+ FAT_GetSfnExt(entry, ext_ptr); /* Get extension into "ext" buffer */
+
+ while (*name) { /* Goto the end of the filename */
+ name++;
+ }
+ if (*ext_ptr) { /* If the extension exists, put a '.' charecter */
+ *name = '.';
+ name++;
+ }
+ while (*ext_ptr) { /* Append the extension to the file name */
+ *name = *ext_ptr;
+ name++;
+ ext_ptr++;
+ }
+ *name = '\0';
+}
+
+/*
+**************************************************************************************************************
+* GET SHORT FILE NAME OF A FILE
+*
+* Description: This function reads the short file name of a file
+*
+* Arguments : ent_buf buffer which contains the 32 byte entry of a file
+* name buffer to store the short file name of a file
+*
+* Returns : None
+*
+**************************************************************************************************************
+*/
+
+void FAT_GetSfnName (volatile USB_INT08U *entry,
+ USB_INT08U *name)
+{
+ USB_INT32U cnt;
+
+
+ cnt = 0;
+ while (cnt < 8) {
+ *name = *entry; /* Get first 8 charecters of an SFN entry */
+ name++;
+ entry++;
+ cnt++;
+ }
+ *name = 0;
+ name--;
+ while (*name == 0x20) { /* If any spaces exist after the file name, replace them with 0 */
+ *name = 0;
+ name--;
+ }
+}
+
+/*
+**************************************************************************************************************
+* GET EXTENSION OF A FILE
+*
+* Description: This function reads the extension of a file
+*
+* Arguments : ent_buf buffer which contains the 32 byte entry of a file
+* ext_ptr buffer to store the extension of a file
+*
+* Returns : None
+*
+**************************************************************************************************************
+*/
+
+void FAT_GetSfnExt (volatile USB_INT08U *entry,
+ USB_INT08U *ext_ptr)
+{
+ USB_INT32U cnt;
+
+
+ cnt = 0;
+ while (cnt < 8) { /* Goto the beginning of the file extension */
+ entry++;
+ cnt++;
+ }
+ cnt = 0;
+ while (cnt < 3) { /* Get 3 charecters from there */
+ *ext_ptr = *entry;
+ ext_ptr++;
+ entry++;
+ cnt++;
+ }
+ *ext_ptr = 0;
+ ext_ptr--;
+ while (*ext_ptr == ' ') { /* If any spaces exist after the file extension, replace them with 0 */
+ *ext_ptr = 0;
+ ext_ptr--;
+ }
+}
+
+/*
+**************************************************************************************************************
+* CASE INSENSITIVE COMPARISION OF STRINGS
+*
+* Description: This function compares two strings case insensitively
+*
+* Arguments : str1 Pointer to the first string
+* str2 Pointer to the second string
+*
+* Returns : MATCH_FOUND if both the strings are same
+* NATCH_NOT_FOUND if both the strings are different
+*
+**************************************************************************************************************
+*/
+
+USB_INT32S FAT_StrCaseCmp (USB_INT08U *str1,
+ USB_INT08U *str2)
+{
+ while (*str1 && *str2) {
+ if (*str1 == *str2 || *str1 == (*str2 + 32) || *str1 == (*str2 - 32)) {
+ str1++;
+ str2++;
+ continue;
+ } else {
+ return (MATCH_NOT_FOUND);
+ }
+ }
+ if (*str1 == 0 && *str2 == 0) {
+ return (MATCH_FOUND);
+ } else {
+ return (MATCH_NOT_FOUND);
+ }
+}
+
+/*
+**************************************************************************************************************
+* CHECK TYPE OF THE ENTRY
+*
+* Description: This function checks the type of file entry.
+*
+* Arguments : ent Pointer to the buffer containing the entry
+*
+* Returns : LAST_ENTRY if the entry is last entry
+* FREE_ENTRY if the entry is free entry
+* LFN_ENTRY if the entry is long file name entry
+* SFN_ENTRY if the entry is short file name entry
+*
+**************************************************************************************************************
+*/
+
+USB_INT32U FAT_ChkEntType (volatile USB_INT08U *ent)
+{
+ if (ent[0] == 0x00) { /* First byte is 0 means it is the last entry */
+ return (LAST_ENTRY);
+ }
+
+ if (ent[0] == 0xE5) { /* First byte is 0xE5 means it is the free entry */
+ return (FREE_ENTRY);
+ }
+
+ if (0x0F == ent[11]) { /* If 11th byte of an entry is 0x0F, it is LFN */
+ return (LFN_ENTRY);
+
+ } else {
+ return (SFN_ENTRY); /* Else it is the SFN */
+ }
+}
+
+/*
+**************************************************************************************************************
+* READ DATA REQUESTED BY THE USER
+*
+* Description: This function reads data requested by the application from the file pointed by file descriptor.
+*
+* Arguments : fd file descriptor that points to a file
+* buffer buffer into which the data is to be read
+* num_bytes number of bytes requested by the application
+*
+* Returns : total_bytes_read Total bytes actually read.
+*
+**************************************************************************************************************
+*/
+
+USB_INT32U FILE_Read ( USB_INT32S fd,
+ volatile USB_INT08U *buffer,
+ USB_INT32U num_bytes)
+{
+ USB_INT32U total_bytes_to_read; /* Total bytes requested by the application */
+ USB_INT32U total_bytes_read; /* Total bytes read */
+ USB_INT32U bytes_read; /* Bytes read from one cluster */
+ USB_INT32U bytes_to_read; /* Bytes to be read in one cluster */
+ FILE_ENTRY *entry; /* Entry that contains the file attribute information */
+ USB_INT16U next_clus; /* Next cluster of the current cluster in the cluster chain */
+
+ entry = &FAT_FileEntry[fd-1]; /* Get file entry from file descriptor */
+ total_bytes_read = 0;
+
+ if (entry->FileSize == 0) {
+ return (0);
+ }
+ if (num_bytes < entry->FileSize) {
+ total_bytes_to_read = num_bytes;
+ } else {
+ total_bytes_to_read = entry->FileSize;
+ }
+ do {
+ next_clus = FAT_GetNextClus(entry->CurrClus); /* Get next cluster */
+ if (next_clus == 0) { /* If the current cluster is the last cluster */
+ /* If the offset is at the end of the file */
+ if (entry->CurrClusOffset == (entry->FileSize % FAT_BootSec.BytsPerClus)) {
+ return (0); /* No more bytes to read */
+ } /* If requested number is > remaining bytes in the last cluster */
+ if (total_bytes_to_read > ((entry->FileSize % FAT_BootSec.BytsPerClus) - entry->CurrClusOffset)) {
+ total_bytes_to_read = (entry->FileSize % FAT_BootSec.BytsPerClus) - entry->CurrClusOffset;
+ }
+ bytes_to_read = total_bytes_to_read;
+ /* If requested number is > remaining bytes in the current cluster */
+ } else if (total_bytes_to_read > (FAT_BootSec.BytsPerClus - entry->CurrClusOffset)) {
+ bytes_to_read = FAT_BootSec.BytsPerClus - entry->CurrClusOffset;
+ } else {
+ bytes_to_read = total_bytes_to_read;
+ }
+ bytes_read = FAT_ClusRead(entry->CurrClus, /* Read bytes from a single cluster */
+ entry->CurrClusOffset,
+ buffer,
+ bytes_to_read);
+ buffer += bytes_read;
+ total_bytes_read += bytes_read;
+ total_bytes_to_read -= bytes_read;
+ /* If the cluster offset reaches end of the cluster, make it 0 */
+ if (entry->CurrClusOffset + bytes_read == FAT_BootSec.BytsPerClus) {
+ entry->CurrClusOffset = 0;
+ } else {
+ entry->CurrClusOffset += bytes_read; /* Else increment the cluster offset */
+ }
+ if (entry->CurrClusOffset == 0) {
+ entry->CurrClus = (next_clus > 0) ? next_clus : entry->CurrClus;
+ }
+ } while (total_bytes_to_read);
+ return (total_bytes_read);
+}
+
+/*
+**************************************************************************************************************
+* READ FROM ONE CLUSTER
+*
+* Description: This function reads the data from a single cluster.
+*
+* Arguments : curr_clus Current cluster from which the data has to read
+* clus_offset Position in the current cluster from which the data has to read
+* buffer Buffer into which the data has to read
+* num_bytes Number of bytes to read
+*
+* Returns : tot_bytes_read Total bytes read from the current cluster
+*
+**************************************************************************************************************
+*/
+
+USB_INT32U FAT_ClusRead ( USB_INT16U curr_clus,
+ USB_INT32U clus_offset,
+ volatile USB_INT08U *buffer,
+ USB_INT32U num_bytes)
+{
+ USB_INT32U tot_bytes_read; /* total bytes read in the current cluster */
+ USB_INT32U n_bytes; /* Bytes to read in the current sector */
+ USB_INT32U start_sec; /* Starting sector of the current cluster */
+ USB_INT32U sec_num; /*Current sector number */
+ USB_INT16U num_sec; /* Number of sectors to be read */
+ USB_INT32U sec_offset; /* Offset in the current sector */
+ USB_INT32U cnt;
+
+
+ tot_bytes_read = 0;
+ start_sec = ((curr_clus - 2) * FAT_BootSec.SecPerClus) + FAT_BootSec.FirstDataSec;
+ sec_num = start_sec + (clus_offset / FAT_BootSec.BytsPerSec);
+ num_sec = num_bytes / FAT_BootSec.BytsPerSec;
+ sec_offset = clus_offset % FAT_BootSec.BytsPerSec;
+
+ if (sec_offset) { /* If the sector offset is at the middle of a sector */
+ MS_BulkRecv(sec_num, 1, FATBuffer); /* Read the first sector */
+ n_bytes = (FAT_BootSec.BytsPerSec - sec_offset <= num_bytes) ?
+ (FAT_BootSec.BytsPerSec - sec_offset) : num_bytes;
+ for (cnt = sec_offset; cnt < sec_offset + n_bytes; cnt++) {
+ *buffer = FATBuffer[cnt]; /* Copy the required bytes to user buffer */
+ buffer++;
+ }
+ tot_bytes_read += n_bytes;
+ clus_offset += n_bytes;
+ num_bytes -= n_bytes;
+ sec_num++;
+ }
+
+ if (num_bytes / FAT_BootSec.BytsPerSec) { /* Read all the remaining full sectors */
+
+ num_sec = num_bytes / FAT_BootSec.BytsPerSec;
+ MS_BulkRecv(sec_num, num_sec, buffer);
+ buffer += (num_sec * FAT_BootSec.BytsPerSec);
+ tot_bytes_read += (num_sec * FAT_BootSec.BytsPerSec);
+ clus_offset += (num_sec * FAT_BootSec.BytsPerSec);
+ num_bytes -= (num_sec * FAT_BootSec.BytsPerSec);
+ sec_num += num_sec;
+ }
+
+ if (num_bytes) { /* Read the last sector for the remaining bytes */
+ MS_BulkRecv(sec_num, 1, FATBuffer);
+ for (cnt = 0; cnt < num_bytes; cnt++) {
+ *buffer = FATBuffer[cnt]; /* Copy the required bytes to user buffer */
+ buffer++;
+ }
+ tot_bytes_read += num_bytes;
+ }
+
+ return (tot_bytes_read);
+}
+
+/*
+**************************************************************************************************************
+* WRITE THE DATA REQUESTED BY THE USER
+*
+* Description: This function writes data requested by the application to the file pointed by file descriptor
+*
+* Arguments : fd file descriptor that points to a file
+* buffer buffer from which the data is to be written
+* num_bytes number of bytes requested by the application
+*
+* Returns : total_bytes_written Total bytes actually written
+*
+**************************************************************************************************************
+*/
+
+USB_INT32U FILE_Write ( USB_INT32S fd,
+ volatile USB_INT08U *buffer,
+ USB_INT32U num_bytes)
+{
+ USB_INT32U total_bytes_to_write; /* Total bytes requested by application */
+ USB_INT32U total_bytes_written; /* Total bytes written */
+ USB_INT32U bytes_written; /* Bytes written in a single cluster */
+ USB_INT32U bytes_to_write; /* Bytes to write in a single cluster */
+ FILE_ENTRY *entry; /* Entry that contains the file attribute information */
+ USB_INT16U free_clus; /* Free cluster available in the disk */
+
+
+ entry = &FAT_FileEntry[fd-1]; /* Get file entry from file descriptor */
+ total_bytes_written = 0;
+ total_bytes_to_write = num_bytes;
+
+ if (num_bytes) {
+ if (entry->FileSize == 0) {
+ free_clus = FAT_GetFreeClus();
+ FAT_UpdateFAT(free_clus, 0xFFFF);
+ entry->CurrClus = free_clus;
+ MS_BulkRecv(entry->EntrySec, 1, FATBuffer);
+ WriteLE16U(&FATBuffer[(entry->EntrySecOffset) + 26], free_clus);
+ MS_BulkSend(entry->EntrySec, 1, FATBuffer);
+ }
+ } else {
+ return (0);
+ }
+ entry->CurrClus = FAT_GetEndClus(entry->CurrClus); /* Make the current cluster as end cluster */
+ entry->CurrClusOffset = entry->FileSize % FAT_BootSec.BytsPerClus; /* Move cluster offset to file end */
+ do {
+ if (total_bytes_to_write > FAT_BootSec.BytsPerClus - entry->CurrClusOffset) {
+ bytes_to_write = FAT_BootSec.BytsPerClus - entry->CurrClusOffset;
+ } else {
+ bytes_to_write = total_bytes_to_write;
+ }
+ bytes_written = FAT_ClusWrite(entry->CurrClus,
+ entry->CurrClusOffset,
+ buffer,
+ bytes_to_write);
+ buffer += bytes_written;
+ total_bytes_written += bytes_written;
+ total_bytes_to_write -= bytes_written;
+ entry->FileSize += bytes_written;
+ if (entry->CurrClusOffset + bytes_written == FAT_BootSec.BytsPerClus) {
+ entry->CurrClusOffset = 0;
+ } else {
+ entry->CurrClusOffset += bytes_written;
+ }
+ if (entry->CurrClusOffset == 0) {
+ free_clus = FAT_GetFreeClus();
+ if (free_clus == 0) {
+ return (total_bytes_written);
+ }
+ FAT_UpdateFAT(entry->CurrClus, free_clus);
+ FAT_UpdateFAT(free_clus, 0xFFFF);
+ entry->CurrClus = free_clus;
+ }
+ } while (total_bytes_to_write);
+ return (total_bytes_written);
+}
+
+/*
+**************************************************************************************************************
+* WRITE TO ONE CLUSTER
+*
+* Description: This function writes the data to a single cluster.
+*
+* Arguments : curr_clus Current cluster into which the data has to write
+* clus_offset Position in the current cluster from which the data has to write
+* buffer Buffer from which the data has to write
+* num_bytes Number of bytes to write
+*
+* Returns : tot_bytes_read Total bytes written into the current cluster
+*
+**************************************************************************************************************
+*/
+
+USB_INT32U FAT_ClusWrite ( USB_INT16U curr_clus,
+ USB_INT32U clus_offset,
+ volatile USB_INT08U *buffer,
+ USB_INT32U num_bytes)
+{
+ USB_INT32U tot_bytes_written;
+ USB_INT32U n_bytes;
+ USB_INT32U start_sec;
+ USB_INT32U sec_num;
+ USB_INT16U num_sec;
+ USB_INT32U sec_offset;
+ USB_INT32U cnt;
+
+
+ tot_bytes_written = 0;
+ start_sec = ((curr_clus - 2) * FAT_BootSec.SecPerClus) + FAT_BootSec.FirstDataSec;
+ sec_num = start_sec + (clus_offset / FAT_BootSec.BytsPerSec);
+ num_sec = num_bytes / FAT_BootSec.BytsPerSec;
+ sec_offset = clus_offset % FAT_BootSec.BytsPerSec;
+
+ if (sec_offset) {
+ MS_BulkRecv(sec_num, 1, FATBuffer);
+ n_bytes = (FAT_BootSec.BytsPerSec - sec_offset <= num_bytes) ?
+ (FAT_BootSec.BytsPerSec - sec_offset) : num_bytes;
+ for (cnt = sec_offset; cnt < (sec_offset + n_bytes); cnt++) {
+ FATBuffer[cnt] = *buffer;
+ buffer++;
+ }
+ MS_BulkSend(sec_num, 1, FATBuffer);
+ tot_bytes_written += n_bytes;
+ clus_offset += n_bytes;
+ num_bytes -= n_bytes;
+ sec_num++;
+ }
+ if (num_bytes / FAT_BootSec.BytsPerSec) {
+ num_sec = num_bytes / FAT_BootSec.BytsPerSec;
+ MS_BulkSend(sec_num, num_sec, buffer);
+ buffer += (num_sec * FAT_BootSec.BytsPerSec);
+ tot_bytes_written += (num_sec * FAT_BootSec.BytsPerSec);
+ clus_offset += (num_sec * FAT_BootSec.BytsPerSec);
+ num_bytes -= (num_sec * FAT_BootSec.BytsPerSec);
+ sec_num += num_sec;
+ }
+ if (num_bytes) {
+ MS_BulkRecv(sec_num, 1, FATBuffer);
+
+ for (cnt = 0; cnt < num_bytes; cnt++) {
+ FATBuffer[cnt] = *buffer;
+ buffer++;
+ }
+ MS_BulkSend(sec_num, 1, FATBuffer);
+ tot_bytes_written += num_bytes;
+ }
+ return (tot_bytes_written);
+}
+
+/*
+**************************************************************************************************************
+* GET NEXT CLUSTER
+*
+* Description: This function returns next cluster of the current cluster in the cluster chain. If the current
+* cluster is the last cluster then this function returns 0
+*
+* Arguments : clus_no The cluster number for which the next cluster to be found
+*
+* Returns : next_clus if the current cluster is not the last cluster
+* 0 if the current cluster is the last cluster
+* Note: In practical cluster number 0 doesn't exist
+*
+**************************************************************************************************************
+*/
+
+USB_INT16U FAT_GetNextClus (USB_INT16U clus_no)
+{
+ USB_INT32U sec_num;
+ USB_INT32U ent_offset;
+ USB_INT16U next_clus;
+
+ /* Get the sector number in the FAT that contains current cluster */
+ sec_num = FAT_BootSec.RsvdSecCnt + ((clus_no * 2) / FAT_BootSec.BytsPerSec);
+ /* Get the sector offset in the FAT where the current cluster is located */
+ ent_offset = (clus_no * 2) % FAT_BootSec.BytsPerSec;
+ MS_BulkRecv(sec_num, 1, FATBuffer); /* Read that sector */
+ next_clus = ReadLE16U(&FATBuffer[ent_offset]); /* Read the next cluster */
+ if (next_clus >= 0xFFF8 && next_clus <= 0xFFFF) { /* If that value is in between 0xFFF8 and 0xFFFF */
+ next_clus = 0; /* Current cluster is the end cluster */
+ }
+ return (next_clus);
+
+}
+
+/*
+**************************************************************************************************************
+* GET FREE CLUSTER
+*
+* Description: This function returns the free cluster if available
+*
+* Arguments : None
+*
+* Returns : free_clus if available
+* 0 if not available(means the disk is full)
+*
+**************************************************************************************************************
+*/
+
+USB_INT16U FAT_GetFreeClus (void)
+{
+ USB_INT32U num_sec;
+ USB_INT32U cnt;
+ USB_INT32U sec_num;
+ USB_INT16U free_clus;
+
+
+ sec_num = FAT_BootSec.RsvdSecCnt;
+ num_sec = FAT_BootSec.FATSz16;
+ while (sec_num < (FAT_BootSec.RsvdSecCnt + num_sec)) {
+ MS_BulkRecv(sec_num, 1, FATBuffer);
+ for (cnt = 0; cnt < FAT_BootSec.BytsPerSec; cnt += 2) {
+ if (ReadLE16U(&FATBuffer[cnt]) == 0) {
+ free_clus = (((sec_num - FAT_BootSec.RsvdSecCnt) * FAT_BootSec.BytsPerSec) + cnt) / 2;
+ return (free_clus);
+ }
+ }
+ sec_num++;
+ }
+ return (0);
+}
+
+/*
+**************************************************************************************************************
+* UPDATE FILE ALLOCATION TABLE
+*
+* Description: This function updates the file allocation table
+*
+* Arguments : curr_clus Offset of the current cluster number in the file allocation table
+* value Value with which this offset to be updated
+*
+* Returns : None
+*
+**************************************************************************************************************
+*/
+
+void FAT_UpdateFAT (USB_INT16U curr_clus,
+ USB_INT16U value)
+{
+ USB_INT32U sec_num;
+ USB_INT32U sec_offset;
+
+ sec_num = FAT_BootSec.RsvdSecCnt + (curr_clus * 2) / FAT_BootSec.BytsPerSec;
+ sec_offset = (curr_clus * 2) % FAT_BootSec.BytsPerSec;
+
+ MS_BulkRecv(sec_num, 1, FATBuffer);
+ WriteLE16U(&FATBuffer[sec_offset], value);
+ MS_BulkSend(sec_num, 1, FATBuffer);
+}
+
+/*
+**************************************************************************************************************
+* UPDATE THE FILE ENTRY
+*
+* Description: This function updates the file entry that is located in the root directory
+*
+* Arguments : entry Pointer to the FILE ENTRY structure which contains the information about the file
+*
+* Returns : None
+*
+**************************************************************************************************************
+*/
+
+void FAT_UpdateEntry (FILE_ENTRY *entry)
+{
+ USB_INT32U sec_num;
+ USB_INT32U offset;
+
+ sec_num = entry->EntrySec;
+ offset = entry->EntrySecOffset;
+ MS_BulkRecv(sec_num, 1, FATBuffer);
+ WriteLE32U(&FATBuffer[offset + 28], entry->FileSize);
+ MS_BulkSend(sec_num, 1, FATBuffer);
+}
+
+/*
+**************************************************************************************************************
+* CREATING AN ENTRY
+*
+* Description: This function creates a file entry in the root directory if the file does not exist
+*
+* Arguments : ent_name_given The file name with which the entry is to be created
+* entry Pointer to FILE ENTRY structure
+*
+* Returns : OK If the entry already exists or successfully created if it doesn't exists
+* ERROR If failed to create the entry
+*
+**************************************************************************************************************
+*/
+
+USB_INT32S FAT_CreateEntry (USB_INT08U *ent_name_given,
+ FILE_ENTRY *entry)
+{
+ USB_INT32S rc;
+
+
+ rc = FAT_FindEntry(ent_name_given, entry); /* Find for the given file name in the root directory */
+ if (rc == MATCH_FOUND) { /* If match found, return */
+ return (rc);
+ } else {
+ rc = FAT_GetFreeEntry(entry); /* Else get a free entry from the root directory */
+ if (rc != OK) {
+ return (rc);
+ } else {
+ FAT_PutSFN(ent_name_given, entry); /* Store the given short file name in that entry */
+ return (rc);
+ }
+ }
+}
+
+/*
+**************************************************************************************************************
+* GET GREE ENTRY
+*
+* Description: This function searches for a free entry in the root directory. If a free entry is found, the
+* sector number and sector offset where the entry is located will be stored
+*
+* Arguments : entry Pointer to FILE_ENTRY structure
+*
+* Returns : OK If a free entry is found
+* ERROR If no free entry is found
+*
+**************************************************************************************************************
+*/
+
+USB_INT32S FAT_GetFreeEntry (FILE_ENTRY *entry)
+{
+ USB_INT32U sec_num;
+ volatile USB_INT08U *buf;
+ USB_INT08U ent_type;
+
+
+ for (sec_num = FAT_BootSec.RootDirStartSec;
+ sec_num < (FAT_BootSec.RootDirStartSec + FAT_BootSec.RootDirSec);
+ sec_num++) {
+
+ MS_BulkRecv(sec_num, 1, FATBuffer);
+ buf = FATBuffer;
+ while (buf < (FATBuffer + FAT_BootSec.BytsPerSec)) {
+ ent_type = FAT_ChkEntType(buf);
+ if (ent_type == FREE_ENTRY) {
+ entry->EntrySec = sec_num;
+ entry->EntrySecOffset = buf - FATBuffer;
+ return (OK);
+ }
+ if (ent_type == LAST_ENTRY) {
+ return (ERR_ROOT_DIR_FULL);
+ } else {
+ buf += 32;
+ }
+ }
+ }
+ return (ERR_ROOT_DIR_FULL);
+}
+
+/*
+**************************************************************************************************************
+* PUT SHORT FILE NAME
+*
+* Description: This function fills the file entry with the short file name given by the user
+*
+* Arguments : ent_name_given File name given by the user
+* entry Pointer to the FILE_ENTRY structure
+*
+* Returns : None
+*
+**************************************************************************************************************
+*/
+
+void FAT_PutSFN (USB_INT08U *ent_name_given,
+ FILE_ENTRY *entry)
+{
+ USB_INT32U idx;
+
+ /* Read the sector from root directory containing the free entry */
+ MS_BulkRecv(entry->EntrySec, 1, FATBuffer);
+ for (idx = 0; idx < 8; idx++) { /* Fill the first eight charecters of the entry with file name */
+ if (*ent_name_given == '.') {
+ while (idx < 8) {
+ FATBuffer[entry->EntrySecOffset + idx] = 0x20;
+ idx++;
+ }
+ ent_name_given++;
+ } else {
+ FATBuffer[entry->EntrySecOffset + idx] = *ent_name_given;
+ ent_name_given++;
+ }
+ }
+
+ for (idx = 8; idx < 11; idx++) { /* Fill the next 3 charecters with file extension */
+ if (*ent_name_given == '.') {
+ while (idx < 11) {
+ FATBuffer[entry->EntrySecOffset + idx] = 0x20;
+ idx++;
+ }
+ } else {
+ FATBuffer[entry->EntrySecOffset + idx] = *ent_name_given;
+ ent_name_given++;
+ }
+ }
+ FATBuffer[entry->EntrySecOffset + idx] = 0x20;
+ for (idx = 12; idx < 32; idx++) { /* Fill all the remaining bytes with 0's */
+ FATBuffer[entry->EntrySecOffset + idx] = 0;
+ }
+ MS_BulkSend(entry->EntrySec, 1, FATBuffer); /* Write the sector into the root directory */
+}
+
+/*
+**************************************************************************************************************
+* FILE CLOSE
+*
+* Description: This function closes the opened file by making all the elements of FILE_ENTRY structure to 0
+*
+* Arguments : fd File descriptor which points to the file to be closed
+*
+* Returns : None
+*
+**************************************************************************************************************
+*/
+
+void FILE_Close (USB_INT32S fd)
+{
+ FILE_ENTRY *entry;
+
+
+ entry = &FAT_FileEntry[fd-1];
+ MS_BulkRecv(entry->EntrySec, 1, FATBuffer);
+ WriteLE32U(&FATBuffer[entry->EntrySecOffset + 28], entry->FileSize); /* Update the file size */
+ MS_BulkSend(entry->EntrySec, 1, FATBuffer);
+ entry->CurrClus = 0;
+ entry->CurrClusOffset = 0;
+ entry->FileSize = 0;
+ entry->EntrySec = 0;
+ entry->EntrySecOffset = 0;
+ entry->FileStatus = 0;
+}
+
+/*
+**************************************************************************************************************
+* GET END CLUSTER
+*
+* Description: This function end cluster in the cluster chain of a cluster
+*
+* Arguments : clus_no Starting cluster of the cluster chain in which end cluster to be found
+*
+* Returns : End cluster in the cluster chain
+*
+**************************************************************************************************************
+*/
+
+USB_INT16U FAT_GetEndClus (USB_INT16U clus_no)
+{
+ USB_INT16U next_clus;
+
+
+ next_clus = clus_no;
+ while (next_clus) {
+ next_clus = FAT_GetNextClus(clus_no);
+ if (next_clus) {
+ clus_no = next_clus;
+ }
+ }
+ return (clus_no);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Fat/usbhost_fat.h Thu Jan 21 01:15:42 2010 +0000
@@ -0,0 +1,146 @@
+/*
+**************************************************************************************************************
+* NXP USB Host Stack
+*
+* (c) Copyright 2008, NXP SemiConductors
+* (c) Copyright 2008, OnChip Technologies LLC
+* All Rights Reserved
+*
+* www.nxp.com
+* www.onchiptech.com
+*
+* File : usbhost_fat.h
+* Programmer(s) : Ravikanth.P
+* Version :
+*
+**************************************************************************************************************
+*/
+
+#ifndef USBHOST_FAT_H
+#define USBHOST_FAT_H
+
+/*
+**************************************************************************************************************
+* INCLUDE HEADER FILES
+**************************************************************************************************************
+*/
+
+#include "usbhost_inc.h"
+
+/*
+**************************************************************************************************************
+* FAT DEFINITIONS
+**************************************************************************************************************
+*/
+
+#define FAT_16 1
+
+#define LAST_ENTRY 1
+#define FREE_ENTRY 2
+#define LFN_ENTRY 3
+#define SFN_ENTRY 4
+
+#define RDONLY 1
+#define RDWR 2
+
+/*
+**************************************************************************************************************
+* TYPE DEFINITIONS
+**************************************************************************************************************
+*/
+
+typedef struct boot_sec {
+ USB_INT32U BootSecOffset; /* Offset of the boot sector from sector 0 */
+ USB_INT16U BytsPerSec; /* Bytes per sector */
+ USB_INT08U SecPerClus; /* Sectors per cluster */
+ USB_INT32U BytsPerClus; /* Bytes per cluster */
+ USB_INT16U RsvdSecCnt; /* Reserved sector count */
+ USB_INT08U NumFATs; /* Number of FAT copies */
+ USB_INT16U RootEntCnt; /* Root entry count */
+ USB_INT16U TotSec16; /* Total sectors in the disk. !=0 if TotSec32 = 0 */
+ USB_INT32U TotSec32; /* Total sectors in the disk. !=0 if TotSec16 = 0 */
+ USB_INT16U FATSz16; /* Sectors occupied by single FAT table */
+ USB_INT08U FATType; /* File system type */
+ USB_INT32U RootDirSec; /* Sectors occupied by root directory */
+ USB_INT32U RootDirStartSec; /* Starting sector of the root directory */
+ USB_INT32U FirstDataSec; /* Starting sector of the first data cluster */
+} BOOT_SEC;
+
+typedef struct file_entry {
+ USB_INT32U FileSize; /* Total size of the file */
+ USB_INT16U CurrClus; /* Current cluster of the cluster offset */
+ USB_INT32U CurrClusOffset; /* Current cluster offset */
+ USB_INT32U EntrySec; /* Sector where the file entry is located */
+ USB_INT32U EntrySecOffset; /* Offset in the entry sector from where the file is located */
+ USB_INT08U FileStatus; /* File's open status */
+} FILE_ENTRY;
+
+/*
+**************************************************************************************************************
+* FUNCTION PROTOTYPES
+**************************************************************************************************************
+*/
+
+USB_INT32S FAT_Init (void);
+
+USB_INT08U FAT_GetFATType (void);
+void PrintBootSec (void);
+
+USB_INT32S FILE_Open ( USB_INT08U *file_name,
+ USB_INT08U flags);
+
+USB_INT32S FAT_FindEntry ( USB_INT08U *ent_name_given,
+ FILE_ENTRY *entry);
+
+void FAT_GetSFN (volatile USB_INT08U *entry,
+ USB_INT08U *name);
+
+void FAT_GetSfnName (volatile USB_INT08U *entry,
+ USB_INT08U *name);
+
+void FAT_GetSfnExt (volatile USB_INT08U *entry,
+ USB_INT08U *ext_ptr);
+
+USB_INT32S FAT_StrCaseCmp ( USB_INT08U *str1,
+ USB_INT08U *str2);
+
+USB_INT32U FAT_ChkEntType (volatile USB_INT08U *ent);
+
+USB_INT32U FAT_ClusRead ( USB_INT16U curr_clus,
+ USB_INT32U clus_offset,
+ volatile USB_INT08U *buffer,
+ USB_INT32U num_bytes);
+
+USB_INT32U FILE_Read ( USB_INT32S fd,
+ volatile USB_INT08U *buffer,
+ USB_INT32U num_bytes);
+USB_INT16U FAT_GetNextClus ( USB_INT16U clus_no);
+
+USB_INT32U FAT_ClusWrite ( USB_INT16U curr_clus,
+ USB_INT32U clus_offset,
+ volatile USB_INT08U *buffer,
+ USB_INT32U num_bytes);
+USB_INT32U FILE_Write ( USB_INT32S fd,
+ volatile USB_INT08U *buffer,
+ USB_INT32U num_bytes);
+
+void FAT_UpdateEntry ( FILE_ENTRY *entry);
+
+void FAT_UpdateFAT ( USB_INT16U curr_clus,
+ USB_INT16U value);
+
+USB_INT16U FAT_GetFreeClus (void);
+
+USB_INT32S FAT_GetFreeEntry( FILE_ENTRY *entry);
+
+void FAT_PutSFN ( USB_INT08U *ent_name_given,
+ FILE_ENTRY *entry);
+
+USB_INT32S FAT_CreateEntry ( USB_INT08U *ent_name_given,
+ FILE_ENTRY *entry);
+
+void FILE_Close ( USB_INT32S fd);
+
+USB_INT16U FAT_GetEndClus ( USB_INT16U clus_no);
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Host/usbhost_lpc17xx.c Thu Jan 21 01:15:42 2010 +0000
@@ -0,0 +1,839 @@
+/*
+**************************************************************************************************************
+* NXP USB Host Stack
+*
+* (c) Copyright 2008, NXP SemiConductors
+* (c) Copyright 2008, OnChip Technologies LLC
+* All Rights Reserved
+*
+* www.nxp.com
+* www.onchiptech.com
+*
+* File : usbhost_lpc17xx.c
+* Programmer(s) : Ravikanth.P
+* Version :
+*
+**************************************************************************************************************
+*/
+
+/*
+**************************************************************************************************************
+* INCLUDE HEADER FILES
+**************************************************************************************************************
+*/
+
+#include "usbhost_lpc17xx.h"
+
+/*
+**************************************************************************************************************
+* GLOBAL VARIABLES
+**************************************************************************************************************
+*/
+int gUSBConnected;
+
+volatile USB_INT32U HOST_RhscIntr = 0; /* Root Hub Status Change interrupt */
+volatile USB_INT32U HOST_WdhIntr = 0; /* Semaphore to wait until the TD is submitted */
+volatile USB_INT08U HOST_TDControlStatus = 0;
+volatile HCED *EDCtrl; /* Control endpoint descriptor structure */
+volatile HCED *EDBulkIn; /* BulkIn endpoint descriptor structure */
+volatile HCED *EDBulkOut; /* BulkOut endpoint descriptor structure */
+volatile HCTD *TDHead; /* Head transfer descriptor structure */
+volatile HCTD *TDTail; /* Tail transfer descriptor structure */
+volatile HCCA *Hcca; /* Host Controller Communications Area structure */
+ USB_INT16U *TDBufNonVol; /* Identical to TDBuffer just to reduce compiler warnings */
+volatile USB_INT08U *TDBuffer; /* Current Buffer Pointer of transfer descriptor */
+volatile USB_INT08U *FATBuffer; /* Buffer used by FAT file system */
+volatile USB_INT08U *UserBuffer; /* Buffer used by application */
+
+/*
+**************************************************************************************************************
+* DELAY IN MILLI SECONDS
+*
+* Description: This function provides a delay in milli seconds
+*
+* Arguments : delay The delay required
+*
+* Returns : None
+*
+**************************************************************************************************************
+*/
+
+void Host_DelayMS (USB_INT32U delay)
+{
+ volatile USB_INT32U i;
+
+
+ for (i = 0; i < delay; i++) {
+ Host_DelayUS(1000);
+ }
+}
+
+/*
+**************************************************************************************************************
+* DELAY IN MICRO SECONDS
+*
+* Description: This function provides a delay in micro seconds
+*
+* Arguments : delay The delay required
+*
+* Returns : None
+*
+**************************************************************************************************************
+*/
+
+void Host_DelayUS (USB_INT32U delay)
+{
+ volatile USB_INT32U i;
+
+
+ for (i = 0; i < (4 * delay); i++) { /* This logic was tested. It gives app. 1 micro sec delay */
+ ;
+ }
+}
+
+/*
+**************************************************************************************************************
+* INITIALIZE THE HOST CONTROLLER
+*
+* Description: This function initializes lpc17xx host controller
+*
+* Arguments : None
+*
+* Returns :
+*
+**************************************************************************************************************
+*/
+void Host_Init (void)
+{
+ USB_INT32U HostBaseAddr;
+
+ PRINT_Log("In Host_Init, LPC_USB=0x%08X\r\n", LPC_USB);
+ //NVIC_DisableIRQ(USB_IRQn); /* Disable the USB interrupt source */
+
+ LPC_SC->PCONP |= (1UL<<31); // set PCUSB bit
+#if 1
+ PRINT_Log("1: OTGClkCtrl == %08X, OTGClkSt == %08X\r\n", LPC_USB->OTGClkCtrl, LPC_USB->OTGClkSt);
+ LPC_USB->OTGClkCtrl = 0x0000001F;
+ PRINT_Log("2: OTGClkCtrl == %08X, OTGClkSt == %08X\r\n", LPC_USB->OTGClkCtrl, LPC_USB->OTGClkSt);
+ while ((LPC_USB->OTGClkSt & 0x0000001F) == 0) { /* Host clock is available */
+ ;
+ }
+#else
+ PRINT_Log("1: USBClkCtrl == %08X, USBClkSt == %08X\r\n", LPC_USB->USBClkCtrl, LPC_USB->USBClkSt);
+ LPC_USB->USBClkCtrl |= 0x01; /* Enable USB host clock */
+ PRINT_Log("2: USBClkCtrl == %08X, USBClkSt == %08X\r\n", LPC_USB->USBClkCtrl, LPC_USB->USBClkSt);
+// while ((LPC_USB->USBClkSt & 0x00000001) == 0) { /* Host clock is available */
+// ;
+// }
+wait(0.5);
+#endif
+
+PRINT_Log("3: OTGStCtrl=%08X\r\n", LPC_USB->OTGStCtrl);
+#if 1
+ LPC_USB->OTGStCtrl = 1; // ? 0x3;
+PRINT_Log("4\r\n");
+#endif
+
+ /* P1[18] = USB_UP_LED, 01 */
+ /* P1[19] = /USB_PPWR, 10 */
+ /* P1[22] = USB_PWRD, 10 */
+ /* P1[27] = /USB_OVRCR, 10 */
+#if 0
+ LPC_PINCON->PINSEL3 &= ~((3<<4) | (3<<6) | (3<<12) | (3<<22));
+ LPC_PINCON->PINSEL3 |= ((1<<4)|(2<<6) | (2<<12) | (2<<22)); // 0x00802080
+PRINT_Log("5\r\n");
+#endif
+
+ /* P0[29] = USB_D+, 01 */
+ /* P0[30] = USB_D-, 01 */
+ LPC_PINCON->PINSEL1 &= ~((3<<26) | (3<<28));
+ LPC_PINCON->PINSEL1 |= ((1<<26)|(1<<28)); // 0x14000000
+
+ PRINT_Log("Initializing Host Stack\r\n");
+
+ // For chip revision V01 and later
+// HostBaseAddr = 0x20080000;
+#ifdef TARGET_LPC1768
+ // mbed's "USB RAM"
+ HostBaseAddr = 0x2007C000;
+#else
+ // USB RAM
+ HostBaseAddr = 0x7FD00000;
+#endif
+
+ Hcca = (volatile HCCA *)(HostBaseAddr+0x000);
+ TDHead = (volatile HCTD *)(HostBaseAddr+0x100);
+ TDTail = (volatile HCTD *)(HostBaseAddr+0x110);
+ EDCtrl = (volatile HCED *)(HostBaseAddr+0x120);
+ EDBulkIn = (volatile HCED *)(HostBaseAddr+0x130);
+ EDBulkOut = (volatile HCED *)(HostBaseAddr+0x140);
+ TDBuffer = (volatile USB_INT08U *)(HostBaseAddr+0x150);
+ FATBuffer = (volatile USB_INT08U *)(HostBaseAddr+0x1D0);
+ UserBuffer = (volatile USB_INT08U *)(HostBaseAddr+0x1000);
+
+ /* Initialize all the TDs, EDs and HCCA to 0 */
+PRINT_Log("6\r\n");
+ Host_EDInit(EDCtrl);
+PRINT_Log("7\r\n");
+ Host_EDInit(EDBulkIn);
+PRINT_Log("8\r\n");
+ Host_EDInit(EDBulkOut);
+PRINT_Log("9\r\n");
+ Host_TDInit(TDHead);
+PRINT_Log("10\r\n");
+ Host_TDInit(TDTail);
+PRINT_Log("11\r\n");
+ Host_HCCAInit(Hcca);
+PRINT_Log("12\r\n");
+
+
+ Host_DelayMS(50); /* Wait 50 ms before apply reset */
+ LPC_USB->HcControl = 0; /* HARDWARE RESET */
+ LPC_USB->HcControlHeadED = 0; /* Initialize Control list head to Zero */
+ LPC_USB->HcBulkHeadED = 0; /* Initialize Bulk list head to Zero */
+
+ /* SOFTWARE RESET */
+ LPC_USB->HcCommandStatus = OR_CMD_STATUS_HCR;
+ LPC_USB->HcFmInterval = DEFAULT_FMINTERVAL; /* Write Fm Interval and Largest Data Packet Counter */
+
+ /* Put HC in operational state */
+ LPC_USB->HcControl = (LPC_USB->HcControl & (~OR_CONTROL_HCFS)) | OR_CONTROL_HC_OPER;
+ LPC_USB->HcRhStatus = OR_RH_STATUS_LPSC; /* Set Global Power */
+
+ LPC_USB->HcHCCA = (USB_INT32U)Hcca;
+ LPC_USB->HcInterruptStatus |= LPC_USB->HcInterruptStatus; /* Clear Interrrupt Status */
+
+
+ LPC_USB->HcInterruptEnable = OR_INTR_ENABLE_MIE |
+ OR_INTR_ENABLE_WDH |
+ OR_INTR_ENABLE_RHSC;
+
+PRINT_Log("15\r\n");
+
+
+#ifdef TARGET_LPC2368
+ NVIC->IntSelect &= ~(1 << USB_IRQn); /* Configure the ISR handler as IRQ */
+ /* Set the vector address */
+ NVIC_SetVector(USB_IRQn, (USB_INT32U)USB_IRQHandler);
+#endif
+ NVIC_SetPriority(USB_IRQn, 0); /* highest priority */
+ /* Enable the USB Interrupt */
+ NVIC_EnableIRQ(USB_IRQn); /* enable USB interrupt */
+// NVIC_SetPriority (USB_IRQn, 0); /* highest priority */
+ PRINT_Log("Host Initialized\r\n");
+}
+
+/*
+**************************************************************************************************************
+* INTERRUPT SERVICE ROUTINE
+*
+* Description: This function services the interrupt caused by host controller
+*
+* Arguments : None
+*
+* Returns : None
+*
+**************************************************************************************************************
+*/
+
+void USB_IRQHandler (void) __irq
+{
+ USB_INT32U int_status;
+ USB_INT32U ie_status;
+
+ int_status = LPC_USB->HcInterruptStatus; /* Read Interrupt Status */
+ ie_status = LPC_USB->HcInterruptEnable; /* Read Interrupt enable status */
+
+//PRINT_Log("In USB_IRQHandler().\r\n");
+ if (!(int_status & ie_status)) {
+ return;
+ } else {
+
+ int_status = int_status & ie_status;
+ if (int_status & OR_INTR_STATUS_RHSC) { /* Root hub status change interrupt */
+ if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_CSC) {
+ if (LPC_USB->HcRhStatus & OR_RH_STATUS_DRWE) {
+ /*
+ * When DRWE is on, Connect Status Change
+ * means a remote wakeup event.
+ */
+ HOST_RhscIntr = 1;// JUST SOMETHING FOR A BREAKPOINT
+ }
+ else {
+ /*
+ * When DRWE is off, Connect Status Change
+ * is NOT a remote wakeup event
+ */
+ if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_CCS) {
+ if (!gUSBConnected) {
+ HOST_TDControlStatus = 0;
+ HOST_WdhIntr = 0;
+ HOST_RhscIntr = 1;
+ gUSBConnected = 1;
+ }
+ else
+ PRINT_Log("Spurious status change (connected)?\r\n");
+ } else {
+ if (gUSBConnected) {
+ LPC_USB->HcInterruptEnable = 0; // why do we get multiple disc. rupts???
+ HOST_RhscIntr = 0;
+ gUSBConnected = 0;
+ }
+ else
+ PRINT_Log("Spurious status change (disconnected)?\r\n");
+ }
+ }
+ LPC_USB->HcRhPortStatus1 = OR_RH_PORT_CSC;
+ }
+ if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_PRSC) {
+ LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC;
+ }
+ }
+ if (int_status & OR_INTR_STATUS_WDH) { /* Writeback Done Head interrupt */
+ HOST_WdhIntr = 1;
+ HOST_TDControlStatus = (TDHead->Control >> 28) & 0xf;
+ }
+ LPC_USB->HcInterruptStatus = int_status; /* Clear interrupt status register */
+ }
+#ifdef TARGET_LPC2368
+ NVIC->Address = 0;
+#endif
+ return;
+}
+
+/*
+**************************************************************************************************************
+* PROCESS TRANSFER DESCRIPTOR
+*
+* Description: This function processes the transfer descriptor
+*
+* Arguments : ed Endpoint descriptor that contains this transfer descriptor
+* token SETUP, IN, OUT
+* buffer Current Buffer Pointer of the transfer descriptor
+* buffer_len Length of the buffer
+*
+* Returns : OK if TD submission is successful
+* ERROR if TD submission fails
+*
+**************************************************************************************************************
+*/
+
+USB_INT32S Host_ProcessTD (volatile HCED *ed,
+ volatile USB_INT32U token,
+ volatile USB_INT08U *buffer,
+ USB_INT32U buffer_len)
+{
+ volatile USB_INT32U td_toggle;
+
+
+ if (ed == EDCtrl) {
+ if (token == TD_SETUP) {
+ td_toggle = TD_TOGGLE_0;
+ } else {
+ td_toggle = TD_TOGGLE_1;
+ }
+ } else {
+ td_toggle = 0;
+ }
+ TDHead->Control = (TD_ROUNDING |
+ token |
+ TD_DELAY_INT(0) |
+ td_toggle |
+ TD_CC);
+ TDTail->Control = 0;
+ TDHead->CurrBufPtr = (USB_INT32U) buffer;
+ TDTail->CurrBufPtr = 0;
+ TDHead->Next = (USB_INT32U) TDTail;
+ TDTail->Next = 0;
+ TDHead->BufEnd = (USB_INT32U)(buffer + (buffer_len - 1));
+ TDTail->BufEnd = 0;
+
+ ed->HeadTd = (USB_INT32U)TDHead | ((ed->HeadTd) & 0x00000002);
+ ed->TailTd = (USB_INT32U)TDTail;
+ ed->Next = 0;
+
+ if (ed == EDCtrl) {
+ LPC_USB->HcControlHeadED = (USB_INT32U)ed;
+ LPC_USB->HcCommandStatus = LPC_USB->HcCommandStatus | OR_CMD_STATUS_CLF;
+ LPC_USB->HcControl = LPC_USB->HcControl | OR_CONTROL_CLE;
+ } else {
+ LPC_USB->HcBulkHeadED = (USB_INT32U)ed;
+ LPC_USB->HcCommandStatus = LPC_USB->HcCommandStatus | OR_CMD_STATUS_BLF;
+ LPC_USB->HcControl = LPC_USB->HcControl | OR_CONTROL_BLE;
+ }
+
+ Host_WDHWait();
+
+// if (!(TDHead->Control & 0xF0000000)) {
+ if (!HOST_TDControlStatus) {
+ return (OK);
+ } else {
+ return (ERR_TD_FAIL);
+ }
+}
+
+/*
+**************************************************************************************************************
+* ENUMERATE THE DEVICE
+*
+* Description: This function is used to enumerate the device connected
+*
+* Arguments : None
+*
+* Returns : None
+*
+**************************************************************************************************************
+*/
+
+USB_INT32S Host_EnumDev (void)
+{
+ USB_INT32S rc;
+
+ PRINT_Log("Connect a Mass Storage device:\r\n");
+ while (!HOST_RhscIntr);
+ Host_DelayMS(100); /* USB 2.0 spec says atleast 50ms delay beore port reset */
+ LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRS; // Initiate port reset
+ while (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_PRS)
+ ; // Wait for port reset to complete...
+ LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC; // ...and clear port reset signal
+ Host_DelayMS(200); /* Wait for 100 MS after port reset */
+
+ EDCtrl->Control = 8 << 16; /* Put max pkt size = 8 */
+ /* Read first 8 bytes of device desc */
+ rc = HOST_GET_DESCRIPTOR(USB_DESCRIPTOR_TYPE_DEVICE, 0, TDBuffer, 8);
+ if (rc != OK) {
+ PRINT_Err(rc);
+ return (rc);
+ }
+ EDCtrl->Control = TDBuffer[7] << 16; /* Get max pkt size of endpoint 0 */
+ rc = HOST_SET_ADDRESS(1); /* Set the device address to 1 */
+ if (rc != OK) {
+ PRINT_Err(rc);
+ return (rc);
+ }
+ Host_DelayMS(2);
+ EDCtrl->Control = (EDCtrl->Control) | 1; /* Modify control pipe with address 1 */
+ /* Get the configuration descriptor */
+ rc = HOST_GET_DESCRIPTOR(USB_DESCRIPTOR_TYPE_CONFIGURATION, 0, TDBuffer, 9);
+ if (rc != OK) {
+ PRINT_Err(rc);
+ return (rc);
+ }
+ /* Get the first configuration data */
+ rc = HOST_GET_DESCRIPTOR(USB_DESCRIPTOR_TYPE_CONFIGURATION, 0, TDBuffer, ReadLE16U(&TDBuffer[2]));
+ if (rc != OK) {
+ PRINT_Err(rc);
+ return (rc);
+ }
+ rc = MS_ParseConfiguration(); /* Parse the configuration */
+ if (rc != OK) {
+ PRINT_Err(rc);
+ return (rc);
+ }
+ rc = USBH_SET_CONFIGURATION(1); /* Select device configuration 1 */
+ if (rc != OK) {
+ PRINT_Err(rc);
+ }
+ Host_DelayMS(100); /* Some devices may require this delay */
+ return (rc);
+}
+
+/*
+**************************************************************************************************************
+* RECEIVE THE CONTROL INFORMATION
+*
+* Description: This function is used to receive the control information
+*
+* Arguments : bm_request_type
+* b_request
+* w_value
+* w_index
+* w_length
+* buffer
+*
+* Returns : OK if Success
+* ERROR if Failed
+*
+**************************************************************************************************************
+*/
+
+USB_INT32S Host_CtrlRecv ( USB_INT08U bm_request_type,
+ USB_INT08U b_request,
+ USB_INT16U w_value,
+ USB_INT16U w_index,
+ USB_INT16U w_length,
+ volatile USB_INT08U *buffer)
+{
+ USB_INT32S rc;
+
+
+ Host_FillSetup(bm_request_type, b_request, w_value, w_index, w_length);
+ rc = Host_ProcessTD(EDCtrl, TD_SETUP, TDBuffer, 8);
+ if (rc == OK) {
+ if (w_length) {
+ rc = Host_ProcessTD(EDCtrl, TD_IN, TDBuffer, w_length);
+ }
+ if (rc == OK) {
+ rc = Host_ProcessTD(EDCtrl, TD_OUT, NULL, 0);
+ }
+ }
+ return (rc);
+}
+
+/*
+**************************************************************************************************************
+* SEND THE CONTROL INFORMATION
+*
+* Description: This function is used to send the control information
+*
+* Arguments : None
+*
+* Returns : OK if Success
+* ERR_INVALID_BOOTSIG if Failed
+*
+**************************************************************************************************************
+*/
+
+USB_INT32S Host_CtrlSend ( USB_INT08U bm_request_type,
+ USB_INT08U b_request,
+ USB_INT16U w_value,
+ USB_INT16U w_index,
+ USB_INT16U w_length,
+ volatile USB_INT08U *buffer)
+{
+ USB_INT32S rc;
+
+
+ Host_FillSetup(bm_request_type, b_request, w_value, w_index, w_length);
+
+ rc = Host_ProcessTD(EDCtrl, TD_SETUP, TDBuffer, 8);
+ if (rc == OK) {
+ if (w_length) {
+ rc = Host_ProcessTD(EDCtrl, TD_OUT, TDBuffer, w_length);
+ }
+ if (rc == OK) {
+ rc = Host_ProcessTD(EDCtrl, TD_IN, NULL, 0);
+ }
+ }
+ return (rc);
+}
+
+/*
+**************************************************************************************************************
+* FILL SETUP PACKET
+*
+* Description: This function is used to fill the setup packet
+*
+* Arguments : None
+*
+* Returns : OK if Success
+* ERR_INVALID_BOOTSIG if Failed
+*
+**************************************************************************************************************
+*/
+
+void Host_FillSetup (USB_INT08U bm_request_type,
+ USB_INT08U b_request,
+ USB_INT16U w_value,
+ USB_INT16U w_index,
+ USB_INT16U w_length)
+{
+ int i;
+ for (i=0;i<w_length;i++)
+ TDBuffer[i] = 0;
+
+ TDBuffer[0] = bm_request_type;
+ TDBuffer[1] = b_request;
+ WriteLE16U(&TDBuffer[2], w_value);
+ WriteLE16U(&TDBuffer[4], w_index);
+ WriteLE16U(&TDBuffer[6], w_length);
+}
+
+
+
+/*
+**************************************************************************************************************
+* INITIALIZE THE TRANSFER DESCRIPTOR
+*
+* Description: This function initializes transfer descriptor
+*
+* Arguments : Pointer to TD structure
+*
+* Returns : None
+*
+**************************************************************************************************************
+*/
+
+void Host_TDInit (volatile HCTD *td)
+{
+
+ td->Control = 0;
+ td->CurrBufPtr = 0;
+ td->Next = 0;
+ td->BufEnd = 0;
+}
+
+/*
+**************************************************************************************************************
+* INITIALIZE THE ENDPOINT DESCRIPTOR
+*
+* Description: This function initializes endpoint descriptor
+*
+* Arguments : Pointer to ED strcuture
+*
+* Returns : None
+*
+**************************************************************************************************************
+*/
+
+void Host_EDInit (volatile HCED *ed)
+{
+
+ ed->Control = 0;
+ ed->TailTd = 0;
+ ed->HeadTd = 0;
+ ed->Next = 0;
+}
+
+/*
+**************************************************************************************************************
+* INITIALIZE HOST CONTROLLER COMMUNICATIONS AREA
+*
+* Description: This function initializes host controller communications area
+*
+* Arguments : Pointer to HCCA
+*
+* Returns :
+*
+**************************************************************************************************************
+*/
+
+void Host_HCCAInit (volatile HCCA *hcca)
+{
+ USB_INT32U i;
+
+
+ for (i = 0; i < 32; i++) {
+
+ hcca->IntTable[i] = 0;
+ hcca->FrameNumber = 0;
+ hcca->DoneHead = 0;
+ }
+
+}
+
+/*
+**************************************************************************************************************
+* WAIT FOR WDH INTERRUPT
+*
+* Description: This function is infinite loop which breaks when ever a WDH interrupt rises
+*
+* Arguments : None
+*
+* Returns : None
+*
+**************************************************************************************************************
+*/
+
+void Host_WDHWait (void)
+{
+ while (!HOST_WdhIntr) {
+ ;
+ }
+ HOST_WdhIntr = 0;
+}
+
+/*
+**************************************************************************************************************
+* READ LE 32U
+*
+* Description: This function is used to read an unsigned integer from a charecter buffer in the platform
+* containing little endian processor
+*
+* Arguments : pmem Pointer to the charecter buffer
+*
+* Returns : val Unsigned integer
+*
+**************************************************************************************************************
+*/
+
+USB_INT32U ReadLE32U (volatile USB_INT08U *pmem)
+{
+ USB_INT32U val;
+
+ ((USB_INT08U *)&val)[0] = pmem[0];
+ ((USB_INT08U *)&val)[1] = pmem[1];
+ ((USB_INT08U *)&val)[2] = pmem[2];
+ ((USB_INT08U *)&val)[3] = pmem[3];
+
+ return (val);
+}
+
+/*
+**************************************************************************************************************
+* WRITE LE 32U
+*
+* Description: This function is used to write an unsigned integer into a charecter buffer in the platform
+* containing little endian processor.
+*
+* Arguments : pmem Pointer to the charecter buffer
+* val Integer value to be placed in the charecter buffer
+*
+* Returns : None
+*
+**************************************************************************************************************
+*/
+
+void WriteLE32U (volatile USB_INT08U *pmem,
+ USB_INT32U val)
+{
+ pmem[0] = ((USB_INT08U *)&val)[0];
+ pmem[1] = ((USB_INT08U *)&val)[1];
+ pmem[2] = ((USB_INT08U *)&val)[2];
+ pmem[3] = ((USB_INT08U *)&val)[3];
+}
+
+/*
+**************************************************************************************************************
+* READ LE 16U
+*
+* Description: This function is used to read an unsigned short integer from a charecter buffer in the platform
+* containing little endian processor
+*
+* Arguments : pmem Pointer to the charecter buffer
+*
+* Returns : val Unsigned short integer
+*
+**************************************************************************************************************
+*/
+
+USB_INT16U ReadLE16U (volatile USB_INT08U *pmem)
+{
+ USB_INT16U val;
+
+ ((USB_INT08U *)&val)[0] = pmem[0];
+ ((USB_INT08U *)&val)[1] = pmem[1];
+
+
+ return (val);
+}
+
+/*
+**************************************************************************************************************
+* WRITE LE 16U
+*
+* Description: This function is used to write an unsigned short integer into a charecter buffer in the
+* platform containing little endian processor
+*
+* Arguments : pmem Pointer to the charecter buffer
+* val Value to be placed in the charecter buffer
+*
+* Returns : None
+*
+**************************************************************************************************************
+*/
+
+void WriteLE16U (volatile USB_INT08U *pmem,
+ USB_INT16U val)
+{
+ pmem[0] = ((USB_INT08U *)&val)[0];
+ pmem[1] = ((USB_INT08U *)&val)[1];
+}
+
+/*
+**************************************************************************************************************
+* READ BE 32U
+*
+* Description: This function is used to read an unsigned integer from a charecter buffer in the platform
+* containing big endian processor
+*
+* Arguments : pmem Pointer to the charecter buffer
+*
+* Returns : val Unsigned integer
+*
+**************************************************************************************************************
+*/
+
+USB_INT32U ReadBE32U (volatile USB_INT08U *pmem)
+{
+ USB_INT32U val;
+
+ ((USB_INT08U *)&val)[0] = pmem[3];
+ ((USB_INT08U *)&val)[1] = pmem[2];
+ ((USB_INT08U *)&val)[2] = pmem[1];
+ ((USB_INT08U *)&val)[3] = pmem[0];
+
+ return (val);
+}
+
+/*
+**************************************************************************************************************
+* WRITE BE 32U
+*
+* Description: This function is used to write an unsigned integer into a charecter buffer in the platform
+* containing big endian processor
+*
+* Arguments : pmem Pointer to the charecter buffer
+* val Value to be placed in the charecter buffer
+*
+* Returns : None
+*
+**************************************************************************************************************
+*/
+
+void WriteBE32U (volatile USB_INT08U *pmem,
+ USB_INT32U val)
+{
+ pmem[0] = ((USB_INT08U *)&val)[3];
+ pmem[1] = ((USB_INT08U *)&val)[2];
+ pmem[2] = ((USB_INT08U *)&val)[1];
+ pmem[3] = ((USB_INT08U *)&val)[0];
+
+}
+
+/*
+**************************************************************************************************************
+* READ BE 16U
+*
+* Description: This function is used to read an unsigned short integer from a charecter buffer in the platform
+* containing big endian processor
+*
+* Arguments : pmem Pointer to the charecter buffer
+*
+* Returns : val Unsigned short integer
+*
+**************************************************************************************************************
+*/
+
+USB_INT16U ReadBE16U (volatile USB_INT08U *pmem)
+{
+ USB_INT16U val;
+
+
+ ((USB_INT08U *)&val)[0] = pmem[1];
+ ((USB_INT08U *)&val)[1] = pmem[0];
+
+ return (val);
+}
+
+/*
+**************************************************************************************************************
+* WRITE BE 16U
+*
+* Description: This function is used to write an unsigned short integer into the charecter buffer in the
+* platform containing big endian processor
+*
+* Arguments : pmem Pointer to the charecter buffer
+* val Value to be placed in the charecter buffer
+*
+* Returns : None
+*
+**************************************************************************************************************
+*/
+
+void WriteBE16U (volatile USB_INT08U *pmem,
+ USB_INT16U val)
+{
+ pmem[0] = ((USB_INT08U *)&val)[1];
+ pmem[1] = ((USB_INT08U *)&val)[0];
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Host/usbhost_lpc17xx.h Thu Jan 21 01:15:42 2010 +0000
@@ -0,0 +1,257 @@
+/*
+**************************************************************************************************************
+* NXP USB Host Stack
+*
+* (c) Copyright 2008, NXP SemiConductors
+* (c) Copyright 2008, OnChip Technologies LLC
+* All Rights Reserved
+*
+* www.nxp.com
+* www.onchiptech.com
+*
+* File : usbhost_lpc17xx.h
+* Programmer(s) : Ravikanth.P
+* Version :
+*
+**************************************************************************************************************
+*/
+
+#ifndef USBHOST_LPC17xx_H
+#define USBHOST_LPC17xx_H
+
+/*
+**************************************************************************************************************
+* INCLUDE HEADER FILES
+**************************************************************************************************************
+*/
+
+#include "usbhost_inc.h"
+
+/*
+**************************************************************************************************************
+* PRINT CONFIGURATION
+**************************************************************************************************************
+*/
+
+#define PRINT_ENABLE 1
+
+#if PRINT_ENABLE
+#define PRINT_Log(...) printf(__VA_ARGS__)
+#define PRINT_Err(rc) printf("ERROR: In %s at Line %u - rc = %d\r\n", __FUNCTION__, __LINE__, rc)
+
+#else
+#define PRINT_Log(...) do {} while(0)
+#define PRINT_Err(rc) do {} while(0)
+
+#endif
+
+/*
+**************************************************************************************************************
+* GENERAL DEFINITIONS
+**************************************************************************************************************
+*/
+
+#define DESC_LENGTH(x) x[0]
+#define DESC_TYPE(x) x[1]
+
+
+#define HOST_GET_DESCRIPTOR(descType, descIndex, data, length) \
+ Host_CtrlRecv(USB_DEVICE_TO_HOST | USB_RECIPIENT_DEVICE, GET_DESCRIPTOR, \
+ (descType << 8)|(descIndex), 0, length, data)
+
+#define HOST_SET_ADDRESS(new_addr) \
+ Host_CtrlSend(USB_HOST_TO_DEVICE | USB_RECIPIENT_DEVICE, SET_ADDRESS, \
+ new_addr, 0, 0, NULL)
+
+#define USBH_SET_CONFIGURATION(configNum) \
+ Host_CtrlSend(USB_HOST_TO_DEVICE | USB_RECIPIENT_DEVICE, SET_CONFIGURATION, \
+ configNum, 0, 0, NULL)
+
+#define USBH_SET_INTERFACE(ifNum, altNum) \
+ Host_CtrlSend(USB_HOST_TO_DEVICE | USB_RECIPIENT_INTERFACE, SET_INTERFACE, \
+ altNum, ifNum, 0, NULL)
+
+/*
+**************************************************************************************************************
+* OHCI OPERATIONAL REGISTER FIELD DEFINITIONS
+**************************************************************************************************************
+*/
+
+ /* ------------------ HcControl Register --------------------- */
+#define OR_CONTROL_CLE 0x00000010
+#define OR_CONTROL_BLE 0x00000020
+#define OR_CONTROL_HCFS 0x000000C0
+#define OR_CONTROL_HC_OPER 0x00000080
+ /* ----------------- HcCommandStatus Register ----------------- */
+#define OR_CMD_STATUS_HCR 0x00000001
+#define OR_CMD_STATUS_CLF 0x00000002
+#define OR_CMD_STATUS_BLF 0x00000004
+ /* --------------- HcInterruptStatus Register ----------------- */
+#define OR_INTR_STATUS_WDH 0x00000002
+#define OR_INTR_STATUS_RHSC 0x00000040
+ /* --------------- HcInterruptEnable Register ----------------- */
+#define OR_INTR_ENABLE_WDH 0x00000002
+#define OR_INTR_ENABLE_RHSC 0x00000040
+#define OR_INTR_ENABLE_MIE 0x80000000
+ /* ---------------- HcRhDescriptorA Register ------------------ */
+#define OR_RH_STATUS_LPSC 0x00010000
+#define OR_RH_STATUS_DRWE 0x00008000
+ /* -------------- HcRhPortStatus[1:NDP] Register -------------- */
+#define OR_RH_PORT_CCS 0x00000001
+#define OR_RH_PORT_PRS 0x00000010
+#define OR_RH_PORT_CSC 0x00010000
+#define OR_RH_PORT_PRSC 0x00100000
+
+
+/*
+**************************************************************************************************************
+* FRAME INTERVAL
+**************************************************************************************************************
+*/
+
+#define FI 0x2EDF /* 12000 bits per frame (-1) */
+#define DEFAULT_FMINTERVAL ((((6 * (FI - 210)) / 7) << 16) | FI)
+
+/*
+**************************************************************************************************************
+* TRANSFER DESCRIPTOR CONTROL FIELDS
+**************************************************************************************************************
+*/
+
+#define TD_ROUNDING (USB_INT32U) (0x00040000) /* Buffer Rounding */
+#define TD_SETUP (USB_INT32U)(0) /* Direction of Setup Packet */
+#define TD_IN (USB_INT32U)(0x00100000) /* Direction In */
+#define TD_OUT (USB_INT32U)(0x00080000) /* Direction Out */
+#define TD_DELAY_INT(x) (USB_INT32U)((x) << 21) /* Delay Interrupt */
+#define TD_TOGGLE_0 (USB_INT32U)(0x02000000) /* Toggle 0 */
+#define TD_TOGGLE_1 (USB_INT32U)(0x03000000) /* Toggle 1 */
+#define TD_CC (USB_INT32U)(0xF0000000) /* Completion Code */
+
+/*
+**************************************************************************************************************
+* USB STANDARD REQUEST DEFINITIONS
+**************************************************************************************************************
+*/
+
+#define USB_DESCRIPTOR_TYPE_DEVICE 1
+#define USB_DESCRIPTOR_TYPE_CONFIGURATION 2
+#define USB_DESCRIPTOR_TYPE_INTERFACE 4
+#define USB_DESCRIPTOR_TYPE_ENDPOINT 5
+ /* ----------- Control RequestType Fields ----------- */
+#define USB_DEVICE_TO_HOST 0x80
+#define USB_HOST_TO_DEVICE 0x00
+#define USB_REQUEST_TYPE_CLASS 0x20
+#define USB_RECIPIENT_DEVICE 0x00
+#define USB_RECIPIENT_INTERFACE 0x01
+ /* -------------- USB Standard Requests -------------- */
+#define SET_ADDRESS 5
+#define GET_DESCRIPTOR 6
+#define SET_CONFIGURATION 9
+#define SET_INTERFACE 11
+
+/*
+**************************************************************************************************************
+* TYPE DEFINITIONS
+**************************************************************************************************************
+*/
+
+typedef struct hcEd { /* ----------- HostController EndPoint Descriptor ------------- */
+ volatile USB_INT32U Control; /* Endpoint descriptor control */
+ volatile USB_INT32U TailTd; /* Physical address of tail in Transfer descriptor list */
+ volatile USB_INT32U HeadTd; /* Physcial address of head in Transfer descriptor list */
+ volatile USB_INT32U Next; /* Physical address of next Endpoint descriptor */
+} HCED;
+
+typedef struct hcTd { /* ------------ HostController Transfer Descriptor ------------ */
+ volatile USB_INT32U Control; /* Transfer descriptor control */
+ volatile USB_INT32U CurrBufPtr; /* Physical address of current buffer pointer */
+ volatile USB_INT32U Next; /* Physical pointer to next Transfer Descriptor */
+ volatile USB_INT32U BufEnd; /* Physical address of end of buffer */
+} HCTD;
+
+typedef struct hcca { /* ----------- Host Controller Communication Area ------------ */
+ volatile USB_INT32U IntTable[32]; /* Interrupt Table */
+ volatile USB_INT32U FrameNumber; /* Frame Number */
+ volatile USB_INT32U DoneHead; /* Done Head */
+ volatile USB_INT08U Reserved[116]; /* Reserved for future use */
+ volatile USB_INT08U Unknown[4]; /* Unused */
+} HCCA;
+
+/*
+**************************************************************************************************************
+* EXTERN DECLARATIONS
+**************************************************************************************************************
+*/
+
+extern volatile HCED *EDBulkIn; /* BulkIn endpoint descriptor structure */
+extern volatile HCED *EDBulkOut; /* BulkOut endpoint descriptor structure */
+extern volatile HCTD *TDHead; /* Head transfer descriptor structure */
+extern volatile HCTD *TDTail; /* Tail transfer descriptor structure */
+extern volatile USB_INT08U *TDBuffer; /* Current Buffer Pointer of transfer descriptor */
+extern volatile USB_INT08U *FATBuffer; /* Buffer used by FAT file system */
+extern volatile USB_INT08U *UserBuffer; /* Buffer used by application */
+
+/*
+**************************************************************************************************************
+* FUNCTION PROTOTYPES
+**************************************************************************************************************
+*/
+
+void Host_Init (void);
+
+//void USB_IRQHandler(void) __irq;
+extern "C" void USB_IRQHandler(void) __irq;
+
+USB_INT32S Host_EnumDev (void);
+
+USB_INT32S Host_ProcessTD(volatile HCED *ed,
+ volatile USB_INT32U token,
+ volatile USB_INT08U *buffer,
+ USB_INT32U buffer_len);
+
+void Host_DelayUS ( USB_INT32U delay);
+void Host_DelayMS ( USB_INT32U delay);
+
+
+void Host_TDInit (volatile HCTD *td);
+void Host_EDInit (volatile HCED *ed);
+void Host_HCCAInit (volatile HCCA *hcca);
+
+USB_INT32S Host_CtrlRecv ( USB_INT08U bm_request_type,
+ USB_INT08U b_request,
+ USB_INT16U w_value,
+ USB_INT16U w_index,
+ USB_INT16U w_length,
+ volatile USB_INT08U *buffer);
+
+USB_INT32S Host_CtrlSend ( USB_INT08U bm_request_type,
+ USB_INT08U b_request,
+ USB_INT16U w_value,
+ USB_INT16U w_index,
+ USB_INT16U w_length,
+ volatile USB_INT08U *buffer);
+
+void Host_FillSetup( USB_INT08U bm_request_type,
+ USB_INT08U b_request,
+ USB_INT16U w_value,
+ USB_INT16U w_index,
+ USB_INT16U w_length);
+
+
+void Host_WDHWait (void);
+
+
+USB_INT32U ReadLE32U (volatile USB_INT08U *pmem);
+void WriteLE32U (volatile USB_INT08U *pmem,
+ USB_INT32U val);
+USB_INT16U ReadLE16U (volatile USB_INT08U *pmem);
+void WriteLE16U (volatile USB_INT08U *pmem,
+ USB_INT16U val);
+USB_INT32U ReadBE32U (volatile USB_INT08U *pmem);
+void WriteBE32U (volatile USB_INT08U *pmem,
+ USB_INT32U val);
+USB_INT16U ReadBE16U (volatile USB_INT08U *pmem);
+void WriteBE16U (volatile USB_INT08U *pmem,
+ USB_INT16U val);
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Include/usbhost_cpu.h Thu Jan 21 01:15:42 2010 +0000
@@ -0,0 +1,35 @@
+/*
+**************************************************************************************************************
+* NXP USB Host Stack
+*
+* (c) Copyright 2008, NXP SemiConductors
+* (c) Copyright 2008, OnChip Technologies LLC
+* All Rights Reserved
+*
+* www.nxp.com
+* www.onchiptech.com
+*
+* File : usbhost_cpu.h
+* Programmer(s) : Ravikanth.P
+* Version :
+*
+**************************************************************************************************************
+*/
+
+#ifndef USBHOST_CPU_H
+#define USBHOST_CPU_H
+
+/*
+**************************************************************************************************************
+* TYPE DEFINITIONS OF DATA TYPES
+**************************************************************************************************************
+*/
+
+typedef unsigned int USB_INT32U;
+typedef signed int USB_INT32S;
+typedef unsigned short USB_INT16U;
+typedef signed short USB_INT16S;
+typedef unsigned char USB_INT08U;
+typedef signed char USB_INT08S;
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Include/usbhost_err.h Thu Jan 21 01:15:42 2010 +0000
@@ -0,0 +1,63 @@
+/*
+**************************************************************************************************************
+* NXP USB Host Stack
+*
+* (c) Copyright 2008, NXP SemiConductors
+* (c) Copyright 2008, OnChip Technologies LLC
+* All Rights Reserved
+*
+* www.nxp.com
+* www.onchiptech.com
+*
+* File : usbhost_err.h
+* Programmer(s) : Ravikanth.P
+* Version :
+*
+**************************************************************************************************************
+*/
+
+#ifndef USBHOST_ERR_H
+#define USBHOST_ERR_H
+
+
+/*
+**************************************************************************************************************
+* GENERAL DEFINITIONS
+**************************************************************************************************************
+*/
+
+#define OK 0
+#define MATCH_FOUND 0
+
+/*
+**************************************************************************************************************
+* HOST CONTROLLER SPECIFIC ERROR CODES
+**************************************************************************************************************
+*/
+
+#define ERR_TD_FAIL -1
+
+/*
+**************************************************************************************************************
+* MASS STORAGE SPECIFIC ERROR CODES
+**************************************************************************************************************
+*/
+
+#define ERR_MS_CMD_FAILED -10
+#define ERR_BAD_CONFIGURATION -11
+#define ERR_NO_MS_INTERFACE -12
+
+/*
+**************************************************************************************************************
+* FAT SPECIFIC ERROR CODES
+**************************************************************************************************************
+*/
+
+#define MATCH_NOT_FOUND -20
+#define ERR_FAT_NOT_SUPPORTED -21
+#define ERR_OPEN_LIMIT_REACHED -22
+#define ERR_INVALID_BOOT_SIG -23
+#define ERR_INVALID_BOOT_SEC -24
+#define ERR_ROOT_DIR_FULL -25
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Include/usbhost_inc.h Thu Jan 21 01:15:42 2010 +0000
@@ -0,0 +1,55 @@
+/*
+**************************************************************************************************************
+* NXP USB Host Stack
+*
+* (c) Copyright 2008, NXP SemiConductors
+* (c) Copyright 2008, OnChip Technologies LLC
+* All Rights Reserved
+*
+* www.nxp.com
+* www.onchiptech.com
+*
+* File : usbhost_inc.h
+* Programmer(s) : Ravikanth.P
+* Version :
+*
+**************************************************************************************************************
+*/
+
+#ifndef USBHOST_INC_H
+#define USBHOST_INC_H
+
+/*
+**************************************************************************************************************
+* INCLUDE HEADER FILES
+**************************************************************************************************************
+*/
+
+#include "usbhost_cpu.h"
+#include "usbhost_err.h"
+//#include "Uart/usbhost_uart.h"
+#include "Host/usbhost_lpc17xx.h"
+#include "MassStorage/usbhost_ms.h"
+#include "Fat/usbhost_fat.h"
+//#include "LPC17xx.h"
+#include "mbed.h"
+
+#ifdef TARGET_LPC2368
+// [iva2k]
+
+// fix for bad define in LPC23xx.h
+#if LPC_USB_BASE != 0xFFE0C000
+#undef LPC_USB_BASE
+#define LPC_USB_BASE 0xFFE0C000
+#define LPC_USB ((LPC_USB_TypeDef *)LPC_USB_BASE)
+#endif
+
+#endif
+
+#ifdef TARGET_LPC2368
+static __INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
+{
+ NVIC->VectPriority[(uint32_t)(IRQn)] = ((priority) & (1 << __NVIC_PRIO_BITS -1 ) );
+}
+#endif
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/MassStorage/usbhost_ms.c Thu Jan 21 01:15:42 2010 +0000
@@ -0,0 +1,456 @@
+/*
+**************************************************************************************************************
+* NXP USB Host Stack
+*
+* (c) Copyright 2008, NXP SemiConductors
+* (c) Copyright 2008, OnChip Technologies LLC
+* All Rights Reserved
+*
+* www.nxp.com
+* www.onchiptech.com
+*
+* File : usbhost_ms.c
+* Programmer(s) : Ravikanth.P
+* Version :
+*
+**************************************************************************************************************
+*/
+
+/*
+**************************************************************************************************************
+* INCLUDE HEADER FILES
+**************************************************************************************************************
+*/
+
+#include "usbhost_ms.h"
+
+/*
+**************************************************************************************************************
+* GLOBAL VARIABLES
+**************************************************************************************************************
+*/
+
+USB_INT32U MS_BlkSize;
+
+/*
+**************************************************************************************************************
+* INITIALIZE MASS STORAGE INTERFACE
+*
+* Description: This function initializes the mass storage interface
+*
+* Arguments : None
+*
+* Returns : OK if Success
+* ERR_INVALID_BOOTSIG if Failed
+*
+**************************************************************************************************************
+*/
+
+USB_INT32S MS_Init (USB_INT32U *blkSize, USB_INT32U *numBlks, USB_INT08U *inquiryResult)
+{
+ USB_INT08U retry;
+ USB_INT32S rc;
+
+ MS_GetMaxLUN(); /* Get maximum logical unit number */
+ retry = 80;
+ while(retry) {
+ rc = MS_TestUnitReady(); /* Test whether the unit is ready */
+ if (rc == OK) {
+ break;
+ }
+ MS_GetSenseInfo(); /* Get sense information */
+ retry--;
+ }
+ if (rc != OK) {
+ PRINT_Err(rc);
+ return (rc);
+ }
+ rc = MS_ReadCapacity(numBlks, blkSize); /* Read capacity of the disk */
+ MS_BlkSize = *blkSize; // Set global
+ rc = MS_Inquire (inquiryResult);
+ return (rc);
+}
+/*
+**************************************************************************************************************
+* PARSE THE CONFIGURATION
+*
+* Description: This function is used to parse the configuration
+*
+* Arguments : None
+*
+* Returns : OK if Success
+* ERR_INVALID_BOOTSIG if Failed
+*
+**************************************************************************************************************
+*/
+
+USB_INT32S MS_ParseConfiguration (void)
+{
+ volatile USB_INT08U *desc_ptr;
+ USB_INT08U ms_int_found;
+
+
+ desc_ptr = TDBuffer;
+ ms_int_found = 0;
+
+ if (desc_ptr[1] != USB_DESCRIPTOR_TYPE_CONFIGURATION) {
+ return (ERR_BAD_CONFIGURATION);
+ }
+ desc_ptr += desc_ptr[0];
+
+ while (desc_ptr != TDBuffer + ReadLE16U(&TDBuffer[2])) {
+// while (desc_ptr != TDBuffer + *((USB_INT16U *) &TDBuffer[2])) {
+
+ switch (desc_ptr[1]) {
+
+ case USB_DESCRIPTOR_TYPE_INTERFACE: /* If it is an interface descriptor */
+ if (desc_ptr[5] == MASS_STORAGE_CLASS && /* check if the class is mass storage */
+ desc_ptr[6] == MASS_STORAGE_SUBCLASS_SCSI && /* check if the subclass is SCSI */
+ desc_ptr[7] == MASS_STORAGE_PROTOCOL_BO) { /* check if the protocol is Bulk only */
+ ms_int_found = 1;
+ desc_ptr += desc_ptr[0]; /* Move to next descriptor start */
+ }
+ break;
+
+ case USB_DESCRIPTOR_TYPE_ENDPOINT: /* If it is an endpoint descriptor */
+ if ((desc_ptr[3] & 0x03) == 0x02) { /* If it is Bulk endpoint */
+ if (desc_ptr[2] & 0x80) { /* If it is In endpoint */
+ EDBulkIn->Control = 1 | /* USB address */
+ ((desc_ptr[2] & 0x7F) << 7) | /* Endpoint address */
+ (2 << 11) | /* direction */
+ (ReadLE16U(&desc_ptr[4]) << 16); /* MaxPkt Size */
+ desc_ptr += desc_ptr[0]; /* Move to next descriptor start */
+ } else { /* If it is Out endpoint */
+ EDBulkOut->Control = 1 | /* USB address */
+ ((desc_ptr[2] & 0x7F) << 7) | /* Endpoint address */
+ (1 << 11) | /* direction */
+ (ReadLE16U(&desc_ptr[4]) << 16); /* MaxPkt Size */
+ desc_ptr += desc_ptr[0]; /* Move to next descriptor start */
+ }
+ } else { /* If it is not bulk end point */
+ desc_ptr += desc_ptr[0]; /* Move to next descriptor start */
+ }
+ break;
+
+ default: /* If the descriptor is neither interface nor endpoint */
+ desc_ptr += desc_ptr[0]; /* Move to next descriptor start */
+ break;
+ }
+ }
+ if (ms_int_found) {
+ PRINT_Log("Mass Storage device connected\r\n");
+ return (OK);
+ } else {
+ PRINT_Log("Not a Mass Storage device\r\n");
+ return (ERR_NO_MS_INTERFACE);
+ }
+}
+
+/*
+**************************************************************************************************************
+* GET MAXIMUM LOGICAL UNIT
+*
+* Description: This function returns the maximum logical unit from the device
+*
+* Arguments : None
+*
+* Returns : OK if Success
+* ERR_INVALID_BOOTSIG if Failed
+*
+**************************************************************************************************************
+*/
+
+USB_INT32S MS_GetMaxLUN (void)
+{
+ USB_INT32S rc;
+
+
+ rc = Host_CtrlRecv(USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE,
+ MS_GET_MAX_LUN_REQ,
+ 0,
+ 0,
+ 1,
+ TDBuffer);
+ return (rc);
+}
+
+/*
+**************************************************************************************************************
+* GET SENSE INFORMATION
+*
+* Description: This function is used to get sense information from the device
+*
+* Arguments : None
+*
+* Returns : OK if Success
+* ERROR if Failed
+*
+**************************************************************************************************************
+*/
+
+USB_INT32S MS_GetSenseInfo (void)
+{
+ USB_INT32S rc;
+
+
+ Fill_MSCommand(0, 0, 0, MS_DATA_DIR_IN, SCSI_CMD_REQUEST_SENSE, 6);
+ rc = Host_ProcessTD(EDBulkOut, TD_OUT, TDBuffer, CBW_SIZE);
+ if (rc == OK) {
+ rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, 18);
+ if (rc == OK) {
+ rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, CSW_SIZE);
+ if (rc == OK) {
+ if (TDBuffer[12] != 0) {
+ rc = ERR_MS_CMD_FAILED;
+ }
+ }
+ }
+ }
+ return (rc);
+}
+
+/*
+**************************************************************************************************************
+* TEST UNIT READY
+*
+* Description: This function is used to test whether the unit is ready or not
+*
+* Arguments : None
+*
+* Returns : OK if Success
+* ERROR if Failed
+*
+**************************************************************************************************************
+*/
+
+USB_INT32S MS_TestUnitReady (void)
+{
+ USB_INT32S rc;
+
+
+ Fill_MSCommand(0, 0, 0, MS_DATA_DIR_NONE, SCSI_CMD_TEST_UNIT_READY, 6);
+ rc = Host_ProcessTD(EDBulkOut, TD_OUT, TDBuffer, CBW_SIZE);
+ if (rc == OK) {
+ rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, CSW_SIZE);
+ if (rc == OK) {
+ if (TDBuffer[12] != 0) {
+ rc = ERR_MS_CMD_FAILED;
+ }
+ }
+ }
+ return (rc);
+}
+
+/*
+**************************************************************************************************************
+* READ CAPACITY
+*
+* Description: This function is used to read the capacity of the mass storage device
+*
+* Arguments : None
+*
+* Returns : OK if Success
+* ERROR if Failed
+*
+**************************************************************************************************************
+*/
+
+USB_INT32S MS_ReadCapacity (USB_INT32U *numBlks, USB_INT32U *blkSize)
+{
+ USB_INT32S rc;
+
+
+ Fill_MSCommand(0, 0, 0, MS_DATA_DIR_IN, SCSI_CMD_READ_CAPACITY, 10);
+ rc = Host_ProcessTD(EDBulkOut, TD_OUT, TDBuffer, CBW_SIZE);
+ if (rc == OK) {
+ rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, 8);
+ if (rc == OK) {
+ if (numBlks)
+ *numBlks = ReadBE32U(&TDBuffer[0]);
+ if (blkSize)
+ *blkSize = ReadBE32U(&TDBuffer[4]);
+ rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, CSW_SIZE);
+ if (rc == OK) {
+ if (TDBuffer[12] != 0) {
+ rc = ERR_MS_CMD_FAILED;
+ }
+ }
+ }
+ }
+ return (rc);
+}
+
+
+
+USB_INT32S MS_Inquire (USB_INT08U *response)
+{
+ USB_INT32S rc;
+ USB_INT32U i;
+
+ Fill_MSCommand(0, 0, 0, MS_DATA_DIR_IN, SCSI_CMD_INQUIRY, 6);
+ rc = Host_ProcessTD(EDBulkOut, TD_OUT, TDBuffer, CBW_SIZE);
+ if (rc == OK) {
+ rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, INQUIRY_LENGTH);
+ if (rc == OK) {
+ if (response) {
+ for ( i = 0; i < INQUIRY_LENGTH; i++ )
+ *response++ = *TDBuffer++;
+#if 0
+ MemCpy (response, TDBuffer, INQUIRY_LENGTH);
+ StrNullTrailingSpace (response->vendorID, SCSI_INQUIRY_VENDORCHARS);
+ StrNullTrailingSpace (response->productID, SCSI_INQUIRY_PRODUCTCHARS);
+ StrNullTrailingSpace (response->productRev, SCSI_INQUIRY_REVCHARS);
+#endif
+ }
+ rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, CSW_SIZE);
+ if (rc == OK) {
+ if (TDBuffer[12] != 0) { // bCSWStatus byte
+ rc = ERR_MS_CMD_FAILED;
+ }
+ }
+ }
+ }
+ return (rc);
+}
+
+/*
+**************************************************************************************************************
+* RECEIVE THE BULK DATA
+*
+* Description: This function is used to receive the bulk data
+*
+* Arguments : None
+*
+* Returns : OK if Success
+* ERR_INVALID_BOOTSIG if Failed
+*
+**************************************************************************************************************
+*/
+
+USB_INT32S MS_BulkRecv ( USB_INT32U block_number,
+ USB_INT16U num_blocks,
+ volatile USB_INT08U *user_buffer)
+{
+ USB_INT32S rc;
+ int i;
+ volatile USB_INT08U *c = user_buffer;
+ for (i=0;i<MS_BlkSize*num_blocks;i++)
+ *c++ = 0;
+
+
+ Fill_MSCommand(block_number, MS_BlkSize, num_blocks, MS_DATA_DIR_IN, SCSI_CMD_READ_10, 10);
+
+ rc = Host_ProcessTD(EDBulkOut, TD_OUT, TDBuffer, CBW_SIZE);
+ if (rc == OK) {
+ rc = Host_ProcessTD(EDBulkIn, TD_IN, user_buffer, MS_BlkSize * num_blocks);
+ if (rc == OK) {
+ rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, CSW_SIZE);
+ if (rc == OK) {
+ if (TDBuffer[12] != 0) {
+ rc = ERR_MS_CMD_FAILED;
+ }
+ }
+ }
+ }
+ return (rc);
+}
+
+/*
+**************************************************************************************************************
+* SEND BULK DATA
+*
+* Description: This function is used to send the bulk data
+*
+* Arguments : None
+*
+* Returns : OK if Success
+* ERR_INVALID_BOOTSIG if Failed
+*
+**************************************************************************************************************
+*/
+
+USB_INT32S MS_BulkSend ( USB_INT32U block_number,
+ USB_INT16U num_blocks,
+ volatile USB_INT08U *user_buffer)
+{
+ USB_INT32S rc;
+
+
+ Fill_MSCommand(block_number, MS_BlkSize, num_blocks, MS_DATA_DIR_OUT, SCSI_CMD_WRITE_10, 10);
+
+ rc = Host_ProcessTD(EDBulkOut, TD_OUT, TDBuffer, CBW_SIZE);
+ if (rc == OK) {
+ rc = Host_ProcessTD(EDBulkOut, TD_OUT, user_buffer, MS_BlkSize * num_blocks);
+ if (rc == OK) {
+ rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, CSW_SIZE);
+ if (rc == OK) {
+ if (TDBuffer[12] != 0) {
+ rc = ERR_MS_CMD_FAILED;
+ }
+ }
+ }
+ }
+ return (rc);
+}
+
+/*
+**************************************************************************************************************
+* FILL MASS STORAGE COMMAND
+*
+* Description: This function is used to fill the mass storage command
+*
+* Arguments : None
+*
+* Returns : OK if Success
+* ERR_INVALID_BOOTSIG if Failed
+*
+**************************************************************************************************************
+*/
+
+void Fill_MSCommand (USB_INT32U block_number,
+ USB_INT32U block_size,
+ USB_INT16U num_blocks,
+ MS_DATA_DIR direction,
+ USB_INT08U scsi_cmd,
+ USB_INT08U scsi_cmd_len)
+{
+ USB_INT32U data_len;
+ static USB_INT32U tag_cnt = 0;
+ USB_INT32U cnt;
+
+
+ for (cnt = 0; cnt < CBW_SIZE; cnt++) {
+ TDBuffer[cnt] = 0;
+ }
+ switch(scsi_cmd) {
+
+ case SCSI_CMD_TEST_UNIT_READY:
+ data_len = 0;
+ break;
+ case SCSI_CMD_READ_CAPACITY:
+ data_len = 8;
+ break;
+ case SCSI_CMD_REQUEST_SENSE:
+ data_len = 18;
+ break;
+ case SCSI_CMD_INQUIRY:
+ data_len = 36;
+ break;
+ default:
+ data_len = block_size * num_blocks;
+ break;
+ }
+ WriteLE32U(TDBuffer, CBW_SIGNATURE);
+ WriteLE32U(&TDBuffer[4], tag_cnt);
+ WriteLE32U(&TDBuffer[8], data_len);
+ TDBuffer[12] = (direction == MS_DATA_DIR_NONE) ? 0 : direction;
+ TDBuffer[14] = scsi_cmd_len; /* Length of the CBW */
+ TDBuffer[15] = scsi_cmd;
+ if ((scsi_cmd == SCSI_CMD_REQUEST_SENSE)
+ || (scsi_cmd == SCSI_CMD_INQUIRY)) {
+ TDBuffer[19] = (USB_INT08U)data_len;
+ } else {
+ WriteBE32U(&TDBuffer[17], block_number);
+ }
+ WriteBE16U(&TDBuffer[22], num_blocks);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/MassStorage/usbhost_ms.h Thu Jan 21 01:15:42 2010 +0000
@@ -0,0 +1,101 @@
+/*
+**************************************************************************************************************
+* NXP USB Host Stack
+*
+* (c) Copyright 2008, NXP SemiConductors
+* (c) Copyright 2008, OnChip Technologies LLC
+* All Rights Reserved
+*
+* www.nxp.com
+* www.onchiptech.com
+*
+* File : usbhost_ms.h
+* Programmer(s) : Ravikanth.P
+* Version :
+*
+**************************************************************************************************************
+*/
+
+#ifndef USBHOST_MS_H
+#define USBHOST_MS_H
+
+/*
+**************************************************************************************************************
+* INCLUDE HEADER FILES
+**************************************************************************************************************
+*/
+
+#include "usbhost_inc.h"
+
+/*
+**************************************************************************************************************
+* MASS STORAGE SPECIFIC DEFINITIONS
+**************************************************************************************************************
+*/
+
+#define MS_GET_MAX_LUN_REQ 0xFE
+#define MASS_STORAGE_CLASS 0x08
+#define MASS_STORAGE_SUBCLASS_SCSI 0x06
+#define MASS_STORAGE_PROTOCOL_BO 0x50
+
+#define INQUIRY_LENGTH 36
+/*
+**************************************************************************************************************
+* SCSI SPECIFIC DEFINITIONS
+**************************************************************************************************************
+*/
+
+#define CBW_SIGNATURE 0x43425355
+#define CSW_SIGNATURE 0x53425355
+#define CBW_SIZE 31
+#define CSW_SIZE 13
+#define CSW_CMD_PASSED 0x00
+#define SCSI_CMD_REQUEST_SENSE 0x03
+#define SCSI_CMD_TEST_UNIT_READY 0x00
+#define SCSI_CMD_INQUIRY 0x12
+#define SCSI_CMD_READ_10 0x28
+#define SCSI_CMD_READ_CAPACITY 0x25
+#define SCSI_CMD_WRITE_10 0x2A
+
+/*
+**************************************************************************************************************
+* TYPE DEFINITIONS
+**************************************************************************************************************
+*/
+
+typedef enum ms_data_dir {
+
+ MS_DATA_DIR_IN = 0x80,
+ MS_DATA_DIR_OUT = 0x00,
+ MS_DATA_DIR_NONE = 0x01
+
+} MS_DATA_DIR;
+
+/*
+**************************************************************************************************************
+* FUNCTION PROTOTYPES
+**************************************************************************************************************
+*/
+
+USB_INT32S MS_BulkRecv ( USB_INT32U block_number,
+ USB_INT16U num_blocks,
+ volatile USB_INT08U *user_buffer);
+
+USB_INT32S MS_BulkSend ( USB_INT32U block_number,
+ USB_INT16U num_blocks,
+ volatile USB_INT08U *user_buffer);
+USB_INT32S MS_ParseConfiguration(void);
+USB_INT32S MS_TestUnitReady (void);
+USB_INT32S MS_ReadCapacity (USB_INT32U *numBlks, USB_INT32U *blkSize);
+USB_INT32S MS_GetMaxLUN (void);
+USB_INT32S MS_GetSenseInfo (void);
+USB_INT32S MS_Init (USB_INT32U *blkSize, USB_INT32U *numBlks, USB_INT08U *inquiryResult);
+USB_INT32S MS_Inquire (USB_INT08U *response);
+
+void Fill_MSCommand ( USB_INT32U block_number,
+ USB_INT32U block_size,
+ USB_INT16U num_blocks,
+ MS_DATA_DIR direction,
+ USB_INT08U scsi_cmd,
+ USB_INT08U scsi_cmd_len);
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp Thu Jan 21 01:15:42 2010 +0000
@@ -0,0 +1,116 @@
+#include "mbed.h"
+#include "usbhost_inc.h"
+
+void print_clock()
+{
+ int Fin = 12000000; // 12MHz XTAL
+
+ printf("PLL Registers:\r\n");
+ printf(" - PLL0STAT = 0x%08X\r\n", LPC_SC->PLL0STAT);
+ printf(" - CLKCFG = 0x%08X\r\n", LPC_SC->CCLKCFG);
+ printf(" - USBCLKCFG = 0x%08X\r\n", LPC_SC->USBCLKCFG);
+
+ int M = (LPC_SC->PLL0STAT & 0x7FFF) + 1;
+ int N = ((LPC_SC->PLL0STAT >> 16) & 0xFF) + 1;
+ int CCLKDIV = LPC_SC->CCLKCFG + 1;
+ int USBDIV = LPC_SC->USBCLKCFG + 1;
+
+ printf("Clock Variables:\r\n");
+ printf(" - Fin = %d\r\n", Fin);
+ printf(" - M = %d\r\n", M);
+ printf(" - N = %d\r\n", N);
+ printf(" - CCLKDIV = %d\r\n", CCLKDIV);
+ printf(" - USBCLKDIV = %d\r\n", USBDIV);
+
+ int Fcco = (2 * M * 12000000) / N;
+ int CCLK = Fcco / CCLKDIV;
+
+ printf("Clock Results:\r\n");
+ printf(" - Fcco = %d\r\n", Fcco);
+ printf(" - CCLK = %d\r\n", CCLK);
+ printf(" - USB Clock = %d\r\n", Fcco / USBDIV);
+ printf("System clock: %d\r\n", SystemCoreClock);
+}
+
+/*
+**************************************************************************************************************
+* COPYING A FILE
+*
+* Description: This function is used by the user to copy a file
+*
+* Arguments : None
+*
+* Returns : None
+*
+**************************************************************************************************************
+*/
+
+#define FILENAME_R "input.txt"
+#define FILENAME_W "output.txt"
+#define MAX_BUFFER_SIZE (4000)
+void Main_Copy (void)
+{
+ USB_INT32S fdr;
+ USB_INT32S fdw;
+ USB_INT32U bytes_read;
+
+
+ fdr = FILE_Open((char *)FILENAME_R, RDONLY);
+ if (fdr > 0) {
+ fdw = FILE_Open((char *)FILENAME_W, RDWR);
+ if (fdw > 0) {
+ PRINT_Log("Copying from %s to %s...\r\n", FILENAME_R, FILENAME_W);
+ do {
+ bytes_read = FILE_Read(fdr, UserBuffer, MAX_BUFFER_SIZE);
+ FILE_Write(fdw, UserBuffer, bytes_read);
+ PRINT_Log(".");
+ } while (bytes_read);
+ PRINT_Log("\r\n");
+ FILE_Close(fdw);
+ } else {
+ PRINT_Log("Could not open file %s\r\n", FILENAME_W);
+ return;
+ }
+ FILE_Close(fdr);
+ PRINT_Log("Copy completed\r\n");
+ } else {
+ PRINT_Log("Could not open file %s\r\n", FILENAME_R);
+ return;
+ }
+}
+
+int main()
+{
+ USB_INT32S rc;
+ USB_INT32U numBlks, blkSize;
+ USB_INT08U inquiryResult[INQUIRY_LENGTH];
+
+ print_clock();
+// UART_Init(115200); /* Initialize the serial port to view the log messages */
+ Host_Init(); /* Initialize the host controller */
+ rc = Host_EnumDev(); /* Enumerate the device connected */
+ if (rc == OK) {
+ /* Initialize the mass storage and scsi interfaces */
+ rc = MS_Init( &blkSize, &numBlks, inquiryResult );
+ if (rc == OK) {
+ rc = FAT_Init(); /* Initialize the FAT16 file system */
+ if (rc == OK) {
+ Main_Copy(); /* Call the application */
+ } else {
+printf("ERROR %d in FAT_Init()\r\n", rc);
+ while ( 1 );
+ // return (0);
+ }
+printf("All OK in main()\r\n");
+ } else {
+printf("ERROR %d in MS_Init()\r\n", rc);
+ while ( 1 );
+// return (0);
+ }
+ } else {
+printf("ERROR %d in Host_EnumDev()\r\n", rc);
+ while ( 1 );
+// return (0);
+ }
+ while(1);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld Thu Jan 21 01:15:42 2010 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/49a220cc26e0