On Thu, Aug 15, 2019 at 12:41:19PM -0400, A Sun wrote: > Fix and eliminate mceusb's IR length limit for IR signals transmitted to > the MCE IR blaster ports. Great, thank you. This code needed cleaning up, nice to see it done. I have 5 different mceusb devices and it works fine with all of them. Tested-by: Sean Young <sean@xxxxxxxx> Thanks, Sean > An IR signal TX exceeding 306 pulse/space samples presently causes -EINVAL > return error. There's no such limitation nor error with the MCE device > hardware. And valid IR signals exist with more than 400 pulse/space for the > control of certain appliances (eg Panasonic ACXA75C00600 air conditioner). > > The scope of this patch is limited to the mceusb driver. There are still > IR signal TX length and time constraints that related modules of rc core > (eg LIRC) impose, further up the driver stack. > > Changes for mceusb_tx_ir(): > > Converts and sends LIRC IR pulse/space sequence to MCE device IR > pulse/space format. > > Break long length LIRC sequence into multiple (unlimited number of) parts > for sending to the MCE device. > Reduce kernel stack IR buffer size: 128 (was 384) > Increase MCE IR data packet size: 31 (was 5) > Zero time LIRC pulse/space no longer copied to MCE IR data. > Eliminate overwriting the source/input LIRC IR data in txbuf[]. > Eliminate -EINVAL return; return number of IR samples sent (>0) or > MCE write error code (<0). > > New mce_write() and mce_write_callback(): > > Implements synchronous blocking I/O, with timeout, for writing/sending > data to the MCE device. > > An unlimited multipart IR signal sent to the MCE device faster than real > time requires flow control absent with the original mce_request_packet() > and mce_async_callback() asynchronous I/O implementation. Also absent is > TX error feedback. > > mce_write() combines and replaces mce_request_packet() and > mce_async_callback() with conversion to synchronous I/O. > mce_write() returns bytes sent (>0) or MCE device write error (<0). > Debug hex dump TX data before processing. > > Rename mce_async_out() -> mce_command_out(): > > The original name is misleading with underlying synchronous I/O > implementation. Function renamed to mce_command_out(). > > Changes in mceusb_handle_command(): > > Add support for MCE device error case MCE_RSP_TX_TIMEOUT > "IR TX timeout (TX buffer underrun)" > > Changes in mceusb_dev_printdata(): > > Changes support test and debug of multipart TX IR. > > Add buffer boundary information (offset and buffer size) to TX hex dump. > Correct TX trace bug "Raw IR data, 0 pulse/space samples" > Add trace for MCE_RSP_TX_TIMEOUT "IR TX timeout (TX buffer underrun)" > > Other changes: > > The driver's write to USB device architecture change (async to sync I/O) > is significant so we bump DRIVER_VERSION to "1.95" (from "1.94"). > > Tests: > > $ cat -n irdata1 | head -3 > 1 carrier 36000 > 2 pulse 6350 > 3 space 6350 > $ cat -n irdata1 | tail -3 > 76 pulse 6350 > 77 space 6350 > 78 pulse 6350 > $ ir-ctl -s irdata1 > > [1549021.073612] mceusb 1-1.3:1.0: requesting 36000 HZ carrier > [1549021.073635] mceusb 1-1.3:1.0: tx data[0]: 9f 06 01 45 (len=4 sz=4) > [1549021.073649] mceusb 1-1.3:1.0: Request carrier of 35714 Hz (period 28us) > [1549021.073848] mceusb 1-1.3:1.0: tx done status = 4 (wait = 100, expire = 100 (1000ms), urb->actual_length = 4, urb->status = 0) > [1549021.074689] mceusb 1-1.3:1.0: rx data[0]: 9f 06 01 45 (len=4 sz=4) > [1549021.074701] mceusb 1-1.3:1.0: Got carrier of 35714 Hz (period 28us) > [1549021.102023] mceusb 1-1.3:1.0: tx data[0]: 9f 08 03 (len=3 sz=3) > [1549021.102036] mceusb 1-1.3:1.0: Request transmit blaster mask of 0x03 > [1549021.102219] mceusb 1-1.3:1.0: tx done status = 3 (wait = 100, expire = 100 (1000ms), urb->actual_length = 3, urb->status = 0) > [1549021.131979] mceusb 1-1.3:1.0: tx data[0]: 9e ff 7f ff 7f ff 7f ff 7f ff 7f ff 7f ff 7f ff 7f ff 7f ff 7f ff 7f ff 7f ff 7f ff 7f ff 7f 9e ff 7f ff 7f ff 7f ff 7f ff 7f ff 7f ff 7f ff 7f ff 7f ff 7f ff 7f ff 7f ff 7f ff 7f ff 7f 91 ff (len=81 sz=81) > [1549021.131992] mceusb 1-1.3:1.0: Raw IR data, 30 pulse/space samples > [1549021.133592] mceusb 1-1.3:1.0: tx done status = 81 (wait = 100, expire = 100 (1000ms), urb->actual_length = 81, urb->status = 0) > > Hex dumps limited to 64 bytes. > 0xff is MCE maximum time pulse, 0x7f is MCE maximum time space. > > $ cat -n irdata2 | head -3 > 1 carrier 36000 > 2 pulse 50 > 3 space 50 > $ cat -n irdata2 | tail -3 > 254 pulse 50 > 255 space 50 > 256 pulse 50 > $ ir-ctl -s irdata2 > > [1549306.586998] mceusb 1-1.3:1.0: tx data[0]: 9f 08 03 (len=3 sz=3) > [1549306.587015] mceusb 1-1.3:1.0: Request transmit blaster mask of 0x03 > [1549306.587252] mceusb 1-1.3:1.0: tx done status = 3 (wait = 100, expire = 100 (1000ms), urb->actual_length = 3, urb->status = 0) > [1549306.613275] mceusb 1-1.3:1.0: tx data[0]: 9e 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 9e 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 9e 81 (len=128 sz=128) > [1549306.613291] mceusb 1-1.3:1.0: Raw IR data, 30 pulse/space samples > [1549306.614837] mceusb 1-1.3:1.0: tx done status = 128 (wait = 100, expire = 100 (1000ms), urb->actual_length = 128, urb->status = 0) > [1549306.614861] mceusb 1-1.3:1.0: tx data[0]: 9e 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 9e 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 9e 01 (len=128 sz=128) > [1549306.614869] mceusb 1-1.3:1.0: Raw IR data, 30 pulse/space samples > [1549306.620199] mceusb 1-1.3:1.0: tx done status = 128 (wait = 100, expire = 100 (1000ms), urb->actual_length = 128, urb->status = 0) > [1549306.620212] mceusb 1-1.3:1.0: tx data[0]: 89 81 01 81 01 81 01 81 01 81 80 (len=11 sz=11) > [1549306.620221] mceusb 1-1.3:1.0: Raw IR data, 9 pulse/space samples > [1549306.633294] mceusb 1-1.3:1.0: tx done status = 11 (wait = 98, expire = 100 (1000ms), urb->actual_length = 11, urb->status = 0) > > Hex dumps limited to 64 bytes. > 0x81 is MCE minimum time pulse, 0x01 is MCE minimum time space. > TX IR part 3 sz=11 shows 20msec I/O blocking delay > (100expire - 98wait = 2jiffies) > > Signed-off-by: A Sun <as1033x@xxxxxxxxxxx> > --- > drivers/media/rc/mceusb.c | 334 +++++++++++++++++++++++++++------------------- > 1 file changed, 196 insertions(+), 138 deletions(-) > > diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c > index 8ba1e2b7e..f9ed855e2 100644 > --- a/drivers/media/rc/mceusb.c > +++ b/drivers/media/rc/mceusb.c > @@ -31,21 +31,22 @@ > #include <linux/pm_wakeup.h> > #include <media/rc-core.h> > > -#define DRIVER_VERSION "1.94" > +#define DRIVER_VERSION "1.95" > #define DRIVER_AUTHOR "Jarod Wilson <jarod@xxxxxxxxxx>" > #define DRIVER_DESC "Windows Media Center Ed. eHome Infrared Transceiver " \ > "device driver" > #define DRIVER_NAME "mceusb" > > +#define USB_TX_TIMEOUT 1000 /* in milliseconds */ > #define USB_CTRL_MSG_SZ 2 /* Size of usb ctrl msg on gen1 hw */ > #define MCE_G1_INIT_MSGS 40 /* Init messages on gen1 hw to throw out */ > > /* MCE constants */ > -#define MCE_CMDBUF_SIZE 384 /* MCE Command buffer length */ > +#define MCE_IRBUF_SIZE 128 /* TX IR buffer length */ > #define MCE_TIME_UNIT 50 /* Approx 50us resolution */ > -#define MCE_CODE_LENGTH 5 /* Normal length of packet (with header) */ > -#define MCE_PACKET_SIZE 4 /* Normal length of packet (without header) */ > -#define MCE_IRDATA_HEADER 0x84 /* Actual header format is 0x80 + num_bytes */ > +#define MCE_PACKET_SIZE 31 /* Max length of packet (with header) */ > +#define MCE_IRDATA_HEADER (0x80 + MCE_PACKET_SIZE - 1) > + /* Actual format is 0x80 + num_bytes */ > #define MCE_IRDATA_TRAILER 0x80 /* End of IR data */ > #define MCE_MAX_CHANNELS 2 /* Two transmitters, hardware dependent? */ > #define MCE_DEFAULT_TX_MASK 0x03 /* Vals: TX1=0x01, TX2=0x02, ALL=0x03 */ > @@ -604,9 +605,9 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, u8 *buf, int buf_len, > if (len <= skip) > return; > > - dev_dbg(dev, "%cx data: %*ph (length=%d)", > - (out ? 't' : 'r'), > - min(len, buf_len - offset), buf + offset, len); > + dev_dbg(dev, "%cx data[%d]: %*ph (len=%d sz=%d)", > + (out ? 't' : 'r'), offset, > + min(len, buf_len - offset), buf + offset, len, buf_len); > > inout = out ? "Request" : "Got"; > > @@ -728,6 +729,9 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, u8 *buf, int buf_len, > case MCE_RSP_CMD_ILLEGAL: > dev_dbg(dev, "Illegal PORT_IR command"); > break; > + case MCE_RSP_TX_TIMEOUT: > + dev_dbg(dev, "IR TX timeout (TX buffer underrun)"); > + break; > default: > dev_dbg(dev, "Unknown command 0x%02x 0x%02x", > cmd, subcmd); > @@ -742,13 +746,14 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, u8 *buf, int buf_len, > dev_dbg(dev, "End of raw IR data"); > else if ((cmd != MCE_CMD_PORT_IR) && > ((cmd & MCE_PORT_MASK) == MCE_COMMAND_IRDATA)) > - dev_dbg(dev, "Raw IR data, %d pulse/space samples", ir->rem); > + dev_dbg(dev, "Raw IR data, %d pulse/space samples", > + cmd & MCE_PACKET_LENGTH_MASK); > #endif > } > > /* > * Schedule work that can't be done in interrupt handlers > - * (mceusb_dev_recv() and mce_async_callback()) nor tasklets. > + * (mceusb_dev_recv() and mce_write_callback()) nor tasklets. > * Invokes mceusb_deferred_kevent() for recovering from > * error events specified by the kevent bit field. > */ > @@ -768,23 +773,80 @@ static void mceusb_defer_kevent(struct mceusb_dev *ir, int kevent) > dev_dbg(ir->dev, "kevent %d scheduled", kevent); > } > > -static void mce_async_callback(struct urb *urb) > +static void mce_write_callback(struct urb *urb) > { > - struct mceusb_dev *ir; > - int len; > - > if (!urb) > return; > > - ir = urb->context; > + complete(urb->context); > +} > + > +/* > + * Write (TX/send) data to MCE device USB endpoint out. > + * Used for IR blaster TX and MCE device commands. > + * > + * Return: The number of bytes written (> 0) or errno (< 0). > + */ > +static int mce_write(struct mceusb_dev *ir, u8 *data, int size) > +{ > + int ret; > + struct urb *urb; > + struct device *dev = ir->dev; > + unsigned char *buf_out; > + struct completion tx_done; > + unsigned long expire; > + unsigned long ret_wait; > + > + mceusb_dev_printdata(ir, data, size, 0, size, true); > + > + urb = usb_alloc_urb(0, GFP_KERNEL); > + if (unlikely(!urb)) { > + dev_err(dev, "Error: mce write couldn't allocate urb"); > + return -ENOMEM; > + } > + > + buf_out = kmalloc(size, GFP_KERNEL); > + if (!buf_out) { > + usb_free_urb(urb); > + return -ENOMEM; > + } > + > + init_completion(&tx_done); > + > + /* outbound data */ > + if (usb_endpoint_xfer_int(ir->usb_ep_out)) > + usb_fill_int_urb(urb, ir->usbdev, ir->pipe_out, > + buf_out, size, mce_write_callback, &tx_done, > + ir->usb_ep_out->bInterval); > + else > + usb_fill_bulk_urb(urb, ir->usbdev, ir->pipe_out, > + buf_out, size, mce_write_callback, &tx_done); > + memcpy(buf_out, data, size); > + > + ret = usb_submit_urb(urb, GFP_KERNEL); > + if (ret) { > + dev_err(dev, "Error: mce write submit urb error = %d", ret); > + kfree(buf_out); > + usb_free_urb(urb); > + return ret; > + } > + > + expire = msecs_to_jiffies(USB_TX_TIMEOUT); > + ret_wait = wait_for_completion_timeout(&tx_done, expire); > + if (!ret_wait) { > + dev_err(dev, "Error: mce write timed out (expire = %lu (%dms))", > + expire, USB_TX_TIMEOUT); > + usb_kill_urb(urb); > + ret = (urb->status == -ENOENT ? -ETIMEDOUT : urb->status); > + } else { > + ret = urb->status; > + } > + if (ret >= 0) > + ret = urb->actual_length; /* bytes written */ > > switch (urb->status) { > /* success */ > case 0: > - len = urb->actual_length; > - > - mceusb_dev_printdata(ir, urb->transfer_buffer, len, > - 0, len, true); > break; > > case -ECONNRESET: > @@ -794,140 +856,135 @@ static void mce_async_callback(struct urb *urb) > break; > > case -EPIPE: > - dev_err(ir->dev, "Error: request urb status = %d (TX HALT)", > + dev_err(ir->dev, "Error: mce write urb status = %d (TX HALT)", > urb->status); > mceusb_defer_kevent(ir, EVENT_TX_HALT); > break; > > default: > - dev_err(ir->dev, "Error: request urb status = %d", urb->status); > + dev_err(ir->dev, "Error: mce write urb status = %d", > + urb->status); > break; > } > > - /* the transfer buffer and urb were allocated in mce_request_packet */ > - kfree(urb->transfer_buffer); > - usb_free_urb(urb); > -} > - > -/* request outgoing (send) usb packet - used to initialize remote */ > -static void mce_request_packet(struct mceusb_dev *ir, unsigned char *data, > - int size) > -{ > - int res; > - struct urb *async_urb; > - struct device *dev = ir->dev; > - unsigned char *async_buf; > + dev_dbg(dev, "tx done status = %d (wait = %lu, expire = %lu (%dms), urb->actual_length = %d, urb->status = %d)", > + ret, ret_wait, expire, USB_TX_TIMEOUT, > + urb->actual_length, urb->status); > > - async_urb = usb_alloc_urb(0, GFP_KERNEL); > - if (unlikely(!async_urb)) { > - dev_err(dev, "Error, couldn't allocate urb!"); > - return; > - } > - > - async_buf = kmalloc(size, GFP_KERNEL); > - if (!async_buf) { > - usb_free_urb(async_urb); > - return; > - } > - > - /* outbound data */ > - if (usb_endpoint_xfer_int(ir->usb_ep_out)) > - usb_fill_int_urb(async_urb, ir->usbdev, ir->pipe_out, > - async_buf, size, mce_async_callback, ir, > - ir->usb_ep_out->bInterval); > - else > - usb_fill_bulk_urb(async_urb, ir->usbdev, ir->pipe_out, > - async_buf, size, mce_async_callback, ir); > - > - memcpy(async_buf, data, size); > - > - dev_dbg(dev, "send request called (size=%#x)", size); > + kfree(buf_out); > + usb_free_urb(urb); > > - res = usb_submit_urb(async_urb, GFP_ATOMIC); > - if (res) { > - dev_err(dev, "send request FAILED! (res=%d)", res); > - kfree(async_buf); > - usb_free_urb(async_urb); > - return; > - } > - dev_dbg(dev, "send request complete (res=%d)", res); > + return ret; > } > > -static void mce_async_out(struct mceusb_dev *ir, unsigned char *data, int size) > +static void mce_command_out(struct mceusb_dev *ir, u8 *data, int size) > { > int rsize = sizeof(DEVICE_RESUME); > > if (ir->need_reset) { > ir->need_reset = false; > - mce_request_packet(ir, DEVICE_RESUME, rsize); > + mce_write(ir, DEVICE_RESUME, rsize); > msleep(10); > } > > - mce_request_packet(ir, data, size); > + mce_write(ir, data, size); > msleep(10); > } > > -/* Send data out the IR blaster port(s) */ > +/* > + * Transmit IR out the MCE device IR blaster port(s). > + * > + * Convert IR pulse/space sequence from LIRC to MCE format. > + * Break up a long IR sequence into multiple parts (MCE IR data packets). > + * > + * u32 txbuf[] consists of IR pulse, space, ..., and pulse times in usec. > + * Pulses and spaces are implicit by their position. > + * The first IR sample, txbuf[0], is always a pulse. > + * > + * u8 irbuf[] consists of multiple IR data packets for the MCE device. > + * A packet is 1 u8 MCE_IRDATA_HEADER and up to 30 u8 IR samples. > + * An IR sample is 1-bit pulse/space flag with 7-bit time > + * in MCE time units (50usec). > + * > + * Return: The number of IR samples sent (> 0) or errno (< 0). > + */ > static int mceusb_tx_ir(struct rc_dev *dev, unsigned *txbuf, unsigned count) > { > struct mceusb_dev *ir = dev->priv; > - int i, length, ret = 0; > - int cmdcount = 0; > - unsigned char cmdbuf[MCE_CMDBUF_SIZE]; > - > - /* MCE tx init header */ > - cmdbuf[cmdcount++] = MCE_CMD_PORT_IR; > - cmdbuf[cmdcount++] = MCE_CMD_SETIRTXPORTS; > - cmdbuf[cmdcount++] = ir->tx_mask; > + u8 cmdbuf[3] = { MCE_CMD_PORT_IR, MCE_CMD_SETIRTXPORTS, 0x00 }; > + u8 irbuf[MCE_IRBUF_SIZE]; > + int ircount = 0; > + unsigned int irsample; > + int i, length, ret; > > /* Send the set TX ports command */ > - mce_async_out(ir, cmdbuf, cmdcount); > - cmdcount = 0; > - > - /* Generate mce packet data */ > - for (i = 0; (i < count) && (cmdcount < MCE_CMDBUF_SIZE); i++) { > - txbuf[i] = txbuf[i] / MCE_TIME_UNIT; > - > - do { /* loop to support long pulses/spaces > 127*50us=6.35ms */ > - > - /* Insert mce packet header every 4th entry */ > - if ((cmdcount < MCE_CMDBUF_SIZE) && > - (cmdcount % MCE_CODE_LENGTH) == 0) > - cmdbuf[cmdcount++] = MCE_IRDATA_HEADER; > - > - /* Insert mce packet data */ > - if (cmdcount < MCE_CMDBUF_SIZE) > - cmdbuf[cmdcount++] = > - (txbuf[i] < MCE_PULSE_BIT ? > - txbuf[i] : MCE_MAX_PULSE_LENGTH) | > - (i & 1 ? 0x00 : MCE_PULSE_BIT); > - else { > - ret = -EINVAL; > - goto out; > + cmdbuf[2] = ir->tx_mask; > + mce_command_out(ir, cmdbuf, sizeof(cmdbuf)); > + > + /* Generate mce IR data packet */ > + for (i = 0; i < count; i++) { > + irsample = txbuf[i] / MCE_TIME_UNIT; > + > + /* loop to support long pulses/spaces > 6350us (127*50us) */ > + while (irsample > 0) { > + /* Insert IR header every 30th entry */ > + if (ircount % MCE_PACKET_SIZE == 0) { > + /* Room for IR header and one IR sample? */ > + if (ircount >= MCE_IRBUF_SIZE - 1) { > + /* Send near full buffer */ > + ret = mce_write(ir, irbuf, ircount); > + if (ret < 0) > + return ret; > + ircount = 0; > + } > + irbuf[ircount++] = MCE_IRDATA_HEADER; > } > > - } while ((txbuf[i] > MCE_MAX_PULSE_LENGTH) && > - (txbuf[i] -= MCE_MAX_PULSE_LENGTH)); > - } > - > - /* Check if we have room for the empty packet at the end */ > - if (cmdcount >= MCE_CMDBUF_SIZE) { > - ret = -EINVAL; > - goto out; > - } > + /* Insert IR sample */ > + if (irsample <= MCE_MAX_PULSE_LENGTH) { > + irbuf[ircount] = irsample; > + irsample = 0; > + } else { > + irbuf[ircount] = MCE_MAX_PULSE_LENGTH; > + irsample -= MCE_MAX_PULSE_LENGTH; > + } > + /* > + * Even i = IR pulse > + * Odd i = IR space > + */ > + irbuf[ircount] |= (i & 1 ? 0 : MCE_PULSE_BIT); > + ircount++; > + > + /* IR buffer full? */ > + if (ircount >= MCE_IRBUF_SIZE) { > + /* Fix packet length in last header */ > + length = ircount % MCE_PACKET_SIZE; > + if (length > 0) > + irbuf[ircount - length] -= > + MCE_PACKET_SIZE - length; > + /* Send full buffer */ > + ret = mce_write(ir, irbuf, ircount); > + if (ret < 0) > + return ret; > + ircount = 0; > + } > + } > + } /* after for loop, 0 <= ircount < MCE_IRBUF_SIZE */ > > /* Fix packet length in last header */ > - length = cmdcount % MCE_CODE_LENGTH; > - cmdbuf[cmdcount - length] -= MCE_CODE_LENGTH - length; > + length = ircount % MCE_PACKET_SIZE; > + if (length > 0) > + irbuf[ircount - length] -= MCE_PACKET_SIZE - length; > > - /* All mce commands end with an empty packet (0x80) */ > - cmdbuf[cmdcount++] = MCE_IRDATA_TRAILER; > + /* Append IR trailer (0x80) to final partial (or empty) IR buffer */ > + irbuf[ircount++] = MCE_IRDATA_TRAILER; > > - /* Transmit the command to the mce device */ > - mce_async_out(ir, cmdbuf, cmdcount); > + /* Send final buffer */ > + ret = mce_write(ir, irbuf, ircount); > + if (ret < 0) > + return ret; > > -out: > - return ret ? ret : count; > + return count; > } > > /* Sets active IR outputs -- mce devices typically have two */ > @@ -967,7 +1024,7 @@ static int mceusb_set_tx_carrier(struct rc_dev *dev, u32 carrier) > cmdbuf[2] = MCE_CMD_SIG_END; > cmdbuf[3] = MCE_IRDATA_TRAILER; > dev_dbg(ir->dev, "disabling carrier modulation"); > - mce_async_out(ir, cmdbuf, sizeof(cmdbuf)); > + mce_command_out(ir, cmdbuf, sizeof(cmdbuf)); > return 0; > } > > @@ -981,7 +1038,7 @@ static int mceusb_set_tx_carrier(struct rc_dev *dev, u32 carrier) > carrier); > > /* Transmit new carrier to mce device */ > - mce_async_out(ir, cmdbuf, sizeof(cmdbuf)); > + mce_command_out(ir, cmdbuf, sizeof(cmdbuf)); > return 0; > } > } > @@ -1004,10 +1061,10 @@ static int mceusb_set_timeout(struct rc_dev *dev, unsigned int timeout) > cmdbuf[2] = units >> 8; > cmdbuf[3] = units; > > - mce_async_out(ir, cmdbuf, sizeof(cmdbuf)); > + mce_command_out(ir, cmdbuf, sizeof(cmdbuf)); > > /* get receiver timeout value */ > - mce_async_out(ir, GET_RX_TIMEOUT, sizeof(GET_RX_TIMEOUT)); > + mce_command_out(ir, GET_RX_TIMEOUT, sizeof(GET_RX_TIMEOUT)); > > return 0; > } > @@ -1032,7 +1089,7 @@ static int mceusb_set_rx_wideband(struct rc_dev *dev, int enable) > ir->wideband_rx_enabled = false; > cmdbuf[2] = 1; /* port 1 is long range receiver */ > } > - mce_async_out(ir, cmdbuf, sizeof(cmdbuf)); > + mce_command_out(ir, cmdbuf, sizeof(cmdbuf)); > /* response from device sets ir->learning_active */ > > return 0; > @@ -1055,7 +1112,7 @@ static int mceusb_set_rx_carrier_report(struct rc_dev *dev, int enable) > ir->carrier_report_enabled = true; > if (!ir->learning_active) { > cmdbuf[2] = 2; /* port 2 is short range receiver */ > - mce_async_out(ir, cmdbuf, sizeof(cmdbuf)); > + mce_command_out(ir, cmdbuf, sizeof(cmdbuf)); > } > } else { > ir->carrier_report_enabled = false; > @@ -1066,7 +1123,7 @@ static int mceusb_set_rx_carrier_report(struct rc_dev *dev, int enable) > */ > if (ir->learning_active && !ir->wideband_rx_enabled) { > cmdbuf[2] = 1; /* port 1 is long range receiver */ > - mce_async_out(ir, cmdbuf, sizeof(cmdbuf)); > + mce_command_out(ir, cmdbuf, sizeof(cmdbuf)); > } > } > > @@ -1145,6 +1202,7 @@ static void mceusb_handle_command(struct mceusb_dev *ir, int index) > } > break; > case MCE_RSP_CMD_ILLEGAL: > + case MCE_RSP_TX_TIMEOUT: > ir->need_reset = true; > break; > default: > @@ -1283,7 +1341,7 @@ static void mceusb_get_emulator_version(struct mceusb_dev *ir) > { > /* If we get no reply or an illegal command reply, its ver 1, says MS */ > ir->emver = 1; > - mce_async_out(ir, GET_EMVER, sizeof(GET_EMVER)); > + mce_command_out(ir, GET_EMVER, sizeof(GET_EMVER)); > } > > static void mceusb_gen1_init(struct mceusb_dev *ir) > @@ -1329,10 +1387,10 @@ static void mceusb_gen1_init(struct mceusb_dev *ir) > dev_dbg(dev, "set handshake - retC = %d", ret); > > /* device resume */ > - mce_async_out(ir, DEVICE_RESUME, sizeof(DEVICE_RESUME)); > + mce_command_out(ir, DEVICE_RESUME, sizeof(DEVICE_RESUME)); > > /* get hw/sw revision? */ > - mce_async_out(ir, GET_REVISION, sizeof(GET_REVISION)); > + mce_command_out(ir, GET_REVISION, sizeof(GET_REVISION)); > > kfree(data); > } > @@ -1340,13 +1398,13 @@ static void mceusb_gen1_init(struct mceusb_dev *ir) > static void mceusb_gen2_init(struct mceusb_dev *ir) > { > /* device resume */ > - mce_async_out(ir, DEVICE_RESUME, sizeof(DEVICE_RESUME)); > + mce_command_out(ir, DEVICE_RESUME, sizeof(DEVICE_RESUME)); > > /* get wake version (protocol, key, address) */ > - mce_async_out(ir, GET_WAKEVERSION, sizeof(GET_WAKEVERSION)); > + mce_command_out(ir, GET_WAKEVERSION, sizeof(GET_WAKEVERSION)); > > /* unknown what this one actually returns... */ > - mce_async_out(ir, GET_UNKNOWN2, sizeof(GET_UNKNOWN2)); > + mce_command_out(ir, GET_UNKNOWN2, sizeof(GET_UNKNOWN2)); > } > > static void mceusb_get_parameters(struct mceusb_dev *ir) > @@ -1360,24 +1418,24 @@ static void mceusb_get_parameters(struct mceusb_dev *ir) > ir->num_rxports = 2; > > /* get number of tx and rx ports */ > - mce_async_out(ir, GET_NUM_PORTS, sizeof(GET_NUM_PORTS)); > + mce_command_out(ir, GET_NUM_PORTS, sizeof(GET_NUM_PORTS)); > > /* get the carrier and frequency */ > - mce_async_out(ir, GET_CARRIER_FREQ, sizeof(GET_CARRIER_FREQ)); > + mce_command_out(ir, GET_CARRIER_FREQ, sizeof(GET_CARRIER_FREQ)); > > if (ir->num_txports && !ir->flags.no_tx) > /* get the transmitter bitmask */ > - mce_async_out(ir, GET_TX_BITMASK, sizeof(GET_TX_BITMASK)); > + mce_command_out(ir, GET_TX_BITMASK, sizeof(GET_TX_BITMASK)); > > /* get receiver timeout value */ > - mce_async_out(ir, GET_RX_TIMEOUT, sizeof(GET_RX_TIMEOUT)); > + mce_command_out(ir, GET_RX_TIMEOUT, sizeof(GET_RX_TIMEOUT)); > > /* get receiver sensor setting */ > - mce_async_out(ir, GET_RX_SENSOR, sizeof(GET_RX_SENSOR)); > + mce_command_out(ir, GET_RX_SENSOR, sizeof(GET_RX_SENSOR)); > > for (i = 0; i < ir->num_txports; i++) { > cmdbuf[2] = i; > - mce_async_out(ir, cmdbuf, sizeof(cmdbuf)); > + mce_command_out(ir, cmdbuf, sizeof(cmdbuf)); > } > } > > @@ -1386,7 +1444,7 @@ static void mceusb_flash_led(struct mceusb_dev *ir) > if (ir->emver < 2) > return; > > - mce_async_out(ir, FLASH_LED, sizeof(FLASH_LED)); > + mce_command_out(ir, FLASH_LED, sizeof(FLASH_LED)); > } > > /* > -- > 2.11.0 >