@@ -124,6 +124,7 @@ struct rtlsdr_dev {
124124 int dev_lost ;
125125 int driver_active ;
126126 unsigned int xfer_errors ;
127+ int rc_active ;
127128};
128129
129130void rtlsdr_set_gpio_bit (rtlsdr_dev_t * dev , uint8_t gpio , int val );
@@ -407,6 +408,51 @@ enum sys_reg {
407408 SYSINTS_1 = 0x300a ,
408409 DEMOD_CTL_1 = 0x300b ,
409410 IR_SUSPEND = 0x300c ,
411+
412+ /* IrDA registers */
413+ SYS_IRRC_PSR = 0x3020 , /* IR protocol selection */
414+ SYS_IRRC_PER = 0x3024 , /* IR protocol extension */
415+ SYS_IRRC_SF = 0x3028 , /* IR sampling frequency */
416+ SYS_IRRC_DPIR = 0x302C , /* IR data package interval */
417+ SYS_IRRC_CR = 0x3030 , /* IR control */
418+ SYS_IRRC_RP = 0x3034 , /* IR read port */
419+ SYS_IRRC_SR = 0x3038 , /* IR status */
420+ /* I2C master registers */
421+ SYS_I2CCR = 0x3040 , /* I2C clock */
422+ SYS_I2CMCR = 0x3044 , /* I2C master control */
423+ SYS_I2CMSTR = 0x3048 , /* I2C master SCL timing */
424+ SYS_I2CMSR = 0x304C , /* I2C master status */
425+ SYS_I2CMFR = 0x3050 , /* I2C master FIFO */
426+
427+ /*
428+ * IR registers
429+ */
430+ IR_RX_BUF = 0xFC00 ,
431+ IR_RX_IE = 0xFD00 ,
432+ IR_RX_IF = 0xFD01 ,
433+ IR_RX_CTRL = 0xFD02 ,
434+ IR_RX_CFG = 0xFD03 ,
435+ IR_MAX_DURATION0 = 0xFD04 ,
436+ IR_MAX_DURATION1 = 0xFD05 ,
437+ IR_IDLE_LEN0 = 0xFD06 ,
438+ IR_IDLE_LEN1 = 0xFD07 ,
439+ IR_GLITCH_LEN = 0xFD08 ,
440+ IR_RX_BUF_CTRL = 0xFD09 ,
441+ IR_RX_BUF_DATA = 0xFD0A ,
442+ IR_RX_BC = 0xFD0B ,
443+ IR_RX_CLK = 0xFD0C ,
444+ IR_RX_C_COUNT_L = 0xFD0D ,
445+ IR_RX_C_COUNT_H = 0xFD0E ,
446+ IR_SUSPEND_CTRL = 0xFD10 ,
447+ IR_ERR_TOL_CTRL = 0xFD11 ,
448+ IR_UNIT_LEN = 0xFD12 ,
449+ IR_ERR_TOL_LEN = 0xFD13 ,
450+ IR_MAX_H_TOL_LEN = 0xFD14 ,
451+ IR_MAX_L_TOL_LEN = 0xFD15 ,
452+ IR_MASK_CTRL = 0xFD16 ,
453+ IR_MASK_DATA = 0xFD17 ,
454+ IR_RES_MASK_ADDR = 0xFD18 ,
455+ IR_RES_MASK_T_LEN = 0xFD19 ,
410456};
411457
412458enum blocks {
@@ -423,6 +469,7 @@ int rtlsdr_read_array(rtlsdr_dev_t *dev, uint8_t block, uint16_t addr, uint8_t *
423469{
424470 int r ;
425471 uint16_t index = (block << 8 );
472+ if (block == IRB ) index = (SYSB << 8 ) | 0x01 ;
426473
427474 r = libusb_control_transfer (dev -> devh , CTRL_IN , 0 , addr , index , array , len , CTRL_TIMEOUT );
428475#if 0
@@ -436,6 +483,7 @@ int rtlsdr_write_array(rtlsdr_dev_t *dev, uint8_t block, uint16_t addr, uint8_t
436483{
437484 int r ;
438485 uint16_t index = (block << 8 ) | 0x10 ;
486+ if (block == IRB ) index = (SYSB << 8 ) | 0x11 ;
439487
440488 r = libusb_control_transfer (dev -> devh , CTRL_OUT , 0 , addr , index , array , len , CTRL_TIMEOUT );
441489#if 0
@@ -490,8 +538,9 @@ uint16_t rtlsdr_read_reg(rtlsdr_dev_t *dev, uint8_t block, uint16_t addr, uint8_
490538{
491539 int r ;
492540 unsigned char data [2 ];
493- uint16_t index = (block << 8 );
494541 uint16_t reg ;
542+ uint16_t index = (block << 8 );
543+ if (block == IRB ) index = (SYSB << 8 ) | 0x01 ;
495544
496545 r = libusb_control_transfer (dev -> devh , CTRL_IN , 0 , addr , index , data , len , CTRL_TIMEOUT );
497546
@@ -509,6 +558,7 @@ int rtlsdr_write_reg(rtlsdr_dev_t *dev, uint8_t block, uint16_t addr, uint16_t v
509558 unsigned char data [2 ];
510559
511560 uint16_t index = (block << 8 ) | 0x10 ;
561+ if (block == IRB ) index = (SYSB << 8 ) | 0x11 ;
512562
513563 if (len == 1 )
514564 data [0 ] = val & 0xff ;
@@ -1992,3 +2042,160 @@ int rtlsdr_i2c_read_fn(void *dev, uint8_t addr, uint8_t *buf, int len)
19922042
19932043 return -1 ;
19942044}
2045+
2046+
2047+ /* Infrared (IR) sensor support
2048+ * based on Linux dvb_usb_rtl28xxu drivers/media/usb/dvb-usb-v2/rtl28xxu.h
2049+ * Copyright (C) 2009 Antti Palosaari <[email protected] > 2050+ * Copyright (C) 2011 Antti Palosaari <[email protected] > 2051+ * Copyright (C) 2012 Thomas Mair <[email protected] > 2052+ */
2053+
2054+ struct rtl28xxu_req {
2055+ uint16_t value ;
2056+ uint16_t index ;
2057+ uint16_t size ;
2058+ uint8_t * data ;
2059+ };
2060+
2061+ struct rtl28xxu_reg_val {
2062+ uint16_t reg ;
2063+ uint8_t val ;
2064+ };
2065+
2066+ struct rtl28xxu_reg_val_mask {
2067+ int block ;
2068+ uint16_t reg ;
2069+ uint8_t val ;
2070+ uint8_t mask ;
2071+ };
2072+
2073+ static int rtlsdr_read_regs (rtlsdr_dev_t * dev , uint8_t block , uint16_t addr , uint8_t * data , uint8_t len )
2074+ {
2075+ int r ;
2076+ uint16_t index = (block << 8 );
2077+ if (block == IRB ) index = (SYSB << 8 ) | 0x01 ;
2078+
2079+ r = libusb_control_transfer (dev -> devh , CTRL_IN , 0 , addr , index , data , len , CTRL_TIMEOUT );
2080+
2081+ if (r < 0 )
2082+ fprintf (stderr , "%s failed with %d\n" , __FUNCTION__ , r );
2083+
2084+ return r ;
2085+ }
2086+
2087+ static int rtlsdr_write_reg_mask (rtlsdr_dev_t * d , int block , uint16_t reg , uint8_t val ,
2088+ uint8_t mask )
2089+ {
2090+ int ret ;
2091+ uint8_t tmp ;
2092+
2093+ /* no need for read if whole reg is written */
2094+ if (mask != 0xff ) {
2095+ tmp = rtlsdr_read_reg (d , block , reg , 1 );
2096+
2097+ val &= mask ;
2098+ tmp &= ~mask ;
2099+ val |= tmp ;
2100+ }
2101+
2102+ return rtlsdr_write_reg (d , block , reg , (uint16_t )val , 1 );
2103+ }
2104+
2105+ #define ARRAY_SIZE (x ) (sizeof(x) / sizeof((x)[0]))
2106+
2107+ int rtlsdr_ir_query (rtlsdr_dev_t * d , uint8_t * buf , size_t buf_len )
2108+ {
2109+ int ret = -1 ;
2110+ size_t i , len ;
2111+ static const struct rtl28xxu_reg_val_mask refresh_tab [] = {
2112+ {IRB , IR_RX_IF , 0x03 , 0xff },
2113+ {IRB , IR_RX_BUF_CTRL , 0x80 , 0xff },
2114+ {IRB , IR_RX_CTRL , 0x80 , 0xff },
2115+ };
2116+
2117+ /* init remote controller */
2118+ if (!d -> rc_active ) {
2119+ //fprintf(stderr, "initializing remote controller\n");
2120+ static const struct rtl28xxu_reg_val_mask init_tab [] = {
2121+ {USBB , DEMOD_CTL , 0x00 , 0x04 },
2122+ {USBB , DEMOD_CTL , 0x00 , 0x08 },
2123+ {USBB , USB_CTRL , 0x20 , 0x20 },
2124+ {USBB , GPD , 0x00 , 0x08 },
2125+ {USBB , GPOE , 0x08 , 0x08 },
2126+ {USBB , GPO , 0x08 , 0x08 },
2127+ {IRB , IR_MAX_DURATION0 , 0xd0 , 0xff },
2128+ {IRB , IR_MAX_DURATION1 , 0x07 , 0xff },
2129+ {IRB , IR_IDLE_LEN0 , 0xc0 , 0xff },
2130+ {IRB , IR_IDLE_LEN1 , 0x00 , 0xff },
2131+ {IRB , IR_GLITCH_LEN , 0x03 , 0xff },
2132+ {IRB , IR_RX_CLK , 0x09 , 0xff },
2133+ {IRB , IR_RX_CFG , 0x1c , 0xff },
2134+ {IRB , IR_MAX_H_TOL_LEN , 0x1e , 0xff },
2135+ {IRB , IR_MAX_L_TOL_LEN , 0x1e , 0xff },
2136+ {IRB , IR_RX_CTRL , 0x80 , 0xff },
2137+ };
2138+
2139+ for (i = 0 ; i < ARRAY_SIZE (init_tab ); i ++ ) {
2140+ ret = rtlsdr_write_reg_mask (d , init_tab [i ].block , init_tab [i ].reg ,
2141+ init_tab [i ].val , init_tab [i ].mask );
2142+ if (ret < 0 ) {
2143+ fprintf (stderr , "write %d reg %d %.4x %.2x %.2x failed\n" , i , init_tab [i ].block ,
2144+ init_tab [i ].reg , init_tab [i ].val , init_tab [i ].mask );
2145+ goto err ;
2146+ }
2147+ }
2148+
2149+ d -> rc_active = 1 ;
2150+ //fprintf(stderr, "rc active\n");
2151+ }
2152+ // TODO: option to ir disable
2153+
2154+ buf [0 ] = rtlsdr_read_reg (d , IRB , IR_RX_IF , 1 );
2155+
2156+ if (buf [0 ] != 0x83 ) {
2157+ if (buf [0 ] == 0 || // no IR signal
2158+ // also observed: 0x82, 0x81 - with lengths 1, 5, 0.. unknown, sometimes occurs at edges
2159+ // "IR not ready"? causes a -7 timeout if we read
2160+ buf [0 ] == 0x82 || buf [0 ] == 0x81 ) {
2161+ // graceful exit
2162+ } else {
2163+ fprintf (stderr , "read IR_RX_IF unexpected: %.2x\n" , buf [0 ]);
2164+ }
2165+
2166+ ret = 0 ;
2167+ goto exit ;
2168+ }
2169+
2170+ buf [0 ] = rtlsdr_read_reg (d , IRB , IR_RX_BC , 1 );
2171+
2172+ len = buf [0 ];
2173+ //fprintf(stderr, "read IR_RX_BC len=%d\n", len);
2174+
2175+ if (len > buf_len ) {
2176+ //fprintf(stderr, "read IR_RX_BC too large for buffer, %lu > %lu\n", buf_len, buf_len);
2177+ goto exit ;
2178+ }
2179+
2180+ /* read raw code from hw */
2181+ ret = rtlsdr_read_regs (d , IRB , IR_RX_BUF , buf , len );
2182+ if (ret < 0 )
2183+ goto err ;
2184+
2185+ /* let hw receive new code */
2186+ for (i = 0 ; i < ARRAY_SIZE (refresh_tab ); i ++ ) {
2187+ ret = rtlsdr_write_reg_mask (d , refresh_tab [i ].block , refresh_tab [i ].reg ,
2188+ refresh_tab [i ].val , refresh_tab [i ].mask );
2189+ if (ret < 0 )
2190+ goto err ;
2191+ }
2192+
2193+ // On success return length
2194+ ret = len ;
2195+
2196+ exit :
2197+ return ret ;
2198+ err :
2199+ printf ("failed=%d\n" , ret );
2200+ return ret ;
2201+ }
0 commit comments