[patch 10/10] firedtv: register input device as child of a FireWire device

Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]
To: <devel@...>
Date: Monday, September 29, 2008 - 1:22 pm

Instead of one virtual input device which exists for the whole lifetime
of the driver and receives events from all connected FireDTVs, register
one input device for each firedtv device. These input devices will show
up as children of the respective firedtv devices in the sysfs hierarchy.

However, the implementation falls short because of a bug in userspace:
Udev's path_id script gets stuck with 100% CPU utilization, maybe
because of an assumption about the maximum ieee1394 device hierarchy
depth.

To avoid this bug, we use the fw-host device instead of the proper
unit_directory device as parent of the input device.

There is hope that the port to the new firewire stack won't be inhibited
by this userspace bug because there are no fw-host devices there.

Signed-off-by: Stefan Richter
---
drivers/media/dvb/firesat/avc_api.c | 4 +-
drivers/media/dvb/firesat/firesat-rc.c | 42 +++++++++++++++--------
drivers/media/dvb/firesat/firesat-rc.h | 9 +++-
drivers/media/dvb/firesat/firesat.h | 5 +-
drivers/media/dvb/firesat/firesat_1394.c | 26 ++++++--------
5 files changed, 52 insertions(+), 34 deletions(-)

Index: linux/drivers/media/dvb/firesat/avc_api.c
===================================================================
--- linux.orig/drivers/media/dvb/firesat/avc_api.c
+++ linux/drivers/media/dvb/firesat/avc_api.c
@@ -225,8 +225,8 @@ int AVCRecv(struct firesat *firesat, u8
RspFrm->operand[2] == SFE_VENDOR_DE_COMPANYID_2 &&
RspFrm->operand[3] == SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL) {
if (RspFrm->resp == CHANGED) {
- firesat_handle_rc(RspFrm->operand[4] << 8 |
- RspFrm->operand[5]);
+ firesat_handle_rc(firesat,
+ RspFrm->operand[4] << 8 | RspFrm->operand[5]);
schedule_work(&firesat->remote_ctrl_work);
} else if (RspFrm->resp != INTERIM) {
dev_info(&firesat->ud->device,
Index: linux/drivers/media/dvb/firesat/firesat-rc.c
===================================================================
--- linux.orig/drivers/media/dvb/firesat/firesat-rc.c
+++ linux/drivers/media/dvb/firesat/firesat-rc.c
@@ -12,9 +12,11 @@
#include
#include
#include
+#include
#include

#include "firesat-rc.h"
+#include "firesat.h"

/* fixed table with older keycodes, geared towards MythTV */
const static u16 oldtable[] = {
@@ -61,7 +63,7 @@ const static u16 oldtable[] = {
};

/* user-modifiable table for a remote as sold in 2008 */
-static u16 keytable[] = {
+const static u16 keytable[] = {

/* code from device: 0x0300...0x031f */

@@ -123,19 +125,24 @@ static u16 keytable[] = {
[0x34] = KEY_EXIT,
};

-static struct input_dev *idev;
-
-int firesat_register_rc(void)
+int firesat_register_rc(struct firesat *firesat, struct device *dev)
{
+ struct input_dev *idev;
int i, err;

idev = input_allocate_device();
if (!idev)
return -ENOMEM;

+ firesat->remote_ctrl_dev = idev;
idev->name = "FireDTV remote control";
+ idev->dev.parent = dev;
idev->evbit[0] = BIT_MASK(EV_KEY);
- idev->keycode = keytable;
+ idev->keycode = kmemdup(keytable, sizeof(keytable), GFP_KERNEL);
+ if (!idev->keycode) {
+ err = -ENOMEM;
+ goto fail;
+ }
idev->keycodesize = sizeof(keytable[0]);
idev->keycodemax = ARRAY_SIZE(keytable);

@@ -144,22 +151,31 @@ int firesat_register_rc(void)

err = input_register_device(idev);
if (err)
- input_free_device(idev);
+ goto fail_free_keymap;

+ return 0;
+
+fail_free_keymap:
+ kfree(idev->keycode);
+fail:
+ input_free_device(idev);
return err;
}

-void firesat_unregister_rc(void)
+void firesat_unregister_rc(struct firesat *firesat)
{
- input_unregister_device(idev);
+ kfree(firesat->remote_ctrl_dev->keycode);
+ input_unregister_device(firesat->remote_ctrl_dev);
}

-void firesat_handle_rc(unsigned int code)
+void firesat_handle_rc(struct firesat *firesat, unsigned int code)
{
+ u16 *keycode = firesat->remote_ctrl_dev->keycode;
+
if (code >= 0x0300 && code <= 0x031f)
- code = keytable[code - 0x0300];
+ code = keycode[code - 0x0300];
else if (code >= 0x0340 && code <= 0x0354)
- code = keytable[code - 0x0320];
+ code = keycode[code - 0x0320];
else if (code >= 0x4501 && code <= 0x451f)
code = oldtable[code - 0x4501];
else if (code >= 0x4540 && code <= 0x4542)
@@ -170,6 +186,6 @@ void firesat_handle_rc(unsigned int code
return;
}

- input_report_key(idev, code, 1);
- input_report_key(idev, code, 0);
+ input_report_key(firesat->remote_ctrl_dev, code, 1);
+ input_report_key(firesat->remote_ctrl_dev, code, 0);
}
Index: linux/drivers/media/dvb/firesat/firesat-rc.h
===================================================================
--- linux.orig/drivers/media/dvb/firesat/firesat-rc.h
+++ linux/drivers/media/dvb/firesat/firesat-rc.h
@@ -1,8 +1,11 @@
#ifndef _FIREDTV_RC_H
#define _FIREDTV_RC_H

-int firesat_register_rc(void);
-void firesat_unregister_rc(void);
-void firesat_handle_rc(unsigned int code);
+struct firesat;
+struct device;
+
+int firesat_register_rc(struct firesat *firesat, struct device *dev);
+void firesat_unregister_rc(struct firesat *firesat);
+void firesat_handle_rc(struct firesat *firesat, unsigned int code);

#endif /* _FIREDTV_RC_H */
Index: linux/drivers/media/dvb/firesat/firesat.h
===================================================================
--- linux.orig/drivers/media/dvb/firesat/firesat.h
+++ linux/drivers/media/dvb/firesat/firesat.h
@@ -127,7 +127,7 @@ enum model_type {
FireSAT_DVB_S2 = 4,
};

-struct hpsb_host;
+struct input_dev;
struct hpsb_iso;
struct unit_directory;

@@ -147,12 +147,13 @@ struct firesat {
wait_queue_head_t avc_wait;
bool avc_reply_received;
struct work_struct remote_ctrl_work;
+ struct input_dev *remote_ctrl_dev;

struct firesat_channel {
bool active;
int pid;
} channel[16];
- struct mutex demux_mutex;
+ struct mutex demux_mutex;

struct unit_directory *ud;

Index: linux/drivers/media/dvb/firesat/firesat_1394.c
===================================================================
--- linux.orig/drivers/media/dvb/firesat/firesat_1394.c
+++ linux/drivers/media/dvb/firesat/firesat_1394.c
@@ -176,6 +176,14 @@ static int firesat_probe(struct device *
break;
firesat->type = i;

+ /*
+ * Work around a bug in udev's path_id script: Use the fw-host's dev
+ * instead of the unit directory's dev as parent of the input device.
+ */
+ err = firesat_register_rc(firesat, dev->parent->parent);
+ if (err)
+ goto fail_free;
+
INIT_LIST_HEAD(&firesat->list);
spin_lock_irqsave(&firesat_list_lock, flags);
list_add_tail(&firesat->list, &firesat_list);
@@ -196,6 +204,8 @@ fail:
spin_lock_irqsave(&firesat_list_lock, flags);
list_del(&firesat->list);
spin_unlock_irqrestore(&firesat_list_lock, flags);
+ firesat_unregister_rc(firesat);
+fail_free:
kfree(firesat);
return err;
}
@@ -220,6 +230,7 @@ static int firesat_remove(struct device
spin_unlock_irqrestore(&firesat_list_lock, flags);

cancel_work_sync(&firesat->remote_ctrl_work);
+ firesat_unregister_rc(firesat);

kfree(firesat);
return 0;
@@ -263,26 +274,13 @@ static int __init firesat_init(void)
ret = hpsb_register_protocol(&firesat_driver);
if (ret) {
printk(KERN_ERR "firedtv: failed to register protocol\n");
- goto fail;
- }
-
- ret = firesat_register_rc();
- if (ret) {
- printk(KERN_ERR "firedtv: failed to register input device\n");
- goto fail_rc;
+ hpsb_unregister_highlevel(&firesat_highlevel);
}
-
- return 0;
-fail_rc:
- hpsb_unregister_protocol(&firesat_driver);
-fail:
- hpsb_unregister_highlevel(&firesat_highlevel);
return ret;
}

static void __exit firesat_exit(void)
{
- firesat_unregister_rc();
hpsb_unregister_protocol(&firesat_driver);
hpsb_unregister_highlevel(&firesat_highlevel);
}

--
Stefan Richter
-=====-==--- =--= ===-=
http://arcgraph.de/sr/

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/devel

Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]

Messages in current thread:
Gettinng started with Linux drivers, Amit Uttamchandani, (Fri Apr 10, 6:04 pm)
broken mailing list, try 47..., Greg KH, (Fri Jan 11, 3:12 pm)
Mailing Lists, Tomasz Grzegurzko, (Fri Feb 8, 8:22 pm)
what is the status of this initiative ?, JoJo jojo, (Thu Mar 13, 3:20 am)
A tablet driver question, Steven Hunt, (Wed May 20, 12:49 am)
Dearest Beloved,, Mr. Kunio Uematsu, (Tue Mar 16, 3:52 pm)
[patch 00/10] firedtv: a few more updates, Stefan Richter, (Mon Sep 29, 1:15 pm)
Re: A tablet driver question, Greg KH, (Wed May 20, 1:12 am)
Re: A tablet driver question, Steven Hunt, (Wed May 20, 2:16 am)
Re: A tablet driver question, Jiri Slaby, (Wed May 20, 3:19 am)
Re: A tablet driver question, Steven Hunt, (Wed May 20, 11:58 am)
Re: A tablet driver question, Jiri Slaby, (Wed May 20, 12:24 pm)
Re: A tablet driver question, Mohamed Ikbel Boulabiar, (Wed May 20, 12:50 pm)
Re: A tablet driver question, Jiri Kosina, (Thu May 21, 4:33 am)
Re: Gettinng started with Linux drivers, Stefan Richter, (Sat Apr 11, 6:00 am)
Re: Gettinng started with Linux drivers, Amit Uttamchandani, (Sun Apr 12, 9:08 pm)
Re: Gettinng started with Linux drivers, Stefan Richter, (Mon Apr 13, 3:39 am)
Re: [patch 00/10] firedtv: a few more updates, Stefan Richter, (Mon Sep 29, 1:46 pm)
[patch 10/10] firedtv: register input device as child of a F..., Stefan Richter, (Mon Sep 29, 1:22 pm)
[patch 08/10] firedtv: remove unused struct members, Stefan Richter, (Mon Sep 29, 1:21 pm)
Re: what is the status of this initiative ?, Greg KH, (Thu Mar 13, 10:51 am)
Re: what is the status of this initiative ?, Javi Roman, (Thu Mar 13, 1:13 pm)
Re: what is the status of this initiative ?, Greg KH, (Thu Mar 13, 1:36 pm)
Re: what is the status of this initiative ?, Davide Madrisan, (Thu Mar 13, 1:30 pm)
Re: broken mailing list, try 47..., Steven Le Roux, (Sat Jan 12, 2:10 pm)
Re: broken mailing list, try 47..., stuart, (Sat Jan 12, 6:56 pm)
Kick off the Linux Driver Project (again, this time for real), Peter W. Morreale, (Thu Sep 27, 9:21 am)
Kick off the Linux Driver Project (again, this time for real), Peter W. Morreale, (Thu Sep 27, 9:55 am)
Kick off the Linux Driver Project (again, this time for real), Peter W. Morreale, (Thu Sep 27, 10:58 am)
Kick off the Linux Driver Project (again, this time for real), Tomasz Grzegurzko, (Thu Sep 27, 9:40 pm)