0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0016
0017 #include <linux/device.h>
0018 #include <linux/module.h>
0019 #include <linux/usb.h>
0020 #include <linux/mutex.h>
0021 #include <linux/hid.h>
0022 #include <sound/core.h>
0023 #include <sound/initval.h>
0024 #include <sound/rawmidi.h>
0025 #include "hid-ids.h"
0026
0027
0028 #define pk_debug(format, arg...) \
0029 pr_debug("hid-prodikeys: " format "\n" , ## arg)
0030 #define pk_error(format, arg...) \
0031 pr_err("hid-prodikeys: " format "\n" , ## arg)
0032
0033 struct pcmidi_snd;
0034
0035 struct pk_device {
0036 unsigned long quirks;
0037
0038 struct hid_device *hdev;
0039 struct pcmidi_snd *pm;
0040 };
0041
0042 struct pcmidi_sustain {
0043 unsigned long in_use;
0044 struct pcmidi_snd *pm;
0045 struct timer_list timer;
0046 unsigned char status;
0047 unsigned char note;
0048 unsigned char velocity;
0049 };
0050
0051 #define PCMIDI_SUSTAINED_MAX 32
0052 struct pcmidi_snd {
0053 struct pk_device *pk;
0054 unsigned short ifnum;
0055 struct hid_report *pcmidi_report6;
0056 struct input_dev *input_ep82;
0057 unsigned short midi_mode;
0058 unsigned short midi_sustain_mode;
0059 unsigned short midi_sustain;
0060 unsigned short midi_channel;
0061 short midi_octave;
0062 struct pcmidi_sustain sustained_notes[PCMIDI_SUSTAINED_MAX];
0063 unsigned short fn_state;
0064 unsigned short last_key[24];
0065 spinlock_t rawmidi_in_lock;
0066 struct snd_card *card;
0067 struct snd_rawmidi *rwmidi;
0068 struct snd_rawmidi_substream *in_substream;
0069 struct snd_rawmidi_substream *out_substream;
0070 unsigned long in_triggered;
0071 unsigned long out_active;
0072 };
0073
0074 #define PK_QUIRK_NOGET 0x00010000
0075 #define PCMIDI_MIDDLE_C 60
0076 #define PCMIDI_CHANNEL_MIN 0
0077 #define PCMIDI_CHANNEL_MAX 15
0078 #define PCMIDI_OCTAVE_MIN (-2)
0079 #define PCMIDI_OCTAVE_MAX 2
0080 #define PCMIDI_SUSTAIN_MIN 0
0081 #define PCMIDI_SUSTAIN_MAX 5000
0082
0083 static const char shortname[] = "PC-MIDI";
0084 static const char longname[] = "Prodikeys PC-MIDI Keyboard";
0085
0086 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
0087 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
0088 static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
0089
0090 module_param_array(index, int, NULL, 0444);
0091 module_param_array(id, charp, NULL, 0444);
0092 module_param_array(enable, bool, NULL, 0444);
0093 MODULE_PARM_DESC(index, "Index value for the PC-MIDI virtual audio driver");
0094 MODULE_PARM_DESC(id, "ID string for the PC-MIDI virtual audio driver");
0095 MODULE_PARM_DESC(enable, "Enable for the PC-MIDI virtual audio driver");
0096
0097
0098
0099 static ssize_t show_channel(struct device *dev,
0100 struct device_attribute *attr, char *buf)
0101 {
0102 struct hid_device *hdev = to_hid_device(dev);
0103 struct pk_device *pk = hid_get_drvdata(hdev);
0104
0105 dbg_hid("pcmidi sysfs read channel=%u\n", pk->pm->midi_channel);
0106
0107 return sprintf(buf, "%u (min:%u, max:%u)\n", pk->pm->midi_channel,
0108 PCMIDI_CHANNEL_MIN, PCMIDI_CHANNEL_MAX);
0109 }
0110
0111
0112 static ssize_t store_channel(struct device *dev,
0113 struct device_attribute *attr, const char *buf, size_t count)
0114 {
0115 struct hid_device *hdev = to_hid_device(dev);
0116 struct pk_device *pk = hid_get_drvdata(hdev);
0117
0118 unsigned channel = 0;
0119
0120 if (sscanf(buf, "%u", &channel) > 0 && channel <= PCMIDI_CHANNEL_MAX) {
0121 dbg_hid("pcmidi sysfs write channel=%u\n", channel);
0122 pk->pm->midi_channel = channel;
0123 return strlen(buf);
0124 }
0125 return -EINVAL;
0126 }
0127
0128 static DEVICE_ATTR(channel, S_IRUGO | S_IWUSR | S_IWGRP , show_channel,
0129 store_channel);
0130
0131 static struct device_attribute *sysfs_device_attr_channel = {
0132 &dev_attr_channel,
0133 };
0134
0135
0136 static ssize_t show_sustain(struct device *dev,
0137 struct device_attribute *attr, char *buf)
0138 {
0139 struct hid_device *hdev = to_hid_device(dev);
0140 struct pk_device *pk = hid_get_drvdata(hdev);
0141
0142 dbg_hid("pcmidi sysfs read sustain=%u\n", pk->pm->midi_sustain);
0143
0144 return sprintf(buf, "%u (off:%u, max:%u (ms))\n", pk->pm->midi_sustain,
0145 PCMIDI_SUSTAIN_MIN, PCMIDI_SUSTAIN_MAX);
0146 }
0147
0148
0149 static ssize_t store_sustain(struct device *dev,
0150 struct device_attribute *attr, const char *buf, size_t count)
0151 {
0152 struct hid_device *hdev = to_hid_device(dev);
0153 struct pk_device *pk = hid_get_drvdata(hdev);
0154
0155 unsigned sustain = 0;
0156
0157 if (sscanf(buf, "%u", &sustain) > 0 && sustain <= PCMIDI_SUSTAIN_MAX) {
0158 dbg_hid("pcmidi sysfs write sustain=%u\n", sustain);
0159 pk->pm->midi_sustain = sustain;
0160 pk->pm->midi_sustain_mode =
0161 (0 == sustain || !pk->pm->midi_mode) ? 0 : 1;
0162 return strlen(buf);
0163 }
0164 return -EINVAL;
0165 }
0166
0167 static DEVICE_ATTR(sustain, S_IRUGO | S_IWUSR | S_IWGRP, show_sustain,
0168 store_sustain);
0169
0170 static struct device_attribute *sysfs_device_attr_sustain = {
0171 &dev_attr_sustain,
0172 };
0173
0174
0175 static ssize_t show_octave(struct device *dev,
0176 struct device_attribute *attr, char *buf)
0177 {
0178 struct hid_device *hdev = to_hid_device(dev);
0179 struct pk_device *pk = hid_get_drvdata(hdev);
0180
0181 dbg_hid("pcmidi sysfs read octave=%d\n", pk->pm->midi_octave);
0182
0183 return sprintf(buf, "%d (min:%d, max:%d)\n", pk->pm->midi_octave,
0184 PCMIDI_OCTAVE_MIN, PCMIDI_OCTAVE_MAX);
0185 }
0186
0187
0188 static ssize_t store_octave(struct device *dev,
0189 struct device_attribute *attr, const char *buf, size_t count)
0190 {
0191 struct hid_device *hdev = to_hid_device(dev);
0192 struct pk_device *pk = hid_get_drvdata(hdev);
0193
0194 int octave = 0;
0195
0196 if (sscanf(buf, "%d", &octave) > 0 &&
0197 octave >= PCMIDI_OCTAVE_MIN && octave <= PCMIDI_OCTAVE_MAX) {
0198 dbg_hid("pcmidi sysfs write octave=%d\n", octave);
0199 pk->pm->midi_octave = octave;
0200 return strlen(buf);
0201 }
0202 return -EINVAL;
0203 }
0204
0205 static DEVICE_ATTR(octave, S_IRUGO | S_IWUSR | S_IWGRP, show_octave,
0206 store_octave);
0207
0208 static struct device_attribute *sysfs_device_attr_octave = {
0209 &dev_attr_octave,
0210 };
0211
0212
0213 static void pcmidi_send_note(struct pcmidi_snd *pm,
0214 unsigned char status, unsigned char note, unsigned char velocity)
0215 {
0216 unsigned long flags;
0217 unsigned char buffer[3];
0218
0219 buffer[0] = status;
0220 buffer[1] = note;
0221 buffer[2] = velocity;
0222
0223 spin_lock_irqsave(&pm->rawmidi_in_lock, flags);
0224
0225 if (!pm->in_substream)
0226 goto drop_note;
0227 if (!test_bit(pm->in_substream->number, &pm->in_triggered))
0228 goto drop_note;
0229
0230 snd_rawmidi_receive(pm->in_substream, buffer, 3);
0231
0232 drop_note:
0233 spin_unlock_irqrestore(&pm->rawmidi_in_lock, flags);
0234
0235 return;
0236 }
0237
0238 static void pcmidi_sustained_note_release(struct timer_list *t)
0239 {
0240 struct pcmidi_sustain *pms = from_timer(pms, t, timer);
0241
0242 pcmidi_send_note(pms->pm, pms->status, pms->note, pms->velocity);
0243 pms->in_use = 0;
0244 }
0245
0246 static void init_sustain_timers(struct pcmidi_snd *pm)
0247 {
0248 struct pcmidi_sustain *pms;
0249 unsigned i;
0250
0251 for (i = 0; i < PCMIDI_SUSTAINED_MAX; i++) {
0252 pms = &pm->sustained_notes[i];
0253 pms->in_use = 0;
0254 pms->pm = pm;
0255 timer_setup(&pms->timer, pcmidi_sustained_note_release, 0);
0256 }
0257 }
0258
0259 static void stop_sustain_timers(struct pcmidi_snd *pm)
0260 {
0261 struct pcmidi_sustain *pms;
0262 unsigned i;
0263
0264 for (i = 0; i < PCMIDI_SUSTAINED_MAX; i++) {
0265 pms = &pm->sustained_notes[i];
0266 pms->in_use = 1;
0267 del_timer_sync(&pms->timer);
0268 }
0269 }
0270
0271 static int pcmidi_get_output_report(struct pcmidi_snd *pm)
0272 {
0273 struct hid_device *hdev = pm->pk->hdev;
0274 struct hid_report *report;
0275
0276 list_for_each_entry(report,
0277 &hdev->report_enum[HID_OUTPUT_REPORT].report_list, list) {
0278 if (!(6 == report->id))
0279 continue;
0280
0281 if (report->maxfield < 1) {
0282 hid_err(hdev, "output report is empty\n");
0283 break;
0284 }
0285 if (report->field[0]->report_count != 2) {
0286 hid_err(hdev, "field count too low\n");
0287 break;
0288 }
0289 pm->pcmidi_report6 = report;
0290 return 0;
0291 }
0292
0293 return -ENODEV;
0294 }
0295
0296 static void pcmidi_submit_output_report(struct pcmidi_snd *pm, int state)
0297 {
0298 struct hid_device *hdev = pm->pk->hdev;
0299 struct hid_report *report = pm->pcmidi_report6;
0300 report->field[0]->value[0] = 0x01;
0301 report->field[0]->value[1] = state;
0302
0303 hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
0304 }
0305
0306 static int pcmidi_handle_report1(struct pcmidi_snd *pm, u8 *data)
0307 {
0308 u32 bit_mask;
0309
0310 bit_mask = data[1];
0311 bit_mask = (bit_mask << 8) | data[2];
0312 bit_mask = (bit_mask << 8) | data[3];
0313
0314 dbg_hid("pcmidi mode: %d\n", pm->midi_mode);
0315
0316
0317 if (pm->midi_mode && bit_mask == 0x004000) {
0318
0319 pm->midi_octave--;
0320 if (pm->midi_octave < -2)
0321 pm->midi_octave = -2;
0322 dbg_hid("pcmidi mode: %d octave: %d\n",
0323 pm->midi_mode, pm->midi_octave);
0324 return 1;
0325 }
0326
0327 else if (pm->midi_mode && bit_mask == 0x000004) {
0328
0329 pm->midi_sustain_mode ^= 0x1;
0330 return 1;
0331 }
0332
0333 return 0;
0334 }
0335
0336 static int pcmidi_handle_report3(struct pcmidi_snd *pm, u8 *data, int size)
0337 {
0338 struct pcmidi_sustain *pms;
0339 unsigned i, j;
0340 unsigned char status, note, velocity;
0341
0342 unsigned num_notes = (size-1)/2;
0343 for (j = 0; j < num_notes; j++) {
0344 note = data[j*2+1];
0345 velocity = data[j*2+2];
0346
0347 if (note < 0x81) {
0348 status = 128 + 16 + pm->midi_channel;
0349 note = note - 0x54 + PCMIDI_MIDDLE_C +
0350 (pm->midi_octave * 12);
0351 if (0 == velocity)
0352 velocity = 1;
0353 } else {
0354 status = 128 + pm->midi_channel;
0355 note = note - 0x94 + PCMIDI_MIDDLE_C +
0356 (pm->midi_octave*12);
0357
0358 if (pm->midi_sustain_mode) {
0359 for (i = 0; i < PCMIDI_SUSTAINED_MAX; i++) {
0360 pms = &pm->sustained_notes[i];
0361 if (!pms->in_use) {
0362 pms->status = status;
0363 pms->note = note;
0364 pms->velocity = velocity;
0365 pms->in_use = 1;
0366
0367 mod_timer(&pms->timer,
0368 jiffies +
0369 msecs_to_jiffies(pm->midi_sustain));
0370 return 1;
0371 }
0372 }
0373 }
0374 }
0375 pcmidi_send_note(pm, status, note, velocity);
0376 }
0377
0378 return 1;
0379 }
0380
0381 static int pcmidi_handle_report4(struct pcmidi_snd *pm, u8 *data)
0382 {
0383 unsigned key;
0384 u32 bit_mask;
0385 u32 bit_index;
0386
0387 bit_mask = data[1];
0388 bit_mask = (bit_mask << 8) | data[2];
0389 bit_mask = (bit_mask << 8) | data[3];
0390
0391
0392 for (bit_index = 0; bit_index < 24; bit_index++) {
0393 if (!((0x01 << bit_index) & bit_mask)) {
0394 input_event(pm->input_ep82, EV_KEY,
0395 pm->last_key[bit_index], 0);
0396 pm->last_key[bit_index] = 0;
0397 }
0398 }
0399
0400
0401 for (bit_index = 0; bit_index < 24; bit_index++) {
0402 key = 0;
0403 switch ((0x01 << bit_index) & bit_mask) {
0404 case 0x000010:
0405 pm->fn_state ^= 0x000010;
0406 if (pm->fn_state)
0407 pcmidi_submit_output_report(pm, 0xc5);
0408 else
0409 pcmidi_submit_output_report(pm, 0xc6);
0410 continue;
0411 case 0x020000:
0412 pcmidi_submit_output_report(pm, 0xc1);
0413 pm->midi_mode ^= 0x01;
0414
0415 dbg_hid("pcmidi mode: %d\n", pm->midi_mode);
0416 continue;
0417 case 0x100000:
0418 dbg_hid("pcmidi mode: %d\n", pm->midi_mode);
0419 if (pm->midi_mode) {
0420 pm->midi_octave++;
0421 if (pm->midi_octave > 2)
0422 pm->midi_octave = 2;
0423 dbg_hid("pcmidi mode: %d octave: %d\n",
0424 pm->midi_mode, pm->midi_octave);
0425 continue;
0426 } else
0427 key = KEY_MESSENGER;
0428 break;
0429 case 0x400000:
0430 key = KEY_CALENDAR;
0431 break;
0432 case 0x080000:
0433 key = KEY_ADDRESSBOOK;
0434 break;
0435 case 0x040000:
0436 key = KEY_DOCUMENTS;
0437 break;
0438 case 0x800000:
0439 key = KEY_WORDPROCESSOR;
0440 break;
0441 case 0x200000:
0442 key = KEY_SPREADSHEET;
0443 break;
0444 case 0x010000:
0445 key = KEY_COFFEE;
0446 break;
0447 case 0x000100:
0448 key = KEY_HELP;
0449 break;
0450 case 0x000200:
0451 key = KEY_SEND;
0452 break;
0453 case 0x000400:
0454 key = KEY_REPLY;
0455 break;
0456 case 0x000800:
0457 key = KEY_FORWARDMAIL;
0458 break;
0459 case 0x001000:
0460 key = KEY_NEW;
0461 break;
0462 case 0x002000:
0463 key = KEY_OPEN;
0464 break;
0465 case 0x004000:
0466 key = KEY_CLOSE;
0467 break;
0468 case 0x008000:
0469 key = KEY_SAVE;
0470 break;
0471 case 0x000001:
0472 key = KEY_UNDO;
0473 break;
0474 case 0x000002:
0475 key = KEY_REDO;
0476 break;
0477 case 0x000004:
0478 key = KEY_SPELLCHECK;
0479 break;
0480 case 0x000008:
0481 key = KEY_PRINT;
0482 break;
0483 }
0484 if (key) {
0485 input_event(pm->input_ep82, EV_KEY, key, 1);
0486 pm->last_key[bit_index] = key;
0487 }
0488 }
0489
0490 return 1;
0491 }
0492
0493 static int pcmidi_handle_report(
0494 struct pcmidi_snd *pm, unsigned report_id, u8 *data, int size)
0495 {
0496 int ret = 0;
0497
0498 switch (report_id) {
0499 case 0x01:
0500 ret = pcmidi_handle_report1(pm, data);
0501 break;
0502 case 0x03:
0503 ret = pcmidi_handle_report3(pm, data, size);
0504 break;
0505 case 0x04:
0506 ret = pcmidi_handle_report4(pm, data);
0507 break;
0508 }
0509 return ret;
0510 }
0511
0512 static void pcmidi_setup_extra_keys(
0513 struct pcmidi_snd *pm, struct input_dev *input)
0514 {
0515
0516
0517
0518
0519 static const unsigned int keys[] = {
0520 KEY_FN,
0521 KEY_MESSENGER, KEY_CALENDAR,
0522 KEY_ADDRESSBOOK, KEY_DOCUMENTS,
0523 KEY_WORDPROCESSOR,
0524 KEY_SPREADSHEET,
0525 KEY_COFFEE,
0526 KEY_HELP, KEY_SEND,
0527 KEY_REPLY, KEY_FORWARDMAIL,
0528 KEY_NEW, KEY_OPEN,
0529 KEY_CLOSE, KEY_SAVE,
0530 KEY_UNDO, KEY_REDO,
0531 KEY_SPELLCHECK, KEY_PRINT,
0532 0
0533 };
0534
0535 const unsigned int *pkeys = &keys[0];
0536 unsigned short i;
0537
0538 if (pm->ifnum != 1)
0539 return;
0540
0541 pm->input_ep82 = input;
0542
0543 for (i = 0; i < 24; i++)
0544 pm->last_key[i] = 0;
0545
0546 while (*pkeys != 0) {
0547 set_bit(*pkeys, pm->input_ep82->keybit);
0548 ++pkeys;
0549 }
0550 }
0551
0552 static int pcmidi_set_operational(struct pcmidi_snd *pm)
0553 {
0554 int rc;
0555
0556 if (pm->ifnum != 1)
0557 return 0;
0558
0559 rc = pcmidi_get_output_report(pm);
0560 if (rc < 0)
0561 return rc;
0562 pcmidi_submit_output_report(pm, 0xc1);
0563 return 0;
0564 }
0565
0566 static int pcmidi_snd_free(struct snd_device *dev)
0567 {
0568 return 0;
0569 }
0570
0571 static int pcmidi_in_open(struct snd_rawmidi_substream *substream)
0572 {
0573 struct pcmidi_snd *pm = substream->rmidi->private_data;
0574
0575 dbg_hid("pcmidi in open\n");
0576 pm->in_substream = substream;
0577 return 0;
0578 }
0579
0580 static int pcmidi_in_close(struct snd_rawmidi_substream *substream)
0581 {
0582 dbg_hid("pcmidi in close\n");
0583 return 0;
0584 }
0585
0586 static void pcmidi_in_trigger(struct snd_rawmidi_substream *substream, int up)
0587 {
0588 struct pcmidi_snd *pm = substream->rmidi->private_data;
0589
0590 dbg_hid("pcmidi in trigger %d\n", up);
0591
0592 pm->in_triggered = up;
0593 }
0594
0595 static const struct snd_rawmidi_ops pcmidi_in_ops = {
0596 .open = pcmidi_in_open,
0597 .close = pcmidi_in_close,
0598 .trigger = pcmidi_in_trigger
0599 };
0600
0601 static int pcmidi_snd_initialise(struct pcmidi_snd *pm)
0602 {
0603 static int dev;
0604 struct snd_card *card;
0605 struct snd_rawmidi *rwmidi;
0606 int err;
0607
0608 static struct snd_device_ops ops = {
0609 .dev_free = pcmidi_snd_free,
0610 };
0611
0612 if (pm->ifnum != 1)
0613 return 0;
0614
0615 if (dev >= SNDRV_CARDS)
0616 return -ENODEV;
0617
0618 if (!enable[dev]) {
0619 dev++;
0620 return -ENOENT;
0621 }
0622
0623
0624
0625 err = snd_card_new(&pm->pk->hdev->dev, index[dev], id[dev],
0626 THIS_MODULE, 0, &card);
0627 if (err < 0) {
0628 pk_error("failed to create pc-midi sound card\n");
0629 err = -ENOMEM;
0630 goto fail;
0631 }
0632 pm->card = card;
0633
0634
0635 err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, pm, &ops);
0636 if (err < 0) {
0637 pk_error("failed to create pc-midi sound device: error %d\n",
0638 err);
0639 goto fail;
0640 }
0641
0642 strncpy(card->driver, shortname, sizeof(card->driver));
0643 strncpy(card->shortname, shortname, sizeof(card->shortname));
0644 strncpy(card->longname, longname, sizeof(card->longname));
0645
0646
0647 err = snd_rawmidi_new(card, card->shortname, 0,
0648 0, 1, &rwmidi);
0649 if (err < 0) {
0650 pk_error("failed to create pc-midi rawmidi device: error %d\n",
0651 err);
0652 goto fail;
0653 }
0654 pm->rwmidi = rwmidi;
0655 strncpy(rwmidi->name, card->shortname, sizeof(rwmidi->name));
0656 rwmidi->info_flags = SNDRV_RAWMIDI_INFO_INPUT;
0657 rwmidi->private_data = pm;
0658
0659 snd_rawmidi_set_ops(rwmidi, SNDRV_RAWMIDI_STREAM_INPUT,
0660 &pcmidi_in_ops);
0661
0662
0663 err = device_create_file(&pm->pk->hdev->dev,
0664 sysfs_device_attr_channel);
0665 if (err < 0) {
0666 pk_error("failed to create sysfs attribute channel: error %d\n",
0667 err);
0668 goto fail;
0669 }
0670
0671 err = device_create_file(&pm->pk->hdev->dev,
0672 sysfs_device_attr_sustain);
0673 if (err < 0) {
0674 pk_error("failed to create sysfs attribute sustain: error %d\n",
0675 err);
0676 goto fail_attr_sustain;
0677 }
0678
0679 err = device_create_file(&pm->pk->hdev->dev,
0680 sysfs_device_attr_octave);
0681 if (err < 0) {
0682 pk_error("failed to create sysfs attribute octave: error %d\n",
0683 err);
0684 goto fail_attr_octave;
0685 }
0686
0687 spin_lock_init(&pm->rawmidi_in_lock);
0688
0689 init_sustain_timers(pm);
0690 err = pcmidi_set_operational(pm);
0691 if (err < 0) {
0692 pk_error("failed to find output report\n");
0693 goto fail_register;
0694 }
0695
0696
0697 err = snd_card_register(card);
0698 if (err < 0) {
0699 pk_error("failed to register pc-midi sound card: error %d\n",
0700 err);
0701 goto fail_register;
0702 }
0703
0704 dbg_hid("pcmidi_snd_initialise finished ok\n");
0705 return 0;
0706
0707 fail_register:
0708 stop_sustain_timers(pm);
0709 device_remove_file(&pm->pk->hdev->dev, sysfs_device_attr_octave);
0710 fail_attr_octave:
0711 device_remove_file(&pm->pk->hdev->dev, sysfs_device_attr_sustain);
0712 fail_attr_sustain:
0713 device_remove_file(&pm->pk->hdev->dev, sysfs_device_attr_channel);
0714 fail:
0715 if (pm->card) {
0716 snd_card_free(pm->card);
0717 pm->card = NULL;
0718 }
0719 return err;
0720 }
0721
0722 static int pcmidi_snd_terminate(struct pcmidi_snd *pm)
0723 {
0724 if (pm->card) {
0725 stop_sustain_timers(pm);
0726
0727 device_remove_file(&pm->pk->hdev->dev,
0728 sysfs_device_attr_channel);
0729 device_remove_file(&pm->pk->hdev->dev,
0730 sysfs_device_attr_sustain);
0731 device_remove_file(&pm->pk->hdev->dev,
0732 sysfs_device_attr_octave);
0733
0734 snd_card_disconnect(pm->card);
0735 snd_card_free_when_closed(pm->card);
0736 }
0737
0738 return 0;
0739 }
0740
0741
0742
0743
0744 static __u8 *pk_report_fixup(struct hid_device *hdev, __u8 *rdesc,
0745 unsigned int *rsize)
0746 {
0747 if (*rsize == 178 &&
0748 rdesc[111] == 0x06 && rdesc[112] == 0x00 &&
0749 rdesc[113] == 0xff) {
0750 hid_info(hdev,
0751 "fixing up pc-midi keyboard report descriptor\n");
0752
0753 rdesc[144] = 0x18;
0754 }
0755 return rdesc;
0756 }
0757
0758 static int pk_input_mapping(struct hid_device *hdev, struct hid_input *hi,
0759 struct hid_field *field, struct hid_usage *usage,
0760 unsigned long **bit, int *max)
0761 {
0762 struct pk_device *pk = hid_get_drvdata(hdev);
0763 struct pcmidi_snd *pm;
0764
0765 pm = pk->pm;
0766
0767 if (HID_UP_MSVENDOR == (usage->hid & HID_USAGE_PAGE) &&
0768 1 == pm->ifnum) {
0769 pcmidi_setup_extra_keys(pm, hi->input);
0770 return 0;
0771 }
0772
0773 return 0;
0774 }
0775
0776
0777 static int pk_raw_event(struct hid_device *hdev, struct hid_report *report,
0778 u8 *data, int size)
0779 {
0780 struct pk_device *pk = hid_get_drvdata(hdev);
0781 int ret = 0;
0782
0783 if (1 == pk->pm->ifnum) {
0784 if (report->id == data[0])
0785 switch (report->id) {
0786 case 0x01:
0787 case 0x03:
0788 case 0x04:
0789 ret = pcmidi_handle_report(pk->pm,
0790 report->id, data, size);
0791 break;
0792 }
0793 }
0794
0795 return ret;
0796 }
0797
0798 static int pk_probe(struct hid_device *hdev, const struct hid_device_id *id)
0799 {
0800 int ret;
0801 struct usb_interface *intf;
0802 unsigned short ifnum;
0803 unsigned long quirks = id->driver_data;
0804 struct pk_device *pk;
0805 struct pcmidi_snd *pm = NULL;
0806
0807 if (!hid_is_usb(hdev))
0808 return -EINVAL;
0809
0810 intf = to_usb_interface(hdev->dev.parent);
0811 ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
0812
0813 pk = kzalloc(sizeof(*pk), GFP_KERNEL);
0814 if (pk == NULL) {
0815 hid_err(hdev, "can't alloc descriptor\n");
0816 return -ENOMEM;
0817 }
0818
0819 pk->hdev = hdev;
0820
0821 pm = kzalloc(sizeof(*pm), GFP_KERNEL);
0822 if (pm == NULL) {
0823 hid_err(hdev, "can't alloc descriptor\n");
0824 ret = -ENOMEM;
0825 goto err_free_pk;
0826 }
0827
0828 pm->pk = pk;
0829 pk->pm = pm;
0830 pm->ifnum = ifnum;
0831
0832 hid_set_drvdata(hdev, pk);
0833
0834 ret = hid_parse(hdev);
0835 if (ret) {
0836 hid_err(hdev, "hid parse failed\n");
0837 goto err_free;
0838 }
0839
0840 if (quirks & PK_QUIRK_NOGET) {
0841 hdev->quirks |= HID_QUIRK_NOGET;
0842 }
0843
0844 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
0845 if (ret) {
0846 hid_err(hdev, "hw start failed\n");
0847 goto err_free;
0848 }
0849
0850 ret = pcmidi_snd_initialise(pm);
0851 if (ret < 0)
0852 goto err_stop;
0853
0854 return 0;
0855 err_stop:
0856 hid_hw_stop(hdev);
0857 err_free:
0858 kfree(pm);
0859 err_free_pk:
0860 kfree(pk);
0861
0862 return ret;
0863 }
0864
0865 static void pk_remove(struct hid_device *hdev)
0866 {
0867 struct pk_device *pk = hid_get_drvdata(hdev);
0868 struct pcmidi_snd *pm;
0869
0870 pm = pk->pm;
0871 if (pm) {
0872 pcmidi_snd_terminate(pm);
0873 kfree(pm);
0874 }
0875
0876 hid_hw_stop(hdev);
0877
0878 kfree(pk);
0879 }
0880
0881 static const struct hid_device_id pk_devices[] = {
0882 {HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS,
0883 USB_DEVICE_ID_PRODIKEYS_PCMIDI),
0884 .driver_data = PK_QUIRK_NOGET},
0885 { }
0886 };
0887 MODULE_DEVICE_TABLE(hid, pk_devices);
0888
0889 static struct hid_driver pk_driver = {
0890 .name = "prodikeys",
0891 .id_table = pk_devices,
0892 .report_fixup = pk_report_fixup,
0893 .input_mapping = pk_input_mapping,
0894 .raw_event = pk_raw_event,
0895 .probe = pk_probe,
0896 .remove = pk_remove,
0897 };
0898 module_hid_driver(pk_driver);
0899
0900 MODULE_LICENSE("GPL");