struct fat_file_struct* openFile(char * file){ if (dd == 0){ return 0; } // printf("openFID\r\n"); struct fat_file_struct* fd = open_file_in_dir((struct fat_fs_struct*)fs, (struct fat_dir_struct*)dd, file); // printf("check fd\r\n"); if (!fd){ struct fat_dir_entry_struct file_entry; // printf_P(PSTR("making file...\r\n")); // for (int i = 0; i < strlen(file); i++){ // printf("%d", file[i]); // printf(" "); // } // printf("\r\n"); if(!fat_create_file((struct fat_dir_struct*)dd, file, &file_entry)){ printf_P(PSTR("failed to create file\r\n")); return 0; } // printf("created file!"); fd = open_file_in_dir((struct fat_fs_struct*)fs, (struct fat_dir_struct*)dd, file); if (!fd){ printf_P(PSTR("failed to get file\r\n")); return 0; } } return fd; }
// START FUNC DECL int mk_temp_file( size_t filesz, char *dir, char *filename ) // STOP FUNC DECL { int status = 0; extern char cwd[MAX_LEN_DIR_NAME+1]; if ( getcwd(cwd, MAX_LEN_DIR_NAME) == NULL ) { go_BYE(-1); } if ( filesz < 0 ) { go_BYE(-1); } if ( ( dir == NULL ) || ( *dir == '\0' ) ) { go_BYE(-1); } if ( ( filename == NULL ) || ( *filename == '\0' ) ) { go_BYE(-1); } status = get_disk_space(dir, &free_space, "free_space"); cBYE(status); if ( free_space < filesz ) { go_BYE(-1); } // Make empty file with that name status = open_file_in_dir(cwd, dir, filename, filesz); cBYE(status); // Stretch it to appropriate size status = mk_file(cwd, dir, filename, filesz); cBYE(status); BYE: return(status); }
/* See documentation in header file. */ int ini_parse(const char* filename, int (*handler)(void*, const char*, const char*, const char*), void* user, struct fat_fs_struct* fs, struct fat_dir_struct* dd) { struct fat_file_struct* file; int error; file = open_file_in_dir(fs, dd, filename); if (!file) { printf("error opening file\r\n"); return -1; } error = ini_parse_file(file, handler, user); fat_close_file(file); return error; }
int main (){ int maxfd, listenfd, connfd, nread, i; char c = 'C'; char temp; char *after; unsigned short block_crc; unsigned char char_block, crc_first, crc_second; char *dirname = "filestore"; struct client *top = malloc(sizeof (struct client)); top->fd = -1; top->next = NULL; struct client *p; fd_set allset; socklen_t clilen; struct sockaddr_in cliaddr, servaddr; listenfd = Socket(PF_INET, SOCK_STREAM, 0); memset(&servaddr, '\0', sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = INADDR_ANY; servaddr.sin_port = htons(PORT); Bind (listenfd, (struct sockaddr *) &servaddr, sizeof (servaddr)); Listen (listenfd, LISTENQ); while(1){ fprintf(stderr, "Time to Select\n"); maxfd = listenfd; FD_ZERO (&allset); FD_SET(listenfd, &allset); //loop through the linked list of clients to refresh the allset for (p = top; p->fd >=0; p = p->next){ FD_SET (p->fd, &allset); if (p->fd > maxfd) maxfd = p->fd; //if the fd is larger than the maxfd, change maxfd. } Select(maxfd+1, &allset, NULL, NULL, NULL); //loop through the linked list until the fd corresponding to the client that is set is found for (p = top; p->fd >=0; p = p->next){ if (FD_ISSET(p->fd, &allset)) break; } //if it is our listening socket then a new client has come if (FD_ISSET(listenfd, &allset)){ newconnection(listenfd, &top); } // otherwise its one of our old clients else if(!p){ //if p is null, we have a problem fprintf(stderr,"uhoh\n"); exit(1); } // if p exists, then we go through the states else { if(p){ if (p->state == initial){ fprintf(stderr, "initial reading from client\n"); // read as many as you can up to 20 characters, leaving off where it last wrote nread = read(p->fd, &(p->buf[p->inbuf]), sizeof(char)*(20 - p->inbuf)); if(nread<0){ perror("read"); removeclient(p->fd, &top); } //use inbuf as an index of where to write next, and how much more can be written p->inbuf = p->inbuf + nread; //transfer stuff in buf to filename until a network newline is reached for (i = 0; i < 20; i++){ p->filename[i] = p->buf[i]; if (p->buf[i] == '\r'){ //once the network newline is found p->filename[i] = '\0';//place a null character to end the string p->state = pre_block; //change states p->fp = open_file_in_dir(p->filename, dirname); //open a file p->inbuf = 0;// reset inbuf to be 0, going to write over buf from 0 index if (write(p->fd, &c, 1)<0){ //send 'C' to client perror("write"); removeclient(p->fd, &top); } break; } } //if the network newline is not found in the 20 characters sent by client, error in filename, drop client if (p->inbuf == 20){ fprintf(stderr, "filename was not found. filename must be less than 20 characters\n"); removeclient(p->fd, &top); } } if (p->state == pre_block){ fprintf(stderr, "pre_block readering from client \n"); nread = read(p->fd, &temp, 1); //read a single character if(nread<0){ //if there was a problem with nread then drop the client perror("read"); removeclient(p->fd, &top); } if (temp== EOT){ temp = ACK; if (write(p->fd, &temp, 1)<0){ perror("write"); removeclient(p->fd, &top); } fprintf(stderr, "finished\n"); removeclient(p->fd, &top); } if (temp == SOH){ p->blocksize = 132; p->state = get_block; } if (temp == STX){ p->blocksize = 1028; p->state = get_block; } } if (p->state == get_block){ fprintf(stderr, "get_block readering from client \n"); /* reads into the buffer as much as it can upto the blocksize of the client * and continues writing where it left off*/ nread = read(p->fd, &(p->buf[p->inbuf]), p->blocksize - p->inbuf); if(nread < 0){ perror("read"); removeclient(p->fd, &top); } p->inbuf = p->inbuf + nread; //once the entire block is received, go to the next state; if (p->inbuf == p->blocksize) p->state = check_block; } if (p->state == check_block){ fprintf(stderr, "checking_block client \n"); char_block = p->current_block; /*removes client if block number and inverse don't match or block number is not * what was expected. however if the blocknum is a previously received block num, send ack*/ if (255 - p->buf[0] != p->buf[1]){ fprintf(stderr, "block number and inverse do not match\n"); removeclient(p->fd, &top); } else if (char_block > p->buf[0]){ temp = ACK; if(write(p->fd, &temp, 1)<0){ perror("write"); removeclient(p->fd, &top); } } else if (char_block != p->buf[0]){ fprintf(stderr, "char_block is not correct\n"); removeclient(p->fd, &top); } //otherwise, need to check crc else{ block_crc = crc_message (XMODEM_KEY, &(p->buf[2]), p->blocksize - 4); crc_first = block_crc>>8; crc_second = block_crc; if ((crc_first != p->buf[p->blocksize -2]) || (crc_second != p->buf[p->blocksize -1])){ fprintf(stderr, "crc does not match \n"); temp = NAK; if(write(p->fd, &temp, 1) < 0){ perror("write"); removeclient(p->fd, &top); } } else{ temp = ACK; fprintf(stderr, "writing to client ACK\n"); if (write (p->fd, &temp, 1)<0){ perror("write"); removeclient(p->fd, &top); } if(fwrite(&(p->buf[2]), p->blocksize-4, 1, p->fp)<0){ perror("write"); exit(1); } p->state = pre_block; p->current_block ++; p->inbuf = 0; if(p->current_block > 255) p->current_block = 1; } } } } } }
int main() { /* we will just use ordinary idle mode */ set_sleep_mode(SLEEP_MODE_IDLE); /* setup uart */ uart_init(); while(1) { /* setup sd card slot */ if(!sd_raw_init()) { #if DEBUG uart_puts_p(PSTR("MMC/SD initialization failed\n")); #endif continue; } /* open first partition */ struct partition_struct* partition = partition_open(sd_raw_read, sd_raw_read_interval, #if SD_RAW_WRITE_SUPPORT sd_raw_write, sd_raw_write_interval, #else 0, 0, #endif 0 ); if(!partition) { /* If the partition did not open, assume the storage device * is a "superfloppy", i.e. has no MBR. */ partition = partition_open(sd_raw_read, sd_raw_read_interval, #if SD_RAW_WRITE_SUPPORT sd_raw_write, sd_raw_write_interval, #else 0, 0, #endif -1 ); if(!partition) { #if DEBUG uart_puts_p(PSTR("opening partition failed\n")); #endif continue; } } /* open file system */ struct fat_fs_struct* fs = fat_open(partition); if(!fs) { #if DEBUG uart_puts_p(PSTR("opening filesystem failed\n")); #endif continue; } /* open root directory */ struct fat_dir_entry_struct directory; fat_get_dir_entry_of_path(fs, "/", &directory); struct fat_dir_struct* dd = fat_open_dir(fs, &directory); if(!dd) { #if DEBUG uart_puts_p(PSTR("opening root directory failed\n")); #endif continue; } /* print some card information as a boot message */ print_disk_info(fs); /* provide a simple shell */ char buffer[24]; while(1) { /* print prompt */ uart_putc('>'); uart_putc(' '); /* read command */ char* command = buffer; if(read_line(command, sizeof(buffer)) < 1) continue; /* execute command */ if(strcmp_P(command, PSTR("init")) == 0) { break; } else if(strncmp_P(command, PSTR("cd "), 3) == 0) { command += 3; if(command[0] == '\0') continue; /* change directory */ struct fat_dir_entry_struct subdir_entry; if(find_file_in_dir(fs, dd, command, &subdir_entry)) { struct fat_dir_struct* dd_new = fat_open_dir(fs, &subdir_entry); if(dd_new) { fat_close_dir(dd); dd = dd_new; continue; } } uart_puts_p(PSTR("directory not found: ")); uart_puts(command); uart_putc('\n'); } else if(strcmp_P(command, PSTR("ls")) == 0) { /* print directory listing */ struct fat_dir_entry_struct dir_entry; while(fat_read_dir(dd, &dir_entry)) { uint8_t spaces = sizeof(dir_entry.long_name) - strlen(dir_entry.long_name) + 4; uart_puts(dir_entry.long_name); uart_putc(dir_entry.attributes & FAT_ATTRIB_DIR ? '/' : ' '); while(spaces--) uart_putc(' '); uart_putdw_dec(dir_entry.file_size); uart_putc('\n'); } } else if(strncmp_P(command, PSTR("cat "), 4) == 0) { command += 4; if(command[0] == '\0') continue; /* search file in current directory and open it */ struct fat_file_struct* fd = open_file_in_dir(fs, dd, command); if(!fd) { uart_puts_p(PSTR("error opening ")); uart_puts(command); uart_putc('\n'); continue; } /* print file contents */ uint8_t buffer[8]; uint32_t offset = 0; while(fat_read_file(fd, buffer, sizeof(buffer)) > 0) { uart_putdw_hex(offset); uart_putc(':'); for(uint8_t i = 0; i < 8; ++i) { uart_putc(' '); uart_putc_hex(buffer[i]); } uart_putc('\n'); offset += 8; } fat_close_file(fd); } else if(strcmp_P(command, PSTR("disk")) == 0) { if(!print_disk_info(fs)) uart_puts_p(PSTR("error reading disk info\n")); } #if FAT_WRITE_SUPPORT else if(strncmp_P(command, PSTR("rm "), 3) == 0) { command += 3; if(command[0] == '\0') continue; struct fat_dir_entry_struct file_entry; if(find_file_in_dir(fs, dd, command, &file_entry)) { if(fat_delete_file(fs, &file_entry)) continue; } uart_puts_p(PSTR("error deleting file: ")); uart_puts(command); uart_putc('\n'); } else if(strncmp_P(command, PSTR("touch "), 6) == 0) { command += 6; if(command[0] == '\0') continue; struct fat_dir_entry_struct file_entry; if(!fat_create_file(dd, command, &file_entry)) { uart_puts_p(PSTR("error creating file: ")); uart_puts(command); uart_putc('\n'); } } else if(strncmp_P(command, PSTR("write "), 6) == 0) { command += 6; if(command[0] == '\0') continue; char* offset_value = command; while(*offset_value != ' ' && *offset_value != '\0') ++offset_value; if(*offset_value == ' ') *offset_value++ = '\0'; else continue; /* search file in current directory and open it */ struct fat_file_struct* fd = open_file_in_dir(fs, dd, command); if(!fd) { uart_puts_p(PSTR("error opening ")); uart_puts(command); uart_putc('\n'); continue; } int32_t offset = strtolong(offset_value); if(!fat_seek_file(fd, &offset, FAT_SEEK_SET)) { uart_puts_p(PSTR("error seeking on ")); uart_puts(command); uart_putc('\n'); fat_close_file(fd); continue; } /* read text from the shell and write it to the file */ uint8_t data_len; while(1) { /* give a different prompt */ uart_putc('<'); uart_putc(' '); /* read one line of text */ data_len = read_line(buffer, sizeof(buffer)); if(!data_len) break; /* write text to file */ if(fat_write_file(fd, (uint8_t*) buffer, data_len) != data_len) { uart_puts_p(PSTR("error writing to file\n")); break; } } fat_close_file(fd); } else if(strncmp_P(command, PSTR("mkdir "), 6) == 0) { command += 6; if(command[0] == '\0') continue; struct fat_dir_entry_struct dir_entry; if(!fat_create_dir(dd, command, &dir_entry)) { uart_puts_p(PSTR("error creating directory: ")); uart_puts(command); uart_putc('\n'); } } #endif #if SD_RAW_WRITE_BUFFERING else if(strcmp_P(command, PSTR("sync")) == 0) { if(!sd_raw_sync()) uart_puts_p(PSTR("error syncing disk\n")); } #endif else if(strcmp_P(command, PSTR("sync")) == 0) { // vytvor adresar mereni_teploty // nekonecna smycka - pomoci RTCka kazdou minutu odmer teplotu } else { uart_puts_p(PSTR("unknown command: ")); uart_puts(command); uart_putc('\n'); } } /* close directory */ fat_close_dir(dd); /* close file system */ fat_close(fs); /* close partition */ partition_close(partition); } return 0; }
void loop() { int bytes_read=0; //Keeps track of how many bytes are read when accessing a file on the SD card. //Init Timer 1 //Used for 45uS Interrupt TCCR1A = 0; //Set Timer to normal mode TCCR1B = 0x0A; //Set Timer clock to 2 MHz. Clear timer on compare TIMSK1 = 0x02; //Enable Timer 1 Compare A Interrupt; OCR1AH = 0X00; //Count to 90 before triggering an interrupt. Counting to 90 with a 2MHz clock makes OCR1AL = 0x5A; //the interrupt trigger at 22.222kHz init_filesystem(); //Initialize the FAT16 file system on the SD card. if(get_wav_filename(dd, file_name)); //Find the first WAV file on the SD card (must be in the root directory) else while(1); //If a WAV file isn't found then the sketch is stopped here. //Open the file file_handle=open_file_in_dir(fs, dd, file_name); //Read the header information. Alternate purpose is to get to the DATA offset of the file. read_wav_header(file_handle, header); //Set the initial play buffer, and grab the initial data from the SD card. play_buffer=0; bytes_read = fat_read_file(file_handle, buffer1, BUFFERSIZE); bytes_read = fat_read_file(file_handle, buffer2, BUFFERSIZE); //Enable interrupts to start the wav playback. sei(); while(1){ if(need_new_data==1) //need_new_data flag is set by ISR to indicate a buffer is empty and should be refilled { need_new_data=0; //Clear the flag. if(play_buffer==0) //play_buffer indicates which buffer is now empty { //Get the next BUFFERSIZE bytes from the file. bytes_read = fat_read_file(file_handle, buffer1, BUFFERSIZE); } else { //Get the next BUFFERSIZE bytes from the file. bytes_read = fat_read_file(file_handle, buffer2, BUFFERSIZE); } new_buffer_ready=1; //new_buffer_ready flag tells the ISR that the buffer has been filled. //If file_read returns 0 or -1 file is over. Find the next file! if(bytes_read<=0) { cli(); //Disable interrupts to stop playback. fat_close_file(file_handle); //Close the current file //Find the next WAV file in the SD card fat_reset_dir(dd); //Make sure we start searching from the beginning of the directory find_file_in_dir(fs, dd, file_name, &dir_entry); //Navigate to the current file in the directory if(get_wav_filename(dd, file_name)); else while(1); //If we don't find another wav file, stop everything! //If we get here we've found another wav file. Open it! file_handle=open_file_in_dir(fs, dd, file_name); //Get the file header and load the initial song data. read_wav_header(file_handle, header); play_buffer=0; bytes_read = fat_read_file(file_handle, buffer1, BUFFERSIZE); bytes_read = fat_read_file(file_handle, buffer2, BUFFERSIZE); sei(); //Start playing the song } } } }
int main() { int listenfd, clientfd, maxfd; fd_set cset, rset; Client *clients = NULL; socklen_t clilen; struct sockaddr_in cliaddr, servaddr; int one = 1; unsigned char temp_block_num, temp_block_inverse; unsigned short temp_crc, block_crc; char temp = 'C'; /*If a client disconnects while we are writing an ACK/NAK to them it sends * a SIGPIPE which needs to be taken care of */ signal(SIGPIPE, SIG_IGN); //Setup the main listening socket listenfd = Socket(AF_INET, SOCK_STREAM, 0); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(PORT); if ((setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int))) == -1) { perror("setsockopt"); } Bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr)); Listen(listenfd, 5); FD_ZERO(&cset); FD_SET(listenfd, &cset); maxfd = listenfd; while (1) { /* * Accept any clients that want to connect. */ rset = cset; Select(maxfd + 1, &rset, NULL, NULL, 0); // Check for new clients. if (FD_ISSET(listenfd, &rset)) { printf("New Client Connected\n"); Client *temp = Malloc(sizeof(Client)); clilen = sizeof(cliaddr); clientfd = Accept(listenfd, (struct sockaddr *) &cliaddr, &clilen); FD_SET(clientfd, &cset); if (clientfd > maxfd) { maxfd = clientfd; } // Populate the client struct with default starter data. temp->fd = clientfd; temp->inbuf = 0; temp->state = initial; temp->next = start; temp->prev = NULL; if (start) { start->prev = temp; } start = temp; continue; } /* * Loop through all the clients in the linked list, * checking their file descriptors for activity. */ clients = start; while (clients) { clientfd = clients->fd; if (FD_ISSET(clientfd, &rset)) { /* * Using switch statement for states is too messy in terms of proper flow control * so just using if statements instead; they're cleaner and easier to follow. */ if (clients->state == initial) { // Read name of the file being sent. clients->inbuf += Read(clientfd, &(clients->filename)[clients->inbuf], 20 - clients->inbuf); if (find_network_newline(clients->filename, clients->inbuf) > 0) { clients->filename[clients->inbuf - 2] = '\0'; // Open/create a file with the name. clients->fp = open_file_in_dir(clients->filename, FILE_DIR); // Assign defaults to client struct. clients->state = pre_block; clients->inbuf = 0; clients->current_block = 1; // Let the client know that the server is ready for the data. temp = 'C'; Write(clientfd, &temp, 1); } } if (clients->state == pre_block) { // Find out what state the client is in. Read(clientfd, (clients->buf), 1); switch (clients->buf[0]) { case EOT: clients->state = finished; break; case SOH: clients->state = get_block; clients->blocksize = 132; break; case STX: clients->state = get_block; clients->blocksize = 1028; break; default: temp = NAK; Write(clientfd, &temp, 1); } } if (clients->state == get_block) { // Keep getting more of the payload till you have the required minimum amount. clients->inbuf += Read(clientfd, (clients->buf) + (clients->inbuf), clients->blocksize - clients->inbuf); if (clients->inbuf == clients->blocksize) { clients->state = check_block; } } if (clients->state == check_block) { // Fetch block numbers from the packet. temp_block_num = (clients->buf)[0]; temp_block_inverse = (clients->buf)[1]; // Make sure the block numbers are correct - drop the client if they're not. if ((temp_block_num != (255 - temp_block_inverse) || (temp_block_num > clients->current_block))) { FD_CLR(clientfd, &cset); clients = drop_client(clients); /* * Since drop_client gives us the client after the one we dropped, * we use continue to go back to start of the loop. */ break; } // Fetch and assemble the CRC given by client for the payload recieved. temp_crc = 0; temp_crc = (unsigned char)(clients->buf)[(clients->blocksize) - 2]; temp_crc <<= 8; temp_crc |= (unsigned char)((clients->buf)[(clients->blocksize) - 1]); // Calculate the actual CRC for the payload recieved. block_crc = crc_message(XMODEM_KEY, (unsigned char *)((clients->buf) + 2), (clients->blocksize) - 4); // Compare the given and calculated CRC to ensure payload integrity. if ((temp_block_num == clients->current_block) && (temp_crc == block_crc)) { printf("File: %s \t Block:%d Successfully recieved\n", clients->filename, clients->current_block); // Write the payload to file if CRCs match if (fwrite((clients->buf) + 2, 1, ((clients->blocksize) - 4), clients->fp) == 0) { perror("Write to File error"); exit(-1); } // Send the client an ACK temp = ACK; Write(clientfd, &temp, 1); // Increment service side block number counter and prepare for next block. clients->state = pre_block; clients->current_block += 1; // Deal w/ wrap around when block number hits 255. if (clients->current_block == 256) { clients->current_block = 0; } // Reset the buffer position. clients->inbuf = 0; } else if (temp_crc != block_crc) { printf("File: %s \t Block:%d CRC mismatch.\nExpected:%x, Got %x\n", clients->filename, clients->current_block, temp_crc, block_crc); // Sent the client a NAK if the CRCs didn't match and prepare for repeat block. temp = NAK; Write(clientfd, &temp, 1); clients->state = pre_block; clients->inbuf = 0; } else if (temp_block_num < clients->current_block) { // If we got a repeat block, just send the client an ACK. temp = ACK; Write(clientfd, &temp, 1); } } if (clients->state == finished) { printf("File Transfer Finished: %s\n", clients->filename); // Cleanup after the client when transfer is finished. // Send the client a final ACK. temp = ACK; Write(clientfd, &temp, 1); // Remove the client and their socket from our list/set of clients. FD_CLR(clientfd, &cset); clients = drop_client(clients); } } // Move on to the next client in the list (if any). if (clients) { clients = clients->next; } } } }
File AF_Wave::open_file(char *name) { return open_file_in_dir(fs, dd, name); }
void FAT::open() { _file_handle=open_file_in_dir(_fs, _dd, _file_name); }
/* A helper function for processing a client. This functions covers all states except the finished state. This function takes in the argument toplist (the top of the linked list, and cl, the current client node/struct. */ int processclient(struct client *cl) { /* Variable used for writing ACK, NAK, and other exciting control codes */ char acker; switch (cl->state) { /* If client is in the initial state */ case initial: { /* Variable to determine if network newline has been found */ int readin = 0; /* Read in one byte at a time so that the read() call doesn't block, top when network newline has been found and add a null terminator at the end of the filename. */ memset(cl->filename, 0, 20); if (read(cl->fd, &cl->filename, 20) <= 0) { /*XXX*/ return 0; } printf("%s:%d--->filename: %s\n", __func__, __LINE__, cl->filename); readin = 1; /* If filename is completely read in, use helper.c to generate the file pointer for it, reset the buffer index, and transition to pre_block state */ if ( readin == 1) { cl->fp = open_file_in_dir(cl->filename, "storage"); cl->inbuf = 0; cl->state = pre_block; } /* Write "C" to the client so it can move on with its transfer, if write fails, drop client by transitioning to finished block */ if ( write(cl->fd, "C", 1) < 1) { perror("Writing C failed"); cl->state = finished; } } break; /* If client is in the pre_block state */ case pre_block: { /* Temporary buffer to hold in any incoming control codes. 2048 is overkill, yes, however it can't hurt to be safe. */ char prebuf[2048]; /* Read in one byte at a time from the client */ if (read(cl->fd, &prebuf[0], 1) == 1) { printf("*"); /* If EOT is received, drop client by transitioning to finish state */ if (prebuf[cl->inbuf] == EOT) { /* Close file pointer */ fclose(cl->fp); /* Set acker to ACK control code and write it to the client */ acker = ACK; printf("receiver successful\n"); if (write(cl->fd, &acker, sizeof(char)) < 1) { perror("writing ACK for EOT in pre_block failed"); } cl->state = finished; } /* If SOH block is received, set the expected blocksize on client to 128, and transition to get_block */ if (prebuf[0] == SOH) { cl->blocksize = 128; cl->state = get_block; } /* If STX block is received, set the expected blocksize on client to 1024, and transition to get_block */ if (prebuf[0] == STX) { cl->blocksize = 1024; cl->state = get_block; } } else { perror("pre_block read fail"); } } break; /* If client is in the get_block state */ case get_block: /* If server is expecting a SOH block */ if (cl->blocksize == 128) { /* Read in one byte for current block number and store it in the client's current_block attribute */ if (read(cl->fd, &cl->current_block, 1) < 1) { perror("reading in current_block failed in SOH, get_block"); } /* Read in one byte for inverse block number and store it in the client's inverse_block attribute */ if (read(cl->fd, &cl->inverse_block, 1) < 1) { perror("reading in inverse_block failed in SOH, get_block"); } /* Read in the actual payload to the client's buf attribute, one byte at a time */ while (cl->inbuf < 128) { if (read(cl->fd, &cl->buf[cl->inbuf], 1) == 1) { cl->inbuf++; } else { perror("get_block_soh_read_failure\n"); } /* Check if blocksize bytes have been read in, if so, caclculate CRC and store it in the client's CRC attributes. Transition to check_block. */ if (cl->inbuf == cl->blocksize) { read(cl->fd, &cl->crca, 1); read(cl->fd, &cl->crcb, 1); cl->state = check_block; } } } /* If server is expecting a STX block */ if (cl->blocksize == 1024 ) { /* Read in one byte for current block number and store it in the client's current_block attribute */ if (read(cl->fd, &cl->current_block, 1) < 1) { perror("reading in current_block failed in STX, get_block"); } /* Read in one byte for inverse block number and store it in the client's inverse_block attribute */ if (read(cl->fd, &cl->inverse_block, 1) < 1) { perror("reading in inverse_block failes in STX, get_block"); } /* Read in the actual payload to the client's buf attribute, one byte at a time */ while (cl->inbuf < 1024) { if ( read(cl->fd, &cl->buf[cl->inbuf], 1) == 1) { cl->inbuf++; } else { perror("get_block_stx_read_failure"); } } /* Check if blocksize bytes have been read in, if so, caclculate CRC and store it in the client's CRC attributes. Transition to check_block. */ if (cl->inbuf == cl->blocksize) { read(cl->fd, &cl->crca, 1); read(cl->fd, &cl->crcb, 1); cl->state = check_block; } } break; case check_block: /* Reset buffer index after previous block */ cl->inbuf = 0; /* If inverse block and current block don't corresond, write ACK and drop client */ if ((255 - cl->inverse_block) != cl->current_block) { /* Set acker to the ACK control code and write it */ acker = ACK; if (write(cl->fd, &acker, sizeof(char)) < 1) { perror("ACK failed to write in check_block for invalid inverse"); } cl->state = finished; } /* If previous block and current block numbers are the same, ACK the second one */ if (cl->previous_block == cl->current_block) { acker = ACK; if (write(cl->fd, &acker, sizeof(char)) < 1) { perror("ACK failed to write in check_block for duplicate blocks"); } } /* If blocks are out of order, write ACK and drop client */ if (cl->current_block != cl->previous_block + 1) { if ((cl->previous_block != 255) && (cl->current_block != 0)) { /* Set acker to the ACK control code and write it */ acker = ACK; if (write(cl->fd, &acker, sizeof(char)) < 1) { perror("ACK failed to write in check_block for invalid block order"); } cl->state = finished; } } /* If CRC's don't match up, send NAK */ if (crc_message(XMODEM_KEY, cl->buf, cl->blocksize) != ((cl->crca << 8) + cl->crcb)) { /* Set acker to NAK and write it */ acker = NAK; if (write(cl->fd, &acker, sizeof(char)) < 1) { perror("NAK failed to write in check_block for invalid CRC"); } } else { /* If none of the above error checks are triggered */ /* Set previous block to current, and account for wrapping at block number 255 */ cl->previous_block = cl->current_block; if ( cl->current_block > 255 ) { cl->current_block = 0; } /* Write the current payload in the client's buf attribute to the file */ if (fwrite(&cl->buf, sizeof(char), cl->blocksize, cl->fp) < cl->blocksize) { perror("Writing payload to file failed"); } /* Set acker to ACK and write it */ acker = ACK; if (write(cl->fd, &acker, sizeof(char)) < 1) { perror("ACK failed to write in check_block file write stage"); } /* Transition back to the pre_block */ cl->state = pre_block; } break; case finished: cl->state = initial; break; default: printf("error status\n"); break; } return 1; }
int main() { /* setup uart */ uart_init(); /* setup stdio */ uart_connect_stdio(); /* setup sd card slot */ if(!sd_raw_init()) { #if DEBUG printf_P(PSTR("MMC/SD initialization failed\n")); #endif return 1; } /* open first partition */ struct partition_struct* partition = partition_open(sd_raw_read, sd_raw_read_interval, sd_raw_write, 0); if(!partition) { /* If the partition did not open, assume the storage device * is a "superfloppy", i.e. has no MBR. */ partition = partition_open(sd_raw_read, sd_raw_read_interval, sd_raw_write, -1 ); if(!partition) { #if DEBUG printf_P(PSTR("opening partition failed\n")); #endif return 1; } } /* open file system */ struct fat16_fs_struct* fs = fat16_open(partition); if(!fs) { #if DEBUG printf_P(PSTR("opening filesystem failed\n")); #endif return 1; } /* open root directory */ struct fat16_dir_entry_struct directory; fat16_get_dir_entry_of_path(fs, "/", &directory); struct fat16_dir_struct* dd = fat16_open_dir(fs, &directory); if(!dd) { #if DEBUG printf_P(PSTR("opening root directory failed\n")); #endif return 1; } /* provide a simple shell */ char buffer[24]; while(1) { /* print prompt */ uart_putc('>'); uart_putc(' '); /* read command */ char* command = buffer; if(read_line(command, sizeof(buffer)) < 1) continue; /* execute command */ if(strncmp_P(command, PSTR("cd "), 3) == 0) { command += 3; if(command[0] == '\0') continue; /* change directory */ struct fat16_dir_entry_struct subdir_entry; if(find_file_in_dir(fs, dd, command, &subdir_entry)) { struct fat16_dir_struct* dd_new = fat16_open_dir(fs, &subdir_entry); if(dd_new) { fat16_close_dir(dd); dd = dd_new; continue; } } printf_P(PSTR("directory not found: %s\n"), command); } else if(strcmp_P(command, PSTR("ls")) == 0) { /* print directory listing */ struct fat16_dir_entry_struct dir_entry; while(fat16_read_dir(dd, &dir_entry)) { printf_P(PSTR("%10lu %s%c\n"), dir_entry.file_size, dir_entry.long_name, (dir_entry.attributes & FAT16_ATTRIB_DIR) ? '/' : ' ' ); } } else if(strncmp_P(command, PSTR("cat "), 4) == 0) { command += 4; if(command[0] == '\0') continue; /* search file in current directory and open it */ struct fat16_file_struct* fd = open_file_in_dir(fs, dd, command); if(!fd) { printf_P(PSTR("error opening %s\n"), command); continue; } /* print file contents */ uint8_t buffer[8]; uint32_t offset = 0; while(fat16_read_file(fd, buffer, sizeof(buffer)) > 0) { printf_P(PSTR("%08lx: %02x %02x %02x %02x %02x %02x %02x %02x\n"), offset, buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7] ); offset += 8; } fat16_close_file(fd); } #if FAT16_WRITE_SUPPORT else if(strncmp_P(command, PSTR("rm "), 3) == 0) { command += 3; if(command[0] == '\0') continue; struct fat16_dir_entry_struct file_entry; if(find_file_in_dir(fs, dd, command, &file_entry)) { if(fat16_delete_file(fs, &file_entry)) continue; } printf_P(PSTR("error deleting file: %s\n"), command); } else if(strncmp_P(command, PSTR("touch "), 6) == 0) { command += 6; if(command[0] == '\0') continue; struct fat16_dir_entry_struct file_entry; if(!fat16_create_file(dd, command, &file_entry)) printf_P(PSTR("error creating file: %s\n"), command); } else if(strncmp_P(command, PSTR("write "), 6) == 0) { command += 6; if(command[0] == '\0') continue; char* offset_value = command; while(*offset_value != ' ' && *offset_value != '\0') ++offset_value; if(*offset_value == ' ') *offset_value++ = '\0'; else continue; /* search file in current directory and open it */ struct fat16_file_struct* fd = open_file_in_dir(fs, dd, command); if(!fd) { printf_P(PSTR("error opening %s\n"), command); continue; } int32_t offset = strtol(offset_value, 0, 0); if(!fat16_seek_file(fd, &offset, FAT16_SEEK_SET)) { printf_P(PSTR("error seeking on %s\n"), command); fat16_close_file(fd); continue; } /* read text from the shell and write it to the file */ uint8_t data_len; while(1) { /* give a different prompt */ uart_putc('<'); uart_putc(' '); /* read one line of text */ data_len = read_line(buffer, sizeof(buffer)); if(!data_len) break; /* write text to file */ if(fat16_write_file(fd, (uint8_t*) buffer, data_len) != data_len) { printf_P(PSTR("error writing to file\n")); break; } } fat16_close_file(fd); } #endif #if SD_RAW_WRITE_BUFFERING else if(strcmp_P(command, PSTR("sync")) == 0) { if(!sd_raw_sync()) printf_P(PSTR("error syncing disk\n")); } #endif else { printf_P(PSTR("unknown command: %s\n"), command); } } /* close file system */ fat16_close(fs); /* close partition */ partition_close(partition); return 0; }
uint8_t RepRapSDCard::open_file(char *name, File *file) { return open_file_in_dir(fs, dd, name, file); }