aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/IR
diff options
context:
space:
mode:
authorJarod Wilson <jarod@redhat.com>2010-06-16 16:55:52 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-08-02 13:58:58 -0400
commite23fb9643bd440fee9106e6df76f01a57db2613c (patch)
tree4bd1858a0a19061646698f6033410750f5738390 /drivers/media/IR
parent9b7c54d926284c5277cff3ef3cfe29f26568306a (diff)
V4L/DVB: IR/mceusb: add tx callback functions and wire up
mchehab: merged with IR/mceusb: userspace buffer copy moved out of driver Userspace buffer copy moved out of driver and into lirc bridge driver [mchehab@redhat.com: merged the patch to avoid compilation errors with allyesconfig ] Signed-off-by: Jarod Wilson <jarod@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/IR')
-rw-r--r--drivers/media/IR/mceusb.c148
1 files changed, 138 insertions, 10 deletions
diff --git a/drivers/media/IR/mceusb.c b/drivers/media/IR/mceusb.c
index 708a71a38443..cc8e2ef28b66 100644
--- a/drivers/media/IR/mceusb.c
+++ b/drivers/media/IR/mceusb.c
@@ -15,10 +15,6 @@
15 * Jon Smirl, which included enhancements and simplifications to the 15 * Jon Smirl, which included enhancements and simplifications to the
16 * incoming IR buffer parsing routines. 16 * incoming IR buffer parsing routines.
17 * 17 *
18 * TODO:
19 * - add rc-core transmit support, once available
20 * - enable support for forthcoming ir-lirc-codec interface
21 *
22 * 18 *
23 * This program is free software; you can redistribute it and/or modify 19 * This program is free software; you can redistribute it and/or modify
24 * it under the terms of the GNU General Public License as published by 20 * it under the terms of the GNU General Public License as published by
@@ -51,7 +47,6 @@
51#define DRIVER_NAME "mceusb" 47#define DRIVER_NAME "mceusb"
52 48
53#define USB_BUFLEN 32 /* USB reception buffer length */ 49#define USB_BUFLEN 32 /* USB reception buffer length */
54#define IRBUF_SIZE 256 /* IR work buffer length */
55#define USB_CTRL_MSG_SZ 2 /* Size of usb ctrl msg on gen1 hw */ 50#define USB_CTRL_MSG_SZ 2 /* Size of usb ctrl msg on gen1 hw */
56#define MCE_G1_INIT_MSGS 40 /* Init messages on gen1 hw to throw out */ 51#define MCE_G1_INIT_MSGS 40 /* Init messages on gen1 hw to throw out */
57 52
@@ -263,14 +258,13 @@ struct mceusb_dev {
263 u32 reserved:28; 258 u32 reserved:28;
264 } flags; 259 } flags;
265 260
266 /* handle sending (init strings) */ 261 /* transmit support */
267 int send_flags; 262 int send_flags;
268 int carrier; 263 u32 carrier;
264 unsigned char tx_mask;
269 265
270 char name[128]; 266 char name[128];
271 char phys[64]; 267 char phys[64];
272
273 unsigned char tx_mask;
274}; 268};
275 269
276/* 270/*
@@ -520,6 +514,91 @@ static void mce_sync_in(struct mceusb_dev *ir, unsigned char *data, int size)
520 mce_request_packet(ir, ir->usb_ep_in, data, size, MCEUSB_RX); 514 mce_request_packet(ir, ir->usb_ep_in, data, size, MCEUSB_RX);
521} 515}
522 516
517/* Send data out the IR blaster port(s) */
518static int mceusb_tx_ir(void *priv, int *txbuf, u32 n)
519{
520 struct mceusb_dev *ir = priv;
521 int i, ret = 0;
522 int count, cmdcount = 0;
523 unsigned char *cmdbuf; /* MCE command buffer */
524 long signal_duration = 0; /* Singnal length in us */
525 struct timeval start_time, end_time;
526
527 do_gettimeofday(&start_time);
528
529 count = n / sizeof(int);
530
531 cmdbuf = kzalloc(sizeof(int) * MCE_CMDBUF_SIZE, GFP_KERNEL);
532 if (!cmdbuf)
533 return -ENOMEM;
534
535 /* MCE tx init header */
536 cmdbuf[cmdcount++] = MCE_CONTROL_HEADER;
537 cmdbuf[cmdcount++] = 0x08;
538 cmdbuf[cmdcount++] = ir->tx_mask;
539
540 /* Generate mce packet data */
541 for (i = 0; (i < count) && (cmdcount < MCE_CMDBUF_SIZE); i++) {
542 signal_duration += txbuf[i];
543 txbuf[i] = txbuf[i] / MCE_TIME_UNIT;
544
545 do { /* loop to support long pulses/spaces > 127*50us=6.35ms */
546
547 /* Insert mce packet header every 4th entry */
548 if ((cmdcount < MCE_CMDBUF_SIZE) &&
549 (cmdcount - MCE_TX_HEADER_LENGTH) %
550 MCE_CODE_LENGTH == 0)
551 cmdbuf[cmdcount++] = MCE_PACKET_HEADER;
552
553 /* Insert mce packet data */
554 if (cmdcount < MCE_CMDBUF_SIZE)
555 cmdbuf[cmdcount++] =
556 (txbuf[i] < MCE_PULSE_BIT ?
557 txbuf[i] : MCE_MAX_PULSE_LENGTH) |
558 (i & 1 ? 0x00 : MCE_PULSE_BIT);
559 else {
560 ret = -EINVAL;
561 goto out;
562 }
563
564 } while ((txbuf[i] > MCE_MAX_PULSE_LENGTH) &&
565 (txbuf[i] -= MCE_MAX_PULSE_LENGTH));
566 }
567
568 /* Fix packet length in last header */
569 cmdbuf[cmdcount - (cmdcount - MCE_TX_HEADER_LENGTH) % MCE_CODE_LENGTH] =
570 0x80 + (cmdcount - MCE_TX_HEADER_LENGTH) % MCE_CODE_LENGTH - 1;
571
572 /* Check if we have room for the empty packet at the end */
573 if (cmdcount >= MCE_CMDBUF_SIZE) {
574 ret = -EINVAL;
575 goto out;
576 }
577
578 /* All mce commands end with an empty packet (0x80) */
579 cmdbuf[cmdcount++] = 0x80;
580
581 /* Transmit the command to the mce device */
582 mce_async_out(ir, cmdbuf, cmdcount);
583
584 /*
585 * The lircd gap calculation expects the write function to
586 * wait the time it takes for the ircommand to be sent before
587 * it returns.
588 */
589 do_gettimeofday(&end_time);
590 signal_duration -= (end_time.tv_usec - start_time.tv_usec) +
591 (end_time.tv_sec - start_time.tv_sec) * 1000000;
592
593 /* delay with the closest number of ticks */
594 set_current_state(TASK_INTERRUPTIBLE);
595 schedule_timeout(usecs_to_jiffies(signal_duration));
596
597out:
598 kfree(cmdbuf);
599 return ret ? ret : n;
600}
601
523/* Sets active IR outputs -- mce devices typically (all?) have two */ 602/* Sets active IR outputs -- mce devices typically (all?) have two */
524static int mceusb_set_tx_mask(void *priv, u32 mask) 603static int mceusb_set_tx_mask(void *priv, u32 mask)
525{ 604{
@@ -533,6 +612,49 @@ static int mceusb_set_tx_mask(void *priv, u32 mask)
533 return 0; 612 return 0;
534} 613}
535 614
615/* Sets the send carrier frequency and mode */
616static int mceusb_set_tx_carrier(void *priv, u32 carrier)
617{
618 struct mceusb_dev *ir = priv;
619 int clk = 10000000;
620 int prescaler = 0, divisor = 0;
621 unsigned char cmdbuf[4] = { 0x9f, 0x06, 0x00, 0x00 };
622
623 /* Carrier has changed */
624 if (ir->carrier != carrier) {
625
626 if (carrier == 0) {
627 ir->carrier = carrier;
628 cmdbuf[2] = 0x01;
629 cmdbuf[3] = 0x80;
630 dev_dbg(ir->dev, "%s: disabling carrier "
631 "modulation\n", __func__);
632 mce_async_out(ir, cmdbuf, sizeof(cmdbuf));
633 return carrier;
634 }
635
636 for (prescaler = 0; prescaler < 4; ++prescaler) {
637 divisor = (clk >> (2 * prescaler)) / carrier;
638 if (divisor <= 0xFF) {
639 ir->carrier = carrier;
640 cmdbuf[2] = prescaler;
641 cmdbuf[3] = divisor;
642 dev_dbg(ir->dev, "%s: requesting %u HZ "
643 "carrier\n", __func__, carrier);
644
645 /* Transmit new carrier to mce device */
646 mce_async_out(ir, cmdbuf, sizeof(cmdbuf));
647 return carrier;
648 }
649 }
650
651 return -EINVAL;
652
653 }
654
655 return carrier;
656}
657
536static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len) 658static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
537{ 659{
538 struct ir_raw_event rawir = { .pulse = false, .duration = 0 }; 660 struct ir_raw_event rawir = { .pulse = false, .duration = 0 };
@@ -724,6 +846,9 @@ static void mceusb_gen2_init(struct mceusb_dev *ir)
724 mce_sync_in(ir, NULL, maxp); 846 mce_sync_in(ir, NULL, maxp);
725 mce_sync_in(ir, NULL, maxp); 847 mce_sync_in(ir, NULL, maxp);
726 848
849 set_current_state(TASK_INTERRUPTIBLE);
850 schedule_timeout(msecs_to_jiffies(100));
851
727 /* device reset */ 852 /* device reset */
728 mce_async_out(ir, DEVICE_RESET, sizeof(DEVICE_RESET)); 853 mce_async_out(ir, DEVICE_RESET, sizeof(DEVICE_RESET));
729 mce_sync_in(ir, NULL, maxp); 854 mce_sync_in(ir, NULL, maxp);
@@ -791,7 +916,7 @@ static struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir)
791 goto ir_dev_alloc_failed; 916 goto ir_dev_alloc_failed;
792 } 917 }
793 918
794 snprintf(ir->name, sizeof(ir->name), "Media Center Edition eHome " 919 snprintf(ir->name, sizeof(ir->name), "Media Center Ed. eHome "
795 "Infrared Remote Transceiver (%04x:%04x)", 920 "Infrared Remote Transceiver (%04x:%04x)",
796 le16_to_cpu(ir->usbdev->descriptor.idVendor), 921 le16_to_cpu(ir->usbdev->descriptor.idVendor),
797 le16_to_cpu(ir->usbdev->descriptor.idProduct)); 922 le16_to_cpu(ir->usbdev->descriptor.idProduct));
@@ -804,6 +929,9 @@ static struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir)
804 props->priv = ir; 929 props->priv = ir;
805 props->driver_type = RC_DRIVER_IR_RAW; 930 props->driver_type = RC_DRIVER_IR_RAW;
806 props->allowed_protos = IR_TYPE_ALL; 931 props->allowed_protos = IR_TYPE_ALL;
932 props->s_tx_mask = mceusb_set_tx_mask;
933 props->s_tx_carrier = mceusb_set_tx_carrier;
934 props->tx_ir = mceusb_tx_ir;
807 935
808 ir->props = props; 936 ir->props = props;
809 ir->irdev = irdev; 937 ir->irdev = irdev;