@@ -124,6 +124,7 @@ struct rtlsdr_dev {
124
124
int dev_lost ;
125
125
int driver_active ;
126
126
unsigned int xfer_errors ;
127
+ int rc_active ;
127
128
};
128
129
129
130
void rtlsdr_set_gpio_bit (rtlsdr_dev_t * dev , uint8_t gpio , int val );
@@ -407,6 +408,51 @@ enum sys_reg {
407
408
SYSINTS_1 = 0x300a ,
408
409
DEMOD_CTL_1 = 0x300b ,
409
410
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 ,
410
456
};
411
457
412
458
enum blocks {
@@ -423,6 +469,7 @@ int rtlsdr_read_array(rtlsdr_dev_t *dev, uint8_t block, uint16_t addr, uint8_t *
423
469
{
424
470
int r ;
425
471
uint16_t index = (block << 8 );
472
+ if (block == IRB ) index = (SYSB << 8 ) | 0x01 ;
426
473
427
474
r = libusb_control_transfer (dev -> devh , CTRL_IN , 0 , addr , index , array , len , CTRL_TIMEOUT );
428
475
#if 0
@@ -436,6 +483,7 @@ int rtlsdr_write_array(rtlsdr_dev_t *dev, uint8_t block, uint16_t addr, uint8_t
436
483
{
437
484
int r ;
438
485
uint16_t index = (block << 8 ) | 0x10 ;
486
+ if (block == IRB ) index = (SYSB << 8 ) | 0x11 ;
439
487
440
488
r = libusb_control_transfer (dev -> devh , CTRL_OUT , 0 , addr , index , array , len , CTRL_TIMEOUT );
441
489
#if 0
@@ -490,8 +538,9 @@ uint16_t rtlsdr_read_reg(rtlsdr_dev_t *dev, uint8_t block, uint16_t addr, uint8_
490
538
{
491
539
int r ;
492
540
unsigned char data [2 ];
493
- uint16_t index = (block << 8 );
494
541
uint16_t reg ;
542
+ uint16_t index = (block << 8 );
543
+ if (block == IRB ) index = (SYSB << 8 ) | 0x01 ;
495
544
496
545
r = libusb_control_transfer (dev -> devh , CTRL_IN , 0 , addr , index , data , len , CTRL_TIMEOUT );
497
546
@@ -509,6 +558,7 @@ int rtlsdr_write_reg(rtlsdr_dev_t *dev, uint8_t block, uint16_t addr, uint16_t v
509
558
unsigned char data [2 ];
510
559
511
560
uint16_t index = (block << 8 ) | 0x10 ;
561
+ if (block == IRB ) index = (SYSB << 8 ) | 0x11 ;
512
562
513
563
if (len == 1 )
514
564
data [0 ] = val & 0xff ;
@@ -1992,3 +2042,160 @@ int rtlsdr_i2c_read_fn(void *dev, uint8_t addr, uint8_t *buf, int len)
1992
2042
1993
2043
return -1 ;
1994
2044
}
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