aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/keyboard/atkbd.c
diff options
context:
space:
mode:
authorDmitry Torokhov <dtor@insightbb.com>2006-11-05 22:39:56 -0500
committerDmitry Torokhov <dtor@insightbb.com>2006-11-05 22:39:56 -0500
commit2b03b60e6b8635fffdd15d5d24943950f2bbf96e (patch)
tree17f0354b7edb08920a89e663ef724c84518c49fa /drivers/input/keyboard/atkbd.c
parent41ad5fbabda0c3930136bb40cfc7a0c23013365f (diff)
Input: keyboards - handle errors when registering input devices
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input/keyboard/atkbd.c')
-rw-r--r--drivers/input/keyboard/atkbd.c159
1 files changed, 129 insertions, 30 deletions
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index cbb93669d1c..73c6946b2d9 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -939,7 +939,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
939 atkbd = kzalloc(sizeof(struct atkbd), GFP_KERNEL); 939 atkbd = kzalloc(sizeof(struct atkbd), GFP_KERNEL);
940 dev = input_allocate_device(); 940 dev = input_allocate_device();
941 if (!atkbd || !dev) 941 if (!atkbd || !dev)
942 goto fail; 942 goto fail1;
943 943
944 atkbd->dev = dev; 944 atkbd->dev = dev;
945 ps2_init(&atkbd->ps2dev, serio); 945 ps2_init(&atkbd->ps2dev, serio);
@@ -967,14 +967,13 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
967 967
968 err = serio_open(serio, drv); 968 err = serio_open(serio, drv);
969 if (err) 969 if (err)
970 goto fail; 970 goto fail2;
971 971
972 if (atkbd->write) { 972 if (atkbd->write) {
973 973
974 if (atkbd_probe(atkbd)) { 974 if (atkbd_probe(atkbd)) {
975 serio_close(serio);
976 err = -ENODEV; 975 err = -ENODEV;
977 goto fail; 976 goto fail3;
978 } 977 }
979 978
980 atkbd->set = atkbd_select_set(atkbd, atkbd_set, atkbd_extra); 979 atkbd->set = atkbd_select_set(atkbd, atkbd_set, atkbd_extra);
@@ -988,16 +987,22 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
988 atkbd_set_keycode_table(atkbd); 987 atkbd_set_keycode_table(atkbd);
989 atkbd_set_device_attrs(atkbd); 988 atkbd_set_device_attrs(atkbd);
990 989
991 sysfs_create_group(&serio->dev.kobj, &atkbd_attribute_group); 990 err = sysfs_create_group(&serio->dev.kobj, &atkbd_attribute_group);
991 if (err)
992 goto fail3;
992 993
993 atkbd_enable(atkbd); 994 atkbd_enable(atkbd);
994 995
995 input_register_device(atkbd->dev); 996 err = input_register_device(atkbd->dev);
997 if (err)
998 goto fail4;
996 999
997 return 0; 1000 return 0;
998 1001
999 fail: serio_set_drvdata(serio, NULL); 1002 fail4: sysfs_remove_group(&serio->dev.kobj, &atkbd_attribute_group);
1000 input_free_device(dev); 1003 fail3: serio_close(serio);
1004 fail2: serio_set_drvdata(serio, NULL);
1005 fail1: input_free_device(dev);
1001 kfree(atkbd); 1006 kfree(atkbd);
1002 return err; 1007 return err;
1003} 1008}
@@ -1133,9 +1138,11 @@ static ssize_t atkbd_show_extra(struct atkbd *atkbd, char *buf)
1133 1138
1134static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t count) 1139static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t count)
1135{ 1140{
1136 struct input_dev *new_dev; 1141 struct input_dev *old_dev, *new_dev;
1137 unsigned long value; 1142 unsigned long value;
1138 char *rest; 1143 char *rest;
1144 int err;
1145 unsigned char old_extra, old_set;
1139 1146
1140 if (!atkbd->write) 1147 if (!atkbd->write)
1141 return -EIO; 1148 return -EIO;
@@ -1147,17 +1154,36 @@ static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t coun
1147 if (atkbd->extra != value) { 1154 if (atkbd->extra != value) {
1148 /* 1155 /*
1149 * Since device's properties will change we need to 1156 * Since device's properties will change we need to
1150 * unregister old device. But allocate new one first 1157 * unregister old device. But allocate and register
1151 * to make sure we have it. 1158 * new one first to make sure we have it.
1152 */ 1159 */
1153 if (!(new_dev = input_allocate_device())) 1160 old_dev = atkbd->dev;
1161 old_extra = atkbd->extra;
1162 old_set = atkbd->set;
1163
1164 new_dev = input_allocate_device();
1165 if (!new_dev)
1154 return -ENOMEM; 1166 return -ENOMEM;
1155 input_unregister_device(atkbd->dev); 1167
1156 atkbd->dev = new_dev; 1168 atkbd->dev = new_dev;
1157 atkbd->set = atkbd_select_set(atkbd, atkbd->set, value); 1169 atkbd->set = atkbd_select_set(atkbd, atkbd->set, value);
1158 atkbd_activate(atkbd); 1170 atkbd_activate(atkbd);
1171 atkbd_set_keycode_table(atkbd);
1159 atkbd_set_device_attrs(atkbd); 1172 atkbd_set_device_attrs(atkbd);
1160 input_register_device(atkbd->dev); 1173
1174 err = input_register_device(atkbd->dev);
1175 if (err) {
1176 input_free_device(new_dev);
1177
1178 atkbd->dev = old_dev;
1179 atkbd->set = atkbd_select_set(atkbd, old_set, old_extra);
1180 atkbd_set_keycode_table(atkbd);
1181 atkbd_set_device_attrs(atkbd);
1182
1183 return err;
1184 }
1185 input_unregister_device(old_dev);
1186
1161 } 1187 }
1162 return count; 1188 return count;
1163} 1189}
@@ -1169,23 +1195,41 @@ static ssize_t atkbd_show_scroll(struct atkbd *atkbd, char *buf)
1169 1195
1170static ssize_t atkbd_set_scroll(struct atkbd *atkbd, const char *buf, size_t count) 1196static ssize_t atkbd_set_scroll(struct atkbd *atkbd, const char *buf, size_t count)
1171{ 1197{
1172 struct input_dev *new_dev; 1198 struct input_dev *old_dev, *new_dev;
1173 unsigned long value; 1199 unsigned long value;
1174 char *rest; 1200 char *rest;
1201 int err;
1202 unsigned char old_scroll;
1175 1203
1176 value = simple_strtoul(buf, &rest, 10); 1204 value = simple_strtoul(buf, &rest, 10);
1177 if (*rest || value > 1) 1205 if (*rest || value > 1)
1178 return -EINVAL; 1206 return -EINVAL;
1179 1207
1180 if (atkbd->scroll != value) { 1208 if (atkbd->scroll != value) {
1181 if (!(new_dev = input_allocate_device())) 1209 old_dev = atkbd->dev;
1210 old_scroll = atkbd->scroll;
1211
1212 new_dev = input_allocate_device();
1213 if (!new_dev)
1182 return -ENOMEM; 1214 return -ENOMEM;
1183 input_unregister_device(atkbd->dev); 1215
1184 atkbd->dev = new_dev; 1216 atkbd->dev = new_dev;
1185 atkbd->scroll = value; 1217 atkbd->scroll = value;
1186 atkbd_set_keycode_table(atkbd); 1218 atkbd_set_keycode_table(atkbd);
1187 atkbd_set_device_attrs(atkbd); 1219 atkbd_set_device_attrs(atkbd);
1188 input_register_device(atkbd->dev); 1220
1221 err = input_register_device(atkbd->dev);
1222 if (err) {
1223 input_free_device(new_dev);
1224
1225 atkbd->scroll = old_scroll;
1226 atkbd->dev = old_dev;
1227 atkbd_set_keycode_table(atkbd);
1228 atkbd_set_device_attrs(atkbd);
1229
1230 return err;
1231 }
1232 input_unregister_device(old_dev);
1189 } 1233 }
1190 return count; 1234 return count;
1191} 1235}
@@ -1197,9 +1241,11 @@ static ssize_t atkbd_show_set(struct atkbd *atkbd, char *buf)
1197 1241
1198static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count) 1242static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count)
1199{ 1243{
1200 struct input_dev *new_dev; 1244 struct input_dev *old_dev, *new_dev;
1201 unsigned long value; 1245 unsigned long value;
1202 char *rest; 1246 char *rest;
1247 int err;
1248 unsigned char old_set, old_extra;
1203 1249
1204 if (!atkbd->write) 1250 if (!atkbd->write)
1205 return -EIO; 1251 return -EIO;
@@ -1209,15 +1255,32 @@ static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count)
1209 return -EINVAL; 1255 return -EINVAL;
1210 1256
1211 if (atkbd->set != value) { 1257 if (atkbd->set != value) {
1212 if (!(new_dev = input_allocate_device())) 1258 old_dev = atkbd->dev;
1259 old_extra = atkbd->extra;
1260 old_set = atkbd->set;
1261
1262 new_dev = input_allocate_device();
1263 if (!new_dev)
1213 return -ENOMEM; 1264 return -ENOMEM;
1214 input_unregister_device(atkbd->dev); 1265
1215 atkbd->dev = new_dev; 1266 atkbd->dev = new_dev;
1216 atkbd->set = atkbd_select_set(atkbd, value, atkbd->extra); 1267 atkbd->set = atkbd_select_set(atkbd, value, atkbd->extra);
1217 atkbd_activate(atkbd); 1268 atkbd_activate(atkbd);
1218 atkbd_set_keycode_table(atkbd); 1269 atkbd_set_keycode_table(atkbd);
1219 atkbd_set_device_attrs(atkbd); 1270 atkbd_set_device_attrs(atkbd);
1220 input_register_device(atkbd->dev); 1271
1272 err = input_register_device(atkbd->dev);
1273 if (err) {
1274 input_free_device(new_dev);
1275
1276 atkbd->dev = old_dev;
1277 atkbd->set = atkbd_select_set(atkbd, old_set, old_extra);
1278 atkbd_set_keycode_table(atkbd);
1279 atkbd_set_device_attrs(atkbd);
1280
1281 return err;
1282 }
1283 input_unregister_device(old_dev);
1221 } 1284 }
1222 return count; 1285 return count;
1223} 1286}
@@ -1229,9 +1292,11 @@ static ssize_t atkbd_show_softrepeat(struct atkbd *atkbd, char *buf)
1229 1292
1230static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t count) 1293static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t count)
1231{ 1294{
1232 struct input_dev *new_dev; 1295 struct input_dev *old_dev, *new_dev;
1233 unsigned long value; 1296 unsigned long value;
1234 char *rest; 1297 char *rest;
1298 int err;
1299 unsigned char old_softrepeat, old_softraw;
1235 1300
1236 if (!atkbd->write) 1301 if (!atkbd->write)
1237 return -EIO; 1302 return -EIO;
@@ -1241,15 +1306,32 @@ static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t
1241 return -EINVAL; 1306 return -EINVAL;
1242 1307
1243 if (atkbd->softrepeat != value) { 1308 if (atkbd->softrepeat != value) {
1244 if (!(new_dev = input_allocate_device())) 1309 old_dev = atkbd->dev;
1310 old_softrepeat = atkbd->softrepeat;
1311 old_softraw = atkbd->softraw;
1312
1313 new_dev = input_allocate_device();
1314 if (!new_dev)
1245 return -ENOMEM; 1315 return -ENOMEM;
1246 input_unregister_device(atkbd->dev); 1316
1247 atkbd->dev = new_dev; 1317 atkbd->dev = new_dev;
1248 atkbd->softrepeat = value; 1318 atkbd->softrepeat = value;
1249 if (atkbd->softrepeat) 1319 if (atkbd->softrepeat)
1250 atkbd->softraw = 1; 1320 atkbd->softraw = 1;
1251 atkbd_set_device_attrs(atkbd); 1321 atkbd_set_device_attrs(atkbd);
1252 input_register_device(atkbd->dev); 1322
1323 err = input_register_device(atkbd->dev);
1324 if (err) {
1325 input_free_device(new_dev);
1326
1327 atkbd->dev = old_dev;
1328 atkbd->softrepeat = old_softrepeat;
1329 atkbd->softraw = old_softraw;
1330 atkbd_set_device_attrs(atkbd);
1331
1332 return err;
1333 }
1334 input_unregister_device(old_dev);
1253 } 1335 }
1254 return count; 1336 return count;
1255} 1337}
@@ -1262,22 +1344,39 @@ static ssize_t atkbd_show_softraw(struct atkbd *atkbd, char *buf)
1262 1344
1263static ssize_t atkbd_set_softraw(struct atkbd *atkbd, const char *buf, size_t count) 1345static ssize_t atkbd_set_softraw(struct atkbd *atkbd, const char *buf, size_t count)
1264{ 1346{
1265 struct input_dev *new_dev; 1347 struct input_dev *old_dev, *new_dev;
1266 unsigned long value; 1348 unsigned long value;
1267 char *rest; 1349 char *rest;
1350 int err;
1351 unsigned char old_softraw;
1268 1352
1269 value = simple_strtoul(buf, &rest, 10); 1353 value = simple_strtoul(buf, &rest, 10);
1270 if (*rest || value > 1) 1354 if (*rest || value > 1)
1271 return -EINVAL; 1355 return -EINVAL;
1272 1356
1273 if (atkbd->softraw != value) { 1357 if (atkbd->softraw != value) {
1274 if (!(new_dev = input_allocate_device())) 1358 old_dev = atkbd->dev;
1359 old_softraw = atkbd->softraw;
1360
1361 new_dev = input_allocate_device();
1362 if (!new_dev)
1275 return -ENOMEM; 1363 return -ENOMEM;
1276 input_unregister_device(atkbd->dev); 1364
1277 atkbd->dev = new_dev; 1365 atkbd->dev = new_dev;
1278 atkbd->softraw = value; 1366 atkbd->softraw = value;
1279 atkbd_set_device_attrs(atkbd); 1367 atkbd_set_device_attrs(atkbd);
1280 input_register_device(atkbd->dev); 1368
1369 err = input_register_device(atkbd->dev);
1370 if (err) {
1371 input_free_device(new_dev);
1372
1373 atkbd->dev = old_dev;
1374 atkbd->softraw = old_softraw;
1375 atkbd_set_device_attrs(atkbd);
1376
1377 return err;
1378 }
1379 input_unregister_device(old_dev);
1281 } 1380 }
1282 return count; 1381 return count;
1283} 1382}