Ejemplo n.º 1
0
/*{{{  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;
}
Ejemplo n.º 2
0
/*{{{  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;
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
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;
}
Ejemplo n.º 5
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;
}
Ejemplo n.º 6
0
/*{{{  AudioIoctlSetKaraoke*/
static int AudioIoctlSetKaraoke (struct DeviceContext_s* Context, audio_karaoke_t* Karaoke)
{
    DVB_ERROR("Not supported\n");
    return -EPERM;
}
Ejemplo n.º 7
0
/*{{{  AudioIoctlSetAttributes*/
static int AudioIoctlSetAttributes (struct DeviceContext_s* Context, audio_attributes_t Attributes)
{
    DVB_ERROR("Not supported\n");
    return -EPERM;
}
Ejemplo n.º 8
0
/*{{{  AudioIoctlSetExtId*/
static int AudioIoctlSetExtId (struct DeviceContext_s* Context, int Id)
{
    DVB_ERROR("Not supported\n");
    return -EPERM;
}
Ejemplo n.º 9
0
/*{{{  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;
}