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