0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #include <linux/device.h>
0019 #include <linux/hid.h>
0020 #include <linux/module.h>
0021 #include "hid-ids.h"
0022
0023 MODULE_AUTHOR("James McKenzie");
0024 MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@redhat.com>");
0025 MODULE_DESCRIPTION("HID Apple IR remote controls");
0026 MODULE_LICENSE("GPL");
0027
0028 #define KEY_MASK 0x0F
0029 #define TWO_PACKETS_MASK 0x40
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087 static const unsigned short appleir_key_table[] = {
0088 KEY_RESERVED,
0089 KEY_MENU,
0090 KEY_PLAYPAUSE,
0091 KEY_FORWARD,
0092 KEY_BACK,
0093 KEY_VOLUMEUP,
0094 KEY_VOLUMEDOWN,
0095 KEY_RESERVED,
0096 KEY_RESERVED,
0097 KEY_RESERVED,
0098 KEY_RESERVED,
0099 KEY_RESERVED,
0100 KEY_RESERVED,
0101 KEY_RESERVED,
0102 KEY_ENTER,
0103 KEY_PLAYPAUSE,
0104 KEY_RESERVED,
0105 };
0106
0107 struct appleir {
0108 struct input_dev *input_dev;
0109 struct hid_device *hid;
0110 unsigned short keymap[ARRAY_SIZE(appleir_key_table)];
0111 struct timer_list key_up_timer;
0112 spinlock_t lock;
0113 int current_key;
0114 int prev_key_idx;
0115 };
0116
0117 static int get_key(int data)
0118 {
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142 int key = (data >> 1) & KEY_MASK;
0143
0144 if ((data & TWO_PACKETS_MASK))
0145
0146 key = -key;
0147
0148 return key;
0149 }
0150
0151 static void key_up(struct hid_device *hid, struct appleir *appleir, int key)
0152 {
0153 input_report_key(appleir->input_dev, key, 0);
0154 input_sync(appleir->input_dev);
0155 }
0156
0157 static void key_down(struct hid_device *hid, struct appleir *appleir, int key)
0158 {
0159 input_report_key(appleir->input_dev, key, 1);
0160 input_sync(appleir->input_dev);
0161 }
0162
0163 static void battery_flat(struct appleir *appleir)
0164 {
0165 dev_err(&appleir->input_dev->dev, "possible flat battery?\n");
0166 }
0167
0168 static void key_up_tick(struct timer_list *t)
0169 {
0170 struct appleir *appleir = from_timer(appleir, t, key_up_timer);
0171 struct hid_device *hid = appleir->hid;
0172 unsigned long flags;
0173
0174 spin_lock_irqsave(&appleir->lock, flags);
0175 if (appleir->current_key) {
0176 key_up(hid, appleir, appleir->current_key);
0177 appleir->current_key = 0;
0178 }
0179 spin_unlock_irqrestore(&appleir->lock, flags);
0180 }
0181
0182 static int appleir_raw_event(struct hid_device *hid, struct hid_report *report,
0183 u8 *data, int len)
0184 {
0185 struct appleir *appleir = hid_get_drvdata(hid);
0186 static const u8 keydown[] = { 0x25, 0x87, 0xee };
0187 static const u8 keyrepeat[] = { 0x26, };
0188 static const u8 flatbattery[] = { 0x25, 0x87, 0xe0 };
0189 unsigned long flags;
0190
0191 if (len != 5)
0192 goto out;
0193
0194 if (!memcmp(data, keydown, sizeof(keydown))) {
0195 int index;
0196
0197 spin_lock_irqsave(&appleir->lock, flags);
0198
0199
0200
0201
0202 if (appleir->current_key)
0203 key_up(hid, appleir, appleir->current_key);
0204
0205
0206 if (appleir->prev_key_idx > 0)
0207 index = appleir->prev_key_idx;
0208 else
0209 index = get_key(data[4]);
0210
0211 if (index >= 0) {
0212 appleir->current_key = appleir->keymap[index];
0213
0214 key_down(hid, appleir, appleir->current_key);
0215
0216
0217
0218
0219
0220 mod_timer(&appleir->key_up_timer, jiffies + HZ / 8);
0221 appleir->prev_key_idx = 0;
0222 } else
0223
0224 appleir->prev_key_idx = -index;
0225 spin_unlock_irqrestore(&appleir->lock, flags);
0226 goto out;
0227 }
0228
0229 appleir->prev_key_idx = 0;
0230
0231 if (!memcmp(data, keyrepeat, sizeof(keyrepeat))) {
0232 key_down(hid, appleir, appleir->current_key);
0233
0234
0235
0236
0237 mod_timer(&appleir->key_up_timer, jiffies + HZ / 8);
0238 goto out;
0239 }
0240
0241 if (!memcmp(data, flatbattery, sizeof(flatbattery))) {
0242 battery_flat(appleir);
0243
0244 }
0245
0246 out:
0247
0248 return 0;
0249 }
0250
0251 static int appleir_input_configured(struct hid_device *hid,
0252 struct hid_input *hidinput)
0253 {
0254 struct input_dev *input_dev = hidinput->input;
0255 struct appleir *appleir = hid_get_drvdata(hid);
0256 int i;
0257
0258 appleir->input_dev = input_dev;
0259
0260 input_dev->keycode = appleir->keymap;
0261 input_dev->keycodesize = sizeof(unsigned short);
0262 input_dev->keycodemax = ARRAY_SIZE(appleir->keymap);
0263
0264 input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
0265
0266 memcpy(appleir->keymap, appleir_key_table, sizeof(appleir->keymap));
0267 for (i = 0; i < ARRAY_SIZE(appleir_key_table); i++)
0268 set_bit(appleir->keymap[i], input_dev->keybit);
0269 clear_bit(KEY_RESERVED, input_dev->keybit);
0270
0271 return 0;
0272 }
0273
0274 static int appleir_input_mapping(struct hid_device *hid,
0275 struct hid_input *hi, struct hid_field *field,
0276 struct hid_usage *usage, unsigned long **bit, int *max)
0277 {
0278 return -1;
0279 }
0280
0281 static int appleir_probe(struct hid_device *hid, const struct hid_device_id *id)
0282 {
0283 int ret;
0284 struct appleir *appleir;
0285
0286 appleir = devm_kzalloc(&hid->dev, sizeof(struct appleir), GFP_KERNEL);
0287 if (!appleir)
0288 return -ENOMEM;
0289
0290 appleir->hid = hid;
0291
0292
0293 hid->quirks |= HID_QUIRK_HIDINPUT_FORCE;
0294
0295 spin_lock_init(&appleir->lock);
0296 timer_setup(&appleir->key_up_timer, key_up_tick, 0);
0297
0298 hid_set_drvdata(hid, appleir);
0299
0300 ret = hid_parse(hid);
0301 if (ret) {
0302 hid_err(hid, "parse failed\n");
0303 goto fail;
0304 }
0305
0306 ret = hid_hw_start(hid, HID_CONNECT_DEFAULT | HID_CONNECT_HIDDEV_FORCE);
0307 if (ret) {
0308 hid_err(hid, "hw start failed\n");
0309 goto fail;
0310 }
0311
0312 return 0;
0313 fail:
0314 devm_kfree(&hid->dev, appleir);
0315 return ret;
0316 }
0317
0318 static void appleir_remove(struct hid_device *hid)
0319 {
0320 struct appleir *appleir = hid_get_drvdata(hid);
0321 hid_hw_stop(hid);
0322 del_timer_sync(&appleir->key_up_timer);
0323 }
0324
0325 static const struct hid_device_id appleir_devices[] = {
0326 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL) },
0327 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL2) },
0328 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL3) },
0329 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) },
0330 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL5) },
0331 { }
0332 };
0333 MODULE_DEVICE_TABLE(hid, appleir_devices);
0334
0335 static struct hid_driver appleir_driver = {
0336 .name = "appleir",
0337 .id_table = appleir_devices,
0338 .raw_event = appleir_raw_event,
0339 .input_configured = appleir_input_configured,
0340 .probe = appleir_probe,
0341 .remove = appleir_remove,
0342 .input_mapping = appleir_input_mapping,
0343 };
0344 module_hid_driver(appleir_driver);