1 /* $NetBSD: umidi_quirks.c,v 1.15 2008/04/28 20:24:00 martin Exp $ */ 2 3 /* 4 * Copyright (c) 2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Takuya SHIOZAKI (tshiozak@NetBSD.org). 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 __KERNEL_RCSID(0, "$NetBSD: umidi_quirks.c,v 1.15 2008/04/28 20:24:00 martin Exp $"); 34 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/kernel.h> 38 #include <sys/malloc.h> 39 #include <sys/device.h> 40 #include <sys/ioctl.h> 41 #include <sys/conf.h> 42 #include <sys/file.h> 43 #include <sys/select.h> 44 #include <sys/proc.h> 45 #include <sys/vnode.h> 46 #include <sys/poll.h> 47 48 #include <dev/usb/usb.h> 49 #include <dev/usb/usbdi.h> 50 #include <dev/usb/usbdi_util.h> 51 52 #include <dev/usb/usbdevs.h> 53 #include <dev/usb/uaudioreg.h> 54 #include <dev/usb/umidireg.h> 55 #include <dev/usb/umidivar.h> 56 #include <dev/usb/umidi_quirks.h> 57 58 /* 59 * quirk codes for UMIDI 60 */ 61 62 #ifdef UMIDIQUIRK_DEBUG 63 #define DPRINTF(x) if (umidiquirkdebug) printf x 64 #define DPRINTFN(n,x) if (umidiquirkdebug >= (n)) printf x 65 int umidiquirkdebug = 1; 66 #else 67 #define DPRINTF(x) 68 #define DPRINTFN(n,x) 69 #endif 70 71 72 /* 73 * YAMAHA UX-256 74 * --- this is a typical yamaha device, but has a broken descriptor :-< 75 */ 76 77 UMQ_FIXED_EP_DEF(YAMAHA, YAMAHA_UX256, ANYIFACE, 1, 1) = { 78 /* out */ 79 { 0, 16 }, 80 /* in */ 81 { 1, 8 } 82 }; 83 84 UMQ_DEF(YAMAHA, YAMAHA_UX256, ANYIFACE) = { 85 UMQ_FIXED_EP_REG(YAMAHA, YAMAHA_UX256, ANYIFACE), 86 #if 0 87 UMQ_YAMAHA_REG(YAMAHA, ANYPRODUCT, ANYIFACE), 88 #endif 89 UMQ_TERMINATOR 90 }; 91 92 93 /* 94 * YAMAHA generic 95 */ 96 UMQ_DEF(YAMAHA, ANYPRODUCT, ANYIFACE) = { 97 UMQ_YAMAHA_REG(YAMAHA, ANYPRODUCT, ANYIFACE), 98 UMQ_TERMINATOR 99 }; 100 101 102 /* 103 * ROLAND UM-1 104 */ 105 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UM1, 2, 1, 1) = { 106 /* out */ 107 { 0, 1 }, 108 /* in */ 109 { 1, 1 } 110 }; 111 112 UMQ_DEF(ROLAND, ROLAND_UM1, 2) = { 113 UMQ_FIXED_EP_REG(ROLAND, ROLAND_UM1, 2), 114 UMQ_TERMINATOR 115 }; 116 117 /* 118 * ROLAND SC-8850 119 */ 120 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_SC8850, 2, 1, 1) = { 121 /* out */ 122 { 0, 6 }, 123 /* in */ 124 { 1, 6 } 125 }; 126 127 UMQ_DEF(ROLAND, ROLAND_SC8850, 2) = { 128 UMQ_FIXED_EP_REG(ROLAND, ROLAND_SC8850, 2), 129 UMQ_TERMINATOR 130 }; 131 132 /* 133 * ROLAND SD-90 134 */ 135 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_SD90, 2, 1, 1) = { 136 /* out */ 137 { 0, 4 }, 138 /* in */ 139 { 1, 4 } 140 }; 141 142 UMQ_DEF(ROLAND, ROLAND_SD90, 2) = { 143 UMQ_FIXED_EP_REG(ROLAND, ROLAND_SD90, 2), 144 UMQ_TERMINATOR 145 }; 146 147 148 /* 149 * ROLAND UM-880 (native mode) 150 */ 151 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UM880N, 0, 1, 1) = { 152 /* out */ 153 { 0, 9 }, 154 /* in */ 155 { 1, 9 } 156 }; 157 158 UMQ_DEF(ROLAND, ROLAND_UM880N, 0) = { 159 UMQ_FIXED_EP_REG(ROLAND, ROLAND_UM880N, 0), 160 UMQ_TERMINATOR 161 }; 162 163 /* 164 * ROLAND UA-100 165 */ 166 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UA100, 2, 1, 1) = { 167 /* out */ 168 { 0, 3 }, 169 /* in */ 170 { 1, 3 } 171 }; 172 173 UMQ_DEF(ROLAND, ROLAND_UA100, 2) = { 174 UMQ_FIXED_EP_REG(ROLAND, ROLAND_UA100, 2), 175 UMQ_TERMINATOR 176 }; 177 178 /* 179 * ROLAND UM-4 180 */ 181 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UM4, 2, 1, 1) = { 182 /* out */ 183 { 0, 4 }, 184 /* in */ 185 { 1, 4 } 186 }; 187 188 UMQ_DEF(ROLAND, ROLAND_UM4, 2) = { 189 UMQ_FIXED_EP_REG(ROLAND, ROLAND_UM4, 2), 190 UMQ_TERMINATOR 191 }; 192 193 /* 194 * ROLAND U-8 195 */ 196 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_U8, 2, 1, 1) = { 197 /* out */ 198 { 0, 2 }, 199 /* in */ 200 { 1, 2 } 201 }; 202 203 UMQ_DEF(ROLAND, ROLAND_U8, 2) = { 204 UMQ_FIXED_EP_REG(ROLAND, ROLAND_U8, 2), 205 UMQ_TERMINATOR 206 }; 207 208 /* 209 * ROLAND UM-2 210 */ 211 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UM2, 2, 1, 1) = { 212 /* out */ 213 { 0, 2 }, 214 /* in */ 215 { 1, 2 } 216 }; 217 218 UMQ_DEF(ROLAND, ROLAND_UM2, 2) = { 219 UMQ_FIXED_EP_REG(ROLAND, ROLAND_UM2, 2), 220 UMQ_TERMINATOR 221 }; 222 223 /* 224 * ROLAND SC-8820 225 */ 226 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_SC8820, 2, 1, 1) = { 227 /* out */ 228 { 0, 5 }, /* cables 0, 1, 4 only */ 229 /* in */ 230 { 1, 5 } /* do. */ 231 }; 232 233 UMQ_DEF(ROLAND, ROLAND_SC8820, 2) = { 234 UMQ_FIXED_EP_REG(ROLAND, ROLAND_SC8820, 2), 235 UMQ_TERMINATOR 236 }; 237 238 /* 239 * ROLAND PC-300 240 */ 241 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_PC300, 2, 1, 1) = { 242 /* out */ 243 { 0, 1 }, 244 /* in */ 245 { 1, 1 } 246 }; 247 248 UMQ_DEF(ROLAND, ROLAND_PC300, 2) = { 249 UMQ_FIXED_EP_REG(ROLAND, ROLAND_PC300, 2), 250 UMQ_TERMINATOR 251 }; 252 253 /* 254 * ROLAND SK-500 255 */ 256 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_SK500, 2, 1, 1) = { 257 /* out */ 258 { 0, 5 }, /* cables 0, 1, 4 only */ 259 /* in */ 260 { 1, 5 } /* do. */ 261 }; 262 263 UMQ_DEF(ROLAND, ROLAND_SK500, 2) = { 264 UMQ_FIXED_EP_REG(ROLAND, ROLAND_SK500, 2), 265 UMQ_TERMINATOR 266 }; 267 268 /* 269 * ROLAND SC-D70 270 */ 271 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_SCD70, 2, 1, 1) = { 272 /* out */ 273 { 0, 3 }, 274 /* in */ 275 { 1, 3 } 276 }; 277 278 UMQ_DEF(ROLAND, ROLAND_SCD70, 2) = { 279 UMQ_FIXED_EP_REG(ROLAND, ROLAND_SCD70, 2), 280 UMQ_TERMINATOR 281 }; 282 283 /* 284 * ROLAND XV-5050 285 */ 286 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_XV5050, 0, 1, 1) = { 287 /* out */ 288 { 0, 1 }, 289 /* in */ 290 { 1, 1 } 291 }; 292 293 UMQ_DEF(ROLAND, ROLAND_XV5050, 0) = { 294 UMQ_FIXED_EP_REG(ROLAND, ROLAND_XV5050, 0), 295 UMQ_TERMINATOR 296 }; 297 298 /* 299 * ROLAND UM-550 300 */ 301 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UM550, 0, 1, 1) = { 302 /* out */ 303 { 0, 6 }, 304 /* in */ 305 { 1, 6 } 306 }; 307 308 UMQ_DEF(ROLAND, ROLAND_UM550, 0) = { 309 UMQ_FIXED_EP_REG(ROLAND, ROLAND_UM550, 0), 310 UMQ_TERMINATOR 311 }; 312 313 /* 314 * ROLAND SD-20 315 */ 316 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_SD20, 0, 1, 1) = { 317 /* out */ 318 { 0, 2 }, 319 /* in */ 320 { 1, 3 } 321 }; 322 323 UMQ_DEF(ROLAND, ROLAND_SD20, 0) = { 324 UMQ_FIXED_EP_REG(ROLAND, ROLAND_SD20, 0), 325 UMQ_TERMINATOR 326 }; 327 328 /* 329 * ROLAND SD-80 330 */ 331 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_SD80, 0, 1, 1) = { 332 /* out */ 333 { 0, 4 }, 334 /* in */ 335 { 1, 4 } 336 }; 337 338 UMQ_DEF(ROLAND, ROLAND_SD80, 0) = { 339 UMQ_FIXED_EP_REG(ROLAND, ROLAND_SD80, 0), 340 UMQ_TERMINATOR 341 }; 342 343 /* 344 * ROLAND UA-700 345 */ 346 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UA700, 3, 1, 1) = { 347 /* out */ 348 { 0, 2 }, 349 /* in */ 350 { 1, 2 } 351 }; 352 353 UMQ_DEF(ROLAND, ROLAND_UA700, 3) = { 354 UMQ_FIXED_EP_REG(ROLAND, ROLAND_UA700, 3), 355 UMQ_TERMINATOR 356 }; 357 358 /* 359 * ROLAND UA-1000 360 */ 361 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UA1000, 3, 1, 1) = { 362 /* out */ 363 { 0, 2 }, 364 /* in */ 365 { 1, 2 } 366 }; 367 368 UMQ_DEF(ROLAND, ROLAND_UA1000, 3) = { 369 UMQ_FIXED_EP_REG(ROLAND, ROLAND_UA1000, 3), 370 UMQ_TERMINATOR 371 }; 372 373 /* 374 * ROLAND UA-101 375 */ 376 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UA101, 2, 1, 1) = { 377 /* out */ 378 { 0, 2 }, 379 /* in */ 380 { 1, 2 } 381 }; 382 383 UMQ_DEF(ROLAND, ROLAND_UA101, 2) = { 384 UMQ_FIXED_EP_REG(ROLAND, ROLAND_UA101, 2), 385 UMQ_TERMINATOR 386 }; 387 388 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UA101F, 2, 1, 1) = { 389 /* out */ 390 { 0, 2 }, 391 /* in */ 392 { 1, 2 } 393 }; 394 395 UMQ_DEF(ROLAND, ROLAND_UA101F, 2) = { 396 UMQ_FIXED_EP_REG(ROLAND, ROLAND_UA101F, 2), 397 UMQ_TERMINATOR 398 }; 399 400 /* 401 * ROLAND Fantom-X 402 */ 403 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_FANTOMX, 0, 1, 1) = { 404 /* out */ 405 { 0, 1 }, 406 /* in */ 407 { 1, 1 } 408 }; 409 410 UMQ_DEF(ROLAND, ROLAND_FANTOMX, 0) = { 411 UMQ_FIXED_EP_REG(ROLAND, ROLAND_FANTOMX, 0), 412 UMQ_TERMINATOR 413 }; 414 415 /* 416 * ROLAND PCR 417 */ 418 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_PCR, 0, 1, 1) = { 419 /* out */ 420 { 0, 3 }, 421 /* in */ 422 { 1, 3 } 423 }; 424 425 UMQ_DEF(ROLAND, ROLAND_PCR, 0) = { 426 UMQ_FIXED_EP_REG(ROLAND, ROLAND_PCR, 0), 427 UMQ_TERMINATOR 428 }; 429 430 /* 431 * ROLAND UM-3EX 432 */ 433 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UM3, 0, 1, 1) = { 434 /* out */ 435 { 0, 3 }, 436 /* in */ 437 { 1, 3 } 438 }; 439 440 UMQ_DEF(ROLAND, ROLAND_UM3, 0) = { 441 UMQ_FIXED_EP_REG(ROLAND, ROLAND_UM3, 0), 442 UMQ_TERMINATOR 443 }; 444 445 /* 446 * ROLAND UA-25 447 */ 448 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UA25, 2, 1, 1) = { 449 /* out */ 450 { 0, 1 }, 451 /* in */ 452 { 1, 1 } 453 }; 454 455 UMQ_DEF(ROLAND, ROLAND_UA25, 2) = { 456 UMQ_FIXED_EP_REG(ROLAND, ROLAND_UA25, 2), 457 UMQ_TERMINATOR 458 }; 459 460 /* 461 * ROLAND UA-4FX 462 */ 463 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UA4FX, 2, 1, 1) = { 464 /* out */ 465 { 0, 1 }, 466 /* in */ 467 { 1, 1 } 468 }; 469 470 UMQ_DEF(ROLAND, ROLAND_UA4FX, 2) = { 471 UMQ_FIXED_EP_REG(ROLAND, ROLAND_UA4FX, 2), 472 UMQ_TERMINATOR 473 }; 474 475 /* 476 * ROLAND SonicCell 477 */ 478 UMQ_FIXED_EP_DEF(ROLAND, ROLAND_SONICCELL, 2, 1, 1) = { 479 /* out */ 480 { 0, 1 }, 481 /* in */ 482 { 1, 1 } 483 }; 484 485 UMQ_DEF(ROLAND, ROLAND_SONICCELL, 2) = { 486 UMQ_FIXED_EP_REG(ROLAND, ROLAND_SONICCELL, 2), 487 UMQ_TERMINATOR 488 }; 489 490 /* 491 * Midiman Midisport 2x4. This has 2 physical MIDI IN jacks that are read 492 * on endpoint 0x81 (descriptor index 0). It has 4 physical MIDI OUT jacks 493 * that can be written on endpoints 2 or 4 (at descriptor index 2 or 4, 494 * coincidentally) interchangeably: either endpoint will accept a Cable Number 495 * field of 0 to 3, and data for a given CN will be routed to the same 496 * physical output regardless of the endpoint used for the transfer. But 497 * there's a catch: flow-control feedback only goes to endpoint 2 for 498 * CN 0 and 2, and only to endpoint 4 for CN 1 and 3. If you send output at 499 * high rates for CN 0 or 2 over endpoint 4, or for CN 1 or 3 over endpoint 2, 500 * the USB transfers complete as fast as possible, giving you an apparent data 501 * rate much higher than MIDI's 3125 cps (easy to measure using dd to blast a 502 * bunch of midi data to the rmidi device). Of course that isn't a way to make 503 * MIDI faster, just a way to overrun the device buffer and spray bits on the 504 * floor. So this device needs the fixed endpoint quirk, the fixed cable number 505 * quirk (to make sure CNs 0 and 2 are put on the first endpoint and 1 and 3 506 * on the other), and then the fixed mididev-assignment quirk (to match jacks 507 * to mididevs so the rmidi devices match the order of the blinkenlights). 508 */ 509 UMQ_FIXED_EP_DEF(MIDIMAN, MIDIMAN_MIDISPORT2X4, ANYIFACE, 2, 1) = { 510 /* out: ep# jacks */ 511 { 2, 2 }, 512 { 4, 2 }, 513 /* in: ep# jacks */ 514 { 0, 2 } 515 }; 516 UMQ_DEF(MIDIMAN, MIDIMAN_MIDISPORT2X4, ANYIFACE) = { 517 UMQ_FIXED_EP_REG(MIDIMAN, MIDIMAN_MIDISPORT2X4, ANYIFACE), 518 UMQ_CN_FIXED_REG(0, 2, 1, 3, 0, 1), 519 UMQ_MD_FIXED_REG(0, 0, 2, 1, 1, -1, 3, -1), 520 UMQ_TYPE(MIDIMAN_GARBLE), 521 UMQ_TERMINATOR 522 }; 523 524 /* 525 * quirk list 526 */ 527 struct umidi_quirk umidi_quirklist[] = { 528 UMQ_REG(YAMAHA, YAMAHA_UX256, ANYIFACE), 529 UMQ_REG(YAMAHA, ANYPRODUCT, ANYIFACE), 530 UMQ_REG(ROLAND, ROLAND_UM1, 2), 531 UMQ_REG(ROLAND, ROLAND_SC8850, 2), 532 UMQ_REG(ROLAND, ROLAND_SD90, 2), 533 UMQ_REG(ROLAND, ROLAND_UM880N, 0), 534 UMQ_REG(ROLAND, ROLAND_UA100, 2), 535 UMQ_REG(ROLAND, ROLAND_UM4, 2), 536 UMQ_REG(ROLAND, ROLAND_U8, 2), 537 UMQ_REG(ROLAND, ROLAND_UM2, 2), 538 UMQ_REG(ROLAND, ROLAND_SC8820, 2), 539 UMQ_REG(ROLAND, ROLAND_PC300, 2), 540 UMQ_REG(ROLAND, ROLAND_SK500, 2), 541 UMQ_REG(ROLAND, ROLAND_SCD70, 2), 542 UMQ_REG(ROLAND, ROLAND_XV5050, 0), 543 UMQ_REG(ROLAND, ROLAND_UM550, 0), 544 UMQ_REG(ROLAND, ROLAND_SD20, 0), 545 UMQ_REG(ROLAND, ROLAND_SD80, 0), 546 UMQ_REG(ROLAND, ROLAND_UA700, 3), 547 UMQ_REG(ROLAND, ROLAND_UA1000, 3), 548 UMQ_REG(ROLAND, ROLAND_UA101, 2), 549 UMQ_REG(ROLAND, ROLAND_UA101F, 2), 550 UMQ_REG(ROLAND, ROLAND_FANTOMX, 0), 551 UMQ_REG(ROLAND, ROLAND_PCR, 0), 552 UMQ_REG(ROLAND, ROLAND_UM3, 0), 553 UMQ_REG(ROLAND, ROLAND_UA25, 2), 554 UMQ_REG(ROLAND, ROLAND_UA4FX, 2), 555 UMQ_REG(ROLAND, ROLAND_SONICCELL, 2), 556 UMQ_REG(MIDIMAN, MIDIMAN_MIDISPORT2X4, ANYIFACE), 557 { .vendor = 0 }, 558 }; 559 560 561 /* 562 * quirk utilities 563 */ 564 565 struct umidi_quirk * 566 umidi_search_quirk(int vendor, int product, int ifaceno) 567 { 568 struct umidi_quirk *p; 569 struct umq_data *q; 570 571 DPRINTF(("umidi_search_quirk: v=%d, p=%d, i=%d\n", 572 vendor, product, ifaceno)); 573 574 for (p=&umidi_quirklist[0]; p->vendor; p++) { 575 DPRINTFN(10, ("\tv=%d, p=%d, i=%d", 576 p->vendor, p->product, p->iface)); 577 if ((p->vendor==vendor || p->vendor==ANYVENDOR) && 578 (p->product==product || p->product==ANYPRODUCT) && 579 (p->iface==ifaceno || p->iface==ANYIFACE)) { 580 DPRINTFN(10, (" found\n")); 581 if (!p->type_mask) 582 /* make quirk mask */ 583 for (q=p->quirks; q->type; q++) 584 p->type_mask |= 1<<(q->type-1); 585 return p; 586 } 587 DPRINTFN(10, ("\n")); 588 } 589 590 return NULL; 591 } 592 593 static const char *quirk_name[] = { 594 "NULL", 595 "Fixed Endpoint", 596 "Yamaha Specific", 597 "Midiman Packet Garbling", 598 "Cable Numbers per Endpoint", 599 "Cable Numbers Global", 600 "Cable Numbers Fixed", 601 "Unit Mapping Fixed", 602 }; 603 604 void 605 umidi_print_quirk(struct umidi_quirk *q) 606 { 607 struct umq_data *qd; 608 if (q) { 609 printf("("); 610 for (qd=q->quirks; qd->type; qd++) 611 printf("%s%s", quirk_name[qd->type], 612 (qd+1)->type?", ":")\n"); 613 } else { 614 printf("(genuine USB-MIDI)\n"); 615 } 616 } 617 618 void * 619 umidi_get_quirk_data_from_type(struct umidi_quirk *q, u_int32_t type) 620 { 621 struct umq_data *qd; 622 if (q) { 623 for (qd=q->quirks; qd->type; qd++) 624 if (qd->type == type) 625 return qd->data; 626 } 627 return NULL; 628 } 629