summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--glcddrivers/dm140gink.c309
-rw-r--r--glcddrivers/dm140gink.h57
2 files changed, 366 insertions, 0 deletions
diff --git a/glcddrivers/dm140gink.c b/glcddrivers/dm140gink.c
new file mode 100644
index 0000000..c7efdba
--- /dev/null
+++ b/glcddrivers/dm140gink.c
@@ -0,0 +1,309 @@
+/*
+ * GraphLCD driver library
+ *
+ * framebuffer.h - framebuffer device
+ * Output goes to a framebuffer device
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2004 Stephan Skrodzki
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <asm/types.h>
+#include <linux/hiddev.h>
+
+
+#include "common.h"
+#include "config.h"
+#include "dm140gink.h"
+
+
+namespace GLCD
+{
+
+cDriverDM140GINK::cDriverDM140GINK(cDriverConfig * config)
+: config(config),
+ fd(-1),
+ framebuff(0)
+{
+ oldConfig = new cDriverConfig(*config);
+}
+
+cDriverDM140GINK::~cDriverDM140GINK()
+{
+ delete oldConfig;
+}
+
+/* hack - fix improper signed char handling - it's seeing 0x80 as a negative value*/
+#define VALUE_FILTER(_value) (_value>0x7F)?(__s32)(0xFFFFFF00 | _value):(_value)
+
+//**************************************************************
+// FUNCTION: SendReport
+//
+// INPUT:
+// int fd - file descriptor to the opened HID device
+// const char *buf - Message to write
+// size_t size - size of buf.
+//
+// OUTPUT:
+// int err - result of the ioctl call (On success 0, On error -1)
+//
+// DESCRIPTION: This function will write the 'buf' to the opened
+// HID device. Specifically, it updates the device's usage
+// reference with the data and then sends a report to the HID.
+//**************************************************************
+int cDriverDM140GINK::SendReport(const char *cbuf, size_t size)
+{
+ const unsigned char *buf=reinterpret_cast<const unsigned char *>(cbuf);
+ struct hiddev_report_info rinfo;
+ struct hiddev_usage_ref uref;
+ int err;
+
+ //******************************************************
+ // Initialize the usage Reference and mark it for OUTPUT
+ //******************************************************
+ memset(&uref, 0, sizeof(uref));
+ uref.report_type = HID_REPORT_TYPE_OUTPUT;
+ uref.report_id = 0;
+ uref.field_index = 0;
+
+ //**************************************************************
+ // Fill in the information that we wish to set
+ //**************************************************************
+ uref.usage_code = 0xffa10005; //unused?
+ for(size_t i=0;i<size;i++)
+ {
+ uref.usage_index = i;
+ uref.value = VALUE_FILTER(buf[i]);
+
+ //**************************************************************
+ // HIDIOCSUSAGE - struct hiddev_usage_ref (write)
+ // Sets the value of a usage in an output report. The user fills
+ // in the hiddev_usage_ref structure as above, but additionally
+ // fills in the value field.
+ //**************************************************************
+ if((err = ioctl(fd, HIDIOCSUSAGE, &uref)) < 0)
+ {
+ syslog(LOG_INFO, "%s: Error with sending the USAGE ioctl %d,0x%02X;size:%d\n", config->name.c_str(), i, (int)buf[i],size);
+ return err;
+ }
+ uref.usage_code = 0xffa10006; //unused?
+ }
+
+ //**************************************************************
+ // HIDIOCSREPORT - struct hiddev_report_info (write)
+ // Instructs the kernel to SEND a report to the device. This
+ // report can be filled in by the user through HIDIOCSUSAGE calls
+ // (below) to fill in individual usage values in the report before
+ // sending the report in full to the device.
+ //**************************************************************
+ memset(&rinfo, 0, sizeof(rinfo));
+ rinfo.report_type = HID_REPORT_TYPE_OUTPUT;
+ rinfo.report_id = 0;
+ rinfo.num_fields = 0;
+ if((err = ioctl(fd, HIDIOCSREPORT, &rinfo)) < 0)
+ {
+ syslog(LOG_INFO, "%s: Error with sending the REPORT ioctl %d\n", config->name.c_str(), err);
+ }
+
+ //******************************************************
+ // All done, let's return what we did.
+ //******************************************************
+ return err;
+}
+
+int cDriverDM140GINK::Init()
+{
+ // default values
+ width = config->width;
+ if (width <= 0)
+ width = 112;
+ height = config->height;
+ if (height <= 0)
+ height = 16;
+
+ vendor = 0x040b;
+ product = 0x7001;
+
+ for (unsigned int i = 0; i < config->options.size(); i++)
+ {
+ if (config->options[i].name == "Vendor")
+ vendor=config->GetInt(config->options[i].value);
+ if (config->options[i].name == "Product")
+ product=config->GetInt(config->options[i].value);
+ }
+
+ //******************************************************
+ // Loop through all the 16 HID ports/devices looking for
+ // one that matches our device.
+ //******************************************************
+ const char *hiddev_prefix = "/dev/usb/hiddev"; /* in devfs */
+ for(int i=0;i<16;i++)
+ {
+ char port[32];
+ sprintf(port, "%s%d", hiddev_prefix, i);
+ if((fd = open(port,O_WRONLY))>=0)
+ {
+ struct hiddev_devinfo device_info;
+ ioctl(fd, HIDIOCGDEVINFO, &device_info);
+
+
+ // If we've found our device, no need to look further, time to stop searching
+ if(vendor==device_info.vendor && product==device_info.product)
+ {
+ //char name[256];
+ //ioctl(fd, HIDIOCGNAME(sizeof(name)), name);
+ //name[sizeof(name)-1]='\0';
+ //syslog(LOG_INFO, "%s: The device %s was opened successfully.\n", config->name.c_str(), name);
+
+ break; // stop the for loop
+ }
+ close(fd); // Added by HL
+ fd=-1;
+ }
+ }
+
+ if (-1 == fd)
+ {
+ syslog(LOG_ERR, "%s: Cannot open device 0x%x:0x%x.\n", config->name.c_str(), vendor, product);
+ return -1;
+ }
+
+ //******************************************************
+ // Initialize the internal report structures
+ //******************************************************
+ if(ioctl(fd, HIDIOCINITREPORT,0)<0)
+ {
+ syslog(LOG_ERR, "%s: cannot init device.\n", config->name.c_str());
+ return -1;
+ }
+
+ //******************************************************
+ // Set up the display to show graphics
+ //******************************************************
+ const char panelCmd[] = {0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00};
+ const char iconCmd[] = {0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; //icon command
+ const char iconoff[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; //icon data
+
+ SendReport(panelCmd, sizeof(panelCmd));
+ SendReport(iconCmd, sizeof(iconCmd));
+ SendReport(iconoff, sizeof(iconoff));
+
+ const char setup[] = {0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+ SendReport(setup, sizeof(setup));
+
+ screensize = width * height / 8;
+
+ // reserve another memory to draw into
+ framebuff = new char[screensize];
+ if (!framebuff)
+ {
+ syslog(LOG_ERR, "%s: failed to alloc memory for device.\n", config->name.c_str());
+ return -1;
+ }
+
+ *oldConfig = *config;
+
+ // clear display
+ Clear();
+ Refresh(true);
+
+ syslog(LOG_INFO, "%s: display initialized.\n", config->name.c_str());
+ return 0;
+}
+
+int cDriverDM140GINK::DeInit()
+{
+ if (framebuff)
+ delete[] framebuff;
+ framebuff=NULL;
+ if (-1 != fd)
+ close(fd);
+ fd=-1;
+ return 0;
+}
+
+int cDriverDM140GINK::CheckSetup()
+{
+ if (config->device != oldConfig->device ||
+ config->port != oldConfig->port ||
+ config->width != oldConfig->width ||
+ config->height != oldConfig->height)
+ {
+ DeInit();
+ Init();
+ return 0;
+ }
+
+ if (config->upsideDown != oldConfig->upsideDown ||
+ config->invert != oldConfig->invert)
+ {
+ oldConfig->upsideDown = config->upsideDown;
+ oldConfig->invert = config->invert;
+ return 1;
+ }
+ return 0;
+}
+
+void cDriverDM140GINK::SetPixel(int x, int y)
+{
+ if (x >= width || y >= height)
+ return;
+
+ if (config->upsideDown)
+ {
+ x = width - 1 - x;
+ y = height - 1 - y;
+ }
+
+ int offset = (y/8) * width + x;
+ char mask = (1 << (7 - (y%8)));
+ framebuff[offset] |= mask;
+}
+
+void cDriverDM140GINK::Clear()
+{
+ memset(framebuff, 0, screensize);
+}
+
+void cDriverDM140GINK::Set8Pixels(int x, int y, unsigned char data)
+{
+ x &= 0xFFF8;
+
+ for (int n = 0; n < 8; ++n)
+ {
+ if (data & (0x80 >> n)) // if bit is set
+ SetPixel(x + n, y);
+ }
+}
+
+void cDriverDM140GINK::Refresh(bool refreshAll)
+{
+ char packet[] = {0x1D, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+ SendReport(packet, sizeof(packet));
+
+ // Send the actual graphics
+ for(int i=0; i< screensize;i+=8)
+ {
+ // make sure we only send 8 bytes at a time
+ int size = (screensize - i);
+ size = (size > 8) ? 8 : size;
+ SendReport(framebuff+i, size);
+ }
+
+ const char show[] = {0x01, 0x05, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00};
+
+ SendReport(show, sizeof(show));
+}
+
+} // end of namespace
diff --git a/glcddrivers/dm140gink.h b/glcddrivers/dm140gink.h
new file mode 100644
index 0000000..526263a
--- /dev/null
+++ b/glcddrivers/dm140gink.h
@@ -0,0 +1,57 @@
+/*
+ * GraphLCD driver library
+ *
+ * framebuffer.h - framebuffer device
+ * Output goes to a framebuffer device
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2004 Stephan Skrodzki
+ */
+
+#ifndef _GLCDDRIVERS_DM140GINK_H_
+#define _GLCDDRIVERS_DM140GINK_H_
+
+#include "driver.h"
+
+
+namespace GLCD
+{
+
+class cDriverConfig;
+
+class cDriverDM140GINK : public cDriver
+{
+private:
+ cDriverConfig * config;
+ cDriverConfig * oldConfig;
+
+ int fd;
+
+ int vendor;
+ int product;
+
+ char *framebuff;
+
+ long int screensize;
+
+ int SendReport(const char *buf, size_t size);
+ int CheckSetup();
+ void SetPixel(int x, int y);
+
+public:
+ cDriverDM140GINK(cDriverConfig * config);
+ virtual ~cDriverDM140GINK();
+
+ virtual int Init();
+ virtual int DeInit();
+
+ virtual void Clear();
+ virtual void Set8Pixels(int x, int y, unsigned char data);
+ virtual void Refresh(bool refreshAll = false);
+};
+
+} // end of namespace
+
+#endif