cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

tm6000-dvb.c (10327B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 *  tm6000-dvb.c - dvb-t support for TM5600/TM6000/TM6010 USB video capture devices
      4 *
      5 *  Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
      6 */
      7
      8#include <linux/kernel.h>
      9#include <linux/slab.h>
     10#include <linux/usb.h>
     11
     12#include "tm6000.h"
     13#include "tm6000-regs.h"
     14
     15#include "zl10353.h"
     16
     17#include <media/tuner.h>
     18
     19#include "xc2028.h"
     20#include "xc5000.h"
     21
     22MODULE_DESCRIPTION("DVB driver extension module for tm5600/6000/6010 based TV cards");
     23MODULE_AUTHOR("Mauro Carvalho Chehab");
     24MODULE_LICENSE("GPL");
     25
     26static int debug;
     27
     28module_param(debug, int, 0644);
     29MODULE_PARM_DESC(debug, "enable debug message");
     30
     31static inline void print_err_status(struct tm6000_core *dev,
     32				    int packet, int status)
     33{
     34	char *errmsg = "Unknown";
     35
     36	switch (status) {
     37	case -ENOENT:
     38		errmsg = "unlinked synchronously";
     39		break;
     40	case -ECONNRESET:
     41		errmsg = "unlinked asynchronously";
     42		break;
     43	case -ENOSR:
     44		errmsg = "Buffer error (overrun)";
     45		break;
     46	case -EPIPE:
     47		errmsg = "Stalled (device not responding)";
     48		break;
     49	case -EOVERFLOW:
     50		errmsg = "Babble (bad cable?)";
     51		break;
     52	case -EPROTO:
     53		errmsg = "Bit-stuff error (bad cable?)";
     54		break;
     55	case -EILSEQ:
     56		errmsg = "CRC/Timeout (could be anything)";
     57		break;
     58	case -ETIME:
     59		errmsg = "Device does not respond";
     60		break;
     61	}
     62	if (packet < 0) {
     63		dprintk(dev, 1, "URB status %d [%s].\n",
     64			status, errmsg);
     65	} else {
     66		dprintk(dev, 1, "URB packet %d, status %d [%s].\n",
     67			packet, status, errmsg);
     68	}
     69}
     70
     71static void tm6000_urb_received(struct urb *urb)
     72{
     73	int ret;
     74	struct tm6000_core *dev = urb->context;
     75
     76	switch (urb->status) {
     77	case 0:
     78	case -ETIMEDOUT:
     79		break;
     80	case -ENOENT:
     81	case -ECONNRESET:
     82	case -ESHUTDOWN:
     83		return;
     84	default:
     85		print_err_status(dev, 0, urb->status);
     86	}
     87
     88	if (urb->actual_length > 0)
     89		dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer,
     90						   urb->actual_length);
     91
     92	if (dev->dvb->streams > 0) {
     93		ret = usb_submit_urb(urb, GFP_ATOMIC);
     94		if (ret < 0) {
     95			printk(KERN_ERR "tm6000:  error %s\n", __func__);
     96			kfree(urb->transfer_buffer);
     97			usb_free_urb(urb);
     98			dev->dvb->bulk_urb = NULL;
     99		}
    100	}
    101}
    102
    103static int tm6000_start_stream(struct tm6000_core *dev)
    104{
    105	int ret;
    106	unsigned int pipe, size;
    107	struct tm6000_dvb *dvb = dev->dvb;
    108
    109	printk(KERN_INFO "tm6000: got start stream request %s\n", __func__);
    110
    111	if (dev->mode != TM6000_MODE_DIGITAL) {
    112		tm6000_init_digital_mode(dev);
    113		dev->mode = TM6000_MODE_DIGITAL;
    114	}
    115
    116	dvb->bulk_urb = usb_alloc_urb(0, GFP_KERNEL);
    117	if (!dvb->bulk_urb)
    118		return -ENOMEM;
    119
    120	pipe = usb_rcvbulkpipe(dev->udev, dev->bulk_in.endp->desc.bEndpointAddress
    121							  & USB_ENDPOINT_NUMBER_MASK);
    122
    123	size = usb_maxpacket(dev->udev, pipe);
    124	size = size * 15; /* 512 x 8 or 12 or 15 */
    125
    126	dvb->bulk_urb->transfer_buffer = kzalloc(size, GFP_KERNEL);
    127	if (!dvb->bulk_urb->transfer_buffer) {
    128		usb_free_urb(dvb->bulk_urb);
    129		dvb->bulk_urb = NULL;
    130		return -ENOMEM;
    131	}
    132
    133	usb_fill_bulk_urb(dvb->bulk_urb, dev->udev, pipe,
    134						 dvb->bulk_urb->transfer_buffer,
    135						 size,
    136						 tm6000_urb_received, dev);
    137
    138	ret = usb_clear_halt(dev->udev, pipe);
    139	if (ret < 0) {
    140		printk(KERN_ERR "tm6000: error %i in %s during pipe reset\n",
    141							ret, __func__);
    142
    143		kfree(dvb->bulk_urb->transfer_buffer);
    144		usb_free_urb(dvb->bulk_urb);
    145		dvb->bulk_urb = NULL;
    146		return ret;
    147	} else
    148		printk(KERN_ERR "tm6000: pipe reset\n");
    149
    150/*	mutex_lock(&tm6000_driver.open_close_mutex); */
    151	ret = usb_submit_urb(dvb->bulk_urb, GFP_ATOMIC);
    152
    153/*	mutex_unlock(&tm6000_driver.open_close_mutex); */
    154	if (ret) {
    155		printk(KERN_ERR "tm6000: submit of urb failed (error=%i)\n",
    156									ret);
    157
    158		kfree(dvb->bulk_urb->transfer_buffer);
    159		usb_free_urb(dvb->bulk_urb);
    160		dvb->bulk_urb = NULL;
    161		return ret;
    162	}
    163
    164	return 0;
    165}
    166
    167static void tm6000_stop_stream(struct tm6000_core *dev)
    168{
    169	struct tm6000_dvb *dvb = dev->dvb;
    170
    171	if (dvb->bulk_urb) {
    172		printk(KERN_INFO "urb killing\n");
    173		usb_kill_urb(dvb->bulk_urb);
    174		printk(KERN_INFO "urb buffer free\n");
    175		kfree(dvb->bulk_urb->transfer_buffer);
    176		usb_free_urb(dvb->bulk_urb);
    177		dvb->bulk_urb = NULL;
    178	}
    179}
    180
    181static int tm6000_start_feed(struct dvb_demux_feed *feed)
    182{
    183	struct dvb_demux *demux = feed->demux;
    184	struct tm6000_core *dev = demux->priv;
    185	struct tm6000_dvb *dvb = dev->dvb;
    186	printk(KERN_INFO "tm6000: got start feed request %s\n", __func__);
    187
    188	mutex_lock(&dvb->mutex);
    189	if (dvb->streams == 0) {
    190		dvb->streams = 1;
    191/*		mutex_init(&tm6000_dev->streming_mutex); */
    192		tm6000_start_stream(dev);
    193	} else
    194		++(dvb->streams);
    195	mutex_unlock(&dvb->mutex);
    196
    197	return 0;
    198}
    199
    200static int tm6000_stop_feed(struct dvb_demux_feed *feed)
    201{
    202	struct dvb_demux *demux = feed->demux;
    203	struct tm6000_core *dev = demux->priv;
    204	struct tm6000_dvb *dvb = dev->dvb;
    205
    206	printk(KERN_INFO "tm6000: got stop feed request %s\n", __func__);
    207
    208	mutex_lock(&dvb->mutex);
    209
    210	printk(KERN_INFO "stream %#x\n", dvb->streams);
    211	--(dvb->streams);
    212	if (dvb->streams == 0) {
    213		printk(KERN_INFO "stop stream\n");
    214		tm6000_stop_stream(dev);
    215/*		mutex_destroy(&tm6000_dev->streaming_mutex); */
    216	}
    217	mutex_unlock(&dvb->mutex);
    218/*	mutex_destroy(&tm6000_dev->streaming_mutex); */
    219
    220	return 0;
    221}
    222
    223static int tm6000_dvb_attach_frontend(struct tm6000_core *dev)
    224{
    225	struct tm6000_dvb *dvb = dev->dvb;
    226
    227	if (dev->caps.has_zl10353) {
    228		struct zl10353_config config = {
    229				     .demod_address = dev->demod_addr,
    230				     .no_tuner = 1,
    231				     .parallel_ts = 1,
    232				     .if2 = 45700,
    233				     .disable_i2c_gate_ctrl = 1,
    234				    };
    235
    236		dvb->frontend = dvb_attach(zl10353_attach, &config,
    237							   &dev->i2c_adap);
    238	} else {
    239		printk(KERN_ERR "tm6000: no frontend defined for the device!\n");
    240		return -1;
    241	}
    242
    243	return (!dvb->frontend) ? -1 : 0;
    244}
    245
    246DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
    247
    248static int register_dvb(struct tm6000_core *dev)
    249{
    250	int ret = -1;
    251	struct tm6000_dvb *dvb = dev->dvb;
    252
    253	mutex_init(&dvb->mutex);
    254
    255	dvb->streams = 0;
    256
    257	/* attach the frontend */
    258	ret = tm6000_dvb_attach_frontend(dev);
    259	if (ret < 0) {
    260		printk(KERN_ERR "tm6000: couldn't attach the frontend!\n");
    261		goto err;
    262	}
    263
    264	ret = dvb_register_adapter(&dvb->adapter, "Trident TVMaster 6000 DVB-T",
    265					THIS_MODULE, &dev->udev->dev, adapter_nr);
    266	if (ret < 0) {
    267		pr_err("tm6000: couldn't register the adapter!\n");
    268		goto err;
    269	}
    270
    271	dvb->adapter.priv = dev;
    272
    273	if (dvb->frontend) {
    274		switch (dev->tuner_type) {
    275		case TUNER_XC2028: {
    276			struct xc2028_config cfg = {
    277				.i2c_adap = &dev->i2c_adap,
    278				.i2c_addr = dev->tuner_addr,
    279			};
    280
    281			dvb->frontend->callback = tm6000_tuner_callback;
    282			ret = dvb_register_frontend(&dvb->adapter, dvb->frontend);
    283			if (ret < 0) {
    284				printk(KERN_ERR
    285					"tm6000: couldn't register frontend\n");
    286				goto adapter_err;
    287			}
    288
    289			if (!dvb_attach(xc2028_attach, dvb->frontend, &cfg)) {
    290				printk(KERN_ERR "tm6000: couldn't register frontend (xc3028)\n");
    291				ret = -EINVAL;
    292				goto frontend_err;
    293			}
    294			printk(KERN_INFO "tm6000: XC2028/3028 asked to be attached to frontend!\n");
    295			break;
    296			}
    297		case TUNER_XC5000: {
    298			struct xc5000_config cfg = {
    299				.i2c_address = dev->tuner_addr,
    300			};
    301
    302			dvb->frontend->callback = tm6000_xc5000_callback;
    303			ret = dvb_register_frontend(&dvb->adapter, dvb->frontend);
    304			if (ret < 0) {
    305				printk(KERN_ERR
    306					"tm6000: couldn't register frontend\n");
    307				goto adapter_err;
    308			}
    309
    310			if (!dvb_attach(xc5000_attach, dvb->frontend, &dev->i2c_adap, &cfg)) {
    311				printk(KERN_ERR "tm6000: couldn't register frontend (xc5000)\n");
    312				ret = -EINVAL;
    313				goto frontend_err;
    314			}
    315			printk(KERN_INFO "tm6000: XC5000 asked to be attached to frontend!\n");
    316			break;
    317			}
    318		}
    319	} else
    320		printk(KERN_ERR "tm6000: no frontend found\n");
    321
    322	dvb->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING
    323							    | DMX_MEMORY_BASED_FILTERING;
    324	dvb->demux.priv = dev;
    325	dvb->demux.filternum = 8;
    326	dvb->demux.feednum = 8;
    327	dvb->demux.start_feed = tm6000_start_feed;
    328	dvb->demux.stop_feed = tm6000_stop_feed;
    329	dvb->demux.write_to_decoder = NULL;
    330	ret = dvb_dmx_init(&dvb->demux);
    331	if (ret < 0) {
    332		printk(KERN_ERR "tm6000: dvb_dmx_init failed (errno = %d)\n", ret);
    333		goto frontend_err;
    334	}
    335
    336	dvb->dmxdev.filternum = dev->dvb->demux.filternum;
    337	dvb->dmxdev.demux = &dev->dvb->demux.dmx;
    338	dvb->dmxdev.capabilities = 0;
    339
    340	ret =  dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
    341	if (ret < 0) {
    342		printk(KERN_ERR "tm6000: dvb_dmxdev_init failed (errno = %d)\n", ret);
    343		goto dvb_dmx_err;
    344	}
    345
    346	return 0;
    347
    348dvb_dmx_err:
    349	dvb_dmx_release(&dvb->demux);
    350frontend_err:
    351	if (dvb->frontend) {
    352		dvb_unregister_frontend(dvb->frontend);
    353		dvb_frontend_detach(dvb->frontend);
    354	}
    355adapter_err:
    356	dvb_unregister_adapter(&dvb->adapter);
    357err:
    358	return ret;
    359}
    360
    361static void unregister_dvb(struct tm6000_core *dev)
    362{
    363	struct tm6000_dvb *dvb = dev->dvb;
    364
    365	if (dvb->bulk_urb) {
    366		struct urb *bulk_urb = dvb->bulk_urb;
    367
    368		kfree(bulk_urb->transfer_buffer);
    369		bulk_urb->transfer_buffer = NULL;
    370		usb_unlink_urb(bulk_urb);
    371		usb_free_urb(bulk_urb);
    372	}
    373
    374/*	mutex_lock(&tm6000_driver.open_close_mutex); */
    375	if (dvb->frontend) {
    376		dvb_unregister_frontend(dvb->frontend);
    377		dvb_frontend_detach(dvb->frontend);
    378	}
    379
    380	dvb_dmxdev_release(&dvb->dmxdev);
    381	dvb_dmx_release(&dvb->demux);
    382	dvb_unregister_adapter(&dvb->adapter);
    383	mutex_destroy(&dvb->mutex);
    384/*	mutex_unlock(&tm6000_driver.open_close_mutex); */
    385}
    386
    387static int dvb_init(struct tm6000_core *dev)
    388{
    389	struct tm6000_dvb *dvb;
    390	int rc;
    391
    392	if (!dev)
    393		return 0;
    394
    395	if (!dev->caps.has_dvb)
    396		return 0;
    397
    398	if (dev->udev->speed == USB_SPEED_FULL) {
    399		printk(KERN_INFO "This USB2.0 device cannot be run on a USB1.1 port. (it lacks a hardware PID filter)\n");
    400		return 0;
    401	}
    402
    403	dvb = kzalloc(sizeof(struct tm6000_dvb), GFP_KERNEL);
    404	if (!dvb)
    405		return -ENOMEM;
    406
    407	dev->dvb = dvb;
    408
    409	rc = register_dvb(dev);
    410	if (rc < 0) {
    411		kfree(dvb);
    412		dev->dvb = NULL;
    413		return 0;
    414	}
    415
    416	return 0;
    417}
    418
    419static int dvb_fini(struct tm6000_core *dev)
    420{
    421	if (!dev)
    422		return 0;
    423
    424	if (!dev->caps.has_dvb)
    425		return 0;
    426
    427	if (dev->dvb) {
    428		unregister_dvb(dev);
    429		kfree(dev->dvb);
    430		dev->dvb = NULL;
    431	}
    432
    433	return 0;
    434}
    435
    436static struct tm6000_ops dvb_ops = {
    437	.type	= TM6000_DVB,
    438	.name	= "TM6000 dvb Extension",
    439	.init	= dvb_init,
    440	.fini	= dvb_fini,
    441};
    442
    443static int __init tm6000_dvb_register(void)
    444{
    445	return tm6000_register_extension(&dvb_ops);
    446}
    447
    448static void __exit tm6000_dvb_unregister(void)
    449{
    450	tm6000_unregister_extension(&dvb_ops);
    451}
    452
    453module_init(tm6000_dvb_register);
    454module_exit(tm6000_dvb_unregister);