1 /* This is the LCDproc driver for Point Of Sale ("POS") devices using
2 various protocols. While it currently only supports AEDEX,
3 it can be extended to provide support for many POS emulation types.
5 Copyright (C) 2006 Eric Pooch
7 This driver is based on MtxOrb.c driver and is subject to its copyrights.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
24 List of driver entry point:
30 clear Implemented by space filling no custom char info.
37 heartbeat Implemented.
38 icon NOT IMPLEMENTED: not part of POS protocol
39 cursor NOT IMPLEMENTED: not part of AEDEX protocol
40 set_char NOT IMPLEMENTED: not part of AEDEX protocol
41 get_free_chars Implemented.
42 cellwidth Implemented.
43 cellheight Implemented.
44 get_contrast NOT IMPLEMENTED: not part of AEDEX protocol
45 set_contrast NOT IMPLEMENTED: not part of AEDEX protocol
46 get_brightness NOT IMPLEMENTED: not part of AEDEX protocol
47 set_brightness NOT IMPLEMENTED: not part of AEDEX protocol
48 backlight NOT IMPLEMENTED: not part of AEDEX protocol
49 output Not implemented.
50 get_key Not implemented, no keys.
57 #include <sys/types.h>
73 #include "serialPOS.h"
74 #include "adv_bignum.h"
80 * The serialPOS driver does not use a lot of hardware features.
81 * We try to replace them with more flexible software alternatives.
82 * That's why vbar/hbar/bignum are using locally-defined functions;
83 * it permits simultaneous use of those features and custom chars.
85 * For the same reason, we don't use the hardware clear but rather
86 * empty the internal frame buffer. The frame buffer holds all
87 * the requested changes until the server asks us to flush the
88 * changes to the display. This also permits us to do an
89 * incremental update and reduce the number of characters to be
90 * sent to the display across the serial link.
92 * In order to display graphic widgets, we define and use our own
93 * custom characters. To avoid multiple definitions of the same
94 * custom characters, we use a caching mechanism that remembers
95 * what is currently defined. In order to avoid always redefining
96 * the same custom character at the beginning of the table, we
97 * rotate the beginning of the table. This is supposed to reduce
98 * the number of character redefinitions and make the caching more
99 * effective. The overall goal is to reduce the number of
100 * characters sent to the display.
115 #define AEDEXPrefix "!#"
118 AEDEXLine1Display
= 1, /* upper line display */
119 AEDEXLine2Display
, /* bottom line display */
120 AEDEXLine3Display
, /* not sure what this code really is */
121 AEDEXContinuousScroll
, /* upper line message scroll continuously */
122 AEDEXDisplayTime
, /* "hh':'mm" h,m='0'-'9' display time */
123 AEDEXSingleScroll
, /* upper line message scroll one pass */
124 AEDEXAllScroll
, /* not sure what this code really is */
125 AEDEXChangeCode
, /* change attention code */
126 AEDEXAllLineDisplay
/* two line display */
131 standard
, /* only char 0 is used for heartbeat */
132 vbar
, /* vertical bars */
133 hbar
, /* horizontal bars */
134 custom
, /* custom settings */
135 bignum
, /* big numbers */
136 bigchar
/* big characters */
143 int fd
; /* The LCD file descriptor */
147 int cellwidth
, cellheight
;
149 /* framebuffer and buffer for old LCD contents */
150 unsigned char *framebuf
;
151 unsigned char *backingstore
;
153 /* defineable characters */
160 POS_EmulationType emulation_mode
; /* The emulation type */
161 int output_state
; /* static data from serialPOS_output */
163 char info
[255]; /* static data from serialPOS_get_info */
167 /* Vars for the server core */
168 MODULE_EXPORT
char *api_version
= API_VERSION
;
169 MODULE_EXPORT
int stay_in_foreground
= 0;
170 MODULE_EXPORT
int supports_multiple
= 1;
171 MODULE_EXPORT
char *symbol_prefix
= "serialPOS_";
173 static void serialPOS_hardware_clear(Driver
*drvthis
);
174 static void serialPOS_linewrap(Driver
*drvthis
, int on
);
175 static void serialPOS_autoscroll(Driver
*drvthis
, int on
);
176 static void serialPOS_cursorblink(Driver
*drvthis
, int on
);
177 static void serialPOS_cursor_goto(Driver
*drvthis
, int x
, int y
);
180 /* Parse one key from the configfile */
182 serialPOS_parse_keypad_setting (Driver
*drvthis
, char *keyname
, char default_value
)
188 s
= drvthis
->config_get_string(drvthis
->name
, keyname
, 0, NULL
);
190 strncpy(buf
, s
, sizeof(buf
));
191 buf
[sizeof(buf
)-1] = '\0';
194 return_val
= default_value
;
201 * Initialize the driver.
202 * \param drvthis Pointer to driver structure.
207 serialPOS_init (Driver
*drvthis
)
209 struct termios portset
;
211 char device
[256] = DEFAULT_DEVICE
;
212 int speed
= DEFAULT_SPEED
;
213 char size
[256] = DEFAULT_SIZE
;
219 /* Alocate and store private data */
220 p
= (PrivateData
*) malloc(sizeof(PrivateData
));
223 if (drvthis
->store_private_ptr(drvthis
, p
))
226 /* Initialise the PrivateData structure */
229 p
->width
= LCD_DEFAULT_WIDTH
;
230 p
->height
= LCD_DEFAULT_HEIGHT
;
231 p
->cellwidth
= LCD_DEFAULT_CELLWIDTH
;
232 p
->cellheight
= LCD_DEFAULT_CELLHEIGHT
;
235 p
->backingstore
= NULL
;
237 p
->output_state
= -1; /* static data from serialPOS_output */
242 p
->emulation_mode
= POS_AEDEX
;
244 debug(RPT_INFO
, "serialPOS: init(%p)", drvthis
);
246 /* READ CONFIG FILE */
248 /* Get serial device to use */
249 strncpy(device
, drvthis
->config_get_string(drvthis
->name
, "Device", 0, DEFAULT_DEVICE
), sizeof(device
));
250 device
[sizeof(device
)-1] = '\0';
251 report(RPT_INFO
, "%s: using Device %s", drvthis
->name
, device
);
253 /* Get emulation type */
254 strncpy(buf
, drvthis
->config_get_string(drvthis
->name
, "Type", 0, DEFAULT_TYPE
), sizeof(buf
));
255 buf
[sizeof(buf
)-1] = '\0';
256 if (strncasecmp(buf
, "IEE", 3) == 0) {
257 p
->emulation_mode
= POS_IEE
;
258 } else if (strncasecmp(buf
, "AED", 3) == 0) {
259 p
->emulation_mode
= POS_AEDEX
;
260 } else if (strncasecmp(buf
, "Eps", 3) == 0) {
261 p
->emulation_mode
= POS_Epson
;
262 } else if (strncasecmp(buf
, "Ema", 3) == 0) {
263 p
->emulation_mode
= POS_Emax
;
264 } else if (strncasecmp(buf
, "Log", 3) == 0) {
265 p
->emulation_mode
= POS_LogicControls
;
266 } else if (strncasecmp(buf
, "IBM", 3) == 0) {
267 p
->emulation_mode
= POS_IBM
;
268 } else if (strncasecmp(buf
, "Ult", 3) == 0) {
269 p
->emulation_mode
= POS_Ultimate
;
271 report(RPT_ERR
, "%s: unknown display Type %s; must be one of IEE, AEDEX, Epson, Emax, Logic Controls or Ultimate",
276 /* Get display size */
277 strncpy(size
, drvthis
->config_get_string(drvthis
->name
, "Size", 0, DEFAULT_SIZE
), sizeof(size
));
278 size
[sizeof(size
)-1] = '\0';
279 if ((sscanf(size
, "%dx%d", &w
, &h
) != 2)
280 || (w
<= 0) || (w
> LCD_MAX_WIDTH
)
281 || (h
<= 0) || (h
> LCD_MAX_HEIGHT
)) {
282 report(RPT_WARNING
, "%s: cannot read Size: %s; using default %s",
283 drvthis
->name
, size
, DEFAULT_SIZE
);
284 sscanf(DEFAULT_SIZE
, "%dx%d", &w
, &h
);
290 tmp
= drvthis
->config_get_int(drvthis
->name
, "Speed", 0, DEFAULT_SPEED
);
306 report(RPT_WARNING
, "%s: Speed must be 1200, 2400, 4800 or 9600; using default %d",
310 /* Set up io port correctly, and open it... */
311 p
->fd
= open(device
, O_RDWR
| O_NOCTTY
);
313 report(RPT_ERR
, "%s: open(%s) failed (%s)", drvthis
->name
, device
, strerror(errno
));
315 report(RPT_ERR
, "%s: %s device could not be opened...", drvthis
->name
, device
);
318 report(RPT_INFO
, "%s: opened display on %s", drvthis
->name
, device
);
320 tcgetattr(p
->fd
, &portset
);
322 // THIS ALL COMMENTED OUT BECAUSE WE NEED TO SET TIMEOUTS
323 /* We use RAW mode */
324 #ifdef HAVE_CFMAKERAW_NOT
329 portset
.c_iflag
&= ~( IGNBRK
| BRKINT
| PARMRK
| ISTRIP
330 | INLCR
| IGNCR
| ICRNL
| IXON
);
331 portset
.c_oflag
&= ~OPOST
;
332 portset
.c_lflag
&= ~( ECHO
| ECHONL
| ICANON
| ISIG
| IEXTEN
);
333 portset
.c_cflag
&= ~( CSIZE
| PARENB
| CRTSCTS
);
334 portset
.c_cflag
|= CS8
| CREAD
| CLOCAL
;
335 portset
.c_cc
[VMIN
] = 1;
336 portset
.c_cc
[VTIME
] = 3;
340 cfsetospeed(&portset
, speed
);
341 cfsetispeed(&portset
, B0
);
344 tcsetattr(p
->fd
, TCSANOW
, &portset
);
346 /* Make sure the frame buffer is there... */
347 p
->framebuf
= (unsigned char *) calloc(p
->width
* p
->height
, 1);
348 if (p
->framebuf
== NULL
) {
349 report(RPT_ERR
, "%s: unable to create framebuffer", drvthis
->name
);
352 memset(p
->framebuf
, ' ', p
->width
* p
->height
);
354 /* make sure the framebuffer backing store is there... */
355 p
->backingstore
= (unsigned char *) malloc(p
->width
* p
->height
);
356 if (p
->backingstore
== NULL
) {
357 report(RPT_ERR
, "%s: unable to create framebuffer backing store", drvthis
->name
);
360 memset(p
->backingstore
, ' ', p
->width
* p
->height
);
362 /* set initial LCD configuration */
363 serialPOS_hardware_clear(drvthis
);
364 serialPOS_linewrap(drvthis
, DEFAULT_LINEWRAP
);
365 serialPOS_autoscroll(drvthis
, DEFAULT_AUTOSCROLL
);
367 report(RPT_DEBUG
, "%s: init() done", drvthis
->name
);
374 * Close the driver (do necessary clean-up).
375 * \param drvthis Pointer to driver structure.
378 serialPOS_close (Driver
*drvthis
)
380 PrivateData
*p
= drvthis
->private_data
;
391 free(p
->backingstore
);
392 p
->backingstore
= NULL
;
396 drvthis
->store_private_ptr(drvthis
, NULL
);
397 debug(RPT_DEBUG
, "serialPOS: closed");
402 * Return the display width in characters.
403 * \param drvthis Pointer to driver structure.
404 * \return Number of characters the display is wide.
407 serialPOS_width (Driver
*drvthis
)
409 PrivateData
*p
= drvthis
->private_data
;
416 * Return the display height in characters.
417 * \param drvthis Pointer to driver structure.
418 * \return Number of characters the display is high.
421 serialPOS_height (Driver
*drvthis
)
423 PrivateData
*p
= drvthis
->private_data
;
430 * Return the width of a character in pixels.
431 * \param drvthis Pointer to driver structure.
432 * \return Number of pixel columns a character cell is wide.
435 MtxcOrb_cellwidth (Driver
*drvthis
)
437 PrivateData
*p
= drvthis
->private_data
;
444 * Return the height of a character in pixels.
445 * \param drvthis Pointer to driver structure.
446 * \return Number of pixel lines a character cell is high.
449 MtxcOrb_cellheight (Driver
*drvthis
)
451 PrivateData
*p
= drvthis
->private_data
;
453 return p
->cellheight
;
458 * Print a string on the screen at position (x,y).
459 * The upper-left corner is (1,1), the lower-right corner is (p->width, p->height).
460 * \param drvthis Pointer to driver structure.
461 * \param x Horizontal character position (column).
462 * \param y Vertical character position (row).
463 * \param string String that gets written.
466 serialPOS_string (Driver
*drvthis
, int x
, int y
, const char string
[])
468 PrivateData
*p
= drvthis
->private_data
;
471 /* Convert 1-based coords to 0-based... */
475 if ((y
< 0) || (y
>= p
->height
))
478 for (i
= 0; (string
[i
] != '\0') && (x
< p
->width
); i
++, x
++) {
479 /* Check for buffer overflows... */
481 p
->framebuf
[(y
* p
->width
) + x
] = string
[i
];
484 report(RPT_DEBUG
, "serialPOS: printed string at (%d,%d)", x
, y
);
489 * Clear the framebuffer.
490 * \param drvthis Pointer to driver structure.
493 serialPOS_clear (Driver
*drvthis
)
495 PrivateData
*p
= drvthis
->private_data
;
497 /* replace all chars in framebuf with spaces */
498 memset(p
->framebuf
, ' ', (p
->width
* p
->height
));
500 report(RPT_DEBUG
, "serialPOS: cleared framebuffer");
505 * Flush data on screen to the LCD.
506 * \param drvthis Pointer to driver structure.
509 serialPOS_flush (Driver
*drvthis
)
511 PrivateData
*p
= drvthis
->private_data
;
516 for (i
= 0; i
< p
->height
; i
++) {
517 // set pointers to start of the line in frame buffer & backing store
518 unsigned char *sp
= p
->framebuf
+ (i
* p
->width
);
519 unsigned char *sq
= p
->backingstore
+ (i
* p
->width
);
521 unsigned int length
= p
->width
+5;
525 debug(RPT_DEBUG
, "Framebuf: '%.*s'", p
->width
, sp
);
526 debug(RPT_DEBUG
, "Backingstore: '%.*s'", p
->width
, sq
);
529 * - not more than one update command per line
530 * - skip lines that are identical
533 // skip over identical lines
534 if ( memcmp(sp
, sq
, p
->width
) == 0) {
535 /* The lines are the same. */
539 /* there are differences, ... */
540 report(RPT_DEBUG
, "%s: l=%d string='%.*s'", __FUNCTION__
, i
, p
->width
, sp
);
542 if (p
->emulation_mode
== POS_AEDEX
) {
544 if ( i
== 0 && p
->hardscroll
== 1 )
545 command
= AEDEXContinuousScroll
;
547 snprintf(out
, length
, "%s%d%.*s%c", AEDEXPrefix
, command
, p
->width
, sp
, 13);
548 debug(RPT_DEBUG
, "%s%d%.*s%c", AEDEXPrefix
, command
, p
->width
, sp
, 13);
551 write(p
->fd
, out
, sizeof(out
));
558 memcpy(p
->backingstore
, p
->framebuf
, p
->width
* p
->height
);
561 report(RPT_DEBUG
, "serialPOS: frame buffer flushed");
566 * Print a character on the screen at position (x,y).
567 * The upper-left corner is (1,1), the lower-right corner is (p->width, p->height).
568 * \param drvthis Pointer to driver structure.
569 * \param x Horizontal character position (column).
570 * \param y Vertical character position (row).
571 * \param c Character that gets written.
574 serialPOS_chr (Driver
*drvthis
, int x
, int y
, char c
)
576 PrivateData
*p
= drvthis
->private_data
;
578 /* Convert 1-based coords to 0-based... */
582 /* The # character might interfere with the AEDEX command set */
583 if (p
->emulation_mode
== POS_AEDEX
&& c
== '#')
586 if ((x
>= 0) && (y
>= 0) && (x
< p
->width
) && (y
< p
->height
))
587 p
->framebuf
[(y
* p
->width
) + x
] = c
;
589 report(RPT_DEBUG
, "writing character %02X to position (%d,%d)", c
, x
, y
);
594 * Set output port(s).
595 * Displays with keypad have 6 outputs whereas the others only have one.
596 * \param drvthis Pointer to driver structure.
597 * \param state Integer with bits representing port states.
601 serialPOS_output (Driver
*drvthis
, int state
)
603 /* I don't get what this does. Many POS displays have a pass-through function. */
604 PrivateData
*p
= drvthis
->private_data
;
611 * Clear the LCD using its hardware command
612 * \param drvthis Pointer to driver structure.
615 serialPOS_hardware_clear (Driver
*drvthis
)
617 /* There is no hardware clear in the POS command sets,
618 but most have an easy software clear. */
619 /*PrivateData *p = drvthis->private_data;
623 if (p->emulation_mode == POS_AEDEX) {
624 snprintf(out, 6, "%s%c %d", AEDEXPrefix, AEDEXAllLineDisplay, 13);
627 write(p->fd, out, 5);*/
628 debug(RPT_DEBUG
, "serialPOS: cleared LCD");
633 * Turn the POS's built-in linewrapping feature on or off.
634 * \param drvthis Pointer to driver structure.
635 * \param on New state.
638 serialPOS_linewrap (Driver
*drvthis
, int on
)
640 PrivateData
*p
= drvthis
->private_data
;
644 debug(RPT_DEBUG
, "serialPOS: linewrap turned %s", (on
) ? "on" : "off");
649 * Turn the POS's built-in automatic scrolling feature on or off.
650 * \param drvthis Pointer to driver structure.
651 * \param on New state.
654 serialPOS_autoscroll (Driver
*drvthis
, int on
)
656 PrivateData
*p
= drvthis
->private_data
;
660 debug(RPT_DEBUG
, "serialPOS: autoscroll turned %s", (on
) ? "on" : "off");
665 * Turn POS's hardware cursor blinking on or off.
666 * \param drvthis Pointer to driver structure.
667 * \param on New state.
671 serialPOS_cursorblink (Driver
*drvthis
, int on
)
673 //PrivateData *p = drvthis->private_data;
675 debug(RPT_DEBUG
, "serialPOS: cursorblink turned %s", (on
) ? "on" : "off");
680 * Move cursor to position (x,y).
681 * \param drvthis Pointer to driver structure.
682 * \param x Horizontal character position (column).
683 * \param y Vertical character position (row).
686 serialPOS_cursor_goto(Driver
*drvthis
, int x
, int y
)
688 //PrivateData *p = drvthis->private_data;
693 * Provide general information about the LCD/VFD display.
694 * \param drvthis Pointer to driver structure.
695 * \return Constant string with information.
697 MODULE_EXPORT
const char *
698 serialPOS_get_info (Driver
*drvthis
)
700 PrivateData
*p
= drvthis
->private_data
;
701 strcpy(p
->info
, "Driver for Point of Sale Displays.");
707 * Draw a vertical bar bottom-up.
708 * \param drvthis Pointer to driver structure.
709 * \param x Horizontal character position (column) of the starting point.
710 * \param y Vertical character position (row) of the starting point.
711 * \param len Number of characters that the bar is high at 100%
712 * \param promille Current height level of the bar in promille.
713 * \param options Options (currently unused).
716 serialPOS_vbar (Driver
*drvthis
, int x
, int y
, int len
, int promille
, int options
)
718 PrivateData
*p
= drvthis
->private_data
;
720 char ascii_map
[] = { ' ', ' ', '-', '-', '=', '=', '%', '%' };
721 char *map
= ascii_map
;
722 int pixels
= ((long) 2 * len
* p
->cellheight
) * promille
/ 2000;
726 if ((x
<= 0) || (y
<= 0) || (x
> p
->width
))
729 /* x and y are the start position of the bar.
730 * The bar by default grows in the 'up' direction
731 * (other direction not yet implemented).
732 * len is the number of characters that the bar is long at 100%
733 * promille is the number of promilles (0..1000) that the bar should be filled.
736 for (pos
= 0; pos
< len
; pos
++) {
741 if (pixels
>= p
->cellheight
) {
742 /* write a "full" block to the screen... */
743 serialPOS_chr(drvthis
, x
, y
-pos
, '%');
745 else if (pixels
> 0) {
746 // write a partial block...
747 serialPOS_chr(drvthis
, x
, y
-pos
, map
[len
-1]);
751 ; // write nothing (not even a space)
754 pixels
-= p
->cellheight
;
760 * Draw a horizontal bar to the right.
761 * \param drvthis Pointer to driver structure.
762 * \param x Horizontal character position (column) of the starting point.
763 * \param y Vertical character position (row) of the starting point.
764 * \param len Number of characters that the bar is long at 100%
765 * \param promille Current length level of the bar in promille.
766 * \param options Options (currently unused).
769 serialPOS_hbar (Driver
*drvthis
, int x
, int y
, int len
, int promille
, int options
)
771 PrivateData
*p
= drvthis
->private_data
;
772 int pixels
= ((long) 2 * len
* p
->cellwidth
) * promille
/ 2000;
775 if ((x
<= 0) || (y
<= 0) || (y
> p
->height
))
778 /* x and y are the start position of the bar.
779 * The bar by default grows in the 'right' direction
780 * (other direction not yet implemented).
781 * len is the number of characters that the bar is long at 100%
782 * promille is the number of promilles (0..1000) that the bar should be filled.
785 for (pos
= 0; pos
< len
; pos
++) {
787 if (x
+ pos
> p
->width
)
790 if (pixels
>= p
->cellwidth
* 2/3) {
791 /* write a "full" block to the screen... */
792 serialPOS_chr(drvthis
, x
+pos
, y
, '=');
794 else if (pixels
> p
->cellwidth
* 1/3) {
795 /* write a partial block... */
796 serialPOS_chr(drvthis
, x
+pos
, y
, '-');
800 ; // write nothing (not even a space)
803 pixels
-= p
->cellwidth
;
809 * Write a big number to the screen.
810 * \param drvthis Pointer to driver structure.
811 * \param x Horizontal character position (column).
812 * \param num Character to write (0 - 10 with 10 representing ':')
815 serialPOS_num (Driver
*drvthis
, int x
, int num
)
817 PrivateData
*p
= drvthis
->private_data
;
820 if ((num
< 0) || (num
> 10))
823 if (p
->ccmode
!= bignum
) {
824 if (p
->ccmode
!= standard
) {
825 /* Not supported (yet) */
826 report(RPT_WARNING
, "%s: num: cannot combine two modes using user-defined characters",
836 // Lib_adv_bignum does everything needed to show the bignumbers.
837 //lib_adv_bignum(drvthis, x, num, 0, do_init);
842 * Get total number of custom characters available.
843 * \param drvthis Pointer to driver structure.
844 * \return Number of custom characters (always NUM_CCs).
847 serialPOS_get_free_chars (Driver
*drvthis
)
849 //PrivateData *p = drvthis->private_data;
856 * Define a custom character and write it to the LCD.
857 * \param drvthis Pointer to driver structure.
858 * \param n Custom character to define [0 - (NUM_CCs-1)].
859 * \param dat Array of 8(=cellheight) bytes, each representing a pixel row
860 * starting from the top to bottom.
861 * The bits in each byte represent the pixels where the LSB
862 * (least significant bit) is the rightmost pixel in each pixel row.
865 serialPOS_set_char (Driver
*drvthis
, int n
, unsigned char *dat
)
867 PrivateData
*p
= drvthis
->private_data
;
868 unsigned char mask
= (1 << p
->cellwidth
) - 1;
871 if ((n
< 0) || (n
>= NUM_CCs
))
876 out
[2] = n
; /* Custom char to define. xxx */
878 for (row
= 0; row
< p
->cellheight
; row
++) {
879 out
[row
+3] = dat
[row
] & mask
;
881 write(p
->fd
, out
, 11);
886 * Place an icon on the screen.
887 * \param drvthis Pointer to driver structure.
888 * \param x Horizontal character position (column).
889 * \param y Vertical character position (row).
890 * \param icon synbolic value representing the icon.
891 * \return Information whether the icon is handled here or needs to be handled by the server core.
894 serialPOS_icon (Driver
*drvthis
, int x
, int y
, int icon
)
896 //PrivateData *p = drvthis->private_data;
903 * Set cursor position and state.
904 * \param drvthis Pointer to driver structure.
905 * \param x Horizontal cursor position (column).
906 * \param y Vertical cursor position (row).
907 * \param state New cursor state.
910 serialPOS_cursor (Driver
*drvthis
, int x
, int y
, int state
)
912 //hPrivateData *p = (PrivateData *) drvthis->private_data;
914 /* set cursor state */
915 //serialPOS_cursor_goto(drvthis, x, y);
919 * Get key from the LCD/VFD.
920 * \param drvthis Pointer to driver structure.
921 * \return String representation of the key.
924 MODULE_EXPORT
const char *
925 serialPOS_get_key (Driver
*drvthis
)
927 PrivateData
*p
= drvthis
->private_data
;
929 struct pollfd fds
[1];
931 /* don't query the keyboard if there are no mapped keys; see \todo above */
932 if ((p
->keys
== 0) && (!p
->keypad_test_mode
))
935 /* poll for data or return */
937 fds
[0].events
= POLLIN
;
940 if (fds
[0].revents
== 0)
943 (void) read(p
->fd
, &key
, 1);
944 report(RPT_DEBUG
, "%s: get_key: key 0x%02X", drvthis
->name
, key
);
949 if (!p
->keypad_test_mode
) {
950 /* we assume standard key mapping here */
951 if ((key
>= 'A') && (key
<= 'A' + MAX_KEY_MAP
)) {
952 return p
->keymap
[key
-'A'];
955 report(RPT_INFO
, "%s: Untreated key 0x%02X", drvthis
->name
, key
);
960 fprintf(stdout
, "serialPOS: Received character %c\n", key
);
961 fprintf(stdout
, "serialPOS: Press another key of your device.\n");