Ticket #124: IRLCD.diff

File IRLCD.diff, 14.4 kB (added by jp@…, 4 months ago)

Driver for IRLCD (AKA USBTiny IRLCD)

  • drivers.m4

     
    3333  [                        (try 'all,\!<driver>' if your shell complains...)]  
    3434  [                        possible drivers are:]  
    3535  [                        BeckmannEgle, BWCT, CrystalFontz, Curses, Cwlinux,] 
    36   [                        G15, HD44780, LCD2USB LCDLinux, LCDTerm, LPH7508,] 
     36  [                        G15, HD44780, IRLCD, LCD2USB LCDLinux, LCDTerm, LPH7508,] 
    3737  [                        LUIse, M50530, MatrixOrbital, MilfordInstruments,] 
    3838  [                        Noritake, NULL, PNG, PPM, picoLCD, RouterBoard, Sample,] 
    3939  [                        serdisplib, SimpleLCD, T6963, Trefon, USBLCD,] 
     
    6666         EA232graphic="yes" 
    6767         G15="yes" 
    6868         HD44780="yes" 
     69   IRLCD="yes" 
    6970         LCD2USB="yes" 
    7071   LCDLINUX="yes" 
    7172         LCDTERM="yes" 
     
    118119      HD44780-I2C) 
    119120         HD44780_I2C=$val 
    120121   ;; 
     122      IRLCD) 
     123         IRLCD=$val 
     124         ;; 
    121125      LCD2USB) 
    122126         LCD2USB=$val 
    123127         ;; 
     
    300304   AC_DEFINE(WITH_HD44780,1,[HD44780 driver]) 
    301305fi 
    302306 
     307if test "$IRLCD" = "yes"; then 
     308   if test "$has_usb" = "true"; then 
     309      TEXT="yes" 
     310      SERIAL="yes" 
     311      DRIVERS="$DRIVERS drv_IRLCD.o" 
     312      LIBUSB="yes" 
     313      AC_DEFINE(WITH_IRLCD,1,[IRLCD driver]) 
     314   else 
     315      AC_MSG_WARN(usb.h not found: LCD2USB driver disabled) 
     316   fi 
     317fi 
     318 
    303319if test "$LCD2USB" = "yes"; then 
    304320   if test "$has_usb" = "true"; then 
    305321      TEXT="yes" 
  • drv.c

     
    5656extern DRIVER drv_G15; 
    5757extern DRIVER drv_HD44780; 
    5858extern DRIVER drv_Image; 
     59extern DRIVER drv_IRLCD; 
    5960extern DRIVER drv_LCD2USB; 
    6061extern DRIVER drv_LCDLinux; 
    6162extern DRIVER drv_LCDTerm; 
     
    113114#if (defined (WITH_PNG) || defined(WITH_PPM)) && defined(WITH_GD) 
    114115    &drv_Image, 
    115116#endif 
     117#ifdef WITH_IRLCD 
     118    &drv_IRLCD, 
     119#endif 
    116120#ifdef WITH_LCD2USB 
    117121    &drv_LCD2USB, 
    118122#endif 
  • drv_IRLCD.c

     
     1/* $Id: drv_IRLCD.c 773 2008-07-14 12:00:00Z jpcivade $ 
     2 * $URL: https://ssl.bulix.org/svn/lcd4linux/branches/0.10.1/drv_IRLCD.c $ 
     3 * 
     4 ************************************************************************** 
     5 * Driver for IRLCD : simple USB1.1 LCD + IR Receiver based on ATtiny2313 * 
     6 ************************************************************************** 
     7 * Hardware from http://www.xs4all.nl/~dicks/avr/usbtiny/index.html :     * 
     8 *        [USBtiny LIRC compatible IR receiver and LCD controller]        * 
     9 * Ths driver is based on LCD2USB software by Till Harbaum, adapted to    * 
     10 * USBTiny protocol by Jean-Philippe Civade                               * 
     11 ************************************************************************** 
     12 * 
     13 * The IR receiving par is compatible with IgrPlug protocol 
     14 * and can be used from LIRC. 
     15 * 
     16 * Copyright (C) 2008 Jean-Philippe Civade <jp@civade.com> (for porting to IRLCD) 
     17 * Copyright (C) 2005 Till Harbaum <till@harbaum.org> (for LCD2USB friver) 
     18 * Copyright (C) 2005, 2006, 2007, 2008 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net> 
     19 * 
     20 * This file is part of LCD4Linux. 
     21 * 
     22 * LCD4Linux is free software; you can redistribute it and/or modify 
     23 * it under the terms of the GNU General Public License as published by 
     24 * the Free Software Foundation; either version 2, or (at your option) 
     25 * any later version. 
     26 * 
     27 * LCD4Linux is distributed in the hope that it will be useful, 
     28 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
     29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
     30 * GNU General Public License for more details. 
     31 * 
     32 * You should have received a copy of the GNU General Public License 
     33 * along with this program; if not, write to the Free Software 
     34 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
     35 * 
     36 */ 
    137 
     38/*  
     39 * 
     40 * exported fuctions: 
     41 * 
     42 * struct DRIVER drv_IRLCD 
     43 * 
     44 */ 
     45 
     46#include "config.h" 
     47 
     48#include <stdlib.h> 
     49#include <stdio.h> 
     50#include <unistd.h> 
     51#include <string.h> 
     52#include <errno.h> 
     53#include <termios.h> 
     54#include <fcntl.h> 
     55#include <ctype.h> 
     56#include <sys/ioctl.h> 
     57#include <sys/time.h> 
     58 
     59#include <usb.h> 
     60 
     61#include "debug.h" 
     62#include "cfg.h" 
     63#include "qprintf.h" 
     64#include "udelay.h" 
     65#include "plugin.h" 
     66#include "widget.h" 
     67#include "widget_text.h" 
     68#include "widget_icon.h" 
     69#include "widget_bar.h" 
     70#include "drv.h" 
     71 
     72/* text mode display? */ 
     73#include "drv_generic_text.h" 
     74 
     75/* vid/pid of IRLCD */ 
     76#define LCD_USB_VENDOR 0x03EB // for Atmel device 
     77#define LCD_USB_DEVICE 0x0002 
     78 
     79/* Protocole IR/LCD */  
     80#define LCD_INSTR      20 
     81#define LCD_DATA       21 
     82 
     83static char Name[] = "IRLCD"; 
     84static char *device_id = NULL, *bus_id = NULL; 
     85 
     86static usb_dev_handle *lcd; 
     87 
     88extern int usb_debug; 
     89extern int got_signal; 
     90 
     91/****************************************/ 
     92/***  hardware dependant functions    ***/ 
     93/****************************************/ 
     94 
     95static int drv_IRLCD_open(char *bus_id, char *device_id) 
     96{ 
     97    struct usb_bus *busses, *bus; 
     98    struct usb_device *dev; 
     99 
     100    lcd = NULL; 
     101 
     102    info("%s: scanning USB for IRLCD interface ...", Name); 
     103 
     104    if (bus_id != NULL) 
     105  info("%s: scanning for bus id: %s", Name, bus_id); 
     106 
     107    if (device_id != NULL) 
     108  info("%s: scanning for device id: %s", Name, device_id); 
     109 
     110    usb_debug = 0; 
     111 
     112    usb_init(); 
     113    usb_find_busses(); 
     114    usb_find_devices(); 
     115    busses = usb_get_busses(); 
     116 
     117    for (bus = busses; bus; bus = bus->next) { 
     118  /* search this bus if no bus id was given or if this is the given bus id */ 
     119  if (!bus_id || (bus_id && !strcasecmp(bus->dirname, bus_id))) { 
     120 
     121      for (dev = bus->devices; dev; dev = dev->next) { 
     122    /* search this device if no device id was given or if this is the given device id */ 
     123    if (!device_id || (device_id && !strcasecmp(dev->filename, device_id))) { 
     124 
     125        if ((dev->descriptor.idVendor == LCD_USB_VENDOR) && (dev->descriptor.idProduct == LCD_USB_DEVICE)) { 
     126      info("%s: found IRLCD interface on bus %s device %s", Name, bus->dirname, dev->filename); 
     127      lcd = usb_open(dev); 
     128      if (usb_claim_interface(lcd, 0) < 0) { 
     129          error("%s: usb_claim_interface() failed!", Name); 
     130          return -1; 
     131      } 
     132      return 0; 
     133        } 
     134    } 
     135      } 
     136  } 
     137    } 
     138    return -1; 
     139} 
     140 
     141 
     142static int drv_IRLCD_close(void) 
     143{ 
     144    usb_release_interface(lcd, 0); 
     145    usb_close(lcd); 
     146 
     147    return 0; 
     148} 
     149 
     150 
     151// Send a buffer to lcd via a control message 
     152static int drv_IRLCD_send(int request, unsigned char *buffer, int size) 
     153{ 
     154    if (usb_control_msg( 
     155      lcd,  
     156      USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT,  // bRequestType  
     157      request,      // bRequest (LCD_INSTR / LCD_DATA) 
     158      0,          // wValue (0) 
     159      0,          // wIndex (0) 
     160      (char *)buffer,   // pointer to destination buffer 
     161      size,         // wLength 
     162      1000) < 0) {    // Timeout in millisectonds 
     163  error("%s: USB request failed! Trying to reconnect device.", Name); 
     164 
     165  usb_release_interface(lcd, 0); 
     166  usb_close(lcd); 
     167 
     168  /* try to close and reopen connection */ 
     169  if (drv_IRLCD_open(bus_id, device_id) < 0) { 
     170      error("%s: could not re-detect IRLCD USB LCD", Name); 
     171      got_signal = -1; 
     172      return -1; 
     173  } 
     174  /* and try to re-send command */ 
     175  if (usb_control_msg( 
     176      lcd,  
     177      USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT,  // bRequestType  
     178      request,      // bRequest (LCD_INSTR / LCD_DATA) 
     179      0,          // wValue (0) 
     180      0,          // wIndex (0) 
     181      (char *)buffer,   // pointer to destination buffer 
     182      size,         // wLength 
     183      1000) < 0) {    // Timeout in millisectonds 
     184      error("%s: retried USB request failed, aborting!", Name); 
     185      got_signal = -1; 
     186      return -1; 
     187  } 
     188 
     189  info("%s: Device successfully reconnected.", Name); 
     190    } 
     191 
     192    return 0; 
     193} 
     194 
     195 
     196/* text mode displays only */ 
     197static void drv_IRLCD_clear(void) 
     198{ 
     199    char cmd[1]; 
     200 
     201    /* do whatever is necessary to clear the display */ 
     202    /* assume 0x01 to be a 'clear display' command */ 
     203    cmd[0] = 0x01; /* clear */ 
     204    drv_IRLCD_send(LCD_INSTR, cmd, 1); 
     205  cmd[0] = 0x03; /* home */ 
     206    drv_IRLCD_send(LCD_INSTR, cmd, 1); 
     207} 
     208 
     209 
     210/* text mode displays only */ 
     211static void drv_IRLCD_write(const int row, const int col, const char *data, int len) 
     212{ 
     213    char cmd[1]; 
     214  static int pos; 
     215 
     216  // for 2 lines display 
     217  pos = (row % 2) * 64 + (row / 2) * 20 + col; 
     218 
     219    /* do the cursor positioning here */ 
     220    cmd[0] = 0x80 | pos; 
     221 
     222  // do positionning 
     223    drv_IRLCD_send(LCD_INSTR, cmd, 1); 
     224 
     225    /* send string to the display */ 
     226    drv_IRLCD_send(LCD_DATA, (unsigned char *)data, len); 
     227 
     228} 
     229 
     230/* text mode displays only */ 
     231static void drv_IRLCD_defchar(const int ascii, const unsigned char *matrix) 
     232{ 
     233    char cmd[10]; 
     234    int i; 
     235 
     236    /* Write to CGRAM */ 
     237    cmd[0] = 0x40 | 8 * ascii; 
     238    drv_IRLCD_send(LCD_INSTR, cmd, 1); 
     239     
     240 
     241    /* send bitmap to the display */ 
     242    for (i = 0; i < 8; i++) { 
     243  cmd[i] = matrix[i] & 0x1f; 
     244    } 
     245    drv_IRLCD_send(LCD_DATA, cmd, 8); 
     246} 
     247 
     248 
     249/* start text mode display */ 
     250static int drv_IRLCD_start(const char *section) 
     251{ 
     252    int rows = -1, cols = -1; 
     253    char *s; 
     254 
     255    s = cfg_get(section, "Size", NULL); 
     256    if (s == NULL || *s == '\0') { 
     257  error("%s: no '%s.Size' entry from %s", Name, section, cfg_source()); 
     258  return -1; 
     259    } 
     260    if (sscanf(s, "%dx%d", &cols, &rows) != 2 || rows < 1 || cols < 1) { 
     261  error("%s: bad %s.Size '%s' from %s", Name, section, s, cfg_source()); 
     262  free(s); 
     263  return -1; 
     264    } 
     265 
     266    DROWS = rows; 
     267    DCOLS = cols; 
     268 
     269    /* bus id and device id are strings and not just intergers, since */ 
     270    /* the windows port of libusb treats them as strings. And this way */ 
     271    /* we keep windows compatibility ... just in case ... */ 
     272    bus_id = cfg_get(section, "Bus", NULL); 
     273    device_id = cfg_get(section, "Device", NULL); 
     274 
     275    if (drv_IRLCD_open(bus_id, device_id) < 0) { 
     276  error("%s: could not find a IRLC USB LCD", Name); 
     277  return -1; 
     278    } 
     279 
     280    /* reset & initialize display */ 
     281    drv_IRLCD_clear();    /* clear display */ 
     282 
     283    return 0; 
     284} 
     285 
     286 
     287/****************************************/ 
     288/***            plugins               ***/ 
     289/****************************************/ 
     290/* no plugins capabilities */ 
     291 
     292/****************************************/ 
     293/***        widget callbacks          ***/ 
     294/****************************************/ 
     295/* using drv_generic_text_draw(W) */ 
     296/* using drv_generic_text_icon_draw(W) */ 
     297/* using drv_generic_text_bar_draw(W) */ 
     298/* using drv_generic_gpio_draw(W) */ 
     299 
     300 
     301/****************************************/ 
     302/***        exported functions        ***/ 
     303/****************************************/ 
     304 
     305/* list models */ 
     306int drv_IRLCD_list(void) 
     307{ 
     308    printf("generic"); 
     309    return 0; 
     310} 
     311 
     312/* initialize driver & display */ 
     313int drv_IRLCD_init(const char *section, const int quiet) 
     314{ 
     315    WIDGET_CLASS wc; 
     316    int asc255bug; 
     317    int ret; 
     318 
     319    info("%s: %s", Name, "$Rev: 773 $"); 
     320 
     321    /* display preferences */ 
     322    XRES = 5;     /* pixel width of one char  */ 
     323    YRES = 8;     /* pixel height of one char  */ 
     324    CHARS = 8;      /* number of user-defineable characters */ 
     325    CHAR0 = 0;      /* ASCII of first user-defineable char */ 
     326    GOTO_COST = 2;    /* number of bytes a goto command requires */ 
     327 
     328    /* real worker functions */ 
     329    drv_generic_text_real_write = drv_IRLCD_write; 
     330    drv_generic_text_real_defchar = drv_IRLCD_defchar; 
     331 
     332    /* start display */ 
     333    if ((ret = drv_IRLCD_start(section)) != 0) 
     334  return ret; 
     335 
     336    if (!quiet) { 
     337    char buffer[40]; 
     338    qprintf(buffer, sizeof(buffer), "%s %dx%d", Name, DCOLS, DROWS); 
     339    if (drv_generic_text_greet(buffer, " www.civade.com")) { 
     340      sleep(3); 
     341      drv_IRLCD_clear(); 
     342      } 
     343    } 
     344 
     345    /* initialize generic text driver */ 
     346    if ((ret = drv_generic_text_init(section, Name)) != 0) 
     347  return ret; 
     348 
     349    /* initialize generic icon driver */ 
     350    if ((ret = drv_generic_text_icon_init()) != 0) 
     351  return ret; 
     352 
     353    /* initialize generic bar driver */ 
     354    if ((ret = drv_generic_text_bar_init(0)) != 0) 
     355  return ret; 
     356 
     357    /* add fixed chars to the bar driver */ 
     358    /* most displays have a full block on ascii 255, but some have kind of  */ 
     359    /* an 'inverted P'. If you specify 'asc255bug 1 in the config, this */ 
     360    /* char will not be used, but rendered by the bar driver */ 
     361    cfg_number(section, "asc255bug", 0, 0, 1, &asc255bug); 
     362    drv_generic_text_bar_add_segment(0, 0, 255, 32);  /* ASCII  32 = blank */ 
     363    if (!asc255bug) 
     364  drv_generic_text_bar_add_segment(255, 255, 255, 255); /* ASCII 255 = block */ 
     365 
     366    /* register text widget */ 
     367    wc = Widget_Text; 
     368    wc.draw = drv_generic_text_draw; 
     369    widget_register(&wc); 
     370 
     371    /* register icon widget */ 
     372    wc = Widget_Icon; 
     373    wc.draw = drv_generic_text_icon_draw; 
     374    widget_register(&wc); 
     375 
     376    /* register bar widget */ 
     377    wc = Widget_Bar; 
     378    wc.draw = drv_generic_text_bar_draw; 
     379    widget_register(&wc); 
     380 
     381    return 0; 
     382} 
     383 
     384 
     385/* close driver & display */ 
     386/* use this function for a text display */ 
     387int drv_IRLCD_quit(const int quiet) 
     388{ 
     389 
     390    info("%s: shutting down.", Name); 
     391 
     392    drv_generic_text_quit(); 
     393 
     394    /* clear display */ 
     395    drv_IRLCD_clear(); 
     396 
     397    /* say goodbye... */ 
     398    if (!quiet) { 
     399  drv_generic_text_greet("goodbye!", NULL); 
     400    } 
     401 
     402    debug("closing usb connection"); 
     403    drv_IRLCD_close(); 
     404 
     405    return (0); 
     406} 
     407 
     408/* use this one for a text display */ 
     409DRIVER drv_IRLCD = { 
     410    .name = Name, 
     411    .list = drv_IRLCD_list, 
     412    .init = drv_IRLCD_init, 
     413    .quit = drv_IRLCD_quit, 
     414}; 
  • lcd4linux.conf.sample

     
    4141    UseBusy 0 
    4242} 
    4343 
     44Display IRLCD { 
     45    Driver 'IRLCD' 
     46    Size '16x2' 
     47    Backlight 0 
     48    Icons 1 
     49} 
     50 
    4451Display LCD2USB { 
    4552    Driver 'LCD2USB' 
    4653    Size '20x2' 
     
    11991206#Display 'T6963-240x128' 
    12001207#Display 'T6963-240x128D' 
    12011208#Display 'XWindow' 
     1209#Display 'IRLCD' 
    12021210#Display 'USBLCD' 
    12031211#Display 'BWCT' 
    12041212#Display 'Image' 
  • Makefile.am

     
    7676drv_G15.c                     \ 
    7777drv_HD44780.c                 \ 
    7878drv_Image.c                   \ 
     79drv_IRLCD.c                   \ 
    7980drv_LCD2USB.c                 \ 
    8081drv_LCDLinux.c                \ 
    8182drv_LCDTerm.c                 \