Commit 20406f9b67e6fde4fff4639225c7a0e5ea6eaa9b
Exists in
master
and in
20 other branches
Merge branch 'topic/jack' into for-linus
Showing 2 changed files Side-by-side Diff
include/sound/jack.h
... | ... | @@ -42,6 +42,11 @@ |
42 | 42 | SND_JACK_MECHANICAL = 0x0008, /* If detected separately */ |
43 | 43 | SND_JACK_VIDEOOUT = 0x0010, |
44 | 44 | SND_JACK_AVOUT = SND_JACK_LINEOUT | SND_JACK_VIDEOOUT, |
45 | + | |
46 | + /* Kept separate from switches to facilitate implementation */ | |
47 | + SND_JACK_BTN_0 = 0x4000, | |
48 | + SND_JACK_BTN_1 = 0x2000, | |
49 | + SND_JACK_BTN_2 = 0x1000, | |
45 | 50 | }; |
46 | 51 | |
47 | 52 | struct snd_jack { |
... | ... | @@ -50,6 +55,7 @@ |
50 | 55 | int type; |
51 | 56 | const char *id; |
52 | 57 | char name[100]; |
58 | + unsigned int key[3]; /* Keep in sync with definitions above */ | |
53 | 59 | void *private_data; |
54 | 60 | void (*private_free)(struct snd_jack *); |
55 | 61 | }; |
... | ... | @@ -59,6 +65,8 @@ |
59 | 65 | int snd_jack_new(struct snd_card *card, const char *id, int type, |
60 | 66 | struct snd_jack **jack); |
61 | 67 | void snd_jack_set_parent(struct snd_jack *jack, struct device *parent); |
68 | +int snd_jack_set_key(struct snd_jack *jack, enum snd_jack_types type, | |
69 | + int keytype); | |
62 | 70 | |
63 | 71 | void snd_jack_report(struct snd_jack *jack, int status); |
64 | 72 |
sound/core/jack.c
... | ... | @@ -24,7 +24,7 @@ |
24 | 24 | #include <sound/jack.h> |
25 | 25 | #include <sound/core.h> |
26 | 26 | |
27 | -static int jack_types[] = { | |
27 | +static int jack_switch_types[] = { | |
28 | 28 | SW_HEADPHONE_INSERT, |
29 | 29 | SW_MICROPHONE_INSERT, |
30 | 30 | SW_LINEOUT_INSERT, |
... | ... | @@ -56,7 +56,7 @@ |
56 | 56 | { |
57 | 57 | struct snd_jack *jack = device->device_data; |
58 | 58 | struct snd_card *card = device->card; |
59 | - int err; | |
59 | + int err, i; | |
60 | 60 | |
61 | 61 | snprintf(jack->name, sizeof(jack->name), "%s %s", |
62 | 62 | card->shortname, jack->id); |
... | ... | @@ -66,6 +66,19 @@ |
66 | 66 | if (!jack->input_dev->dev.parent) |
67 | 67 | jack->input_dev->dev.parent = snd_card_get_device_link(card); |
68 | 68 | |
69 | + /* Add capabilities for any keys that are enabled */ | |
70 | + for (i = 0; i < ARRAY_SIZE(jack->key); i++) { | |
71 | + int testbit = SND_JACK_BTN_0 >> i; | |
72 | + | |
73 | + if (!(jack->type & testbit)) | |
74 | + continue; | |
75 | + | |
76 | + if (!jack->key[i]) | |
77 | + jack->key[i] = BTN_0 + i; | |
78 | + | |
79 | + input_set_capability(jack->input_dev, EV_KEY, jack->key[i]); | |
80 | + } | |
81 | + | |
69 | 82 | err = input_register_device(jack->input_dev); |
70 | 83 | if (err == 0) |
71 | 84 | jack->registered = 1; |
72 | 85 | |
... | ... | @@ -113,10 +126,10 @@ |
113 | 126 | |
114 | 127 | jack->type = type; |
115 | 128 | |
116 | - for (i = 0; i < ARRAY_SIZE(jack_types); i++) | |
129 | + for (i = 0; i < ARRAY_SIZE(jack_switch_types); i++) | |
117 | 130 | if (type & (1 << i)) |
118 | 131 | input_set_capability(jack->input_dev, EV_SW, |
119 | - jack_types[i]); | |
132 | + jack_switch_types[i]); | |
120 | 133 | |
121 | 134 | err = snd_device_new(card, SNDRV_DEV_JACK, jack, &ops); |
122 | 135 | if (err < 0) |
... | ... | @@ -152,6 +165,43 @@ |
152 | 165 | EXPORT_SYMBOL(snd_jack_set_parent); |
153 | 166 | |
154 | 167 | /** |
168 | + * snd_jack_set_key - Set a key mapping on a jack | |
169 | + * | |
170 | + * @jack: The jack to configure | |
171 | + * @type: Jack report type for this key | |
172 | + * @keytype: Input layer key type to be reported | |
173 | + * | |
174 | + * Map a SND_JACK_BTN_ button type to an input layer key, allowing | |
175 | + * reporting of keys on accessories via the jack abstraction. If no | |
176 | + * mapping is provided but keys are enabled in the jack type then | |
177 | + * BTN_n numeric buttons will be reported. | |
178 | + * | |
179 | + * Note that this is intended to be use by simple devices with small | |
180 | + * numbers of keys that can be reported. It is also possible to | |
181 | + * access the input device directly - devices with complex input | |
182 | + * capabilities on accessories should consider doing this rather than | |
183 | + * using this abstraction. | |
184 | + * | |
185 | + * This function may only be called prior to registration of the jack. | |
186 | + */ | |
187 | +int snd_jack_set_key(struct snd_jack *jack, enum snd_jack_types type, | |
188 | + int keytype) | |
189 | +{ | |
190 | + int key = fls(SND_JACK_BTN_0) - fls(type); | |
191 | + | |
192 | + WARN_ON(jack->registered); | |
193 | + | |
194 | + if (!keytype || key >= ARRAY_SIZE(jack->key)) | |
195 | + return -EINVAL; | |
196 | + | |
197 | + jack->type |= type; | |
198 | + jack->key[key] = keytype; | |
199 | + | |
200 | + return 0; | |
201 | +} | |
202 | +EXPORT_SYMBOL(snd_jack_set_key); | |
203 | + | |
204 | +/** | |
155 | 205 | * snd_jack_report - Report the current status of a jack |
156 | 206 | * |
157 | 207 | * @jack: The jack to report status for |
158 | 208 | |
... | ... | @@ -164,10 +214,19 @@ |
164 | 214 | if (!jack) |
165 | 215 | return; |
166 | 216 | |
167 | - for (i = 0; i < ARRAY_SIZE(jack_types); i++) { | |
217 | + for (i = 0; i < ARRAY_SIZE(jack->key); i++) { | |
218 | + int testbit = SND_JACK_BTN_0 >> i; | |
219 | + | |
220 | + if (jack->type & testbit) | |
221 | + input_report_key(jack->input_dev, jack->key[i], | |
222 | + status & testbit); | |
223 | + } | |
224 | + | |
225 | + for (i = 0; i < ARRAY_SIZE(jack_switch_types); i++) { | |
168 | 226 | int testbit = 1 << i; |
169 | 227 | if (jack->type & testbit) |
170 | - input_report_switch(jack->input_dev, jack_types[i], | |
228 | + input_report_switch(jack->input_dev, | |
229 | + jack_switch_types[i], | |
171 | 230 | status & testbit); |
172 | 231 | } |
173 | 232 |