⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 a2dp_sd_interface_usb.c

📁 蓝牙a2dp_source_dongle的例程
💻 C
📖 第 1 页 / 共 2 页
字号:
    }

    if (activity)
        /* 
            USB has signalled to our interface which is a good sign that
            it is about to send audio data.  Kick the A2DP profile to get 
            the sink connected ASAP. 
        */
        MessageSend(getTheAppTask(), APP_KICK_PROFILE_REQ, 0);
}


/*
    Process class requests to the Audio Streaming Interface or Endpoint
*/
static void handleAudioStreamingClassRequest(Source req)
{
    uint16 packet_size;
    bool activity = FALSE;
    Sink resp = StreamSinkFromSource(req);

    /* Check for outstanding Class requests */
    while ((packet_size = SourceBoundary(req)) != 0)
    {
        /*
            Build the response. It must contain the original request, 
            so copy from the source header.
        */
        UsbResponse usbresp;    
        memcpy(&usbresp.original_request, SourceMapHeader(req), sizeof(UsbRequest));

        /* Set the response fields to default values to make the code below simpler */
        usbresp.success = TRUE;
        usbresp.data_length = 0;

        /* Endpoint only allows SET_/GET_ of sampling frequency */
        if (((usbresp.original_request.wValue >> 8) == SAMPLING_FREQ_CONTROL) &&
            (usbresp.original_request.wLength == 3))
        {
            if (usbresp.original_request.bRequest == SET_CUR)
            {
                uint32 new_rate = (uint32)SourceMap(req)[0] |
                                ((uint32)SourceMap(req)[1] << 8) |
                                ((uint32)SourceMap(req)[2] << 16);
                    
                /* Reject bad value */
                if (new_rate != SAMPLE_RATE)
                    usbresp.success = FALSE;
            }
            else if (usbresp.original_request.bRequest == GET_CUR)
            {
                /* Return current value */
                uint8 *ptr = SinkMap(resp) + SinkClaim(resp, 3);
                ptr[0] = (uint16)(SAMPLE_RATE & 0xff);
                ptr[1] = (uint16)(SAMPLE_RATE >> 8);
                ptr[2] = (uint16)(SAMPLE_RATE >> 16);	/*lint !e572 !e778 */
                usbresp.data_length = 3;
            }
            else usbresp.success = FALSE;
        }
        else
            usbresp.success = FALSE;

        /* Send response */
        if (usbresp.data_length)
        {
            (void)SinkFlushHeader(resp, usbresp.data_length, (void *)&usbresp, sizeof(UsbResponse));
        }
        else
        {
            /* Sink packets can never be zero-length, so flush a dummy byte */
            (void)SinkClaim(resp, 1);
            (void)SinkFlushHeader(resp, 1, (void *)&usbresp, sizeof(UsbResponse));          
        }

        /* Discard the original request */
        SourceDrop(req, packet_size);

        activity = TRUE;
    }

    if (activity)
        /* 
            USB has signalled to our interface which is a good sign that
            it is about to send audio data.  Kick the A2DP profile to get 
            the sink connected ASAP. 
        */
        MessageSend(getTheAppTask(), APP_KICK_PROFILE_REQ, 0);
}


/*
    Called when a class request could have arrived for
    the HID interface.

    The USB Host can also communicate to the dongle using
    the Feature report defined in the descriptor.
    The protcol is made up of GET_REPORT/SET_REPORT pairs
    with 8 bytes report payloads.

    Host sends SET_REPORT(Feature) with payload:
        <request(0x01 to 0xff)> <7 data bytes>
    Host issues GET_REPORT(Feature) to read response.
    Device responds with:
        <response - as in request> <result 0x00=ok, 0x01-0xff=failure> <6 data bytes>

    GET_STATE - used to read current device state
    Request Payload:
        0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00
    Response Payload:
        0x01 <result> a2dp_state avrcp_state 0x00 0x00 0x00 0x00
        a2dp_state:     a2dp_state_initialising = 0
                        a2dp_state_discovering  = 1
                        a2dp_state_accepting    = 2
                        a2dp_state_initiating   = 3
                        a2dp_state_connected    = 4
                        a2dp_state_streaming    = 5
                        a2dp_state_disconnecting= 6
        avrcp_state:    avrcp_state_idle = 0
                        avrcp_state_accepting = 1 
                        avrcp_state_connected = 2
                        avrcp_state_disconnecting =3

    GET_REMOTE_BDADDR - returns the Bluetooth address of the sink
    Request Payload:
        0x02 0x00 0x00 0x00 0x00 0x00 0x00 0x00
    Response Payload:
        0x02 <result> nap nap uap lap lap lap

    DISCOVER - simulate pressing the devices 'Discover' button
    Request Payload:
        0x03 0x00 0x00 0x00 0x00 0x00 0x00 0x00
    Response Payload:
        0x03 <result> 0x00 0x00 0x00 0x00 0x00 0x00

    SWITCH_TO_DFU - requests the dongle instantly switches to DFU mode
    Request Payload:
        0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00
    Response Payload:
        None - device will reboot as new USB and hence can't reply

    READ_CODEC - returns the current A2DP Codec parameters
    Request Payload:
        0x05 0x00 0x00 0x00 0x00 0x00 0x00 0x00
    Response Payload:
        0x05 <result> codec param1 param2 param3 param4 param5
        Codec:
            1 = SBC: param1=format, param2=bitpool.
*/
static void handleHIDClassRequest(Source req, const a2dpSourceDongleTaskData *theApp)
{
    uint16 packet_size;
    static uint8 last_request=0;
    Sink resp = StreamSinkFromSource(req);

    /* Check for outstanding Class requests */
    while ((packet_size = SourceBoundary(req)) != 0)
    {
        /*
            Build the response. It must contain the original request, 
            so copy from the source header.
        */
        UsbResponse usbresp;    
        memcpy(&usbresp.original_request, SourceMapHeader(req), sizeof(UsbRequest));

        /* Set the response fields to default values to make the code below simpler */
        usbresp.success = FALSE;
        usbresp.data_length = 0;

        switch (usbresp.original_request.bRequest)
        {
            /* GET_REPORT */
            case 0x01:
            {
                /* Data phase is min of report and wLength */
                uint8 *ptr = SinkMap(resp) + SinkClaim(resp,8);
                memset(ptr, 0, 8);
                ptr[0] = last_request;
                ptr[1] = 0; /* ok */

                /* Follow */
                switch (last_request)
                {
                    /* Get state */
                    case 1: 
                    {
                        ptr[2] = (uint8) theApp->a2dpState; /* A2DP state */
                        ptr[3] = (uint8) theApp->avrcpState; /* AVRCP state */
                    }
                    break;

                    /* Get remote Bluetooth address */
                    case 2:
                    {
                        ptr[2] = theApp->av_sink_addr.nap >> 8;
                        ptr[3] = theApp->av_sink_addr.nap & 0xff;
                        ptr[4] = theApp->av_sink_addr.uap;
                        ptr[5] = theApp->av_sink_addr.lap >> 16;
                        ptr[6] = (uint8) theApp->av_sink_addr.lap >> 8;
                        ptr[7] = theApp->av_sink_addr.lap & 0xff;
                    }
                    break;

                    case 3:
                    case 4:
                        /* No specific responses, just return ok */
                        break;

                    case 5:
                    {
                        ptr[2] = 1; /* SBC */
                        ptr[3] = 0;	/* The app no longer stores this info. */
                        ptr[4] = 0; /* The app no longer stores this info. */
                    }
                    break;

                    default:
                        ptr[1] = 1; /* Error */
                }

                /* 8 byte report returned */
                usbresp.data_length = 8;
                usbresp.success = TRUE;
            }
            break;

            /* SET_REPORT */
            case 0x09:
            {
                if (usbresp.original_request.wLength == 8)
                {
                    /* Store the request type so we can respond on the GET */
                    last_request = SourceMap(req)[0];
            
                    /* Process command */
                    if (last_request == 3)
                    {
                        /* Initiate discovery */
                        MessageSend((Task) &theApp->task, APP_DISCOVER_REQ, 0);
                    }
                    else if (last_request == 4)
                    {
                        /* DFU - switch to boot mode 0 */
                        BootSetMode(0);
                    }

                    usbresp.success = TRUE;
                }
            }
            break;

            default:
                break;
        }

        /* Send response */
        if (usbresp.data_length)
        {
            (void) SinkFlushHeader(resp, usbresp.data_length, (uint16 *) &usbresp, sizeof(UsbResponse));
        }
        else
        {
            /* Sink packets can never be zero-length, so flush a dummy byte */
            (void) SinkClaim(resp, 1);
            (void) SinkFlushHeader(resp, 1, (uint16 *) &usbresp, sizeof(UsbResponse));          
        }   

        /* Discard the original request */
        SourceDrop(req, packet_size);
    }
}


/****************************************************************************
NAME    
    a2dpSdSendHidButton
    
DESCRIPTION
    Presses and releases the specified HID button to simulate a key press.

RETURNS
    void
*/
static void a2dpSdSendHidButton(uint8 button)
{
    uint8 *ptr;

    /* Get the sink */
    Sink sink = StreamUsbEndPointSink(end_point_int_out);   

    /* Button down - copy data into sink and flush it */
    (void) SinkClaim(sink, 1);
    ptr = SinkMap(sink);
    ptr[0] = button;
    (void) SinkFlush(sink, 1);

    /* Button up - - copy data into sink and flush it */
    (void) SinkClaim(sink, 1);
    ptr = SinkMap(sink);
    ptr[0] = 0x00;
    (void) SinkFlush(sink, 1);
}

/****************************************************************************
NAME    
    a2dpSdHandleButtons
    
DESCRIPTION
    Processes a received button press from the remote end

RETURNS
    void
*/
void a2dpSdHandleButtons(avc_operation_id opid, bool state)
{
	/* Convert the AVRCP event to HID */
	if (!state)
	{
   		if (opid == opid_pause)
   	 	{
        	a2dpSdSendHidButton(HID_PLAYPAUSE);
   		}
   		else if (opid == opid_play)
  		{
        	a2dpSdSendHidButton(HID_PLAYPAUSE);
    	}
        else if (opid == opid_forward)
    	{
        	a2dpSdSendHidButton(HID_TRACK_FORWARD);
    	}
    	else if (opid == opid_backward)
    	{
       		a2dpSdSendHidButton(HID_TRACK_BACKWARD);
    	}
    	else if (opid == opid_stop)
    	{
       		a2dpSdSendHidButton(HID_STOP);
    	}
	}
}


/****************************************************************************
NAME    
	a2dpSdConnectInterfaceToKalimba
    
DESCRIPTION
	Connect Interface Source into Kalimba Sink

RETURNS
    void
*/
void a2dpSdConnectInterfaceToKalimba()
{
	(void) StreamConnect(PanicNull(StreamUsbEndPointSource(end_point_iso_in)), StreamKalimbaSink(0));
}

/****************************************************************************
NAME    
	a2dpSdHandleCodecSettingsInd
    
DESCRIPTION
	Not used	

RETURNS
    void
*/
void a2dpSdHandleCodecSettingsInd(const a2dpSourceDongleTaskData *theApp, uint32 rate)
{	
	rate = rate;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -