File: hd44780-usblcd.c

package info (click to toggle)
lcdproc 0.5.9-3
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, buster, sid
  • size: 5,064 kB
  • sloc: ansic: 59,645; sh: 1,740; perl: 681; makefile: 417
file content (176 lines) | stat: -rw-r--r-- 4,780 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
/** \file server/drivers/hd44780-usblcd.c
 * \c ucdlcd connection type of \c hd44780 driver for Hitachi HD44780 based LCD
 * displays. This driver does only work with Linux and requires a kernel driver
 * available since 2.4.20-pre7.
 *
 * See http://www.usblcd.de for hardware and documentation.
 */

/*
 * Copyright (C)  2002 Adams IT Services <info@usblcd.de>
 *
 * This driver is based on pic-an-lcd driver. See file hd44780-serial.c for
 * additional Copyrights.
 *
 * This file is released under the GNU General Public License. Refer to the
 * COPYING file distributed with this package.
 *
 * Modified February 2009 by Markus Dolze to use API v0.5.
 */

#include "hd44780-usblcd.h"
#include "hd44780-low.h"
#include "shared/report.h"

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#define DEFAULT_DEVICE  "/dev/usb/lcd"

#define IOCTL_GET_HARD_VERSION  1
#define IOCTL_GET_DRV_VERSION	2

void usblcd_HD44780_senddata(PrivateData *p, unsigned char displayID, unsigned char flags, unsigned char ch);
void usblcd_HD44780_backlight(PrivateData *p, unsigned char state);
void usblcd_HD44780_close(PrivateData *p);

/**
 * Initialize the driver.
 * \param drvthis  Pointer to driver structure.
 * \retval 0       Success.
 * \retval -1      Error opening device.
 * \retval -2      Error reading or unsupported driver version.
 * \retval -3      Error reading or unsupported hardware version.
 */
int
hd_init_usblcd(Driver *drvthis)
{
	PrivateData *p = (PrivateData *) drvthis->private_data;

	char device[256] = DEFAULT_DEVICE;
	char buf[128];
	int major, minor;

	/* Get device to use */
	strncpy(device, drvthis->config_get_string(drvthis->name, "device", 0, DEFAULT_DEVICE), sizeof(device));
	device[sizeof(device) - 1] = '\0';
	report(RPT_INFO, "HD44780: USBLCD: using device: %s", device);

	/* Set up io port correctly, and open it... */
	p->fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY);
	if (p->fd == -1) {
		report(RPT_ERR, "HD44780: USBLCD: could not open device %s (%s)", device, strerror(errno));
		return -1;
	}

	/* Read and check kernel driver version */
	memset(buf, 0, 128);
	if (ioctl(p->fd, IOCTL_GET_DRV_VERSION, buf) != 0) {
		report(RPT_ERR, "IOCTL failed, could not get Driver Version");
		return -2;
	}
	report(RPT_INFO, "Driver Version: %s", buf);

	if (sscanf(buf, "USBLCD Driver Version %d.%d", &major, &minor) != 2) {
		report(RPT_ERR, "Could not read Driver Version");
		return -2;
	}
	if (major != 1) {
		report(RPT_ERR, "Driver Version not supported");
		return -2;
	}

	/* Read and check hardware version */
	memset(buf, 0, 128);
	if (ioctl(p->fd, IOCTL_GET_HARD_VERSION, buf) != 0) {
		report(RPT_ERR, "IOCTL failed, could not get Hardware Version");
		return -3;
	};
	report(RPT_INFO, "Hardware Version: %s", buf);
	if (sscanf(buf, "%d.%d", &major, &minor) != 2) {
		report(RPT_ERR, "Could not read Hardware Version");
		return -3;
	};
	if (major != 1) {
		report(RPT_ERR, "Hardware Version not supported");
		return -3;
	}

	/* Set local functions */
	p->hd44780_functions->senddata = usblcd_HD44780_senddata;
	p->hd44780_functions->backlight = usblcd_HD44780_backlight;
	p->hd44780_functions->close = usblcd_HD44780_close;

	common_init(p, IF_8BIT);
	return 0;
}

/**
 * Send data or commands to the display.
 * \param p          Pointer to driver's private data structure.
 * \param displayID  ID of the display (or 0 for all) to send data to.
 * \param flags      Defines whether to end a command or data.
 * \param ch         The value to send.
 */
void
usblcd_HD44780_senddata(PrivateData *p, unsigned char displayID, unsigned char flags, unsigned char ch)
{
	static const char instr_byte = 0;

	if (flags == RS_DATA) {
		/*
		 * Escape data byte 0x00 by sending it twice because it is
		 * used as instruction byte
		 */
		if (ch == '\0')
			write(p->fd, &ch, 1);
		write(p->fd, &ch, 1);
	} else {
		/* Instructions are sent prepending 0x00 as escape sequence */
		write(p->fd, &instr_byte, 1);
		write(p->fd, &ch, 1);
	}
}

/**
 * Turn display backlight on or off.
 * \param p      Pointer to driver's private data structure.
 * \param state  New backlight status.
 */
void
usblcd_HD44780_backlight(PrivateData *p, unsigned char state)
{
	static const char instr_byte = 0;
	static const char bl_on = 0x21;
	static const char bl_off = 0x20;

	write(p->fd, &instr_byte, 1);

	if (state == BACKLIGHT_OFF)
		write(p->fd, &bl_off, 1);
	else
		write(p->fd, &bl_on, 1);
}

/**
 * Close the driver (do necessary clean-up).
 * \param p  Pointer to driver's private data structure.
 */
void
usblcd_HD44780_close(PrivateData *p)
{
	if (p->fd >= 0)
		close(p->fd);
}

/* EOF */