📄 xp_osd_drv.c
字号:
/*----------------------------------------------------------------------------+|| This source code has been made available to you by IBM on an AS-IS| basis. Anyone receiving this source is licensed under IBM| copyrights to use it in any way he or she deems fit, including| copying it, modifying it, compiling it, and redistributing it either| with or without modifications. No license under IBM patents or| patent applications is to be implied by the copyright license.|| Any user of this software should understand that IBM cannot provide| technical support for this software and will not be responsible for| any consequences resulting from the use of this software.|| Any person who transfers this source code or any derivative work| must include the IBM copyright notice, this paragraph, and the| preceding two paragraphs in the transferred software.|| COPYRIGHT I B M CORPORATION 1998| LICENSED MATERIAL - PROGRAM PROPERTY OF I B M|+----------------------------------------------------------------------------*//*----------------------------------------------------------------------------+|| Author : Lin Guo Hui| File : xp_osd_drv.c| Purpose : The set of functions provide a interface to Linux user| space, as os dependent layer| Changes :| Date Comments| ----------------------------------------------------------------------| 25-Jun-2001 Created| 06-Jul-2001 Add audio and video PES reading feature| 24-Jul-2001 Fix the semaphore bug, and add demux_channel_free() when| DmxFilterAlloc() fail. Add xp_os_enter_critical_section()| in DmxFilterRead()| 30-Sep-2001 Updated for Pallas| 10-Oct-2001 Add ts_res set and select source| 08-Jan-2002 Fix filter length bug when section filtering| 10-Jan-2002 Add PCR sync when enable filterring PCR| 25-Mar-2002 Allow two and more section filters added to a channel| 10-Apil-02 Add positive enable in section filter para, add get| filter num ioctl, for PLR| 11-May-2002 Change the buffer to circle queue for section filter| 02-Jun-2002 Add STC event| 18-jun-2002 Support VESTA and VULCAN| 19-Jun-2002 Add notification when the filter is stoped to avoid reading| waiting forever| 12-aug-2002 Add condition(pDmxfilter->chid != ILLEGAL_CHANNEL) for the| operation chid[pDmxfilter->chid].inuse++| 17-aug-2002 Fix the bug foe queue management when multiple filters| attached to on queue| 22-Jul-2003 Corrected problem such that filters with the same PID and| channel can be opened, set, and started in any order instead| of in-sequence.| 22-Jul-2003 Removed all "demux_" functions to eliminate similarity to| proprietary API definitions.+----------------------------------------------------------------------------*/#include <linux/config.h>#include <linux/version.h>#ifdef MODVERSIONS#include <linux/modversions.h>#endif#include <linux/kernel.h>#define __NO_VERSION__#include <linux/module.h>#include <linux/sched.h>#include <linux/fs.h>#include <linux/ptrace.h>#include <linux/string.h>#include <linux/ioport.h>#include <linux/version.h>#include <linux/delay.h>#include <linux/errno.h>#include <linux/fcntl.h>#include <linux/in.h>#include <linux/interrupt.h>#include <linux/init.h>#include <linux/poll.h>#include <linux/vmalloc.h>#include <linux/slab.h>#include <asm/system.h>#include <asm/uaccess.h>#include <asm/bitops.h>#include <asm/io.h>#include <asm/irq.h>#include "xp_osi_global.h"#include "xp_atom_reg.h"#include "xp_osd_drv.h"/*----------------------------------------------------------------------------+| Local Defines+----------------------------------------------------------------------------*/#ifdef PDEBUG#undef PDEBUG#endif#define PDEBUG(fmt,args...)#define PDEBUG1(fmt,args...) /*----------------------------------------------------------------------------+| Type Declarations+----------------------------------------------------------------------------*/typedef struct demux_channel_acquire_type { XP_CHANNEL_TYPE channel_type; /* channel type */ XP_CHANNEL_UNLOAD_TYPE unload_type; /* type of data to unload */ XP_CHANNEL_NOTIFY_FN notify_data_fn; /* func to call when data recv */ unsigned short bthreshold; /* boundary threshold */ unsigned short pid; /* program id */ unsigned long queue_size; /* queue size */} DEMUX_CHANNEL_ACQUIRE_TYPE, *DEMUX_CHANNEL_ACQUIRE_PTR;/*----------------------------------------------------------------------------+| Static Declarations+----------------------------------------------------------------------------*/static INT uAlreadyInit = 0;static INT DEFAULT_FILTER_LENGTH = 9;static void vma_open(struct vm_area_struct *vma);static void vma_close(struct vm_area_struct *vma);static struct vm_operations_struct my_vm_ops ={ open: vma_open, close: vma_close};/*----------------------------------------------------------------------------+| Global Declarations+----------------------------------------------------------------------------*/DEMUX_DEVICE *pDemux_dev[MAX_XP_NUM];GLOBAL_RESOURCES XpGlobal[MAX_XP_NUM];MUTEX_T hMutex;/*----------------------------------------------------------------------------+| External Declarations+----------------------------------------------------------------------------*/extern XP_STC_NOTIFY_FN stc_notify_fn;/*----------------------------------------------------------------------------+| Prototype Definitions+----------------------------------------------------------------------------*/static DECLARE_WAIT_QUEUE_HEAD(stc_WaitQ);DECLARE_WAIT_QUEUE_HEAD(temp_queue);/*----------------------------------------------------------------------------+| XX XX XXXXXX XXXXXX XXXX XXXXXXX XX XXX| XXX XX XX XX X XX X XX XX XX XX| XXXX XX XX XX XX XX XX XXXX| XX XXXX XX XX XX XX XXXX XX| XX XXX XX XX XX XX XX XX| XX XX XX XX XX XX XX XX| XX XX XXXXXX XXXX XXXX XXXX XX+----------------------------------------------------------------------------*//*----------------------------------------------------------------------------+| DemuxGetQPBase+----------------------------------------------------------------------------*/static UCHAR *DemuxGetQPBase( GLOBAL_RESOURCES *pGlobal, DEMUX_FILTER *pDmxfilter, UCHAR *plBuffer){ UCHAR *ppBQueue; UCHAR *ppBuffer; UCHAR *plBQueue; plBQueue = (UCHAR*)os_get_logical_address( pGlobal->QueueInfo.XpQueueChData[pDmxfilter->chid].hMem); ppBQueue = (UCHAR*)os_get_physical_address( pGlobal->QueueInfo.XpQueueChData[pDmxfilter->chid].hMem); ppBuffer = (UCHAR*)((ULONG)ppBQueue + (ULONG)plBuffer - (ULONG)plBQueue); return(ppBuffer);}/*----------------------------------------------------------------------------+| DemuxCopyToCBuf+----------------------------------------------------------------------------*/static void DemuxCopyToCBuf( DEMUX_FILTER_BUF *pDmxfbuf, XP_CHANNEL_NOTIFY_DATA *pInfo){ ULONG BErem, QErem; ULONG nulWrite; UCHAR *pBloc, *pQloc; UCHAR *pBstart, *pQstart; /*-------------------------------------------------------------------------+ | Determine Queue and Circular Buffer Start and Wrap point +-------------------------------------------------------------------------*/ nulWrite = (pDmxfbuf->ulWrite + 1) % pDmxfbuf->ulSize; pBstart = pDmxfbuf->plData; pQstart = pDmxfbuf->plBQueue; pBloc = &pDmxfbuf->plData[nulWrite]; pQloc = pInfo->plData; BErem = pDmxfbuf->ulSize - nulWrite; QErem = pDmxfbuf->plEQueue - pInfo->plData; /*-------------------------------------------------------------------------+ | Transfer Transport Queue Data to Internal Circular Buffer | Manage Wrap on both Circular Queues +-------------------------------------------------------------------------*/ if ((BErem < pInfo->ulLength) && (QErem < pInfo->ulLength)) { if (QErem > BErem) { memcpy(&pBloc[0], &pQloc[0], BErem); memcpy(&pBstart[0], &pQloc[BErem], QErem-BErem); memcpy(&pBstart[QErem-BErem], &pQstart[0], pInfo->ulLength-QErem); } else if (BErem > QErem) { memcpy(&pBloc[0], &pQloc[0], QErem); memcpy(&pBloc[QErem], &pQstart[0], BErem-QErem); memcpy(&pBstart[0], &pQstart[BErem-QErem], pInfo->ulLength-BErem); } else { memcpy(&pBloc[0], &pQloc[0], BErem); memcpy(&pBstart[0], &pQstart[0], pInfo->ulLength-BErem); } } else if (BErem < pInfo->ulLength) { memcpy(&pBloc[0], &pQloc[0], BErem); memcpy(&pBstart[0], &pQloc[BErem], pInfo->ulLength-BErem); } else if (QErem < pInfo->ulLength) { memcpy(&pBloc[0], &pQloc[0], QErem); memcpy(&pBloc[QErem], &pQstart[0], pInfo->ulLength-QErem); } else { memcpy(&pBloc[0], &pQloc[0], pInfo->ulLength); } /*-------------------------------------------------------------------------+ | Bump Internal Circular Buffer pointers +-------------------------------------------------------------------------*/ pDmxfbuf->count = pDmxfbuf->count + pInfo->ulLength; pDmxfbuf->ulWrite = (pDmxfbuf->ulWrite + pInfo->ulLength) % pDmxfbuf->ulSize; return;}/*----------------------------------------------------------------------------+| DemuxSectioncallback+----------------------------------------------------------------------------*/static void DemuxSectionCallback( XP_CHANNEL_NOTIFY_DATA * pInfo){ int i; int j; int MatchCount = 0; int match[32]; ULONG bytes_available; ULONG notify_length; unsigned char *data; unsigned char *b_data; unsigned char *e_data; unsigned char *s; UCHAR *ppBuffer; DEMUX_FILTER *pDmxfilter=NULL; SECTION_HEADER_PTR SectionHeader; GLOBAL_RESOURCES *pGlobal; DEMUX_DEVICE *pDemuxDev; PDEBUG1("DemuxSectioncallback(): Entering\n"); pGlobal = pInfo->pGlobal; pDemuxDev = pDemux_dev[pGlobal->uDeviceIndex]; //Find the filter which matched the recieved section for (i = 0; i < pDemuxDev->uFilterNum; i++) { if (pDemuxDev->filter[i].chid == pInfo->wChannelId && ((pDemuxDev->filter[i].ulMatchWord & pInfo->ulMatchWord) == pDemuxDev->filter[i].ulMatchWord)) { match[MatchCount] = i; MatchCount++; } } if (!MatchCount) { printk("DemuxSectioncallback(): Error - no filter matched section received\n"); return; } for(j=0;j<MatchCount;j++) { i = match[j]; pDmxfilter = (DEMUX_FILTER *) (&pDemuxDev->filter[i]); //If received section data 's size is smaller than 3 bytes, ehich is the minimum byte //of the section. retun if (pInfo->ulLength < 3) { ppBuffer = DemuxGetQPBase(pGlobal,pDmxfilter,pInfo->plData); xp_osi_queue_unlock_data(pGlobal, pDmxfilter->chid, (UCHAR *)ppBuffer, (ULONG)pInfo->ulLength); printk("DemuxSectioncallback(): Error - notify length =0\n"); return; } //bytes_availbale is the size of the received data bytes_available = pDmxfilter->buffer.plEQueue - pInfo->plData; data = pInfo->plData; SectionHeader = (SECTION_HEADER_PTR) (data); //Notify_length is the size of a complete table section notify_length = SectionHeader->sectionLength + 3; if (SectionHeader->sectionLength == 0) { ppBuffer = DemuxGetQPBase(pGlobal,pDmxfilter,pInfo->plData); xp_osi_queue_unlock_data(pGlobal, pDmxfilter->chid, (UCHAR *) ppBuffer, (ULONG) pInfo->ulLength); printk("DemuxSectioncallback(): Error - Section Filter length =0\n"); return; } if (notify_length > pInfo->ulLength) { ppBuffer = DemuxGetQPBase(pGlobal,pDmxfilter,pInfo->plData); xp_osi_queue_unlock_data(pGlobal,pDmxfilter->chid, (UCHAR *)ppBuffer, (ULONG)pInfo->ulLength); printk("DemuxSectioncallback(): Warning - notify length > available_length\n"); notify_length = pInfo->ulLength; return; } b_data = pInfo->plData; if (notify_length >= bytes_available) { e_data = pDmxfilter->buffer.plBQueue + (notify_length - bytes_available); } else { e_data = pInfo->plData + notify_length; } pDmxfilter->ulNotifySize = notify_length; //special process when the queue is wrap if (pDmxfilter->buffer.plData) { if(pDmxfilter->buffer.count + notify_length >= pDmxfilter->buffer.ulSize) { printk("DemuxSectioncallback(): Error - Buffer is full\n"); } else { for (i = 0, s = b_data; i < notify_length; i++, s++) { if (s == pDmxfilter->buffer.plEQueue) { s = pDmxfilter->buffer.plBQueue; } pDmxfilter->buffer.count++; pDmxfilter->buffer.ulWrite = (pDmxfilter->buffer.ulWrite + 1)%pDmxfilter->buffer.ulSize; pDmxfilter->buffer.plData[pDmxfilter->buffer.ulWrite] = *s; } } } if(pDmxfilter->async_queue != NULL) kill_fasync(&pDmxfilter->async_queue, SIGIO, POLL_IN); // unlock queue wake_up_interruptible(&pDmxfilter->buffer.queue); } ppBuffer = DemuxGetQPBase(pGlobal,pDmxfilter,pInfo->plData); xp_osi_queue_unlock_data(pGlobal,pDmxfilter->chid, (UCHAR *)ppBuffer, (ULONG)pInfo->ulLength); return;}/*----------------------------------------------------------------------------+| DemuxPESCallback+----------------------------------------------------------------------------*/static void DemuxPESCallback( XP_CHANNEL_NOTIFY_DATA * pInfo){ int i; ULONG BTrem; UCHAR *ppBuffer; DEMUX_FILTER *pDmxfilter; DEMUX_DEVICE *pDemuxDev; GLOBAL_RESOURCES *pGlobal; PDEBUG1("DemuxPESCallback(): Entering\n"); /*-------------------------------------------------------------------------+ | Find Filter Associated with PES Callback +-------------------------------------------------------------------------*/ pGlobal = pInfo->pGlobal; pDemuxDev = pDemux_dev[pGlobal->uDeviceIndex]; for (i = 0; i < pDemuxDev->uFilterNum; i++) { if (pDemuxDev->filter[i].chid == pInfo->wChannelId) { break; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -