blob: e4656e0e54f89912750059d9bc4d74f0048830f3 [file] [log] [blame]
/**************************************************************************//**
* @file cimax+usb-driver.h
*
* @brief CIMaX+ USB Driver for linux based operating systems.
*
* Copyright (C) 2009-2011 Bruno Tonelli <bruno.tonelli@smardtv.com>
* & Franck Descours <franck.descours@smardtv.com>
* for SmarDTV France, La Ciotat
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
******************************************************************************/
#include <linux/version.h>
#ifndef CIMAXPLUS_USB_DRIVER_H
#define CIMAXPLUS_USB_DRIVER_H
/******************************************************************************
* Includes
*****************************************************************************/
/******************************************************************************
* Defines
*****************************************************************************/
/**
* @brief
* Driver Name
*/
#define DRIVER_NAME "cimax+usb"
/**
* @brief
* An unassigned USB minor.
*/
#define DEVICE_MINOR 240
/**
* @brief
* Driver version.
*/
#define DEVICE_VERSION 0x1000
/**
* @brief
* Number of CA module supported by the driver.
*/
#define DEVICE_NUM_CAM 2
/**
* @brief
* Buffer length.
*/
#define DEVICE_MESSAGE_LENGTH 4100
/* Offset */
#define DEVICE_COMMAND_OFFSET 0
#define DEVICE_STATUS_OFFSET 0
#define DEVICE_COUNTER_OFFSET 1
#define DEVICE_LENGTH_MSB_OFFSET 2
#define DEVICE_LENGTH_LSB_OFFSET 3
#define DEVICE_DATA_OFFSET 4
/* Mask */
#define DEVICE_SEL_MASK 0x80
#define DEVICE_TYP_MASK 0x40
#define DEVICE_CMD_MASK 0x3F
/* Command tag */
#define DEVICE_CMD_INIT 0x00
#define DEVICE_CMD_WRITE_REG 0x7F
#define DEVICE_CMD_READ_REG 0xFF
#define DEVICE_CMD_CAMRESET 0x01
#define DEVICE_CMD_GETCIS 0x02
#define DEVICE_CMD_WRITECOR 0x03
#define DEVICE_CMD_NEGOTIATE 0x04
#define DEVICE_CMD_WRITELPDU 0x05
#define DEVICE_CMD_READLPDU 0x06
#define DEVICE_CMD_WRITEEXT 0x07
#define DEVICE_CMD_READEXT 0x08
#define DEVICE_CMD_CC1RESET 0x09
#define DEVICE_CMD_MCARD_WRITE 0x0a
/* Status field */
#define DEVICE_CAMRESETOK 0x00
#define DEVICE_CISOK 0x01
#define DEVICE_WRITECOROK 0x02
#define DEVICE_NEGOTIATEOK 0x03
#define DEVICE_WRITELPDUOK 0x04
#define DEVICE_CAMDET 0x05
#define DEVICE_READLPDUOK 0x06
#define DEVICE_WRITEEXTOK 0x07
#define DEVICE_READEXTOK 0x08
#define DEVICE_NO_CAM 0x09
#define DEVICE_NOK 0x0a
#define DEVICE_INITOK 0x0b
#define DEVICE_READ_REGOK 0x0c
#define DEVICE_WRITE_REGOK 0x0d
#define DEVICE_DATAREADY 0x0e
#define DEVICE_MCARD_WRITEOK 0x0f
#define DEVICE_MCARD_READ 0x10
#define DEVICE_CAMPARSE_ERROR 0x11
#define DEVICE_WRITELPDUBUSY 0x14
#define DEVICE_CMDPENDING 0x16
#define DEVICE_REGSTATUSOK 0x17
#define DEVICE_GPIOCHANGE 0x18
#define DEVICE_FRBit 0x1A
#define DEVICE_DATAREADY_SYNC 0x3e
/**
* @brief
* MPEG2 transport size,.isochronous size and number of frames per URB.
*/
#define DEVICE_MPEG2_PACKET_SIZE 188
#define DEVICE_MPEG2_SYNC_BYTE 0x47
#define DEVICE_NULL_HEADER_SIZE 8
#define DEVICE_NUM_FRAMES_PER_URB 8
#define DEVICE_ISOC_LENGTH(x) (DEVICE_NUM_FRAMES_PER_URB*x)
#define DEVICE_VB_LENGTH 902400
/**
* @brief
* Endpoint address.
*/
#define DEVICE_TS_IN_PIPE 1 /* and 2 */
#define DEVICE_TS_OUT_PIPE 3 /* and 4 */
#define DEVICE_INT_IN_PIPE 5
#define DEVICE_BULK_OUT_PIPE 6
#define DEVICE_BULK_OUT_MAXPACKET 256
/**
* @brief
* Number of isochronous/int URBs in the driver.
*/
#define DEVICE_NUM_ISOC_OUT_URBS 3
#define DEVICE_NUM_ISOC_IN_URBS 2
#define DEVICE_NUM_INT_IN_URBS 2
/**
* @brief
* ioctl() calls definition.
*/
#define DEVICE_IOC_MAGIC 'a'
#define DEVICE_IOC_SELECT_INTF _IOWR(DEVICE_IOC_MAGIC, 0, signed long)
#define DEVICE_IOC_CI_WRITE _IOWR(DEVICE_IOC_MAGIC, 1, struct ioctl_data_s)
#define DEVICE_IOC_UNLOCK_READ _IOWR(DEVICE_IOC_MAGIC, 2, signed long)
#define DEVICE_IOC_SET_CONFIG _IOWR(DEVICE_IOC_MAGIC, 3, struct ioctl_data_s)
#define DEVICE_IOC_MAXNR 4
/******************************************************************************
* Types
*****************************************************************************/
#ifdef __KERNEL__
#include <linux/list.h>
#include <linux/atomic.h>
#include <linux/printk.h>
#undef dbg
#undef dbg_isoc_in
#undef dbg_isoc_out
#undef err
#undef info
#undef warn
#define DEBUG
#ifdef DEBUG
#define dbg(format, arg...) pr_debug("cimax+usb: %s> " format "\n" , \
__func__, ## arg)
#define dbg_s(format, arg...)\
pr_debug("cimax+usb: " format "\n" , ## arg)
#else
#define dbg(format, arg...) do {} while (0)
#define dbg_s(format, arg...) do {} while (0)
#endif
#ifdef DEBUG_ISOC_IN
#define dbg_isoc_in(format, arg...)\
pr_debug("cimax+usb: %s> " format "\n" , \
__func__, ## arg)
#else
#define dbg_isoc_in(format, arg...) do {} while (0)
#endif
#ifdef DEBUG_ISOC_OUT
#define dbg_isoc_out(format, arg...)\
pr_debug("cimax+usb: %s> " format "\n" , \
__func__, ## arg)
#else
#define dbg_isoc_out(format, arg...) do {} while (0)
#endif
#define err(format, arg...)\
pr_err("cimax+usb: %s> ERROR " format "\n" , \
__func__, ## arg)
#define info(format, arg...)\
pr_info("cimax+usb: %s> " format "\n" , \
__func__, ## arg)
#define warn(format, arg...)\
pr_warn("cimax+usb: %s> WARN" format "\n" , \
__func__, ## arg)
/**
* @brief
* Video buffer structure.
*/
struct video_buf_s {
__u8 data[DEVICE_VB_LENGTH];
int readOffset;
int writeOffset;
int isEmpty;
};
#endif
/**
* @brief
* Io control data structure exchanged between user and kernel space.
*/
struct ioctl_data_s {
__u8 *txData;
__u32 txSize;
__u8 *rxData;
__u32 rxSize;
};
/**
* @brief
* Read/write type exchanged between user and kernel space.
*/
enum rw_type_e {
DEVICE_TYPE_CI_READ,
DEVICE_TYPE_TS_WRITE,
DEVICE_TYPE_TS_READ
};
/**
* @brief
* Read/write data structure exchanged between user and kernel space.
*/
struct rw_data_s {
enum rw_type_e type;
__u8 moduleId;
__u8 *data;
__u32 size;
__u32 copiedSize;
};
#ifdef __KERNEL__
/**
* @brief
* Message node structure. Can be inserted in a list.
*/
struct message_node_s {
__u8 data[DEVICE_MESSAGE_LENGTH];
__u32 size;
struct list_head node;
};
/**
* @brief
* Received CI data.
*/
struct ci_rx_data_s {
wait_queue_head_t syncWait;
__u8 syncSignal;
__u8 syncData[DEVICE_MESSAGE_LENGTH];
__u32 syncDataSize;
wait_queue_head_t asyncWait;
struct list_head asyncDataList;
__u8 bPendingSend;
};
/**
* @brief
* CI bulk channel.
*/
struct ci_bulk_s {
__u8 counter;
__u16 inMaxPacketSize;
__u16 outMaxPacketSize;
struct urb *intUrb[DEVICE_NUM_INT_IN_URBS];
spinlock_t intLock;
spinlock_t intUrbLock;
__u8 intCurrStatus;
__u8 intCurrIndex;
__u16 intSizeToReceive;
struct ci_rx_data_s ciData[DEVICE_NUM_CAM];
};
/**
* @brief
* TS channel (can use isoc or bulk interface).
*/
struct ts_channel_s {
spinlock_t inLock;
wait_queue_head_t inWait;
struct video_buf_s inVb;
int syncOffset;
int prevOffset;
__u8 lastPacket[DEVICE_MPEG2_PACKET_SIZE];
__u8 lastPacketSize;
spinlock_t outLock;
__u8 nextFreeOutUrbIndex;
atomic_t numOutUrbs;
__u8 outStop;
__u16 maxPacketSize;
/* isochronous urbs */
struct urb *isocInUrb[DEVICE_NUM_ISOC_IN_URBS];
struct urb *isocOutUrb[DEVICE_NUM_ISOC_OUT_URBS];
/* bulk urbs */
struct urb *bulkInUrb;
int nbByteSend;
int nbByteRead;
__u8 FirstTransfer;
struct timer_list StartBulkReadTimer;
#ifdef DEBUG_BITRATE
ktime_t bitrateTime
#endif
};
struct device_s {
struct mutex lock;
struct usb_device *usbdev;
__u8 opened;
__u8 askToRelease;
__u8 askToSuspend;
struct ci_bulk_s ciBulk;
__u8 useIsoc;
struct ts_channel_s channel[DEVICE_NUM_CAM];
/* bus adapter private ops callback */
struct cimaxusb_priv_ops_t *ops;
int ref;
};
struct bulk_timer_s {
struct device_s *device;
__u8 index;
};
int cimax_usb_select_interface(struct device_s *device, unsigned long intf);
int cimax_usb_ci_write(struct device_s *device,
u8 *txData, int txSize, u8 *rxData, int rxSize);
int cimax_usb_ci_read_evt(struct device_s *device,
int moduleId, u8 *buf, int size);
int cimax_usb_device_unlock_read(struct device_s *device);
int cimax_usb_device_open(struct device_s *device);
int cimax_usb_device_close(struct device_s *device);
void cimax_usb_set_cb(void *cb1, void *cb2);
#endif
#endif