mirror of https://github.com/drowe67/librtlsdr.git
rtl_ir: merge some init code from Linux dvb-usb-v2 driver
9256d5a308/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
master
parent
024f3c57a2
commit
4b4942fb05
341
src/rtl_ir.c
341
src/rtl_ir.c
|
@ -1,5 +1,8 @@
|
|||
/*
|
||||
* rtl-sdr, turns your Realtek RTL2832 based DVB dongle into a SDR receiver
|
||||
* Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
|
||||
* Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
|
||||
* Copyright (C) 2012 Thomas Mair <thomas.mair86@googlemail.com>
|
||||
* Copyright (C) 2012 by Steve Markgraf <steve@steve-m.de>
|
||||
* Copyright (C) 2012 by Hoernchen <la@tfc-server.de>
|
||||
* Copyright (C) 2012 by Kyle Keen <keenerd@gmail.com>
|
||||
|
@ -48,19 +51,263 @@
|
|||
#include "rtl-sdr.h"
|
||||
#include "convenience/convenience.h"
|
||||
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
|
||||
// Registers from Linux drivers/media/usb/dvb-usb-v2/rtl28xxu.h TODO: merge into librtlsdr?
|
||||
struct rtl28xxu_req {
|
||||
uint16_t value;
|
||||
uint16_t index;
|
||||
uint16_t size;
|
||||
uint8_t *data;
|
||||
};
|
||||
|
||||
struct rtl28xxu_reg_val {
|
||||
uint16_t reg;
|
||||
uint8_t val;
|
||||
};
|
||||
|
||||
struct rtl28xxu_reg_val_mask {
|
||||
uint16_t reg;
|
||||
uint8_t val;
|
||||
uint8_t mask;
|
||||
};
|
||||
|
||||
/*
|
||||
* memory map
|
||||
*
|
||||
* 0x0000 DEMOD : demodulator
|
||||
* 0x2000 USB : SIE, USB endpoint, debug, DMA
|
||||
* 0x3000 SYS : system
|
||||
* 0xfc00 RC : remote controller (not RTL2831U)
|
||||
*/
|
||||
|
||||
/*
|
||||
* USB registers
|
||||
*/
|
||||
/* SIE Control Registers */
|
||||
#define USB_SYSCTL 0x2000 /* USB system control */
|
||||
#define USB_SYSCTL_0 0x2000 /* USB system control */
|
||||
#define USB_SYSCTL_1 0x2001 /* USB system control */
|
||||
#define USB_SYSCTL_2 0x2002 /* USB system control */
|
||||
#define USB_SYSCTL_3 0x2003 /* USB system control */
|
||||
#define USB_IRQSTAT 0x2008 /* SIE interrupt status */
|
||||
#define USB_IRQEN 0x200C /* SIE interrupt enable */
|
||||
#define USB_CTRL 0x2010 /* USB control */
|
||||
#define USB_STAT 0x2014 /* USB status */
|
||||
#define USB_DEVADDR 0x2018 /* USB device address */
|
||||
#define USB_TEST 0x201C /* USB test mode */
|
||||
#define USB_FRAME_NUMBER 0x2020 /* frame number */
|
||||
#define USB_FIFO_ADDR 0x2028 /* address of SIE FIFO RAM */
|
||||
#define USB_FIFO_CMD 0x202A /* SIE FIFO RAM access command */
|
||||
#define USB_FIFO_DATA 0x2030 /* SIE FIFO RAM data */
|
||||
/* Endpoint Registers */
|
||||
#define EP0_SETUPA 0x20F8 /* EP 0 setup packet lower byte */
|
||||
#define EP0_SETUPB 0x20FC /* EP 0 setup packet higher byte */
|
||||
#define USB_EP0_CFG 0x2104 /* EP 0 configure */
|
||||
#define USB_EP0_CTL 0x2108 /* EP 0 control */
|
||||
#define USB_EP0_STAT 0x210C /* EP 0 status */
|
||||
#define USB_EP0_IRQSTAT 0x2110 /* EP 0 interrupt status */
|
||||
#define USB_EP0_IRQEN 0x2114 /* EP 0 interrupt enable */
|
||||
#define USB_EP0_MAXPKT 0x2118 /* EP 0 max packet size */
|
||||
#define USB_EP0_BC 0x2120 /* EP 0 FIFO byte counter */
|
||||
#define USB_EPA_CFG 0x2144 /* EP A configure */
|
||||
#define USB_EPA_CFG_0 0x2144 /* EP A configure */
|
||||
#define USB_EPA_CFG_1 0x2145 /* EP A configure */
|
||||
#define USB_EPA_CFG_2 0x2146 /* EP A configure */
|
||||
#define USB_EPA_CFG_3 0x2147 /* EP A configure */
|
||||
#define USB_EPA_CTL 0x2148 /* EP A control */
|
||||
#define USB_EPA_CTL_0 0x2148 /* EP A control */
|
||||
#define USB_EPA_CTL_1 0x2149 /* EP A control */
|
||||
#define USB_EPA_CTL_2 0x214A /* EP A control */
|
||||
#define USB_EPA_CTL_3 0x214B /* EP A control */
|
||||
#define USB_EPA_STAT 0x214C /* EP A status */
|
||||
#define USB_EPA_IRQSTAT 0x2150 /* EP A interrupt status */
|
||||
#define USB_EPA_IRQEN 0x2154 /* EP A interrupt enable */
|
||||
#define USB_EPA_MAXPKT 0x2158 /* EP A max packet size */
|
||||
#define USB_EPA_MAXPKT_0 0x2158 /* EP A max packet size */
|
||||
#define USB_EPA_MAXPKT_1 0x2159 /* EP A max packet size */
|
||||
#define USB_EPA_MAXPKT_2 0x215A /* EP A max packet size */
|
||||
#define USB_EPA_MAXPKT_3 0x215B /* EP A max packet size */
|
||||
#define USB_EPA_FIFO_CFG 0x2160 /* EP A FIFO configure */
|
||||
#define USB_EPA_FIFO_CFG_0 0x2160 /* EP A FIFO configure */
|
||||
#define USB_EPA_FIFO_CFG_1 0x2161 /* EP A FIFO configure */
|
||||
#define USB_EPA_FIFO_CFG_2 0x2162 /* EP A FIFO configure */
|
||||
#define USB_EPA_FIFO_CFG_3 0x2163 /* EP A FIFO configure */
|
||||
/* Debug Registers */
|
||||
#define USB_PHYTSTDIS 0x2F04 /* PHY test disable */
|
||||
#define USB_TOUT_VAL 0x2F08 /* USB time-out time */
|
||||
#define USB_VDRCTRL 0x2F10 /* UTMI vendor signal control */
|
||||
#define USB_VSTAIN 0x2F14 /* UTMI vendor signal status in */
|
||||
#define USB_VLOADM 0x2F18 /* UTMI load vendor signal status in */
|
||||
#define USB_VSTAOUT 0x2F1C /* UTMI vendor signal status out */
|
||||
#define USB_UTMI_TST 0x2F80 /* UTMI test */
|
||||
#define USB_UTMI_STATUS 0x2F84 /* UTMI status */
|
||||
#define USB_TSTCTL 0x2F88 /* test control */
|
||||
#define USB_TSTCTL2 0x2F8C /* test control 2 */
|
||||
#define USB_PID_FORCE 0x2F90 /* force PID */
|
||||
#define USB_PKTERR_CNT 0x2F94 /* packet error counter */
|
||||
#define USB_RXERR_CNT 0x2F98 /* RX error counter */
|
||||
#define USB_MEM_BIST 0x2F9C /* MEM BIST test */
|
||||
#define USB_SLBBIST 0x2FA0 /* self-loop-back BIST */
|
||||
#define USB_CNTTEST 0x2FA4 /* counter test */
|
||||
#define USB_PHYTST 0x2FC0 /* USB PHY test */
|
||||
#define USB_DBGIDX 0x2FF0 /* select individual block debug signal */
|
||||
#define USB_DBGMUX 0x2FF4 /* debug signal module mux */
|
||||
|
||||
/*
|
||||
* SYS registers
|
||||
*/
|
||||
/* demod control registers */
|
||||
#define SYS_SYS0 0x3000 /* include DEMOD_CTL, GPO, GPI, GPOE */
|
||||
#define SYS_DEMOD_CTL 0x3000 /* control register for DVB-T demodulator */
|
||||
/* GPIO registers */
|
||||
#define SYS_GPIO_OUT_VAL 0x3001 /* output value of GPIO */
|
||||
#define SYS_GPIO_IN_VAL 0x3002 /* input value of GPIO */
|
||||
#define SYS_GPIO_OUT_EN 0x3003 /* output enable of GPIO */
|
||||
#define SYS_SYS1 0x3004 /* include GPD, SYSINTE, SYSINTS, GP_CFG0 */
|
||||
#define SYS_GPIO_DIR 0x3004 /* direction control for GPIO */
|
||||
#define SYS_SYSINTE 0x3005 /* system interrupt enable */
|
||||
#define SYS_SYSINTS 0x3006 /* system interrupt status */
|
||||
#define SYS_GPIO_CFG0 0x3007 /* PAD configuration for GPIO0-GPIO3 */
|
||||
#define SYS_SYS2 0x3008 /* include GP_CFG1 and 3 reserved bytes */
|
||||
#define SYS_GPIO_CFG1 0x3008 /* PAD configuration for GPIO4 */
|
||||
#define SYS_DEMOD_CTL1 0x300B
|
||||
|
||||
/* IrDA registers */
|
||||
#define SYS_IRRC_PSR 0x3020 /* IR protocol selection */
|
||||
#define SYS_IRRC_PER 0x3024 /* IR protocol extension */
|
||||
#define SYS_IRRC_SF 0x3028 /* IR sampling frequency */
|
||||
#define SYS_IRRC_DPIR 0x302C /* IR data package interval */
|
||||
#define SYS_IRRC_CR 0x3030 /* IR control */
|
||||
#define SYS_IRRC_RP 0x3034 /* IR read port */
|
||||
#define SYS_IRRC_SR 0x3038 /* IR status */
|
||||
/* I2C master registers */
|
||||
#define SYS_I2CCR 0x3040 /* I2C clock */
|
||||
#define SYS_I2CMCR 0x3044 /* I2C master control */
|
||||
#define SYS_I2CMSTR 0x3048 /* I2C master SCL timing */
|
||||
#define SYS_I2CMSR 0x304C /* I2C master status */
|
||||
#define SYS_I2CMFR 0x3050 /* I2C master FIFO */
|
||||
|
||||
/*
|
||||
* IR registers
|
||||
*/
|
||||
#define IR_RX_BUF 0xFC00
|
||||
#define IR_RX_IE 0xFD00
|
||||
#define IR_RX_IF 0xFD01
|
||||
#define IR_RX_CTRL 0xFD02
|
||||
#define IR_RX_CFG 0xFD03
|
||||
#define IR_MAX_DURATION0 0xFD04
|
||||
#define IR_MAX_DURATION1 0xFD05
|
||||
#define IR_IDLE_LEN0 0xFD06
|
||||
#define IR_IDLE_LEN1 0xFD07
|
||||
#define IR_GLITCH_LEN 0xFD08
|
||||
#define IR_RX_BUF_CTRL 0xFD09
|
||||
#define IR_RX_BUF_DATA 0xFD0A
|
||||
#define IR_RX_BC 0xFD0B
|
||||
#define IR_RX_CLK 0xFD0C
|
||||
#define IR_RX_C_COUNT_L 0xFD0D
|
||||
#define IR_RX_C_COUNT_H 0xFD0E
|
||||
#define IR_SUSPEND_CTRL 0xFD10
|
||||
#define IR_ERR_TOL_CTRL 0xFD11
|
||||
#define IR_UNIT_LEN 0xFD12
|
||||
#define IR_ERR_TOL_LEN 0xFD13
|
||||
#define IR_MAX_H_TOL_LEN 0xFD14
|
||||
#define IR_MAX_L_TOL_LEN 0xFD15
|
||||
#define IR_MASK_CTRL 0xFD16
|
||||
#define IR_MASK_DATA 0xFD17
|
||||
#define IR_RES_MASK_ADDR 0xFD18
|
||||
#define IR_RES_MASK_T_LEN 0xFD19
|
||||
|
||||
static volatile int do_exit = 0;
|
||||
|
||||
struct dongle_state
|
||||
{
|
||||
int exit_flag;
|
||||
int rc_active;
|
||||
pthread_t thread;
|
||||
rtlsdr_dev_t *dev;
|
||||
int dev_index;
|
||||
};
|
||||
|
||||
// Register I/O
|
||||
static int rtl28xxu_wr_regs(struct dongle_state *d, uint16_t reg, uint8_t *val, int len)
|
||||
{
|
||||
/* TODO
|
||||
struct rtl28xxu_req req;
|
||||
|
||||
if (reg < 0x3000)
|
||||
req.index = CMD_USB_WR;
|
||||
else if (reg < 0x4000)
|
||||
req.index = CMD_SYS_WR;
|
||||
else
|
||||
req.index = CMD_IR_WR;
|
||||
|
||||
req.value = reg;
|
||||
req.size = len;
|
||||
req.data = val;
|
||||
|
||||
return rtl28xxu_ctrl_msg(d, &req);
|
||||
*/
|
||||
}
|
||||
|
||||
static int rtl28xxu_rd_regs(struct dongle_state *d, uint16_t reg, uint8_t *val, int len)
|
||||
{
|
||||
/* TODO
|
||||
struct rtl28xxu_req req;
|
||||
|
||||
if (reg < 0x3000)
|
||||
req.index = CMD_USB_RD;
|
||||
else if (reg < 0x4000)
|
||||
req.index = CMD_SYS_RD;
|
||||
else
|
||||
req.index = CMD_IR_RD;
|
||||
|
||||
req.value = reg;
|
||||
req.size = len;
|
||||
req.data = val;
|
||||
|
||||
return rtl28xxu_ctrl_msg(d, &req);
|
||||
*/
|
||||
}
|
||||
|
||||
static int rtl28xxu_wr_reg(struct dongle_state *d, uint16_t reg, uint8_t val)
|
||||
{
|
||||
return rtl28xxu_wr_regs(d, reg, &val, 1);
|
||||
}
|
||||
|
||||
static int rtl28xxu_rd_reg(struct dongle_state *d, uint16_t reg, uint8_t *val)
|
||||
{
|
||||
return rtl28xxu_rd_regs(d, reg, val, 1);
|
||||
}
|
||||
|
||||
static int rtl28xxu_wr_reg_mask(struct dongle_state *d, uint16_t reg, uint8_t val,
|
||||
uint8_t mask)
|
||||
{
|
||||
int ret;
|
||||
uint8_t tmp;
|
||||
|
||||
/* no need for read if whole reg is written */
|
||||
if (mask != 0xff) {
|
||||
ret = rtl28xxu_rd_reg(d, reg, &tmp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
val &= mask;
|
||||
tmp &= ~mask;
|
||||
val |= tmp;
|
||||
}
|
||||
|
||||
return rtl28xxu_wr_reg(d, reg, val);
|
||||
}
|
||||
|
||||
struct rtlsdr_dev2 {
|
||||
libusb_context *ctx;
|
||||
struct libusb_device_handle *devh;
|
||||
};
|
||||
|
||||
void dongle_init(struct dongle_state *s)
|
||||
{
|
||||
s->dev_index = 0;
|
||||
bzero(s, sizeof(struct dongle_state));
|
||||
}
|
||||
|
||||
struct dongle_state dongle;
|
||||
|
@ -103,6 +350,98 @@ static void *dongle_thread_fn(void *arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int rtl2832u_rc_query(struct dongle_state *d)
|
||||
{
|
||||
int ret, i, len;
|
||||
rtlsdr_dev_t *dev = d->dev;
|
||||
uint8_t buf[128];
|
||||
static const struct rtl28xxu_reg_val_mask refresh_tab[] = {
|
||||
{IR_RX_IF, 0x03, 0xff},
|
||||
{IR_RX_BUF_CTRL, 0x80, 0xff},
|
||||
{IR_RX_CTRL, 0x80, 0xff},
|
||||
};
|
||||
|
||||
/* init remote controller */
|
||||
if (!d->rc_active) {
|
||||
static const struct rtl28xxu_reg_val_mask init_tab[] = {
|
||||
{SYS_DEMOD_CTL1, 0x00, 0x04},
|
||||
{SYS_DEMOD_CTL1, 0x00, 0x08},
|
||||
{USB_CTRL, 0x20, 0x20},
|
||||
{SYS_GPIO_DIR, 0x00, 0x08},
|
||||
{SYS_GPIO_OUT_EN, 0x08, 0x08},
|
||||
{SYS_GPIO_OUT_VAL, 0x08, 0x08},
|
||||
{IR_MAX_DURATION0, 0xd0, 0xff},
|
||||
{IR_MAX_DURATION1, 0x07, 0xff},
|
||||
{IR_IDLE_LEN0, 0xc0, 0xff},
|
||||
{IR_IDLE_LEN1, 0x00, 0xff},
|
||||
{IR_GLITCH_LEN, 0x03, 0xff},
|
||||
{IR_RX_CLK, 0x09, 0xff},
|
||||
{IR_RX_CFG, 0x1c, 0xff},
|
||||
{IR_MAX_H_TOL_LEN, 0x1e, 0xff},
|
||||
{IR_MAX_L_TOL_LEN, 0x1e, 0xff},
|
||||
{IR_RX_CTRL, 0x80, 0xff},
|
||||
};
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(init_tab); i++) {
|
||||
ret = rtl28xxu_wr_reg_mask(d, init_tab[i].reg,
|
||||
init_tab[i].val, init_tab[i].mask);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
||||
d->rc_active = 1;
|
||||
}
|
||||
|
||||
ret = rtl28xxu_rd_reg(d, IR_RX_IF, &buf[0]);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
if (buf[0] != 0x83)
|
||||
goto exit;
|
||||
|
||||
ret = rtl28xxu_rd_reg(d, IR_RX_BC, &buf[0]);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
len = buf[0];
|
||||
|
||||
/* read raw code from hw */
|
||||
ret = rtl28xxu_rd_regs(d, IR_RX_BUF, buf, len);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
/* let hw receive new code */
|
||||
for (i = 0; i < ARRAY_SIZE(refresh_tab); i++) {
|
||||
ret = rtl28xxu_wr_reg_mask(d, refresh_tab[i].reg,
|
||||
refresh_tab[i].val, refresh_tab[i].mask);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* pass data to Kernel IR decoder */
|
||||
//TODO init_ir_raw_event(&ev);
|
||||
|
||||
printf("IR: \n");
|
||||
for (i = 0; i < len; i++) {
|
||||
//ev.pulse = buf[i] >> 7;
|
||||
//ev.duration = 50800 * (buf[i] & 0x7f);
|
||||
|
||||
printf("pulse %d, duration %d\n", buf[i] >> 7, 50800 * (buf[i] & 0x7f));
|
||||
//TODO
|
||||
//ir_raw_event_store_with_filter(d->rc_dev, &ev);
|
||||
}
|
||||
|
||||
/* 'flush' ir_raw_event_store_with_filter() */
|
||||
/*TODO
|
||||
ir_raw_event_set_idle(d->rc_dev, true);
|
||||
ir_raw_event_handle(d->rc_dev);
|
||||
*/
|
||||
exit:
|
||||
return ret;
|
||||
err:
|
||||
//dev_dbg(&d->intf->dev, "failed=%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
#ifndef _WIN32
|
||||
|
|
Loading…
Reference in New Issue