Subversion Repositories shark

Rev

Rev 1049 | Blame | Compare with Previous | Last modification | View Log | RSS feed


/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */


#include <linuxcomp.h>

#include <linux/config.h>
#include <linux/types.h>
#include <linux/major.h>
#include <linux/errno.h>
#include <linux/signal.h>

#include "media/pwc-ioctl.h"
#include <linux/videodev.h>
#include <drivers/shark_pwc26.h>

/*
* shark lowlevel wrapper
*/


struct PWC_data {
        struct file* file;
        struct pwc_imagesize RealSize;
        struct pwc_coord m_ViewSize, m_RealSize;
        struct pwc_coord m_Offset;
        struct video_capability Capability;
        struct pwc_probe Probe;
        struct video_picture Picture;
        struct video_window Window;
        struct pwc_video_command VideoCmd;
        void *m_pPWCXBuffer, *m_pInputBuffer, *m_pImageBuffer;
        int m_Frames, len, m_UseRaw, m_ImageSize, m_ImageLen;
        int m_Type, m_Bandlength, m_Bayer;
        int m_InputLen;
};


extern int usb_pwc_init();
extern void* malloc(size_t size);

extern int pwc_video_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg);
extern int pwc_video_open(struct inode *inode, struct file *file);
extern int pwc_video_close(struct inode *inode, struct file *file);
extern ssize_t pwc_video_read(struct file *file, char *buf, size_t count, loff_t *ppos);
extern int pwc_video_ioctl(struct inode *inode, struct file *file, unsigned int ioctlnr, unsigned long arg);

void shark_PWC_init()
{
        usb_pwc_init();
}

int shark_PWC_open(struct PWC26_DEVICE *pwc26, int width, int height, int fps, int quality, int webcamnr)
{
        int err;
        struct PWC_data *pwc_data;
        struct file *file;
        struct inode *inode;

        pwc_data = malloc(sizeof(struct PWC_data));
        pwc26->private_data = (void*)pwc_data;

        if (!pwc_data)
                return -ENOMEM;

        memset(pwc_data, 0, sizeof(struct PWC_data));
        file =  malloc(sizeof(struct file));
        if (!file)
                return -ENOMEM;

        file->f_dentry= malloc(sizeof(struct dentry));
        if (!file->f_dentry)
                return -ENOMEM;

        file->f_dentry->d_inode = malloc(sizeof(struct inode));
        if (!file->f_dentry->d_inode)
                return -ENOMEM;

        file->f_dentry->d_inode->i_rdev = webcamnr;
        inode = file->f_dentry->d_inode;

        pwc_data->file = file;
        pwc_data->m_ViewSize.x = width;
        pwc_data->m_ViewSize.y = height;
        pwc_data->m_Frames = fps;

        pwc_data->m_RealSize = pwc_data->m_ViewSize;

        pwc_data->m_Offset.x = 0;
        pwc_data->m_Offset.y = 0;
        pwc_data->m_UseRaw = TRUE;
        pwc_data->m_Bayer = FALSE;
        pwc_data->m_pInputBuffer = NULL;
        pwc_data->m_InputLen = 0;
        pwc_data->m_pImageBuffer = NULL;
        pwc_data->m_ImageLen = NULL;
        pwc_data->m_Type = NULL;

        pwc_data->m_pPWCXBuffer = malloc(60000); // large enoug for all cams
        if (!pwc_data->m_pPWCXBuffer)
                return -ENOMEM;

        err=pwc_video_open(inode, file);
        if (err <0)
                return err;

        pwc_video_do_ioctl(inode, file, VIDIOCGCAP, &pwc_data->Capability);

        printk(KERN_INFO "Capability->type= %d\n", pwc_data->Capability.type);
        printk(KERN_INFO "Capability->channels =%d\n",pwc_data->Capability.channels);
        printk(KERN_INFO "Capability->audios=%d\n",pwc_data->Capability.audios);
        printk(KERN_INFO "Capability->minwidth=%d\n",pwc_data->Capability.minwidth);
        printk(KERN_INFO "Capability->minheight=%d\n",pwc_data->Capability.minheight);
        printk(KERN_INFO "Capability->maxwidth=%d\n",pwc_data->Capability.maxwidth);
        printk(KERN_INFO "Capability->maxheight=%d\n",pwc_data->Capability.maxheight);

        memset(&pwc_data->Probe, 0, sizeof(pwc_data->Probe));
        pwc_video_do_ioctl(inode, file, VIDIOCPWCPROBE, &pwc_data->Probe);
        pwc_video_do_ioctl(inode, file, VIDIOCGPICT, &pwc_data->Picture);

        if (pwc_data->m_UseRaw)
                pwc_data->Picture.palette = VIDEO_PALETTE_RAW;
        else
                pwc_data->Picture.palette = VIDEO_PALETTE_YUV420P;

        pwc_video_do_ioctl(inode, file, VIDIOCSPICT, &pwc_data->Picture);
        pwc_video_do_ioctl(inode, file, VIDIOCGWIN, &pwc_data->Window);

        /* unavailable in pwc 10.x */
        if (pwc_data->m_Bayer)
        {
                // special raw Bayer mode
                pwc_data->m_ViewSize.x = 640;
                pwc_data->m_ViewSize.y = 480;
                pwc_data->m_Frames = 5;
                pwc_data->m_RealSize = pwc_data->m_ViewSize;
        }

        pwc_data->Window.width = pwc_data->m_ViewSize.x;
        pwc_data->Window.height = pwc_data->m_ViewSize.y;
        pwc_data->Window.flags = (pwc_data->m_Frames << PWC_FPS_SHIFT);

        if (pwc_data->m_Bayer)
                pwc_data->Window.flags |= PWC_FPS_SNAPSHOT;

        pwc_video_do_ioctl(inode, file, VIDIOCSWIN, &pwc_data->Window);

        if (pwc_data->m_UseRaw)
        {
                pwc_video_do_ioctl(inode, file, VIDIOCPWCGVIDCMD, &pwc_data->VideoCmd);

                pwc_data->m_Type = pwc_data->VideoCmd.type;
                pwc_data->m_InputLen = pwc_data->VideoCmd.frame_size;
                pwc_data->m_Bandlength = pwc_data->VideoCmd.bandlength;

                if (pwc_data->m_Bandlength > 0)
                {
                        switch(pwc_data->m_Type)
                        {
                                case 645:
                                case 646:
                                        pwcx_init_decompress_Nala(pwc_data->m_Type, pwc_data->VideoCmd.release, &pwc_data->VideoCmd.command_buf, pwc_data->m_pPWCXBuffer);
                                break;

                                case 675:
                                case 680:
                                case 690:
                                        pwcx_init_decompress_Timon(pwc_data->m_Type, pwc_data->VideoCmd.release, &pwc_data->VideoCmd.command_buf, pwc_data->m_pPWCXBuffer);
                                        break;

                                case 720:
                                case 730:
                                case 740:
                                case 750:
                                        pwcx_init_decompress_Kiara(pwc_data->m_Type, pwc_data->VideoCmd.release, &pwc_data->VideoCmd.command_buf, pwc_data->m_pPWCXBuffer);
                                        break;

                                default:
                                        //                              qDebug("Unknown type of camera (%d)!", VideoCmd.type);
                                        break;
                        } // ..switch
                } // ..m_Bandlength > 0

                if (pwc_video_do_ioctl(inode, file, VIDIOCPWCGREALSIZE, &pwc_data->RealSize) == 0)
                {
                        pwc_data->m_Offset.x = (pwc_data->m_ViewSize.x - pwc_data->RealSize.width) / 2;
                        pwc_data->m_Offset.y = (pwc_data->m_ViewSize.y - pwc_data->RealSize.height) / 2;
                }
        }

        pwc_data->m_ImageLen = pwc_data->m_ViewSize.x * pwc_data->m_ViewSize.y * 3;
        pwc_data->m_pImageBuffer = malloc (pwc_data->m_ImageLen);

        if (pwc_data->m_UseRaw)
        {
                pwc_data->m_pInputBuffer = malloc(pwc_data->m_InputLen);
        }
        else
        {
                if (pwc_data->m_pImageBuffer != 0)
                {
                        pwc_data->m_pInputBuffer = pwc_data->m_pImageBuffer;
                        pwc_data->m_InputLen = pwc_data->m_ImageLen;
                }
        }

        pwc26->width=pwc_data->m_ViewSize.x ;
        pwc26->height=pwc_data->m_ViewSize.y ;
        pwc26->imgptr=(BYTE*)pwc_data->m_pImageBuffer;

        return 0;
}

int shark_PWC_read(struct PWC26_DEVICE *pwc26)
{
        int len;
        struct PWC_data *pwc_data = (struct PWC_data*)pwc26->private_data;

        if (pwc_data->m_pInputBuffer == 0 || pwc_data->m_pImageBuffer == 0)
                return -666;

        len = pwc_video_read(pwc_data->file, pwc_data->m_pInputBuffer, pwc_data->m_InputLen, 0);

        if (len > 0 && pwc_data->m_Bandlength > 0)
        {
                switch(pwc_data->m_Type)
                {
                        case 645:
                        case 646:
                                pwcx_decompress_Nala(&pwc_data->m_RealSize, &pwc_data->m_ViewSize, &pwc_data->m_Offset, \
                                pwc_data->m_pInputBuffer, pwc_data->m_pImageBuffer, \
                                PWCX_FLAG_PLANAR, \
                                pwc_data->m_pPWCXBuffer, pwc_data->m_Bandlength);
                                break;

                        case 675:
                        case 680:
                        case 690:
                                pwcx_decompress_Timon(&pwc_data->m_RealSize, &pwc_data->m_ViewSize, &pwc_data->m_Offset, \
                                pwc_data->m_pInputBuffer, pwc_data->m_pImageBuffer, \
                                PWCX_FLAG_PLANAR, \
                                pwc_data->m_pPWCXBuffer, pwc_data->m_Bandlength);
                                break;

                        case 720:
                        case 730:
                        case 740:
                        case 750:
                                pwcx_decompress_Kiara(&pwc_data->m_RealSize, &pwc_data->m_ViewSize, &pwc_data->m_Offset, \
                                pwc_data->m_pInputBuffer, pwc_data->m_pImageBuffer, \
                                PWCX_FLAG_PLANAR | (pwc_data->m_Bayer ? PWCX_FLAG_BAYER : 0), \
                                pwc_data->m_pPWCXBuffer, pwc_data->m_Bandlength);
                                break;
                }
        }
        return len;
}

void shark_PWC_close(struct PWC26_DEVICE *pwc26)
{
        struct file *file;
        struct inode *inode;
        struct PWC_data *pwc_data = (struct PWC_data*)pwc26->private_data;

        if (!pwc_data)
                return;

        free(pwc_data->m_pPWCXBuffer);

        file = pwc_data->file;
        inode = file->f_dentry->d_inode;
        //  pwc_video_close(inode, file);

        free(inode);
        free(file->f_dentry);
        free(file);
        free(pwc_data);
}