Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 264747
b: refs/heads/master
c: 98a558a
h: refs/heads/master
i:
  264745: 496ce29
  264743: f729bef
v: v3
  • Loading branch information
David Herrmann authored and Jiri Kosina committed Sep 7, 2011
1 parent f922920 commit e06abb2
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 11 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: d020be9246735ff1fc49b99bea0574a597592709
refs/heads/master: 98a558ae35930e02dfc2dd0a124c93ad39b0828d
99 changes: 89 additions & 10 deletions trunk/drivers/hid/hid-wiimote.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ struct wiimote_data {
struct hid_device *hdev;
struct input_dev *input;
struct led_classdev *leds[4];
struct input_dev *accel;

spinlock_t qlock;
__u8 head;
Expand All @@ -51,6 +52,7 @@ struct wiimote_data {
#define WIIPROTO_FLAG_LED3 0x04
#define WIIPROTO_FLAG_LED4 0x08
#define WIIPROTO_FLAG_RUMBLE 0x10
#define WIIPROTO_FLAG_ACCEL 0x20
#define WIIPROTO_FLAGS_LEDS (WIIPROTO_FLAG_LED1 | WIIPROTO_FLAG_LED2 | \
WIIPROTO_FLAG_LED3 | WIIPROTO_FLAG_LED4)

Expand Down Expand Up @@ -257,6 +259,20 @@ static void wiiproto_req_drm(struct wiimote_data *wdata, __u8 drm)
wiimote_queue(wdata, cmd, sizeof(cmd));
}

static void wiiproto_req_accel(struct wiimote_data *wdata, __u8 accel)
{
accel = !!accel;
if (accel == !!(wdata->state.flags & WIIPROTO_FLAG_ACCEL))
return;

if (accel)
wdata->state.flags |= WIIPROTO_FLAG_ACCEL;
else
wdata->state.flags &= ~WIIPROTO_FLAG_ACCEL;

wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
}

static enum led_brightness wiimote_leds_get(struct led_classdev *led_dev)
{
struct wiimote_data *wdata;
Expand Down Expand Up @@ -344,6 +360,35 @@ static void wiimote_input_close(struct input_dev *dev)
hid_hw_close(wdata->hdev);
}

static int wiimote_accel_open(struct input_dev *dev)
{
struct wiimote_data *wdata = input_get_drvdata(dev);
int ret;
unsigned long flags;

ret = hid_hw_open(wdata->hdev);
if (ret)
return ret;

spin_lock_irqsave(&wdata->state.lock, flags);
wiiproto_req_accel(wdata, true);
spin_unlock_irqrestore(&wdata->state.lock, flags);

return 0;
}

static void wiimote_accel_close(struct input_dev *dev)
{
struct wiimote_data *wdata = input_get_drvdata(dev);
unsigned long flags;

spin_lock_irqsave(&wdata->state.lock, flags);
wiiproto_req_accel(wdata, false);
spin_unlock_irqrestore(&wdata->state.lock, flags);

hid_hw_close(wdata->hdev);
}

static void handler_keys(struct wiimote_data *wdata, const __u8 *payload)
{
input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_LEFT],
Expand Down Expand Up @@ -490,10 +535,8 @@ static struct wiimote_data *wiimote_create(struct hid_device *hdev)
return NULL;

wdata->input = input_allocate_device();
if (!wdata->input) {
kfree(wdata);
return NULL;
}
if (!wdata->input)
goto err;

wdata->hdev = hdev;
hid_set_drvdata(hdev, wdata);
Expand All @@ -513,24 +556,50 @@ static struct wiimote_data *wiimote_create(struct hid_device *hdev)
set_bit(wiiproto_keymap[i], wdata->input->keybit);

set_bit(FF_RUMBLE, wdata->input->ffbit);
if (input_ff_create_memless(wdata->input, NULL, wiimote_ff_play)) {
input_free_device(wdata->input);
kfree(wdata);
return NULL;
}
if (input_ff_create_memless(wdata->input, NULL, wiimote_ff_play))
goto err_input;

wdata->accel = input_allocate_device();
if (!wdata->accel)
goto err_input;

input_set_drvdata(wdata->accel, wdata);
wdata->accel->open = wiimote_accel_open;
wdata->accel->close = wiimote_accel_close;
wdata->accel->dev.parent = &wdata->hdev->dev;
wdata->accel->id.bustype = wdata->hdev->bus;
wdata->accel->id.vendor = wdata->hdev->vendor;
wdata->accel->id.product = wdata->hdev->product;
wdata->accel->id.version = wdata->hdev->version;
wdata->accel->name = WIIMOTE_NAME " Accelerometer";

set_bit(EV_ABS, wdata->accel->evbit);
set_bit(ABS_RX, wdata->accel->absbit);
set_bit(ABS_RY, wdata->accel->absbit);
set_bit(ABS_RZ, wdata->accel->absbit);
input_set_abs_params(wdata->accel, ABS_RX, -500, 500, 2, 4);
input_set_abs_params(wdata->accel, ABS_RY, -500, 500, 2, 4);
input_set_abs_params(wdata->accel, ABS_RZ, -500, 500, 2, 4);

spin_lock_init(&wdata->qlock);
INIT_WORK(&wdata->worker, wiimote_worker);

spin_lock_init(&wdata->state.lock);

return wdata;

err_input:
input_free_device(wdata->input);
err:
kfree(wdata);
return NULL;
}

static void wiimote_destroy(struct wiimote_data *wdata)
{
wiimote_leds_destroy(wdata);

input_unregister_device(wdata->accel);
input_unregister_device(wdata->input);
cancel_work_sync(&wdata->worker);
hid_hw_stop(wdata->hdev);
Expand Down Expand Up @@ -562,12 +631,18 @@ static int wiimote_hid_probe(struct hid_device *hdev,
goto err;
}

ret = input_register_device(wdata->input);
ret = input_register_device(wdata->accel);
if (ret) {
hid_err(hdev, "Cannot register input device\n");
goto err_stop;
}

ret = input_register_device(wdata->input);
if (ret) {
hid_err(hdev, "Cannot register input device\n");
goto err_input;
}

ret = wiimote_leds_create(wdata);
if (ret)
goto err_free;
Expand All @@ -585,9 +660,13 @@ static int wiimote_hid_probe(struct hid_device *hdev,
wiimote_destroy(wdata);
return ret;

err_input:
input_unregister_device(wdata->accel);
wdata->accel = NULL;
err_stop:
hid_hw_stop(hdev);
err:
input_free_device(wdata->accel);
input_free_device(wdata->input);
kfree(wdata);
return ret;
Expand Down

0 comments on commit e06abb2

Please sign in to comment.