📄 applesmc.c
字号:
* - show actual speed * - show/store minimum speed * - show maximum speed * - show safe speed * - show/store target speed * - show/store manual mode */#define sysfs_fan_speeds_offset(offset) \static SENSOR_DEVICE_ATTR_2(fan##offset##_input, S_IRUGO, \ applesmc_show_fan_speed, NULL, 0, offset-1); \\static SENSOR_DEVICE_ATTR_2(fan##offset##_min, S_IRUGO | S_IWUSR, \ applesmc_show_fan_speed, applesmc_store_fan_speed, 1, offset-1); \\static SENSOR_DEVICE_ATTR_2(fan##offset##_max, S_IRUGO, \ applesmc_show_fan_speed, NULL, 2, offset-1); \\static SENSOR_DEVICE_ATTR_2(fan##offset##_safe, S_IRUGO, \ applesmc_show_fan_speed, NULL, 3, offset-1); \\static SENSOR_DEVICE_ATTR_2(fan##offset##_output, S_IRUGO | S_IWUSR, \ applesmc_show_fan_speed, applesmc_store_fan_speed, 4, offset-1); \\static SENSOR_DEVICE_ATTR(fan##offset##_manual, S_IRUGO | S_IWUSR, \ applesmc_show_fan_manual, applesmc_store_fan_manual, offset-1); \\static SENSOR_DEVICE_ATTR(fan##offset##_label, S_IRUGO, \ applesmc_show_fan_position, NULL, offset-1); \\static struct attribute *fan##offset##_attributes[] = { \ &sensor_dev_attr_fan##offset##_input.dev_attr.attr, \ &sensor_dev_attr_fan##offset##_min.dev_attr.attr, \ &sensor_dev_attr_fan##offset##_max.dev_attr.attr, \ &sensor_dev_attr_fan##offset##_safe.dev_attr.attr, \ &sensor_dev_attr_fan##offset##_output.dev_attr.attr, \ &sensor_dev_attr_fan##offset##_manual.dev_attr.attr, \ &sensor_dev_attr_fan##offset##_label.dev_attr.attr, \ NULL \};/* * Create the needed functions for each fan using the macro defined above * (4 fans are supported) */sysfs_fan_speeds_offset(1);sysfs_fan_speeds_offset(2);sysfs_fan_speeds_offset(3);sysfs_fan_speeds_offset(4);static const struct attribute_group fan_attribute_groups[] = { { .attrs = fan1_attributes }, { .attrs = fan2_attributes }, { .attrs = fan3_attributes }, { .attrs = fan4_attributes },};/* * Temperature sensors sysfs entries. */static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, applesmc_show_temperature, NULL, 0);static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, applesmc_show_temperature, NULL, 1);static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, applesmc_show_temperature, NULL, 2);static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, applesmc_show_temperature, NULL, 3);static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, applesmc_show_temperature, NULL, 4);static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, applesmc_show_temperature, NULL, 5);static SENSOR_DEVICE_ATTR(temp7_input, S_IRUGO, applesmc_show_temperature, NULL, 6);static SENSOR_DEVICE_ATTR(temp8_input, S_IRUGO, applesmc_show_temperature, NULL, 7);static SENSOR_DEVICE_ATTR(temp9_input, S_IRUGO, applesmc_show_temperature, NULL, 8);static SENSOR_DEVICE_ATTR(temp10_input, S_IRUGO, applesmc_show_temperature, NULL, 9);static SENSOR_DEVICE_ATTR(temp11_input, S_IRUGO, applesmc_show_temperature, NULL, 10);static SENSOR_DEVICE_ATTR(temp12_input, S_IRUGO, applesmc_show_temperature, NULL, 11);static SENSOR_DEVICE_ATTR(temp13_input, S_IRUGO, applesmc_show_temperature, NULL, 12);static SENSOR_DEVICE_ATTR(temp14_input, S_IRUGO, applesmc_show_temperature, NULL, 13);static SENSOR_DEVICE_ATTR(temp15_input, S_IRUGO, applesmc_show_temperature, NULL, 14);static SENSOR_DEVICE_ATTR(temp16_input, S_IRUGO, applesmc_show_temperature, NULL, 15);static SENSOR_DEVICE_ATTR(temp17_input, S_IRUGO, applesmc_show_temperature, NULL, 16);static SENSOR_DEVICE_ATTR(temp18_input, S_IRUGO, applesmc_show_temperature, NULL, 17);static SENSOR_DEVICE_ATTR(temp19_input, S_IRUGO, applesmc_show_temperature, NULL, 18);static SENSOR_DEVICE_ATTR(temp20_input, S_IRUGO, applesmc_show_temperature, NULL, 19);static SENSOR_DEVICE_ATTR(temp21_input, S_IRUGO, applesmc_show_temperature, NULL, 20);static SENSOR_DEVICE_ATTR(temp22_input, S_IRUGO, applesmc_show_temperature, NULL, 21);static SENSOR_DEVICE_ATTR(temp23_input, S_IRUGO, applesmc_show_temperature, NULL, 22);static SENSOR_DEVICE_ATTR(temp24_input, S_IRUGO, applesmc_show_temperature, NULL, 23);static SENSOR_DEVICE_ATTR(temp25_input, S_IRUGO, applesmc_show_temperature, NULL, 24);static SENSOR_DEVICE_ATTR(temp26_input, S_IRUGO, applesmc_show_temperature, NULL, 25);static SENSOR_DEVICE_ATTR(temp27_input, S_IRUGO, applesmc_show_temperature, NULL, 26);static SENSOR_DEVICE_ATTR(temp28_input, S_IRUGO, applesmc_show_temperature, NULL, 27);static SENSOR_DEVICE_ATTR(temp29_input, S_IRUGO, applesmc_show_temperature, NULL, 28);static SENSOR_DEVICE_ATTR(temp30_input, S_IRUGO, applesmc_show_temperature, NULL, 29);static SENSOR_DEVICE_ATTR(temp31_input, S_IRUGO, applesmc_show_temperature, NULL, 30);static SENSOR_DEVICE_ATTR(temp32_input, S_IRUGO, applesmc_show_temperature, NULL, 31);static SENSOR_DEVICE_ATTR(temp33_input, S_IRUGO, applesmc_show_temperature, NULL, 32);static SENSOR_DEVICE_ATTR(temp34_input, S_IRUGO, applesmc_show_temperature, NULL, 33);static SENSOR_DEVICE_ATTR(temp35_input, S_IRUGO, applesmc_show_temperature, NULL, 34);static struct attribute *temperature_attributes[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, &sensor_dev_attr_temp2_input.dev_attr.attr, &sensor_dev_attr_temp3_input.dev_attr.attr, &sensor_dev_attr_temp4_input.dev_attr.attr, &sensor_dev_attr_temp5_input.dev_attr.attr, &sensor_dev_attr_temp6_input.dev_attr.attr, &sensor_dev_attr_temp7_input.dev_attr.attr, &sensor_dev_attr_temp8_input.dev_attr.attr, &sensor_dev_attr_temp9_input.dev_attr.attr, &sensor_dev_attr_temp10_input.dev_attr.attr, &sensor_dev_attr_temp11_input.dev_attr.attr, &sensor_dev_attr_temp12_input.dev_attr.attr, &sensor_dev_attr_temp13_input.dev_attr.attr, &sensor_dev_attr_temp14_input.dev_attr.attr, &sensor_dev_attr_temp15_input.dev_attr.attr, &sensor_dev_attr_temp16_input.dev_attr.attr, &sensor_dev_attr_temp17_input.dev_attr.attr, &sensor_dev_attr_temp18_input.dev_attr.attr, &sensor_dev_attr_temp19_input.dev_attr.attr, &sensor_dev_attr_temp20_input.dev_attr.attr, &sensor_dev_attr_temp21_input.dev_attr.attr, &sensor_dev_attr_temp22_input.dev_attr.attr, &sensor_dev_attr_temp23_input.dev_attr.attr, &sensor_dev_attr_temp24_input.dev_attr.attr, &sensor_dev_attr_temp25_input.dev_attr.attr, &sensor_dev_attr_temp26_input.dev_attr.attr, &sensor_dev_attr_temp27_input.dev_attr.attr, &sensor_dev_attr_temp28_input.dev_attr.attr, &sensor_dev_attr_temp29_input.dev_attr.attr, &sensor_dev_attr_temp30_input.dev_attr.attr, &sensor_dev_attr_temp31_input.dev_attr.attr, &sensor_dev_attr_temp32_input.dev_attr.attr, &sensor_dev_attr_temp33_input.dev_attr.attr, &sensor_dev_attr_temp34_input.dev_attr.attr, &sensor_dev_attr_temp35_input.dev_attr.attr, NULL};static const struct attribute_group temperature_attributes_group = { .attrs = temperature_attributes };/* Module stuff *//* * applesmc_dmi_match - found a match. return one, short-circuiting the hunt. */static int applesmc_dmi_match(const struct dmi_system_id *id){ int i = 0; struct dmi_match_data* dmi_data = id->driver_data; printk(KERN_INFO "applesmc: %s detected:\n", id->ident); applesmc_accelerometer = dmi_data->accelerometer; printk(KERN_INFO "applesmc: - Model %s accelerometer\n", applesmc_accelerometer ? "with" : "without"); applesmc_light = dmi_data->light; printk(KERN_INFO "applesmc: - Model %s light sensors and backlight\n", applesmc_light ? "with" : "without"); applesmc_temperature_set = dmi_data->temperature_set; while (temperature_sensors_sets[applesmc_temperature_set][i] != NULL) i++; printk(KERN_INFO "applesmc: - Model with %d temperature sensors\n", i); return 1;}/* Create accelerometer ressources */static int applesmc_create_accelerometer(void){ struct input_dev *idev; int ret; ret = sysfs_create_group(&pdev->dev.kobj, &accelerometer_attributes_group); if (ret) goto out; applesmc_idev = input_allocate_polled_device(); if (!applesmc_idev) { ret = -ENOMEM; goto out_sysfs; } applesmc_idev->poll = applesmc_idev_poll; applesmc_idev->poll_interval = APPLESMC_POLL_INTERVAL; /* initial calibrate for the input device */ applesmc_calibrate(); /* initialize the input device */ idev = applesmc_idev->input; idev->name = "applesmc"; idev->id.bustype = BUS_HOST; idev->dev.parent = &pdev->dev; idev->evbit[0] = BIT_MASK(EV_ABS); input_set_abs_params(idev, ABS_X, -256, 256, APPLESMC_INPUT_FUZZ, APPLESMC_INPUT_FLAT); input_set_abs_params(idev, ABS_Y, -256, 256, APPLESMC_INPUT_FUZZ, APPLESMC_INPUT_FLAT); ret = input_register_polled_device(applesmc_idev); if (ret) goto out_idev; return 0;out_idev: input_free_polled_device(applesmc_idev);out_sysfs: sysfs_remove_group(&pdev->dev.kobj, &accelerometer_attributes_group);out: printk(KERN_WARNING "applesmc: driver init failed (ret=%d)!\n", ret); return ret;}/* Release all ressources used by the accelerometer */static void applesmc_release_accelerometer(void){ input_unregister_polled_device(applesmc_idev); input_free_polled_device(applesmc_idev); sysfs_remove_group(&pdev->dev.kobj, &accelerometer_attributes_group);}static __initdata struct dmi_match_data applesmc_dmi_data[] = {/* MacBook Pro: accelerometer, backlight and temperature set 0 */ { .accelerometer = 1, .light = 1, .temperature_set = 0 },/* MacBook: accelerometer and temperature set 1 */ { .accelerometer = 1, .light = 0, .temperature_set = 1 },/* MacMini: temperature set 2 */ { .accelerometer = 0, .light = 0, .temperature_set = 2 },/* MacPro: temperature set 3 */ { .accelerometer = 0, .light = 0, .temperature_set = 3 },};/* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1". * So we need to put "Apple MacBook Pro" before "Apple MacBook". */static __initdata struct dmi_system_id applesmc_whitelist[] = { { applesmc_dmi_match, "Apple MacBook Pro", { DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), DMI_MATCH(DMI_PRODUCT_NAME,"MacBookPro") }, (void*)&applesmc_dmi_data[0]}, { applesmc_dmi_match, "Apple MacBook", { DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), DMI_MATCH(DMI_PRODUCT_NAME,"MacBook") }, (void*)&applesmc_dmi_data[1]}, { applesmc_dmi_match, "Apple Macmini", { DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), DMI_MATCH(DMI_PRODUCT_NAME,"Macmini") }, (void*)&applesmc_dmi_data[2]}, { applesmc_dmi_match, "Apple MacPro2", { DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), DMI_MATCH(DMI_PRODUCT_NAME,"MacPro2") }, (void*)&applesmc_dmi_data[3]}, { .ident = NULL }};static int __init applesmc_init(void){ int ret; int count; int i; if (!dmi_check_system(applesmc_whitelist)) { printk(KERN_WARNING "applesmc: supported laptop not found!\n"); ret = -ENODEV; goto out; } if (!request_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS, "applesmc")) { ret = -ENXIO; goto out; } ret = platform_driver_register(&applesmc_driver); if (ret) goto out_region; pdev = platform_device_register_simple("applesmc", APPLESMC_DATA_PORT, NULL, 0); if (IS_ERR(pdev)) { ret = PTR_ERR(pdev); goto out_driver; } ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_name.attr); if (ret) goto out_device; /* Create key enumeration sysfs files */ ret = sysfs_create_group(&pdev->dev.kobj, &key_enumeration_group); if (ret) goto out_name; /* create fan files */ count = applesmc_get_fan_count(); if (count < 0) { printk(KERN_ERR "applesmc: Cannot get the number of fans.\n"); } else { printk(KERN_INFO "applesmc: %d fans found.\n", count); switch (count) { default: printk(KERN_WARNING "applesmc: More than 4 fans found," " but at most 4 fans are supported" " by the driver.\n"); case 4: ret = sysfs_create_group(&pdev->dev.kobj, &fan_attribute_groups[3]); if (ret) goto out_key_enumeration; case 3: ret = sysfs_create_group(&pdev->dev.kobj, &fan_attribute_groups[2]); if (ret) goto out_key_enumeration; case 2: ret = sysfs_create_group(&pdev->dev.kobj, &fan_attribute_groups[1]); if (ret) goto out_key_enumeration; case 1: ret = sysfs_create_group(&pdev->dev.kobj, &fan_attribute_groups[0]); if (ret) goto out_fan_1; case 0: ; } } for (i = 0; temperature_sensors_sets[applesmc_temperature_set][i] != NULL; i++) { if (temperature_attributes[i] == NULL) { printk(KERN_ERR "applesmc: More temperature sensors " "in temperature_sensors_sets (at least %i)" "than available sysfs files in " "temperature_attributes (%i), please report " "this bug.\n", i, i-1); goto out_temperature; } ret = sysfs_create_file(&pdev->dev.kobj, temperature_attributes[i]); if (ret) goto out_temperature; } if (applesmc_accelerometer) { ret = applesmc_create_accelerometer(); if (ret) goto out_temperature; } if (applesmc_light) { /* Add light sensor file */ ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_light.attr); if (ret) goto out_accelerometer; /* Create the workqueue */ applesmc_led_wq = create_singlethread_workqueue("applesmc-led"); if (!applesmc_led_wq) { ret = -ENOMEM; goto out_light_sysfs; } /* register as a led device */ ret = led_classdev_register(&pdev->dev, &applesmc_backlight); if (ret < 0) goto out_light_wq; } hwmon_dev = hwmon_device_register(&pdev->dev); if (IS_ERR(hwmon_dev)) { ret = PTR_ERR(hwmon_dev); goto out_light_ledclass; } printk(KERN_INFO "applesmc: driver successfully loaded.\n"); return 0;out_light_ledclass: if (applesmc_light) led_classdev_unregister(&applesmc_backlight);out_light_wq: if (applesmc_light) destroy_workqueue(applesmc_led_wq);out_light_sysfs: if (applesmc_light) sysfs_remove_file(&pdev->dev.kobj, &dev_attr_light.attr);out_accelerometer: if (applesmc_accelerometer) applesmc_release_accelerometer();out_temperature: sysfs_remove_group(&pdev->dev.kobj, &temperature_attributes_group); sysfs_remove_group(&pdev->dev.kobj, &fan_attribute_groups[0]);out_fan_1: sysfs_remove_group(&pdev->dev.kobj, &fan_attribute_groups[1]);out_key_enumeration: sysfs_remove_group(&pdev->dev.kobj, &key_enumeration_group);out_name: sysfs_remove_file(&pdev->dev.kobj, &dev_attr_name.attr);out_device: platform_device_unregister(pdev);out_driver: platform_driver_unregister(&applesmc_driver);out_region: release_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS);out: printk(KERN_WARNING "applesmc: driver init failed (ret=%d)!\n", ret); return ret;}static void __exit applesmc_exit(void){ hwmon_device_unregister(hwmon_dev); if (applesmc_light) { led_classdev_unregister(&applesmc_backlight); destroy_workqueue(applesmc_led_wq); sysfs_remove_file(&pdev->dev.kobj, &dev_attr_light.attr); } if (applesmc_accelerometer) applesmc_release_accelerometer(); sysfs_remove_group(&pdev->dev.kobj, &temperature_attributes_group); sysfs_remove_group(&pdev->dev.kobj, &fan_attribute_groups[0]); sysfs_remove_group(&pdev->dev.kobj, &fan_attribute_groups[1]); sysfs_remove_group(&pdev->dev.kobj, &key_enumeration_group); sysfs_remove_file(&pdev->dev.kobj, &dev_attr_name.attr); platform_device_unregister(pdev); platform_driver_unregister(&applesmc_driver); release_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS); printk(KERN_INFO "applesmc: driver unloaded.\n");}module_init(applesmc_init);module_exit(applesmc_exit);MODULE_AUTHOR("Nicolas Boichat");MODULE_DESCRIPTION("Apple SMC");MODULE_LICENSE("GPL v2");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -