aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@gmail.com>2013-05-05 17:13:01 -0400
committerJiri Kosina <jkosina@suse.cz>2013-06-03 05:07:04 -0400
commit34472d370f698f891b92eed879c87a2a82eaaace (patch)
treea01d8c4d2df3ae7c58dccd2bd2219e7cb20224cb /drivers/hid
parent9d6f9ecb0cbf714f39c0ae492fe8678bcb93a001 (diff)
HID: wiimote: add Motion Plus extension module
Add parsers for motion plus data so we can hotplug motion plus extensions and make use of them. This is mostly the same as the old static motion plus parser. Signed-off-by: David Herrmann <dh.herrmann@gmail.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid')
-rw-r--r--drivers/hid/hid-wiimote-modules.c144
-rw-r--r--drivers/hid/hid-wiimote.h1
2 files changed, 145 insertions, 0 deletions
diff --git a/drivers/hid/hid-wiimote-modules.c b/drivers/hid/hid-wiimote-modules.c
index daeb679f98ff..aee1b2caae13 100644
--- a/drivers/hid/hid-wiimote-modules.c
+++ b/drivers/hid/hid-wiimote-modules.c
@@ -1475,11 +1475,155 @@ static const struct wiimod_ops wiimod_bboard = {
1475 1475
1476/* 1476/*
1477 * Motion Plus 1477 * Motion Plus
1478 * The Motion Plus extension provides rotation sensors (gyro) as a small
1479 * extension device for Wii Remotes. Many devices have them built-in so
1480 * you cannot see them from the outside.
1481 * Motion Plus extensions are special because they are on a separate extension
1482 * port and allow other extensions to be used simultaneously. This is all
1483 * handled by the Wiimote Core so we don't have to deal with it.
1478 */ 1484 */
1479 1485
1486static void wiimod_mp_in_mp(struct wiimote_data *wdata, const __u8 *ext)
1487{
1488 __s32 x, y, z;
1489
1490 /* | 8 7 6 5 4 3 | 2 | 1 |
1491 * -----+------------------------------+-----+-----+
1492 * 1 | Yaw Speed <7:0> |
1493 * 2 | Roll Speed <7:0> |
1494 * 3 | Pitch Speed <7:0> |
1495 * -----+------------------------------+-----+-----+
1496 * 4 | Yaw Speed <13:8> | Yaw |Pitch|
1497 * -----+------------------------------+-----+-----+
1498 * 5 | Roll Speed <13:8> |Roll | Ext |
1499 * -----+------------------------------+-----+-----+
1500 * 6 | Pitch Speed <13:8> | 1 | 0 |
1501 * -----+------------------------------+-----+-----+
1502 * The single bits Yaw, Roll, Pitch in the lower right corner specify
1503 * whether the wiimote is rotating fast (0) or slow (1). Speed for slow
1504 * roation is 440 deg/s and for fast rotation 2000 deg/s. To get a
1505 * linear scale we multiply by 2000/440 = ~4.5454 which is 18 for fast
1506 * and 9 for slow.
1507 * If the wiimote is not rotating the sensor reports 2^13 = 8192.
1508 * Ext specifies whether an extension is connected to the motionp.
1509 * which is parsed by wiimote-core.
1510 */
1511
1512 x = ext[0];
1513 y = ext[1];
1514 z = ext[2];
1515
1516 x |= (((__u16)ext[3]) << 6) & 0xff00;
1517 y |= (((__u16)ext[4]) << 6) & 0xff00;
1518 z |= (((__u16)ext[5]) << 6) & 0xff00;
1519
1520 x -= 8192;
1521 y -= 8192;
1522 z -= 8192;
1523
1524 if (!(ext[3] & 0x02))
1525 x *= 18;
1526 else
1527 x *= 9;
1528 if (!(ext[4] & 0x02))
1529 y *= 18;
1530 else
1531 y *= 9;
1532 if (!(ext[3] & 0x01))
1533 z *= 18;
1534 else
1535 z *= 9;
1536
1537 input_report_abs(wdata->mp, ABS_RX, x);
1538 input_report_abs(wdata->mp, ABS_RY, y);
1539 input_report_abs(wdata->mp, ABS_RZ, z);
1540 input_sync(wdata->mp);
1541}
1542
1543static int wiimod_mp_open(struct input_dev *dev)
1544{
1545 struct wiimote_data *wdata = input_get_drvdata(dev);
1546 unsigned long flags;
1547
1548 spin_lock_irqsave(&wdata->state.lock, flags);
1549 wdata->state.flags |= WIIPROTO_FLAG_MP_USED;
1550 wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
1551 __wiimote_schedule(wdata);
1552 spin_unlock_irqrestore(&wdata->state.lock, flags);
1553
1554 return 0;
1555}
1556
1557static void wiimod_mp_close(struct input_dev *dev)
1558{
1559 struct wiimote_data *wdata = input_get_drvdata(dev);
1560 unsigned long flags;
1561
1562 spin_lock_irqsave(&wdata->state.lock, flags);
1563 wdata->state.flags &= ~WIIPROTO_FLAG_MP_USED;
1564 wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
1565 __wiimote_schedule(wdata);
1566 spin_unlock_irqrestore(&wdata->state.lock, flags);
1567}
1568
1569static int wiimod_mp_probe(const struct wiimod_ops *ops,
1570 struct wiimote_data *wdata)
1571{
1572 int ret;
1573
1574 wdata->mp = input_allocate_device();
1575 if (!wdata->mp)
1576 return -ENOMEM;
1577
1578 input_set_drvdata(wdata->mp, wdata);
1579 wdata->mp->open = wiimod_mp_open;
1580 wdata->mp->close = wiimod_mp_close;
1581 wdata->mp->dev.parent = &wdata->hdev->dev;
1582 wdata->mp->id.bustype = wdata->hdev->bus;
1583 wdata->mp->id.vendor = wdata->hdev->vendor;
1584 wdata->mp->id.product = wdata->hdev->product;
1585 wdata->mp->id.version = wdata->hdev->version;
1586 wdata->mp->name = WIIMOTE_NAME " Motion Plus";
1587
1588 set_bit(EV_ABS, wdata->mp->evbit);
1589 set_bit(ABS_RX, wdata->mp->absbit);
1590 set_bit(ABS_RY, wdata->mp->absbit);
1591 set_bit(ABS_RZ, wdata->mp->absbit);
1592 input_set_abs_params(wdata->mp,
1593 ABS_RX, -16000, 16000, 4, 8);
1594 input_set_abs_params(wdata->mp,
1595 ABS_RY, -16000, 16000, 4, 8);
1596 input_set_abs_params(wdata->mp,
1597 ABS_RZ, -16000, 16000, 4, 8);
1598
1599 ret = input_register_device(wdata->mp);
1600 if (ret)
1601 goto err_free;
1602
1603 return 0;
1604
1605err_free:
1606 input_free_device(wdata->mp);
1607 wdata->mp = NULL;
1608 return ret;
1609}
1610
1611static void wiimod_mp_remove(const struct wiimod_ops *ops,
1612 struct wiimote_data *wdata)
1613{
1614 if (!wdata->mp)
1615 return;
1616
1617 input_unregister_device(wdata->mp);
1618 wdata->mp = NULL;
1619}
1620
1480const struct wiimod_ops wiimod_mp = { 1621const struct wiimod_ops wiimod_mp = {
1481 .flags = 0, 1622 .flags = 0,
1482 .arg = 0, 1623 .arg = 0,
1624 .probe = wiimod_mp_probe,
1625 .remove = wiimod_mp_remove,
1626 .in_mp = wiimod_mp_in_mp,
1483}; 1627};
1484 1628
1485/* module table */ 1629/* module table */
diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h
index 118520a79211..3a8bdb94152a 100644
--- a/drivers/hid/hid-wiimote.h
+++ b/drivers/hid/hid-wiimote.h
@@ -139,6 +139,7 @@ struct wiimote_data {
139 struct input_dev *accel; 139 struct input_dev *accel;
140 struct input_dev *ir; 140 struct input_dev *ir;
141 struct power_supply battery; 141 struct power_supply battery;
142 struct input_dev *mp;
142 struct timer_list timer; 143 struct timer_list timer;
143 struct wiimote_ext *ext; 144 struct wiimote_ext *ext;
144 struct wiimote_debug *debug; 145 struct wiimote_debug *debug;