Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

David Herrmann and committed by
Jiri Kosina
34472d37 9d6f9ecb

+145
+144
drivers/hid/hid-wiimote-modules.c
··· 1475 1475 1476 1476 /* 1477 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 */ 1485 + 1486 + static 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 + 1543 + static 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 + 1557 + static 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 + 1569 + static 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 + 1605 + err_free: 1606 + input_free_device(wdata->mp); 1607 + wdata->mp = NULL; 1608 + return ret; 1609 + } 1610 + 1611 + static 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 + } 1479 1620 1480 1621 const struct wiimod_ops wiimod_mp = { 1481 1622 .flags = 0, 1482 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 1629 /* module table */
+1
drivers/hid/hid-wiimote.h
··· 139 139 struct input_dev *accel; 140 140 struct input_dev *ir; 141 141 struct power_supply battery; 142 + struct input_dev *mp; 142 143 struct timer_list timer; 143 144 struct wiimote_ext *ext; 144 145 struct wiimote_debug *debug;