Linux Audio

Check our new training course

Loading...
v6.8
  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	strscpy(card->driver, shortname, sizeof(card->driver));
643	strscpy(card->shortname, shortname, sizeof(card->shortname));
644	strscpy(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	strscpy(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");
v5.4
  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 = 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;
849err_stop:
850	hid_hw_stop(hdev);
851err_free:
852	kfree(pm);
853err_free_pk:
854	kfree(pk);
855
856	return ret;
857}
858
859static 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
875static 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};
881MODULE_DEVICE_TABLE(hid, pk_devices);
882
883static 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};
892module_hid_driver(pk_driver);
893
894MODULE_LICENSE("GPL");