diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-12 12:31:28 +0900 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-12 12:31:28 +0900 |
commit | 2fc07efa2241afe08de136c061b3baa103fb286c (patch) | |
tree | 113b58740841098c3cc363a4069b5ba77549a881 | |
parent | 79360ddd73dfe9a26f49ef4e27b8c26612929b0e (diff) | |
parent | f7f4b2322bf7b8c5929b7eb5a667091f32592580 (diff) |
Merge tag 'sound-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates #2 from Takashi Iwai:
"This update contains a few cleanup works, regression/stable fixes
gathered since the last pull request.
- Clean up with generic hd-audio jack handling code by David
Henningsson
- A few regression fixes for standardized HD-audio auto-parser
- Misc clean-up and small fixes"
* tag 'sound-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
ALSA: hda - do not detect jack on internal speakers for Realtek
ALSA: hda - Fix missing beep on ASUS X43U notebook
ALSA: hda - Remove AZX_DCAPS_POSFIX_COMBO
ALSA: hda - Warn an allocation for an uninitialized array
ALSA: hda/cirrus - Add missing init/free of hda_gen_spec
ALSA: hda - Fix memory leaks at error path in patch_cirrus.c
ALSA: hda - Add missing hda_gen_spec to struct via_spec
ALSA: hda - remove "Mic Jack Mode" for headset jacks (Latitude Exx30)
ALSA: hda - make Cirrus codec use generic unsol event handler
ALSA: hda - make VIA codec use generic unsol event handler
ALSA: hda - Remove dead GPIO code for VIA codec
ALSA: usb-audio: Add TASCAM US122 MKII playback
-rw-r--r-- | sound/pci/hda/hda_codec.c | 2 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.c | 5 | ||||
-rw-r--r-- | sound/pci/hda/patch_cirrus.c | 58 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 3 | ||||
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 27 | ||||
-rw-r--r-- | sound/pci/hda/patch_via.c | 98 | ||||
-rw-r--r-- | sound/usb/quirks-table.h | 46 |
7 files changed, 122 insertions, 117 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index c0ab72cbeed1..70d4848b5cd0 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -5168,6 +5168,8 @@ EXPORT_SYMBOL_HDA(snd_hda_resume); */ void *snd_array_new(struct snd_array *array) { + if (snd_BUG_ON(!array->elem_size)) + return NULL; if (array->used >= array->alloced) { int num = array->alloced + array->alloc_align; int size = (num + 1) * array->elem_size; diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index f09ff6c14041..6833835a218b 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -554,7 +554,6 @@ enum { #define AZX_DCAPS_BUFSIZE (1 << 21) /* no buffer size alignment */ #define AZX_DCAPS_ALIGN_BUFSIZE (1 << 22) /* buffer size alignment */ #define AZX_DCAPS_4K_BDLE_BOUNDARY (1 << 23) /* BDLE in 4k boundary */ -#define AZX_DCAPS_POSFIX_COMBO (1 << 24) /* Use COMBO as default */ #define AZX_DCAPS_COUNT_LPIB_DELAY (1 << 25) /* Take LPIB as delay */ /* quirks for ATI SB / AMD Hudson */ @@ -2858,10 +2857,6 @@ static int __devinit check_position_fix(struct azx *chip, int fix) snd_printd(SFX "Using LPIB position fix\n"); return POS_FIX_LPIB; } - if (chip->driver_caps & AZX_DCAPS_POSFIX_COMBO) { - snd_printd(SFX "Using COMBO position fix\n"); - return POS_FIX_COMBO; - } return POS_FIX_AUTO; } diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index fcfc9f0a056b..61a71131711c 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -897,7 +897,7 @@ static int build_digital_input(struct hda_codec *codec) * HP/SPK/SPDIF */ -static void cs_automute(struct hda_codec *codec) +static void cs_automute(struct hda_codec *codec, struct hda_jack_tbl *tbl) { struct cs_spec *spec = codec->spec; struct auto_pin_cfg *cfg = &spec->autocfg; @@ -973,7 +973,7 @@ static void cs_automute(struct hda_codec *codec) * Switch max 3 inputs of a single ADC (nid 3) */ -static void cs_automic(struct hda_codec *codec) +static void cs_automic(struct hda_codec *codec, struct hda_jack_tbl *tbl) { struct cs_spec *spec = codec->spec; struct auto_pin_cfg *cfg = &spec->autocfg; @@ -1035,7 +1035,7 @@ static void init_output(struct hda_codec *codec) if (!cfg->speaker_outs) continue; if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) { - snd_hda_jack_detect_enable(codec, nid, HP_EVENT); + snd_hda_jack_detect_enable_callback(codec, nid, HP_EVENT, cs_automute); spec->hp_detect = 1; } } @@ -1046,7 +1046,7 @@ static void init_output(struct hda_codec *codec) /* SPDIF is enabled on presence detect for CS421x */ if (spec->hp_detect || spec->spdif_detect) - cs_automute(codec); + cs_automute(codec, NULL); } static void init_input(struct hda_codec *codec) @@ -1070,13 +1070,13 @@ static void init_input(struct hda_codec *codec) AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(spec->adc_idx[i])); if (spec->mic_detect && spec->automic_idx == i) - snd_hda_jack_detect_enable(codec, pin, MIC_EVENT); + snd_hda_jack_detect_enable_callback(codec, pin, MIC_EVENT, cs_automic); } /* CS420x has multiple ADC, CS421x has single ADC */ if (spec->vendor_nid == CS420X_VENDOR_NID) { change_cur_input(codec, spec->cur_input, 1); if (spec->mic_detect) - cs_automic(codec); + cs_automic(codec, NULL); coef = 0x000a; /* ADC1/2 - Digital and Analog Soft Ramp */ if (is_active_pin(codec, CS_DMIC2_PIN_NID)) @@ -1089,7 +1089,7 @@ static void init_input(struct hda_codec *codec) cs_vendor_coef_set(codec, IDX_ADC_CFG, coef); } else { if (spec->mic_detect) - cs_automic(codec); + cs_automic(codec, NULL); else { spec->cur_adc = spec->adc_nid[spec->cur_input]; cs_update_input_select(codec); @@ -1243,28 +1243,16 @@ static void cs_free(struct hda_codec *codec) struct cs_spec *spec = codec->spec; kfree(spec->capture_bind[0]); kfree(spec->capture_bind[1]); + snd_hda_gen_free(&spec->gen); kfree(codec->spec); } -static void cs_unsol_event(struct hda_codec *codec, unsigned int res) -{ - switch (snd_hda_jack_get_action(codec, res >> 26)) { - case HP_EVENT: - cs_automute(codec); - break; - case MIC_EVENT: - cs_automic(codec); - break; - } - snd_hda_jack_report_sync(codec); -} - static const struct hda_codec_ops cs_patch_ops = { .build_controls = cs_build_controls, .build_pcms = cs_build_pcms, .init = cs_init, .free = cs_free, - .unsol_event = cs_unsol_event, + .unsol_event = snd_hda_jack_unsol_event, }; static int cs_parse_auto_config(struct hda_codec *codec) @@ -1439,6 +1427,7 @@ static int patch_cs420x(struct hda_codec *codec) if (!spec) return -ENOMEM; codec->spec = spec; + snd_hda_gen_init(&spec->gen); spec->vendor_nid = CS420X_VENDOR_NID; @@ -1457,7 +1446,7 @@ static int patch_cs420x(struct hda_codec *codec) return 0; error: - kfree(codec->spec); + cs_free(codec); codec->spec = NULL; return err; } @@ -1674,7 +1663,7 @@ static void init_cs421x_digital(struct hda_codec *codec) if (!cfg->speaker_outs) continue; if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) { - snd_hda_jack_detect_enable(codec, nid, SPDIF_EVENT); + snd_hda_jack_detect_enable_callback(codec, nid, SPDIF_EVENT, cs_automute); spec->spdif_detect = 1; } } @@ -1889,21 +1878,6 @@ static int cs421x_build_controls(struct hda_codec *codec) return 0; } -static void cs421x_unsol_event(struct hda_codec *codec, unsigned int res) -{ - switch (snd_hda_jack_get_action(codec, res >> 26)) { - case HP_EVENT: - case SPDIF_EVENT: - cs_automute(codec); - break; - - case MIC_EVENT: - cs_automic(codec); - break; - } - snd_hda_jack_report_sync(codec); -} - static int parse_cs421x_input(struct hda_codec *codec) { struct cs_spec *spec = codec->spec; @@ -1977,7 +1951,7 @@ static struct hda_codec_ops cs421x_patch_ops = { .build_pcms = cs_build_pcms, .init = cs421x_init, .free = cs_free, - .unsol_event = cs421x_unsol_event, + .unsol_event = snd_hda_jack_unsol_event, #ifdef CONFIG_PM .suspend = cs421x_suspend, #endif @@ -1992,6 +1966,7 @@ static int patch_cs4210(struct hda_codec *codec) if (!spec) return -ENOMEM; codec->spec = spec; + snd_hda_gen_init(&spec->gen); spec->vendor_nid = CS4210_VENDOR_NID; @@ -2017,7 +1992,7 @@ static int patch_cs4210(struct hda_codec *codec) return 0; error: - kfree(codec->spec); + cs_free(codec); codec->spec = NULL; return err; } @@ -2031,6 +2006,7 @@ static int patch_cs4213(struct hda_codec *codec) if (!spec) return -ENOMEM; codec->spec = spec; + snd_hda_gen_init(&spec->gen); spec->vendor_nid = CS4213_VENDOR_NID; @@ -2042,7 +2018,7 @@ static int patch_cs4213(struct hda_codec *codec) return 0; error: - kfree(codec->spec); + cs_free(codec); codec->spec = NULL; return err; } diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 8568aee56e2d..8253b4eeb6a1 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -611,6 +611,8 @@ static void alc_line_automute(struct hda_codec *codec, struct hda_jack_tbl *jack { struct alc_spec *spec = codec->spec; + if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT) + return; /* check LO jack only when it's different from HP */ if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0]) return; @@ -4245,6 +4247,7 @@ static void alc_auto_init_std(struct hda_codec *codec) ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir)) static const struct snd_pci_quirk beep_white_list[] = { + SND_PCI_QUIRK(0x1043, 0x103c, "ASUS", 1), SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1), SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1), SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1), diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index fe163547f906..770013ff556f 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -104,6 +104,7 @@ enum { STAC_92HD83XXX_HP_LED, STAC_92HD83XXX_HP_INV_LED, STAC_92HD83XXX_HP_MIC_LED, + STAC_92HD83XXX_HEADSET_JACK, STAC_92HD83XXX_MODELS }; @@ -204,6 +205,7 @@ struct sigmatel_spec { unsigned int check_volume_offset:1; unsigned int auto_mic:1; unsigned int linear_tone_beep:1; + unsigned int headset_jack:1; /* 4-pin headset jack (hp + mono mic) */ /* gpio lines */ unsigned int eapd_mask; @@ -1684,6 +1686,7 @@ static const char * const stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = { [STAC_92HD83XXX_HP_LED] = "hp-led", [STAC_92HD83XXX_HP_INV_LED] = "hp-inv-led", [STAC_92HD83XXX_HP_MIC_LED] = "hp-mic-led", + [STAC_92HD83XXX_HEADSET_JACK] = "headset-jack", }; static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { @@ -1694,6 +1697,24 @@ static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { "DFI LanParty", STAC_92HD83XXX_REF), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ba, "unknown Dell", STAC_DELL_S14), + SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0532, + "Dell Latitude E6230", STAC_92HD83XXX_HEADSET_JACK), + SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0533, + "Dell Latitude E6330", STAC_92HD83XXX_HEADSET_JACK), + SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0534, + "Dell Latitude E6430", STAC_92HD83XXX_HEADSET_JACK), + SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0535, + "Dell Latitude E6530", STAC_92HD83XXX_HEADSET_JACK), + SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x053c, + "Dell Latitude E5430", STAC_92HD83XXX_HEADSET_JACK), + SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x053d, + "Dell Latitude E5530", STAC_92HD83XXX_HEADSET_JACK), + SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0549, + "Dell Latitude E5430", STAC_92HD83XXX_HEADSET_JACK), + SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x057d, + "Dell Latitude E6430s", STAC_92HD83XXX_HEADSET_JACK), + SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0584, + "Dell Latitude E6430U", STAC_92HD83XXX_HEADSET_JACK), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x1028, "Dell Vostro 3500", STAC_DELL_VOSTRO_3500), SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1656, @@ -2855,6 +2876,9 @@ static inline int stac92xx_add_jack_mode_control(struct hda_codec *codec, char name[22]; if (snd_hda_get_input_pin_attr(def_conf) != INPUT_PIN_ATTR_INT) { + if (spec->headset_jack && snd_hda_get_input_pin_attr(def_conf) + != INPUT_PIN_ATTR_DOCK) + return 0; if (snd_hda_get_default_vref(codec, nid) == AC_PINCTL_VREF_GRD && nid == spec->line_switch) control = STAC_CTL_WIDGET_IO_SWITCH; @@ -5626,6 +5650,9 @@ again: case STAC_92HD83XXX_HP_MIC_LED: spec->mic_mute_led_gpio = 0x08; /* GPIO3 */ break; + case STAC_92HD83XXX_HEADSET_JACK: + spec->headset_jack = 1; + break; } if (find_mute_led_cfg(codec, default_polarity)) diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 5a45a912aedc..72a2f60b087c 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -118,6 +118,8 @@ enum { }; struct via_spec { + struct hda_gen_spec gen; + /* codec parameterization */ const struct snd_kcontrol_new *mixers[6]; unsigned int num_mixers; @@ -246,6 +248,7 @@ static struct via_spec * via_new_spec(struct hda_codec *codec) /* VT1708BCE & VT1708S are almost same */ if (spec->codec_type == VT1708BCE) spec->codec_type = VT1708S; + snd_hda_gen_init(&spec->gen); return spec; } @@ -299,7 +302,6 @@ static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec) #define VIA_JACK_EVENT 0x20 #define VIA_HP_EVENT 0x01 -#define VIA_GPIO_EVENT 0x02 #define VIA_LINE_EVENT 0x03 enum { @@ -1628,6 +1630,7 @@ static void via_free(struct hda_codec *codec) vt1708_stop_hp_work(spec); kfree(spec->bind_cap_vol); kfree(spec->bind_cap_sw); + snd_hda_gen_free(&spec->gen); kfree(spec); } @@ -1685,69 +1688,6 @@ static void via_hp_automute(struct hda_codec *codec) via_line_automute(codec, present); } -static void via_gpio_control(struct hda_codec *codec) -{ - unsigned int gpio_data; - unsigned int vol_counter; - unsigned int vol; - unsigned int master_vol; - - struct via_spec *spec = codec->spec; - - gpio_data = snd_hda_codec_read(codec, codec->afg, 0, - AC_VERB_GET_GPIO_DATA, 0) & 0x03; - - vol_counter = (snd_hda_codec_read(codec, codec->afg, 0, - 0xF84, 0) & 0x3F0000) >> 16; - - vol = vol_counter & 0x1F; - master_vol = snd_hda_codec_read(codec, 0x1A, 0, - AC_VERB_GET_AMP_GAIN_MUTE, - AC_AMP_GET_INPUT); - - if (gpio_data == 0x02) { - /* unmute line out */ - snd_hda_set_pin_ctl(codec, spec->autocfg.line_out_pins[0], - PIN_OUT); - if (vol_counter & 0x20) { - /* decrease volume */ - if (vol > master_vol) - vol = master_vol; - snd_hda_codec_amp_stereo(codec, 0x1A, HDA_INPUT, - 0, HDA_AMP_VOLMASK, - master_vol-vol); - } else { - /* increase volume */ - snd_hda_codec_amp_stereo(codec, 0x1A, HDA_INPUT, 0, - HDA_AMP_VOLMASK, - ((master_vol+vol) > 0x2A) ? 0x2A : - (master_vol+vol)); - } - } else if (!(gpio_data & 0x02)) { - /* mute line out */ - snd_hda_set_pin_ctl(codec, spec->autocfg.line_out_pins[0], 0); - } -} - -/* unsolicited event for jack sensing */ -static void via_unsol_event(struct hda_codec *codec, - unsigned int res) -{ - res >>= 26; - res = snd_hda_jack_get_action(codec, res); - - if (res & VIA_JACK_EVENT) - set_widgets_power_state(codec); - - res &= ~VIA_JACK_EVENT; - - if (res == VIA_HP_EVENT || res == VIA_LINE_EVENT) - via_hp_automute(codec); - else if (res == VIA_GPIO_EVENT) - via_gpio_control(codec); - snd_hda_jack_report_sync(codec); -} - #ifdef CONFIG_PM static int via_suspend(struct hda_codec *codec) { @@ -1783,7 +1723,7 @@ static const struct hda_codec_ops via_patch_ops = { .build_pcms = via_build_pcms, .init = via_init, .free = via_free, - .unsol_event = via_unsol_event, + .unsol_event = snd_hda_jack_unsol_event, #ifdef CONFIG_PM .suspend = via_suspend, .check_power_status = via_check_power_status, @@ -2761,6 +2701,17 @@ static void via_auto_init_dig_in(struct hda_codec *codec) snd_hda_set_pin_ctl(codec, spec->autocfg.dig_in_pin, PIN_IN); } +static void via_jack_output_event(struct hda_codec *codec, struct hda_jack_tbl *tbl) +{ + set_widgets_power_state(codec); + via_hp_automute(codec); +} + +static void via_jack_powerstate_event(struct hda_codec *codec, struct hda_jack_tbl *tbl) +{ + set_widgets_power_state(codec); +} + /* initialize the unsolicited events */ static void via_auto_init_unsol_event(struct hda_codec *codec) { @@ -2768,26 +2719,31 @@ static void via_auto_init_unsol_event(struct hda_codec *codec) struct auto_pin_cfg *cfg = &spec->autocfg; unsigned int ev; int i; + hda_jack_callback cb; if (cfg->hp_pins[0] && is_jack_detectable(codec, cfg->hp_pins[0])) - snd_hda_jack_detect_enable(codec, cfg->hp_pins[0], - VIA_HP_EVENT | VIA_JACK_EVENT); + snd_hda_jack_detect_enable_callback(codec, cfg->hp_pins[0], + VIA_HP_EVENT | VIA_JACK_EVENT, + via_jack_output_event); if (cfg->speaker_pins[0]) ev = VIA_LINE_EVENT; else ev = 0; + cb = ev ? via_jack_output_event : via_jack_powerstate_event; + for (i = 0; i < cfg->line_outs; i++) { if (cfg->line_out_pins[i] && is_jack_detectable(codec, cfg->line_out_pins[i])) - snd_hda_jack_detect_enable(codec, cfg->line_out_pins[i], - ev | VIA_JACK_EVENT); + snd_hda_jack_detect_enable_callback(codec, cfg->line_out_pins[i], + ev | VIA_JACK_EVENT, cb); } for (i = 0; i < cfg->num_inputs; i++) { if (is_jack_detectable(codec, cfg->inputs[i].pin)) - snd_hda_jack_detect_enable(codec, cfg->inputs[i].pin, - VIA_JACK_EVENT); + snd_hda_jack_detect_enable_callback(codec, cfg->inputs[i].pin, + VIA_JACK_EVENT, + via_jack_powerstate_event); } } diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index d73ac9bc4272..88d8cebbb244 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -2780,6 +2780,52 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, +{ + /* Tascam US122 MKII - playback-only support */ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = 0x0644, + .idProduct = 0x8021, + .bInterfaceClass = USB_CLASS_AUDIO, + .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + .vendor_name = "TASCAM", + .product_name = "US122 MKII", + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_COMPOSITE, + .data = (const struct snd_usb_audio_quirk[]) { + { + .ifnum = 0, + .type = QUIRK_IGNORE_INTERFACE + }, + { + .ifnum = 1, + .type = QUIRK_AUDIO_FIXED_ENDPOINT, + .data = &(const struct audioformat) { + .formats = SNDRV_PCM_FMTBIT_S24_3LE, + .channels = 2, + .iface = 1, + .altsetting = 1, + .altset_idx = 1, + .attributes = UAC_EP_CS_ATTR_SAMPLE_RATE, + .endpoint = 0x02, + .ep_attr = USB_ENDPOINT_XFER_ISOC, + .rates = SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_88200 | + SNDRV_PCM_RATE_96000, + .rate_min = 44100, + .rate_max = 96000, + .nr_rates = 4, + .rate_table = (unsigned int[]) { + 44100, 48000, 88200, 96000 + } + } + }, + { + .ifnum = -1 + } + } + } +}, /* Microsoft XboxLive Headset/Xbox Communicator */ { |