Annotation of qemu/hw/usb/dev-audio.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * QEMU USB audio device
                      3:  *
                      4:  * written by:
                      5:  *  H. Peter Anvin <[email protected]>
                      6:  *  Gerd Hoffmann <[email protected]>
                      7:  *
                      8:  * lousely based on usb net device code which is:
                      9:  *
                     10:  * Copyright (c) 2006 Thomas Sailer
                     11:  * Copyright (c) 2008 Andrzej Zaborowski
                     12:  *
                     13:  * Permission is hereby granted, free of charge, to any person obtaining a copy
                     14:  * of this software and associated documentation files (the "Software"), to deal
                     15:  * in the Software without restriction, including without limitation the rights
                     16:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     17:  * copies of the Software, and to permit persons to whom the Software is
                     18:  * furnished to do so, subject to the following conditions:
                     19:  *
                     20:  * The above copyright notice and this permission notice shall be included in
                     21:  * all copies or substantial portions of the Software.
                     22:  *
                     23:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     24:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     25:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
                     26:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     27:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     28:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     29:  * THE SOFTWARE.
                     30:  */
                     31: 
                     32: #include "qemu-common.h"
                     33: #include "hw/usb.h"
                     34: #include "hw/usb/desc.h"
                     35: #include "hw/hw.h"
                     36: #include "hw/audiodev.h"
                     37: #include "audio/audio.h"
                     38: 
                     39: #define USBAUDIO_VENDOR_NUM     0x46f4 /* CRC16() of "QEMU" */
                     40: #define USBAUDIO_PRODUCT_NUM    0x0002
                     41: 
                     42: #define DEV_CONFIG_VALUE        1 /* The one and only */
                     43: 
                     44: /* Descriptor subtypes for AC interfaces */
                     45: #define DST_AC_HEADER           1
                     46: #define DST_AC_INPUT_TERMINAL   2
                     47: #define DST_AC_OUTPUT_TERMINAL  3
                     48: #define DST_AC_FEATURE_UNIT     6
                     49: /* Descriptor subtypes for AS interfaces */
                     50: #define DST_AS_GENERAL          1
                     51: #define DST_AS_FORMAT_TYPE      2
                     52: /* Descriptor subtypes for endpoints */
                     53: #define DST_EP_GENERAL          1
                     54: 
                     55: enum usb_audio_strings {
                     56:     STRING_NULL,
                     57:     STRING_MANUFACTURER,
                     58:     STRING_PRODUCT,
                     59:     STRING_SERIALNUMBER,
                     60:     STRING_CONFIG,
                     61:     STRING_USBAUDIO_CONTROL,
                     62:     STRING_INPUT_TERMINAL,
                     63:     STRING_FEATURE_UNIT,
                     64:     STRING_OUTPUT_TERMINAL,
                     65:     STRING_NULL_STREAM,
                     66:     STRING_REAL_STREAM,
                     67: };
                     68: 
                     69: static const USBDescStrings usb_audio_stringtable = {
                     70:     [STRING_MANUFACTURER]       = "QEMU",
                     71:     [STRING_PRODUCT]            = "QEMU USB Audio",
                     72:     [STRING_SERIALNUMBER]       = "1",
                     73:     [STRING_CONFIG]             = "Audio Configuration",
                     74:     [STRING_USBAUDIO_CONTROL]   = "Audio Device",
                     75:     [STRING_INPUT_TERMINAL]     = "Audio Output Pipe",
                     76:     [STRING_FEATURE_UNIT]       = "Audio Output Volume Control",
                     77:     [STRING_OUTPUT_TERMINAL]    = "Audio Output Terminal",
                     78:     [STRING_NULL_STREAM]        = "Audio Output - Disabled",
                     79:     [STRING_REAL_STREAM]        = "Audio Output - 48 kHz Stereo",
                     80: };
                     81: 
                     82: #define U16(x) ((x) & 0xff), (((x) >> 8) & 0xff)
                     83: #define U24(x) U16(x), (((x) >> 16) & 0xff)
                     84: #define U32(x) U24(x), (((x) >> 24) & 0xff)
                     85: 
                     86: /*
                     87:  * A Basic Audio Device uses these specific values
                     88:  */
                     89: #define USBAUDIO_PACKET_SIZE     192
                     90: #define USBAUDIO_SAMPLE_RATE     48000
                     91: #define USBAUDIO_PACKET_INTERVAL 1
                     92: 
                     93: static const USBDescIface desc_iface[] = {
                     94:     {
                     95:         .bInterfaceNumber              = 0,
                     96:         .bNumEndpoints                 = 0,
                     97:         .bInterfaceClass               = USB_CLASS_AUDIO,
                     98:         .bInterfaceSubClass            = USB_SUBCLASS_AUDIO_CONTROL,
                     99:         .bInterfaceProtocol            = 0x04,
                    100:         .iInterface                    = STRING_USBAUDIO_CONTROL,
                    101:         .ndesc                         = 4,
                    102:         .descs = (USBDescOther[]) {
                    103:             {
                    104:                 /* Headphone Class-Specific AC Interface Header Descriptor */
                    105:                 .data = (uint8_t[]) {
                    106:                     0x09,                       /*  u8  bLength */
                    107:                     USB_DT_CS_INTERFACE,        /*  u8  bDescriptorType */
                    108:                     DST_AC_HEADER,              /*  u8  bDescriptorSubtype */
                    109:                     U16(0x0100),                /* u16  bcdADC */
                    110:                     U16(0x2b),                  /* u16  wTotalLength */
                    111:                     0x01,                       /*  u8  bInCollection */
                    112:                     0x01,                       /*  u8  baInterfaceNr */
                    113:                 }
                    114:             },{
                    115:                 /* Generic Stereo Input Terminal ID1 Descriptor */
                    116:                 .data = (uint8_t[]) {
                    117:                     0x0c,                       /*  u8  bLength */
                    118:                     USB_DT_CS_INTERFACE,        /*  u8  bDescriptorType */
                    119:                     DST_AC_INPUT_TERMINAL,      /*  u8  bDescriptorSubtype */
                    120:                     0x01,                       /*  u8  bTerminalID */
                    121:                     U16(0x0101),                /* u16  wTerminalType */
                    122:                     0x00,                       /*  u8  bAssocTerminal */
                    123:                     0x02,                       /* u16  bNrChannels */
                    124:                     U16(0x0003),                /* u16  wChannelConfig */
                    125:                     0x00,                       /*  u8  iChannelNames */
                    126:                     STRING_INPUT_TERMINAL,      /*  u8  iTerminal */
                    127:                 }
                    128:             },{
                    129:                 /* Generic Stereo Feature Unit ID2 Descriptor */
                    130:                 .data = (uint8_t[]) {
                    131:                     0x0d,                       /*  u8  bLength */
                    132:                     USB_DT_CS_INTERFACE,        /*  u8  bDescriptorType */
                    133:                     DST_AC_FEATURE_UNIT,        /*  u8  bDescriptorSubtype */
                    134:                     0x02,                       /*  u8  bUnitID */
                    135:                     0x01,                       /*  u8  bSourceID */
                    136:                     0x02,                       /*  u8  bControlSize */
                    137:                     U16(0x0001),                /* u16  bmaControls(0) */
                    138:                     U16(0x0002),                /* u16  bmaControls(1) */
                    139:                     U16(0x0002),                /* u16  bmaControls(2) */
                    140:                     STRING_FEATURE_UNIT,        /*  u8  iFeature */
                    141:                 }
                    142:             },{
                    143:                 /* Headphone Ouptut Terminal ID3 Descriptor */
                    144:                 .data = (uint8_t[]) {
                    145:                     0x09,                       /*  u8  bLength */
                    146:                     USB_DT_CS_INTERFACE,        /*  u8  bDescriptorType */
                    147:                     DST_AC_OUTPUT_TERMINAL,     /*  u8  bDescriptorSubtype */
                    148:                     0x03,                       /*  u8  bUnitID */
                    149:                     U16(0x0301),                /* u16  wTerminalType (SPK) */
                    150:                     0x00,                       /*  u8  bAssocTerminal */
                    151:                     0x02,                       /*  u8  bSourceID */
                    152:                     STRING_OUTPUT_TERMINAL,     /*  u8  iTerminal */
                    153:                 }
                    154:             }
                    155:         },
                    156:     },{
                    157:         .bInterfaceNumber              = 1,
                    158:         .bAlternateSetting             = 0,
                    159:         .bNumEndpoints                 = 0,
                    160:         .bInterfaceClass               = USB_CLASS_AUDIO,
                    161:         .bInterfaceSubClass            = USB_SUBCLASS_AUDIO_STREAMING,
                    162:         .iInterface                    = STRING_NULL_STREAM,
                    163:     },{
                    164:         .bInterfaceNumber              = 1,
                    165:         .bAlternateSetting             = 1,
                    166:         .bNumEndpoints                 = 1,
                    167:         .bInterfaceClass               = USB_CLASS_AUDIO,
                    168:         .bInterfaceSubClass            = USB_SUBCLASS_AUDIO_STREAMING,
                    169:         .iInterface                    = STRING_REAL_STREAM,
                    170:         .ndesc                         = 2,
                    171:         .descs = (USBDescOther[]) {
                    172:             {
                    173:                 /* Headphone Class-specific AS General Interface Descriptor */
                    174:                 .data = (uint8_t[]) {
                    175:                     0x07,                       /*  u8  bLength */
                    176:                     USB_DT_CS_INTERFACE,        /*  u8  bDescriptorType */
                    177:                     DST_AS_GENERAL,             /*  u8  bDescriptorSubtype */
                    178:                     0x01,                       /*  u8  bTerminalLink */
                    179:                     0x00,                       /*  u8  bDelay */
                    180:                     0x01, 0x00,                 /* u16  wFormatTag */
                    181:                 }
                    182:             },{
                    183:                 /* Headphone Type I Format Type Descriptor */
                    184:                 .data = (uint8_t[]) {
                    185:                     0x0b,                       /*  u8  bLength */
                    186:                     USB_DT_CS_INTERFACE,        /*  u8  bDescriptorType */
                    187:                     DST_AS_FORMAT_TYPE,         /*  u8  bDescriptorSubtype */
                    188:                     0x01,                       /*  u8  bFormatType */
                    189:                     0x02,                       /*  u8  bNrChannels */
                    190:                     0x02,                       /*  u8  bSubFrameSize */
                    191:                     0x10,                       /*  u8  bBitResolution */
                    192:                     0x01,                       /*  u8  bSamFreqType */
                    193:                     U24(USBAUDIO_SAMPLE_RATE),  /* u24  tSamFreq */
                    194:                 }
                    195:             }
                    196:         },
                    197:         .eps = (USBDescEndpoint[]) {
                    198:             {
                    199:                 .bEndpointAddress      = USB_DIR_OUT | 0x01,
                    200:                 .bmAttributes          = 0x0d,
                    201:                 .wMaxPacketSize        = USBAUDIO_PACKET_SIZE,
                    202:                 .bInterval             = 1,
                    203:                 .is_audio              = 1,
                    204:                 /* Stereo Headphone Class-specific
                    205:                    AS Audio Data Endpoint Descriptor */
                    206:                 .extra = (uint8_t[]) {
                    207:                     0x07,                       /*  u8  bLength */
                    208:                     USB_DT_CS_ENDPOINT,         /*  u8  bDescriptorType */
                    209:                     DST_EP_GENERAL,             /*  u8  bDescriptorSubtype */
                    210:                     0x00,                       /*  u8  bmAttributes */
                    211:                     0x00,                       /*  u8  bLockDelayUnits */
                    212:                     U16(0x0000),                /* u16  wLockDelay */
                    213:                 },
                    214:             },
                    215:         }
                    216:     }
                    217: };
                    218: 
                    219: static const USBDescDevice desc_device = {
                    220:     .bcdUSB                        = 0x0200,
                    221:     .bMaxPacketSize0               = 64,
                    222:     .bNumConfigurations            = 1,
                    223:     .confs = (USBDescConfig[]) {
                    224:         {
                    225:             .bNumInterfaces        = 2,
                    226:             .bConfigurationValue   = DEV_CONFIG_VALUE,
                    227:             .iConfiguration        = STRING_CONFIG,
                    228:             .bmAttributes          = 0xc0,
                    229:             .bMaxPower             = 0x32,
                    230:             .nif = ARRAY_SIZE(desc_iface),
                    231:             .ifs = desc_iface,
                    232:         },
                    233:     },
                    234: };
                    235: 
                    236: static const USBDesc desc_audio = {
                    237:     .id = {
                    238:         .idVendor          = USBAUDIO_VENDOR_NUM,
                    239:         .idProduct         = USBAUDIO_PRODUCT_NUM,
                    240:         .bcdDevice         = 0,
                    241:         .iManufacturer     = STRING_MANUFACTURER,
                    242:         .iProduct          = STRING_PRODUCT,
                    243:         .iSerialNumber     = STRING_SERIALNUMBER,
                    244:     },
                    245:     .full = &desc_device,
                    246:     .str  = usb_audio_stringtable,
                    247: };
                    248: 
                    249: /*
                    250:  * A USB audio device supports an arbitrary number of alternate
                    251:  * interface settings for each interface.  Each corresponds to a block
                    252:  * diagram of parameterized blocks.  This can thus refer to things like
                    253:  * number of channels, data rates, or in fact completely different
                    254:  * block diagrams.  Alternative setting 0 is always the null block diagram,
                    255:  * which is used by a disabled device.
                    256:  */
                    257: enum usb_audio_altset {
                    258:     ALTSET_OFF  = 0x00,         /* No endpoint */
                    259:     ALTSET_ON   = 0x01,         /* Single endpoint */
                    260: };
                    261: 
                    262: /*
                    263:  * Class-specific control requests
                    264:  */
                    265: #define CR_SET_CUR      0x01
                    266: #define CR_GET_CUR      0x81
                    267: #define CR_SET_MIN      0x02
                    268: #define CR_GET_MIN      0x82
                    269: #define CR_SET_MAX      0x03
                    270: #define CR_GET_MAX      0x83
                    271: #define CR_SET_RES      0x04
                    272: #define CR_GET_RES      0x84
                    273: #define CR_SET_MEM      0x05
                    274: #define CR_GET_MEM      0x85
                    275: #define CR_GET_STAT     0xff
                    276: 
                    277: /*
                    278:  * Feature Unit Control Selectors
                    279:  */
                    280: #define MUTE_CONTROL                    0x01
                    281: #define VOLUME_CONTROL                  0x02
                    282: #define BASS_CONTROL                    0x03
                    283: #define MID_CONTROL                     0x04
                    284: #define TREBLE_CONTROL                  0x05
                    285: #define GRAPHIC_EQUALIZER_CONTROL       0x06
                    286: #define AUTOMATIC_GAIN_CONTROL          0x07
                    287: #define DELAY_CONTROL                   0x08
                    288: #define BASS_BOOST_CONTROL              0x09
                    289: #define LOUDNESS_CONTROL                0x0a
                    290: 
                    291: /*
                    292:  * buffering
                    293:  */
                    294: 
                    295: struct streambuf {
                    296:     uint8_t *data;
                    297:     uint32_t size;
                    298:     uint32_t prod;
                    299:     uint32_t cons;
                    300: };
                    301: 
                    302: static void streambuf_init(struct streambuf *buf, uint32_t size)
                    303: {
                    304:     g_free(buf->data);
                    305:     buf->size = size - (size % USBAUDIO_PACKET_SIZE);
                    306:     buf->data = g_malloc(buf->size);
                    307:     buf->prod = 0;
                    308:     buf->cons = 0;
                    309: }
                    310: 
                    311: static void streambuf_fini(struct streambuf *buf)
                    312: {
                    313:     g_free(buf->data);
                    314:     buf->data = NULL;
                    315: }
                    316: 
                    317: static int streambuf_put(struct streambuf *buf, USBPacket *p)
                    318: {
                    319:     uint32_t free = buf->size - (buf->prod - buf->cons);
                    320: 
                    321:     if (!free) {
                    322:         return 0;
                    323:     }
                    324:     assert(free >= USBAUDIO_PACKET_SIZE);
                    325:     usb_packet_copy(p, buf->data + (buf->prod % buf->size),
                    326:                     USBAUDIO_PACKET_SIZE);
                    327:     buf->prod += USBAUDIO_PACKET_SIZE;
                    328:     return USBAUDIO_PACKET_SIZE;
                    329: }
                    330: 
                    331: static uint8_t *streambuf_get(struct streambuf *buf)
                    332: {
                    333:     uint32_t used = buf->prod - buf->cons;
                    334:     uint8_t *data;
                    335: 
                    336:     if (!used) {
                    337:         return NULL;
                    338:     }
                    339:     assert(used >= USBAUDIO_PACKET_SIZE);
                    340:     data = buf->data + (buf->cons % buf->size);
                    341:     buf->cons += USBAUDIO_PACKET_SIZE;
                    342:     return data;
                    343: }
                    344: 
                    345: typedef struct USBAudioState {
                    346:     /* qemu interfaces */
                    347:     USBDevice dev;
                    348:     QEMUSoundCard card;
                    349: 
                    350:     /* state */
                    351:     struct {
                    352:         enum usb_audio_altset altset;
                    353:         struct audsettings as;
                    354:         SWVoiceOut *voice;
                    355:         bool mute;
                    356:         uint8_t vol[2];
                    357:         struct streambuf buf;
                    358:     } out;
                    359: 
                    360:     /* properties */
                    361:     uint32_t debug;
                    362:     uint32_t buffer;
                    363: } USBAudioState;
                    364: 
                    365: static void output_callback(void *opaque, int avail)
                    366: {
                    367:     USBAudioState *s = opaque;
                    368:     uint8_t *data;
                    369: 
                    370:     for (;;) {
                    371:         if (avail < USBAUDIO_PACKET_SIZE) {
                    372:             return;
                    373:         }
                    374:         data = streambuf_get(&s->out.buf);
                    375:         if (NULL == data) {
                    376:             return;
                    377:         }
                    378:         AUD_write(s->out.voice, data, USBAUDIO_PACKET_SIZE);
                    379:         avail -= USBAUDIO_PACKET_SIZE;
                    380:     }
                    381: }
                    382: 
                    383: static int usb_audio_set_output_altset(USBAudioState *s, int altset)
                    384: {
                    385:     switch (altset) {
                    386:     case ALTSET_OFF:
                    387:         streambuf_init(&s->out.buf, s->buffer);
                    388:         AUD_set_active_out(s->out.voice, false);
                    389:         break;
                    390:     case ALTSET_ON:
                    391:         AUD_set_active_out(s->out.voice, true);
                    392:         break;
                    393:     default:
                    394:         return -1;
                    395:     }
                    396: 
                    397:     if (s->debug) {
                    398:         fprintf(stderr, "usb-audio: set interface %d\n", altset);
                    399:     }
                    400:     s->out.altset = altset;
                    401:     return 0;
                    402: }
                    403: 
                    404: /*
                    405:  * Note: we arbitrarily map the volume control range onto -inf..+8 dB
                    406:  */
                    407: #define ATTRIB_ID(cs, attrib, idif)     \
                    408:     (((cs) << 24) | ((attrib) << 16) | (idif))
                    409: 
                    410: static int usb_audio_get_control(USBAudioState *s, uint8_t attrib,
                    411:                                  uint16_t cscn, uint16_t idif,
                    412:                                  int length, uint8_t *data)
                    413: {
                    414:     uint8_t cs = cscn >> 8;
                    415:     uint8_t cn = cscn - 1;      /* -1 for the non-present master control */
                    416:     uint32_t aid = ATTRIB_ID(cs, attrib, idif);
                    417:     int ret = USB_RET_STALL;
                    418: 
                    419:     switch (aid) {
                    420:     case ATTRIB_ID(MUTE_CONTROL, CR_GET_CUR, 0x0200):
                    421:         data[0] = s->out.mute;
                    422:         ret = 1;
                    423:         break;
                    424:     case ATTRIB_ID(VOLUME_CONTROL, CR_GET_CUR, 0x0200):
                    425:         if (cn < 2) {
                    426:             uint16_t vol = (s->out.vol[cn] * 0x8800 + 127) / 255 + 0x8000;
                    427:             data[0] = vol;
                    428:             data[1] = vol >> 8;
                    429:             ret = 2;
                    430:         }
                    431:         break;
                    432:     case ATTRIB_ID(VOLUME_CONTROL, CR_GET_MIN, 0x0200):
                    433:         if (cn < 2) {
                    434:             data[0] = 0x01;
                    435:             data[1] = 0x80;
                    436:             ret = 2;
                    437:         }
                    438:         break;
                    439:     case ATTRIB_ID(VOLUME_CONTROL, CR_GET_MAX, 0x0200):
                    440:         if (cn < 2) {
                    441:             data[0] = 0x00;
                    442:             data[1] = 0x08;
                    443:             ret = 2;
                    444:         }
                    445:         break;
                    446:     case ATTRIB_ID(VOLUME_CONTROL, CR_GET_RES, 0x0200):
                    447:         if (cn < 2) {
                    448:             data[0] = 0x88;
                    449:             data[1] = 0x00;
                    450:             ret = 2;
                    451:         }
                    452:         break;
                    453:     }
                    454: 
                    455:     return ret;
                    456: }
                    457: static int usb_audio_set_control(USBAudioState *s, uint8_t attrib,
                    458:                                  uint16_t cscn, uint16_t idif,
                    459:                                  int length, uint8_t *data)
                    460: {
                    461:     uint8_t cs = cscn >> 8;
                    462:     uint8_t cn = cscn - 1;      /* -1 for the non-present master control */
                    463:     uint32_t aid = ATTRIB_ID(cs, attrib, idif);
                    464:     int ret = USB_RET_STALL;
                    465:     bool set_vol = false;
                    466: 
                    467:     switch (aid) {
                    468:     case ATTRIB_ID(MUTE_CONTROL, CR_SET_CUR, 0x0200):
                    469:         s->out.mute = data[0] & 1;
                    470:         set_vol = true;
                    471:         ret = 0;
                    472:         break;
                    473:     case ATTRIB_ID(VOLUME_CONTROL, CR_SET_CUR, 0x0200):
                    474:         if (cn < 2) {
                    475:             uint16_t vol = data[0] + (data[1] << 8);
                    476: 
                    477:             if (s->debug) {
                    478:                 fprintf(stderr, "usb-audio: vol %04x\n", (uint16_t)vol);
                    479:             }
                    480: 
                    481:             vol -= 0x8000;
                    482:             vol = (vol * 255 + 0x4400) / 0x8800;
                    483:             if (vol > 255) {
                    484:                 vol = 255;
                    485:             }
                    486: 
                    487:             s->out.vol[cn] = vol;
                    488:             set_vol = true;
                    489:             ret = 0;
                    490:         }
                    491:         break;
                    492:     }
                    493: 
                    494:     if (set_vol) {
                    495:         if (s->debug) {
                    496:             fprintf(stderr, "usb-audio: mute %d, lvol %3d, rvol %3d\n",
                    497:                     s->out.mute, s->out.vol[0], s->out.vol[1]);
                    498:         }
                    499:         AUD_set_volume_out(s->out.voice, s->out.mute,
                    500:                            s->out.vol[0], s->out.vol[1]);
                    501:     }
                    502: 
                    503:     return ret;
                    504: }
                    505: 
                    506: static int usb_audio_handle_control(USBDevice *dev, USBPacket *p,
                    507:                                     int request, int value, int index,
                    508:                                     int length, uint8_t *data)
                    509: {
                    510:     USBAudioState *s = DO_UPCAST(USBAudioState, dev, dev);
                    511:     int ret = 0;
                    512: 
                    513:     if (s->debug) {
                    514:         fprintf(stderr, "usb-audio: control transaction: "
                    515:                 "request 0x%04x value 0x%04x index 0x%04x length 0x%04x\n",
                    516:                 request, value, index, length);
                    517:     }
                    518: 
                    519:     ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
                    520:     if (ret >= 0) {
                    521:         return ret;
                    522:     }
                    523: 
                    524:     switch (request) {
                    525:     case ClassInterfaceRequest | CR_GET_CUR:
                    526:     case ClassInterfaceRequest | CR_GET_MIN:
                    527:     case ClassInterfaceRequest | CR_GET_MAX:
                    528:     case ClassInterfaceRequest | CR_GET_RES:
                    529:         ret = usb_audio_get_control(s, request & 0xff, value, index,
                    530:                                     length, data);
                    531:         if (ret < 0) {
                    532:             if (s->debug) {
                    533:                 fprintf(stderr, "usb-audio: fail: get control\n");
                    534:             }
                    535:             goto fail;
                    536:         }
                    537:         break;
                    538: 
                    539:     case ClassInterfaceOutRequest | CR_SET_CUR:
                    540:     case ClassInterfaceOutRequest | CR_SET_MIN:
                    541:     case ClassInterfaceOutRequest | CR_SET_MAX:
                    542:     case ClassInterfaceOutRequest | CR_SET_RES:
                    543:         ret = usb_audio_set_control(s, request & 0xff, value, index,
                    544:                                     length, data);
                    545:         if (ret < 0) {
                    546:             if (s->debug) {
                    547:                 fprintf(stderr, "usb-audio: fail: set control\n");
                    548:             }
                    549:             goto fail;
                    550:         }
                    551:         break;
                    552: 
                    553:     default:
                    554: fail:
                    555:         if (s->debug) {
                    556:             fprintf(stderr, "usb-audio: failed control transaction: "
                    557:                     "request 0x%04x value 0x%04x index 0x%04x length 0x%04x\n",
                    558:                     request, value, index, length);
                    559:         }
                    560:         ret = USB_RET_STALL;
                    561:         break;
                    562:     }
                    563:     return ret;
                    564: }
                    565: 
                    566: static void usb_audio_set_interface(USBDevice *dev, int iface,
                    567:                                     int old, int value)
                    568: {
                    569:     USBAudioState *s = DO_UPCAST(USBAudioState, dev, dev);
                    570: 
                    571:     if (iface == 1) {
                    572:         usb_audio_set_output_altset(s, value);
                    573:     }
                    574: }
                    575: 
                    576: static void usb_audio_handle_reset(USBDevice *dev)
                    577: {
                    578:     USBAudioState *s = DO_UPCAST(USBAudioState, dev, dev);
                    579: 
                    580:     if (s->debug) {
                    581:         fprintf(stderr, "usb-audio: reset\n");
                    582:     }
                    583:     usb_audio_set_output_altset(s, ALTSET_OFF);
                    584: }
                    585: 
                    586: static int usb_audio_handle_dataout(USBAudioState *s, USBPacket *p)
                    587: {
                    588:     int rc;
                    589: 
                    590:     if (s->out.altset == ALTSET_OFF) {
                    591:         return USB_RET_STALL;
                    592:     }
                    593: 
                    594:     rc = streambuf_put(&s->out.buf, p);
                    595:     if (rc < p->iov.size && s->debug > 1) {
                    596:         fprintf(stderr, "usb-audio: output overrun (%zd bytes)\n",
                    597:                 p->iov.size - rc);
                    598:     }
                    599: 
                    600:     return 0;
                    601: }
                    602: 
                    603: static int usb_audio_handle_data(USBDevice *dev, USBPacket *p)
                    604: {
                    605:     USBAudioState *s = (USBAudioState *) dev;
                    606:     int ret = 0;
                    607: 
                    608:     switch (p->pid) {
                    609:     case USB_TOKEN_OUT:
                    610:         switch (p->ep->nr) {
                    611:         case 1:
                    612:             ret = usb_audio_handle_dataout(s, p);
                    613:             break;
                    614:         default:
                    615:             goto fail;
                    616:         }
                    617:         break;
                    618: 
                    619:     default:
                    620: fail:
                    621:         ret = USB_RET_STALL;
                    622:         break;
                    623:     }
                    624:     if (ret == USB_RET_STALL && s->debug) {
                    625:         fprintf(stderr, "usb-audio: failed data transaction: "
                    626:                         "pid 0x%x ep 0x%x len 0x%zx\n",
                    627:                         p->pid, p->ep->nr, p->iov.size);
                    628:     }
                    629:     return ret;
                    630: }
                    631: 
                    632: static void usb_audio_handle_destroy(USBDevice *dev)
                    633: {
                    634:     USBAudioState *s = DO_UPCAST(USBAudioState, dev, dev);
                    635: 
                    636:     if (s->debug) {
                    637:         fprintf(stderr, "usb-audio: destroy\n");
                    638:     }
                    639: 
                    640:     usb_audio_set_output_altset(s, ALTSET_OFF);
                    641:     AUD_close_out(&s->card, s->out.voice);
                    642:     AUD_remove_card(&s->card);
                    643: 
                    644:     streambuf_fini(&s->out.buf);
                    645: }
                    646: 
                    647: static int usb_audio_initfn(USBDevice *dev)
                    648: {
                    649:     USBAudioState *s = DO_UPCAST(USBAudioState, dev, dev);
                    650: 
                    651:     usb_desc_create_serial(dev);
                    652:     usb_desc_init(dev);
                    653:     s->dev.opaque = s;
                    654:     AUD_register_card("usb-audio", &s->card);
                    655: 
                    656:     s->out.altset        = ALTSET_OFF;
                    657:     s->out.mute          = false;
                    658:     s->out.vol[0]        = 240; /* 0 dB */
                    659:     s->out.vol[1]        = 240; /* 0 dB */
                    660:     s->out.as.freq       = USBAUDIO_SAMPLE_RATE;
                    661:     s->out.as.nchannels  = 2;
                    662:     s->out.as.fmt        = AUD_FMT_S16;
                    663:     s->out.as.endianness = 0;
                    664:     streambuf_init(&s->out.buf, s->buffer);
                    665: 
                    666:     s->out.voice = AUD_open_out(&s->card, s->out.voice, "usb-audio",
                    667:                                 s, output_callback, &s->out.as);
                    668:     AUD_set_volume_out(s->out.voice, s->out.mute, s->out.vol[0], s->out.vol[1]);
                    669:     AUD_set_active_out(s->out.voice, 0);
                    670:     return 0;
                    671: }
                    672: 
                    673: static const VMStateDescription vmstate_usb_audio = {
                    674:     .name = "usb-audio",
                    675:     .unmigratable = 1,
                    676: };
                    677: 
                    678: static Property usb_audio_properties[] = {
                    679:     DEFINE_PROP_UINT32("debug", USBAudioState, debug, 0),
                    680:     DEFINE_PROP_UINT32("buffer", USBAudioState, buffer,
                    681:                        8 * USBAUDIO_PACKET_SIZE),
                    682:     DEFINE_PROP_END_OF_LIST(),
                    683: };
                    684: 
                    685: static void usb_audio_class_init(ObjectClass *klass, void *data)
                    686: {
                    687:     DeviceClass *dc = DEVICE_CLASS(klass);
                    688:     USBDeviceClass *k = USB_DEVICE_CLASS(klass);
                    689: 
                    690:     dc->vmsd          = &vmstate_usb_audio;
                    691:     dc->props         = usb_audio_properties;
                    692:     k->product_desc   = "QEMU USB Audio Interface";
                    693:     k->usb_desc       = &desc_audio;
                    694:     k->init           = usb_audio_initfn;
                    695:     k->handle_reset   = usb_audio_handle_reset;
                    696:     k->handle_control = usb_audio_handle_control;
                    697:     k->handle_data    = usb_audio_handle_data;
                    698:     k->handle_destroy = usb_audio_handle_destroy;
                    699:     k->set_interface  = usb_audio_set_interface;
                    700: }
                    701: 
                    702: static TypeInfo usb_audio_info = {
                    703:     .name          = "usb-audio",
                    704:     .parent        = TYPE_USB_DEVICE,
                    705:     .instance_size = sizeof(USBAudioState),
                    706:     .class_init    = usb_audio_class_init,
                    707: };
                    708: 
                    709: static void usb_audio_register_types(void)
                    710: {
                    711:     type_register_static(&usb_audio_info);
                    712:     usb_legacy_register("usb-audio", "audio", NULL);
                    713: }
                    714: 
                    715: type_init(usb_audio_register_types)

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.