mirror of
https://github.com/Leonmmcoset/cleonos.git
synced 2026-04-21 10:40:00 +00:00
wav支持(没有测试)
This commit is contained in:
126
clks/drivers/audio/pcspeaker.c
Normal file
126
clks/drivers/audio/pcspeaker.c
Normal file
@@ -0,0 +1,126 @@
|
||||
#include <clks/audio.h>
|
||||
#include <clks/exec.h>
|
||||
#include <clks/log.h>
|
||||
#include <clks/types.h>
|
||||
|
||||
#define CLKS_AUDIO_PIT_BASE_HZ 1193182ULL
|
||||
#define CLKS_AUDIO_FREQ_MIN 20ULL
|
||||
#define CLKS_AUDIO_FREQ_MAX 20000ULL
|
||||
#define CLKS_AUDIO_TICKS_MAX 2048ULL
|
||||
|
||||
static clks_bool clks_audio_ready = CLKS_FALSE;
|
||||
static u64 clks_audio_played_count = 0ULL;
|
||||
|
||||
#if defined(CLKS_ARCH_X86_64)
|
||||
static inline void clks_audio_outb(u16 port, u8 value) {
|
||||
__asm__ volatile("outb %0, %1" : : "a"(value), "Nd"(port));
|
||||
}
|
||||
|
||||
static inline u8 clks_audio_inb(u16 port) {
|
||||
u8 value;
|
||||
__asm__ volatile("inb %1, %0" : "=a"(value) : "Nd"(port));
|
||||
return value;
|
||||
}
|
||||
|
||||
static void clks_audio_program_pc_speaker(u64 hz) {
|
||||
u64 divisor64 = CLKS_AUDIO_PIT_BASE_HZ / hz;
|
||||
u16 divisor;
|
||||
u8 control;
|
||||
|
||||
if (divisor64 == 0ULL) {
|
||||
divisor64 = 1ULL;
|
||||
}
|
||||
|
||||
if (divisor64 > 0xFFFFULL) {
|
||||
divisor64 = 0xFFFFULL;
|
||||
}
|
||||
|
||||
divisor = (u16)divisor64;
|
||||
clks_audio_outb(0x43U, 0xB6U);
|
||||
clks_audio_outb(0x42U, (u8)(divisor & 0xFFU));
|
||||
clks_audio_outb(0x42U, (u8)((divisor >> 8) & 0xFFU));
|
||||
|
||||
control = clks_audio_inb(0x61U);
|
||||
clks_audio_outb(0x61U, (u8)(control | 0x03U));
|
||||
}
|
||||
#endif
|
||||
|
||||
static u64 clks_audio_clamp_hz(u64 hz) {
|
||||
if (hz < CLKS_AUDIO_FREQ_MIN) {
|
||||
return CLKS_AUDIO_FREQ_MIN;
|
||||
}
|
||||
|
||||
if (hz > CLKS_AUDIO_FREQ_MAX) {
|
||||
return CLKS_AUDIO_FREQ_MAX;
|
||||
}
|
||||
|
||||
return hz;
|
||||
}
|
||||
|
||||
void clks_audio_init(void) {
|
||||
#if defined(CLKS_ARCH_X86_64)
|
||||
clks_audio_ready = CLKS_TRUE;
|
||||
clks_audio_played_count = 0ULL;
|
||||
clks_audio_stop();
|
||||
|
||||
clks_log(CLKS_LOG_INFO, "AUDIO", "PC SPEAKER ONLINE");
|
||||
clks_log_hex(CLKS_LOG_INFO, "AUDIO", "PIT_BASE_HZ", CLKS_AUDIO_PIT_BASE_HZ);
|
||||
#else
|
||||
clks_audio_ready = CLKS_FALSE;
|
||||
clks_audio_played_count = 0ULL;
|
||||
clks_log(CLKS_LOG_WARN, "AUDIO", "AUDIO OUTPUT NOT AVAILABLE ON THIS ARCH");
|
||||
#endif
|
||||
}
|
||||
|
||||
clks_bool clks_audio_available(void) {
|
||||
return clks_audio_ready;
|
||||
}
|
||||
|
||||
clks_bool clks_audio_play_tone(u64 hz, u64 ticks) {
|
||||
if (clks_audio_ready == CLKS_FALSE) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
if (ticks == 0ULL) {
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
if (ticks > CLKS_AUDIO_TICKS_MAX) {
|
||||
ticks = CLKS_AUDIO_TICKS_MAX;
|
||||
}
|
||||
|
||||
if (hz == 0ULL) {
|
||||
clks_audio_stop();
|
||||
(void)clks_exec_sleep_ticks(ticks);
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
hz = clks_audio_clamp_hz(hz);
|
||||
|
||||
#if defined(CLKS_ARCH_X86_64)
|
||||
clks_audio_program_pc_speaker(hz);
|
||||
(void)clks_exec_sleep_ticks(ticks);
|
||||
clks_audio_stop();
|
||||
clks_audio_played_count++;
|
||||
return CLKS_TRUE;
|
||||
#else
|
||||
return CLKS_FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
void clks_audio_stop(void) {
|
||||
#if defined(CLKS_ARCH_X86_64)
|
||||
u8 control;
|
||||
|
||||
if (clks_audio_ready == CLKS_FALSE) {
|
||||
return;
|
||||
}
|
||||
|
||||
control = clks_audio_inb(0x61U);
|
||||
clks_audio_outb(0x61U, (u8)(control & 0xFCU));
|
||||
#endif
|
||||
}
|
||||
|
||||
u64 clks_audio_play_count(void) {
|
||||
return clks_audio_played_count;
|
||||
}
|
||||
12
clks/include/clks/audio.h
Normal file
12
clks/include/clks/audio.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef CLKS_AUDIO_H
|
||||
#define CLKS_AUDIO_H
|
||||
|
||||
#include <clks/types.h>
|
||||
|
||||
void clks_audio_init(void);
|
||||
clks_bool clks_audio_available(void);
|
||||
clks_bool clks_audio_play_tone(u64 hz, u64 ticks);
|
||||
void clks_audio_stop(void);
|
||||
u64 clks_audio_play_count(void);
|
||||
|
||||
#endif
|
||||
@@ -10,6 +10,7 @@ enum clks_driver_kind {
|
||||
CLKS_DRIVER_KIND_BUILTIN_VIDEO = 2,
|
||||
CLKS_DRIVER_KIND_BUILTIN_TTY = 3,
|
||||
CLKS_DRIVER_KIND_ELF = 4,
|
||||
CLKS_DRIVER_KIND_BUILTIN_AUDIO = 5,
|
||||
};
|
||||
|
||||
enum clks_driver_state {
|
||||
|
||||
@@ -51,6 +51,9 @@
|
||||
#define CLKS_SYSCALL_YIELD 45ULL
|
||||
#define CLKS_SYSCALL_SHUTDOWN 46ULL
|
||||
#define CLKS_SYSCALL_RESTART 47ULL
|
||||
#define CLKS_SYSCALL_AUDIO_AVAILABLE 48ULL
|
||||
#define CLKS_SYSCALL_AUDIO_PLAY_TONE 49ULL
|
||||
#define CLKS_SYSCALL_AUDIO_STOP 50ULL
|
||||
|
||||
void clks_syscall_init(void);
|
||||
u64 clks_syscall_dispatch(void *frame_ptr);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <clks/driver.h>
|
||||
#include <clks/audio.h>
|
||||
#include <clks/elf64.h>
|
||||
#include <clks/framebuffer.h>
|
||||
#include <clks/fs.h>
|
||||
@@ -115,6 +116,12 @@ static void clks_driver_register_builtins(void) {
|
||||
clks_driver_push("framebuffer", CLKS_DRIVER_KIND_BUILTIN_VIDEO, CLKS_DRIVER_STATE_FAILED, CLKS_FALSE, 0ULL, 0ULL);
|
||||
clks_driver_push("tty", CLKS_DRIVER_KIND_BUILTIN_TTY, CLKS_DRIVER_STATE_FAILED, CLKS_FALSE, 0ULL, 0ULL);
|
||||
}
|
||||
|
||||
if (clks_audio_available() == CLKS_TRUE) {
|
||||
clks_driver_push("pcspeaker", CLKS_DRIVER_KIND_BUILTIN_AUDIO, CLKS_DRIVER_STATE_READY, CLKS_FALSE, 0ULL, 0ULL);
|
||||
} else {
|
||||
clks_driver_push("pcspeaker", CLKS_DRIVER_KIND_BUILTIN_AUDIO, CLKS_DRIVER_STATE_FAILED, CLKS_FALSE, 0ULL, 0ULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void clks_driver_probe_driver_dir(void) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Kernel main function
|
||||
|
||||
#include <clks/boot.h>
|
||||
#include <clks/audio.h>
|
||||
#include <clks/cpu.h>
|
||||
#include <clks/desktop.h>
|
||||
#include <clks/driver.h>
|
||||
@@ -175,6 +176,7 @@ void clks_kernel_main(void) {
|
||||
}
|
||||
|
||||
clks_exec_init();
|
||||
clks_audio_init();
|
||||
clks_keyboard_init();
|
||||
clks_mouse_init();
|
||||
clks_desktop_init();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <clks/cpu.h>
|
||||
#include <clks/audio.h>
|
||||
#include <clks/exec.h>
|
||||
#include <clks/fs.h>
|
||||
#include <clks/heap.h>
|
||||
@@ -280,6 +281,22 @@ static u64 clks_syscall_restart(void) {
|
||||
}
|
||||
|
||||
|
||||
static u64 clks_syscall_audio_available(void) {
|
||||
return (clks_audio_available() == CLKS_TRUE) ? 1ULL : 0ULL;
|
||||
}
|
||||
|
||||
static u64 clks_syscall_audio_play_tone(u64 arg0, u64 arg1) {
|
||||
if (clks_audio_play_tone(arg0, arg1) == CLKS_FALSE) {
|
||||
return 0ULL;
|
||||
}
|
||||
|
||||
return 1ULL;
|
||||
}
|
||||
|
||||
static u64 clks_syscall_audio_stop(void) {
|
||||
clks_audio_stop();
|
||||
return 1ULL;
|
||||
}
|
||||
static u64 clks_syscall_fs_stat_type(u64 arg0) {
|
||||
char path[CLKS_SYSCALL_PATH_MAX];
|
||||
struct clks_fs_node_info info;
|
||||
@@ -582,6 +599,12 @@ u64 clks_syscall_dispatch(void *frame_ptr) {
|
||||
return clks_syscall_shutdown();
|
||||
case CLKS_SYSCALL_RESTART:
|
||||
return clks_syscall_restart();
|
||||
case CLKS_SYSCALL_AUDIO_AVAILABLE:
|
||||
return clks_syscall_audio_available();
|
||||
case CLKS_SYSCALL_AUDIO_PLAY_TONE:
|
||||
return clks_syscall_audio_play_tone(frame->rbx, frame->rcx);
|
||||
case CLKS_SYSCALL_AUDIO_STOP:
|
||||
return clks_syscall_audio_stop();
|
||||
default:
|
||||
return (u64)-1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user