install go2rtc on bob
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
//go:build 386 || arm
|
||||
|
||||
package device
|
||||
|
||||
type unsigned_char = byte
|
||||
type signed_int = int32
|
||||
type unsigned_int = uint32
|
||||
type signed_long = int64
|
||||
type unsigned_long = uint64
|
||||
type __u32 = uint32
|
||||
type void__user = uintptr
|
||||
|
||||
const (
|
||||
SNDRV_PCM_STREAM_PLAYBACK = 0
|
||||
SNDRV_PCM_STREAM_CAPTURE = 1
|
||||
|
||||
SNDRV_PCM_ACCESS_MMAP_INTERLEAVED = 0
|
||||
SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED = 1
|
||||
SNDRV_PCM_ACCESS_MMAP_COMPLEX = 2
|
||||
SNDRV_PCM_ACCESS_RW_INTERLEAVED = 3
|
||||
SNDRV_PCM_ACCESS_RW_NONINTERLEAVED = 4
|
||||
|
||||
SNDRV_PCM_FORMAT_S8 = 0
|
||||
SNDRV_PCM_FORMAT_U8 = 1
|
||||
SNDRV_PCM_FORMAT_S16_LE = 2
|
||||
SNDRV_PCM_FORMAT_S16_BE = 3
|
||||
SNDRV_PCM_FORMAT_U16_LE = 4
|
||||
SNDRV_PCM_FORMAT_U16_BE = 5
|
||||
SNDRV_PCM_FORMAT_S24_LE = 6
|
||||
SNDRV_PCM_FORMAT_S24_BE = 7
|
||||
SNDRV_PCM_FORMAT_U24_LE = 8
|
||||
SNDRV_PCM_FORMAT_U24_BE = 9
|
||||
SNDRV_PCM_FORMAT_S32_LE = 10
|
||||
SNDRV_PCM_FORMAT_S32_BE = 11
|
||||
SNDRV_PCM_FORMAT_U32_LE = 12
|
||||
SNDRV_PCM_FORMAT_U32_BE = 13
|
||||
SNDRV_PCM_FORMAT_FLOAT_LE = 14
|
||||
SNDRV_PCM_FORMAT_FLOAT_BE = 15
|
||||
SNDRV_PCM_FORMAT_FLOAT64_LE = 16
|
||||
SNDRV_PCM_FORMAT_FLOAT64_BE = 17
|
||||
SNDRV_PCM_FORMAT_MU_LAW = 20
|
||||
SNDRV_PCM_FORMAT_A_LAW = 21
|
||||
SNDRV_PCM_FORMAT_MPEG = 23
|
||||
|
||||
SNDRV_PCM_IOCTL_PVERSION = 0x80044100
|
||||
SNDRV_PCM_IOCTL_INFO = 0x81204101
|
||||
SNDRV_PCM_IOCTL_HW_REFINE = 0xc25c4110
|
||||
SNDRV_PCM_IOCTL_HW_PARAMS = 0xc25c4111
|
||||
SNDRV_PCM_IOCTL_SW_PARAMS = 0xc0684113
|
||||
SNDRV_PCM_IOCTL_PREPARE = 0x00004140
|
||||
SNDRV_PCM_IOCTL_WRITEI_FRAMES = 0x400c4150
|
||||
SNDRV_PCM_IOCTL_READI_FRAMES = 0x800c4151
|
||||
)
|
||||
|
||||
type snd_pcm_info struct { // size 288
|
||||
device unsigned_int // offset 0, size 4
|
||||
subdevice unsigned_int // offset 4, size 4
|
||||
stream signed_int // offset 8, size 4
|
||||
card signed_int // offset 12, size 4
|
||||
id [64]unsigned_char // offset 16, size 64
|
||||
name [80]unsigned_char // offset 80, size 80
|
||||
subname [32]unsigned_char // offset 160, size 32
|
||||
dev_class signed_int // offset 192, size 4
|
||||
dev_subclass signed_int // offset 196, size 4
|
||||
subdevices_count unsigned_int // offset 200, size 4
|
||||
subdevices_avail unsigned_int // offset 204, size 4
|
||||
pad1 [16]unsigned_char
|
||||
reserved [64]unsigned_char // offset 224, size 64
|
||||
}
|
||||
|
||||
type snd_pcm_uframes_t = unsigned_long
|
||||
type snd_pcm_sframes_t = signed_long
|
||||
|
||||
type snd_xferi struct { // size 12
|
||||
result snd_pcm_sframes_t // offset 0, size 4
|
||||
buf void__user // offset 4, size 4
|
||||
frames snd_pcm_uframes_t // offset 8, size 4
|
||||
}
|
||||
|
||||
const (
|
||||
SNDRV_PCM_HW_PARAM_ACCESS = 0
|
||||
SNDRV_PCM_HW_PARAM_FORMAT = 1
|
||||
SNDRV_PCM_HW_PARAM_SUBFORMAT = 2
|
||||
SNDRV_PCM_HW_PARAM_FIRST_MASK = 0
|
||||
SNDRV_PCM_HW_PARAM_LAST_MASK = 2
|
||||
|
||||
SNDRV_PCM_HW_PARAM_SAMPLE_BITS = 8
|
||||
SNDRV_PCM_HW_PARAM_FRAME_BITS = 9
|
||||
SNDRV_PCM_HW_PARAM_CHANNELS = 10
|
||||
SNDRV_PCM_HW_PARAM_RATE = 11
|
||||
SNDRV_PCM_HW_PARAM_PERIOD_TIME = 12
|
||||
SNDRV_PCM_HW_PARAM_PERIOD_SIZE = 13
|
||||
SNDRV_PCM_HW_PARAM_PERIOD_BYTES = 14
|
||||
SNDRV_PCM_HW_PARAM_PERIODS = 15
|
||||
SNDRV_PCM_HW_PARAM_BUFFER_TIME = 16
|
||||
SNDRV_PCM_HW_PARAM_BUFFER_SIZE = 17
|
||||
SNDRV_PCM_HW_PARAM_BUFFER_BYTES = 18
|
||||
SNDRV_PCM_HW_PARAM_TICK_TIME = 19
|
||||
SNDRV_PCM_HW_PARAM_FIRST_INTERVAL = 8
|
||||
SNDRV_PCM_HW_PARAM_LAST_INTERVAL = 19
|
||||
|
||||
SNDRV_MASK_MAX = 256
|
||||
|
||||
SNDRV_PCM_TSTAMP_NONE = 0
|
||||
SNDRV_PCM_TSTAMP_ENABLE = 1
|
||||
)
|
||||
|
||||
type snd_mask struct { // size 32
|
||||
bits [(SNDRV_MASK_MAX + 31) / 32]__u32 // offset 0, size 32
|
||||
}
|
||||
|
||||
type snd_interval struct { // size 12
|
||||
min unsigned_int // offset 0, size 4
|
||||
max unsigned_int // offset 4, size 4
|
||||
bit unsigned_int
|
||||
}
|
||||
|
||||
type snd_pcm_hw_params struct { // size 604
|
||||
flags unsigned_int // offset 0, size 4
|
||||
masks [SNDRV_PCM_HW_PARAM_LAST_MASK - SNDRV_PCM_HW_PARAM_FIRST_MASK + 1]snd_mask // offset 4, size 96
|
||||
mres [5]snd_mask // offset 100, size 160
|
||||
intervals [SNDRV_PCM_HW_PARAM_LAST_INTERVAL - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1]snd_interval // offset 260, size 144
|
||||
ires [9]snd_interval // offset 404, size 108
|
||||
rmask unsigned_int // offset 512, size 4
|
||||
cmask unsigned_int // offset 516, size 4
|
||||
info unsigned_int // offset 520, size 4
|
||||
msbits unsigned_int // offset 524, size 4
|
||||
rate_num unsigned_int // offset 528, size 4
|
||||
rate_den unsigned_int // offset 532, size 4
|
||||
fifo_size snd_pcm_uframes_t // offset 536, size 4
|
||||
reserved [64]unsigned_char // offset 540, size 64
|
||||
}
|
||||
|
||||
type snd_pcm_sw_params struct { // size 104
|
||||
tstamp_mode signed_int // offset 0, size 4
|
||||
period_step unsigned_int // offset 4, size 4
|
||||
sleep_min unsigned_int // offset 8, size 4
|
||||
avail_min snd_pcm_uframes_t // offset 12, size 4
|
||||
xfer_align snd_pcm_uframes_t // offset 16, size 4
|
||||
start_threshold snd_pcm_uframes_t // offset 20, size 4
|
||||
stop_threshold snd_pcm_uframes_t // offset 24, size 4
|
||||
silence_threshold snd_pcm_uframes_t // offset 28, size 4
|
||||
silence_size snd_pcm_uframes_t // offset 32, size 4
|
||||
boundary snd_pcm_uframes_t // offset 36, size 4
|
||||
proto unsigned_int // offset 40, size 4
|
||||
tstamp_type unsigned_int // offset 44, size 4
|
||||
reserved [56]unsigned_char // offset 48, size 56
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
//go:build amd64 || arm64
|
||||
|
||||
package device
|
||||
|
||||
type unsigned_char = byte
|
||||
type signed_int = int32
|
||||
type unsigned_int = uint32
|
||||
type signed_long = int64
|
||||
type unsigned_long = uint64
|
||||
type __u32 = uint32
|
||||
type void__user = uintptr
|
||||
|
||||
const (
|
||||
SNDRV_PCM_STREAM_PLAYBACK = 0
|
||||
SNDRV_PCM_STREAM_CAPTURE = 1
|
||||
|
||||
SNDRV_PCM_ACCESS_MMAP_INTERLEAVED = 0
|
||||
SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED = 1
|
||||
SNDRV_PCM_ACCESS_MMAP_COMPLEX = 2
|
||||
SNDRV_PCM_ACCESS_RW_INTERLEAVED = 3
|
||||
SNDRV_PCM_ACCESS_RW_NONINTERLEAVED = 4
|
||||
|
||||
SNDRV_PCM_FORMAT_S8 = 0
|
||||
SNDRV_PCM_FORMAT_U8 = 1
|
||||
SNDRV_PCM_FORMAT_S16_LE = 2
|
||||
SNDRV_PCM_FORMAT_S16_BE = 3
|
||||
SNDRV_PCM_FORMAT_U16_LE = 4
|
||||
SNDRV_PCM_FORMAT_U16_BE = 5
|
||||
SNDRV_PCM_FORMAT_S24_LE = 6
|
||||
SNDRV_PCM_FORMAT_S24_BE = 7
|
||||
SNDRV_PCM_FORMAT_U24_LE = 8
|
||||
SNDRV_PCM_FORMAT_U24_BE = 9
|
||||
SNDRV_PCM_FORMAT_S32_LE = 10
|
||||
SNDRV_PCM_FORMAT_S32_BE = 11
|
||||
SNDRV_PCM_FORMAT_U32_LE = 12
|
||||
SNDRV_PCM_FORMAT_U32_BE = 13
|
||||
SNDRV_PCM_FORMAT_FLOAT_LE = 14
|
||||
SNDRV_PCM_FORMAT_FLOAT_BE = 15
|
||||
SNDRV_PCM_FORMAT_FLOAT64_LE = 16
|
||||
SNDRV_PCM_FORMAT_FLOAT64_BE = 17
|
||||
SNDRV_PCM_FORMAT_MU_LAW = 20
|
||||
SNDRV_PCM_FORMAT_A_LAW = 21
|
||||
SNDRV_PCM_FORMAT_MPEG = 23
|
||||
|
||||
SNDRV_PCM_IOCTL_PVERSION = 0x80044100
|
||||
SNDRV_PCM_IOCTL_INFO = 0x81204101
|
||||
SNDRV_PCM_IOCTL_HW_REFINE = 0xc2604110
|
||||
SNDRV_PCM_IOCTL_HW_PARAMS = 0xc2604111
|
||||
SNDRV_PCM_IOCTL_SW_PARAMS = 0xc0884113
|
||||
SNDRV_PCM_IOCTL_PREPARE = 0x00004140
|
||||
SNDRV_PCM_IOCTL_WRITEI_FRAMES = 0x40184150
|
||||
SNDRV_PCM_IOCTL_READI_FRAMES = 0x80184151
|
||||
)
|
||||
|
||||
type snd_pcm_info struct { // size 288
|
||||
device unsigned_int // offset 0, size 4
|
||||
subdevice unsigned_int // offset 4, size 4
|
||||
stream signed_int // offset 8, size 4
|
||||
card signed_int // offset 12, size 4
|
||||
id [64]unsigned_char // offset 16, size 64
|
||||
name [80]unsigned_char // offset 80, size 80
|
||||
subname [32]unsigned_char // offset 160, size 32
|
||||
dev_class signed_int // offset 192, size 4
|
||||
dev_subclass signed_int // offset 196, size 4
|
||||
subdevices_count unsigned_int // offset 200, size 4
|
||||
subdevices_avail unsigned_int // offset 204, size 4
|
||||
pad1 [16]unsigned_char
|
||||
reserved [64]unsigned_char // offset 224, size 64
|
||||
}
|
||||
|
||||
type snd_pcm_uframes_t = unsigned_long
|
||||
type snd_pcm_sframes_t = signed_long
|
||||
|
||||
type snd_xferi struct { // size 24
|
||||
result snd_pcm_sframes_t // offset 0, size 8
|
||||
buf void__user // offset 8, size 8
|
||||
frames snd_pcm_uframes_t // offset 16, size 8
|
||||
}
|
||||
|
||||
const (
|
||||
SNDRV_PCM_HW_PARAM_ACCESS = 0
|
||||
SNDRV_PCM_HW_PARAM_FORMAT = 1
|
||||
SNDRV_PCM_HW_PARAM_SUBFORMAT = 2
|
||||
SNDRV_PCM_HW_PARAM_FIRST_MASK = 0
|
||||
SNDRV_PCM_HW_PARAM_LAST_MASK = 2
|
||||
|
||||
SNDRV_PCM_HW_PARAM_SAMPLE_BITS = 8
|
||||
SNDRV_PCM_HW_PARAM_FRAME_BITS = 9
|
||||
SNDRV_PCM_HW_PARAM_CHANNELS = 10
|
||||
SNDRV_PCM_HW_PARAM_RATE = 11
|
||||
SNDRV_PCM_HW_PARAM_PERIOD_TIME = 12
|
||||
SNDRV_PCM_HW_PARAM_PERIOD_SIZE = 13
|
||||
SNDRV_PCM_HW_PARAM_PERIOD_BYTES = 14
|
||||
SNDRV_PCM_HW_PARAM_PERIODS = 15
|
||||
SNDRV_PCM_HW_PARAM_BUFFER_TIME = 16
|
||||
SNDRV_PCM_HW_PARAM_BUFFER_SIZE = 17
|
||||
SNDRV_PCM_HW_PARAM_BUFFER_BYTES = 18
|
||||
SNDRV_PCM_HW_PARAM_TICK_TIME = 19
|
||||
SNDRV_PCM_HW_PARAM_FIRST_INTERVAL = 8
|
||||
SNDRV_PCM_HW_PARAM_LAST_INTERVAL = 19
|
||||
|
||||
SNDRV_MASK_MAX = 256
|
||||
|
||||
SNDRV_PCM_TSTAMP_NONE = 0
|
||||
SNDRV_PCM_TSTAMP_ENABLE = 1
|
||||
)
|
||||
|
||||
type snd_mask struct { // size 32
|
||||
bits [(SNDRV_MASK_MAX + 31) / 32]__u32 // offset 0, size 32
|
||||
}
|
||||
|
||||
type snd_interval struct { // size 12
|
||||
min unsigned_int // offset 0, size 4
|
||||
max unsigned_int // offset 4, size 4
|
||||
bit unsigned_int
|
||||
}
|
||||
|
||||
type snd_pcm_hw_params struct { // size 608
|
||||
flags unsigned_int // offset 0, size 4
|
||||
masks [SNDRV_PCM_HW_PARAM_LAST_MASK - SNDRV_PCM_HW_PARAM_FIRST_MASK + 1]snd_mask // offset 4, size 96
|
||||
mres [5]snd_mask // offset 100, size 160
|
||||
intervals [SNDRV_PCM_HW_PARAM_LAST_INTERVAL - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1]snd_interval // offset 260, size 144
|
||||
ires [9]snd_interval // offset 404, size 108
|
||||
rmask unsigned_int // offset 512, size 4
|
||||
cmask unsigned_int // offset 516, size 4
|
||||
info unsigned_int // offset 520, size 4
|
||||
msbits unsigned_int // offset 524, size 4
|
||||
rate_num unsigned_int // offset 528, size 4
|
||||
rate_den unsigned_int // offset 532, size 4
|
||||
fifo_size snd_pcm_uframes_t // offset 536, size 8
|
||||
reserved [64]unsigned_char // offset 544, size 64
|
||||
}
|
||||
|
||||
type snd_pcm_sw_params struct { // size 136
|
||||
tstamp_mode signed_int // offset 0, size 4
|
||||
period_step unsigned_int // offset 4, size 4
|
||||
sleep_min unsigned_int // offset 8, size 4
|
||||
avail_min snd_pcm_uframes_t // offset 16, size 8
|
||||
xfer_align snd_pcm_uframes_t // offset 24, size 8
|
||||
start_threshold snd_pcm_uframes_t // offset 32, size 8
|
||||
stop_threshold snd_pcm_uframes_t // offset 40, size 8
|
||||
silence_threshold snd_pcm_uframes_t // offset 48, size 8
|
||||
silence_size snd_pcm_uframes_t // offset 56, size 8
|
||||
boundary snd_pcm_uframes_t // offset 64, size 8
|
||||
proto unsigned_int // offset 72, size 4
|
||||
tstamp_type unsigned_int // offset 76, size 4
|
||||
reserved [56]unsigned_char // offset 80, size 56
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
//go:build ignore
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sound/asound.h>
|
||||
|
||||
#define print_line(text) printf("%s\n", text)
|
||||
#define print_hex_const(name) printf("\t%s = 0x%08lx\n", #name, name)
|
||||
#define print_int_const(con) printf("\t%s = %d\n", #con, con)
|
||||
|
||||
#define print_struct_header(str) printf("type %s struct { // size %lu\n", #str, sizeof(struct str))
|
||||
#define print_struct_member(str, mem, typ) printf("\t%s %s // offset %lu, size %lu\n", #mem == "type" ? "typ" : #mem, typ, offsetof(struct str, mem), sizeof((struct str){0}.mem))
|
||||
|
||||
// https://github.com/torvalds/linux/blob/master/include/uapi/sound/asound.h
|
||||
int main() {
|
||||
print_line("package device\n");
|
||||
|
||||
print_line("type unsigned_char = byte");
|
||||
print_line("type signed_int = int32");
|
||||
print_line("type unsigned_int = uint32");
|
||||
print_line("type signed_long = int64");
|
||||
print_line("type unsigned_long = uint64");
|
||||
print_line("type __u32 = uint32");
|
||||
print_line("type void__user = uintptr\n");
|
||||
|
||||
print_line("const (");
|
||||
print_int_const(SNDRV_PCM_STREAM_PLAYBACK);
|
||||
print_int_const(SNDRV_PCM_STREAM_CAPTURE);
|
||||
print_line("");
|
||||
print_int_const(SNDRV_PCM_ACCESS_MMAP_INTERLEAVED);
|
||||
print_int_const(SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED);
|
||||
print_int_const(SNDRV_PCM_ACCESS_MMAP_COMPLEX);
|
||||
print_int_const(SNDRV_PCM_ACCESS_RW_INTERLEAVED);
|
||||
print_int_const(SNDRV_PCM_ACCESS_RW_NONINTERLEAVED);
|
||||
print_line("");
|
||||
print_int_const(SNDRV_PCM_FORMAT_S8);
|
||||
print_int_const(SNDRV_PCM_FORMAT_U8);
|
||||
print_int_const(SNDRV_PCM_FORMAT_S16_LE);
|
||||
print_int_const(SNDRV_PCM_FORMAT_S16_BE);
|
||||
print_int_const(SNDRV_PCM_FORMAT_U16_LE);
|
||||
print_int_const(SNDRV_PCM_FORMAT_U16_BE);
|
||||
print_int_const(SNDRV_PCM_FORMAT_S24_LE);
|
||||
print_int_const(SNDRV_PCM_FORMAT_S24_BE);
|
||||
print_int_const(SNDRV_PCM_FORMAT_U24_LE);
|
||||
print_int_const(SNDRV_PCM_FORMAT_U24_BE);
|
||||
print_int_const(SNDRV_PCM_FORMAT_S32_LE);
|
||||
print_int_const(SNDRV_PCM_FORMAT_S32_BE);
|
||||
print_int_const(SNDRV_PCM_FORMAT_U32_LE);
|
||||
print_int_const(SNDRV_PCM_FORMAT_U32_BE);
|
||||
print_int_const(SNDRV_PCM_FORMAT_FLOAT_LE);
|
||||
print_int_const(SNDRV_PCM_FORMAT_FLOAT_BE);
|
||||
print_int_const(SNDRV_PCM_FORMAT_FLOAT64_LE);
|
||||
print_int_const(SNDRV_PCM_FORMAT_FLOAT64_BE);
|
||||
print_int_const(SNDRV_PCM_FORMAT_MU_LAW);
|
||||
print_int_const(SNDRV_PCM_FORMAT_A_LAW);
|
||||
print_int_const(SNDRV_PCM_FORMAT_MPEG);
|
||||
print_line("");
|
||||
print_hex_const(SNDRV_PCM_IOCTL_PVERSION); // A 0x00
|
||||
print_hex_const(SNDRV_PCM_IOCTL_INFO); // A 0x01
|
||||
print_hex_const(SNDRV_PCM_IOCTL_HW_REFINE); // A 0x10
|
||||
print_hex_const(SNDRV_PCM_IOCTL_HW_PARAMS); // A 0x11
|
||||
print_hex_const(SNDRV_PCM_IOCTL_SW_PARAMS); // A 0x13
|
||||
print_hex_const(SNDRV_PCM_IOCTL_PREPARE); // A 0x40
|
||||
print_hex_const(SNDRV_PCM_IOCTL_WRITEI_FRAMES); // A 0x50
|
||||
print_hex_const(SNDRV_PCM_IOCTL_READI_FRAMES); // A 0x51
|
||||
print_line(")\n");
|
||||
|
||||
print_struct_header(snd_pcm_info);
|
||||
print_struct_member(snd_pcm_info, device, "unsigned_int");
|
||||
print_struct_member(snd_pcm_info, subdevice, "unsigned_int");
|
||||
print_struct_member(snd_pcm_info, stream, "signed_int");
|
||||
print_struct_member(snd_pcm_info, card, "signed_int");
|
||||
print_struct_member(snd_pcm_info, id, "[64]unsigned_char");
|
||||
print_struct_member(snd_pcm_info, name, "[80]unsigned_char");
|
||||
print_struct_member(snd_pcm_info, subname, "[32]unsigned_char");
|
||||
print_struct_member(snd_pcm_info, dev_class, "signed_int");
|
||||
print_struct_member(snd_pcm_info, dev_subclass, "signed_int");
|
||||
print_struct_member(snd_pcm_info, subdevices_count, "unsigned_int");
|
||||
print_struct_member(snd_pcm_info, subdevices_avail, "unsigned_int");
|
||||
print_line("\tpad1 [16]unsigned_char");
|
||||
print_struct_member(snd_pcm_info, reserved, "[64]unsigned_char");
|
||||
print_line("}\n");
|
||||
|
||||
print_line("type snd_pcm_uframes_t = unsigned_long");
|
||||
print_line("type snd_pcm_sframes_t = signed_long\n");
|
||||
|
||||
print_struct_header(snd_xferi);
|
||||
print_struct_member(snd_xferi, result, "snd_pcm_sframes_t");
|
||||
print_struct_member(snd_xferi, buf, "void__user");
|
||||
print_struct_member(snd_xferi, frames, "snd_pcm_uframes_t");
|
||||
print_line("}\n");
|
||||
|
||||
print_line("const (");
|
||||
print_int_const(SNDRV_PCM_HW_PARAM_ACCESS);
|
||||
print_int_const(SNDRV_PCM_HW_PARAM_FORMAT);
|
||||
print_int_const(SNDRV_PCM_HW_PARAM_SUBFORMAT);
|
||||
print_int_const(SNDRV_PCM_HW_PARAM_FIRST_MASK);
|
||||
print_int_const(SNDRV_PCM_HW_PARAM_LAST_MASK);
|
||||
print_line("");
|
||||
print_int_const(SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
|
||||
print_int_const(SNDRV_PCM_HW_PARAM_FRAME_BITS);
|
||||
print_int_const(SNDRV_PCM_HW_PARAM_CHANNELS);
|
||||
print_int_const(SNDRV_PCM_HW_PARAM_RATE);
|
||||
print_int_const(SNDRV_PCM_HW_PARAM_PERIOD_TIME);
|
||||
print_int_const(SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
|
||||
print_int_const(SNDRV_PCM_HW_PARAM_PERIOD_BYTES);
|
||||
print_int_const(SNDRV_PCM_HW_PARAM_PERIODS);
|
||||
print_int_const(SNDRV_PCM_HW_PARAM_BUFFER_TIME);
|
||||
print_int_const(SNDRV_PCM_HW_PARAM_BUFFER_SIZE);
|
||||
print_int_const(SNDRV_PCM_HW_PARAM_BUFFER_BYTES);
|
||||
print_int_const(SNDRV_PCM_HW_PARAM_TICK_TIME);
|
||||
print_int_const(SNDRV_PCM_HW_PARAM_FIRST_INTERVAL);
|
||||
print_int_const(SNDRV_PCM_HW_PARAM_LAST_INTERVAL);
|
||||
print_line("");
|
||||
print_int_const(SNDRV_MASK_MAX);
|
||||
print_line("");
|
||||
print_int_const(SNDRV_PCM_TSTAMP_NONE);
|
||||
print_int_const(SNDRV_PCM_TSTAMP_ENABLE);
|
||||
print_line(")\n");
|
||||
|
||||
print_struct_header(snd_mask);
|
||||
print_struct_member(snd_mask, bits, "[(SNDRV_MASK_MAX+31)/32]__u32");
|
||||
print_line("}\n");
|
||||
|
||||
print_struct_header(snd_interval);
|
||||
print_struct_member(snd_interval, min, "unsigned_int");
|
||||
print_struct_member(snd_interval, max, "unsigned_int");
|
||||
print_line("\tbit unsigned_int");
|
||||
print_line("}\n");
|
||||
|
||||
print_struct_header(snd_pcm_hw_params);
|
||||
print_struct_member(snd_pcm_hw_params, flags, "unsigned_int");
|
||||
print_struct_member(snd_pcm_hw_params, masks, "[SNDRV_PCM_HW_PARAM_LAST_MASK-SNDRV_PCM_HW_PARAM_FIRST_MASK+1]snd_mask");
|
||||
print_struct_member(snd_pcm_hw_params, mres, "[5]snd_mask");
|
||||
print_struct_member(snd_pcm_hw_params, intervals, "[SNDRV_PCM_HW_PARAM_LAST_INTERVAL-SNDRV_PCM_HW_PARAM_FIRST_INTERVAL+1]snd_interval");
|
||||
print_struct_member(snd_pcm_hw_params, ires, "[9]snd_interval");
|
||||
print_struct_member(snd_pcm_hw_params, rmask, "unsigned_int");
|
||||
print_struct_member(snd_pcm_hw_params, cmask, "unsigned_int");
|
||||
print_struct_member(snd_pcm_hw_params, info, "unsigned_int");
|
||||
print_struct_member(snd_pcm_hw_params, msbits, "unsigned_int");
|
||||
print_struct_member(snd_pcm_hw_params, rate_num, "unsigned_int");
|
||||
print_struct_member(snd_pcm_hw_params, rate_den, "unsigned_int");
|
||||
print_struct_member(snd_pcm_hw_params, fifo_size, "snd_pcm_uframes_t");
|
||||
print_struct_member(snd_pcm_hw_params, reserved, "[64]unsigned_char");
|
||||
print_line("}\n");
|
||||
|
||||
print_struct_header(snd_pcm_sw_params);
|
||||
print_struct_member(snd_pcm_sw_params, tstamp_mode, "signed_int");
|
||||
print_struct_member(snd_pcm_sw_params, period_step, "unsigned_int");
|
||||
print_struct_member(snd_pcm_sw_params, sleep_min, "unsigned_int");
|
||||
print_struct_member(snd_pcm_sw_params, avail_min, "snd_pcm_uframes_t");
|
||||
print_struct_member(snd_pcm_sw_params, xfer_align, "snd_pcm_uframes_t");
|
||||
print_struct_member(snd_pcm_sw_params, start_threshold, "snd_pcm_uframes_t");
|
||||
print_struct_member(snd_pcm_sw_params, stop_threshold, "snd_pcm_uframes_t");
|
||||
print_struct_member(snd_pcm_sw_params, silence_threshold, "snd_pcm_uframes_t");
|
||||
print_struct_member(snd_pcm_sw_params, silence_size, "snd_pcm_uframes_t");
|
||||
print_struct_member(snd_pcm_sw_params, boundary, "snd_pcm_uframes_t");
|
||||
print_struct_member(snd_pcm_sw_params, proto, "unsigned_int");
|
||||
print_struct_member(snd_pcm_sw_params, tstamp_type, "unsigned_int");
|
||||
print_struct_member(snd_pcm_sw_params, reserved, "[56]unsigned_char");
|
||||
print_line("}\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
package device
|
||||
|
||||
type unsigned_char = byte
|
||||
type signed_int = int32
|
||||
type unsigned_int = uint32
|
||||
type signed_long = int64
|
||||
type unsigned_long = uint64
|
||||
type __u32 = uint32
|
||||
type void__user = uintptr
|
||||
|
||||
const (
|
||||
SNDRV_PCM_STREAM_PLAYBACK = 0
|
||||
SNDRV_PCM_STREAM_CAPTURE = 1
|
||||
|
||||
SNDRV_PCM_ACCESS_MMAP_INTERLEAVED = 0
|
||||
SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED = 1
|
||||
SNDRV_PCM_ACCESS_MMAP_COMPLEX = 2
|
||||
SNDRV_PCM_ACCESS_RW_INTERLEAVED = 3
|
||||
SNDRV_PCM_ACCESS_RW_NONINTERLEAVED = 4
|
||||
|
||||
SNDRV_PCM_FORMAT_S8 = 0
|
||||
SNDRV_PCM_FORMAT_U8 = 1
|
||||
SNDRV_PCM_FORMAT_S16_LE = 2
|
||||
SNDRV_PCM_FORMAT_S16_BE = 3
|
||||
SNDRV_PCM_FORMAT_U16_LE = 4
|
||||
SNDRV_PCM_FORMAT_U16_BE = 5
|
||||
SNDRV_PCM_FORMAT_S24_LE = 6
|
||||
SNDRV_PCM_FORMAT_S24_BE = 7
|
||||
SNDRV_PCM_FORMAT_U24_LE = 8
|
||||
SNDRV_PCM_FORMAT_U24_BE = 9
|
||||
SNDRV_PCM_FORMAT_S32_LE = 10
|
||||
SNDRV_PCM_FORMAT_S32_BE = 11
|
||||
SNDRV_PCM_FORMAT_U32_LE = 12
|
||||
SNDRV_PCM_FORMAT_U32_BE = 13
|
||||
SNDRV_PCM_FORMAT_FLOAT_LE = 14
|
||||
SNDRV_PCM_FORMAT_FLOAT_BE = 15
|
||||
SNDRV_PCM_FORMAT_FLOAT64_LE = 16
|
||||
SNDRV_PCM_FORMAT_FLOAT64_BE = 17
|
||||
SNDRV_PCM_FORMAT_MU_LAW = 20
|
||||
SNDRV_PCM_FORMAT_A_LAW = 21
|
||||
SNDRV_PCM_FORMAT_MPEG = 23
|
||||
|
||||
SNDRV_PCM_IOCTL_PVERSION = 0x40044100
|
||||
SNDRV_PCM_IOCTL_INFO = 0x41204101
|
||||
SNDRV_PCM_IOCTL_HW_REFINE = 0xc25c4110
|
||||
SNDRV_PCM_IOCTL_HW_PARAMS = 0xc25c4111
|
||||
SNDRV_PCM_IOCTL_SW_PARAMS = 0xc0684113
|
||||
SNDRV_PCM_IOCTL_PREPARE = 0x20004140
|
||||
SNDRV_PCM_IOCTL_WRITEI_FRAMES = 0x800c4150
|
||||
SNDRV_PCM_IOCTL_READI_FRAMES = 0x400c4151
|
||||
)
|
||||
|
||||
type snd_pcm_info struct { // size 288
|
||||
device unsigned_int // offset 0, size 4
|
||||
subdevice unsigned_int // offset 4, size 4
|
||||
stream signed_int // offset 8, size 4
|
||||
card signed_int // offset 12, size 4
|
||||
id [64]unsigned_char // offset 16, size 64
|
||||
name [80]unsigned_char // offset 80, size 80
|
||||
subname [32]unsigned_char // offset 160, size 32
|
||||
dev_class signed_int // offset 192, size 4
|
||||
dev_subclass signed_int // offset 196, size 4
|
||||
subdevices_count unsigned_int // offset 200, size 4
|
||||
subdevices_avail unsigned_int // offset 204, size 4
|
||||
pad1 [16]unsigned_char
|
||||
reserved [64]unsigned_char // offset 224, size 64
|
||||
}
|
||||
|
||||
type snd_pcm_uframes_t = unsigned_long
|
||||
type snd_pcm_sframes_t = signed_long
|
||||
|
||||
type snd_xferi struct { // size 12
|
||||
result snd_pcm_sframes_t // offset 0, size 4
|
||||
buf void__user // offset 4, size 4
|
||||
frames snd_pcm_uframes_t // offset 8, size 4
|
||||
}
|
||||
|
||||
const (
|
||||
SNDRV_PCM_HW_PARAM_ACCESS = 0
|
||||
SNDRV_PCM_HW_PARAM_FORMAT = 1
|
||||
SNDRV_PCM_HW_PARAM_SUBFORMAT = 2
|
||||
SNDRV_PCM_HW_PARAM_FIRST_MASK = 0
|
||||
SNDRV_PCM_HW_PARAM_LAST_MASK = 2
|
||||
|
||||
SNDRV_PCM_HW_PARAM_SAMPLE_BITS = 8
|
||||
SNDRV_PCM_HW_PARAM_FRAME_BITS = 9
|
||||
SNDRV_PCM_HW_PARAM_CHANNELS = 10
|
||||
SNDRV_PCM_HW_PARAM_RATE = 11
|
||||
SNDRV_PCM_HW_PARAM_PERIOD_TIME = 12
|
||||
SNDRV_PCM_HW_PARAM_PERIOD_SIZE = 13
|
||||
SNDRV_PCM_HW_PARAM_PERIOD_BYTES = 14
|
||||
SNDRV_PCM_HW_PARAM_PERIODS = 15
|
||||
SNDRV_PCM_HW_PARAM_BUFFER_TIME = 16
|
||||
SNDRV_PCM_HW_PARAM_BUFFER_SIZE = 17
|
||||
SNDRV_PCM_HW_PARAM_BUFFER_BYTES = 18
|
||||
SNDRV_PCM_HW_PARAM_TICK_TIME = 19
|
||||
SNDRV_PCM_HW_PARAM_FIRST_INTERVAL = 8
|
||||
SNDRV_PCM_HW_PARAM_LAST_INTERVAL = 19
|
||||
|
||||
SNDRV_MASK_MAX = 256
|
||||
|
||||
SNDRV_PCM_TSTAMP_NONE = 0
|
||||
SNDRV_PCM_TSTAMP_ENABLE = 1
|
||||
)
|
||||
|
||||
type snd_mask struct { // size 32
|
||||
bits [(SNDRV_MASK_MAX + 31) / 32]__u32 // offset 0, size 32
|
||||
}
|
||||
|
||||
type snd_interval struct { // size 12
|
||||
min unsigned_int // offset 0, size 4
|
||||
max unsigned_int // offset 4, size 4
|
||||
bit unsigned_int
|
||||
}
|
||||
|
||||
type snd_pcm_hw_params struct { // size 604
|
||||
flags unsigned_int // offset 0, size 4
|
||||
masks [SNDRV_PCM_HW_PARAM_LAST_MASK - SNDRV_PCM_HW_PARAM_FIRST_MASK + 1]snd_mask // offset 4, size 96
|
||||
mres [5]snd_mask // offset 100, size 160
|
||||
intervals [SNDRV_PCM_HW_PARAM_LAST_INTERVAL - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1]snd_interval // offset 260, size 144
|
||||
ires [9]snd_interval // offset 404, size 108
|
||||
rmask unsigned_int // offset 512, size 4
|
||||
cmask unsigned_int // offset 516, size 4
|
||||
info unsigned_int // offset 520, size 4
|
||||
msbits unsigned_int // offset 524, size 4
|
||||
rate_num unsigned_int // offset 528, size 4
|
||||
rate_den unsigned_int // offset 532, size 4
|
||||
fifo_size snd_pcm_uframes_t // offset 536, size 4
|
||||
reserved [64]unsigned_char // offset 540, size 64
|
||||
}
|
||||
|
||||
type snd_pcm_sw_params struct { // size 104
|
||||
tstamp_mode signed_int // offset 0, size 4
|
||||
period_step unsigned_int // offset 4, size 4
|
||||
sleep_min unsigned_int // offset 8, size 4
|
||||
avail_min snd_pcm_uframes_t // offset 12, size 4
|
||||
xfer_align snd_pcm_uframes_t // offset 16, size 4
|
||||
start_threshold snd_pcm_uframes_t // offset 20, size 4
|
||||
stop_threshold snd_pcm_uframes_t // offset 24, size 4
|
||||
silence_threshold snd_pcm_uframes_t // offset 28, size 4
|
||||
silence_size snd_pcm_uframes_t // offset 32, size 4
|
||||
boundary snd_pcm_uframes_t // offset 36, size 4
|
||||
proto unsigned_int // offset 40, size 4
|
||||
tstamp_type unsigned_int // offset 44, size 4
|
||||
reserved [56]unsigned_char // offset 48, size 56
|
||||
}
|
||||
@@ -0,0 +1,231 @@
|
||||
package device
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type Device struct {
|
||||
fd uintptr
|
||||
path string
|
||||
|
||||
hwparams snd_pcm_hw_params
|
||||
frameBytes int // sample size * channels
|
||||
}
|
||||
|
||||
func Open(path string) (*Device, error) {
|
||||
// important to use nonblock because can get lock
|
||||
fd, err := syscall.Open(path, syscall.O_RDWR|syscall.O_NONBLOCK, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// important to remove nonblock because better to handle reads and writes
|
||||
if err = syscall.SetNonblock(fd, false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
d := &Device{fd: uintptr(fd), path: path}
|
||||
d.init()
|
||||
|
||||
// load all supported formats, channels, rates, etc.
|
||||
if err = ioctl(d.fd, SNDRV_PCM_IOCTL_HW_REFINE, &d.hwparams); err != nil {
|
||||
_ = d.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
d.setMask(SNDRV_PCM_HW_PARAM_ACCESS, SNDRV_PCM_ACCESS_RW_INTERLEAVED)
|
||||
|
||||
return d, nil
|
||||
}
|
||||
|
||||
func (d *Device) Close() error {
|
||||
return syscall.Close(int(d.fd))
|
||||
}
|
||||
|
||||
func (d *Device) IsCapture() bool {
|
||||
// path: /dev/snd/pcmC0D0c, where p - playback, c - capture
|
||||
return d.path[len(d.path)-1] == 'c'
|
||||
}
|
||||
|
||||
type Info struct {
|
||||
Card int
|
||||
Device int
|
||||
SubDevice int
|
||||
Stream int
|
||||
ID string
|
||||
Name string
|
||||
SubName string
|
||||
}
|
||||
|
||||
func (d *Device) Info() (*Info, error) {
|
||||
var info snd_pcm_info
|
||||
if err := ioctl(d.fd, SNDRV_PCM_IOCTL_INFO, &info); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Info{
|
||||
Card: int(info.card),
|
||||
Device: int(info.device),
|
||||
SubDevice: int(info.subdevice),
|
||||
Stream: int(info.stream),
|
||||
ID: str(info.id[:]),
|
||||
Name: str(info.name[:]),
|
||||
SubName: str(info.subname[:]),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (d *Device) CheckFormat(format byte) bool {
|
||||
return d.checkMask(SNDRV_PCM_HW_PARAM_FORMAT, uint32(format))
|
||||
}
|
||||
|
||||
func (d *Device) ListFormats() (formats []byte) {
|
||||
for i := byte(0); i <= 28; i++ {
|
||||
if d.CheckFormat(i) {
|
||||
formats = append(formats, i)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Device) RangeRates() (uint32, uint32) {
|
||||
return d.getInterval(SNDRV_PCM_HW_PARAM_RATE)
|
||||
}
|
||||
|
||||
func (d *Device) RangeChannels() (byte, byte) {
|
||||
minCh, maxCh := d.getInterval(SNDRV_PCM_HW_PARAM_CHANNELS)
|
||||
return byte(minCh), byte(maxCh)
|
||||
}
|
||||
|
||||
func (d *Device) GetRateNear(rate uint32) uint32 {
|
||||
r1, r2 := d.RangeRates()
|
||||
if rate < r1 {
|
||||
return r1
|
||||
}
|
||||
if rate > r2 {
|
||||
return r2
|
||||
}
|
||||
return rate
|
||||
}
|
||||
|
||||
func (d *Device) GetChannelsNear(channels byte) byte {
|
||||
c1, c2 := d.RangeChannels()
|
||||
if channels < c1 {
|
||||
return c1
|
||||
}
|
||||
if channels > c2 {
|
||||
return c2
|
||||
}
|
||||
return channels
|
||||
}
|
||||
|
||||
const bufferSize = 4096
|
||||
|
||||
func (d *Device) SetHWParams(format byte, rate uint32, channels byte) error {
|
||||
d.setInterval(SNDRV_PCM_HW_PARAM_CHANNELS, uint32(channels))
|
||||
d.setInterval(SNDRV_PCM_HW_PARAM_RATE, rate)
|
||||
d.setMask(SNDRV_PCM_HW_PARAM_FORMAT, uint32(format))
|
||||
//d.setMask(SNDRV_PCM_HW_PARAM_SUBFORMAT, 0)
|
||||
|
||||
// important for smooth playback
|
||||
d.setInterval(SNDRV_PCM_HW_PARAM_BUFFER_SIZE, bufferSize)
|
||||
//d.setInterval(SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 2000)
|
||||
|
||||
if err := ioctl(d.fd, SNDRV_PCM_IOCTL_HW_PARAMS, &d.hwparams); err != nil {
|
||||
return fmt.Errorf("[alsa] set hw_params: %w", err)
|
||||
}
|
||||
|
||||
_, i := d.getInterval(SNDRV_PCM_HW_PARAM_FRAME_BITS)
|
||||
d.frameBytes = int(i / 8)
|
||||
|
||||
_, periods := d.getInterval(SNDRV_PCM_HW_PARAM_PERIODS)
|
||||
_, periodSize := d.getInterval(SNDRV_PCM_HW_PARAM_PERIOD_SIZE)
|
||||
threshold := snd_pcm_uframes_t(periods * periodSize) // same as bufferSize
|
||||
|
||||
swparams := snd_pcm_sw_params{
|
||||
//tstamp_mode: SNDRV_PCM_TSTAMP_ENABLE,
|
||||
period_step: 1,
|
||||
avail_min: 1, // start as soon as possible
|
||||
stop_threshold: threshold,
|
||||
}
|
||||
|
||||
if d.IsCapture() {
|
||||
swparams.start_threshold = 1
|
||||
} else {
|
||||
swparams.start_threshold = threshold
|
||||
}
|
||||
|
||||
if err := ioctl(d.fd, SNDRV_PCM_IOCTL_SW_PARAMS, &swparams); err != nil {
|
||||
return fmt.Errorf("[alsa] set sw_params: %w", err)
|
||||
}
|
||||
|
||||
if err := ioctl(d.fd, SNDRV_PCM_IOCTL_PREPARE, nil); err != nil {
|
||||
return fmt.Errorf("[alsa] prepare: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Device) Write(b []byte) (n int, err error) {
|
||||
xfer := &snd_xferi{
|
||||
buf: uintptr(unsafe.Pointer(&b[0])),
|
||||
frames: snd_pcm_uframes_t(len(b) / d.frameBytes),
|
||||
}
|
||||
err = ioctl(d.fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, xfer)
|
||||
if err == syscall.EPIPE {
|
||||
// auto handle underrun state
|
||||
// https://stackoverflow.com/questions/59396728/how-to-properly-handle-xrun-in-alsa-programming-when-playing-audio-with-snd-pcm
|
||||
err = ioctl(d.fd, SNDRV_PCM_IOCTL_PREPARE, nil)
|
||||
}
|
||||
n = int(xfer.result) * d.frameBytes
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Device) Read(b []byte) (n int, err error) {
|
||||
xfer := &snd_xferi{
|
||||
buf: uintptr(unsafe.Pointer(&b[0])),
|
||||
frames: snd_pcm_uframes_t(len(b) / d.frameBytes),
|
||||
}
|
||||
err = ioctl(d.fd, SNDRV_PCM_IOCTL_READI_FRAMES, xfer)
|
||||
n = int(xfer.result) * d.frameBytes
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Device) init() {
|
||||
for i := range d.hwparams.masks {
|
||||
d.hwparams.masks[i].bits[0] = 0xFFFFFFFF
|
||||
d.hwparams.masks[i].bits[1] = 0xFFFFFFFF
|
||||
}
|
||||
for i := range d.hwparams.intervals {
|
||||
d.hwparams.intervals[i].max = 0xFFFFFFFF
|
||||
}
|
||||
|
||||
d.hwparams.rmask = 0xFFFFFFFF
|
||||
d.hwparams.cmask = 0
|
||||
d.hwparams.info = 0xFFFFFFFF
|
||||
}
|
||||
|
||||
func (d *Device) setInterval(param, val uint32) {
|
||||
d.hwparams.intervals[param-SNDRV_PCM_HW_PARAM_FIRST_INTERVAL].min = val
|
||||
d.hwparams.intervals[param-SNDRV_PCM_HW_PARAM_FIRST_INTERVAL].max = val
|
||||
d.hwparams.intervals[param-SNDRV_PCM_HW_PARAM_FIRST_INTERVAL].bit = 0b0100 // integer
|
||||
}
|
||||
|
||||
func (d *Device) setIntervalMin(param, val uint32) {
|
||||
d.hwparams.intervals[param-SNDRV_PCM_HW_PARAM_FIRST_INTERVAL].min = val
|
||||
}
|
||||
|
||||
func (d *Device) getInterval(param uint32) (uint32, uint32) {
|
||||
return d.hwparams.intervals[param-SNDRV_PCM_HW_PARAM_FIRST_INTERVAL].min,
|
||||
d.hwparams.intervals[param-SNDRV_PCM_HW_PARAM_FIRST_INTERVAL].max
|
||||
}
|
||||
|
||||
func (d *Device) setMask(mask, val uint32) {
|
||||
d.hwparams.masks[mask].bits[0] = 0
|
||||
d.hwparams.masks[mask].bits[1] = 0
|
||||
d.hwparams.masks[mask].bits[val>>5] = 1 << (val & 0x1F)
|
||||
}
|
||||
|
||||
func (d *Device) checkMask(mask, val uint32) bool {
|
||||
return d.hwparams.masks[mask].bits[val>>5]&(1<<(val&0x1F)) > 0
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package device
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"reflect"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func ioctl(fd, req uintptr, arg any) error {
|
||||
var ptr uintptr
|
||||
if arg != nil {
|
||||
ptr = reflect.ValueOf(arg).Pointer()
|
||||
}
|
||||
_, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, req, ptr)
|
||||
if err != 0 {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func str(b []byte) string {
|
||||
if i := bytes.IndexByte(b, 0); i >= 0 {
|
||||
return string(b[:i])
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
Reference in New Issue
Block a user