Index: firmware/export/usb_core.h =================================================================== --- firmware/export/usb_core.h (revision 17404) +++ firmware/export/usb_core.h (working copy) @@ -24,6 +24,7 @@ //#define USB_SERIAL #define USB_STORAGE #define USB_CHARGING_ONLY +#define USB_AUDIO #else /* BOOTLOADER */ #define USB_CHARGING_ONLY #endif /* BOOTLOADER */ Index: firmware/export/usb.h =================================================================== --- firmware/export/usb.h (revision 17404) +++ firmware/export/usb.h (working copy) @@ -71,6 +71,7 @@ USB_DRIVER_MASS_STORAGE, USB_DRIVER_SERIAL, USB_DRIVER_CHARGING_ONLY, + USB_DRIVER_AUDIO, USB_NUM_DRIVERS }; #endif Index: firmware/usbstack/usb_audio.h =================================================================== --- firmware/usbstack/usb_audio.h (revision 0) +++ firmware/usbstack/usb_audio.h (revision 0) @@ -0,0 +1,31 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: $ + * + * Copyright (C) 2008 by Frank Gevaerts + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#ifndef USB_AUDIO_H +#define USB_AUDIO_H + +#include "usb_ch9.h" + +void usb_audio_init(void); +int usb_audio_set_first_endpoint(int endpoint); +int usb_audio_set_first_interface(int interface); +int usb_audio_get_config_descriptor(unsigned char *dest,int max_packet_size); +bool usb_audio_control_request(struct usb_ctrlrequest* req); + +#endif + Index: firmware/usbstack/usb_core.c =================================================================== --- firmware/usbstack/usb_core.c (revision 17404) +++ firmware/usbstack/usb_core.c (working copy) @@ -37,6 +37,10 @@ #include "usb_serial.h" #endif +#if defined(USB_AUDIO) +#include "usb_audio.h" +#endif + #if defined(USB_CHARGING_ONLY) #include "usb_charging_only.h" #endif @@ -228,6 +232,25 @@ #endif }, #endif +#ifdef USB_AUDIO + [USB_DRIVER_AUDIO] = { + .enabled = false, + .needs_exclusive_ata = false, + .first_interface = 0, + .last_interface = 0, + .set_first_interface = usb_audio_set_first_interface, + .set_first_endpoint = usb_audio_set_first_endpoint, + .get_config_descriptor = usb_audio_get_config_descriptor, + .init_connection = NULL, + .init = usb_audio_init, + .disconnect = NULL, + .transfer_complete = NULL, + .control_request = usb_audio_control_request, +#ifdef HAVE_HOTSWAP + .notify_hotswap = NULL, +#endif + }, +#endif }; static void usb_core_control_request_handler(struct usb_ctrlrequest* req); Index: firmware/usbstack/usb_audio.c =================================================================== --- firmware/usbstack/usb_audio.c (revision 0) +++ firmware/usbstack/usb_audio.c (revision 0) @@ -0,0 +1,228 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: $ + * + * Copyright (C) 2008 by Frank Gevaerts + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "string.h" +#include "system.h" +#include "usb_core.h" +#include "usb_drv.h" +#include "kernel.h" +#include "sound.h" +#include "../apps/settings.h" + +#define LOGF_ENABLE +#include "logf.h" + +#ifdef USB_AUDIO + +#define USB_SUBCLASS_AUDIO_CONTROL 1 +#define USB_SUBCLASS_AUDIO_STREAMING 2 + +#define USB_AC_HEADER 1 +#define USB_AC_INPUT_TERMINAL 2 +#define USB_AC_OUTPUT_TERMINAL 3 +#define USB_AC_MIXER_UNIT 4 +#define USB_AC_SELECTOR_UNIT 5 +#define USB_AC_FEATURE_UNIT 6 +#define USB_AC_PROCESSING_UNIT 8 +#define USB_AC_EXTENSION_UNIT 9 + +#define SET_CUR 0x01 +#define SET_MIN 0x02 +#define SET_MAX 0x03 +#define SET_RES 0x04 +#define GET_CUR 0x81 +#define GET_MIN 0x82 +#define GET_MAX 0x83 +#define GET_RES 0x84 + +#define TTYPE_MINIDISK 0x0706 +#define TTYPE_HEADPHONES 0x0302 + +/* usb audio datastructures */ +struct usb_ac_header { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubType; + uint8_t bcdADC[2]; + uint8_t wTotalLength[2]; /* Should be a unit16_t, but it's not aligned, so this is safer */ + uint8_t bInCollection; + uint8_t baInterfaceNr[1]; +} __attribute__ ((packed)); + +struct usb_ac_input_terminal { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubType; + uint8_t bTerminalId; + uint16_t wTerminalType; + uint8_t bAssocTerminal; + uint8_t bNrChannels; + uint16_t wChannelConfig; + uint8_t iChannelNames; + uint8_t iTerminal; +} __attribute__ ((packed)); + +struct usb_ac_output_terminal { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubType; + uint8_t bTerminalId; + uint16_t wTerminalType; + uint8_t bAssocTerminal; + uint8_t bSourceId; + uint8_t iTerminal; +} __attribute__ ((packed)); + +struct usb_ac_feature_unit { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubType; + uint8_t bUnitId; + uint8_t bSourceId; + uint8_t bControlSize; + uint8_t bmaControls[2]; + uint8_t iFeature; +} __attribute__ ((packed)); + +struct usb_as_class { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubType; + uint8_t bTerminalLink; + uint8_t bDelay; + uint8_t wFormatTag[2]; /* Yet another unaligned field */ +} __attribute__ ((packed)); + +static unsigned char _buffer[32] __attribute__((aligned(32))); +static unsigned char* buffer; + +/* audio interface */ +static struct usb_interface_descriptor __attribute__((aligned(2))) + interface_descriptor = +{ + .bLength = sizeof(struct usb_interface_descriptor), + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 0, + .bAlternateSetting = 0, + .bNumEndpoints = 0, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = USB_SUBCLASS_AUDIO_CONTROL, + .bInterfaceProtocol = 0, + .iInterface = 0 +}; + +static struct usb_ac_header __attribute__((aligned(2))) ac_header = +{ + .bLength = sizeof(struct usb_ac_header), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_AC_HEADER, + .bcdADC = {0x00,0x01}, + .wTotalLength = {30,0},// TODO + .bInCollection = 1, + .baInterfaceNr = {0}, +}; + +static struct usb_ac_input_terminal __attribute__((aligned(2))) ac_input = +{ + .bLength = sizeof(struct usb_ac_input_terminal), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_AC_INPUT_TERMINAL, + .bTerminalId = 1, + .wTerminalType = TTYPE_MINIDISK, + .bAssocTerminal = 0, + .bNrChannels = 2, + .wChannelConfig = 3, + .iChannelNames = 0, + .iTerminal = 0, +}; + +static struct usb_ac_output_terminal __attribute__((aligned(2))) ac_output = +{ + .bLength = sizeof(struct usb_ac_output_terminal), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_AC_INPUT_TERMINAL, + .bTerminalId = 2, + .wTerminalType = TTYPE_HEADPHONES, + .bAssocTerminal = 0, + .bSourceId = 1, + .iTerminal = 0, +}; + + + +static int usb_interface; + +void usb_audio_init(void) +{ + buffer = (void*)UNCACHED_ADDR(&_buffer); +} + +int usb_audio_set_first_endpoint(int endpoint) +{ + /* The dummy audio driver doesn't need an endpoint pair */ + return endpoint; +} +int usb_audio_set_first_interface(int interface) +{ + usb_interface = interface; + return interface + 2; +} + +int usb_audio_get_config_descriptor(unsigned char *dest,int max_packet_size) +{ + (void)max_packet_size; + unsigned char *orig_dest = dest; + + interface_descriptor.bInterfaceNumber=usb_interface; + interface_descriptor.bInterfaceSubClass=USB_SUBCLASS_AUDIO_CONTROL; + ac_header.baInterfaceNr[0] = usb_interface + 1; + + memcpy(dest,&interface_descriptor,sizeof(struct usb_interface_descriptor)); + dest+=sizeof(struct usb_interface_descriptor); + + memcpy(dest,&ac_header,sizeof(struct usb_ac_header)); + dest+=sizeof(struct usb_ac_header); + + memcpy(dest,&ac_input,sizeof(struct usb_ac_input_terminal)); + dest+=sizeof(struct usb_ac_input_terminal); + + memcpy(dest,&ac_output,sizeof(struct usb_ac_output_terminal)); + dest+=sizeof(struct usb_ac_output_terminal); + + interface_descriptor.bInterfaceNumber=usb_interface + 1; + interface_descriptor.bInterfaceSubClass=USB_SUBCLASS_AUDIO_STREAMING; + + memcpy(dest,&interface_descriptor,sizeof(struct usb_interface_descriptor)); + dest+=sizeof(struct usb_interface_descriptor); + + return (dest-orig_dest); +} + + +/* called by usb_core_control_request() */ +bool usb_audio_control_request(struct usb_ctrlrequest* req) +{ + bool handled = false; + switch (req->bRequest) { + default: + logf("audio: unhandeld req %d", req->bRequest); + } + return handled; +} + +#endif /*USB_AUDIO*/ Index: firmware/SOURCES =================================================================== --- firmware/SOURCES (revision 17404) +++ firmware/SOURCES (working copy) @@ -241,6 +241,7 @@ usbstack/usb_core.c usbstack/usb_storage.c usbstack/usb_serial.c +usbstack/usb_audio.c usbstack/usb_charging_only.c #if CONFIG_USBOTG == USBOTG_ARC target/arm/usb-drv-arc.c Index: firmware/usb.c =================================================================== --- firmware/usb.c (revision 17404) +++ firmware/usb.c (working copy) @@ -199,8 +199,12 @@ { usb_state = USB_POWERED; #ifdef HAVE_USBSTACK +#ifdef USB_STORAGE usb_core_enable_driver(USB_DRIVER_MASS_STORAGE,false); - usb_core_enable_driver(USB_DRIVER_CHARGING_ONLY,true); +#endif +#ifdef USB_AUDIO + usb_core_enable_driver(USB_DRIVER_AUDIO,true); +#endif usb_enable(true); #endif } @@ -211,8 +215,12 @@ /* Set the state to USB_POWERED for now. if a real connection is detected it will switch to USB_INSERTED */ usb_state = USB_POWERED; +#ifdef USB_STORAGE usb_core_enable_driver(USB_DRIVER_MASS_STORAGE,true); - usb_core_enable_driver(USB_DRIVER_CHARGING_ONLY,false); +#endif +#ifdef USB_AUDIO + usb_core_enable_driver(USB_DRIVER_AUDIO,false); +#endif usb_enable(true); #else /* Tell all threads that they have to back off the ATA.