#include #include #include #include /* * 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 1 #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; }