2019-05-31 01:09:32 -07:00
// SPDX-License-Identifier: GPL-2.0-only
2005-06-23 22:02:35 -07:00
/* DVB USB compliant Linux driver for the
* - TwinhanDTV Alpha / MagicBoxII USB2 .0 DVB - T receiver
* - DigitalNow TinyUSB2 DVB - t receiver
*
2016-01-24 12:56:58 -02:00
* Copyright ( C ) 2004 - 5 Patrick Boettcher ( patrick . boettcher @ posteo . de )
2005-06-23 22:02:35 -07:00
*
* Thanks to Twinhan who kindly provided hardware and information .
*
2020-03-04 15:54:10 +01:00
* see Documentation / driver - api / media / drivers / dvb - usb . rst for more information
2005-06-23 22:02:35 -07:00
*/
# include "vp7045.h"
/* debug */
2007-11-05 14:07:06 -03:00
static int dvb_usb_vp7045_debug ;
2005-06-23 22:02:35 -07:00
module_param_named ( debug , dvb_usb_vp7045_debug , int , 0644 ) ;
MODULE_PARM_DESC ( debug , " set debugging level (1=info,xfer=2,rc=4 (or-able)). " DVB_USB_DEBUG_STATUS ) ;
2008-04-09 19:13:13 -03:00
DVB_DEFINE_MOD_OPT_ADAPTER_NR ( adapter_nr ) ;
2007-11-05 14:07:06 -03:00
# define deb_info(args...) dprintk(dvb_usb_vp7045_debug,0x01,args)
# define deb_xfer(args...) dprintk(dvb_usb_vp7045_debug,0x02,args)
# define deb_rc(args...) dprintk(dvb_usb_vp7045_debug,0x04,args)
2005-06-23 22:02:35 -07:00
int vp7045_usb_op ( struct dvb_usb_device * d , u8 cmd , u8 * out , int outlen , u8 * in , int inlen , int msec )
{
int ret = 0 ;
2011-03-21 15:33:42 -03:00
u8 * buf = d - > priv ;
2005-06-23 22:02:35 -07:00
2011-03-21 15:33:42 -03:00
buf [ 0 ] = cmd ;
2005-06-23 22:02:35 -07:00
if ( outlen > 19 )
outlen = 19 ;
if ( inlen > 11 )
inlen = 11 ;
2011-03-21 15:33:42 -03:00
ret = mutex_lock_interruptible ( & d - > usb_mutex ) ;
if ( ret )
return ret ;
2005-06-23 22:02:35 -07:00
if ( out ! = NULL & & outlen > 0 )
2011-03-21 15:33:42 -03:00
memcpy ( & buf [ 1 ] , out , outlen ) ;
2005-06-23 22:02:35 -07:00
deb_xfer ( " out buffer: " ) ;
2011-03-21 15:33:42 -03:00
debug_dump ( buf , outlen + 1 , deb_xfer ) ;
2005-06-23 22:02:35 -07:00
if ( usb_control_msg ( d - > udev ,
usb_sndctrlpipe ( d - > udev , 0 ) ,
TH_COMMAND_OUT , USB_TYPE_VENDOR | USB_DIR_OUT , 0 , 0 ,
2011-03-21 15:33:42 -03:00
buf , 20 , 2000 ) ! = 20 ) {
2005-06-23 22:02:35 -07:00
err ( " USB control message 'out' went wrong. " ) ;
ret = - EIO ;
goto unlock ;
}
msleep ( msec ) ;
if ( usb_control_msg ( d - > udev ,
usb_rcvctrlpipe ( d - > udev , 0 ) ,
TH_COMMAND_IN , USB_TYPE_VENDOR | USB_DIR_IN , 0 , 0 ,
2011-03-21 15:33:42 -03:00
buf , 12 , 2000 ) ! = 12 ) {
2005-06-23 22:02:35 -07:00
err ( " USB control message 'in' went wrong. " ) ;
ret = - EIO ;
goto unlock ;
}
deb_xfer ( " in buffer: " ) ;
2011-03-21 15:33:42 -03:00
debug_dump ( buf , 12 , deb_xfer ) ;
2005-06-23 22:02:35 -07:00
if ( in ! = NULL & & inlen > 0 )
2011-03-21 15:33:42 -03:00
memcpy ( in , & buf [ 1 ] , inlen ) ;
2005-06-23 22:02:35 -07:00
unlock :
2006-02-07 06:49:14 -02:00
mutex_unlock ( & d - > usb_mutex ) ;
2005-06-23 22:02:35 -07:00
return ret ;
}
u8 vp7045_read_reg ( struct dvb_usb_device * d , u8 reg )
{
u8 obuf [ 2 ] = { 0 } , v ;
obuf [ 1 ] = reg ;
vp7045_usb_op ( d , TUNER_REG_READ , obuf , 2 , & v , 1 , 30 ) ;
return v ;
}
static int vp7045_power_ctrl ( struct dvb_usb_device * d , int onoff )
{
u8 v = onoff ;
return vp7045_usb_op ( d , SET_TUNER_POWER , & v , 1 , NULL , 0 , 150 ) ;
}
2017-09-06 08:19:06 -03:00
static int vp7045_rc_query ( struct dvb_usb_device * d )
2005-06-23 22:02:35 -07:00
{
2019-11-10 11:25:13 +01:00
int ret ;
2005-06-23 22:02:35 -07:00
u8 key ;
2019-11-10 11:25:13 +01:00
ret = vp7045_usb_op ( d , RC_VAL_READ , NULL , 0 , & key , 1 , 20 ) ;
if ( ret )
return ret ;
deb_rc ( " remote query key: %x \n " , key ) ;
2005-06-23 22:02:35 -07:00
2017-09-06 08:19:06 -03:00
if ( key ! = 0x44 ) {
/*
* The 8 bit address isn ' t available , but since the remote uses
* address 0 we ' ll use that . nec repeats are ignored too , even
* though the remote sends them .
*/
rc_keydown ( d - > rc_dev , RC_PROTO_NEC , RC_SCANCODE_NEC ( 0 , key ) , 0 ) ;
2005-06-23 22:02:35 -07:00
}
return 0 ;
}
static int vp7045_read_eeprom ( struct dvb_usb_device * d , u8 * buf , int len , int offset )
{
2019-11-10 11:25:13 +01:00
int i , ret ;
u8 v , br [ 2 ] ;
2005-06-23 22:02:35 -07:00
for ( i = 0 ; i < len ; i + + ) {
v = offset + i ;
2019-11-10 11:25:13 +01:00
ret = vp7045_usb_op ( d , GET_EE_VALUE , & v , 1 , br , 2 , 5 ) ;
if ( ret )
return ret ;
2005-06-23 22:02:35 -07:00
buf [ i ] = br [ 1 ] ;
}
2019-11-10 11:25:13 +01:00
deb_info ( " VP7045 EEPROM read (offs: %d, len: %d) : " , offset , i ) ;
debug_dump ( buf , i , deb_info ) ;
2005-06-23 22:02:35 -07:00
return 0 ;
}
static int vp7045_read_mac_addr ( struct dvb_usb_device * d , u8 mac [ 6 ] )
{
return vp7045_read_eeprom ( d , mac , 6 , MAC_0_ADDR ) ;
}
2006-09-30 06:53:48 -03:00
static int vp7045_frontend_attach ( struct dvb_usb_adapter * adap )
2005-06-23 22:02:35 -07:00
{
u8 buf [ 255 ] = { 0 } ;
2006-09-30 06:53:48 -03:00
vp7045_usb_op ( adap - > dev , VENDOR_STRING_READ , NULL , 0 , buf , 20 , 0 ) ;
2005-06-23 22:02:35 -07:00
buf [ 10 ] = ' \0 ' ;
deb_info ( " firmware says: %s " , buf ) ;
2006-09-30 06:53:48 -03:00
vp7045_usb_op ( adap - > dev , PRODUCT_STRING_READ , NULL , 0 , buf , 20 , 0 ) ;
2005-06-23 22:02:35 -07:00
buf [ 10 ] = ' \0 ' ;
deb_info ( " %s " , buf ) ;
2006-09-30 06:53:48 -03:00
vp7045_usb_op ( adap - > dev , FW_VERSION_READ , NULL , 0 , buf , 20 , 0 ) ;
2005-06-23 22:02:35 -07:00
buf [ 10 ] = ' \0 ' ;
deb_info ( " v%s \n " , buf ) ;
/* Dump the EEPROM */
/* vp7045_read_eeprom(d,buf, 255, FX2_ID_ADDR); */
2011-09-06 09:31:57 -03:00
adap - > fe_adap [ 0 ] . fe = vp7045_fe_attach ( adap - > dev ) ;
2005-06-23 22:02:35 -07:00
return 0 ;
}
2006-09-30 06:53:48 -03:00
static struct dvb_usb_device_properties vp7045_properties ;
2005-06-23 22:02:35 -07:00
static int vp7045_usb_probe ( struct usb_interface * intf ,
const struct usb_device_id * id )
{
2011-08-10 07:05:20 -03:00
return dvb_usb_device_init ( intf , & vp7045_properties ,
THIS_MODULE , NULL , adapter_nr ) ;
2005-06-23 22:02:35 -07:00
}
static struct usb_device_id vp7045_usb_table [ ] = {
{ USB_DEVICE ( USB_VID_VISIONPLUS , USB_PID_TWINHAN_VP7045_COLD ) } ,
{ USB_DEVICE ( USB_VID_VISIONPLUS , USB_PID_TWINHAN_VP7045_WARM ) } ,
{ USB_DEVICE ( USB_VID_VISIONPLUS , USB_PID_DNTV_TINYUSB2_COLD ) } ,
{ USB_DEVICE ( USB_VID_VISIONPLUS , USB_PID_DNTV_TINYUSB2_WARM ) } ,
{ 0 } ,
} ;
MODULE_DEVICE_TABLE ( usb , vp7045_usb_table ) ;
2006-09-30 06:53:48 -03:00
static struct dvb_usb_device_properties vp7045_properties = {
2005-06-23 22:02:35 -07:00
. usb_ctrl = CYPRESS_FX2 ,
. firmware = " dvb-usb-vp7045-01.fw " ,
2011-08-10 07:05:20 -03:00
. size_of_priv = 20 ,
2005-06-23 22:02:35 -07:00
2006-09-30 06:53:48 -03:00
. num_adapters = 1 ,
. adapter = {
{
2011-09-06 09:31:57 -03:00
. num_frontends = 1 ,
. fe = { {
2006-10-13 11:34:46 -03:00
. frontend_attach = vp7045_frontend_attach ,
/* parameter for the MPEG2-data transfer */
2006-09-30 06:53:48 -03:00
. stream = {
. type = USB_BULK ,
2006-10-13 11:34:46 -03:00
. count = 7 ,
. endpoint = 0x02 ,
. u = {
. bulk = {
. buffersize = 4096 ,
}
}
} ,
2011-09-06 09:31:57 -03:00
} } ,
2006-09-30 06:53:48 -03:00
}
} ,
. power_ctrl = vp7045_power_ctrl ,
. read_mac_address = vp7045_read_mac_addr ,
2017-09-06 08:19:06 -03:00
. rc . core = {
. rc_interval = 400 ,
. rc_codes = RC_MAP_TWINHAN_VP1027_DVBS ,
. module_name = KBUILD_MODNAME ,
. rc_query = vp7045_rc_query ,
. allowed_protos = RC_PROTO_BIT_NEC ,
. scancode_mask = 0xff ,
2010-07-31 18:04:09 -03:00
} ,
2005-06-23 22:02:35 -07:00
. num_device_descs = 2 ,
. devices = {
{ . name = " Twinhan USB2.0 DVB-T receiver (TwinhanDTV Alpha/MagicBox II) " ,
. cold_ids = { & vp7045_usb_table [ 0 ] , NULL } ,
. warm_ids = { & vp7045_usb_table [ 1 ] , NULL } ,
} ,
{ . name = " DigitalNow TinyUSB 2 DVB-t Receiver " ,
. cold_ids = { & vp7045_usb_table [ 2 ] , NULL } ,
. warm_ids = { & vp7045_usb_table [ 3 ] , NULL } ,
} ,
2006-02-01 06:02:50 -05:00
{ NULL } ,
2005-06-23 22:02:35 -07:00
}
} ;
/* usb specific object needed to register this driver with the usb subsystem */
static struct usb_driver vp7045_usb_driver = {
2005-07-07 17:58:30 -07:00
. name = " dvb_usb_vp7045 " ,
2005-09-09 13:02:50 -07:00
. probe = vp7045_usb_probe ,
2011-08-10 07:05:20 -03:00
. disconnect = dvb_usb_device_exit ,
2005-09-09 13:02:50 -07:00
. id_table = vp7045_usb_table ,
2005-06-23 22:02:35 -07:00
} ;
2011-11-18 09:46:12 -08:00
module_usb_driver ( vp7045_usb_driver ) ;
2005-06-23 22:02:35 -07:00
2016-01-24 12:56:58 -02:00
MODULE_AUTHOR ( " Patrick Boettcher <patrick.boettcher@posteo.de> " ) ;
2005-06-23 22:02:35 -07:00
MODULE_DESCRIPTION ( " Driver for Twinhan MagicBox/Alpha and DNTV tinyUSB2 DVB-T USB2.0 " ) ;
MODULE_VERSION ( " 1.0 " ) ;
MODULE_LICENSE ( " GPL " ) ;