This source file includes following definitions.
- hpi_validate_response
- hpi_add_adapter
- hpi_delete_adapter
- hpi_find_adapter
- wipe_adapter_list
- subsys_get_adapter
- control_cache_alloc_check
- find_control
- hpi_check_control_cache_single
- hpi_check_control_cache
- hpi_cmn_control_cache_sync_to_msg_single
- hpi_cmn_control_cache_sync_to_msg
- hpi_alloc_control_cache
- hpi_free_control_cache
- subsys_message
- HPI_COMMON
1
2
3
4
5
6
7
8
9
10
11
12
13
14 #define SOURCEFILE_NAME "hpicmn.c"
15
16 #include "hpi_internal.h"
17 #include "hpidebug.h"
18 #include "hpimsginit.h"
19
20 #include "hpicmn.h"
21
22 struct hpi_adapters_list {
23 struct hpios_spinlock list_lock;
24 struct hpi_adapter_obj adapter[HPI_MAX_ADAPTERS];
25 u16 gw_num_adapters;
26 };
27
28 static struct hpi_adapters_list adapters;
29
30
31
32
33
34
35 u16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr)
36 {
37 if (phr->type != HPI_TYPE_RESPONSE) {
38 HPI_DEBUG_LOG(ERROR, "header type %d invalid\n", phr->type);
39 return HPI_ERROR_INVALID_RESPONSE;
40 }
41
42 if (phr->object != phm->object) {
43 HPI_DEBUG_LOG(ERROR, "header object %d invalid\n",
44 phr->object);
45 return HPI_ERROR_INVALID_RESPONSE;
46 }
47
48 if (phr->function != phm->function) {
49 HPI_DEBUG_LOG(ERROR, "header function %d invalid\n",
50 phr->function);
51 return HPI_ERROR_INVALID_RESPONSE;
52 }
53
54 return 0;
55 }
56
57 u16 hpi_add_adapter(struct hpi_adapter_obj *pao)
58 {
59 u16 retval = 0;
60
61
62 hpios_alistlock_lock(&adapters);
63
64 if (pao->index >= HPI_MAX_ADAPTERS) {
65 retval = HPI_ERROR_BAD_ADAPTER_NUMBER;
66 goto unlock;
67 }
68
69 if (adapters.adapter[pao->index].type) {
70 int a;
71 for (a = HPI_MAX_ADAPTERS - 1; a >= 0; a--) {
72 if (!adapters.adapter[a].type) {
73 HPI_DEBUG_LOG(WARNING,
74 "ASI%X duplicate index %d moved to %d\n",
75 pao->type, pao->index, a);
76 pao->index = a;
77 break;
78 }
79 }
80 if (a < 0) {
81 retval = HPI_ERROR_DUPLICATE_ADAPTER_NUMBER;
82 goto unlock;
83 }
84 }
85 adapters.adapter[pao->index] = *pao;
86 hpios_dsplock_init(&adapters.adapter[pao->index]);
87 adapters.gw_num_adapters++;
88
89 unlock:
90 hpios_alistlock_unlock(&adapters);
91 return retval;
92 }
93
94 void hpi_delete_adapter(struct hpi_adapter_obj *pao)
95 {
96 if (!pao->type) {
97 HPI_DEBUG_LOG(ERROR, "removing null adapter?\n");
98 return;
99 }
100
101 hpios_alistlock_lock(&adapters);
102 if (adapters.adapter[pao->index].type)
103 adapters.gw_num_adapters--;
104 memset(&adapters.adapter[pao->index], 0, sizeof(adapters.adapter[0]));
105 hpios_alistlock_unlock(&adapters);
106 }
107
108
109
110
111
112
113 struct hpi_adapter_obj *hpi_find_adapter(u16 adapter_index)
114 {
115 struct hpi_adapter_obj *pao = NULL;
116
117 if (adapter_index >= HPI_MAX_ADAPTERS) {
118 HPI_DEBUG_LOG(VERBOSE, "find_adapter invalid index %d\n",
119 adapter_index);
120 return NULL;
121 }
122
123 pao = &adapters.adapter[adapter_index];
124 if (pao->type != 0) {
125
126
127
128
129 return pao;
130 } else {
131
132
133
134
135 return NULL;
136 }
137 }
138
139
140
141
142
143
144 static void wipe_adapter_list(void)
145 {
146 memset(&adapters, 0, sizeof(adapters));
147 }
148
149 static void subsys_get_adapter(struct hpi_message *phm,
150 struct hpi_response *phr)
151 {
152 int count = phm->obj_index;
153 u16 index = 0;
154
155
156 for (index = 0; index < HPI_MAX_ADAPTERS; index++) {
157 if (adapters.adapter[index].type) {
158 if (!count)
159 break;
160 count--;
161 }
162 }
163
164 if (index < HPI_MAX_ADAPTERS) {
165 phr->u.s.adapter_index = adapters.adapter[index].index;
166 phr->u.s.adapter_type = adapters.adapter[index].type;
167 } else {
168 phr->u.s.adapter_index = 0;
169 phr->u.s.adapter_type = 0;
170 phr->error = HPI_ERROR_INVALID_OBJ_INDEX;
171 }
172 }
173
174 static unsigned int control_cache_alloc_check(struct hpi_control_cache *pC)
175 {
176 unsigned int i;
177 int cached = 0;
178 if (!pC)
179 return 0;
180
181 if (pC->init)
182 return pC->init;
183
184 if (!pC->p_cache)
185 return 0;
186
187 if (pC->control_count && pC->cache_size_in_bytes) {
188 char *p_master_cache;
189 unsigned int byte_count = 0;
190
191 p_master_cache = (char *)pC->p_cache;
192 HPI_DEBUG_LOG(DEBUG, "check %d controls\n",
193 pC->control_count);
194 for (i = 0; i < pC->control_count; i++) {
195 struct hpi_control_cache_info *info =
196 (struct hpi_control_cache_info *)
197 &p_master_cache[byte_count];
198 u16 control_index = info->control_index;
199
200 if (control_index >= pC->control_count) {
201 HPI_DEBUG_LOG(INFO,
202 "adap %d control index %d out of range, cache not ready?\n",
203 pC->adap_idx, control_index);
204 return 0;
205 }
206
207 if (!info->size_in32bit_words) {
208 if (!i) {
209 HPI_DEBUG_LOG(INFO,
210 "adap %d cache not ready?\n",
211 pC->adap_idx);
212 return 0;
213 }
214
215
216
217
218 HPI_DEBUG_LOG(ERROR,
219 "adap %d zero size cache entry %d\n",
220 pC->adap_idx, i);
221 break;
222 }
223
224 if (info->control_type) {
225 pC->p_info[control_index] = info;
226 cached++;
227 } else {
228 pC->p_info[control_index] = NULL;
229 }
230
231 byte_count += info->size_in32bit_words * 4;
232
233 HPI_DEBUG_LOG(VERBOSE,
234 "cached %d, pinfo %p index %d type %d size %d\n",
235 cached, pC->p_info[info->control_index],
236 info->control_index, info->control_type,
237 info->size_in32bit_words);
238
239
240
241
242
243 if (byte_count >= pC->cache_size_in_bytes)
244 break;
245
246 if (info->control_index == pC->control_count - 1)
247 break;
248 }
249
250 if (byte_count != pC->cache_size_in_bytes)
251 HPI_DEBUG_LOG(WARNING,
252 "adap %d bytecount %d != cache size %d\n",
253 pC->adap_idx, byte_count,
254 pC->cache_size_in_bytes);
255 else
256 HPI_DEBUG_LOG(DEBUG,
257 "adap %d cache good, bytecount == cache size = %d\n",
258 pC->adap_idx, byte_count);
259
260 pC->init = (u16)cached;
261 }
262 return pC->init;
263 }
264
265
266
267 static short find_control(u16 control_index,
268 struct hpi_control_cache *p_cache, struct hpi_control_cache_info **pI)
269 {
270 if (!control_cache_alloc_check(p_cache)) {
271 HPI_DEBUG_LOG(VERBOSE,
272 "control_cache_alloc_check() failed %d\n",
273 control_index);
274 return 0;
275 }
276
277 *pI = p_cache->p_info[control_index];
278 if (!*pI) {
279 HPI_DEBUG_LOG(VERBOSE, "Uncached Control %d\n",
280 control_index);
281 return 0;
282 } else {
283 HPI_DEBUG_LOG(VERBOSE, "find_control() type %d\n",
284 (*pI)->control_type);
285 }
286 return 1;
287 }
288
289
290 #define HPICMN_PAD_OFS_AND_SIZE(m) {\
291 offsetof(struct hpi_control_cache_pad, m), \
292 sizeof(((struct hpi_control_cache_pad *)(NULL))->m) }
293
294 struct pad_ofs_size {
295 unsigned int offset;
296 unsigned int field_size;
297 };
298
299 static const struct pad_ofs_size pad_desc[] = {
300 HPICMN_PAD_OFS_AND_SIZE(c_channel),
301 HPICMN_PAD_OFS_AND_SIZE(c_artist),
302 HPICMN_PAD_OFS_AND_SIZE(c_title),
303 HPICMN_PAD_OFS_AND_SIZE(c_comment),
304 };
305
306
307
308
309 short hpi_check_control_cache_single(struct hpi_control_cache_single *pC,
310 struct hpi_message *phm, struct hpi_response *phr)
311 {
312 size_t response_size;
313 short found = 1;
314
315
316 response_size =
317 sizeof(struct hpi_response_header) +
318 sizeof(struct hpi_control_res);
319
320 switch (pC->u.i.control_type) {
321
322 case HPI_CONTROL_METER:
323 if (phm->u.c.attribute == HPI_METER_PEAK) {
324 phr->u.c.an_log_value[0] = pC->u.meter.an_log_peak[0];
325 phr->u.c.an_log_value[1] = pC->u.meter.an_log_peak[1];
326 } else if (phm->u.c.attribute == HPI_METER_RMS) {
327 if (pC->u.meter.an_logRMS[0] ==
328 HPI_CACHE_INVALID_SHORT) {
329 phr->error =
330 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
331 phr->u.c.an_log_value[0] = HPI_METER_MINIMUM;
332 phr->u.c.an_log_value[1] = HPI_METER_MINIMUM;
333 } else {
334 phr->u.c.an_log_value[0] =
335 pC->u.meter.an_logRMS[0];
336 phr->u.c.an_log_value[1] =
337 pC->u.meter.an_logRMS[1];
338 }
339 } else
340 found = 0;
341 break;
342 case HPI_CONTROL_VOLUME:
343 if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
344 phr->u.c.an_log_value[0] = pC->u.vol.an_log[0];
345 phr->u.c.an_log_value[1] = pC->u.vol.an_log[1];
346 } else if (phm->u.c.attribute == HPI_VOLUME_MUTE) {
347 if (pC->u.vol.flags & HPI_VOLUME_FLAG_HAS_MUTE) {
348 if (pC->u.vol.flags & HPI_VOLUME_FLAG_MUTED)
349 phr->u.c.param1 =
350 HPI_BITMASK_ALL_CHANNELS;
351 else
352 phr->u.c.param1 = 0;
353 } else {
354 phr->error =
355 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
356 phr->u.c.param1 = 0;
357 }
358 } else {
359 found = 0;
360 }
361 break;
362 case HPI_CONTROL_MULTIPLEXER:
363 if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
364 phr->u.c.param1 = pC->u.mux.source_node_type;
365 phr->u.c.param2 = pC->u.mux.source_node_index;
366 } else {
367 found = 0;
368 }
369 break;
370 case HPI_CONTROL_CHANNEL_MODE:
371 if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
372 phr->u.c.param1 = pC->u.mode.mode;
373 else
374 found = 0;
375 break;
376 case HPI_CONTROL_LEVEL:
377 if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
378 phr->u.c.an_log_value[0] = pC->u.level.an_log[0];
379 phr->u.c.an_log_value[1] = pC->u.level.an_log[1];
380 } else
381 found = 0;
382 break;
383 case HPI_CONTROL_TUNER:
384 if (phm->u.c.attribute == HPI_TUNER_FREQ)
385 phr->u.c.param1 = pC->u.tuner.freq_ink_hz;
386 else if (phm->u.c.attribute == HPI_TUNER_BAND)
387 phr->u.c.param1 = pC->u.tuner.band;
388 else if (phm->u.c.attribute == HPI_TUNER_LEVEL_AVG)
389 if (pC->u.tuner.s_level_avg ==
390 HPI_CACHE_INVALID_SHORT) {
391 phr->u.cu.tuner.s_level = 0;
392 phr->error =
393 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
394 } else
395 phr->u.cu.tuner.s_level =
396 pC->u.tuner.s_level_avg;
397 else
398 found = 0;
399 break;
400 case HPI_CONTROL_AESEBU_RECEIVER:
401 if (phm->u.c.attribute == HPI_AESEBURX_ERRORSTATUS)
402 phr->u.c.param1 = pC->u.aes3rx.error_status;
403 else if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
404 phr->u.c.param1 = pC->u.aes3rx.format;
405 else
406 found = 0;
407 break;
408 case HPI_CONTROL_AESEBU_TRANSMITTER:
409 if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
410 phr->u.c.param1 = pC->u.aes3tx.format;
411 else
412 found = 0;
413 break;
414 case HPI_CONTROL_TONEDETECTOR:
415 if (phm->u.c.attribute == HPI_TONEDETECTOR_STATE)
416 phr->u.c.param1 = pC->u.tone.state;
417 else
418 found = 0;
419 break;
420 case HPI_CONTROL_SILENCEDETECTOR:
421 if (phm->u.c.attribute == HPI_SILENCEDETECTOR_STATE) {
422 phr->u.c.param1 = pC->u.silence.state;
423 } else
424 found = 0;
425 break;
426 case HPI_CONTROL_MICROPHONE:
427 if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
428 phr->u.c.param1 = pC->u.microphone.phantom_state;
429 else
430 found = 0;
431 break;
432 case HPI_CONTROL_SAMPLECLOCK:
433 if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
434 phr->u.c.param1 = pC->u.clk.source;
435 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX) {
436 if (pC->u.clk.source_index ==
437 HPI_CACHE_INVALID_UINT16) {
438 phr->u.c.param1 = 0;
439 phr->error =
440 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
441 } else
442 phr->u.c.param1 = pC->u.clk.source_index;
443 } else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
444 phr->u.c.param1 = pC->u.clk.sample_rate;
445 else
446 found = 0;
447 break;
448 case HPI_CONTROL_PAD:{
449 struct hpi_control_cache_pad *p_pad;
450 p_pad = (struct hpi_control_cache_pad *)pC;
451
452 if (!(p_pad->field_valid_flags & (1 <<
453 HPI_CTL_ATTR_INDEX(phm->u.c.
454 attribute)))) {
455 phr->error =
456 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
457 break;
458 }
459
460 if (phm->u.c.attribute == HPI_PAD_PROGRAM_ID)
461 phr->u.c.param1 = p_pad->pI;
462 else if (phm->u.c.attribute == HPI_PAD_PROGRAM_TYPE)
463 phr->u.c.param1 = p_pad->pTY;
464 else {
465 unsigned int index =
466 HPI_CTL_ATTR_INDEX(phm->u.c.
467 attribute) - 1;
468 unsigned int offset = phm->u.c.param1;
469 unsigned int pad_string_len, field_size;
470 char *pad_string;
471 unsigned int tocopy;
472
473 if (index > ARRAY_SIZE(pad_desc) - 1) {
474 phr->error =
475 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
476 break;
477 }
478
479 pad_string =
480 ((char *)p_pad) +
481 pad_desc[index].offset;
482 field_size = pad_desc[index].field_size;
483
484 pad_string[field_size - 1] = 0;
485
486 pad_string_len = strlen(pad_string) + 1;
487
488 if (offset > pad_string_len) {
489 phr->error =
490 HPI_ERROR_INVALID_CONTROL_VALUE;
491 break;
492 }
493
494 tocopy = pad_string_len - offset;
495 if (tocopy > sizeof(phr->u.cu.chars8.sz_data))
496 tocopy = sizeof(phr->u.cu.chars8.
497 sz_data);
498
499 memcpy(phr->u.cu.chars8.sz_data,
500 &pad_string[offset], tocopy);
501
502 phr->u.cu.chars8.remaining_chars =
503 pad_string_len - offset - tocopy;
504 }
505 }
506 break;
507 default:
508 found = 0;
509 break;
510 }
511
512 HPI_DEBUG_LOG(VERBOSE, "%s Adap %d, Ctl %d, Type %d, Attr %d\n",
513 found ? "Cached" : "Uncached", phm->adapter_index,
514 pC->u.i.control_index, pC->u.i.control_type,
515 phm->u.c.attribute);
516
517 if (found) {
518 phr->size = (u16)response_size;
519 phr->type = HPI_TYPE_RESPONSE;
520 phr->object = phm->object;
521 phr->function = phm->function;
522 }
523
524 return found;
525 }
526
527 short hpi_check_control_cache(struct hpi_control_cache *p_cache,
528 struct hpi_message *phm, struct hpi_response *phr)
529 {
530 struct hpi_control_cache_info *pI;
531
532 if (!find_control(phm->obj_index, p_cache, &pI)) {
533 HPI_DEBUG_LOG(VERBOSE,
534 "HPICMN find_control() failed for adap %d\n",
535 phm->adapter_index);
536 return 0;
537 }
538
539 phr->error = 0;
540 phr->specific_error = 0;
541 phr->version = 0;
542
543 return hpi_check_control_cache_single((struct hpi_control_cache_single
544 *)pI, phm, phr);
545 }
546
547
548
549
550
551
552
553 void hpi_cmn_control_cache_sync_to_msg_single(struct hpi_control_cache_single
554 *pC, struct hpi_message *phm, struct hpi_response *phr)
555 {
556 switch (pC->u.i.control_type) {
557 case HPI_CONTROL_VOLUME:
558 if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
559 pC->u.vol.an_log[0] = phr->u.c.an_log_value[0];
560 pC->u.vol.an_log[1] = phr->u.c.an_log_value[1];
561 } else if (phm->u.c.attribute == HPI_VOLUME_MUTE) {
562 if (phm->u.c.param1)
563 pC->u.vol.flags |= HPI_VOLUME_FLAG_MUTED;
564 else
565 pC->u.vol.flags &= ~HPI_VOLUME_FLAG_MUTED;
566 }
567 break;
568 case HPI_CONTROL_MULTIPLEXER:
569
570 if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
571 pC->u.mux.source_node_type = (u16)phm->u.c.param1;
572 pC->u.mux.source_node_index = (u16)phm->u.c.param2;
573 }
574 break;
575 case HPI_CONTROL_CHANNEL_MODE:
576
577 if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
578 pC->u.mode.mode = (u16)phm->u.c.param1;
579 break;
580 case HPI_CONTROL_LEVEL:
581 if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
582 pC->u.vol.an_log[0] = phr->u.c.an_log_value[0];
583 pC->u.vol.an_log[1] = phr->u.c.an_log_value[1];
584 }
585 break;
586 case HPI_CONTROL_MICROPHONE:
587 if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
588 pC->u.microphone.phantom_state = (u16)phm->u.c.param1;
589 break;
590 case HPI_CONTROL_AESEBU_TRANSMITTER:
591 if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
592 pC->u.aes3tx.format = phm->u.c.param1;
593 break;
594 case HPI_CONTROL_AESEBU_RECEIVER:
595 if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
596 pC->u.aes3rx.format = phm->u.c.param1;
597 break;
598 case HPI_CONTROL_SAMPLECLOCK:
599 if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
600 pC->u.clk.source = (u16)phm->u.c.param1;
601 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX)
602 pC->u.clk.source_index = (u16)phm->u.c.param1;
603 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
604 pC->u.clk.sample_rate = phm->u.c.param1;
605 break;
606 default:
607 break;
608 }
609 }
610
611 void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *p_cache,
612 struct hpi_message *phm, struct hpi_response *phr)
613 {
614 struct hpi_control_cache_single *pC;
615 struct hpi_control_cache_info *pI;
616
617 if (phr->error)
618 return;
619
620 if (!find_control(phm->obj_index, p_cache, &pI)) {
621 HPI_DEBUG_LOG(VERBOSE,
622 "HPICMN find_control() failed for adap %d\n",
623 phm->adapter_index);
624 return;
625 }
626
627
628
629
630 pC = (struct hpi_control_cache_single *)pI;
631
632 hpi_cmn_control_cache_sync_to_msg_single(pC, phm, phr);
633 }
634
635
636
637
638
639 struct hpi_control_cache *hpi_alloc_control_cache(const u32 control_count,
640 const u32 size_in_bytes, u8 *p_dsp_control_buffer)
641 {
642 struct hpi_control_cache *p_cache =
643 kmalloc(sizeof(*p_cache), GFP_KERNEL);
644 if (!p_cache)
645 return NULL;
646
647 p_cache->p_info =
648 kcalloc(control_count, sizeof(*p_cache->p_info), GFP_KERNEL);
649 if (!p_cache->p_info) {
650 kfree(p_cache);
651 return NULL;
652 }
653
654 p_cache->cache_size_in_bytes = size_in_bytes;
655 p_cache->control_count = control_count;
656 p_cache->p_cache = p_dsp_control_buffer;
657 p_cache->init = 0;
658 return p_cache;
659 }
660
661 void hpi_free_control_cache(struct hpi_control_cache *p_cache)
662 {
663 if (p_cache) {
664 kfree(p_cache->p_info);
665 kfree(p_cache);
666 }
667 }
668
669 static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
670 {
671 hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, phm->function, 0);
672
673 switch (phm->function) {
674 case HPI_SUBSYS_OPEN:
675 case HPI_SUBSYS_CLOSE:
676 case HPI_SUBSYS_DRIVER_UNLOAD:
677 break;
678 case HPI_SUBSYS_DRIVER_LOAD:
679 wipe_adapter_list();
680 hpios_alistlock_init(&adapters);
681 break;
682 case HPI_SUBSYS_GET_ADAPTER:
683 subsys_get_adapter(phm, phr);
684 break;
685 case HPI_SUBSYS_GET_NUM_ADAPTERS:
686 phr->u.s.num_adapters = adapters.gw_num_adapters;
687 break;
688 case HPI_SUBSYS_CREATE_ADAPTER:
689 break;
690 default:
691 phr->error = HPI_ERROR_INVALID_FUNC;
692 break;
693 }
694 }
695
696 void HPI_COMMON(struct hpi_message *phm, struct hpi_response *phr)
697 {
698 switch (phm->type) {
699 case HPI_TYPE_REQUEST:
700 switch (phm->object) {
701 case HPI_OBJ_SUBSYSTEM:
702 subsys_message(phm, phr);
703 break;
704 }
705 break;
706
707 default:
708 phr->error = HPI_ERROR_INVALID_TYPE;
709 break;
710 }
711 }