Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+34 −9
Original line number Diff line number Diff line
@@ -14,7 +14,7 @@ struct imon {
	struct device *dev;
	struct urb *ir_urb;
	struct rc_dev *rcdev;
	u8 ir_buf[8] __aligned(__alignof__(u64));
	__be64 ir_buf;
	char phys[64];
};

@@ -29,14 +29,35 @@ struct imon {
static void imon_ir_data(struct imon *imon)
{
	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 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 {
		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) {
			dev_dbg(imon->dev, "pulse: %d bits", offset - bit);
			rawir.pulse = true;
@@ -49,7 +70,12 @@ static void imon_ir_data(struct imon *imon)
			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);

		rawir.pulse = false;
@@ -59,7 +85,7 @@ static void imon_ir_data(struct imon *imon)
		offset = bit;
	} while (offset > 0);

	if (imon->ir_buf[7] == 0x0a) {
	if (packet_no == 0x0a) {
		ir_raw_event_set_idle(imon->rcdev, true);
		ir_raw_event_handle(imon->rcdev);
	}
@@ -72,7 +98,6 @@ static void imon_ir_rx(struct urb *urb)

	switch (urb->status) {
	case 0:
		if (imon->ir_buf[7] != 0xff)
		imon_ir_data(imon);
		break;
	case -ECONNRESET:
@@ -129,7 +154,7 @@ static int imon_probe(struct usb_interface *intf,
	imon->dev = &intf->dev;
	usb_fill_int_urb(imon->ir_urb, udev,
			 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);

	rcdev = devm_rc_allocate_device(&intf->dev, RC_DRIVER_IR_RAW);