xref: /linux/sound/usb/caiaq/input.c (revision d39d0ed196aa1685bb24771e92f78633c66ac9cb)
1 /*
2  *   Copyright (c) 2006,2007 Daniel Mack, Tim Ruetz
3  *
4  *   This program is free software; you can redistribute it and/or modify
5  *   it under the terms of the GNU General Public License as published by
6  *   the Free Software Foundation; either version 2 of the License, or
7  *   (at your option) any later version.
8  *
9  *   This program is distributed in the hope that it will be useful,
10  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *   GNU General Public License for more details.
13  *
14  *   You should have received a copy of the GNU General Public License
15  *   along with this program; if not, write to the Free Software
16  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 */
18 
19 #include <linux/gfp.h>
20 #include <linux/init.h>
21 #include <linux/usb.h>
22 #include <linux/usb/input.h>
23 #include <sound/core.h>
24 #include <sound/pcm.h>
25 
26 #include "device.h"
27 #include "input.h"
28 
29 static unsigned short keycode_ak1[] =  { KEY_C, KEY_B, KEY_A };
30 static unsigned short keycode_rk2[] =  { KEY_1, KEY_2, KEY_3, KEY_4,
31 					 KEY_5, KEY_6, KEY_7 };
32 static unsigned short keycode_rk3[] =  { KEY_1, KEY_2, KEY_3, KEY_4,
33 					 KEY_5, KEY_6, KEY_7, KEY_5, KEY_6 };
34 
35 static unsigned short keycode_kore[] = {
36 	KEY_FN_F1,      /* "menu"               */
37 	KEY_FN_F7,      /* "lcd backlight       */
38 	KEY_FN_F2,      /* "control"            */
39 	KEY_FN_F3,      /* "enter"              */
40 	KEY_FN_F4,      /* "view"               */
41 	KEY_FN_F5,      /* "esc"                */
42 	KEY_FN_F6,      /* "sound"              */
43 	KEY_FN_F8,      /* array spacer, never triggered. */
44 	KEY_RIGHT,
45 	KEY_DOWN,
46 	KEY_UP,
47 	KEY_LEFT,
48 	KEY_SOUND,      /* "listen"             */
49 	KEY_RECORD,
50 	KEY_PLAYPAUSE,
51 	KEY_STOP,
52 	BTN_4,          /* 8 softkeys */
53 	BTN_3,
54 	BTN_2,
55 	BTN_1,
56 	BTN_8,
57 	BTN_7,
58 	BTN_6,
59 	BTN_5,
60 	KEY_BRL_DOT4,   /* touch sensitive knobs */
61 	KEY_BRL_DOT3,
62 	KEY_BRL_DOT2,
63 	KEY_BRL_DOT1,
64 	KEY_BRL_DOT8,
65 	KEY_BRL_DOT7,
66 	KEY_BRL_DOT6,
67 	KEY_BRL_DOT5
68 };
69 
70 #define KONTROLX1_INPUTS 40
71 
72 #define DEG90		(range / 2)
73 #define DEG180		(range)
74 #define DEG270		(DEG90 + DEG180)
75 #define DEG360		(DEG180 * 2)
76 #define HIGH_PEAK	(268)
77 #define LOW_PEAK	(-7)
78 
79 /* some of these devices have endless rotation potentiometers
80  * built in which use two tapers, 90 degrees phase shifted.
81  * this algorithm decodes them to one single value, ranging
82  * from 0 to 999 */
83 static unsigned int decode_erp(unsigned char a, unsigned char b)
84 {
85 	int weight_a, weight_b;
86 	int pos_a, pos_b;
87 	int ret;
88 	int range = HIGH_PEAK - LOW_PEAK;
89 	int mid_value = (HIGH_PEAK + LOW_PEAK) / 2;
90 
91 	weight_b = abs(mid_value - a) - (range / 2 - 100) / 2;
92 
93 	if (weight_b < 0)
94 		weight_b = 0;
95 
96 	if (weight_b > 100)
97 		weight_b = 100;
98 
99 	weight_a = 100 - weight_b;
100 
101 	if (a < mid_value) {
102 		/* 0..90 and 270..360 degrees */
103 		pos_b = b - LOW_PEAK + DEG270;
104 		if (pos_b >= DEG360)
105 			pos_b -= DEG360;
106 	} else
107 		/* 90..270 degrees */
108 		pos_b = HIGH_PEAK - b + DEG90;
109 
110 
111 	if (b > mid_value)
112 		/* 0..180 degrees */
113 		pos_a = a - LOW_PEAK;
114 	else
115 		/* 180..360 degrees */
116 		pos_a = HIGH_PEAK - a + DEG180;
117 
118 	/* interpolate both slider values, depending on weight factors */
119 	/* 0..99 x DEG360 */
120 	ret = pos_a * weight_a + pos_b * weight_b;
121 
122 	/* normalize to 0..999 */
123 	ret *= 10;
124 	ret /= DEG360;
125 
126 	if (ret < 0)
127 		ret += 1000;
128 
129 	if (ret >= 1000)
130 		ret -= 1000;
131 
132 	return ret;
133 }
134 
135 #undef DEG90
136 #undef DEG180
137 #undef DEG270
138 #undef DEG360
139 #undef HIGH_PEAK
140 #undef LOW_PEAK
141 
142 
143 static void snd_caiaq_input_read_analog(struct snd_usb_caiaqdev *dev,
144 					const unsigned char *buf,
145 					unsigned int len)
146 {
147 	struct input_dev *input_dev = dev->input_dev;
148 
149 	switch (dev->chip.usb_id) {
150 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL2):
151 		input_report_abs(input_dev, ABS_X, (buf[4] << 8) | buf[5]);
152 		input_report_abs(input_dev, ABS_Y, (buf[0] << 8) | buf[1]);
153 		input_report_abs(input_dev, ABS_Z, (buf[2] << 8) | buf[3]);
154 		input_sync(input_dev);
155 		break;
156 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3):
157 		input_report_abs(input_dev, ABS_X, (buf[0] << 8) | buf[1]);
158 		input_report_abs(input_dev, ABS_Y, (buf[2] << 8) | buf[3]);
159 		input_report_abs(input_dev, ABS_Z, (buf[4] << 8) | buf[5]);
160 		input_sync(input_dev);
161 		break;
162 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER):
163 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2):
164 		input_report_abs(input_dev, ABS_X, (buf[0] << 8) | buf[1]);
165 		input_report_abs(input_dev, ABS_Y, (buf[2] << 8) | buf[3]);
166 		input_report_abs(input_dev, ABS_Z, (buf[4] << 8) | buf[5]);
167 		input_sync(input_dev);
168 		break;
169 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
170 		input_report_abs(input_dev, ABS_HAT0X, (buf[8] << 8)  | buf[9]);
171 		input_report_abs(input_dev, ABS_HAT0Y, (buf[4] << 8)  | buf[5]);
172 		input_report_abs(input_dev, ABS_HAT1X, (buf[12] << 8) | buf[13]);
173 		input_report_abs(input_dev, ABS_HAT1Y, (buf[2] << 8)  | buf[3]);
174 		input_report_abs(input_dev, ABS_HAT2X, (buf[14] << 8) | buf[15]);
175 		input_report_abs(input_dev, ABS_HAT2Y, (buf[0] << 8)  | buf[1]);
176 		input_report_abs(input_dev, ABS_HAT3X, (buf[10] << 8) | buf[11]);
177 		input_report_abs(input_dev, ABS_HAT3Y, (buf[6] << 8)  | buf[7]);
178 		input_sync(input_dev);
179 		break;
180 	}
181 }
182 
183 static void snd_caiaq_input_read_erp(struct snd_usb_caiaqdev *dev,
184 				     const char *buf, unsigned int len)
185 {
186 	struct input_dev *input_dev = dev->input_dev;
187 	int i;
188 
189 	switch (dev->chip.usb_id) {
190 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1):
191 		i = decode_erp(buf[0], buf[1]);
192 		input_report_abs(input_dev, ABS_X, i);
193 		input_sync(input_dev);
194 		break;
195 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER):
196 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2):
197 		i = decode_erp(buf[7], buf[5]);
198 		input_report_abs(input_dev, ABS_HAT0X, i);
199 		i = decode_erp(buf[12], buf[14]);
200 		input_report_abs(input_dev, ABS_HAT0Y, i);
201 		i = decode_erp(buf[15], buf[13]);
202 		input_report_abs(input_dev, ABS_HAT1X, i);
203 		i = decode_erp(buf[0], buf[2]);
204 		input_report_abs(input_dev, ABS_HAT1Y, i);
205 		i = decode_erp(buf[3], buf[1]);
206 		input_report_abs(input_dev, ABS_HAT2X, i);
207 		i = decode_erp(buf[8], buf[10]);
208 		input_report_abs(input_dev, ABS_HAT2Y, i);
209 		i = decode_erp(buf[11], buf[9]);
210 		input_report_abs(input_dev, ABS_HAT3X, i);
211 		i = decode_erp(buf[4], buf[6]);
212 		input_report_abs(input_dev, ABS_HAT3Y, i);
213 		input_sync(input_dev);
214 		break;
215 	}
216 }
217 
218 static void snd_caiaq_input_read_io(struct snd_usb_caiaqdev *dev,
219 				    unsigned char *buf, unsigned int len)
220 {
221 	struct input_dev *input_dev = dev->input_dev;
222 	unsigned short *keycode = input_dev->keycode;
223 	int i;
224 
225 	if (!keycode)
226 		return;
227 
228 	if (input_dev->id.product == USB_PID_RIGKONTROL2)
229 		for (i = 0; i < len; i++)
230 			buf[i] = ~buf[i];
231 
232 	for (i = 0; i < input_dev->keycodemax && i < len * 8; i++)
233 		input_report_key(input_dev, keycode[i],
234 				 buf[i / 8] & (1 << (i % 8)));
235 
236 	switch (dev->chip.usb_id) {
237 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER):
238 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2):
239 		input_report_abs(dev->input_dev, ABS_MISC, 255 - buf[4]);
240 		break;
241 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
242 		/* rotary encoders */
243 		input_report_abs(dev->input_dev, ABS_X, buf[5] & 0xf);
244 		input_report_abs(dev->input_dev, ABS_Y, buf[5] >> 4);
245 		input_report_abs(dev->input_dev, ABS_Z, buf[6] & 0xf);
246 		input_report_abs(dev->input_dev, ABS_MISC, buf[6] >> 4);
247 		break;
248 	}
249 
250 	input_sync(input_dev);
251 }
252 
253 static void snd_usb_caiaq_ep4_reply_dispatch(struct urb *urb)
254 {
255 	struct snd_usb_caiaqdev *dev = urb->context;
256 	unsigned char *buf = urb->transfer_buffer;
257 	int ret;
258 
259 	if (urb->status || !dev || urb != dev->ep4_in_urb)
260 		return;
261 
262 	if (urb->actual_length < 24)
263 		goto requeue;
264 
265 	switch (dev->chip.usb_id) {
266 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
267 		if (buf[0] & 0x3)
268 			snd_caiaq_input_read_io(dev, buf + 1, 7);
269 
270 		if (buf[0] & 0x4)
271 			snd_caiaq_input_read_analog(dev, buf + 8, 16);
272 
273 		break;
274 	}
275 
276 requeue:
277 	dev->ep4_in_urb->actual_length = 0;
278 	ret = usb_submit_urb(dev->ep4_in_urb, GFP_ATOMIC);
279 	if (ret < 0)
280 		log("unable to submit urb. OOM!?\n");
281 }
282 
283 static int snd_usb_caiaq_input_open(struct input_dev *idev)
284 {
285 	struct snd_usb_caiaqdev *dev = input_get_drvdata(idev);
286 
287 	if (!dev)
288 		return -EINVAL;
289 
290 	switch (dev->chip.usb_id) {
291 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
292 		if (usb_submit_urb(dev->ep4_in_urb, GFP_KERNEL) != 0)
293 			return -EIO;
294 		break;
295 	}
296 
297 	return 0;
298 }
299 
300 static void snd_usb_caiaq_input_close(struct input_dev *idev)
301 {
302 	struct snd_usb_caiaqdev *dev = input_get_drvdata(idev);
303 
304 	if (!dev)
305 		return;
306 
307 	switch (dev->chip.usb_id) {
308 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
309 		usb_kill_urb(dev->ep4_in_urb);
310 		break;
311 	}
312 }
313 
314 void snd_usb_caiaq_input_dispatch(struct snd_usb_caiaqdev *dev,
315 				  char *buf,
316 				  unsigned int len)
317 {
318 	if (!dev->input_dev || len < 1)
319 		return;
320 
321 	switch (buf[0]) {
322 	case EP1_CMD_READ_ANALOG:
323 		snd_caiaq_input_read_analog(dev, buf + 1, len - 1);
324 		break;
325 	case EP1_CMD_READ_ERP:
326 		snd_caiaq_input_read_erp(dev, buf + 1, len - 1);
327 		break;
328 	case EP1_CMD_READ_IO:
329 		snd_caiaq_input_read_io(dev, buf + 1, len - 1);
330 		break;
331 	}
332 }
333 
334 int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev)
335 {
336 	struct usb_device *usb_dev = dev->chip.dev;
337 	struct input_dev *input;
338 	int i, ret = 0;
339 
340 	input = input_allocate_device();
341 	if (!input)
342 		return -ENOMEM;
343 
344 	usb_make_path(usb_dev, dev->phys, sizeof(dev->phys));
345 	strlcat(dev->phys, "/input0", sizeof(dev->phys));
346 
347 	input->name = dev->product_name;
348 	input->phys = dev->phys;
349 	usb_to_input_id(usb_dev, &input->id);
350 	input->dev.parent = &usb_dev->dev;
351 
352 	input_set_drvdata(input, dev);
353 
354 	switch (dev->chip.usb_id) {
355 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL2):
356 		input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
357 		input->absbit[0] = BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) |
358 			BIT_MASK(ABS_Z);
359 		BUILD_BUG_ON(sizeof(dev->keycode) < sizeof(keycode_rk2));
360 		memcpy(dev->keycode, keycode_rk2, sizeof(keycode_rk2));
361 		input->keycodemax = ARRAY_SIZE(keycode_rk2);
362 		input_set_abs_params(input, ABS_X, 0, 4096, 0, 10);
363 		input_set_abs_params(input, ABS_Y, 0, 4096, 0, 10);
364 		input_set_abs_params(input, ABS_Z, 0, 4096, 0, 10);
365 		snd_usb_caiaq_set_auto_msg(dev, 1, 10, 0);
366 		break;
367 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3):
368 		input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
369 		input->absbit[0] = BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) |
370 			BIT_MASK(ABS_Z);
371 		BUILD_BUG_ON(sizeof(dev->keycode) < sizeof(keycode_rk3));
372 		memcpy(dev->keycode, keycode_rk3, sizeof(keycode_rk3));
373 		input->keycodemax = ARRAY_SIZE(keycode_rk3);
374 		input_set_abs_params(input, ABS_X, 0, 1024, 0, 10);
375 		input_set_abs_params(input, ABS_Y, 0, 1024, 0, 10);
376 		input_set_abs_params(input, ABS_Z, 0, 1024, 0, 10);
377 		snd_usb_caiaq_set_auto_msg(dev, 1, 10, 0);
378 		break;
379 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1):
380 		input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
381 		input->absbit[0] = BIT_MASK(ABS_X);
382 		BUILD_BUG_ON(sizeof(dev->keycode) < sizeof(keycode_ak1));
383 		memcpy(dev->keycode, keycode_ak1, sizeof(keycode_ak1));
384 		input->keycodemax = ARRAY_SIZE(keycode_ak1);
385 		input_set_abs_params(input, ABS_X, 0, 999, 0, 10);
386 		snd_usb_caiaq_set_auto_msg(dev, 1, 0, 5);
387 		break;
388 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER):
389 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2):
390 		input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
391 		input->absbit[0] = BIT_MASK(ABS_HAT0X) | BIT_MASK(ABS_HAT0Y) |
392 				   BIT_MASK(ABS_HAT1X) | BIT_MASK(ABS_HAT1Y) |
393 				   BIT_MASK(ABS_HAT2X) | BIT_MASK(ABS_HAT2Y) |
394 				   BIT_MASK(ABS_HAT3X) | BIT_MASK(ABS_HAT3Y) |
395 				   BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) |
396 				   BIT_MASK(ABS_Z);
397 		input->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC);
398 		BUILD_BUG_ON(sizeof(dev->keycode) < sizeof(keycode_kore));
399 		memcpy(dev->keycode, keycode_kore, sizeof(keycode_kore));
400 		input->keycodemax = ARRAY_SIZE(keycode_kore);
401 		input_set_abs_params(input, ABS_HAT0X, 0, 999, 0, 10);
402 		input_set_abs_params(input, ABS_HAT0Y, 0, 999, 0, 10);
403 		input_set_abs_params(input, ABS_HAT1X, 0, 999, 0, 10);
404 		input_set_abs_params(input, ABS_HAT1Y, 0, 999, 0, 10);
405 		input_set_abs_params(input, ABS_HAT2X, 0, 999, 0, 10);
406 		input_set_abs_params(input, ABS_HAT2Y, 0, 999, 0, 10);
407 		input_set_abs_params(input, ABS_HAT3X, 0, 999, 0, 10);
408 		input_set_abs_params(input, ABS_HAT3Y, 0, 999, 0, 10);
409 		input_set_abs_params(input, ABS_X, 0, 4096, 0, 10);
410 		input_set_abs_params(input, ABS_Y, 0, 4096, 0, 10);
411 		input_set_abs_params(input, ABS_Z, 0, 4096, 0, 10);
412 		input_set_abs_params(input, ABS_MISC, 0, 255, 0, 1);
413 		snd_usb_caiaq_set_auto_msg(dev, 1, 10, 5);
414 		break;
415 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
416 		input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
417 		input->absbit[0] = BIT_MASK(ABS_HAT0X) | BIT_MASK(ABS_HAT0Y) |
418 				   BIT_MASK(ABS_HAT1X) | BIT_MASK(ABS_HAT1Y) |
419 				   BIT_MASK(ABS_HAT2X) | BIT_MASK(ABS_HAT2Y) |
420 				   BIT_MASK(ABS_HAT3X) | BIT_MASK(ABS_HAT3Y) |
421 				   BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) |
422 				   BIT_MASK(ABS_Z);
423 		input->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC);
424 		BUILD_BUG_ON(sizeof(dev->keycode) < KONTROLX1_INPUTS);
425 		for (i = 0; i < KONTROLX1_INPUTS; i++)
426 			dev->keycode[i] = BTN_MISC + i;
427 		input->keycodemax = KONTROLX1_INPUTS;
428 
429 		/* analog potentiometers */
430 		input_set_abs_params(input, ABS_HAT0X, 0, 4096, 0, 10);
431 		input_set_abs_params(input, ABS_HAT0Y, 0, 4096, 0, 10);
432 		input_set_abs_params(input, ABS_HAT1X, 0, 4096, 0, 10);
433 		input_set_abs_params(input, ABS_HAT1Y, 0, 4096, 0, 10);
434 		input_set_abs_params(input, ABS_HAT2X, 0, 4096, 0, 10);
435 		input_set_abs_params(input, ABS_HAT2Y, 0, 4096, 0, 10);
436 		input_set_abs_params(input, ABS_HAT3X, 0, 4096, 0, 10);
437 		input_set_abs_params(input, ABS_HAT3Y, 0, 4096, 0, 10);
438 
439 		/* rotary encoders */
440 		input_set_abs_params(input, ABS_X, 0, 0xf, 0, 1);
441 		input_set_abs_params(input, ABS_Y, 0, 0xf, 0, 1);
442 		input_set_abs_params(input, ABS_Z, 0, 0xf, 0, 1);
443 		input_set_abs_params(input, ABS_MISC, 0, 0xf, 0, 1);
444 
445 		dev->ep4_in_urb = usb_alloc_urb(0, GFP_KERNEL);
446 		if (!dev->ep4_in_urb) {
447 			ret = -ENOMEM;
448 			goto exit_free_idev;
449 		}
450 
451 		usb_fill_bulk_urb(dev->ep4_in_urb, usb_dev,
452 				  usb_rcvbulkpipe(usb_dev, 0x4),
453 				  dev->ep4_in_buf, EP4_BUFSIZE,
454 				  snd_usb_caiaq_ep4_reply_dispatch, dev);
455 
456 		snd_usb_caiaq_set_auto_msg(dev, 1, 10, 5);
457 
458 		break;
459 	default:
460 		/* no input methods supported on this device */
461 		goto exit_free_idev;
462 	}
463 
464 	input->open = snd_usb_caiaq_input_open;
465 	input->close = snd_usb_caiaq_input_close;
466 	input->keycode = dev->keycode;
467 	input->keycodesize = sizeof(unsigned short);
468 	for (i = 0; i < input->keycodemax; i++)
469 		__set_bit(dev->keycode[i], input->keybit);
470 
471 	ret = input_register_device(input);
472 	if (ret < 0)
473 		goto exit_free_idev;
474 
475 	dev->input_dev = input;
476 	return 0;
477 
478 exit_free_idev:
479 	input_free_device(input);
480 	return ret;
481 }
482 
483 void snd_usb_caiaq_input_free(struct snd_usb_caiaqdev *dev)
484 {
485 	if (!dev || !dev->input_dev)
486 		return;
487 
488 	usb_kill_urb(dev->ep4_in_urb);
489 	usb_free_urb(dev->ep4_in_urb);
490 	dev->ep4_in_urb = NULL;
491 
492 	input_unregister_device(dev->input_dev);
493 	dev->input_dev = NULL;
494 }
495 
496