linux/drivers/staging/asus_oled/asus_oled.c
<<
>>
Prefs
   1/*
   2 *  Asus OLED USB driver
   3 *
   4 *  Copyright (C) 2007,2008 Jakub Schmidtke (sjakub@gmail.com)
   5 *
   6 *  This program is free software; you can redistribute it and/or modify
   7 *  it under the terms of the GNU General Public License as published by
   8 *  the Free Software Foundation; either version 2 of the License, or
   9 *  (at your option) any later version.
  10 *
  11 *  This program is distributed in the hope that it will be useful,
  12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 *  GNU General Public License for more details.
  15 *
  16 *  You should have received a copy of the GNU General Public License
  17 *  along with this program; if not, write to the Free Software
  18 *  Foundation, Inc.,
  19 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  20 *
  21 *
  22 *
  23 *  This module is based on usbled and asus-laptop modules.
  24 *
  25 *
  26 *  Asus OLED support is based on asusoled program taken from
  27 *  <http://lapsus.berlios.de/asus_oled.html>.
  28 *
  29 *
  30 */
  31
  32#include <linux/kernel.h>
  33#include <linux/errno.h>
  34#include <linux/init.h>
  35#include <linux/slab.h>
  36#include <linux/module.h>
  37#include <linux/usb.h>
  38#include <linux/platform_device.h>
  39#include <linux/ctype.h>
  40
  41#define ASUS_OLED_VERSION               "0.04-dev"
  42#define ASUS_OLED_NAME                  "asus-oled"
  43#define ASUS_OLED_UNDERSCORE_NAME       "asus_oled"
  44
  45#define ASUS_OLED_STATIC                's'
  46#define ASUS_OLED_ROLL                  'r'
  47#define ASUS_OLED_FLASH                 'f'
  48
  49#define ASUS_OLED_MAX_WIDTH             1792
  50#define ASUS_OLED_DISP_HEIGHT           32
  51#define ASUS_OLED_PACKET_BUF_SIZE       256
  52
  53#define USB_VENDOR_ID_ASUS      0x0b05
  54#define USB_DEVICE_ID_ASUS_LCM      0x1726
  55#define USB_DEVICE_ID_ASUS_LCM2     0x175b
  56
  57MODULE_AUTHOR("Jakub Schmidtke, sjakub@gmail.com");
  58MODULE_DESCRIPTION("Asus OLED Driver");
  59MODULE_LICENSE("GPL");
  60MODULE_VERSION(ASUS_OLED_VERSION);
  61
  62static struct class *oled_class;
  63static int oled_num;
  64
  65static uint start_off;
  66
  67module_param(start_off, uint, 0644);
  68
  69MODULE_PARM_DESC(start_off,
  70                 "Set to 1 to switch off OLED display after it is attached");
  71
  72enum oled_pack_mode {
  73        PACK_MODE_G1,
  74        PACK_MODE_G50,
  75        PACK_MODE_LAST
  76};
  77
  78struct oled_dev_desc_str {
  79        uint16_t                idVendor;
  80        uint16_t                idProduct;
  81        /* width of display */
  82        uint16_t                devWidth;
  83        /* formula to be used while packing the picture */
  84        enum oled_pack_mode     packMode;
  85        const char              *devDesc;
  86};
  87
  88/* table of devices that work with this driver */
  89static const struct usb_device_id id_table[] = {
  90        /* Asus G1/G2 (and variants)*/
  91        { USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM) },
  92        /* Asus G50V (and possibly others - G70? G71?)*/
  93        { USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM2) },
  94        { },
  95};
  96
  97/* parameters of specific devices */
  98static struct oled_dev_desc_str oled_dev_desc_table[] = {
  99        { USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM, 128, PACK_MODE_G1,
 100                "G1/G2" },
 101        { USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM2, 256, PACK_MODE_G50,
 102                "G50" },
 103        { },
 104};
 105
 106MODULE_DEVICE_TABLE(usb, id_table);
 107
 108struct asus_oled_header {
 109        uint8_t         magic1;
 110        uint8_t         magic2;
 111        uint8_t         flags;
 112        uint8_t         value3;
 113        uint8_t         buffer1;
 114        uint8_t         buffer2;
 115        uint8_t         value6;
 116        uint8_t         value7;
 117        uint8_t         value8;
 118        uint8_t         padding2[7];
 119} __attribute((packed));
 120
 121struct asus_oled_packet {
 122        struct asus_oled_header         header;
 123        uint8_t                         bitmap[ASUS_OLED_PACKET_BUF_SIZE];
 124} __attribute((packed));
 125
 126struct asus_oled_dev {
 127        struct usb_device       *udev;
 128        uint8_t                 pic_mode;
 129        uint16_t                dev_width;
 130        enum oled_pack_mode     pack_mode;
 131        size_t                  height;
 132        size_t                  width;
 133        size_t                  x_shift;
 134        size_t                  y_shift;
 135        size_t                  buf_offs;
 136        uint8_t                 last_val;
 137        size_t                  buf_size;
 138        char                    *buf;
 139        uint8_t                 enabled;
 140        uint8_t                 enabled_post_resume;
 141        struct device           *dev;
 142};
 143
 144static void setup_packet_header(struct asus_oled_packet *packet, char flags,
 145                         char value3, char buffer1, char buffer2, char value6,
 146                         char value7, char value8)
 147{
 148        memset(packet, 0, sizeof(struct asus_oled_header));
 149        packet->header.magic1 = 0x55;
 150        packet->header.magic2 = 0xaa;
 151        packet->header.flags = flags;
 152        packet->header.value3 = value3;
 153        packet->header.buffer1 = buffer1;
 154        packet->header.buffer2 = buffer2;
 155        packet->header.value6 = value6;
 156        packet->header.value7 = value7;
 157        packet->header.value8 = value8;
 158}
 159
 160static void enable_oled(struct asus_oled_dev *odev, uint8_t enabl)
 161{
 162        int retval;
 163        int act_len;
 164        struct asus_oled_packet *packet;
 165
 166        packet = kzalloc(sizeof(struct asus_oled_packet), GFP_KERNEL);
 167        if (!packet)
 168                return;
 169
 170        setup_packet_header(packet, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00);
 171
 172        if (enabl)
 173                packet->bitmap[0] = 0xaf;
 174        else
 175                packet->bitmap[0] = 0xae;
 176
 177        retval = usb_bulk_msg(odev->udev,
 178                usb_sndbulkpipe(odev->udev, 2),
 179                packet,
 180                sizeof(struct asus_oled_header) + 1,
 181                &act_len,
 182                -1);
 183
 184        if (retval)
 185                dev_dbg(&odev->udev->dev, "retval = %d\n", retval);
 186
 187        odev->enabled = enabl;
 188
 189        kfree(packet);
 190}
 191
 192static ssize_t set_enabled(struct device *dev, struct device_attribute *attr,
 193                           const char *buf, size_t count)
 194{
 195        struct usb_interface *intf = to_usb_interface(dev);
 196        struct asus_oled_dev *odev = usb_get_intfdata(intf);
 197        unsigned long value;
 198        if (kstrtoul(buf, 10, &value))
 199                return -EINVAL;
 200
 201        enable_oled(odev, value);
 202
 203        return count;
 204}
 205
 206static ssize_t class_set_enabled(struct device *device,
 207                                 struct device_attribute *attr,
 208                                 const char *buf, size_t count)
 209{
 210        struct asus_oled_dev *odev =
 211                (struct asus_oled_dev *) dev_get_drvdata(device);
 212        unsigned long value;
 213
 214        if (kstrtoul(buf, 10, &value))
 215                return -EINVAL;
 216
 217        enable_oled(odev, value);
 218
 219        return count;
 220}
 221
 222static ssize_t get_enabled(struct device *dev, struct device_attribute *attr,
 223                           char *buf)
 224{
 225        struct usb_interface *intf = to_usb_interface(dev);
 226        struct asus_oled_dev *odev = usb_get_intfdata(intf);
 227
 228        return sprintf(buf, "%d\n", odev->enabled);
 229}
 230
 231static ssize_t class_get_enabled(struct device *device,
 232                                 struct device_attribute *attr, char *buf)
 233{
 234        struct asus_oled_dev *odev =
 235                (struct asus_oled_dev *) dev_get_drvdata(device);
 236
 237        return sprintf(buf, "%d\n", odev->enabled);
 238}
 239
 240static void send_packets(struct usb_device *udev,
 241                         struct asus_oled_packet *packet,
 242                         char *buf, uint8_t p_type, size_t p_num)
 243{
 244        size_t i;
 245        int act_len;
 246
 247        for (i = 0; i < p_num; i++) {
 248                int retval;
 249
 250                switch (p_type) {
 251                case ASUS_OLED_ROLL:
 252                        setup_packet_header(packet, 0x40, 0x80, p_num,
 253                                            i + 1, 0x00, 0x01, 0xff);
 254                        break;
 255                case ASUS_OLED_STATIC:
 256                        setup_packet_header(packet, 0x10 + i, 0x80, 0x01,
 257                                            0x01, 0x00, 0x01, 0x00);
 258                        break;
 259                case ASUS_OLED_FLASH:
 260                        setup_packet_header(packet, 0x10 + i, 0x80, 0x01,
 261                                            0x01, 0x00, 0x00, 0xff);
 262                        break;
 263                }
 264
 265                memcpy(packet->bitmap, buf + (ASUS_OLED_PACKET_BUF_SIZE*i),
 266                       ASUS_OLED_PACKET_BUF_SIZE);
 267
 268                retval = usb_bulk_msg(udev, usb_sndctrlpipe(udev, 2),
 269                                      packet, sizeof(struct asus_oled_packet),
 270                                      &act_len, -1);
 271
 272                if (retval)
 273                        dev_dbg(&udev->dev, "retval = %d\n", retval);
 274        }
 275}
 276
 277static void send_packet(struct usb_device *udev,
 278                        struct asus_oled_packet *packet,
 279                        size_t offset, size_t len, char *buf, uint8_t b1,
 280                        uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5,
 281                        uint8_t b6) {
 282        int retval;
 283        int act_len;
 284
 285        setup_packet_header(packet, b1, b2, b3, b4, b5, b6, 0x00);
 286        memcpy(packet->bitmap, buf + offset, len);
 287
 288        retval = usb_bulk_msg(udev,
 289                              usb_sndctrlpipe(udev, 2),
 290                              packet,
 291                              sizeof(struct asus_oled_packet),
 292                              &act_len,
 293                              -1);
 294
 295        if (retval)
 296                dev_dbg(&udev->dev, "retval = %d\n", retval);
 297}
 298
 299
 300static void send_packets_g50(struct usb_device *udev,
 301                             struct asus_oled_packet *packet, char *buf)
 302{
 303        send_packet(udev, packet,     0, 0x100, buf,
 304                    0x10, 0x00, 0x02, 0x01, 0x00, 0x01);
 305        send_packet(udev, packet, 0x100, 0x080, buf,
 306                    0x10, 0x00, 0x02, 0x02, 0x80, 0x00);
 307
 308        send_packet(udev, packet, 0x180, 0x100, buf,
 309                    0x11, 0x00, 0x03, 0x01, 0x00, 0x01);
 310        send_packet(udev, packet, 0x280, 0x100, buf,
 311                    0x11, 0x00, 0x03, 0x02, 0x00, 0x01);
 312        send_packet(udev, packet, 0x380, 0x080, buf,
 313                    0x11, 0x00, 0x03, 0x03, 0x80, 0x00);
 314}
 315
 316
 317static void send_data(struct asus_oled_dev *odev)
 318{
 319        size_t packet_num = odev->buf_size / ASUS_OLED_PACKET_BUF_SIZE;
 320        struct asus_oled_packet *packet;
 321
 322        packet = kzalloc(sizeof(struct asus_oled_packet), GFP_KERNEL);
 323        if (!packet)
 324                return;
 325
 326        if (odev->pack_mode == PACK_MODE_G1) {
 327                /* When sending roll-mode data the display updated only
 328                   first packet.  I have no idea why, but when static picture
 329                   is sent just before rolling picture everything works fine. */
 330                if (odev->pic_mode == ASUS_OLED_ROLL)
 331                        send_packets(odev->udev, packet, odev->buf,
 332                                     ASUS_OLED_STATIC, 2);
 333
 334                /* Only ROLL mode can use more than 2 packets.*/
 335                if (odev->pic_mode != ASUS_OLED_ROLL && packet_num > 2)
 336                        packet_num = 2;
 337
 338                send_packets(odev->udev, packet, odev->buf,
 339                             odev->pic_mode, packet_num);
 340        } else if (odev->pack_mode == PACK_MODE_G50) {
 341                send_packets_g50(odev->udev, packet, odev->buf);
 342        }
 343
 344        kfree(packet);
 345}
 346
 347static int append_values(struct asus_oled_dev *odev, uint8_t val, size_t count)
 348{
 349        odev->last_val = val;
 350
 351        if (val == 0) {
 352                odev->buf_offs += count;
 353                return 0;
 354        }
 355
 356        while (count-- > 0) {
 357                size_t x = odev->buf_offs % odev->width;
 358                size_t y = odev->buf_offs / odev->width;
 359                size_t i;
 360
 361                x += odev->x_shift;
 362                y += odev->y_shift;
 363
 364                switch (odev->pack_mode) {
 365                case PACK_MODE_G1:
 366                        /* i = (x/128)*640 + 127 - x + (y/8)*128;
 367                           This one for 128 is the same, but might be better
 368                           for different widths? */
 369                        i = (x/odev->dev_width)*640 +
 370                                odev->dev_width - 1 - x +
 371                                (y/8)*odev->dev_width;
 372                        break;
 373
 374                case PACK_MODE_G50:
 375                        i =  (odev->dev_width - 1 - x)/8 + y*odev->dev_width/8;
 376                        break;
 377
 378                default:
 379                        i = 0;
 380                        dev_err(odev->dev, "Unknown OLED Pack Mode: %d!\n",
 381                               odev->pack_mode);
 382                        break;
 383                }
 384
 385                if (i >= odev->buf_size) {
 386                        dev_err(odev->dev, "Buffer overflow! Report a bug:"
 387                               "offs: %d >= %d i: %d (x: %d y: %d)\n",
 388                               (int) odev->buf_offs, (int) odev->buf_size,
 389                               (int) i, (int) x, (int) y);
 390                        return -EIO;
 391                }
 392
 393                switch (odev->pack_mode) {
 394                case PACK_MODE_G1:
 395                        odev->buf[i] &= ~(1<<(y%8));
 396                        break;
 397
 398                case PACK_MODE_G50:
 399                        odev->buf[i] &= ~(1<<(x%8));
 400                        break;
 401
 402                default:
 403                        /* cannot get here; stops gcc complaining*/
 404                        ;
 405                }
 406
 407                odev->buf_offs++;
 408        }
 409
 410        return 0;
 411}
 412
 413static ssize_t odev_set_picture(struct asus_oled_dev *odev,
 414                                const char *buf, size_t count)
 415{
 416        size_t offs = 0, max_offs;
 417
 418        if (count < 1)
 419                return 0;
 420
 421        if (tolower(buf[0]) == 'b') {
 422                /* binary mode, set the entire memory*/
 423
 424                size_t i;
 425
 426                odev->buf_size = (odev->dev_width * ASUS_OLED_DISP_HEIGHT) / 8;
 427
 428                kfree(odev->buf);
 429                odev->buf = kmalloc(odev->buf_size, GFP_KERNEL);
 430                if (odev->buf == NULL) {
 431                        odev->buf_size = 0;
 432                        dev_err(odev->dev, "Out of memory!\n");
 433                        return -ENOMEM;
 434                }
 435
 436                memset(odev->buf, 0xff, odev->buf_size);
 437
 438                for (i = 1; i < count && i <= 32 * 32; i++) {
 439                        odev->buf[i-1] = buf[i];
 440                        odev->buf_offs = i-1;
 441                }
 442
 443                odev->width = odev->dev_width / 8;
 444                odev->height = ASUS_OLED_DISP_HEIGHT;
 445                odev->x_shift = 0;
 446                odev->y_shift = 0;
 447                odev->last_val =  0;
 448
 449                send_data(odev);
 450
 451                return count;
 452        }
 453
 454        if (buf[0] == '<') {
 455                size_t i;
 456                size_t w = 0, h = 0;
 457                size_t w_mem, h_mem;
 458
 459                if (count < 10 || buf[2] != ':')
 460                        goto error_header;
 461
 462
 463                switch (tolower(buf[1])) {
 464                case ASUS_OLED_STATIC:
 465                case ASUS_OLED_ROLL:
 466                case ASUS_OLED_FLASH:
 467                        odev->pic_mode = buf[1];
 468                        break;
 469                default:
 470                        dev_err(odev->dev, "Wrong picture mode: '%c'.\n",
 471                               buf[1]);
 472                        return -EIO;
 473                        break;
 474                }
 475
 476                for (i = 3; i < count; ++i) {
 477                        if (buf[i] >= '0' && buf[i] <= '9') {
 478                                w = 10*w + (buf[i] - '0');
 479
 480                                if (w > ASUS_OLED_MAX_WIDTH)
 481                                        goto error_width;
 482                        } else if (tolower(buf[i]) == 'x') {
 483                                break;
 484                        } else {
 485                                goto error_width;
 486                        }
 487                }
 488
 489                for (++i; i < count; ++i) {
 490                        if (buf[i] >= '0' && buf[i] <= '9') {
 491                                h = 10*h + (buf[i] - '0');
 492
 493                                if (h > ASUS_OLED_DISP_HEIGHT)
 494                                        goto error_height;
 495                        } else if (tolower(buf[i]) == '>') {
 496                                break;
 497                        } else {
 498                                goto error_height;
 499                        }
 500                }
 501
 502                if (w < 1 || w > ASUS_OLED_MAX_WIDTH)
 503                        goto error_width;
 504
 505                if (h < 1 || h > ASUS_OLED_DISP_HEIGHT)
 506                        goto error_height;
 507
 508                if (i >= count || buf[i] != '>')
 509                        goto error_header;
 510
 511                offs = i+1;
 512
 513                if (w % (odev->dev_width) != 0)
 514                        w_mem = (w/(odev->dev_width) + 1)*(odev->dev_width);
 515                else
 516                        w_mem = w;
 517
 518                if (h < ASUS_OLED_DISP_HEIGHT)
 519                        h_mem = ASUS_OLED_DISP_HEIGHT;
 520                else
 521                        h_mem = h;
 522
 523                odev->buf_size = w_mem * h_mem / 8;
 524
 525                kfree(odev->buf);
 526                odev->buf = kmalloc(odev->buf_size, GFP_KERNEL);
 527
 528                if (odev->buf == NULL) {
 529                        odev->buf_size = 0;
 530                        dev_err(odev->dev, "Out of memory!\n");
 531                        return -ENOMEM;
 532                }
 533
 534                memset(odev->buf, 0xff, odev->buf_size);
 535
 536                odev->buf_offs = 0;
 537                odev->width = w;
 538                odev->height = h;
 539                odev->x_shift = 0;
 540                odev->y_shift = 0;
 541                odev->last_val = 0;
 542
 543                if (odev->pic_mode == ASUS_OLED_FLASH) {
 544                        if (h < ASUS_OLED_DISP_HEIGHT/2)
 545                                odev->y_shift = (ASUS_OLED_DISP_HEIGHT/2 - h)/2;
 546                } else {
 547                        if (h < ASUS_OLED_DISP_HEIGHT)
 548                                odev->y_shift = (ASUS_OLED_DISP_HEIGHT - h)/2;
 549                }
 550
 551                if (w < (odev->dev_width))
 552                        odev->x_shift = ((odev->dev_width) - w)/2;
 553        }
 554
 555        max_offs = odev->width * odev->height;
 556
 557        while (offs < count && odev->buf_offs < max_offs) {
 558                int ret = 0;
 559
 560                if (buf[offs] == '1' || buf[offs] == '#') {
 561                        ret = append_values(odev, 1, 1);
 562                        if (ret < 0)
 563                                return ret;
 564                } else if (buf[offs] == '0' || buf[offs] == ' ') {
 565                        ret = append_values(odev, 0, 1);
 566                        if (ret < 0)
 567                                return ret;
 568                } else if (buf[offs] == '\n') {
 569                        /* New line detected. Lets assume, that all characters
 570                           till the end of the line were equal to the last
 571                           character in this line.*/
 572                        if (odev->buf_offs % odev->width != 0)
 573                                ret = append_values(odev, odev->last_val,
 574                                                    odev->width -
 575                                                    (odev->buf_offs %
 576                                                     odev->width));
 577                        if (ret < 0)
 578                                return ret;
 579                }
 580
 581                offs++;
 582        }
 583
 584        if (odev->buf_offs >= max_offs)
 585                send_data(odev);
 586
 587        return count;
 588
 589error_width:
 590        dev_err(odev->dev, "Wrong picture width specified.\n");
 591        return -EIO;
 592
 593error_height:
 594        dev_err(odev->dev, "Wrong picture height specified.\n");
 595        return -EIO;
 596
 597error_header:
 598        dev_err(odev->dev, "Wrong picture header.\n");
 599        return -EIO;
 600}
 601
 602static ssize_t set_picture(struct device *dev, struct device_attribute *attr,
 603                           const char *buf, size_t count)
 604{
 605        struct usb_interface *intf = to_usb_interface(dev);
 606
 607        return odev_set_picture(usb_get_intfdata(intf), buf, count);
 608}
 609
 610static ssize_t class_set_picture(struct device *device,
 611                                 struct device_attribute *attr,
 612                                 const char *buf, size_t count)
 613{
 614        return odev_set_picture((struct asus_oled_dev *)
 615                                dev_get_drvdata(device), buf, count);
 616}
 617
 618#define ASUS_OLED_DEVICE_ATTR(_file)            dev_attr_asus_oled_##_file
 619
 620static DEVICE_ATTR(asus_oled_enabled, S_IWUSR | S_IRUGO,
 621                   get_enabled, set_enabled);
 622static DEVICE_ATTR(asus_oled_picture, S_IWUSR , NULL, set_picture);
 623
 624static DEVICE_ATTR(enabled, S_IWUSR | S_IRUGO,
 625                   class_get_enabled, class_set_enabled);
 626static DEVICE_ATTR(picture, S_IWUSR, NULL, class_set_picture);
 627
 628static int asus_oled_probe(struct usb_interface *interface,
 629                           const struct usb_device_id *id)
 630{
 631        struct usb_device *udev = interface_to_usbdev(interface);
 632        struct asus_oled_dev *odev = NULL;
 633        int retval = -ENOMEM;
 634        uint16_t dev_width = 0;
 635        enum oled_pack_mode pack_mode = PACK_MODE_LAST;
 636        const struct oled_dev_desc_str *dev_desc = oled_dev_desc_table;
 637        const char *desc = NULL;
 638
 639        if (!id) {
 640                /* Even possible? Just to make sure...*/
 641                dev_err(&interface->dev, "No usb_device_id provided!\n");
 642                return -ENODEV;
 643        }
 644
 645        for (; dev_desc->idVendor; dev_desc++) {
 646                if (dev_desc->idVendor == id->idVendor
 647                    && dev_desc->idProduct == id->idProduct) {
 648                        dev_width = dev_desc->devWidth;
 649                        desc = dev_desc->devDesc;
 650                        pack_mode = dev_desc->packMode;
 651                        break;
 652                }
 653        }
 654
 655        if (!desc || dev_width < 1 || pack_mode == PACK_MODE_LAST) {
 656                dev_err(&interface->dev,
 657                        "Missing or incomplete device description!\n");
 658                return -ENODEV;
 659        }
 660
 661        odev = kzalloc(sizeof(struct asus_oled_dev), GFP_KERNEL);
 662        if (odev == NULL)
 663                return -ENOMEM;
 664
 665        odev->udev = usb_get_dev(udev);
 666        odev->pic_mode = ASUS_OLED_STATIC;
 667        odev->dev_width = dev_width;
 668        odev->pack_mode = pack_mode;
 669        odev->height = 0;
 670        odev->width = 0;
 671        odev->x_shift = 0;
 672        odev->y_shift = 0;
 673        odev->buf_offs = 0;
 674        odev->buf_size = 0;
 675        odev->last_val = 0;
 676        odev->buf = NULL;
 677        odev->enabled = 1;
 678        odev->dev = NULL;
 679
 680        usb_set_intfdata(interface, odev);
 681
 682        retval = device_create_file(&interface->dev,
 683                                    &ASUS_OLED_DEVICE_ATTR(enabled));
 684        if (retval)
 685                goto err_files;
 686
 687        retval = device_create_file(&interface->dev,
 688                                    &ASUS_OLED_DEVICE_ATTR(picture));
 689        if (retval)
 690                goto err_files;
 691
 692        odev->dev = device_create(oled_class, &interface->dev, MKDEV(0, 0),
 693                                  NULL, "oled_%d", ++oled_num);
 694
 695        if (IS_ERR(odev->dev)) {
 696                retval = PTR_ERR(odev->dev);
 697                goto err_files;
 698        }
 699
 700        dev_set_drvdata(odev->dev, odev);
 701
 702        retval = device_create_file(odev->dev, &dev_attr_enabled);
 703        if (retval)
 704                goto err_class_enabled;
 705
 706        retval = device_create_file(odev->dev, &dev_attr_picture);
 707        if (retval)
 708                goto err_class_picture;
 709
 710        dev_info(&interface->dev,
 711                 "Attached Asus OLED device: %s [width %u, pack_mode %d]\n",
 712                 desc, odev->dev_width, odev->pack_mode);
 713
 714        if (start_off)
 715                enable_oled(odev, 0);
 716
 717        return 0;
 718
 719err_class_picture:
 720        device_remove_file(odev->dev, &dev_attr_picture);
 721
 722err_class_enabled:
 723        device_remove_file(odev->dev, &dev_attr_enabled);
 724        device_unregister(odev->dev);
 725
 726err_files:
 727        device_remove_file(&interface->dev, &ASUS_OLED_DEVICE_ATTR(enabled));
 728        device_remove_file(&interface->dev, &ASUS_OLED_DEVICE_ATTR(picture));
 729
 730        usb_set_intfdata(interface, NULL);
 731        usb_put_dev(odev->udev);
 732        kfree(odev);
 733
 734        return retval;
 735}
 736
 737static void asus_oled_disconnect(struct usb_interface *interface)
 738{
 739        struct asus_oled_dev *odev;
 740
 741        odev = usb_get_intfdata(interface);
 742        usb_set_intfdata(interface, NULL);
 743
 744        device_remove_file(odev->dev, &dev_attr_picture);
 745        device_remove_file(odev->dev, &dev_attr_enabled);
 746        device_unregister(odev->dev);
 747
 748        device_remove_file(&interface->dev, &ASUS_OLED_DEVICE_ATTR(picture));
 749        device_remove_file(&interface->dev, &ASUS_OLED_DEVICE_ATTR(enabled));
 750
 751        usb_put_dev(odev->udev);
 752
 753        kfree(odev->buf);
 754
 755        kfree(odev);
 756
 757        dev_info(&interface->dev, "Disconnected Asus OLED device\n");
 758}
 759
 760#ifdef CONFIG_PM
 761static int asus_oled_suspend(struct usb_interface *intf, pm_message_t message)
 762{
 763        struct asus_oled_dev *odev;
 764
 765        odev = usb_get_intfdata(intf);
 766        if (!odev)
 767                return -ENODEV;
 768
 769        odev->enabled_post_resume = odev->enabled;
 770        enable_oled(odev, 0);
 771
 772        return 0;
 773}
 774
 775static int asus_oled_resume(struct usb_interface *intf)
 776{
 777        struct asus_oled_dev *odev;
 778
 779        odev = usb_get_intfdata(intf);
 780        if (!odev)
 781                return -ENODEV;
 782
 783        enable_oled(odev, odev->enabled_post_resume);
 784
 785        return 0;
 786}
 787#else
 788#define asus_oled_suspend NULL
 789#define asus_oled_resume NULL
 790#endif
 791
 792static struct usb_driver oled_driver = {
 793        .name =         ASUS_OLED_NAME,
 794        .probe =        asus_oled_probe,
 795        .disconnect =   asus_oled_disconnect,
 796        .id_table =     id_table,
 797        .suspend =      asus_oled_suspend,
 798        .resume =       asus_oled_resume,
 799};
 800
 801static CLASS_ATTR_STRING(version, S_IRUGO,
 802                        ASUS_OLED_UNDERSCORE_NAME " " ASUS_OLED_VERSION);
 803
 804static int __init asus_oled_init(void)
 805{
 806        int retval = 0;
 807        oled_class = class_create(THIS_MODULE, ASUS_OLED_UNDERSCORE_NAME);
 808
 809        if (IS_ERR(oled_class)) {
 810                pr_err("Error creating " ASUS_OLED_UNDERSCORE_NAME " class\n");
 811                return PTR_ERR(oled_class);
 812        }
 813
 814        retval = class_create_file(oled_class, &class_attr_version.attr);
 815        if (retval) {
 816                pr_err("Error creating class version file\n");
 817                goto error;
 818        }
 819
 820        retval = usb_register(&oled_driver);
 821
 822        if (retval) {
 823                pr_err("usb_register failed. Error number %d\n", retval);
 824                goto error;
 825        }
 826
 827        return retval;
 828
 829error:
 830        class_destroy(oled_class);
 831        return retval;
 832}
 833
 834static void __exit asus_oled_exit(void)
 835{
 836        usb_deregister(&oled_driver);
 837        class_remove_file(oled_class, &class_attr_version.attr);
 838        class_destroy(oled_class);
 839}
 840
 841module_init(asus_oled_init);
 842module_exit(asus_oled_exit);
 843
 844