static int redrat3_transmit_ir(struct rc_dev *rcdev, unsigned *txbuf, unsigned count) { struct redrat3_dev *rr3 = rcdev->priv; struct device *dev = rr3->dev; struct redrat3_signal_header header; int i, j, ret, ret_len, offset; int lencheck, cur_sample_len, pipe; char *buffer = NULL, *sigdata = NULL; int *sample_lens = NULL; u32 tmpi; u16 tmps; u8 *datap; u8 curlencheck = 0; u16 *lengths_ptr; int sendbuf_len; rr3_ftr(dev, "Entering %s\n", __func__); if (rr3->transmitting) { dev_warn(dev, "%s: transmitter already in use\n", __func__); return -EAGAIN; } if (count > (RR3_DRIVER_MAXLENS * 2)) return -EINVAL; /* */ rr3->det_enabled = false; rr3->transmitting = true; sample_lens = kzalloc(sizeof(int) * RR3_DRIVER_MAXLENS, GFP_KERNEL); if (!sample_lens) { ret = -ENOMEM; goto out; } for (i = 0; i < count; i++) { for (lencheck = 0; lencheck < curlencheck; lencheck++) { cur_sample_len = redrat3_us_to_len(txbuf[i]); if (sample_lens[lencheck] == cur_sample_len) break; } if (lencheck == curlencheck) { cur_sample_len = redrat3_us_to_len(txbuf[i]); rr3_dbg(dev, "txbuf[%d]=%u, pos %d, enc %u\n", i, txbuf[i], curlencheck, cur_sample_len); if (curlencheck < 255) { /* */ sample_lens[curlencheck] = cur_sample_len; curlencheck++; } else { dev_err(dev, "signal too long\n"); ret = -EINVAL; goto out; } } } sigdata = kzalloc((count + RR3_TX_TRAILER_LEN), GFP_KERNEL); if (!sigdata) { ret = -ENOMEM; goto out; } sigdata[count] = RR3_END_OF_SIGNAL; sigdata[count + 1] = RR3_END_OF_SIGNAL; for (i = 0; i < count; i++) { for (j = 0; j < curlencheck; j++) { if (sample_lens[j] == redrat3_us_to_len(txbuf[i])) sigdata[i] = j; } } offset = RR3_TX_HEADER_OFFSET; sendbuf_len = RR3_HEADER_LENGTH + (sizeof(u16) * RR3_DRIVER_MAXLENS) + count + RR3_TX_TRAILER_LEN + offset; buffer = kzalloc(sendbuf_len, GFP_KERNEL); if (!buffer) { ret = -ENOMEM; goto out; } /* */ header.length = sendbuf_len - offset; header.transfer_type = RR3_MOD_SIGNAL_OUT; header.pause = redrat3_len_to_us(100); header.mod_freq_count = mod_freq_to_val(rr3->carrier); header.no_periods = 0; /* */ header.max_lengths = RR3_DRIVER_MAXLENS; header.no_lengths = curlencheck; header.max_sig_size = RR3_MAX_SIG_SIZE; header.sig_size = count + RR3_TX_TRAILER_LEN; /* */ header.no_repeats = 0; tmps = cpu_to_be16(header.length); memcpy(buffer, &tmps, 2); tmps = cpu_to_be16(header.transfer_type); memcpy(buffer + 2, &tmps, 2); tmpi = cpu_to_be32(header.pause); memcpy(buffer + offset, &tmpi, sizeof(tmpi)); tmps = cpu_to_be16(header.mod_freq_count); memcpy(buffer + offset + RR3_FREQ_COUNT_OFFSET, &tmps, 2); buffer[offset + RR3_NUM_LENGTHS_OFFSET] = header.no_lengths; tmps = cpu_to_be16(header.sig_size); memcpy(buffer + offset + RR3_NUM_SIGS_OFFSET, &tmps, 2); buffer[offset + RR3_REPEATS_OFFSET] = header.no_repeats; lengths_ptr = (u16 *)(buffer + offset + RR3_HEADER_LENGTH); for (i = 0; i < curlencheck; ++i) lengths_ptr[i] = cpu_to_be16(sample_lens[i]); datap = (u8 *)(buffer + offset + RR3_HEADER_LENGTH + (sizeof(u16) * RR3_DRIVER_MAXLENS)); memcpy(datap, sigdata, (count + RR3_TX_TRAILER_LEN)); if (debug) { redrat3_dump_signal_header(&header); redrat3_dump_signal_data(buffer, header.sig_size); } pipe = usb_sndbulkpipe(rr3->udev, rr3->ep_out->bEndpointAddress); tmps = usb_bulk_msg(rr3->udev, pipe, buffer, sendbuf_len, &ret_len, 10 * HZ); rr3_dbg(dev, "sent %d bytes, (ret %d)\n", ret_len, tmps); /* */ pipe = usb_rcvctrlpipe(rr3->udev, 0); ret = usb_control_msg(rr3->udev, pipe, RR3_TX_SEND_SIGNAL, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 0, 0, buffer, 2, HZ * 10); if (ret < 0) dev_err(dev, "Error: control msg send failed, rc %d\n", ret); else ret = count; out: kfree(sample_lens); kfree(buffer); kfree(sigdata); rr3->transmitting = false; /* */ rr3->det_enabled = true; return ret; }
static int redrat3_transmit_ir(struct rc_dev *rcdev, unsigned *txbuf, unsigned count) { struct redrat3_dev *rr3 = rcdev->priv; struct device *dev = rr3->dev; struct redrat3_irdata *irdata = NULL; int ret, ret_len; int lencheck, cur_sample_len, pipe; int *sample_lens = NULL; u8 curlencheck = 0; unsigned i, sendbuf_len; rr3_ftr(dev, "Entering %s\n", __func__); if (rr3->transmitting) { dev_warn(dev, "%s: transmitter already in use\n", __func__); return -EAGAIN; } if (count > RR3_MAX_SIG_SIZE - RR3_TX_TRAILER_LEN) return -EINVAL; /* rr3 will disable rc detector on transmit */ rr3->transmitting = true; sample_lens = kzalloc(sizeof(int) * RR3_DRIVER_MAXLENS, GFP_KERNEL); if (!sample_lens) { ret = -ENOMEM; goto out; } irdata = kzalloc(sizeof(*irdata), GFP_KERNEL); if (!irdata) { ret = -ENOMEM; goto out; } for (i = 0; i < count; i++) { cur_sample_len = redrat3_us_to_len(txbuf[i]); if (cur_sample_len > 0xffff) { dev_warn(dev, "transmit period of %uus truncated to %uus\n", txbuf[i], redrat3_len_to_us(0xffff)); cur_sample_len = 0xffff; } for (lencheck = 0; lencheck < curlencheck; lencheck++) { if (sample_lens[lencheck] == cur_sample_len) break; } if (lencheck == curlencheck) { rr3_dbg(dev, "txbuf[%d]=%u, pos %d, enc %u\n", i, txbuf[i], curlencheck, cur_sample_len); if (curlencheck < RR3_DRIVER_MAXLENS) { /* now convert the value to a proper * rr3 value.. */ sample_lens[curlencheck] = cur_sample_len; put_unaligned_be16(cur_sample_len, &irdata->lens[curlencheck]); curlencheck++; } else { ret = -EINVAL; goto out; } } irdata->sigdata[i] = lencheck; } irdata->sigdata[count] = RR3_END_OF_SIGNAL; irdata->sigdata[count + 1] = RR3_END_OF_SIGNAL; sendbuf_len = offsetof(struct redrat3_irdata, sigdata[count + RR3_TX_TRAILER_LEN]); /* fill in our packet header */ irdata->header.length = cpu_to_be16(sendbuf_len - sizeof(struct redrat3_header)); irdata->header.transfer_type = cpu_to_be16(RR3_MOD_SIGNAL_OUT); irdata->pause = cpu_to_be32(redrat3_len_to_us(100)); irdata->mod_freq_count = cpu_to_be16(mod_freq_to_val(rr3->carrier)); irdata->no_lengths = curlencheck; irdata->sig_size = cpu_to_be16(count + RR3_TX_TRAILER_LEN); pipe = usb_sndbulkpipe(rr3->udev, rr3->ep_out->bEndpointAddress); ret = usb_bulk_msg(rr3->udev, pipe, irdata, sendbuf_len, &ret_len, 10 * HZ); rr3_dbg(dev, "sent %d bytes, (ret %d)\n", ret_len, ret); /* now tell the hardware to transmit what we sent it */ pipe = usb_rcvctrlpipe(rr3->udev, 0); ret = usb_control_msg(rr3->udev, pipe, RR3_TX_SEND_SIGNAL, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 0, 0, irdata, 2, HZ * 10); if (ret < 0) dev_err(dev, "Error: control msg send failed, rc %d\n", ret); else ret = count; out: kfree(sample_lens); kfree(irdata); rr3->transmitting = false; /* rr3 re-enables rc detector because it was enabled before */ return ret; }