fix 'ret' have not initialized
[mfgtools.git] / uuu / uuu.cpp
blobcafd2f8e40c1d677d82536bc32e9a49238601dea
1 /*
2 * Copyright 2018 NXP.
4 * Redistribution and use in source and binary forms, with or without modification,
5 * are permitted provided that the following conditions are met:
7 * Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright notice, this
11 * list of conditions and the following disclaimer in the documentation and/or
12 * other materials provided with the distribution.
14 * Neither the name of the NXP Semiconductor nor the names of its
15 * contributors may be used to endorse or promote products derived from this
16 * software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
32 #include <iostream>
33 #include <stdio.h>
34 #include <thread>
35 #include <atomic>
36 #include <iomanip>
37 #include <map>
38 #include <mutex>
39 #include <vector>
40 #include <sstream>
41 #include <fstream>
42 #include <stdarg.h>
43 #include <time.h>
44 #include <string.h>
45 #include <signal.h>
46 #include "buildincmd.h"
47 #include <string>
48 #include <streambuf>
50 #include "../libuuu/libuuu.h"
52 const char * g_vt_yellow = "\x1B[93m";
53 const char * g_vt_default = "\x1B[0m";
54 const char * g_vt_green = "\x1B[92m";
55 const char * g_vt_red = "\x1B[91m";
56 const char * g_vt_kcyn = "\x1B[36m";
57 const char * g_vt_boldwhite = "\x1B[97m";
59 void clean_vt_color() noexcept
61 g_vt_yellow = "";
62 g_vt_default = g_vt_yellow;
63 g_vt_green = g_vt_yellow;
64 g_vt_red = g_vt_yellow;
65 g_vt_kcyn = g_vt_yellow;
66 g_vt_boldwhite = g_vt_yellow;
69 using namespace std;
71 int get_console_width();
72 void print_oneline(string str);
73 int auto_complete(int argc, char**argv);
74 void print_autocomplete_help();
76 char g_sample_cmd_list[] = {
77 #include "uuu.clst"
80 vector<string> g_usb_path_filter;
81 vector<string> g_usb_serial_no_filter;
83 int g_verbose = 0;
84 static bool g_start_usb_transfer;
86 bmap_mode g_bmap_mode = bmap_mode::Default;
88 class AutoCursor
90 public:
91 ~AutoCursor()
93 printf("\x1b[?25h\n\n\n");
97 void ctrl_c_handle(int)
99 do {
100 AutoCursor a;
101 } while(0);
103 exit(1);
106 class string_ex : public std::string
108 public:
109 int format(const char *fmt, ...)
111 va_list args;
112 va_start(args, fmt);
113 size_t len = std::vsnprintf(NULL, 0, fmt, args);
114 va_end(args);
116 this->resize(len);
118 va_start(args, fmt);
119 std::vsnprintf((char*)c_str(), len + 1, fmt, args);
120 va_end(args);
122 return 0;
126 #ifdef _WIN32
127 #include <conio.h>
128 #else
129 #include <termios.h>
130 #include <unistd.h>
131 #endif
133 int ask_passwd(char* prompt, char user[MAX_USER_LEN], char passwd[MAX_USER_LEN])
135 cout << endl << prompt << " Required Login"<<endl;
136 cout << "Username:";
137 cin.getline(user, 128);
138 cout << "Password:";
139 int i = 0;
141 #ifdef _WIN32
142 while ((passwd[i] = _getch()) != '\r') {
143 if (passwd[i] == '\b') {
144 if (i != 0) {
145 cout << "\b \b";
146 i--;
149 else {
150 cout << '*';
151 i++;
154 #else
155 struct termios old, tty;
156 tcgetattr(STDIN_FILENO, &tty);
157 old = tty;
158 tty.c_lflag &= ~ECHO;
159 tcsetattr(STDIN_FILENO, TCSANOW, &tty);
161 string pd;
162 getline(cin, pd);
164 tcsetattr(STDIN_FILENO, TCSANOW, &old);
165 if(pd.size() > MAX_USER_LEN -1)
166 return -1;
167 memcpy(passwd, pd.data(), pd.size());
168 i=pd.size();
170 #endif
171 passwd[i] = 0;
172 cout << endl;
173 return 0;
176 void print_help(bool detail = false)
178 const char help[] =
179 "uuu [-d -m -v -V -bmap -no-bmap] <" "bootloader|cmdlists|cmd" ">\n\n"
180 " bootloader download bootloader to board by usb\n"
181 " cmdlist run all commands in cmdlist file\n"
182 " If it is path, search uuu.auto in dir\n"
183 " If it is zip, search uuu.auto in zip\n"
184 " cmd Run one command, use -H see detail\n"
185 " example: SDPS: boot -f flash.bin\n"
186 " -d Daemon mode, wait for forever.\n"
187 " -v -V verbose mode, -V enable libusb error\\warning info\n"
188 " -dry Dry run mode, check if script or cmd correct \n"
189 " -bmap Try using .bmap files even if flash commands do not specify them\n"
190 " -no-bmap Ignore .bmap files even if flash commands specify them\n"
191 " -m USBPATH Only monitor these paths.\n"
192 " -m 1:2 -m 1:3\n\n"
193 " -ms serial_no Monitor the serial number prefix of the device using 'serial_no'.\n"
194 " -t Timeout second for wait known usb device appeared\n"
195 " -T Timeout second for wait next known usb device appeared at stage switch\n"
196 " -e set environment variable key=value\n"
197 " -pp usb polling period in milliseconds\n"
198 " -dm disable small memory\n"
199 "uuu -s Enter shell mode. uuu.inputlog record all input commands\n"
200 " you can use \"uuu uuu.inputlog\" next time to run all commands\n\n"
201 "uuu -udev linux: show udev rule to avoid sudo each time \n"
202 "uuu -lsusb List connected know devices\n"
203 "uuu -IgSerNum Set windows registry to ignore USB serial number for known uuu devices\n"
204 "uuu -h show general help\n"
205 "uuu -H show general help and detailed help for commands\n\n";
206 printf("%s", help);
207 printf("uuu [-d -m -v -bmap -no-bmap] -b[run] ");
208 g_BuildScripts.ShowCmds();
209 printf(" arg...\n");
210 printf("\tRun Built-in scripts\n");
211 g_BuildScripts.ShowAll();
212 printf("\nuuu -bshow ");
213 g_BuildScripts.ShowCmds();
214 printf("\n");
215 printf("\tShow built-in script\n");
216 printf("\n");
218 print_autocomplete_help();
220 if (detail == false)
221 return;
223 size_t start = 0, pos = 0;
224 string str= g_sample_cmd_list;
226 bool bprint = false;
227 while ((pos = str.find('\n',pos)) != str.npos)
229 string s = str.substr(start, pos - start);
230 if (s.substr(0, 6) == "# ----")
231 bprint = true;
233 if (bprint)
235 if (s[0] == '#')
237 printf("%s\n", &(s[1]));
240 pos += 1;
241 start = pos;
244 void print_version()
246 printf("uuu (Universal Update Utility) for nxp imx chips -- %s\n\n", uuu_get_version_string());
249 int print_cfg(const char *pro, const char * chip, const char * /*compatible*/, uint16_t vid, uint16_t pid, uint16_t bcdmin, uint16_t bcdmax, void * /*p*/)
251 const char *ext;
252 if (strlen(chip) >= 7)
253 ext = "";
254 else
255 ext = "\t";
257 if (bcdmin == 0 && bcdmax == 0xFFFF)
258 printf("\t%s\t %s\t%s 0x%04x\t 0x%04x\n", pro, chip, ext, vid, pid);
259 else
260 printf("\t%s\t %s\t%s 0x%04x\t 0x%04x\t [0x%04x..0x%04x]\n", pro, chip, ext, vid, pid, bcdmin, bcdmax);
261 return 0;
264 int print_udev_rule(const char * /*pro*/, const char * /*chip*/, const char * /*compatible*/,
265 uint16_t vid, uint16_t pid, uint16_t /*bcdmin*/, uint16_t /*bcdmax*/, void * /*p*/)
267 printf("SUBSYSTEM==\"usb\", ATTRS{idVendor}==\"%04x\", ATTRS{idProduct}==\"%04x\", TAG+=\"uaccess\"\n",
268 vid, pid);
269 return 0;
272 int polling_usb(std::atomic<int>& bexit);
274 int g_overall_status;
275 int g_overall_okay;
276 int g_overall_failure;
277 char g_wait[] = "|/-\\";
278 int g_wait_index;
281 string build_process_bar(size_t width, size_t pos, size_t total)
283 string str;
284 str.resize(width, ' ');
285 str[0] = '[';
286 str[width - 1] = ']';
288 if (total == 0)
290 if (pos == 0)
291 return str;
293 string_ex loc;
294 size_t s = pos / (1024 * 1024);
295 loc.format("%dM", s);
296 str.replace(1, loc.size(), loc);
297 return str;
300 size_t i;
302 if (pos > total)
303 pos = total;
305 for (i = 1; i < (width-2) * pos / total; i++)
307 str[i] = '=';
310 if (i > 1)
311 str[i] = '>';
313 if (pos == total)
314 str[str.size() - 2] = '=';
316 string_ex per;
317 per.format("%d%%", pos * 100 / total);
319 size_t start = (width - per.size()) / 2;
320 str.replace(start, per.size(), per);
321 str.insert(start, g_vt_yellow);
322 str.insert(start + per.size() + strlen(g_vt_yellow), g_vt_default);
323 return str;
326 void print_auto_scroll(string str, size_t len, size_t start)
328 if (str.size() <= len)
330 str.resize(len, ' ');
331 cout << str;
332 return;
335 if(str.size())
336 start = start % str.size();
337 else
338 start = 0;
340 string s = str.substr(start, len);
341 s.resize(len, ' ');
342 cout << s;
344 class ShowNotify
346 public:
347 string m_cmd;
348 string m_dev;
349 size_t m_trans_pos = 0;
350 int m_status = 0;
351 size_t m_cmd_total = 0;
352 size_t m_cmd_index = 0;
353 string m_last_err;
354 int m_done = 0;
355 size_t m_start_pos = 0;
356 size_t m_trans_size = 0;
357 clock_t m_start_time;
358 uint64_t m_cmd_start_time;
359 uint64_t m_cmd_end_time;
360 bool m_IsEmptyLine = false;
362 ShowNotify() : m_start_time{clock()} {}
364 bool update(uuu_notify nt)
366 if (nt.type == uuu_notify::NOTIFY_DEV_ATTACH)
368 m_dev = nt.str;
369 m_done = 0;
370 m_status = 0;
372 if (nt.type == uuu_notify::NOTIFY_CMD_START)
374 m_start_pos = 0;
375 m_cmd = nt.str;
376 m_cmd_start_time = nt.timestamp;
378 if (nt.type == uuu_notify::NOTIFY_DECOMPRESS_START)
380 m_start_pos = 0;
381 m_cmd = nt.str;
382 m_cmd_start_time = nt.timestamp;
383 m_dev = "Prep";
385 if (nt.type == uuu_notify::NOTIFY_DOWNLOAD_START)
387 m_start_pos = 0;
388 m_cmd = nt.str;
389 m_cmd_start_time = nt.timestamp;
390 m_dev = "Prep";
392 if (nt.type == uuu_notify::NOTIFY_DOWNLOAD_END)
394 m_IsEmptyLine = true;
396 if (nt.type == uuu_notify::NOTIFY_TRANS_SIZE || nt.type == uuu_notify::NOTIFY_DECOMPRESS_SIZE)
398 m_trans_size = nt.total;
399 return false;
401 if (nt.type == uuu_notify::NOTIFY_CMD_TOTAL)
403 m_cmd_total = nt.total;
404 return false;
406 if (nt.type == uuu_notify::NOTIFY_CMD_INDEX)
408 m_cmd_index = nt.index;
409 return false;
411 if (nt.type == uuu_notify::NOTIFY_DONE)
413 if (m_status)
414 g_overall_failure++;
415 else
416 g_overall_okay++;
418 m_done = 1;
420 if (nt.type == uuu_notify::NOTIFY_CMD_END)
422 m_cmd_end_time = nt.timestamp;
423 if(nt.status)
425 g_overall_status = nt.status;
426 m_last_err = uuu_get_last_err_string();
428 m_status |= nt.status;
429 if (m_status)
430 g_overall_failure++;
432 if (nt.type == uuu_notify::NOTIFY_TRANS_POS || nt.type == uuu_notify::NOTIFY_DECOMPRESS_POS)
434 if (m_trans_size == 0) {
436 m_trans_pos = nt.index;
437 return true;
440 if ((nt.index - m_trans_pos) < (m_trans_size / 100)
441 && nt.index != m_trans_size)
442 return false;
444 m_trans_pos = nt.index;
447 return true;
449 void print_verbose(uuu_notify*nt)
451 if (this->m_dev == "Prep" && g_start_usb_transfer)
452 return;
454 if (nt->type == uuu_notify::NOTIFY_DEV_ATTACH)
456 cout << "New USB Device Attached at " << nt->str << endl;
458 if (nt->type == uuu_notify::NOTIFY_CMD_START)
460 cout << m_dev << ">" << "Start Cmd:" << nt->str << endl;
462 if (nt->type == uuu_notify::NOTIFY_CMD_END)
464 double diff = m_cmd_end_time - m_cmd_start_time;
465 diff /= 1000;
466 if (nt->status)
468 cout << m_dev << ">" << g_vt_red <<"Fail " << uuu_get_last_err_string() << "("<< std::setprecision(4) << diff << "s)" << g_vt_default << endl;
470 else
472 cout << m_dev << ">" << g_vt_green << "Okay ("<< std::setprecision(4) << diff << "s)" << g_vt_default << endl;
476 if (nt->type == uuu_notify::NOTIFY_TRANS_POS || nt->type == uuu_notify::NOTIFY_DECOMPRESS_POS)
478 if (m_trans_size)
479 cout << g_vt_yellow << "\r" << m_trans_pos * 100 / m_trans_size <<"%" << g_vt_default;
480 else
481 cout << "\r" << m_trans_pos;
483 cout.flush();
486 if (nt->type == uuu_notify::NOTIFY_CMD_INFO)
487 cout << nt->str;
489 if (nt->type == uuu_notify::NOTIFY_WAIT_FOR)
490 cout << "\r" << nt->str << " "<< g_wait[((g_wait_index++) & 0x3)];
492 if (nt->type == uuu_notify::NOTIFY_DECOMPRESS_START)
493 cout << "Decompress file:" << nt->str << endl;
495 if (nt->type == uuu_notify::NOTIFY_DOWNLOAD_START)
496 cout << "Download file:" << nt->str << endl;
499 void print(int verbose = 0, uuu_notify*nt=NULL)
501 verbose ? print_verbose(nt) : print_simple();
503 string get_print_dev_string()
505 string str;
506 str = m_dev;
507 str.resize(12, ' ');
509 string_ex s;
510 s.format("%2d/%2d", m_cmd_index+1, m_cmd_total);
512 str += s;
513 return str;
515 void print_simple()
517 int width = get_console_width();
518 int info, bar;
519 info = 18;
520 bar = 40;
522 if (m_IsEmptyLine)
524 string str(width, ' ');
525 cout << str;
526 return;
528 if (width <= bar + info + 3)
530 string_ex str;
532 str += get_print_dev_string();
534 str += g_wait[(g_wait_index++) & 0x3];
536 print_oneline(str);
537 return ;
539 else
541 string_ex str;
542 str += get_print_dev_string();
544 str.resize(info, ' ');
545 cout << str;
547 if (m_done || m_status)
549 string str;
550 str.resize(bar, ' ');
551 str[0] = '[';
552 str[str.size() - 1] = ']';
553 string err;
554 if (m_status)
556 err = uuu_get_last_err_string();
557 err.resize(bar - 2, ' ');
558 str.replace(1, err.size(), err);
559 str.insert(1, g_vt_red);
560 str.insert(1 + strlen(g_vt_red) + err.size(), g_vt_default);
562 else
564 str.replace(1, 4, "Done");
565 str.insert(1, g_vt_green);
566 str.insert(1 + strlen(g_vt_green) + strlen("Done"), g_vt_default);
568 cout << str;
569 } else {
570 cout << build_process_bar(bar, m_trans_pos, m_trans_size);
572 cout << " ";
573 print_auto_scroll(m_cmd, width - bar - info-1, m_start_pos);
575 if (clock() - m_start_time > CLOCKS_PER_SEC / 4)
577 m_start_pos++;
578 m_start_time = clock();
580 cout << endl;
582 return;
587 static map<string, ShowNotify> g_map_path_nt;
588 mutex g_callback_mutex;
590 void print_oneline(string str)
592 size_t w = get_console_width();
593 if (w <= 3)
594 return;
596 if (str.size() >= w)
598 str.resize(w - 1);
599 str[str.size() - 1] = '.';
600 str[str.size() - 2] = '.';
601 str[str.size() - 3] = '.';
603 else
605 str.resize(w, ' ');
607 cout << str << endl;
611 ShowNotify Summary(map<uint64_t, ShowNotify> *np)
613 ShowNotify sn;
614 for (auto it = np->begin(); it != np->end(); it++)
616 if (it->second.m_dev == "Prep")
618 sn.m_trans_size += it->second.m_trans_size;
619 sn.m_trans_pos += it->second.m_trans_pos;
621 else
623 if (it->second.m_trans_pos || it->second.m_cmd_index)
624 g_start_usb_transfer = true; // Hidden HTTP download when USB start transfer
628 if(g_start_usb_transfer)
629 sn.m_IsEmptyLine = true; // Hidden HTTP download when USB start transfer
631 sn.m_dev = "Prep";
632 sn.m_cmd = "Http Download\\Uncompress";
633 return sn;
636 int progress(uuu_notify nt, void *p)
638 map<uint64_t, ShowNotify> *np = (map<uint64_t, ShowNotify>*)p;
639 map<string, ShowNotify>::iterator it;
641 std::lock_guard<std::mutex> lock(g_callback_mutex);
643 if ((*np)[nt.id].update(nt))
645 if (!(*np)[nt.id].m_dev.empty())
646 if ((*np)[nt.id].m_dev != "Prep")
647 g_map_path_nt[(*np)[nt.id].m_dev] = (*np)[nt.id];
649 if (g_verbose)
651 if((*np)[nt.id].m_dev == "Prep")
652 Summary(np).print(g_verbose, &nt);
653 else
654 (*np)[nt.id].print(g_verbose, &nt);
656 else
658 string_ex str;
659 str.format("\rSuccess %d Failure %d ", g_overall_okay, g_overall_failure);
661 if (g_map_path_nt.empty())
662 str += "Wait for Known USB Device Appear...";
664 if (!g_usb_path_filter.empty())
666 str += " at path ";
667 for (size_t i = 0; i < g_usb_path_filter.size(); i++)
668 str += g_usb_path_filter[i] + " ";
671 if (!g_usb_serial_no_filter.empty())
673 str += " at serial_no ";
674 for (auto it: g_usb_serial_no_filter)
675 str += it + "*";
678 print_oneline(str);
679 print_oneline("");
680 if ((*np)[nt.id].m_dev == "Prep" && !g_start_usb_transfer)
682 Summary(np).print();
683 }else
684 print_oneline("");
686 for (it = g_map_path_nt.begin(); it != g_map_path_nt.end(); it++)
687 it->second.print();
689 for (size_t i = 0; i < g_map_path_nt.size() + 3; i++)
690 cout << "\x1B[1F";
694 //(*np)[nt.id] = g_map_path_nt[(*np)[nt.id].m_dev];
697 if (nt.type == uuu_notify::NOTIFY_THREAD_EXIT)
699 if(np->find(nt.id) != np->end())
700 np->erase(nt.id);
702 return 0;
704 #ifdef _MSC_VER
706 #define DEFINE_CONSOLEV2_PROPERTIES
707 #include <windows.h>
708 #include <stdlib.h>
709 #include <stdio.h>
711 bool enable_vt_mode()
713 // Set output mode to handle virtual terminal sequences
714 HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
715 if (hOut == INVALID_HANDLE_VALUE)
717 clean_vt_color();
718 return false;
721 DWORD dwMode = 0;
722 if (!GetConsoleMode(hOut, &dwMode))
724 clean_vt_color();
725 return false;
728 dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
729 if (!SetConsoleMode(hOut, dwMode))
731 clean_vt_color();
732 return false;
734 return true;
737 int get_console_width()
739 CONSOLE_SCREEN_BUFFER_INFO sbInfo;
740 GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &sbInfo);
741 return sbInfo.dwSize.X;
743 #else
744 #include <sys/ioctl.h>
745 bool enable_vt_mode() { return true; }
746 int get_console_width()
748 struct winsize w;
749 ioctl(0, TIOCGWINSZ, &w);
750 return w.ws_col;
752 #endif
753 void print_usb_filter()
755 if (!g_usb_path_filter.empty())
757 cout << " at path ";
758 for (size_t i = 0; i < g_usb_path_filter.size(); i++)
759 cout << g_usb_path_filter[i] << " ";
763 int runshell(int shell)
765 int uboot_cmd = 0;
766 string prompt = "U>";
768 if (shell)
770 cout << "Please input command: " << endl;
771 string cmd;
772 ofstream log("uuu.inputlog", ofstream::binary);
773 log << "uuu_version "
774 << ((uuu_get_version() & 0xFF000000) >> 24)
775 << "."
776 << ((uuu_get_version() & 0xFFF000) >> 12)
777 << "."
778 << ((uuu_get_version() & 0xFFF))
779 << endl;
780 while (1)
782 cout << prompt;
783 getline(cin, cmd);
785 if (cmd == "uboot")
787 uboot_cmd = 1;
788 prompt = "=>";
789 cout << "Enter into u-boot cmd mode" << endl;
790 cout << "Okay" << endl;
792 else if (cmd == "exit" && uboot_cmd == 1)
794 uboot_cmd = 0;
795 prompt = "U>";
796 cout << "Exit u-boot cmd mode" << endl;
797 cout << "Okay" << endl;
798 }else if (cmd == "help" || cmd == "?")
800 print_help();
802 else if (cmd == "q" || cmd == "quit")
804 return 0;
806 else
808 log << cmd << endl;
809 log.flush();
811 if (uboot_cmd)
812 cmd = "fb: ucmd " + cmd;
814 int ret = uuu_run_cmd(cmd.c_str(), 0);
815 if (ret)
816 cout << uuu_get_last_err_string() << endl;
817 else
818 cout << "Okay" << endl;
821 return 0;
824 return -1;
827 void print_udev()
829 uuu_for_each_cfg(print_udev_rule, NULL);
830 fprintf(stderr, "\n1: put above udev run into /etc/udev/rules.d/70-uuu.rules\n");
831 fprintf(stderr, "\tsudo sh -c \"uuu -udev >> /etc/udev/rules.d/70-uuu.rules\"\n");
832 fprintf(stderr, "2: update udev rule\n");
833 fprintf(stderr, "\tsudo udevadm control --reload\n");
836 int print_usb_device(const char *path, const char *chip, const char *pro, uint16_t vid, uint16_t pid, uint16_t bcd, const char *serial_no, void * /*p*/)
838 printf("\t%s\t %s\t %s\t 0x%04X\t0x%04X\t 0x%04X\t %s\n", path, chip, pro, vid, pid, bcd, serial_no);
839 return 0;
842 void print_lsusb()
844 cout << "Connected Known USB Devices\n";
845 printf("\tPath\t Chip\t Pro\t Vid\t Pid\t BcdVersion\t Serial_no\n");
846 printf("\t====================================================================\n");
848 uuu_for_each_devices(print_usb_device, NULL);
851 #ifdef WIN32
853 int ignore_serial_number(const char *pro, const char *chip, const char */*comp*/, uint16_t vid, uint16_t pid, uint16_t /*bcdlow*/, uint16_t /*bcdhigh*/, void */*p*/)
855 printf("\t %s\t %s\t 0x%04X\t0x%04X\n", chip, pro, vid, pid);
857 char sub[128];
858 snprintf(sub, 128, "IgnoreHWSerNum%04x%04x", vid, pid);
859 const BYTE value = 1;
861 LSTATUS ret = RegSetKeyValueA(HKEY_LOCAL_MACHINE,
862 "SYSTEM\\CurrentControlSet\\Control\\UsbFlags",
863 sub, REG_BINARY, &value, 1);
864 if(ret == ERROR_SUCCESS)
865 return 0;
867 printf("Set key failure, try run as administrator permission\n");
868 return -1;
870 #endif
872 int set_ignore_serial_number()
874 #ifndef WIN32
875 printf("Only windows system need set ignore serial number registry");
876 return -1;
877 #else
878 printf("Set window registry to ignore usb hardware serial number for known uuu device:\n");
879 return uuu_for_each_cfg(ignore_serial_number, NULL);
880 #endif
883 int main(int argc, char **argv)
885 if (auto_complete(argc, argv) == 0)
886 return 0;
888 if (argc >= 2)
890 string s = argv[1];
891 if(s == "-udev")
893 print_udev();
894 return 0;
896 if (s == "-bshow")
898 if (2 == argc || g_BuildScripts.find(argv[2]) == g_BuildScripts.end())
900 fprintf(stderr, "Error, must be have script name: ");
901 g_BuildScripts.ShowCmds(stderr);
902 fprintf(stderr,"\n");
903 return -1;
905 else
907 string str = g_BuildScripts[argv[2]].m_text;
908 while (str.size() > 0 && (str[0] == '\n' || str[0] == ' '))
909 str = str.erase(0,1);
911 printf("%s", str.c_str());
912 return 0;
917 AutoCursor a;
919 print_version();
921 if (!enable_vt_mode())
923 cout << "Your console don't support VT mode, fail back to verbose mode" << endl;
924 g_verbose = 1;
927 if (argc == 1)
929 print_help();
930 return 0;
933 int deamon = 0;
934 int shell = 0;
935 string filename;
936 string cmd;
937 int ret;
938 int dryrun = 0;
940 string cmd_script;
942 for (int i = 1; i < argc; i++)
944 string s = argv[i];
945 if (!s.empty() && s[0] == '-')
947 if (s == "-d")
949 deamon = 1;
950 uuu_set_small_mem(0);
953 else if (s == "-dm")
955 uuu_set_small_mem(0);
957 else if (s == "-s")
959 shell = 1;
960 g_verbose = 1;
962 else if (s == "-v")
964 g_verbose = 1;
966 else if (s == "-V")
968 g_verbose = 1;
969 uuu_set_debug_level(2);
970 }else if (s == "-dry")
972 dryrun = 1;
973 g_verbose = 1;
975 else if (s == "-h")
977 print_help(false);
978 return 0;
980 else if (s == "-H")
982 print_help(true);
983 return 0;
985 else if (s == "-m")
987 i++;
988 uuu_add_usbpath_filter(argv[i]);
989 g_usb_path_filter.push_back(argv[i]);
991 else if (s == "-ms")
993 i++;
994 uuu_add_usbserial_no_filter(argv[i]);
995 g_usb_serial_no_filter.push_back(argv[i]);
997 else if (s == "-t")
999 i++;
1000 uuu_set_wait_timeout(atoll(argv[i]));
1002 else if (s == "-T")
1004 i++;
1005 uuu_set_wait_next_timeout(atoll(argv[i]));
1007 else if (s == "-pp")
1009 i++;
1010 uuu_set_poll_period(atoll(argv[i]));
1012 else if (s == "-lsusb")
1014 print_lsusb();
1015 return 0;
1017 else if (s == "-IgSerNum")
1019 return set_ignore_serial_number();
1021 else if (s == "-bmap")
1023 g_bmap_mode = bmap_mode::Force;
1025 else if (s == "-no-bmap")
1027 g_bmap_mode = bmap_mode::Ignore;
1029 else if (s == "-e")
1031 #ifndef WIN32
1032 #define _putenv putenv
1033 #endif
1034 i++;
1035 if (_putenv(argv[i]))
1037 printf("error, failed to set '%s', environment parameter must have the form key=value\n", argv[i]);
1038 return -1;
1041 else if (s == "-b" || s == "-brun")
1043 if (i + 1 == argc)
1045 printf("error, must be have script name: ");
1046 g_BuildScripts.ShowCmds();
1047 printf("\n");
1048 return -1;
1051 vector<string> args;
1052 for (int j = i + 2; j < argc; j++)
1054 string s = argv[j];
1055 if (s.find(' ') != string::npos)
1057 s.insert(s.begin(), '"');
1058 s.insert(s.end(), '"');
1060 args.push_back(s);
1063 // if script name is not build-in, try to look for a file
1064 if (g_BuildScripts.find(argv[i + 1]) == g_BuildScripts.end()) {
1065 const string tmpCmdFileName{argv[i + 1]};
1067 std::ifstream t(tmpCmdFileName);
1068 std::string fileContents((std::istreambuf_iterator<char>(t)),
1069 std::istreambuf_iterator<char>());
1071 if (fileContents.empty()) {
1072 printf("%s is not built-in script or fail load external script file", tmpCmdFileName.c_str());
1073 return -1;
1076 BuiltInScriptRawData tmpCmd{
1077 tmpCmdFileName.c_str(),
1078 fileContents.c_str(),
1079 "Script loaded from file"
1082 g_BuildScripts.emplace(tmpCmdFileName, &tmpCmd);
1084 cmd_script = g_BuildScripts[tmpCmdFileName].replace_script_args(args);
1086 else {
1087 cmd_script = g_BuildScripts[argv[i + 1]].replace_script_args(args);
1089 break;
1091 else
1093 cout << "Unknown option: " << s.c_str();
1094 return -1;
1096 }else if (!s.empty() && s[s.size() - 1] == ':')
1098 for (int j = i; j < argc; j++)
1100 s = argv[j];
1101 if (s.find(' ') != string::npos && s[s.size() - 1] != ':')
1103 s.insert(s.begin(), '"');
1104 s.insert(s.end(), '"');
1106 cmd.append(s);
1107 if(j != (argc -1)) /* Don't add space at last arg */
1108 cmd.append(" ");
1110 break;
1112 else
1114 filename = s;
1115 break;
1119 signal(SIGINT, ctrl_c_handle);
1121 uuu_set_askpasswd(ask_passwd);
1123 if (deamon && shell)
1125 printf("Error: -d -s Can't apply at the same time\n");
1126 return -1;
1129 if (deamon && dryrun)
1131 printf("Error: -d -dry Can't apply at the same time\n");
1132 return -1;
1135 if (shell && dryrun)
1137 printf("Error: -dry -s Can't apply at the same time\n");
1138 return -1;
1141 if (g_verbose)
1143 printf("%sBuild in config:%s\n", g_vt_boldwhite, g_vt_default);
1144 printf("\tPctl\t Chip\t\t Vid\t Pid\t BcdVersion\t Serial_No\n");
1145 printf("\t==================================================\n");
1146 uuu_for_each_cfg(print_cfg, NULL);
1148 if (!cmd_script.empty())
1149 printf("\n%sRun built-in script:%s\n %s\n\n", g_vt_boldwhite, g_vt_default, cmd_script.c_str());
1151 if (!shell)
1152 cout << "Wait for Known USB Device Appear...";
1154 print_usb_filter();
1156 printf("\n");
1158 else {
1159 cout << "Wait for Known USB Device Appear...";
1160 print_usb_filter();
1161 cout << "\r";
1162 cout << "\x1b[?25l";
1163 cout.flush();
1166 map<uint64_t, ShowNotify> nt_session;
1168 uuu_register_notify_callback(progress, &nt_session);
1171 if (!cmd.empty())
1173 ret = uuu_run_cmd(cmd.c_str(), dryrun);
1175 for (size_t i = 0; i < g_map_path_nt.size()+3; i++)
1176 printf("\n");
1177 if(ret)
1178 printf("\nError: %s\n", uuu_get_last_err_string());
1179 else
1180 printf("Okay\n");
1182 runshell(shell);
1183 return ret;
1186 if (!cmd_script.empty())
1187 ret = uuu_run_cmd_script(cmd_script.c_str(), dryrun);
1188 else
1189 ret = uuu_auto_detect_file(filename.c_str());
1191 if (ret)
1193 ret = runshell(shell);
1194 if(ret)
1195 cout << g_vt_red << "\nError: " << g_vt_default << uuu_get_last_err_string();
1196 return ret;
1199 if (uuu_wait_uuu_finish(deamon, dryrun))
1201 cout << g_vt_red << "\nError: " << g_vt_default << uuu_get_last_err_string();
1202 return -1;
1205 runshell(shell);
1207 /*Wait for the other thread exit, after send out CMD_DONE*/
1208 std::this_thread::sleep_for(std::chrono::milliseconds(100));
1209 if(!g_verbose)
1210 printf("\n\n\n");
1211 return g_overall_status;