qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

adb-mouse.c (7657B)


      1 /*
      2  * QEMU ADB mouse support
      3  *
      4  * Copyright (c) 2004 Fabrice Bellard
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a copy
      7  * of this software and associated documentation files (the "Software"), to deal
      8  * in the Software without restriction, including without limitation the rights
      9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     10  * copies of the Software, and to permit persons to whom the Software is
     11  * furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included in
     14  * all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     22  * THE SOFTWARE.
     23  */
     24 
     25 #include "qemu/osdep.h"
     26 #include "ui/console.h"
     27 #include "hw/input/adb.h"
     28 #include "migration/vmstate.h"
     29 #include "qemu/module.h"
     30 #include "adb-internal.h"
     31 #include "trace.h"
     32 #include "qom/object.h"
     33 
     34 OBJECT_DECLARE_TYPE(MouseState, ADBMouseClass, ADB_MOUSE)
     35 
     36 struct MouseState {
     37     /*< public >*/
     38     ADBDevice parent_obj;
     39     /*< private >*/
     40 
     41     int buttons_state, last_buttons_state;
     42     int dx, dy, dz;
     43 };
     44 
     45 
     46 struct ADBMouseClass {
     47     /*< public >*/
     48     ADBDeviceClass parent_class;
     49     /*< private >*/
     50 
     51     DeviceRealize parent_realize;
     52 };
     53 
     54 static void adb_mouse_event(void *opaque,
     55                             int dx1, int dy1, int dz1, int buttons_state)
     56 {
     57     MouseState *s = opaque;
     58 
     59     s->dx += dx1;
     60     s->dy += dy1;
     61     s->dz += dz1;
     62     s->buttons_state = buttons_state;
     63 }
     64 
     65 
     66 static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf)
     67 {
     68     MouseState *s = ADB_MOUSE(d);
     69     int dx, dy;
     70 
     71     if (s->last_buttons_state == s->buttons_state &&
     72         s->dx == 0 && s->dy == 0) {
     73         return 0;
     74     }
     75 
     76     dx = s->dx;
     77     if (dx < -63) {
     78         dx = -63;
     79     } else if (dx > 63) {
     80         dx = 63;
     81     }
     82 
     83     dy = s->dy;
     84     if (dy < -63) {
     85         dy = -63;
     86     } else if (dy > 63) {
     87         dy = 63;
     88     }
     89 
     90     s->dx -= dx;
     91     s->dy -= dy;
     92     s->last_buttons_state = s->buttons_state;
     93 
     94     dx &= 0x7f;
     95     dy &= 0x7f;
     96 
     97     if (!(s->buttons_state & MOUSE_EVENT_LBUTTON)) {
     98         dy |= 0x80;
     99     }
    100     if (!(s->buttons_state & MOUSE_EVENT_RBUTTON)) {
    101         dx |= 0x80;
    102     }
    103 
    104     obuf[0] = dy;
    105     obuf[1] = dx;
    106     return 2;
    107 }
    108 
    109 static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
    110                              const uint8_t *buf, int len)
    111 {
    112     MouseState *s = ADB_MOUSE(d);
    113     int cmd, reg, olen;
    114 
    115     if ((buf[0] & 0x0f) == ADB_FLUSH) {
    116         /* flush mouse fifo */
    117         s->buttons_state = s->last_buttons_state;
    118         s->dx = 0;
    119         s->dy = 0;
    120         s->dz = 0;
    121         trace_adb_device_mouse_flush();
    122         return 0;
    123     }
    124 
    125     cmd = buf[0] & 0xc;
    126     reg = buf[0] & 0x3;
    127     olen = 0;
    128     switch (cmd) {
    129     case ADB_WRITEREG:
    130         trace_adb_device_mouse_writereg(reg, buf[1]);
    131         switch (reg) {
    132         case 2:
    133             break;
    134         case 3:
    135             /*
    136              * MacOS 9 has a bug in its ADB driver whereby after configuring
    137              * the ADB bus devices it sends another write of invalid length
    138              * to reg 3. Make sure we ignore it to prevent an address clash
    139              * with the previous device.
    140              */
    141             if (len != 3) {
    142                 return 0;
    143             }
    144 
    145             switch (buf[2]) {
    146             case ADB_CMD_SELF_TEST:
    147                 break;
    148             case ADB_CMD_CHANGE_ID:
    149             case ADB_CMD_CHANGE_ID_AND_ACT:
    150             case ADB_CMD_CHANGE_ID_AND_ENABLE:
    151                 d->devaddr = buf[1] & 0xf;
    152                 trace_adb_device_mouse_request_change_addr(d->devaddr);
    153                 break;
    154             default:
    155                 d->devaddr = buf[1] & 0xf;
    156                 /*
    157                  * we support handlers:
    158                  * 0x01: Classic Apple Mouse Protocol / 100 cpi operations
    159                  * 0x02: Classic Apple Mouse Protocol / 200 cpi operations
    160                  * we don't support handlers (at least):
    161                  * 0x03: Mouse systems A3 trackball
    162                  * 0x04: Extended Apple Mouse Protocol
    163                  * 0x2f: Microspeed mouse
    164                  * 0x42: Macally
    165                  * 0x5f: Microspeed mouse
    166                  * 0x66: Microspeed mouse
    167                  */
    168                 if (buf[2] == 1 || buf[2] == 2) {
    169                     d->handler = buf[2];
    170                 }
    171 
    172                 trace_adb_device_mouse_request_change_addr_and_handler(
    173                     d->devaddr, d->handler);
    174                 break;
    175             }
    176         }
    177         break;
    178     case ADB_READREG:
    179         switch (reg) {
    180         case 0:
    181             olen = adb_mouse_poll(d, obuf);
    182             break;
    183         case 1:
    184             break;
    185         case 3:
    186             obuf[0] = d->devaddr;
    187             obuf[1] = d->handler;
    188             olen = 2;
    189             break;
    190         }
    191         trace_adb_device_mouse_readreg(reg, obuf[0], obuf[1]);
    192         break;
    193     }
    194     return olen;
    195 }
    196 
    197 static bool adb_mouse_has_data(ADBDevice *d)
    198 {
    199     MouseState *s = ADB_MOUSE(d);
    200 
    201     return !(s->last_buttons_state == s->buttons_state &&
    202              s->dx == 0 && s->dy == 0);
    203 }
    204 
    205 static void adb_mouse_reset(DeviceState *dev)
    206 {
    207     ADBDevice *d = ADB_DEVICE(dev);
    208     MouseState *s = ADB_MOUSE(dev);
    209 
    210     d->handler = 2;
    211     d->devaddr = ADB_DEVID_MOUSE;
    212     s->last_buttons_state = s->buttons_state = 0;
    213     s->dx = s->dy = s->dz = 0;
    214 }
    215 
    216 static const VMStateDescription vmstate_adb_mouse = {
    217     .name = "adb_mouse",
    218     .version_id = 2,
    219     .minimum_version_id = 2,
    220     .fields = (VMStateField[]) {
    221         VMSTATE_STRUCT(parent_obj, MouseState, 0, vmstate_adb_device,
    222                        ADBDevice),
    223         VMSTATE_INT32(buttons_state, MouseState),
    224         VMSTATE_INT32(last_buttons_state, MouseState),
    225         VMSTATE_INT32(dx, MouseState),
    226         VMSTATE_INT32(dy, MouseState),
    227         VMSTATE_INT32(dz, MouseState),
    228         VMSTATE_END_OF_LIST()
    229     }
    230 };
    231 
    232 static void adb_mouse_realizefn(DeviceState *dev, Error **errp)
    233 {
    234     MouseState *s = ADB_MOUSE(dev);
    235     ADBMouseClass *amc = ADB_MOUSE_GET_CLASS(dev);
    236 
    237     amc->parent_realize(dev, errp);
    238 
    239     qemu_add_mouse_event_handler(adb_mouse_event, s, 0, "QEMU ADB Mouse");
    240 }
    241 
    242 static void adb_mouse_initfn(Object *obj)
    243 {
    244     ADBDevice *d = ADB_DEVICE(obj);
    245 
    246     d->devaddr = ADB_DEVID_MOUSE;
    247 }
    248 
    249 static void adb_mouse_class_init(ObjectClass *oc, void *data)
    250 {
    251     DeviceClass *dc = DEVICE_CLASS(oc);
    252     ADBDeviceClass *adc = ADB_DEVICE_CLASS(oc);
    253     ADBMouseClass *amc = ADB_MOUSE_CLASS(oc);
    254 
    255     device_class_set_parent_realize(dc, adb_mouse_realizefn,
    256                                     &amc->parent_realize);
    257     set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
    258 
    259     adc->devreq = adb_mouse_request;
    260     adc->devhasdata = adb_mouse_has_data;
    261     dc->reset = adb_mouse_reset;
    262     dc->vmsd = &vmstate_adb_mouse;
    263 }
    264 
    265 static const TypeInfo adb_mouse_type_info = {
    266     .name = TYPE_ADB_MOUSE,
    267     .parent = TYPE_ADB_DEVICE,
    268     .instance_size = sizeof(MouseState),
    269     .instance_init = adb_mouse_initfn,
    270     .class_init = adb_mouse_class_init,
    271     .class_size = sizeof(ADBMouseClass),
    272 };
    273 
    274 static void adb_mouse_register_types(void)
    275 {
    276     type_register_static(&adb_mouse_type_info);
    277 }
    278 
    279 type_init(adb_mouse_register_types)