Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 219165
b: refs/heads/master
c: 693508d
h: refs/heads/master
i:
  219163: 67fb500
v: v3
  • Loading branch information
Jarod Wilson authored and Mauro Carvalho Chehab committed Oct 21, 2010
1 parent 4f13d88 commit 832207e
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 7 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: eaf2bcc923ed6c56da8f856e7dc380321433fbda
refs/heads/master: 693508df9824ecc2bf308a35b58159aa2fecf91f
52 changes: 46 additions & 6 deletions trunk/drivers/media/IR/imon.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* imon.c: input and display driver for SoundGraph iMON IR/VFD/LCD
*
* Copyright(C) 2009 Jarod Wilson <jarod@wilsonet.com>
* Copyright(C) 2010 Jarod Wilson <jarod@wilsonet.com>
* Portions based on the original lirc_imon driver,
* Copyright(C) 2004 Venky Raju(dev@venky.ws)
*
Expand Down Expand Up @@ -125,6 +125,7 @@ struct imon_context {
struct input_dev *idev; /* input device for panel & IR mouse */
struct input_dev *touch; /* input device for touchscreen */

spinlock_t kc_lock; /* make sure we get keycodes right */
u32 kc; /* current input keycode */
u32 last_keycode; /* last reported input keycode */
u32 rc_scancode; /* the computed remote scancode */
Expand Down Expand Up @@ -1210,6 +1211,9 @@ static bool imon_mouse_event(struct imon_context *ictx,
u8 right_shift = 1;
bool mouse_input = true;
int dir = 0;
unsigned long flags;

spin_lock_irqsave(&ictx->kc_lock, flags);

/* newer iMON device PAD or mouse button */
if (ictx->product != 0xffdc && (buf[0] & 0x01) && len == 5) {
Expand Down Expand Up @@ -1241,6 +1245,8 @@ static bool imon_mouse_event(struct imon_context *ictx,
} else
mouse_input = false;

spin_unlock_irqrestore(&ictx->kc_lock, flags);

if (mouse_input) {
dev_dbg(ictx->dev, "sending mouse data via input subsystem\n");

Expand All @@ -1255,7 +1261,9 @@ static bool imon_mouse_event(struct imon_context *ictx,
buf[1] >> right_shift & 0x1);
}
input_sync(ictx->idev);
spin_lock_irqsave(&ictx->kc_lock, flags);
ictx->last_keycode = ictx->kc;
spin_unlock_irqrestore(&ictx->kc_lock, flags);
}

return mouse_input;
Expand All @@ -1278,6 +1286,7 @@ static void imon_pad_to_keys(struct imon_context *ictx, unsigned char *buf)
char rel_x = 0x00, rel_y = 0x00;
u16 timeout, threshold;
u32 scancode = KEY_RESERVED;
unsigned long flags;

/*
* The imon directional pad functions more like a touchpad. Bytes 3 & 4
Expand All @@ -1301,7 +1310,11 @@ static void imon_pad_to_keys(struct imon_context *ictx, unsigned char *buf)
dir = stabilize((int)rel_x, (int)rel_y,
timeout, threshold);
if (!dir) {
spin_lock_irqsave(&ictx->kc_lock,
flags);
ictx->kc = KEY_UNKNOWN;
spin_unlock_irqrestore(&ictx->kc_lock,
flags);
return;
}
buf[2] = dir & 0xFF;
Expand Down Expand Up @@ -1363,7 +1376,9 @@ static void imon_pad_to_keys(struct imon_context *ictx, unsigned char *buf)
dir = stabilize((int)rel_x, (int)rel_y,
timeout, threshold);
if (!dir) {
spin_lock_irqsave(&ictx->kc_lock, flags);
ictx->kc = KEY_UNKNOWN;
spin_unlock_irqrestore(&ictx->kc_lock, flags);
return;
}
buf[2] = dir & 0xFF;
Expand Down Expand Up @@ -1392,8 +1407,11 @@ static void imon_pad_to_keys(struct imon_context *ictx, unsigned char *buf)
}
}

if (scancode)
if (scancode) {
spin_lock_irqsave(&ictx->kc_lock, flags);
ictx->kc = imon_remote_key_lookup(ictx, scancode);
spin_unlock_irqrestore(&ictx->kc_lock, flags);
}
}

/**
Expand All @@ -1405,6 +1423,9 @@ static int imon_parse_press_type(struct imon_context *ictx,
unsigned char *buf, u8 ktype)
{
int press_type = 0;
unsigned long flags;

spin_lock_irqsave(&ictx->kc_lock, flags);

/* key release of 0x02XXXXXX key */
if (ictx->kc == KEY_RESERVED && buf[0] == 0x02 && buf[3] == 0x00)
Expand Down Expand Up @@ -1437,6 +1458,8 @@ static int imon_parse_press_type(struct imon_context *ictx,
else
press_type = 1;

spin_unlock_irqrestore(&ictx->kc_lock, flags);

return press_type;
}

Expand All @@ -1449,6 +1472,7 @@ static void imon_incoming_packet(struct imon_context *ictx,
int len = urb->actual_length;
unsigned char *buf = urb->transfer_buffer;
struct device *dev = ictx->dev;
unsigned long flags;
u32 kc;
bool norelease = false;
int i;
Expand Down Expand Up @@ -1486,13 +1510,15 @@ static void imon_incoming_packet(struct imon_context *ictx,
}
}

spin_lock_irqsave(&ictx->kc_lock, flags);
/* keyboard/mouse mode toggle button */
if (kc == KEY_KEYBOARD && !ictx->release_code) {
ictx->last_keycode = kc;
if (!nomouse) {
ictx->pad_mouse = ~(ictx->pad_mouse) & 0x1;
dev_dbg(dev, "toggling to %s mode\n",
ictx->pad_mouse ? "mouse" : "keyboard");
spin_unlock_irqrestore(&ictx->kc_lock, flags);
return;
} else {
ictx->pad_mouse = 0;
Expand All @@ -1501,6 +1527,7 @@ static void imon_incoming_packet(struct imon_context *ictx,
}

ictx->kc = kc;
spin_unlock_irqrestore(&ictx->kc_lock, flags);

/* send touchscreen events through input subsystem if touchpad data */
if (ictx->display_type == IMON_DISPLAY_TYPE_VGA && len == 8 &&
Expand Down Expand Up @@ -1534,42 +1561,54 @@ static void imon_incoming_packet(struct imon_context *ictx,
if (press_type < 0)
goto not_input_data;

spin_lock_irqsave(&ictx->kc_lock, flags);
if (ictx->kc == KEY_UNKNOWN)
goto unknown_key;
spin_unlock_irqrestore(&ictx->kc_lock, flags);

if (ktype != IMON_KEY_PANEL) {
if (press_type == 0)
ir_keyup(irdev);
else {
ir_keydown(ictx->rdev, ictx->rc_scancode,
ictx->rc_toggle);
spin_lock_irqsave(&ictx->kc_lock, flags);
ictx->last_keycode = ictx->kc;
spin_unlock_irqrestore(&ictx->kc_lock, flags);
}
return;
}

/* Only panel type events left to process now */
spin_lock_irqsave(&ictx->kc_lock, flags);

/* 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;
if (msec < idev->rep[REP_DELAY])
if (msec < idev->rep[REP_DELAY]) {
spin_unlock_irqrestore(&ictx->kc_lock, flags);
return;
}
}
kc = ictx->kc;

spin_unlock_irqrestore(&ictx->kc_lock, flags);

input_report_key(idev, ictx->kc, press_type);
input_report_key(idev, kc, press_type);
input_sync(idev);

/* panel keys don't generate a release */
input_report_key(idev, ictx->kc, 0);
input_report_key(idev, kc, 0);
input_sync(idev);

ictx->last_keycode = ictx->kc;
ictx->last_keycode = kc;

return;

unknown_key:
spin_unlock_irqrestore(&ictx->kc_lock, flags);
dev_info(dev, "%s: unknown keypress, code 0x%llx\n", __func__,
(long long)scancode);
return;
Expand Down Expand Up @@ -1927,6 +1966,7 @@ static struct imon_context *imon_init_intf0(struct usb_interface *intf)
}

mutex_init(&ictx->lock);
spin_lock_init(&ictx->kc_lock);

mutex_lock(&ictx->lock);

Expand Down

0 comments on commit 832207e

Please sign in to comment.