diff options
-rw-r--r-- | drivers/media/IR/imon.c | 273 |
1 files changed, 160 insertions, 113 deletions
diff --git a/drivers/media/IR/imon.c b/drivers/media/IR/imon.c index c185422ef28c..d36fe7239782 100644 --- a/drivers/media/IR/imon.c +++ b/drivers/media/IR/imon.c | |||
@@ -44,7 +44,7 @@ | |||
44 | #define MOD_AUTHOR "Jarod Wilson <jarod@wilsonet.com>" | 44 | #define MOD_AUTHOR "Jarod Wilson <jarod@wilsonet.com>" |
45 | #define MOD_DESC "Driver for SoundGraph iMON MultiMedia IR/Display" | 45 | #define MOD_DESC "Driver for SoundGraph iMON MultiMedia IR/Display" |
46 | #define MOD_NAME "imon" | 46 | #define MOD_NAME "imon" |
47 | #define MOD_VERSION "0.9.1" | 47 | #define MOD_VERSION "0.9.2" |
48 | 48 | ||
49 | #define DISPLAY_MINOR_BASE 144 | 49 | #define DISPLAY_MINOR_BASE 144 |
50 | #define DEVICE_NAME "lcd%d" | 50 | #define DEVICE_NAME "lcd%d" |
@@ -121,21 +121,25 @@ struct imon_context { | |||
121 | u16 vendor; /* usb vendor ID */ | 121 | u16 vendor; /* usb vendor ID */ |
122 | u16 product; /* usb product ID */ | 122 | u16 product; /* usb product ID */ |
123 | 123 | ||
124 | struct input_dev *idev; /* input device for remote */ | 124 | struct input_dev *rdev; /* input device for remote */ |
125 | struct input_dev *idev; /* input device for panel & IR mouse */ | ||
125 | struct input_dev *touch; /* input device for touchscreen */ | 126 | struct input_dev *touch; /* input device for touchscreen */ |
126 | 127 | ||
127 | u32 kc; /* current input keycode */ | 128 | u32 kc; /* current input keycode */ |
128 | u32 last_keycode; /* last reported input keycode */ | 129 | u32 last_keycode; /* last reported input keycode */ |
130 | u32 rc_scancode; /* the computed remote scancode */ | ||
131 | u8 rc_toggle; /* the computed remote toggle bit */ | ||
129 | u64 ir_type; /* iMON or MCE (RC6) IR protocol? */ | 132 | u64 ir_type; /* iMON or MCE (RC6) IR protocol? */ |
130 | u8 mce_toggle_bit; /* last mce toggle bit */ | ||
131 | bool release_code; /* some keys send a release code */ | 133 | bool release_code; /* some keys send a release code */ |
132 | 134 | ||
133 | u8 display_type; /* store the display type */ | 135 | u8 display_type; /* store the display type */ |
134 | bool pad_mouse; /* toggle kbd(0)/mouse(1) mode */ | 136 | bool pad_mouse; /* toggle kbd(0)/mouse(1) mode */ |
135 | 137 | ||
138 | char name_rdev[128]; /* rc input device name */ | ||
139 | char phys_rdev[64]; /* rc input device phys path */ | ||
140 | |||
136 | char name_idev[128]; /* input device name */ | 141 | char name_idev[128]; /* input device name */ |
137 | char phys_idev[64]; /* input device phys path */ | 142 | char phys_idev[64]; /* input device phys path */ |
138 | struct timer_list itimer; /* input device timer, need for rc6 */ | ||
139 | 143 | ||
140 | char name_touch[128]; /* touch screen name */ | 144 | char name_touch[128]; /* touch screen name */ |
141 | char phys_touch[64]; /* touch screen phys path */ | 145 | char phys_touch[64]; /* touch screen phys path */ |
@@ -956,17 +960,6 @@ static void usb_tx_callback(struct urb *urb) | |||
956 | } | 960 | } |
957 | 961 | ||
958 | /** | 962 | /** |
959 | * mce/rc6 keypresses have no distinct release code, use timer | ||
960 | */ | ||
961 | static void imon_mce_timeout(unsigned long data) | ||
962 | { | ||
963 | struct imon_context *ictx = (struct imon_context *)data; | ||
964 | |||
965 | input_report_key(ictx->idev, ictx->last_keycode, 0); | ||
966 | input_sync(ictx->idev); | ||
967 | } | ||
968 | |||
969 | /** | ||
970 | * report touchscreen input | 963 | * report touchscreen input |
971 | */ | 964 | */ |
972 | static void imon_touch_display_timeout(unsigned long data) | 965 | static void imon_touch_display_timeout(unsigned long data) |
@@ -1006,9 +999,6 @@ int imon_ir_change_protocol(void *priv, u64 ir_type) | |||
1006 | dev_dbg(dev, "Configuring IR receiver for MCE protocol\n"); | 999 | dev_dbg(dev, "Configuring IR receiver for MCE protocol\n"); |
1007 | ir_proto_packet[0] = 0x01; | 1000 | ir_proto_packet[0] = 0x01; |
1008 | pad_mouse = false; | 1001 | pad_mouse = false; |
1009 | init_timer(&ictx->itimer); | ||
1010 | ictx->itimer.data = (unsigned long)ictx; | ||
1011 | ictx->itimer.function = imon_mce_timeout; | ||
1012 | break; | 1002 | break; |
1013 | case IR_TYPE_UNKNOWN: | 1003 | case IR_TYPE_UNKNOWN: |
1014 | case IR_TYPE_OTHER: | 1004 | case IR_TYPE_OTHER: |
@@ -1147,20 +1137,21 @@ static int stabilize(int a, int b, u16 timeout, u16 threshold) | |||
1147 | return result; | 1137 | return result; |
1148 | } | 1138 | } |
1149 | 1139 | ||
1150 | static u32 imon_remote_key_lookup(struct imon_context *ictx, u32 hw_code) | 1140 | static u32 imon_remote_key_lookup(struct imon_context *ictx, u32 scancode) |
1151 | { | 1141 | { |
1152 | u32 scancode = be32_to_cpu(hw_code); | ||
1153 | u32 keycode; | 1142 | u32 keycode; |
1154 | u32 release; | 1143 | u32 release; |
1155 | bool is_release_code = false; | 1144 | bool is_release_code = false; |
1156 | 1145 | ||
1157 | /* Look for the initial press of a button */ | 1146 | /* Look for the initial press of a button */ |
1158 | keycode = ir_g_keycode_from_table(ictx->idev, scancode); | 1147 | keycode = ir_g_keycode_from_table(ictx->rdev, scancode); |
1148 | ictx->rc_toggle = 0x0; | ||
1149 | ictx->rc_scancode = scancode; | ||
1159 | 1150 | ||
1160 | /* Look for the release of a button */ | 1151 | /* Look for the release of a button */ |
1161 | if (keycode == KEY_RESERVED) { | 1152 | if (keycode == KEY_RESERVED) { |
1162 | release = scancode & ~0x4000; | 1153 | release = scancode & ~0x4000; |
1163 | keycode = ir_g_keycode_from_table(ictx->idev, release); | 1154 | keycode = ir_g_keycode_from_table(ictx->rdev, release); |
1164 | if (keycode != KEY_RESERVED) | 1155 | if (keycode != KEY_RESERVED) |
1165 | is_release_code = true; | 1156 | is_release_code = true; |
1166 | } | 1157 | } |
@@ -1170,9 +1161,8 @@ static u32 imon_remote_key_lookup(struct imon_context *ictx, u32 hw_code) | |||
1170 | return keycode; | 1161 | return keycode; |
1171 | } | 1162 | } |
1172 | 1163 | ||
1173 | static u32 imon_mce_key_lookup(struct imon_context *ictx, u32 hw_code) | 1164 | static u32 imon_mce_key_lookup(struct imon_context *ictx, u32 scancode) |
1174 | { | 1165 | { |
1175 | u32 scancode = be32_to_cpu(hw_code); | ||
1176 | u32 keycode; | 1166 | u32 keycode; |
1177 | 1167 | ||
1178 | #define MCE_KEY_MASK 0x7000 | 1168 | #define MCE_KEY_MASK 0x7000 |
@@ -1186,18 +1176,21 @@ static u32 imon_mce_key_lookup(struct imon_context *ictx, u32 hw_code) | |||
1186 | * but we can't or them into all codes, as some keys are decoded in | 1176 | * but we can't or them into all codes, as some keys are decoded in |
1187 | * a different way w/o the same use of the toggle bit... | 1177 | * a different way w/o the same use of the toggle bit... |
1188 | */ | 1178 | */ |
1189 | if ((scancode >> 24) & 0x80) | 1179 | if (scancode & 0x80000000) |
1190 | scancode = scancode | MCE_KEY_MASK | MCE_TOGGLE_BIT; | 1180 | scancode = scancode | MCE_KEY_MASK | MCE_TOGGLE_BIT; |
1191 | 1181 | ||
1192 | keycode = ir_g_keycode_from_table(ictx->idev, scancode); | 1182 | ictx->rc_scancode = scancode; |
1183 | keycode = ir_g_keycode_from_table(ictx->rdev, scancode); | ||
1184 | |||
1185 | /* not used in mce mode, but make sure we know its false */ | ||
1186 | ictx->release_code = false; | ||
1193 | 1187 | ||
1194 | return keycode; | 1188 | return keycode; |
1195 | } | 1189 | } |
1196 | 1190 | ||
1197 | static u32 imon_panel_key_lookup(u64 hw_code) | 1191 | static u32 imon_panel_key_lookup(u64 code) |
1198 | { | 1192 | { |
1199 | int i; | 1193 | int i; |
1200 | u64 code = be64_to_cpu(hw_code); | ||
1201 | u32 keycode = KEY_RESERVED; | 1194 | u32 keycode = KEY_RESERVED; |
1202 | 1195 | ||
1203 | for (i = 0; i < ARRAY_SIZE(imon_panel_key_table); i++) { | 1196 | for (i = 0; i < ARRAY_SIZE(imon_panel_key_table); i++) { |
@@ -1284,8 +1277,7 @@ static void imon_pad_to_keys(struct imon_context *ictx, unsigned char *buf) | |||
1284 | int dir = 0; | 1277 | int dir = 0; |
1285 | char rel_x = 0x00, rel_y = 0x00; | 1278 | char rel_x = 0x00, rel_y = 0x00; |
1286 | u16 timeout, threshold; | 1279 | u16 timeout, threshold; |
1287 | u64 temp_key; | 1280 | u32 scancode = KEY_RESERVED; |
1288 | u32 remote_key; | ||
1289 | 1281 | ||
1290 | /* | 1282 | /* |
1291 | * The imon directional pad functions more like a touchpad. Bytes 3 & 4 | 1283 | * The imon directional pad functions more like a touchpad. Bytes 3 & 4 |
@@ -1314,21 +1306,27 @@ static void imon_pad_to_keys(struct imon_context *ictx, unsigned char *buf) | |||
1314 | } | 1306 | } |
1315 | buf[2] = dir & 0xFF; | 1307 | buf[2] = dir & 0xFF; |
1316 | buf[3] = (dir >> 8) & 0xFF; | 1308 | buf[3] = (dir >> 8) & 0xFF; |
1317 | memcpy(&temp_key, buf, sizeof(temp_key)); | 1309 | scancode = be32_to_cpu(*((u32 *)buf)); |
1318 | remote_key = (u32) (le64_to_cpu(temp_key) | ||
1319 | & 0xffffffff); | ||
1320 | ictx->kc = imon_remote_key_lookup(ictx, | ||
1321 | remote_key); | ||
1322 | } | 1310 | } |
1323 | } else { | 1311 | } else { |
1312 | /* | ||
1313 | * Hack alert: instead of using keycodes, we have | ||
1314 | * to use hard-coded scancodes here... | ||
1315 | */ | ||
1324 | if (abs(rel_y) > abs(rel_x)) { | 1316 | if (abs(rel_y) > abs(rel_x)) { |
1325 | buf[2] = (rel_y > 0) ? 0x7F : 0x80; | 1317 | buf[2] = (rel_y > 0) ? 0x7F : 0x80; |
1326 | buf[3] = 0; | 1318 | buf[3] = 0; |
1327 | ictx->kc = (rel_y > 0) ? KEY_DOWN : KEY_UP; | 1319 | if (rel_y > 0) |
1320 | scancode = 0x01007f00; /* KEY_DOWN */ | ||
1321 | else | ||
1322 | scancode = 0x01008000; /* KEY_UP */ | ||
1328 | } else { | 1323 | } else { |
1329 | buf[2] = 0; | 1324 | buf[2] = 0; |
1330 | buf[3] = (rel_x > 0) ? 0x7F : 0x80; | 1325 | buf[3] = (rel_x > 0) ? 0x7F : 0x80; |
1331 | ictx->kc = (rel_x > 0) ? KEY_RIGHT : KEY_LEFT; | 1326 | if (rel_x > 0) |
1327 | scancode = 0x0100007f; /* KEY_RIGHT */ | ||
1328 | else | ||
1329 | scancode = 0x01000080; /* KEY_LEFT */ | ||
1332 | } | 1330 | } |
1333 | } | 1331 | } |
1334 | 1332 | ||
@@ -1370,29 +1368,43 @@ static void imon_pad_to_keys(struct imon_context *ictx, unsigned char *buf) | |||
1370 | } | 1368 | } |
1371 | buf[2] = dir & 0xFF; | 1369 | buf[2] = dir & 0xFF; |
1372 | buf[3] = (dir >> 8) & 0xFF; | 1370 | buf[3] = (dir >> 8) & 0xFF; |
1373 | memcpy(&temp_key, buf, sizeof(temp_key)); | 1371 | scancode = be32_to_cpu(*((u32 *)buf)); |
1374 | remote_key = (u32) (le64_to_cpu(temp_key) & 0xffffffff); | ||
1375 | ictx->kc = imon_remote_key_lookup(ictx, remote_key); | ||
1376 | } else { | 1372 | } else { |
1373 | /* | ||
1374 | * Hack alert: instead of using keycodes, we have | ||
1375 | * to use hard-coded scancodes here... | ||
1376 | */ | ||
1377 | if (abs(rel_y) > abs(rel_x)) { | 1377 | if (abs(rel_y) > abs(rel_x)) { |
1378 | buf[2] = (rel_y > 0) ? 0x7F : 0x80; | 1378 | buf[2] = (rel_y > 0) ? 0x7F : 0x80; |
1379 | buf[3] = 0; | 1379 | buf[3] = 0; |
1380 | ictx->kc = (rel_y > 0) ? KEY_DOWN : KEY_UP; | 1380 | if (rel_y > 0) |
1381 | scancode = 0x01007f00; /* KEY_DOWN */ | ||
1382 | else | ||
1383 | scancode = 0x01008000; /* KEY_UP */ | ||
1381 | } else { | 1384 | } else { |
1382 | buf[2] = 0; | 1385 | buf[2] = 0; |
1383 | buf[3] = (rel_x > 0) ? 0x7F : 0x80; | 1386 | buf[3] = (rel_x > 0) ? 0x7F : 0x80; |
1384 | ictx->kc = (rel_x > 0) ? KEY_RIGHT : KEY_LEFT; | 1387 | if (rel_x > 0) |
1388 | scancode = 0x0100007f; /* KEY_RIGHT */ | ||
1389 | else | ||
1390 | scancode = 0x01000080; /* KEY_LEFT */ | ||
1385 | } | 1391 | } |
1386 | } | 1392 | } |
1387 | } | 1393 | } |
1394 | |||
1395 | if (scancode) | ||
1396 | ictx->kc = imon_remote_key_lookup(ictx, scancode); | ||
1388 | } | 1397 | } |
1389 | 1398 | ||
1399 | /** | ||
1400 | * figure out if these is a press or a release. We don't actually | ||
1401 | * care about repeats, as those will be auto-generated within the IR | ||
1402 | * subsystem for repeating scancodes. | ||
1403 | */ | ||
1390 | static int imon_parse_press_type(struct imon_context *ictx, | 1404 | static int imon_parse_press_type(struct imon_context *ictx, |
1391 | unsigned char *buf, u8 ktype) | 1405 | unsigned char *buf, u8 ktype) |
1392 | { | 1406 | { |
1393 | int press_type = 0; | 1407 | int press_type = 0; |
1394 | int rep_delay = ictx->idev->rep[REP_DELAY]; | ||
1395 | int rep_period = ictx->idev->rep[REP_PERIOD]; | ||
1396 | 1408 | ||
1397 | /* key release of 0x02XXXXXX key */ | 1409 | /* key release of 0x02XXXXXX key */ |
1398 | if (ictx->kc == KEY_RESERVED && buf[0] == 0x02 && buf[3] == 0x00) | 1410 | if (ictx->kc == KEY_RESERVED && buf[0] == 0x02 && buf[3] == 0x00) |
@@ -1408,22 +1420,10 @@ static int imon_parse_press_type(struct imon_context *ictx, | |||
1408 | buf[2] == 0x81 && buf[3] == 0xb7) | 1420 | buf[2] == 0x81 && buf[3] == 0xb7) |
1409 | ictx->kc = ictx->last_keycode; | 1421 | ictx->kc = ictx->last_keycode; |
1410 | 1422 | ||
1411 | /* mce-specific button handling */ | 1423 | /* mce-specific button handling, no keyup events */ |
1412 | else if (ktype == IMON_KEY_MCE) { | 1424 | else if (ktype == IMON_KEY_MCE) { |
1413 | /* initial press */ | 1425 | ictx->rc_toggle = buf[2]; |
1414 | if (ictx->kc != ictx->last_keycode | 1426 | press_type = 1; |
1415 | || buf[2] != ictx->mce_toggle_bit) { | ||
1416 | ictx->last_keycode = ictx->kc; | ||
1417 | ictx->mce_toggle_bit = buf[2]; | ||
1418 | press_type = 1; | ||
1419 | mod_timer(&ictx->itimer, | ||
1420 | jiffies + msecs_to_jiffies(rep_delay)); | ||
1421 | /* repeat */ | ||
1422 | } else { | ||
1423 | press_type = 2; | ||
1424 | mod_timer(&ictx->itimer, | ||
1425 | jiffies + msecs_to_jiffies(rep_period)); | ||
1426 | } | ||
1427 | 1427 | ||
1428 | /* incoherent or irrelevant data */ | 1428 | /* incoherent or irrelevant data */ |
1429 | } else if (ictx->kc == KEY_RESERVED) | 1429 | } else if (ictx->kc == KEY_RESERVED) |
@@ -1452,36 +1452,38 @@ static void imon_incoming_packet(struct imon_context *ictx, | |||
1452 | u32 kc; | 1452 | u32 kc; |
1453 | bool norelease = false; | 1453 | bool norelease = false; |
1454 | int i; | 1454 | int i; |
1455 | u64 temp_key; | 1455 | u64 scancode; |
1456 | u64 panel_key = 0; | ||
1457 | u32 remote_key = 0; | ||
1458 | struct input_dev *idev = NULL; | 1456 | struct input_dev *idev = NULL; |
1457 | struct ir_input_dev *irdev = NULL; | ||
1459 | int press_type = 0; | 1458 | int press_type = 0; |
1460 | int msec; | 1459 | int msec; |
1461 | struct timeval t; | 1460 | struct timeval t; |
1462 | static struct timeval prev_time = { 0, 0 }; | 1461 | static struct timeval prev_time = { 0, 0 }; |
1463 | u8 ktype = IMON_KEY_IMON; | 1462 | u8 ktype; |
1464 | 1463 | ||
1465 | idev = ictx->idev; | 1464 | idev = ictx->idev; |
1465 | irdev = input_get_drvdata(idev); | ||
1466 | 1466 | ||
1467 | /* filter out junk data on the older 0xffdc imon devices */ | 1467 | /* filter out junk data on the older 0xffdc imon devices */ |
1468 | if ((buf[0] == 0xff) && (buf[1] == 0xff) && (buf[2] == 0xff)) | 1468 | if ((buf[0] == 0xff) && (buf[1] == 0xff) && (buf[2] == 0xff)) |
1469 | return; | 1469 | return; |
1470 | 1470 | ||
1471 | /* Figure out what key was pressed */ | 1471 | /* Figure out what key was pressed */ |
1472 | memcpy(&temp_key, buf, sizeof(temp_key)); | ||
1473 | if (len == 8 && buf[7] == 0xee) { | 1472 | if (len == 8 && buf[7] == 0xee) { |
1473 | scancode = be64_to_cpu(*((u64 *)buf)); | ||
1474 | ktype = IMON_KEY_PANEL; | 1474 | ktype = IMON_KEY_PANEL; |
1475 | panel_key = le64_to_cpu(temp_key); | 1475 | kc = imon_panel_key_lookup(scancode); |
1476 | kc = imon_panel_key_lookup(panel_key); | ||
1477 | } else { | 1476 | } else { |
1478 | remote_key = (u32) (le64_to_cpu(temp_key) & 0xffffffff); | 1477 | scancode = be32_to_cpu(*((u32 *)buf)); |
1479 | if (ictx->ir_type == IR_TYPE_RC6) { | 1478 | if (ictx->ir_type == IR_TYPE_RC6) { |
1479 | ktype = IMON_KEY_IMON; | ||
1480 | if (buf[0] == 0x80) | 1480 | if (buf[0] == 0x80) |
1481 | ktype = IMON_KEY_MCE; | 1481 | ktype = IMON_KEY_MCE; |
1482 | kc = imon_mce_key_lookup(ictx, remote_key); | 1482 | kc = imon_mce_key_lookup(ictx, scancode); |
1483 | } else | 1483 | } else { |
1484 | kc = imon_remote_key_lookup(ictx, remote_key); | 1484 | ktype = IMON_KEY_IMON; |
1485 | kc = imon_remote_key_lookup(ictx, scancode); | ||
1486 | } | ||
1485 | } | 1487 | } |
1486 | 1488 | ||
1487 | /* keyboard/mouse mode toggle button */ | 1489 | /* keyboard/mouse mode toggle button */ |
@@ -1504,6 +1506,7 @@ static void imon_incoming_packet(struct imon_context *ictx, | |||
1504 | if (ictx->display_type == IMON_DISPLAY_TYPE_VGA && len == 8 && | 1506 | if (ictx->display_type == IMON_DISPLAY_TYPE_VGA && len == 8 && |
1505 | buf[7] == 0x86) { | 1507 | buf[7] == 0x86) { |
1506 | imon_touch_event(ictx, buf); | 1508 | imon_touch_event(ictx, buf); |
1509 | return; | ||
1507 | 1510 | ||
1508 | /* look for mouse events with pad in mouse mode */ | 1511 | /* look for mouse events with pad in mouse mode */ |
1509 | } else if (ictx->pad_mouse) { | 1512 | } else if (ictx->pad_mouse) { |
@@ -1534,9 +1537,20 @@ static void imon_incoming_packet(struct imon_context *ictx, | |||
1534 | if (ictx->kc == KEY_UNKNOWN) | 1537 | if (ictx->kc == KEY_UNKNOWN) |
1535 | goto unknown_key; | 1538 | goto unknown_key; |
1536 | 1539 | ||
1537 | /* KEY_MUTE repeats from MCE and knob need to be suppressed */ | 1540 | if (ktype != IMON_KEY_PANEL) { |
1538 | if ((ictx->kc == KEY_MUTE && ictx->kc == ictx->last_keycode) | 1541 | if (press_type == 0) |
1539 | && (buf[7] == 0xee || ktype == IMON_KEY_MCE)) { | 1542 | ir_keyup(irdev); |
1543 | else { | ||
1544 | ir_keydown(ictx->rdev, ictx->rc_scancode, | ||
1545 | ictx->rc_toggle); | ||
1546 | ictx->last_keycode = ictx->kc; | ||
1547 | } | ||
1548 | return; | ||
1549 | } | ||
1550 | |||
1551 | /* Only panel type events left to process now */ | ||
1552 | /* KEY_MUTE repeats from knob need to be suppressed */ | ||
1553 | if (ictx->kc == KEY_MUTE && ictx->kc == ictx->last_keycode) { | ||
1540 | do_gettimeofday(&t); | 1554 | do_gettimeofday(&t); |
1541 | msec = tv2int(&t, &prev_time); | 1555 | msec = tv2int(&t, &prev_time); |
1542 | prev_time = t; | 1556 | prev_time = t; |
@@ -1547,11 +1561,9 @@ static void imon_incoming_packet(struct imon_context *ictx, | |||
1547 | input_report_key(idev, ictx->kc, press_type); | 1561 | input_report_key(idev, ictx->kc, press_type); |
1548 | input_sync(idev); | 1562 | input_sync(idev); |
1549 | 1563 | ||
1550 | /* panel keys and some remote keys don't generate a release */ | 1564 | /* panel keys don't generate a release */ |
1551 | if (panel_key || norelease) { | 1565 | input_report_key(idev, ictx->kc, 0); |
1552 | input_report_key(idev, ictx->kc, 0); | 1566 | input_sync(idev); |
1553 | input_sync(idev); | ||
1554 | } | ||
1555 | 1567 | ||
1556 | ictx->last_keycode = ictx->kc; | 1568 | ictx->last_keycode = ictx->kc; |
1557 | 1569 | ||
@@ -1559,8 +1571,7 @@ static void imon_incoming_packet(struct imon_context *ictx, | |||
1559 | 1571 | ||
1560 | unknown_key: | 1572 | unknown_key: |
1561 | dev_info(dev, "%s: unknown keypress, code 0x%llx\n", __func__, | 1573 | dev_info(dev, "%s: unknown keypress, code 0x%llx\n", __func__, |
1562 | (panel_key ? be64_to_cpu(panel_key) : | 1574 | (long long)scancode); |
1563 | be32_to_cpu(remote_key))); | ||
1564 | return; | 1575 | return; |
1565 | 1576 | ||
1566 | not_input_data: | 1577 | not_input_data: |
@@ -1651,31 +1662,71 @@ static void usb_rx_callback_intf1(struct urb *urb) | |||
1651 | usb_submit_urb(ictx->rx_urb_intf1, GFP_ATOMIC); | 1662 | usb_submit_urb(ictx->rx_urb_intf1, GFP_ATOMIC); |
1652 | } | 1663 | } |
1653 | 1664 | ||
1665 | static struct input_dev *imon_init_rdev(struct imon_context *ictx) | ||
1666 | { | ||
1667 | struct input_dev *rdev; | ||
1668 | struct ir_dev_props *props; | ||
1669 | int ret; | ||
1670 | |||
1671 | rdev = input_allocate_device(); | ||
1672 | props = kzalloc(sizeof(*props), GFP_KERNEL); | ||
1673 | if (!rdev || !props) { | ||
1674 | dev_err(ictx->dev, "remote control dev allocation failed\n"); | ||
1675 | goto out; | ||
1676 | } | ||
1677 | |||
1678 | snprintf(ictx->name_rdev, sizeof(ictx->name_rdev), | ||
1679 | "iMON Remote (%04x:%04x)", ictx->vendor, ictx->product); | ||
1680 | usb_make_path(ictx->usbdev_intf0, ictx->phys_rdev, | ||
1681 | sizeof(ictx->phys_rdev)); | ||
1682 | strlcat(ictx->phys_rdev, "/input0", sizeof(ictx->phys_rdev)); | ||
1683 | |||
1684 | rdev->name = ictx->name_rdev; | ||
1685 | rdev->phys = ictx->phys_rdev; | ||
1686 | usb_to_input_id(ictx->usbdev_intf0, &rdev->id); | ||
1687 | rdev->dev.parent = ictx->dev; | ||
1688 | rdev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); | ||
1689 | input_set_drvdata(rdev, ictx); | ||
1690 | |||
1691 | props->priv = ictx; | ||
1692 | props->driver_type = RC_DRIVER_SCANCODE; | ||
1693 | props->allowed_protos = IR_TYPE_OTHER | IR_TYPE_RC6; /* iMON PAD or MCE */ | ||
1694 | props->change_protocol = imon_ir_change_protocol; | ||
1695 | ictx->props = props; | ||
1696 | |||
1697 | ret = ir_input_register(rdev, RC_MAP_IMON_PAD, props, MOD_NAME); | ||
1698 | if (ret < 0) { | ||
1699 | dev_err(ictx->dev, "remote input dev register failed\n"); | ||
1700 | goto out; | ||
1701 | } | ||
1702 | |||
1703 | return rdev; | ||
1704 | |||
1705 | out: | ||
1706 | kfree(props); | ||
1707 | input_free_device(rdev); | ||
1708 | return NULL; | ||
1709 | } | ||
1710 | |||
1654 | static struct input_dev *imon_init_idev(struct imon_context *ictx) | 1711 | static struct input_dev *imon_init_idev(struct imon_context *ictx) |
1655 | { | 1712 | { |
1656 | struct input_dev *idev; | 1713 | struct input_dev *idev; |
1657 | struct ir_dev_props *props; | ||
1658 | int ret, i; | 1714 | int ret, i; |
1659 | 1715 | ||
1660 | idev = input_allocate_device(); | 1716 | idev = input_allocate_device(); |
1661 | if (!idev) { | 1717 | if (!idev) { |
1662 | dev_err(ictx->dev, "remote input dev allocation failed\n"); | 1718 | dev_err(ictx->dev, "input dev allocation failed\n"); |
1663 | goto idev_alloc_failed; | 1719 | goto out; |
1664 | } | ||
1665 | |||
1666 | props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL); | ||
1667 | if (!props) { | ||
1668 | dev_err(ictx->dev, "remote ir dev props allocation failed\n"); | ||
1669 | goto props_alloc_failed; | ||
1670 | } | 1720 | } |
1671 | 1721 | ||
1672 | snprintf(ictx->name_idev, sizeof(ictx->name_idev), | 1722 | snprintf(ictx->name_idev, sizeof(ictx->name_idev), |
1673 | "iMON Remote (%04x:%04x)", ictx->vendor, ictx->product); | 1723 | "iMON Panel, Knob and Mouse(%04x:%04x)", |
1724 | ictx->vendor, ictx->product); | ||
1674 | idev->name = ictx->name_idev; | 1725 | idev->name = ictx->name_idev; |
1675 | 1726 | ||
1676 | usb_make_path(ictx->usbdev_intf0, ictx->phys_idev, | 1727 | usb_make_path(ictx->usbdev_intf0, ictx->phys_idev, |
1677 | sizeof(ictx->phys_idev)); | 1728 | sizeof(ictx->phys_idev)); |
1678 | strlcat(ictx->phys_idev, "/input0", sizeof(ictx->phys_idev)); | 1729 | strlcat(ictx->phys_idev, "/input1", sizeof(ictx->phys_idev)); |
1679 | idev->phys = ictx->phys_idev; | 1730 | idev->phys = ictx->phys_idev; |
1680 | 1731 | ||
1681 | idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) | BIT_MASK(EV_REL); | 1732 | idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) | BIT_MASK(EV_REL); |
@@ -1691,30 +1742,20 @@ static struct input_dev *imon_init_idev(struct imon_context *ictx) | |||
1691 | __set_bit(kc, idev->keybit); | 1742 | __set_bit(kc, idev->keybit); |
1692 | } | 1743 | } |
1693 | 1744 | ||
1694 | props->priv = ictx; | ||
1695 | props->driver_type = RC_DRIVER_SCANCODE; | ||
1696 | /* IR_TYPE_OTHER maps to iMON PAD remote, IR_TYPE_RC6 to MCE remote */ | ||
1697 | props->allowed_protos = IR_TYPE_OTHER | IR_TYPE_RC6; | ||
1698 | props->change_protocol = imon_ir_change_protocol; | ||
1699 | ictx->props = props; | ||
1700 | |||
1701 | usb_to_input_id(ictx->usbdev_intf0, &idev->id); | 1745 | usb_to_input_id(ictx->usbdev_intf0, &idev->id); |
1702 | idev->dev.parent = ictx->dev; | 1746 | idev->dev.parent = ictx->dev; |
1747 | input_set_drvdata(idev, ictx); | ||
1703 | 1748 | ||
1704 | ret = ir_input_register(idev, RC_MAP_IMON_PAD, props, MOD_NAME); | 1749 | ret = input_register_device(idev); |
1705 | if (ret < 0) { | 1750 | if (ret < 0) { |
1706 | dev_err(ictx->dev, "remote input dev register failed\n"); | 1751 | dev_err(ictx->dev, "input dev register failed\n"); |
1707 | goto idev_register_failed; | 1752 | goto out; |
1708 | } | 1753 | } |
1709 | 1754 | ||
1710 | return idev; | 1755 | return idev; |
1711 | 1756 | ||
1712 | idev_register_failed: | 1757 | out: |
1713 | kfree(props); | ||
1714 | props_alloc_failed: | ||
1715 | input_free_device(idev); | 1758 | input_free_device(idev); |
1716 | idev_alloc_failed: | ||
1717 | |||
1718 | return NULL; | 1759 | return NULL; |
1719 | } | 1760 | } |
1720 | 1761 | ||
@@ -1736,7 +1777,7 @@ static struct input_dev *imon_init_touch(struct imon_context *ictx) | |||
1736 | 1777 | ||
1737 | usb_make_path(ictx->usbdev_intf1, ictx->phys_touch, | 1778 | usb_make_path(ictx->usbdev_intf1, ictx->phys_touch, |
1738 | sizeof(ictx->phys_touch)); | 1779 | sizeof(ictx->phys_touch)); |
1739 | strlcat(ictx->phys_touch, "/input1", sizeof(ictx->phys_touch)); | 1780 | strlcat(ictx->phys_touch, "/input2", sizeof(ictx->phys_touch)); |
1740 | touch->phys = ictx->phys_touch; | 1781 | touch->phys = ictx->phys_touch; |
1741 | 1782 | ||
1742 | touch->evbit[0] = | 1783 | touch->evbit[0] = |
@@ -1911,6 +1952,12 @@ static struct imon_context *imon_init_intf0(struct usb_interface *intf) | |||
1911 | goto idev_setup_failed; | 1952 | goto idev_setup_failed; |
1912 | } | 1953 | } |
1913 | 1954 | ||
1955 | ictx->rdev = imon_init_rdev(ictx); | ||
1956 | if (!ictx->rdev) { | ||
1957 | dev_err(dev, "%s: rc device setup failed\n", __func__); | ||
1958 | goto rdev_setup_failed; | ||
1959 | } | ||
1960 | |||
1914 | usb_fill_int_urb(ictx->rx_urb_intf0, ictx->usbdev_intf0, | 1961 | usb_fill_int_urb(ictx->rx_urb_intf0, ictx->usbdev_intf0, |
1915 | usb_rcvintpipe(ictx->usbdev_intf0, | 1962 | usb_rcvintpipe(ictx->usbdev_intf0, |
1916 | ictx->rx_endpoint_intf0->bEndpointAddress), | 1963 | ictx->rx_endpoint_intf0->bEndpointAddress), |
@@ -1928,7 +1975,9 @@ static struct imon_context *imon_init_intf0(struct usb_interface *intf) | |||
1928 | return ictx; | 1975 | return ictx; |
1929 | 1976 | ||
1930 | urb_submit_failed: | 1977 | urb_submit_failed: |
1931 | ir_input_unregister(ictx->idev); | 1978 | ir_input_unregister(ictx->rdev); |
1979 | rdev_setup_failed: | ||
1980 | input_unregister_device(ictx->idev); | ||
1932 | idev_setup_failed: | 1981 | idev_setup_failed: |
1933 | find_endpoint_failed: | 1982 | find_endpoint_failed: |
1934 | mutex_unlock(&ictx->lock); | 1983 | mutex_unlock(&ictx->lock); |
@@ -2289,7 +2338,8 @@ static void __devexit imon_disconnect(struct usb_interface *interface) | |||
2289 | if (ifnum == 0) { | 2338 | if (ifnum == 0) { |
2290 | ictx->dev_present_intf0 = false; | 2339 | ictx->dev_present_intf0 = false; |
2291 | usb_kill_urb(ictx->rx_urb_intf0); | 2340 | usb_kill_urb(ictx->rx_urb_intf0); |
2292 | ir_input_unregister(ictx->idev); | 2341 | input_unregister_device(ictx->idev); |
2342 | ir_input_unregister(ictx->rdev); | ||
2293 | if (ictx->display_supported) { | 2343 | if (ictx->display_supported) { |
2294 | if (ictx->display_type == IMON_DISPLAY_TYPE_LCD) | 2344 | if (ictx->display_type == IMON_DISPLAY_TYPE_LCD) |
2295 | usb_deregister_dev(interface, &imon_lcd_class); | 2345 | usb_deregister_dev(interface, &imon_lcd_class); |
@@ -2309,11 +2359,8 @@ static void __devexit imon_disconnect(struct usb_interface *interface) | |||
2309 | mutex_unlock(&ictx->lock); | 2359 | mutex_unlock(&ictx->lock); |
2310 | if (!ictx->display_isopen) | 2360 | if (!ictx->display_isopen) |
2311 | free_imon_context(ictx); | 2361 | free_imon_context(ictx); |
2312 | } else { | 2362 | } else |
2313 | if (ictx->ir_type == IR_TYPE_RC6) | ||
2314 | del_timer_sync(&ictx->itimer); | ||
2315 | mutex_unlock(&ictx->lock); | 2363 | mutex_unlock(&ictx->lock); |
2316 | } | ||
2317 | 2364 | ||
2318 | mutex_unlock(&driver_lock); | 2365 | mutex_unlock(&driver_lock); |
2319 | 2366 | ||