Lines Matching +full:key +full:- +full:up
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * HID driver for the Prodikeys PC-MIDI Keyboard
8 * Controls for Octave Shift Up/Down, Channel, and
25 #include "hid-ids.h"
29 pr_debug("hid-prodikeys: " format "\n" , ## arg)
31 pr_err("hid-prodikeys: " format "\n" , ## arg)
69 #define PCMIDI_OCTAVE_MIN (-2)
74 static const char shortname[] = "PC-MIDI";
75 static const char longname[] = "Prodikeys PC-MIDI Keyboard";
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");
96 dbg_hid("pcmidi sysfs read channel=%u\n", pm->midi_channel); in show_channel()
98 return sprintf(buf, "%u (min:%u, max:%u)\n", pm->midi_channel, in show_channel()
113 pm->midi_channel = channel; in store_channel()
116 return -EINVAL; in store_channel()
133 dbg_hid("pcmidi sysfs read sustain=%u\n", pm->midi_sustain); in show_sustain()
135 return sprintf(buf, "%u (off:%u, max:%u (ms))\n", pm->midi_sustain, in show_sustain()
150 pm->midi_sustain = sustain; in store_sustain()
151 pm->midi_sustain_mode = (0 == sustain || !pm->midi_mode) ? 0 : 1; in store_sustain()
154 return -EINVAL; in store_sustain()
171 dbg_hid("pcmidi sysfs read octave=%d\n", pm->midi_octave); in show_octave()
173 return sprintf(buf, "%d (min:%d, max:%d)\n", pm->midi_octave, in show_octave()
189 pm->midi_octave = octave; in store_octave()
192 return -EINVAL; in store_octave()
213 spin_lock_irqsave(&pm->rawmidi_in_lock, flags); in pcmidi_send_note()
215 if (!pm->in_substream) in pcmidi_send_note()
217 if (!test_bit(pm->in_substream->number, &pm->in_triggered)) in pcmidi_send_note()
220 snd_rawmidi_receive(pm->in_substream, buffer, 3); in pcmidi_send_note()
223 spin_unlock_irqrestore(&pm->rawmidi_in_lock, flags); in pcmidi_send_note()
232 pcmidi_send_note(pms->pm, pms->status, pms->note, pms->velocity); in pcmidi_sustained_note_release()
233 pms->in_use = 0; in pcmidi_sustained_note_release()
242 pms = &pm->sustained_notes[i]; in init_sustain_timers()
243 pms->in_use = 0; in init_sustain_timers()
244 pms->pm = pm; in init_sustain_timers()
245 timer_setup(&pms->timer, pcmidi_sustained_note_release, 0); in init_sustain_timers()
255 pms = &pm->sustained_notes[i]; in stop_sustain_timers()
256 pms->in_use = 1; in stop_sustain_timers()
257 del_timer_sync(&pms->timer); in stop_sustain_timers()
263 struct hid_device *hdev = pm->hdev; in pcmidi_get_output_report()
267 &hdev->report_enum[HID_OUTPUT_REPORT].report_list, list) { in pcmidi_get_output_report()
268 if (!(6 == report->id)) in pcmidi_get_output_report()
271 if (report->maxfield < 1) { in pcmidi_get_output_report()
275 if (report->field[0]->report_count != 2) { in pcmidi_get_output_report()
279 pm->pcmidi_report6 = report; in pcmidi_get_output_report()
283 return -ENODEV; in pcmidi_get_output_report()
288 struct hid_device *hdev = pm->hdev; in pcmidi_submit_output_report()
289 struct hid_report *report = pm->pcmidi_report6; in pcmidi_submit_output_report()
290 report->field[0]->value[0] = 0x01; in pcmidi_submit_output_report()
291 report->field[0]->value[1] = state; in pcmidi_submit_output_report()
304 dbg_hid("pcmidi mode: %d\n", pm->midi_mode); in pcmidi_handle_report1()
307 if (pm->midi_mode && bit_mask == 0x004000) { in pcmidi_handle_report1()
309 pm->midi_octave--; in pcmidi_handle_report1()
310 if (pm->midi_octave < -2) in pcmidi_handle_report1()
311 pm->midi_octave = -2; in pcmidi_handle_report1()
313 pm->midi_mode, pm->midi_octave); in pcmidi_handle_report1()
317 else if (pm->midi_mode && bit_mask == 0x000004) { in pcmidi_handle_report1()
319 pm->midi_sustain_mode ^= 0x1; in pcmidi_handle_report1()
323 return 0; /* continue key processing */ in pcmidi_handle_report1()
332 unsigned num_notes = (size-1)/2; in pcmidi_handle_report3()
338 status = 128 + 16 + pm->midi_channel; /* 1001nnnn */ in pcmidi_handle_report3()
339 note = note - 0x54 + PCMIDI_MIDDLE_C + in pcmidi_handle_report3()
340 (pm->midi_octave * 12); in pcmidi_handle_report3()
344 status = 128 + pm->midi_channel; /* 1000nnnn */ in pcmidi_handle_report3()
345 note = note - 0x94 + PCMIDI_MIDDLE_C + in pcmidi_handle_report3()
346 (pm->midi_octave*12); in pcmidi_handle_report3()
348 if (pm->midi_sustain_mode) { in pcmidi_handle_report3()
350 pms = &pm->sustained_notes[i]; in pcmidi_handle_report3()
351 if (!pms->in_use) { in pcmidi_handle_report3()
352 pms->status = status; in pcmidi_handle_report3()
353 pms->note = note; in pcmidi_handle_report3()
354 pms->velocity = velocity; in pcmidi_handle_report3()
355 pms->in_use = 1; in pcmidi_handle_report3()
357 mod_timer(&pms->timer, in pcmidi_handle_report3()
359 msecs_to_jiffies(pm->midi_sustain)); in pcmidi_handle_report3()
373 unsigned key; in pcmidi_handle_report4() local
384 input_event(pm->input_ep82, EV_KEY, in pcmidi_handle_report4()
385 pm->last_key[bit_index], 0); in pcmidi_handle_report4()
386 pm->last_key[bit_index] = 0; in pcmidi_handle_report4()
392 key = 0; in pcmidi_handle_report4()
395 pm->fn_state ^= 0x000010; in pcmidi_handle_report4()
396 if (pm->fn_state) in pcmidi_handle_report4()
401 case 0x020000: /* midi launcher..send a key (qwerty) or not? */ in pcmidi_handle_report4()
403 pm->midi_mode ^= 0x01; in pcmidi_handle_report4()
405 dbg_hid("pcmidi mode: %d\n", pm->midi_mode); in pcmidi_handle_report4()
407 case 0x100000: /* KEY_MESSENGER or octave up */ in pcmidi_handle_report4()
408 dbg_hid("pcmidi mode: %d\n", pm->midi_mode); in pcmidi_handle_report4()
409 if (pm->midi_mode) { in pcmidi_handle_report4()
410 pm->midi_octave++; in pcmidi_handle_report4()
411 if (pm->midi_octave > 2) in pcmidi_handle_report4()
412 pm->midi_octave = 2; in pcmidi_handle_report4()
414 pm->midi_mode, pm->midi_octave); in pcmidi_handle_report4()
417 key = KEY_MESSENGER; in pcmidi_handle_report4()
420 key = KEY_CALENDAR; in pcmidi_handle_report4()
423 key = KEY_ADDRESSBOOK; in pcmidi_handle_report4()
426 key = KEY_DOCUMENTS; in pcmidi_handle_report4()
429 key = KEY_WORDPROCESSOR; in pcmidi_handle_report4()
432 key = KEY_SPREADSHEET; in pcmidi_handle_report4()
435 key = KEY_COFFEE; in pcmidi_handle_report4()
438 key = KEY_HELP; in pcmidi_handle_report4()
441 key = KEY_SEND; in pcmidi_handle_report4()
444 key = KEY_REPLY; in pcmidi_handle_report4()
447 key = KEY_FORWARDMAIL; in pcmidi_handle_report4()
450 key = KEY_NEW; in pcmidi_handle_report4()
453 key = KEY_OPEN; in pcmidi_handle_report4()
456 key = KEY_CLOSE; in pcmidi_handle_report4()
459 key = KEY_SAVE; in pcmidi_handle_report4()
462 key = KEY_UNDO; in pcmidi_handle_report4()
465 key = KEY_REDO; in pcmidi_handle_report4()
468 key = KEY_SPELLCHECK; in pcmidi_handle_report4()
471 key = KEY_PRINT; in pcmidi_handle_report4()
474 if (key) { in pcmidi_handle_report4()
475 input_event(pm->input_ep82, EV_KEY, key, 1); in pcmidi_handle_report4()
476 pm->last_key[bit_index] = key; in pcmidi_handle_report4()
528 if (pm->ifnum != 1) /* only set up ONCE for interace 1 */ in pcmidi_setup_extra_keys()
531 pm->input_ep82 = input; in pcmidi_setup_extra_keys()
534 pm->last_key[i] = 0; in pcmidi_setup_extra_keys()
537 set_bit(*pkeys, pm->input_ep82->keybit); in pcmidi_setup_extra_keys()
546 if (pm->ifnum != 1) in pcmidi_set_operational()
547 return 0; /* only set up ONCE for interace 1 */ in pcmidi_set_operational()
563 struct pcmidi_snd *pm = substream->rmidi->private_data; in pcmidi_in_open()
566 pm->in_substream = substream; in pcmidi_in_open()
576 static void pcmidi_in_trigger(struct snd_rawmidi_substream *substream, int up) in pcmidi_in_trigger() argument
578 struct pcmidi_snd *pm = substream->rmidi->private_data; in pcmidi_in_trigger()
580 dbg_hid("pcmidi in trigger %d\n", up); in pcmidi_in_trigger()
582 pm->in_triggered = up; in pcmidi_in_trigger()
602 if (pm->ifnum != 1) in pcmidi_snd_initialise()
603 return 0; /* only set up midi device ONCE for interace 1 */ in pcmidi_snd_initialise()
606 return -ENODEV; in pcmidi_snd_initialise()
610 return -ENOENT; in pcmidi_snd_initialise()
615 err = snd_card_new(&pm->hdev->dev, index[dev], id[dev], in pcmidi_snd_initialise()
618 pk_error("failed to create pc-midi sound card\n"); in pcmidi_snd_initialise()
619 err = -ENOMEM; in pcmidi_snd_initialise()
622 pm->card = card; in pcmidi_snd_initialise()
627 pk_error("failed to create pc-midi sound device: error %d\n", in pcmidi_snd_initialise()
632 strscpy(card->driver, shortname, sizeof(card->driver)); in pcmidi_snd_initialise()
633 strscpy(card->shortname, shortname, sizeof(card->shortname)); in pcmidi_snd_initialise()
634 strscpy(card->longname, longname, sizeof(card->longname)); in pcmidi_snd_initialise()
636 /* Set up rawmidi */ in pcmidi_snd_initialise()
637 err = snd_rawmidi_new(card, card->shortname, 0, in pcmidi_snd_initialise()
640 pk_error("failed to create pc-midi rawmidi device: error %d\n", in pcmidi_snd_initialise()
644 pm->rwmidi = rwmidi; in pcmidi_snd_initialise()
645 strscpy(rwmidi->name, card->shortname, sizeof(rwmidi->name)); in pcmidi_snd_initialise()
646 rwmidi->info_flags = SNDRV_RAWMIDI_INFO_INPUT; in pcmidi_snd_initialise()
647 rwmidi->private_data = pm; in pcmidi_snd_initialise()
653 err = device_create_file(&pm->hdev->dev, in pcmidi_snd_initialise()
661 err = device_create_file(&pm->hdev->dev, in pcmidi_snd_initialise()
669 err = device_create_file(&pm->hdev->dev, in pcmidi_snd_initialise()
677 spin_lock_init(&pm->rawmidi_in_lock); in pcmidi_snd_initialise()
689 pk_error("failed to register pc-midi sound card: error %d\n", in pcmidi_snd_initialise()
699 device_remove_file(&pm->hdev->dev, sysfs_device_attr_octave); in pcmidi_snd_initialise()
701 device_remove_file(&pm->hdev->dev, sysfs_device_attr_sustain); in pcmidi_snd_initialise()
703 device_remove_file(&pm->hdev->dev, sysfs_device_attr_channel); in pcmidi_snd_initialise()
705 if (pm->card) { in pcmidi_snd_initialise()
706 snd_card_free(pm->card); in pcmidi_snd_initialise()
707 pm->card = NULL; in pcmidi_snd_initialise()
714 if (pm->card) { in pcmidi_snd_terminate()
717 device_remove_file(&pm->hdev->dev, sysfs_device_attr_channel); in pcmidi_snd_terminate()
718 device_remove_file(&pm->hdev->dev, sysfs_device_attr_sustain); in pcmidi_snd_terminate()
719 device_remove_file(&pm->hdev->dev, sysfs_device_attr_octave); in pcmidi_snd_terminate()
721 snd_card_disconnect(pm->card); in pcmidi_snd_terminate()
722 snd_card_free_when_closed(pm->card); in pcmidi_snd_terminate()
729 * PC-MIDI report descriptor for report id is wrong.
738 "fixing up pc-midi keyboard report descriptor\n"); in pk_report_fixup()
751 if (HID_UP_MSVENDOR == (usage->hid & HID_USAGE_PAGE) && in pk_input_mapping()
752 1 == pm->ifnum) { in pk_input_mapping()
753 pcmidi_setup_extra_keys(pm, hi->input); in pk_input_mapping()
767 if (1 == pm->ifnum) { in pk_raw_event()
768 if (report->id == data[0]) in pk_raw_event()
769 switch (report->id) { in pk_raw_event()
774 report->id, data, size); in pk_raw_event()
787 unsigned long quirks = id->driver_data; in pk_probe()
791 return -EINVAL; in pk_probe()
793 intf = to_usb_interface(hdev->dev.parent); in pk_probe()
794 ifnum = intf->cur_altsetting->desc.bInterfaceNumber; in pk_probe()
799 return -ENOMEM; in pk_probe()
802 pm->hdev = hdev; in pk_probe()
803 pm->ifnum = ifnum; in pk_probe()
814 hdev->quirks |= HID_QUIRK_NOGET; in pk_probe()
865 MODULE_DESCRIPTION("HID driver for the Prodikeys PC-MIDI Keyboard");