diff options
Diffstat (limited to 'drivers/misc/thinkpad_acpi.c')
-rw-r--r-- | drivers/misc/thinkpad_acpi.c | 144 |
1 files changed, 132 insertions, 12 deletions
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index 83a8d984e709..6c36a55cb3d1 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c | |||
@@ -1020,8 +1020,54 @@ static struct ibm_struct hotkey_driver_data = { | |||
1020 | * Bluetooth subdriver | 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 | static int __init bluetooth_init(struct ibm_init_struct *iibm) | 1068 | static int __init bluetooth_init(struct ibm_init_struct *iibm) |
1024 | { | 1069 | { |
1070 | int res; | ||
1025 | int status = 0; | 1071 | int status = 0; |
1026 | 1072 | ||
1027 | vdbg_printk(TPACPI_DBG_INIT, "initializing bluetooth subdriver\n"); | 1073 | vdbg_printk(TPACPI_DBG_INIT, "initializing bluetooth subdriver\n"); |
@@ -1037,17 +1083,29 @@ static int __init bluetooth_init(struct ibm_init_struct *iibm) | |||
1037 | str_supported(tp_features.bluetooth), | 1083 | str_supported(tp_features.bluetooth), |
1038 | status); | 1084 | status); |
1039 | 1085 | ||
1040 | if (tp_features.bluetooth && | 1086 | if (tp_features.bluetooth) { |
1041 | !(status & TP_ACPI_BLUETOOTH_HWPRESENT)) { | 1087 | if (!(status & TP_ACPI_BLUETOOTH_HWPRESENT)) { |
1042 | /* no bluetooth hardware present in system */ | 1088 | /* no bluetooth hardware present in system */ |
1043 | tp_features.bluetooth = 0; | 1089 | tp_features.bluetooth = 0; |
1044 | dbg_printk(TPACPI_DBG_INIT, | 1090 | dbg_printk(TPACPI_DBG_INIT, |
1045 | "bluetooth hardware not installed\n"); | 1091 | "bluetooth hardware not installed\n"); |
1092 | } else { | ||
1093 | res = sysfs_create_group(&tpacpi_pdev->dev.kobj, | ||
1094 | &bluetooth_attr_group); | ||
1095 | if (res) | ||
1096 | return res; | ||
1097 | } | ||
1046 | } | 1098 | } |
1047 | 1099 | ||
1048 | return (tp_features.bluetooth)? 0 : 1; | 1100 | return (tp_features.bluetooth)? 0 : 1; |
1049 | } | 1101 | } |
1050 | 1102 | ||
1103 | static void bluetooth_exit(void) | ||
1104 | { | ||
1105 | sysfs_remove_group(&tpacpi_pdev->dev.kobj, | ||
1106 | &bluetooth_attr_group); | ||
1107 | } | ||
1108 | |||
1051 | static int bluetooth_get_radiosw(void) | 1109 | static int bluetooth_get_radiosw(void) |
1052 | { | 1110 | { |
1053 | int status; | 1111 | int status; |
@@ -1080,6 +1138,7 @@ static int bluetooth_set_radiosw(int radio_on) | |||
1080 | return 0; | 1138 | return 0; |
1081 | } | 1139 | } |
1082 | 1140 | ||
1141 | /* procfs -------------------------------------------------------------- */ | ||
1083 | static int bluetooth_read(char *p) | 1142 | static int bluetooth_read(char *p) |
1084 | { | 1143 | { |
1085 | int len = 0; | 1144 | int len = 0; |
@@ -1119,14 +1178,61 @@ static struct ibm_struct bluetooth_driver_data = { | |||
1119 | .name = "bluetooth", | 1178 | .name = "bluetooth", |
1120 | .read = bluetooth_read, | 1179 | .read = bluetooth_read, |
1121 | .write = bluetooth_write, | 1180 | .write = bluetooth_write, |
1181 | .exit = bluetooth_exit, | ||
1122 | }; | 1182 | }; |
1123 | 1183 | ||
1124 | /************************************************************************* | 1184 | /************************************************************************* |
1125 | * Wan subdriver | 1185 | * Wan subdriver |
1126 | */ | 1186 | */ |
1127 | 1187 | ||
1188 | /* sysfs wan enable ---------------------------------------------------- */ | ||
1189 | static ssize_t wan_enable_show(struct device *dev, | ||
1190 | struct device_attribute *attr, | ||
1191 | char *buf) | ||
1192 | { | ||
1193 | int status; | ||
1194 | |||
1195 | status = wan_get_radiosw(); | ||
1196 | if (status < 0) | ||
1197 | return status; | ||
1198 | |||
1199 | return snprintf(buf, PAGE_SIZE, "%d\n", status ? 1 : 0); | ||
1200 | } | ||
1201 | |||
1202 | static ssize_t wan_enable_store(struct device *dev, | ||
1203 | struct device_attribute *attr, | ||
1204 | const char *buf, size_t count) | ||
1205 | { | ||
1206 | unsigned long t; | ||
1207 | int res; | ||
1208 | |||
1209 | if (parse_strtoul(buf, 1, &t)) | ||
1210 | return -EINVAL; | ||
1211 | |||
1212 | res = wan_set_radiosw(t); | ||
1213 | |||
1214 | return (res) ? res : count; | ||
1215 | } | ||
1216 | |||
1217 | static struct device_attribute dev_attr_wan_enable = | ||
1218 | __ATTR(enable, S_IWUSR | S_IRUGO, | ||
1219 | wan_enable_show, wan_enable_store); | ||
1220 | |||
1221 | /* --------------------------------------------------------------------- */ | ||
1222 | |||
1223 | static struct attribute *wan_attributes[] = { | ||
1224 | &dev_attr_wan_enable.attr, | ||
1225 | NULL | ||
1226 | }; | ||
1227 | |||
1228 | static const struct attribute_group wan_attr_group = { | ||
1229 | .name = TPACPI_WAN_SYSFS_GROUP, | ||
1230 | .attrs = wan_attributes, | ||
1231 | }; | ||
1232 | |||
1128 | static int __init wan_init(struct ibm_init_struct *iibm) | 1233 | static int __init wan_init(struct ibm_init_struct *iibm) |
1129 | { | 1234 | { |
1235 | int res; | ||
1130 | int status = 0; | 1236 | int status = 0; |
1131 | 1237 | ||
1132 | vdbg_printk(TPACPI_DBG_INIT, "initializing wan subdriver\n"); | 1238 | vdbg_printk(TPACPI_DBG_INIT, "initializing wan subdriver\n"); |
@@ -1140,17 +1246,29 @@ static int __init wan_init(struct ibm_init_struct *iibm) | |||
1140 | str_supported(tp_features.wan), | 1246 | str_supported(tp_features.wan), |
1141 | status); | 1247 | status); |
1142 | 1248 | ||
1143 | if (tp_features.wan && | 1249 | if (tp_features.wan) { |
1144 | !(status & TP_ACPI_WANCARD_HWPRESENT)) { | 1250 | if (!(status & TP_ACPI_WANCARD_HWPRESENT)) { |
1145 | /* no wan hardware present in system */ | 1251 | /* no wan hardware present in system */ |
1146 | tp_features.wan = 0; | 1252 | tp_features.wan = 0; |
1147 | dbg_printk(TPACPI_DBG_INIT, | 1253 | dbg_printk(TPACPI_DBG_INIT, |
1148 | "wan hardware not installed\n"); | 1254 | "wan hardware not installed\n"); |
1255 | } else { | ||
1256 | res = sysfs_create_group(&tpacpi_pdev->dev.kobj, | ||
1257 | &wan_attr_group); | ||
1258 | if (res) | ||
1259 | return res; | ||
1260 | } | ||
1149 | } | 1261 | } |
1150 | 1262 | ||
1151 | return (tp_features.wan)? 0 : 1; | 1263 | return (tp_features.wan)? 0 : 1; |
1152 | } | 1264 | } |
1153 | 1265 | ||
1266 | static void wan_exit(void) | ||
1267 | { | ||
1268 | sysfs_remove_group(&tpacpi_pdev->dev.kobj, | ||
1269 | &wan_attr_group); | ||
1270 | } | ||
1271 | |||
1154 | static int wan_get_radiosw(void) | 1272 | static int wan_get_radiosw(void) |
1155 | { | 1273 | { |
1156 | int status; | 1274 | int status; |
@@ -1183,6 +1301,7 @@ static int wan_set_radiosw(int radio_on) | |||
1183 | return 0; | 1301 | return 0; |
1184 | } | 1302 | } |
1185 | 1303 | ||
1304 | /* procfs -------------------------------------------------------------- */ | ||
1186 | static int wan_read(char *p) | 1305 | static int wan_read(char *p) |
1187 | { | 1306 | { |
1188 | int len = 0; | 1307 | int len = 0; |
@@ -1222,6 +1341,7 @@ static struct ibm_struct wan_driver_data = { | |||
1222 | .name = "wan", | 1341 | .name = "wan", |
1223 | .read = wan_read, | 1342 | .read = wan_read, |
1224 | .write = wan_write, | 1343 | .write = wan_write, |
1344 | .exit = wan_exit, | ||
1225 | .flags.experimental = 1, | 1345 | .flags.experimental = 1, |
1226 | }; | 1346 | }; |
1227 | 1347 | ||