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

HID: wiimote: add "bboard_calib" attribute

Balance-Boards provide 3 16bit calibration values for each of the 4
sensors. We provide these now as 192bit value via a new "bboard_calib"
sysfs attribute.
We also re-read the calibration data from the device whenever user-space
attempts to read this file. On normal Nintendo boards, this always
produces the same results, however, on some 3rd party devices these values
change until the device is fully initialized. As I have currently no idea
how long to wait until it's ready (sometimes takes up to 10s?) we provide
a simple workaround for users by reading this file.

If we, at some point, figure out how it works, we can implement it in the
kernel and provide offline data via "bboard_calib". This won't break
user-space then.

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
8b1fded7 c7da0867

+82 -1
+15
Documentation/ABI/testing/sysfs-driver-hid-wiimote
··· 42 42 gen10: First Wii Remote generation 43 43 gen20: Second Wii Remote Plus generation (builtin MP) 44 44 balanceboard: Wii Balance Board 45 + 46 + What: /sys/bus/hid/drivers/wiimote/<dev>/bboard_calib 47 + Date: May 2013 48 + KernelVersion: 3.11 49 + Contact: David Herrmann <dh.herrmann@gmail.com> 50 + Description: This attribute is only provided if the device was detected as a 51 + balance board. It provides a single line with 3 calibration 52 + values for all 4 sensors. The values are separated by colons and 53 + are each 2 bytes long (encoded as 4 digit hexadecimal value). 54 + First, 0kg values for all 4 sensors are written, followed by the 55 + 17kg values for all 4 sensors and last the 34kg values for all 4 56 + sensors. 57 + Calibration data is already applied by the kernel to all input 58 + values but may be used by user-space to perform other 59 + transformations.
+67 -1
drivers/hid/hid-wiimote-modules.c
··· 1380 1380 spin_unlock_irqrestore(&wdata->state.lock, flags); 1381 1381 } 1382 1382 1383 + static ssize_t wiimod_bboard_calib_show(struct device *dev, 1384 + struct device_attribute *attr, 1385 + char *out) 1386 + { 1387 + struct wiimote_data *wdata = dev_to_wii(dev); 1388 + int i, j, ret; 1389 + __u16 val; 1390 + __u8 buf[24], offs; 1391 + 1392 + ret = wiimote_cmd_acquire(wdata); 1393 + if (ret) 1394 + return ret; 1395 + 1396 + ret = wiimote_cmd_read(wdata, 0xa40024, buf, 12); 1397 + if (ret != 12) { 1398 + wiimote_cmd_release(wdata); 1399 + return ret < 0 ? ret : -EIO; 1400 + } 1401 + ret = wiimote_cmd_read(wdata, 0xa40024 + 12, buf + 12, 12); 1402 + if (ret != 12) { 1403 + wiimote_cmd_release(wdata); 1404 + return ret < 0 ? ret : -EIO; 1405 + } 1406 + 1407 + wiimote_cmd_release(wdata); 1408 + 1409 + spin_lock_irq(&wdata->state.lock); 1410 + offs = 0; 1411 + for (i = 0; i < 3; ++i) { 1412 + for (j = 0; j < 4; ++j) { 1413 + wdata->state.calib_bboard[j][i] = buf[offs]; 1414 + wdata->state.calib_bboard[j][i] <<= 8; 1415 + wdata->state.calib_bboard[j][i] |= buf[offs + 1]; 1416 + offs += 2; 1417 + } 1418 + } 1419 + spin_unlock_irq(&wdata->state.lock); 1420 + 1421 + ret = 0; 1422 + for (i = 0; i < 3; ++i) { 1423 + for (j = 0; j < 4; ++j) { 1424 + val = wdata->state.calib_bboard[j][i]; 1425 + if (i == 2 && j == 3) 1426 + ret += sprintf(&out[ret], "%04x\n", val); 1427 + else 1428 + ret += sprintf(&out[ret], "%04x:", val); 1429 + } 1430 + } 1431 + 1432 + return ret; 1433 + } 1434 + 1435 + static DEVICE_ATTR(bboard_calib, S_IRUGO, wiimod_bboard_calib_show, NULL); 1436 + 1383 1437 static int wiimod_bboard_probe(const struct wiimod_ops *ops, 1384 1438 struct wiimote_data *wdata) 1385 1439 { ··· 1469 1415 if (!wdata->extension.input) 1470 1416 return -ENOMEM; 1471 1417 1418 + ret = device_create_file(&wdata->hdev->dev, 1419 + &dev_attr_bboard_calib); 1420 + if (ret) { 1421 + hid_err(wdata->hdev, "cannot create sysfs attribute\n"); 1422 + goto err_free; 1423 + } 1424 + 1472 1425 input_set_drvdata(wdata->extension.input, wdata); 1473 1426 wdata->extension.input->open = wiimod_bboard_open; 1474 1427 wdata->extension.input->close = wiimod_bboard_close; ··· 1505 1444 1506 1445 ret = input_register_device(wdata->extension.input); 1507 1446 if (ret) 1508 - goto err_free; 1447 + goto err_file; 1509 1448 1510 1449 return 0; 1511 1450 1451 + err_file: 1452 + device_remove_file(&wdata->hdev->dev, 1453 + &dev_attr_bboard_calib); 1512 1454 err_free: 1513 1455 input_free_device(wdata->extension.input); 1514 1456 wdata->extension.input = NULL; ··· 1526 1462 1527 1463 input_unregister_device(wdata->extension.input); 1528 1464 wdata->extension.input = NULL; 1465 + device_remove_file(&wdata->hdev->dev, 1466 + &dev_attr_bboard_calib); 1529 1467 } 1530 1468 1531 1469 static const struct wiimod_ops wiimod_bboard = {