#include #include #include #include // close() #include // strcpy, memset(), and memcpy() #include #include // errno, perror() #include #include #include #include #include #include #include #include #include #include // struct addrinfo #include #include // macro ioctl is defined #include // defines values for argument "request" of ioctl. #include #include // needed for socket(), uint8_t, uint16_t, uint32_t #include #include // needed for socket() #include #include #include #include #include // IPPROTO_ICMP, INET_ADDRSTRLEN #include // struct ip and IP_MAXPACKET (which is 65535) #include // struct icmp, ICMP_ECHO #include // inet_pton() and inet_ntop() #include // struct ifreq #include #include // ETH_P_IP = 0x0800, ETH_P_IPV6 = 0x86DD #include // struct sockaddr_ll (see man 7 packet) #include #include #include typedef enum { ACCEPTED, REJECTED, SUCCESS, FAIL, IDLE, UPDATING, }state_t; typedef struct update { int quit; int fd; int state; struct sockaddr_in peer_addr; socklen_t peer_addrlen; uint8_t rxbuff[1024]; int rxbyte; uint8_t txbuff[1024]; int txbyte; int filesize; int majorVersion; int minorVersion; int buildVersion; int major; int minor; int build; char ip_string[64]; int port; FILE *logfp; }update_t; static update_t update = { .fd = -1, .logfp = NULL }; // #define printd(fmt, ...) printf("%s:%d, %s | "fmt, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__) #define printd(fmt, ...) fprintf(dev->logfp, "%s:%d, %s | "fmt, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__) int wait_android_message(update_t* dev) { dev->rxbyte = 0; while(dev->rxbyte < 1024) { int ret = recv(dev->fd, &dev->rxbuff[dev->rxbyte], 1, 0); if (ret <= 0) { printd("ret : %d, errno:%d\n", ret, errno); shutdown(dev->fd, SHUT_RDWR); close(dev->fd); dev->fd = -1; return -1; } if (ret > 0) dev->rxbyte += ret; if (dev->rxbyte>=5) { if (strncmp(dev->rxbuff, "Event", 5)==0) { if (dev->rxbuff[dev->rxbyte-1] == '\n') { printd("recv:%s\n",dev->rxbuff); return 0; } }else{ memmove(&dev->rxbuff[0], &dev->rxbuff[1], dev->rxbyte - 1); dev->rxbyte = dev->rxbyte - 1; } } } return -1; } int android_LoadVersion(update_t* dev, const char* filename) { char filebuff[256]; dev->major = dev->major = dev->build = 0; memset(filebuff,0,sizeof(filebuff)); int ret = readlink(filename, filebuff, sizeof(filebuff)); printd("app_version.linkname=%s\n", filebuff); if (ret > 0) { // char* basename_str = strchr(filebuff, '/'); // if (basename_str) { sscanf(filebuff, "app_XHHW_%d_%d_%d", &dev->major, &dev->minor, &dev->build); printd("app_XHHW_%d_%d_%d\n", dev->major, dev->minor, dev->build); } } return 0; } int android_DowanloadFile(update_t* dev, const char* filename) { FILE *fp = fopen(filename, "rw"); if (fp) { dev->state = UPDATING; int recved = 0; while(recved < dev->filesize) { int len = dev->filesize - recved; if (len > 1024) len = 1024; int ret = recv(dev->fd, dev->rxbuff, len, 0); if (ret <= 0) { printd("ret:%d, errno:%d\n", ret, errno); shutdown(dev->fd, SHUT_RDWR); close(dev->fd); dev->fd = -1; return -1; } if (ret > 0) recved += ret; fwrite(dev->rxbuff, ret, 1, fp); } if (recved == dev->filesize) { dev->state = SUCCESS; }else{ dev->state = FAIL; } fclose(fp); printd("recvd.filename=%s, recvd.bytes:%d\n", filename, recved); return 0; } return -1; } int android_Upgrade(update_t* dev, const char* oldfilename, const char* newfilename) { if (dev->state == SUCCESS) { int idx = 0; char cmdbuff[256]; memset(cmdbuff,0,sizeof(cmdbuff)); idx += sprintf(&cmdbuff[idx], "pkill app_XHHW\n"); idx += sprintf(&cmdbuff[idx], "chmod +x %s\n", newfilename); idx += sprintf(&cmdbuff[idx], "rm -f %s\n", oldfilename); idx += sprintf(&cmdbuff[idx], "ln -s %s %s\n", newfilename, oldfilename); idx += sprintf(&cmdbuff[idx], "sync\n"); idx += sprintf(&cmdbuff[idx], "reboot\n"); int ret = system(cmdbuff); printf( "ret = %d, cmd = %s\n", ret, cmdbuff); // sprintf(cmdbuff, "chmod +x %s", newfilename);system(cmdbuff); // sprintf(cmdbuff, "rm -f %s", oldfilename);system(cmdbuff); // sprintf(cmdbuff, "ln -s %s %s", newfilename, oldfilename);system(cmdbuff); // sprintf(cmdbuff, "/home/root/bin/hmi.sh");system(cmdbuff); // chmod(filename, S_IRUSR|S_IWUSR|S_IXUSR | S_IXGRP|S_IRGRP|S_IXGRP | S_IROTH|S_IWOTH|S_IXOTH); // unlink(newfilename); // symlink(filename, newfilename); dev->state = IDLE; return 0; } return -1; } int android_NotifyUpdateFirmware_res(update_t* dev, const char* status) { int len = sprintf(dev->txbuff, "Event=NotifyUpdateFirmware,Type=HW,Status=%s,Message=NONE\n", status); printd("send : %s\n",dev->txbuff); if (dev->fd > 0) return send(dev->fd, dev->txbuff, len, 0); else return -1; } int android_RequestUpdateFirmware_req(update_t* dev,int major, int minor, int build) { int len = sprintf(dev->txbuff, "Event=UpdateFirmware,Type=HW,Version=%d.%d.%d\n",major, minor, build); printd("send : %s\n",dev->txbuff); if (dev->fd > 0) return send(dev->fd, dev->txbuff, len, 0); else return -1; } int android_NotifyUpdateFirmwareResult_res(update_t* dev, const char* status,int major, int minor, int build) { int len = sprintf(dev->txbuff, "Event=NotifyUpdateFirmwareResult,Type=HW,Status=%s,Version=%d.%d.%d,Message=NONE\n", status, major, minor, build); printd("send : %s\n",dev->txbuff); if (dev->fd > 0) return send(dev->fd, dev->txbuff, len, 0); else return -1; } int android_GetFirmwareVersion_res(update_t* dev, int major, int minor, int build) { int len = sprintf(dev->txbuff, "Event=GetFirmwareVersion,Type=HW,Version=%d.%d.%d\n", major, minor, build); printd("send : %s\n",dev->txbuff); if (dev->fd > 0) return send(dev->fd, dev->txbuff, len, 0); else return -1; } int android_connect(update_t *dev) { if (dev) { while (dev->fd < 0) { dev->fd = socket(AF_INET, SOCK_STREAM, 0); if (dev->fd > 0) { dev->peer_addr.sin_family = AF_INET; dev->peer_addr.sin_addr.s_addr = inet_addr(dev->ip_string); dev->peer_addr.sin_port = htons(dev->port); dev->peer_addrlen = sizeof(dev->peer_addr); while(connect(dev->fd, (struct sockaddr*)&dev->peer_addr, dev->peer_addrlen) < 0){ printd("local socket connect to %s.%d failed.retry...\n", dev->ip_string, dev->port); sleep(1); } printf("local socket connect to %s.%d ok.\n", dev->ip_string, dev->port); return 0; } printd("create socket failed.retry...\n"); sleep(1); } return 0; } return -1; } void* xh_update_loop(void* argv) { update_t *dev = (update_t*)argv; while(dev->quit == 0) { android_connect(dev); if (wait_android_message(dev) == 0) { if (strncmp(dev->rxbuff, "Event=NotifyUpdateFirmware,Type=HW", 34)==0) { char newfilename[256]; char oldfilename[256]; memset(newfilename,0,sizeof(newfilename)); memset(oldfilename,0,sizeof(oldfilename)); sprintf(oldfilename, "/home/root/bin/app_XHHW"); sscanf(dev->rxbuff, "Event=NotifyUpdateFirmware,Type=HW,Size=%d,Version=%d.%d.%d\n", &dev->filesize, &dev->majorVersion, &dev->minorVersion, &dev->buildVersion); sprintf(newfilename, "/home/root/bin/app_XHHW_%d_%d_%d", dev->majorVersion, dev->minorVersion, dev->buildVersion); if (dev->major != dev->majorVersion || dev->minor!=dev->minorVersion || dev->build!=dev->buildVersion) { if (android_NotifyUpdateFirmware_res(dev, "Accepted") == 0) { sleep(1); if (android_RequestUpdateFirmware_req(dev, dev->major, dev->minor, dev->build) == 0) { if (android_DowanloadFile(dev, newfilename) == 0) { if (android_Upgrade(dev, oldfilename, newfilename) == 0) { dev->major = dev->majorVersion; dev->minor = dev->minorVersion; dev->build = dev->buildVersion; android_NotifyUpdateFirmwareResult_res(dev, "Success", dev->majorVersion, dev->minorVersion, dev->buildVersion); } }else{ android_NotifyUpdateFirmwareResult_res(dev, "Fail", dev->majorVersion, dev->minorVersion, dev->buildVersion); } } } }else{ android_NotifyUpdateFirmware_res(dev, "Rejected"); } } if (strncmp(dev->rxbuff, "Event=NotifyUpdateFirmwareResult,Type=HW", 40)==0) { continue; } if (strncmp(dev->rxbuff, "Event=GetFirmwareVersion,Type=HW", 32)==0) { android_GetFirmwareVersion_res(dev, dev->major, dev->minor, dev->build); } } } return NULL; } int xh_update_init(update_t *dev) { if (dev) { dev->fd = -1; // dev->logfp = fopen("/home/root/bin/log.txt", "w"); android_connect(dev); android_LoadVersion(dev, "/home/root/bin/app_XHHW"); } return -1; } void xh_update_exit(update_t *dev) { if (dev) { dev->quit = 1; close(dev->fd); dev->fd = -1; } } int main(int argc, char* argv[]) { sleep(10); update_t* dev = (update_t*)&update; { int c; dev->port = 20248; sprintf(dev->ip_string, "%s", "192.168.223.10"); while ((c = getopt(argc, argv, "ip:")) != -1) { switch (c) { case 'i': sprintf(dev->ip_string, "%s", optarg); break; case 'p': dev->port = atoi(optarg); break; case '?': break; default: exit(2); } } xh_update_init(dev); xh_update_loop(dev); xh_update_exit(dev); } return 0; }