agilelamp-driver 0.1.3 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,321 @@
1
+ // !$*UTF8*$!
2
+ {
3
+ archiveVersion = 1;
4
+ classes = {
5
+ };
6
+ objectVersion = 42;
7
+ objects = {
8
+
9
+ /* Begin PBXBuildFile section */
10
+ 32D94FC60562CBF700B6AF17 /* k8055.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A224C3EFF42367911CA2CB7 /* k8055.h */; };
11
+ 32D94FC80562CBF700B6AF17 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C167DFE841241C02AAC07 /* InfoPlist.strings */; };
12
+ 32D94FCA0562CBF700B6AF17 /* k8055.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A224C3FFF42367911CA2CB7 /* k8055.cpp */; settings = {ATTRIBUTES = (); }; };
13
+ F94465280806A0E100539834 /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 32D94FCF0562CBF700B6AF17 /* Info.plist */; };
14
+ /* End PBXBuildFile section */
15
+
16
+ /* Begin PBXFileReference section */
17
+ 089C167EFE841241C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
18
+ 1A224C3EFF42367911CA2CB7 /* k8055.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = k8055.h; sourceTree = "<group>"; };
19
+ 1A224C3FFF42367911CA2CB7 /* k8055.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = k8055.cpp; sourceTree = "<group>"; };
20
+ 32D94FCF0562CBF700B6AF17 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = Info.plist; sourceTree = "<group>"; };
21
+ 32D94FD00562CBF700B6AF17 /* USB Missile Launcher.kext */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "USB Missile Launcher.kext"; sourceTree = BUILT_PRODUCTS_DIR; };
22
+ /* End PBXFileReference section */
23
+
24
+ /* Begin PBXFrameworksBuildPhase section */
25
+ 32D94FCB0562CBF700B6AF17 /* Frameworks */ = {
26
+ isa = PBXFrameworksBuildPhase;
27
+ buildActionMask = 2147483647;
28
+ files = (
29
+ );
30
+ runOnlyForDeploymentPostprocessing = 0;
31
+ };
32
+ /* End PBXFrameworksBuildPhase section */
33
+
34
+ /* Begin PBXGroup section */
35
+ 089C166AFE841209C02AAC07 /* k8055 */ = {
36
+ isa = PBXGroup;
37
+ children = (
38
+ 247142CAFF3F8F9811CA285C /* Source */,
39
+ 089C167CFE841241C02AAC07 /* Resources */,
40
+ 19C28FB6FE9D52B211CA2CBB /* Products */,
41
+ );
42
+ name = k8055;
43
+ sourceTree = "<group>";
44
+ };
45
+ 089C167CFE841241C02AAC07 /* Resources */ = {
46
+ isa = PBXGroup;
47
+ children = (
48
+ 32D94FCF0562CBF700B6AF17 /* Info.plist */,
49
+ 089C167DFE841241C02AAC07 /* InfoPlist.strings */,
50
+ );
51
+ name = Resources;
52
+ sourceTree = "<group>";
53
+ };
54
+ 19C28FB6FE9D52B211CA2CBB /* Products */ = {
55
+ isa = PBXGroup;
56
+ children = (
57
+ 32D94FD00562CBF700B6AF17 /* USB Missile Launcher.kext */,
58
+ );
59
+ name = Products;
60
+ sourceTree = "<group>";
61
+ };
62
+ 247142CAFF3F8F9811CA285C /* Source */ = {
63
+ isa = PBXGroup;
64
+ children = (
65
+ 1A224C3EFF42367911CA2CB7 /* k8055.h */,
66
+ 1A224C3FFF42367911CA2CB7 /* k8055.cpp */,
67
+ );
68
+ name = Source;
69
+ sourceTree = "<group>";
70
+ };
71
+ /* End PBXGroup section */
72
+
73
+ /* Begin PBXHeadersBuildPhase section */
74
+ 32D94FC50562CBF700B6AF17 /* Headers */ = {
75
+ isa = PBXHeadersBuildPhase;
76
+ buildActionMask = 2147483647;
77
+ files = (
78
+ 32D94FC60562CBF700B6AF17 /* k8055.h in Headers */,
79
+ );
80
+ runOnlyForDeploymentPostprocessing = 0;
81
+ };
82
+ /* End PBXHeadersBuildPhase section */
83
+
84
+ /* Begin PBXNativeTarget section */
85
+ 32D94FC30562CBF700B6AF17 /* USB Missile Launcher */ = {
86
+ isa = PBXNativeTarget;
87
+ buildConfigurationList = 213D03B70A27F0D4006447D9 /* Build configuration list for PBXNativeTarget "USB Missile Launcher" */;
88
+ buildPhases = (
89
+ 32D94FC40562CBF700B6AF17 /* ShellScript */,
90
+ 32D94FC50562CBF700B6AF17 /* Headers */,
91
+ 32D94FC70562CBF700B6AF17 /* Resources */,
92
+ 32D94FC90562CBF700B6AF17 /* Sources */,
93
+ 32D94FCB0562CBF700B6AF17 /* Frameworks */,
94
+ 32D94FCC0562CBF700B6AF17 /* Rez */,
95
+ 32D94FCD0562CBF700B6AF17 /* ShellScript */,
96
+ );
97
+ buildRules = (
98
+ );
99
+ dependencies = (
100
+ );
101
+ name = "USB Missile Launcher";
102
+ productInstallPath = "$(SYSTEM_LIBRARY_DIR)/Extensions";
103
+ productName = k8055;
104
+ productReference = 32D94FD00562CBF700B6AF17 /* USB Missile Launcher.kext */;
105
+ productType = "com.apple.product-type.kernel-extension.iokit";
106
+ };
107
+ /* End PBXNativeTarget section */
108
+
109
+ /* Begin PBXProject section */
110
+ 089C1669FE841209C02AAC07 /* Project object */ = {
111
+ isa = PBXProject;
112
+ buildConfigurationList = 213D03BB0A27F0D4006447D9 /* Build configuration list for PBXProject "USB Missile Launcher" */;
113
+ hasScannedForEncodings = 1;
114
+ mainGroup = 089C166AFE841209C02AAC07 /* k8055 */;
115
+ projectDirPath = "";
116
+ projectRoot = "";
117
+ targets = (
118
+ 32D94FC30562CBF700B6AF17 /* USB Missile Launcher */,
119
+ );
120
+ };
121
+ /* End PBXProject section */
122
+
123
+ /* Begin PBXResourcesBuildPhase section */
124
+ 32D94FC70562CBF700B6AF17 /* Resources */ = {
125
+ isa = PBXResourcesBuildPhase;
126
+ buildActionMask = 2147483647;
127
+ files = (
128
+ 32D94FC80562CBF700B6AF17 /* InfoPlist.strings in Resources */,
129
+ F94465280806A0E100539834 /* Info.plist in Resources */,
130
+ );
131
+ runOnlyForDeploymentPostprocessing = 0;
132
+ };
133
+ /* End PBXResourcesBuildPhase section */
134
+
135
+ /* Begin PBXRezBuildPhase section */
136
+ 32D94FCC0562CBF700B6AF17 /* Rez */ = {
137
+ isa = PBXRezBuildPhase;
138
+ buildActionMask = 2147483647;
139
+ files = (
140
+ );
141
+ runOnlyForDeploymentPostprocessing = 0;
142
+ };
143
+ /* End PBXRezBuildPhase section */
144
+
145
+ /* Begin PBXShellScriptBuildPhase section */
146
+ 32D94FC40562CBF700B6AF17 /* ShellScript */ = {
147
+ isa = PBXShellScriptBuildPhase;
148
+ buildActionMask = 2147483647;
149
+ files = (
150
+ );
151
+ runOnlyForDeploymentPostprocessing = 0;
152
+ shellPath = /bin/sh;
153
+ shellScript = "script=\"${SYSTEM_DEVELOPER_DIR}/ProjectBuilder Extras/Kernel Extension Support/KEXTPreprocess\";\nif [ -x \"$script\" ]; then\n . \"$script\"\nfi";
154
+ };
155
+ 32D94FCD0562CBF700B6AF17 /* ShellScript */ = {
156
+ isa = PBXShellScriptBuildPhase;
157
+ buildActionMask = 2147483647;
158
+ files = (
159
+ );
160
+ runOnlyForDeploymentPostprocessing = 0;
161
+ shellPath = /bin/sh;
162
+ shellScript = "script=\"${SYSTEM_DEVELOPER_DIR}/ProjectBuilder Extras/Kernel Extension Support/KEXTPostprocess\";\nif [ -x \"$script\" ]; then\n . \"$script\"\nfi";
163
+ };
164
+ /* End PBXShellScriptBuildPhase section */
165
+
166
+ /* Begin PBXSourcesBuildPhase section */
167
+ 32D94FC90562CBF700B6AF17 /* Sources */ = {
168
+ isa = PBXSourcesBuildPhase;
169
+ buildActionMask = 2147483647;
170
+ files = (
171
+ 32D94FCA0562CBF700B6AF17 /* k8055.cpp in Sources */,
172
+ );
173
+ runOnlyForDeploymentPostprocessing = 0;
174
+ };
175
+ /* End PBXSourcesBuildPhase section */
176
+
177
+ /* Begin PBXVariantGroup section */
178
+ 089C167DFE841241C02AAC07 /* InfoPlist.strings */ = {
179
+ isa = PBXVariantGroup;
180
+ children = (
181
+ 089C167EFE841241C02AAC07 /* English */,
182
+ );
183
+ name = InfoPlist.strings;
184
+ sourceTree = "<group>";
185
+ };
186
+ /* End PBXVariantGroup section */
187
+
188
+ /* Begin XCBuildConfiguration section */
189
+ 213D03B80A27F0D4006447D9 /* Development */ = {
190
+ isa = XCBuildConfiguration;
191
+ buildSettings = {
192
+ ARCHS = (
193
+ ppc,
194
+ i386,
195
+ );
196
+ COPY_PHASE_STRIP = NO;
197
+ FRAMEWORK_SEARCH_PATHS = "";
198
+ GCC_DYNAMIC_NO_PIC = NO;
199
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
200
+ GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
201
+ GCC_OPTIMIZATION_LEVEL = 0;
202
+ GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO;
203
+ GCC_WARN_UNKNOWN_PRAGMAS = NO;
204
+ HEADER_SEARCH_PATHS = "";
205
+ INFOPLIST_FILE = Info.plist;
206
+ INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Extensions";
207
+ LIBRARY_SEARCH_PATHS = "";
208
+ MODULE_NAME = com.MySoftwareCompany.driver.k8055;
209
+ MODULE_VERSION = 1.0.0d1;
210
+ OPTIMIZATION_CFLAGS = "-O0";
211
+ OTHER_CFLAGS = "";
212
+ OTHER_LDFLAGS = "";
213
+ OTHER_REZFLAGS = "";
214
+ PRODUCT_NAME = "USB Missile Launcher";
215
+ SECTORDER_FLAGS = "";
216
+ WARNING_CFLAGS = "-Wmost";
217
+ WRAPPER_EXTENSION = kext;
218
+ ZERO_LINK = YES;
219
+ };
220
+ name = Development;
221
+ };
222
+ 213D03B90A27F0D4006447D9 /* Deployment */ = {
223
+ isa = XCBuildConfiguration;
224
+ buildSettings = {
225
+ ARCHS = (
226
+ ppc,
227
+ i386,
228
+ );
229
+ COPY_PHASE_STRIP = YES;
230
+ FRAMEWORK_SEARCH_PATHS = "";
231
+ GCC_ENABLE_FIX_AND_CONTINUE = NO;
232
+ GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO;
233
+ GCC_WARN_UNKNOWN_PRAGMAS = NO;
234
+ HEADER_SEARCH_PATHS = "";
235
+ INFOPLIST_FILE = Info.plist;
236
+ INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Extensions";
237
+ LIBRARY_SEARCH_PATHS = "";
238
+ MODULE_NAME = com.MySoftwareCompany.driver.k8055;
239
+ MODULE_VERSION = 1.0.0d1;
240
+ OTHER_CFLAGS = "";
241
+ OTHER_LDFLAGS = "";
242
+ OTHER_REZFLAGS = "";
243
+ PRODUCT_NAME = "USB Missile Launcher";
244
+ SECTORDER_FLAGS = "";
245
+ WARNING_CFLAGS = "-Wmost";
246
+ WRAPPER_EXTENSION = kext;
247
+ ZERO_LINK = NO;
248
+ };
249
+ name = Deployment;
250
+ };
251
+ 213D03BA0A27F0D4006447D9 /* Default */ = {
252
+ isa = XCBuildConfiguration;
253
+ buildSettings = {
254
+ ARCHS = (
255
+ ppc,
256
+ i386,
257
+ );
258
+ FRAMEWORK_SEARCH_PATHS = "";
259
+ GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO;
260
+ GCC_WARN_UNKNOWN_PRAGMAS = NO;
261
+ HEADER_SEARCH_PATHS = "";
262
+ INFOPLIST_FILE = Info.plist;
263
+ INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Extensions";
264
+ LIBRARY_SEARCH_PATHS = "";
265
+ MODULE_NAME = com.MySoftwareCompany.driver.k8055;
266
+ MODULE_VERSION = 1.0.0d1;
267
+ OTHER_CFLAGS = "";
268
+ OTHER_LDFLAGS = "";
269
+ OTHER_REZFLAGS = "";
270
+ PRODUCT_NAME = "USB Missile Launcher";
271
+ SECTORDER_FLAGS = "";
272
+ WARNING_CFLAGS = "-Wmost";
273
+ WRAPPER_EXTENSION = kext;
274
+ };
275
+ name = Default;
276
+ };
277
+ 213D03BC0A27F0D4006447D9 /* Development */ = {
278
+ isa = XCBuildConfiguration;
279
+ buildSettings = {
280
+ };
281
+ name = Development;
282
+ };
283
+ 213D03BD0A27F0D4006447D9 /* Deployment */ = {
284
+ isa = XCBuildConfiguration;
285
+ buildSettings = {
286
+ };
287
+ name = Deployment;
288
+ };
289
+ 213D03BE0A27F0D4006447D9 /* Default */ = {
290
+ isa = XCBuildConfiguration;
291
+ buildSettings = {
292
+ };
293
+ name = Default;
294
+ };
295
+ /* End XCBuildConfiguration section */
296
+
297
+ /* Begin XCConfigurationList section */
298
+ 213D03B70A27F0D4006447D9 /* Build configuration list for PBXNativeTarget "USB Missile Launcher" */ = {
299
+ isa = XCConfigurationList;
300
+ buildConfigurations = (
301
+ 213D03B80A27F0D4006447D9 /* Development */,
302
+ 213D03B90A27F0D4006447D9 /* Deployment */,
303
+ 213D03BA0A27F0D4006447D9 /* Default */,
304
+ );
305
+ defaultConfigurationIsVisible = 0;
306
+ defaultConfigurationName = Default;
307
+ };
308
+ 213D03BB0A27F0D4006447D9 /* Build configuration list for PBXProject "USB Missile Launcher" */ = {
309
+ isa = XCConfigurationList;
310
+ buildConfigurations = (
311
+ 213D03BC0A27F0D4006447D9 /* Development */,
312
+ 213D03BD0A27F0D4006447D9 /* Deployment */,
313
+ 213D03BE0A27F0D4006447D9 /* Default */,
314
+ );
315
+ defaultConfigurationIsVisible = 0;
316
+ defaultConfigurationName = Default;
317
+ };
318
+ /* End XCConfigurationList section */
319
+ };
320
+ rootObject = 089C1669FE841209C02AAC07 /* Project object */;
321
+ }
@@ -0,0 +1 @@
1
+ /* add your code here */
@@ -0,0 +1 @@
1
+ /* add your code here */
@@ -0,0 +1,16 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>BuildVersion</key>
6
+ <string>1</string>
7
+ <key>CFBundleShortVersionString</key>
8
+ <string>1.0</string>
9
+ <key>CFBundleVersion</key>
10
+ <string>1.0.0d1</string>
11
+ <key>ProjectName</key>
12
+ <string>DevToolsWizardTemplates</string>
13
+ <key>SourceVersion</key>
14
+ <string>3070000</string>
15
+ </dict>
16
+ </plist>
@@ -0,0 +1,18 @@
1
+ About this directory
2
+ --------------------
3
+
4
+ The approach to getting the code onto your system is a hack of Rubygems, which
5
+ really only wants to install libraries and executables for you. The
6
+ install-agilelamp-driver executable finds the gem directory, builds the
7
+ agilelamp binary in place using agilelamp.c, and installs it to the system
8
+ (this means agilelamp-driver won't be removed on gem uninstall either). It also
9
+ installs 44-usblamp-rules to /etc/udev/rules.d/ and restarts udev. This is to
10
+ keep the kernel from binding to the device. There is a Linux-specific call in
11
+ libusb that is also necessary, usb_detach_kernel_np.
12
+
13
+ On MacOS, it is necessary to install a "codeless kext" (a driver extension
14
+ which does not contain accompanying C code, only a *.plist metadata file) to
15
+ match the device and steal it from the kernel. sudo fetch_kext performs the
16
+ operations necessary to build and install the codeless kext to the system.
17
+ Unfortunately, at the time of this writing, the libusb code still does not work
18
+ on MacOS, perhaps because of something wrong with the codeless kext.
Binary file
@@ -3,7 +3,11 @@
3
3
  #include <unistd.h>
4
4
  #include <string.h>
5
5
 
6
+ // I should acknowledge the USB missile launcher code that served as an initial
7
+ // template. Need to find the URL first...
8
+
6
9
  usb_dev_handle* launcher;
10
+
7
11
  //wrapper for control_msg
8
12
  int send_message(char* msg, int index)
9
13
  {
@@ -20,7 +24,11 @@ void send_cbw(){
20
24
  }
21
25
 
22
26
  void send_lamp_command(char* title, char* message1, char* message2){
23
- usb_reset(launcher);
27
+ //usb_reset(launcher);
28
+ //usb_resetep(launcher, 0);
29
+ //usb_resetep(launcher, 1);
30
+ //usb_clear_halt(launcher, 0);
31
+ //usb_clear_halt(launcher, 1);
24
32
  send_cbw();
25
33
  fprintf(stderr, "Submitting %s\n", title);
26
34
  int ret = send_message(message1, 0);
@@ -36,23 +44,23 @@ void set_red_with_bell(){
36
44
  }
37
45
 
38
46
  /*
39
- Fun with bit-math:
47
+ Fun with bit-math:
40
48
 
41
- Everything on the first (from right) 8 bits of first (from right) byte
49
+ Everything on the first (from right) 8 bits of first (from right) byte
42
50
 
43
51
  b0:=1:Bell active;=0:Bell off
44
52
  b1:=1:Green led on; =0:Green led off
45
53
  b2:=1:Red led on;=0:red led off
46
54
  b3:=0:7 colors led on;=1:7 colors led off
47
55
 
48
- b0
56
+ b0
49
57
  1 1 1 1 1 111
50
58
  128 64 32 16 8 421 = 255
51
59
 
52
60
  c c c c c rgb (c's are colors to cycle through, then red, green, bell)
53
61
 
54
62
  0 0 0 16 0 000 =
55
-
63
+
56
64
  */
57
65
 
58
66
  void only_bell_on(){
@@ -85,8 +93,31 @@ void set_colors_with_bell(){
85
93
  send_lamp_command("colors with bells", message_part_1, message_part_2);
86
94
  }
87
95
 
96
+ int claim_interface(int num){
97
+ int claimed = -1;
98
+ //do stuff
99
+
100
+ claimed = usb_claim_interface(launcher, num);
101
+ printf("Interface %d claimed with %d\n", num, claimed);
102
+
103
+ //usb_detach_kernel_driver_np(launcher, 1);
104
+ //usb_detach_kernel_driver_np(launcher, 0);
105
+
106
+ if (claimed < 0)
107
+ {
108
+ printf("Preparing to release interface %d\n", num);
109
+ usb_release_interface(launcher, num);
110
+ printf("Couldn't claim interface %d \n", num);
111
+ usb_close(launcher);
112
+ return 1;
113
+ } else if (claimed >= 0){
114
+ printf("Claimed interface %d \n", num);
115
+ }
116
+ return 0;
117
+ }
118
+
88
119
  int load_device(){
89
- int claimed;
120
+ int ret;
90
121
 
91
122
  fprintf(stderr, "Starting\n");
92
123
 
@@ -122,29 +153,37 @@ int load_device(){
122
153
  }
123
154
  }
124
155
 
125
- fprintf(stderr, "Got launcher...\n");
126
-
127
- //do stuff
128
- if(launcher != NULL)
129
- {
130
- int claimed = usb_claim_interface(launcher, 1);
156
+ if(launcher == NULL){
157
+ printf("Didn't get launcher!\n");
158
+ return 1;
159
+ } else {
160
+ printf("Got launcher...\n");
131
161
  }
132
- else
133
- {
134
- fprintf(stderr, "You didn't really get the launcher!\n");
162
+
163
+ ret = claim_interface(0);
164
+ printf("Interface 0 returned %d\n", ret);
165
+ if(ret == 1){
166
+ printf("Returning 1 in claim_interface\n");
135
167
  return 1;
136
168
  }
137
- usb_detach_kernel_driver_np(launcher, 1);
138
- usb_detach_kernel_driver_np(launcher, 0);
139
169
 
140
- if (claimed == 0)
141
- {
142
- usb_release_interface(launcher, 1);
170
+ ret = claim_interface(1);
171
+ printf("Interface 1 returned %d\n", ret);
172
+ if(ret == 1){
173
+ printf("Returning 1 in claim_interface\n");
143
174
  return 1;
144
- } else if (claimed > 0){
145
- fprintf(stderr, "Found launcher...\n");
146
175
  }
147
176
 
177
+ fprintf(stderr, "Claimed interfaces\n");
178
+ return 0;
179
+ }
180
+
181
+ void lamp_shutdown(){
182
+ int ret = usb_release_interface(launcher, 0);
183
+ printf("Released interface 0: %d\n", ret);
184
+ ret = usb_release_interface(launcher, 1);
185
+ printf("Released interface 1: %d\n", ret);
186
+ usb_close(launcher);
148
187
  }
149
188
 
150
189
  int main(int argc, char *argv[])
@@ -153,10 +192,15 @@ int main(int argc, char *argv[])
153
192
  {
154
193
  /* We print argv[0] assuming it is the program name */
155
194
  printf( "usage: %s red|green|bell|various\n", argv[0] );
195
+ return 1;
156
196
  }
157
197
  else
158
198
  {
159
199
  int ret = load_device();
200
+ if(ret == 1){
201
+ lamp_shutdown();
202
+ return 1;
203
+ }
160
204
  char* argument = argv[1];
161
205
  if(strcmp(argument, "green") == 0){
162
206
  set_green();
@@ -170,5 +214,6 @@ int main(int argc, char *argv[])
170
214
  only_bell_on();
171
215
  }
172
216
  }
217
+ lamp_shutdown();
173
218
  return 0;
174
219
  }