x10-cm17a 1.0.1-i386-mswin32

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,204 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rake/clean'
4
+ require 'rake/testtask'
5
+ require 'rake/rdoctask'
6
+ require 'rbconfig'
7
+
8
+ begin
9
+ require 'rubygems'
10
+ require 'rake/gempackagetask'
11
+ rescue Exception
12
+ nil
13
+ end
14
+
15
+ ARCH = Config::CONFIG['arch']
16
+ SO_FILE = "lib/#{ARCH}/cm17a_api.so"
17
+
18
+ MAKE = (ARCH =~ /win32/) ? 'nmake' : 'make'
19
+
20
+ CLOBBER.include(
21
+ SO_FILE,
22
+ 'ext/cm17a_api/*.o',
23
+ 'ext/cm17a_api/*.obj',
24
+ 'ext/cm17a_api/*.def',
25
+ 'ext/cm17a_api/*.exp',
26
+ 'ext/cm17a_api/*.lib',
27
+ 'ext/cm17a_api/*.pdb',
28
+ 'ext/cm17a_api/*.so',
29
+ 'ext/cm17a_api/Makefile',
30
+ 'ext/cm17a_api/MANIFEST',
31
+ 'lib/*-*',
32
+ '**/*.log'
33
+ )
34
+
35
+ desc "Default task (run tests)"
36
+ task :default => :test
37
+
38
+ desc "Run the unit tests"
39
+ Rake::TestTask.new do |t|
40
+ t.test_files = FileList['test/test_*.rb']
41
+ t.libs << "lib/#{ARCH}"
42
+ end
43
+ task :test => [SO_FILE]
44
+
45
+ task :xtest => [SO_FILE] do
46
+ test_files = FileList['test/test_*.rb']
47
+ ruby "-Ilib", "-Ilib/#{ARCH}", '-e0', *test_files.collect { |fn| "-r#{fn}" }
48
+ end
49
+
50
+ task :compile => [SO_FILE]
51
+
52
+ directory File.dirname(SO_FILE)
53
+
54
+ file SO_FILE => ["ext/cm17a_api/cm17a_api.so", File.dirname(SO_FILE)] do |t|
55
+ cp t.prerequisites.first, SO_FILE
56
+ end
57
+
58
+ file "ext/cm17a_api/Makefile" => ["ext/cm17a_api/extconf.rb"] do
59
+ Dir.chdir("ext/cm17a_api") do ruby "extconf.rb" end
60
+ end
61
+
62
+ CM17A_FILES = FileList[
63
+ 'ext/cm17a_api/*.c',
64
+ 'ext/cm17a_api/*.h',
65
+ 'ext/cm17a_api/extconf.rb',
66
+ 'ext/cm17a_api/Makefile',
67
+ 'ext/cm17a_api/MANIFEST',
68
+ ]
69
+
70
+ file "ext/cm17a_api/cm17a_api.so" => CM17A_FILES do
71
+ Dir.chdir("ext/cm17a_api") do
72
+ sh MAKE
73
+ end
74
+ end
75
+
76
+ # RDoc Documentation -------------------------------------------------
77
+
78
+ # Choose template, prefer the jamis template if it is available
79
+
80
+ def choose_rdoc_template
81
+ libdir = Config::CONFIG['rubylibdir']
82
+ templates = Dir[File.join(libdir, 'rdoc/**/jamis.rb')]
83
+ templates.empty? ? 'html': 'jamis'
84
+ end
85
+
86
+ rd = Rake::RDocTask.new("rdoc") { |rdoc|
87
+ rdoc.rdoc_dir = 'html'
88
+ rdoc.template = choose_rdoc_template
89
+ rdoc.title = "Ruby X10 Software"
90
+ rdoc.options << '--line-numbers' << '--inline-source' << '--main' << 'README'
91
+ rdoc.rdoc_files.include(
92
+ 'lib/**/*.rb',
93
+ 'doc/*.rdoc',
94
+ 'ext/**/cm17a_api.c',
95
+ 'README',
96
+ 'MIT-LICENSE')
97
+ rdoc.rdoc_files.exclude('lib/**/other.rb', 'lib/**/bottlerocket.rb')
98
+ }
99
+
100
+
101
+ # Packaging Tasks ----------------------------------------------------
102
+
103
+ file "ext/cm17a_api/MANIFEST" do |t|
104
+ open(t.name, "w") do |f|
105
+ f.puts Dir["ext/cm17a_api/*"].select { |fn|
106
+ fn =~ /\.(h|c|rb)$/
107
+ }.collect { |fn|
108
+ File.basename(fn)
109
+ }
110
+ end
111
+ end
112
+
113
+ PKG_VERSION = '1.0.1'
114
+ PKG_FILES = FileList[
115
+ 'Rakefile',
116
+ 'setup.rb',
117
+ 'test/*.rb',
118
+ 'lib/**/*.rb',
119
+ 'ext/cm17a_api/MANIFEST',
120
+ 'ext/cm17a_api/*.h',
121
+ 'ext/cm17a_api/*.c',
122
+ 'ext/cm17a_api/*.rb',
123
+ ]
124
+
125
+ if ! defined?(Gem)
126
+ puts "Package Target requires RubyGEMs"
127
+ else
128
+ spec = Gem::Specification.new do |s|
129
+
130
+ #### Basic information.
131
+
132
+ s.name = 'x10-cm17a'
133
+ s.version = PKG_VERSION
134
+ s.summary = "Ruby based X10 CM17A Firecracker Controller"
135
+ s.description = <<-EOF
136
+ EOF
137
+
138
+ s.files = PKG_FILES.to_a
139
+
140
+ #### C code extensions.
141
+
142
+ s.extensions << "ext/cm17a_api/extconf.rb"
143
+
144
+ #### Load-time details: library and application (you will need one or both).
145
+
146
+ s.require_paths << 'lib' << "lib/#{ARCH}"
147
+
148
+ #### Documentation and testing.
149
+
150
+ s.has_rdoc = true
151
+ # s.extra_rdoc_files = rd.rdoc_files.reject { |fn| fn =~ /\.rb$/ }.to_a
152
+ # s.rdoc_options <<
153
+ # '--title' << 'Rake -- Ruby Make' <<
154
+ # '--main' << 'README' <<
155
+ # '--line-numbers'
156
+
157
+ #### Author and project details.
158
+
159
+ s.author = "Jim Weirich"
160
+ s.email = "jim@weirichhouse.org"
161
+ s.homepage = "http://x10-cm17a.rubyforge.org"
162
+ end
163
+
164
+ binary_spec = spec.dup
165
+ binary_spec.platform = ARCH
166
+ binary_spec.files += ["lib/#{ARCH}/cm17a_api.so"]
167
+ binary_spec.extensions = []
168
+
169
+ puts binary_spec.files.class
170
+
171
+ Rake::GemPackageTask.new(binary_spec) do |pkg|
172
+ pkg.need_zip = false
173
+ pkg.need_tar = false
174
+ end
175
+
176
+ # Rake::GemPackageTask.new(binary_spec) do end
177
+ end
178
+
179
+
180
+ # Publishing Tasks ---------------------------------------------------
181
+
182
+
183
+ task :publish_on_osb => ["pkg/cm17a-#{PKG_VERSION}.tgz", "pkg/cm17a-#{PKG_VERSION}.gem"] do |t|
184
+ sh %{ssh umlcoop mkdir -p "htdocs/software/cm17a"}
185
+ sh %{scp -rq #{t.prerequisites.join(' ')} umlcoop:htdocs/software/cm17a}
186
+ end
187
+
188
+ # Optional publish task for Rake
189
+
190
+ require 'rake/contrib/sshpublisher'
191
+ require 'rake/contrib/rubyforgepublisher'
192
+
193
+ publisher = Rake::CompositePublisher.new
194
+ publisher.add Rake::RubyForgePublisher.new('x10-cm17a', 'jimweirich')
195
+ publisher.add Rake::SshFilePublisher.new(
196
+ 'umlcoop',
197
+ 'htdocs/software/x10-cm17a',
198
+ '.',
199
+ 'x10-cm17a.blurb')
200
+
201
+ desc "Publish the Documentation to RubyForge."
202
+ task :publish => [:rdoc] do
203
+ publisher.upload
204
+ end
@@ -0,0 +1,4 @@
1
+ cm17a.c
2
+ cm17a.h
3
+ cm17a_api.c
4
+ extconf.rb
@@ -0,0 +1,443 @@
1
+ /*
2
+ * Modification for dual Unix/Windows compatibility:
3
+ * Copyright 2004 by Jim Weirich (jim@weirichhouse.org)
4
+ * All rights reserved.
5
+ *
6
+ * See the MIT-LICENSE file included with the distribution for
7
+ * details on redistribution rights.
8
+ *
9
+ * This cm17a driver file is a merging of two separate cm17a drivers,
10
+ * one for Linux by Matt Armstrong and the other for Windows by Adam
11
+ * Briggs. Both Matt and Adam have licensed their code so that it can
12
+ * be modified and reused as long as the relevent copyrights notices,
13
+ * conditions and disclaimers are intact.
14
+ *
15
+ * So first we have Matt's copyright notice for the Linux code:
16
+ *
17
+ * Copyright (C) 1999, 2002 Matt Armstrong
18
+ * All rights reserved.
19
+ *
20
+ * Redistribution and use in source and binary forms, with or
21
+ * without modification, are permitted provided that the
22
+ * following conditions are met:
23
+ *
24
+ * 1. Redistributions of source code must retain the above
25
+ * copyright notice, this list of conditions and the following
26
+ * disclaimer.
27
+ *
28
+ * 2. Redistributions in binary form must reproduce the above
29
+ * copyright notice, this list of conditions and the following
30
+ * disclaimer in the documentation and/or other materials
31
+ * provided with the distribution.
32
+ *
33
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS
34
+ * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
35
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
36
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
37
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
38
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
39
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
40
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
41
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
42
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
43
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
44
+ * OF SUCH DAMAGE.
45
+ *
46
+ * Next we have Adam's copyright for the Windows code.
47
+ *
48
+ * This code is (c)2000, Adam Briggs. All Rights Reserved.
49
+ *
50
+ * Permission to use, copy, and distribute this software and its
51
+ * documentation for any purpose and without fee is hereby granted,
52
+ * provided that the above copyright notice appear in all copies
53
+ * and that both that copyright notice and this permission notice
54
+ * appear in supporting documentation, and that the name Adam
55
+ * Briggs not be used in advertising or publicity pertaining to
56
+ * distribution of the software without specific, written prior
57
+ * permission.
58
+ *
59
+ * *** DISCLAIMER ***
60
+ *
61
+ * ADAM BRIGGS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
62
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
63
+ * AND FITNESS, IN NO EVENT SHALL ADAM BRIGGS BE LIABLE FOR ANY
64
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
65
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
66
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTUOUS ACTION,
67
+ * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
68
+ * THIS SOFTWARE.
69
+ * ***
70
+ */
71
+
72
+ #ifdef HAVE_CONFIG_H
73
+ #include <config.h>
74
+ #endif
75
+
76
+ #ifdef CM17A_WIN32
77
+
78
+ #include <windows.h>
79
+ #include <stdio.h>
80
+
81
+ #else
82
+
83
+ #include <stdio.h>
84
+ #include <stddef.h>
85
+ #include <ctype.h>
86
+ #include <stdlib.h>
87
+ #include <assert.h>
88
+
89
+ #if HAVE_FCNTL_H
90
+ #include <fcntl.h>
91
+ #endif
92
+ #if HAVE_SYS_IOCTL_H
93
+ #include <sys/ioctl.h>
94
+ #endif
95
+ #if HAVE_SYS_TIME_H
96
+ #include <sys/time.h>
97
+ #endif
98
+ #if HAVE_SYS_TYPES_H
99
+ #include <sys/types.h>
100
+ #endif
101
+ #if HAVE_UNISTD_H
102
+ #include <unistd.h>
103
+ #endif
104
+ #if HAVE_TERMIO_H
105
+ #include <termio.h>
106
+ #endif
107
+
108
+ #endif
109
+
110
+ #include "cm17a.h"
111
+
112
+ /* The house code is the high nibble of the command data. */
113
+ unsigned short house_codes[16] = {
114
+ 0x6000, /* A */
115
+ 0x7000, /* B */
116
+ 0x4000, /* C */
117
+ 0x5000, /* D */
118
+ 0x8000, /* E */
119
+ 0x9000, /* F */
120
+ 0xA000, /* G */
121
+ 0xB000, /* H */
122
+ 0xE000, /* I */
123
+ 0xF000, /* J */
124
+ 0xC000, /* K */
125
+ 0xD000, /* L */
126
+ 0x0000, /* M */
127
+ 0x1000, /* N */
128
+ 0x2000, /* O */
129
+ 0x3000, /* P */
130
+ };
131
+
132
+ /* The device codes are described by bits 3, 4, 6, and 10. */
133
+ #define DEVICE_BITS 0x0458
134
+ unsigned short device_codes[16] = {
135
+ 0x0000, /* 1 */
136
+ 0x0010, /* 2 */
137
+ 0x0008, /* 3 */
138
+ 0x0018, /* 4 */
139
+ 0x0040, /* 5 */
140
+ 0x0050, /* 6 */
141
+ 0x0048, /* 7 */
142
+ 0x0058, /* 8 */
143
+ 0x0400, /* 9 */
144
+ 0x0410, /* 10 */
145
+ 0x0408, /* 11 */
146
+ 0x0418, /* 12 */
147
+ 0x0440, /* 13 */
148
+ 0x0450, /* 14 */
149
+ 0x0448, /* 15 */
150
+ 0x0458, /* 16 */
151
+ };
152
+
153
+ /* The command codes are described by bits 1, 2, 5, 7, 8, 9, and
154
+ 11. */
155
+ unsigned short command_codes[] = {
156
+ 0x0000, /* CM17A_ON */
157
+ 0x0020, /* CM17A_OFF */
158
+ 0x0088, /* BRIGHT */
159
+ 0x0098, /* CM17A_DIM */
160
+ };
161
+
162
+ #define ELEMENT_COUNT(a) (sizeof(a) / sizeof((a)[0]))
163
+
164
+ static unsigned short
165
+ cm17a_command_word(int house,
166
+ int device,
167
+ enum CM17A_COMMAND command)
168
+ {
169
+ unsigned short retval;
170
+
171
+ switch (command) {
172
+ case CM17A_BRIGHTEN:
173
+ case CM17A_DIM:
174
+ retval = house_codes[house] | command_codes[command];
175
+ break;
176
+
177
+ default:
178
+ retval = (house_codes[house] |
179
+ device_codes[device] |
180
+ command_codes[command]);
181
+ break;
182
+ }
183
+
184
+ return retval;
185
+ }
186
+
187
+ #ifdef CM17A_WIN32
188
+
189
+ #define X10_DEVICE HANDLE
190
+
191
+ /* delay between bits */
192
+ static void delay(void)
193
+ {
194
+ Sleep(2);
195
+ }
196
+
197
+ /* delay between commands */
198
+ static void long_delay(void)
199
+ {
200
+ Sleep(5);
201
+ }
202
+
203
+ static int cm17a_standby(X10_DEVICE fd)
204
+ {
205
+ EscapeCommFunction(fd, SETDTR);
206
+ EscapeCommFunction(fd, SETRTS);
207
+ delay();
208
+ return 0;
209
+ }
210
+
211
+ static int write_byte(X10_DEVICE fd, unsigned char byte)
212
+ {
213
+ int theMask = 0x80 ;
214
+
215
+ while (theMask) {
216
+ if (byte & theMask) {
217
+ EscapeCommFunction(fd, SETRTS);
218
+ EscapeCommFunction(fd, CLRDTR);
219
+ }
220
+ else {
221
+ EscapeCommFunction(fd, SETDTR);
222
+ EscapeCommFunction(fd, CLRRTS);
223
+ }
224
+ delay();
225
+
226
+ EscapeCommFunction(fd, SETDTR);
227
+ EscapeCommFunction(fd, SETRTS);
228
+ delay();
229
+
230
+ theMask >>= 1;
231
+ }
232
+ return 0;
233
+ }
234
+
235
+ X10_DEVICE cm17a_open_device(const char * device_name) {
236
+ X10_DEVICE fd = CreateFile(
237
+ device_name,
238
+ GENERIC_READ | GENERIC_WRITE,
239
+ 0,
240
+ NULL,
241
+ OPEN_EXISTING,
242
+ FILE_FLAG_WRITE_THROUGH,
243
+ NULL) ;
244
+ return fd;
245
+ }
246
+
247
+ void cm17a_close_device(X10_DEVICE fd) {
248
+ CloseHandle(fd);
249
+ }
250
+
251
+
252
+ #else
253
+
254
+ #define X10_DEVICE int
255
+
256
+ enum SIGNAL {
257
+ RESET = 0,
258
+ HIGH = TIOCM_RTS,
259
+ LOW = TIOCM_DTR,
260
+ STANDBY = (TIOCM_RTS | TIOCM_DTR)
261
+ };
262
+
263
+ static void
264
+ sleep_us(unsigned int nusecs)
265
+ {
266
+ struct timeval tval;
267
+
268
+ tval.tv_sec = nusecs / 1000000;
269
+ tval.tv_usec = nusecs % 1000000;
270
+ select(0, NULL, NULL, NULL, &tval);
271
+ }
272
+
273
+ static void delay(void)
274
+ {
275
+ sleep_us(500);
276
+ }
277
+
278
+ static void long_delay(void)
279
+ {
280
+ sleep_us(500000);
281
+ }
282
+
283
+ static int set(X10_DEVICE fd, enum SIGNAL signal)
284
+ {
285
+ int lines = signal;
286
+ int current;
287
+ /* FIXME: we should just remember this in a static
288
+ variable. */
289
+ if (ioctl(fd, TIOCMGET, &current) != 0) {
290
+ return -1;
291
+ }
292
+ current &= ~RESET;
293
+ current |= signal;
294
+ return ioctl(fd, TIOCMSET, &lines);
295
+ }
296
+
297
+ static int cm17a_standby(X10_DEVICE fd)
298
+ {
299
+ if (set(fd, STANDBY) != 0) {
300
+ return -1;
301
+ }
302
+ delay();
303
+ return 0;
304
+ }
305
+
306
+ static int write_byte(X10_DEVICE fd, unsigned char byte)
307
+ {
308
+ int mask = 0x80;
309
+ do {
310
+ enum SIGNAL signal = (byte & mask) ? HIGH : LOW;
311
+ if (set(fd, signal) != 0) {
312
+ return -1;
313
+ }
314
+ delay();
315
+ if (set(fd, STANDBY) != 0) {
316
+ return -1;
317
+ }
318
+ delay();
319
+ mask >>= 1;
320
+ } while (mask);
321
+ return 0;
322
+ }
323
+
324
+ X10_DEVICE cm17a_open_device(const char * device_name) {
325
+ X10_DEVICE fd = open(device_name, O_RDONLY | O_NDELAY);
326
+ return (fd < 0) ? INVALID_X10_DEVICE : fd;
327
+ }
328
+
329
+ void cm17a_close_device(fd) {
330
+ close(fd);
331
+ }
332
+
333
+ #endif
334
+
335
+ static int
336
+ write_stream(
337
+ X10_DEVICE fd,
338
+ const unsigned char* data,
339
+ size_t byte_count)
340
+ {
341
+ int i;
342
+ for (i = 0; i < byte_count; i++) {
343
+ int ret = write_byte(fd, data[i]);
344
+ if (ret) {
345
+ return ret;
346
+ }
347
+ }
348
+ return 0;
349
+ }
350
+
351
+ static int
352
+ cm17a_header(X10_DEVICE fd)
353
+ {
354
+ /* Header bits taken straight from the CM17A spec. */
355
+ const unsigned char header[] = {
356
+ 0xD5, 0xAA
357
+ };
358
+ return write_stream(fd, header, sizeof(header));
359
+ }
360
+
361
+ static int
362
+ footer(X10_DEVICE fd)
363
+ {
364
+ /* Footer bits taken straight from the CM17A spec. */
365
+ return write_byte(fd, 0xAD);
366
+ }
367
+
368
+ static int
369
+ cm17a_write_command(
370
+ X10_DEVICE fd,
371
+ int house,
372
+ int device,
373
+ enum CM17A_COMMAND command)
374
+ {
375
+ short command_word;
376
+
377
+ command_word = cm17a_command_word(house, device, command);
378
+
379
+ if (cm17a_standby(fd)) {
380
+ return -1;
381
+ }
382
+
383
+ /* The cm17a seems to need another delay period after a
384
+ standby to settle down after the reset. */
385
+ delay();
386
+
387
+ if (cm17a_header(fd) ||
388
+ write_byte(fd, command_word >> 8) ||
389
+ write_byte(fd, command_word) ||
390
+ footer(fd)) {
391
+ return -1;
392
+ }
393
+
394
+ long_delay();
395
+
396
+ return 0;
397
+ }
398
+
399
+ void
400
+ cm17a_command(
401
+ X10_DEVICE fd,
402
+ int house,
403
+ int device,
404
+ enum CM17A_COMMAND cmd,
405
+ int steps)
406
+ {
407
+ switch (cmd) {
408
+ case CM17A_ON:
409
+ case CM17A_OFF:
410
+ if (cm17a_write_command(fd, house, device, cmd) != 0) {
411
+ fprintf(stderr, "Command failed.\n");
412
+ }
413
+ break;
414
+ case CM17A_BRIGHTEN:
415
+ case CM17A_DIM:
416
+ {
417
+ if (steps < 1 || steps > 6) {
418
+ fprintf(stderr,
419
+ "Invalid steps (%d). Must be [1..6].\n",
420
+ steps);
421
+ return;
422
+ }
423
+
424
+ /* Turn the device we wish to control on first. If we don't
425
+ do this, the dim command gets handled by the last device
426
+ that got turned on. The cm17a dim/brighten command doesn't
427
+ use a device code. */
428
+
429
+ if (cm17a_write_command(fd, house, device, CM17A_ON) != 0) {
430
+ fprintf(stderr, "Command failed.\n");
431
+ }
432
+
433
+ while (--steps >= 0) {
434
+ if (cm17a_write_command(fd, house, device, cmd)) {
435
+ fprintf(stderr, "Command failed.\n");
436
+ }
437
+ }
438
+ break;
439
+ }
440
+ default:
441
+ fprintf(stderr, "Invalid flip operation\n");
442
+ }
443
+ }