root/trunk/drv_picoLCD.c

Revision 899, 10.6 kB (checked in by bwalle, 6 weeks ago)

Replace write to external variable usb_debug by calling usb_set_debug().
This fixes build on openSUSE Factory.

  • Property svn:keywords set to Id URL Rev
Line 
1/* $Id$
2 * $URL$
3 *
4 * driver for picoLCD displays from mini-box.com
5 *
6 * Copyright (C) 2005 Michael Reinelt <michael@reinelt.co.at>
7 * Copyright (C) 2005, 2006, 2007 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
8 *
9 * Copyright (C) 2007 Nicu Pavel, Mini-Box.com <npavel@mini-box.com>
10 *
11 * This file is part of LCD4Linux.
12 *
13 * LCD4Linux is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2, or (at your option)
16 * any later version.
17 *
18 * LCD4Linux is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 *
27 */
28
29/*
30 *
31 * exported fuctions:
32 *
33 * struct DRIVER drv_picoLCD
34 *
35 */
36
37#include "config.h"
38
39#include <stdlib.h>
40#include <stdio.h>
41#include <string.h>
42#include <errno.h>
43#include <unistd.h>
44#include <termios.h>
45#include <fcntl.h>
46#include <sys/ioctl.h>
47#include <sys/time.h>
48
49#include <usb.h>
50
51#include "debug.h"
52#include "cfg.h"
53#include "qprintf.h"
54#include "udelay.h"
55#include "plugin.h"
56#include "widget.h"
57#include "widget_text.h"
58#include "widget_icon.h"
59#include "widget_bar.h"
60#include "drv.h"
61#include "drv_generic_text.h"
62#include "drv_generic_gpio.h"
63#include "drv_generic_keypad.h"
64
65
66
67#define picoLCD_VENDOR  0x04d8
68#define picoLCD_DEVICE  0x0002
69
70static char Name[] = "picoLCD";
71
72static unsigned int gpo = 0;
73
74static char *Buffer;
75static char *BufPtr;
76
77static usb_dev_handle *lcd;
78
79
80
81/****************************************/
82/***  hardware dependant functions    ***/
83/****************************************/
84
85static int drv_pL_open(void)
86{
87    struct usb_bus *busses, *bus;
88    struct usb_device *dev;
89    char driver[1024];
90    char product[1024];
91    char manufacturer[1024];
92    char serialnumber[1024];
93    int ret;
94
95    lcd = NULL;
96
97    info("%s: scanning for picoLCD...", Name);
98
99    usb_set_debug(0);
100
101    usb_init();
102    usb_find_busses();
103    usb_find_devices();
104    busses = usb_get_busses();
105
106    for (bus = busses; bus; bus = bus->next) {
107  for (dev = bus->devices; dev; dev = dev->next) {
108      if ((dev->descriptor.idVendor == picoLCD_VENDOR) && (dev->descriptor.idProduct == picoLCD_DEVICE)) {
109
110    info("%s: found picoLCD on bus %s device %s", Name, bus->dirname, dev->filename);
111
112    lcd = usb_open(dev);
113
114    ret = usb_get_driver_np(lcd, 0, driver, sizeof(driver));
115
116    if (ret == 0) {
117        info("%s: interface 0 already claimed by '%s'", Name, driver);
118        info("%s: attempting to detach driver...", Name);
119        if (usb_detach_kernel_driver_np(lcd, 0) < 0) {
120      error("%s: usb_detach_kernel_driver_np() failed!", Name);
121      return -1;
122        }
123    }
124
125    usb_set_configuration(lcd, 1);
126    usleep(100);
127
128    if (usb_claim_interface(lcd, 0) < 0) {
129        error("%s: usb_claim_interface() failed!", Name);
130        return -1;
131    }
132
133    usb_set_altinterface(lcd, 0);
134
135    usb_get_string_simple(lcd, dev->descriptor.iProduct, product, sizeof(product));
136    usb_get_string_simple(lcd, dev->descriptor.iManufacturer, manufacturer, sizeof(manufacturer));
137    usb_get_string_simple(lcd, dev->descriptor.iSerialNumber, serialnumber, sizeof(serialnumber));
138
139    info("%s: Manufacturer='%s' Product='%s' SerialNumber='%s'", Name, manufacturer, product, serialnumber);
140
141    return 0;
142      }
143  }
144    }
145    error("%s: could not find a picoLCD", Name);
146    return -1;
147}
148
149
150static int drv_pL_close(void)
151{
152    usb_release_interface(lcd, 0);
153    usb_close(lcd);
154
155    return 0;
156}
157
158
159static void drv_pL_send(unsigned char *data, int size)
160{
161    usb_interrupt_write(lcd, USB_ENDPOINT_OUT + 1, (char *) data, size, 1000);
162}
163
164static int drv_pL_read(unsigned char *data, int size)
165{
166    return usb_interrupt_read(lcd, USB_ENDPOINT_OUT + 1, (char *) data, size, 1000);
167}
168
169
170
171static void drv_pL_clear(void)
172{
173    unsigned char cmd[1] = { 0x94 };  /* clear display */
174    drv_pL_send(cmd, 1);
175}
176
177static int drv_pL_contrast(int contrast)
178{
179    unsigned char cmd[2] = { 0x92 };  /* set contrast */
180
181    if (contrast < 0)
182  contrast = 0;
183    if (contrast > 255)
184  contrast = 255;
185
186    cmd[1] = contrast;
187    drv_pL_send(cmd, 2);
188
189    return contrast;
190}
191
192
193static int drv_pL_backlight(int backlight)
194{
195    unsigned char cmd[2] = { 0x91 };  /* set backlight */
196
197    if (backlight < 0)
198  backlight = 0;
199    if (backlight > 1)
200  backlight = 1;
201
202    cmd[1] = backlight;
203    drv_pL_send(cmd, 2);
204
205    return backlight;
206}
207
208#define _USBLCD_MAX_DATA_LEN          24
209#define IN_REPORT_KEY_STATE           0x11
210static int drv_pL_gpi(int num)
211{
212    int ret;
213    unsigned char read_packet[_USBLCD_MAX_DATA_LEN];
214    ret = drv_pL_read(read_packet, _USBLCD_MAX_DATA_LEN);
215    if ((ret > 0) && (read_packet[0] == IN_REPORT_KEY_STATE)) {
216  debug("picoLCD: pressed key= 0x%02x\n", read_packet[1]);
217  return read_packet[1];
218    }
219    return 0;
220}
221
222static int drv_pL_gpo(int num, int val)
223{
224    unsigned char cmd[2] = { 0x81 };  /* set GPO */
225
226    if (num < 0)
227  num = 0;
228    if (num > 7)
229  num = 7;
230
231    if (val < 0)
232  val = 0;
233    if (val > 1)
234  val = 1;
235
236    /* set led bit to 1 or 0 */
237    if (val)
238  gpo |= 1 << num;
239    else
240  gpo &= ~(1 << num);
241
242    cmd[1] = gpo;
243    drv_pL_send(cmd, 2);
244
245    return val;
246}
247
248
249static void drv_pL_write(const int row, const int col, const char *data, int len)
250{
251    unsigned char cmd[64];
252    int i;
253
254    cmd[0] = 0x98;    /* goto/write */
255    cmd[1] = row;
256    cmd[2] = col;
257    cmd[3] = len;
258
259    i = 4;
260    while (len--) {
261  cmd[i++] = *data++;
262    }
263
264    drv_pL_send(cmd, i);
265}
266
267static void drv_pL_defchar(const int ascii, const unsigned char *matrix)
268{
269    unsigned char cmd[10] = { 0x9c }; /* define character */
270    int i;
271
272    cmd[1] = ascii;
273    for (i = 0; i < 8; i++) {
274  cmd[i + 2] = *matrix++ & 0x1f;
275    }
276
277    drv_pL_send(cmd, 10);
278}
279
280
281static int drv_pL_start(const char *section, const int quiet)
282{
283    int rows = -1, cols = -1;
284    int value;
285    char *s;
286
287    s = cfg_get(section, "Size", NULL);
288    if (s == NULL || *s == '\0') {
289  error("%s: no '%s.Size' entry from %s", Name, section, cfg_source());
290  return -1;
291    }
292    if (sscanf(s, "%dx%d", &cols, &rows) != 2 || rows < 1 || cols < 1) {
293  error("%s: bad %s.Size '%s' from %s", Name, section, s, cfg_source());
294  free(s);
295  return -1;
296    }
297
298    DROWS = rows;
299    DCOLS = cols;
300
301    if (drv_pL_open() < 0) {
302  return -1;
303    }
304
305    /* Init the command buffer */
306    Buffer = (char *) malloc(1024);
307    if (Buffer == NULL) {
308  error("%s: coommand buffer could not be allocated: malloc() failed", Name);
309  return -1;
310    }
311    BufPtr = Buffer;
312
313    if (cfg_number(section, "Contrast", 0, 0, 255, &value) > 0) {
314  info("Setting contrast to %d", value);
315  drv_pL_contrast(value);
316    }
317
318    if (cfg_number(section, "Backlight", 0, 0, 1, &value) > 0) {
319  info("Setting backlight to %d", value);
320  drv_pL_backlight(value);
321    }
322
323    drv_pL_clear();   /* clear display */
324
325    if (!quiet) {
326  char buffer[40];
327  qprintf(buffer, sizeof(buffer), "%s %dx%d", Name, DCOLS, DROWS);
328  if (drv_generic_text_greet(buffer, "http://www.picolcd.com")) {
329      sleep(3);
330      drv_pL_clear();
331  }
332    }
333
334    return 0;
335}
336
337
338/****************************************/
339/***            plugins               ***/
340/****************************************/
341
342static void plugin_contrast(RESULT * result, RESULT * arg1)
343{
344    double contrast;
345
346    contrast = drv_pL_contrast(R2N(arg1));
347    SetResult(&result, R_NUMBER, &contrast);
348}
349
350static void plugin_backlight(RESULT * result, RESULT * arg1)
351{
352    double backlight;
353
354    backlight = drv_pL_backlight(R2N(arg1));
355    SetResult(&result, R_NUMBER, &backlight);
356}
357
358static void plugin_gpo(RESULT * result, RESULT * argv[])
359{
360    double gpo;
361    gpo = drv_pL_gpo(R2N(argv[0]), R2N(argv[1]));
362    SetResult(&result, R_NUMBER, &gpo);
363}
364
365/****************************************/
366/***        widget callbacks          ***/
367/****************************************/
368
369
370/* using drv_generic_text_draw(W) */
371/* using drv_generic_text_icon_draw(W) */
372/* using drv_generic_text_bar_draw(W) */
373
374
375/****************************************/
376/***        exported functions        ***/
377/****************************************/
378
379
380/* list models */
381int drv_pL_list(void)
382{
383    printf("generic");
384    return 0;
385}
386
387
388/* initialize driver & display */
389int drv_pL_init(const char *section, const int quiet)
390{
391    WIDGET_CLASS wc;
392    int ret;
393
394    info("%s: %s", Name, "$Rev$");
395
396    /* display preferences */
397    XRES = 5;     /* pixel width of one char  */
398    YRES = 8;     /* pixel height of one char  */
399    CHARS = 8;      /* number of user-defineable characters */
400    CHAR0 = 0;      /* ASCII of first user-defineable char */
401    GPOS = 8;
402    GPIS = 1;
403    INVALIDATE = 1;
404    GOTO_COST = 2;    /* number of bytes a goto command requires */
405
406    /* real worker functions */
407    drv_generic_text_real_write = drv_pL_write;
408    drv_generic_text_real_defchar = drv_pL_defchar;
409    drv_generic_gpio_real_set = drv_pL_gpo;
410    drv_generic_gpio_real_get = drv_pL_gpi;
411
412    /* start display */
413    if ((ret = drv_pL_start(section, quiet)) != 0)
414  return ret;
415
416    /* initialize generic text driver */
417    if ((ret = drv_generic_text_init(section, Name)) != 0)
418  return ret;
419
420    /* initialize generic icon driver */
421    if ((ret = drv_generic_text_icon_init()) != 0)
422  return ret;
423
424    /* initialize generic bar driver */
425    if ((ret = drv_generic_text_bar_init(0)) != 0)
426  return ret;
427
428    drv_generic_text_bar_add_segment(0, 0, 255, 32);
429
430    /* GPO's init */
431    if ((ret = drv_generic_gpio_init(section, Name)) != 0)
432  return ret;
433
434    /* register text widget */
435    wc = Widget_Text;
436    wc.draw = drv_generic_text_draw;
437    widget_register(&wc);
438
439    /* register icon widget */
440    wc = Widget_Icon;
441    wc.draw = drv_generic_text_icon_draw;
442    widget_register(&wc);
443
444    /* register bar widget */
445    wc = Widget_Bar;
446    wc.draw = drv_generic_text_bar_draw;
447    widget_register(&wc);
448
449    /* register plugins */
450    AddFunction("LCD::contrast", -1, plugin_contrast);
451    AddFunction("LCD::backlight", -1, plugin_backlight);
452    AddFunction("LCD::gpo", -1, plugin_gpo);
453
454    return 0;
455}
456
457
458/* close driver & display */
459int drv_pL_quit(const int quiet)
460{
461
462    info("%s: shutting down.", Name);
463
464    drv_generic_text_quit();
465
466    /* clear display */
467    drv_pL_clear();
468
469    /* say goodbye... */
470    if (!quiet) {
471  drv_generic_text_greet("goodbye!", NULL);
472    }
473
474    drv_pL_close();
475
476    if (Buffer) {
477  free(Buffer);
478  Buffer = NULL;
479  BufPtr = Buffer;
480    }
481
482    return (0);
483}
484
485
486DRIVER drv_picoLCD = {
487    .name = Name,
488    .list = drv_pL_list,
489    .init = drv_pL_init,
490    .quit = drv_pL_quit,
491};
Note: See TracBrowser for help on using the browser.