123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802 |
- /*
- * Lowlevel hardware access for the
- * Razer Deathadder mouse
- *
- * Important notice:
- * This hardware driver is based on reverse engineering and
- * hardware documentation provided under NDA.
- *
- * Copyright (C) 2007-2011 Michael Buesch <m@bues.ch>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
- #include "hw_deathadder.h"
- #include "razer_private.h"
- #include "cypress_bootloader.h"
- #include <errno.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <stdint.h>
- #include <string.h>
- enum deathadder_type {
- DEATHADDER_CLASSIC, /* DeathAdder Classic */
- DEATHADDER_3500, /* DeathAdder 3500DPI */
- DEATHADDER_BLACK, /* DeathAdder Black Edition */
- };
- enum {
- DEATHADDER_LED_SCROLL = 0,
- DEATHADDER_LED_LOGO,
- DEATHADDER_NR_LEDS,
- };
- /* This is the device configuration structure sent to the device
- * for firmware version >= 1.25 */
- struct deathadder_125_cfg {
- uint8_t freq;
- uint8_t res;
- uint8_t profile;
- uint8_t leds;
- } _packed;
- struct deathadder_private {
- struct razer_mouse *m;
- /* The deathadder hardware revision type */
- enum deathadder_type type;
- bool in_bootloader;
- /* Firmware version number. */
- uint16_t fw_version;
- /* The currently set LED states. */
- bool led_states[DEATHADDER_NR_LEDS];
- /* The currently set frequency. */
- enum razer_mouse_freq frequency;
- /* Previous freq. For predicting reconnect events only. */
- enum razer_mouse_freq old_frequency;
- /* The currently set resolution. */
- struct razer_mouse_dpimapping *cur_dpimapping;
- struct razer_mouse_profile profile;
- struct razer_mouse_dpimapping dpimapping[4];
- bool commit_pending;
- struct razer_event_spacing commit_spacing;
- };
- #define DADD_FW(major, minor) (((major) << 8) | (minor))
- #define DEATHADDER_FW_IMAGE_SIZE 0x4000
- static int deathadder_usb_write(struct deathadder_private *priv,
- int request, int command,
- void *buf, size_t size)
- {
- int err;
- if (priv->in_bootloader) {
- /* Deathadder firmware is down and we're in the bootloader. */
- return 0;
- }
- err = libusb_control_transfer(
- priv->m->usb_ctx->h,
- LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS |
- LIBUSB_RECIPIENT_INTERFACE,
- request, command, 0,
- (unsigned char *)buf, size,
- RAZER_USB_TIMEOUT);
- if (err < 0 || (size_t)err != size) {
- razer_error("razer-deathadder: "
- "USB write 0x%02X 0x%02X failed: %d\n",
- request, command, err);
- return err;
- }
- return 0;
- }
- static int deathadder_usb_read(struct deathadder_private *priv,
- int request, int command,
- void *buf, size_t size)
- {
- int err;
- if (priv->in_bootloader) {
- /* Deathadder firmware is down and we're in the bootloader. */
- memset(buf, 0, size);
- return 0;
- }
- err = libusb_control_transfer(
- priv->m->usb_ctx->h,
- LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS |
- LIBUSB_RECIPIENT_INTERFACE,
- request, command, 0,
- buf, size,
- RAZER_USB_TIMEOUT);
- if (err < 0 || (size_t)err != size) {
- razer_error("razer-deathadder: "
- "USB read 0x%02X 0x%02X failed: %d\n",
- request, command, err);
- return err;
- }
- return 0;
- }
- static int deathadder_read_fw_ver(struct deathadder_private *priv)
- {
- char buf[2];
- uint16_t ver;
- int err;
- err = deathadder_usb_read(priv, LIBUSB_REQUEST_CLEAR_FEATURE,
- 0x05, buf, sizeof(buf));
- if (err)
- return err;
- ver = buf[0];
- ver <<= 8;
- ver |= buf[1];
- return ver;
- }
- static int deathadder_do_commit(struct deathadder_private *priv)
- {
- struct razer_usb_reconnect_guard guard;
- int i, err;
- if (priv->in_bootloader)
- return 0;
- razer_event_spacing_enter(&priv->commit_spacing);
- err = razer_usb_reconnect_guard_init(&guard, priv->m->usb_ctx);
- if (err)
- goto out;
- if (priv->type == DEATHADDER_CLASSIC &&
- priv->fw_version < DADD_FW(1,25)) {
- char value, freq_value, res_value;
- /* Translate frequency setting. */
- switch (priv->frequency) {
- case RAZER_MOUSE_FREQ_125HZ:
- freq_value = 3;
- break;
- case RAZER_MOUSE_FREQ_500HZ:
- freq_value = 2;
- break;
- case RAZER_MOUSE_FREQ_1000HZ:
- case RAZER_MOUSE_FREQ_UNKNOWN:
- freq_value = 1;
- break;
- default:
- err = -EINVAL;
- goto out;
- }
- /* Translate resolution setting. */
- switch (priv->cur_dpimapping->res[RAZER_DIM_0]) {
- case RAZER_MOUSE_RES_450DPI:
- res_value = 3;
- break;
- case RAZER_MOUSE_RES_900DPI:
- res_value = 2;
- break;
- case RAZER_MOUSE_RES_1800DPI:
- case RAZER_MOUSE_RES_UNKNOWN:
- res_value = 1;
- break;
- default:
- err = -EINVAL;
- goto out;
- }
- if (priv->old_frequency != priv->frequency) {
- /* Commit frequency setting. */
- err = deathadder_usb_write(priv, LIBUSB_REQUEST_SET_CONFIGURATION,
- 0x07, &freq_value, sizeof(freq_value));
- if (err)
- goto out;
- /* The frequency setting changed. The device firmware
- * will reboot the mouse now. This will cause a reconnect
- * on the USB bus. Call the guard... */
- err = razer_usb_reconnect_guard_wait(&guard, 0);
- if (err)
- goto out;
- /* The device needs a bit of punching in the face after reconnect. */
- for (i = 0; i < 5; i++) {
- int ver = deathadder_read_fw_ver(priv);
- if ((ver > 0) && ((ver & 0xFFFF) == priv->fw_version))
- break;
- razer_msleep(100);
- }
- if (i >= 5) {
- razer_error("razer-deathadder: The device didn't wake up "
- "after a frequency change. Try to replug it.\n");
- }
- }
- /* Commit LED states. */
- value = 0;
- if (priv->led_states[DEATHADDER_LED_LOGO])
- value |= 0x01;
- if (priv->led_states[DEATHADDER_LED_SCROLL])
- value |= 0x02;
- err = deathadder_usb_write(priv, LIBUSB_REQUEST_SET_CONFIGURATION,
- 0x06, &value, sizeof(value));
- if (err)
- goto out;
- /* Commit resolution setting. */
- err = deathadder_usb_write(priv, LIBUSB_REQUEST_SET_CONFIGURATION,
- 0x09, &res_value, sizeof(res_value));
- if (err)
- goto out;
- } else {
- struct deathadder_125_cfg config = { 0, };
- /* Translate frequency setting. */
- switch (priv->frequency) {
- case RAZER_MOUSE_FREQ_125HZ:
- config.freq = 3;
- break;
- case RAZER_MOUSE_FREQ_500HZ:
- config.freq = 2;
- break;
- case RAZER_MOUSE_FREQ_1000HZ:
- case RAZER_MOUSE_FREQ_UNKNOWN:
- config.freq = 1;
- break;
- default:
- err = -EINVAL;
- goto out;
- }
- /* Translate resolution setting. */
- if (priv->type == DEATHADDER_CLASSIC) {
- switch (priv->cur_dpimapping->res[RAZER_DIM_0]) {
- case RAZER_MOUSE_RES_450DPI:
- config.res = 3;
- break;
- case RAZER_MOUSE_RES_900DPI:
- config.res = 2;
- break;
- case RAZER_MOUSE_RES_1800DPI:
- case RAZER_MOUSE_RES_UNKNOWN:
- config.res = 1;
- break;
- default:
- err = -EINVAL;
- goto out;
- }
- } else {
- switch (priv->cur_dpimapping->res[RAZER_DIM_0]) {
- case RAZER_MOUSE_RES_450DPI:
- config.res = 4;
- break;
- case RAZER_MOUSE_RES_900DPI:
- config.res = 3;
- break;
- case RAZER_MOUSE_RES_1800DPI:
- config.res = 2;
- break;
- case RAZER_MOUSE_RES_3500DPI:
- case RAZER_MOUSE_RES_UNKNOWN:
- config.res = 1;
- break;
- default:
- err = -EINVAL;
- goto out;
- }
- }
- /* The profile ID. */
- config.profile = 1;
- /* Translate the LED states. */
- if (priv->type == DEATHADDER_BLACK) {
- /* There are no LEDs.
- * Bit 0 and 1 are always set, though. */
- config.leds = 0x03;
- } else {
- if (priv->led_states[DEATHADDER_LED_LOGO])
- config.leds |= 0x01;
- if (priv->led_states[DEATHADDER_LED_SCROLL])
- config.leds |= 0x02;
- }
- /* Commit the settings. */
- err = deathadder_usb_write(priv, LIBUSB_REQUEST_SET_CONFIGURATION,
- 0x10, &config, sizeof(config));
- if (err)
- goto out;
- if ((priv->type == DEATHADDER_CLASSIC ||
- priv->type == DEATHADDER_3500) &&
- priv->frequency != priv->old_frequency) {
- /* The frequency setting changed. The device firmware
- * will reboot the mouse now. This will cause a reconnect
- * on the USB bus. Call the guard... */
- err = razer_usb_reconnect_guard_wait(&guard, 0);
- if (err)
- goto out;
- /* The device has reconnected, so write the config
- * another time to ensure all settings are active.
- */
- err = deathadder_usb_write(priv, LIBUSB_REQUEST_SET_CONFIGURATION,
- 0x10, &config, sizeof(config));
- if (err)
- goto out;
- }
- if (priv->type == DEATHADDER_CLASSIC) {
- /* The device needs a bit of punching in the face.
- * Ensure it properly responds to read accesses. */
- for (i = 0; i < 5; i++) {
- int ver = deathadder_read_fw_ver(priv);
- if ((ver > 0) && ((ver & 0xFFFF) == priv->fw_version))
- break;
- razer_msleep(100);
- }
- if (i >= 5) {
- razer_error("razer-deathadder: The device didn't wake up "
- "after a config change. Try to replug it.\n");
- }
- }
- }
- priv->old_frequency = priv->frequency;
- err = 0;
- out:
- razer_event_spacing_leave(&priv->commit_spacing);
- return err;
- }
- static int deathadder_get_fw_version(struct razer_mouse *m)
- {
- struct deathadder_private *priv = m->drv_data;
- return priv->fw_version;
- }
- static int deathadder_commit(struct razer_mouse *m, int force)
- {
- struct deathadder_private *priv = m->drv_data;
- int err = 0;
- if (!m->claim_count)
- return -EBUSY;
- if (priv->commit_pending || force) {
- err = deathadder_do_commit(priv);
- if (!err)
- priv->commit_pending = 0;
- }
- return err;
- }
- static int deathadder_led_toggle(struct razer_led *led,
- enum razer_led_state new_state)
- {
- struct razer_mouse *m = led->u.mouse;
- struct deathadder_private *priv = m->drv_data;
- if (led->id >= DEATHADDER_NR_LEDS)
- return -EINVAL;
- if ((new_state != RAZER_LED_OFF) &&
- (new_state != RAZER_LED_ON))
- return -EINVAL;
- if (priv->type == DEATHADDER_BLACK)
- return -ENODEV;
- if (!m->claim_count)
- return -EBUSY;
- priv->led_states[led->id] = new_state;
- priv->commit_pending = 1;
- return 0;
- }
- static int deathadder_get_leds(struct razer_mouse *m,
- struct razer_led **leds_list)
- {
- struct deathadder_private *priv = m->drv_data;
- struct razer_led *scroll, *logo;
- if (priv->type == DEATHADDER_BLACK)
- return 0; /* No LEDs */
- scroll = zalloc(sizeof(struct razer_led));
- if (!scroll)
- return -ENOMEM;
- logo = zalloc(sizeof(struct razer_led));
- if (!logo) {
- free(scroll);
- return -ENOMEM;
- }
- scroll->name = "Scrollwheel";
- scroll->id = DEATHADDER_LED_SCROLL;
- scroll->state = priv->led_states[DEATHADDER_LED_SCROLL];
- scroll->toggle_state = deathadder_led_toggle;
- scroll->u.mouse = m;
- logo->name = "GlowingLogo";
- logo->id = DEATHADDER_LED_LOGO;
- logo->state = priv->led_states[DEATHADDER_LED_LOGO];
- logo->toggle_state = deathadder_led_toggle;
- logo->u.mouse = m;
- /* Link the list */
- *leds_list = scroll;
- scroll->next = logo;
- logo->next = NULL;
- return DEATHADDER_NR_LEDS;
- }
- static int deathadder_supported_freqs(struct razer_mouse *m,
- enum razer_mouse_freq **freq_list)
- {
- enum razer_mouse_freq *list;
- const int count = 3;
- list = zalloc(sizeof(*list) * count);
- if (!list)
- return -ENOMEM;
- list[0] = RAZER_MOUSE_FREQ_125HZ;
- list[1] = RAZER_MOUSE_FREQ_500HZ;
- list[2] = RAZER_MOUSE_FREQ_1000HZ;
- *freq_list = list;
- return count;
- }
- static enum razer_mouse_freq deathadder_get_freq(struct razer_mouse_profile *p)
- {
- struct deathadder_private *priv = p->mouse->drv_data;
- return priv->frequency;
- }
- static int deathadder_set_freq(struct razer_mouse_profile *p,
- enum razer_mouse_freq freq)
- {
- struct deathadder_private *priv = p->mouse->drv_data;
- if (!priv->m->claim_count)
- return -EBUSY;
- priv->frequency = freq;
- priv->commit_pending = 1;
- return 0;
- }
- static int deathadder_supported_resolutions(struct razer_mouse *m,
- enum razer_mouse_res **res_list)
- {
- struct deathadder_private *priv = m->drv_data;
- enum razer_mouse_res *list;
- const int count = (priv->type == DEATHADDER_CLASSIC) ? 3 : 4;
- list = zalloc(sizeof(*list) * count);
- if (!list)
- return -ENOMEM;
- list[0] = RAZER_MOUSE_RES_450DPI;
- list[1] = RAZER_MOUSE_RES_900DPI;
- list[2] = RAZER_MOUSE_RES_1800DPI;
- if (priv->type != DEATHADDER_CLASSIC)
- list[3] = RAZER_MOUSE_RES_3500DPI;
- *res_list = list;
- return count;
- }
- //TODO
- #if 0
- static struct usb_device * wait_for_usbdev(struct usb_device *dev,
- uint16_t vendor_id,
- uint16_t product_id)
- {
- struct usb_bus *bus, *buslist;
- unsigned int i;
- if (dev->descriptor.idVendor == vendor_id &&
- dev->descriptor.idProduct == product_id)
- return dev;
- for (i = 0; i < 100; i++) {
- usb_find_busses();
- usb_find_devices();
- buslist = usb_get_busses();
- for_each_usbbus(bus, buslist) {
- for_each_usbdev(dev, bus->devices) {
- if (dev->descriptor.idVendor == vendor_id &&
- dev->descriptor.idProduct == product_id)
- return dev;
- }
- }
- razer_msleep(100);
- }
- return NULL;
- }
- #endif
- static int deathadder_flash_firmware(struct razer_mouse *m,
- const char *data, size_t len,
- unsigned int magic_number)
- {
- struct deathadder_private *priv = m->drv_data;
- int err;
- char value;
- struct libusb_device *cydev;
- struct cypress cy;
- if (magic_number != RAZER_FW_FLASH_MAGIC)
- return -EINVAL;
- if (!m->claim_count)
- return -EBUSY;
- if (len != DEATHADDER_FW_IMAGE_SIZE) {
- razer_error("razer-deathadder: "
- "Firmware image has wrong size %u (expected %u).\n",
- (unsigned int)len,
- (unsigned int)DEATHADDER_FW_IMAGE_SIZE);
- return -EINVAL;
- }
- razer_msleep(50);
- if (priv->in_bootloader) {
- /* We're already inside of the bootloader */
- cydev = m->usb_ctx->dev;
- } else {
- /* Enter bootloader mode */
- value = 0;
- err = deathadder_usb_write(priv, LIBUSB_REQUEST_SET_CONFIGURATION,
- 0x08, &value, sizeof(value));
- if (err) {
- razer_error("razer-deathadder: Failed to enter the bootloader.\n");
- return err;
- }
- /* Wait for the cypress device to appear. */
- //TODO cydev = wait_for_usbdev(priv->usb.dev, CYPRESS_BOOT_VENDORID, CYPRESS_BOOT_PRODUCTID);
- cydev=NULL;
- if (!cydev) {
- razer_error("razer-deathadder: Cypress device didn't appear.\n");
- return -1;
- }
- }
- razer_msleep(100);
- err = cypress_open(&cy, cydev, NULL);
- if (err)
- return err;
- err = cypress_upload_image(&cy, data, len);
- cypress_close(&cy);
- if (err)
- return err;
- //FIXME need to reconnect the device?
- return 0;
- }
- static struct razer_mouse_profile * deathadder_get_profiles(struct razer_mouse *m)
- {
- struct deathadder_private *priv = m->drv_data;
- return &priv->profile;
- }
- static int deathadder_supported_dpimappings(struct razer_mouse *m,
- struct razer_mouse_dpimapping **res_ptr)
- {
- struct deathadder_private *priv = m->drv_data;
- *res_ptr = &priv->dpimapping[0];
- if (priv->type == DEATHADDER_CLASSIC)
- return ARRAY_SIZE(priv->dpimapping) - 1;
- return ARRAY_SIZE(priv->dpimapping);
- }
- static struct razer_mouse_dpimapping * deathadder_get_dpimapping(struct razer_mouse_profile *p,
- struct razer_axis *axis)
- {
- struct deathadder_private *priv = p->mouse->drv_data;
- return priv->cur_dpimapping;
- }
- static int deathadder_set_dpimapping(struct razer_mouse_profile *p,
- struct razer_axis *axis,
- struct razer_mouse_dpimapping *d)
- {
- struct deathadder_private *priv = p->mouse->drv_data;
- if (!priv->m->claim_count)
- return -EBUSY;
- priv->cur_dpimapping = d;
- priv->commit_pending = 1;
- return 0;
- }
- int razer_deathadder_init(struct razer_mouse *m,
- struct libusb_device *usbdev)
- {
- struct deathadder_private *priv;
- struct libusb_device_descriptor desc;
- unsigned int i;
- int err, fwver;
- const char *devname = "";
- err = libusb_get_device_descriptor(usbdev, &desc);
- if (err) {
- razer_error("hw_deathadder: Failed to get device descriptor\n");
- return -EIO;
- }
- priv = zalloc(sizeof(struct deathadder_private));
- if (!priv)
- return -ENOMEM;
- priv->m = m;
- m->drv_data = priv;
- priv->in_bootloader = is_cypress_bootloader(&desc);
- /* We need to wait some time between commits */
- razer_event_spacing_init(&priv->commit_spacing, 1000);
- err = razer_usb_add_used_interface(m->usb_ctx, 0, 0);
- if (err)
- goto err_free;
- if (!priv->in_bootloader && desc.idProduct == 0x0007) {
- err = razer_usb_force_hub_reset(m->usb_ctx);
- if (err) {
- razer_error("hw_deathadder: Failed to reinit USB device\n");
- goto err_free;
- }
- usbdev = m->usb_ctx->dev;
- }
- err = m->claim(m);
- if (err) {
- razer_error("hw_deathadder: Failed to claim device\n");
- goto err_free;
- }
- /* Fetch firmware version */
- fwver = deathadder_read_fw_ver(priv);
- if (fwver < 0) {
- razer_error("hw_deathadder: Failed to get firmware version\n");
- err = fwver;
- goto err_release;
- }
- priv->fw_version = fwver;
- /* Determine the hardware revision */
- priv->type = DEATHADDER_CLASSIC;
- if (desc.idVendor == 0x1532 && desc.idProduct == 0x0029) {
- priv->type = DEATHADDER_BLACK;
- } else {
- if (fwver >= DADD_FW(2,0))
- priv->type = DEATHADDER_3500;
- }
- priv->frequency = RAZER_MOUSE_FREQ_1000HZ;
- priv->old_frequency = priv->frequency;
- for (i = 0; i < DEATHADDER_NR_LEDS; i++)
- priv->led_states[i] = RAZER_LED_ON;
- priv->profile.nr = 0;
- priv->profile.get_freq = deathadder_get_freq;
- priv->profile.set_freq = deathadder_set_freq;
- priv->profile.get_dpimapping = deathadder_get_dpimapping;
- priv->profile.set_dpimapping = deathadder_set_dpimapping;
- priv->profile.mouse = m;
- priv->dpimapping[0].nr = 0;
- priv->dpimapping[0].res[RAZER_DIM_0] = RAZER_MOUSE_RES_450DPI;
- priv->dpimapping[0].dimension_mask = (1 << RAZER_DIM_0);
- priv->dpimapping[0].change = NULL;
- priv->dpimapping[0].mouse = m;
- priv->dpimapping[1].nr = 1;
- priv->dpimapping[1].res[RAZER_DIM_0] = RAZER_MOUSE_RES_900DPI;
- priv->dpimapping[1].dimension_mask = (1 << RAZER_DIM_0);
- priv->dpimapping[1].change = NULL;
- priv->dpimapping[1].mouse = m;
- priv->dpimapping[2].nr = 2;
- priv->dpimapping[2].res[RAZER_DIM_0] = RAZER_MOUSE_RES_1800DPI;
- priv->dpimapping[2].dimension_mask = (1 << RAZER_DIM_0);
- priv->dpimapping[2].change = NULL;
- priv->dpimapping[2].mouse = m;
- if (priv->type == DEATHADDER_CLASSIC) {
- priv->cur_dpimapping = &priv->dpimapping[2];
- } else {
- priv->dpimapping[3].nr = 3;
- priv->dpimapping[3].res[RAZER_DIM_0] = RAZER_MOUSE_RES_3500DPI;
- priv->dpimapping[3].dimension_mask = (1 << RAZER_DIM_0);
- priv->dpimapping[3].change = NULL;
- priv->dpimapping[3].mouse = m;
- priv->cur_dpimapping = &priv->dpimapping[3];
- }
- m->type = RAZER_MOUSETYPE_DEATHADDER;
- switch (priv->type) {
- case DEATHADDER_CLASSIC:
- devname = "DeathAdder Classic";
- break;
- case DEATHADDER_3500:
- devname = "DeathAdder 3500DPI";
- break;
- case DEATHADDER_BLACK:
- devname = "DeathAdder Black Edition";
- break;
- }
- razer_generic_usb_gen_idstr(usbdev, m->usb_ctx->h, devname, 0,
- NULL, m->idstr);
- m->get_fw_version = deathadder_get_fw_version;
- m->commit = deathadder_commit;
- m->flash_firmware = deathadder_flash_firmware;
- m->global_get_leds = deathadder_get_leds;
- m->get_profiles = deathadder_get_profiles;
- m->supported_resolutions = deathadder_supported_resolutions;
- m->supported_freqs = deathadder_supported_freqs;
- m->supported_dpimappings = deathadder_supported_dpimappings;
- err = deathadder_do_commit(priv);
- if (err) {
- razer_error("hw_deathadder: Failed to commit initial settings\n");
- goto err_release;
- }
- m->release(m);
- return 0;
- err_release:
- m->release(m);
- err_free:
- free(priv);
- return err;
- }
- void razer_deathadder_release(struct razer_mouse *m)
- {
- struct deathadder_private *priv = m->drv_data;
- free(priv);
- }
|