diff options
author | Sean Young <sean@mess.org> | 2016-12-20 12:18:06 -0200 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@s-opensource.com> | 2017-01-30 14:34:57 -0200 |
commit | f41003a23a02dc7299539300f74360c2a932714a (patch) | |
tree | debe19e93a55607f8d20624c0c10610ba24b8b58 /drivers/media/rc/imon.c | |
parent | d48982f49b53ca9bf0c5fb17834830254d84390f (diff) | |
download | op-kernel-dev-f41003a23a02dc7299539300f74360c2a932714a.zip op-kernel-dev-f41003a23a02dc7299539300f74360c2a932714a.tar.gz |
[media] staging: lirc_imon: port remaining usb ids to imon and remove
The staging lirc_imon driver contains 4 usb ids. Two of those have a VFD
and two don't. The VFD code is exactly the same in the mainline imon
driver, so that part is easily ported.
The staging driver produces raw IR rather than scancodes for the four
devices, so I've ported the raw IR code from staging to mainline imon.
Now that mainline imon can handle these four devices, lirc_imon is no
longer needed.
Compile tested only.
Signed-off-by: Sean Young <sean@mess.org>
Cc: Venky Raju <dev@venky.ws>
Cc: Jarod Wilson <jarod@redhat.com>
Cc: Alexey Khoroshilov <khoroshilov@ispras.ru>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Diffstat (limited to 'drivers/media/rc/imon.c')
-rw-r--r-- | drivers/media/rc/imon.c | 133 |
1 files changed, 127 insertions, 6 deletions
diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c index ef1f33e..89823d2 100644 --- a/drivers/media/rc/imon.c +++ b/drivers/media/rc/imon.c @@ -92,6 +92,7 @@ struct imon_usb_dev_descr { __u16 flags; #define IMON_NO_FLAGS 0 #define IMON_NEED_20MS_PKT_DELAY 1 +#define IMON_IR_RAW 2 struct imon_panel_key_table key_table[]; }; @@ -122,6 +123,12 @@ struct imon_context { unsigned char usb_tx_buf[8]; unsigned int send_packet_delay; + struct rx_data { + int count; /* length of 0 or 1 sequence */ + int prev_bit; /* logic level of sequence */ + int initial_space; /* initial space flag */ + } rx; + struct tx_t { unsigned char data_buf[35]; /* user data buffer */ struct completion finished; /* wait for write to finish */ @@ -324,6 +331,10 @@ static const struct imon_usb_dev_descr imon_DH102 = { } }; +static const struct imon_usb_dev_descr imon_ir_raw = { + .flags = IMON_IR_RAW, +}; + /* * USB Device ID for iMON USB Control Boards * @@ -407,6 +418,18 @@ static struct usb_device_id imon_usb_id_table[] = { /* device specifics unknown */ { USB_DEVICE(0x15c2, 0x0046), .driver_info = (unsigned long)&imon_default_table}, + /* TriGem iMON (IR only) -- TG_iMON.inf */ + { USB_DEVICE(0x0aa8, 0x8001), + .driver_info = (unsigned long)&imon_ir_raw}, + /* SoundGraph iMON (IR only) -- sg_imon.inf */ + { USB_DEVICE(0x04e8, 0xff30), + .driver_info = (unsigned long)&imon_ir_raw}, + /* SoundGraph iMON VFD (IR & VFD) -- iMON_VFD.inf */ + { USB_DEVICE(0x0aa8, 0xffda), + .driver_info = (unsigned long)&imon_ir_raw}, + /* SoundGraph iMON SS (IR & VFD) -- iMON_SS.inf */ + { USB_DEVICE(0x15c2, 0xffda), + .driver_info = (unsigned long)&imon_ir_raw}, {} }; @@ -1573,11 +1596,94 @@ static int imon_parse_press_type(struct imon_context *ictx, /** * Process the incoming packet */ -static void imon_incoming_packet(struct imon_context *ictx, +/** + * Convert bit count to time duration (in us) and submit + * the value to lirc_dev. + */ +static void submit_data(struct imon_context *context) +{ + DEFINE_IR_RAW_EVENT(ev); + + ev.pulse = context->rx.prev_bit; + ev.duration = US_TO_NS(context->rx.count * BIT_DURATION); + ir_raw_event_store_with_filter(context->rdev, &ev); +} + +/** + * Process the incoming packet + */ +static void imon_incoming_ir_raw(struct imon_context *context, struct urb *urb, int intf) { int len = urb->actual_length; unsigned char *buf = urb->transfer_buffer; + struct device *dev = context->dev; + int octet, bit; + unsigned char mask; + + if (len != 8) { + dev_warn(dev, "imon %s: invalid incoming packet size (len = %d, intf%d)\n", + __func__, len, intf); + return; + } + + if (debug) + dev_info(dev, "raw packet: %*ph\n", len, buf); + /* + * Translate received data to pulse and space lengths. + * Received data is active low, i.e. pulses are 0 and + * spaces are 1. + * + * My original algorithm was essentially similar to + * Changwoo Ryu's with the exception that he switched + * the incoming bits to active high and also fed an + * initial space to LIRC at the start of a new sequence + * if the previous bit was a pulse. + * + * I've decided to adopt his algorithm. + */ + + if (buf[7] == 1 && context->rx.initial_space) { + /* LIRC requires a leading space */ + context->rx.prev_bit = 0; + context->rx.count = 4; + submit_data(context); + context->rx.count = 0; + } + + for (octet = 0; octet < 5; ++octet) { + mask = 0x80; + for (bit = 0; bit < 8; ++bit) { + int curr_bit = !(buf[octet] & mask); + + if (curr_bit != context->rx.prev_bit) { + if (context->rx.count) { + submit_data(context); + context->rx.count = 0; + } + context->rx.prev_bit = curr_bit; + } + ++context->rx.count; + mask >>= 1; + } + } + + if (buf[7] == 10) { + if (context->rx.count) { + submit_data(context); + context->rx.count = 0; + } + context->rx.initial_space = context->rx.prev_bit; + } + + ir_raw_event_handle(context->rdev); +} + +static void imon_incoming_scancode(struct imon_context *ictx, + struct urb *urb, int intf) +{ + int len = urb->actual_length; + unsigned char *buf = urb->transfer_buffer; struct device *dev = ictx->dev; unsigned long flags; u32 kc; @@ -1757,7 +1863,10 @@ static void usb_rx_callback_intf0(struct urb *urb) break; case 0: - imon_incoming_packet(ictx, urb, intfnum); + if (ictx->rdev->driver_type == RC_DRIVER_IR_RAW) + imon_incoming_ir_raw(ictx, urb, intfnum); + else + imon_incoming_scancode(ictx, urb, intfnum); break; default: @@ -1798,7 +1907,10 @@ static void usb_rx_callback_intf1(struct urb *urb) break; case 0: - imon_incoming_packet(ictx, urb, intfnum); + if (ictx->rdev->driver_type == RC_DRIVER_IR_RAW) + imon_incoming_ir_raw(ictx, urb, intfnum); + else + imon_incoming_scancode(ictx, urb, intfnum); break; default: @@ -1906,11 +2018,14 @@ static void imon_set_display_type(struct imon_context *ictx) case 0x0041: case 0x0042: case 0x0043: + case 0x8001: + case 0xff30: configured_display_type = IMON_DISPLAY_TYPE_NONE; ictx->display_supported = false; break; case 0x0036: case 0x0044: + case 0xffda: default: configured_display_type = IMON_DISPLAY_TYPE_VFD; break; @@ -1935,7 +2050,8 @@ static struct rc_dev *imon_init_rdev(struct imon_context *ictx) const unsigned char fp_packet[] = { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88 }; - rdev = rc_allocate_device(RC_DRIVER_SCANCODE); + rdev = rc_allocate_device(ictx->dev_descr->flags & IMON_IR_RAW ? + RC_DRIVER_IR_RAW : RC_DRIVER_SCANCODE); if (!rdev) { dev_err(ictx->dev, "remote control dev allocation failed\n"); goto out; @@ -1953,7 +2069,11 @@ static struct rc_dev *imon_init_rdev(struct imon_context *ictx) rdev->dev.parent = ictx->dev; rdev->priv = ictx; - rdev->allowed_protocols = RC_BIT_OTHER | RC_BIT_RC6_MCE; /* iMON PAD or MCE */ + if (ictx->dev_descr->flags & IMON_IR_RAW) + rdev->allowed_protocols = RC_BIT_ALL_IR_DECODER; + else + /* iMON PAD or MCE */ + rdev->allowed_protocols = RC_BIT_OTHER | RC_BIT_RC6_MCE; rdev->change_protocol = imon_ir_change_protocol; rdev->driver_name = MOD_NAME; @@ -1971,7 +2091,8 @@ static struct rc_dev *imon_init_rdev(struct imon_context *ictx) imon_set_display_type(ictx); - if (ictx->rc_type == RC_BIT_RC6_MCE) + if (ictx->rc_type == RC_BIT_RC6_MCE || + ictx->dev_descr->flags & IMON_IR_RAW) rdev->map_name = RC_MAP_IMON_MCE; else rdev->map_name = RC_MAP_IMON_PAD; |