1 /*---------------------------------------------------------------------------*
2 
3   Copyright (C) Nintendo.  All rights reserved.
4 
5   These coded instructions, statements, and computer programs contain
6   proprietary information of Nintendo of America Inc. and/or Nintendo
7   Company Ltd., and are protected by Federal copyright law.  They may
8   not be disclosed to third parties or copied or duplicated in any form,
9   in whole or in part, without the prior written consent of Nintendo.
10 
11  *---------------------------------------------------------------------------*/
12 using System;
13 using System.Diagnostics;
14 using System.Net.Sockets;
15 using System.Linq;
16 using System.IO;
17 using System.Net;
18 using System.Collections.Generic;
19 using System.Threading;
20 using System.Text;
21 using System.Text.RegularExpressions;
22 
23 namespace CafeX
24 {
25     /// <summary>
26     /// This class encapsulates the functionality of the dkt.exe tool used by CafeX.
27     /// </summary>
28     static class dkt
29     {
30         static string cygwin_dkt_exe_path = "\"" + Environment.GetEnvironmentVariable("CAFE_ROOT") + "\\system\\bin\\tool\\dkt.exe" + "\"";
31 
GetExeName()32         private static string GetExeName()
33         {
34             string dkt_or_temp_exe_path;
35             if (FileUtil.RunningFromCygwin)
36             {
37                 // take the monitor from cygwin
38                 dkt_or_temp_exe_path = cygwin_dkt_exe_path;
39             }
40             else
41             {
42                 dkt_or_temp_exe_path = FileUtil.ExpandExecutable(CafeX.Properties.Resources.win_dkt, "win_dkt.exe");
43             }
44             return dkt_or_temp_exe_path;
45         }
46 
FlushOutputBuffer()47         internal static int FlushOutputBuffer()
48         {
49             #if DEBUG
50                 Log.WriteLine("dkt.FlushOutputBuffer started -> calls FlushOuputBuffer( 1 second).");
51             #endif
52 
53             return dkt.FlushOutputBuffer(1);
54         }
55 
FlushOutputBuffer(uint seconds)56         internal static int FlushOutputBuffer(uint seconds)
57         {
58             string strSeconds = seconds.ToString();
59             #if DEBUG
60                 Log.WriteLine("dkt.FlushOutputBuffer(" + strSeconds + ") started.");
61             #endif
62 
63             return ProcessExecutor.DoProcess(GetExeName(), "-d 40 " + strSeconds);
64         }
65     }
66 
67     /// <summary>
68     /// This class encapsulates the functionality of the PCFSServer used by CafeX.
69     /// </summary>
70     static class PCFSServer
71     {
72         static string exe_path = null;
73         static string output_log = String.Empty;
setExePath()74         private static void setExePath()
75         {
76             string testInMionBridge = Environment.GetEnvironmentVariable("MION_BRIDGE_TOOLS") + "\\pcfs\\PCFSServer.exe";
77             if (File.Exists(testInMionBridge))
78             {
79                 exe_path = testInMionBridge;
80             }
81             else
82             {
83                 exe_path = Environment.GetEnvironmentVariable("CAFE_ROOT") + "\\system\\bin\\tool\\PCFSServer.exe";
84             }
85 
86             FileUtil.AddQuotes(ref exe_path);
87         }
88 
Shutdown()89         internal static int Shutdown()
90         {
91             #if DEBUG
92                 Log.WriteLine("PCFSServer.Shutdown started.");
93             #endif
94 
95             setExePath();
96 
97             return ProcessExecutor.DoProcess(exe_path, "-q");
98         }
99 
Start(string parameters, string mapping, string log)100         internal static int Start(string parameters, string mapping, string log)
101         {
102             #if DEBUG
103                 Log.WriteLine("PCFSServer.Start started. parameters=" + parameters + ", mapping=" + mapping + ", log=" + log);
104             #endif
105 
106             setExePath();
107             output_log = log;
108             return ProcessExecutor.StartProcess_RedirectOutput(exe_path, "-r 100 " + parameters + " " + Environment.GetEnvironmentVariable("PCFS_HEADLESS_EMUL") + " " + mapping, output_callback, false);
109         }
110 
output_callback(Object sender, DataReceivedEventArgs line)111         static void output_callback(Object sender, DataReceivedEventArgs line)
112         {
113             #if DEBUG
114                 Log.WriteLine("PCFSServer.output_callback started.");
115             #endif
116 
117             setExePath();
118             if (output_log != "/dev/null")
119             {
120                 try
121                 {
122                     FileStream s = new FileStream(output_log, FileMode.Append, FileAccess.Write);
123                     StreamWriter w = new StreamWriter(s);
124                     w.Write(line.Data);
125                     w.Flush();
126                     w.Close();
127                 }
128                 catch (IOException ex)
129                 {
130                     Console.WriteLine("cafex [PCFSServer]: Caught exception while writing stdout to '{0}':", output_log);
131                     Console.WriteLine("    {0}", ex.Message);
132 
133                     // Prevent future log file writes
134                     output_log = "/dev/null";
135                 }
136             }
137         }
138     }
139 
140     /// <summary>
141     /// This class encapsulates the functionality of the checkbridge tool used by CafeX.
142     /// </summary>
143     static class checkbridgename
144     {
145         static string exe_path = "\"" + Environment.GetEnvironmentVariable("MION_BRIDGE_TOOLS") + "\\checkbridgename.exe" + "\"";
146 
CheckName(ref string output)147         internal static int CheckName(ref string output)
148         {
149             #if DEBUG
150                 Log.WriteLine("checkbridgename.CheckName started.");
151             #endif
152             string args = string.Format("\"{0}\" -ip {1}",
153                                         Environment.GetEnvironmentVariable("BRIDGE_CURRENT_NAME"),
154                                         Environment.GetEnvironmentVariable("BRIDGE_CURRENT_IP_ADDRESS"));
155 
156             int returnVal = ProcessExecutor.DoProcess_GetOutput(exe_path,  args, out output);
157 
158             return returnVal;
159         }
160 
CheckName()161         internal static int CheckName()
162         {
163             string output = string.Empty;
164             return CheckName(ref output);
165         }
166 
CheckName_IPOnly()167         internal static int CheckName_IPOnly()
168         {
169             #if DEBUG
170                 Log.WriteLine("checkbridgename.CheckName_IPOnly started.");
171             #endif
172 
173             int returnVal;
174             string output = string.Empty;
175 
176             returnVal = ProcessExecutor.DoProcess_GetOutput(exe_path, "-s -ip " + Environment.GetEnvironmentVariable("BRIDGE_CURRENT_IP_ADDRESS"), out output);
177             Console.Write(output);
178 
179             return returnVal;
180         }
181     }
182 
183     /// <summary>
184     /// This class encapsulates the functionality of the toucanreset tool used by CafeX.
185     /// </summary>
186     static class ToucanReset
187     {
188         static string exe_path = "\"" + Environment.GetEnvironmentVariable("MION_BRIDGE_TOOLS") + "\\ToucanReset.exe" + "\"";
189 
Stop()190         internal static int Stop()
191         {
192             #if DEBUG
193                 Log.WriteLine("ToucanReset.Stop started.");
194             #endif
195 
196             return ProcessExecutor.DoProcess(exe_path, "-stop");
197         }
198 
Reset()199         internal static int Reset()
200         {
201             #if DEBUG
202                 Log.WriteLine("ToucanReset.Reset started.");
203             #endif
204 
205             return ProcessExecutor.DoProcess(exe_path, Environment.GetEnvironmentVariable("HOSTSTOP_RESET_OPTION"));
206         }
207     }
208 
209     /// <summary>
210     /// This class encapsulates the functionality of the fsemul tool used by CafeX.
211     /// </summary>
212     static class FSEmul
213     {
214         static string exe_path = "\"" + Environment.GetEnvironmentVariable("MION_BRIDGE_TOOLS") + "\\FSEmul.exe" + "\"";
215 
makemine()216         internal static int makemine()
217         {
218             #if DEBUG
219                 Log.WriteLine("FSEmul.makemine started.");
220             #endif
221 
222             int returnVal;
223             string output = string.Empty;
224             returnVal = ProcessExecutor.DoProcess_GetOutput(exe_path, "-ip " + Environment.GetEnvironmentVariable("BRIDGE_CURRENT_IP_ADDRESS") + " -makemine", out output);
225             Console.Write(output);
226 
227             return returnVal;
228         }
229 
FW_SW_Version(string ip, out string fw_ver, out string sw_ver)230         internal static int FW_SW_Version(string ip, out string fw_ver, out string sw_ver)
231         {
232 #if DEBUG
233             Log.WriteLine("FSEmul.FW_SW_Version started.");
234 #endif
235 
236             string arguments = (ip != null) ? "-ver -ip " + ip : "-ver";
237 
238             // Set initial empty values
239             fw_ver = string.Empty;
240             sw_ver = string.Empty;
241 
242             // Remember and clear the TOUCAN_VERBOSE variable as this causes the version to be parsed as blank
243             string localTOUCAN_VERBOSE = Environment.GetEnvironmentVariable("TOUCAN_VERBOSE");
244             Environment.SetEnvironmentVariable("TOUCAN_VERBOSE", "");
245 
246             string output = string.Empty;
247             int ret = ProcessExecutor.DoProcess_GetOutput(exe_path, arguments, out output);
248 
249             // Restore the TOUCAN_VERBOSE variable
250             if (!string.IsNullOrEmpty(localTOUCAN_VERBOSE))
251             {
252                 Environment.SetEnvironmentVariable("TOUCAN_VERBOSE", localTOUCAN_VERBOSE);
253             }
254 
255             // FSEmul was successful, now let's parse the output
256             if (ret == 0)
257             {
258                 // Sample output from FSEmul:
259                 // Firmware version : 0.0.14.77\r\nSoftware version : 3.2.6.4\r\nFPGA version : 13052071\r\n
260                 //
261                 // Sometimes there is other text preceding output. So try to find where the "Firmware version" text starts.
262                 int realOutputStartIndex = output.IndexOf("Firmware version");
263                 if (realOutputStartIndex >= 0)
264                 {
265                     string realOutput = output.Substring(realOutputStartIndex);
266 
267                     // Strip string into only numbers (integer or decimal). Discard any empty strings.
268                     string[] split = Regex.Split(realOutput, @"[^0-9\.]+").Where(s => !string.IsNullOrEmpty(s.Trim())).ToArray();
269 
270                     if (split.Length >= 3) // FW, SW, FPGA versions
271                     {
272                         fw_ver = split[0];
273                         sw_ver = split[1];
274 
275                         // Success
276                         return ret;
277                     }
278                 }
279             }
280 
281             // Failure in all other cases
282             Console.WriteLine("FSEmul failed: Couldn't get firmware versions");
283             return ret;
284         }
285 
boot_mode_detect(string ip, out string boot_mode)286         internal static int boot_mode_detect(string ip, out string boot_mode)
287         {
288 #if DEBUG
289             Log.WriteLine("FSEmul.boot_mode_detect started.");
290 #endif
291 
292             if (string.IsNullOrEmpty(ip))
293             {
294                 boot_mode = "UNKNOWN";
295                 return 1;
296             }
297 
298             string arguments = "-ip " + ip + " -modedetect";
299 
300             // Remember and clear the TOUCAN_VERBOSE variable as this causes the version to be parsed as blank
301             string localTOUCAN_VERBOSE = Environment.GetEnvironmentVariable("TOUCAN_VERBOSE");
302             Environment.SetEnvironmentVariable("TOUCAN_VERBOSE", "");
303 
304             string output = string.Empty;
305             int ret = ProcessExecutor.DoProcess_GetOutput(exe_path, arguments, out output);
306 
307             // Restore the TOUCAN_VERBOSE variable
308             if (!string.IsNullOrEmpty(localTOUCAN_VERBOSE))
309             {
310                 Environment.SetEnvironmentVariable("TOUCAN_VERBOSE", localTOUCAN_VERBOSE);
311             }
312 
313             if (ret != 0)
314             {
315                 Console.WriteLine("FSEmul failed: Couldn't detect boot mode!");
316                 boot_mode = "UNKNOWN";
317                 return ret;
318             }
319 
320             boot_mode = output.Trim();
321             return 0;
322         }
323 
start(string arguments, string fsemul_params)324         internal static int start(string arguments, string fsemul_params)
325         {
326             #if DEBUG
327                 Log.WriteLine("FSEmul.start started.");
328             #endif
329 
330             DataReceivedEventHandler handler = new DataReceivedEventHandler((sender, args) => {
331                 if (args != null && args.Data != null)
332                 {
333                     Console.WriteLine(args.Data);
334                     // If FSEmul throws, suggest using cafestop -makemine
335                     if (args.Data.ToString().Contains("Bridge is being used by the PC with IP Address"))
336                     {
337                         Console.WriteLine("\nTry using 'cafex stop -makemine' to take control of the Bridge.");
338                     }
339                 }
340             });
341 
342             return ProcessExecutor.StartProcess_RedirectOutput(exe_path, arguments + " " + fsemul_params, handler, false);
343         }
344     }
345 
346     /// <summary>
347     /// This class encapsulates the functionality of the mionbutton tool used by CafeX.
348     /// </summary>
349     static class MionButton
350     {
351         static string exe_path = "\"" + Environment.GetEnvironmentVariable("MION_BRIDGE_TOOLS") + "\\MionButton.exe" + "\"";
352 
rsthold(string[] args)353         internal static int rsthold(string[] args)
354         {
355             #if DEBUG
356                 Log.WriteLine("MionButton.rsthold started.");
357             #endif
358             string output = string.Empty;
359             int returnVal;
360             string arg_string = StringCombiner.MakeDelimitedString(args, ' ');
361 
362             returnVal = ProcessExecutor.DoProcess_GetOutput(exe_path, "-ip " + Environment.GetEnvironmentVariable("BRIDGE_CURRENT_IP_ADDRESS") + " -rsthold " + arg_string, out output);
363 
364             // Print output to console
365             Console.Write(output);
366             return returnVal;
367         }
368 
forceOff1(string[] args)369         internal static int forceOff1(string[] args)
370         {
371             #if DEBUG
372                 Log.WriteLine("mionButton.forceOff1 started.");
373             #endif
374 
375             string output = string.Empty;
376             int returnVal;
377             string arg_string = StringCombiner.MakeDelimitedString(args, ' ');
378 
379             returnVal = ProcessExecutor.DoProcess_GetOutput(exe_path, "-ip " + Environment.GetEnvironmentVariable("BRIDGE_CURRENT_IP_ADDRESS") + " -forceOff1 " + arg_string, out output);
380 
381             // Print output to console
382             Console.Write(output);
383             return returnVal;
384         }
385 
init_shutdown_w_FOFF2(string[] args)386         internal static int init_shutdown_w_FOFF2(string[] args)
387         {
388             #if DEBUG
389                 Log.WriteLine("MionButton.init_shutdown_w_FOFF2 started.");
390             #endif
391 
392             string output = string.Empty;
393             int returnVal;
394             string arg_string = StringCombiner.MakeDelimitedString(args, ' ');
395 
396             returnVal = ProcessExecutor.DoProcess_GetOutput(exe_path, "-ip " + Environment.GetEnvironmentVariable("BRIDGE_CURRENT_IP_ADDRESS") + " -init_shutdown_w_FOFF2 60000 " + arg_string, out output);
397 
398             // Print output to console
399             Console.Write(output);
400             return returnVal;
401         }
402 
forceOff2_off_single_cgi(string[] args)403         internal static int forceOff2_off_single_cgi(string[] args)
404         {
405             #if DEBUG
406                 Log.WriteLine("MionButton.forceOff2_off_single_cgi started.");
407             #endif
408 
409             string output = string.Empty;
410             int returnVal;
411             string arg_string = StringCombiner.MakeDelimitedString(args, ' ');
412 
413             returnVal = ProcessExecutor.DoProcess_GetOutput(exe_path, "-ip " + Environment.GetEnvironmentVariable("BRIDGE_CURRENT_IP_ADDRESS") + " -forceOff2_off_single_cgi " + arg_string, out output);
414 
415             // Print output to console
416             Console.Write(output);
417             return returnVal;
418 
419         }
420     }
421 
422     /// <summary>
423     /// This class encapsulates the functionality of the miontelnet tool used by CafeX.
424     /// </summary>
425     static class miontelnet
426     {
427         static string exe_path = "\"" + Environment.GetEnvironmentVariable("CAFE_ROOT") + "\\system\\bin\\tool\\miontelnet.exe" + "\"";
428 
Reboot(out string output)429         internal static int Reboot(out string output)
430         {
431             #if DEBUG
432                 Log.WriteLine("miontelnet.Reboot started.");
433             #endif
434 
435             return ProcessExecutor.DoProcess_GetOutput(exe_path, "-reboot", out output);
436         }
437 
Run(out string output)438         internal static int Run(out string output)
439         {
440 #if DEBUG
441             Log.WriteLine("miontelnet.Run started.");
442 #endif
443 
444             return ProcessExecutor.DoProcess_GetOutput(exe_path, null, out output);
445         }
446     }
447 
448     /// <summary>
449     /// This class encapsulates the functionality of the mionps tool used by CafeX.
450     /// </summary>
451     static class mionps
452     {
453         static string exe_path = "\"" + Environment.GetEnvironmentVariable("CAFE_ROOT") + "\\system\\bin\\tool\\mionps.exe" + "\"";
454         private static readonly int MIONPS_TIMEOUT_MS = 30000; // 30 seconds
455 
Run(string arguments)456         internal static string Run(string arguments)
457         {
458             #if DEBUG
459                 Log.WriteLine("mionps.Run started.");
460             #endif
461 
462             string output = string.Empty;
463             int returnVal = ProcessExecutor.DoProcess_GetOutput(exe_path, arguments, true, MIONPS_TIMEOUT_MS, out output);
464             // Currently, all the calls to mionps are assuming a single line without CRLF.
465             // If that changes, removing CRLF below will need to be removed and calls to RUN revisited.
466             output = output.Replace("\r\n", "");
467             // Error checking for mionps
468             if (returnVal != 0)
469             {
470                 Console.WriteLine("cafex : Warning! mionps tool returned code {0}.", returnVal);
471                 Console.WriteLine("mionps stdout and stderr received:");
472                 Console.WriteLine(output);
473             }
474 
475             return output;
476         }
477     }
478 
479     /// <summary>
480     /// This class encapsulates the functionality of the mionurl tool used by CafeX.
481     /// </summary>
482     static class mionurl
483     {
484         static string exe_path = "\"" + Environment.GetEnvironmentVariable("CAFE_ROOT") + "\\system\\bin\\tool\\mionurl.exe" + "\"";
485         private static readonly int MIONURL_TIMEOUT_MS = 30000; // 30 seconds
486 
Run(string arguments)487         internal static int Run(string arguments)
488         {
489 #if DEBUG
490             Log.WriteLine("mionurl.Run started.");
491 #endif
492 
493             string output = string.Empty;
494             int returnVal = ProcessExecutor.DoProcess_GetOutput(exe_path, arguments, true, MIONURL_TIMEOUT_MS, out output);
495             // Currently, all the calls to mionurl are assuming a single line without CRLF.
496             // If that changes, removing CRLF below will need to be removed and calls to RUN revisited.
497             output = output.Replace("\r\n", "");
498             // Error checking for mionurl
499             if (returnVal != 0)
500             {
501                 Console.WriteLine("cafex : Warning! mionurl tool returned code {0}.", returnVal);
502                 Console.WriteLine("mionurl stdout and stderr received:");
503                 Console.WriteLine(output);
504             }
505 
506             return returnVal;
507         }
508     }
509 
510     /// <summary>
511     /// This class encapsulates the functionality of the sessionmanager tool used by CafeX.
512     /// </summary>
513     static class SessionManagerUtil
514     {
515         static string exe_path = "\"" + Environment.GetEnvironmentVariable("MION_BRIDGE_TOOLS") + "\\SessionManagerUtil.exe" + "\"";
516 
GetSessionInfo(out string output)517         internal static int GetSessionInfo(out string output)
518         {
519             #if DEBUG
520                 Log.WriteLine("SessionManagerUtil.GetSessionInfo started.");
521             #endif
522 
523             return ProcessExecutor.DoProcess_GetOutput(exe_path, "-p NAME DEBUG_OUT DEBUG_CONTROL HIO_OUT LAUNCH_CTRL NET_MANAGE PCFS_SATA", out output);
524         }
525     }
526 
527     /// <summary>
528     /// This class encapsulates the functionality of the devkitmsg tool used by CafeX.
529     /// </summary>
530     static class devkitmsg
531     {
532         internal static string CAFEX_RECOVER_TEST = Environment.GetEnvironmentVariable("CAFEX_RECOVER_TEST");
533         static string exe_path = "\"" + Environment.GetEnvironmentVariable("MION_BRIDGE_TOOLS") + "\\devkitmsg.exe" + "\"";
534 
help(int timeout)535         internal static int help(int timeout)
536         {
537 #if DEBUG
538             Log.WriteLine("devkitmsg.help started with timeout = " + timeout.ToString());
539 #endif
540             int returnVal = 2;
541 
542             Console.WriteLine("cafex: Probing if COS is ready by sending devkit help msg:");
543             string msg = "\"help\" -v -p " + Environment.GetEnvironmentVariable("SESSION_LAUNCH_CTRL_PORT");
544             DateTime maxTime = DateTime.Now.AddMilliseconds((double)timeout);
545 
546             //I don't think the following do-while does what some expect it to do. It seems like
547             //it is going to wait "timeout" seconds for devkitmsg to finish and then kill it? What's
548             //actually happening is that you will spam devkitmsg.help for "timeout" seconds
549 
550             do
551             {
552                 returnVal = ProcessExecutor.DoProcess_WaitTime(exe_path, msg, 10000); //10 seconds should be more than enough
553                 if (returnVal == 0)
554                 {
555                     break;
556                 }
557 
558                 System.Threading.Thread.Sleep(Program.RETRY_TIMESPAN); // wait for a second.
559             }
560             while (maxTime.CompareTo(DateTime.Now) > 0);
561 
562 #if DEBUG
563             Log.WriteLine("devkitmsg.help returnVal = " + returnVal.ToString());
564 #endif
565 
566             return returnVal;
567         }
568 
CosFlags(string ppc_os_flags)569         internal static int CosFlags(string ppc_os_flags)
570         {
571             #if DEBUG
572                 Log.WriteLine("devkitmsg.CosFlags started.");
573             #endif
574 
575             return ProcessExecutor.DoProcess(exe_path, "\"cos_flags " + ppc_os_flags + "\" -v -p " + Environment.GetEnvironmentVariable("SESSION_LAUNCH_CTRL_PORT"));
576         }
577 
title_softlaunch_with_hint(string os, string tid, string hint, string port)578         internal static int title_softlaunch_with_hint(string os, string tid, string hint, string port)
579         {
580             #if DEBUG
581                 Log.WriteLine("devkitmsg.title_softlaunch_with_hint started.");
582             #endif
583 
584             return ProcessExecutor.DoProcess(exe_path, "\"title_softlaunch " + os + " " + tid + " " + hint + "\" -v -p " + port);
585         }
586 
title_softlaunch(string os, string tid, string port)587         internal static int title_softlaunch(string os, string tid, string port)
588         {
589             #if DEBUG
590                 Log.WriteLine("devkitmsg.title_softlaunch started.");
591             #endif
592             DataReceivedEventHandler callback = (sender, e) =>
593             {
594                 if (e != null && e.Data != null)
595                 {
596                     Console.WriteLine(e.Data);
597                 }
598             };
599 
600             return ProcessExecutor.StartProcess_RedirectOutput(exe_path, "\"title_softlaunch " + os + " " + tid + "\" -v -p " + port, callback, true);
601         }
602 
recover()603         internal static int recover()
604         {
605             #if DEBUG
606                 Log.WriteLine("devkitmsg.recover started.");
607             #endif
608 
609             if (CAFEX_RECOVER_TEST == "1")
610             {
611                 Console.WriteLine("devkitmsg_cmd: recover -v -p ");
612                 return 0;
613             }
614 
615             return ProcessExecutor.DoProcess(exe_path, "recover -v -p " + Environment.GetEnvironmentVariable("SESSION_LAUNCH_CTRL_PORT"));
616         }
617 
update_pcfs()618         internal static int update_pcfs()
619         {
620             #if DEBUG
621                 Log.WriteLine("dvkitmsg.update_pcfs started.");
622             #endif
623 
624             if (CAFEX_RECOVER_TEST == "1")
625             {
626                 Console.WriteLine("devkitmsg_cmd: update /vol/storage_hfiomlc01/sys/update/pcfs -v -p ");
627                 return 0;
628             }
629 
630             return ProcessExecutor.DoProcess(exe_path, "\"update /vol/storage_hfiomlc01/sys/update/pcfs\" -v -p " + Environment.GetEnvironmentVariable("SESSION_LAUNCH_CTRL_PORT"));
631         }
632 
update_reflash()633         internal static int update_reflash()
634         {
635             #if DEBUG
636                 Log.WriteLine("devkitmsg.update_reflash started.");
637             #endif
638 
639             if (CAFEX_RECOVER_TEST == "1")
640             {
641                 Console.WriteLine("devkitmsg_cmd: reflash /vol/storage_hfiomlc01/sys/update/nand -v -p ");
642                 return 0;
643             }
644 
645             return ProcessExecutor.DoProcess(exe_path, "\"reflash /vol/storage_hfiomlc01/sys/update/nand\" -v -p " + Environment.GetEnvironmentVariable("SESSION_LAUNCH_CTRL_PORT"));
646         }
647 
update_nand()648         internal static int update_nand()
649         {
650             #if DEBUG
651                 Log.WriteLine("devkitmsg.update_nand started.");
652             #endif
653 
654             if (CAFEX_RECOVER_TEST == "1")
655             {
656                 Console.WriteLine("devkitmsg_cmd: update /vol/storage_hfiomlc01/sys/update/nand -v -p ");
657                 return 0;
658             }
659 
660             return ProcessExecutor.DoProcess(exe_path, "\"update /vol/storage_hfiomlc01/sys/update/nand\" -v -p " + Environment.GetEnvironmentVariable("SESSION_LAUNCH_CTRL_PORT"));
661         }
662 
update(string update_path)663         internal static int update(string update_path)
664         {
665 #if DEBUG
666             Log.WriteLine("devkitmsg.update started.");
667 #endif
668 
669             if (string.IsNullOrEmpty(update_path))
670             {
671                 return 1;
672             }
673 
674             if (CAFEX_RECOVER_TEST == "1")
675             {
676                 Console.WriteLine("devkitmsg_cmd: update " + update_path + " -v -p ");
677                 return 0;
678             }
679 
680             return ProcessExecutor.DoProcess(exe_path, "\"update " + update_path + "\" -v -p " + Environment.GetEnvironmentVariable("SESSION_LAUNCH_CTRL_PORT"));
681         }
682 
reflash(string reflash_path)683         internal static int reflash(string reflash_path)
684         {
685 #if DEBUG
686             Log.WriteLine("devkitmsg.reflash started.");
687 #endif
688             if (string.IsNullOrEmpty(reflash_path))
689             {
690                 return 1;
691             }
692 
693             if (CAFEX_RECOVER_TEST == "1")
694             {
695                 Console.WriteLine("devkitmsg_cmd: reflash " + reflash_path + " -v -p ");
696                 return 0;
697             }
698 
699             return ProcessExecutor.DoProcess(exe_path, "\"reflash " + reflash_path + "\" -v -p " + Environment.GetEnvironmentVariable("SESSION_LAUNCH_CTRL_PORT"));
700         }
701 
clr_usrdata()702         internal static int clr_usrdata()
703         {
704             #if DEBUG
705                 Log.WriteLine("devkitmsg.clr_usrdata started.");
706             #endif
707 
708             if (CAFEX_RECOVER_TEST == "1")
709             {
710                 Console.WriteLine("devkitmsg_cmd: clr_usrdata -v -p ");
711                 return 0;
712             }
713 
714             return ProcessExecutor.DoProcess(exe_path, "clr_usrdata -v -p " + Environment.GetEnvironmentVariable("SESSION_LAUNCH_CTRL_PORT"));
715         }
716 
sys_mode_dev()717         internal static int sys_mode_dev()
718         {
719             #if DEBUG
720                 Log.WriteLine("devkitmsg.sys_mode_dev started.");
721             #endif
722 
723             return ProcessExecutor.DoProcess(exe_path, "\"sys_mode 1\" -v -p " + Environment.GetEnvironmentVariable("SESSION_LAUNCH_CTRL_PORT"));
724         }
725 
sys_mode_prod()726         internal static int sys_mode_prod()
727         {
728             #if DEBUG
729             Log.WriteLine("devkitmsg.sys_mode_prod started.");
730             #endif
731 
732             return ProcessExecutor.DoProcess(exe_path, "\"sys_mode 0\" -v -p " + Environment.GetEnvironmentVariable("SESSION_LAUNCH_CTRL_PORT"));
733         }
734 
sys_mode_test()735         internal static int sys_mode_test()
736         {
737             #if DEBUG
738             Log.WriteLine("devkitmsg.sys_mode_test started.");
739             #endif
740 
741             return ProcessExecutor.DoProcess(exe_path, "\"sys_mode 2\" -v -p " + Environment.GetEnvironmentVariable("SESSION_LAUNCH_CTRL_PORT"));
742         }
743 
standby_en(int value)744         internal static int standby_en(int value)
745         {
746             #if DEBUG
747             Log.WriteLine("devkitmsg.standby_en " + value);
748             #endif
749 
750             return ProcessExecutor.DoProcess(exe_path, " 'standby_en 1' -v -p " + Environment.GetEnvironmentVariable("SESSION_LAUNCH_CTRL_PORT"));
751         }
752 
753 
754     }
755 
756     static class cosdebug
757     {
758 #if TIMER
759         public static PerfTimer cosdebugSetupTime = new PerfTimer("cosdebugSetupTime");
760 #endif
761 #if false
762         private static Thread retry_thread = null;
763         private static ManualResetEvent stop_event = null;
764 
765         private struct LaunchRetryParams
766         {
767             public int port;
768             public string TID_HI;
769             public string TID_LO;
770             public int retries;
771             public int timeout;
772             public int delay;
773         }
774 #endif
775 
StreamDiscard(Stream stream)776         internal static void StreamDiscard(Stream stream)
777         {
778             try
779             {
780                 int b;
781                 stream.ReadTimeout = 500;
782 #if DEBUG
783                 Console.Write("cafex: cosdebug.launch discarding:");
784 #endif
785                 while ((b = stream.ReadByte()) != -1)
786                 {
787 #if DEBUG
788                     Console.Write(" {0:X2}", b);
789 #endif
790                 }
791             }
792             catch (IOException)
793             {
794                 // Eat this exception.  The timeout just expired
795             }
796             finally
797             {
798 #if DEBUG
799                 Console.WriteLine();
800 #endif
801             }
802         }
803 #if false
launch_retry_thread(object data)804         private static void launch_retry_thread(object data)
805         {
806             LaunchRetryParams lrparams = (LaunchRetryParams)data;
807 #if DEBUG
808             Log.WriteLine("cosdebug.launch_retry_thread started.");
809             Log.WriteLine("Params:");
810             Log.WriteLine(string.Format("    port:       {0}.", lrparams.port));
811             Log.WriteLine(string.Format("    TID_HI:     {0}.", lrparams.TID_HI));
812             Log.WriteLine(string.Format("    TID_LO:     {0}.", lrparams.TID_LO));
813             Log.WriteLine(string.Format("    retries:    {0}.", lrparams.retries));
814             Log.WriteLine(string.Format("    timeout:    {0}.", lrparams.timeout));
815 #endif
816             cattoucan.ClearNotifications();
817 
818             ManualResetEvent[] evtHandle = new ManualResetEvent[3];
819 
820             evtHandle[0] = new ManualResetEvent(false);
821             cattoucan.AddNotification(Nintendo.SDSG.CatToucan.Terms.KI_PIREPARE_TITLE_ASYNC, evtHandle[0]);
822 
823             evtHandle[1] = new ManualResetEvent(false);
824             cattoucan.AddNotification("System busy, try again", evtHandle[1]);
825 
826             evtHandle[2] = stop_event;
827 
828             for (int retry = 0; retry < lrparams.retries; retry++)
829             {
830                 launch(lrparams.port, lrparams.TID_HI, lrparams.TID_LO);
831 
832                 long start = DateTime.Now.Ticks;
833 #if DEBUG
834                 Log.WriteLine(string.Format("cosdebug.launch_retry_thread: waiting on handles {0} and {1}.", evtHandle[0].Handle, evtHandle[1].Handle));
835 #endif
836                 switch (WaitHandle.WaitAny(evtHandle, lrparams.timeout))
837                 {
838                     case 0:
839                         // Got the success message and we are done
840                         Log.WriteLineRaw("cafex: Got successful title fast launch message.");
841 #if DEBUG
842                         Log.WriteLine(string.Format("cosdebug.launch_retry_thread: waited {0}mS.", TimeSpan.FromTicks(DateTime.Now.Ticks - start).TotalMilliseconds));
843 #endif
844                         evtHandle[0].Reset();
845                         return;
846 
847                     case 1:
848                         // Got the retry, so we continue
849                         Log.WriteLineRaw(string.Format("cafex: Got system busy message after fast launch, waiting {0}mS and retrying...", lrparams.delay));
850 #if DEBUG
851                         Log.WriteLine(string.Format("cosdebug.launch_retry_thread: waited {0}mS.", TimeSpan.FromTicks(DateTime.Now.Ticks - start).TotalMilliseconds));
852                         Log.WriteLine(string.Format("                            : delaying {0}mS.", lrparams.delay));
853 #endif
854                         evtHandle[1].Reset();
855                         Thread.Sleep(lrparams.delay);
856                         break;
857 
858                     case 2:
859 #if DEBUG
860                         Log.WriteLine("cosdebug.retry_launch_thread: Got stop event, returning.");
861 #endif
862                         return;
863 
864                     case WaitHandle.WaitTimeout:
865                         Log.WriteLineRaw(string.Format("cafex: Fastlaunch timeout of {0}mS exceeded waiting for title to start, exiting.", lrparams.timeout));
866                         Environment.Exit((int)CAFEX_ERROR.RUN_FASTLAUNCH_FAILED);
867                         return;
868                 }
869             }
870 
871             // Exhausted all of our tries
872             Log.WriteLineRaw(string .Format("cafex: Unable to fastlaunch title after {0} attempts, exiting.", lrparams.retries));
873             Environment.Exit((int)CAFEX_ERROR.RUN_FASTLAUNCH_FAILED);
874         }
875 
launch_retry(int port, string TID_HI, string TID_LO, int retries, int timeout, int delay)876         internal static void launch_retry(int port, string TID_HI, string TID_LO, int retries, int timeout, int delay)
877         {
878 #if DEBUG
879             Log.WriteLine("cosdebug.launch_retry started.");
880 #endif
881             LaunchRetryParams lrparams = new LaunchRetryParams();
882 
883             lrparams.port = port;
884             lrparams.TID_HI = TID_HI;
885             lrparams.TID_LO = TID_LO;
886             lrparams.retries = retries;
887             lrparams.timeout = timeout;
888             lrparams.delay = delay;
889 
890             retry_thread = new Thread(cosdebug.launch_retry_thread);
891             stop_event = new ManualResetEvent(false);
892 
893             retry_thread.Start(lrparams);
894 #if DEBUG
895             Log.WriteLine("cosdebug.launch_retry exited.");
896 #endif
897         }
898 
stop_retry(int timeout)899         public static void stop_retry(int timeout)
900         {
901             if (retry_thread != null)
902             {
903                 stop_event.Set();
904                 retry_thread.Join(timeout);
905             }
906         }
907 #endif
908 
launch(int port, string TID_HI, string TID_LO)909         internal static int launch(int port, string TID_HI, string TID_LO)
910         {
911 #if DEBUG
912             Log.WriteLine("cosdebug.launch started.");
913 #endif
914             try
915             {
916                 TcpClient client = new TcpClient("localhost", port);
917                 NetworkStream stream = client.GetStream();
918 
919                 // Discard any input if anything is waiting after connect.  COS sends some prompts after connect.
920                 StreamDiscard(stream);
921 
922                 string message = string.Format("\rcos launch 0x{0} 0x{1}\r", TID_HI, TID_LO);
923                 Log.WriteLineRaw(string.Format("cafex: sending '{0}' to the devkit using port {1}...", message.Trim(), port));
924                 byte[] data = System.Text.Encoding.ASCII.GetBytes(message);
925 
926 #if DEBUG
927                 Console.Write("cafex: cosdebug.launch write ({0} bytes):", data.Length);
928                 for (int i = 0; i < data.Length; i++)
929                 {
930                     Console.Write(" 0x{0:X2}", data[i]);
931                 }
932                 Console.WriteLine();
933 #endif
934                 stream.WriteTimeout = 5000;
935                 stream.Write(data, 0, data.Length);
936 
937                 // Discard any input stream if anything is sent after the write.
938                 StreamDiscard(stream);
939 
940                 client.Close();
941             }
942             catch (InvalidOperationException e)
943             {
944                 Log.WriteLine(string.Format("cafex: cosdebug.launch: InvalidOperationException: {0}", e));
945             }
946             catch (ArgumentNullException e)
947             {
948                 Log.WriteLine(string.Format("cafex: cosdebug.launch: ArgumentNullException: {0}", e));
949             }
950             catch (SocketException e)
951             {
952                 Log.WriteLine(string.Format("cafex: cosdebug.launch: SocketException: {0}", e));
953             }
954             catch (IOException e)
955             {
956                 Log.WriteLine(string.Format("cafex: cosdebug.launch: IOException: {0}", e));
957             }
958 
959             return 0;
960         }
961 
try_launch(string TID, int index)962         internal static bool try_launch(string TID, int index)
963         {
964             int retries = Convert.ToInt32(Program.CAFERUN_OPTION_FASTLAUNCH_RETRIES.value);
965             int timeout = Convert.ToInt32(Program.CAFERUN_OPTION_FASTLAUNCH_TIMEOUT.value);
966             int delay = Convert.ToInt32(Program.CAFERUN_OPTION_FASTLAUNCH_DELAY.value);
967             int port = Convert.ToInt32(Program.SESSION_NET_MANAGE_PORT.value);
968             string TID_HI = TID.Substring(index, 8);
969             string TID_LO = TID.Substring(index + 8, 8);
970 
971             if (Program.CAFE_PROFILE.value != null && Program.CAFE_PROFILE.value == "1")
972             {
973                 CafeXEventtLog.Instance.WriteToEventLog(562, string.Format("[{0}] [BEGIN] [CafeX] System is doing FAST RELAUNCH", DateTime.Now.ToString("HH:mm:ss:fff")));
974             }
975 
976             cattoucan.BeginTitleFastSync();
977             for (index = 0; index < retries; ++index)
978             {
979                 cattoucan.PrepareFastLaunch(delay);
980                 launch(port, TID_HI, TID_LO);
981                 if (cattoucan.SyncWithTitle(timeout, true))
982                 {
983                     return true;
984                 }
985 #if DEBUG
986                 Log.WriteLine("Retrying fast launch...");
987 #endif
988             }
989 
990             cattoucan.FinishSync(true);
991             return false;
992         }
993 
ParseReceivedMessage(string sMessage, string sParseStr, string sArgs)994         internal static bool ParseReceivedMessage(string sMessage, string sParseStr, string sArgs)
995         {
996             string[] msgArray = sMessage.Split(' ');
997             for (int i = 0; i < msgArray.Length; i++)
998             {
999                 string str = msgArray[i];
1000                 if ((str.CompareTo(sParseStr) == 0) &&
1001                     ((i + 1) < msgArray.Length) &&
1002                     (msgArray[i + 1].CompareTo(sArgs) == 0))
1003                     return true;
1004             }
1005 
1006             return false;
1007         }
1008 
SendCOSCommandAndRecvReply(int iPort, string sCmd, string sArgs, int iRetries, int iTimeout, int iDelay)1009         internal static string SendCOSCommandAndRecvReply(int iPort, string sCmd, string sArgs, int iRetries, int iTimeout, int iDelay)
1010         {
1011             StringBuilder completeMessage = new StringBuilder();
1012             TcpClient client = null;
1013             NetworkStream stream = null;
1014 #if DEBUG
1015             Log.WriteLine("cosdebug." + sCmd + " started.");
1016 #endif
1017             try
1018             {
1019 #if TIMER
1020                 Log.WriteLine("new TcpClient start");
1021                 cosdebugSetupTime.Report();
1022 #endif
1023                 client = new TcpClient("localhost", iPort);
1024 #if TIMER
1025                 Log.WriteLine("new TcpClient end");
1026                 cosdebugSetupTime.Report();
1027 #endif
1028                 stream = client.GetStream();
1029                 // Discard any input if anything is waiting after connect.  COS sends some prompts after connect.
1030                 //StreamDiscard(stream);
1031 
1032                 string message = string.Format("{0} {1}\r", sCmd, sArgs);
1033                 Log.WriteLineRaw(string.Format("cafex: sending '{0}' to the devkit using port {1}...", message.Trim(), iPort));
1034                 byte[] data = System.Text.Encoding.ASCII.GetBytes(message);
1035 
1036 #if DEBUG
1037                 Console.Write("cafex: cosdebug.{0} write ({1} bytes):", sCmd, data.Length);
1038                 for (int i = 0; i < data.Length; i++)
1039                 {
1040                     Console.Write(" 0x{0:X2}", data[i]);
1041                 }
1042                 Console.WriteLine();
1043 #endif
1044                 stream.WriteTimeout = iTimeout;
1045                 stream.ReadTimeout = iTimeout;
1046                 stream.Write(data, 0, data.Length);
1047 
1048                 Thread.Sleep(iDelay);
1049 
1050                 if (stream.CanRead)
1051                 {
1052                     byte[] readBuffer = new byte[4096];
1053                     int readIndex = 0;
1054                     int numberOfBytesRead = 0;
1055                     int count = 0;
1056 
1057                     while (!stream.DataAvailable)
1058                     {
1059                         if (count == iRetries)
1060                         {
1061                             break;
1062                         }
1063                         Thread.Sleep(iDelay);
1064                         count++;
1065                     }
1066                     if (count <= iRetries || stream.DataAvailable)
1067                     {
1068 
1069                         // Incoming message may be larger than the buffer size.
1070                         while (stream.DataAvailable)
1071                         {
1072                             numberOfBytesRead = stream.Read(readBuffer, readIndex, readBuffer.Length);
1073                             completeMessage.AppendFormat("{0}", Encoding.ASCII.GetString(readBuffer, 0, numberOfBytesRead));
1074                             readIndex += numberOfBytesRead;
1075                             Thread.Sleep(200);
1076                         }
1077 #if DEBUG
1078                         Console.Write("cafex: cosdebug.{0} read ({1}):", sCmd, completeMessage);
1079                         Console.WriteLine();
1080 #endif
1081                     }
1082                 }
1083             }
1084             catch (InvalidOperationException e)
1085             {
1086                 Log.WriteLine(string.Format("cafex: cosdebug.{0}: InvalidOperationException: {1}", sCmd, e));
1087             }
1088             catch (ArgumentNullException e)
1089             {
1090                 Log.WriteLine(string.Format("cafex: cosdebug.{0}: ArgumentNullException: {1}", sCmd, e));
1091             }
1092             catch (SocketException e)
1093             {
1094                 Log.WriteLine(string.Format("cafex: cosdebug.{0}: SocketException: {1}", sCmd, e));
1095             }
1096             catch (IOException e)
1097             {
1098                 Log.WriteLine(string.Format("cafex: cosdebug.{0}: IOException: {1}", sCmd, e));
1099             }
1100             catch (Exception e)
1101             {
1102                 Log.WriteLine(string.Format("cafex: cosdebug.{0}: Exception: {1}", sCmd, e));
1103             }
1104 
1105             finally
1106             {
1107                 if (stream != null)
1108                 {
1109                     stream.Close();
1110                 }
1111                 if (client != null)
1112                 {
1113                     client.Close();
1114                 }
1115             }
1116             return completeMessage.ToString();
1117         }
1118 
1119 #if false
SendCOSCommandAndRecvReply(int iPort, string sCmd, string sArgs, int iRetries, int iTimeout, int iDelay)1120        internal static string SendCOSCommandAndRecvReply(int iPort, string sCmd, string sArgs, int iRetries, int iTimeout, int iDelay)
1121         {
1122 #if DEBUG
1123             Log.WriteLine("cosdebug." + sCmd + " started.");
1124 #endif
1125             Socket skt = null;
1126             StringBuilder completeMessage = new StringBuilder();
1127             try
1128             {
1129                 IPAddress[] ipAddrList = Dns.GetHostEntry("localhost").AddressList;
1130 
1131                 skt = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
1132 
1133                 skt.Connect(ipAddrList, iPort);
1134 
1135                 if (skt.Connected)
1136                 {
1137                     string message = string.Format("{0} {1}\r", sCmd, sArgs);
1138                     Log.WriteLineRaw(string.Format("cafex: sending '{0}' to the devkit using port {1}...", message.Trim(), iPort));
1139                     byte[] bytesSent = System.Text.Encoding.ASCII.GetBytes(message);
1140 
1141 #if DEBUG
1142                     Console.Write("cafex: cosdebug.{0} write ({1} bytes):", sCmd, bytesSent.Length);
1143                     for (int i = 0; i < bytesSent.Length; i++)
1144                     {
1145                         Console.Write(" 0x{0:X2}", bytesSent[i]);
1146                     }
1147                     Console.WriteLine();
1148 #endif
1149                     skt.SendTimeout = iTimeout;
1150                     skt.ReceiveTimeout = iTimeout;
1151                     skt.Send(bytesSent, bytesSent.Length, 0);
1152 
1153                     Thread.Sleep(1000);
1154 
1155                     byte[] bytesRead = new byte[4096];
1156                     int numberOfBytesRead = 0;
1157 
1158                     numberOfBytesRead = skt.Receive(bytesRead, bytesRead.Length, 0);
1159                     completeMessage.AppendFormat("{0}", Encoding.ASCII.GetString(bytesRead, 0, numberOfBytesRead));
1160 
1161 #if DEBUG
1162                     Console.Write("cafex: cosdebug.{0} read ({1}):", sCmd, completeMessage);
1163                     Console.WriteLine();
1164 #endif
1165                 }
1166             }
1167             catch (InvalidOperationException e)
1168             {
1169                 Log.WriteLine(string.Format("cafex: cosdebug.{0}: InvalidOperationException: {1}", sCmd, e));
1170             }
1171             catch (ArgumentNullException e)
1172             {
1173                 Log.WriteLine(string.Format("cafex: cosdebug.{0}: ArgumentNullException: {1}", sCmd, e));
1174             }
1175             catch (SocketException e)
1176             {
1177                 Log.WriteLine(string.Format("cafex: cosdebug.{0}: SocketException: {1}", sCmd, e));
1178             }
1179             catch (IOException e)
1180             {
1181                 Log.WriteLine(string.Format("cafex: cosdebug.{0}: IOException: {1}", sCmd, e));
1182             }
1183             finally
1184             {
1185                 if (skt != null)
1186                 {
1187                     skt.Close();
1188                 }
1189             }
1190             return completeMessage.ToString();
1191         }
1192 #endif
1193 
RecvReply(int iPort, int iTimeout)1194         internal static string RecvReply(int iPort, int iTimeout)
1195         {
1196             try
1197             {
1198                 TcpClient client = new TcpClient("localhost", iPort);
1199                 NetworkStream stream = client.GetStream();
1200 
1201                 if (stream.CanRead)
1202                 {
1203                     byte[] readBuffer = new byte[4096];
1204                     StringBuilder completeMessage = new StringBuilder();
1205                     int numberOfBytesRead = 0;
1206                     int count = 10;
1207 
1208                     while (!stream.DataAvailable)
1209                     {
1210                         if (count == 0)
1211                         {
1212                             break;
1213                         }
1214                         Thread.Sleep(10);
1215                         count--;
1216                     }
1217 
1218                     if (count > 0 || stream.DataAvailable)
1219                     {
1220 
1221                         // Incoming message may be larger than the buffer size.
1222                         do
1223                         {
1224                             numberOfBytesRead = stream.Read(readBuffer, 0, readBuffer.Length);
1225 
1226                             completeMessage.AppendFormat("{0}", Encoding.ASCII.GetString(readBuffer, 0, numberOfBytesRead));
1227 
1228                         } while (stream.DataAvailable);
1229 #if DEBUG
1230                         Console.Write("cafex: cosdebug.RecvReply read ({0}):", completeMessage);
1231                         Console.WriteLine();
1232 #endif
1233                     }
1234                     client.Close();
1235                     return completeMessage.ToString();
1236                 }
1237 
1238                 client.Close();
1239                 return string.Empty;
1240             }
1241             catch (InvalidOperationException e)
1242             {
1243                 Log.WriteLine(string.Format("cafex: cosdebug.RecvReply: InvalidOperationException: {0}", e));
1244             }
1245             catch (ArgumentNullException e)
1246             {
1247                 Log.WriteLine(string.Format("cafex: cosdebug.RecvReply: ArgumentNullException: {0}", e));
1248             }
1249             catch (SocketException e)
1250             {
1251                 Log.WriteLine(string.Format("cafex: cosdebug.RecvReply: SocketException: {0}", e));
1252             }
1253             catch (IOException e)
1254             {
1255                 Log.WriteLine(string.Format("cafex: cosdebug.RecvReply: IOException: {0}", e));
1256             }
1257 
1258             return string.Empty;
1259         }
1260 
SendKillRestartAndResponse(int iPort, int iRetries, int iTimeout, int iDelay)1261         internal static bool SendKillRestartAndResponse(int iPort, int iRetries, int iTimeout, int iDelay)
1262         {
1263             string args = Convert.ToString((int)DateTime.Now.Ticks);
1264 #if TIMER
1265             Log.WriteLine("SendCOSCommandAndRecvReply start");
1266             cosdebugSetupTime.Reset();
1267             cosdebugSetupTime.Start();
1268 #endif
1269             string reply = SendCOSCommandAndRecvReply(iPort,
1270                                                      "cos killrestart",
1271                                                      args,
1272                                                      iRetries,
1273                                                      iTimeout,
1274                                                      iDelay);
1275 #if TIMER
1276             Log.WriteLine("SendCOSCommandAndRecvReply end");
1277             cosdebugSetupTime.Stop();
1278 #endif
1279             if (string.IsNullOrEmpty(reply))
1280             {
1281                 return false;
1282             }
1283 
1284             bool bFoundAck = ParseReceivedMessage(reply, "kill_ack", args);
1285             bool bFoundDone = ParseReceivedMessage(reply, "kill_done", args);
1286 
1287             if (bFoundAck && bFoundDone)
1288                 return true;
1289 
1290             //This happens rarely
1291             if (bFoundAck && !bFoundDone)
1292             {
1293                 Thread.Sleep(iDelay);
1294                 reply = RecvReply(iPort, iDelay);
1295 
1296                 if (string.IsNullOrEmpty(reply))
1297                     return false;
1298                 bFoundDone = ParseReceivedMessage(reply, "kill_done", args);
1299 
1300                 if (bFoundDone)
1301                     return true;
1302             }
1303 
1304             return (bFoundAck && bFoundDone);
1305         }
1306     }
1307 
1308     /// <summary>
1309     /// This class encapsulates the functionality of the synctool used by CafeX.
1310     /// </summary>
1311     static class synctool
1312     {
1313         static string exe_path = "\"" + Environment.GetEnvironmentVariable("CAFE_ROOT") + "\\system\\bin\\tool\\synctool.exe" + "\"";
1314 
sync(string cfg, string src, string dst, string log)1315         internal static int sync(string cfg, string src, string dst, string log)
1316         {
1317             #if DEBUG
1318                 Log.WriteLine("synctool.sync started.");
1319             #endif
1320 
1321             FileUtil.AddQuotes(ref src);
1322             FileUtil.AddQuotes(ref dst);
1323             string output = string.Empty;
1324             int ret = ProcessExecutor.DoProcess_GetOutput(exe_path, "-cfgxml " + cfg + " " + src + " " + dst + " ", out output);
1325             FileStream fs = new FileStream(log, FileMode.Create);
1326             StreamWriter sw = new StreamWriter(fs);
1327             sw.Write(output);
1328             sw.Flush();
1329             sw.Close();
1330             return ret;
1331         }
1332     }
1333 
1334     /// <summary>
1335     /// This class encapsulates the functionality of the pcfsserversync tool used by CafeX.
1336     /// </summary>
1337     static class PCFSServerSync
1338     {
1339         static string exe_path = Environment.GetEnvironmentVariable("CAFE_ROOT") + "\\system\\bin\\tool\\PCFSServerSync.exe";
1340 
sync(string date, string elf, string mapping)1341         internal static int sync(string date, string elf, string mapping)
1342         {
1343             #if DEBUG
1344                 Log.WriteLine("PCFSServerSync.sync started.");
1345             #endif
1346 
1347             return ProcessExecutor.DoProcess(exe_path, "-comment \"cafex run: ----- [" + date + "] Launching " + Path.GetFileName(elf) + " -----\" " + Environment.GetEnvironmentVariable("PCFS_HEADLESS_EMUL") + " -softlaunch -message " + mapping);
1348         }
1349 
wait_sync(string date)1350         internal static int wait_sync(string date)
1351         {
1352             #if DEBUG
1353                 Log.WriteLine("PCFSServerSync.wait_sync started.");
1354             #endif
1355 
1356             return ProcessExecutor.DoProcess(exe_path, "-wait 25000 " + Environment.GetEnvironmentVariable("PCFS_HEADLESS_EMUL") + " -comment cafex run: [" + date + "] ----- Hard-launch Startup Complete -----");
1357         }
1358     }
1359 
1360 
1361     /// <summary>
1362     /// This class encapsulates the functionality of the ImageUploader tool used by CafeX.
1363     /// </summary>
1364     static class ImageUploader
1365     {
1366         static string exe_path = Environment.GetEnvironmentVariable("MION_BRIDGE_TOOLS") + "\\ImageUploader.exe";
1367 
upload(string ip, int bankno, string wumad_file)1368         internal static int upload(string ip, int bankno, string wumad_file)
1369         {
1370 #if DEBUG
1371             Log.WriteLine("ImageUploader.upload started.");
1372 #endif
1373             DataReceivedEventHandler callback = (sender, e) =>
1374             {
1375                 if (e != null && e.Data != null)
1376                 {
1377                     Console.WriteLine(e.Data);
1378                 }
1379             };
1380 
1381             return ProcessExecutor.StartProcess_RedirectOutput(exe_path, string.Format("-ip {0} -upload {1} -w {2}", ip, bankno, wumad_file), callback, true);
1382         }
1383     }
1384 
1385     /// <summary>
1386     /// This class encapsulates the functionality of the winmakebsf tool used by CafeX.
1387     /// </summary>
1388     static class makebsf
1389     {
1390         static string exe_path = "\"" + Environment.GetEnvironmentVariable("CAFE_ROOT") + "\\system\\bin\\tool\\winmakebsf.exe" + "\"";
1391 
make(string quiet, string bsf_file, string flags)1392         internal static int make(string quiet, string bsf_file, string flags)
1393         {
1394             #if DEBUG
1395                 Log.WriteLine("makebsf.make started.");
1396             #endif
1397             FileUtil.AddQuotes(ref bsf_file);
1398 
1399             string output = string.Empty;
1400             int ret = ProcessExecutor.DoProcess_GetOutput(exe_path, quiet + " -i 0x20008000 -j 0x20008800 -o " + bsf_file + " -f " + flags, out output);
1401             if (!string.IsNullOrEmpty(output))
1402             {
1403                 Console.Write(output);
1404             }
1405 
1406             return ret;
1407         }
1408     }
1409 
1410     /// <summary>
1411     /// This class encapsulates the functionality of the winmakedlf tool used by CafeX.
1412     /// </summary>
1413     static class makedlf
1414     {
1415         static string exe_path = "\"" + Environment.GetEnvironmentVariable("CAFE_ROOT") + "\\system\\bin\\tool\\winmakedlf.exe" + "\"";
1416 
make(string quiet, string file_list, string output_dlf_file, out string commandResult)1417         internal static int make(string quiet, string file_list, string output_dlf_file, out string commandResult)
1418         {
1419             #if DEBUG
1420                 Log.WriteLine("makedlf.make started.");
1421             #endif
1422             commandResult = string.Empty;
1423             FileUtil.AddQuotes(ref file_list);
1424             FileUtil.AddQuotes(ref output_dlf_file);
1425             return ProcessExecutor.DoProcess_GetOutput(exe_path, quiet + " -p " + file_list + " -l 0x0,0x80000,0x90000 -o " + output_dlf_file, out commandResult);
1426         }
1427     }
1428 
1429     /// <summary>
1430     /// This class encapsulates the functionality of the makewumaddlf tool used by CafeX.
1431     /// </summary>
1432     static class makewumaddlf
1433     {
1434         static string exe_path = "\"" + Environment.GetEnvironmentVariable("CAFE_ROOT") + "\\system\\bin\\tool\\mastering\\makewumaddlf.exe" + "\"";
1435 
make(string wumadFile, string extractionFolder, string output_dlf_file)1436         internal static int make(string wumadFile, string extractionFolder, string output_dlf_file)
1437         {
1438             #if DEBUG
1439                 Log.WriteLine("make_wumad_dlf make started.");
1440             #endif
1441 
1442             FileUtil.AddQuotes(ref extractionFolder);
1443             FileUtil.AddQuotes(ref output_dlf_file);
1444 
1445             // In case the file is null, adjust the parameters accordingly
1446             if (!string.IsNullOrEmpty(wumadFile))
1447             {
1448                 FileUtil.AddQuotes(ref wumadFile);
1449                 wumadFile = wumadFile + " ";
1450             }
1451 
1452             DataReceivedEventHandler callback = (sender, e) =>
1453             {
1454                 if (e != null && e.Data != null)
1455                 {
1456                     Console.WriteLine(e.Data);
1457                 }
1458             };
1459 
1460             return ProcessExecutor.StartProcess_RedirectOutput(exe_path, wumadFile + extractionFolder + " " + output_dlf_file, callback, true);
1461         }
1462     }
1463 
1464     /// <summary>
1465     /// This class encapsulates the functionality of the cafemakedlf tool used by CafeX.
1466     /// </summary>
1467     static class cafemakedlf
1468     {
1469         static string exe_path = "\"" + Environment.GetEnvironmentVariable("CAFE_ROOT") + "\\system\\bin\\tool\\mastering\\cafemakedlf.exe" + "\"";
1470 
make(string default_ddf, string common_ddf_file, string individual_ddf_file, string options)1471         internal static int make(string default_ddf, string common_ddf_file, string individual_ddf_file, string options)
1472         {
1473             #if DEBUG
1474                 Log.WriteLine("cafemakedlf.make started.");
1475             #endif
1476             FileUtil.AddQuotes(ref default_ddf);
1477             FileUtil.AddQuotes(ref common_ddf_file);
1478             string arguments = "-uf " + default_ddf + " " + common_ddf_file + " ";
1479             if (individual_ddf_file != null)
1480             {
1481                 FileUtil.AddQuotes(ref individual_ddf_file);
1482                 arguments += " " + individual_ddf_file;
1483             }
1484 
1485             if (options != null)
1486             {
1487                 arguments += " " + options;
1488             }
1489 
1490             return ProcessExecutor.DoProcess(exe_path, arguments);
1491         }
1492     }
1493 
1494     /// <summary>
1495     /// This class encapsulates the functionality of the multi compiler used by CafeX.
1496     /// </summary>
1497     static class multi
1498     {
1499         static string exe_path = "\"" + Environment.GetEnvironmentVariable("GHS_ROOT") + "\\multi.exe" + "\"";
1500 
start(string multi_connect, string cafe_multi_init, string multielf)1501         internal static int start(string multi_connect, string cafe_multi_init, string multielf)
1502         {
1503 #if DEBUG
1504             Log.WriteLine("multi.start started.");
1505 #endif
1506             String ProfCmd = "";
1507             String ProfComment = Path.GetFileName(multielf);       // change wacks so it prints out as a string nicely...
1508             FileUtil.AddQuotes(ref multielf);
1509 
1510             if (Program.CAFE_PROFILE.value != null && Program.CAFE_PROFILE.value == "1")
1511             {
1512                 CafeXEventtLog.Instance.WriteToEventLog(900, DateTime.Now, ProfComment);
1513                 String ProfFunc = "eventCreate2 /id 901 /d " + ProfComment;
1514                 // the ugliest line of code in the entire world
1515                 ProfCmd = "-cmd \"python -b -s \\\"os.system('" + ProfFunc + "')\\\"\" ";
1516             }
1517             String ExeCmd = "-cmd prepare_target " + multi_connect + " " + cafe_multi_init + " " + ProfCmd + multielf;
1518             // Console.WriteLine("\n---------------\n" + exe_path + " " + ExeCmd + "\n-------------\n");
1519             return ProcessExecutor.DoProcess_DontWait(exe_path, ExeCmd);
1520         }
1521 
1522     }
1523 
1524     internal enum SyncStage
1525     {
1526         None,
1527         Busy,
1528         Boot,
1529         TitleSoft,
1530         TitleFast,
1531         Menu,
1532     }
1533 
1534     /// <summary>
1535     /// This class emulates the functionality of the cattoucan tool.
1536     /// </summary>
1537     static class cattoucan
1538     {
1539         private static List<KeyValuePair<string, ManualResetEvent>> notifyList = new List<KeyValuePair<string, ManualResetEvent>>();
1540         private static List<KeyValuePair<string, Func<string, bool>>> callbackList = new List<KeyValuePair<string, Func<string, bool>>>();
1541 
1542         internal static SyncStage sync = SyncStage.None;
1543         private static Nintendo.SDSG.CatToucan toucan;
1544         private static EventWaitHandle evtHandle = null;
1545         private static Thread cattoucanThread = null;
1546         private static Nintendo.SDSG.CatToucan.ExitReason exit_reason = null;
1547 
outputThread(object arg)1548         static void outputThread(object arg)
1549         {
1550             // Start relaying data
1551             exit_reason = toucan.RelaySerialCharacters((Program.quiet_mode && !Program.ignore_quiet_mode) ?
1552                                                             TextWriter.Null : Console.Out,
1553                                                        true);
1554             lock (cattoucanThread)
1555             {
1556                 toucan = null;
1557             }
1558 
1559             // We don't expect for toucan to exit if we're trying to sync something
1560             if (sync != SyncStage.None)
1561             {
1562                 Console.WriteLine("cafex {0}: WARNING: CatToucan exited during sync! Cafex Code={1}, App Code={2}, Sync={3}",
1563                                   Program.command,
1564                                   exit_reason.reason,
1565                                   exit_reason.AppExitCode,
1566                                   sync);
1567             }
1568 #if DEBUG
1569             Log.WriteLine("cattoucan exiting with reason = " + exit_reason.reason);
1570             Log.WriteLine("Application exited with code " + exit_reason.AppExitCode);
1571 #endif
1572             if (exit_reason.reason == Nintendo.SDSG.CatToucan.ExitReason.Reason.StoppedDueToDroppedConnection)
1573             {
1574                 Console.WriteLine("cafex : connection to CAT-DEV on port {0} failed or was dropped.", arg);
1575             }
1576         }
1577 
createCattoucan(bool exclusive_match)1578         static void createCattoucan(bool exclusive_match)
1579         {
1580             string port = Program.SESSION_DEBUG_OUT_PORT.value;
1581 #if DEBUG
1582             Log.WriteLine("cattoucan.start started. port=" + port);
1583 #endif
1584             if (port.StartsWith("localhost:"))
1585             {
1586                 port = port.Remove(0, 10);
1587             }
1588 #if DEBUG
1589             Log.WriteLine("cattoucan starting to read from port " + port);
1590 #endif
1591             toucan = new Nintendo.SDSG.CatToucan(Convert.ToInt32(port));
1592             foreach (KeyValuePair<string, ManualResetEvent> kvp in notifyList)
1593             {
1594                 toucan.AddNotification(kvp);
1595             }
1596             foreach (KeyValuePair<string, Func<string, bool>> kvp in callbackList)
1597             {
1598                 toucan.AddNotification(kvp);
1599             }
1600 
1601             toucan.ExclusiveMatch = exclusive_match;
1602             cattoucanThread = new Thread(new ParameterizedThreadStart(outputThread));
1603             cattoucanThread.Start(port);
1604         }
1605 
start(bool no_console, bool exclusive_match)1606         internal static int start(bool no_console, bool exclusive_match)
1607         {
1608             if (Program.quiet_mode)
1609             {
1610                 stopCattoucan();
1611 #if DEBUG
1612                 Log.WriteLine("cattoucan DID NOT START because quiet is true");
1613 #endif
1614                 return 0;
1615             }
1616 
1617             if (cattoucanThread != null)
1618             {
1619                 lock (cattoucanThread)
1620                 {
1621                     if (toucan != null)
1622                     {
1623                         toucan.ExclusiveMatch = exclusive_match;
1624                     }
1625                 }
1626             }
1627             else
1628             {
1629                 createCattoucan(exclusive_match);
1630             }
1631 
1632 #if DEBUG
1633             Log.WriteLine("Joining cattoucan thread from start");
1634 #endif
1635             cattoucanThread.Join();
1636             cattoucanThread = null;
1637 #if DEBUG
1638             Log.WriteLine("Async cattoucan exited from start");
1639 #endif
1640             return exit_reason.AppExitCode;
1641         }
1642 
stopCattoucan()1643         internal static int stopCattoucan()
1644         {
1645             if (cattoucanThread == null)
1646             {
1647                 return -1;
1648             }
1649 #if DEBUG
1650             Log.WriteLine("Stopping relay");
1651 #endif
1652             lock (cattoucanThread)
1653             {
1654                 if (toucan != null)
1655                 {
1656                     toucan.StopRelay();
1657                 }
1658             }
1659 #if DEBUG
1660             Log.WriteLine("Joining cattoucan thread from stop");
1661 #endif
1662             cattoucanThread.Join();
1663             cattoucanThread = null;
1664 #if DEBUG
1665             Log.WriteLine("Async cattoucan stopped");
1666 #endif
1667             if (exit_reason.reason != Nintendo.SDSG.CatToucan.ExitReason.Reason.StoppedDueToDroppedConnection)
1668             {
1669                 return exit_reason.AppExitCode;
1670             }
1671 
1672             return 0;
1673         }
1674 
AddNotification(string match, ManualResetEvent evt)1675         internal static void AddNotification(string match, ManualResetEvent evt)
1676         {
1677             KeyValuePair<string, ManualResetEvent> kvp = new KeyValuePair<string, ManualResetEvent>(match, evt);
1678             if (toucan != null)
1679             {
1680                 toucan.AddNotification(kvp);
1681             }
1682 
1683             notifyList.Add(kvp);
1684         }
1685 
closeEvent(ref EventWaitHandle evtHandle)1686         private static void closeEvent(ref EventWaitHandle evtHandle)
1687         {
1688             if (evtHandle != null)
1689             {
1690                 evtHandle.Close();
1691                 evtHandle = null;
1692             }
1693         }
1694 
AddNotification(string match, Func<string, bool> callback)1695         internal static void AddNotification(string match, Func<string, bool> callback)
1696         {
1697             KeyValuePair<string, Func<string, bool>> kvp = new KeyValuePair<string, Func<string, bool>>(match, callback);
1698             if (toucan != null)
1699             {
1700                 toucan.AddNotification(kvp);
1701             }
1702 
1703             int already = callbackList.IndexOf(kvp);
1704             if (already >= 0)
1705             {
1706 #if DEBUG
1707                 Log.WriteLine("Overriding existing handler for '{0}'!", match);
1708 #endif
1709                 callbackList.RemoveAt(already);
1710             }
1711             callbackList.Add(kvp);
1712         }
1713 
ClearNotifications()1714         internal static void ClearNotifications()
1715         {
1716             if (toucan != null)
1717             {
1718                 toucan.ClearNotifications();
1719             }
1720 
1721             notifyList.Clear();
1722             callbackList.Clear();
1723         }
1724 
BeginBootSync()1725         internal static void BeginBootSync()
1726         {
1727             sync = SyncStage.None;
1728 
1729             // Prepare cattoucan to wait for boot syncronization
1730             closeEvent(ref evtHandle);
1731             evtHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
1732 
1733             if (cattoucanThread == null)
1734             {
1735                 createCattoucan(false);
1736             }
1737         }
1738 
SendSyncRequest(int timeout)1739         internal static bool SendSyncRequest(int timeout)
1740         {
1741             if (evtHandle == null)
1742             {
1743                 return false;
1744             }
1745 
1746             lock (cattoucanThread)
1747             {
1748                 sync = SyncStage.None;
1749             }
1750 
1751             // Reset the handle and try sending the request
1752             evtHandle.Reset();
1753             sync = SyncStage.Boot;
1754             return devkitmsg.help(timeout) == 0;
1755         }
1756 
SignalBootEvent()1757         internal static void SignalBootEvent()
1758         {
1759             lock (cattoucanThread)
1760             {
1761                 if (sync == SyncStage.Boot)
1762                 {
1763                     sync = SyncStage.None;
1764                     evtHandle.Set();
1765                 }
1766             }
1767         }
1768 
SyncWithBoot(int timeout)1769         internal static bool SyncWithBoot(int timeout)
1770         {
1771             if (evtHandle == null)
1772             {
1773                 return false;
1774             }
1775 
1776             // Wait for this message to be triggered
1777             Console.WriteLine("\nCafex {0}: Waiting for response...", Program.command);
1778             return evtHandle.WaitOne(timeout);
1779         }
1780 
BeginTitleSoftSync()1781         internal static void BeginTitleSoftSync()
1782         {
1783             sync = SyncStage.None;
1784 
1785             closeEvent(ref evtHandle);
1786             evtHandle = new EventWaitHandle(false, EventResetMode.AutoReset);
1787 
1788             sync = SyncStage.TitleSoft;
1789 
1790             if (cattoucanThread == null)
1791             {
1792                 createCattoucan(false);
1793             }
1794         }
1795 
BeginTitleFastSync()1796         internal static void BeginTitleFastSync()
1797         {
1798             stopCattoucan();
1799 
1800             closeEvent(ref evtHandle);
1801             evtHandle = new EventWaitHandle(false, EventResetMode.AutoReset);
1802 
1803             sync = SyncStage.None;
1804 
1805             createCattoucan(true);
1806         }
1807 
PrepareFastLaunch(int delay)1808         internal static void PrepareFastLaunch(int delay)
1809         {
1810             if (sync != SyncStage.Busy)
1811             {
1812                 delay = 0;
1813             }
1814 
1815             lock (cattoucanThread)
1816             {
1817                 sync = SyncStage.None;
1818             }
1819 
1820             if (delay != 0)
1821             {
1822                 Thread.Sleep(delay);
1823             }
1824 
1825             sync = SyncStage.TitleFast;
1826         }
1827 
SignalTitleEvent(SyncStage next)1828         internal static void SignalTitleEvent(SyncStage next)
1829         {
1830             lock (cattoucanThread)
1831             {
1832                 if (sync != SyncStage.None)
1833                 {
1834 #if DEBUG
1835                     Log.WriteLine("Signaling title event, next=" + next.ToString());
1836 #endif
1837                     sync = next;
1838                     evtHandle.Set();
1839                 }
1840             }
1841         }
1842 
SyncWithTitle(int timeout, bool stop)1843         internal static bool SyncWithTitle(int timeout, bool stop)
1844         {
1845             if (evtHandle != null)
1846             {
1847                 // Wait for the event to be called
1848                 while (evtHandle.WaitOne(timeout))
1849                 {
1850                     if (sync == SyncStage.None)
1851                     {
1852                         // Successfully called
1853                         FinishSync(stop);
1854                         return true;
1855                     }
1856 
1857                     if (sync == SyncStage.Busy)
1858                     {
1859                         return false;
1860                     }
1861                 }
1862             }
1863             return false;
1864         }
1865 
BeginMenuSync()1866         internal static void BeginMenuSync()
1867         {
1868             if (cattoucanThread != null)
1869             {
1870                 Monitor.Enter(cattoucanThread);
1871             }
1872 
1873             sync = SyncStage.None;
1874 
1875             if (cattoucanThread != null)
1876             {
1877                 Monitor.Exit(cattoucanThread);
1878             }
1879 
1880             // Prepare cattoucan to wait for menu syncronization
1881             closeEvent(ref evtHandle);
1882             evtHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
1883 
1884             sync = SyncStage.Menu;
1885 
1886             if (cattoucanThread == null)
1887             {
1888                 createCattoucan(false);
1889             }
1890         }
1891 
SignalMenuEvent()1892         internal static void SignalMenuEvent()
1893         {
1894             lock (cattoucanThread)
1895             {
1896                 sync = SyncStage.None;
1897                 evtHandle.Set();
1898             }
1899         }
1900 
SyncWithMenu()1901         internal static void SyncWithMenu()
1902         {
1903             if (evtHandle != null)
1904             {
1905                 // Wait for the event to be called
1906                 evtHandle.WaitOne();
1907                 FinishSync(true);
1908             }
1909         }
1910 
FinishSync(bool stop)1911         internal static void FinishSync(bool stop)
1912         {
1913             // Clear the sync flags
1914             if (cattoucanThread != null)
1915             {
1916                 Monitor.Enter(cattoucanThread);
1917                 sync = SyncStage.None;
1918 
1919                 if (stop)
1920                 {
1921                     Monitor.Exit(cattoucanThread);
1922 
1923                     // Stop async cattoucan
1924                     stopCattoucan();
1925                 }
1926             }
1927             else
1928             {
1929                 // Do not try and exit lock
1930                 stop = true;
1931             }
1932 
1933             // Delete the event handles
1934             closeEvent(ref evtHandle);
1935 
1936             if (!stop)
1937             {
1938                 Monitor.Exit(cattoucanThread);
1939             }
1940         }
1941     }
1942 
1943     /// <summary>
1944     /// This class encapsulates the functionality required to set the COM ports.
1945     /// </summary>
1946     static class cmd
1947     {
1948         static string exe_path = "cmd.exe";
1949 
mode(int comport)1950         internal static int mode(int comport)
1951         {
1952             #if DEBUG
1953                 Log.WriteLine("cmd.mode started.");
1954             #endif
1955 
1956             return ProcessExecutor.DoProcess(exe_path, "mode.com com" + comport + ": BAUD=115200 PARITY=N DATA=8 STOP=1 to=off xon=off odsr=off octs=on dtr=off rts=on idsr=off");
1957         }
1958     }
1959 
1960     /// <summary>
1961     /// This class encapsulates the functionality of the monitor tool used by CafeX.
1962     /// </summary>
1963     static class monitor
1964     {
1965         static string cygwin_monitor_exe_path = "\"" + Environment.GetEnvironmentVariable("CAFE_ROOT") + "\\system\\bin\\tool\\monitor.exe" + "\"";
1966         static readonly int MONITOR_FLUSH_TIME = 1;
1967 
GetExeName()1968         private static string GetExeName()
1969         {
1970             string monitor_or_temp_exe_path;
1971             if (FileUtil.RunningFromCygwin)
1972             {
1973                 // take the monitor from cygwin
1974                 monitor_or_temp_exe_path = cygwin_monitor_exe_path;
1975             }
1976             else
1977             {
1978                 monitor_or_temp_exe_path = FileUtil.ExpandExecutable(CafeX.Properties.Resources.win_monitor, "win_monitor.exe");
1979             }
1980             return monitor_or_temp_exe_path;
1981         }
1982 
start(string str_opt, string test_str, string timeout, string rc_file, string log)1983         internal static int start(string str_opt, string test_str, string timeout, string rc_file, string log)
1984         {
1985             #if DEBUG
1986                 Log.WriteLine("monitor.start started.");
1987             #endif
1988 
1989             string output = string.Empty;
1990 
1991             int ret = ProcessExecutor.DoProcess_GetOutput(GetExeName(), str_opt + " \"" + test_str + "\" -t " + timeout + " -p " + Environment.GetEnvironmentVariable("SESSION_DEBUG_OUT_PORT"), out output);
1992 
1993             FileStream fs = new FileStream(rc_file, FileMode.Create);
1994             StreamWriter sw = new StreamWriter(fs);
1995             sw.WriteLine(ret);
1996             sw.Flush();
1997             sw.Close();
1998 
1999             fs = new FileStream(log, FileMode.Create);
2000             sw = new StreamWriter(fs);
2001             sw.WriteLine(output);
2002             sw.Flush();
2003             sw.Close();
2004 
2005             return ret;
2006         }
2007 
start_redirectionCallback(string str_opt, string test_str, string timeout, DataReceivedEventHandler callback)2008         internal static int start_redirectionCallback(string str_opt, string test_str, string timeout, DataReceivedEventHandler callback)
2009         {
2010             #if DEBUG
2011                 Log.WriteLine("start_redirectionCallback started.");
2012             #endif
2013 
2014             string output = string.Empty;
2015             int ret = ProcessExecutor.StartProcess_RedirectOutput(GetExeName(), str_opt + " \"" + test_str + "\" -t " + timeout + " -p " + Environment.GetEnvironmentVariable("SESSION_DEBUG_OUT_PORT"), callback, true);
2016 
2017             return ret;
2018         }
2019 
flush()2020         internal static void flush()
2021         {
2022             #if DEBUG
2023                 Log.WriteLine("monitor.flush started.");
2024             #endif
2025 
2026             int ret = ProcessExecutor.DoProcess(GetExeName(), "-t " + MONITOR_FLUSH_TIME + " -s " + MONITOR_FLUSH_TIME);
2027 
2028             #if DEBUG
2029                 Log.WriteLine("monitor.flush returned = " + ret);
2030             #endif
2031         }
2032 
2033     }
2034 
2035     static class mionsig
2036     {
2037         static class HTML_CONTENT_TYPE
2038         {
2039             public const string APP_FORM_URL_ENCODED = "application/x-www-form-urlencoded";
2040         }
2041 
2042         static class HTML_METHOD
2043         {
2044             public const string POST = "POST";
2045         }
2046 
2047         internal const string MION_SIG_FMT_ADDR = "http://{0}/signal_get.cgi";
2048         internal const string MION_ADMIN_USER   = "mion";
2049         internal const string MION_ADMIN_PASS   = "/Multi_I/O_Network/";
2050         internal const string HTML_TAG_END      = "</HTML>";
2051 
2052         // Get message between "<html>" tag
getHtmlMsg(ref string response)2053         static void getHtmlMsg(ref string response)
2054         {
2055             int end = response.IndexOf(HTML_TAG_END, StringComparison.OrdinalIgnoreCase);
2056             response = response.Substring(6, end - 6);
2057         }
2058 
getVDD2()2059         internal static int getVDD2()
2060         {
2061             int VDD2 = 0;
2062 
2063             try
2064             {
2065                 // Setup web request to MION
2066                 HttpWebRequest webReq = (HttpWebRequest)WebRequest.Create(string.Format(MION_SIG_FMT_ADDR, Program.BRIDGE_CURRENT_IP_ADDRESS.value));
2067 
2068                 byte[] data = Encoding.UTF8.GetBytes("sig=VDD2");
2069 
2070                 webReq.Method          = HTML_METHOD.POST;
2071                 webReq.ContentType     = HTML_CONTENT_TYPE.APP_FORM_URL_ENCODED;
2072                 webReq.PreAuthenticate = true;
2073                 webReq.Credentials     = new NetworkCredential(MION_ADMIN_USER, MION_ADMIN_PASS);
2074                 webReq.ContentLength   = data.Length;
2075 
2076                 // Write the request to the stream
2077                 using (Stream reqStream = webReq.GetRequestStream())
2078                 {
2079                     reqStream.Write(data, 0, data.Length);
2080                     reqStream.Flush();
2081                 }
2082 
2083                 // Obtain the response
2084                 data = null;
2085                 HttpWebResponse webResp = (HttpWebResponse)webReq.GetResponse();
2086                 webReq = null;
2087 
2088                 // Read response
2089                 string response;
2090                 using (Stream respStream = webResp.GetResponseStream())
2091                 {
2092                     response = (new StreamReader(respStream)).ReadToEnd();
2093                 }
2094                 webResp = null;
2095 
2096                 // Parse VDD2 signal
2097                 getHtmlMsg(ref response);
2098                 int.TryParse(response, out VDD2);
2099 
2100             } // Any web or IO exception just report VDD2 as low
2101             catch (WebException e)
2102             {
2103                 Console.WriteLine(e.Message);
2104             }
2105             catch (IOException e)
2106             {
2107                 Console.WriteLine(e.Message);
2108             }
2109 
2110             return VDD2;
2111         }
2112     }
2113 }