提交 479901ba 编写于 作者: D David Herrmann 提交者: Jiri Kosina

HID: wiimote: Register input devices for extensions

Motion+ and regular extensions are physical adapters for the wiimote so create
one input device for each of them. This also allows to enable only opened
extensions and turn unused extenions off to save battery power.
Signed-off-by: NDavid Herrmann <dh.herrmann@googlemail.com>
Signed-off-by: NJiri Kosina <jkosina@suse.cz>
上级 c1e51398
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
struct wiimote_ext { struct wiimote_ext {
struct wiimote_data *wdata; struct wiimote_data *wdata;
struct work_struct worker; struct work_struct worker;
struct input_dev *input;
struct input_dev *mp_input;
atomic_t opened; atomic_t opened;
atomic_t mp_opened; atomic_t mp_opened;
...@@ -57,6 +59,9 @@ static bool motionp_read(struct wiimote_ext *ext) ...@@ -57,6 +59,9 @@ static bool motionp_read(struct wiimote_ext *ext)
ssize_t ret; ssize_t ret;
bool avail = false; bool avail = false;
if (!atomic_read(&ext->mp_opened))
return false;
if (wiimote_cmd_acquire(ext->wdata)) if (wiimote_cmd_acquire(ext->wdata))
return false; return false;
...@@ -82,7 +87,7 @@ static __u8 ext_read(struct wiimote_ext *ext) ...@@ -82,7 +87,7 @@ static __u8 ext_read(struct wiimote_ext *ext)
__u8 rmem[2], wmem; __u8 rmem[2], wmem;
__u8 type = WIIEXT_NONE; __u8 type = WIIEXT_NONE;
if (!ext->plugged) if (!ext->plugged || !atomic_read(&ext->opened))
return WIIEXT_NONE; return WIIEXT_NONE;
if (wiimote_cmd_acquire(ext->wdata)) if (wiimote_cmd_acquire(ext->wdata))
...@@ -234,6 +239,54 @@ static ssize_t wiiext_show(struct device *dev, struct device_attribute *attr, ...@@ -234,6 +239,54 @@ static ssize_t wiiext_show(struct device *dev, struct device_attribute *attr,
static DEVICE_ATTR(extension, S_IRUGO, wiiext_show, NULL); static DEVICE_ATTR(extension, S_IRUGO, wiiext_show, NULL);
static int wiiext_input_open(struct input_dev *dev)
{
struct wiimote_ext *ext = input_get_drvdata(dev);
int ret;
ret = hid_hw_open(ext->wdata->hdev);
if (ret)
return ret;
atomic_inc(&ext->opened);
wiiext_schedule(ext);
return 0;
}
static void wiiext_input_close(struct input_dev *dev)
{
struct wiimote_ext *ext = input_get_drvdata(dev);
atomic_dec(&ext->opened);
wiiext_schedule(ext);
hid_hw_close(ext->wdata->hdev);
}
static int wiiext_mp_open(struct input_dev *dev)
{
struct wiimote_ext *ext = input_get_drvdata(dev);
int ret;
ret = hid_hw_open(ext->wdata->hdev);
if (ret)
return ret;
atomic_inc(&ext->mp_opened);
wiiext_schedule(ext);
return 0;
}
static void wiiext_mp_close(struct input_dev *dev)
{
struct wiimote_ext *ext = input_get_drvdata(dev);
atomic_dec(&ext->mp_opened);
wiiext_schedule(ext);
hid_hw_close(ext->wdata->hdev);
}
/* Initializes the extension driver of a wiimote */ /* Initializes the extension driver of a wiimote */
int wiiext_init(struct wiimote_data *wdata) int wiiext_init(struct wiimote_data *wdata)
{ {
...@@ -248,9 +301,53 @@ int wiiext_init(struct wiimote_data *wdata) ...@@ -248,9 +301,53 @@ int wiiext_init(struct wiimote_data *wdata)
ext->wdata = wdata; ext->wdata = wdata;
INIT_WORK(&ext->worker, wiiext_worker); INIT_WORK(&ext->worker, wiiext_worker);
ext->input = input_allocate_device();
if (!ext->input) {
ret = -ENOMEM;
goto err_input;
}
input_set_drvdata(ext->input, ext);
ext->input->open = wiiext_input_open;
ext->input->close = wiiext_input_close;
ext->input->dev.parent = &wdata->hdev->dev;
ext->input->id.bustype = wdata->hdev->bus;
ext->input->id.vendor = wdata->hdev->vendor;
ext->input->id.product = wdata->hdev->product;
ext->input->id.version = wdata->hdev->version;
ext->input->name = WIIMOTE_NAME " Extension";
ret = input_register_device(ext->input);
if (ret) {
input_free_device(ext->input);
goto err_input;
}
ext->mp_input = input_allocate_device();
if (!ext->mp_input) {
ret = -ENOMEM;
goto err_mp;
}
input_set_drvdata(ext->mp_input, ext);
ext->mp_input->open = wiiext_mp_open;
ext->mp_input->close = wiiext_mp_close;
ext->mp_input->dev.parent = &wdata->hdev->dev;
ext->mp_input->id.bustype = wdata->hdev->bus;
ext->mp_input->id.vendor = wdata->hdev->vendor;
ext->mp_input->id.product = wdata->hdev->product;
ext->mp_input->id.version = wdata->hdev->version;
ext->mp_input->name = WIIMOTE_NAME " Motion+";
ret = input_register_device(ext->mp_input);
if (ret) {
input_free_device(ext->mp_input);
goto err_mp;
}
ret = device_create_file(&wdata->hdev->dev, &dev_attr_extension); ret = device_create_file(&wdata->hdev->dev, &dev_attr_extension);
if (ret) if (ret)
goto err; goto err_dev;
spin_lock_irqsave(&wdata->state.lock, flags); spin_lock_irqsave(&wdata->state.lock, flags);
wdata->ext = ext; wdata->ext = ext;
...@@ -258,7 +355,11 @@ int wiiext_init(struct wiimote_data *wdata) ...@@ -258,7 +355,11 @@ int wiiext_init(struct wiimote_data *wdata)
return 0; return 0;
err: err_dev:
input_unregister_device(ext->mp_input);
err_mp:
input_unregister_device(ext->input);
err_input:
kfree(ext); kfree(ext);
return ret; return ret;
} }
...@@ -285,6 +386,8 @@ void wiiext_deinit(struct wiimote_data *wdata) ...@@ -285,6 +386,8 @@ void wiiext_deinit(struct wiimote_data *wdata)
spin_unlock_irqrestore(&wdata->state.lock, flags); spin_unlock_irqrestore(&wdata->state.lock, flags);
device_remove_file(&wdata->hdev->dev, &dev_attr_extension); device_remove_file(&wdata->hdev->dev, &dev_attr_extension);
input_unregister_device(ext->mp_input);
input_unregister_device(ext->input);
cancel_work_sync(&ext->worker); cancel_work_sync(&ext->worker);
kfree(ext); kfree(ext);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册