~ubuntu-branches/ubuntu/natty/pd-zexy/natty

« back to all changes in this revision

Viewing changes to src/lpt.c

  • Committer: Bazaar Package Importer
  • Author(s): Jonas Smedegaard, IOhannes m zmölnig, Jonas Smedegaard
  • Date: 2010-08-20 12:17:41 UTC
  • mfrom: (2.1.2 sid)
  • Revision ID: james.westby@ubuntu.com-20100820121741-4kxozn8b9rhee9fr
Tags: 2.2.3-1
* New upstream version

[ IOhannes m zmölnig ]
* Adopt package, on behalf of Multimedia Team.
  Closes: #546964
* Simply debian/rules with CDBS, and don't unconditionally strip
  binaries.
  Closes: #437763
* Install into /usr/lib/pd/extra/zexy/. Document usage in REAME.Debian
  and warn about change in NEWS.
* git'ify package. Add Vcs-* stanzas to control file.
* Use dpkg source format 3.0 (quilt). Drop build-dependency on quilt.

[ Jonas Smedegaard ]
* Enable CDBS copyright-check routine.
* Add copyright and licensing header to debian/rules.
* Add myself as uploader.
* Rewrite debian/copyright using rev. 135 of draft DEP5 format.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/******************************************************
 
2
 *
 
3
 * zexy - implementation file
 
4
 *
 
5
 * copyleft (c) IOhannes m zm�lnig
 
6
 *
 
7
 *   1999:forum::f�r::uml�ute:2004
 
8
 *
 
9
 *   institute of electronic music and acoustics (iem)
 
10
 *
 
11
 ******************************************************
 
12
 *
 
13
 * license: GNU General Public License v.2
 
14
 *
 
15
 ******************************************************/
 
16
 
 
17
/* 
 
18
   (c) 2000:forum::f�r::uml�ute:2005
 
19
 
 
20
   write to the parallel port
 
21
   extended to write to any port (if we do have permissions)
 
22
 
 
23
   2005-09-28: write to devices instead of hardware-addresses
 
24
     http://people.redhat.com/twaugh/parport/html/ppdev.html
 
25
     TODO: don't lock when multiple objects refer to the same device
 
26
     TODO: allow readonly/writeonly access
 
27
     TODO: test for timeouts,...
 
28
 
 
29
   thanks to
 
30
    Olaf Matthes: porting to WindozeNT/2000/XP
 
31
    Thomas Musil: adding "control-output" and "input"
 
32
*/
 
33
#define BASE0  0x3bc
 
34
#define BASE1  0x378
 
35
#define BASE2  0x278
 
36
 
 
37
#define MODE_IOPERM 1
 
38
#define MODE_IOPL   0
 
39
#define MODE_NONE   -1
 
40
 
 
41
#include "zexy.h"
 
42
 
 
43
/* ----------------------- lpt --------------------- */
 
44
 
 
45
#ifdef Z_WANT_LPT
 
46
# include <stdlib.h>
 
47
# include <errno.h>
 
48
 
 
49
# ifdef HAVE_LINUX_PPDEV_H
 
50
#  include <unistd.h>
 
51
#  include <sys/ioctl.h>
 
52
#  include <linux/ppdev.h>
 
53
#  include <linux/parport.h>
 
54
#  include <fcntl.h>
 
55
#  include <stdio.h>
 
56
# endif /* HAVE_LINUX_PPDEV_H */
 
57
 
 
58
 
 
59
# ifdef __WIN32__
 
60
/* on windoze everything is so complicated... */
 
61
extern int read_parport(int port);
 
62
extern void write_parport(int port, int value);
 
63
extern int open_port(int port);
 
64
 
 
65
static int ioperm(int port, int a, int b)
 
66
{
 
67
  if(open_port(port) == -1)return(1);
 
68
  return(0);
 
69
}
 
70
 
 
71
static int iopl(int i)
 
72
{
 
73
  return(-1);
 
74
}
 
75
 
 
76
static void sys_outb(unsigned char byte, int port)
 
77
{
 
78
  write_parport(port, byte);
 
79
}
 
80
static int sys_inb(int port)
 
81
{
 
82
  return read_parport(port);
 
83
}
 
84
# else
 
85
/* thankfully there is linux */
 
86
#  include <sys/io.h>
 
87
 
 
88
static void sys_outb(unsigned char byte, int port)
 
89
{
 
90
  outb(byte, port);
 
91
}
 
92
static int sys_inb(int port)
 
93
{
 
94
  return inb(port);
 
95
}
 
96
# endif /* __WIN32__ */
 
97
#endif /* Z_WANT_LP */
 
98
 
 
99
 
 
100
static int count_iopl = 0;
 
101
static t_class *lpt_class;
 
102
 
 
103
typedef struct _lpt
 
104
{
 
105
  t_object x_obj;
 
106
 
 
107
  unsigned long port;
 
108
  int device; /* file descriptor of device, in case we are using one ...*/
 
109
 
 
110
  int mode; /* MODE_IOPERM, MODE_IOPL */
 
111
} t_lpt;
 
112
 
 
113
static void lpt_float(t_lpt *x, t_floatarg f)
 
114
{
 
115
#ifdef Z_WANT_LPT
 
116
  unsigned char b = f;
 
117
# ifdef HAVE_LINUX_PPDEV_H
 
118
  if (x->device>0){
 
119
    ioctl (x->device, PPWDATA, &b);
 
120
  } else
 
121
# endif
 
122
  if (x->port) {
 
123
    sys_outb(b, x->port+0);
 
124
  }
 
125
#endif /*  Z_WANT_LPT */
 
126
}
 
127
 
 
128
static void lpt_control(t_lpt *x, t_floatarg f)
 
129
{
 
130
#ifdef Z_WANT_LPT
 
131
  unsigned char b = f;
 
132
# ifdef HAVE_LINUX_PPDEV_H
 
133
  if (x->device>0){
 
134
    ioctl (x->device, PPWCONTROL, &b);
 
135
  } else
 
136
# endif
 
137
  if (x->port) {
 
138
    sys_outb(b, x->port+2);
 
139
  }
 
140
#endif /*  Z_WANT_LPT */
 
141
}
 
142
 
 
143
static void lpt_bang(t_lpt *x)
 
144
{
 
145
#ifdef Z_WANT_LPT
 
146
# ifdef HAVE_LINUX_PPDEV_H
 
147
  if (x->device>0){
 
148
    unsigned char b=0;
 
149
    ioctl (x->device, PPRCONTROL, &b);
 
150
      outlet_float(x->x_obj.ob_outlet, (t_float)b);
 
151
  } else
 
152
# endif
 
153
  if (x->port)  {
 
154
    outlet_float(x->x_obj.ob_outlet, (t_float)sys_inb(x->port+1));
 
155
  }
 
156
#endif /*  Z_WANT_LPT */
 
157
}
 
158
 
 
159
 
 
160
static void *lpt_new(t_symbol *s, int argc, t_atom *argv)
 
161
{
 
162
  t_lpt *x = (t_lpt *)pd_new(lpt_class);
 
163
  char*devname=atom_getsymbol(argv)->s_name;
 
164
  if(s==gensym("lp"))
 
165
    error("lpt: the use of 'lp' has been deprecated; use 'lpt' instead");
 
166
 
 
167
 
 
168
  inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("control"));
 
169
  outlet_new(&x->x_obj, &s_float);
 
170
  x->mode = MODE_NONE;
 
171
  x->port = 0;
 
172
  x->device = -1;
 
173
 
 
174
#ifdef Z_WANT_LPT
 
175
  if ((argc==0)||(argv->a_type==A_FLOAT)) {
 
176
    /* FLOAT specifies a parallel port */
 
177
    switch ((int)((argc)?atom_getfloat(argv):0)) {
 
178
    case 0:
 
179
      x->port = BASE0;
 
180
      break;
 
181
    case 1:
 
182
      x->port = BASE1;
 
183
      break;  
 
184
    case 2:
 
185
      x->port = BASE2;
 
186
      break;
 
187
    default:
 
188
      error("lpt : only lpt0, lpt1 and lpt2 are accessible");
 
189
      x->port = 0;
 
190
      return (x);
 
191
    }
 
192
  } else { 
 
193
    /* SYMBOL might be a file or a hex port-number;
 
194
       we ignore the file (device) case by now;
 
195
       LATER think about this
 
196
    */
 
197
    x->device=-1;
 
198
    x->port=strtol(devname, 0, 16);
 
199
    if(0==x->port){
 
200
#ifdef HAVE_LINUX_PPDEV_H
 
201
      x->device = open(devname, O_RDWR);
 
202
      if(x->device<=0){
 
203
        error("lpt: bad device %s", devname);
 
204
        return(x);
 
205
      } else {
 
206
        if (ioctl (x->device, PPCLAIM)) {
 
207
          perror ("PPCLAIM");
 
208
          close (x->device);
 
209
          x->device=-1;
 
210
        }
 
211
      }
 
212
#endif /* HAVE_LINUX_PPDEV_H */
 
213
    }
 
214
  }
 
215
 
 
216
  if ((x->device<0) && (!x->port || x->port>65535)){
 
217
    post("lpt : bad port %x", x->port);
 
218
    x->port = 0;
 
219
    return (x);
 
220
  }
 
221
  if (x->device<0){
 
222
    /* this is ugly: when using a named device,
 
223
     * we are currently assuming that we have read/write-access
 
224
     * of course, this is not necessary true
 
225
     */
 
226
    /* furthermore, we might also use the object
 
227
     * withOUT write permissions
 
228
     * (just reading the parport)
 
229
     */
 
230
    if (x->port && x->port < 0x400){
 
231
      if (ioperm(x->port, 8, 1)) {
 
232
        x->mode=MODE_NONE;
 
233
      } else x->mode = MODE_IOPERM;
 
234
    }
 
235
    if(x->mode==MODE_NONE){
 
236
      if (iopl(3)){
 
237
        x->mode=MODE_NONE;
 
238
      } else x->mode=MODE_IOPL;
 
239
      count_iopl++;
 
240
    }
 
241
    
 
242
    if(x->mode==MODE_NONE){
 
243
      error("lpt : couldn't get write permissions");
 
244
      x->port = 0;
 
245
      return (x);
 
246
    }
 
247
  }
 
248
  if(x->device>0)
 
249
    post("lpt: connected to device %s", devname);
 
250
  else
 
251
    post("lpt: connected to port %x in mode '%s'", x->port, (x->mode==MODE_IOPL)?"iopl":"ioperm");
 
252
  if (x->mode==MODE_IOPL)post("lpt-warning: this might seriously damage your pc...");
 
253
#else
 
254
  error("zexy has been compiled without [lpt]!");
 
255
  count_iopl=0;
 
256
#endif /* Z_WANT_LPT */
 
257
 
 
258
  devname=0;
 
259
 
 
260
  return (x);
 
261
}
 
262
 
 
263
static void lpt_free(t_lpt *x)
 
264
{
 
265
#ifdef Z_WANT_LPT
 
266
# ifdef HAVE_LINUX_PPDEV_H
 
267
  if (x->device>0){
 
268
    ioctl (x->device, PPRELEASE);
 
269
    close(x->device);
 
270
    x->device=0;
 
271
  } else
 
272
# endif
 
273
  if (x->port) {
 
274
    if (x->mode==MODE_IOPERM && ioperm(x->port, 8, 0)) error("lpt: couldn't clean up device");
 
275
    else if (x->mode==MODE_IOPL && (!--count_iopl) && iopl(0))
 
276
      error("lpt: couldn't clean up device");
 
277
  }
 
278
#endif /* Z_WANT_LPT */
 
279
}
 
280
 
 
281
 
 
282
static void lpt_helper(t_lpt *x)
 
283
{
 
284
  ZEXY_USEVAR(x);
 
285
  post("\n%c lpt :: direct access to the parallel port", HEARTSYMBOL);
 
286
  post("<byte>\t: write byte to the parallel-port");
 
287
  post("\ncreation:\t\"lpt [<port>]\": connect to parallel port <port> (0..2)");
 
288
  post("\t\t\"lpt <portaddr>\": connect to port @ <portaddr> (hex)");
 
289
}
 
290
 
 
291
void lpt_setup(void)
 
292
{
 
293
  lpt_class = class_new(gensym("lpt"),
 
294
                          (t_newmethod)lpt_new, (t_method)lpt_free,
 
295
                          sizeof(t_lpt), 0, A_GIMME, 0);
 
296
  class_addcreator((t_newmethod)lpt_new, gensym("lp"), A_GIMME, 0);
 
297
 
 
298
  class_addfloat(lpt_class, (t_method)lpt_float);
 
299
  class_addmethod(lpt_class, (t_method)lpt_control, gensym("control"), A_FLOAT, 0);
 
300
  class_addbang(lpt_class, (t_method)lpt_bang);
 
301
 
 
302
  class_addmethod(lpt_class, (t_method)lpt_helper, gensym("help"), 0);
 
303
  zexy_register("lpt");
 
304
}