Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 250310
b: refs/heads/master
c: 08aeb7c
h: refs/heads/master
v: v3
  • Loading branch information
Jarod Wilson authored and Mauro Carvalho Chehab committed May 20, 2011
1 parent 99db140 commit 9c8d789
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 9 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 51ea62927e5bbb577360dd92c3f282edbf4cd3f8
refs/heads/master: 08aeb7c9a42ab7aa8b53c8f7779ec58f860a565c
47 changes: 41 additions & 6 deletions trunk/drivers/media/rc/rc-main.c
Original file line number Diff line number Diff line change
Expand Up @@ -749,6 +749,9 @@ static struct {
* it is trigged by reading /sys/class/rc/rc?/protocols.
* It returns the protocol names of supported protocols.
* Enabled protocols are printed in brackets.
*
* dev->lock is taken to guard against races between device
* registration, store_protocols and show_protocols.
*/
static ssize_t show_protocols(struct device *device,
struct device_attribute *mattr, char *buf)
Expand All @@ -762,6 +765,8 @@ static ssize_t show_protocols(struct device *device,
if (!dev)
return -EINVAL;

mutex_lock(&dev->lock);

if (dev->driver_type == RC_DRIVER_SCANCODE) {
enabled = dev->rc_map.rc_type;
allowed = dev->allowed_protos;
Expand All @@ -784,6 +789,9 @@ static ssize_t show_protocols(struct device *device,
if (tmp != buf)
tmp--;
*tmp = '\n';

mutex_unlock(&dev->lock);

return tmp + 1 - buf;
}

Expand All @@ -802,6 +810,9 @@ static ssize_t show_protocols(struct device *device,
* Writing "none" will disable all protocols.
* Returns -EINVAL if an invalid protocol combination or unknown protocol name
* is used, otherwise @len.
*
* dev->lock is taken to guard against races between device
* registration, store_protocols and show_protocols.
*/
static ssize_t store_protocols(struct device *device,
struct device_attribute *mattr,
Expand All @@ -815,18 +826,22 @@ static ssize_t store_protocols(struct device *device,
u64 mask;
int rc, i, count = 0;
unsigned long flags;
ssize_t ret;

/* Device is being removed */
if (!dev)
return -EINVAL;

mutex_lock(&dev->lock);

if (dev->driver_type == RC_DRIVER_SCANCODE)
type = dev->rc_map.rc_type;
else if (dev->raw)
type = dev->raw->enabled_protocols;
else {
IR_dprintk(1, "Protocol switching not supported\n");
return -EINVAL;
ret = -EINVAL;
goto out;
}

while ((tmp = strsep((char **) &data, " \n")) != NULL) {
Expand Down Expand Up @@ -860,7 +875,8 @@ static ssize_t store_protocols(struct device *device,
}
if (i == ARRAY_SIZE(proto_names)) {
IR_dprintk(1, "Unknown protocol: '%s'\n", tmp);
return -EINVAL;
ret = -EINVAL;
goto out;
}
count++;
}
Expand All @@ -875,15 +891,17 @@ static ssize_t store_protocols(struct device *device,

if (!count) {
IR_dprintk(1, "Protocol not specified\n");
return -EINVAL;
ret = -EINVAL;
goto out;
}

if (dev->change_protocol) {
rc = dev->change_protocol(dev, type);
if (rc < 0) {
IR_dprintk(1, "Error setting protocols to 0x%llx\n",
(long long)type);
return -EINVAL;
ret = -EINVAL;
goto out;
}
}

Expand All @@ -898,7 +916,11 @@ static ssize_t store_protocols(struct device *device,
IR_dprintk(1, "Current protocol(s): 0x%llx\n",
(long long)type);

return len;
ret = len;

out:
mutex_unlock(&dev->lock);
return ret;
}

static void rc_dev_release(struct device *device)
Expand Down Expand Up @@ -974,6 +996,7 @@ struct rc_dev *rc_allocate_device(void)

spin_lock_init(&dev->rc_map.lock);
spin_lock_init(&dev->keylock);
mutex_init(&dev->lock);
setup_timer(&dev->timer_keyup, ir_timer_keyup, (unsigned long)dev);

dev->dev.type = &rc_dev_type;
Expand Down Expand Up @@ -1019,12 +1042,21 @@ int rc_register_device(struct rc_dev *dev)
if (dev->close)
dev->input_dev->close = ir_close;

/*
* Take the lock here, as the device sysfs node will appear
* when device_add() is called, which may trigger an ir-keytable udev
* rule, which will in turn call show_protocols and access either
* dev->rc_map.rc_type or dev->raw->enabled_protocols before it has
* been initialized.
*/
mutex_lock(&dev->lock);

dev->devno = (unsigned long)(atomic_inc_return(&devno) - 1);
dev_set_name(&dev->dev, "rc%ld", dev->devno);
dev_set_drvdata(&dev->dev, dev);
rc = device_add(&dev->dev);
if (rc)
return rc;
goto out_unlock;

rc = ir_setkeytable(dev, rc_map);
if (rc)
Expand Down Expand Up @@ -1058,6 +1090,7 @@ int rc_register_device(struct rc_dev *dev)
if (rc < 0)
goto out_input;
}
mutex_unlock(&dev->lock);

if (dev->change_protocol) {
rc = dev->change_protocol(dev, rc_map->rc_type);
Expand All @@ -1083,6 +1116,8 @@ int rc_register_device(struct rc_dev *dev)
ir_free_table(&dev->rc_map);
out_dev:
device_del(&dev->dev);
out_unlock:
mutex_unlock(&dev->lock);
return rc;
}
EXPORT_SYMBOL_GPL(rc_register_device);
Expand Down
7 changes: 5 additions & 2 deletions trunk/include/media/rc-core.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,12 @@ enum rc_driver_type {
* @driver_name: name of the hardware driver which registered this device
* @map_name: name of the default keymap
* @rc_map: current scan/key table
* @lock: used to ensure we've filled in all protocol details before
* anyone can call show_protocols or store_protocols
* @devno: unique remote control device number
* @raw: additional data for raw pulse/space devices
* @input_dev: the input child device used to communicate events to userspace
* @driver_type: specifies if protocol decoding is done in hardware or software
* @driver_type: specifies if protocol decoding is done in hardware or software
* @idle: used to keep track of RX state
* @allowed_protos: bitmask with the supported RC_TYPE_* protocols
* @scanmask: some hardware decoders are not capable of providing the full
Expand Down Expand Up @@ -86,7 +88,8 @@ struct rc_dev {
struct input_id input_id;
char *driver_name;
const char *map_name;
struct rc_map rc_map;
struct rc_map rc_map;
struct mutex lock;
unsigned long devno;
struct ir_raw_event_ctrl *raw;
struct input_dev *input_dev;
Expand Down

0 comments on commit 9c8d789

Please sign in to comment.