Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

media: imon_raw: simplify and explain bit operations

This code needs some explanation.

Signed-off-by: Sean Young <sean@mess.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>

authored by

Sean Young and committed by
Mauro Carvalho Chehab
e70d13f7 1b09a2af

+34 -9
+34 -9
drivers/media/rc/imon_raw.c
··· 14 14 struct device *dev; 15 15 struct urb *ir_urb; 16 16 struct rc_dev *rcdev; 17 - u8 ir_buf[8] __aligned(__alignof__(u64)); 17 + __be64 ir_buf; 18 18 char phys[64]; 19 19 }; 20 20 ··· 29 29 static void imon_ir_data(struct imon *imon) 30 30 { 31 31 struct ir_raw_event rawir = {}; 32 - u64 d = be64_to_cpup((__be64 *)imon->ir_buf) >> 24; 32 + u64 data = be64_to_cpu(imon->ir_buf); 33 + u8 packet_no = data & 0xff; 33 34 int offset = 40; 34 35 int bit; 35 36 36 - dev_dbg(imon->dev, "data: %*ph", 8, imon->ir_buf); 37 + if (packet_no == 0xff) 38 + return; 39 + 40 + dev_dbg(imon->dev, "data: %*ph", 8, &imon->ir_buf); 41 + 42 + /* 43 + * Only the first 5 bytes contain IR data. Right shift so we move 44 + * the IR bits to the lower 40 bits. 45 + */ 46 + data >>= 24; 37 47 38 48 do { 39 - bit = fls64(d & (BIT_ULL(offset) - 1)); 49 + /* 50 + * Find highest set bit which is less or equal to offset 51 + * 52 + * offset is the bit above (base 0) where we start looking. 53 + * 54 + * data & (BIT_ULL(offset) - 1) masks off any unwanted bits, 55 + * so we have just bits less than offset. 56 + * 57 + * fls will tell us the highest bit set plus 1 (or 0 if no 58 + * bits are set). 59 + */ 60 + bit = fls64(data & (BIT_ULL(offset) - 1)); 40 61 if (bit < offset) { 41 62 dev_dbg(imon->dev, "pulse: %d bits", offset - bit); 42 63 rawir.pulse = true; ··· 70 49 offset = bit; 71 50 } 72 51 73 - bit = fls64(~d & (BIT_ULL(offset) - 1)); 52 + /* 53 + * Find highest clear bit which is less than offset. 54 + * 55 + * Just invert the data and use same trick as above. 56 + */ 57 + bit = fls64(~data & (BIT_ULL(offset) - 1)); 74 58 dev_dbg(imon->dev, "space: %d bits", offset - bit); 75 59 76 60 rawir.pulse = false; ··· 85 59 offset = bit; 86 60 } while (offset > 0); 87 61 88 - if (imon->ir_buf[7] == 0x0a) { 62 + if (packet_no == 0x0a) { 89 63 ir_raw_event_set_idle(imon->rcdev, true); 90 64 ir_raw_event_handle(imon->rcdev); 91 65 } ··· 98 72 99 73 switch (urb->status) { 100 74 case 0: 101 - if (imon->ir_buf[7] != 0xff) 102 - imon_ir_data(imon); 75 + imon_ir_data(imon); 103 76 break; 104 77 case -ECONNRESET: 105 78 case -ENOENT: ··· 154 129 imon->dev = &intf->dev; 155 130 usb_fill_int_urb(imon->ir_urb, udev, 156 131 usb_rcvintpipe(udev, ir_ep->bEndpointAddress), 157 - imon->ir_buf, sizeof(imon->ir_buf), 132 + &imon->ir_buf, sizeof(imon->ir_buf), 158 133 imon_ir_rx, imon, ir_ep->bInterval); 159 134 160 135 rcdev = devm_rc_allocate_device(&intf->dev, RC_DRIVER_IR_RAW);