diff options
author | Roman Yeryomin <roman@advem.lv> | 2012-09-22 19:44:27 +0300 |
---|---|---|
committer | Roman Yeryomin <roman@advem.lv> | 2012-09-22 19:44:27 +0300 |
commit | 1784b1575a27ac1bfc5cf9d9e5fd3b2d869d991d (patch) | |
tree | f8cad2717e99cad8b0f3e027430b03c38ec02aec /package/librtk-inband/src/inband_cmd.c | |
parent | 6fc13c5885603ee5257c79b0f922f6b220ddfcf2 (diff) |
Add hostapd-rtk and librtk-inband packages
Signed-off-by: Roman Yeryomin <roman@advem.lv>
Diffstat (limited to 'package/librtk-inband/src/inband_cmd.c')
-rw-r--r-- | package/librtk-inband/src/inband_cmd.c | 465 |
1 files changed, 465 insertions, 0 deletions
diff --git a/package/librtk-inband/src/inband_cmd.c b/package/librtk-inband/src/inband_cmd.c new file mode 100644 index 000000000..a85a04f8a --- /dev/null +++ b/package/librtk-inband/src/inband_cmd.c @@ -0,0 +1,465 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <signal.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <errno.h> + +#include <fcntl.h> +#include <sys/types.h> +#include <sys/uio.h> + +#include <sys/stat.h> //mark_file + +#include "inband_if.h" + +#define HOST_NETIF ("wlan0") +#define SLAVE_MAC ("001234567899") +#define ETH_P_RTK 0x8899 // Realtek Remote Control Protocol (RRCP) +int hcd_inband_chan=0; + +// command ID +#define id_ioctl 0x01 +#define id_systemcall 0x02 +#define id_firm_upgrade 0x03 +#define id_hostcmd_only 0xff //only for new hostcmd implement ,if the cmd is not real "inband cmd" + +// Command Table +struct inband_cmd_table_t { + char cmd_id; + const char *cmd; // Input command string + int (*func)(int index,int argc, char *argv[]); + void (*print_func)(char *para,char *data,int len); + const char *msg; // Help message +}; + +/*firmware define*/ +#define __PACK__ __attribute__ ((packed)) + +#define SIGNATURE_LEN 4 +#define FW_HEADER_WITH_ROOT ((char *)"cr6c") +#define FW_HEADER ((char *)"cs6c") +#define ROOT_HEADER ((char *)"r6cr") +#define WEB_HEADER ((char *)"w6cg") //no ap sign now //mark_issue + +typedef struct img_header { + unsigned char signature[SIGNATURE_LEN] __PACK__; + unsigned int startAddr __PACK__; + unsigned int burnAddr __PACK__; + unsigned int len __PACK__; +} IMG_HEADER_T, *IMG_HEADER_Tp; + + +unsigned int host_inband_seq=0; //use to do requset <-> response check + +int cmd_systemcall(int index,int argc, char *argv[]); +int cmd_firmware_upgrade(int index,int argc, char *argv[]); +void print_systemcall(char *para,char *data,int len); + + +struct inband_cmd_table_t inband_cmd_table[]= +{ + // + {id_systemcall,"systemcall", cmd_systemcall, print_systemcall, "inband systemcall \'cmd_string\'"}, + {id_firm_upgrade,"firm_upgrade", cmd_firmware_upgrade, NULL,"inband firm_upgrade /var/linux.bin"}, + //{id_hostcmd_only,"send_conf", cmd_sendconf, NULL,"inband send_conf /etc/xxx.conf"}, + {NULL, NULL, NULL}, +}; + + +unsigned int get_random(int max) +{ + struct timeval tod; + + gettimeofday(&tod , NULL); + srand(tod.tv_usec); + return rand()%max; +} + +void print_command_list(void) +{ + int i; + + printf("\n==========commands for debugging============\n"); + i = 0; + while (inband_cmd_table[i].cmd != NULL) { + printf("%s\n", inband_cmd_table[i].msg); + i++; + } +} + +void print_systemcall(char *para,char *data,int len) +{ + int i=0; + unsigned char *value; + + data[len] = '\0'; + printf("cmd_cfgread \n"); + printf("%s",data); +} + +static int host_inband_write(char cmd_id,char *data,int data_len) +{ + int ret; + + host_inband_seq = get_random(65536); + + ret = inband_write(hcd_inband_chan,host_inband_seq,cmd_id,data,data_len,0); //send request + return ret; +} + +static inline int CHECKSUM_OK(unsigned char *data, int len) +{ + int i; + unsigned char sum=0; + + for (i=0; i<len; i++) + sum += data[i]; + + if (sum == 0) + return 1; + else + return 0; +} + +static int fwChecksumOk(char *data, int len) +{ + unsigned short sum=0; + int i; + + for (i=0; i<len; i+=2) { +#ifdef _LITTLE_ENDIAN_ + sum += WORD_SWAP( *((unsigned short *)&data[i]) ); +#else + sum += *((unsigned short *)&data[i]); +#endif + + } + return( (sum==0) ? 1 : 0); +} +static int host_firmware_write(char *data,int len) +{ + unsigned int tx_seq,rx_seq; + int ret=0,count; + char rx_cmd_type; + char *buf_p; + + ret = host_inband_write(id_firm_upgrade,data,len); //send request + + tx_seq = host_inband_seq; + + if(ret < 0) + return -1; + + ret = inband_rcv_data_and_seq(hcd_inband_chan,&rx_seq,&rx_cmd_type,&buf_p,20000); //return data length + + if(ret < 0) + { + ret=-1; + goto out; + } + + if( (rx_cmd_type == id_firm_upgrade) && (tx_seq == rx_seq)) + printf("host_firmware_write ok!\n"); + else + { + ret=-1; + printf("host_firmware_write fail!\n"); + } + +out: + inband_free_buf(buf_p, count); + return ret; + +} + +static int rtk_firmware_update(char *upload_data, int upload_len) +{ +int head_offset=0 ; +int isIncludeRoot=0; +int len; + int numLeft; +int numWrite; +IMG_HEADER_Tp pHeader; +int fh; +int fwSizeLimit = 0x200000; +char buffer[100]; +int flag=0; + +while(head_offset < upload_len) { + + pHeader = (IMG_HEADER_Tp) &upload_data[head_offset]; + len = pHeader->len; +#ifdef _LITTLE_ENDIAN_ + len = DWORD_SWAP(len); +#endif + + numLeft = len + sizeof(IMG_HEADER_T) ; + + // check header and checksum + if (!memcmp(&upload_data[head_offset], FW_HEADER, SIGNATURE_LEN) || + !memcmp(&upload_data[head_offset], FW_HEADER_WITH_ROOT, SIGNATURE_LEN)) + flag = 1; + else if (!memcmp(&upload_data[head_offset], WEB_HEADER, SIGNATURE_LEN)) + flag = 2; + else if (!memcmp(&upload_data[head_offset], ROOT_HEADER, SIGNATURE_LEN)){ + flag = 3; + isIncludeRoot = 1; + } + else { + strcpy(buffer, "Invalid file format!"); + goto ret_upload; + } + + if(len > fwSizeLimit){ //len check by sc_yang + sprintf(buffer, "Image len exceed max size 0x%x ! len=0x%x",fwSizeLimit, len); + goto ret_upload; + } + if ( (flag == 1) || (flag == 3)) { + if ( !fwChecksumOk(&upload_data[sizeof(IMG_HEADER_T)+head_offset], len)) { + sprintf(buffer, "Image checksum mismatched! len=0x%x, checksum=0x%x", len, + *((unsigned short *)&upload_data[len-2]) ); + goto ret_upload; + } + } + else { + char *ptr = &upload_data[sizeof(IMG_HEADER_T)+head_offset]; + if ( !CHECKSUM_OK(ptr, len) ) { + sprintf(buffer, "Image checksum mismatched! len=0x%x", len); + goto ret_upload; + } + } + + //numWrite = write(fh, &(upload_data[locWrite+head_offset]), numLeft); + //inband write , and check ack + if(host_firmware_write(&(upload_data[head_offset]),numLeft) < 0 ) + { + sprintf(buffer, "host_firmware_write! numLeft=0x%x", numLeft); + goto ret_upload; + } + + head_offset += len + sizeof(IMG_HEADER_T) ; + } + + return 0; + + ret_upload: + fprintf(stderr, "%s\n", buffer); + return -1; +} //while //sc_yang + +int cmd_firmware_upgrade(int index,int argc, char *argv[]) +{ + int len,ret,count; + //char data[1480]; + char filename[50]; + char *data; + int fd,rc; + struct stat ffstat; + int flen=0; + + //sprintf(data,"%s",argv[2]); + sprintf(filename,"%s",argv[2]); + + fd = open(filename, O_RDONLY); + + if (fd < 0) { + printf("Cannot Open file %s!\n", filename); + return -1; + } + fstat(fd, &ffstat); + flen = ffstat.st_size; + printf("flen = %d \n",flen); + + if((data = (char *)malloc(flen)) == NULL) + { + printf("data buffer allocation failed!\n"); + return -1; + } + + // rc = read(fd, data, 1480); + rc = read(fd, data, flen); + + //if (rc != 1480) { + if (rc != flen) { + printf("Reading error\n"); + free(data); //need free before return!!!!! + return -1; + } + + close(fd); + + ret = rtk_firmware_update(data, flen); + + if(ret < 0) + printf("rtk_firmware_update fail \n"); + else + printf("rtk_firmware_update ok \n"); + + free(data); //need free before return!!!!! + + return ret; +} + +#if 0 +int cmd_sendconf(int index,int argc, char *argv[]) +{ + int len,ret,count; + //char data[1480]; + char cmd_id,rx_cmd_type; + char *buf_p; + unsigned int tx_seq,rx_seq; + char filename[50]; + char *data; + int fd,rc; + struct stat ffstat; + int flen=0; + + cmd_id = id_set_mib; + + //sprintf(data,"%s",argv[2]); + sprintf(filename,"%s",argv[2]); + + fd = open(filename, O_RDONLY); + + if (fd < 0) { + printf("Cannot Open file %s!\n", filename); + return -1; + } + fstat(fd, &ffstat); + flen = ffstat.st_size; + printf("flen = %d \n",flen); + + if((data = (char *)malloc(flen)) == NULL) + { + printf("data buffer allocation failed!\n"); + return -1; + } + + // rc = read(fd, data, 1480); + rc = read(fd, data, flen); + + //if (rc != 1480) { + if (rc != flen) { + printf("Reading error\n"); + free(data); //need free before return!!!!! + return -1; + } + + close(fd); + //len = 1480; + len = flen; + tx_seq = host_inband_seq; + ret = host_inband_write(cmd_id,data,len); //send request + + free(data); //need free before return!!!!! + + if(ret < 0) + return -1; + + //count = inband_rcv_data(&rx_cmd_type,&buf_p,1000); //return data length + count = inband_rcv_data_and_seq(hcd_inband_chan,&rx_seq,&rx_cmd_type,&buf_p,3000); //return data length + if(count < 0) + { + ret=-1; + goto out; + } + + if( (rx_cmd_type == cmd_id) && (tx_seq == rx_seq)) + printf("remote write ok!\n"); + else + { + ret=-1; + printf("remote write fail!\n"); + } + + out: + inband_free_buf(buf_p, count); + + return ret; +} +#endif +int cmd_systemcall(int index,int argc, char *argv[]) +{ + int len,ret,count; + char data[1480]; + char cmd_id,rx_cmd_type; + char *buf_p; + unsigned int tx_seq,rx_seq; + + cmd_id = inband_cmd_table[index].cmd_id; + + if(argc > 3) + sprintf(data,"%s %s",argv[2],argv[3]); + else + sprintf(data,"%s",argv[2]); + + len = strlen(data); + + + ret = host_inband_write(cmd_id,data,len); //send request + + tx_seq = host_inband_seq; + + if(ret < 0) + return -1; + + //count = inband_rcv_data(&rx_cmd_type,&buf_p,1000); //return data length + count = inband_rcv_data_and_seq(hcd_inband_chan,&rx_seq,&rx_cmd_type,&buf_p,1000); //return data length + + if(count < 0) + return -1; + //printf("count=%d rx_cmd_type=%x,cmd_id=%x,tx_seq=%d,rx_seq=%d",count,rx_cmd_type,cmd_id,tx_seq,rx_seq); + + if((rx_cmd_type == cmd_id) && (tx_seq == rx_seq)) + { + if(inband_cmd_table[index].print_func) + inband_cmd_table[index].print_func(data,buf_p,count); + } + else + return -1; + + return 0; + +} + +int main(int argc, char *argv[]) +{ + //int fdflags; + //unsigned int arg; + int i, ret; + int chan; + + if (argc < 2) { + print_command_list(); + return 0; + } + + //open inband + chan = inband_open(HOST_NETIF,SLAVE_MAC,ETH_P_RTK,0); + if (chan < 0) { + printf("open inband failed!\n"); + return -1; + } + hcd_inband_chan = chan; + + i = 0; + while (inband_cmd_table[i].cmd != NULL) { + if (0 == strcmp(argv[1], inband_cmd_table[i].cmd)) { + if (inband_cmd_table[i].func) { + ret = inband_cmd_table[i].func(i,argc, argv); + if (ret > 0) + printf("OK\n"); + else if (ret < 0) + printf("FAIL\n"); + } + break; + } + i++; + } + + inband_close(hcd_inband_chan); + + return 0; +} |