summaryrefslogtreecommitdiffstats
path: root/temper/temper.c
diff options
context:
space:
mode:
Diffstat (limited to 'temper/temper.c')
-rw-r--r--temper/temper.c277
1 files changed, 277 insertions, 0 deletions
diff --git a/temper/temper.c b/temper/temper.c
new file mode 100644
index 00000000..390f9056
--- /dev/null
+++ b/temper/temper.c
@@ -0,0 +1,277 @@
+#include <stdio.h>
+#include <string.h>
+#include <usb.h>
+#include <errno.h>
+
+/*
+ * Temper.c by Robert Kavaler (c) 2009 (relavak.com)
+ * All rights reserved.
+ *
+ * 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 Robert Kavaler ''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 "temper.h"
+
+#define VENDOR_ID 0x1130
+#define PRODUCT_ID 0x660c
+
+struct Temper {
+ struct usb_device *device;
+ usb_dev_handle *handle;
+ int debug;
+ int timeout;
+};
+
+ Temper *
+TemperCreate(struct usb_device *dev, int timeout, int debug)
+{
+ Temper *t;
+ int ret;
+
+ t = calloc(1, sizeof(*t));
+ t->device = dev;
+ t->debug = debug;
+ t->timeout = timeout;
+ t->handle = usb_open(t->device);
+ if(!t->handle) {
+ free(t);
+ return NULL;
+ }
+ if(t->debug) {
+ printf("Trying to detach kernel driver\n");
+ }
+
+ ret = usb_detach_kernel_driver_np(t->handle, 0);
+ if(ret) {
+ if(errno == ENODATA) {
+ if(t->debug) {
+ printf("Device already detached\n");
+ }
+ } else {
+ if(t->debug) {
+ printf("Detach failed: %s[%d]\n",
+ strerror(errno), errno);
+ printf("Continuing anyway\n");
+ }
+ }
+ } else {
+ if(t->debug) {
+ printf("detach successful\n");
+ }
+ }
+ ret = usb_detach_kernel_driver_np(t->handle, 1);
+ if(ret) {
+ if(errno == ENODATA) {
+ if(t->debug)
+ printf("Device already detached\n");
+ } else {
+ if(t->debug) {
+ printf("Detach failed: %s[%d]\n",
+ strerror(errno), errno);
+ printf("Continuing anyway\n");
+ }
+ }
+ } else {
+ if(t->debug) {
+ printf("detach successful\n");
+ }
+ }
+
+ if(usb_set_configuration(t->handle, 1) < 0 ||
+ usb_claim_interface(t->handle, 0) < 0 ||
+ usb_claim_interface(t->handle, 1)) {
+ usb_close(t->handle);
+ free(t);
+ return NULL;
+ }
+ return t;
+}
+
+ Temper *
+TemperCreateFromDeviceNumber(int deviceNum, int timeout, int debug)
+{
+ struct usb_bus *bus;
+ int n;
+
+ n = 0;
+ for(bus=usb_get_busses(); bus; bus=bus->next) {
+ struct usb_device *dev;
+
+ for(dev=bus->devices; dev; dev=dev->next) {
+ if(debug) {
+ printf("Found device: %04x:%04x\n",
+ dev->descriptor.idVendor,
+ dev->descriptor.idProduct);
+ }
+ if(dev->descriptor.idVendor == VENDOR_ID &&
+ dev->descriptor.idProduct == PRODUCT_ID) {
+ if(debug) {
+ printf("Found deviceNum %d\n", n);
+ }
+ if(n == deviceNum) {
+ return TemperCreate(dev, timeout, debug);
+ }
+ n++;
+ }
+ }
+ }
+ return NULL;
+}
+
+ void
+TemperFree(Temper *t)
+{
+ if(t) {
+ if(t->handle) {
+ usb_close(t->handle);
+ }
+ free(t);
+ }
+}
+
+ static int
+TemperSendCommand(Temper *t, int a, int b, int c, int d, int e, int f, int g, int h)
+{
+ unsigned char buf[32];
+ int ret;
+
+ bzero(buf, 32);
+ buf[0] = a;
+ buf[1] = b;
+ buf[2] = c;
+ buf[3] = d;
+ buf[4] = e;
+ buf[5] = f;
+ buf[6] = g;
+ buf[7] = h;
+
+ if(t->debug) {
+ printf("sending bytes %d, %d, %d, %d, %d, %d, %d, %d\n",
+ a, b, c, d, e, f, g, h);
+ }
+
+ ret = usb_control_msg(t->handle, 0x21, 9, 0x200, 0x01,
+ (char *) buf, 32, t->timeout);
+ if(ret != 32) {
+ perror("usb_control_msg failed");
+ return -1;
+ }
+ return 0;
+}
+
+ static int
+TemperGetData(Temper *t, char *buf, int len)
+{
+ int ret;
+
+ return usb_control_msg(t->handle, 0xa1, 1, 0x300, 0x01,
+ (char *) buf, len, t->timeout);
+}
+
+ int
+TemperGetTemperatureInC(Temper *t, float *tempC)
+{
+ char buf[256];
+ int ret, temperature, i;
+
+ TemperSendCommand(t, 10, 11, 12, 13, 0, 0, 2, 0);
+ TemperSendCommand(t, 0x54, 0, 0, 0, 0, 0, 0, 0);
+ for(i = 0; i < 7; i++) {
+ TemperSendCommand(t, 0, 0, 0, 0, 0, 0, 0, 0);
+ }
+ TemperSendCommand(t, 10, 11, 12, 13, 0, 0, 1, 0);
+ ret = TemperGetData(t, buf, 256);
+ if(ret < 2) {
+ return -1;
+ }
+
+ temperature = (buf[1] & 0xFF) + (buf[0] << 8);
+ temperature += 1152; // calibration value
+ *tempC = temperature * (125.0 / 32000.0);
+ return 0;
+}
+
+ int
+TemperGetOtherStuff(Temper *t, char *buf, int length)
+{
+ TemperSendCommand(t, 10, 11, 12, 13, 0, 0, 2, 0);
+ TemperSendCommand(t, 0x52, 0, 0, 0, 0, 0, 0, 0);
+ TemperSendCommand(t, 10, 11, 12, 13, 0, 0, 1, 0);
+ return TemperGetData(t, buf, length);
+}
+
+
+#define USB_TIMEOUT 1000 /* milliseconds */
+#define DEBUG_MODE 0
+#define SLEEP_TIMEOUT 10
+
+ int
+main(int argv,char** args)
+{
+
+
+ Temper *t;
+ char buf[256];
+ int i, ret,oneshot=0;
+ if (argv == 2 && (args[1][1] == 'h' || args[1][0] == 'h'))
+ {
+ printf("Temper, does the right thing in C\n");
+ printf("recompile with DEBUG_MODE = 1 for all the debug printing\n");
+ printf("recompile with SLEEP_TIMEOUT = XX for a different polling interval\n");
+ exit(0);
+ }
+
+ usb_set_debug(DEBUG_MODE);
+ usb_init();
+ usb_find_busses();
+ usb_find_devices();
+
+ t = TemperCreateFromDeviceNumber(0, USB_TIMEOUT, DEBUG_MODE);
+ if(!t) {
+ perror("TemperCreate");
+ exit(-1);
+ }
+
+ /*
+ TemperSendCommand(t, 10, 11, 12, 13, 0, 0, 2, 0);
+ TemperSendCommand(t, 0x43, 0, 0, 0, 0, 0, 0, 0);
+ TemperSendCommand(t, 0, 0, 0, 0, 0, 0, 0, 0);
+ TemperSendCommand(t, 0, 0, 0, 0, 0, 0, 0, 0);
+ TemperSendCommand(t, 0, 0, 0, 0, 0, 0, 0, 0);
+ TemperSendCommand(t, 0, 0, 0, 0, 0, 0, 0, 0);
+ TemperSendCommand(t, 0, 0, 0, 0, 0, 0, 0, 0);
+ TemperSendCommand(t, 0, 0, 0, 0, 0, 0, 0, 0);
+ */
+
+ bzero(buf, 256);
+ ret = TemperGetOtherStuff(t, buf, 256);
+
+ float tempc;
+
+ if(TemperGetTemperatureInC(t, &tempc) < 0) {
+ perror("TemperGetTemperatureInC");
+ exit(1);
+ }
+
+ printf("%.2f\n", tempc);
+ return 0;
+}