brintos

brintos / linux-shallow public Read only

0
0
Text · 6.0 KiB · 1dc2b18 Raw
257 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* DVB USB compliant Linux driver for the3 *  - TwinhanDTV Alpha/MagicBoxII USB2.0 DVB-T receiver4 *  - DigitalNow TinyUSB2 DVB-t receiver5 *6 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de)7 *8 * Thanks to Twinhan who kindly provided hardware and information.9 *10 * see Documentation/driver-api/media/drivers/dvb-usb.rst for more information11 */12#include "vp7045.h"13 14/* debug */15static int dvb_usb_vp7045_debug;16module_param_named(debug,dvb_usb_vp7045_debug, int, 0644);17MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);18 19DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);20 21#define deb_info(args...) dprintk(dvb_usb_vp7045_debug,0x01,args)22#define deb_xfer(args...) dprintk(dvb_usb_vp7045_debug,0x02,args)23#define deb_rc(args...)   dprintk(dvb_usb_vp7045_debug,0x04,args)24 25int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in, int inlen, int msec)26{27	int ret = 0;28	u8 *buf = d->priv;29 30	buf[0] = cmd;31 32	if (outlen > 19)33		outlen = 19;34 35	if (inlen > 11)36		inlen = 11;37 38	ret = mutex_lock_interruptible(&d->usb_mutex);39	if (ret)40		return ret;41 42	if (out != NULL && outlen > 0)43		memcpy(&buf[1], out, outlen);44 45	deb_xfer("out buffer: ");46	debug_dump(buf, outlen+1, deb_xfer);47 48 49	if (usb_control_msg(d->udev,50			usb_sndctrlpipe(d->udev,0),51			TH_COMMAND_OUT, USB_TYPE_VENDOR | USB_DIR_OUT, 0, 0,52			buf, 20, 2000) != 20) {53		err("USB control message 'out' went wrong.");54		ret = -EIO;55		goto unlock;56	}57 58	msleep(msec);59 60	if (usb_control_msg(d->udev,61			usb_rcvctrlpipe(d->udev,0),62			TH_COMMAND_IN, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,63			buf, 12, 2000) != 12) {64		err("USB control message 'in' went wrong.");65		ret = -EIO;66		goto unlock;67	}68 69	deb_xfer("in buffer: ");70	debug_dump(buf, 12, deb_xfer);71 72	if (in != NULL && inlen > 0)73		memcpy(in, &buf[1], inlen);74 75unlock:76	mutex_unlock(&d->usb_mutex);77 78	return ret;79}80 81u8 vp7045_read_reg(struct dvb_usb_device *d, u8 reg)82{83	u8 obuf[2] = { 0 },v;84	obuf[1] = reg;85 86	vp7045_usb_op(d,TUNER_REG_READ,obuf,2,&v,1,30);87 88	return v;89}90 91static int vp7045_power_ctrl(struct dvb_usb_device *d, int onoff)92{93	u8 v = onoff;94	return vp7045_usb_op(d,SET_TUNER_POWER,&v,1,NULL,0,150);95}96 97static int vp7045_rc_query(struct dvb_usb_device *d)98{99	int ret;100	u8 key;101 102	ret = vp7045_usb_op(d, RC_VAL_READ, NULL, 0, &key, 1, 20);103	if (ret)104		return ret;105 106	deb_rc("remote query key: %x\n", key);107 108	if (key != 0x44) {109		/*110		 * The 8 bit address isn't available, but since the remote uses111		 * address 0 we'll use that. nec repeats are ignored too, even112		 * though the remote sends them.113		 */114		rc_keydown(d->rc_dev, RC_PROTO_NEC, RC_SCANCODE_NEC(0, key), 0);115	}116 117	return 0;118}119 120static int vp7045_read_eeprom(struct dvb_usb_device *d,u8 *buf, int len, int offset)121{122	int i, ret;123	u8 v, br[2];124	for (i=0; i < len; i++) {125		v = offset + i;126		ret = vp7045_usb_op(d, GET_EE_VALUE, &v, 1, br, 2, 5);127		if (ret)128			return ret;129 130		buf[i] = br[1];131	}132	deb_info("VP7045 EEPROM read (offs: %d, len: %d) : ", offset, i);133	debug_dump(buf, i, deb_info);134	return 0;135}136 137static int vp7045_read_mac_addr(struct dvb_usb_device *d,u8 mac[6])138{139	return vp7045_read_eeprom(d,mac, 6, MAC_0_ADDR);140}141 142static int vp7045_frontend_attach(struct dvb_usb_adapter *adap)143{144	u8 buf[255] = { 0 };145 146	vp7045_usb_op(adap->dev,VENDOR_STRING_READ,NULL,0,buf,20,0);147	buf[10] = '\0';148	deb_info("firmware says: %s ",buf);149 150	vp7045_usb_op(adap->dev,PRODUCT_STRING_READ,NULL,0,buf,20,0);151	buf[10] = '\0';152	deb_info("%s ",buf);153 154	vp7045_usb_op(adap->dev,FW_VERSION_READ,NULL,0,buf,20,0);155	buf[10] = '\0';156	deb_info("v%s\n",buf);157 158/*	Dump the EEPROM */159/*	vp7045_read_eeprom(d,buf, 255, FX2_ID_ADDR); */160 161	adap->fe_adap[0].fe = vp7045_fe_attach(adap->dev);162 163	return 0;164}165 166static struct dvb_usb_device_properties vp7045_properties;167 168static int vp7045_usb_probe(struct usb_interface *intf,169		const struct usb_device_id *id)170{171	return dvb_usb_device_init(intf, &vp7045_properties,172				   THIS_MODULE, NULL, adapter_nr);173}174 175enum {176	VISIONPLUS_VP7045_COLD,177	VISIONPLUS_VP7045_WARM,178	VISIONPLUS_TINYUSB2_COLD,179	VISIONPLUS_TINYUSB2_WARM,180};181 182static struct usb_device_id vp7045_usb_table[] = {183	DVB_USB_DEV(VISIONPLUS, VISIONPLUS_VP7045_COLD),184	DVB_USB_DEV(VISIONPLUS, VISIONPLUS_VP7045_WARM),185	DVB_USB_DEV(VISIONPLUS, VISIONPLUS_TINYUSB2_COLD),186	DVB_USB_DEV(VISIONPLUS, VISIONPLUS_TINYUSB2_WARM),187	{ }188};189 190MODULE_DEVICE_TABLE(usb, vp7045_usb_table);191 192static struct dvb_usb_device_properties vp7045_properties = {193	.usb_ctrl = CYPRESS_FX2,194	.firmware = "dvb-usb-vp7045-01.fw",195	.size_of_priv = 20,196 197	.num_adapters = 1,198	.adapter = {199		{200		.num_frontends = 1,201		.fe = {{202			.frontend_attach  = vp7045_frontend_attach,203			/* parameter for the MPEG2-data transfer */204			.stream = {205				.type = USB_BULK,206				.count = 7,207				.endpoint = 0x02,208				.u = {209					.bulk = {210						.buffersize = 4096,211					}212				}213			},214		}},215		}216	},217	.power_ctrl       = vp7045_power_ctrl,218	.read_mac_address = vp7045_read_mac_addr,219 220	.rc.core = {221		.rc_interval	= 400,222		.rc_codes	= RC_MAP_TWINHAN_VP1027_DVBS,223		.module_name    = KBUILD_MODNAME,224		.rc_query	= vp7045_rc_query,225		.allowed_protos = RC_PROTO_BIT_NEC,226		.scancode_mask	= 0xff,227	},228 229	.num_device_descs = 2,230	.devices = {231		{ .name = "Twinhan USB2.0 DVB-T receiver (TwinhanDTV Alpha/MagicBox II)",232		  .cold_ids = { &vp7045_usb_table[VISIONPLUS_VP7045_COLD], NULL },233		  .warm_ids = { &vp7045_usb_table[VISIONPLUS_VP7045_WARM], NULL },234		},235		{ .name = "DigitalNow TinyUSB 2 DVB-t Receiver",236		  .cold_ids = { &vp7045_usb_table[VISIONPLUS_TINYUSB2_COLD], NULL },237		  .warm_ids = { &vp7045_usb_table[VISIONPLUS_TINYUSB2_WARM], NULL },238		},239		{ NULL },240	}241};242 243/* usb specific object needed to register this driver with the usb subsystem */244static struct usb_driver vp7045_usb_driver = {245	.name		= "dvb_usb_vp7045",246	.probe		= vp7045_usb_probe,247	.disconnect	= dvb_usb_device_exit,248	.id_table	= vp7045_usb_table,249};250 251module_usb_driver(vp7045_usb_driver);252 253MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");254MODULE_DESCRIPTION("Driver for Twinhan MagicBox/Alpha and DNTV tinyUSB2 DVB-T USB2.0");255MODULE_VERSION("1.0");256MODULE_LICENSE("GPL");257