0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/module.h>
0009 #include <linux/acpi.h>
0010 #include <linux/rfkill.h>
0011 #include <linux/input.h>
0012
0013 #include "dell-rbtn.h"
0014
0015 enum rbtn_type {
0016 RBTN_UNKNOWN,
0017 RBTN_TOGGLE,
0018 RBTN_SLIDER,
0019 };
0020
0021 struct rbtn_data {
0022 enum rbtn_type type;
0023 struct rfkill *rfkill;
0024 struct input_dev *input_dev;
0025 bool suspended;
0026 };
0027
0028
0029
0030
0031
0032
0033 static enum rbtn_type rbtn_check(struct acpi_device *device)
0034 {
0035 unsigned long long output;
0036 acpi_status status;
0037
0038 status = acpi_evaluate_integer(device->handle, "CRBT", NULL, &output);
0039 if (ACPI_FAILURE(status))
0040 return RBTN_UNKNOWN;
0041
0042 switch (output) {
0043 case 0:
0044 case 1:
0045 return RBTN_TOGGLE;
0046 case 2:
0047 case 3:
0048 return RBTN_SLIDER;
0049 default:
0050 return RBTN_UNKNOWN;
0051 }
0052 }
0053
0054 static int rbtn_get(struct acpi_device *device)
0055 {
0056 unsigned long long output;
0057 acpi_status status;
0058
0059 status = acpi_evaluate_integer(device->handle, "GRBT", NULL, &output);
0060 if (ACPI_FAILURE(status))
0061 return -EINVAL;
0062
0063 return !output;
0064 }
0065
0066 static int rbtn_acquire(struct acpi_device *device, bool enable)
0067 {
0068 struct acpi_object_list input;
0069 union acpi_object param;
0070 acpi_status status;
0071
0072 param.type = ACPI_TYPE_INTEGER;
0073 param.integer.value = enable;
0074 input.count = 1;
0075 input.pointer = ¶m;
0076
0077 status = acpi_evaluate_object(device->handle, "ARBT", &input, NULL);
0078 if (ACPI_FAILURE(status))
0079 return -EINVAL;
0080
0081 return 0;
0082 }
0083
0084
0085
0086
0087
0088
0089 static void rbtn_rfkill_query(struct rfkill *rfkill, void *data)
0090 {
0091 struct acpi_device *device = data;
0092 int state;
0093
0094 state = rbtn_get(device);
0095 if (state < 0)
0096 return;
0097
0098 rfkill_set_states(rfkill, state, state);
0099 }
0100
0101 static int rbtn_rfkill_set_block(void *data, bool blocked)
0102 {
0103
0104 return -EINVAL;
0105 }
0106
0107 static const struct rfkill_ops rbtn_ops = {
0108 .query = rbtn_rfkill_query,
0109 .set_block = rbtn_rfkill_set_block,
0110 };
0111
0112 static int rbtn_rfkill_init(struct acpi_device *device)
0113 {
0114 struct rbtn_data *rbtn_data = device->driver_data;
0115 int ret;
0116
0117 if (rbtn_data->rfkill)
0118 return 0;
0119
0120
0121
0122
0123
0124
0125 rbtn_data->rfkill = rfkill_alloc("dell-rbtn", &device->dev,
0126 RFKILL_TYPE_WLAN, &rbtn_ops, device);
0127 if (!rbtn_data->rfkill)
0128 return -ENOMEM;
0129
0130 ret = rfkill_register(rbtn_data->rfkill);
0131 if (ret) {
0132 rfkill_destroy(rbtn_data->rfkill);
0133 rbtn_data->rfkill = NULL;
0134 return ret;
0135 }
0136
0137 return 0;
0138 }
0139
0140 static void rbtn_rfkill_exit(struct acpi_device *device)
0141 {
0142 struct rbtn_data *rbtn_data = device->driver_data;
0143
0144 if (!rbtn_data->rfkill)
0145 return;
0146
0147 rfkill_unregister(rbtn_data->rfkill);
0148 rfkill_destroy(rbtn_data->rfkill);
0149 rbtn_data->rfkill = NULL;
0150 }
0151
0152 static void rbtn_rfkill_event(struct acpi_device *device)
0153 {
0154 struct rbtn_data *rbtn_data = device->driver_data;
0155
0156 if (rbtn_data->rfkill)
0157 rbtn_rfkill_query(rbtn_data->rfkill, device);
0158 }
0159
0160
0161
0162
0163
0164
0165 static int rbtn_input_init(struct rbtn_data *rbtn_data)
0166 {
0167 int ret;
0168
0169 rbtn_data->input_dev = input_allocate_device();
0170 if (!rbtn_data->input_dev)
0171 return -ENOMEM;
0172
0173 rbtn_data->input_dev->name = "DELL Wireless hotkeys";
0174 rbtn_data->input_dev->phys = "dellabce/input0";
0175 rbtn_data->input_dev->id.bustype = BUS_HOST;
0176 rbtn_data->input_dev->evbit[0] = BIT(EV_KEY);
0177 set_bit(KEY_RFKILL, rbtn_data->input_dev->keybit);
0178
0179 ret = input_register_device(rbtn_data->input_dev);
0180 if (ret) {
0181 input_free_device(rbtn_data->input_dev);
0182 rbtn_data->input_dev = NULL;
0183 return ret;
0184 }
0185
0186 return 0;
0187 }
0188
0189 static void rbtn_input_exit(struct rbtn_data *rbtn_data)
0190 {
0191 input_unregister_device(rbtn_data->input_dev);
0192 rbtn_data->input_dev = NULL;
0193 }
0194
0195 static void rbtn_input_event(struct rbtn_data *rbtn_data)
0196 {
0197 input_report_key(rbtn_data->input_dev, KEY_RFKILL, 1);
0198 input_sync(rbtn_data->input_dev);
0199 input_report_key(rbtn_data->input_dev, KEY_RFKILL, 0);
0200 input_sync(rbtn_data->input_dev);
0201 }
0202
0203
0204
0205
0206
0207
0208 static int rbtn_add(struct acpi_device *device);
0209 static int rbtn_remove(struct acpi_device *device);
0210 static void rbtn_notify(struct acpi_device *device, u32 event);
0211
0212 static const struct acpi_device_id rbtn_ids[] = {
0213 { "DELRBTN", 0 },
0214 { "DELLABCE", 0 },
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241 { "", 0 },
0242 };
0243
0244 #ifdef CONFIG_PM_SLEEP
0245 static void ACPI_SYSTEM_XFACE rbtn_clear_suspended_flag(void *context)
0246 {
0247 struct rbtn_data *rbtn_data = context;
0248
0249 rbtn_data->suspended = false;
0250 }
0251
0252 static int rbtn_suspend(struct device *dev)
0253 {
0254 struct acpi_device *device = to_acpi_device(dev);
0255 struct rbtn_data *rbtn_data = acpi_driver_data(device);
0256
0257 rbtn_data->suspended = true;
0258
0259 return 0;
0260 }
0261
0262 static int rbtn_resume(struct device *dev)
0263 {
0264 struct acpi_device *device = to_acpi_device(dev);
0265 struct rbtn_data *rbtn_data = acpi_driver_data(device);
0266 acpi_status status;
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278 status = acpi_os_execute(OSL_NOTIFY_HANDLER,
0279 rbtn_clear_suspended_flag, rbtn_data);
0280 if (ACPI_FAILURE(status))
0281 rbtn_clear_suspended_flag(rbtn_data);
0282
0283 return 0;
0284 }
0285 #endif
0286
0287 static SIMPLE_DEV_PM_OPS(rbtn_pm_ops, rbtn_suspend, rbtn_resume);
0288
0289 static struct acpi_driver rbtn_driver = {
0290 .name = "dell-rbtn",
0291 .ids = rbtn_ids,
0292 .drv.pm = &rbtn_pm_ops,
0293 .ops = {
0294 .add = rbtn_add,
0295 .remove = rbtn_remove,
0296 .notify = rbtn_notify,
0297 },
0298 .owner = THIS_MODULE,
0299 };
0300
0301
0302
0303
0304
0305
0306 static bool auto_remove_rfkill = true;
0307
0308 static ATOMIC_NOTIFIER_HEAD(rbtn_chain_head);
0309
0310 static int rbtn_inc_count(struct device *dev, void *data)
0311 {
0312 struct acpi_device *device = to_acpi_device(dev);
0313 struct rbtn_data *rbtn_data = device->driver_data;
0314 int *count = data;
0315
0316 if (rbtn_data->type == RBTN_SLIDER)
0317 (*count)++;
0318
0319 return 0;
0320 }
0321
0322 static int rbtn_switch_dev(struct device *dev, void *data)
0323 {
0324 struct acpi_device *device = to_acpi_device(dev);
0325 struct rbtn_data *rbtn_data = device->driver_data;
0326 bool enable = data;
0327
0328 if (rbtn_data->type != RBTN_SLIDER)
0329 return 0;
0330
0331 if (enable)
0332 rbtn_rfkill_init(device);
0333 else
0334 rbtn_rfkill_exit(device);
0335
0336 return 0;
0337 }
0338
0339 int dell_rbtn_notifier_register(struct notifier_block *nb)
0340 {
0341 bool first;
0342 int count;
0343 int ret;
0344
0345 count = 0;
0346 ret = driver_for_each_device(&rbtn_driver.drv, NULL, &count,
0347 rbtn_inc_count);
0348 if (ret || count == 0)
0349 return -ENODEV;
0350
0351 first = !rbtn_chain_head.head;
0352
0353 ret = atomic_notifier_chain_register(&rbtn_chain_head, nb);
0354 if (ret != 0)
0355 return ret;
0356
0357 if (auto_remove_rfkill && first)
0358 ret = driver_for_each_device(&rbtn_driver.drv, NULL,
0359 (void *)false, rbtn_switch_dev);
0360
0361 return ret;
0362 }
0363 EXPORT_SYMBOL_GPL(dell_rbtn_notifier_register);
0364
0365 int dell_rbtn_notifier_unregister(struct notifier_block *nb)
0366 {
0367 int ret;
0368
0369 ret = atomic_notifier_chain_unregister(&rbtn_chain_head, nb);
0370 if (ret != 0)
0371 return ret;
0372
0373 if (auto_remove_rfkill && !rbtn_chain_head.head)
0374 ret = driver_for_each_device(&rbtn_driver.drv, NULL,
0375 (void *)true, rbtn_switch_dev);
0376
0377 return ret;
0378 }
0379 EXPORT_SYMBOL_GPL(dell_rbtn_notifier_unregister);
0380
0381
0382
0383
0384
0385
0386 static int rbtn_add(struct acpi_device *device)
0387 {
0388 struct rbtn_data *rbtn_data;
0389 enum rbtn_type type;
0390 int ret = 0;
0391
0392 type = rbtn_check(device);
0393 if (type == RBTN_UNKNOWN) {
0394 dev_info(&device->dev, "Unknown device type\n");
0395 return -EINVAL;
0396 }
0397
0398 ret = rbtn_acquire(device, true);
0399 if (ret < 0) {
0400 dev_err(&device->dev, "Cannot enable device\n");
0401 return ret;
0402 }
0403
0404 rbtn_data = devm_kzalloc(&device->dev, sizeof(*rbtn_data), GFP_KERNEL);
0405 if (!rbtn_data)
0406 return -ENOMEM;
0407
0408 rbtn_data->type = type;
0409 device->driver_data = rbtn_data;
0410
0411 switch (rbtn_data->type) {
0412 case RBTN_TOGGLE:
0413 ret = rbtn_input_init(rbtn_data);
0414 break;
0415 case RBTN_SLIDER:
0416 if (auto_remove_rfkill && rbtn_chain_head.head)
0417 ret = 0;
0418 else
0419 ret = rbtn_rfkill_init(device);
0420 break;
0421 default:
0422 ret = -EINVAL;
0423 }
0424
0425 return ret;
0426
0427 }
0428
0429 static int rbtn_remove(struct acpi_device *device)
0430 {
0431 struct rbtn_data *rbtn_data = device->driver_data;
0432
0433 switch (rbtn_data->type) {
0434 case RBTN_TOGGLE:
0435 rbtn_input_exit(rbtn_data);
0436 break;
0437 case RBTN_SLIDER:
0438 rbtn_rfkill_exit(device);
0439 break;
0440 default:
0441 break;
0442 }
0443
0444 rbtn_acquire(device, false);
0445 device->driver_data = NULL;
0446
0447 return 0;
0448 }
0449
0450 static void rbtn_notify(struct acpi_device *device, u32 event)
0451 {
0452 struct rbtn_data *rbtn_data = device->driver_data;
0453
0454
0455
0456
0457
0458 if (rbtn_data->suspended) {
0459 dev_dbg(&device->dev, "ACPI notification ignored\n");
0460 return;
0461 }
0462
0463 if (event != 0x80) {
0464 dev_info(&device->dev, "Received unknown event (0x%x)\n",
0465 event);
0466 return;
0467 }
0468
0469 switch (rbtn_data->type) {
0470 case RBTN_TOGGLE:
0471 rbtn_input_event(rbtn_data);
0472 break;
0473 case RBTN_SLIDER:
0474 rbtn_rfkill_event(device);
0475 atomic_notifier_call_chain(&rbtn_chain_head, event, device);
0476 break;
0477 default:
0478 break;
0479 }
0480 }
0481
0482
0483
0484
0485
0486
0487 module_acpi_driver(rbtn_driver);
0488
0489 module_param(auto_remove_rfkill, bool, 0444);
0490
0491 MODULE_PARM_DESC(auto_remove_rfkill, "Automatically remove rfkill devices when "
0492 "other modules start receiving events "
0493 "from this module and re-add them when "
0494 "the last module stops receiving events "
0495 "(default true)");
0496 MODULE_DEVICE_TABLE(acpi, rbtn_ids);
0497 MODULE_DESCRIPTION("Dell Airplane Mode Switch driver");
0498 MODULE_AUTHOR("Pali Rohár <pali@kernel.org>");
0499 MODULE_LICENSE("GPL");