21 Dec, 2020

1 commit

  • commit 43d5ca88dfcd35e43010fdd818e067aa9a55f5ba upstream.

    syzbot spotted a potential out-of-bounds shift in the USB-audio format
    parser that receives the arbitrary shift value from the USB
    descriptor.

    Add a range check for avoiding the undefined behavior.

    Reported-by: syzbot+df7dc146ebdd6435eea3@syzkaller.appspotmail.com
    Cc:
    Link: https://lore.kernel.org/r/20201209084552.17109-1-tiwai@suse.de
    Signed-off-by: Takashi Iwai
    Signed-off-by: Greg Kroah-Hartman

    Takashi Iwai
     

20 Oct, 2020

1 commit


15 Jun, 2020

1 commit

  • Like the Line6 devices, the Rode Rodecaster Pro does not support
    UAC2_CS_RANGE and only supports a sample rate of 48 kHz.

    Tested against a Rode Rodecaster Pro.

    Tested-by: Christopher Swenson
    Signed-off-by: Christopher Swenson
    Cc:
    Link: https://lore.kernel.org/r/ebdb9e72-9649-0b5e-b9b9-d757dbf26927@swenson.io
    Signed-off-by: Takashi Iwai

    Christopher Swenson
     

19 Apr, 2020

1 commit

  • Many Focusrite devices supports a limited set of sample rates per
    altsetting. These includes audio interfaces with ADAT ports:
    - Scarlett 18i6, 18i8 1st gen, 18i20 1st gen;
    - Scarlett 18i8 2nd gen, 18i20 2nd gen;
    - Scarlett 18i8 3rd gen, 18i20 3rd gen;
    - Clarett 2Pre USB, 4Pre USB, 8Pre USB.

    Maximum rate is exposed in the last 4 bytes of Format Type descriptor
    which has a non-standard bLength = 10.

    Tested-by: Alexey Skobkin
    Signed-off-by: Alexander Tsoy
    Cc:
    Link: https://lore.kernel.org/r/20200418175815.12211-1-alexander@tsoy.me
    Signed-off-by: Takashi Iwai

    Alexander Tsoy
     

17 Feb, 2020

1 commit


15 Feb, 2020

1 commit

  • This patch adds support for Presonus Studio 1810c, a usb interface
    that's UAC2 compliant with a few quirks and a few extra hw-specific
    controls. I've tested all 3 altsettings and the added switch
    controls and they work as expected.

    More infos on the card:
    https://www.presonus.com/products/Studio-1810c

    Note that this work is based on packet inspection with
    usbmon. I just wanted to get this card to work for using
    it on our open-source radio station:
    https://github.com/UoC-Radio

    v2 address issues reported by Takashi:
    * Properly get/set enum type controls
    * Prevent race condition on switch_get/set
    * Various control naming changes
    * Various coding style fixes

    v3 improve readability of sample rate filtering
    and some other minor changes.

    Signed-off-by: Nick Kossifidis
    Link: https://lore.kernel.org/r/5e47481a.1c69fb81.befb3.8dac@mx.google.com
    Signed-off-by: Takashi Iwai

    Nick Kossifidis
     

13 Feb, 2020

1 commit

  • It should be safe to ignore clock validity check result if the following
    conditions are met:
    - only one single sample rate is supported;
    - the terminal is directly connected to the clock source;
    - the clock type is internal.

    This is to deal with some Denon DJ controllers that always reports that
    clock is invalid.

    Tested-by: Tobias Oszlanyi
    Signed-off-by: Alexander Tsoy
    Cc:
    Link: https://lore.kernel.org/r/20200212235450.697348-1-alexander@tsoy.me
    Signed-off-by: Takashi Iwai

    Alexander Tsoy
     

11 Feb, 2020

1 commit

  • Jabra Evolve 65 headset appears as if supporting lower rates than
    48kHz, but it actually doesn't work but with 48kHz for playback.

    This patch applies a workaround to enforce the 48kHz like LINE6
    devices already did. The workaround is put in a unified helper
    function, set_fixed_rate(), to be called from both places now.

    BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=206149
    Link: https://lore.kernel.org/r/20200211111419.5895-1-tiwai@suse.de
    Signed-off-by: Takashi Iwai

    Takashi Iwai
     

26 Jan, 2020

2 commits


05 Jan, 2020

1 commit


08 Jul, 2019

1 commit

  • …/sound into for-linus

    ASoC: Updates for v5.3

    This is a very big update, mainly thanks to Morimoto-san's refactoring
    work and some fairly large new drivers.

    - Lots more work on moving towards a component based framework from
    Morimoto-san.
    - Support for force disconnecting muxes from Jerome Brunet.
    - New drivers for Cirrus Logic CS47L35, CS47L85 and CS47L90, Conexant
    CX2072X, Realtek RT1011 and RT1308.

    Signed-off-by: Takashi Iwai <tiwai@suse.de>

    Takashi Iwai
     

07 Jul, 2019

1 commit


31 May, 2019

1 commit

  • Based on 1 normalized pattern(s):

    this program is free software you can redistribute it and or modify
    it under the terms of the gnu general public license as published by
    the free software foundation either version 2 of the license or at
    your option any later version this program is distributed in the
    hope that it will be useful but without any warranty without even
    the implied warranty of merchantability or fitness for a particular
    purpose see the gnu general public license for more details you
    should have received a copy of the gnu general public license along
    with this program if not write to the free software foundation inc
    59 temple place suite 330 boston ma 02111 1307 usa

    extracted by the scancode license scanner the SPDX license identifier

    GPL-2.0-or-later

    has been chosen to replace the boilerplate/reference in 1334 file(s).

    Signed-off-by: Thomas Gleixner
    Reviewed-by: Allison Randal
    Reviewed-by: Richard Fontana
    Cc: linux-spdx@vger.kernel.org
    Link: https://lkml.kernel.org/r/20190527070033.113240726@linutronix.de
    Signed-off-by: Greg Kroah-Hartman

    Thomas Gleixner
     

18 Feb, 2019

1 commit


15 Jun, 2018

1 commit

  • Pull sound fixes from Takashi Iwai:
    "Here is a collection of small fixes on top of the previous update.

    All small and obvious fixes. Mostly for usual suspects, USB-audio and
    HD-audio, but a few trivial error handling fixes for misc drivers as
    well"

    * tag 'sound-fix-4.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
    ALSA: usb-audio: Always create the interrupt pipe for the mixer
    ALSA: usb-audio: Add insertion control for UAC3 BADD
    ALSA: usb-audio: Change in connectors control creation interface
    ALSA: usb-audio: Add bi-directional terminal types
    ALSA: lx6464es: add error handling for pci_ioremap_bar
    ALSA: sonicvibes: add error handling for snd_ctl_add
    ALSA: usb-audio: Remove explicitly listed Mytek devices
    ALSA: usb-audio: Generic DSD detection for XMOS-based implementations
    ALSA: usb-audio: Add native DSD support for Mytek DACs
    ALSA: hda/realtek - Add shutup hint
    ALSA: usb-audio: Disable the quirk for Nura headset
    ALSA: hda: add dock and led support for HP ProBook 640 G4
    ALSA: hda: add dock and led support for HP EliteBook 830 G5
    ALSA: emu10k1: add error handling for snd_ctl_add
    ALSA: fm801: add error handling for snd_ctl_add

    Linus Torvalds
     

13 Jun, 2018

2 commits

  • Add new mostly generic code with Mytek VID to support native DSD mode.

    This implementation should be easier to maintain when manufacturers
    release new products.

    Signed-off-by: Jussi Laako
    Signed-off-by: Takashi Iwai

    Jussi Laako
     
  • The kmalloc() function has a 2-factor argument form, kmalloc_array(). This
    patch replaces cases of:

    kmalloc(a * b, gfp)

    with:
    kmalloc_array(a * b, gfp)

    as well as handling cases of:

    kmalloc(a * b * c, gfp)

    with:

    kmalloc(array3_size(a, b, c), gfp)

    as it's slightly less ugly than:

    kmalloc_array(array_size(a, b), c, gfp)

    This does, however, attempt to ignore constant size factors like:

    kmalloc(4 * 1024, gfp)

    though any constants defined via macros get caught up in the conversion.

    Any factors with a sizeof() of "unsigned char", "char", and "u8" were
    dropped, since they're redundant.

    The tools/ directory was manually excluded, since it has its own
    implementation of kmalloc().

    The Coccinelle script used for this was:

    // Fix redundant parens around sizeof().
    @@
    type TYPE;
    expression THING, E;
    @@

    (
    kmalloc(
    - (sizeof(TYPE)) * E
    + sizeof(TYPE) * E
    , ...)
    |
    kmalloc(
    - (sizeof(THING)) * E
    + sizeof(THING) * E
    , ...)
    )

    // Drop single-byte sizes and redundant parens.
    @@
    expression COUNT;
    typedef u8;
    typedef __u8;
    @@

    (
    kmalloc(
    - sizeof(u8) * (COUNT)
    + COUNT
    , ...)
    |
    kmalloc(
    - sizeof(__u8) * (COUNT)
    + COUNT
    , ...)
    |
    kmalloc(
    - sizeof(char) * (COUNT)
    + COUNT
    , ...)
    |
    kmalloc(
    - sizeof(unsigned char) * (COUNT)
    + COUNT
    , ...)
    |
    kmalloc(
    - sizeof(u8) * COUNT
    + COUNT
    , ...)
    |
    kmalloc(
    - sizeof(__u8) * COUNT
    + COUNT
    , ...)
    |
    kmalloc(
    - sizeof(char) * COUNT
    + COUNT
    , ...)
    |
    kmalloc(
    - sizeof(unsigned char) * COUNT
    + COUNT
    , ...)
    )

    // 2-factor product with sizeof(type/expression) and identifier or constant.
    @@
    type TYPE;
    expression THING;
    identifier COUNT_ID;
    constant COUNT_CONST;
    @@

    (
    - kmalloc
    + kmalloc_array
    (
    - sizeof(TYPE) * (COUNT_ID)
    + COUNT_ID, sizeof(TYPE)
    , ...)
    |
    - kmalloc
    + kmalloc_array
    (
    - sizeof(TYPE) * COUNT_ID
    + COUNT_ID, sizeof(TYPE)
    , ...)
    |
    - kmalloc
    + kmalloc_array
    (
    - sizeof(TYPE) * (COUNT_CONST)
    + COUNT_CONST, sizeof(TYPE)
    , ...)
    |
    - kmalloc
    + kmalloc_array
    (
    - sizeof(TYPE) * COUNT_CONST
    + COUNT_CONST, sizeof(TYPE)
    , ...)
    |
    - kmalloc
    + kmalloc_array
    (
    - sizeof(THING) * (COUNT_ID)
    + COUNT_ID, sizeof(THING)
    , ...)
    |
    - kmalloc
    + kmalloc_array
    (
    - sizeof(THING) * COUNT_ID
    + COUNT_ID, sizeof(THING)
    , ...)
    |
    - kmalloc
    + kmalloc_array
    (
    - sizeof(THING) * (COUNT_CONST)
    + COUNT_CONST, sizeof(THING)
    , ...)
    |
    - kmalloc
    + kmalloc_array
    (
    - sizeof(THING) * COUNT_CONST
    + COUNT_CONST, sizeof(THING)
    , ...)
    )

    // 2-factor product, only identifiers.
    @@
    identifier SIZE, COUNT;
    @@

    - kmalloc
    + kmalloc_array
    (
    - SIZE * COUNT
    + COUNT, SIZE
    , ...)

    // 3-factor product with 1 sizeof(type) or sizeof(expression), with
    // redundant parens removed.
    @@
    expression THING;
    identifier STRIDE, COUNT;
    type TYPE;
    @@

    (
    kmalloc(
    - sizeof(TYPE) * (COUNT) * (STRIDE)
    + array3_size(COUNT, STRIDE, sizeof(TYPE))
    , ...)
    |
    kmalloc(
    - sizeof(TYPE) * (COUNT) * STRIDE
    + array3_size(COUNT, STRIDE, sizeof(TYPE))
    , ...)
    |
    kmalloc(
    - sizeof(TYPE) * COUNT * (STRIDE)
    + array3_size(COUNT, STRIDE, sizeof(TYPE))
    , ...)
    |
    kmalloc(
    - sizeof(TYPE) * COUNT * STRIDE
    + array3_size(COUNT, STRIDE, sizeof(TYPE))
    , ...)
    |
    kmalloc(
    - sizeof(THING) * (COUNT) * (STRIDE)
    + array3_size(COUNT, STRIDE, sizeof(THING))
    , ...)
    |
    kmalloc(
    - sizeof(THING) * (COUNT) * STRIDE
    + array3_size(COUNT, STRIDE, sizeof(THING))
    , ...)
    |
    kmalloc(
    - sizeof(THING) * COUNT * (STRIDE)
    + array3_size(COUNT, STRIDE, sizeof(THING))
    , ...)
    |
    kmalloc(
    - sizeof(THING) * COUNT * STRIDE
    + array3_size(COUNT, STRIDE, sizeof(THING))
    , ...)
    )

    // 3-factor product with 2 sizeof(variable), with redundant parens removed.
    @@
    expression THING1, THING2;
    identifier COUNT;
    type TYPE1, TYPE2;
    @@

    (
    kmalloc(
    - sizeof(TYPE1) * sizeof(TYPE2) * COUNT
    + array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
    , ...)
    |
    kmalloc(
    - sizeof(TYPE1) * sizeof(THING2) * (COUNT)
    + array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
    , ...)
    |
    kmalloc(
    - sizeof(THING1) * sizeof(THING2) * COUNT
    + array3_size(COUNT, sizeof(THING1), sizeof(THING2))
    , ...)
    |
    kmalloc(
    - sizeof(THING1) * sizeof(THING2) * (COUNT)
    + array3_size(COUNT, sizeof(THING1), sizeof(THING2))
    , ...)
    |
    kmalloc(
    - sizeof(TYPE1) * sizeof(THING2) * COUNT
    + array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
    , ...)
    |
    kmalloc(
    - sizeof(TYPE1) * sizeof(THING2) * (COUNT)
    + array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
    , ...)
    )

    // 3-factor product, only identifiers, with redundant parens removed.
    @@
    identifier STRIDE, SIZE, COUNT;
    @@

    (
    kmalloc(
    - (COUNT) * STRIDE * SIZE
    + array3_size(COUNT, STRIDE, SIZE)
    , ...)
    |
    kmalloc(
    - COUNT * (STRIDE) * SIZE
    + array3_size(COUNT, STRIDE, SIZE)
    , ...)
    |
    kmalloc(
    - COUNT * STRIDE * (SIZE)
    + array3_size(COUNT, STRIDE, SIZE)
    , ...)
    |
    kmalloc(
    - (COUNT) * (STRIDE) * SIZE
    + array3_size(COUNT, STRIDE, SIZE)
    , ...)
    |
    kmalloc(
    - COUNT * (STRIDE) * (SIZE)
    + array3_size(COUNT, STRIDE, SIZE)
    , ...)
    |
    kmalloc(
    - (COUNT) * STRIDE * (SIZE)
    + array3_size(COUNT, STRIDE, SIZE)
    , ...)
    |
    kmalloc(
    - (COUNT) * (STRIDE) * (SIZE)
    + array3_size(COUNT, STRIDE, SIZE)
    , ...)
    |
    kmalloc(
    - COUNT * STRIDE * SIZE
    + array3_size(COUNT, STRIDE, SIZE)
    , ...)
    )

    // Any remaining multi-factor products, first at least 3-factor products,
    // when they're not all constants...
    @@
    expression E1, E2, E3;
    constant C1, C2, C3;
    @@

    (
    kmalloc(C1 * C2 * C3, ...)
    |
    kmalloc(
    - (E1) * E2 * E3
    + array3_size(E1, E2, E3)
    , ...)
    |
    kmalloc(
    - (E1) * (E2) * E3
    + array3_size(E1, E2, E3)
    , ...)
    |
    kmalloc(
    - (E1) * (E2) * (E3)
    + array3_size(E1, E2, E3)
    , ...)
    |
    kmalloc(
    - E1 * E2 * E3
    + array3_size(E1, E2, E3)
    , ...)
    )

    // And then all remaining 2 factors products when they're not all constants,
    // keeping sizeof() as the second factor argument.
    @@
    expression THING, E1, E2;
    type TYPE;
    constant C1, C2, C3;
    @@

    (
    kmalloc(sizeof(THING) * C2, ...)
    |
    kmalloc(sizeof(TYPE) * C2, ...)
    |
    kmalloc(C1 * C2 * C3, ...)
    |
    kmalloc(C1 * C2, ...)
    |
    - kmalloc
    + kmalloc_array
    (
    - sizeof(TYPE) * (E2)
    + E2, sizeof(TYPE)
    , ...)
    |
    - kmalloc
    + kmalloc_array
    (
    - sizeof(TYPE) * E2
    + E2, sizeof(TYPE)
    , ...)
    |
    - kmalloc
    + kmalloc_array
    (
    - sizeof(THING) * (E2)
    + E2, sizeof(THING)
    , ...)
    |
    - kmalloc
    + kmalloc_array
    (
    - sizeof(THING) * E2
    + E2, sizeof(THING)
    , ...)
    |
    - kmalloc
    + kmalloc_array
    (
    - (E1) * E2
    + E1, E2
    , ...)
    |
    - kmalloc
    + kmalloc_array
    (
    - (E1) * (E2)
    + E1, E2
    , ...)
    |
    - kmalloc
    + kmalloc_array
    (
    - E1 * E2
    + E1, E2
    , ...)
    )

    Signed-off-by: Kees Cook

    Kees Cook
     

29 Mar, 2018

1 commit


21 Mar, 2018

1 commit

  • Recently released USB Audio Class 3.0 specification
    introduces many significant changes comparing to
    previous versions, like
    - new Power Domains, support for LPM/L1
    - new Cluster descriptor
    - changed layout of all class-specific descriptors
    - new High Capability descriptors
    - New class-specific String descriptors
    - new and removed units
    - additional sources for interrupts
    - removed Type II Audio Data Formats
    - ... and many other things (check spec)

    It also provides backward compatibility through
    multiple configurations, as well as requires
    mandatory support for BADD (Basic Audio Device
    Definition) on each ADC3.0 compliant device

    This patch adds initial support of UAC3 specification
    that is enough for Generic I/O Profile (BAOF, BAIF)
    device support from BADD document.

    Signed-off-by: Ruslan Bilovol
    Reviewed-by: Greg Kroah-Hartman
    Signed-off-by: Takashi Iwai

    Ruslan Bilovol
     

22 Aug, 2016

1 commit


21 Apr, 2015

1 commit

  • Roland SC-D70 reports its device class as vendor specific class and
    the quirk QUIRK_AUDIO_FIXED_ENDPOINT was used for audio output.

    In the quirks table the sampling rate was hard-coded to 44100 Hz
    and therefore not worked when the sound module was in 48000 Hz mode.

    In this change the quirk is changed to QUIRK_AUDIO_STANDARD_INTERFACE
    but as the sound module reports incorrect bSubframeSize in its
    descriptors, additional change is made in format.c to detect it and
    to override it (which uses the existing code for Edirol SD-90).

    Tested both when the sound module was in 44100 Hz mode and 48000 Hz
    mode and both audio input and output. MIDI related part of the driver
    is not touched.

    Signed-off-by: Takamichi Horikawa
    Signed-off-by: Takashi Iwai

    Takamichi Horikawa
     

26 Feb, 2014

1 commit

  • Convert with dev_err() and co from snd_printk(), etc.
    As there are too deep indirections (e.g. ep->chip->dev->dev),
    a few new local macros, usb_audio_err() & co, are introduced.

    Also, the device numbers in some messages are dropped, as they are
    shown in the prefix automatically.

    Signed-off-by: Takashi Iwai

    Takashi Iwai
     

14 Jan, 2014

1 commit


28 Jun, 2013

1 commit


29 Apr, 2013

1 commit


18 Apr, 2013

1 commit

  • Unfortunately, none of the UAC standards provides a way to identify DSD
    (Direct Stream Digital) formats. Hence, this patch adds a quirks
    handler to identify USB interfaces that are capable of handling DSD.

    That quirks handler can augment the already parsed formats bit-field,
    by any of the new SNDRV_PCM_FMTBIT_DSD_{U8_U16} and setting the dsd_dop
    flag in the audio format, if the driver should take care for the DOP
    byte stuffing.

    The only devices that are known to work with this are the ones with
    a 'Playback Designs' vendor id.

    Signed-off-by: Daniel Mack
    Signed-off-by: Takashi Iwai

    Daniel Mack
     

04 Apr, 2013

1 commit

  • Move the check that parse_audio_format_rates_v2() do after
    receiving the clock source entity ID directly into the find
    function and add a validation flag to the function.

    This patch does not introduce any logic flow change.

    It is provided to allow introducing automatic clock switching
    easier later. By moving this uac_clock_source_is_valid callsite,
    2 additional callsites can be avoided.

    Signed-off-by: Eldad Zack
    Signed-off-by: Takashi Iwai

    Eldad Zack
     

18 Mar, 2013

2 commits


21 Nov, 2012

1 commit


15 Feb, 2012

1 commit

  • A malicious USB device could feed in a large nr_rates value. This would
    cause the subsequent call to kmemdup() to allocate a smaller buffer than
    expected, leading to out-of-bounds access.

    This patch validates the nr_rates value and reuses the limit introduced
    in commit 4fa0e81b ("ALSA: usb-audio: fix possible hang and overflow
    in parse_uac2_sample_rate_range()").

    Signed-off-by: Xi Wang
    Signed-off-by: Takashi Iwai

    Xi Wang
     

08 Jan, 2012

1 commit

  • A malicious USB device may feed in carefully crafted min/max/res values,
    so that the inner loop in parse_uac2_sample_rate_range() could run for
    a long time or even never terminate, e.g., given max = INT_MAX.

    Also nr_rates could be a large integer, which causes an integer overflow
    in the subsequent call to kmalloc() in parse_audio_format_rates_v2().
    Thus, kmalloc() would allocate a smaller buffer than expected, leading
    to a memory corruption.

    To exploit the two vulnerabilities, an attacker needs physical access
    to the machine to plug in a malicious USB device.

    This patch makes two changes.

    1) The type of "rate" is changed to unsigned int, so that the loop could
    stop once "rate" is larger than INT_MAX.

    2) Limit nr_rates to 1024.

    Suggested-by: Takashi Iwai
    Signed-off-by: Xi Wang
    Signed-off-by: Takashi Iwai

    Xi Wang
     

27 Sep, 2011

1 commit

  • There are certain devices that are reportedly so slow that they need
    more than 100 ms to handle control transfers. Therefore, increase the
    timeout in mixer(_quirks).c to 1000 ms.

    The timeout parameter of snd_usb_ctl_msg() is now constant, so we can
    drop it.

    Reported-by: Felipe Balbi
    Signed-off-by: Clemens Ladisch
    Signed-off-by: Takashi Iwai

    Clemens Ladisch
     

22 May, 2011

1 commit


18 May, 2011

1 commit


29 Apr, 2011

1 commit


10 Jan, 2011

1 commit


04 Sep, 2010

1 commit

  • The Audio Class v2 support code in 2.6.35 added checks for the
    bInterfaceProtocol field. However, there are devices (usually those
    detected by vendor-specific quirks) that do not have one of the
    predefined values in this field, which made the driver reject them.

    To fix this regression, restore the old behaviour, i.e., assume that
    a device with an unknown bInterfaceProtocol field (other than
    UAC_VERSION_2) has more or less UAC-v1-compatible descriptors.

    [compile warning fixes by tiwai]

    Signed-off-by: Clemens Ladisch
    Cc: Daniel Mack
    Cc:
    Signed-off-by: Takashi Iwai

    Clemens Ladisch
     

15 Aug, 2010

1 commit

  • Gcc complains that ret might be used uninitialized:

    sound/usb/format.c: In function ‘snd_usb_parse_audio_format’:
    sound/usb/format.c:354: warning: ‘ret’ may be used uninitialized in this function
    sound/usb/format.c:354: note: ‘ret’ was declared here
    sound/usb/format.c:414: warning: ‘ret’ may be used uninitialized in this function
    sound/usb/format.c:414: note: ‘ret’ was declared here

    I suppose it could be uninitialized if there is ever a UAC_VERSION_3
    released. Anyway this patch is worthwhile if only to silence the gcc
    warning.

    Signed-off-by: Dan Carpenter
    Acked-by: Daniel Mack
    Signed-off-by: Takashi Iwai

    Dan Carpenter