Commit e70d13f7 authored by Sean Young's avatar Sean Young Committed by Mauro Carvalho Chehab

media: imon_raw: simplify and explain bit operations

This code needs some explanation.
Signed-off-by: default avatarSean Young <sean@mess.org>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+samsung@kernel.org>
parent 1b09a2af
...@@ -14,7 +14,7 @@ struct imon { ...@@ -14,7 +14,7 @@ struct imon {
struct device *dev; struct device *dev;
struct urb *ir_urb; struct urb *ir_urb;
struct rc_dev *rcdev; struct rc_dev *rcdev;
u8 ir_buf[8] __aligned(__alignof__(u64)); __be64 ir_buf;
char phys[64]; char phys[64];
}; };
...@@ -29,14 +29,35 @@ struct imon { ...@@ -29,14 +29,35 @@ struct imon {
static void imon_ir_data(struct imon *imon) static void imon_ir_data(struct imon *imon)
{ {
struct ir_raw_event rawir = {}; struct ir_raw_event rawir = {};
u64 d = be64_to_cpup((__be64 *)imon->ir_buf) >> 24; u64 data = be64_to_cpu(imon->ir_buf);
u8 packet_no = data & 0xff;
int offset = 40; int offset = 40;
int bit; int bit;
dev_dbg(imon->dev, "data: %*ph", 8, imon->ir_buf); if (packet_no == 0xff)
return;
dev_dbg(imon->dev, "data: %*ph", 8, &imon->ir_buf);
/*
* Only the first 5 bytes contain IR data. Right shift so we move
* the IR bits to the lower 40 bits.
*/
data >>= 24;
do { do {
bit = fls64(d & (BIT_ULL(offset) - 1)); /*
* Find highest set bit which is less or equal to offset
*
* offset is the bit above (base 0) where we start looking.
*
* data & (BIT_ULL(offset) - 1) masks off any unwanted bits,
* so we have just bits less than offset.
*
* fls will tell us the highest bit set plus 1 (or 0 if no
* bits are set).
*/
bit = fls64(data & (BIT_ULL(offset) - 1));
if (bit < offset) { if (bit < offset) {
dev_dbg(imon->dev, "pulse: %d bits", offset - bit); dev_dbg(imon->dev, "pulse: %d bits", offset - bit);
rawir.pulse = true; rawir.pulse = true;
...@@ -49,7 +70,12 @@ static void imon_ir_data(struct imon *imon) ...@@ -49,7 +70,12 @@ static void imon_ir_data(struct imon *imon)
offset = bit; offset = bit;
} }
bit = fls64(~d & (BIT_ULL(offset) - 1)); /*
* Find highest clear bit which is less than offset.
*
* Just invert the data and use same trick as above.
*/
bit = fls64(~data & (BIT_ULL(offset) - 1));
dev_dbg(imon->dev, "space: %d bits", offset - bit); dev_dbg(imon->dev, "space: %d bits", offset - bit);
rawir.pulse = false; rawir.pulse = false;
...@@ -59,7 +85,7 @@ static void imon_ir_data(struct imon *imon) ...@@ -59,7 +85,7 @@ static void imon_ir_data(struct imon *imon)
offset = bit; offset = bit;
} while (offset > 0); } while (offset > 0);
if (imon->ir_buf[7] == 0x0a) { if (packet_no == 0x0a) {
ir_raw_event_set_idle(imon->rcdev, true); ir_raw_event_set_idle(imon->rcdev, true);
ir_raw_event_handle(imon->rcdev); ir_raw_event_handle(imon->rcdev);
} }
...@@ -72,8 +98,7 @@ static void imon_ir_rx(struct urb *urb) ...@@ -72,8 +98,7 @@ static void imon_ir_rx(struct urb *urb)
switch (urb->status) { switch (urb->status) {
case 0: case 0:
if (imon->ir_buf[7] != 0xff) imon_ir_data(imon);
imon_ir_data(imon);
break; break;
case -ECONNRESET: case -ECONNRESET:
case -ENOENT: case -ENOENT:
...@@ -129,7 +154,7 @@ static int imon_probe(struct usb_interface *intf, ...@@ -129,7 +154,7 @@ static int imon_probe(struct usb_interface *intf,
imon->dev = &intf->dev; imon->dev = &intf->dev;
usb_fill_int_urb(imon->ir_urb, udev, usb_fill_int_urb(imon->ir_urb, udev,
usb_rcvintpipe(udev, ir_ep->bEndpointAddress), usb_rcvintpipe(udev, ir_ep->bEndpointAddress),
imon->ir_buf, sizeof(imon->ir_buf), &imon->ir_buf, sizeof(imon->ir_buf),
imon_ir_rx, imon, ir_ep->bInterval); imon_ir_rx, imon, ir_ep->bInterval);
rcdev = devm_rc_allocate_device(&intf->dev, RC_DRIVER_IR_RAW); rcdev = devm_rc_allocate_device(&intf->dev, RC_DRIVER_IR_RAW);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment