|
@@ -44,7 +44,7 @@
|
|
|
#define MOD_AUTHOR "Jarod Wilson <jarod@wilsonet.com>"
|
|
|
#define MOD_DESC "Driver for SoundGraph iMON MultiMedia IR/Display"
|
|
|
#define MOD_NAME "imon"
|
|
|
-#define MOD_VERSION "0.9.1"
|
|
|
+#define MOD_VERSION "0.9.2"
|
|
|
|
|
|
#define DISPLAY_MINOR_BASE 144
|
|
|
#define DEVICE_NAME "lcd%d"
|
|
@@ -121,21 +121,25 @@ struct imon_context {
|
|
|
u16 vendor; /* usb vendor ID */
|
|
|
u16 product; /* usb product ID */
|
|
|
|
|
|
- struct input_dev *idev; /* input device for remote */
|
|
|
+ struct input_dev *rdev; /* input device for remote */
|
|
|
+ struct input_dev *idev; /* input device for panel & IR mouse */
|
|
|
struct input_dev *touch; /* input device for touchscreen */
|
|
|
|
|
|
u32 kc; /* current input keycode */
|
|
|
u32 last_keycode; /* last reported input keycode */
|
|
|
+ u32 rc_scancode; /* the computed remote scancode */
|
|
|
+ u8 rc_toggle; /* the computed remote toggle bit */
|
|
|
u64 ir_type; /* iMON or MCE (RC6) IR protocol? */
|
|
|
- u8 mce_toggle_bit; /* last mce toggle bit */
|
|
|
bool release_code; /* some keys send a release code */
|
|
|
|
|
|
u8 display_type; /* store the display type */
|
|
|
bool pad_mouse; /* toggle kbd(0)/mouse(1) mode */
|
|
|
|
|
|
+ char name_rdev[128]; /* rc input device name */
|
|
|
+ char phys_rdev[64]; /* rc input device phys path */
|
|
|
+
|
|
|
char name_idev[128]; /* input device name */
|
|
|
char phys_idev[64]; /* input device phys path */
|
|
|
- struct timer_list itimer; /* input device timer, need for rc6 */
|
|
|
|
|
|
char name_touch[128]; /* touch screen name */
|
|
|
char phys_touch[64]; /* touch screen phys path */
|
|
@@ -955,17 +959,6 @@ static void usb_tx_callback(struct urb *urb)
|
|
|
complete(&ictx->tx.finished);
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * mce/rc6 keypresses have no distinct release code, use timer
|
|
|
- */
|
|
|
-static void imon_mce_timeout(unsigned long data)
|
|
|
-{
|
|
|
- struct imon_context *ictx = (struct imon_context *)data;
|
|
|
-
|
|
|
- input_report_key(ictx->idev, ictx->last_keycode, 0);
|
|
|
- input_sync(ictx->idev);
|
|
|
-}
|
|
|
-
|
|
|
/**
|
|
|
* report touchscreen input
|
|
|
*/
|
|
@@ -1006,9 +999,6 @@ int imon_ir_change_protocol(void *priv, u64 ir_type)
|
|
|
dev_dbg(dev, "Configuring IR receiver for MCE protocol\n");
|
|
|
ir_proto_packet[0] = 0x01;
|
|
|
pad_mouse = false;
|
|
|
- init_timer(&ictx->itimer);
|
|
|
- ictx->itimer.data = (unsigned long)ictx;
|
|
|
- ictx->itimer.function = imon_mce_timeout;
|
|
|
break;
|
|
|
case IR_TYPE_UNKNOWN:
|
|
|
case IR_TYPE_OTHER:
|
|
@@ -1147,20 +1137,21 @@ static int stabilize(int a, int b, u16 timeout, u16 threshold)
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
-static u32 imon_remote_key_lookup(struct imon_context *ictx, u32 hw_code)
|
|
|
+static u32 imon_remote_key_lookup(struct imon_context *ictx, u32 scancode)
|
|
|
{
|
|
|
- u32 scancode = be32_to_cpu(hw_code);
|
|
|
u32 keycode;
|
|
|
u32 release;
|
|
|
bool is_release_code = false;
|
|
|
|
|
|
/* Look for the initial press of a button */
|
|
|
- keycode = ir_g_keycode_from_table(ictx->idev, scancode);
|
|
|
+ keycode = ir_g_keycode_from_table(ictx->rdev, scancode);
|
|
|
+ ictx->rc_toggle = 0x0;
|
|
|
+ ictx->rc_scancode = scancode;
|
|
|
|
|
|
/* Look for the release of a button */
|
|
|
if (keycode == KEY_RESERVED) {
|
|
|
release = scancode & ~0x4000;
|
|
|
- keycode = ir_g_keycode_from_table(ictx->idev, release);
|
|
|
+ keycode = ir_g_keycode_from_table(ictx->rdev, release);
|
|
|
if (keycode != KEY_RESERVED)
|
|
|
is_release_code = true;
|
|
|
}
|
|
@@ -1170,9 +1161,8 @@ static u32 imon_remote_key_lookup(struct imon_context *ictx, u32 hw_code)
|
|
|
return keycode;
|
|
|
}
|
|
|
|
|
|
-static u32 imon_mce_key_lookup(struct imon_context *ictx, u32 hw_code)
|
|
|
+static u32 imon_mce_key_lookup(struct imon_context *ictx, u32 scancode)
|
|
|
{
|
|
|
- u32 scancode = be32_to_cpu(hw_code);
|
|
|
u32 keycode;
|
|
|
|
|
|
#define MCE_KEY_MASK 0x7000
|
|
@@ -1186,18 +1176,21 @@ static u32 imon_mce_key_lookup(struct imon_context *ictx, u32 hw_code)
|
|
|
* but we can't or them into all codes, as some keys are decoded in
|
|
|
* a different way w/o the same use of the toggle bit...
|
|
|
*/
|
|
|
- if ((scancode >> 24) & 0x80)
|
|
|
+ if (scancode & 0x80000000)
|
|
|
scancode = scancode | MCE_KEY_MASK | MCE_TOGGLE_BIT;
|
|
|
|
|
|
- keycode = ir_g_keycode_from_table(ictx->idev, scancode);
|
|
|
+ ictx->rc_scancode = scancode;
|
|
|
+ keycode = ir_g_keycode_from_table(ictx->rdev, scancode);
|
|
|
+
|
|
|
+ /* not used in mce mode, but make sure we know its false */
|
|
|
+ ictx->release_code = false;
|
|
|
|
|
|
return keycode;
|
|
|
}
|
|
|
|
|
|
-static u32 imon_panel_key_lookup(u64 hw_code)
|
|
|
+static u32 imon_panel_key_lookup(u64 code)
|
|
|
{
|
|
|
int i;
|
|
|
- u64 code = be64_to_cpu(hw_code);
|
|
|
u32 keycode = KEY_RESERVED;
|
|
|
|
|
|
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)
|
|
|
int dir = 0;
|
|
|
char rel_x = 0x00, rel_y = 0x00;
|
|
|
u16 timeout, threshold;
|
|
|
- u64 temp_key;
|
|
|
- u32 remote_key;
|
|
|
+ u32 scancode = KEY_RESERVED;
|
|
|
|
|
|
/*
|
|
|
* 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)
|
|
|
}
|
|
|
buf[2] = dir & 0xFF;
|
|
|
buf[3] = (dir >> 8) & 0xFF;
|
|
|
- memcpy(&temp_key, buf, sizeof(temp_key));
|
|
|
- remote_key = (u32) (le64_to_cpu(temp_key)
|
|
|
- & 0xffffffff);
|
|
|
- ictx->kc = imon_remote_key_lookup(ictx,
|
|
|
- remote_key);
|
|
|
+ scancode = be32_to_cpu(*((u32 *)buf));
|
|
|
}
|
|
|
} else {
|
|
|
+ /*
|
|
|
+ * Hack alert: instead of using keycodes, we have
|
|
|
+ * to use hard-coded scancodes here...
|
|
|
+ */
|
|
|
if (abs(rel_y) > abs(rel_x)) {
|
|
|
buf[2] = (rel_y > 0) ? 0x7F : 0x80;
|
|
|
buf[3] = 0;
|
|
|
- ictx->kc = (rel_y > 0) ? KEY_DOWN : KEY_UP;
|
|
|
+ if (rel_y > 0)
|
|
|
+ scancode = 0x01007f00; /* KEY_DOWN */
|
|
|
+ else
|
|
|
+ scancode = 0x01008000; /* KEY_UP */
|
|
|
} else {
|
|
|
buf[2] = 0;
|
|
|
buf[3] = (rel_x > 0) ? 0x7F : 0x80;
|
|
|
- ictx->kc = (rel_x > 0) ? KEY_RIGHT : KEY_LEFT;
|
|
|
+ if (rel_x > 0)
|
|
|
+ scancode = 0x0100007f; /* KEY_RIGHT */
|
|
|
+ else
|
|
|
+ scancode = 0x01000080; /* KEY_LEFT */
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1370,29 +1368,43 @@ static void imon_pad_to_keys(struct imon_context *ictx, unsigned char *buf)
|
|
|
}
|
|
|
buf[2] = dir & 0xFF;
|
|
|
buf[3] = (dir >> 8) & 0xFF;
|
|
|
- memcpy(&temp_key, buf, sizeof(temp_key));
|
|
|
- remote_key = (u32) (le64_to_cpu(temp_key) & 0xffffffff);
|
|
|
- ictx->kc = imon_remote_key_lookup(ictx, remote_key);
|
|
|
+ scancode = be32_to_cpu(*((u32 *)buf));
|
|
|
} else {
|
|
|
+ /*
|
|
|
+ * Hack alert: instead of using keycodes, we have
|
|
|
+ * to use hard-coded scancodes here...
|
|
|
+ */
|
|
|
if (abs(rel_y) > abs(rel_x)) {
|
|
|
buf[2] = (rel_y > 0) ? 0x7F : 0x80;
|
|
|
buf[3] = 0;
|
|
|
- ictx->kc = (rel_y > 0) ? KEY_DOWN : KEY_UP;
|
|
|
+ if (rel_y > 0)
|
|
|
+ scancode = 0x01007f00; /* KEY_DOWN */
|
|
|
+ else
|
|
|
+ scancode = 0x01008000; /* KEY_UP */
|
|
|
} else {
|
|
|
buf[2] = 0;
|
|
|
buf[3] = (rel_x > 0) ? 0x7F : 0x80;
|
|
|
- ictx->kc = (rel_x > 0) ? KEY_RIGHT : KEY_LEFT;
|
|
|
+ if (rel_x > 0)
|
|
|
+ scancode = 0x0100007f; /* KEY_RIGHT */
|
|
|
+ else
|
|
|
+ scancode = 0x01000080; /* KEY_LEFT */
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ if (scancode)
|
|
|
+ ictx->kc = imon_remote_key_lookup(ictx, scancode);
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * figure out if these is a press or a release. We don't actually
|
|
|
+ * care about repeats, as those will be auto-generated within the IR
|
|
|
+ * subsystem for repeating scancodes.
|
|
|
+ */
|
|
|
static int imon_parse_press_type(struct imon_context *ictx,
|
|
|
unsigned char *buf, u8 ktype)
|
|
|
{
|
|
|
int press_type = 0;
|
|
|
- int rep_delay = ictx->idev->rep[REP_DELAY];
|
|
|
- int rep_period = ictx->idev->rep[REP_PERIOD];
|
|
|
|
|
|
/* key release of 0x02XXXXXX key */
|
|
|
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,
|
|
|
buf[2] == 0x81 && buf[3] == 0xb7)
|
|
|
ictx->kc = ictx->last_keycode;
|
|
|
|
|
|
- /* mce-specific button handling */
|
|
|
+ /* mce-specific button handling, no keyup events */
|
|
|
else if (ktype == IMON_KEY_MCE) {
|
|
|
- /* initial press */
|
|
|
- if (ictx->kc != ictx->last_keycode
|
|
|
- || buf[2] != ictx->mce_toggle_bit) {
|
|
|
- ictx->last_keycode = ictx->kc;
|
|
|
- ictx->mce_toggle_bit = buf[2];
|
|
|
- press_type = 1;
|
|
|
- mod_timer(&ictx->itimer,
|
|
|
- jiffies + msecs_to_jiffies(rep_delay));
|
|
|
- /* repeat */
|
|
|
- } else {
|
|
|
- press_type = 2;
|
|
|
- mod_timer(&ictx->itimer,
|
|
|
- jiffies + msecs_to_jiffies(rep_period));
|
|
|
- }
|
|
|
+ ictx->rc_toggle = buf[2];
|
|
|
+ press_type = 1;
|
|
|
|
|
|
/* incoherent or irrelevant data */
|
|
|
} else if (ictx->kc == KEY_RESERVED)
|
|
@@ -1452,36 +1452,38 @@ static void imon_incoming_packet(struct imon_context *ictx,
|
|
|
u32 kc;
|
|
|
bool norelease = false;
|
|
|
int i;
|
|
|
- u64 temp_key;
|
|
|
- u64 panel_key = 0;
|
|
|
- u32 remote_key = 0;
|
|
|
+ u64 scancode;
|
|
|
struct input_dev *idev = NULL;
|
|
|
+ struct ir_input_dev *irdev = NULL;
|
|
|
int press_type = 0;
|
|
|
int msec;
|
|
|
struct timeval t;
|
|
|
static struct timeval prev_time = { 0, 0 };
|
|
|
- u8 ktype = IMON_KEY_IMON;
|
|
|
+ u8 ktype;
|
|
|
|
|
|
idev = ictx->idev;
|
|
|
+ irdev = input_get_drvdata(idev);
|
|
|
|
|
|
/* filter out junk data on the older 0xffdc imon devices */
|
|
|
if ((buf[0] == 0xff) && (buf[1] == 0xff) && (buf[2] == 0xff))
|
|
|
return;
|
|
|
|
|
|
/* Figure out what key was pressed */
|
|
|
- memcpy(&temp_key, buf, sizeof(temp_key));
|
|
|
if (len == 8 && buf[7] == 0xee) {
|
|
|
+ scancode = be64_to_cpu(*((u64 *)buf));
|
|
|
ktype = IMON_KEY_PANEL;
|
|
|
- panel_key = le64_to_cpu(temp_key);
|
|
|
- kc = imon_panel_key_lookup(panel_key);
|
|
|
+ kc = imon_panel_key_lookup(scancode);
|
|
|
} else {
|
|
|
- remote_key = (u32) (le64_to_cpu(temp_key) & 0xffffffff);
|
|
|
+ scancode = be32_to_cpu(*((u32 *)buf));
|
|
|
if (ictx->ir_type == IR_TYPE_RC6) {
|
|
|
+ ktype = IMON_KEY_IMON;
|
|
|
if (buf[0] == 0x80)
|
|
|
ktype = IMON_KEY_MCE;
|
|
|
- kc = imon_mce_key_lookup(ictx, remote_key);
|
|
|
- } else
|
|
|
- kc = imon_remote_key_lookup(ictx, remote_key);
|
|
|
+ kc = imon_mce_key_lookup(ictx, scancode);
|
|
|
+ } else {
|
|
|
+ ktype = IMON_KEY_IMON;
|
|
|
+ kc = imon_remote_key_lookup(ictx, scancode);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/* keyboard/mouse mode toggle button */
|
|
@@ -1504,6 +1506,7 @@ static void imon_incoming_packet(struct imon_context *ictx,
|
|
|
if (ictx->display_type == IMON_DISPLAY_TYPE_VGA && len == 8 &&
|
|
|
buf[7] == 0x86) {
|
|
|
imon_touch_event(ictx, buf);
|
|
|
+ return;
|
|
|
|
|
|
/* look for mouse events with pad in mouse mode */
|
|
|
} else if (ictx->pad_mouse) {
|
|
@@ -1534,9 +1537,20 @@ static void imon_incoming_packet(struct imon_context *ictx,
|
|
|
if (ictx->kc == KEY_UNKNOWN)
|
|
|
goto unknown_key;
|
|
|
|
|
|
- /* KEY_MUTE repeats from MCE and knob need to be suppressed */
|
|
|
- if ((ictx->kc == KEY_MUTE && ictx->kc == ictx->last_keycode)
|
|
|
- && (buf[7] == 0xee || ktype == IMON_KEY_MCE)) {
|
|
|
+ if (ktype != IMON_KEY_PANEL) {
|
|
|
+ if (press_type == 0)
|
|
|
+ ir_keyup(irdev);
|
|
|
+ else {
|
|
|
+ ir_keydown(ictx->rdev, ictx->rc_scancode,
|
|
|
+ ictx->rc_toggle);
|
|
|
+ ictx->last_keycode = ictx->kc;
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Only panel type events left to process now */
|
|
|
+ /* KEY_MUTE repeats from knob need to be suppressed */
|
|
|
+ if (ictx->kc == KEY_MUTE && ictx->kc == ictx->last_keycode) {
|
|
|
do_gettimeofday(&t);
|
|
|
msec = tv2int(&t, &prev_time);
|
|
|
prev_time = t;
|
|
@@ -1547,11 +1561,9 @@ static void imon_incoming_packet(struct imon_context *ictx,
|
|
|
input_report_key(idev, ictx->kc, press_type);
|
|
|
input_sync(idev);
|
|
|
|
|
|
- /* panel keys and some remote keys don't generate a release */
|
|
|
- if (panel_key || norelease) {
|
|
|
- input_report_key(idev, ictx->kc, 0);
|
|
|
- input_sync(idev);
|
|
|
- }
|
|
|
+ /* panel keys don't generate a release */
|
|
|
+ input_report_key(idev, ictx->kc, 0);
|
|
|
+ input_sync(idev);
|
|
|
|
|
|
ictx->last_keycode = ictx->kc;
|
|
|
|
|
@@ -1559,8 +1571,7 @@ static void imon_incoming_packet(struct imon_context *ictx,
|
|
|
|
|
|
unknown_key:
|
|
|
dev_info(dev, "%s: unknown keypress, code 0x%llx\n", __func__,
|
|
|
- (panel_key ? be64_to_cpu(panel_key) :
|
|
|
- be32_to_cpu(remote_key)));
|
|
|
+ (long long)scancode);
|
|
|
return;
|
|
|
|
|
|
not_input_data:
|
|
@@ -1651,31 +1662,71 @@ static void usb_rx_callback_intf1(struct urb *urb)
|
|
|
usb_submit_urb(ictx->rx_urb_intf1, GFP_ATOMIC);
|
|
|
}
|
|
|
|
|
|
+static struct input_dev *imon_init_rdev(struct imon_context *ictx)
|
|
|
+{
|
|
|
+ struct input_dev *rdev;
|
|
|
+ struct ir_dev_props *props;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ rdev = input_allocate_device();
|
|
|
+ props = kzalloc(sizeof(*props), GFP_KERNEL);
|
|
|
+ if (!rdev || !props) {
|
|
|
+ dev_err(ictx->dev, "remote control dev allocation failed\n");
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
+ snprintf(ictx->name_rdev, sizeof(ictx->name_rdev),
|
|
|
+ "iMON Remote (%04x:%04x)", ictx->vendor, ictx->product);
|
|
|
+ usb_make_path(ictx->usbdev_intf0, ictx->phys_rdev,
|
|
|
+ sizeof(ictx->phys_rdev));
|
|
|
+ strlcat(ictx->phys_rdev, "/input0", sizeof(ictx->phys_rdev));
|
|
|
+
|
|
|
+ rdev->name = ictx->name_rdev;
|
|
|
+ rdev->phys = ictx->phys_rdev;
|
|
|
+ usb_to_input_id(ictx->usbdev_intf0, &rdev->id);
|
|
|
+ rdev->dev.parent = ictx->dev;
|
|
|
+ rdev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
|
|
|
+ input_set_drvdata(rdev, ictx);
|
|
|
+
|
|
|
+ props->priv = ictx;
|
|
|
+ props->driver_type = RC_DRIVER_SCANCODE;
|
|
|
+ props->allowed_protos = IR_TYPE_OTHER | IR_TYPE_RC6; /* iMON PAD or MCE */
|
|
|
+ props->change_protocol = imon_ir_change_protocol;
|
|
|
+ ictx->props = props;
|
|
|
+
|
|
|
+ ret = ir_input_register(rdev, RC_MAP_IMON_PAD, props, MOD_NAME);
|
|
|
+ if (ret < 0) {
|
|
|
+ dev_err(ictx->dev, "remote input dev register failed\n");
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
+ return rdev;
|
|
|
+
|
|
|
+out:
|
|
|
+ kfree(props);
|
|
|
+ input_free_device(rdev);
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
static struct input_dev *imon_init_idev(struct imon_context *ictx)
|
|
|
{
|
|
|
struct input_dev *idev;
|
|
|
- struct ir_dev_props *props;
|
|
|
int ret, i;
|
|
|
|
|
|
idev = input_allocate_device();
|
|
|
if (!idev) {
|
|
|
- dev_err(ictx->dev, "remote input dev allocation failed\n");
|
|
|
- goto idev_alloc_failed;
|
|
|
- }
|
|
|
-
|
|
|
- props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL);
|
|
|
- if (!props) {
|
|
|
- dev_err(ictx->dev, "remote ir dev props allocation failed\n");
|
|
|
- goto props_alloc_failed;
|
|
|
+ dev_err(ictx->dev, "input dev allocation failed\n");
|
|
|
+ goto out;
|
|
|
}
|
|
|
|
|
|
snprintf(ictx->name_idev, sizeof(ictx->name_idev),
|
|
|
- "iMON Remote (%04x:%04x)", ictx->vendor, ictx->product);
|
|
|
+ "iMON Panel, Knob and Mouse(%04x:%04x)",
|
|
|
+ ictx->vendor, ictx->product);
|
|
|
idev->name = ictx->name_idev;
|
|
|
|
|
|
usb_make_path(ictx->usbdev_intf0, ictx->phys_idev,
|
|
|
sizeof(ictx->phys_idev));
|
|
|
- strlcat(ictx->phys_idev, "/input0", sizeof(ictx->phys_idev));
|
|
|
+ strlcat(ictx->phys_idev, "/input1", sizeof(ictx->phys_idev));
|
|
|
idev->phys = ictx->phys_idev;
|
|
|
|
|
|
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)
|
|
|
__set_bit(kc, idev->keybit);
|
|
|
}
|
|
|
|
|
|
- props->priv = ictx;
|
|
|
- props->driver_type = RC_DRIVER_SCANCODE;
|
|
|
- /* IR_TYPE_OTHER maps to iMON PAD remote, IR_TYPE_RC6 to MCE remote */
|
|
|
- props->allowed_protos = IR_TYPE_OTHER | IR_TYPE_RC6;
|
|
|
- props->change_protocol = imon_ir_change_protocol;
|
|
|
- ictx->props = props;
|
|
|
-
|
|
|
usb_to_input_id(ictx->usbdev_intf0, &idev->id);
|
|
|
idev->dev.parent = ictx->dev;
|
|
|
+ input_set_drvdata(idev, ictx);
|
|
|
|
|
|
- ret = ir_input_register(idev, RC_MAP_IMON_PAD, props, MOD_NAME);
|
|
|
+ ret = input_register_device(idev);
|
|
|
if (ret < 0) {
|
|
|
- dev_err(ictx->dev, "remote input dev register failed\n");
|
|
|
- goto idev_register_failed;
|
|
|
+ dev_err(ictx->dev, "input dev register failed\n");
|
|
|
+ goto out;
|
|
|
}
|
|
|
|
|
|
return idev;
|
|
|
|
|
|
-idev_register_failed:
|
|
|
- kfree(props);
|
|
|
-props_alloc_failed:
|
|
|
+out:
|
|
|
input_free_device(idev);
|
|
|
-idev_alloc_failed:
|
|
|
-
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
@@ -1736,7 +1777,7 @@ static struct input_dev *imon_init_touch(struct imon_context *ictx)
|
|
|
|
|
|
usb_make_path(ictx->usbdev_intf1, ictx->phys_touch,
|
|
|
sizeof(ictx->phys_touch));
|
|
|
- strlcat(ictx->phys_touch, "/input1", sizeof(ictx->phys_touch));
|
|
|
+ strlcat(ictx->phys_touch, "/input2", sizeof(ictx->phys_touch));
|
|
|
touch->phys = ictx->phys_touch;
|
|
|
|
|
|
touch->evbit[0] =
|
|
@@ -1911,6 +1952,12 @@ static struct imon_context *imon_init_intf0(struct usb_interface *intf)
|
|
|
goto idev_setup_failed;
|
|
|
}
|
|
|
|
|
|
+ ictx->rdev = imon_init_rdev(ictx);
|
|
|
+ if (!ictx->rdev) {
|
|
|
+ dev_err(dev, "%s: rc device setup failed\n", __func__);
|
|
|
+ goto rdev_setup_failed;
|
|
|
+ }
|
|
|
+
|
|
|
usb_fill_int_urb(ictx->rx_urb_intf0, ictx->usbdev_intf0,
|
|
|
usb_rcvintpipe(ictx->usbdev_intf0,
|
|
|
ictx->rx_endpoint_intf0->bEndpointAddress),
|
|
@@ -1928,7 +1975,9 @@ static struct imon_context *imon_init_intf0(struct usb_interface *intf)
|
|
|
return ictx;
|
|
|
|
|
|
urb_submit_failed:
|
|
|
- ir_input_unregister(ictx->idev);
|
|
|
+ ir_input_unregister(ictx->rdev);
|
|
|
+rdev_setup_failed:
|
|
|
+ input_unregister_device(ictx->idev);
|
|
|
idev_setup_failed:
|
|
|
find_endpoint_failed:
|
|
|
mutex_unlock(&ictx->lock);
|
|
@@ -2289,7 +2338,8 @@ static void __devexit imon_disconnect(struct usb_interface *interface)
|
|
|
if (ifnum == 0) {
|
|
|
ictx->dev_present_intf0 = false;
|
|
|
usb_kill_urb(ictx->rx_urb_intf0);
|
|
|
- ir_input_unregister(ictx->idev);
|
|
|
+ input_unregister_device(ictx->idev);
|
|
|
+ ir_input_unregister(ictx->rdev);
|
|
|
if (ictx->display_supported) {
|
|
|
if (ictx->display_type == IMON_DISPLAY_TYPE_LCD)
|
|
|
usb_deregister_dev(interface, &imon_lcd_class);
|
|
@@ -2309,11 +2359,8 @@ static void __devexit imon_disconnect(struct usb_interface *interface)
|
|
|
mutex_unlock(&ictx->lock);
|
|
|
if (!ictx->display_isopen)
|
|
|
free_imon_context(ictx);
|
|
|
- } else {
|
|
|
- if (ictx->ir_type == IR_TYPE_RC6)
|
|
|
- del_timer_sync(&ictx->itimer);
|
|
|
+ } else
|
|
|
mutex_unlock(&ictx->lock);
|
|
|
- }
|
|
|
|
|
|
mutex_unlock(&driver_lock);
|
|
|
|