From owner-freebsd-multimedia@FreeBSD.ORG Mon Jan 31 21:32:08 2011 Return-Path: Delivered-To: freebsd-multimedia@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 6E4971065693; Mon, 31 Jan 2011 21:32:08 +0000 (UTC) (envelope-from nox@jelal.kn-bremen.de) Received: from smtp.kn-bremen.de (gelbbaer.kn-bremen.de [78.46.108.116]) by mx1.freebsd.org (Postfix) with ESMTP id 171158FC14; Mon, 31 Jan 2011 21:32:08 +0000 (UTC) Received: by smtp.kn-bremen.de (Postfix, from userid 10) id 2844D1E00252; Mon, 31 Jan 2011 22:32:07 +0100 (CET) Received: from triton8.kn-bremen.de (noident@localhost [127.0.0.1]) by triton8.kn-bremen.de (8.14.4/8.14.3) with ESMTP id p0VLRAlM087132; Mon, 31 Jan 2011 22:27:10 +0100 (CET) (envelope-from nox@triton8.kn-bremen.de) Received: (from nox@localhost) by triton8.kn-bremen.de (8.14.4/8.14.3/Submit) id p0VLRAlX087131; Mon, 31 Jan 2011 22:27:10 +0100 (CET) (envelope-from nox) From: Juergen Lock Date: Mon, 31 Jan 2011 22:27:10 +0100 To: freebsd-multimedia@FreeBSD.org Message-ID: <20110131212710.GA85739@triton8.kn-bremen.de> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) Cc: hselasky@FreeBSD.org Subject: New dvb-s2 tuner, and a hack to get remaining remotes working X-BeenThere: freebsd-multimedia@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Multimedia discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 31 Jan 2011 21:32:08 -0000 The hack was to force dvb tuner remotes to /dev/lircX which webcamd svn now supports: http://people.freebsd.org/~nox/dvb/webcamd/patch-remote1.txt (also copied below) - I wasn't able to test this with the lirc port yet (it complained that it can't set /dev/lirc0 to O_NONBLOCK), but at least it seems to work when used as -h /dev/lirc0 with my port of the vdr remote plugin, so vdr can now _finally_ use all the remotes of the usb dvb tuners I have working here. :) The new tuner is a "TechnoTrend S2-3600 DVB-S2 USB" and it needs a small patch that Hans already committed to webcamd svn: http://people.freebsd.org/~nox/dvb/webcamd/patch-pctv452e.c.txt It is driven by pctv452e.c out of the liplianin repo like my other dvb-s2 tuner and seems to work just as well, the advantage of this one is that it a) has the most complete remote of all the tuners I have here (the other one, the original PCTV 452e has the most minimalistic remote of them all) and b) it seems to be more readily available here than the PCTV 452e now, that one meanwhile seems to have been replaced by a PCTV 460e for which there still is no Linux driver... If you want to test webcamd svn see hps' page: http://www.selasky.org/hans_petter/video4bsd/ To use it with the remote patch and vdr add this to vdr's args: '-Premote -h /dev/lirc0' then when you start vdr and vdr-sxfe the on-screen-display (osd) should ask you to configure the remote by pressing the buttons you want to assign. The vdr Call for testing post with further notes is here: http://lists.freebsd.org/pipermail/freebsd-multimedia/2011-January/011554.html and more links are here: http://people.freebsd.org/~nox/dvb/ And now for the remote patch... Enjoy, Juergen --- v4l-dvb/linux/drivers/media/dvb/dvb-usb/dvb-usb-remote.c.orig +++ v4l-dvb/linux/drivers/media/dvb/dvb-usb/dvb-usb-remote.c @@ -12,6 +12,112 @@ #include #endif +/* webcamd svn currently only supports raw lirc devices */ +#define FORCE_LIRC_RAW + +#ifdef FORCE_LIRC_RAW +#define MODULE_NAME "dvb-usb-remote" +#include + +struct dvb_usb_IR { + struct dvb_usb_device *dev; + struct input_dev *input; + char name[32]; + char phys[32]; + + /* poll external decoder */ + int polling; + struct delayed_work work; + u32 lastevent; + + /* IR device properties */ + struct ir_dev_props props; +}; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) +static void dvb_usb_ir_work(void *data) +#else +static void dvb_usb_ir_work(struct work_struct *work) +#endif +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) + struct dvb_usb_IR *ir = data; +#else + struct dvb_usb_IR *ir = container_of(work, struct dvb_usb_IR, work.work); +#endif + + u32 event; + int state; + struct ir_raw_event ev; + + /* TODO: need a lock here. We can simply skip checking for the remote control + if we're busy. */ + + /* when the parameter has been set to 1 via sysfs while the driver was running */ + if (dvb_usb_disable_rc_polling) + return; + + if (ir->dev->props.rc_query(ir->dev,&event,&state)) { + err("error while querying for an remote control event."); + goto schedule; + } + + + switch (state) { + case REMOTE_NO_KEY_PRESSED: + if (!ir->lastevent) + break; + ev.pulse = false; + ev.duration = 100; + ir_raw_event_store(ir->input, &ev); + ir_raw_event_reset(ir->input); + ir->lastevent = 0; + break; + case REMOTE_KEY_PRESSED: + deb_rc("key pressed\n"); + case REMOTE_KEY_REPEAT: + deb_rc("key repeated\n"); +#if 1 + printf("lirc event 0x%lx\n", (long)event); +#endif + if (event < 1000) + event *= 1000; + ir_raw_event_reset(ir->input); + ev.duration = event; + ev.pulse = true; + ir_raw_event_store(ir->input, &ev); + ir->lastevent = event; + break; + default: + break; + } + +schedule: + schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling)); +} + +static int dvb_usb_ir_start(void *priv) +{ + struct dvb_usb_IR *ir = priv; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) + INIT_DELAYED_WORK(&ir->work, dvb_usb_ir_work, ir); +#else + INIT_DELAYED_WORK(&ir->work, dvb_usb_ir_work); +#endif + schedule_delayed_work(&ir->work, 0); + + return 0; +} + +static void dvb_usb_ir_stop(void *priv) +{ + struct dvb_usb_IR *ir = priv; + + cancel_delayed_work_sync(&ir->work); +} +#endif + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) static int dvb_usb_getkeycode(struct input_dev *dev, int scancode, int *keycode) @@ -79,6 +185,7 @@ static int dvb_usb_setkeycode(struct inp } #endif +#ifndef FORCE_LIRC_RAW /* Remote-control poll function - called every dib->rc_query_interval ms to see * whether the remote control has received anything. * @@ -167,18 +274,80 @@ static void dvb_usb_read_remote_control( schedule: schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc_interval)); } +#endif int dvb_usb_remote_init(struct dvb_usb_device *d) { struct input_dev *input_dev; int i; int err; +#ifdef FORCE_LIRC_RAW + struct dvb_usb_IR *ir; +#endif if (d->props.rc_key_map == NULL || d->props.rc_query == NULL || dvb_usb_disable_rc_polling) return 0; +#ifdef FORCE_LIRC_RAW + ir = kzalloc(sizeof(*ir), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!ir || !input_dev) + goto err_out_free; + + /* record handles to ourself */ + ir->dev = d; + + ir->input = input_dev; + + ir->props.allowed_protos = IR_TYPE_LIRC; + ir->props.priv = ir; +#if 0 /* XXX never gets called */ + ir->props.open = dvb_usb_ir_start; + ir->props.close = dvb_usb_ir_stop; +#endif + ir->props.driver_type = RC_DRIVER_IR_RAW; + + /* This is how often we ask the chip for IR information */ + ir->polling = 100; /* ms */ + + ir->lastevent = 0; + + /* init input device */ + snprintf(ir->name, sizeof(ir->name), "USB DVB IR"); + + usb_make_path(d->udev, ir->phys, sizeof(ir->phys)); + strlcat(ir->phys, "/input0", sizeof(ir->phys)); + + input_dev->name = ir->name; + input_dev->phys = ir->phys; + input_dev->id.bustype = BUS_USB; + input_dev->id.version = 1; + input_dev->id.vendor = le16_to_cpu(d->udev->descriptor.idVendor); + input_dev->id.product = le16_to_cpu(d->udev->descriptor.idProduct); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) + input_dev->dev.parent = &d->udev->dev; +#else + input_dev->cdev.dev = &d->udev->dev; +#endif + + + /* all done */ + err = ir_input_register(ir->input, RC_MAP_RC5_TV /*RC_MAP_EMPTY*/, + &ir->props, MODULE_NAME); + if (err) + goto err_out_free; + +#if 1 /* XXX */ + dvb_usb_ir_start(ir); +#endif + return 0; + err_out_free: + kfree(ir); + return err; +#else usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys)); strlcat(d->rc_phys, "/ir0", sizeof(d->rc_phys)); @@ -237,6 +406,7 @@ int dvb_usb_remote_init(struct dvb_usb_d d->state |= DVB_USB_STATE_REMOTE; +#endif return 0; }