linux/drivers/input/misc/yealink.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * drivers/usb/input/yealink.c
 *
 * Copyright (c) 2005 Henk Vergonet <[email protected]>
 */
/*
 * Description:
 *   Driver for the USB-P1K voip usb phone.
 *   This device is produced by Yealink Network Technology Co Ltd
 *   but may be branded under several names:
 *	- Yealink usb-p1k
 *	- Tiptel 115
 *	- ...
 *
 * This driver is based on:
 *   - the usbb2k-api	http://savannah.nongnu.org/projects/usbb2k-api/
 *   - information from	http://memeteau.free.fr/usbb2k
 *   - the xpad-driver	drivers/input/joystick/xpad.c
 *
 * Thanks to:
 *   - Olivier Vandorpe, for providing the usbb2k-api.
 *   - Martin Diehl, for spotting my memory allocation bug.
 *
 * History:
 *   20050527 henk	First version, functional keyboard. Keyboard events
 *			will pop-up on the ../input/eventX bus.
 *   20050531 henk	Added led, LCD, dialtone and sysfs interface.
 *   20050610 henk	Cleanups, make it ready for public consumption.
 *   20050630 henk	Cleanups, fixes in response to comments.
 *   20050701 henk	sysfs write serialisation, fix potential unload races
 *   20050801 henk	Added ringtone, restructure USB
 *   20050816 henk	Merge 2.6.13-rc6
 */

#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/usb/input.h>
#include <linux/map_to_7segment.h>

#include "yealink.h"

#define DRIVER_VERSION

#define YEALINK_POLLING_FREQUENCY

struct yld_status {} __attribute__ ((packed));

/*
 * Register the LCD segment and icon map
 */
#define _LOC(k,l)
#define _SEG
#define _PIC

static const struct lcd_segment_map {} lcdMap[] =;

struct yealink_dev {};


/*******************************************************************************
 * Yealink lcd interface
 ******************************************************************************/

/*
 * Register a default 7 segment character set
 */
static SEG7_DEFAULT_MAP(map_seg7);

 /* Display a char,
  * char '\9' and '\n' are placeholders and do not overwrite the original text.
  * A space will always hide an icon.
  */
static int setChar(struct yealink_dev *yld, int el, int chr)
{
	int i, a, m, val;

	if (el >= ARRAY_SIZE(lcdMap))
		return -EINVAL;

	if (chr == '\t' || chr == '\n')
	    return 0;

	yld->lcdMap[el] = chr;

	if (lcdMap[el].type == '.') {
		a = lcdMap[el].u.p.a;
		m = lcdMap[el].u.p.m;
		if (chr != ' ')
			yld->master.b[a] |= m;
		else
			yld->master.b[a] &= ~m;
		return 0;
	}

	val = map_to_seg7(&map_seg7, chr);
	for (i = 0; i < ARRAY_SIZE(lcdMap[0].u.s); i++) {
		m = lcdMap[el].u.s[i].m;

		if (m == 0)
			continue;

		a = lcdMap[el].u.s[i].a;
		if (val & 1)
			yld->master.b[a] |= m;
		else
			yld->master.b[a] &= ~m;
		val = val >> 1;
	}
	return 0;
};

/*******************************************************************************
 * Yealink key interface
 ******************************************************************************/

/* Map device buttons to internal key events.
 *
 * USB-P1K button layout:
 *
 *             up
 *       IN           OUT
 *            down
 *
 *     pickup   C    hangup
 *       1      2      3
 *       4      5      6
 *       7      8      9
 *       *      0      #
 *
 * The "up" and "down" keys, are symbolised by arrows on the button.
 * The "pickup" and "hangup" keys are symbolised by a green and red phone
 * on the button.
 */
static int map_p1k_to_key(int scancode)
{}

/* Completes a request by converting the data into events for the
 * input subsystem.
 *
 * The key parameter can be cascaded: key2 << 8 | key1
 */
static void report_key(struct yealink_dev *yld, int key)
{}

/*******************************************************************************
 * Yealink usb communication interface
 ******************************************************************************/

static int yealink_cmd(struct yealink_dev *yld, struct yld_ctl_packet *p)
{}

static u8 default_ringtone[] =;

static int yealink_set_ringtone(struct yealink_dev *yld, u8 *buf, size_t size)
{}

/* keep stat_master & stat_copy in sync.
 */
static int yealink_do_idle_tasks(struct yealink_dev *yld)
{}

/* Decide on how to handle responses
 *
 * The state transition diagram is somethhing like:
 *
 *          syncState<--+
 *               |      |
 *               |    idle
 *              \|/     |
 * init --ok--> waitForKey --ok--> getKey
 *  ^               ^                |
 *  |               +-------ok-------+
 * error,start
 *
 */
static void urb_irq_callback(struct urb *urb)
{}

static void urb_ctl_callback(struct urb *urb)
{}

/*******************************************************************************
 * input event interface
 ******************************************************************************/

/* TODO should we issue a ringtone on a SND_BELL event?
static int input_ev(struct input_dev *dev, unsigned int type,
		unsigned int code, int value)
{

	if (type != EV_SND)
		return -EINVAL;

	switch (code) {
	case SND_BELL:
	case SND_TONE:
		break;
	default:
		return -EINVAL;
	}

	return 0;
}
*/

static int input_open(struct input_dev *dev)
{}

static void input_close(struct input_dev *dev)
{}

/*******************************************************************************
 * sysfs interface
 ******************************************************************************/

/* Interface to the 7-segments translation table aka. char set.
 */
static ssize_t show_map(struct device *dev, struct device_attribute *attr,
				char *buf)
{}

static ssize_t store_map(struct device *dev, struct device_attribute *attr,
				const char *buf, size_t cnt)
{}

/* Interface to the LCD.
 */

/* Reading /sys/../lineX will return the format string with its settings:
 *
 * Example:
 * cat ./line3
 * 888888888888
 * Linux Rocks!
 */
static ssize_t show_line(struct device *dev, char *buf, int a, int b)
{}

static ssize_t show_line1(struct device *dev, struct device_attribute *attr,
			char *buf)
{}

static ssize_t show_line2(struct device *dev, struct device_attribute *attr,
			char *buf)
{}

static ssize_t show_line3(struct device *dev, struct device_attribute *attr,
			char *buf)
{}

/* Writing to /sys/../lineX will set the coresponding LCD line.
 * - Excess characters are ignored.
 * - If less characters are written than allowed, the remaining digits are
 *   unchanged.
 * - The '\n' or '\t' char is a placeholder, it does not overwrite the
 *   original content.
 */
static ssize_t store_line(struct device *dev, const char *buf, size_t count,
		int el, size_t len)
{}

static ssize_t store_line1(struct device *dev, struct device_attribute *attr,
				const char *buf, size_t count)
{}

static ssize_t store_line2(struct device *dev, struct device_attribute *attr,
				const char *buf, size_t count)
{}

static ssize_t store_line3(struct device *dev, struct device_attribute *attr,
				const char *buf, size_t count)
{}

/* Interface to visible and audible "icons", these include:
 * pictures on the LCD, the LED, and the dialtone signal.
 */

/* Get a list of "switchable elements" with their current state. */
static ssize_t get_icons(struct device *dev, struct device_attribute *attr,
			char *buf)
{}

/* Change the visibility of a particular element. */
static ssize_t set_icon(struct device *dev, const char *buf, size_t count,
			int chr)
{}

static ssize_t show_icon(struct device *dev, struct device_attribute *attr,
		const char *buf, size_t count)
{}

static ssize_t hide_icon(struct device *dev, struct device_attribute *attr,
		const char *buf, size_t count)
{}

/* Upload a ringtone to the device.
 */

/* Stores raw ringtone data in the phone */
static ssize_t store_ringtone(struct device *dev, struct device_attribute *attr,
			      const char *buf, size_t count)
{}

#define _M444
#define _M664
#define _M220

static DEVICE_ATTR(map_seg7	, _M664, show_map	, store_map	);
static DEVICE_ATTR(line1	, _M664, show_line1	, store_line1	);
static DEVICE_ATTR(line2	, _M664, show_line2	, store_line2	);
static DEVICE_ATTR(line3	, _M664, show_line3	, store_line3	);
static DEVICE_ATTR(get_icons	, _M444, get_icons	, NULL		);
static DEVICE_ATTR(show_icon	, _M220, NULL		, show_icon	);
static DEVICE_ATTR(hide_icon	, _M220, NULL		, hide_icon	);
static DEVICE_ATTR(ringtone	, _M220, NULL		, store_ringtone);

static struct attribute *yld_attrs[] =;
ATTRIBUTE_GROUPS();

/*******************************************************************************
 * Linux interface and usb initialisation
 ******************************************************************************/

struct driver_info {};

static const struct driver_info info_P1K =;

static const struct usb_device_id usb_table [] =;

static int usb_cleanup(struct yealink_dev *yld, int err)
{}

static void usb_disconnect(struct usb_interface *intf)
{}

static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
{}

static struct usb_driver yealink_driver =;

module_usb_driver();

MODULE_DEVICE_TABLE (usb, usb_table);

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();