From 1fc407cac055599496c8bda955e0a3689e7c79ed Mon Sep 17 00:00:00 2001
From: Peter Farsinsen <peter@farsinsen.dk>
Date: Thu, 13 Sep 2012 20:03:51 +0200
Subject: [PATCH] Initial commit of pcsensor v. 1.0.1

---
 99-tempsensor.rules |   1 +
 Makefile            |  12 ++
 pcsensor            | Bin 0 -> 17090 bytes
 pcsensor.c          | 450 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 463 insertions(+)
 create mode 100644 99-tempsensor.rules
 create mode 100644 Makefile
 create mode 100755 pcsensor
 create mode 100644 pcsensor.c

diff --git a/99-tempsensor.rules b/99-tempsensor.rules
new file mode 100644
index 0000000..30a2e1e
--- /dev/null
+++ b/99-tempsensor.rules
@@ -0,0 +1 @@
+SUBSYSTEMS=="usb", ACTION=="add", ATTRS{idVendor}=="0c45", ATTRS{idProduct}=="7401", MODE="666"
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..0557550
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,12 @@
+all:	pcsensor
+
+CFLAGS = -O2 -Wall
+
+pcsensor:	pcsensor.c
+	${CC} -DUNIT_TEST -o $@ $^ -lusb
+
+clean:		
+	rm -f pcsensor *.o
+
+rules-install:			# must be superuser to do this
+	cp 99-tempsensor.rules /etc/udev/rules.d
diff --git a/pcsensor b/pcsensor
new file mode 100755
index 0000000000000000000000000000000000000000..ea22415784610780d5666d1afd7dbbda6ff4db40
GIT binary patch
literal 17090
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

literal 0
HcmV?d00001

diff --git a/pcsensor.c b/pcsensor.c
new file mode 100644
index 0000000..ea2b03b
--- /dev/null
+++ b/pcsensor.c
@@ -0,0 +1,450 @@
+/*
+ * pcsensor.c by Juan Carlos Perez (c) 2011 (cray@isp-sl.com)
+ * based on Temper.c by Robert Kavaler (c) 2009 (relavak.com)
+ * All rights reserved.
+ *
+ * 2011/08/30 Thanks to EdorFaus: bugfix to support negative temperatures
+ *
+ * Temper driver for linux. This program can be compiled either as a library
+ * or as a standalone program (-DUNIT_TEST). The driver will work with some
+ * TEMPer usb devices from RDing (www.PCsensor.com).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Juan Carlos Perez ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Robert kavaler BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+
+#include <usb.h>
+#include <stdio.h>
+#include <time.h>
+
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+
+
+#define VERSION "1.0.1"
+
+#define VENDOR_ID  0x0c45
+#define PRODUCT_ID 0x7401
+
+#define INTERFACE1 0x00
+#define INTERFACE2 0x01
+
+const static int reqIntLen=8;
+const static int reqBulkLen=8;
+const static int endpoint_Int_in=0x82; /* endpoint 0x81 address for IN */
+const static int endpoint_Int_out=0x00; /* endpoint 1 address for OUT */
+const static int endpoint_Bulk_in=0x82; /* endpoint 0x81 address for IN */
+const static int endpoint_Bulk_out=0x00; /* endpoint 1 address for OUT */
+const static int timeout=5000; /* timeout in ms */
+
+const static char uTemperatura[] = { 0x01, 0x80, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00 };
+const static char uIni1[] = { 0x01, 0x82, 0x77, 0x01, 0x00, 0x00, 0x00, 0x00 };
+const static char uIni2[] = { 0x01, 0x86, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00 };
+
+static int bsalir=1;
+static int debug=0;
+static int seconds=5;
+static int formato=0;
+static int mrtg=0;
+static int calibration=0;
+
+
+void bad(const char *why) {
+        fprintf(stderr,"Fatal error> %s\n",why);
+        exit(17);
+}
+
+
+usb_dev_handle *find_lvr_winusb();
+
+void usb_detach(usb_dev_handle *lvr_winusb, int iInterface) {
+        int ret;
+
+	ret = usb_detach_kernel_driver_np(lvr_winusb, iInterface);
+	if(ret) {
+		if(errno == ENODATA) {
+			if(debug) {
+				printf("Device already detached\n");
+			}
+		} else {
+			if(debug) {
+				printf("Detach failed: %s[%d]\n",
+				       strerror(errno), errno);
+				printf("Continuing anyway\n");
+			}
+		}
+	} else {
+		if(debug) {
+			printf("detach successful\n");
+		}
+	}
+}
+
+usb_dev_handle* setup_libusb_access() {
+     usb_dev_handle *lvr_winusb;
+
+     if(debug) {
+        usb_set_debug(255);
+     } else {
+        usb_set_debug(0);
+     }
+     usb_init();
+     usb_find_busses();
+     usb_find_devices();
+
+
+     if(!(lvr_winusb = find_lvr_winusb())) {
+                printf("Couldn't find the USB device, Exiting\n");
+                return NULL;
+        }
+
+
+        usb_detach(lvr_winusb, INTERFACE1);
+
+
+        usb_detach(lvr_winusb, INTERFACE2);
+
+
+        if (usb_set_configuration(lvr_winusb, 0x01) < 0) {
+                printf("Could not set configuration 1\n");
+                return NULL;
+        }
+
+
+        // Microdia tiene 2 interfaces
+        if (usb_claim_interface(lvr_winusb, INTERFACE1) < 0) {
+                printf("Could not claim interface\n");
+                return NULL;
+        }
+
+        if (usb_claim_interface(lvr_winusb, INTERFACE2) < 0) {
+                printf("Could not claim interface\n");
+                return NULL;
+        }
+
+        return lvr_winusb;
+}
+
+
+
+usb_dev_handle *find_lvr_winusb() {
+
+     struct usb_bus *bus;
+        struct usb_device *dev;
+
+        for (bus = usb_busses; bus; bus = bus->next) {
+        for (dev = bus->devices; dev; dev = dev->next) {
+                        if (dev->descriptor.idVendor == VENDOR_ID &&
+                                dev->descriptor.idProduct == PRODUCT_ID ) {
+                                usb_dev_handle *handle;
+                                if(debug) {
+                                  printf("lvr_winusb with Vendor Id: %x and Product Id: %x found.\n", VENDOR_ID, PRODUCT_ID);
+                                }
+
+                                if (!(handle = usb_open(dev))) {
+                                        printf("Could not open USB device\n");
+                                        return NULL;
+                                }
+                                return handle;
+                        }
+                }
+        }
+        return NULL;
+}
+
+
+void ini_control_transfer(usb_dev_handle *dev) {
+    int r,i;
+
+    char question[] = { 0x01,0x01 };
+
+    r = usb_control_msg(dev, 0x21, 0x09, 0x0201, 0x00, (char *) question, 2, timeout);
+    if( r < 0 )
+    {
+          perror("USB control write"); bad("USB write failed");
+    }
+
+
+    if(debug) {
+      for (i=0;i<reqIntLen; i++) printf("%02x ",question[i] & 0xFF);
+      printf("\n");
+    }
+}
+
+void control_transfer(usb_dev_handle *dev, const char *pquestion) {
+    int r,i;
+
+    char question[reqIntLen];
+
+    memcpy(question, pquestion, sizeof question);
+
+    r = usb_control_msg(dev, 0x21, 0x09, 0x0200, 0x01, (char *) question, reqIntLen, timeout);
+    if( r < 0 )
+    {
+          perror("USB control write"); bad("USB write failed");
+    }
+
+    if(debug) {
+        for (i=0;i<reqIntLen; i++) printf("%02x ",question[i]  & 0xFF);
+        printf("\n");
+    }
+}
+
+void interrupt_transfer(usb_dev_handle *dev) {
+
+    int r,i;
+    char answer[reqIntLen];
+    char question[reqIntLen];
+    for (i=0;i<reqIntLen; i++) question[i]=i;
+    r = usb_interrupt_write(dev, endpoint_Int_out, question, reqIntLen, timeout);
+    if( r < 0 )
+    {
+          perror("USB interrupt write"); bad("USB write failed");
+    }
+    r = usb_interrupt_read(dev, endpoint_Int_in, answer, reqIntLen, timeout);
+    if( r != reqIntLen )
+    {
+          perror("USB interrupt read"); bad("USB read failed");
+    }
+
+    if(debug) {
+       for (i=0;i<reqIntLen; i++) printf("%i, %i, \n",question[i],answer[i]);
+    }
+
+    usb_release_interface(dev, 0);
+}
+
+void interrupt_read(usb_dev_handle *dev) {
+
+    int r,i;
+    unsigned char answer[reqIntLen];
+    bzero(answer, reqIntLen);
+
+    r = usb_interrupt_read(dev, 0x82, answer, reqIntLen, timeout);
+    if( r != reqIntLen )
+    {
+          perror("USB interrupt read"); bad("USB read failed");
+    }
+
+    if(debug) {
+       for (i=0;i<reqIntLen; i++) printf("%02x ",answer[i]  & 0xFF);
+
+       printf("\n");
+    }
+}
+
+void interrupt_read_temperatura(usb_dev_handle *dev, float *tempC) {
+
+    int r,i, temperature;
+    unsigned char answer[reqIntLen];
+    bzero(answer, reqIntLen);
+
+    r = usb_interrupt_read(dev, 0x82, answer, reqIntLen, timeout);
+    if( r != reqIntLen )
+    {
+          perror("USB interrupt read"); bad("USB read failed");
+    }
+
+
+    if(debug) {
+      for (i=0;i<reqIntLen; i++) printf("%02x ",answer[i]  & 0xFF);
+
+      printf("\n");
+    }
+
+    temperature = (answer[3] & 0xFF) + ((signed char)answer[2] << 8);
+    temperature += calibration;
+    *tempC = temperature * (125.0 / 32000.0);
+
+}
+
+void bulk_transfer(usb_dev_handle *dev) {
+
+    int r,i;
+    char answer[reqBulkLen];
+
+    r = usb_bulk_write(dev, endpoint_Bulk_out, NULL, 0, timeout);
+    if( r < 0 )
+    {
+          perror("USB bulk write"); bad("USB write failed");
+    }
+    r = usb_bulk_read(dev, endpoint_Bulk_in, answer, reqBulkLen, timeout);
+    if( r != reqBulkLen )
+    {
+          perror("USB bulk read"); bad("USB read failed");
+    }
+
+
+    if(debug) {
+      for (i=0;i<reqBulkLen; i++) printf("%02x ",answer[i]  & 0xFF);
+    }
+
+    usb_release_interface(dev, 0);
+}
+
+
+void ex_program(int sig) {
+      bsalir=1;
+
+      (void) signal(SIGINT, SIG_DFL);
+}
+
+int main( int argc, char **argv) {
+
+     usb_dev_handle *lvr_winusb = NULL;
+     float tempc;
+     int c;
+     struct tm *local;
+     time_t t;
+
+     while ((c = getopt (argc, argv, "mfcvhl::a:")) != -1)
+     switch (c)
+       {
+       case 'v':
+         debug = 1;
+         break;
+       case 'c':
+         formato=1; //Celsius
+         break;
+       case 'f':
+         formato=2; //Fahrenheit
+         break;
+       case 'm':
+         mrtg=1;
+         break;
+       case 'l':
+         if (optarg!=NULL){
+           if (!sscanf(optarg,"%i",&seconds)==1) {
+             fprintf (stderr, "Error: '%s' is not numeric.\n", optarg);
+             exit(EXIT_FAILURE);
+           } else {
+              bsalir = 0;
+              break;
+           }
+         } else {
+           bsalir = 0;
+           seconds = 5;
+           break;
+         }
+       case 'a':
+         if (!sscanf(optarg,"%i",&calibration)==1) {
+             fprintf (stderr, "Error: '%s' is not numeric.\n", optarg);
+             exit(EXIT_FAILURE);
+         } else {
+              break;
+         }
+       case '?':
+       case 'h':
+         printf("pcsensor version %s\n",VERSION);
+	 printf("      Aviable options:\n");
+	 printf("          -h help\n");
+	 printf("          -v verbose\n");
+	 printf("          -l[n] loop every 'n' seconds, default value is 5s\n");
+	 printf("          -c output only in Celsius\n");
+	 printf("          -f output only in Fahrenheit\n");
+	 printf("          -a[n] increase or decrease temperature in 'n' degrees for device calibration\n");
+	 printf("          -m output for mrtg integration\n");
+
+	 exit(EXIT_FAILURE);
+       default:
+         if (isprint (optopt))
+           fprintf (stderr, "Unknown option `-%c'.\n", optopt);
+         else
+           fprintf (stderr,
+                    "Unknown option character `\\x%x'.\n",
+                    optopt);
+         exit(EXIT_FAILURE);
+       }
+
+     if (optind < argc) {
+        fprintf(stderr, "Non-option ARGV-elements, try -h for help.\n");
+        exit(EXIT_FAILURE);
+     }
+
+     if ((lvr_winusb = setup_libusb_access()) == NULL) {
+         exit(EXIT_FAILURE);
+     }
+
+     (void) signal(SIGINT, ex_program);
+
+     ini_control_transfer(lvr_winusb);
+
+     control_transfer(lvr_winusb, uTemperatura );
+     interrupt_read(lvr_winusb);
+
+     control_transfer(lvr_winusb, uIni1 );
+     interrupt_read(lvr_winusb);
+
+     control_transfer(lvr_winusb, uIni2 );
+     interrupt_read(lvr_winusb);
+     interrupt_read(lvr_winusb);
+
+
+
+     do {
+           control_transfer(lvr_winusb, uTemperatura );
+           interrupt_read_temperatura(lvr_winusb, &tempc);
+
+           t = time(NULL);
+           local = localtime(&t);
+
+           if (mrtg) {
+              if (formato==2) {
+                  printf("%.2f\n", (9.0 / 5.0 * tempc + 32.0));
+                  printf("%.2f\n", (9.0 / 5.0 * tempc + 32.0));
+              } else {
+                  printf("%.2f\n", tempc);
+                  printf("%.2f\n", tempc);
+              }
+
+              printf("%02d:%02d\n",
+                          local->tm_hour,
+                          local->tm_min);
+
+              printf("pcsensor\n");
+           } else {
+              printf("%04d/%02d/%02d %02d:%02d:%02d ",
+                          local->tm_year +1900,
+                          local->tm_mon + 1,
+                          local->tm_mday,
+                          local->tm_hour,
+                          local->tm_min,
+                          local->tm_sec);
+
+              if (formato==2) {
+                  printf("Temperature %.2fF\n", (9.0 / 5.0 * tempc + 32.0));
+              } else if (formato==1) {
+                  printf("Temperature %.2fC\n", tempc);
+              } else {
+                  printf("Temperature %.2fF %.2fC\n", (9.0 / 5.0 * tempc + 32.0), tempc);
+              }
+           }
+
+           if (!bsalir)
+              sleep(seconds);
+     } while (!bsalir);
+
+     usb_release_interface(lvr_winusb, INTERFACE1);
+     usb_release_interface(lvr_winusb, INTERFACE2);
+
+     usb_close(lvr_winusb);
+
+     return 0;
+}