/**************************************************************************** NAME usbAudioRoute DESCRIPTION Connect USB audio stream RETURNS void */ void usbAudioRoute(void) { AudioPluginFeatures features; Sink sink; Source source; uint16 sampleFreq; UsbDeviceClassGetValue(USB_DEVICE_CLASS_GET_VALUE_AUDIO_SOURCE, (uint16*)(&source)); /* Note: UsbDeviceClassGetValue uses uint16 which limits max value of sample frequency to 64k (uint 16 has range 0->65536) */ UsbDeviceClassGetValue(USB_DEVICE_CLASS_GET_VALUE_SAMPLE_FREQ, &sampleFreq); sink = StreamSinkFromSource(source); /* determine additional features applicable for this audio plugin */ features.stereo = (AUDIO_PLUGIN_FORCE_STEREO || theSink.features.stereo); features.use_i2s_output = theSink.features.UseI2SOutputCapability; USB_DEBUG(("USB: Audio ")); /* Check Audio configured (sink will be NULL if VM USB not enabled) */ if(USB_CLASS_ENABLED(USB_DEVICE_CLASS_AUDIO) && sink) { USB_DEBUG(("Configured ")); if(usbAudioIsAttached()) { USB_DEBUG(("Attached\n")); if(theSink.routed_audio != sink) { Task plugin; AUDIO_MODE_T mode; uint16 volume = usbGetVolume(&mode); const usb_plugin_info* plugin_info = usbAudioGetPluginInfo(&plugin, theSink.usb.config.plugin_type, theSink.usb.config.plugin_index); theSink.routed_audio = sink; UsbDeviceClassGetValue(USB_DEVICE_CLASS_GET_VALUE_AUDIO_SINK, (uint16*)(&theSink.cvc_params.usb_params.usb_sink)); /* Make sure we're using correct parameters for USB */ theSink.a2dp_link_data->a2dp_audio_connect_params.mode_params = &theSink.a2dp_link_data->a2dp_audio_mode_params; USB_DEBUG(("USB: Connect 0x%X 0x%X", (uint16)sink, (uint16)(theSink.cvc_params.usb_params.usb_sink))); #ifdef ENABLE_SUBWOOFER /* set the sub woofer link type prior to passing to audio connect */ theSink.a2dp_link_data->a2dp_audio_connect_params.sub_woofer_type = AUDIO_SUB_WOOFER_NONE; theSink.a2dp_link_data->a2dp_audio_connect_params.sub_sink = NULL; /* bits inverted in dsp plugin */ sinkAudioSetEnhancement(MUSIC_CONFIG_SUB_WOOFER_BYPASS,TRUE); #else /* no subwoofer support, set the sub woofer bypass bit in music config message sent o dsp */ sinkAudioSetEnhancement(MUSIC_CONFIG_SUB_WOOFER_BYPASS,FALSE); #endif /* use a2dp connect parameters */ /* sample frequency is not fixed so read this from usb library */ if(plugin_info->plugin_type == usb_plugin_stereo) AudioConnect(plugin, sink, AUDIO_SINK_USB, theSink.codec_task, volume, sampleFreq, features, mode, 0, powerManagerGetLBIPM(), &theSink.a2dp_link_data->a2dp_audio_connect_params, &theSink.task); /* all other plugins use cvc connect parameters */ else AudioConnect(plugin, sink, AUDIO_SINK_USB, theSink.codec_task, volume, sampleFreq, features, mode, 0, powerManagerGetLBIPM(), &theSink.cvc_params, &theSink.task); } } } USB_DEBUG(("\n")); }
/**************************************************************************** NAME usbAudioSinkMatch DESCRIPTION Compare sink to the USB audio sink RETURNS TRUE if sink matches USB audio sink, otherwise FALSE */ bool usbAudioSinkMatch(Sink sink) { Source usb_source = NULL; UsbDeviceClassGetValue(USB_DEVICE_CLASS_GET_VALUE_AUDIO_SOURCE, (uint16*)&usb_source); USB_DEBUG(("USB: usbAudioSinkMatch sink %x = %x, enabled = %x\n", (uint16)sink , (uint16)StreamSinkFromSource(usb_source), USB_CLASS_ENABLED(USB_DEVICE_CLASS_AUDIO) )); return (USB_CLASS_ENABLED(USB_DEVICE_CLASS_AUDIO) && sink && (sink == StreamSinkFromSource(usb_source))); }
Source avrcpSourceFromData(AVRCP *avrcp, uint8 *data, uint16 length) { /* Create a source from the data */ Source src = StreamRegionSource(data, length); /* Register a task for freeing the data and store a ptr to it */ avrcp->dataFreeTask.sent_data = data; MessageSinkTask(StreamSinkFromSource(src), &avrcp->dataFreeTask.cleanUpTask); return src; }
/**************************************************************************** NAME usbGetAudioSink DESCRIPTION check USB state and return sink if available RETURNS sink if available, otherwise 0 */ Sink usbGetAudioSink(void) { Source usb_source = NULL; Sink sink = NULL; UsbDeviceClassGetValue(USB_DEVICE_CLASS_GET_VALUE_AUDIO_SOURCE, (uint16*)&usb_source); /* if the usb lead is attached and the speaker is active, try to obtain the audio sink */ if((usbAudioIsAttached())&&(theSink.usb.spkr_active)) { /* attempt to obtain USB audio sink */ sink = StreamSinkFromSource(usb_source); USB_DEBUG(("USB: usbGetAudioSink sink %x, enabled = %x\n", (uint16)sink , USB_CLASS_ENABLED(USB_DEVICE_CLASS_AUDIO) )); } /* USB not attached */ else USB_DEBUG(("USB: usbGetAudioSink sink %x, enabled = %x, speaker active = %x\n", (uint16)sink , USB_CLASS_ENABLED(USB_DEVICE_CLASS_AUDIO), theSink.usb.spkr_active )); return sink; }
void a2dpProfileHandler(Task task, MessageId id, Message message) { switch (id) { case A2DP_INTERNAL_L2CAP_CONNECT_REQ + 0: case A2DP_INTERNAL_L2CAP_CONNECT_REQ + 1: case A2DP_INTERNAL_L2CAP_CONNECT_REQ + 2: case A2DP_INTERNAL_L2CAP_CONNECT_REQ + 3: case A2DP_INTERNAL_L2CAP_CONNECT_REQ + 4: case A2DP_INTERNAL_L2CAP_CONNECT_REQ + 5: case A2DP_INTERNAL_L2CAP_CONNECT_REQ + 6: PRINT(("A2DP_INTERNAL_L2CAP_CONNECT_REQ\n")); a2dpHandleL2capConnectReq((A2DP_INTERNAL_L2CAP_CONNECT_REQ_T *) message); break; case A2DP_INTERNAL_SIGNALLING_CONNECT_REQ: PRINT(("A2DP_INTERNAL_SIGNALLING_CONNECT_REQ\n")); a2dpHandleSignallingConnectReq((A2DP_INTERNAL_SIGNALLING_CONNECT_REQ_T *) message); break; case A2DP_INTERNAL_SIGNALLING_CONNECT_RES: PRINT(("A2DP_INTERNAL_SIGNALLING_CONNECT_RES\n")); a2dpHandleSignallingConnectRes((A2DP_INTERNAL_SIGNALLING_CONNECT_RES_T *) message); break; case A2DP_INTERNAL_SIGNALLING_DISCONNECT_REQ: PRINT(("A2DP_INTERNAL_SIGNALLING_DISCONNECT_REQ\n")); a2dpHandleSignallingDisconnectReq((A2DP_INTERNAL_SIGNALLING_DISCONNECT_REQ_T *) message); break; case A2DP_INTERNAL_CODEC_CONFIGURE_RSP: PRINT(("A2DP_INTERNAL_CODEC_CONFIGURE_RSP\n")); a2dpHandleCodecConfigureResponse((A2DP_INTERNAL_CODEC_CONFIGURE_RSP_T *) message); break; case A2DP_INTERNAL_MEDIA_OPEN_REQ: PRINT(("A2DP_INTERNAL_OPEN_REQ\n")); a2dpStreamEstablish((A2DP_INTERNAL_MEDIA_OPEN_REQ_T *) message); break; case A2DP_INTERNAL_MEDIA_OPEN_RES: PRINT(("A2DP_INTERNAL_OPEN_RES\n")); a2dpStreamOpenResponse((A2DP_INTERNAL_MEDIA_OPEN_RES_T *) message); break; case A2DP_INTERNAL_MEDIA_START_REQ: PRINT(("A2DP_INTERNAL_START_REQ\n")); a2dpStreamStart((A2DP_INTERNAL_MEDIA_START_REQ_T *) message); break; case A2DP_INTERNAL_MEDIA_START_RES: PRINT(("A2DP_INTERNAL_START_RES\n")); a2dpStreamStartResponse((A2DP_INTERNAL_MEDIA_START_RES_T *) message); break; case A2DP_INTERNAL_MEDIA_SUSPEND_REQ: PRINT(("A2DP_INTERNAL_MEDIA_SUSPEND_REQ\n")); a2dpStreamSuspend((A2DP_INTERNAL_MEDIA_SUSPEND_REQ_T *) message); break; case A2DP_INTERNAL_MEDIA_CLOSE_REQ: PRINT(("A2DP_INTERNAL_MEDIA_CLOSE_REQ\n")); a2dpStreamRelease((A2DP_INTERNAL_MEDIA_CLOSE_REQ_T *) message); break; case A2DP_INTERNAL_MEDIA_RECONFIGURE_REQ: PRINT(("A2DP_INTERNAL_MEDIA_RECONFIGURE_REQ\n")); a2dpStreamReconfigure((A2DP_INTERNAL_MEDIA_RECONFIGURE_REQ_T *) message); break; case A2DP_INTERNAL_MEDIA_AV_SYNC_DELAY_REQ: PRINT(("A2DP_INTERNAL_MEDIA_AV_SYNC_DELAY_REQ\n")); a2dpStreamDelayReport(((A2DP_INTERNAL_MEDIA_AV_SYNC_DELAY_REQ_T *)message)->device, ((A2DP_INTERNAL_MEDIA_AV_SYNC_DELAY_REQ_T *)message)->delay); break; case A2DP_INTERNAL_MEDIA_AV_SYNC_DELAY_RES: PRINT(("A2DP_INTERNAL_MEDIA_AV_SYNC_DELAY_RES\n")); a2dpStreamDelayReport(((A2DP_INTERNAL_MEDIA_AV_SYNC_DELAY_RES_T *)message)->device, ((A2DP_INTERNAL_MEDIA_AV_SYNC_DELAY_RES_T *)message)->delay); break; case A2DP_INTERNAL_LINKLOSS_TIMEOUT_BASE + 0: case A2DP_INTERNAL_LINKLOSS_TIMEOUT_BASE + 1: case A2DP_INTERNAL_LINKLOSS_TIMEOUT_BASE + 2: case A2DP_INTERNAL_LINKLOSS_TIMEOUT_BASE + 3: case A2DP_INTERNAL_LINKLOSS_TIMEOUT_BASE + 4: case A2DP_INTERNAL_LINKLOSS_TIMEOUT_BASE + 5: case A2DP_INTERNAL_LINKLOSS_TIMEOUT_BASE + 6: PRINT(("A2DP_INTERNAL_LINKLOSS_TIMEOUT\n")); a2dpHandleL2capLinklossTimeout(id); break; case A2DP_INTERNAL_CLIENT_RSP_TIMEOUT_BASE + 0: case A2DP_INTERNAL_CLIENT_RSP_TIMEOUT_BASE + 1: case A2DP_INTERNAL_CLIENT_RSP_TIMEOUT_BASE + 2: case A2DP_INTERNAL_CLIENT_RSP_TIMEOUT_BASE + 3: case A2DP_INTERNAL_CLIENT_RSP_TIMEOUT_BASE + 4: case A2DP_INTERNAL_CLIENT_RSP_TIMEOUT_BASE + 5: case A2DP_INTERNAL_CLIENT_RSP_TIMEOUT_BASE + 6: PRINT(("A2DP_INTERNAL_CLIENT_RSP_TIMEOUT\n")); a2dpHandleInternalClientRspTimeout(id); break; case A2DP_INTERNAL_REMOTE_CMD_TIMEOUT_BASE + 0: case A2DP_INTERNAL_REMOTE_CMD_TIMEOUT_BASE + 1: case A2DP_INTERNAL_REMOTE_CMD_TIMEOUT_BASE + 2: case A2DP_INTERNAL_REMOTE_CMD_TIMEOUT_BASE + 3: case A2DP_INTERNAL_REMOTE_CMD_TIMEOUT_BASE + 4: case A2DP_INTERNAL_REMOTE_CMD_TIMEOUT_BASE + 5: case A2DP_INTERNAL_REMOTE_CMD_TIMEOUT_BASE + 6: PRINT(("A2DP_INTERNAL_REMOTE_CMD_TIMEOUT\n")); a2dpHandleInternalRemoteCmdTimeout(id); break; case A2DP_INTERNAL_WATCHDOG_BASE + 0: case A2DP_INTERNAL_WATCHDOG_BASE + 1: case A2DP_INTERNAL_WATCHDOG_BASE + 2: case A2DP_INTERNAL_WATCHDOG_BASE + 3: case A2DP_INTERNAL_WATCHDOG_BASE + 4: case A2DP_INTERNAL_WATCHDOG_BASE + 5: case A2DP_INTERNAL_WATCHDOG_BASE + 6: PRINT(("A2DP_INTERNAL_WATCHDOG_IND\n")); a2dpHandleInternalWatchdogTimeout(id); break; #if 0 case A2DP_INTERNAL_RECONFIGURE_REQ: PRINT(("A2DP_INTERNAL_RECONFIGURE_REQ\n")); a2dpHandleReconfigureReq((A2DP_INTERNAL_RECONFIGURE_REQ_T *) message); break; #endif #if 0 case A2DP_INTERNAL_SEND_CODEC_PARAMS_REQ: PRINT(("A2DP_INTERNAL_SEND_CODEC_PARAMS_REQ\n")); a2dpSendCodecAudioParams(); if (((A2DP_INTERNAL_SEND_CODEC_PARAMS_REQ_T *) message)->send_reconfigure_message) a2dpSendReconfigureCfm(a2dp_success); break; #endif #if 0 case A2DP_INTERNAL_GET_CAPS_TIMEOUT_IND: PRINT(("A2DP_INTERNAL_GET_CAPS_TIMEOUT_IND\n")); a2dpGetCapsTimeout(); break; #endif default: switch(id) { case CL_SDP_REGISTER_CFM: PRINT(("CL_SDP_REGISTER_CFM\n")); a2dpHandleSdpRegisterCfm((CL_SDP_REGISTER_CFM_T *) message); break; case CL_L2CAP_REGISTER_CFM: PRINT(("CL_L2CAP_REGISTER_CFM\n")); a2dpHandleL2capRegisterCfm((CL_L2CAP_REGISTER_CFM_T *) message); break; case CL_L2CAP_CONNECT_IND: PRINT(("CL_L2CAP_CONNECT_IND\n")); a2dpHandleL2capConnectInd((CL_L2CAP_CONNECT_IND_T *) message); break; case CL_L2CAP_CONNECT_CFM: PRINT(("CL_L2CAP_CONNECT_CFM\n")); a2dpHandleL2capConnectCfm((CL_L2CAP_CONNECT_CFM_T *) message); break; case CL_L2CAP_DISCONNECT_IND: PRINT(("CL_L2CAP_DISCONNECT_IND\n")); a2dpHandleL2capDisconnect(((CL_L2CAP_DISCONNECT_IND_T *)message)->identifier, ((CL_L2CAP_DISCONNECT_IND_T *)message)->sink, ((CL_L2CAP_DISCONNECT_IND_T *)message)->status); ConnectionL2capDisconnectResponse(((CL_L2CAP_DISCONNECT_IND_T *)message)->identifier, ((CL_L2CAP_DISCONNECT_IND_T *)message)->sink); break; case CL_L2CAP_DISCONNECT_CFM: PRINT(("CL_L2CAP_DISCONNECT_CFM\n")); a2dpHandleL2capDisconnect(0, ((CL_L2CAP_DISCONNECT_CFM_T *)message)->sink, ((CL_L2CAP_DISCONNECT_CFM_T *)message)->status); break; case CL_SM_ENCRYPTION_CHANGE_IND: PRINT(("CL_SM_ENCRYPTION_CHANGE_IND\n")); /* We have received an indication that the encryption status of the sink has changed */ sendEncryptionChangeInd((CL_SM_ENCRYPTION_CHANGE_IND_T *) message); break; case CL_DM_ROLE_CFM: case CL_SM_ENCRYPTION_KEY_REFRESH_IND: case CL_L2CAP_TIMEOUT_IND: break; case CL_SDP_SERVICE_SEARCH_ATTRIBUTE_CFM: a2dpHandleSdpServiceSearchAttributeCfm ((CL_SDP_SERVICE_SEARCH_ATTRIBUTE_CFM_T *)message); break; default: switch(id) { case MESSAGE_MORE_DATA: PRINT(("MESSAGE_MORE_DATA\n")); /* Data has arrived on the signalling channel */ a2dpHandleSignalPacket( a2dpFindDeviceFromSink( StreamSinkFromSource(((MessageMoreData *)message)->source) )); break; case MESSAGE_MORE_SPACE: case MESSAGE_STREAM_DISCONNECT: case MESSAGE_SOURCE_EMPTY: break; default: handleUnexpected(id); break; } } } }
void swatHandleSwatSignallingData(Source source) { uint16 packet_size, data_size; const uint8 *ptr = SourceMap(source); /* Get the device that sent the signalling data */ remoteDevice* device = swatFindDeviceFromSink( StreamSinkFromSource(source) ); packet_size = SourceSize(source); /* Process each signalling packet in the source (may be more than one signal in the source) */ while(packet_size >= PKT_PAYLOAD) { /* calculate size of packet */ data_size = ((ptr[PKT_PAYLOAD_LEN] & 0x7f) + 3); /* Process the signalling data by the remote device */ switch(ptr[PKT_SIGNAL_ID]) { /*****************************************************************************/ case SWAT_OPEN: { /* send to command handler, include message payload */ MAKE_SWAT_MESSAGE_WITH_LEN(SWAT_COMMAND_OPEN, data_size); message->device = device; memmove(&message->data[0], &ptr[0], data_size); /* If message is a response, send immediatley, otherwise add to queue */ if (ptr[PKT_SIGNAL_TYPE] == SWAT_RSP) { MessageSend(&swat->command_task, SWAT_COMMAND_OPEN, message); } else { SWAT_DEBUG(("[SWAT] SWAT_OPEN_CMD [%x]\n", device->signalling_block)); /* Action the message or add to queue if already handling another message */ MessageSendConditionally(&swat->command_task, SWAT_COMMAND_OPEN, message, &device->signalling_block); } /* command actioned, discard buffer data leaving any additional data behind */ SourceDrop(source, data_size); /* having removed a packet reset the pointer to the start of any more packets */ ptr = SourceMap(source); } break; /*****************************************************************************/ case SWAT_CLOSE: { /* send to command handler, include message payload */ MAKE_SWAT_MESSAGE_WITH_LEN(SWAT_COMMAND_CLOSE, data_size); message->device = device; memmove(&message->data[0], &ptr[0], data_size); /* If message is a response, send immediatley, otherwise add to queue */ if (ptr[PKT_SIGNAL_TYPE] == SWAT_RSP) { MessageSend(&swat->command_task, SWAT_COMMAND_CLOSE, message); } else { SWAT_DEBUG(("[SWAT] SWAT_CLOSE_CMD [%x]\n", device->signalling_block)); /* Action the message or add to queue if already handling another message */ MessageSendConditionally(&swat->command_task, SWAT_COMMAND_CLOSE, message, &device->signalling_block); } /* command actioned, discard buffer data leaving any additional data behind */ SourceDrop(source, data_size); /* having removed a packet reset the pointer to the start of any more packets */ ptr = SourceMap(source); } break; /*****************************************************************************/ case SWAT_START: { /* send to command handler, include message payload */ MAKE_SWAT_MESSAGE_WITH_LEN(SWAT_COMMAND_START, data_size); message->device = device; memmove(&message->data[0], &ptr[0], data_size); /* If message is a response, send immediatley, otherwise add to queue */ if (ptr[PKT_SIGNAL_TYPE] == SWAT_RSP) { MessageSend(&swat->command_task, SWAT_COMMAND_START, message); } else { SWAT_DEBUG(("[SWAT] SWAT_START_CMD [%x]\n", device->signalling_block)); /* Action the message or add to queue if already handling another message */ MessageSendConditionally(&swat->command_task, SWAT_COMMAND_START, message, &device->signalling_block); } /* command actioned, discard buffer data leaving any additional data behind */ SourceDrop(source, data_size); /* having removed a packet reset the pointer to the start of any more packets */ ptr = SourceMap(source); } break; /*****************************************************************************/ case SWAT_SUSPEND: { /* send to command handler, include message payload */ MAKE_SWAT_MESSAGE_WITH_LEN(SWAT_COMMAND_SUSPEND, data_size); message->device = device; memmove(&message->data[0], &ptr[0], data_size); /* If message is a response, send immediatley, otherwise add to queue */ if (ptr[PKT_SIGNAL_TYPE] == SWAT_RSP) { MessageSend(&swat->command_task, SWAT_COMMAND_SUSPEND, message); } else { SWAT_DEBUG(("[SWAT] SWAT_SUSPEND_CMD [%x]\n", device->signalling_block)); /* Action the message or add to queue if already handling another message */ MessageSendConditionally(&swat->command_task, SWAT_COMMAND_SUSPEND, message, &device->signalling_block); } /* command actioned, discard buffer data leaving any additional data behind */ SourceDrop(source, data_size); /* having removed a packet reset the pointer to the start of any more packets */ ptr = SourceMap(source); } break; /*****************************************************************************/ case SWAT_SET_VOLUME: { /* send to command handler, include message payload */ MAKE_SWAT_MESSAGE_WITH_LEN(SWAT_COMMAND_SET_VOLUME, data_size); message->device = device; memmove(&message->data[0], &ptr[0], data_size); /* If message is a response, send immediatley, otherwise add to queue */ if (ptr[PKT_SIGNAL_TYPE] == SWAT_RSP) { MessageSend(&swat->command_task, SWAT_COMMAND_SET_VOLUME, message); } else { SWAT_DEBUG(("[SWAT] SWAT_SET_VOLUME_CMD [%x]\n", device->signalling_block)); /* Action the message or add to queue if already handling another message */ MessageSendConditionally(&swat->command_task, SWAT_COMMAND_SET_VOLUME, message, &device->signalling_block); } /* command actioned, discard buffer data leaving any additional data behind */ SourceDrop(source, data_size); /* having removed a packet reset the pointer to the start of any more packets */ ptr = SourceMap(source); } break; /*****************************************************************************/ case SWAT_SAMPLE_RATE: { /* send to command handler, include message payload */ MAKE_SWAT_MESSAGE_WITH_LEN(SWAT_COMMAND_SAMPLE_RATE, data_size); message->device = device; memmove(&message->data[0], &ptr[0], data_size); /* If message is a response, send immediatley, otherwise add to queue */ if (ptr[PKT_SIGNAL_TYPE] == SWAT_RSP) { MessageSend(&swat->command_task, SWAT_COMMAND_SAMPLE_RATE, message); } else { SWAT_DEBUG(("[SWAT] SWAT_SAMPLE_RATE_CMD [%x]\n", device->signalling_block)); /* Action the message or add to queue if already handling another message */ MessageSendConditionally(&swat->command_task, SWAT_COMMAND_SAMPLE_RATE, message, &device->signalling_block); } /* Command actioned, discard buffer data leaving any additional data behind */ SourceDrop(source, data_size); /* Having removed a packet reset the pointer to the start of any more packets */ ptr = SourceMap(source); } break; /*****************************************************************************/ case SWAT_GET_VERSION: { /* send to command handler, include message payload */ MAKE_SWAT_MESSAGE_WITH_LEN(SWAT_COMMAND_GET_VERSION, data_size); message->device = device; memmove(&message->data[0], &ptr[0], data_size); /* If message is a response, send immediatley, otherwise add to queue */ if (ptr[PKT_SIGNAL_TYPE] == SWAT_RSP) { MessageSend(&swat->command_task, SWAT_COMMAND_GET_VERSION, message); } else { SWAT_DEBUG(("[SWAT] SWAT_COMMAND_GET_VERSION [%x]\n", device->signalling_block)); /* Action the message or add to queue if already handling another message */ MessageSendConditionally(&swat->command_task, SWAT_COMMAND_GET_VERSION, message, &device->signalling_block); } /* Command actioned, discard buffer data leaving any additional data behind */ SourceDrop(source, data_size); /* Having removed a packet reset the pointer to the start of any more packets */ ptr = SourceMap(source); } break; /*****************************************************************************/ case SWAT_GENERAL_REJECT: { /* send to command handler, include message payload */ MAKE_SWAT_MESSAGE_WITH_LEN(SWAT_COMMAND_GENERAL_REJECT, data_size); message->device = device; memmove(&message->data[0], &ptr[0], data_size); /* Handle the GENERAL_REJECT command as it won't affect ongoing operations */ MessageSend(&swat->command_task, SWAT_COMMAND_GENERAL_REJECT, message); /* command actioned, discard buffer data leaving any additional data behind */ SourceDrop(source, data_size); /* having removed a packet reset the pointer to the start of any more packets */ ptr = SourceMap(source); } break; /*****************************************************************************/ default: { /* send to command handler, include message payload */ MAKE_SWAT_MESSAGE(SWAT_COMMAND_DEFAULT); message->device = device; MessageSend(&swat->command_task, SWAT_COMMAND_DEFAULT, message); /* block any more signalling commands until current process has completed */ device->signalling_block = DATA_BLOCK; /* Discard entire buffer as got out of sync */ SourceDrop(source, packet_size); } } /* recalculate the packet size of any data left in the source */ packet_size = SourceSize(source); } }
static void handleHidClassRequest(Source source, usb_device_class_type class_type) { static uint8 idle_rate = 0; { Sink sink = StreamSinkFromSource(source); uint16 packet_size; while ((packet_size = SourceBoundary(source)) != 0) { /* Build the respnse. It must contain the original request, so copy from the source header. */ UsbResponse resp; memcpy(&resp.original_request, SourceMapHeader(source), sizeof(UsbRequest)); /* Set the response fields to default values to make the code below simpler */ resp.success = FALSE; resp.data_length = 0; switch (resp.original_request.bRequest) { /* GET_REPORT */ case 0x01: { PRINT(("USB: HID Get_Report src=0x%X wValue=0x%X wIndex=0x%X wLength=0x%X\n", (uint16)source, resp.original_request.wValue, resp.original_request.wIndex, resp.original_request.wLength)); break; } /* GET_IDLE */ case 0x02: { uint8 *out; if ((out = claimSink(sink, 1)) != 0) { PRINT(("USB: HID Get_Idle src=0x%X wValue=0x%X wIndex=0x%X\n", (uint16)source, resp.original_request.wValue, resp.original_request.wIndex)); out[0] = idle_rate; resp.success = TRUE; resp.data_length = 1; } break; } /* SET_REPORT */ case 0x09: { const uint8 *in = SourceMap(source); uint16 size_data = resp.original_request.wLength; uint8 report_id = resp.original_request.wValue & 0xff; PRINT(("USB: HID Set_Report src=0x%X wValue=0x%X wIndex=0x%X wLength=0x%X -> \n", (uint16)source, resp.original_request.wValue, resp.original_request.wIndex, resp.original_request.wLength)); resp.success = TRUE; if (size_data) { if (class_type == USB_DEVICE_CLASS_TYPE_HID_CONSUMER_TRANSPORT_CONTROL) { USB_DEVICE_CLASS_MSG_REPORT_IND_T *message = PanicUnlessMalloc(sizeof(USB_DEVICE_CLASS_MSG_REPORT_IND_T) + size_data); uint16 source_size = SourceSize(source); PRINT((" send report ind source_size[0x%x]\n", source_size)); message->class_type = class_type; message->report_id = report_id; message->size_report = size_data; in = SourceMap(source); if (source_size < message->size_report) { message->size_report = source_size; } memmove(message->report, in, message->size_report); MessageSend(device->app_task, USB_DEVICE_CLASS_MSG_REPORT_IND, message); PRINT((" sent report ind to Task [0x%x]\n", (uint16)device->app_task)); } } break; } /* SET_IDLE */ case 0x0A: { PRINT(("USB: HID Set_Idle src=0x%X wValue=0x%X wIndex=0x%X\n", (uint16)source, resp.original_request.wValue, resp.original_request.wIndex)); idle_rate = resp.original_request.wValue >> 8; resp.success = TRUE; break; } default: { PRINT(("USB: HID req=0x%X src=0x%X wValue=0x%X wIndex=0x%X wLength=0x%X\n", resp.original_request.bRequest, (uint16)source, resp.original_request.wValue, resp.original_request.wIndex, resp.original_request.wLength)); break; } } /* Send response */ if (resp.data_length) { (void)SinkFlushHeader(sink, resp.data_length, (uint16 *)&resp, sizeof(UsbResponse)); } else { /* Sink packets can never be zero-length, so flush a dummy byte */ (void) SinkClaim(sink, 1); (void) SinkFlushHeader(sink, 1, (uint16 *) &resp, sizeof(UsbResponse)); } /* Discard the original request */ SourceDrop(source, packet_size); } } }
void ConnectionHandleComplexMessage(Task task, MessageId id, Message message) { switch (id) { case CL_L2CAP_CONNECT_IND: { CL_L2CAP_CONNECT_IND_T *original; CL_L2CAP_CONNECT_IND_TEST_EXTRA_T *new_msg = malloc(sizeof(CL_L2CAP_CONNECT_IND_TEST_EXTRA_T)); original = (CL_L2CAP_CONNECT_IND_T *) message; new_msg->bd_addr = original->bd_addr; new_msg->psm = original->psm; new_msg->cid = original->connection_id; new_msg->identifier = original->identifier; new_msg->task = (uint16) task; MessageSend(task, CL_L2CAP_CONNECT_IND_TEST_EXTRA, new_msg); } break; case CL_L2CAP_CONNECT_CFM: { CL_L2CAP_CONNECT_CFM_T *original; CL_L2CAP_CONNECT_CFM_TEST_EXTRA_T *new_msg = malloc(sizeof(CL_L2CAP_CONNECT_CFM_TEST_EXTRA_T)); original = (CL_L2CAP_CONNECT_CFM_T *) message; new_msg->status = original->status; new_msg->psm_local = original->psm_local; new_msg->sink = original->sink; new_msg->connection_id = original->connection_id; new_msg->mtu_remote = original->mtu_remote; new_msg->flush_timeout_remote = original->flush_timeout_remote; new_msg->qos_remote = original->qos_remote; new_msg->flow_mode = original->mode; new_msg->task = (uint16) MessageSinkGetTask(original->sink); MessageSend(task, CL_L2CAP_CONNECT_CFM_TEST_EXTRA, new_msg); } break; case MESSAGE_MORE_DATA: { Source src = ((MessageMoreData*)message)->source; CL_SYSTEM_MORE_DATA_TEST_EXTRA_T *pdu; const uint8 *s = SourceMap(src); uint16 len = SourceBoundary(src); uint16 datalen=len; /* Do not allow large data more than 512 ..Just Limit to * 128 bytes. */ if(len > 128) len=128; pdu = malloc(sizeof(CL_SYSTEM_MORE_DATA_TEST_EXTRA_T)+len); memset(pdu, 0, sizeof(CL_SYSTEM_MORE_DATA_TEST_EXTRA_T)); pdu->sink = StreamSinkFromSource(src); pdu->size_data = datalen; memmove(pdu->data, s, len); SourceDrop(src, datalen); MessageSend(task, CL_SYSTEM_MORE_DATA_TEST_EXTRA, pdu); } break; case MESSAGE_MORE_SPACE: case MESSAGE_SOURCE_EMPTY: break; case CL_SM_READ_LOCAL_OOB_DATA_CFM: { /* Create new message */ CL_SM_READ_LOCAL_OOB_DATA_CFM_T *original; CL_SM_READ_LOCAL_OOB_DATA_CFM_TEST_EXTRA_T *new_msg = malloc( sizeof(CL_SM_READ_LOCAL_OOB_DATA_CFM_TEST_EXTRA_T) + (2 * CL_SIZE_OOB_DATA) ); original = (CL_SM_READ_LOCAL_OOB_DATA_CFM_T*)message; /* Copy over the status */ new_msg->status = original->status; /* Copy over transport */ new_msg->transport = original->transport; /* Copy over what type of OOB data is present */ new_msg->oob_data_present = original->oob_data; /* Set size */ new_msg->size_oob_data = 2*CL_SIZE_OOB_DATA; /* Copy over the OOB data */ memmove( new_msg->oob_data, original->oob_hash_c, CL_SIZE_OOB_DATA ); memmove( new_msg->oob_data+CL_SIZE_OOB_DATA, original->oob_rand_r, CL_SIZE_OOB_DATA ); /* Send it to the app */ MessageSend( task, CL_SM_READ_LOCAL_OOB_DATA_CFM_TEST_EXTRA, new_msg ); } break; /* Flatten CL_SM_GET_INDEXED_ATTRIBUTE_CFM */ case CL_SM_GET_INDEXED_ATTRIBUTE_CFM: { CL_SM_GET_INDEXED_ATTRIBUTE_CFM_T *original = (CL_SM_GET_INDEXED_ATTRIBUTE_CFM_T *) message; CL_SM_GET_INDEXED_ATTRIBUTE_CFM_TEST_EXTRA_T *new_msg = malloc( sizeof(CL_SM_GET_INDEXED_ATTRIBUTE_CFM_TEST_EXTRA_T) + (original->size_psdata * sizeof(uint8)) - 1 /* for the psdata array of 1 */ ); new_msg->status = original->status; new_msg->type = original->taddr.type; new_msg->bd_addr = original->taddr.addr; new_msg->size_psdata = original->size_psdata; memmove(new_msg->psdata, original->psdata, original->size_psdata); /* Send the copied message to the app. */ MessageSend( task, CL_SM_GET_INDEXED_ATTRIBUTE_CFM_TEST_EXTRA, new_msg ); } break; FLATTEN_BDADDR(CL_DM_ACL_OPENED_IND); FLATTEN_BDADDR(CL_DM_ACL_CLOSED_IND); FLATTEN_BDADDR(CL_DM_APT_IND); FLATTEN_BDADDR(CL_SM_USER_PASSKEY_REQ_IND); FLATTEN_BDADDR(CL_SM_USER_PASSKEY_NOTIFICATION_IND); FLATTEN_BDADDR(CL_SM_USER_CONFIRMATION_REQ_IND); FLATTEN_BDADDR(CL_SM_PIN_CODE_IND); FLATTEN_BDADDR(CL_SM_ENCRYPTION_KEY_REFRESH_IND); FLATTEN_BDADDR(CL_SM_ENCRYPTION_CHANGE_IND); FLATTEN_BDADDR(CL_SM_IO_CAPABILITY_REQ_IND); FLATTEN_BDADDR(CL_SM_REMOTE_IO_CAPABILITY_IND); #ifndef DISABLE_BLE /* Flatten the typed_bdaddr parts of the message - grrr! */ case CL_DM_BLE_ADVERTISING_REPORT_IND: { CL_DM_BLE_ADVERTISING_REPORT_IND_T *original = (CL_DM_BLE_ADVERTISING_REPORT_IND_T *)message; CL_DM_BLE_ADVERTISING_REPORT_IND_TEST_EXTRA_T *new_msg = (CL_DM_BLE_ADVERTISING_REPORT_IND_TEST_EXTRA_T *) PanicUnlessMalloc( sizeof(CL_DM_BLE_ADVERTISING_REPORT_IND_TEST_EXTRA_T) + original->size_advertising_data - 1 ); new_msg->num_reports = original->num_reports; new_msg->event_type = original->event_type; new_msg->current_addr_type = original->current_taddr.type; new_msg->current_addr = original->current_taddr.addr; new_msg->permanent_addr_type = original->permanent_taddr.type; new_msg->permanent_addr = original->permanent_taddr.addr; new_msg->rssi = original->rssi; new_msg->size_ad_data = original->size_advertising_data; memmove( new_msg->ad_data, original->advertising_data, original->size_advertising_data ); MessageSend( task, CL_DM_BLE_ADVERTISING_REPORT_IND_TEST_EXTRA, new_msg ); } break; FLATTEN_BDADDR(CL_SM_BLE_SIMPLE_PAIRING_COMPLETE_IND); FLATTEN_BDADDR(CL_DM_BLE_SECURITY_CFM); FLATTEN_BDADDR(CL_DM_BLE_CONFIGURE_LOCAL_ADDRESS_CFM); #endif default: printf("CL_MESSAGE_TOP 0x%X\n", CL_MESSAGE_TOP); printf("CL_SHIM_MESSAGE_TOP 0x%X\n", CL_SHIM_MESSAGE_TOP); printf("Message received id 0x%X\n", id); Panic(); break; } }