text: #include "FreeRTOS.h"
  #include "task.h"
  #include <platform/platform_stdlib.h>
  #include "basic_types.h"
  #include "platform_opts.h"
  #include "section_config.h"
  
  #include <httpd/httpd.h>
  #include "log_service.h"
  #if CONFIG_SDCARD_UPLOAD_HTTPD
  
  #include "ff.h"
  #include <fatfs_ext/inc/ff_driver.h>
  #include <disk_if/inc/sdcard.h>
  #if defined(CONFIG_PLATFORM_8195A) || defined(CONFIG_PLATFORM_8195BHP) || defined(CONFIG_PLATFORM_8710C)
  #include "sdio_combine.h"
  #include "sdio_host.h"
  extern phal_sdio_host_adapter_t psdioh_adapter;
  #endif
  
  //#if (_USE_MKFS != 1)
  //	#error define _USE_MKFS MACRO to 1 in ffconf.h to enable f_mkfs() which creates FATFS volume on Flash.
  //#endif
  //#define	_DBG_SDIO_          	0x00000400 //don`t know where it was used..
  #define STACK_SIZE		2048
  #define READ_SIZE 		2048
  #define MP4_NAME		 "OTA_ALL.bin"
  
  FATFS 	fs_sd;
  FIL     m_file;
  FILINFO fno = {0};
  char path[64];
  
  
  int fatfs_init(char *file_name)
  { 
  	char sd_drv[4]; /* root diretory */
  	int sd_drv_num;
  	int br,bw;
  	int Fatfs_ok = 0;
  	FRESULT res; 
  #if defined(CONFIG_PLATFORM_8195A) || defined(CONFIG_PLATFORM_8195BHP) || defined(CONFIG_PLATFORM_8710C)	
  	sdio_driver_init();
   #endif
  	printf("Register disk driver to Fatfs.\n\r");
  	sd_drv_num = FATFS_RegisterDiskDriver(&SD_disk_Driver);
  	
  	if(sd_drv_num < 0){
  		printf("Rigester disk driver to FATFS fail.\n\r");
  	}else{
  		Fatfs_ok = 1;
  		
  		sd_drv[0] = sd_drv_num + '0';
  		sd_drv[1] = ':';
  		sd_drv[2] = '/';
  		sd_drv[3] = 0;
  	}
  	
  	if(Fatfs_ok){
  		res = f_mount(&fs_sd, sd_drv, 1);
  		
  		if(res){
  #if 0
  			if(f_mkfs(sd_drv, 1, 4096)!= FR_OK){
  				printf("Create FAT volume on Flash fail.\n\r");
  				goto exit;
  			}
  #endif
  			   if(f_mount(&fs_sd, sd_drv, 0)!= FR_OK){
  				printf("FATFS mount logical drive on Flash fail.\n\r");
  				goto exit;
  			}
  		}else{
  			printf("f_mount OK\n\r");
  		} 
  		
  		strcpy(path, sd_drv);
  		sprintf(&path[strlen(path)],"%s",MP4_NAME);
  		
  		//FILINFO fno;
  		
  		res = f_stat(path, &fno);
  		switch (res) {
  			
  			case FR_OK:
  				printf("Size: %d\n", fno.fsize);
  				printf("Timestamp: %d/%2d/%2d, %2d:%2d\n",
  							(fno.fdate >> 9) + 1980, fno.fdate >> 5 & 15, fno.fdate & 31,
  							fno.ftime >> 11, fno.ftime >> 5 & 63);
  				printf("Attributes: %c%c%c%c%c\n",
  							(fno.fattrib & AM_DIR) ? 'D' : '-',
  							(fno.fattrib & AM_RDO) ? 'R' : '-',
  							(fno.fattrib & AM_HID) ? 'H' : '-',
  							(fno.fattrib & AM_SYS) ? 'S' : '-',
  							(fno.fattrib & AM_ARC) ? 'A' : '-');
  				break;
  				
  			case FR_NO_FILE:
  				printf("It is not exist.\n");
  				break;
  				
  			default:
  				printf("An error occured. (%d)\n", res);
  		}
  		//3.open 
  		res = f_open(&m_file, path, FA_OPEN_ALWAYS | FA_READ | FA_WRITE);
  		if(res){
  			printf("open file (%s) fail. res = %d\n\r", MP4_NAME,res);
  			goto exit;
  		}
  	}  
  	return 0;
  exit:
  	return -1;
  }
  
  
  
  void fatfs_homepage_cb(struct httpd_conn *conn)
  {
  	char *user_agent = NULL;
  	FRESULT res; 
  	unsigned char *buf_ptr= malloc(READ_SIZE);
  	int ret = 0;
  	unsigned int time_1 = 0;
  	unsigned int time_2 = 0;
  	
  	memset(buf_ptr,0,READ_SIZE);
  	
  	httpd_conn_dump_header(conn);
  	
  	if(httpd_request_get_header_field(conn, "User-Agent", &user_agent) != -1) {
  		printf("\nUser-Agent=[%s]\n", user_agent);
  		httpd_free(user_agent);
  	}
  	
  	if(httpd_request_is_method(conn, "GET")) {
  		httpd_response_write_header_start(conn, "200 OK", "application/octet-stream", fno.fsize);
  		httpd_response_write_header(conn,"Content-Disposition","attachment; filename="MP4_NAME);
  		httpd_response_write_header(conn, "Connection", "close");
  		httpd_response_write_header_finish(conn);
  		
  		int i = 0;
  		
  		int br,bw;
  		
  		time_1 = rtw_get_current_time();
  		printf("start time =%d\r\n",time_1);
  		for(i=0;i<fno.fsize/READ_SIZE;i++){
  			res = f_read(&m_file, buf_ptr, READ_SIZE, (u32*)&br);
  			if(res){
  				printf("Read error. re = %d\n\r",res);
  				f_lseek(&m_file, 0);
  				res = f_close(&m_file);
  				goto exit;
  			}
                          //ret = httpd_response_write_data(conn, buf_temp_ptr, READ_SIZE);
                          ret = httpd_response_write_data(conn, buf_ptr, READ_SIZE);
  		}
                  if(fno.fsize%READ_SIZE){
                          res = f_read(&m_file, buf_ptr, i%fno.fsize, (u32*)&br);
                          ret = httpd_response_write_data(conn, buf_ptr, fno.fsize%READ_SIZE);
                  }
  		
  	}else {
  		// HTTP/1.1 405 Method Not Allowed
  		httpd_response_method_not_allowed(conn, NULL);
  	}
  	
  	time_2 = rtw_get_current_time();
  	printf("start time =%d ms end time =%d ms cost = %d ms  speed = %d MB/s\r\n",time_1,time_2,(time_2-time_1),(float)((float)(fno.fsize)/((float)(time_2-time_1))/1000.f));
  	
  	if(res){
  		printf("close file (%s) fail.\n\r", MP4_NAME);
  	}
  	
  	if(buf_ptr)
  		free(buf_ptr);
  	
  	res = f_close(&m_file);
  	
  exit:
  	httpd_conn_close(conn);
  }
  
  #include "wifi_constants.h"
  #include "wifi_structures.h"
  #include "lwip_netconf.h"
  
  static void wifi_init()
  {
  	rtw_mdelay_os(2000);
  	
  	printf("\r\nuse ATW0, ATW1, ATWC to make wifi connection\r\n");
  	printf("wait for wifi connection...\r\n");
  	
  	while (wifi_is_ready_to_transceive(RTW_STA_INTERFACE) != RTW_SUCCESS){
  		vTaskDelay(1000);
  	}
  }
  
  
  void example_sdcard_upload_httpd_main(void *parm)
  {
  	int ret = 0;
  	wifi_init();
  	
  	ret = fatfs_init(MP4_NAME);
  	if(ret >= 0){
  		printf("open file %s successful\r\n",MP4_NAME);
  		httpd_reg_page_callback("/", fatfs_homepage_cb);
  		httpd_reg_page_callback("/index.htm", fatfs_homepage_cb);
  		if(httpd_start(80, 5, 4096, HTTPD_THREAD_SINGLE, HTTPD_SECURE_NONE) != 0) {
  			printf("ERROR: httpd_start");
  			httpd_clear_page_callbacks();
  		}
  	}else{
  		printf("open %s failed\r\n",MP4_NAME);
  	}
  	
  exit:
  	vTaskDelete(NULL);
  }
  
  void example_sdcard_upload_httpd(void)
  {
  	if(xTaskCreate(example_sdcard_upload_httpd_main, ((const char*)"example_sdcard_upload_httpd_main"), STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL) != pdPASS)
  		printf("\n\r%s xTaskCreate(example_sdcard_upload_httpd_main) failed", __FUNCTION__);
  }
  
  #endif