HRESULT avcPadToNextQuadletInStream(pDataStream pStream) { HRESULT hResult = NO_ERROR; uint32 remainder = 0; uint32 payloadsize = 0; hResult = dsSwitchMode(pStream, dsMODE_WRITE); if (hResult != NO_ERROR) return hResult; payloadsize = dsGetPosition(pStream); remainder = payloadsize % 4; if (remainder) { #if 0 //LM??? dsWriteBits(pStream, 8 * (4 - remainder), 0xFFFFFFFF); #else dsWriteBits(pStream, 8 * (4 - remainder), 0); #endif payloadsize += (4 - remainder); } 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); }