All pastes #170626 Raw Edit

Unnamed

public text v1 · immutable
·published 2006-09-14 18:16 UTC
rendered paste body
--- lirc_mceusb2.c.org	2006-08-12 16:47:34.000000000 +0200
+++ lirc_mceusb2.c	2006-08-19 02:57:18.000000000 +0200
@@ -4,6 +4,9 @@
  * 
  * (C) by Martin A. Blatter <martin_a_blatter@yahoo.com>
  *
+ * Transmitter support

+ * (C) by Daniel Melander <lirc@rajidae.se>

+ *

  * Derived from ATI USB driver by Paul Miller and the original
  * MCE USB driver by Dan Corti
  *
@@ -56,8 +59,8 @@
 #include "drivers/kcompat.h"
 #include "drivers/lirc_dev/lirc_dev.h"
 
-#define DRIVER_VERSION		"0.22"
-#define DRIVER_AUTHOR		"Martin Blatter <martin_a_blatter@yahoo.com>"
+#define DRIVER_VERSION          "0.23"

+#define DRIVER_AUTHOR           "Martin Blatter <martin_a_blatter@yahoo.com>, Daniel Melander <lirc@rajidae.se>"

 #define DRIVER_DESC		"USB remote driver for LIRC"
 #define DRIVER_NAME		"lirc_mceusb2"
 
@@ -67,7 +70,7 @@
 #define MCE_CODE_LENGTH		5
 #define MCE_TIME_UNIT           50
 #define MCE_PACKET_SIZE 	4
-#define MCE_PACKET_HEADER 	0x84
+#define MCE_PACKET_HEADER       0x84  //Actual format is 0x80+num_bytes

 
 /* module parameters */
 #ifdef CONFIG_USB_DEBUG
@@ -411,6 +414,130 @@
 	usb_submit_urb(urb, SLAB_ATOMIC);
 }
 
+

+//////////////////////////////////////////////////

+///////////////////SEND SUPPORT///////////////////

+//////////////////////////////////////////////////

+

+#define CMDBUF_LEN 256                         //MCE Command buffer length

+#define WBUF_LEN   256                         //Work buffer length

+#define MCE_PULSE_MASK 0x80                    //Pulse mask, MSB set == PULSE else SPACE

+#define MCE_TX_RESOLUTION 50                   //Approx 50us resolution, could use MCE_TIME_UNIT

+#define MCE_MAX_CHANNELS 2                     //Only 2 transmitters, hardware dependent?

+#define MCE_MAX_PULSE_LENGTH 0x7F              //Longest transmittable pulse symbol

+

+static unsigned int active_transmitters=0x06;  //Supported values are TX1=0x2, TX2=0x4, ALL=0x6

+static lirc_t wbuf[WBUF_LEN];                  //Workbuffer with values from lirc

+static unsigned char cmdbuf[CMDBUF_LEN];       //MCE Command buffer

+

+struct irctl *usb_ir=NULL;

+struct usb_endpoint_descriptor *usb_ep_out=NULL;

+

+

+static ssize_t lirc_write(struct file *file, const char *buf, size_t n, loff_t * ppos)

+{

+      int i, count=0, cmdcount=0;

+      

+      if(n%sizeof(lirc_t)) return(-EINVAL);

+      count=n/sizeof(lirc_t);

+      

+      //Check if command is within limits

+      if(count>WBUF_LEN || count%2==0) return(-EINVAL);

+      if(copy_from_user(wbuf,buf,n)) return -EFAULT;

+

+      //MCE tx header

+      cmdbuf[cmdcount++]=0x9F;

+      cmdbuf[cmdcount++]=0x08;

+      cmdbuf[cmdcount++]=active_transmitters;

+      

+      //Generate mce packet data

+      for(i=0;(i<count) && (i+1 < CMDBUF_LEN);i++)  {

+         wbuf[i]=wbuf[i]/MCE_TX_RESOLUTION;

+         

+         do { //Support long pulses > 127*50us=6.35ms

+         	

+           //Insert mce packet header every 4th packet

+           if ((cmdcount+2)%MCE_CODE_LENGTH==0) { 

+              cmdbuf[cmdcount++]=0x80+((count-i>=MCE_PACKET_SIZE)?MCE_PACKET_SIZE:count-i);

+           }

+           

+           //Insert mce packet data

+           cmdbuf[cmdcount++]=(wbuf[i]<MCE_PULSE_MASK?wbuf[i]:MCE_MAX_PULSE_LENGTH) | (i%2?0x00:MCE_PULSE_MASK);

+           

+         } while ((wbuf[i] > MCE_MAX_PULSE_LENGTH) && (wbuf[i]-=MCE_MAX_PULSE_LENGTH));

+      }

+      

+      if (cmdcount>CMDBUF_LEN) return(-EINVAL);

+     

+      //Always end with an empty packet (0x80)

+      cmdbuf[cmdcount++]=0x80;

+   

+      //Transmit packet to mce device

+      request_packet_async( usb_ir, usb_ep_out, cmdbuf, cmdcount, PHILUSB_OUTBOUND );

+        

+      return(n);

+}

+

+

+static int lirc_ioctl(struct inode *node,struct file *filep,unsigned int cmd, unsigned long arg)

+{

+      int result;

+      unsigned int ivalue;

+      unsigned long lvalue;

+

+      switch(cmd) {

+

+        case LIRC_SET_TRANSMITTER_MASK:

+            

+            result=get_user(ivalue,(unsigned int *) arg);

+            if(result) return(result);

+

+            switch(ivalue) {

+               case 0x01: //Transmitter 2

+               case 0x02: //Transmitter 1               

+               case 0x03: //Transmitter 1 and 2

+                    active_transmitters = (ivalue!=0x03?ivalue ^ 0x03:ivalue) << 1; //Yhe mask begins at 0x02 and has an inverted numbering scheme

+                    break;

+             

+               default: //If unsupported transmitter mask

+                    return MCE_MAX_CHANNELS;            

+            }

+               

+            printk(DRIVER_NAME ":SET_TRANSMITTERS mask=%d\n", ivalue);

+            return (0);

+            break;

+

+        case LIRC_GET_SEND_MODE:

+            

+            result=put_user(LIRC_SEND2MODE (LIRC_CAN_SEND_PULSE&LIRC_CAN_SEND_MASK), (unsigned long *) arg);

+               

+            if(result) return(result);

+            break;

+

+        case LIRC_SET_SEND_MODE:

+            

+            result=get_user(lvalue,(unsigned long *) arg);

+            

+            if(result) return(result);

+            if(lvalue!=(LIRC_MODE_PULSE&LIRC_CAN_SEND_MASK)) return(-EINVAL);

+            break;

+          

+        default:

+            return(-ENOIOCTLCMD);

+      }

+

+      return(0);

+}

+

+static struct file_operations lirc_fops =

+{

+  write:   lirc_write,

+};

+

+//////////////////////////////////////////////////

+///////////////////SEND SUPPORT///////////////////

+//////////////////////////////////////////////////

+

 static int usb_remote_probe(struct usb_interface *intf,
 				const struct usb_device_id *id)
 {
@@ -493,13 +620,16 @@
 
 			strcpy(plugin->name, DRIVER_NAME " ");
 			plugin->minor = -1;
-			plugin->features = LIRC_CAN_REC_MODE2;
+                      plugin->features = LIRC_CAN_SEND_PULSE |

+                                           LIRC_CAN_SET_TRANSMITTER_MASK | 

+                                           LIRC_CAN_REC_MODE2;

 			plugin->data = ir;
 			plugin->rbuf = rbuf;
 			plugin->set_use_inc = &set_use_inc;
 			plugin->set_use_dec = &set_use_dec;
 			plugin->code_length = sizeof(lirc_t) * 8;
-			plugin->ioctl = NULL;
+                     plugin->ioctl = lirc_ioctl;

+                     plugin->fops  = &lirc_fops;

 			plugin->owner = THIS_MODULE;
 
 			init_MUTEX(&ir->lock);
@@ -561,6 +691,11 @@
 	request_packet_async( ir, ep_in, NULL, maxp, 0);
 
 	usb_set_intfdata(intf, ir);
+      

+        //Saving usb interface data for use by the transmitter routine

+        usb_ir=ir;

+        usb_ep_out=ep_out;

+

 	return SUCCESS;
 }