/* DVB USB Linux driver for Anysee E30 DVB-C & DVB-T USB2.0 receiver * * Copyright (C) 2007 Antti Palosaari * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation, version 2. * * see Documentation/dvb/README.dvb-usb for more information * * * TODO: * - put required TDA10023 options configurable * - add Common Interface (CI) support * - fixes overall */ #include "anysee.h" #include "tda1002x.h" //--HB-- Seems that my E30 has 353 //#include "mt352.h" //#include "mt352_priv.h" //--HB-- Seems that my E30 has 353. #include "zl10353.h" #include "zl10353_priv.h" /* debug */ //static int dvb_usb_anysee_debug = -1; static int dvb_usb_anysee_debug; module_param_named(debug, dvb_usb_anysee_debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS); static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen, u8 *rbuf, u8 rlen) { int act_len, ret; u8 buf[64]; static u8 seq; /* packet sequence number */ memcpy(&buf[0], sbuf, slen); buf[60] = seq++; if (mutex_lock_interruptible(&d->i2c_mutex) < 0) return -EAGAIN; deb_xfer(">>> "); debug_dump(buf, sizeof(buf), deb_xfer); /* send request */ ret = usb_bulk_msg(d->udev, usb_sndbulkpipe(d->udev, 0x01), buf, sizeof(buf), &act_len, ANYSEE_USB_TIMEOUT); if (ret) err("%s: sending failed: %d (%d/%d)", __FUNCTION__, ret, sizeof(buf), act_len); else ret = act_len != sizeof(buf) ? -1 : 0; if (ret) return ret; /* receive 1st answer (skip, answer to previous call) */ ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev, 0x81), buf, sizeof(buf), &act_len, ANYSEE_USB_TIMEOUT); if (ret) { err("%s: 1st receiving failed: %d", __FUNCTION__, ret); return ret; } deb_xfer("<<< "); debug_dump(buf, act_len, deb_xfer); /* receive 2nd answer */ ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev, 0x81), buf, sizeof(buf), &act_len, ANYSEE_USB_TIMEOUT); if (ret) { err("%s: 2nd receiving failed: %d", __FUNCTION__, ret); return ret; } deb_xfer("<<< "); debug_dump(buf, act_len, deb_xfer); mutex_unlock(&d->i2c_mutex); /* read request, copy returned data to return buf */ if(rbuf && rlen) memcpy(rbuf, buf, rlen); return 0; } static int anysee_read_reg(struct dvb_usb_device *d, u16 reg, u8 *val) { u8 buf[] = {CMD_REG_READ, (reg & 0xff00) >> 8, reg & 0x00ff, 0x01}; int ret; ret = anysee_ctrl_msg(d, buf, sizeof(buf), val, 1); deb_info("%s: reg:%04x val:%02x\n", __FUNCTION__, reg, *val); return ret; } static int anysee_write_reg(struct dvb_usb_device *d, u16 reg, u8 val) { u8 buf[] = {CMD_REG_WRITE, (reg & 0xff00) >> 8, reg & 0x00ff, 0x01, val}; deb_info("%s: reg:%04x val:%02x\n", __FUNCTION__, reg, val); return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0); } static int anysee_get_board_id(struct dvb_usb_device *d, u8 *id) { u8 buf[] = {CMD_GET_BOARD_ID}; return anysee_ctrl_msg(d, buf, sizeof(buf), id, 3); } static int anysee_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) { u8 buf[] = {CMD_STREAMING_CTRL, (u8)onoff, 0x00}; deb_info("%s: onoff:%02x\n", __FUNCTION__, onoff); return anysee_ctrl_msg(adap->dev, buf, sizeof(buf), NULL, 0); } static int anysee_led_ctrl(struct dvb_usb_device *d, u8 mode, u8 interval) { u8 buf[] = {CMD_LED_AND_IR_CTRL, 0x01, mode, interval}; deb_info("%s: state:%02x interval:%02x\n", __FUNCTION__, mode, interval); return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0); } static int anysee_ir_ctrl(struct dvb_usb_device *d, u8 onoff) { u8 buf[] = {CMD_LED_AND_IR_CTRL, 0x02, onoff}; deb_info("%s: onoff:%02x\n", __FUNCTION__, onoff); return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0); } static int anysee_init(struct dvb_usb_device *d) { int ret; /* LED light */ ret = anysee_led_ctrl(d, 0x01, 0x03); if (ret) return ret; /* enable IR */ ret = anysee_ir_ctrl(d, 1); if (ret) return ret; return 0; } /* I2C */ static int anysee_master_xfer(struct i2c_adapter* adap, struct i2c_msg *msg, int num) { struct dvb_usb_device *d = i2c_get_adapdata(adap); int i = 0; int inc; int ret; while (i < num) { if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) { u8 buf[6]; buf[0] = CMD_I2C_READ; buf[1] = msg[i].addr + 1; buf[2] = msg[i].buf[0]; buf[3] = 0x00; buf[4] = 0x00; buf[5] = 0x01; ret = anysee_ctrl_msg(d, buf, sizeof(buf), msg[i+1].buf, msg[i+1].len); inc = 2; } else { u8 buf[4+msg[i].len]; buf[0] = CMD_I2C_WRITE; buf[1] = msg[i].addr; buf[2] = msg[i].len; buf[3] = 0x01; memcpy(&buf[4], msg[i].buf, msg[i].len); ret = anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0); inc = 1; } if (ret) return ret; i += inc; } return i; } static u32 anysee_i2c_func(struct i2c_adapter *adapter) { return I2C_FUNC_I2C; } static struct i2c_algorithm anysee_i2c_algo = { .master_xfer = anysee_master_xfer, .functionality = anysee_i2c_func, }; //--HB-- Seems that my E30 has 353 /*static int anysee_dee1601_mt352_demod_init(struct dvb_frontend* fe) { static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x28 }; static u8 reset [] = { RESET, 0x80 }; static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; static u8 agc_cfg [] = { AGC_TARGET, 0x28, 0x20 }; static u8 gpp_ctl_cfg [] = { GPP_CTL, 0x33 }; static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 }; mt352_write(fe, clock_config, sizeof(clock_config)); udelay(200); mt352_write(fe, reset, sizeof(reset)); mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); mt352_write(fe, agc_cfg, sizeof(agc_cfg)); mt352_write(fe, gpp_ctl_cfg, sizeof(gpp_ctl_cfg)); mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); return 0; } */ //--HB-- Looks like my E30 has 353 //--HB-- Lets try to remove this (Just following au6610) //TODO: Needs to be checked. Now this is just copied from 352 /*static int anysee_dee1601_zl10353_demod_init(struct dvb_frontend* fe) { static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x28 }; static u8 reset [] = { RESET, 0x80 }; static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; static u8 agc_cfg [] = { AGC_TARGET, 0x28, 0x20 }; static u8 gpp_ctl_cfg [] = { GPP_CTL, 0x33 }; static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 }; zl10353_write(fe, clock_config, sizeof(clock_config)); udelay(200); zl10353_write(fe, reset, sizeof(reset)); zl10353_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); zl10353_write(fe, agc_cfg, sizeof(agc_cfg)); zl10353_write(fe, gpp_ctl_cfg, sizeof(gpp_ctl_cfg)); zl10353_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); return 0; } */ /* Callbacks for DVB USB */ static int anysee_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props, struct dvb_usb_device_description **desc, int *cold) { *cold = 0; return 0; } static int anysee_rc_query(struct dvb_usb_device *d, u32 *event, int *state) { u8 buf[] = {CMD_GET_IR_CODE}; struct dvb_usb_rc_key *keymap = d->props.rc_key_map; u8 ircode[2]; int i, ret; ret = anysee_ctrl_msg(d, buf, sizeof(buf), &ircode[0], 2); if (ret) return ret; *event = 0; *state = REMOTE_NO_KEY_PRESSED; for (i = 0; i < d->props.rc_key_map_size; i++) { if (keymap[i].custom == ircode[0] && keymap[i].data == ircode[1]) { *event = keymap[i].event; *state = REMOTE_KEY_PRESSED; return 0; } } return 0; } static struct tda1002x_config anysee_tda1002x_config = { .demod_address = 0x1a, .invert = 0, .xtal = 16000000, .pll_m = 11, .pll_p = 3, .pll_n = 1, .deltaf = 0xfed6, }; //--HB-- Seems that my E30 has 353 /* static struct mt352_config anysee_dee1601_mt352_config = { .demod_address = 0x1e, .demod_init = anysee_dee1601_mt352_demod_init, }; */ //--HB-- Looks like my E30 has zl10353 //TODO: Just copied from mt352 version static struct zl10353_config anysee_dee1601_zl10353_config = { .demod_address = 0x1e, .parallel_ts = 1, // .demod_init = anysee_dee1601_zl10353_demod_init, }; /* Philips TDA10023 DVB-C demod */ static int anysee_tda1002x_frontend_attach(struct dvb_usb_adapter *adap) { int ret; /* connect demod on IO port D */ ret = anysee_write_reg(adap->dev, 0xb0, 0x25); if (ret) return ret; if ((adap->fe = dvb_attach(tda10023_attach, &anysee_tda1002x_config, &adap->dev->i2c_adap, 0x48)) != NULL) { return 0; } return -EIO; } /* Unknown PLL inside of Samsung DTOS403IH102A tuner module */ static int anysee_unknown_2_tuner_attach(struct dvb_usb_adapter *adap) { deb_info("%s: \n", __FUNCTION__); dvb_attach(dvb_pll_attach, adap->fe, 0xc0, &adap->dev->i2c_adap, DVB_PLL_UNKNOWN_2); return 0; } //--HB-- Seems that my E30 has 353 /* Zarlink MT352 DVB-T demod inside of Samsung DNOS4D4ZH102A NIM */ /*static int anysee_dee1601_mt352_frontend_attach(struct dvb_usb_adapter *adap) { if ((adap->fe = dvb_attach(mt352_attach, &anysee_dee1601_mt352_config, &adap->dev->i2c_adap)) != NULL) { return 0; } return -EIO; } */ //--HB-- Looks like my E30 has 353 //TODO: This is just copied from 352 version /*TODO: Zarlink MT352 DVB-T demod inside of Samsung DNOS4D4ZH102A NIM */ static int anysee_dee1601_zl10353_frontend_attach(struct dvb_usb_adapter *adap) { if ((adap->fe = dvb_attach(zl10353_attach, &anysee_dee1601_zl10353_config, &adap->dev->i2c_adap)) != NULL) { return 0; } return -EIO; } /* Thomson dtt7579 (not sure) PLL inside of Samsung DNOS4D4ZH102A NIM */ static int anysee_dee1601_dtt7579_tuner_attach(struct dvb_usb_adapter *adap) { dvb_attach(dvb_pll_attach, adap->fe, 0x61, NULL, DVB_PLL_THOMSON_DTT7579); return 0; } static struct dvb_usb_rc_key anysee_rc_keys[] = { { 0x01, 0x00, KEY_0 }, { 0x01, 0x01, KEY_1 }, { 0x01, 0x02, KEY_2 }, { 0x01, 0x03, KEY_3 }, { 0x01, 0x04, KEY_4 }, { 0x01, 0x05, KEY_5 }, { 0x01, 0x06, KEY_6 }, { 0x01, 0x07, KEY_7 }, { 0x01, 0x08, KEY_8 }, { 0x01, 0x09, KEY_9 }, { 0x01, 0x0a, KEY_POWER }, { 0x01, 0x0b, KEY_DOCUMENTS }, /* '*' */ { 0x01, 0x19, KEY_FAVORITES }, { 0x01, 0x20, KEY_SLEEP }, { 0x01, 0x21, KEY_MODE }, /* 4:3 / 16:9 select */ { 0x01, 0x22, KEY_ZOOM }, { 0x01, 0x47, KEY_TEXT }, { 0x01, 0x16, KEY_TV }, /* TV / radio select */ { 0x01, 0x1e, KEY_LANGUAGE }, /* Second Audio Program */ { 0x01, 0x1a, KEY_SUBTITLE }, { 0x01, 0x1b, KEY_CAMERA }, /* screenshot */ { 0x01, 0x42, KEY_MUTE }, { 0x01, 0x0e, KEY_MENU }, { 0x01, 0x0f, KEY_EPG }, { 0x01, 0x17, KEY_INFO }, { 0x01, 0x10, KEY_EXIT }, { 0x01, 0x13, KEY_VOLUMEUP }, { 0x01, 0x12, KEY_VOLUMEDOWN }, { 0x01, 0x11, KEY_CHANNELUP }, { 0x01, 0x14, KEY_CHANNELDOWN }, { 0x01, 0x15, KEY_OK }, { 0x01, 0x1d, KEY_RED }, { 0x01, 0x1f, KEY_GREEN }, { 0x01, 0x1c, KEY_YELLOW }, { 0x01, 0x44, KEY_BLUE }, { 0x01, 0x0c, KEY_SHUFFLE }, /* snapshot */ { 0x01, 0x48, KEY_STOP }, { 0x01, 0x50, KEY_PLAY }, { 0x01, 0x51, KEY_PAUSE }, { 0x01, 0x49, KEY_RECORD }, { 0x01, 0x18, KEY_PREVIOUS }, /* |<< */ { 0x01, 0x0d, KEY_NEXT }, /* >>| */ { 0x01, 0x24, KEY_PROG1 }, /* 'F1' */ { 0x01, 0x25, KEY_PROG2 }, /* 'F2' */ }; /* DVB USB Driver stuff */ static struct dvb_usb_device_properties anysee_identify_properties; static struct dvb_usb_device_properties anysee_e30c_properties; static struct dvb_usb_device_properties anysee_e30_properties; static int anysee_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct dvb_usb_device *d; struct usb_host_interface *alt; struct usb_device *udev; struct dvb_usb_device_properties *anysee_properties; int ret; u8 board_id[3]; if (intf->num_altsetting < 1) return -ENODEV; if ((ret = dvb_usb_device_init(intf, &anysee_identify_properties, THIS_MODULE, &d)) == 0) { if (d && (ret = anysee_get_board_id(d, board_id) != 0)) return ret; deb_info("%s: board id:%02x %02x %02x\n", __FUNCTION__, board_id[0], board_id[1], board_id[2]); } //TODO check if dvb_usb_device_init calling twice leak resources switch (board_id[0]) { case 0x0a: //0a 01 00 anysee_properties = &anysee_e30c_properties; break; case 0x02: //02 02 01 anysee_properties = &anysee_e30_properties; break; default: err("Unkown Anysee version:%02x %02x %02x. Please report the linux-dvb@linuxtv.org.", board_id[0], board_id[1], board_id[2]); /* try load Anysee E30 DVB-T as fallback */ anysee_properties = &anysee_e30_properties; break; } if ((ret = dvb_usb_device_init(intf, anysee_properties, THIS_MODULE, &d)) == 0) { alt = usb_altnum_to_altsetting(intf, 0); if (alt == NULL) { deb_info("no alt found!\n"); return -ENODEV; } ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber, alt->desc.bAlternateSetting); udev = interface_to_usbdev(intf); if (d && (ret = anysee_init(d)) != 0) return ret; } return ret; } static struct usb_device_id anysee_table [] = { // { USB_DEVICE(USB_VID_CYPRESS, 123) }, { USB_DEVICE(USB_VID_CYPRESS, USB_PID_ANYSEE) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE (usb, anysee_table); /* device for identify board */ static struct dvb_usb_device_properties anysee_identify_properties = { .caps = DVB_USB_IS_AN_I2C_ADAPTER, .usb_ctrl = DEVICE_SPECIFIC, .size_of_priv = 0, .identify_state = anysee_identify_state, .num_adapters = 0, .i2c_algo = &anysee_i2c_algo, .num_device_descs = 1, .devices = { { "Anysee USB2.0", { &anysee_table[0], NULL }, { NULL }, }, } }; /* Anysee E30C DVB-C */ static struct dvb_usb_device_properties anysee_e30c_properties = { .caps = DVB_USB_IS_AN_I2C_ADAPTER, .usb_ctrl = DEVICE_SPECIFIC, .rc_interval = 250, /* windows driver uses 500ms */ .rc_key_map = anysee_rc_keys, .rc_key_map_size = ARRAY_SIZE(anysee_rc_keys), .rc_query = anysee_rc_query, .size_of_priv = 0, .identify_state = anysee_identify_state, .num_adapters = 1, .adapter = { { .streaming_ctrl = anysee_streaming_ctrl, .frontend_attach = anysee_tda1002x_frontend_attach, .tuner_attach = anysee_unknown_2_tuner_attach, /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, .count = 8, .endpoint = 0x82, .u = { .bulk = { .buffersize = 512, } } }, } }, .i2c_algo = &anysee_i2c_algo, .num_device_descs = 1, .devices = { { "Anysee E30C DVB-C USB2.0", { &anysee_table[0], NULL }, { NULL }, }, } }; /* Anysee E30 DVB-T */ static struct dvb_usb_device_properties anysee_e30_properties = { .caps = DVB_USB_IS_AN_I2C_ADAPTER, .usb_ctrl = DEVICE_SPECIFIC, .rc_interval = 250, /* windows driver uses 500ms */ .rc_key_map = anysee_rc_keys, .rc_key_map_size = ARRAY_SIZE(anysee_rc_keys), .rc_query = anysee_rc_query, .size_of_priv = 0, .identify_state = anysee_identify_state, .num_adapters = 1, .adapter = { { .streaming_ctrl = anysee_streaming_ctrl, //--HB-- Lets change this. It seems that my Anysee E30 DVB-T has other frontend .frontend_attach = anysee_dee1601_zl10353_frontend_attach, //--HB--.frontend_attach = anysee_dee1601_mt352_frontend_attach, .tuner_attach = anysee_dee1601_dtt7579_tuner_attach, /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, .count = 8, .endpoint = 0x82, .u = { .bulk = { .buffersize = 512, } } }, }, }, .i2c_algo = &anysee_i2c_algo, .num_device_descs = 1, .devices = { { "Anysee E30 DVB-T USB2.0", { &anysee_table[0], NULL }, { NULL }, }, } }; static struct usb_driver anysee_driver = { #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) .owner = THIS_MODULE, #endif .name = "dvb_usb_anysee", .probe = anysee_probe, .disconnect = dvb_usb_device_exit, .id_table = anysee_table, }; /* module stuff */ static int __init anysee_module_init(void) { int ret; if ((ret = usb_register(&anysee_driver))) { err("usb_register failed. Error number %d", ret); return ret; } return 0; } static void __exit anysee_module_exit(void) { /* deregister this driver from the USB subsystem */ usb_deregister(&anysee_driver); } module_init (anysee_module_init); module_exit (anysee_module_exit); MODULE_AUTHOR("Antti Palosaari "); MODULE_DESCRIPTION("Driver Anysee E30 DVB-C & DVB-T USB2.0"); MODULE_VERSION("0.1"); MODULE_LICENSE("GPL");