static HRESULT avcUnitSignalSourceNotifyUpdateCB(UNION_NOTIFY *notify, pDataStream pStream) { HRESULT hResult = NO_ERROR; SIGNAL_SOURCE_NOTIFY* signalSourceNotify = (SIGNAL_SOURCE_NOTIFY *) notify; hResult = dsWrite8Bits(pStream, signalSourceNotify->data.channel); // operand[0]: channel if (hResult != NO_ERROR) return hResult; hResult = dsWrite16Bits(pStream, 0xFFFF); // operand[1,..,2]: nodeAddr if (hResult != NO_ERROR) return hResult; hResult = dsWrite8Bits(pStream, 0xFF); // operand[3]: oPCR if (hResult != NO_ERROR) return hResult; return hResult; }
HRESULT avcSendResponsePacket(uint32 response, PB *packetBlock) { HRESULT hResult = NO_ERROR; pDataStream pStream = NULL; hResult = pbGetApplicationDatastream(packetBlock, &pStream); if (hResult != NO_ERROR) return hResult; hResult = dsReOpenStream(pStream, dsMODE_WRITE); if (hResult != NO_ERROR) return hResult; hResult = dsWrite8Bits(pStream, (uint8) response); if (hResult != NO_ERROR) return hResult; hResult = avcSendResponse(response, packetBlock); if (hResult != NO_ERROR) return hResult; return hResult; }
HRESULT avcCmdSignalSource(AVC_HEADER *pHeader, PB *packetBlock, pDataStream pStream) { HRESULT hResultError = E_PKT_AVC_NOT_IMPLEMENTED; HRESULT hResult = NO_ERROR; uint8 inByte = 0; uint16 inVal = 0; uint8 dest_su = 0; uint8 dest_plug_id = 0; uint8 source_su = 0; uint8 source_plug_id = 0; uint8 status = 0; AVC_SIGNAL_PATH *path = NULL; switch (pHeader->ctype) { case AVC_CTYPE_NOTIFY: // - : M:Mandatory, R:Recommended, O:Optional, -:Not Defined hResultError = E_PKT_AVC_REJECTED; break; case AVC_CTYPE_STATUS: // - : M:Mandatory, R:Recommended, O:Optional, -:Not Defined hResultError = E_PKT_AVC_REJECTED; // operand[0,1]: 0xFFFF hResult = dsRead16Bits(pStream, &inVal); if (hResult != NO_ERROR) return hResultError; if (inVal != 0xFFFF) return hResultError; // operand[2]: 0xFE hResult = dsRead8Bits(pStream, &inByte); if (hResult != NO_ERROR) return hResultError; if (inByte != 0xFE) return hResultError; // operand[3]: signal_dest_su hResult = dsRead8Bits(pStream, &dest_su); if (hResult != NO_ERROR) return hResultError; // operand[4]: signal_dest_plug_id hResult = dsRead8Bits(pStream, &dest_plug_id); if (hResult != NO_ERROR) return hResultError; // incoming status command has parsed successfully SYS_DEBUG(SYSDEBUG_TRACE_AVC_MUSIC, "Sig Src status: dest_su: 0x%02x, dest_plug_id 0x%02x\n\r", dest_su, dest_plug_id); hResult = targetSignalSourceFindPath(dest_plug_id, dest_su, &source_plug_id, &source_su, &status, &path); if (NO_ERROR != hResult) { return E_PKT_AVC_REJECTED; } // reply with the appropriate contents - go back to beginning of operand[0] hResult = dsGotoMarker(pStream, DSMARKER_OPERAND_0); if (hResult != NO_ERROR) return hResultError; hResult = dsSwitchMode(pStream, dsMODE_WRITE); if (hResult != NO_ERROR) return hResultError; // operand[0]: 3:output_status, 1:conv, 4:signal_status hResult = dsWrite8Bits(pStream, status); if (hResult != NO_ERROR) return hResultError; // operand[1]: source_su hResult = dsWrite8Bits(pStream, source_su); if (hResult != NO_ERROR) return hResultError; // operand[2]: source_plug_id hResult = dsWrite8Bits(pStream, source_plug_id); if (hResult != NO_ERROR) return hResultError; // operand[3]: dest_su hResult = dsWrite8Bits(pStream, dest_su); if (hResult != NO_ERROR) return hResultError; // operand[4]: dest_plug_id hResult = dsWrite8Bits(pStream, dest_plug_id); if (hResult != NO_ERROR) return hResultError; if (pHeader->ctype == AVC_CTYPE_STATUS) { hResult = E_PKT_AVC_STABLE; } break; case AVC_CTYPE_SPECIFIC_INQUIRY: // asking if a plug is a possible clock sync source case AVC_CTYPE_CONTROL: // setting the clock sync source to a plug { BYTE src_su = 0; BYTE src_plug_id = 0; BYTE dst_su = 0; BYTE dst_plug_id = 0; hResultError = E_PKT_AVC_NOT_IMPLEMENTED; // operand[1]: 0x0F hResult = dsRead8Bits(pStream, &inByte); if (hResult != NO_ERROR) return hResultError; // operand[2]: signal_src subunit hResult = dsRead8Bits(pStream, &src_su); if (hResult != NO_ERROR) return hResultError; // operand[3]: signal_src plug id hResult = dsRead8Bits(pStream, &src_plug_id); if (hResult != NO_ERROR) return hResultError; // operand[4]: signal_dest subunit hResult = dsRead8Bits(pStream, &dst_su); if (hResult != NO_ERROR) return hResultError; // operand[5]: signal_dest plug id hResult = dsRead8Bits(pStream, &dst_plug_id); if (hResult != NO_ERROR) return hResultError; SYS_DEBUG(SYSDEBUG_TRACE_AVC_MUSIC, "Sig Src s_su 0x%02x, s_id 0x%02x, d_su 0x%02x, d_id 0x%02x\n\r", src_su, src_plug_id, dst_su, dst_plug_id); if ( avcDriverPlugIsSyncPath(dst_su, dst_plug_id, src_su, src_plug_id) ) { // host is asking if it can connect a unit input plug to a subunit output plug (i.e. for sync) hResult = dsGotoMarker(pStream, DSMARKER_OPERAND_0); if (hResult != NO_ERROR) return hResultError; hResult = dsSwitchMode(pStream, dsMODE_WRITE); if (hResult != NO_ERROR) return hResultError; hResult = dsWrite8Bits(pStream, 0x00); // accepted if (hResult != NO_ERROR) return hResultError; hResult = dsWrite8Bits(pStream, 0xff); if (hResult != NO_ERROR) return hResultError; if (AVC_CTYPE_SPECIFIC_INQUIRY == pHeader->ctype) { SYS_DEBUG(SYSDEBUG_TRACE_AVC_MUSIC, " accepted clock source inquiry, src_plug_id: %d\n\r", src_plug_id); return E_PKT_AVC_ACCEPTED; } else if (AVC_CTYPE_CONTROL == pHeader->ctype) // set clock source { hResult = avcDriverSetClockSrc(src_su, src_plug_id); if (hResult != NO_ERROR) return hResultError; SYS_DEBUG(SYSDEBUG_TRACE_AVC_MUSIC, " accepted set clock source, src_plug_id: %d\n\r", src_plug_id); } return E_PKT_AVC_ACCEPTED; } SYS_DEBUG(SYSDEBUG_TRACE_AVC_MUSIC, " rejected clock source inquiry\n\r"); hResult = E_PKT_AVC_REJECTED; } break; case AVC_CTYPE_GENERAL_INQUIRY: // don't even bother parsing hResult = E_PKT_AVC_IMPLEMENTED; break; default: hResult = hResultError; break; } return hResult; }
static HRESULT muteControlHandler(DataStream *pAvcStream, FUNCTION_BLOCK_PARMS *pFbParms, uint32 audioChannel, PB *packetBlock) { uint8 muteValue=0; uint32 fbIDOperand = 4; uint8 fbID = 0; uint32 streamPosMute; // save stream position in case its a status command HRESULT hResult = NO_ERROR; streamPosMute = dsGetPosition(pAvcStream); if (AVC_AUDIO_CHANNEL_MASTER != audioChannel) { hResult = E_PKT_AVC_NOT_IMPLEMENTED; // only one mute is supported, mutes all channels } if (NO_ERROR == hResult) { dsSetPosition(pAvcStream, fbIDOperand); hResult = dsRead8Bits (pAvcStream, &fbID); if (fbID != 1) { hResult = E_PKT_AVC_NOT_IMPLEMENTED; } } if (NO_ERROR == hResult) { /* Switch depending on command type and control attribute. General inquiry CTYPE has been handled at the highest level, so we can ignore that one. */ switch (pFbParms->ctype_attribute) { // ctype GENERAL INQUIRY has been handled already at some higher level // ctype NOTIFY is supported for Current only case CTYPE_ATTRIBUTE (AVC_CTYPE_NOTIFY, AVC_FB_CTRL_ATTRIBUTE_CURRENT): // wants to be 'notified' when current delay changes hResult = postNotifyMute(audioChannel, pFbParms->fbId, packetBlock); if (NO_ERROR == hResult) { hResult = E_PKT_AVC_INTERIM; } break; // ctype CONTROL case CTYPE_ATTRIBUTE (AVC_CTYPE_CONTROL, AVC_FB_CTRL_ATTRIBUTE_CURRENT): // getp the mute parameter dsSetPosition(pAvcStream, fbIDOperand+6); hResult = dsRead8Bits (pAvcStream, &muteValue); SYS_DEBUG(SYSDEBUG_TRACE_AVC_MUSIC, "mute value: %x\n\r", muteValue); if (AVC_AUDIO_MUTE_ON == muteValue) { avsRxMute(0, TRUE); hResult = avrDrdSetMute (TRUE); } else if (AVC_AUDIO_MUTE_OFF == muteValue) { avsRxMute(0, FALSE); hResult = avrDrdSetMute (FALSE); } if (NO_ERROR == hResult) { // all ok, return 'accepted' to avc_main and avc_main will send the response hResult = E_PKT_AVC_ACCEPTED; } break; // ctype STATUS case CTYPE_ATTRIBUTE (AVC_CTYPE_STATUS, AVC_FB_CTRL_ATTRIBUTE_CURRENT): dsSetPosition(pAvcStream, streamPosMute); hResult = dsSwitchMode(pAvcStream, dsMODE_WRITE); if (NO_ERROR == hResult) { if (avrDrdHostState.mute) { hResult = dsWrite8Bits (pAvcStream, AVC_AUDIO_MUTE_ON); } else { hResult = dsWrite8Bits (pAvcStream, AVC_AUDIO_MUTE_OFF); } } if (NO_ERROR == hResult) { // all ok, return 'stable' to avc_main and avc_main will send the response hResult = E_PKT_AVC_STABLE; } break; // ctype SPECIFIC INQUIRY case CTYPE_ATTRIBUTE (AVC_CTYPE_SPECIFIC_INQUIRY, AVC_FB_CTRL_ATTRIBUTE_CURRENT): hResult = E_PKT_AVC_IMPLEMENTED; break; default: hResult = E_PKT_AVC_NOT_IMPLEMENTED; break; } } return(hResult); }
static HRESULT delayControlHandler(DataStream *pAvcStream, FUNCTION_BLOCK_PARMS *pFbParms, uint32 audioChannel, PB *packetBlock) { uint8 valueMsb=0; uint8 valueLsb=0; uint32 streamPosDelay; // save stream position in case its a status command HRESULT hResult=NO_ERROR; streamPosDelay = dsGetPosition(pAvcStream); if (AVC_AUDIO_CHANNEL_MASTER == audioChannel) { hResult = E_PKT_AVC_NOT_IMPLEMENTED; // delay is not available on master channel } // trap the delay parameters if (NO_ERROR == hResult) { hResult = dsRead8Bits (pAvcStream, &valueMsb); if (NO_ERROR == hResult) { hResult = dsRead8Bits (pAvcStream, &valueLsb); } } if (NO_ERROR == hResult) { /* diverge again, depending on command type and control attribute. General inquiry CTYPE has been handled at the highest level, so we can ignore that one. */ switch (pFbParms->ctype_attribute) { // ctype GENERAL INQUIRY has been handled already at some higher level // ctype NOTIFY is supported for Current only case CTYPE_ATTRIBUTE (AVC_CTYPE_NOTIFY, AVC_FB_CTRL_ATTRIBUTE_CURRENT): // wants to be 'notified' when current delay changes hResult = postNotifyDelay(audioChannel, pFbParms->fbId, packetBlock); if (NO_ERROR == hResult) { hResult = E_PKT_AVC_INTERIM; } break; // ctype CONTROL case CTYPE_ATTRIBUTE (AVC_CTYPE_CONTROL, AVC_FB_CTRL_ATTRIBUTE_CURRENT): // change current delay for a channel { uint32 delay = (valueMsb << 8) + valueLsb; hResult = avrDrdSetAudioDelay (delay, audioChannel); if (NO_ERROR == hResult) { hResult = E_PKT_AVC_ACCEPTED; } break; } // ctype STATUS case CTYPE_ATTRIBUTE (AVC_CTYPE_STATUS, AVC_FB_CTRL_ATTRIBUTE_CURRENT): /* get the requested delay and write it into the packet block at the previously saved location, overwriting the delay field */ { uint32 delay; delay = avrDrdHostState.audioDelays[audioChannel]; valueMsb = (uint8)((delay >> 8) & 0xFF); valueLsb = (uint8)(delay & 0xFF); dsSetPosition(pAvcStream, streamPosDelay); hResult = dsSwitchMode(pAvcStream, dsMODE_WRITE); if (NO_ERROR == hResult) { hResult = dsWrite8Bits (pAvcStream, valueMsb); if (NO_ERROR == hResult) { hResult = dsWrite8Bits (pAvcStream, valueLsb); } } if (NO_ERROR == hResult) { // all ok, return 'stable' to avc_main and avc_main will send the response hResult = E_PKT_AVC_STABLE; } break; } // ctype SPECIFIC INQUIRY case CTYPE_ATTRIBUTE (AVC_CTYPE_SPECIFIC_INQUIRY, AVC_FB_CTRL_ATTRIBUTE_DELTA): case CTYPE_ATTRIBUTE (AVC_CTYPE_SPECIFIC_INQUIRY, AVC_FB_CTRL_ATTRIBUTE_CURRENT): hResult = E_PKT_AVC_IMPLEMENTED; break; default: hResult = E_PKT_AVC_NOT_IMPLEMENTED; break; } } return(hResult); }
static HRESULT volumeControlHandler(DataStream *pAvcStream, FUNCTION_BLOCK_PARMS *pFbParms, uint32 audioChannel, PB *packetBlock) { uint8 valueMsb=0; uint8 valueLsb=0; uint32 streamPosVolume; // save stream position in case its a status command HRESULT hResult = NO_ERROR; streamPosVolume = dsGetPosition(pAvcStream); // trap the volume parameters hResult = dsRead8Bits (pAvcStream, &valueMsb); if (NO_ERROR == hResult) { hResult = dsRead8Bits (pAvcStream, &valueLsb); } if (NO_ERROR == hResult) { /* diverge again, depending on command type and control attribute. General inquiry CTYPE has been handled at the highest level, so we can ignore that one. */ switch (pFbParms->ctype_attribute) { // ctype GENERAL INQUIRY has been handled already at some higher level // ctype NOTIFY is supported for Current only case CTYPE_ATTRIBUTE (AVC_CTYPE_NOTIFY, AVC_FB_CTRL_ATTRIBUTE_CURRENT): // wants to be 'notified' when current volume changes hResult = postNotifyVolume(audioChannel, pFbParms->fbId, packetBlock); if (NO_ERROR == hResult) { hResult = E_PKT_AVC_INTERIM; } break; // ctype CONTROL case CTYPE_ATTRIBUTE (AVC_CTYPE_CONTROL, AVC_FB_CTRL_ATTRIBUTE_DELTA): // relative change in volume { int16 relativeVolume = (int16)((valueMsb << 8) + valueLsb); // signed value /* Request is a relative change, based on a 16-bit signed value. We will convert this to an absolute volume value and set it as such for the appropriate channel. */ if (AVC_AUDIO_CHANNEL_MASTER == audioChannel) { hResult = avrDrdSetMasterVolume ( (uint32)(avrDrdHostState.masterVolume + relativeVolume)); } else { hResult = avrDrdSetTrimVolume ( (uint32)(avrDrdHostState.masterVolume + relativeVolume), audioChannel); } if (NO_ERROR == hResult) { hResult = E_PKT_AVC_ACCEPTED; } } break; case CTYPE_ATTRIBUTE (AVC_CTYPE_CONTROL, AVC_FB_CTRL_ATTRIBUTE_CURRENT): // absolute change in volume { uint32 absoluteVolume = (valueMsb << 8) + valueLsb; if (AVC_AUDIO_CHANNEL_MASTER == audioChannel) { hResult = avrDrdSetMasterVolume (absoluteVolume); } else { hResult = avrDrdSetTrimVolume (absoluteVolume, audioChannel); } if (NO_ERROR == hResult) { hResult = E_PKT_AVC_ACCEPTED; } } break; // ctype STATUS case CTYPE_ATTRIBUTE (AVC_CTYPE_STATUS, AVC_FB_CTRL_ATTRIBUTE_CURRENT): /* get the requested volume and write it into the packet block at the previously saved location, overwriting the volume field */ { uint32 volume; if (AVC_AUDIO_CHANNEL_MASTER == audioChannel) { volume = avrDrdHostState.masterVolume; } else { volume = avrDrdHostState.trimVolume[audioChannel]; } valueMsb = (uint8)((volume >> 8) & 0xFF); valueLsb = (uint8)(volume & 0xFF); dsSetPosition(pAvcStream, streamPosVolume); hResult = dsSwitchMode(pAvcStream, dsMODE_WRITE); if (NO_ERROR == hResult) { hResult = dsWrite8Bits (pAvcStream, valueMsb); if (NO_ERROR == hResult) { hResult = dsWrite8Bits (pAvcStream, valueLsb); } } if (NO_ERROR == hResult) { // all ok, return 'stable' to avc_main and avc_main will send the response hResult = E_PKT_AVC_STABLE; } } break; // ctype STATUS case CTYPE_ATTRIBUTE (AVC_CTYPE_STATUS, AVC_FB_CTRL_ATTRIBUTE_RESOLUTION): /* get the requested value and write it into the packet block at the previously saved location, overwriting the return parameter field */ { dsSetPosition(pAvcStream, streamPosVolume); hResult = dsSwitchMode(pAvcStream, dsMODE_WRITE); if (NO_ERROR == hResult) { hResult = dsWrite8Bits (pAvcStream, 0x01); if (NO_ERROR == hResult) { hResult = dsWrite8Bits (pAvcStream, 0x00); } } if (NO_ERROR == hResult) { // all ok, return 'stable' to avc_main and avc_main will send the response hResult = E_PKT_AVC_STABLE; } } break; // ctype STATUS case CTYPE_ATTRIBUTE (AVC_CTYPE_STATUS, AVC_FB_CTRL_ATTRIBUTE_MINIMUM): /* get the requested value and write it into the packet block at the previously saved location, overwriting the return parameter field */ { dsSetPosition(pAvcStream, streamPosVolume); hResult = dsSwitchMode(pAvcStream, dsMODE_WRITE); if (NO_ERROR == hResult) { hResult = dsWrite8Bits (pAvcStream, 0x89); if (NO_ERROR == hResult) { hResult = dsWrite8Bits (pAvcStream, 0x00); } } if (NO_ERROR == hResult) { // all ok, return 'stable' to avc_main and avc_main will send the response hResult = E_PKT_AVC_STABLE; } } break; // ctype STATUS case CTYPE_ATTRIBUTE (AVC_CTYPE_STATUS, AVC_FB_CTRL_ATTRIBUTE_MAXIMUM): /* get the requested value and write it into the packet block at the previously saved location, overwriting the return parameter field */ { dsSetPosition(pAvcStream, streamPosVolume); hResult = dsSwitchMode(pAvcStream, dsMODE_WRITE); if (NO_ERROR == hResult) { hResult = dsWrite8Bits (pAvcStream, 0x00); if (NO_ERROR == hResult) { hResult = dsWrite8Bits (pAvcStream, 0x00); } } if (NO_ERROR == hResult) { // all ok, return 'stable' to avc_main and avc_main will send the response hResult = E_PKT_AVC_STABLE; } } break; // ctype SPECIFIC INQUIRY case CTYPE_ATTRIBUTE (AVC_CTYPE_SPECIFIC_INQUIRY, AVC_FB_CTRL_ATTRIBUTE_DELTA): case CTYPE_ATTRIBUTE (AVC_CTYPE_SPECIFIC_INQUIRY, AVC_FB_CTRL_ATTRIBUTE_CURRENT): hResult = E_PKT_AVC_IMPLEMENTED; break; default: hResult = E_PKT_AVC_NOT_IMPLEMENTED; break; } } return(hResult); }
/* Handle the AV/C function block command */ static HRESULT changeConfigurationHandler(DataStream *pAvcStream, AVC_HEADER *pAvcHeaderInfo, PB *pPacketBlock) { uint8 configIdLsb=0; uint8 configIdMsb; uint32 configId; uint32 streamConfigIdPosition; HRESULT hResult = NO_ERROR; UNUSED_ARG(pPacketBlock); // stream is positioned at operand[0], the config id msb streamConfigIdPosition = dsGetPosition(pAvcStream); // extract the config id hResult = dsRead8Bits(pAvcStream, &configIdMsb); if (NO_ERROR == hResult) { hResult = dsRead8Bits(pAvcStream, &configIdLsb); } if (NO_ERROR != hResult) { return(hResult); } configId = (configIdMsb << 8) + configIdLsb; switch (pAvcHeaderInfo->ctype) { case AVC_CTYPE_CONTROL: // tell host to change its mode hResult = avrDrdSetAudioMode (configId); if (NO_ERROR == hResult) { // all ok, return 'accepted' to avc_main and avc_main will send the response hResult = E_PKT_AVC_ACCEPTED; } break; case AVC_CTYPE_STATUS: // send a response with the current configuration configId = avrDrdHostState.audioMode; configIdMsb = (uint8)((configId >> 8) & 0xFF); configIdLsb = (uint8)(configId & 0xFF); // repostion stream at the config id location dsSetPosition(pAvcStream, streamConfigIdPosition); hResult = dsSwitchMode(pAvcStream, dsMODE_WRITE); if (NO_ERROR == hResult) { hResult = dsWrite8Bits(pAvcStream, configIdMsb); if (NO_ERROR == hResult) { hResult = dsWrite8Bits(pAvcStream, configIdLsb); } } if (NO_ERROR == hResult) { // all ok, return 'stable' to avc_main and avc_main will send the response hResult = E_PKT_AVC_STABLE; } break; case AVC_CTYPE_NOTIFY: hResult = AVC_RESPONSE_NOT_IMPLEMENTED; break; case AVC_CTYPE_SPECIFIC_INQUIRY: case AVC_CTYPE_GENERAL_INQUIRY: hResult = AVC_RESPONSE_IMPLEMENTED; break; default: hResult = AVC_RESPONSE_NOT_IMPLEMENTED; break; } return(hResult); }