1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: © 2021 Ahmad Fatoum
#include <common.h>
#include <linux/list.h>
#include <sound.h>
#include <poller.h>
#include <linux/iopoll.h>
static LIST_HEAD(card_list);
struct beep {
int freq;
unsigned int us;
struct list_head list;
};
static int sound_card_do_beep(struct sound_card *card,
int freq, unsigned int us)
{
if (freq == -1)
freq = card->bell_frequency;
return card->beep(card, freq, us);
}
static void sound_card_poller_cb(void *_card)
{
struct sound_card *card = _card;
struct beep *beep;
beep = list_first_entry_or_null(&card->tune, struct beep, list);
if (!beep) {
sound_card_do_beep(card, 0, 0);
return;
}
list_del(&beep->list);
poller_call_async(&card->poller, beep->us * 1000ULL,
sound_card_poller_cb, card);
sound_card_do_beep(card, beep->freq, beep->us);
free(beep);
}
int sound_card_register(struct sound_card *card)
{
if (!card->name)
return -EINVAL;
if (card->bell_frequency <= 0)
card->bell_frequency = 1000;
poller_async_register(&card->poller, card->name);
INIT_LIST_HEAD(&card->tune);
list_add_tail(&card->list, &card_list);
return 0;
}
struct sound_card *sound_card_get_default(void)
{
return list_first_entry_or_null(&card_list, struct sound_card, list);
}
int sound_card_beep(struct sound_card *card, int freq, unsigned int us)
{
struct beep *beep;
int ret;
if (!card)
return -ENODEV;
if (!poller_async_active(&card->poller)) {
ret = sound_card_do_beep(card, freq, us);
if (!ret)
poller_call_async(&card->poller, us * 1000ULL,
sound_card_poller_cb, card);
return ret;
}
beep = malloc(sizeof(*beep));
if (!beep)
return -ENOMEM;
beep->freq = freq;
beep->us = us;
list_add_tail(&beep->list, &card->tune);
return 0;
}
int sound_card_beep_wait(struct sound_card *card, unsigned timeout)
{
bool active;
return read_poll_timeout(poller_async_active, active,
!active, timeout, &card->poller);
}
int sound_card_beep_cancel(struct sound_card *card)
{
struct beep *beep, *tmp;
int ret;
if (!card)
return -ENODEV;
poller_async_cancel(&card->poller);
ret = card->beep(card, 0, 0);
list_for_each_entry_safe(beep, tmp, &card->tune, list) {
list_del(&beep->list);
free(beep);
}
return ret;
}
|