1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * HID driver for the Prodikeys PC-MIDI Keyboard 4 * providing midi & extra multimedia keys functionality 5 * 6 * Copyright (c) 2009 Don Prince <dhprince.devel@yahoo.co.uk> 7 * 8 * Controls for Octave Shift Up/Down, Channel, and 9 * Sustain Duration available via sysfs. 10 */ 11 12 /* 13 */ 14 15 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 16 17 #include <linux/device.h> 18 #include <linux/module.h> 19 #include <linux/usb.h> 20 #include <linux/mutex.h> 21 #include <linux/hid.h> 22 #include <sound/core.h> 23 #include <sound/initval.h> 24 #include <sound/rawmidi.h> 25 #include "hid-ids.h" 26 27 28 #define pk_debug(format, arg...) \ 29 pr_debug("hid-prodikeys: " format "\n" , ## arg) 30 #define pk_error(format, arg...) \ 31 pr_err("hid-prodikeys: " format "\n" , ## arg) 32 33 struct pcmidi_snd; 34 35 struct pcmidi_sustain { 36 unsigned long in_use; 37 struct pcmidi_snd *pm; 38 struct timer_list timer; 39 unsigned char status; 40 unsigned char note; 41 unsigned char velocity; 42 }; 43 44 #define PCMIDI_SUSTAINED_MAX 32 45 struct pcmidi_snd { 46 struct hid_device *hdev; 47 unsigned short ifnum; 48 struct hid_report *pcmidi_report6; 49 struct input_dev *input_ep82; 50 unsigned short midi_mode; 51 unsigned short midi_sustain_mode; 52 unsigned short midi_sustain; 53 unsigned short midi_channel; 54 short midi_octave; 55 struct pcmidi_sustain sustained_notes[PCMIDI_SUSTAINED_MAX]; 56 unsigned short fn_state; 57 unsigned short last_key[24]; 58 spinlock_t rawmidi_in_lock; 59 struct snd_card *card; 60 struct snd_rawmidi *rwmidi; 61 struct snd_rawmidi_substream *in_substream; 62 unsigned long in_triggered; 63 }; 64 65 #define PK_QUIRK_NOGET 0x00010000 66 #define PCMIDI_MIDDLE_C 60 67 #define PCMIDI_CHANNEL_MIN 0 68 #define PCMIDI_CHANNEL_MAX 15 69 #define PCMIDI_OCTAVE_MIN (-2) 70 #define PCMIDI_OCTAVE_MAX 2 71 #define PCMIDI_SUSTAIN_MIN 0 72 #define PCMIDI_SUSTAIN_MAX 5000 73 74 static const char shortname[] = "PC-MIDI"; 75 static const char longname[] = "Prodikeys PC-MIDI Keyboard"; 76 77 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; 78 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; 79 static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; 80 81 module_param_array(index, int, NULL, 0444); 82 module_param_array(id, charp, NULL, 0444); 83 module_param_array(enable, bool, NULL, 0444); 84 MODULE_PARM_DESC(index, "Index value for the PC-MIDI virtual audio driver"); 85 MODULE_PARM_DESC(id, "ID string for the PC-MIDI virtual audio driver"); 86 MODULE_PARM_DESC(enable, "Enable for the PC-MIDI virtual audio driver"); 87 88 89 /* Output routine for the sysfs channel file */ 90 static ssize_t show_channel(struct device *dev, 91 struct device_attribute *attr, char *buf) 92 { 93 struct hid_device *hdev = to_hid_device(dev); 94 struct pcmidi_snd *pm = hid_get_drvdata(hdev); 95 96 dbg_hid("pcmidi sysfs read channel=%u\n", pm->midi_channel); 97 98 return sprintf(buf, "%u (min:%u, max:%u)\n", pm->midi_channel, 99 PCMIDI_CHANNEL_MIN, PCMIDI_CHANNEL_MAX); 100 } 101 102 /* Input routine for the sysfs channel file */ 103 static ssize_t store_channel(struct device *dev, 104 struct device_attribute *attr, const char *buf, size_t count) 105 { 106 struct hid_device *hdev = to_hid_device(dev); 107 struct pcmidi_snd *pm = hid_get_drvdata(hdev); 108 109 unsigned channel = 0; 110 111 if (sscanf(buf, "%u", &channel) > 0 && channel <= PCMIDI_CHANNEL_MAX) { 112 dbg_hid("pcmidi sysfs write channel=%u\n", channel); 113 pm->midi_channel = channel; 114 return strlen(buf); 115 } 116 return -EINVAL; 117 } 118 119 static DEVICE_ATTR(channel, S_IRUGO | S_IWUSR | S_IWGRP , show_channel, 120 store_channel); 121 122 static struct device_attribute *sysfs_device_attr_channel = { 123 &dev_attr_channel, 124 }; 125 126 /* Output routine for the sysfs sustain file */ 127 static ssize_t show_sustain(struct device *dev, 128 struct device_attribute *attr, char *buf) 129 { 130 struct hid_device *hdev = to_hid_device(dev); 131 struct pcmidi_snd *pm = hid_get_drvdata(hdev); 132 133 dbg_hid("pcmidi sysfs read sustain=%u\n", pm->midi_sustain); 134 135 return sprintf(buf, "%u (off:%u, max:%u (ms))\n", pm->midi_sustain, 136 PCMIDI_SUSTAIN_MIN, PCMIDI_SUSTAIN_MAX); 137 } 138 139 /* Input routine for the sysfs sustain file */ 140 static ssize_t store_sustain(struct device *dev, 141 struct device_attribute *attr, const char *buf, size_t count) 142 { 143 struct hid_device *hdev = to_hid_device(dev); 144 struct pcmidi_snd *pm = hid_get_drvdata(hdev); 145 146 unsigned sustain = 0; 147 148 if (sscanf(buf, "%u", &sustain) > 0 && sustain <= PCMIDI_SUSTAIN_MAX) { 149 dbg_hid("pcmidi sysfs write sustain=%u\n", sustain); 150 pm->midi_sustain = sustain; 151 pm->midi_sustain_mode = (0 == sustain || !pm->midi_mode) ? 0 : 1; 152 return strlen(buf); 153 } 154 return -EINVAL; 155 } 156 157 static DEVICE_ATTR(sustain, S_IRUGO | S_IWUSR | S_IWGRP, show_sustain, 158 store_sustain); 159 160 static struct device_attribute *sysfs_device_attr_sustain = { 161 &dev_attr_sustain, 162 }; 163 164 /* Output routine for the sysfs octave file */ 165 static ssize_t show_octave(struct device *dev, 166 struct device_attribute *attr, char *buf) 167 { 168 struct hid_device *hdev = to_hid_device(dev); 169 struct pcmidi_snd *pm = hid_get_drvdata(hdev); 170 171 dbg_hid("pcmidi sysfs read octave=%d\n", pm->midi_octave); 172 173 return sprintf(buf, "%d (min:%d, max:%d)\n", pm->midi_octave, 174 PCMIDI_OCTAVE_MIN, PCMIDI_OCTAVE_MAX); 175 } 176 177 /* Input routine for the sysfs octave file */ 178 static ssize_t store_octave(struct device *dev, 179 struct device_attribute *attr, const char *buf, size_t count) 180 { 181 struct hid_device *hdev = to_hid_device(dev); 182 struct pcmidi_snd *pm = hid_get_drvdata(hdev); 183 184 int octave = 0; 185 186 if (sscanf(buf, "%d", &octave) > 0 && 187 octave >= PCMIDI_OCTAVE_MIN && octave <= PCMIDI_OCTAVE_MAX) { 188 dbg_hid("pcmidi sysfs write octave=%d\n", octave); 189 pm->midi_octave = octave; 190 return strlen(buf); 191 } 192 return -EINVAL; 193 } 194 195 static DEVICE_ATTR(octave, S_IRUGO | S_IWUSR | S_IWGRP, show_octave, 196 store_octave); 197 198 static struct device_attribute *sysfs_device_attr_octave = { 199 &dev_attr_octave, 200 }; 201 202 203 static void pcmidi_send_note(struct pcmidi_snd *pm, 204 unsigned char status, unsigned char note, unsigned char velocity) 205 { 206 unsigned long flags; 207 unsigned char buffer[3]; 208 209 buffer[0] = status; 210 buffer[1] = note; 211 buffer[2] = velocity; 212 213 spin_lock_irqsave(&pm->rawmidi_in_lock, flags); 214 215 if (!pm->in_substream) 216 goto drop_note; 217 if (!test_bit(pm->in_substream->number, &pm->in_triggered)) 218 goto drop_note; 219 220 snd_rawmidi_receive(pm->in_substream, buffer, 3); 221 222 drop_note: 223 spin_unlock_irqrestore(&pm->rawmidi_in_lock, flags); 224 225 return; 226 } 227 228 static void pcmidi_sustained_note_release(struct timer_list *t) 229 { 230 struct pcmidi_sustain *pms = timer_container_of(pms, t, timer); 231 232 pcmidi_send_note(pms->pm, pms->status, pms->note, pms->velocity); 233 pms->in_use = 0; 234 } 235 236 static void init_sustain_timers(struct pcmidi_snd *pm) 237 { 238 struct pcmidi_sustain *pms; 239 unsigned i; 240 241 for (i = 0; i < PCMIDI_SUSTAINED_MAX; i++) { 242 pms = &pm->sustained_notes[i]; 243 pms->in_use = 0; 244 pms->pm = pm; 245 timer_setup(&pms->timer, pcmidi_sustained_note_release, 0); 246 } 247 } 248 249 static void stop_sustain_timers(struct pcmidi_snd *pm) 250 { 251 struct pcmidi_sustain *pms; 252 unsigned i; 253 254 for (i = 0; i < PCMIDI_SUSTAINED_MAX; i++) { 255 pms = &pm->sustained_notes[i]; 256 pms->in_use = 1; 257 timer_delete_sync(&pms->timer); 258 } 259 } 260 261 static int pcmidi_get_output_report(struct pcmidi_snd *pm) 262 { 263 struct hid_device *hdev = pm->hdev; 264 struct hid_report *report; 265 266 list_for_each_entry(report, 267 &hdev->report_enum[HID_OUTPUT_REPORT].report_list, list) { 268 if (!(6 == report->id)) 269 continue; 270 271 if (report->maxfield < 1) { 272 hid_err(hdev, "output report is empty\n"); 273 break; 274 } 275 if (report->field[0]->report_count != 2) { 276 hid_err(hdev, "field count too low\n"); 277 break; 278 } 279 pm->pcmidi_report6 = report; 280 return 0; 281 } 282 /* should never get here */ 283 return -ENODEV; 284 } 285 286 static void pcmidi_submit_output_report(struct pcmidi_snd *pm, int state) 287 { 288 struct hid_device *hdev = pm->hdev; 289 struct hid_report *report = pm->pcmidi_report6; 290 report->field[0]->value[0] = 0x01; 291 report->field[0]->value[1] = state; 292 293 hid_hw_request(hdev, report, HID_REQ_SET_REPORT); 294 } 295 296 static int pcmidi_handle_report1(struct pcmidi_snd *pm, u8 *data) 297 { 298 u32 bit_mask; 299 300 bit_mask = data[1]; 301 bit_mask = (bit_mask << 8) | data[2]; 302 bit_mask = (bit_mask << 8) | data[3]; 303 304 dbg_hid("pcmidi mode: %d\n", pm->midi_mode); 305 306 /*KEY_MAIL or octave down*/ 307 if (pm->midi_mode && bit_mask == 0x004000) { 308 /* octave down */ 309 pm->midi_octave--; 310 if (pm->midi_octave < -2) 311 pm->midi_octave = -2; 312 dbg_hid("pcmidi mode: %d octave: %d\n", 313 pm->midi_mode, pm->midi_octave); 314 return 1; 315 } 316 /*KEY_WWW or sustain*/ 317 else if (pm->midi_mode && bit_mask == 0x000004) { 318 /* sustain on/off*/ 319 pm->midi_sustain_mode ^= 0x1; 320 return 1; 321 } 322 323 return 0; /* continue key processing */ 324 } 325 326 static int pcmidi_handle_report3(struct pcmidi_snd *pm, u8 *data, int size) 327 { 328 struct pcmidi_sustain *pms; 329 unsigned i, j; 330 unsigned char status, note, velocity; 331 332 unsigned num_notes = (size-1)/2; 333 for (j = 0; j < num_notes; j++) { 334 note = data[j*2+1]; 335 velocity = data[j*2+2]; 336 337 if (note < 0x81) { /* note on */ 338 status = 128 + 16 + pm->midi_channel; /* 1001nnnn */ 339 note = note - 0x54 + PCMIDI_MIDDLE_C + 340 (pm->midi_octave * 12); 341 if (0 == velocity) 342 velocity = 1; /* force note on */ 343 } else { /* note off */ 344 status = 128 + pm->midi_channel; /* 1000nnnn */ 345 note = note - 0x94 + PCMIDI_MIDDLE_C + 346 (pm->midi_octave*12); 347 348 if (pm->midi_sustain_mode) { 349 for (i = 0; i < PCMIDI_SUSTAINED_MAX; i++) { 350 pms = &pm->sustained_notes[i]; 351 if (!pms->in_use) { 352 pms->status = status; 353 pms->note = note; 354 pms->velocity = velocity; 355 pms->in_use = 1; 356 357 mod_timer(&pms->timer, 358 jiffies + 359 msecs_to_jiffies(pm->midi_sustain)); 360 return 1; 361 } 362 } 363 } 364 } 365 pcmidi_send_note(pm, status, note, velocity); 366 } 367 368 return 1; 369 } 370 371 static int pcmidi_handle_report4(struct pcmidi_snd *pm, u8 *data) 372 { 373 unsigned key; 374 u32 bit_mask; 375 u32 bit_index; 376 377 bit_mask = data[1]; 378 bit_mask = (bit_mask << 8) | data[2]; 379 bit_mask = (bit_mask << 8) | data[3]; 380 381 /* robustness in case input_mapping hook does not get called */ 382 if (!pm->input_ep82) 383 return 0; 384 385 /* break keys */ 386 for (bit_index = 0; bit_index < 24; bit_index++) { 387 if (!((0x01 << bit_index) & bit_mask)) { 388 input_event(pm->input_ep82, EV_KEY, 389 pm->last_key[bit_index], 0); 390 pm->last_key[bit_index] = 0; 391 } 392 } 393 394 /* make keys */ 395 for (bit_index = 0; bit_index < 24; bit_index++) { 396 key = 0; 397 switch ((0x01 << bit_index) & bit_mask) { 398 case 0x000010: /* Fn lock*/ 399 pm->fn_state ^= 0x000010; 400 if (pm->fn_state) 401 pcmidi_submit_output_report(pm, 0xc5); 402 else 403 pcmidi_submit_output_report(pm, 0xc6); 404 continue; 405 case 0x020000: /* midi launcher..send a key (qwerty) or not? */ 406 pcmidi_submit_output_report(pm, 0xc1); 407 pm->midi_mode ^= 0x01; 408 409 dbg_hid("pcmidi mode: %d\n", pm->midi_mode); 410 continue; 411 case 0x100000: /* KEY_MESSENGER or octave up */ 412 dbg_hid("pcmidi mode: %d\n", pm->midi_mode); 413 if (pm->midi_mode) { 414 pm->midi_octave++; 415 if (pm->midi_octave > 2) 416 pm->midi_octave = 2; 417 dbg_hid("pcmidi mode: %d octave: %d\n", 418 pm->midi_mode, pm->midi_octave); 419 continue; 420 } else 421 key = KEY_MESSENGER; 422 break; 423 case 0x400000: 424 key = KEY_CALENDAR; 425 break; 426 case 0x080000: 427 key = KEY_ADDRESSBOOK; 428 break; 429 case 0x040000: 430 key = KEY_DOCUMENTS; 431 break; 432 case 0x800000: 433 key = KEY_WORDPROCESSOR; 434 break; 435 case 0x200000: 436 key = KEY_SPREADSHEET; 437 break; 438 case 0x010000: 439 key = KEY_COFFEE; 440 break; 441 case 0x000100: 442 key = KEY_HELP; 443 break; 444 case 0x000200: 445 key = KEY_SEND; 446 break; 447 case 0x000400: 448 key = KEY_REPLY; 449 break; 450 case 0x000800: 451 key = KEY_FORWARDMAIL; 452 break; 453 case 0x001000: 454 key = KEY_NEW; 455 break; 456 case 0x002000: 457 key = KEY_OPEN; 458 break; 459 case 0x004000: 460 key = KEY_CLOSE; 461 break; 462 case 0x008000: 463 key = KEY_SAVE; 464 break; 465 case 0x000001: 466 key = KEY_UNDO; 467 break; 468 case 0x000002: 469 key = KEY_REDO; 470 break; 471 case 0x000004: 472 key = KEY_SPELLCHECK; 473 break; 474 case 0x000008: 475 key = KEY_PRINT; 476 break; 477 } 478 if (key) { 479 input_event(pm->input_ep82, EV_KEY, key, 1); 480 pm->last_key[bit_index] = key; 481 } 482 } 483 484 return 1; 485 } 486 487 static int pcmidi_handle_report( 488 struct pcmidi_snd *pm, unsigned report_id, u8 *data, int size) 489 { 490 int ret = 0; 491 492 switch (report_id) { 493 case 0x01: /* midi keys (qwerty)*/ 494 ret = pcmidi_handle_report1(pm, data); 495 break; 496 case 0x03: /* midi keyboard (musical)*/ 497 ret = pcmidi_handle_report3(pm, data, size); 498 break; 499 case 0x04: /* multimedia/midi keys (qwerty)*/ 500 ret = pcmidi_handle_report4(pm, data); 501 break; 502 } 503 return ret; 504 } 505 506 static void pcmidi_setup_extra_keys( 507 struct pcmidi_snd *pm, struct input_dev *input) 508 { 509 /* reassigned functionality for N/A keys 510 MY PICTURES => KEY_WORDPROCESSOR 511 MY MUSIC=> KEY_SPREADSHEET 512 */ 513 static const unsigned int keys[] = { 514 KEY_FN, 515 KEY_MESSENGER, KEY_CALENDAR, 516 KEY_ADDRESSBOOK, KEY_DOCUMENTS, 517 KEY_WORDPROCESSOR, 518 KEY_SPREADSHEET, 519 KEY_COFFEE, 520 KEY_HELP, KEY_SEND, 521 KEY_REPLY, KEY_FORWARDMAIL, 522 KEY_NEW, KEY_OPEN, 523 KEY_CLOSE, KEY_SAVE, 524 KEY_UNDO, KEY_REDO, 525 KEY_SPELLCHECK, KEY_PRINT, 526 0 527 }; 528 529 const unsigned int *pkeys = &keys[0]; 530 unsigned short i; 531 532 if (pm->ifnum != 1) /* only set up ONCE for interace 1 */ 533 return; 534 535 pm->input_ep82 = input; 536 537 for (i = 0; i < 24; i++) 538 pm->last_key[i] = 0; 539 540 while (*pkeys != 0) { 541 set_bit(*pkeys, pm->input_ep82->keybit); 542 ++pkeys; 543 } 544 } 545 546 static int pcmidi_set_operational(struct pcmidi_snd *pm) 547 { 548 int rc; 549 550 if (pm->ifnum != 1) 551 return 0; /* only set up ONCE for interace 1 */ 552 553 rc = pcmidi_get_output_report(pm); 554 if (rc < 0) 555 return rc; 556 pcmidi_submit_output_report(pm, 0xc1); 557 return 0; 558 } 559 560 static int pcmidi_snd_free(struct snd_device *dev) 561 { 562 return 0; 563 } 564 565 static int pcmidi_in_open(struct snd_rawmidi_substream *substream) 566 { 567 struct pcmidi_snd *pm = substream->rmidi->private_data; 568 569 dbg_hid("pcmidi in open\n"); 570 pm->in_substream = substream; 571 return 0; 572 } 573 574 static int pcmidi_in_close(struct snd_rawmidi_substream *substream) 575 { 576 dbg_hid("pcmidi in close\n"); 577 return 0; 578 } 579 580 static void pcmidi_in_trigger(struct snd_rawmidi_substream *substream, int up) 581 { 582 struct pcmidi_snd *pm = substream->rmidi->private_data; 583 584 dbg_hid("pcmidi in trigger %d\n", up); 585 586 pm->in_triggered = up; 587 } 588 589 static const struct snd_rawmidi_ops pcmidi_in_ops = { 590 .open = pcmidi_in_open, 591 .close = pcmidi_in_close, 592 .trigger = pcmidi_in_trigger 593 }; 594 595 static int pcmidi_snd_initialise(struct pcmidi_snd *pm) 596 { 597 static int dev; 598 struct snd_card *card; 599 struct snd_rawmidi *rwmidi; 600 int err; 601 602 static struct snd_device_ops ops = { 603 .dev_free = pcmidi_snd_free, 604 }; 605 606 if (pm->ifnum != 1) 607 return 0; /* only set up midi device ONCE for interace 1 */ 608 609 if (dev >= SNDRV_CARDS) 610 return -ENODEV; 611 612 if (!enable[dev]) { 613 dev++; 614 return -ENOENT; 615 } 616 617 /* Setup sound card */ 618 619 err = snd_card_new(&pm->hdev->dev, index[dev], id[dev], 620 THIS_MODULE, 0, &card); 621 if (err < 0) { 622 pk_error("failed to create pc-midi sound card\n"); 623 err = -ENOMEM; 624 goto fail; 625 } 626 pm->card = card; 627 628 /* Setup sound device */ 629 err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, pm, &ops); 630 if (err < 0) { 631 pk_error("failed to create pc-midi sound device: error %d\n", 632 err); 633 goto fail; 634 } 635 636 strscpy(card->driver, shortname, sizeof(card->driver)); 637 strscpy(card->shortname, shortname, sizeof(card->shortname)); 638 strscpy(card->longname, longname, sizeof(card->longname)); 639 640 /* Set up rawmidi */ 641 err = snd_rawmidi_new(card, card->shortname, 0, 642 0, 1, &rwmidi); 643 if (err < 0) { 644 pk_error("failed to create pc-midi rawmidi device: error %d\n", 645 err); 646 goto fail; 647 } 648 pm->rwmidi = rwmidi; 649 strscpy(rwmidi->name, card->shortname, sizeof(rwmidi->name)); 650 rwmidi->info_flags = SNDRV_RAWMIDI_INFO_INPUT; 651 rwmidi->private_data = pm; 652 653 snd_rawmidi_set_ops(rwmidi, SNDRV_RAWMIDI_STREAM_INPUT, 654 &pcmidi_in_ops); 655 656 /* create sysfs variables */ 657 err = device_create_file(&pm->hdev->dev, 658 sysfs_device_attr_channel); 659 if (err < 0) { 660 pk_error("failed to create sysfs attribute channel: error %d\n", 661 err); 662 goto fail; 663 } 664 665 err = device_create_file(&pm->hdev->dev, 666 sysfs_device_attr_sustain); 667 if (err < 0) { 668 pk_error("failed to create sysfs attribute sustain: error %d\n", 669 err); 670 goto fail_attr_sustain; 671 } 672 673 err = device_create_file(&pm->hdev->dev, 674 sysfs_device_attr_octave); 675 if (err < 0) { 676 pk_error("failed to create sysfs attribute octave: error %d\n", 677 err); 678 goto fail_attr_octave; 679 } 680 681 spin_lock_init(&pm->rawmidi_in_lock); 682 683 init_sustain_timers(pm); 684 err = pcmidi_set_operational(pm); 685 if (err < 0) { 686 pk_error("failed to find output report\n"); 687 goto fail_register; 688 } 689 690 /* register it */ 691 err = snd_card_register(card); 692 if (err < 0) { 693 pk_error("failed to register pc-midi sound card: error %d\n", 694 err); 695 goto fail_register; 696 } 697 698 dbg_hid("pcmidi_snd_initialise finished ok\n"); 699 return 0; 700 701 fail_register: 702 stop_sustain_timers(pm); 703 device_remove_file(&pm->hdev->dev, sysfs_device_attr_octave); 704 fail_attr_octave: 705 device_remove_file(&pm->hdev->dev, sysfs_device_attr_sustain); 706 fail_attr_sustain: 707 device_remove_file(&pm->hdev->dev, sysfs_device_attr_channel); 708 fail: 709 if (pm->card) { 710 snd_card_free(pm->card); 711 pm->card = NULL; 712 } 713 return err; 714 } 715 716 static int pcmidi_snd_terminate(struct pcmidi_snd *pm) 717 { 718 if (pm->card) { 719 stop_sustain_timers(pm); 720 721 device_remove_file(&pm->hdev->dev, sysfs_device_attr_channel); 722 device_remove_file(&pm->hdev->dev, sysfs_device_attr_sustain); 723 device_remove_file(&pm->hdev->dev, sysfs_device_attr_octave); 724 725 snd_card_disconnect(pm->card); 726 snd_card_free_when_closed(pm->card); 727 } 728 729 return 0; 730 } 731 732 /* 733 * PC-MIDI report descriptor for report id is wrong. 734 */ 735 static const __u8 *pk_report_fixup(struct hid_device *hdev, __u8 *rdesc, 736 unsigned int *rsize) 737 { 738 if (*rsize == 178 && 739 rdesc[111] == 0x06 && rdesc[112] == 0x00 && 740 rdesc[113] == 0xff) { 741 hid_info(hdev, 742 "fixing up pc-midi keyboard report descriptor\n"); 743 744 rdesc[144] = 0x18; /* report 4: was 0x10 report count */ 745 } 746 return rdesc; 747 } 748 749 static int pk_input_mapping(struct hid_device *hdev, struct hid_input *hi, 750 struct hid_field *field, struct hid_usage *usage, 751 unsigned long **bit, int *max) 752 { 753 struct pcmidi_snd *pm = hid_get_drvdata(hdev); 754 755 if (HID_UP_MSVENDOR == (usage->hid & HID_USAGE_PAGE) && 756 1 == pm->ifnum) { 757 pcmidi_setup_extra_keys(pm, hi->input); 758 return 0; 759 } 760 761 return 0; 762 } 763 764 765 static int pk_raw_event(struct hid_device *hdev, struct hid_report *report, 766 u8 *data, int size) 767 { 768 struct pcmidi_snd *pm = hid_get_drvdata(hdev); 769 int ret = 0; 770 771 if (1 == pm->ifnum) { 772 if (report->id == data[0]) 773 switch (report->id) { 774 case 0x01: /* midi keys (qwerty)*/ 775 case 0x03: /* midi keyboard (musical)*/ 776 case 0x04: /* extra/midi keys (qwerty)*/ 777 ret = pcmidi_handle_report(pm, 778 report->id, data, size); 779 break; 780 } 781 } 782 783 return ret; 784 } 785 786 static int pk_probe(struct hid_device *hdev, const struct hid_device_id *id) 787 { 788 int ret; 789 struct usb_interface *intf; 790 unsigned short ifnum; 791 unsigned long quirks = id->driver_data; 792 struct pcmidi_snd *pm; 793 794 if (!hid_is_usb(hdev)) 795 return -EINVAL; 796 797 intf = to_usb_interface(hdev->dev.parent); 798 ifnum = intf->cur_altsetting->desc.bInterfaceNumber; 799 800 pm = kzalloc(sizeof(*pm), GFP_KERNEL); 801 if (pm == NULL) { 802 hid_err(hdev, "can't alloc descriptor\n"); 803 return -ENOMEM; 804 } 805 806 pm->hdev = hdev; 807 pm->ifnum = ifnum; 808 809 hid_set_drvdata(hdev, pm); 810 811 ret = hid_parse(hdev); 812 if (ret) { 813 hid_err(hdev, "hid parse failed\n"); 814 goto err_free; 815 } 816 817 if (quirks & PK_QUIRK_NOGET) { /* hid_parse cleared all the quirks */ 818 hdev->quirks |= HID_QUIRK_NOGET; 819 } 820 821 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); 822 if (ret) { 823 hid_err(hdev, "hw start failed\n"); 824 goto err_free; 825 } 826 827 ret = pcmidi_snd_initialise(pm); 828 if (ret < 0) 829 goto err_stop; 830 831 return 0; 832 err_stop: 833 hid_hw_stop(hdev); 834 err_free: 835 kfree(pm); 836 837 return ret; 838 } 839 840 static void pk_remove(struct hid_device *hdev) 841 { 842 struct pcmidi_snd *pm = hid_get_drvdata(hdev); 843 844 pcmidi_snd_terminate(pm); 845 hid_hw_stop(hdev); 846 847 kfree(pm); 848 } 849 850 static const struct hid_device_id pk_devices[] = { 851 {HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, 852 USB_DEVICE_ID_PRODIKEYS_PCMIDI), 853 .driver_data = PK_QUIRK_NOGET}, 854 { } 855 }; 856 MODULE_DEVICE_TABLE(hid, pk_devices); 857 858 static struct hid_driver pk_driver = { 859 .name = "prodikeys", 860 .id_table = pk_devices, 861 .report_fixup = pk_report_fixup, 862 .input_mapping = pk_input_mapping, 863 .raw_event = pk_raw_event, 864 .probe = pk_probe, 865 .remove = pk_remove, 866 }; 867 module_hid_driver(pk_driver); 868 869 MODULE_DESCRIPTION("HID driver for the Prodikeys PC-MIDI Keyboard"); 870 MODULE_LICENSE("GPL"); 871