/*{{{ AudioIoctlSetSyncGroup*/ static int AudioIoctlSetSyncGroup (struct DeviceContext_s* Context, unsigned int Group) { int Result = 0; if (Context != Context->SyncContext) { DVB_ERROR("Sync group already set - cannot reset\n"); return -EPERM; } if ((Group < 0) || (Group >= DVB_MAX_DEVICES_PER_ADAPTER)) { DVB_ERROR("Invalid sync group - out of range.\n"); return -EPERM; } if (Context->SyncContext->Playback) { DVB_ERROR("Sync group already set - cannot reset\n"); return -EPERM; } Context->SyncContext = &Context->DvbContext->DeviceContext[Group]; DVB_DEBUG("Sync group set to device %d\n", Group); return Result; }
/*{{{ AudioIoctlSetEncoding*/ static int AudioIoctlSetEncoding (struct DeviceContext_s* Context, unsigned int Encoding) { DVB_DEBUG("Set encoding to %d\n", Encoding); if ((Encoding < AUDIO_ENCODING_AUTO) || (Encoding > AUDIO_ENCODING_PRIVATE)) return -EINVAL; if ((Context->AudioState.play_state != AUDIO_STOPPED) && (Context->AudioState.play_state != AUDIO_INCOMPLETE)) { DVB_ERROR("Cannot change encoding after play has started\n"); return -EPERM; } Context->AudioEncoding = (audio_encoding_t)Encoding; /* At this point we have received the missing piece of information which will allow the * stream to be fully populated so we can reissue the play. */ if (Context->AudioState.play_state == AUDIO_INCOMPLETE) AudioIoctlPlay (Context); return 0; }
int StartFeed (struct dvb_demux_feed* Feed) { struct dvb_demux* DvbDemux = Feed->demux; struct dmxdev_filter* Filter = (struct dmxdev_filter*)Feed->feed.ts.priv; struct dmx_pes_filter_params* Params = &Filter->params.pes; struct DeviceContext_s* Context = (struct DeviceContext_s*)DvbDemux->priv; struct DvbContext_s* DvbContext = Context->DvbContext; int Result = 0; int i; unsigned int Video = false; unsigned int Audio = false; #ifdef __TDT__ struct DeviceContext_s *AvContext = NULL; #endif DVB_DEBUG ("(demux%d)\n", Context->Id); /* either numRunningFeeds == 0 and reset_tsm == 1 or reset_tsm > 1 */ #ifdef __TDT__ // fix recoding freezer on tuner0 and demux1/2 or tuner1 and demux0/2 or tuner2 and demux0/1 int tsm_reset = 1; for (i = 0; i < DVB_MAX_DEVICES_PER_ADAPTER; i++) { struct DeviceContext_s* DeviceContext = &DvbContext->DeviceContext[i]; if(DeviceContext->numRunningFeeds != 0) tsm_reset = 0; } if (tsm_reset && reset_tsm) { printk(KERN_WARNING "reset_tsm: %d numRunningFeeds: %d => calling stm_tsm_init(1)\n", reset_tsm, Context->numRunningFeeds); stm_tsm_init(1); } #else if (Context->numRunningFeeds == 0 && reset_tsm) { printk(KERN_WARNING "reset_tsm: %d numRunningFeeds: %d => calling stm_tsm_init(1)\n", reset_tsm, Context->numRunningFeeds); stm_tsm_init(1); } #endif #if defined(ADB_BOX)//tutaj if (glowica == SINGLE) { if ((Context->pPtiSession->source==DMX_SOURCE_FRONT1)&&(StartFeed_!=NULL)) StartFeed_(Feed); } else if (glowica == TWIN) { if ((Context->pPtiSession->source==DMX_SOURCE_FRONT2)&&(StartFeed_!=NULL)) StartFeed_(Feed); } #endif #ifdef __TDT__ #ifdef no_subtitles if ((Feed->type == DMX_TYPE_TS) && (Feed->pes_type > DMX_TS_PES_OTHER)) { DVB_DEBUG ("pes_type %d > %d (OTHER)>\n", Feed->pes_type, DMX_TS_PES_OTHER); return -EINVAL; } #endif DVB_DEBUG("t = %d, pt = %d, pid = %d\n", Feed->type, Feed->pes_type, Feed->pid); #endif switch (Feed->type) { case DMX_TYPE_TS: if (Feed->pes_type > DMX_TS_PES_OTHER) return -EINVAL; for (i = 0; i < DVB_MAX_DEVICES_PER_ADAPTER; i++) { if (Feed->pes_type == AudioId[i]) { Audio = true; break; } if (Feed->pes_type == VideoId[i]) { Video = true; break; } } #ifdef __TDT__ AvContext = &Context->DvbContext->DeviceContext[i]; //fix freeze if record starts in background //AvContext->DemuxContext = Context; //videotext & subtitles (other) if ((Feed->pes_type == DMX_TS_PES_TELETEXT) || (Feed->pes_type == DMX_TS_PES_OTHER)) { mutex_lock (&(DvbContext->Lock)); Context->numRunningFeeds++; //printk("%s:%d numRunningFeeds: %d\n", __func__,__LINE__,Context->numRunningFeeds); stpti_start_feed (Feed, Context); mutex_unlock (&(DvbContext->Lock)); break; } #endif if (!Audio && !Video) { #ifdef __TDT__ DVB_DEBUG ("pes_type = %d\n<\n", Feed->pes_type); #endif /*mutex_unlock (&(DvbContext->Lock)); This doesn't look right we haven't taken it yet*/ return 0; } mutex_lock (&(DvbContext->Lock)); #ifndef __TDT__ if ((Video && !Context->VideoOpenWrite) || (Audio && !Context->AudioOpenWrite)) { mutex_unlock (&(DvbContext->Lock)); return -EBADF; } #endif if ((Context->Playback == NULL) && (Context->SyncContext->Playback == NULL)) { Result = DvbPlaybackCreate (&Context->Playback); if (Result < 0) { mutex_unlock (&(DvbContext->Lock)); return Result; } Context->SyncContext->Playback = Context->Playback; if (Context->PlaySpeed != DVB_SPEED_NORMAL_PLAY) { Result = VideoIoctlSetSpeed (Context, Context->PlaySpeed); if (Result < 0) #ifdef __TDT__ { mutex_unlock (&(DvbContext->Lock)); return Result; } #else return Result; #endif } #ifdef __TDT__ if ((Context->VideoPlayInterval.start != DVB_TIME_NOT_BOUNDED) || (Context->VideoPlayInterval.end != DVB_TIME_NOT_BOUNDED)) { Result = VideoIoctlSetPlayInterval (Context, &Context->AudioPlayInterval); if (Result < 0) { mutex_unlock (&(DvbContext->Lock)); return Result; } } #endif } else if (Context->Playback == NULL) Context->Playback = Context->SyncContext->Playback; else if (Context->SyncContext->Playback == NULL) Context->SyncContext->Playback = Context->Playback; else if (Context->Playback != Context->SyncContext->Playback) DVB_ERROR ("Context playback not equal to sync context playback\n"); if (Context->DemuxStream == NULL) { Result = DvbPlaybackAddDemux (Context->Playback, Context->DemuxContext->Id, &Context->DemuxStream); if (Result < 0) { mutex_unlock (&(DvbContext->Lock)); return Result; } } #ifdef __TDT__ if (Video) { Context->numRunningFeeds++; //printk("%s:%d numRunningFeeds: %d\n", __func__,__LINE__,Context->numRunningFeeds); stpti_start_feed (Feed, Context); if(Feed->ts_type & TS_DECODER) VideoIoctlSetId (AvContext, Feed->pid); } else if (Audio) { Context->numRunningFeeds++; //printk("%s:%d numRunningFeeds: %d\n", __func__,__LINE__,Context->numRunningFeeds); stpti_start_feed (Feed, Context); if(Feed->ts_type & TS_DECODER) AudioIoctlSetId (AvContext, Feed->pid); } #else if (Video) { struct DeviceContext_s* VideoContext = &Context->DvbContext->DeviceContext[i]; VideoContext->DemuxContext = Context; VideoIoctlSetId (VideoContext, Feed->pid | (Params->flags & DMX_FILTER_BY_PRIORITY_MASK)); VideoIoctlPlay (VideoContext); if ((Context->VideoPlayInterval.start != DVB_TIME_NOT_BOUNDED) || (Context->VideoPlayInterval.end != DVB_TIME_NOT_BOUNDED)) VideoIoctlSetPlayInterval (Context, &Context->AudioPlayInterval); } else { struct DeviceContext_s* AudioContext = &Context->DvbContext->DeviceContext[i]; AudioContext->DemuxContext = Context; AudioIoctlSetId (AudioContext, Feed->pid | (Params->flags & DMX_FILTER_BY_PRIORITY_MASK)); AudioIoctlPlay (AudioContext); if ((Context->AudioPlayInterval.start != DVB_TIME_NOT_BOUNDED) || (Context->AudioPlayInterval.end != DVB_TIME_NOT_BOUNDED)) AudioIoctlSetPlayInterval (Context, &Context->AudioPlayInterval); } #endif mutex_unlock (&(DvbContext->Lock)); break; case DMX_TYPE_SEC: #ifdef __TDT__ //DVB_DEBUG ("feed type = SEC\n"); mutex_lock (&(DvbContext->Lock)); Context->numRunningFeeds++; //printk("%s:%d numRunningFeeds: %d\n", __func__,__LINE__,Context->numRunningFeeds); stpti_start_feed (Feed, Context); mutex_unlock (&(DvbContext->Lock)); #endif break; default: #ifdef __TDT DVB_DEBUG ("< (type = %d unknown\n", Feed->type); #endif return -EINVAL; } return 0; }
/*static*/ int __init StmLoadModule(void) { int Result; int i; short int AdapterNumbers[] = { -1 }; DvbContext = kzalloc(sizeof(struct DvbContext_s), GFP_KERNEL); if (DvbContext == NULL) { DVB_ERROR("Unable to allocate device memory\n"); return -ENOMEM; } #ifdef __TDT__ memset(DvbContext, 0, sizeof * DvbContext); #endif #ifdef __TDT__ if (swts) printk("swts ->routing streams from dvr0 to tsm to pti to player\n"); else printk("no swts ->routing streams from dvr0 direct to the player\n"); #endif #if DVB_API_VERSION < 5 Result = dvb_register_adapter(&DvbContext->DvbAdapter, MODULE_NAME, THIS_MODULE, NULL); #else Result = dvb_register_adapter(&DvbContext->DvbAdapter, MODULE_NAME, THIS_MODULE, NULL, AdapterNumbers); #endif if (Result < 0) { DVB_ERROR("Failed to register adapter (%d)\n", Result); kfree(DvbContext); DvbContext = NULL; return -ENOMEM; } mutex_init(&(DvbContext->Lock)); mutex_lock(&(DvbContext->Lock)); /*{{{ Register devices*/ for (i = 0; i < DVB_MAX_DEVICES_PER_ADAPTER; i++) { struct DeviceContext_s* DeviceContext = &DvbContext->DeviceContext[i]; struct dvb_demux* DvbDemux = &DeviceContext->DvbDemux; struct dmxdev* DmxDevice = &DeviceContext->DmxDevice; struct dvb_device* DvrDevice; #ifdef __TDT__ //sylvester: wenn der stream vom user kommt soll WriteToDecoder nix //tun, da das ja hier schon passiert. keine ahnung wie man das ansonsten //verhindern soll;-) DeviceContext->dvr_write = 0; #endif DeviceContext->DvbContext = DvbContext; #if defined (USE_KERNEL_DEMUX) memset(DvbDemux, 0, sizeof(struct dvb_demux)); #ifdef __TDT__ DvbDemux->dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING | DMX_TS_DESCRAMBLING; /* currently only dummy to avoid EINVAL error. Later we need it for second frontend ?! */ DvbDemux->dmx.set_source = SetSource; #else DvbDemux->dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING; #endif DvbDemux->priv = DeviceContext; DvbDemux->filternum = 32; DvbDemux->feednum = 32; DvbDemux->start_feed = StartFeed; DvbDemux->stop_feed = StopFeed; #ifdef __TDT__ DvbDemux->write_to_decoder = WriteToDecoder; #else DvbDemux->write_to_decoder = NULL; #endif Result = dvb_dmx_init(DvbDemux); if (Result < 0) { DVB_ERROR("dvb_dmx_init failed (errno = %d)\n", Result); return Result; } memset(DmxDevice, 0, sizeof(struct dmxdev)); DmxDevice->filternum = DvbDemux->filternum; DmxDevice->demux = &DvbDemux->dmx; DmxDevice->capabilities = 0; Result = dvb_dmxdev_init(DmxDevice, &DvbContext->DvbAdapter); if (Result < 0) { DVB_ERROR("dvb_dmxdev_init failed (errno = %d)\n", Result); dvb_dmx_release(DvbDemux); return Result; } DvrDevice = DvrInit(DmxDevice->dvr_dvbdev->fops); #ifdef __TDT__ printk("%d: DeviceContext %p, DvbDemux %p, DmxDevice %p\n", i, DeviceContext, DvbDemux, DmxDevice); #endif /* Unregister the built-in dvr device and replace it with our own version */ dvb_unregister_device(DmxDevice->dvr_dvbdev); dvb_register_device(&DvbContext->DvbAdapter, &DmxDevice->dvr_dvbdev, DvrDevice, DmxDevice, DVB_DEVICE_DVR); DeviceContext->MemoryFrontend.source = DMX_MEMORY_FE; Result = DvbDemux->dmx.add_frontend(&DvbDemux->dmx, &DeviceContext->MemoryFrontend); if (Result < 0) { DVB_ERROR("add_frontend failed (errno = %d)\n", Result); dvb_dmxdev_release(DmxDevice); dvb_dmx_release(DvbDemux); return Result; } #else dvb_register_device(&DvbContext->DvbAdapter, &DeviceContext->DemuxDevice, DemuxInit(DeviceContext), DeviceContext, DVB_DEVICE_DEMUX); dvb_register_device(&DvbContext->DvbAdapter, &DeviceContext->DvrDevice, DvrInit(DeviceContext), DeviceContext, DVB_DEVICE_DVR); #endif dvb_register_device(&DvbContext->DvbAdapter, &DeviceContext->AudioDevice, AudioInit(DeviceContext), DeviceContext, DVB_DEVICE_AUDIO); #ifdef __TDT__ /* register the CA device (e.g. CIMAX) */ if (i < 3) #ifndef VIP2_V1 dvb_register_device(&DvbContext->DvbAdapter, &DeviceContext->CaDevice, CaInit(DeviceContext), DeviceContext, DVB_DEVICE_CA); #endif #else dvb_register_device(&DvbContext->DvbAdapter, &DeviceContext->CaDevice, CaInit(DeviceContext), DeviceContext, DVB_DEVICE_CA); #endif dvb_register_device(&DvbContext->DvbAdapter, &DeviceContext->VideoDevice, VideoInit(DeviceContext), DeviceContext, DVB_DEVICE_VIDEO); DeviceContext->Id = i; DeviceContext->numRunningFeeds = 0; DeviceContext->DemuxContext = DeviceContext; /* wire directly to own demux by default */ DeviceContext->SyncContext = DeviceContext; /* we are our own sync group by default */ DeviceContext->Playback = NULL; DeviceContext->StreamType = STREAM_TYPE_TRANSPORT; DeviceContext->DvbContext = DvbContext; DeviceContext->DemuxStream = NULL; DeviceContext->VideoStream = NULL; DeviceContext->AudioStream = NULL; DeviceContext->PlaySpeed = DVB_SPEED_NORMAL_PLAY; DeviceContext->dvr_in = kmalloc(65536, GFP_KERNEL); // 128Kbytes is quite a lot per device. DeviceContext->dvr_out = kmalloc(65536, GFP_KERNEL); // However allocating on each write is expensive. DeviceContext->EncryptionOn = 0; #ifdef __TDT__ DeviceContext->VideoPlaySpeed = DVB_SPEED_NORMAL_PLAY; DeviceContext->provideToDecoder = 0; DeviceContext->feedPesType = 0; mutex_init(&DeviceContext->injectMutex); if (i < 4) { ptiInit(DeviceContext); } if (i < 1) { init_e2_proc(DeviceContext); } #endif } mutex_unlock(&(DvbContext->Lock)); DvbBackendInit(); #ifndef __TDT__ #if defined (CONFIG_CPU_SUBTYPE_STX7105) // || defined (CONFIG_CPU_SUBTYPE_STX7200) cap_init(); #endif #endif linuxdvb_v4l2_init(); DVB_DEBUG("STM stream device loaded\n"); return 0; }
/*{{{ AudioIoctl*/ static int AudioIoctl (struct inode* Inode, struct file* File, unsigned int IoctlCode, void* Parameter) { struct dvb_device* DvbDevice = (struct dvb_device*)File->private_data; struct DeviceContext_s* Context = (struct DeviceContext_s*)DvbDevice->priv; struct DvbContext_s* DvbContext = Context->DvbContext; int Result = 0; /*DVB_DEBUG("AudioIoctl : Ioctl %08x\n", IoctlCode); */ if (((File->f_flags & O_ACCMODE) == O_RDONLY) && (IoctlCode != AUDIO_GET_STATUS)) return -EPERM; if (!Context->AudioOpenWrite) /* Check to see that somebody has the device open for write */ return -EBADF; mutex_lock (&(DvbContext->Lock)); switch (IoctlCode) { case AUDIO_STOP: Result = AudioIoctlStop (Context); break; case AUDIO_PLAY: Result = AudioIoctlPlay (Context); break; case AUDIO_PAUSE: Result = AudioIoctlPause (Context); break; case AUDIO_CONTINUE: Result = AudioIoctlContinue (Context); break; case AUDIO_SELECT_SOURCE: Result = AudioIoctlSelectSource (Context, (audio_stream_source_t)Parameter); break; case AUDIO_SET_MUTE: Result = AudioIoctlSetMute (Context, (unsigned int)Parameter); break; case AUDIO_SET_AV_SYNC: Result = AudioIoctlSetAvSync (Context, (unsigned int)Parameter); break; case AUDIO_SET_BYPASS_MODE: Result = AudioIoctlSetBypassMode (Context, (unsigned int)Parameter); break; case AUDIO_CHANNEL_SELECT: Result = AudioIoctlChannelSelect (Context, (audio_channel_select_t)Parameter); break; case AUDIO_GET_STATUS: Result = AudioIoctlGetStatus (Context, (struct audio_status*)Parameter); break; case AUDIO_GET_CAPABILITIES: Result = AudioIoctlGetCapabilities (Context, (int*)Parameter); break; case AUDIO_GET_PTS: Result = AudioIoctlGetPts (Context, (unsigned long long int*)Parameter); break; case AUDIO_CLEAR_BUFFER: Result = AudioIoctlClearBuffer (Context); break; case AUDIO_SET_ID: Result = AudioIoctlSetId (Context, (int)Parameter); break; case AUDIO_SET_MIXER: Result = AudioIoctlSetMixer (Context, (audio_mixer_t*)Parameter); break; case AUDIO_SET_STREAMTYPE: Result = AudioIoctlSetStreamType (Context, (unsigned int)Parameter); break; case AUDIO_SET_EXT_ID: Result = AudioIoctlSetExtId (Context, (int)Parameter); break; case AUDIO_SET_ATTRIBUTES: Result = AudioIoctlSetAttributes (Context, (audio_attributes_t) ((int)Parameter)); break; case AUDIO_SET_KARAOKE: Result = AudioIoctlSetKaraoke (Context, (audio_karaoke_t*)Parameter); break; case AUDIO_SET_ENCODING: Result = AudioIoctlSetEncoding (Context, (unsigned int)Parameter); break; case AUDIO_FLUSH: Result = AudioIoctlFlush (Context); break; case AUDIO_SET_SPDIF_SOURCE: Result = AudioIoctlSetSpdifSource (Context, (unsigned int)Parameter); break; case AUDIO_SET_SPEED: Result = AudioIoctlSetSpeed (Context, (int)Parameter); break; case AUDIO_DISCONTINUITY: Result = AudioIoctlDiscontinuity (Context, (audio_discontinuity_t)Parameter); break; case AUDIO_SET_PLAY_INTERVAL: Result = AudioIoctlSetPlayInterval (Context, (dvb_play_interval_t*)Parameter); break; case AUDIO_SET_SYNC_GROUP: Result = AudioIoctlSetSyncGroup (Context, (unsigned int)Parameter); break; case AUDIO_GET_PLAY_TIME: Result = AudioIoctlGetPlayTime (Context, (audio_play_time_t*)Parameter); break; case AUDIO_GET_PLAY_INFO: Result = AudioIoctlGetPlayInfo (Context, (audio_play_info_t*)Parameter); break; default: DVB_ERROR("Invalid ioctl %08x\n", IoctlCode); Result = -ENOIOCTLCMD; } mutex_unlock (&(DvbContext->Lock)); return Result; }
/*{{{ AudioIoctlSetKaraoke*/ static int AudioIoctlSetKaraoke (struct DeviceContext_s* Context, audio_karaoke_t* Karaoke) { DVB_ERROR("Not supported\n"); return -EPERM; }
/*{{{ AudioIoctlSetAttributes*/ static int AudioIoctlSetAttributes (struct DeviceContext_s* Context, audio_attributes_t Attributes) { DVB_ERROR("Not supported\n"); return -EPERM; }
/*{{{ AudioIoctlSetExtId*/ static int AudioIoctlSetExtId (struct DeviceContext_s* Context, int Id) { DVB_ERROR("Not supported\n"); return -EPERM; }
/*{{{ AudioWrite*/ static ssize_t AudioWrite (struct file *File, const char __user* Buffer, size_t Count, loff_t* ppos) { struct dvb_device* DvbDevice = (struct dvb_device*)File->private_data; struct DeviceContext_s* Context = (struct DeviceContext_s*)DvbDevice->priv; int Result = 0; #ifdef CONFIG_STM_TKDMA char* InBuffer = &Context->dvr_in[16*2048]; char* OutBuffer = &Context->dvr_out[16*2048]; #endif void* PhysicalBuffer = NULL; const unsigned char* ClearData = Buffer; if ((File->f_flags & O_ACCMODE) == O_RDONLY) return -EPERM; if (Context->AudioState.stream_source == AUDIO_SOURCE_DEMUX) { DVB_ERROR("Audio stream source not AUDIO_SOURCE_MEMORY - cannot use write\n"); return -EPERM; /* Not allowed to write to device if connected to demux */ } mutex_lock (&(Context->AudioWriteLock)); if (Context->AudioStream == NULL) { DVB_ERROR ("No audio stream exists to be written to (previous AUDIO_PLAY failed?)\n"); mutex_unlock (&(Context->AudioWriteLock)); return -ENODEV; } if (!StreamBufferFree (Context->AudioStream) && ((File->f_flags & O_NONBLOCK) != 0)) { mutex_unlock (&(Context->AudioWriteLock)); return -EWOULDBLOCK; } PhysicalBuffer = stm_v4l2_findbuffer ((unsigned long)Buffer, Count, 0); #ifdef CONFIG_STM_TKDMA if (Context->EncryptionOn) { if ((Count % 2048) != 0) { DVB_ERROR ("Count size incorrect for decryption (%d)\n", Count); mutex_unlock (&(Context->AudioWriteLock)); return -EINVAL; } if (PhysicalBuffer != NULL) { tkdma_hddvd_decrypt_data (OutBuffer, PhysicalBuffer, Count/2048, TKDMA_VIDEO_CHANNEL, 0); // Got to check blocking } else { /* If the incoming data is aligned to 2K/4K we would be able to avoid this copy from user, we just decrypt max two packets at a time, certainly scatter gather would be easier. */ copy_from_user (InBuffer, Buffer, Count); tkdma_hddvd_decrypt_data (OutBuffer, InBuffer, Count/2048, TKDMA_VIDEO_CHANNEL, 0); // Got to check blocking } ClearData = OutBuffer; } else #endif /* CONFIG_STM_TKDMA */ if (PhysicalBuffer) ClearData = PhysicalBuffer; #define PACK_HEADER_START_CODE ((ClearData[0]==0x00)&&(ClearData[1]==0x00)&&(ClearData[2]==0x01)&&(ClearData[3]==0xba)) #define PACK_HEADER_LENGTH 14 #define PES_LENGTH ((ClearData[4]<<8)+ClearData[5]+6) /* Extra 6 includes bytes up to length bytes */ if (PACK_HEADER_START_CODE) /* TODO Skip Pack header until handled by audio collator */ { ClearData = &ClearData[PACK_HEADER_LENGTH]; Count = PES_LENGTH; } if (Context->AudioState.play_state == AUDIO_INCOMPLETE) { if (Context->AudioEncoding == AUDIO_ENCODING_AUTO) { StreamGetFirstBuffer (Context->AudioStream, Buffer, Count); StreamIdentifyAudio (Context->AudioStream, &Context->AudioEncoding); } else DVB_ERROR("Audio incomplete with encoding set (%d)\n", Context->AudioEncoding); AudioIoctlPlay (Context); if (Context->AudioState.play_state == AUDIO_INCOMPLETE) Context->AudioState.play_state = AUDIO_STOPPED; } if (Context->AudioState.play_state != AUDIO_PLAYING) { DVB_ERROR("Audio not playing - cannot write (state %x)\n", Context->AudioState.play_state); Result = -EPERM; /* Not allowed to write to device if paused */ } else Result = StreamInject (Context->AudioStream, ClearData, Count); /*Result = StreamInjectFromUser (Context->AudioStream, Buffer, Count);*/ mutex_unlock (&(Context->AudioWriteLock)); return Result; }