1/* 2 * Copyright 2017, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the BSD 2-Clause license. Note that NO WARRANTY is provided. 8 * See "LICENSE_BSD2.txt" for details. 9 * 10 * @TAG(DATA61_BSD) 11 */ 12 13/** 14 * @brief USB HID Mouse driver 15 * @see USB HID spec Appendix B 16 */ 17#include <string.h> 18#include <stdlib.h> 19#include <stdio.h> 20 21#include <usb/drivers/mouse.h> 22#include "../services.h" 23#include "hid.h" 24 25struct usb_mouse_device { 26 struct usb_dev *udev; 27 struct usb_hid_device *hid; 28 struct endpoint *ep_int; 29 struct xact int_xact; 30 struct mouse_event event; 31}; 32 33static ssize_t mouse_read(ps_chardevice_t* d, void* vdata, size_t bytes, 34 chardev_callback_t cb, void* token) 35{ 36 int size; 37 struct usb_mouse_device *mouse; 38 mouse = (struct usb_mouse_device*)d->vaddr; 39 40 size = sizeof(struct mouse_event); 41 if (size > bytes) { 42 return 0; 43 } 44 45 memcpy((uint8_t*)vdata, &mouse->event, size); 46 47 return size; 48} 49 50static int mouse_irq_handler(void* token, enum usb_xact_status stat, int bytes_remaining) 51{ 52 struct usb_mouse_device *mouse; 53 uint8_t *data; 54 55 mouse = (struct usb_mouse_device*)token; 56 data = xact_get_vaddr(&mouse->int_xact); 57 58 if (stat != XACTSTAT_SUCCESS) { 59 ZF_LOGD("Received unsuccessful IRQ\n"); 60 } 61 62 mouse->event.button = data[0]; 63 mouse->event.x = data[1]; 64 mouse->event.y = data[2]; 65 66 usbdev_schedule_xact(mouse->udev, mouse->ep_int, &mouse->int_xact, 1, 67 &mouse_irq_handler, mouse); 68 69 return 0; 70} 71 72int usb_mouse_driver_bind(struct usb_dev *usb_dev, struct ps_chardevice *cdev) 73{ 74 struct usb_mouse_device *mouse; 75 int err; 76 77 mouse = (struct usb_mouse_device*)usb_malloc(sizeof(struct usb_mouse_device)); 78 if (!mouse) { 79 ZF_LOGF("Out of memory\n"); 80 } 81 82 usb_dev->dev_data = (struct udev_priv*)mouse; 83 mouse->udev = usb_dev; 84 85 mouse->hid = usb_hid_alloc(usb_dev); 86 87 if (mouse->hid->protocol != 2) { 88 ZF_LOGF("Not a mouse: %d\n", mouse->hid->protocol); 89 } 90 91 cdev->vaddr = mouse; 92 cdev->read = mouse_read; 93 94 /* Find endpoint */ 95 mouse->ep_int = usb_dev->ep[mouse->hid->iface]; 96 if (mouse->ep_int == NULL || mouse->ep_int->type != EP_INTERRUPT) { 97 ZF_LOGF("Endpoint not found\n"); 98 } 99 100 ZF_LOGD("Configuring mouse\n"); 101 102 err = usb_hid_set_idle(mouse->hid, 0); 103 if (err < 0) { 104 ZF_LOGF("Mouse initialisation error\n"); 105 } 106 107 /* Initialise IRQs */ 108 if (mouse->ep_int->dir == EP_DIR_IN) { 109 mouse->int_xact.type = PID_IN; 110 } else { 111 mouse->int_xact.type = PID_OUT; 112 } 113 114 mouse->int_xact.len = mouse->ep_int->max_pkt; 115 116 err = usb_alloc_xact(usb_dev->dman, &mouse->int_xact, 1); 117 if (err) { 118 ZF_LOGF("Out of DMA memory\n"); 119 } 120 121 usbdev_schedule_xact(usb_dev, mouse->ep_int, &mouse->int_xact, 1, 122 &mouse_irq_handler, mouse); 123 124 ZF_LOGD("Successfully initialised\n"); 125 126 return 0; 127} 128 129