1192a1acfSDavid Herrmann /* 2192a1acfSDavid Herrmann * HID driver for Nintendo Wiimote devices 3192a1acfSDavid Herrmann * Copyright (c) 2011 David Herrmann 4192a1acfSDavid Herrmann */ 5192a1acfSDavid Herrmann 6192a1acfSDavid Herrmann /* 7192a1acfSDavid Herrmann * This program is free software; you can redistribute it and/or modify it 8192a1acfSDavid Herrmann * under the terms of the GNU General Public License as published by the Free 9192a1acfSDavid Herrmann * Software Foundation; either version 2 of the License, or (at your option) 10192a1acfSDavid Herrmann * any later version. 11192a1acfSDavid Herrmann */ 12192a1acfSDavid Herrmann 13192a1acfSDavid Herrmann #include <linux/completion.h> 14192a1acfSDavid Herrmann #include <linux/device.h> 15192a1acfSDavid Herrmann #include <linux/hid.h> 16192a1acfSDavid Herrmann #include <linux/input.h> 17192a1acfSDavid Herrmann #include <linux/leds.h> 18192a1acfSDavid Herrmann #include <linux/module.h> 19192a1acfSDavid Herrmann #include <linux/mutex.h> 20192a1acfSDavid Herrmann #include <linux/power_supply.h> 21192a1acfSDavid Herrmann #include <linux/spinlock.h> 22192a1acfSDavid Herrmann #include "hid-ids.h" 237e274400SDavid Herrmann #include "hid-wiimote.h" 24192a1acfSDavid Herrmann 25192a1acfSDavid Herrmann #define WIIMOTE_VERSION "0.2" 26192a1acfSDavid Herrmann 27192a1acfSDavid Herrmann enum wiiproto_keys { 28192a1acfSDavid Herrmann WIIPROTO_KEY_LEFT, 29192a1acfSDavid Herrmann WIIPROTO_KEY_RIGHT, 30192a1acfSDavid Herrmann WIIPROTO_KEY_UP, 31192a1acfSDavid Herrmann WIIPROTO_KEY_DOWN, 32192a1acfSDavid Herrmann WIIPROTO_KEY_PLUS, 33192a1acfSDavid Herrmann WIIPROTO_KEY_MINUS, 34192a1acfSDavid Herrmann WIIPROTO_KEY_ONE, 35192a1acfSDavid Herrmann WIIPROTO_KEY_TWO, 36192a1acfSDavid Herrmann WIIPROTO_KEY_A, 37192a1acfSDavid Herrmann WIIPROTO_KEY_B, 38192a1acfSDavid Herrmann WIIPROTO_KEY_HOME, 39192a1acfSDavid Herrmann WIIPROTO_KEY_COUNT 40192a1acfSDavid Herrmann }; 41192a1acfSDavid Herrmann 42192a1acfSDavid Herrmann static __u16 wiiproto_keymap[] = { 43192a1acfSDavid Herrmann KEY_LEFT, /* WIIPROTO_KEY_LEFT */ 44192a1acfSDavid Herrmann KEY_RIGHT, /* WIIPROTO_KEY_RIGHT */ 45192a1acfSDavid Herrmann KEY_UP, /* WIIPROTO_KEY_UP */ 46192a1acfSDavid Herrmann KEY_DOWN, /* WIIPROTO_KEY_DOWN */ 47192a1acfSDavid Herrmann KEY_NEXT, /* WIIPROTO_KEY_PLUS */ 48192a1acfSDavid Herrmann KEY_PREVIOUS, /* WIIPROTO_KEY_MINUS */ 49192a1acfSDavid Herrmann BTN_1, /* WIIPROTO_KEY_ONE */ 50192a1acfSDavid Herrmann BTN_2, /* WIIPROTO_KEY_TWO */ 51192a1acfSDavid Herrmann BTN_A, /* WIIPROTO_KEY_A */ 52192a1acfSDavid Herrmann BTN_B, /* WIIPROTO_KEY_B */ 53192a1acfSDavid Herrmann BTN_MODE, /* WIIPROTO_KEY_HOME */ 54192a1acfSDavid Herrmann }; 55192a1acfSDavid Herrmann 56192a1acfSDavid Herrmann static enum power_supply_property wiimote_battery_props[] = { 57192a1acfSDavid Herrmann POWER_SUPPLY_PROP_CAPACITY 58192a1acfSDavid Herrmann }; 59192a1acfSDavid Herrmann 60192a1acfSDavid Herrmann static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer, 61192a1acfSDavid Herrmann size_t count) 62192a1acfSDavid Herrmann { 63192a1acfSDavid Herrmann __u8 *buf; 64192a1acfSDavid Herrmann ssize_t ret; 65192a1acfSDavid Herrmann 66192a1acfSDavid Herrmann if (!hdev->hid_output_raw_report) 67192a1acfSDavid Herrmann return -ENODEV; 68192a1acfSDavid Herrmann 69192a1acfSDavid Herrmann buf = kmemdup(buffer, count, GFP_KERNEL); 70192a1acfSDavid Herrmann if (!buf) 71192a1acfSDavid Herrmann return -ENOMEM; 72192a1acfSDavid Herrmann 73192a1acfSDavid Herrmann ret = hdev->hid_output_raw_report(hdev, buf, count, HID_OUTPUT_REPORT); 74192a1acfSDavid Herrmann 75192a1acfSDavid Herrmann kfree(buf); 76192a1acfSDavid Herrmann return ret; 77192a1acfSDavid Herrmann } 78192a1acfSDavid Herrmann 79192a1acfSDavid Herrmann static void wiimote_worker(struct work_struct *work) 80192a1acfSDavid Herrmann { 81192a1acfSDavid Herrmann struct wiimote_data *wdata = container_of(work, struct wiimote_data, 82192a1acfSDavid Herrmann worker); 83192a1acfSDavid Herrmann unsigned long flags; 84192a1acfSDavid Herrmann 85192a1acfSDavid Herrmann spin_lock_irqsave(&wdata->qlock, flags); 86192a1acfSDavid Herrmann 87192a1acfSDavid Herrmann while (wdata->head != wdata->tail) { 88192a1acfSDavid Herrmann spin_unlock_irqrestore(&wdata->qlock, flags); 89192a1acfSDavid Herrmann wiimote_hid_send(wdata->hdev, wdata->outq[wdata->tail].data, 90192a1acfSDavid Herrmann wdata->outq[wdata->tail].size); 91192a1acfSDavid Herrmann spin_lock_irqsave(&wdata->qlock, flags); 92192a1acfSDavid Herrmann 93192a1acfSDavid Herrmann wdata->tail = (wdata->tail + 1) % WIIMOTE_BUFSIZE; 94192a1acfSDavid Herrmann } 95192a1acfSDavid Herrmann 96192a1acfSDavid Herrmann spin_unlock_irqrestore(&wdata->qlock, flags); 97192a1acfSDavid Herrmann } 98192a1acfSDavid Herrmann 99192a1acfSDavid Herrmann static void wiimote_queue(struct wiimote_data *wdata, const __u8 *buffer, 100192a1acfSDavid Herrmann size_t count) 101192a1acfSDavid Herrmann { 102192a1acfSDavid Herrmann unsigned long flags; 103192a1acfSDavid Herrmann __u8 newhead; 104192a1acfSDavid Herrmann 105192a1acfSDavid Herrmann if (count > HID_MAX_BUFFER_SIZE) { 106192a1acfSDavid Herrmann hid_warn(wdata->hdev, "Sending too large output report\n"); 107192a1acfSDavid Herrmann return; 108192a1acfSDavid Herrmann } 109192a1acfSDavid Herrmann 110192a1acfSDavid Herrmann /* 111192a1acfSDavid Herrmann * Copy new request into our output queue and check whether the 112192a1acfSDavid Herrmann * queue is full. If it is full, discard this request. 113192a1acfSDavid Herrmann * If it is empty we need to start a new worker that will 114192a1acfSDavid Herrmann * send out the buffer to the hid device. 115192a1acfSDavid Herrmann * If the queue is not empty, then there must be a worker 116192a1acfSDavid Herrmann * that is currently sending out our buffer and this worker 117192a1acfSDavid Herrmann * will reschedule itself until the queue is empty. 118192a1acfSDavid Herrmann */ 119192a1acfSDavid Herrmann 120192a1acfSDavid Herrmann spin_lock_irqsave(&wdata->qlock, flags); 121192a1acfSDavid Herrmann 122192a1acfSDavid Herrmann memcpy(wdata->outq[wdata->head].data, buffer, count); 123192a1acfSDavid Herrmann wdata->outq[wdata->head].size = count; 124192a1acfSDavid Herrmann newhead = (wdata->head + 1) % WIIMOTE_BUFSIZE; 125192a1acfSDavid Herrmann 126192a1acfSDavid Herrmann if (wdata->head == wdata->tail) { 127192a1acfSDavid Herrmann wdata->head = newhead; 128192a1acfSDavid Herrmann schedule_work(&wdata->worker); 129192a1acfSDavid Herrmann } else if (newhead != wdata->tail) { 130192a1acfSDavid Herrmann wdata->head = newhead; 131192a1acfSDavid Herrmann } else { 132192a1acfSDavid Herrmann hid_warn(wdata->hdev, "Output queue is full"); 133192a1acfSDavid Herrmann } 134192a1acfSDavid Herrmann 135192a1acfSDavid Herrmann spin_unlock_irqrestore(&wdata->qlock, flags); 136192a1acfSDavid Herrmann } 137192a1acfSDavid Herrmann 138192a1acfSDavid Herrmann /* 139192a1acfSDavid Herrmann * This sets the rumble bit on the given output report if rumble is 140192a1acfSDavid Herrmann * currently enabled. 141192a1acfSDavid Herrmann * \cmd1 must point to the second byte in the output report => &cmd[1] 142192a1acfSDavid Herrmann * This must be called on nearly every output report before passing it 143192a1acfSDavid Herrmann * into the output queue! 144192a1acfSDavid Herrmann */ 145192a1acfSDavid Herrmann static inline void wiiproto_keep_rumble(struct wiimote_data *wdata, __u8 *cmd1) 146192a1acfSDavid Herrmann { 147192a1acfSDavid Herrmann if (wdata->state.flags & WIIPROTO_FLAG_RUMBLE) 148192a1acfSDavid Herrmann *cmd1 |= 0x01; 149192a1acfSDavid Herrmann } 150192a1acfSDavid Herrmann 151192a1acfSDavid Herrmann static void wiiproto_req_rumble(struct wiimote_data *wdata, __u8 rumble) 152192a1acfSDavid Herrmann { 153192a1acfSDavid Herrmann __u8 cmd[2]; 154192a1acfSDavid Herrmann 155192a1acfSDavid Herrmann rumble = !!rumble; 156192a1acfSDavid Herrmann if (rumble == !!(wdata->state.flags & WIIPROTO_FLAG_RUMBLE)) 157192a1acfSDavid Herrmann return; 158192a1acfSDavid Herrmann 159192a1acfSDavid Herrmann if (rumble) 160192a1acfSDavid Herrmann wdata->state.flags |= WIIPROTO_FLAG_RUMBLE; 161192a1acfSDavid Herrmann else 162192a1acfSDavid Herrmann wdata->state.flags &= ~WIIPROTO_FLAG_RUMBLE; 163192a1acfSDavid Herrmann 164192a1acfSDavid Herrmann cmd[0] = WIIPROTO_REQ_RUMBLE; 165192a1acfSDavid Herrmann cmd[1] = 0; 166192a1acfSDavid Herrmann 167192a1acfSDavid Herrmann wiiproto_keep_rumble(wdata, &cmd[1]); 168192a1acfSDavid Herrmann wiimote_queue(wdata, cmd, sizeof(cmd)); 169192a1acfSDavid Herrmann } 170192a1acfSDavid Herrmann 171192a1acfSDavid Herrmann static void wiiproto_req_leds(struct wiimote_data *wdata, int leds) 172192a1acfSDavid Herrmann { 173192a1acfSDavid Herrmann __u8 cmd[2]; 174192a1acfSDavid Herrmann 175192a1acfSDavid Herrmann leds &= WIIPROTO_FLAGS_LEDS; 176192a1acfSDavid Herrmann if ((wdata->state.flags & WIIPROTO_FLAGS_LEDS) == leds) 177192a1acfSDavid Herrmann return; 178192a1acfSDavid Herrmann wdata->state.flags = (wdata->state.flags & ~WIIPROTO_FLAGS_LEDS) | leds; 179192a1acfSDavid Herrmann 180192a1acfSDavid Herrmann cmd[0] = WIIPROTO_REQ_LED; 181192a1acfSDavid Herrmann cmd[1] = 0; 182192a1acfSDavid Herrmann 183192a1acfSDavid Herrmann if (leds & WIIPROTO_FLAG_LED1) 184192a1acfSDavid Herrmann cmd[1] |= 0x10; 185192a1acfSDavid Herrmann if (leds & WIIPROTO_FLAG_LED2) 186192a1acfSDavid Herrmann cmd[1] |= 0x20; 187192a1acfSDavid Herrmann if (leds & WIIPROTO_FLAG_LED3) 188192a1acfSDavid Herrmann cmd[1] |= 0x40; 189192a1acfSDavid Herrmann if (leds & WIIPROTO_FLAG_LED4) 190192a1acfSDavid Herrmann cmd[1] |= 0x80; 191192a1acfSDavid Herrmann 192192a1acfSDavid Herrmann wiiproto_keep_rumble(wdata, &cmd[1]); 193192a1acfSDavid Herrmann wiimote_queue(wdata, cmd, sizeof(cmd)); 194192a1acfSDavid Herrmann } 195192a1acfSDavid Herrmann 196192a1acfSDavid Herrmann /* 197192a1acfSDavid Herrmann * Check what peripherals of the wiimote are currently 198192a1acfSDavid Herrmann * active and select a proper DRM that supports all of 199192a1acfSDavid Herrmann * the requested data inputs. 200192a1acfSDavid Herrmann */ 201192a1acfSDavid Herrmann static __u8 select_drm(struct wiimote_data *wdata) 202192a1acfSDavid Herrmann { 203192a1acfSDavid Herrmann __u8 ir = wdata->state.flags & WIIPROTO_FLAGS_IR; 204cb99221bSDavid Herrmann bool ext = wiiext_active(wdata); 205192a1acfSDavid Herrmann 206192a1acfSDavid Herrmann if (ir == WIIPROTO_FLAG_IR_BASIC) { 207192a1acfSDavid Herrmann if (wdata->state.flags & WIIPROTO_FLAG_ACCEL) 208192a1acfSDavid Herrmann return WIIPROTO_REQ_DRM_KAIE; 209192a1acfSDavid Herrmann else 210192a1acfSDavid Herrmann return WIIPROTO_REQ_DRM_KIE; 211192a1acfSDavid Herrmann } else if (ir == WIIPROTO_FLAG_IR_EXT) { 212192a1acfSDavid Herrmann return WIIPROTO_REQ_DRM_KAI; 213192a1acfSDavid Herrmann } else if (ir == WIIPROTO_FLAG_IR_FULL) { 214192a1acfSDavid Herrmann return WIIPROTO_REQ_DRM_SKAI1; 215192a1acfSDavid Herrmann } else { 216cb99221bSDavid Herrmann if (wdata->state.flags & WIIPROTO_FLAG_ACCEL) { 217cb99221bSDavid Herrmann if (ext) 218cb99221bSDavid Herrmann return WIIPROTO_REQ_DRM_KAE; 219cb99221bSDavid Herrmann else 220192a1acfSDavid Herrmann return WIIPROTO_REQ_DRM_KA; 221cb99221bSDavid Herrmann } else { 222cb99221bSDavid Herrmann if (ext) 223cb99221bSDavid Herrmann return WIIPROTO_REQ_DRM_KE; 224192a1acfSDavid Herrmann else 225192a1acfSDavid Herrmann return WIIPROTO_REQ_DRM_K; 226192a1acfSDavid Herrmann } 227192a1acfSDavid Herrmann } 228cb99221bSDavid Herrmann } 229192a1acfSDavid Herrmann 2307e274400SDavid Herrmann void wiiproto_req_drm(struct wiimote_data *wdata, __u8 drm) 231192a1acfSDavid Herrmann { 232192a1acfSDavid Herrmann __u8 cmd[3]; 233192a1acfSDavid Herrmann 234192a1acfSDavid Herrmann if (drm == WIIPROTO_REQ_NULL) 235192a1acfSDavid Herrmann drm = select_drm(wdata); 236192a1acfSDavid Herrmann 237192a1acfSDavid Herrmann cmd[0] = WIIPROTO_REQ_DRM; 238192a1acfSDavid Herrmann cmd[1] = 0; 239192a1acfSDavid Herrmann cmd[2] = drm; 240192a1acfSDavid Herrmann 241192a1acfSDavid Herrmann wiiproto_keep_rumble(wdata, &cmd[1]); 242192a1acfSDavid Herrmann wiimote_queue(wdata, cmd, sizeof(cmd)); 243192a1acfSDavid Herrmann } 244192a1acfSDavid Herrmann 245192a1acfSDavid Herrmann static void wiiproto_req_status(struct wiimote_data *wdata) 246192a1acfSDavid Herrmann { 247192a1acfSDavid Herrmann __u8 cmd[2]; 248192a1acfSDavid Herrmann 249192a1acfSDavid Herrmann cmd[0] = WIIPROTO_REQ_SREQ; 250192a1acfSDavid Herrmann cmd[1] = 0; 251192a1acfSDavid Herrmann 252192a1acfSDavid Herrmann wiiproto_keep_rumble(wdata, &cmd[1]); 253192a1acfSDavid Herrmann wiimote_queue(wdata, cmd, sizeof(cmd)); 254192a1acfSDavid Herrmann } 255192a1acfSDavid Herrmann 256192a1acfSDavid Herrmann static void wiiproto_req_accel(struct wiimote_data *wdata, __u8 accel) 257192a1acfSDavid Herrmann { 258192a1acfSDavid Herrmann accel = !!accel; 259192a1acfSDavid Herrmann if (accel == !!(wdata->state.flags & WIIPROTO_FLAG_ACCEL)) 260192a1acfSDavid Herrmann return; 261192a1acfSDavid Herrmann 262192a1acfSDavid Herrmann if (accel) 263192a1acfSDavid Herrmann wdata->state.flags |= WIIPROTO_FLAG_ACCEL; 264192a1acfSDavid Herrmann else 265192a1acfSDavid Herrmann wdata->state.flags &= ~WIIPROTO_FLAG_ACCEL; 266192a1acfSDavid Herrmann 267192a1acfSDavid Herrmann wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); 268192a1acfSDavid Herrmann } 269192a1acfSDavid Herrmann 270192a1acfSDavid Herrmann static void wiiproto_req_ir1(struct wiimote_data *wdata, __u8 flags) 271192a1acfSDavid Herrmann { 272192a1acfSDavid Herrmann __u8 cmd[2]; 273192a1acfSDavid Herrmann 274192a1acfSDavid Herrmann cmd[0] = WIIPROTO_REQ_IR1; 275192a1acfSDavid Herrmann cmd[1] = flags; 276192a1acfSDavid Herrmann 277192a1acfSDavid Herrmann wiiproto_keep_rumble(wdata, &cmd[1]); 278192a1acfSDavid Herrmann wiimote_queue(wdata, cmd, sizeof(cmd)); 279192a1acfSDavid Herrmann } 280192a1acfSDavid Herrmann 281192a1acfSDavid Herrmann static void wiiproto_req_ir2(struct wiimote_data *wdata, __u8 flags) 282192a1acfSDavid Herrmann { 283192a1acfSDavid Herrmann __u8 cmd[2]; 284192a1acfSDavid Herrmann 285192a1acfSDavid Herrmann cmd[0] = WIIPROTO_REQ_IR2; 286192a1acfSDavid Herrmann cmd[1] = flags; 287192a1acfSDavid Herrmann 288192a1acfSDavid Herrmann wiiproto_keep_rumble(wdata, &cmd[1]); 289192a1acfSDavid Herrmann wiimote_queue(wdata, cmd, sizeof(cmd)); 290192a1acfSDavid Herrmann } 291192a1acfSDavid Herrmann 292192a1acfSDavid Herrmann #define wiiproto_req_wreg(wdata, os, buf, sz) \ 293192a1acfSDavid Herrmann wiiproto_req_wmem((wdata), false, (os), (buf), (sz)) 294192a1acfSDavid Herrmann 295192a1acfSDavid Herrmann #define wiiproto_req_weeprom(wdata, os, buf, sz) \ 296192a1acfSDavid Herrmann wiiproto_req_wmem((wdata), true, (os), (buf), (sz)) 297192a1acfSDavid Herrmann 298192a1acfSDavid Herrmann static void wiiproto_req_wmem(struct wiimote_data *wdata, bool eeprom, 299192a1acfSDavid Herrmann __u32 offset, const __u8 *buf, __u8 size) 300192a1acfSDavid Herrmann { 301192a1acfSDavid Herrmann __u8 cmd[22]; 302192a1acfSDavid Herrmann 303192a1acfSDavid Herrmann if (size > 16 || size == 0) { 304192a1acfSDavid Herrmann hid_warn(wdata->hdev, "Invalid length %d wmem request\n", size); 305192a1acfSDavid Herrmann return; 306192a1acfSDavid Herrmann } 307192a1acfSDavid Herrmann 308192a1acfSDavid Herrmann memset(cmd, 0, sizeof(cmd)); 309192a1acfSDavid Herrmann cmd[0] = WIIPROTO_REQ_WMEM; 310192a1acfSDavid Herrmann cmd[2] = (offset >> 16) & 0xff; 311192a1acfSDavid Herrmann cmd[3] = (offset >> 8) & 0xff; 312192a1acfSDavid Herrmann cmd[4] = offset & 0xff; 313192a1acfSDavid Herrmann cmd[5] = size; 314192a1acfSDavid Herrmann memcpy(&cmd[6], buf, size); 315192a1acfSDavid Herrmann 316192a1acfSDavid Herrmann if (!eeprom) 317192a1acfSDavid Herrmann cmd[1] |= 0x04; 318192a1acfSDavid Herrmann 319192a1acfSDavid Herrmann wiiproto_keep_rumble(wdata, &cmd[1]); 320192a1acfSDavid Herrmann wiimote_queue(wdata, cmd, sizeof(cmd)); 321192a1acfSDavid Herrmann } 322192a1acfSDavid Herrmann 323*1d3452c6SDavid Herrmann void wiiproto_req_rmem(struct wiimote_data *wdata, bool eeprom, __u32 offset, 324*1d3452c6SDavid Herrmann __u16 size) 325fad8c0e3SDavid Herrmann { 326fad8c0e3SDavid Herrmann __u8 cmd[7]; 327fad8c0e3SDavid Herrmann 328fad8c0e3SDavid Herrmann if (size == 0) { 329fad8c0e3SDavid Herrmann hid_warn(wdata->hdev, "Invalid length %d rmem request\n", size); 330fad8c0e3SDavid Herrmann return; 331fad8c0e3SDavid Herrmann } 332fad8c0e3SDavid Herrmann 333fad8c0e3SDavid Herrmann cmd[0] = WIIPROTO_REQ_RMEM; 334fad8c0e3SDavid Herrmann cmd[1] = 0; 335fad8c0e3SDavid Herrmann cmd[2] = (offset >> 16) & 0xff; 336fad8c0e3SDavid Herrmann cmd[3] = (offset >> 8) & 0xff; 337fad8c0e3SDavid Herrmann cmd[4] = offset & 0xff; 338fad8c0e3SDavid Herrmann cmd[5] = (size >> 8) & 0xff; 339fad8c0e3SDavid Herrmann cmd[6] = size & 0xff; 340fad8c0e3SDavid Herrmann 341fad8c0e3SDavid Herrmann if (!eeprom) 342fad8c0e3SDavid Herrmann cmd[1] |= 0x04; 343fad8c0e3SDavid Herrmann 344fad8c0e3SDavid Herrmann wiiproto_keep_rumble(wdata, &cmd[1]); 345fad8c0e3SDavid Herrmann wiimote_queue(wdata, cmd, sizeof(cmd)); 346fad8c0e3SDavid Herrmann } 347fad8c0e3SDavid Herrmann 348192a1acfSDavid Herrmann /* requries the cmd-mutex to be held */ 3497e274400SDavid Herrmann int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset, 350192a1acfSDavid Herrmann const __u8 *wmem, __u8 size) 351192a1acfSDavid Herrmann { 352192a1acfSDavid Herrmann unsigned long flags; 353192a1acfSDavid Herrmann int ret; 354192a1acfSDavid Herrmann 355192a1acfSDavid Herrmann spin_lock_irqsave(&wdata->state.lock, flags); 356192a1acfSDavid Herrmann wiimote_cmd_set(wdata, WIIPROTO_REQ_WMEM, 0); 357192a1acfSDavid Herrmann wiiproto_req_wreg(wdata, offset, wmem, size); 358192a1acfSDavid Herrmann spin_unlock_irqrestore(&wdata->state.lock, flags); 359192a1acfSDavid Herrmann 360192a1acfSDavid Herrmann ret = wiimote_cmd_wait(wdata); 361192a1acfSDavid Herrmann if (!ret && wdata->state.cmd_err) 362192a1acfSDavid Herrmann ret = -EIO; 363192a1acfSDavid Herrmann 364192a1acfSDavid Herrmann return ret; 365192a1acfSDavid Herrmann } 366192a1acfSDavid Herrmann 367fad8c0e3SDavid Herrmann /* requries the cmd-mutex to be held */ 368fad8c0e3SDavid Herrmann ssize_t wiimote_cmd_read(struct wiimote_data *wdata, __u32 offset, __u8 *rmem, 369fad8c0e3SDavid Herrmann __u8 size) 370fad8c0e3SDavid Herrmann { 371fad8c0e3SDavid Herrmann unsigned long flags; 372fad8c0e3SDavid Herrmann ssize_t ret; 373fad8c0e3SDavid Herrmann 374fad8c0e3SDavid Herrmann spin_lock_irqsave(&wdata->state.lock, flags); 375fad8c0e3SDavid Herrmann wdata->state.cmd_read_size = size; 376fad8c0e3SDavid Herrmann wdata->state.cmd_read_buf = rmem; 377fad8c0e3SDavid Herrmann wiimote_cmd_set(wdata, WIIPROTO_REQ_RMEM, offset & 0xffff); 378fad8c0e3SDavid Herrmann wiiproto_req_rreg(wdata, offset, size); 379fad8c0e3SDavid Herrmann spin_unlock_irqrestore(&wdata->state.lock, flags); 380fad8c0e3SDavid Herrmann 381fad8c0e3SDavid Herrmann ret = wiimote_cmd_wait(wdata); 382fad8c0e3SDavid Herrmann 383fad8c0e3SDavid Herrmann spin_lock_irqsave(&wdata->state.lock, flags); 384fad8c0e3SDavid Herrmann wdata->state.cmd_read_buf = NULL; 385fad8c0e3SDavid Herrmann spin_unlock_irqrestore(&wdata->state.lock, flags); 386fad8c0e3SDavid Herrmann 387fad8c0e3SDavid Herrmann if (!ret) { 388fad8c0e3SDavid Herrmann if (wdata->state.cmd_read_size == 0) 389fad8c0e3SDavid Herrmann ret = -EIO; 390fad8c0e3SDavid Herrmann else 391fad8c0e3SDavid Herrmann ret = wdata->state.cmd_read_size; 392fad8c0e3SDavid Herrmann } 393fad8c0e3SDavid Herrmann 394fad8c0e3SDavid Herrmann return ret; 395fad8c0e3SDavid Herrmann } 396fad8c0e3SDavid Herrmann 397192a1acfSDavid Herrmann static int wiimote_battery_get_property(struct power_supply *psy, 398192a1acfSDavid Herrmann enum power_supply_property psp, 399192a1acfSDavid Herrmann union power_supply_propval *val) 400192a1acfSDavid Herrmann { 401192a1acfSDavid Herrmann struct wiimote_data *wdata = container_of(psy, 402192a1acfSDavid Herrmann struct wiimote_data, battery); 403192a1acfSDavid Herrmann int ret = 0, state; 404192a1acfSDavid Herrmann unsigned long flags; 405192a1acfSDavid Herrmann 406192a1acfSDavid Herrmann ret = wiimote_cmd_acquire(wdata); 407192a1acfSDavid Herrmann if (ret) 408192a1acfSDavid Herrmann return ret; 409192a1acfSDavid Herrmann 410192a1acfSDavid Herrmann spin_lock_irqsave(&wdata->state.lock, flags); 411192a1acfSDavid Herrmann wiimote_cmd_set(wdata, WIIPROTO_REQ_SREQ, 0); 412192a1acfSDavid Herrmann wiiproto_req_status(wdata); 413192a1acfSDavid Herrmann spin_unlock_irqrestore(&wdata->state.lock, flags); 414192a1acfSDavid Herrmann 415192a1acfSDavid Herrmann ret = wiimote_cmd_wait(wdata); 416192a1acfSDavid Herrmann state = wdata->state.cmd_battery; 417192a1acfSDavid Herrmann wiimote_cmd_release(wdata); 418192a1acfSDavid Herrmann 419192a1acfSDavid Herrmann if (ret) 420192a1acfSDavid Herrmann return ret; 421192a1acfSDavid Herrmann 422192a1acfSDavid Herrmann switch (psp) { 423192a1acfSDavid Herrmann case POWER_SUPPLY_PROP_CAPACITY: 424192a1acfSDavid Herrmann val->intval = state * 100 / 255; 425192a1acfSDavid Herrmann break; 426192a1acfSDavid Herrmann default: 427192a1acfSDavid Herrmann ret = -EINVAL; 428192a1acfSDavid Herrmann break; 429192a1acfSDavid Herrmann } 430192a1acfSDavid Herrmann 431192a1acfSDavid Herrmann return ret; 432192a1acfSDavid Herrmann } 433192a1acfSDavid Herrmann 434192a1acfSDavid Herrmann static int wiimote_init_ir(struct wiimote_data *wdata, __u16 mode) 435192a1acfSDavid Herrmann { 436192a1acfSDavid Herrmann int ret; 437192a1acfSDavid Herrmann unsigned long flags; 438192a1acfSDavid Herrmann __u8 format = 0; 439192a1acfSDavid Herrmann static const __u8 data_enable[] = { 0x01 }; 440192a1acfSDavid Herrmann static const __u8 data_sens1[] = { 0x02, 0x00, 0x00, 0x71, 0x01, 441192a1acfSDavid Herrmann 0x00, 0xaa, 0x00, 0x64 }; 442192a1acfSDavid Herrmann static const __u8 data_sens2[] = { 0x63, 0x03 }; 443192a1acfSDavid Herrmann static const __u8 data_fin[] = { 0x08 }; 444192a1acfSDavid Herrmann 445192a1acfSDavid Herrmann spin_lock_irqsave(&wdata->state.lock, flags); 446192a1acfSDavid Herrmann 447192a1acfSDavid Herrmann if (mode == (wdata->state.flags & WIIPROTO_FLAGS_IR)) { 448192a1acfSDavid Herrmann spin_unlock_irqrestore(&wdata->state.lock, flags); 449192a1acfSDavid Herrmann return 0; 450192a1acfSDavid Herrmann } 451192a1acfSDavid Herrmann 452192a1acfSDavid Herrmann if (mode == 0) { 453192a1acfSDavid Herrmann wdata->state.flags &= ~WIIPROTO_FLAGS_IR; 454192a1acfSDavid Herrmann wiiproto_req_ir1(wdata, 0); 455192a1acfSDavid Herrmann wiiproto_req_ir2(wdata, 0); 456192a1acfSDavid Herrmann wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); 457192a1acfSDavid Herrmann spin_unlock_irqrestore(&wdata->state.lock, flags); 458192a1acfSDavid Herrmann return 0; 459192a1acfSDavid Herrmann } 460192a1acfSDavid Herrmann 461192a1acfSDavid Herrmann spin_unlock_irqrestore(&wdata->state.lock, flags); 462192a1acfSDavid Herrmann 463192a1acfSDavid Herrmann ret = wiimote_cmd_acquire(wdata); 464192a1acfSDavid Herrmann if (ret) 465192a1acfSDavid Herrmann return ret; 466192a1acfSDavid Herrmann 467192a1acfSDavid Herrmann /* send PIXEL CLOCK ENABLE cmd first */ 468192a1acfSDavid Herrmann spin_lock_irqsave(&wdata->state.lock, flags); 469192a1acfSDavid Herrmann wiimote_cmd_set(wdata, WIIPROTO_REQ_IR1, 0); 470192a1acfSDavid Herrmann wiiproto_req_ir1(wdata, 0x06); 471192a1acfSDavid Herrmann spin_unlock_irqrestore(&wdata->state.lock, flags); 472192a1acfSDavid Herrmann 473192a1acfSDavid Herrmann ret = wiimote_cmd_wait(wdata); 474192a1acfSDavid Herrmann if (ret) 475192a1acfSDavid Herrmann goto unlock; 476192a1acfSDavid Herrmann if (wdata->state.cmd_err) { 477192a1acfSDavid Herrmann ret = -EIO; 478192a1acfSDavid Herrmann goto unlock; 479192a1acfSDavid Herrmann } 480192a1acfSDavid Herrmann 481192a1acfSDavid Herrmann /* enable IR LOGIC */ 482192a1acfSDavid Herrmann spin_lock_irqsave(&wdata->state.lock, flags); 483192a1acfSDavid Herrmann wiimote_cmd_set(wdata, WIIPROTO_REQ_IR2, 0); 484192a1acfSDavid Herrmann wiiproto_req_ir2(wdata, 0x06); 485192a1acfSDavid Herrmann spin_unlock_irqrestore(&wdata->state.lock, flags); 486192a1acfSDavid Herrmann 487192a1acfSDavid Herrmann ret = wiimote_cmd_wait(wdata); 488192a1acfSDavid Herrmann if (ret) 489192a1acfSDavid Herrmann goto unlock; 490192a1acfSDavid Herrmann if (wdata->state.cmd_err) { 491192a1acfSDavid Herrmann ret = -EIO; 492192a1acfSDavid Herrmann goto unlock; 493192a1acfSDavid Herrmann } 494192a1acfSDavid Herrmann 495192a1acfSDavid Herrmann /* enable IR cam but do not make it send data, yet */ 496192a1acfSDavid Herrmann ret = wiimote_cmd_write(wdata, 0xb00030, data_enable, 497192a1acfSDavid Herrmann sizeof(data_enable)); 498192a1acfSDavid Herrmann if (ret) 499192a1acfSDavid Herrmann goto unlock; 500192a1acfSDavid Herrmann 501192a1acfSDavid Herrmann /* write first sensitivity block */ 502192a1acfSDavid Herrmann ret = wiimote_cmd_write(wdata, 0xb00000, data_sens1, 503192a1acfSDavid Herrmann sizeof(data_sens1)); 504192a1acfSDavid Herrmann if (ret) 505192a1acfSDavid Herrmann goto unlock; 506192a1acfSDavid Herrmann 507192a1acfSDavid Herrmann /* write second sensitivity block */ 508192a1acfSDavid Herrmann ret = wiimote_cmd_write(wdata, 0xb0001a, data_sens2, 509192a1acfSDavid Herrmann sizeof(data_sens2)); 510192a1acfSDavid Herrmann if (ret) 511192a1acfSDavid Herrmann goto unlock; 512192a1acfSDavid Herrmann 513192a1acfSDavid Herrmann /* put IR cam into desired state */ 514192a1acfSDavid Herrmann switch (mode) { 515192a1acfSDavid Herrmann case WIIPROTO_FLAG_IR_FULL: 516192a1acfSDavid Herrmann format = 5; 517192a1acfSDavid Herrmann break; 518192a1acfSDavid Herrmann case WIIPROTO_FLAG_IR_EXT: 519192a1acfSDavid Herrmann format = 3; 520192a1acfSDavid Herrmann break; 521192a1acfSDavid Herrmann case WIIPROTO_FLAG_IR_BASIC: 522192a1acfSDavid Herrmann format = 1; 523192a1acfSDavid Herrmann break; 524192a1acfSDavid Herrmann } 525192a1acfSDavid Herrmann ret = wiimote_cmd_write(wdata, 0xb00033, &format, sizeof(format)); 526192a1acfSDavid Herrmann if (ret) 527192a1acfSDavid Herrmann goto unlock; 528192a1acfSDavid Herrmann 529192a1acfSDavid Herrmann /* make IR cam send data */ 530192a1acfSDavid Herrmann ret = wiimote_cmd_write(wdata, 0xb00030, data_fin, sizeof(data_fin)); 531192a1acfSDavid Herrmann if (ret) 532192a1acfSDavid Herrmann goto unlock; 533192a1acfSDavid Herrmann 534192a1acfSDavid Herrmann /* request new DRM mode compatible to IR mode */ 535192a1acfSDavid Herrmann spin_lock_irqsave(&wdata->state.lock, flags); 536192a1acfSDavid Herrmann wdata->state.flags &= ~WIIPROTO_FLAGS_IR; 537192a1acfSDavid Herrmann wdata->state.flags |= mode & WIIPROTO_FLAGS_IR; 538192a1acfSDavid Herrmann wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); 539192a1acfSDavid Herrmann spin_unlock_irqrestore(&wdata->state.lock, flags); 540192a1acfSDavid Herrmann 541192a1acfSDavid Herrmann unlock: 542192a1acfSDavid Herrmann wiimote_cmd_release(wdata); 543192a1acfSDavid Herrmann return ret; 544192a1acfSDavid Herrmann } 545192a1acfSDavid Herrmann 546192a1acfSDavid Herrmann static enum led_brightness wiimote_leds_get(struct led_classdev *led_dev) 547192a1acfSDavid Herrmann { 548192a1acfSDavid Herrmann struct wiimote_data *wdata; 549192a1acfSDavid Herrmann struct device *dev = led_dev->dev->parent; 550192a1acfSDavid Herrmann int i; 551192a1acfSDavid Herrmann unsigned long flags; 552192a1acfSDavid Herrmann bool value = false; 553192a1acfSDavid Herrmann 554192a1acfSDavid Herrmann wdata = hid_get_drvdata(container_of(dev, struct hid_device, dev)); 555192a1acfSDavid Herrmann 556192a1acfSDavid Herrmann for (i = 0; i < 4; ++i) { 557192a1acfSDavid Herrmann if (wdata->leds[i] == led_dev) { 558192a1acfSDavid Herrmann spin_lock_irqsave(&wdata->state.lock, flags); 559192a1acfSDavid Herrmann value = wdata->state.flags & WIIPROTO_FLAG_LED(i + 1); 560192a1acfSDavid Herrmann spin_unlock_irqrestore(&wdata->state.lock, flags); 561192a1acfSDavid Herrmann break; 562192a1acfSDavid Herrmann } 563192a1acfSDavid Herrmann } 564192a1acfSDavid Herrmann 565192a1acfSDavid Herrmann return value ? LED_FULL : LED_OFF; 566192a1acfSDavid Herrmann } 567192a1acfSDavid Herrmann 568192a1acfSDavid Herrmann static void wiimote_leds_set(struct led_classdev *led_dev, 569192a1acfSDavid Herrmann enum led_brightness value) 570192a1acfSDavid Herrmann { 571192a1acfSDavid Herrmann struct wiimote_data *wdata; 572192a1acfSDavid Herrmann struct device *dev = led_dev->dev->parent; 573192a1acfSDavid Herrmann int i; 574192a1acfSDavid Herrmann unsigned long flags; 575192a1acfSDavid Herrmann __u8 state, flag; 576192a1acfSDavid Herrmann 577192a1acfSDavid Herrmann wdata = hid_get_drvdata(container_of(dev, struct hid_device, dev)); 578192a1acfSDavid Herrmann 579192a1acfSDavid Herrmann for (i = 0; i < 4; ++i) { 580192a1acfSDavid Herrmann if (wdata->leds[i] == led_dev) { 581192a1acfSDavid Herrmann flag = WIIPROTO_FLAG_LED(i + 1); 582192a1acfSDavid Herrmann spin_lock_irqsave(&wdata->state.lock, flags); 583192a1acfSDavid Herrmann state = wdata->state.flags; 584192a1acfSDavid Herrmann if (value == LED_OFF) 585192a1acfSDavid Herrmann wiiproto_req_leds(wdata, state & ~flag); 586192a1acfSDavid Herrmann else 587192a1acfSDavid Herrmann wiiproto_req_leds(wdata, state | flag); 588192a1acfSDavid Herrmann spin_unlock_irqrestore(&wdata->state.lock, flags); 589192a1acfSDavid Herrmann break; 590192a1acfSDavid Herrmann } 591192a1acfSDavid Herrmann } 592192a1acfSDavid Herrmann } 593192a1acfSDavid Herrmann 594192a1acfSDavid Herrmann static int wiimote_ff_play(struct input_dev *dev, void *data, 595192a1acfSDavid Herrmann struct ff_effect *eff) 596192a1acfSDavid Herrmann { 597192a1acfSDavid Herrmann struct wiimote_data *wdata = input_get_drvdata(dev); 598192a1acfSDavid Herrmann __u8 value; 599192a1acfSDavid Herrmann unsigned long flags; 600192a1acfSDavid Herrmann 601192a1acfSDavid Herrmann /* 602192a1acfSDavid Herrmann * The wiimote supports only a single rumble motor so if any magnitude 603192a1acfSDavid Herrmann * is set to non-zero then we start the rumble motor. If both are set to 604192a1acfSDavid Herrmann * zero, we stop the rumble motor. 605192a1acfSDavid Herrmann */ 606192a1acfSDavid Herrmann 607192a1acfSDavid Herrmann if (eff->u.rumble.strong_magnitude || eff->u.rumble.weak_magnitude) 608192a1acfSDavid Herrmann value = 1; 609192a1acfSDavid Herrmann else 610192a1acfSDavid Herrmann value = 0; 611192a1acfSDavid Herrmann 612192a1acfSDavid Herrmann spin_lock_irqsave(&wdata->state.lock, flags); 613192a1acfSDavid Herrmann wiiproto_req_rumble(wdata, value); 614192a1acfSDavid Herrmann spin_unlock_irqrestore(&wdata->state.lock, flags); 615192a1acfSDavid Herrmann 616192a1acfSDavid Herrmann return 0; 617192a1acfSDavid Herrmann } 618192a1acfSDavid Herrmann 619192a1acfSDavid Herrmann static int wiimote_input_open(struct input_dev *dev) 620192a1acfSDavid Herrmann { 621192a1acfSDavid Herrmann struct wiimote_data *wdata = input_get_drvdata(dev); 622192a1acfSDavid Herrmann 623192a1acfSDavid Herrmann return hid_hw_open(wdata->hdev); 624192a1acfSDavid Herrmann } 625192a1acfSDavid Herrmann 626192a1acfSDavid Herrmann static void wiimote_input_close(struct input_dev *dev) 627192a1acfSDavid Herrmann { 628192a1acfSDavid Herrmann struct wiimote_data *wdata = input_get_drvdata(dev); 629192a1acfSDavid Herrmann 630192a1acfSDavid Herrmann hid_hw_close(wdata->hdev); 631192a1acfSDavid Herrmann } 632192a1acfSDavid Herrmann 633192a1acfSDavid Herrmann static int wiimote_accel_open(struct input_dev *dev) 634192a1acfSDavid Herrmann { 635192a1acfSDavid Herrmann struct wiimote_data *wdata = input_get_drvdata(dev); 636192a1acfSDavid Herrmann int ret; 637192a1acfSDavid Herrmann unsigned long flags; 638192a1acfSDavid Herrmann 639192a1acfSDavid Herrmann ret = hid_hw_open(wdata->hdev); 640192a1acfSDavid Herrmann if (ret) 641192a1acfSDavid Herrmann return ret; 642192a1acfSDavid Herrmann 643192a1acfSDavid Herrmann spin_lock_irqsave(&wdata->state.lock, flags); 644192a1acfSDavid Herrmann wiiproto_req_accel(wdata, true); 645192a1acfSDavid Herrmann spin_unlock_irqrestore(&wdata->state.lock, flags); 646192a1acfSDavid Herrmann 647192a1acfSDavid Herrmann return 0; 648192a1acfSDavid Herrmann } 649192a1acfSDavid Herrmann 650192a1acfSDavid Herrmann static void wiimote_accel_close(struct input_dev *dev) 651192a1acfSDavid Herrmann { 652192a1acfSDavid Herrmann struct wiimote_data *wdata = input_get_drvdata(dev); 653192a1acfSDavid Herrmann unsigned long flags; 654192a1acfSDavid Herrmann 655192a1acfSDavid Herrmann spin_lock_irqsave(&wdata->state.lock, flags); 656192a1acfSDavid Herrmann wiiproto_req_accel(wdata, false); 657192a1acfSDavid Herrmann spin_unlock_irqrestore(&wdata->state.lock, flags); 658192a1acfSDavid Herrmann 659192a1acfSDavid Herrmann hid_hw_close(wdata->hdev); 660192a1acfSDavid Herrmann } 661192a1acfSDavid Herrmann 662192a1acfSDavid Herrmann static int wiimote_ir_open(struct input_dev *dev) 663192a1acfSDavid Herrmann { 664192a1acfSDavid Herrmann struct wiimote_data *wdata = input_get_drvdata(dev); 665192a1acfSDavid Herrmann int ret; 666192a1acfSDavid Herrmann 667192a1acfSDavid Herrmann ret = hid_hw_open(wdata->hdev); 668192a1acfSDavid Herrmann if (ret) 669192a1acfSDavid Herrmann return ret; 670192a1acfSDavid Herrmann 671192a1acfSDavid Herrmann ret = wiimote_init_ir(wdata, WIIPROTO_FLAG_IR_BASIC); 672192a1acfSDavid Herrmann if (ret) { 673192a1acfSDavid Herrmann hid_hw_close(wdata->hdev); 674192a1acfSDavid Herrmann return ret; 675192a1acfSDavid Herrmann } 676192a1acfSDavid Herrmann 677192a1acfSDavid Herrmann return 0; 678192a1acfSDavid Herrmann } 679192a1acfSDavid Herrmann 680192a1acfSDavid Herrmann static void wiimote_ir_close(struct input_dev *dev) 681192a1acfSDavid Herrmann { 682192a1acfSDavid Herrmann struct wiimote_data *wdata = input_get_drvdata(dev); 683192a1acfSDavid Herrmann 684192a1acfSDavid Herrmann wiimote_init_ir(wdata, 0); 685192a1acfSDavid Herrmann hid_hw_close(wdata->hdev); 686192a1acfSDavid Herrmann } 687192a1acfSDavid Herrmann 688192a1acfSDavid Herrmann static void handler_keys(struct wiimote_data *wdata, const __u8 *payload) 689192a1acfSDavid Herrmann { 690192a1acfSDavid Herrmann input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_LEFT], 691192a1acfSDavid Herrmann !!(payload[0] & 0x01)); 692192a1acfSDavid Herrmann input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_RIGHT], 693192a1acfSDavid Herrmann !!(payload[0] & 0x02)); 694192a1acfSDavid Herrmann input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_DOWN], 695192a1acfSDavid Herrmann !!(payload[0] & 0x04)); 696192a1acfSDavid Herrmann input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_UP], 697192a1acfSDavid Herrmann !!(payload[0] & 0x08)); 698192a1acfSDavid Herrmann input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_PLUS], 699192a1acfSDavid Herrmann !!(payload[0] & 0x10)); 700192a1acfSDavid Herrmann input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_TWO], 701192a1acfSDavid Herrmann !!(payload[1] & 0x01)); 702192a1acfSDavid Herrmann input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_ONE], 703192a1acfSDavid Herrmann !!(payload[1] & 0x02)); 704192a1acfSDavid Herrmann input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_B], 705192a1acfSDavid Herrmann !!(payload[1] & 0x04)); 706192a1acfSDavid Herrmann input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_A], 707192a1acfSDavid Herrmann !!(payload[1] & 0x08)); 708192a1acfSDavid Herrmann input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_MINUS], 709192a1acfSDavid Herrmann !!(payload[1] & 0x10)); 710192a1acfSDavid Herrmann input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_HOME], 711192a1acfSDavid Herrmann !!(payload[1] & 0x80)); 712192a1acfSDavid Herrmann input_sync(wdata->input); 713192a1acfSDavid Herrmann } 714192a1acfSDavid Herrmann 715192a1acfSDavid Herrmann static void handler_accel(struct wiimote_data *wdata, const __u8 *payload) 716192a1acfSDavid Herrmann { 717192a1acfSDavid Herrmann __u16 x, y, z; 718192a1acfSDavid Herrmann 719192a1acfSDavid Herrmann if (!(wdata->state.flags & WIIPROTO_FLAG_ACCEL)) 720192a1acfSDavid Herrmann return; 721192a1acfSDavid Herrmann 722192a1acfSDavid Herrmann /* 723192a1acfSDavid Herrmann * payload is: BB BB XX YY ZZ 724192a1acfSDavid Herrmann * Accelerometer data is encoded into 3 10bit values. XX, YY and ZZ 725192a1acfSDavid Herrmann * contain the upper 8 bits of each value. The lower 2 bits are 726192a1acfSDavid Herrmann * contained in the buttons data BB BB. 727192a1acfSDavid Herrmann * Bits 6 and 7 of the first buttons byte BB is the lower 2 bits of the 728192a1acfSDavid Herrmann * X accel value. Bit 5 of the second buttons byte is the 2nd bit of Y 729192a1acfSDavid Herrmann * accel value and bit 6 is the second bit of the Z value. 730192a1acfSDavid Herrmann * The first bit of Y and Z values is not available and always set to 0. 731192a1acfSDavid Herrmann * 0x200 is returned on no movement. 732192a1acfSDavid Herrmann */ 733192a1acfSDavid Herrmann 734192a1acfSDavid Herrmann x = payload[2] << 2; 735192a1acfSDavid Herrmann y = payload[3] << 2; 736192a1acfSDavid Herrmann z = payload[4] << 2; 737192a1acfSDavid Herrmann 738192a1acfSDavid Herrmann x |= (payload[0] >> 5) & 0x3; 739192a1acfSDavid Herrmann y |= (payload[1] >> 4) & 0x2; 740192a1acfSDavid Herrmann z |= (payload[1] >> 5) & 0x2; 741192a1acfSDavid Herrmann 742192a1acfSDavid Herrmann input_report_abs(wdata->accel, ABS_RX, x - 0x200); 743192a1acfSDavid Herrmann input_report_abs(wdata->accel, ABS_RY, y - 0x200); 744192a1acfSDavid Herrmann input_report_abs(wdata->accel, ABS_RZ, z - 0x200); 745192a1acfSDavid Herrmann input_sync(wdata->accel); 746192a1acfSDavid Herrmann } 747192a1acfSDavid Herrmann 748192a1acfSDavid Herrmann #define ir_to_input0(wdata, ir, packed) __ir_to_input((wdata), (ir), (packed), \ 749192a1acfSDavid Herrmann ABS_HAT0X, ABS_HAT0Y) 750192a1acfSDavid Herrmann #define ir_to_input1(wdata, ir, packed) __ir_to_input((wdata), (ir), (packed), \ 751192a1acfSDavid Herrmann ABS_HAT1X, ABS_HAT1Y) 752192a1acfSDavid Herrmann #define ir_to_input2(wdata, ir, packed) __ir_to_input((wdata), (ir), (packed), \ 753192a1acfSDavid Herrmann ABS_HAT2X, ABS_HAT2Y) 754192a1acfSDavid Herrmann #define ir_to_input3(wdata, ir, packed) __ir_to_input((wdata), (ir), (packed), \ 755192a1acfSDavid Herrmann ABS_HAT3X, ABS_HAT3Y) 756192a1acfSDavid Herrmann 757192a1acfSDavid Herrmann static void __ir_to_input(struct wiimote_data *wdata, const __u8 *ir, 758192a1acfSDavid Herrmann bool packed, __u8 xid, __u8 yid) 759192a1acfSDavid Herrmann { 760192a1acfSDavid Herrmann __u16 x, y; 761192a1acfSDavid Herrmann 762192a1acfSDavid Herrmann if (!(wdata->state.flags & WIIPROTO_FLAGS_IR)) 763192a1acfSDavid Herrmann return; 764192a1acfSDavid Herrmann 765192a1acfSDavid Herrmann /* 766192a1acfSDavid Herrmann * Basic IR data is encoded into 3 bytes. The first two bytes are the 767192a1acfSDavid Herrmann * upper 8 bit of the X/Y data, the 3rd byte contains the lower 2 bits 768192a1acfSDavid Herrmann * of both. 769192a1acfSDavid Herrmann * If data is packed, then the 3rd byte is put first and slightly 770192a1acfSDavid Herrmann * reordered. This allows to interleave packed and non-packed data to 771192a1acfSDavid Herrmann * have two IR sets in 5 bytes instead of 6. 772192a1acfSDavid Herrmann * The resulting 10bit X/Y values are passed to the ABS_HATXY input dev. 773192a1acfSDavid Herrmann */ 774192a1acfSDavid Herrmann 775192a1acfSDavid Herrmann if (packed) { 776192a1acfSDavid Herrmann x = ir[1] << 2; 777192a1acfSDavid Herrmann y = ir[2] << 2; 778192a1acfSDavid Herrmann 779192a1acfSDavid Herrmann x |= ir[0] & 0x3; 780192a1acfSDavid Herrmann y |= (ir[0] >> 2) & 0x3; 781192a1acfSDavid Herrmann } else { 782192a1acfSDavid Herrmann x = ir[0] << 2; 783192a1acfSDavid Herrmann y = ir[1] << 2; 784192a1acfSDavid Herrmann 785192a1acfSDavid Herrmann x |= (ir[2] >> 4) & 0x3; 786192a1acfSDavid Herrmann y |= (ir[2] >> 6) & 0x3; 787192a1acfSDavid Herrmann } 788192a1acfSDavid Herrmann 789192a1acfSDavid Herrmann input_report_abs(wdata->ir, xid, x); 790192a1acfSDavid Herrmann input_report_abs(wdata->ir, yid, y); 791192a1acfSDavid Herrmann } 792192a1acfSDavid Herrmann 793192a1acfSDavid Herrmann static void handler_status(struct wiimote_data *wdata, const __u8 *payload) 794192a1acfSDavid Herrmann { 795192a1acfSDavid Herrmann handler_keys(wdata, payload); 796192a1acfSDavid Herrmann 797192a1acfSDavid Herrmann /* on status reports the drm is reset so we need to resend the drm */ 798192a1acfSDavid Herrmann wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); 799192a1acfSDavid Herrmann 800cb99221bSDavid Herrmann wiiext_event(wdata, payload[2] & 0x02); 801cb99221bSDavid Herrmann 802192a1acfSDavid Herrmann if (wiimote_cmd_pending(wdata, WIIPROTO_REQ_SREQ, 0)) { 803192a1acfSDavid Herrmann wdata->state.cmd_battery = payload[5]; 804192a1acfSDavid Herrmann wiimote_cmd_complete(wdata); 805192a1acfSDavid Herrmann } 806192a1acfSDavid Herrmann } 807192a1acfSDavid Herrmann 808192a1acfSDavid Herrmann static void handler_data(struct wiimote_data *wdata, const __u8 *payload) 809192a1acfSDavid Herrmann { 810fad8c0e3SDavid Herrmann __u16 offset = payload[3] << 8 | payload[4]; 811fad8c0e3SDavid Herrmann __u8 size = (payload[2] >> 4) + 1; 812fad8c0e3SDavid Herrmann __u8 err = payload[2] & 0x0f; 813fad8c0e3SDavid Herrmann 814192a1acfSDavid Herrmann handler_keys(wdata, payload); 815fad8c0e3SDavid Herrmann 816fad8c0e3SDavid Herrmann if (wiimote_cmd_pending(wdata, WIIPROTO_REQ_RMEM, offset)) { 817fad8c0e3SDavid Herrmann if (err) 818fad8c0e3SDavid Herrmann size = 0; 819fad8c0e3SDavid Herrmann else if (size > wdata->state.cmd_read_size) 820fad8c0e3SDavid Herrmann size = wdata->state.cmd_read_size; 821fad8c0e3SDavid Herrmann 822fad8c0e3SDavid Herrmann wdata->state.cmd_read_size = size; 823fad8c0e3SDavid Herrmann if (wdata->state.cmd_read_buf) 824fad8c0e3SDavid Herrmann memcpy(wdata->state.cmd_read_buf, &payload[5], size); 825fad8c0e3SDavid Herrmann wiimote_cmd_complete(wdata); 826fad8c0e3SDavid Herrmann } 827192a1acfSDavid Herrmann } 828192a1acfSDavid Herrmann 829192a1acfSDavid Herrmann static void handler_return(struct wiimote_data *wdata, const __u8 *payload) 830192a1acfSDavid Herrmann { 831192a1acfSDavid Herrmann __u8 err = payload[3]; 832192a1acfSDavid Herrmann __u8 cmd = payload[2]; 833192a1acfSDavid Herrmann 834192a1acfSDavid Herrmann handler_keys(wdata, payload); 835192a1acfSDavid Herrmann 836192a1acfSDavid Herrmann if (wiimote_cmd_pending(wdata, cmd, 0)) { 837192a1acfSDavid Herrmann wdata->state.cmd_err = err; 838192a1acfSDavid Herrmann wiimote_cmd_complete(wdata); 839192a1acfSDavid Herrmann } else if (err) { 840192a1acfSDavid Herrmann hid_warn(wdata->hdev, "Remote error %hhu on req %hhu\n", err, 841192a1acfSDavid Herrmann cmd); 842192a1acfSDavid Herrmann } 843192a1acfSDavid Herrmann } 844192a1acfSDavid Herrmann 845192a1acfSDavid Herrmann static void handler_drm_KA(struct wiimote_data *wdata, const __u8 *payload) 846192a1acfSDavid Herrmann { 847192a1acfSDavid Herrmann handler_keys(wdata, payload); 848192a1acfSDavid Herrmann handler_accel(wdata, payload); 849192a1acfSDavid Herrmann } 850192a1acfSDavid Herrmann 851192a1acfSDavid Herrmann static void handler_drm_KE(struct wiimote_data *wdata, const __u8 *payload) 852192a1acfSDavid Herrmann { 853192a1acfSDavid Herrmann handler_keys(wdata, payload); 8540b6815d7SDavid Herrmann wiiext_handle(wdata, &payload[2]); 855192a1acfSDavid Herrmann } 856192a1acfSDavid Herrmann 857192a1acfSDavid Herrmann static void handler_drm_KAI(struct wiimote_data *wdata, const __u8 *payload) 858192a1acfSDavid Herrmann { 859192a1acfSDavid Herrmann handler_keys(wdata, payload); 860192a1acfSDavid Herrmann handler_accel(wdata, payload); 861192a1acfSDavid Herrmann ir_to_input0(wdata, &payload[5], false); 862192a1acfSDavid Herrmann ir_to_input1(wdata, &payload[8], false); 863192a1acfSDavid Herrmann ir_to_input2(wdata, &payload[11], false); 864192a1acfSDavid Herrmann ir_to_input3(wdata, &payload[14], false); 865192a1acfSDavid Herrmann input_sync(wdata->ir); 866192a1acfSDavid Herrmann } 867192a1acfSDavid Herrmann 868192a1acfSDavid Herrmann static void handler_drm_KEE(struct wiimote_data *wdata, const __u8 *payload) 869192a1acfSDavid Herrmann { 870192a1acfSDavid Herrmann handler_keys(wdata, payload); 8710b6815d7SDavid Herrmann wiiext_handle(wdata, &payload[2]); 872192a1acfSDavid Herrmann } 873192a1acfSDavid Herrmann 874192a1acfSDavid Herrmann static void handler_drm_KIE(struct wiimote_data *wdata, const __u8 *payload) 875192a1acfSDavid Herrmann { 876192a1acfSDavid Herrmann handler_keys(wdata, payload); 877192a1acfSDavid Herrmann ir_to_input0(wdata, &payload[2], false); 878192a1acfSDavid Herrmann ir_to_input1(wdata, &payload[4], true); 879192a1acfSDavid Herrmann ir_to_input2(wdata, &payload[7], false); 880192a1acfSDavid Herrmann ir_to_input3(wdata, &payload[9], true); 881192a1acfSDavid Herrmann input_sync(wdata->ir); 8820b6815d7SDavid Herrmann wiiext_handle(wdata, &payload[12]); 883192a1acfSDavid Herrmann } 884192a1acfSDavid Herrmann 885192a1acfSDavid Herrmann static void handler_drm_KAE(struct wiimote_data *wdata, const __u8 *payload) 886192a1acfSDavid Herrmann { 887192a1acfSDavid Herrmann handler_keys(wdata, payload); 888192a1acfSDavid Herrmann handler_accel(wdata, payload); 8890b6815d7SDavid Herrmann wiiext_handle(wdata, &payload[5]); 890192a1acfSDavid Herrmann } 891192a1acfSDavid Herrmann 892192a1acfSDavid Herrmann static void handler_drm_KAIE(struct wiimote_data *wdata, const __u8 *payload) 893192a1acfSDavid Herrmann { 894192a1acfSDavid Herrmann handler_keys(wdata, payload); 895192a1acfSDavid Herrmann handler_accel(wdata, payload); 896192a1acfSDavid Herrmann ir_to_input0(wdata, &payload[5], false); 897192a1acfSDavid Herrmann ir_to_input1(wdata, &payload[7], true); 898192a1acfSDavid Herrmann ir_to_input2(wdata, &payload[10], false); 899192a1acfSDavid Herrmann ir_to_input3(wdata, &payload[12], true); 900192a1acfSDavid Herrmann input_sync(wdata->ir); 9010b6815d7SDavid Herrmann wiiext_handle(wdata, &payload[15]); 902192a1acfSDavid Herrmann } 903192a1acfSDavid Herrmann 904192a1acfSDavid Herrmann static void handler_drm_E(struct wiimote_data *wdata, const __u8 *payload) 905192a1acfSDavid Herrmann { 9060b6815d7SDavid Herrmann wiiext_handle(wdata, payload); 907192a1acfSDavid Herrmann } 908192a1acfSDavid Herrmann 909192a1acfSDavid Herrmann static void handler_drm_SKAI1(struct wiimote_data *wdata, const __u8 *payload) 910192a1acfSDavid Herrmann { 911192a1acfSDavid Herrmann handler_keys(wdata, payload); 912192a1acfSDavid Herrmann 913192a1acfSDavid Herrmann wdata->state.accel_split[0] = payload[2]; 914192a1acfSDavid Herrmann wdata->state.accel_split[1] = (payload[0] >> 1) & (0x10 | 0x20); 915192a1acfSDavid Herrmann wdata->state.accel_split[1] |= (payload[1] << 1) & (0x40 | 0x80); 916192a1acfSDavid Herrmann 917192a1acfSDavid Herrmann ir_to_input0(wdata, &payload[3], false); 918192a1acfSDavid Herrmann ir_to_input1(wdata, &payload[12], false); 919192a1acfSDavid Herrmann input_sync(wdata->ir); 920192a1acfSDavid Herrmann } 921192a1acfSDavid Herrmann 922192a1acfSDavid Herrmann static void handler_drm_SKAI2(struct wiimote_data *wdata, const __u8 *payload) 923192a1acfSDavid Herrmann { 924192a1acfSDavid Herrmann __u8 buf[5]; 925192a1acfSDavid Herrmann 926192a1acfSDavid Herrmann handler_keys(wdata, payload); 927192a1acfSDavid Herrmann 928192a1acfSDavid Herrmann wdata->state.accel_split[1] |= (payload[0] >> 5) & (0x01 | 0x02); 929192a1acfSDavid Herrmann wdata->state.accel_split[1] |= (payload[1] >> 3) & (0x04 | 0x08); 930192a1acfSDavid Herrmann 931192a1acfSDavid Herrmann buf[0] = 0; 932192a1acfSDavid Herrmann buf[1] = 0; 933192a1acfSDavid Herrmann buf[2] = wdata->state.accel_split[0]; 934192a1acfSDavid Herrmann buf[3] = payload[2]; 935192a1acfSDavid Herrmann buf[4] = wdata->state.accel_split[1]; 936192a1acfSDavid Herrmann handler_accel(wdata, buf); 937192a1acfSDavid Herrmann 938192a1acfSDavid Herrmann ir_to_input2(wdata, &payload[3], false); 939192a1acfSDavid Herrmann ir_to_input3(wdata, &payload[12], false); 940192a1acfSDavid Herrmann input_sync(wdata->ir); 941192a1acfSDavid Herrmann } 942192a1acfSDavid Herrmann 943192a1acfSDavid Herrmann struct wiiproto_handler { 944192a1acfSDavid Herrmann __u8 id; 945192a1acfSDavid Herrmann size_t size; 946192a1acfSDavid Herrmann void (*func)(struct wiimote_data *wdata, const __u8 *payload); 947192a1acfSDavid Herrmann }; 948192a1acfSDavid Herrmann 949192a1acfSDavid Herrmann static struct wiiproto_handler handlers[] = { 950192a1acfSDavid Herrmann { .id = WIIPROTO_REQ_STATUS, .size = 6, .func = handler_status }, 951192a1acfSDavid Herrmann { .id = WIIPROTO_REQ_DATA, .size = 21, .func = handler_data }, 952192a1acfSDavid Herrmann { .id = WIIPROTO_REQ_RETURN, .size = 4, .func = handler_return }, 953192a1acfSDavid Herrmann { .id = WIIPROTO_REQ_DRM_K, .size = 2, .func = handler_keys }, 954192a1acfSDavid Herrmann { .id = WIIPROTO_REQ_DRM_KA, .size = 5, .func = handler_drm_KA }, 955192a1acfSDavid Herrmann { .id = WIIPROTO_REQ_DRM_KE, .size = 10, .func = handler_drm_KE }, 956192a1acfSDavid Herrmann { .id = WIIPROTO_REQ_DRM_KAI, .size = 17, .func = handler_drm_KAI }, 957192a1acfSDavid Herrmann { .id = WIIPROTO_REQ_DRM_KEE, .size = 21, .func = handler_drm_KEE }, 958192a1acfSDavid Herrmann { .id = WIIPROTO_REQ_DRM_KAE, .size = 21, .func = handler_drm_KAE }, 959192a1acfSDavid Herrmann { .id = WIIPROTO_REQ_DRM_KIE, .size = 21, .func = handler_drm_KIE }, 960192a1acfSDavid Herrmann { .id = WIIPROTO_REQ_DRM_KAIE, .size = 21, .func = handler_drm_KAIE }, 961192a1acfSDavid Herrmann { .id = WIIPROTO_REQ_DRM_E, .size = 21, .func = handler_drm_E }, 962192a1acfSDavid Herrmann { .id = WIIPROTO_REQ_DRM_SKAI1, .size = 21, .func = handler_drm_SKAI1 }, 963192a1acfSDavid Herrmann { .id = WIIPROTO_REQ_DRM_SKAI2, .size = 21, .func = handler_drm_SKAI2 }, 964192a1acfSDavid Herrmann { .id = 0 } 965192a1acfSDavid Herrmann }; 966192a1acfSDavid Herrmann 967192a1acfSDavid Herrmann static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report, 968192a1acfSDavid Herrmann u8 *raw_data, int size) 969192a1acfSDavid Herrmann { 970192a1acfSDavid Herrmann struct wiimote_data *wdata = hid_get_drvdata(hdev); 971192a1acfSDavid Herrmann struct wiiproto_handler *h; 972192a1acfSDavid Herrmann int i; 973192a1acfSDavid Herrmann unsigned long flags; 974192a1acfSDavid Herrmann bool handled = false; 975192a1acfSDavid Herrmann 976192a1acfSDavid Herrmann if (size < 1) 977192a1acfSDavid Herrmann return -EINVAL; 978192a1acfSDavid Herrmann 979192a1acfSDavid Herrmann spin_lock_irqsave(&wdata->state.lock, flags); 980192a1acfSDavid Herrmann 981192a1acfSDavid Herrmann for (i = 0; handlers[i].id; ++i) { 982192a1acfSDavid Herrmann h = &handlers[i]; 983192a1acfSDavid Herrmann if (h->id == raw_data[0] && h->size < size) { 984192a1acfSDavid Herrmann h->func(wdata, &raw_data[1]); 985192a1acfSDavid Herrmann handled = true; 986192a1acfSDavid Herrmann } 987192a1acfSDavid Herrmann } 988192a1acfSDavid Herrmann 989192a1acfSDavid Herrmann if (!handled) 990192a1acfSDavid Herrmann hid_warn(hdev, "Unhandled report %hhu size %d\n", raw_data[0], 991192a1acfSDavid Herrmann size); 992192a1acfSDavid Herrmann 993192a1acfSDavid Herrmann spin_unlock_irqrestore(&wdata->state.lock, flags); 994192a1acfSDavid Herrmann 995192a1acfSDavid Herrmann return 0; 996192a1acfSDavid Herrmann } 997192a1acfSDavid Herrmann 998192a1acfSDavid Herrmann static void wiimote_leds_destroy(struct wiimote_data *wdata) 999192a1acfSDavid Herrmann { 1000192a1acfSDavid Herrmann int i; 1001192a1acfSDavid Herrmann struct led_classdev *led; 1002192a1acfSDavid Herrmann 1003192a1acfSDavid Herrmann for (i = 0; i < 4; ++i) { 1004192a1acfSDavid Herrmann if (wdata->leds[i]) { 1005192a1acfSDavid Herrmann led = wdata->leds[i]; 1006192a1acfSDavid Herrmann wdata->leds[i] = NULL; 1007192a1acfSDavid Herrmann led_classdev_unregister(led); 1008192a1acfSDavid Herrmann kfree(led); 1009192a1acfSDavid Herrmann } 1010192a1acfSDavid Herrmann } 1011192a1acfSDavid Herrmann } 1012192a1acfSDavid Herrmann 1013192a1acfSDavid Herrmann static int wiimote_leds_create(struct wiimote_data *wdata) 1014192a1acfSDavid Herrmann { 1015192a1acfSDavid Herrmann int i, ret; 1016192a1acfSDavid Herrmann struct device *dev = &wdata->hdev->dev; 1017192a1acfSDavid Herrmann size_t namesz = strlen(dev_name(dev)) + 9; 1018192a1acfSDavid Herrmann struct led_classdev *led; 1019192a1acfSDavid Herrmann char *name; 1020192a1acfSDavid Herrmann 1021192a1acfSDavid Herrmann for (i = 0; i < 4; ++i) { 1022192a1acfSDavid Herrmann led = kzalloc(sizeof(struct led_classdev) + namesz, GFP_KERNEL); 1023192a1acfSDavid Herrmann if (!led) { 1024192a1acfSDavid Herrmann ret = -ENOMEM; 1025192a1acfSDavid Herrmann goto err; 1026192a1acfSDavid Herrmann } 1027192a1acfSDavid Herrmann name = (void*)&led[1]; 1028192a1acfSDavid Herrmann snprintf(name, namesz, "%s:blue:p%d", dev_name(dev), i); 1029192a1acfSDavid Herrmann led->name = name; 1030192a1acfSDavid Herrmann led->brightness = 0; 1031192a1acfSDavid Herrmann led->max_brightness = 1; 1032192a1acfSDavid Herrmann led->brightness_get = wiimote_leds_get; 1033192a1acfSDavid Herrmann led->brightness_set = wiimote_leds_set; 1034192a1acfSDavid Herrmann 1035192a1acfSDavid Herrmann ret = led_classdev_register(dev, led); 1036192a1acfSDavid Herrmann if (ret) { 1037192a1acfSDavid Herrmann kfree(led); 1038192a1acfSDavid Herrmann goto err; 1039192a1acfSDavid Herrmann } 1040192a1acfSDavid Herrmann wdata->leds[i] = led; 1041192a1acfSDavid Herrmann } 1042192a1acfSDavid Herrmann 1043192a1acfSDavid Herrmann return 0; 1044192a1acfSDavid Herrmann 1045192a1acfSDavid Herrmann err: 1046192a1acfSDavid Herrmann wiimote_leds_destroy(wdata); 1047192a1acfSDavid Herrmann return ret; 1048192a1acfSDavid Herrmann } 1049192a1acfSDavid Herrmann 1050192a1acfSDavid Herrmann static struct wiimote_data *wiimote_create(struct hid_device *hdev) 1051192a1acfSDavid Herrmann { 1052192a1acfSDavid Herrmann struct wiimote_data *wdata; 1053192a1acfSDavid Herrmann int i; 1054192a1acfSDavid Herrmann 1055192a1acfSDavid Herrmann wdata = kzalloc(sizeof(*wdata), GFP_KERNEL); 1056192a1acfSDavid Herrmann if (!wdata) 1057192a1acfSDavid Herrmann return NULL; 1058192a1acfSDavid Herrmann 1059192a1acfSDavid Herrmann wdata->input = input_allocate_device(); 1060192a1acfSDavid Herrmann if (!wdata->input) 1061192a1acfSDavid Herrmann goto err; 1062192a1acfSDavid Herrmann 1063192a1acfSDavid Herrmann wdata->hdev = hdev; 1064192a1acfSDavid Herrmann hid_set_drvdata(hdev, wdata); 1065192a1acfSDavid Herrmann 1066192a1acfSDavid Herrmann input_set_drvdata(wdata->input, wdata); 1067192a1acfSDavid Herrmann wdata->input->open = wiimote_input_open; 1068192a1acfSDavid Herrmann wdata->input->close = wiimote_input_close; 1069192a1acfSDavid Herrmann wdata->input->dev.parent = &wdata->hdev->dev; 1070192a1acfSDavid Herrmann wdata->input->id.bustype = wdata->hdev->bus; 1071192a1acfSDavid Herrmann wdata->input->id.vendor = wdata->hdev->vendor; 1072192a1acfSDavid Herrmann wdata->input->id.product = wdata->hdev->product; 1073192a1acfSDavid Herrmann wdata->input->id.version = wdata->hdev->version; 1074192a1acfSDavid Herrmann wdata->input->name = WIIMOTE_NAME; 1075192a1acfSDavid Herrmann 1076192a1acfSDavid Herrmann set_bit(EV_KEY, wdata->input->evbit); 1077192a1acfSDavid Herrmann for (i = 0; i < WIIPROTO_KEY_COUNT; ++i) 1078192a1acfSDavid Herrmann set_bit(wiiproto_keymap[i], wdata->input->keybit); 1079192a1acfSDavid Herrmann 1080192a1acfSDavid Herrmann set_bit(FF_RUMBLE, wdata->input->ffbit); 1081192a1acfSDavid Herrmann if (input_ff_create_memless(wdata->input, NULL, wiimote_ff_play)) 1082192a1acfSDavid Herrmann goto err_input; 1083192a1acfSDavid Herrmann 1084192a1acfSDavid Herrmann wdata->accel = input_allocate_device(); 1085192a1acfSDavid Herrmann if (!wdata->accel) 1086192a1acfSDavid Herrmann goto err_input; 1087192a1acfSDavid Herrmann 1088192a1acfSDavid Herrmann input_set_drvdata(wdata->accel, wdata); 1089192a1acfSDavid Herrmann wdata->accel->open = wiimote_accel_open; 1090192a1acfSDavid Herrmann wdata->accel->close = wiimote_accel_close; 1091192a1acfSDavid Herrmann wdata->accel->dev.parent = &wdata->hdev->dev; 1092192a1acfSDavid Herrmann wdata->accel->id.bustype = wdata->hdev->bus; 1093192a1acfSDavid Herrmann wdata->accel->id.vendor = wdata->hdev->vendor; 1094192a1acfSDavid Herrmann wdata->accel->id.product = wdata->hdev->product; 1095192a1acfSDavid Herrmann wdata->accel->id.version = wdata->hdev->version; 1096192a1acfSDavid Herrmann wdata->accel->name = WIIMOTE_NAME " Accelerometer"; 1097192a1acfSDavid Herrmann 1098192a1acfSDavid Herrmann set_bit(EV_ABS, wdata->accel->evbit); 1099192a1acfSDavid Herrmann set_bit(ABS_RX, wdata->accel->absbit); 1100192a1acfSDavid Herrmann set_bit(ABS_RY, wdata->accel->absbit); 1101192a1acfSDavid Herrmann set_bit(ABS_RZ, wdata->accel->absbit); 1102192a1acfSDavid Herrmann input_set_abs_params(wdata->accel, ABS_RX, -500, 500, 2, 4); 1103192a1acfSDavid Herrmann input_set_abs_params(wdata->accel, ABS_RY, -500, 500, 2, 4); 1104192a1acfSDavid Herrmann input_set_abs_params(wdata->accel, ABS_RZ, -500, 500, 2, 4); 1105192a1acfSDavid Herrmann 1106192a1acfSDavid Herrmann wdata->ir = input_allocate_device(); 1107192a1acfSDavid Herrmann if (!wdata->ir) 1108192a1acfSDavid Herrmann goto err_ir; 1109192a1acfSDavid Herrmann 1110192a1acfSDavid Herrmann input_set_drvdata(wdata->ir, wdata); 1111192a1acfSDavid Herrmann wdata->ir->open = wiimote_ir_open; 1112192a1acfSDavid Herrmann wdata->ir->close = wiimote_ir_close; 1113192a1acfSDavid Herrmann wdata->ir->dev.parent = &wdata->hdev->dev; 1114192a1acfSDavid Herrmann wdata->ir->id.bustype = wdata->hdev->bus; 1115192a1acfSDavid Herrmann wdata->ir->id.vendor = wdata->hdev->vendor; 1116192a1acfSDavid Herrmann wdata->ir->id.product = wdata->hdev->product; 1117192a1acfSDavid Herrmann wdata->ir->id.version = wdata->hdev->version; 1118192a1acfSDavid Herrmann wdata->ir->name = WIIMOTE_NAME " IR"; 1119192a1acfSDavid Herrmann 1120192a1acfSDavid Herrmann set_bit(EV_ABS, wdata->ir->evbit); 1121192a1acfSDavid Herrmann set_bit(ABS_HAT0X, wdata->ir->absbit); 1122192a1acfSDavid Herrmann set_bit(ABS_HAT0Y, wdata->ir->absbit); 1123192a1acfSDavid Herrmann set_bit(ABS_HAT1X, wdata->ir->absbit); 1124192a1acfSDavid Herrmann set_bit(ABS_HAT1Y, wdata->ir->absbit); 1125192a1acfSDavid Herrmann set_bit(ABS_HAT2X, wdata->ir->absbit); 1126192a1acfSDavid Herrmann set_bit(ABS_HAT2Y, wdata->ir->absbit); 1127192a1acfSDavid Herrmann set_bit(ABS_HAT3X, wdata->ir->absbit); 1128192a1acfSDavid Herrmann set_bit(ABS_HAT3Y, wdata->ir->absbit); 1129192a1acfSDavid Herrmann input_set_abs_params(wdata->ir, ABS_HAT0X, 0, 1023, 2, 4); 1130192a1acfSDavid Herrmann input_set_abs_params(wdata->ir, ABS_HAT0Y, 0, 767, 2, 4); 1131192a1acfSDavid Herrmann input_set_abs_params(wdata->ir, ABS_HAT1X, 0, 1023, 2, 4); 1132192a1acfSDavid Herrmann input_set_abs_params(wdata->ir, ABS_HAT1Y, 0, 767, 2, 4); 1133192a1acfSDavid Herrmann input_set_abs_params(wdata->ir, ABS_HAT2X, 0, 1023, 2, 4); 1134192a1acfSDavid Herrmann input_set_abs_params(wdata->ir, ABS_HAT2Y, 0, 767, 2, 4); 1135192a1acfSDavid Herrmann input_set_abs_params(wdata->ir, ABS_HAT3X, 0, 1023, 2, 4); 1136192a1acfSDavid Herrmann input_set_abs_params(wdata->ir, ABS_HAT3Y, 0, 767, 2, 4); 1137192a1acfSDavid Herrmann 1138192a1acfSDavid Herrmann spin_lock_init(&wdata->qlock); 1139192a1acfSDavid Herrmann INIT_WORK(&wdata->worker, wiimote_worker); 1140192a1acfSDavid Herrmann 1141192a1acfSDavid Herrmann spin_lock_init(&wdata->state.lock); 1142192a1acfSDavid Herrmann init_completion(&wdata->state.ready); 1143192a1acfSDavid Herrmann mutex_init(&wdata->state.sync); 1144192a1acfSDavid Herrmann 1145192a1acfSDavid Herrmann return wdata; 1146192a1acfSDavid Herrmann 1147192a1acfSDavid Herrmann err_ir: 1148192a1acfSDavid Herrmann input_free_device(wdata->accel); 1149192a1acfSDavid Herrmann err_input: 1150192a1acfSDavid Herrmann input_free_device(wdata->input); 1151192a1acfSDavid Herrmann err: 1152192a1acfSDavid Herrmann kfree(wdata); 1153192a1acfSDavid Herrmann return NULL; 1154192a1acfSDavid Herrmann } 1155192a1acfSDavid Herrmann 1156192a1acfSDavid Herrmann static void wiimote_destroy(struct wiimote_data *wdata) 1157192a1acfSDavid Herrmann { 115843e5e7c6SDavid Herrmann wiidebug_deinit(wdata); 1159cb99221bSDavid Herrmann wiiext_deinit(wdata); 1160192a1acfSDavid Herrmann wiimote_leds_destroy(wdata); 1161192a1acfSDavid Herrmann 1162192a1acfSDavid Herrmann power_supply_unregister(&wdata->battery); 1163192a1acfSDavid Herrmann input_unregister_device(wdata->accel); 1164192a1acfSDavid Herrmann input_unregister_device(wdata->ir); 1165192a1acfSDavid Herrmann input_unregister_device(wdata->input); 1166192a1acfSDavid Herrmann cancel_work_sync(&wdata->worker); 1167192a1acfSDavid Herrmann hid_hw_stop(wdata->hdev); 1168192a1acfSDavid Herrmann 1169192a1acfSDavid Herrmann kfree(wdata); 1170192a1acfSDavid Herrmann } 1171192a1acfSDavid Herrmann 1172192a1acfSDavid Herrmann static int wiimote_hid_probe(struct hid_device *hdev, 1173192a1acfSDavid Herrmann const struct hid_device_id *id) 1174192a1acfSDavid Herrmann { 1175192a1acfSDavid Herrmann struct wiimote_data *wdata; 1176192a1acfSDavid Herrmann int ret; 1177192a1acfSDavid Herrmann 1178192a1acfSDavid Herrmann wdata = wiimote_create(hdev); 1179192a1acfSDavid Herrmann if (!wdata) { 1180192a1acfSDavid Herrmann hid_err(hdev, "Can't alloc device\n"); 1181192a1acfSDavid Herrmann return -ENOMEM; 1182192a1acfSDavid Herrmann } 1183192a1acfSDavid Herrmann 1184192a1acfSDavid Herrmann ret = hid_parse(hdev); 1185192a1acfSDavid Herrmann if (ret) { 1186192a1acfSDavid Herrmann hid_err(hdev, "HID parse failed\n"); 1187192a1acfSDavid Herrmann goto err; 1188192a1acfSDavid Herrmann } 1189192a1acfSDavid Herrmann 1190192a1acfSDavid Herrmann ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW); 1191192a1acfSDavid Herrmann if (ret) { 1192192a1acfSDavid Herrmann hid_err(hdev, "HW start failed\n"); 1193192a1acfSDavid Herrmann goto err; 1194192a1acfSDavid Herrmann } 1195192a1acfSDavid Herrmann 1196192a1acfSDavid Herrmann ret = input_register_device(wdata->accel); 1197192a1acfSDavid Herrmann if (ret) { 1198192a1acfSDavid Herrmann hid_err(hdev, "Cannot register input device\n"); 1199192a1acfSDavid Herrmann goto err_stop; 1200192a1acfSDavid Herrmann } 1201192a1acfSDavid Herrmann 1202192a1acfSDavid Herrmann ret = input_register_device(wdata->ir); 1203192a1acfSDavid Herrmann if (ret) { 1204192a1acfSDavid Herrmann hid_err(hdev, "Cannot register input device\n"); 1205192a1acfSDavid Herrmann goto err_ir; 1206192a1acfSDavid Herrmann } 1207192a1acfSDavid Herrmann 1208192a1acfSDavid Herrmann ret = input_register_device(wdata->input); 1209192a1acfSDavid Herrmann if (ret) { 1210192a1acfSDavid Herrmann hid_err(hdev, "Cannot register input device\n"); 1211192a1acfSDavid Herrmann goto err_input; 1212192a1acfSDavid Herrmann } 1213192a1acfSDavid Herrmann 1214192a1acfSDavid Herrmann wdata->battery.properties = wiimote_battery_props; 1215192a1acfSDavid Herrmann wdata->battery.num_properties = ARRAY_SIZE(wiimote_battery_props); 1216192a1acfSDavid Herrmann wdata->battery.get_property = wiimote_battery_get_property; 1217192a1acfSDavid Herrmann wdata->battery.name = "wiimote_battery"; 1218192a1acfSDavid Herrmann wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY; 1219192a1acfSDavid Herrmann wdata->battery.use_for_apm = 0; 1220192a1acfSDavid Herrmann 1221192a1acfSDavid Herrmann ret = power_supply_register(&wdata->hdev->dev, &wdata->battery); 1222192a1acfSDavid Herrmann if (ret) { 1223192a1acfSDavid Herrmann hid_err(hdev, "Cannot register battery device\n"); 1224192a1acfSDavid Herrmann goto err_battery; 1225192a1acfSDavid Herrmann } 1226192a1acfSDavid Herrmann 1227192a1acfSDavid Herrmann ret = wiimote_leds_create(wdata); 1228192a1acfSDavid Herrmann if (ret) 1229192a1acfSDavid Herrmann goto err_free; 1230192a1acfSDavid Herrmann 1231cb99221bSDavid Herrmann ret = wiiext_init(wdata); 1232cb99221bSDavid Herrmann if (ret) 1233cb99221bSDavid Herrmann goto err_free; 1234cb99221bSDavid Herrmann 123543e5e7c6SDavid Herrmann ret = wiidebug_init(wdata); 123643e5e7c6SDavid Herrmann if (ret) 123743e5e7c6SDavid Herrmann goto err_free; 123843e5e7c6SDavid Herrmann 1239192a1acfSDavid Herrmann hid_info(hdev, "New device registered\n"); 1240192a1acfSDavid Herrmann 1241192a1acfSDavid Herrmann /* by default set led1 after device initialization */ 1242192a1acfSDavid Herrmann spin_lock_irq(&wdata->state.lock); 1243192a1acfSDavid Herrmann wiiproto_req_leds(wdata, WIIPROTO_FLAG_LED1); 1244192a1acfSDavid Herrmann spin_unlock_irq(&wdata->state.lock); 1245192a1acfSDavid Herrmann 1246192a1acfSDavid Herrmann return 0; 1247192a1acfSDavid Herrmann 1248192a1acfSDavid Herrmann err_free: 1249192a1acfSDavid Herrmann wiimote_destroy(wdata); 1250192a1acfSDavid Herrmann return ret; 1251192a1acfSDavid Herrmann 1252192a1acfSDavid Herrmann err_battery: 1253192a1acfSDavid Herrmann input_unregister_device(wdata->input); 1254192a1acfSDavid Herrmann wdata->input = NULL; 1255192a1acfSDavid Herrmann err_input: 1256192a1acfSDavid Herrmann input_unregister_device(wdata->ir); 1257192a1acfSDavid Herrmann wdata->ir = NULL; 1258192a1acfSDavid Herrmann err_ir: 1259192a1acfSDavid Herrmann input_unregister_device(wdata->accel); 1260192a1acfSDavid Herrmann wdata->accel = NULL; 1261192a1acfSDavid Herrmann err_stop: 1262192a1acfSDavid Herrmann hid_hw_stop(hdev); 1263192a1acfSDavid Herrmann err: 1264192a1acfSDavid Herrmann input_free_device(wdata->ir); 1265192a1acfSDavid Herrmann input_free_device(wdata->accel); 1266192a1acfSDavid Herrmann input_free_device(wdata->input); 1267192a1acfSDavid Herrmann kfree(wdata); 1268192a1acfSDavid Herrmann return ret; 1269192a1acfSDavid Herrmann } 1270192a1acfSDavid Herrmann 1271192a1acfSDavid Herrmann static void wiimote_hid_remove(struct hid_device *hdev) 1272192a1acfSDavid Herrmann { 1273192a1acfSDavid Herrmann struct wiimote_data *wdata = hid_get_drvdata(hdev); 1274192a1acfSDavid Herrmann 1275192a1acfSDavid Herrmann hid_info(hdev, "Device removed\n"); 1276192a1acfSDavid Herrmann wiimote_destroy(wdata); 1277192a1acfSDavid Herrmann } 1278192a1acfSDavid Herrmann 1279192a1acfSDavid Herrmann static const struct hid_device_id wiimote_hid_devices[] = { 1280192a1acfSDavid Herrmann { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, 1281192a1acfSDavid Herrmann USB_DEVICE_ID_NINTENDO_WIIMOTE) }, 1282192a1acfSDavid Herrmann { } 1283192a1acfSDavid Herrmann }; 1284192a1acfSDavid Herrmann MODULE_DEVICE_TABLE(hid, wiimote_hid_devices); 1285192a1acfSDavid Herrmann 1286192a1acfSDavid Herrmann static struct hid_driver wiimote_hid_driver = { 1287192a1acfSDavid Herrmann .name = "wiimote", 1288192a1acfSDavid Herrmann .id_table = wiimote_hid_devices, 1289192a1acfSDavid Herrmann .probe = wiimote_hid_probe, 1290192a1acfSDavid Herrmann .remove = wiimote_hid_remove, 1291192a1acfSDavid Herrmann .raw_event = wiimote_hid_event, 1292192a1acfSDavid Herrmann }; 1293192a1acfSDavid Herrmann 1294192a1acfSDavid Herrmann static int __init wiimote_init(void) 1295192a1acfSDavid Herrmann { 1296192a1acfSDavid Herrmann int ret; 1297192a1acfSDavid Herrmann 1298192a1acfSDavid Herrmann ret = hid_register_driver(&wiimote_hid_driver); 1299192a1acfSDavid Herrmann if (ret) 1300192a1acfSDavid Herrmann pr_err("Can't register wiimote hid driver\n"); 1301192a1acfSDavid Herrmann 1302192a1acfSDavid Herrmann return ret; 1303192a1acfSDavid Herrmann } 1304192a1acfSDavid Herrmann 1305192a1acfSDavid Herrmann static void __exit wiimote_exit(void) 1306192a1acfSDavid Herrmann { 1307192a1acfSDavid Herrmann hid_unregister_driver(&wiimote_hid_driver); 1308192a1acfSDavid Herrmann } 1309192a1acfSDavid Herrmann 1310192a1acfSDavid Herrmann module_init(wiimote_init); 1311192a1acfSDavid Herrmann module_exit(wiimote_exit); 1312192a1acfSDavid Herrmann MODULE_LICENSE("GPL"); 1313192a1acfSDavid Herrmann MODULE_AUTHOR("David Herrmann <dh.herrmann@gmail.com>"); 1314192a1acfSDavid Herrmann MODULE_DESCRIPTION(WIIMOTE_NAME " Device Driver"); 1315192a1acfSDavid Herrmann MODULE_VERSION(WIIMOTE_VERSION); 1316