0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/device.h>
0011 #include <linux/hid.h>
0012 #include <linux/module.h>
0013 #include "hid-ids.h"
0014
0015 MODULE_AUTHOR("Ben Chen");
0016 MODULE_AUTHOR("Thomas Weißschuh");
0017 MODULE_DESCRIPTION("CM6533 HID jack controls and HS100B mute button");
0018 MODULE_LICENSE("GPL");
0019
0020 #define CM6533_JD_TYPE_COUNT 1
0021 #define CM6533_JD_RAWEV_LEN 16
0022 #define CM6533_JD_SFX_OFFSET 8
0023
0024 #define HS100B_RDESC_ORIG_SIZE 60
0025
0026
0027
0028
0029 static __u8 hs100b_rdesc_fixed[] = {
0030 0x05, 0x0C,
0031 0x09, 0x01,
0032 0xA1, 0x01,
0033 0x15, 0x00,
0034 0x25, 0x01,
0035 0x09, 0xE9,
0036 0x09, 0xEA,
0037 0x75, 0x01,
0038 0x95, 0x02,
0039 0x81, 0x02,
0040 0x09, 0xE2,
0041 0x95, 0x01,
0042 0x81, 0x06,
0043 0x05, 0x0B,
0044 0x09, 0x2F,
0045 0x81, 0x02,
0046 0x09, 0x20,
0047 0x81, 0x06,
0048 0x05, 0x0C,
0049 0x09, 0x00,
0050 0x95, 0x03,
0051 0x81, 0x02,
0052 0x26, 0xFF, 0x00,
0053 0x09, 0x00,
0054 0x75, 0x08,
0055 0x95, 0x03,
0056 0x81, 0x02,
0057 0x09, 0x00,
0058 0x95, 0x04,
0059 0x91, 0x02,
0060 0xC0
0061 };
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077 static const u8 ji_sfx[] = { 0x08, 0x00, 0x08, 0xc0 };
0078 static const u8 ji_in[] = { 0x01, 0x00, 0x06, 0x00 };
0079 static const u8 ji_out[] = { 0x01, 0x00, 0x04, 0x00 };
0080
0081 static int jack_switch_types[CM6533_JD_TYPE_COUNT] = {
0082 SW_HEADPHONE_INSERT,
0083 };
0084
0085 struct cmhid {
0086 struct input_dev *input_dev;
0087 struct hid_device *hid;
0088 unsigned short switch_map[CM6533_JD_TYPE_COUNT];
0089 };
0090
0091 static void hp_ev(struct hid_device *hid, struct cmhid *cm, int value)
0092 {
0093 input_report_switch(cm->input_dev, SW_HEADPHONE_INSERT, value);
0094 input_sync(cm->input_dev);
0095 }
0096
0097 static int cmhid_raw_event(struct hid_device *hid, struct hid_report *report,
0098 u8 *data, int len)
0099 {
0100 struct cmhid *cm = hid_get_drvdata(hid);
0101
0102 if (len != CM6533_JD_RAWEV_LEN)
0103 goto out;
0104 if (memcmp(data+CM6533_JD_SFX_OFFSET, ji_sfx, sizeof(ji_sfx)))
0105 goto out;
0106
0107 if (!memcmp(data, ji_out, sizeof(ji_out))) {
0108 hp_ev(hid, cm, 0);
0109 goto out;
0110 }
0111 if (!memcmp(data, ji_in, sizeof(ji_in))) {
0112 hp_ev(hid, cm, 1);
0113 goto out;
0114 }
0115
0116 out:
0117 return 0;
0118 }
0119
0120 static int cmhid_input_configured(struct hid_device *hid,
0121 struct hid_input *hidinput)
0122 {
0123 struct input_dev *input_dev = hidinput->input;
0124 struct cmhid *cm = hid_get_drvdata(hid);
0125 int i;
0126
0127 cm->input_dev = input_dev;
0128 memcpy(cm->switch_map, jack_switch_types, sizeof(cm->switch_map));
0129 input_dev->evbit[0] = BIT(EV_SW);
0130 for (i = 0; i < CM6533_JD_TYPE_COUNT; i++)
0131 input_set_capability(cm->input_dev,
0132 EV_SW, jack_switch_types[i]);
0133 return 0;
0134 }
0135
0136 static int cmhid_input_mapping(struct hid_device *hid,
0137 struct hid_input *hi, struct hid_field *field,
0138 struct hid_usage *usage, unsigned long **bit, int *max)
0139 {
0140 return -1;
0141 }
0142
0143 static int cmhid_probe(struct hid_device *hid, const struct hid_device_id *id)
0144 {
0145 int ret;
0146 struct cmhid *cm;
0147
0148 cm = kzalloc(sizeof(struct cmhid), GFP_KERNEL);
0149 if (!cm) {
0150 ret = -ENOMEM;
0151 goto allocfail;
0152 }
0153
0154 cm->hid = hid;
0155
0156 hid->quirks |= HID_QUIRK_HIDINPUT_FORCE;
0157 hid_set_drvdata(hid, cm);
0158
0159 ret = hid_parse(hid);
0160 if (ret) {
0161 hid_err(hid, "parse failed\n");
0162 goto fail;
0163 }
0164
0165 ret = hid_hw_start(hid, HID_CONNECT_DEFAULT | HID_CONNECT_HIDDEV_FORCE);
0166 if (ret) {
0167 hid_err(hid, "hw start failed\n");
0168 goto fail;
0169 }
0170
0171 return 0;
0172 fail:
0173 kfree(cm);
0174 allocfail:
0175 return ret;
0176 }
0177
0178 static void cmhid_remove(struct hid_device *hid)
0179 {
0180 struct cmhid *cm = hid_get_drvdata(hid);
0181
0182 hid_hw_stop(hid);
0183 kfree(cm);
0184 }
0185
0186 static const struct hid_device_id cmhid_devices[] = {
0187 { HID_USB_DEVICE(USB_VENDOR_ID_CMEDIA, USB_DEVICE_ID_CM6533) },
0188 { }
0189 };
0190 MODULE_DEVICE_TABLE(hid, cmhid_devices);
0191
0192 static struct hid_driver cmhid_driver = {
0193 .name = "cm6533_jd",
0194 .id_table = cmhid_devices,
0195 .raw_event = cmhid_raw_event,
0196 .input_configured = cmhid_input_configured,
0197 .probe = cmhid_probe,
0198 .remove = cmhid_remove,
0199 .input_mapping = cmhid_input_mapping,
0200 };
0201
0202 static __u8 *cmhid_hs100b_report_fixup(struct hid_device *hid, __u8 *rdesc,
0203 unsigned int *rsize)
0204 {
0205 if (*rsize == HS100B_RDESC_ORIG_SIZE) {
0206 hid_info(hid, "Fixing CMedia HS-100B report descriptor\n");
0207 rdesc = hs100b_rdesc_fixed;
0208 *rsize = sizeof(hs100b_rdesc_fixed);
0209 }
0210 return rdesc;
0211 }
0212
0213 static const struct hid_device_id cmhid_hs100b_devices[] = {
0214 { HID_USB_DEVICE(USB_VENDOR_ID_CMEDIA, USB_DEVICE_ID_CMEDIA_HS100B) },
0215 { }
0216 };
0217 MODULE_DEVICE_TABLE(hid, cmhid_hs100b_devices);
0218
0219 static struct hid_driver cmhid_hs100b_driver = {
0220 .name = "cmedia_hs100b",
0221 .id_table = cmhid_hs100b_devices,
0222 .report_fixup = cmhid_hs100b_report_fixup,
0223 };
0224
0225 static int cmedia_init(void)
0226 {
0227 int ret;
0228
0229 ret = hid_register_driver(&cmhid_driver);
0230 if (ret)
0231 return ret;
0232
0233 ret = hid_register_driver(&cmhid_hs100b_driver);
0234 if (ret)
0235 hid_unregister_driver(&cmhid_driver);
0236
0237 return ret;
0238 }
0239 module_init(cmedia_init);
0240
0241 static void cmedia_exit(void)
0242 {
0243 hid_unregister_driver(&cmhid_driver);
0244 hid_unregister_driver(&cmhid_hs100b_driver);
0245 }
0246 module_exit(cmedia_exit);