차이

문서의 선택한 두 판 사이의 차이를 보여줍니다.

차이 보기로 링크

linuxpc:buzzer:index [2026/06/09 14:50] – created adminlinuxpc:buzzer:index [2026/06/09 23:03] (현재) admin
줄 26: 줄 26:
 [[https://www.kernel.org/doc/html/latest/input/input_uapi.html|Linux Input Subsystem]] [[https://www.kernel.org/doc/html/latest/input/input_uapi.html|Linux Input Subsystem]]
  
 +++++[소스 코드]|
 <code C#> <code C#>
-(원본 코드 그대로) </code>+using System; 
 +using System.IO; 
 +using System.Runtime.InteropServices; 
 +using System.Threading; 
 + 
 +class Siren 
 +
 +    static void Main(string[] args) 
 +    { 
 +        Console.CancelKeyPress += (sender, e) => 
 +        { 
 +            e.Cancel = true; 
 +            exiting = true; 
 +            Console.WriteLine("\nCtrl+C received. Stopping siren..."); 
 +        }; 
 + 
 +        const string eventPath = "/dev/input/by-path/platform-buzzer-event"; 
 + 
 +        Console.WriteLine("Siren generator running. Press Ctrl+C to stop."); 
 + 
 +        double time = 0; 
 +        double step = 0.02; // 50 Hz update rate (20ms) 
 + 
 +        FileStream? fs = null; 
 + 
 +        try 
 +        { 
 +            fs = new FileStream(eventPath, FileMode.Open, FileAccess.Write, FileShare.ReadWrite); 
 + 
 +            while (!exiting) 
 +            { 
 +                // Siren: 500 Hz to 1500 Hz and back in 2 seconds 
 +                double cycleTime = time % 2.0; 
 +                double frequency; 
 + 
 +                if (cycleTime < 1.0) 
 +                    frequency = 500 + (cycleTime * 1000);          // Rise 
 +                else 
 +                    frequency = 1500 - ((cycleTime - 1.0) * 1000); // Fall 
 + 
 +                int hz = (int)Math.Round(frequency); 
 + 
 +                SendTone(fs, hz); 
 + 
 +                Thread.Sleep((int)(step * 1000)); 
 +                time += step; 
 +            } 
 +        } 
 +        catch (Exception ex) 
 +        { 
 +            Console.Error.WriteLine(ex.Message); 
 +        } 
 +        finally 
 +        { 
 +            // Ensure buzzer is silenced 
 +            try 
 +            { 
 +                if (fs != null) 
 +                { 
 +                    SendTone(fs, 0); 
 +                    fs.Dispose(); 
 +                } 
 +            } 
 +            catch (Exception ex) 
 +            { 
 +                Console.Error.WriteLine(ex.Message); 
 +            } 
 + 
 +            Console.WriteLine("Siren stopped."); 
 +        } 
 +    } 
 +  
 +    // Linux input event constants 
 +    const ushort EV_SYN = 0x00; 
 +    const ushort EV_SND = 0x12; 
 +    const ushort SYN_REPORT = 0x00; 
 +    const ushort SND_BELL = 0x01; 
 +    const ushort SND_TONE = 0x02; 
 + 
 +    static bool exiting = false; 
 + 
 +    // input_event struct from <linux/input.h> 
 +    // struct timeval { long tv_sec; long tv_usec; }; 
 +    // struct input_event { struct timeval time; __u16 type; __u16 code; __s32 value; }; 
 +    [StructLayout(LayoutKind.Sequential)] 
 +    struct TimeVal 
 +    { 
 +        public long tv_sec; 
 +        public long tv_usec; 
 +    } 
 + 
 +    [StructLayout(LayoutKind.Sequential)] 
 +    struct InputEvent 
 +    { 
 +        public TimeVal time; 
 +        public ushort type; 
 +        public ushort code; 
 +        public int value; 
 +    } 
 + 
 +    // Compute once to avoid repeated reflection-ish cost 
 +    static readonly int InputEventSize = Marshal.SizeOf<InputEvent>(); 
 + 
 +    static void SendTone(FileStream fs, int hz) 
 +    { 
 +        // hz > 0 => play tone at hz 
 +        // hz == 0 => stop tone 
 +        WriteEvent(fs, EV_SND, SND_TONE, hz); 
 +        WriteEvent(fs, EV_SYN, SYN_REPORT, 0); 
 +        fs.Flush(); 
 +    } 
 + 
 +    static void WriteEvent(FileStream fs, ushort type, ushort code, int value) 
 +    { 
 +        // Local struct lives on the stack (no heap allocation) 
 +        InputEvent ev = new InputEvent 
 +        { 
 +            time = default, // kernel will timestamp; zeroed is fine 
 +            type = type, 
 +            code = code, 
 +            value = value 
 +        }; 
 + 
 +        // Stack-allocated byte buffer 
 +        Span<byte> buffer = stackalloc byte[InputEventSize]; 
 + 
 +        // Copy struct bytes into the stack buffer 
 +        MemoryMarshal.Write(buffer, in ev); 
 + 
 +        // Write without allocating 
 +        fs.Write(buffer); 
 +    } 
 +
 + 
 +</code> 
 +++++
  
 [[..:index|JPC (임베디드 리눅스 Panel PC)]] [[..:index|JPC (임베디드 리눅스 Panel PC)]]