diff --git a/[refs] b/[refs] index b52f05492d01..049be220d4c1 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: c87019e41d61f3f972bd2f6a2380fc9896e4ab74 +refs/heads/master: 4a4c879904aa0cc64629e14a49b64fb3d149bf1a diff --git a/trunk/drivers/hid/Kconfig b/trunk/drivers/hid/Kconfig index 1130a8987125..306b15f39c9c 100644 --- a/trunk/drivers/hid/Kconfig +++ b/trunk/drivers/hid/Kconfig @@ -589,7 +589,6 @@ config HID_WACOM_POWER_SUPPLY config HID_WIIMOTE tristate "Nintendo Wii Remote support" depends on BT_HIDP - depends on LEDS_CLASS ---help--- Support for the Nintendo Wii Remote bluetooth device. diff --git a/trunk/drivers/hid/hid-apple.c b/trunk/drivers/hid/hid-apple.c index b85744fe8464..18b3bc646bf3 100644 --- a/trunk/drivers/hid/hid-apple.c +++ b/trunk/drivers/hid/hid-apple.c @@ -444,6 +444,12 @@ static const struct hid_device_id apple_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS), .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN | APPLE_RDESC_JIS }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ANSI), + .driver_data = APPLE_HAS_FN }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ISO), + .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_JIS), + .driver_data = APPLE_HAS_FN }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI), .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO), diff --git a/trunk/drivers/hid/hid-core.c b/trunk/drivers/hid/hid-core.c index 1a5cf0c9cfca..242353df3dc4 100644 --- a/trunk/drivers/hid/hid-core.c +++ b/trunk/drivers/hid/hid-core.c @@ -1340,6 +1340,9 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_JIS) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, diff --git a/trunk/drivers/hid/hid-ids.h b/trunk/drivers/hid/hid-ids.h index db63ccf21cc8..61c880939f56 100644 --- a/trunk/drivers/hid/hid-ids.h +++ b/trunk/drivers/hid/hid-ids.h @@ -109,6 +109,9 @@ #define USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI 0x0245 #define USB_DEVICE_ID_APPLE_WELLSPRING5_ISO 0x0246 #define USB_DEVICE_ID_APPLE_WELLSPRING5_JIS 0x0247 +#define USB_DEVICE_ID_APPLE_ALU_REVB_ANSI 0x024f +#define USB_DEVICE_ID_APPLE_ALU_REVB_ISO 0x0250 +#define USB_DEVICE_ID_APPLE_ALU_REVB_JIS 0x0251 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI 0x0239 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO 0x023a #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS 0x023b diff --git a/trunk/drivers/hid/hid-wiimote.c b/trunk/drivers/hid/hid-wiimote.c index 85a02e5f9fe8..a594383ce03d 100644 --- a/trunk/drivers/hid/hid-wiimote.c +++ b/trunk/drivers/hid/hid-wiimote.c @@ -10,10 +10,10 @@ * any later version. */ +#include #include #include #include -#include #include #include #include "hid-ids.h" @@ -33,9 +33,9 @@ struct wiimote_state { }; struct wiimote_data { + atomic_t ready; struct hid_device *hdev; struct input_dev *input; - struct led_classdev *leds[4]; spinlock_t qlock; __u8 head; @@ -53,15 +53,8 @@ struct wiimote_data { #define WIIPROTO_FLAGS_LEDS (WIIPROTO_FLAG_LED1 | WIIPROTO_FLAG_LED2 | \ WIIPROTO_FLAG_LED3 | WIIPROTO_FLAG_LED4) -/* return flag for led \num */ -#define WIIPROTO_FLAG_LED(num) (WIIPROTO_FLAG_LED1 << (num - 1)) - enum wiiproto_reqs { - WIIPROTO_REQ_NULL = 0x0, WIIPROTO_REQ_LED = 0x11, - WIIPROTO_REQ_DRM = 0x12, - WIIPROTO_REQ_STATUS = 0x20, - WIIPROTO_REQ_RETURN = 0x22, WIIPROTO_REQ_DRM_K = 0x30, }; @@ -94,6 +87,9 @@ static __u16 wiiproto_keymap[] = { BTN_MODE, /* WIIPROTO_KEY_HOME */ }; +#define dev_to_wii(pdev) hid_get_drvdata(container_of(pdev, struct hid_device, \ + dev)) + static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer, size_t count) { @@ -196,96 +192,66 @@ static void wiiproto_req_leds(struct wiimote_data *wdata, int leds) wiimote_queue(wdata, cmd, sizeof(cmd)); } -/* - * Check what peripherals of the wiimote are currently - * active and select a proper DRM that supports all of - * the requested data inputs. - */ -static __u8 select_drm(struct wiimote_data *wdata) -{ - return WIIPROTO_REQ_DRM_K; -} - -static void wiiproto_req_drm(struct wiimote_data *wdata, __u8 drm) -{ - __u8 cmd[3]; - - if (drm == WIIPROTO_REQ_NULL) - drm = select_drm(wdata); - - cmd[0] = WIIPROTO_REQ_DRM; - cmd[1] = 0; - cmd[2] = drm; - - wiimote_queue(wdata, cmd, sizeof(cmd)); -} - -static enum led_brightness wiimote_leds_get(struct led_classdev *led_dev) -{ - struct wiimote_data *wdata; - struct device *dev = led_dev->dev->parent; - int i; - unsigned long flags; - bool value = false; - - wdata = hid_get_drvdata(container_of(dev, struct hid_device, dev)); - - for (i = 0; i < 4; ++i) { - if (wdata->leds[i] == led_dev) { - spin_lock_irqsave(&wdata->state.lock, flags); - value = wdata->state.flags & WIIPROTO_FLAG_LED(i + 1); - spin_unlock_irqrestore(&wdata->state.lock, flags); - break; - } - } - - return value ? LED_FULL : LED_OFF; -} - -static void wiimote_leds_set(struct led_classdev *led_dev, - enum led_brightness value) -{ - struct wiimote_data *wdata; - struct device *dev = led_dev->dev->parent; - int i; - unsigned long flags; - __u8 state, flag; - - wdata = hid_get_drvdata(container_of(dev, struct hid_device, dev)); - - for (i = 0; i < 4; ++i) { - if (wdata->leds[i] == led_dev) { - flag = WIIPROTO_FLAG_LED(i + 1); - spin_lock_irqsave(&wdata->state.lock, flags); - state = wdata->state.flags; - if (value == LED_OFF) - wiiproto_req_leds(wdata, state & ~flag); - else - wiiproto_req_leds(wdata, state | flag); - spin_unlock_irqrestore(&wdata->state.lock, flags); - break; - } - } -} +#define wiifs_led_show_set(num) \ +static ssize_t wiifs_led_show_##num(struct device *dev, \ + struct device_attribute *attr, char *buf) \ +{ \ + struct wiimote_data *wdata = dev_to_wii(dev); \ + unsigned long flags; \ + int state; \ + \ + if (!atomic_read(&wdata->ready)) \ + return -EBUSY; \ + \ + spin_lock_irqsave(&wdata->state.lock, flags); \ + state = !!(wdata->state.flags & WIIPROTO_FLAG_LED##num); \ + spin_unlock_irqrestore(&wdata->state.lock, flags); \ + \ + return sprintf(buf, "%d\n", state); \ +} \ +static ssize_t wiifs_led_set_##num(struct device *dev, \ + struct device_attribute *attr, const char *buf, size_t count) \ +{ \ + struct wiimote_data *wdata = dev_to_wii(dev); \ + int tmp = simple_strtoul(buf, NULL, 10); \ + unsigned long flags; \ + __u8 state; \ + \ + if (!atomic_read(&wdata->ready)) \ + return -EBUSY; \ + \ + spin_lock_irqsave(&wdata->state.lock, flags); \ + \ + state = wdata->state.flags; \ + \ + if (tmp) \ + wiiproto_req_leds(wdata, state | WIIPROTO_FLAG_LED##num);\ + else \ + wiiproto_req_leds(wdata, state & ~WIIPROTO_FLAG_LED##num);\ + \ + spin_unlock_irqrestore(&wdata->state.lock, flags); \ + \ + return count; \ +} \ +static DEVICE_ATTR(led##num, S_IRUGO | S_IWUSR, wiifs_led_show_##num, \ + wiifs_led_set_##num) + +wiifs_led_show_set(1); +wiifs_led_show_set(2); +wiifs_led_show_set(3); +wiifs_led_show_set(4); static int wiimote_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) -{ - return 0; -} - -static int wiimote_input_open(struct input_dev *dev) { struct wiimote_data *wdata = input_get_drvdata(dev); - return hid_hw_open(wdata->hdev); -} - -static void wiimote_input_close(struct input_dev *dev) -{ - struct wiimote_data *wdata = input_get_drvdata(dev); + if (!atomic_read(&wdata->ready)) + return -EBUSY; + /* smp_rmb: Make sure wdata->xy is available when wdata->ready is 1 */ + smp_rmb(); - hid_hw_close(wdata->hdev); + return 0; } static void handler_keys(struct wiimote_data *wdata, const __u8 *payload) @@ -315,26 +281,6 @@ static void handler_keys(struct wiimote_data *wdata, const __u8 *payload) input_sync(wdata->input); } -static void handler_status(struct wiimote_data *wdata, const __u8 *payload) -{ - handler_keys(wdata, payload); - - /* on status reports the drm is reset so we need to resend the drm */ - wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); -} - -static void handler_return(struct wiimote_data *wdata, const __u8 *payload) -{ - __u8 err = payload[3]; - __u8 cmd = payload[2]; - - handler_keys(wdata, payload); - - if (err) - hid_warn(wdata->hdev, "Remote error %hhu on req %hhu\n", err, - cmd); -} - struct wiiproto_handler { __u8 id; size_t size; @@ -342,8 +288,6 @@ struct wiiproto_handler { }; static struct wiiproto_handler handlers[] = { - { .id = WIIPROTO_REQ_STATUS, .size = 6, .func = handler_status }, - { .id = WIIPROTO_REQ_RETURN, .size = 4, .func = handler_return }, { .id = WIIPROTO_REQ_DRM_K, .size = 2, .func = handler_keys }, { .id = 0 } }; @@ -356,6 +300,11 @@ static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report, int i; unsigned long flags; + if (!atomic_read(&wdata->ready)) + return -EBUSY; + /* smp_rmb: Make sure wdata->xy is available when wdata->ready is 1 */ + smp_rmb(); + if (size < 1) return -EINVAL; @@ -372,58 +321,6 @@ static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report, return 0; } -static void wiimote_leds_destroy(struct wiimote_data *wdata) -{ - int i; - struct led_classdev *led; - - for (i = 0; i < 4; ++i) { - if (wdata->leds[i]) { - led = wdata->leds[i]; - wdata->leds[i] = NULL; - led_classdev_unregister(led); - kfree(led); - } - } -} - -static int wiimote_leds_create(struct wiimote_data *wdata) -{ - int i, ret; - struct device *dev = &wdata->hdev->dev; - size_t namesz = strlen(dev_name(dev)) + 9; - struct led_classdev *led; - char *name; - - for (i = 0; i < 4; ++i) { - led = kzalloc(sizeof(struct led_classdev) + namesz, GFP_KERNEL); - if (!led) { - ret = -ENOMEM; - goto err; - } - name = (void*)&led[1]; - snprintf(name, namesz, "%s:blue:p%d", dev_name(dev), i); - led->name = name; - led->brightness = 0; - led->max_brightness = 1; - led->brightness_get = wiimote_leds_get; - led->brightness_set = wiimote_leds_set; - - ret = led_classdev_register(dev, led); - if (ret) { - kfree(led); - goto err; - } - wdata->leds[i] = led; - } - - return 0; - -err: - wiimote_leds_destroy(wdata); - return ret; -} - static struct wiimote_data *wiimote_create(struct hid_device *hdev) { struct wiimote_data *wdata; @@ -444,8 +341,6 @@ static struct wiimote_data *wiimote_create(struct hid_device *hdev) input_set_drvdata(wdata->input, wdata); wdata->input->event = wiimote_input_event; - wdata->input->open = wiimote_input_open; - wdata->input->close = wiimote_input_close; wdata->input->dev.parent = &wdata->hdev->dev; wdata->input->id.bustype = wdata->hdev->bus; wdata->input->id.vendor = wdata->hdev->vendor; @@ -467,12 +362,6 @@ static struct wiimote_data *wiimote_create(struct hid_device *hdev) static void wiimote_destroy(struct wiimote_data *wdata) { - wiimote_leds_destroy(wdata); - - input_unregister_device(wdata->input); - cancel_work_sync(&wdata->worker); - hid_hw_stop(wdata->hdev); - kfree(wdata); } @@ -488,6 +377,19 @@ static int wiimote_hid_probe(struct hid_device *hdev, return -ENOMEM; } + ret = device_create_file(&hdev->dev, &dev_attr_led1); + if (ret) + goto err; + ret = device_create_file(&hdev->dev, &dev_attr_led2); + if (ret) + goto err; + ret = device_create_file(&hdev->dev, &dev_attr_led3); + if (ret) + goto err; + ret = device_create_file(&hdev->dev, &dev_attr_led4); + if (ret) + goto err; + ret = hid_parse(hdev); if (ret) { hid_err(hdev, "HID parse failed\n"); @@ -506,10 +408,9 @@ static int wiimote_hid_probe(struct hid_device *hdev, goto err_stop; } - ret = wiimote_leds_create(wdata); - if (ret) - goto err_free; - + /* smp_wmb: Write wdata->xy first before wdata->ready is set to 1 */ + smp_wmb(); + atomic_set(&wdata->ready, 1); hid_info(hdev, "New device registered\n"); /* by default set led1 after device initialization */ @@ -519,15 +420,15 @@ static int wiimote_hid_probe(struct hid_device *hdev, return 0; -err_free: - wiimote_destroy(wdata); - return ret; - err_stop: hid_hw_stop(hdev); err: input_free_device(wdata->input); - kfree(wdata); + device_remove_file(&hdev->dev, &dev_attr_led1); + device_remove_file(&hdev->dev, &dev_attr_led2); + device_remove_file(&hdev->dev, &dev_attr_led3); + device_remove_file(&hdev->dev, &dev_attr_led4); + wiimote_destroy(wdata); return ret; } @@ -536,6 +437,16 @@ static void wiimote_hid_remove(struct hid_device *hdev) struct wiimote_data *wdata = hid_get_drvdata(hdev); hid_info(hdev, "Device removed\n"); + + device_remove_file(&hdev->dev, &dev_attr_led1); + device_remove_file(&hdev->dev, &dev_attr_led2); + device_remove_file(&hdev->dev, &dev_attr_led3); + device_remove_file(&hdev->dev, &dev_attr_led4); + + hid_hw_stop(hdev); + input_unregister_device(wdata->input); + + cancel_work_sync(&wdata->worker); wiimote_destroy(wdata); }