gen10: First Wii Remote generation
                        gen20: Second Wii Remote Plus generation (builtin MP)
                        balanceboard: Wii Balance Board
+
+What:          /sys/bus/hid/drivers/wiimote/<dev>/bboard_calib
+Date:          May 2013
+KernelVersion: 3.11
+Contact:       David Herrmann <dh.herrmann@gmail.com>
+Description:   This attribute is only provided if the device was detected as a
+               balance board. It provides a single line with 3 calibration
+               values for all 4 sensors. The values are separated by colons and
+               are each 2 bytes long (encoded as 4 digit hexadecimal value).
+               First, 0kg values for all 4 sensors are written, followed by the
+               17kg values for all 4 sensors and last the 34kg values for all 4
+               sensors.
+               Calibration data is already applied by the kernel to all input
+               values but may be used by user-space to perform other
+               transformations.
 
        spin_unlock_irqrestore(&wdata->state.lock, flags);
 }
 
+static ssize_t wiimod_bboard_calib_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *out)
+{
+       struct wiimote_data *wdata = dev_to_wii(dev);
+       int i, j, ret;
+       __u16 val;
+       __u8 buf[24], offs;
+
+       ret = wiimote_cmd_acquire(wdata);
+       if (ret)
+               return ret;
+
+       ret = wiimote_cmd_read(wdata, 0xa40024, buf, 12);
+       if (ret != 12) {
+               wiimote_cmd_release(wdata);
+               return ret < 0 ? ret : -EIO;
+       }
+       ret = wiimote_cmd_read(wdata, 0xa40024 + 12, buf + 12, 12);
+       if (ret != 12) {
+               wiimote_cmd_release(wdata);
+               return ret < 0 ? ret : -EIO;
+       }
+
+       wiimote_cmd_release(wdata);
+
+       spin_lock_irq(&wdata->state.lock);
+       offs = 0;
+       for (i = 0; i < 3; ++i) {
+               for (j = 0; j < 4; ++j) {
+                       wdata->state.calib_bboard[j][i] = buf[offs];
+                       wdata->state.calib_bboard[j][i] <<= 8;
+                       wdata->state.calib_bboard[j][i] |= buf[offs + 1];
+                       offs += 2;
+               }
+       }
+       spin_unlock_irq(&wdata->state.lock);
+
+       ret = 0;
+       for (i = 0; i < 3; ++i) {
+               for (j = 0; j < 4; ++j) {
+                       val = wdata->state.calib_bboard[j][i];
+                       if (i == 2 && j == 3)
+                               ret += sprintf(&out[ret], "%04x\n", val);
+                       else
+                               ret += sprintf(&out[ret], "%04x:", val);
+               }
+       }
+
+       return ret;
+}
+
+static DEVICE_ATTR(bboard_calib, S_IRUGO, wiimod_bboard_calib_show, NULL);
+
 static int wiimod_bboard_probe(const struct wiimod_ops *ops,
                               struct wiimote_data *wdata)
 {
        if (!wdata->extension.input)
                return -ENOMEM;
 
+       ret = device_create_file(&wdata->hdev->dev,
+                                &dev_attr_bboard_calib);
+       if (ret) {
+               hid_err(wdata->hdev, "cannot create sysfs attribute\n");
+               goto err_free;
+       }
+
        input_set_drvdata(wdata->extension.input, wdata);
        wdata->extension.input->open = wiimod_bboard_open;
        wdata->extension.input->close = wiimod_bboard_close;
 
        ret = input_register_device(wdata->extension.input);
        if (ret)
-               goto err_free;
+               goto err_file;
 
        return 0;
 
+err_file:
+       device_remove_file(&wdata->hdev->dev,
+                          &dev_attr_bboard_calib);
 err_free:
        input_free_device(wdata->extension.input);
        wdata->extension.input = NULL;
 
        input_unregister_device(wdata->extension.input);
        wdata->extension.input = NULL;
+       device_remove_file(&wdata->hdev->dev,
+                          &dev_attr_bboard_calib);
 }
 
 static const struct wiimod_ops wiimod_bboard = {