Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ACPI: thinkpad-acpi: add sysfs support to wan and bluetooth subdrivers

Add support to sysfs to the wan and bluetooth subdrivers.

Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Signed-off-by: Len Brown <len.brown@intel.com>

authored by

Henrique de Moraes Holschuh and committed by
Len Brown
d3a6ade4 a0416420

+186 -23
+50 -11
Documentation/thinkpad-acpi.txt
··· 225 225 keys mask, and allows one to modify it. 226 226 227 227 228 - Bluetooth -- /proc/acpi/ibm/bluetooth 229 - ------------------------------------- 228 + Bluetooth 229 + --------- 230 230 231 - This feature shows the presence and current state of a Bluetooth 232 - device. If Bluetooth is installed, the following commands can be used: 231 + procfs: /proc/acpi/ibm/bluetooth 232 + sysfs device attribute: bluetooth/enable 233 + 234 + This feature shows the presence and current state of a ThinkPad 235 + Bluetooth device in the internal ThinkPad CDC slot. 236 + 237 + Procfs notes: 238 + 239 + If Bluetooth is installed, the following commands can be used: 233 240 234 241 echo enable > /proc/acpi/ibm/bluetooth 235 242 echo disable > /proc/acpi/ibm/bluetooth 243 + 244 + Sysfs notes: 245 + 246 + If the Bluetooth CDC card is installed, it can be enabled / 247 + disabled through the "bluetooth/enable" thinkpad-acpi device 248 + attribute, and its current status can also be queried. 249 + 250 + enable: 251 + 0: disables Bluetooth / Bluetooth is disabled 252 + 1: enables Bluetooth / Bluetooth is enabled. 253 + 254 + Note: this interface will be probably be superseeded by the 255 + generic rfkill class. 236 256 237 257 Video output control -- /proc/acpi/ibm/video 238 258 -------------------------------------------- ··· 894 874 would be the safest choice, though). 895 875 896 876 897 - EXPERIMENTAL: WAN -- /proc/acpi/ibm/wan 898 - --------------------------------------- 877 + EXPERIMENTAL: WAN 878 + ----------------- 879 + 880 + procfs: /proc/acpi/ibm/wan 881 + sysfs device attribute: wwan/enable 899 882 900 883 This feature is marked EXPERIMENTAL because the implementation 901 884 directly accesses hardware registers and may not work as expected. USE 902 885 WITH CAUTION! To use this feature, you need to supply the 903 886 experimental=1 parameter when loading the module. 904 887 905 - This feature shows the presence and current state of a WAN (Sierra 906 - Wireless EV-DO) device. If WAN is installed, the following commands can 907 - be used: 888 + This feature shows the presence and current state of a W-WAN (Sierra 889 + Wireless EV-DO) device. 890 + 891 + It was tested on a Lenovo Thinkpad X60. It should probably work on other 892 + Thinkpad models which come with this module installed. 893 + 894 + Procfs notes: 895 + 896 + If the W-WAN card is installed, the following commands can be used: 908 897 909 898 echo enable > /proc/acpi/ibm/wan 910 899 echo disable > /proc/acpi/ibm/wan 911 900 912 - It was tested on a Lenovo Thinkpad X60. It should probably work on other 913 - Thinkpad models which come with this module installed. 901 + Sysfs notes: 902 + 903 + If the W-WAN card is installed, it can be enabled / 904 + disabled through the "wwan/enable" thinkpad-acpi device 905 + attribute, and its current status can also be queried. 906 + 907 + enable: 908 + 0: disables WWAN card / WWAN card is disabled 909 + 1: enables WWAN card / WWAN card is enabled. 910 + 911 + Note: this interface will be probably be superseeded by the 912 + generic rfkill class. 914 913 915 914 Multiple Commands, Module Parameters 916 915 ------------------------------------
+132 -12
drivers/misc/thinkpad_acpi.c
··· 1020 1020 * Bluetooth subdriver 1021 1021 */ 1022 1022 1023 + /* sysfs bluetooth enable ---------------------------------------------- */ 1024 + static ssize_t bluetooth_enable_show(struct device *dev, 1025 + struct device_attribute *attr, 1026 + char *buf) 1027 + { 1028 + int status; 1029 + 1030 + status = bluetooth_get_radiosw(); 1031 + if (status < 0) 1032 + return status; 1033 + 1034 + return snprintf(buf, PAGE_SIZE, "%d\n", status ? 1 : 0); 1035 + } 1036 + 1037 + static ssize_t bluetooth_enable_store(struct device *dev, 1038 + struct device_attribute *attr, 1039 + const char *buf, size_t count) 1040 + { 1041 + unsigned long t; 1042 + int res; 1043 + 1044 + if (parse_strtoul(buf, 1, &t)) 1045 + return -EINVAL; 1046 + 1047 + res = bluetooth_set_radiosw(t); 1048 + 1049 + return (res) ? res : count; 1050 + } 1051 + 1052 + static struct device_attribute dev_attr_bluetooth_enable = 1053 + __ATTR(enable, S_IWUSR | S_IRUGO, 1054 + bluetooth_enable_show, bluetooth_enable_store); 1055 + 1056 + /* --------------------------------------------------------------------- */ 1057 + 1058 + static struct attribute *bluetooth_attributes[] = { 1059 + &dev_attr_bluetooth_enable.attr, 1060 + NULL 1061 + }; 1062 + 1063 + static const struct attribute_group bluetooth_attr_group = { 1064 + .name = TPACPI_BLUETH_SYSFS_GROUP, 1065 + .attrs = bluetooth_attributes, 1066 + }; 1067 + 1023 1068 static int __init bluetooth_init(struct ibm_init_struct *iibm) 1024 1069 { 1070 + int res; 1025 1071 int status = 0; 1026 1072 1027 1073 vdbg_printk(TPACPI_DBG_INIT, "initializing bluetooth subdriver\n"); ··· 1083 1037 str_supported(tp_features.bluetooth), 1084 1038 status); 1085 1039 1086 - if (tp_features.bluetooth && 1087 - !(status & TP_ACPI_BLUETOOTH_HWPRESENT)) { 1088 - /* no bluetooth hardware present in system */ 1089 - tp_features.bluetooth = 0; 1090 - dbg_printk(TPACPI_DBG_INIT, 1091 - "bluetooth hardware not installed\n"); 1040 + if (tp_features.bluetooth) { 1041 + if (!(status & TP_ACPI_BLUETOOTH_HWPRESENT)) { 1042 + /* no bluetooth hardware present in system */ 1043 + tp_features.bluetooth = 0; 1044 + dbg_printk(TPACPI_DBG_INIT, 1045 + "bluetooth hardware not installed\n"); 1046 + } else { 1047 + res = sysfs_create_group(&tpacpi_pdev->dev.kobj, 1048 + &bluetooth_attr_group); 1049 + if (res) 1050 + return res; 1051 + } 1092 1052 } 1093 1053 1094 1054 return (tp_features.bluetooth)? 0 : 1; 1055 + } 1056 + 1057 + static void bluetooth_exit(void) 1058 + { 1059 + sysfs_remove_group(&tpacpi_pdev->dev.kobj, 1060 + &bluetooth_attr_group); 1095 1061 } 1096 1062 1097 1063 static int bluetooth_get_radiosw(void) ··· 1138 1080 return 0; 1139 1081 } 1140 1082 1083 + /* procfs -------------------------------------------------------------- */ 1141 1084 static int bluetooth_read(char *p) 1142 1085 { 1143 1086 int len = 0; ··· 1178 1119 .name = "bluetooth", 1179 1120 .read = bluetooth_read, 1180 1121 .write = bluetooth_write, 1122 + .exit = bluetooth_exit, 1181 1123 }; 1182 1124 1183 1125 /************************************************************************* 1184 1126 * Wan subdriver 1185 1127 */ 1186 1128 1129 + /* sysfs wan enable ---------------------------------------------------- */ 1130 + static ssize_t wan_enable_show(struct device *dev, 1131 + struct device_attribute *attr, 1132 + char *buf) 1133 + { 1134 + int status; 1135 + 1136 + status = wan_get_radiosw(); 1137 + if (status < 0) 1138 + return status; 1139 + 1140 + return snprintf(buf, PAGE_SIZE, "%d\n", status ? 1 : 0); 1141 + } 1142 + 1143 + static ssize_t wan_enable_store(struct device *dev, 1144 + struct device_attribute *attr, 1145 + const char *buf, size_t count) 1146 + { 1147 + unsigned long t; 1148 + int res; 1149 + 1150 + if (parse_strtoul(buf, 1, &t)) 1151 + return -EINVAL; 1152 + 1153 + res = wan_set_radiosw(t); 1154 + 1155 + return (res) ? res : count; 1156 + } 1157 + 1158 + static struct device_attribute dev_attr_wan_enable = 1159 + __ATTR(enable, S_IWUSR | S_IRUGO, 1160 + wan_enable_show, wan_enable_store); 1161 + 1162 + /* --------------------------------------------------------------------- */ 1163 + 1164 + static struct attribute *wan_attributes[] = { 1165 + &dev_attr_wan_enable.attr, 1166 + NULL 1167 + }; 1168 + 1169 + static const struct attribute_group wan_attr_group = { 1170 + .name = TPACPI_WAN_SYSFS_GROUP, 1171 + .attrs = wan_attributes, 1172 + }; 1173 + 1187 1174 static int __init wan_init(struct ibm_init_struct *iibm) 1188 1175 { 1176 + int res; 1189 1177 int status = 0; 1190 1178 1191 1179 vdbg_printk(TPACPI_DBG_INIT, "initializing wan subdriver\n"); ··· 1246 1140 str_supported(tp_features.wan), 1247 1141 status); 1248 1142 1249 - if (tp_features.wan && 1250 - !(status & TP_ACPI_WANCARD_HWPRESENT)) { 1251 - /* no wan hardware present in system */ 1252 - tp_features.wan = 0; 1253 - dbg_printk(TPACPI_DBG_INIT, 1254 - "wan hardware not installed\n"); 1143 + if (tp_features.wan) { 1144 + if (!(status & TP_ACPI_WANCARD_HWPRESENT)) { 1145 + /* no wan hardware present in system */ 1146 + tp_features.wan = 0; 1147 + dbg_printk(TPACPI_DBG_INIT, 1148 + "wan hardware not installed\n"); 1149 + } else { 1150 + res = sysfs_create_group(&tpacpi_pdev->dev.kobj, 1151 + &wan_attr_group); 1152 + if (res) 1153 + return res; 1154 + } 1255 1155 } 1256 1156 1257 1157 return (tp_features.wan)? 0 : 1; 1158 + } 1159 + 1160 + static void wan_exit(void) 1161 + { 1162 + sysfs_remove_group(&tpacpi_pdev->dev.kobj, 1163 + &wan_attr_group); 1258 1164 } 1259 1165 1260 1166 static int wan_get_radiosw(void) ··· 1301 1183 return 0; 1302 1184 } 1303 1185 1186 + /* procfs -------------------------------------------------------------- */ 1304 1187 static int wan_read(char *p) 1305 1188 { 1306 1189 int len = 0; ··· 1341 1222 .name = "wan", 1342 1223 .read = wan_read, 1343 1224 .write = wan_write, 1225 + .exit = wan_exit, 1344 1226 .flags.experimental = 1, 1345 1227 }; 1346 1228
+4
drivers/misc/thinkpad_acpi.h
··· 278 278 * Bluetooth subdriver 279 279 */ 280 280 281 + #define TPACPI_BLUETH_SYSFS_GROUP "bluetooth" 282 + 281 283 enum { 282 284 /* ACPI GBDC/SBDC bits */ 283 285 TP_ACPI_BLUETOOTH_HWPRESENT = 0x01, /* Bluetooth hw available */ ··· 552 550 /* 553 551 * Wan subdriver 554 552 */ 553 + 554 + #define TPACPI_WAN_SYSFS_GROUP "wwan" 555 555 556 556 enum { 557 557 /* ACPI GWAN/SWAN bits */