You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Staging: add frontier tranzport and alphatrack drivers
Adds the tranzport and alphatrack drivers to the staging tree. Cc: David Taht <d@teklibre.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
1242c70df5
commit
8da3dc2875
@@ -0,0 +1,6 @@
|
||||
config TRANZPORT
|
||||
tristate "Frontier Tranzport and Alphatrack support"
|
||||
depends on USB
|
||||
default N
|
||||
---help---
|
||||
Enable support for the Frontier Tranzport and Alphatrack devices.
|
||||
@@ -0,0 +1,2 @@
|
||||
obj-$(CONFIG_TRANZPORT) += tranzport.o
|
||||
obj-$(CONFIG_TRANZPORT) += alphatrack.o
|
||||
@@ -0,0 +1,28 @@
|
||||
This directory contains the USB Tranzport and Alphatrack Kernel drivers for Linux.
|
||||
|
||||
At present the tranzport does reads/writes of 8 byte cmds to /dev/tranzport0 to control
|
||||
the lights and screen and wheel
|
||||
|
||||
At present the alphatrack accepts reads/writes of 12 byte cmds to /dev/tranzport0 to control
|
||||
the lights and screen and fader.
|
||||
|
||||
Both drivers also have some sysfs hooks that are non-functional at the moment.
|
||||
|
||||
The API is currently closely tied to the ardour revision and WILL change.
|
||||
|
||||
A sysfs interface is PERFECT for simple userspace apps to do fun things with the
|
||||
lights and screen. It's fairly lousy for handling input events and very lousy
|
||||
for watching the state of the shuttle wheel.
|
||||
|
||||
A linux input events interface is great for the input events and shuttle wheel. It's
|
||||
theoretically OK on LEDs. A Fader can be mapped to an absolute mouse device.
|
||||
But there is no LCD support at all.
|
||||
|
||||
In the end this is going to be driven by a midi layer, which handles all those
|
||||
cases via a defined API, but - among other things - is slow, doesn't do
|
||||
flow control, and is a LOT of extra work. Frankly, I'd like to keep the
|
||||
core driver simple because the only realtime work really required is
|
||||
the bottom half interrupt handler and the output overlapping.
|
||||
|
||||
Exposing some sort of clean aio api to userspace would be perfect. What that
|
||||
API looks like? Gah. beats me.
|
||||
@@ -0,0 +1,9 @@
|
||||
TODO:
|
||||
- checkpatch.pl clean
|
||||
- sparse clean
|
||||
- fix userspace interface to be sane
|
||||
- possibly just port to userspace with libusb
|
||||
- review by the USB developer community
|
||||
|
||||
Please send any patches for this driver to Greg Kroah-Hartman <greg@kroah.com>
|
||||
and David Taht <d@teklibre.com>.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,117 @@
|
||||
#define show_set_bit(a) show_set_mbit(alphatrack,a)
|
||||
#define show_set_cmd(a) show_set_mcmd(alphatrack,a)
|
||||
#define show_set_int(a) show_set_mint(alphatrack,a)
|
||||
#define show_set_char(a) show_set_mchar(alphatrack,a)
|
||||
#define show_set_light(a) show_set_ebit(alphatrack,LightID,lights,a)
|
||||
#define show_set_button(a) show_set_ebit(alphatrack,ButtonID,button,a)
|
||||
|
||||
struct alphatrack_icmd {
|
||||
unsigned char cmd[12];
|
||||
};
|
||||
|
||||
struct alphatrack_ocmd {
|
||||
unsigned char cmd[8];
|
||||
};
|
||||
|
||||
enum LightID {
|
||||
LIGHT_EQ = 0,
|
||||
LIGHT_OUT,
|
||||
LIGHT_F2,
|
||||
LIGHT_SEND,
|
||||
LIGHT_IN,
|
||||
LIGHT_F1,
|
||||
LIGHT_PAN,
|
||||
LIGHT_UNDEF1,
|
||||
LIGHT_UNDEF2,
|
||||
LIGHT_SHIFT,
|
||||
LIGHT_TRACKMUTE,
|
||||
LIGHT_TRACKSOLO,
|
||||
LIGHT_TRACKREC,
|
||||
LIGHT_READ,
|
||||
LIGHT_WRITE,
|
||||
LIGHT_ANYSOLO,
|
||||
LIGHT_AUTO,
|
||||
LIGHT_F4,
|
||||
LIGHT_RECORD,
|
||||
LIGHT_WINDOW,
|
||||
LIGHT_PLUGIN,
|
||||
LIGHT_F3,
|
||||
LIGHT_LOOP
|
||||
};
|
||||
|
||||
static const char *Lightname[] = { "eq",
|
||||
"out",
|
||||
"f2",
|
||||
"send",
|
||||
"in",
|
||||
"f1",
|
||||
"pan",
|
||||
"undef1",
|
||||
"undef2",
|
||||
"shift",
|
||||
"mute",
|
||||
"tracksolo",
|
||||
"trackrec",
|
||||
"read",
|
||||
"write",
|
||||
"anysolo",
|
||||
"auto",
|
||||
"f4",
|
||||
"record",
|
||||
"window",
|
||||
"plugin",
|
||||
"f3",
|
||||
"loop",
|
||||
NULL };
|
||||
|
||||
#define BUTTONMASK_BATTERY 0x00004000
|
||||
#define BUTTONMASK_BACKLIGHT 0x00008000
|
||||
#define BUTTONMASK_FASTFORWARD 0x04000000
|
||||
#define BUTTONMASK_TRACKMUTE 0x00040000
|
||||
#define BUTTONMASK_TRACKSOLO 0x00800000
|
||||
#define BUTTONMASK_TRACKLEFT 0x80000000
|
||||
#define BUTTONMASK_RECORD 0x02000000
|
||||
#define BUTTONMASK_SHIFT 0x20000000
|
||||
#define BUTTONMASK_PUNCH 0x00800000
|
||||
#define BUTTONMASK_TRACKRIGHT 0x00020000
|
||||
#define BUTTONMASK_REWIND 0x01000000
|
||||
#define BUTTONMASK_STOP 0x10000000
|
||||
#define BUTTONMASK_LOOP 0x00010000
|
||||
#define BUTTONMASK_TRACKREC 0x00001000
|
||||
#define BUTTONMASK_PLAY 0x08000000
|
||||
#define BUTTONMASK_TOUCH1 0x00000008
|
||||
#define BUTTONMASK_TOUCH2 0x00000010
|
||||
#define BUTTONMASK_TOUCH3 0x00000020
|
||||
|
||||
#define BUTTONMASK_PRESS1 0x00000009
|
||||
#define BUTTONMASK_PRESS2 0x00008010
|
||||
#define BUTTONMASK_PRESS3 0x00002020
|
||||
|
||||
// last 3 bytes are the slider position
|
||||
// 40 is the actual slider moving, the most sig bits, and 3 lsb
|
||||
|
||||
#define BUTTONMASK_FLIP 0x40000000
|
||||
#define BUTTONMASK_F1 0x00100000
|
||||
#define BUTTONMASK_F2 0x00400000
|
||||
#define BUTTONMASK_F3 0x00200000
|
||||
#define BUTTONMASK_F4 0x00080000
|
||||
#define BUTTONMASK_PAN 0x00000200
|
||||
#define BUTTONMASK_SEND 0x00000800
|
||||
#define BUTTONMASK_EQ 0x00004000
|
||||
#define BUTTONMASK_PLUGIN 0x00000400
|
||||
#define BUTTONMASK_AUTO 0x00000100
|
||||
|
||||
|
||||
// #define BUTTONMASK_FOOTSWITCH FIXME
|
||||
|
||||
// Lookup. name. midi out. midi in.
|
||||
|
||||
struct buttonmap_t {
|
||||
u32 mask;
|
||||
short midi_in;
|
||||
short midi_out;
|
||||
char *name;
|
||||
// void (*function) (buttonmap_t *);
|
||||
void (*function) (void);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,279 @@
|
||||
/* This was an attempt - ultimately proved pointless - at making a full fledged sysfs interface to the alphatrack */
|
||||
/* won't even compile at present */
|
||||
|
||||
char *alphatrack_sys_margs;
|
||||
spinlock_t alphatrack_sys_margs_lock;
|
||||
|
||||
struct alphatrack_attr {
|
||||
struct attribute attr;
|
||||
ssize_t (*show)(struct device *, char *);
|
||||
ssize_t (*store)(struct device *, const char *, size_t);
|
||||
};
|
||||
|
||||
#define ALPHATRACK_ATTR(name, mode, show, store) \
|
||||
static struct alphatrack_attr alphatrack_attr_##name = __ATTR(name, mode, show, store)
|
||||
|
||||
/* now a great deal of callback code generation */
|
||||
|
||||
// FOREACH_LIGHT(show_set_light)
|
||||
// FOREACH_BUTTON(show_set_button)
|
||||
|
||||
show_set_light(LIGHT_RECORD); show_set_light(LIGHT_EQ); show_set_light(LIGHT_OUT);
|
||||
show_set_light(LIGHT_F2); show_set_light(LIGHT_SEND); show_set_light(LIGHT_IN);
|
||||
show_set_light(LIGHT_F1); show_set_light(LIGHT_PAN); show_set_light(LIGHT_UNDEF1);
|
||||
show_set_light(LIGHT_UNDEF2); show_set_light(LIGHT_SHIFT); show_set_light(LIGHT_TRACKMUTE);
|
||||
show_set_light(LIGHT_TRACKSOLO); show_set_light(LIGHT_TRACKREC); show_set_light(LIGHT_READ);
|
||||
show_set_light(LIGHT_WRITE); show_set_light(LIGHT_ANYSOLO); show_set_light(LIGHT_AUTO);
|
||||
show_set_light(LIGHT_F4); show_set_light(LIGHT_RECORD); show_set_light(LIGHT_WINDOW);
|
||||
show_set_light(LIGHT_PLUGIN); show_set_light(LIGHT_F3); show_set_light(LIGHT_LOOP);
|
||||
|
||||
show_set_opt(enable); show_set_opt(offline); show_set_opt(compress_fader); show_set_opt(dump_state);
|
||||
show_set_int(fader); show_set_int(event);
|
||||
|
||||
|
||||
static ssize_t show_lights(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct usb_interface *intf = to_usb_interface(dev);
|
||||
struct usb_alphatrack *t = usb_get_intfdata(intf);
|
||||
return sprintf(buf, "%d\n", t->lights);
|
||||
}
|
||||
|
||||
static ssize_t set_lights(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
struct usb_interface *intf = to_usb_interface(dev);
|
||||
struct usb_alphatrack *t = usb_get_intfdata(intf);
|
||||
int temp = simple_strtoul(buf, NULL, 10);
|
||||
t->lights = temp;
|
||||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_lights, set_lights);
|
||||
|
||||
|
||||
ALPHATRACK_ATTR(LightRecord, 0200, NULL, LightRecord_store);
|
||||
|
||||
static struct attribute *alphatrack_attrs[] = {
|
||||
&alphatrack_attr_LightRecord.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static ssize_t alphatrack_attr_show(struct kobject *kobj, struct attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct device *sdp = container_of(kobj, struct device, kobj);
|
||||
struct alphatrack_attr *a = container_of(attr, struct alphatrack_attr, attr);
|
||||
return a->show ? a->show(sdp, buf) : 0;
|
||||
}
|
||||
|
||||
static ssize_t alphatrack_attr_store(struct kobject *kobj, struct attribute *attr,
|
||||
const char *buf, size_t len)
|
||||
{
|
||||
struct device *sdp = container_of(kobj, struct device, kobj);
|
||||
struct alphatrack_attr *a = container_of(attr, struct alphatrack_attr, attr);
|
||||
return a->store ? a->store(sdp, buf, len) : len;
|
||||
}
|
||||
|
||||
static struct sysfs_ops alphatrack_attr_ops = {
|
||||
.show = alphatrack_attr_show,
|
||||
.store = alphatrack_attr_store,
|
||||
};
|
||||
|
||||
static struct kobj_type alphatrack_ktype = {
|
||||
.default_attrs = alphatrack_attrs,
|
||||
.sysfs_ops = &alphatrack_attr_ops,
|
||||
};
|
||||
|
||||
static struct kset alphatrack_kset = {
|
||||
.subsys = &fs_subsys,
|
||||
.kobj = {.name = "alphatrack"},
|
||||
.ktype = &alphatrack_ktype,
|
||||
};
|
||||
|
||||
|
||||
static struct attribute *lights_attrs[] = {
|
||||
&tune_attr_demote_secs.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
||||
static struct attribute_group leds_group = {
|
||||
.name = "leds",
|
||||
.attrs = lights_attrs,
|
||||
};
|
||||
|
||||
static struct attribute_group faders_group = {
|
||||
.name = "faders",
|
||||
.attrs = faders_attrs,
|
||||
};
|
||||
|
||||
static struct attribute_group lcds_group = {
|
||||
.name = "lcds",
|
||||
.attrs = lcds_attrs,
|
||||
};
|
||||
|
||||
static struct attribute_group wheels_group = {
|
||||
.name = "wheels",
|
||||
.attrs = wheels_attrs,
|
||||
};
|
||||
|
||||
static struct attribute_group touchsurfaces_group = {
|
||||
.name = "touchsurfaces",
|
||||
.attrs = touchsurfaces_attrs,
|
||||
};
|
||||
|
||||
static struct attribute_group buttons_group = {
|
||||
.name = "buttons",
|
||||
.attrs = buttons_attrs,
|
||||
};
|
||||
|
||||
|
||||
int alphatrack_sys_fs_add(struct device *sdp)
|
||||
{
|
||||
int error;
|
||||
|
||||
sdp->kobj.kset = &alphatrack_kset;
|
||||
sdp->kobj.ktype = &alphatrack_ktype;
|
||||
|
||||
// error = kobject_set_name(&sdp->kobj, "%s", sdp->sd_table_name);
|
||||
error = kobject_set_name(&sdp->kobj, "%s", "alphatrack");
|
||||
if (error)
|
||||
goto fail;
|
||||
|
||||
error = kobject_register(&sdp->kobj);
|
||||
if (error)
|
||||
goto fail;
|
||||
|
||||
error = sysfs_create_group(&sdp->kobj, &lcds_group);
|
||||
if (error)
|
||||
goto fail_reg;
|
||||
|
||||
error = sysfs_create_group(&sdp->kobj, &leds_group);
|
||||
if (error)
|
||||
goto fail_leds;
|
||||
|
||||
error = sysfs_create_group(&sdp->kobj, &wheels_group);
|
||||
if (error)
|
||||
goto fail_wheels;
|
||||
|
||||
error = sysfs_create_group(&sdp->kobj, &faders_group);
|
||||
if (error)
|
||||
goto fail_lcds;
|
||||
|
||||
error = sysfs_create_group(&sdp->kobj, &buttons_group);
|
||||
if (error)
|
||||
goto fail_faders;
|
||||
|
||||
error = sysfs_create_group(&sdp->kobj, &touchsurfaces_group);
|
||||
if (error)
|
||||
goto fail_buttons;
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
fail_buttons:
|
||||
sysfs_remove_group(&sdp->kobj, &buttons_group);
|
||||
fail_faders:
|
||||
sysfs_remove_group(&sdp->kobj, &faders_group);
|
||||
fail_wheels:
|
||||
sysfs_remove_group(&sdp->kobj, &wheels_group);
|
||||
fail_lcds:
|
||||
sysfs_remove_group(&sdp->kobj, &lcds_group);
|
||||
fail_leds:
|
||||
sysfs_remove_group(&sdp->kobj, &leds_group);
|
||||
|
||||
|
||||
|
||||
fail_reg:
|
||||
kobject_unregister(&sdp->kobj);
|
||||
fail:
|
||||
fs_err(sdp, "error %d adding sysfs files", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
// int sysfs_create_link(struct kobject *kobj,
|
||||
// struct kobject *target,
|
||||
// char *name);
|
||||
|
||||
void alphatrack_sys_fs_del(struct device *sdp)
|
||||
{
|
||||
sysfs_remove_group(&sdp->kobj, &touchsurfaces_group);
|
||||
sysfs_remove_group(&sdp->kobj, &buttons_group);
|
||||
sysfs_remove_group(&sdp->kobj, &faders_group);
|
||||
sysfs_remove_group(&sdp->kobj, &lcds_group);
|
||||
sysfs_remove_group(&sdp->kobj, &wheels_group);
|
||||
sysfs_remove_group(&sdp->kobj, &leds_group)
|
||||
//void sysfs_remove_link(struct kobject *kobj, char *name);
|
||||
kobject_unregister(&sdp->kobj);
|
||||
}
|
||||
|
||||
int alphatrack_sys_init(void)
|
||||
{
|
||||
alphatrack_sys_margs = NULL;
|
||||
spin_lock_init(&alphatrack_sys_margs_lock);
|
||||
return kset_register(&alphatrack_kset);
|
||||
}
|
||||
|
||||
void alphatrack_sys_uninit(void)
|
||||
{
|
||||
kfree(alphatrack_sys_margs);
|
||||
kset_unregister(&alphatrack_kset);
|
||||
}
|
||||
|
||||
|
||||
//decl_subsys(char *name, struct kobj_type *type,
|
||||
// struct kset_hotplug_ops *hotplug_ops);
|
||||
|
||||
/* End of all the crazy sysfs stuff */
|
||||
|
||||
#define SYSEX_INQUIRE signed char *SYSEX_INQUIRE[] = { 0xf0,0x7e,0x00,0x06,0x01,0x17 };
|
||||
|
||||
#define COMMAND(NAME,CONT_NAME) { BUTTONMASK_##NAME, ((0x90 << 8) | CONT_NAME), ((0x90 << 8) | CONT_NAME), #NAME, NAME ## _set }
|
||||
#define ROTARY(NAME,CONT_NAME) { FADER_##NAME, ((0xb0 << 8) | CONT_NAME), ((0xb0 << 8) | CONT_NAME), #NAME, NAME ## _set }
|
||||
#define SPOSITION(NAME,CONT_NAME) { BUTTON_##NAME ((0xe9 << 8) | CONT_NAME), #NAME, NAME ## _set }
|
||||
#define ENDCOMMAND { 0,NULL,0,NULL,NULL}
|
||||
|
||||
/* Now that we've generated all our callbacks */
|
||||
|
||||
static struct buttonmap_t buttonmap[] =
|
||||
{
|
||||
COMMAND (REWIND,0x5b),
|
||||
COMMAND (FASTFORWARD,0x5c),
|
||||
COMMAND (STOP,0x5d),
|
||||
COMMAND (PLAY,0x5e),
|
||||
COMMAND (RECORD,0x5f),
|
||||
COMMAND (SHIFT,0x46),
|
||||
COMMAND (TRACKLEFT,0x57),
|
||||
COMMAND (TRACKRIGHT,0x58),
|
||||
COMMAND (LOOP,0x56),
|
||||
COMMAND (FLIP,0x32),
|
||||
COMMAND (MUTE,0x10),
|
||||
COMMAND (F1,0x36),
|
||||
COMMAND (F2,0x37),
|
||||
COMMAND (F3,0x38),
|
||||
COMMAND (F4,0x39),
|
||||
COMMAND (SOLO,0x08),
|
||||
COMMAND (ANY,0x73),
|
||||
COMMAND (PAN,0x2a),
|
||||
COMMAND (SEND,0x29),
|
||||
COMMAND (EQ,0x2c),
|
||||
COMMAND (PLUGIN,0x2b),
|
||||
COMMAND (AUTO,0x4a),
|
||||
COMMAND (TRACKREC,0x00),
|
||||
COMMAND (FOOTSWITCH1,0x67),
|
||||
COMMAND (KNOBTOUCH1,0x78),
|
||||
COMMAND (KNOBPUSH1,0x20),
|
||||
ROTARY (KNOBTURN1,0x10),
|
||||
COMMAND (KNOBTOUCH2,0x79),
|
||||
COMMAND (KNOBPUSH2,0x21),
|
||||
ROTARY (KNOBTURN2,0x11),
|
||||
COMMAND (KNOBTOUCH3,0x7a),
|
||||
COMMAND (KNOBPUSH3,0x22),
|
||||
ROTARY (KNOBTURN3,0x12),
|
||||
COMMAND (FADERTOUCH1,0x68),
|
||||
COMMAND (STRIPTOUCH1,0x74),
|
||||
COMMAND (STRIPTOUCH2,0x6b),
|
||||
SPOSITION (STRIPPOS1,0x00),
|
||||
ENDCOMMAND
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/* USB defines for older kernels */
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
|
||||
|
||||
/**
|
||||
* usb_endpoint_dir_out - check if the endpoint has OUT direction
|
||||
* @epd: endpoint to be checked
|
||||
*
|
||||
* Returns true if the endpoint is of type OUT, otherwise it returns false.
|
||||
*/
|
||||
|
||||
static inline int usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd)
|
||||
{
|
||||
return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT);
|
||||
}
|
||||
|
||||
static inline int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd)
|
||||
{
|
||||
return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* usb_endpoint_xfer_int - check if the endpoint has interrupt transfer type
|
||||
* @epd: endpoint to be checked
|
||||
*
|
||||
* Returns true if the endpoint is of type interrupt, otherwise it returns
|
||||
* false.
|
||||
*/
|
||||
static inline int usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd)
|
||||
{
|
||||
return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
|
||||
USB_ENDPOINT_XFER_INT);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* usb_endpoint_is_int_in - check if the endpoint is interrupt IN
|
||||
* @epd: endpoint to be checked
|
||||
*
|
||||
* Returns true if the endpoint has interrupt transfer type and IN direction,
|
||||
* otherwise it returns false.
|
||||
*/
|
||||
|
||||
static inline int usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd)
|
||||
{
|
||||
return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_in(epd));
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_endpoint_is_int_out - check if the endpoint is interrupt OUT
|
||||
* @epd: endpoint to be checked
|
||||
*
|
||||
* Returns true if the endpoint has interrupt transfer type and OUT direction,
|
||||
* otherwise it returns false.
|
||||
*/
|
||||
|
||||
static inline int usb_endpoint_is_int_out(const struct usb_endpoint_descriptor *epd)
|
||||
{
|
||||
return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_out(epd));
|
||||
}
|
||||
|
||||
#endif /* older kernel versions */
|
||||
@@ -0,0 +1,100 @@
|
||||
/* If you are going to abuse the preprocessor, why not ABUSE the preprocessor?
|
||||
I stuck this header in a separate file so I don't have to look at it */
|
||||
|
||||
// FIXME Need locking or atomic ops
|
||||
|
||||
#define show_set_mbit(dname,value,bit) \
|
||||
static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \
|
||||
{ \
|
||||
struct usb_interface *intf = to_usb_interface(dev); \
|
||||
struct usb_##dname *t = usb_get_intfdata(intf); \
|
||||
int temp = (1 && (t->value & (1 << bit))); \
|
||||
return sprintf(buf, "%d\n", temp); \
|
||||
} \
|
||||
static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
|
||||
{ \
|
||||
struct usb_interface *intf = to_usb_interface(dev); \
|
||||
struct usb_##dname *t = usb_get_intfdata(intf); \
|
||||
int temp = simple_strtoul(buf, NULL, 10); \
|
||||
if(temp > 0) { long b = 1 << bit; t->value |= b; } \
|
||||
else { long b = ~(1 << bit); t->value &= b ; \
|
||||
return count; \
|
||||
} \
|
||||
static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value);
|
||||
|
||||
#define show_set_ebit(dname,enumname,value,bit) \
|
||||
static ssize_t show_##bit(struct device *dev, struct device_attribute *attr, char *buf) \
|
||||
{ \
|
||||
struct usb_interface *intf = to_usb_interface(dev); \
|
||||
struct usb_##dname *t = usb_get_intfdata(intf); \
|
||||
enum enumname l = bit; \
|
||||
int temp = t->value & (1 << l); \
|
||||
return sprintf(buf, "%d\n", temp); \
|
||||
} \
|
||||
static ssize_t set_##bit(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
|
||||
{ \
|
||||
struct usb_interface *intf = to_usb_interface(dev); \
|
||||
struct usb_##dname *t = usb_get_intfdata(intf); \
|
||||
int temp = simple_strtoul(buf, NULL, 10); \
|
||||
enum enumname l = bit;\
|
||||
long b = 1 << l; \
|
||||
if(temp > 0) { t->value |= b; } \
|
||||
else { t->value &= ~b ; \
|
||||
return count; \
|
||||
} \
|
||||
static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value);
|
||||
|
||||
// FIXME FOR CORRECTLY SETTING HEX from a string
|
||||
#define show_set_mcmd(dname,value) \
|
||||
static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \
|
||||
{ \
|
||||
struct usb_interface *intf = to_usb_interface(dev); \
|
||||
struct usb_##dname *t = usb_get_intfdata(intf); \
|
||||
int count = 0;\
|
||||
int i; \
|
||||
for (i = 0,i<sizeof(dname); i++) count += snprintf(buf, "%02x",t->dname[i]); \
|
||||
return(count);\
|
||||
} \
|
||||
static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
|
||||
{ \
|
||||
struct usb_interface *intf = to_usb_interface(dev); \
|
||||
struct usb_##dname *t = usb_get_intfdata(intf); \
|
||||
int temp = simple_strtoul(buf, NULL, 10); \
|
||||
t->value = temp; \
|
||||
return count; \
|
||||
} \
|
||||
static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value);
|
||||
|
||||
#define show_set_mint(dname,value) \
|
||||
static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \
|
||||
{ \
|
||||
struct usb_interface *intf = to_usb_interface(dev); \
|
||||
struct usb_##dname *t = usb_get_intfdata(intf); \
|
||||
return sprintf(buf, "%d\n", t->value); \
|
||||
} \
|
||||
static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
|
||||
{ \
|
||||
struct usb_interface *intf = to_usb_interface(dev); \
|
||||
struct usb_##dname *t = usb_get_intfdata(intf); \
|
||||
int temp = simple_strtoul(buf, NULL, 10); \
|
||||
t->value = temp; \
|
||||
return count; \
|
||||
} \
|
||||
static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value);
|
||||
|
||||
#define show_set_mchar(dname,value) \
|
||||
static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \
|
||||
{ \
|
||||
struct usb_interface *intf = to_usb_interface(dev); \
|
||||
struct usb_##dname *t = usb_get_intfdata(intf); \
|
||||
return sprintf(buf, "%c\n", t->value); \
|
||||
} \
|
||||
static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
|
||||
{ \
|
||||
struct usb_interface *intf = to_usb_interface(dev); \
|
||||
struct usb_##dname *t = usb_get_intfdata(intf); \
|
||||
int temp = simple_strtoul(buf, NULL, 10); \
|
||||
t->value = temp; \
|
||||
return count; \
|
||||
} \
|
||||
static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value);
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user