Sound/HID: wiimote: add speaker support
Subsystems (3)
RFC 1/1 Sound/HID: wiimote: add speaker support
Classic Wii Remotes provide a speaker on the device. We can stream PCM data, mute and change volume via special protocol requests and remote audio registers.
The device supports several different formats, but fully understood are only signed 8-bit PCM and something that looks like 4-bit Yamaha ADPCM. Theoretically, we can set data-rates from 183Hz up to 12MHz, but a realistic range for Bluetooth l2cap is 1500-4000 Hz.
Data is streamed as 20bytes blocks and must be sent in a constant rate. There is no way to read the current position. It would be way too slow, anyway.
---
Hi
I'm reworking large parts of the HID Nintendo Wii Remote driver and wanted to add speaker support. I have never worked with the sound subsystem until now and need some help.
The Wii Remote is a Bluetooth gamepad that features a small speaker on the remote. All information was gathered via reverse-engineering so I cannot tell you any specifics about the hardware, sorry. What I figured out so far is how to set up the speaker, stream data, set volume and mute the speaker.
Supported formats are:
signed 8-bit PCM
4-bit Yamaha ADPCM
I implemented only the 8-bit PCM as I couldn't figure out whether the kernel supports the other format?
The wiiproto_* helpers in hid-wiimote-core.c are used to send the requests. Data is streamed as 20-bytes packets and must be sent at a constant rate.
I would really appreciate if someone can have a look at hid-wiimote-speaker.c and help me fill the gaps. I figured out how to write the basic snd_card management and PCM setup, but I am stuck with buffer management now.
I have a function called wiiproto_req_audio() which sends up to 20bytes of PCM data to the device. However, I cannot figure out how to integrate that into the snd_pcm object. The problem is that all other drivers I found have large DMA buffers which are filled whenever an interrupt signals more data. However, I don't have this setup but instead I need a timer (does the sound-core provide that?) which causes the "copy" callback to be called with 20bytes of data at a constant rate.
Any help welcome! And if this whole idea is stupid, please tell me! ;)
Thanks
David
drivers/hid/Kconfig | 3 + drivers/hid/Makefile | 3 + drivers/hid/hid-wiimote-core.c | 54 +++- drivers/hid/hid-wiimote-modules.c | 5 + drivers/hid/hid-wiimote-speaker.c | 539 ++++++++++++++++++++++++++++++++++++++ drivers/hid/hid-wiimote.h | 17 ++ 6 files changed, 619 insertions(+), 2 deletions(-) create mode 100644 drivers/hid/hid-wiimote-speaker.c
drivers/hid/Kconfig +3 -0
@@ -715,6 +715,9 @@ config HID_WIIMOTE the Wii U Gamepad) might be supported in the future. But currently support is limited to Bluetooth based devices. + If Alsa sound support (CONFIG_SND) is enabled, this driver also provides + a sound card interface for Wii Remote speakers. + If unsure, say N. To compile this driver as a module, choose M here: the
drivers/hid/Makefile +3 -0
@@ -32,6 +32,9 @@ hid-wiimote-y := hid-wiimote-core.o hid-wiimote-modules.o ifdef CONFIG_DEBUG_FS hid-wiimote-y += hid-wiimote-debug.o endif +ifdef CONFIG_SND + hid-wiimote-y += hid-wiimote-speaker.o +endif obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o obj-$(CONFIG_HID_ACRUX) += hid-axff.o
drivers/hid/hid-wiimote-core.c +52 -2
90 lines not on this page · raw message
drivers/hid/hid-wiimote-modules.c +5 -0
@@ -2072,6 +2072,11 @@ const struct wiimod_ops *wiimod_table[WIIMOD_NUM] = { [WIIMOD_IR] = &wiimod_ir, [WIIMOD_BUILTIN_MP] = &wiimod_builtin_mp, [WIIMOD_NO_MP ] = &wiimod_no_mp, +#ifdef CONFIG_SND + [WIIMOD_SPEAKER ] = &wiimod_speaker, +#else + [WIIMOD_SPEAKER] = &wiimod_dummy, +#endif };const struct wiimod_ops *wiimod_ext_table[WIIMOTE_EXT_NUM ] = {
drivers/hid/hid-wiimote-speaker.c new file +539 -0
539 lines not on this page · raw message
drivers/hid/hid-wiimote.h +17 -0
@@ -148,6 +148,7 @@ struct wiimote_data {struct timer_list timer;struct wiimote_ext *ext;struct wiimote_debug *debug; +struct wiimote_speaker *speaker;union {struct input_dev *input;
@@ -172,6 +173,7 @@ enum wiimod_module {WIIMOD_IR ,WIIMOD_BUILTIN_MP ,WIIMOD_NO_MP , +WIIMOD_SPEAKER ,WIIMOD_NUM , WIIMOD_NULL = WIIMOD_NUM, };
@@ -208,9 +210,12 @@ enum wiiproto_reqs {WIIPROTO_REQ_LED =0x11 ,WIIPROTO_REQ_DRM =0x12 ,WIIPROTO_REQ_IR1 =0x13 , +WIIPROTO_REQ_SPEAKER =0x14 ,WIIPROTO_REQ_SREQ =0x15 ,WIIPROTO_REQ_WMEM =0x16 ,WIIPROTO_REQ_RMEM =0x17 , +WIIPROTO_REQ_AUDIO =0x18 , +WIIPROTO_REQ_MUTE =0x19 ,WIIPROTO_REQ_IR2 =0x1a ,WIIPROTO_REQ_STATUS =0x20 , WIIPROTO_REQ_DATA = 0x21,
@@ -241,6 +246,12 @@ extern void wiiproto_req_status(struct wiimote_data *wdata);extern void wiiproto_req_accel (struct wiimote_data *wdata,__u8 accel);extern void wiiproto_req_ir1 (struct wiimote_data *wdata,__u8 flags);extern void wiiproto_req_ir2 (struct wiimote_data *wdata,__u8 flags); +extern void wiiproto_req_wmem (struct wiimote_data *wdata,bool eeprom, +__u32 offset,const __u8 *buf,__u8 size); +extern void wiiproto_req_speaker (struct wiimote_data *wdata,bool on); +extern void wiiproto_req_mute (struct wiimote_data *wdata,bool on); +extern int wiiproto_req_audio_user (struct wiimote_data *wdata, +void __user *buf,size_t len);extern int wiimote_cmd_write (struct wiimote_data *wdata,__u32 offset,const __u8 *wmem,__u8 size); extern ssize_t wiimote_cmd_read(struct wiimote_data *wdata, __u32 offset,
@@ -283,6 +294,12 @@ static inline void wiidebug_deinit(void *u) { }#endif +#ifdef CONFIG_SND + +extern const struct wiimod_ops wiimod_speaker; + +#endif +/* requires the state.lock spinlock to be held */ static inline bool wiimote_cmd_pending (struct wiimote_data *wdata,int cmd,__u32 opt)
Signature · 1 line
1.8.2.1