root/drivers/hid/hid-prodikeys.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. show_channel
  2. store_channel
  3. show_sustain
  4. store_sustain
  5. show_octave
  6. store_octave
  7. pcmidi_send_note
  8. pcmidi_sustained_note_release
  9. init_sustain_timers
  10. stop_sustain_timers
  11. pcmidi_get_output_report
  12. pcmidi_submit_output_report
  13. pcmidi_handle_report1
  14. pcmidi_handle_report3
  15. pcmidi_handle_report4
  16. pcmidi_handle_report
  17. pcmidi_setup_extra_keys
  18. pcmidi_set_operational
  19. pcmidi_snd_free
  20. pcmidi_in_open
  21. pcmidi_in_close
  22. pcmidi_in_trigger
  23. pcmidi_snd_initialise
  24. pcmidi_snd_terminate
  25. pk_report_fixup
  26. pk_input_mapping
  27. pk_raw_event
  28. pk_probe
  29. pk_remove

   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 pk_device {
  36         unsigned long           quirks;
  37 
  38         struct hid_device       *hdev;
  39         struct pcmidi_snd       *pm; /* pcmidi device context */
  40 };
  41 
  42 struct 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
  52 struct 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 
  83 static const char shortname[] = "PC-MIDI";
  84 static const char longname[] = "Prodikeys PC-MIDI Keyboard";
  85 
  86 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
  87 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
  88 static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
  89 
  90 module_param_array(index, int, NULL, 0444);
  91 module_param_array(id, charp, NULL, 0444);
  92 module_param_array(enable, bool, NULL, 0444);
  93 MODULE_PARM_DESC(index, "Index value for the PC-MIDI virtual audio driver");
  94 MODULE_PARM_DESC(id, "ID string for the PC-MIDI virtual audio driver");
  95 MODULE_PARM_DESC(enable, "Enable for the PC-MIDI virtual audio driver");
  96 
  97 
  98 /* Output routine for the sysfs channel file */
  99 static 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 */
 112 static 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 
 128 static DEVICE_ATTR(channel, S_IRUGO | S_IWUSR | S_IWGRP , show_channel,
 129                 store_channel);
 130 
 131 static struct device_attribute *sysfs_device_attr_channel = {
 132                 &dev_attr_channel,
 133                 };
 134 
 135 /* Output routine for the sysfs sustain file */
 136 static 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 */
 149 static 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 
 167 static DEVICE_ATTR(sustain, S_IRUGO | S_IWUSR | S_IWGRP, show_sustain,
 168                 store_sustain);
 169 
 170 static struct device_attribute *sysfs_device_attr_sustain = {
 171                 &dev_attr_sustain,
 172                 };
 173 
 174 /* Output routine for the sysfs octave file */
 175 static 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 */
 188 static 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 
 205 static DEVICE_ATTR(octave, S_IRUGO | S_IWUSR | S_IWGRP, show_octave,
 206                 store_octave);
 207 
 208 static struct device_attribute *sysfs_device_attr_octave = {
 209                 &dev_attr_octave,
 210                 };
 211 
 212 
 213 static 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 
 232 drop_note:
 233         spin_unlock_irqrestore(&pm->rawmidi_in_lock, flags);
 234 
 235         return;
 236 }
 237 
 238 static 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 
 246 static 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 
 259 static 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 
 271 static 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 
 296 static 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 
 306 static 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 
 336 static 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 
 381 static 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 
 493 static 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 
 512 static 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 
 552 static 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 
 566 static int pcmidi_snd_free(struct snd_device *dev)
 567 {
 568         return 0;
 569 }
 570 
 571 static 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 
 580 static int pcmidi_in_close(struct snd_rawmidi_substream *substream)
 581 {
 582         dbg_hid("pcmidi in close\n");
 583         return 0;
 584 }
 585 
 586 static 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 
 595 static 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 
 601 static 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 
 707 fail_register:
 708         stop_sustain_timers(pm);
 709         device_remove_file(&pm->pk->hdev->dev, sysfs_device_attr_octave);
 710 fail_attr_octave:
 711         device_remove_file(&pm->pk->hdev->dev, sysfs_device_attr_sustain);
 712 fail_attr_sustain:
 713         device_remove_file(&pm->pk->hdev->dev, sysfs_device_attr_channel);
 714 fail:
 715         if (pm->card) {
 716                 snd_card_free(pm->card);
 717                 pm->card = NULL;
 718         }
 719         return err;
 720 }
 721 
 722 static 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  */
 744 static __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 
 758 static 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 
 777 static 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 
 798 static int pk_probe(struct hid_device *hdev, const struct hid_device_id *id)
 799 {
 800         int ret;
 801         struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
 802         unsigned short ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
 803         unsigned long quirks = id->driver_data;
 804         struct pk_device *pk;
 805         struct pcmidi_snd *pm = NULL;
 806 
 807         pk = kzalloc(sizeof(*pk), GFP_KERNEL);
 808         if (pk == NULL) {
 809                 hid_err(hdev, "can't alloc descriptor\n");
 810                 return -ENOMEM;
 811         }
 812 
 813         pk->hdev = hdev;
 814 
 815         pm = kzalloc(sizeof(*pm), GFP_KERNEL);
 816         if (pm == NULL) {
 817                 hid_err(hdev, "can't alloc descriptor\n");
 818                 ret = -ENOMEM;
 819                 goto err_free_pk;
 820         }
 821 
 822         pm->pk = pk;
 823         pk->pm = pm;
 824         pm->ifnum = ifnum;
 825 
 826         hid_set_drvdata(hdev, pk);
 827 
 828         ret = hid_parse(hdev);
 829         if (ret) {
 830                 hid_err(hdev, "hid parse failed\n");
 831                 goto err_free;
 832         }
 833 
 834         if (quirks & PK_QUIRK_NOGET) { /* hid_parse cleared all the quirks */
 835                 hdev->quirks |= HID_QUIRK_NOGET;
 836         }
 837 
 838         ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
 839         if (ret) {
 840                 hid_err(hdev, "hw start failed\n");
 841                 goto err_free;
 842         }
 843 
 844         ret = pcmidi_snd_initialise(pm);
 845         if (ret < 0)
 846                 goto err_stop;
 847 
 848         return 0;
 849 err_stop:
 850         hid_hw_stop(hdev);
 851 err_free:
 852         kfree(pm);
 853 err_free_pk:
 854         kfree(pk);
 855 
 856         return ret;
 857 }
 858 
 859 static void pk_remove(struct hid_device *hdev)
 860 {
 861         struct pk_device *pk = hid_get_drvdata(hdev);
 862         struct pcmidi_snd *pm;
 863 
 864         pm = pk->pm;
 865         if (pm) {
 866                 pcmidi_snd_terminate(pm);
 867                 kfree(pm);
 868         }
 869 
 870         hid_hw_stop(hdev);
 871 
 872         kfree(pk);
 873 }
 874 
 875 static const struct hid_device_id pk_devices[] = {
 876         {HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS,
 877                 USB_DEVICE_ID_PRODIKEYS_PCMIDI),
 878             .driver_data = PK_QUIRK_NOGET},
 879         { }
 880 };
 881 MODULE_DEVICE_TABLE(hid, pk_devices);
 882 
 883 static struct hid_driver pk_driver = {
 884         .name = "prodikeys",
 885         .id_table = pk_devices,
 886         .report_fixup = pk_report_fixup,
 887         .input_mapping = pk_input_mapping,
 888         .raw_event = pk_raw_event,
 889         .probe = pk_probe,
 890         .remove = pk_remove,
 891 };
 892 module_hid_driver(pk_driver);
 893 
 894 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */