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