17e274400SDavid Herrmann #ifndef __HID_WIIMOTE_H 27e274400SDavid Herrmann #define __HID_WIIMOTE_H 37e274400SDavid Herrmann 47e274400SDavid Herrmann /* 592eda7e4SDavid Herrmann * HID driver for Nintendo Wii / Wii U peripherals 692eda7e4SDavid Herrmann * Copyright (c) 2011-2013 David Herrmann <dh.herrmann@gmail.com> 77e274400SDavid Herrmann */ 87e274400SDavid Herrmann 97e274400SDavid Herrmann /* 107e274400SDavid Herrmann * This program is free software; you can redistribute it and/or modify it 117e274400SDavid Herrmann * under the terms of the GNU General Public License as published by the Free 127e274400SDavid Herrmann * Software Foundation; either version 2 of the License, or (at your option) 137e274400SDavid Herrmann * any later version. 147e274400SDavid Herrmann */ 157e274400SDavid Herrmann 167e274400SDavid Herrmann #include <linux/completion.h> 177e274400SDavid Herrmann #include <linux/device.h> 187e274400SDavid Herrmann #include <linux/hid.h> 197e274400SDavid Herrmann #include <linux/input.h> 207e274400SDavid Herrmann #include <linux/leds.h> 217e274400SDavid Herrmann #include <linux/module.h> 227e274400SDavid Herrmann #include <linux/mutex.h> 237e274400SDavid Herrmann #include <linux/power_supply.h> 247e274400SDavid Herrmann #include <linux/spinlock.h> 254148b6bfSDavid Herrmann #include <linux/timer.h> 267e274400SDavid Herrmann 277e274400SDavid Herrmann #define WIIMOTE_NAME "Nintendo Wii Remote" 287e274400SDavid Herrmann #define WIIMOTE_BUFSIZE 32 297e274400SDavid Herrmann 307e274400SDavid Herrmann #define WIIPROTO_FLAG_LED1 0x01 317e274400SDavid Herrmann #define WIIPROTO_FLAG_LED2 0x02 327e274400SDavid Herrmann #define WIIPROTO_FLAG_LED3 0x04 337e274400SDavid Herrmann #define WIIPROTO_FLAG_LED4 0x08 347e274400SDavid Herrmann #define WIIPROTO_FLAG_RUMBLE 0x10 357e274400SDavid Herrmann #define WIIPROTO_FLAG_ACCEL 0x20 367e274400SDavid Herrmann #define WIIPROTO_FLAG_IR_BASIC 0x40 377e274400SDavid Herrmann #define WIIPROTO_FLAG_IR_EXT 0x80 387e274400SDavid Herrmann #define WIIPROTO_FLAG_IR_FULL 0xc0 /* IR_BASIC | IR_EXT */ 39c57ff761SDavid Herrmann #define WIIPROTO_FLAG_EXT_PLUGGED 0x0100 404148b6bfSDavid Herrmann #define WIIPROTO_FLAG_EXT_USED 0x0200 414148b6bfSDavid Herrmann #define WIIPROTO_FLAG_EXT_ACTIVE 0x0400 424148b6bfSDavid Herrmann #define WIIPROTO_FLAG_MP_PLUGGED 0x0800 434148b6bfSDavid Herrmann #define WIIPROTO_FLAG_MP_USED 0x1000 444148b6bfSDavid Herrmann #define WIIPROTO_FLAG_MP_ACTIVE 0x2000 454148b6bfSDavid Herrmann #define WIIPROTO_FLAG_EXITING 0x4000 46d76f89e1SDavid Herrmann #define WIIPROTO_FLAG_DRM_LOCKED 0x8000 479f329741SDavid Herrmann #define WIIPROTO_FLAG_BUILTIN_MP 0x010000 489f329741SDavid Herrmann #define WIIPROTO_FLAG_NO_MP 0x020000 49c57ff761SDavid Herrmann 507e274400SDavid Herrmann #define WIIPROTO_FLAGS_LEDS (WIIPROTO_FLAG_LED1 | WIIPROTO_FLAG_LED2 | \ 517e274400SDavid Herrmann WIIPROTO_FLAG_LED3 | WIIPROTO_FLAG_LED4) 527e274400SDavid Herrmann #define WIIPROTO_FLAGS_IR (WIIPROTO_FLAG_IR_BASIC | WIIPROTO_FLAG_IR_EXT | \ 537e274400SDavid Herrmann WIIPROTO_FLAG_IR_FULL) 547e274400SDavid Herrmann 557e274400SDavid Herrmann /* return flag for led \num */ 567e274400SDavid Herrmann #define WIIPROTO_FLAG_LED(num) (WIIPROTO_FLAG_LED1 << (num - 1)) 577e274400SDavid Herrmann 5820cef813SDavid Herrmann enum wiiproto_keys { 5920cef813SDavid Herrmann WIIPROTO_KEY_LEFT, 6020cef813SDavid Herrmann WIIPROTO_KEY_RIGHT, 6120cef813SDavid Herrmann WIIPROTO_KEY_UP, 6220cef813SDavid Herrmann WIIPROTO_KEY_DOWN, 6320cef813SDavid Herrmann WIIPROTO_KEY_PLUS, 6420cef813SDavid Herrmann WIIPROTO_KEY_MINUS, 6520cef813SDavid Herrmann WIIPROTO_KEY_ONE, 6620cef813SDavid Herrmann WIIPROTO_KEY_TWO, 6720cef813SDavid Herrmann WIIPROTO_KEY_A, 6820cef813SDavid Herrmann WIIPROTO_KEY_B, 6920cef813SDavid Herrmann WIIPROTO_KEY_HOME, 7020cef813SDavid Herrmann WIIPROTO_KEY_COUNT 7120cef813SDavid Herrmann }; 7220cef813SDavid Herrmann 73c57ff761SDavid Herrmann enum wiimote_devtype { 74c57ff761SDavid Herrmann WIIMOTE_DEV_PENDING, 75c57ff761SDavid Herrmann WIIMOTE_DEV_UNKNOWN, 76c57ff761SDavid Herrmann WIIMOTE_DEV_GENERIC, 77c57ff761SDavid Herrmann WIIMOTE_DEV_GEN10, 78c57ff761SDavid Herrmann WIIMOTE_DEV_GEN20, 79f1d4bed4SDavid Herrmann WIIMOTE_DEV_BALANCE_BOARD, 80b8e0fe31SDavid Herrmann WIIMOTE_DEV_PRO_CONTROLLER, 81c57ff761SDavid Herrmann WIIMOTE_DEV_NUM, 82c57ff761SDavid Herrmann }; 83c57ff761SDavid Herrmann 84c57ff761SDavid Herrmann enum wiimote_exttype { 85c57ff761SDavid Herrmann WIIMOTE_EXT_NONE, 86c57ff761SDavid Herrmann WIIMOTE_EXT_UNKNOWN, 87b6ee67b3SDavid Herrmann WIIMOTE_EXT_NUNCHUK, 889d6f9ecbSDavid Herrmann WIIMOTE_EXT_CLASSIC_CONTROLLER, 89f1d4bed4SDavid Herrmann WIIMOTE_EXT_BALANCE_BOARD, 90b8e0fe31SDavid Herrmann WIIMOTE_EXT_PRO_CONTROLLER, 91c57ff761SDavid Herrmann WIIMOTE_EXT_NUM, 92c57ff761SDavid Herrmann }; 93c57ff761SDavid Herrmann 944148b6bfSDavid Herrmann enum wiimote_mptype { 954148b6bfSDavid Herrmann WIIMOTE_MP_NONE, 964148b6bfSDavid Herrmann WIIMOTE_MP_UNKNOWN, 974148b6bfSDavid Herrmann WIIMOTE_MP_SINGLE, 984148b6bfSDavid Herrmann WIIMOTE_MP_PASSTHROUGH_NUNCHUK, 994148b6bfSDavid Herrmann WIIMOTE_MP_PASSTHROUGH_CLASSIC, 1004148b6bfSDavid Herrmann }; 1014148b6bfSDavid Herrmann 1027e274400SDavid Herrmann struct wiimote_buf { 1037e274400SDavid Herrmann __u8 data[HID_MAX_BUFFER_SIZE]; 1047e274400SDavid Herrmann size_t size; 1057e274400SDavid Herrmann }; 1067e274400SDavid Herrmann 10713938538SDavid Herrmann struct wiimote_queue { 10813938538SDavid Herrmann spinlock_t lock; 10913938538SDavid Herrmann struct work_struct worker; 11013938538SDavid Herrmann __u8 head; 11113938538SDavid Herrmann __u8 tail; 11213938538SDavid Herrmann struct wiimote_buf outq[WIIMOTE_BUFSIZE]; 11313938538SDavid Herrmann }; 11413938538SDavid Herrmann 1157e274400SDavid Herrmann struct wiimote_state { 1167e274400SDavid Herrmann spinlock_t lock; 117c57ff761SDavid Herrmann __u32 flags; 1187e274400SDavid Herrmann __u8 accel_split[2]; 11943d782aeSDavid Herrmann __u8 drm; 120c57ff761SDavid Herrmann __u8 devtype; 1214148b6bfSDavid Herrmann __u8 exttype; 1224148b6bfSDavid Herrmann __u8 mp; 1237e274400SDavid Herrmann 1247e274400SDavid Herrmann /* synchronous cmd requests */ 1257e274400SDavid Herrmann struct mutex sync; 1267e274400SDavid Herrmann struct completion ready; 1277e274400SDavid Herrmann int cmd; 1287e274400SDavid Herrmann __u32 opt; 1297e274400SDavid Herrmann 1307e274400SDavid Herrmann /* results of synchronous requests */ 1317e274400SDavid Herrmann __u8 cmd_battery; 1327e274400SDavid Herrmann __u8 cmd_err; 133fad8c0e3SDavid Herrmann __u8 *cmd_read_buf; 134fad8c0e3SDavid Herrmann __u8 cmd_read_size; 135f1d4bed4SDavid Herrmann 136f50f9aabSDavid Herrmann /* calibration/cache data */ 137f1d4bed4SDavid Herrmann __u16 calib_bboard[4][3]; 138f50f9aabSDavid Herrmann __u8 cache_rumble; 1397e274400SDavid Herrmann }; 1407e274400SDavid Herrmann 1417e274400SDavid Herrmann struct wiimote_data { 1427e274400SDavid Herrmann struct hid_device *hdev; 1437e274400SDavid Herrmann struct input_dev *input; 144f50f9aabSDavid Herrmann struct work_struct rumble_worker; 1457e274400SDavid Herrmann struct led_classdev *leds[4]; 1467e274400SDavid Herrmann struct input_dev *accel; 1477e274400SDavid Herrmann struct input_dev *ir; 1487e274400SDavid Herrmann struct power_supply battery; 14934472d37SDavid Herrmann struct input_dev *mp; 1504148b6bfSDavid Herrmann struct timer_list timer; 15143e5e7c6SDavid Herrmann struct wiimote_debug *debug; 1527e274400SDavid Herrmann 153f1d4bed4SDavid Herrmann union { 154f1d4bed4SDavid Herrmann struct input_dev *input; 155f1d4bed4SDavid Herrmann } extension; 156f1d4bed4SDavid Herrmann 15713938538SDavid Herrmann struct wiimote_queue queue; 1587e274400SDavid Herrmann struct wiimote_state state; 159c57ff761SDavid Herrmann struct work_struct init_worker; 1607e274400SDavid Herrmann }; 1617e274400SDavid Herrmann 16227f06942SDavid Herrmann /* wiimote modules */ 16327f06942SDavid Herrmann 16427f06942SDavid Herrmann enum wiimod_module { 16520cef813SDavid Herrmann WIIMOD_KEYS, 16620cef813SDavid Herrmann WIIMOD_RUMBLE, 167dcf39231SDavid Herrmann WIIMOD_BATTERY, 1686c5ae018SDavid Herrmann WIIMOD_LED1, 1696c5ae018SDavid Herrmann WIIMOD_LED2, 1706c5ae018SDavid Herrmann WIIMOD_LED3, 1716c5ae018SDavid Herrmann WIIMOD_LED4, 1720ea16757SDavid Herrmann WIIMOD_ACCEL, 1733b5f03c4SDavid Herrmann WIIMOD_IR, 1749f329741SDavid Herrmann WIIMOD_BUILTIN_MP, 1759f329741SDavid Herrmann WIIMOD_NO_MP, 17627f06942SDavid Herrmann WIIMOD_NUM, 17727f06942SDavid Herrmann WIIMOD_NULL = WIIMOD_NUM, 17827f06942SDavid Herrmann }; 17927f06942SDavid Herrmann 18027f06942SDavid Herrmann #define WIIMOD_FLAG_INPUT 0x0001 1814148b6bfSDavid Herrmann #define WIIMOD_FLAG_EXT8 0x0002 1824148b6bfSDavid Herrmann #define WIIMOD_FLAG_EXT16 0x0004 18327f06942SDavid Herrmann 18427f06942SDavid Herrmann struct wiimod_ops { 18527f06942SDavid Herrmann __u16 flags; 18627f06942SDavid Herrmann unsigned long arg; 18727f06942SDavid Herrmann int (*probe) (const struct wiimod_ops *ops, 18827f06942SDavid Herrmann struct wiimote_data *wdata); 18927f06942SDavid Herrmann void (*remove) (const struct wiimod_ops *ops, 19027f06942SDavid Herrmann struct wiimote_data *wdata); 19127f06942SDavid Herrmann 19227f06942SDavid Herrmann void (*in_keys) (struct wiimote_data *wdata, const __u8 *keys); 19327f06942SDavid Herrmann void (*in_accel) (struct wiimote_data *wdata, const __u8 *accel); 19427f06942SDavid Herrmann void (*in_ir) (struct wiimote_data *wdata, const __u8 *ir, bool packed, 19527f06942SDavid Herrmann unsigned int id); 1964148b6bfSDavid Herrmann void (*in_mp) (struct wiimote_data *wdata, const __u8 *mp); 1974148b6bfSDavid Herrmann void (*in_ext) (struct wiimote_data *wdata, const __u8 *ext); 19827f06942SDavid Herrmann }; 19927f06942SDavid Herrmann 20027f06942SDavid Herrmann extern const struct wiimod_ops *wiimod_table[WIIMOD_NUM]; 2014148b6bfSDavid Herrmann extern const struct wiimod_ops *wiimod_ext_table[WIIMOTE_EXT_NUM]; 2024148b6bfSDavid Herrmann extern const struct wiimod_ops wiimod_mp; 20327f06942SDavid Herrmann 20427f06942SDavid Herrmann /* wiimote requests */ 20527f06942SDavid Herrmann 2067e274400SDavid Herrmann enum wiiproto_reqs { 2077e274400SDavid Herrmann WIIPROTO_REQ_NULL = 0x0, 2087e274400SDavid Herrmann WIIPROTO_REQ_RUMBLE = 0x10, 2097e274400SDavid Herrmann WIIPROTO_REQ_LED = 0x11, 2107e274400SDavid Herrmann WIIPROTO_REQ_DRM = 0x12, 2117e274400SDavid Herrmann WIIPROTO_REQ_IR1 = 0x13, 2127e274400SDavid Herrmann WIIPROTO_REQ_SREQ = 0x15, 2137e274400SDavid Herrmann WIIPROTO_REQ_WMEM = 0x16, 2147e274400SDavid Herrmann WIIPROTO_REQ_RMEM = 0x17, 2157e274400SDavid Herrmann WIIPROTO_REQ_IR2 = 0x1a, 2167e274400SDavid Herrmann WIIPROTO_REQ_STATUS = 0x20, 2177e274400SDavid Herrmann WIIPROTO_REQ_DATA = 0x21, 2187e274400SDavid Herrmann WIIPROTO_REQ_RETURN = 0x22, 2194148b6bfSDavid Herrmann 2204148b6bfSDavid Herrmann /* DRM_K: BB*2 */ 2217e274400SDavid Herrmann WIIPROTO_REQ_DRM_K = 0x30, 2224148b6bfSDavid Herrmann 2234148b6bfSDavid Herrmann /* DRM_KA: BB*2 AA*3 */ 2247e274400SDavid Herrmann WIIPROTO_REQ_DRM_KA = 0x31, 2254148b6bfSDavid Herrmann 2264148b6bfSDavid Herrmann /* DRM_KE: BB*2 EE*8 */ 2277e274400SDavid Herrmann WIIPROTO_REQ_DRM_KE = 0x32, 2284148b6bfSDavid Herrmann 2294148b6bfSDavid Herrmann /* DRM_KAI: BB*2 AA*3 II*12 */ 2307e274400SDavid Herrmann WIIPROTO_REQ_DRM_KAI = 0x33, 2314148b6bfSDavid Herrmann 2324148b6bfSDavid Herrmann /* DRM_KEE: BB*2 EE*19 */ 2337e274400SDavid Herrmann WIIPROTO_REQ_DRM_KEE = 0x34, 2344148b6bfSDavid Herrmann 2354148b6bfSDavid Herrmann /* DRM_KAE: BB*2 AA*3 EE*16 */ 2367e274400SDavid Herrmann WIIPROTO_REQ_DRM_KAE = 0x35, 2374148b6bfSDavid Herrmann 2384148b6bfSDavid Herrmann /* DRM_KIE: BB*2 II*10 EE*9 */ 2397e274400SDavid Herrmann WIIPROTO_REQ_DRM_KIE = 0x36, 2404148b6bfSDavid Herrmann 2414148b6bfSDavid Herrmann /* DRM_KAIE: BB*2 AA*3 II*10 EE*6 */ 2427e274400SDavid Herrmann WIIPROTO_REQ_DRM_KAIE = 0x37, 2434148b6bfSDavid Herrmann 2444148b6bfSDavid Herrmann /* DRM_E: EE*21 */ 2457e274400SDavid Herrmann WIIPROTO_REQ_DRM_E = 0x3d, 2464148b6bfSDavid Herrmann 2474148b6bfSDavid Herrmann /* DRM_SKAI1: BB*2 AA*1 II*18 */ 2487e274400SDavid Herrmann WIIPROTO_REQ_DRM_SKAI1 = 0x3e, 2494148b6bfSDavid Herrmann 2504148b6bfSDavid Herrmann /* DRM_SKAI2: BB*2 AA*1 II*18 */ 2517e274400SDavid Herrmann WIIPROTO_REQ_DRM_SKAI2 = 0x3f, 2524148b6bfSDavid Herrmann 25343d782aeSDavid Herrmann WIIPROTO_REQ_MAX 2547e274400SDavid Herrmann }; 2557e274400SDavid Herrmann 2567e274400SDavid Herrmann #define dev_to_wii(pdev) hid_get_drvdata(container_of(pdev, struct hid_device, \ 2577e274400SDavid Herrmann dev)) 2587e274400SDavid Herrmann 2594148b6bfSDavid Herrmann void __wiimote_schedule(struct wiimote_data *wdata); 2604148b6bfSDavid Herrmann 2617e274400SDavid Herrmann extern void wiiproto_req_drm(struct wiimote_data *wdata, __u8 drm); 26220cef813SDavid Herrmann extern void wiiproto_req_rumble(struct wiimote_data *wdata, __u8 rumble); 2636c5ae018SDavid Herrmann extern void wiiproto_req_leds(struct wiimote_data *wdata, int leds); 264dcf39231SDavid Herrmann extern void wiiproto_req_status(struct wiimote_data *wdata); 2650ea16757SDavid Herrmann extern void wiiproto_req_accel(struct wiimote_data *wdata, __u8 accel); 2663b5f03c4SDavid Herrmann extern void wiiproto_req_ir1(struct wiimote_data *wdata, __u8 flags); 2673b5f03c4SDavid Herrmann extern void wiiproto_req_ir2(struct wiimote_data *wdata, __u8 flags); 2687e274400SDavid Herrmann extern int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset, 2697e274400SDavid Herrmann const __u8 *wmem, __u8 size); 270fad8c0e3SDavid Herrmann extern ssize_t wiimote_cmd_read(struct wiimote_data *wdata, __u32 offset, 271fad8c0e3SDavid Herrmann __u8 *rmem, __u8 size); 2727e274400SDavid Herrmann 2731d3452c6SDavid Herrmann #define wiiproto_req_rreg(wdata, os, sz) \ 2741d3452c6SDavid Herrmann wiiproto_req_rmem((wdata), false, (os), (sz)) 2751d3452c6SDavid Herrmann #define wiiproto_req_reeprom(wdata, os, sz) \ 2761d3452c6SDavid Herrmann wiiproto_req_rmem((wdata), true, (os), (sz)) 2771d3452c6SDavid Herrmann extern void wiiproto_req_rmem(struct wiimote_data *wdata, bool eeprom, 2781d3452c6SDavid Herrmann __u32 offset, __u16 size); 2791d3452c6SDavid Herrmann 28043e5e7c6SDavid Herrmann #ifdef CONFIG_DEBUG_FS 28143e5e7c6SDavid Herrmann 28243e5e7c6SDavid Herrmann extern int wiidebug_init(struct wiimote_data *wdata); 28343e5e7c6SDavid Herrmann extern void wiidebug_deinit(struct wiimote_data *wdata); 28443e5e7c6SDavid Herrmann 28543e5e7c6SDavid Herrmann #else 28643e5e7c6SDavid Herrmann 28743e5e7c6SDavid Herrmann static inline int wiidebug_init(void *u) { return 0; } 28843e5e7c6SDavid Herrmann static inline void wiidebug_deinit(void *u) { } 28943e5e7c6SDavid Herrmann 29043e5e7c6SDavid Herrmann #endif 29143e5e7c6SDavid Herrmann 2927e274400SDavid Herrmann /* requires the state.lock spinlock to be held */ 2937e274400SDavid Herrmann static inline bool wiimote_cmd_pending(struct wiimote_data *wdata, int cmd, 2947e274400SDavid Herrmann __u32 opt) 2957e274400SDavid Herrmann { 2967e274400SDavid Herrmann return wdata->state.cmd == cmd && wdata->state.opt == opt; 2977e274400SDavid Herrmann } 2987e274400SDavid Herrmann 2997e274400SDavid Herrmann /* requires the state.lock spinlock to be held */ 3007e274400SDavid Herrmann static inline void wiimote_cmd_complete(struct wiimote_data *wdata) 3017e274400SDavid Herrmann { 3027e274400SDavid Herrmann wdata->state.cmd = WIIPROTO_REQ_NULL; 3037e274400SDavid Herrmann complete(&wdata->state.ready); 3047e274400SDavid Herrmann } 3057e274400SDavid Herrmann 306d758b1f0SDavid Herrmann /* requires the state.lock spinlock to be held */ 307d758b1f0SDavid Herrmann static inline void wiimote_cmd_abort(struct wiimote_data *wdata) 308d758b1f0SDavid Herrmann { 309d758b1f0SDavid Herrmann /* Abort synchronous request by waking up the sleeping caller. But 310d758b1f0SDavid Herrmann * reset the state.cmd field to an invalid value so no further event 311d758b1f0SDavid Herrmann * handlers will work with it. */ 312d758b1f0SDavid Herrmann wdata->state.cmd = WIIPROTO_REQ_MAX; 313d758b1f0SDavid Herrmann complete(&wdata->state.ready); 314d758b1f0SDavid Herrmann } 315d758b1f0SDavid Herrmann 3167e274400SDavid Herrmann static inline int wiimote_cmd_acquire(struct wiimote_data *wdata) 3177e274400SDavid Herrmann { 3187e274400SDavid Herrmann return mutex_lock_interruptible(&wdata->state.sync) ? -ERESTARTSYS : 0; 3197e274400SDavid Herrmann } 3207e274400SDavid Herrmann 321c57ff761SDavid Herrmann static inline void wiimote_cmd_acquire_noint(struct wiimote_data *wdata) 322c57ff761SDavid Herrmann { 323c57ff761SDavid Herrmann mutex_lock(&wdata->state.sync); 324c57ff761SDavid Herrmann } 325c57ff761SDavid Herrmann 3267e274400SDavid Herrmann /* requires the state.lock spinlock to be held */ 3277e274400SDavid Herrmann static inline void wiimote_cmd_set(struct wiimote_data *wdata, int cmd, 3287e274400SDavid Herrmann __u32 opt) 3297e274400SDavid Herrmann { 330*16735d02SWolfram Sang reinit_completion(&wdata->state.ready); 3317e274400SDavid Herrmann wdata->state.cmd = cmd; 3327e274400SDavid Herrmann wdata->state.opt = opt; 3337e274400SDavid Herrmann } 3347e274400SDavid Herrmann 3357e274400SDavid Herrmann static inline void wiimote_cmd_release(struct wiimote_data *wdata) 3367e274400SDavid Herrmann { 3377e274400SDavid Herrmann mutex_unlock(&wdata->state.sync); 3387e274400SDavid Herrmann } 3397e274400SDavid Herrmann 3407e274400SDavid Herrmann static inline int wiimote_cmd_wait(struct wiimote_data *wdata) 3417e274400SDavid Herrmann { 3427e274400SDavid Herrmann int ret; 3437e274400SDavid Herrmann 344d758b1f0SDavid Herrmann /* The completion acts as implicit memory barrier so we can safely 345d758b1f0SDavid Herrmann * assume that state.cmd is set on success/failure and isn't accessed 346d758b1f0SDavid Herrmann * by any other thread, anymore. */ 347d758b1f0SDavid Herrmann 3487e274400SDavid Herrmann ret = wait_for_completion_interruptible_timeout(&wdata->state.ready, HZ); 3497e274400SDavid Herrmann if (ret < 0) 3507e274400SDavid Herrmann return -ERESTARTSYS; 3517e274400SDavid Herrmann else if (ret == 0) 3527e274400SDavid Herrmann return -EIO; 353d758b1f0SDavid Herrmann else if (wdata->state.cmd != WIIPROTO_REQ_NULL) 354d758b1f0SDavid Herrmann return -EIO; 3557e274400SDavid Herrmann else 3567e274400SDavid Herrmann return 0; 3577e274400SDavid Herrmann } 3587e274400SDavid Herrmann 359c57ff761SDavid Herrmann static inline int wiimote_cmd_wait_noint(struct wiimote_data *wdata) 360c57ff761SDavid Herrmann { 361c57ff761SDavid Herrmann unsigned long ret; 362c57ff761SDavid Herrmann 363d758b1f0SDavid Herrmann /* no locking needed; see wiimote_cmd_wait() */ 364c57ff761SDavid Herrmann ret = wait_for_completion_timeout(&wdata->state.ready, HZ); 365c57ff761SDavid Herrmann if (!ret) 366c57ff761SDavid Herrmann return -EIO; 367d758b1f0SDavid Herrmann else if (wdata->state.cmd != WIIPROTO_REQ_NULL) 368d758b1f0SDavid Herrmann return -EIO; 369c57ff761SDavid Herrmann else 370c57ff761SDavid Herrmann return 0; 371c57ff761SDavid Herrmann } 372c57ff761SDavid Herrmann 3737e274400SDavid Herrmann #endif 374