BeRTOS
|
00001 00041 #include "usb_hid.h" 00042 #include "usbmouse.h" 00043 00044 #include "cfg/cfg_usbmouse.h" 00045 00046 #define LOG_LEVEL USB_MOUSE_LOG_LEVEL 00047 #define LOG_FORMAT USB_MOUSE_LOG_FORMAT 00048 00049 #include <cfg/log.h> 00050 #include <cfg/debug.h> 00051 #include <cfg/macros.h> 00052 #include <cfg/compiler.h> 00053 #include <cfg/module.h> 00054 00055 #include <cpu/power.h> // cpu_relax() 00056 00057 #include <drv/usb.h> 00058 #include <drv/usb_endpoint.h> 00059 00060 00061 /* 00062 * HID device configuration (usb-mouse) 00063 */ 00064 #define USB_HID_VENDOR_ID USB_MOUSE_VENDOR_ID 00065 #define USB_HID_PRODUCT_ID USB_MOUSE_PRODUCT_ID 00066 00067 #define USB_HID_INTERFACES 1 00068 #define USB_HID_ENDPOINTS 1 00069 00070 #define USB_STRING_MANUFACTURER 1 00071 #define USB_STRING_PRODUCT 2 00072 00073 #define USB_HID_REPORT_EP (USB_DIR_IN | USB_MOUSE_EP_REPORT) 00074 00075 static UsbDeviceDesc usb_hid_device_descriptor = 00076 { 00077 .bLength = sizeof(usb_hid_device_descriptor), 00078 .bDescriptorType = USB_DT_DEVICE, 00079 .bcdUSB = 0x100, 00080 .bDeviceClass = 0, 00081 .bDeviceSubClass = 0, 00082 .bDeviceProtocol = 0, 00083 .idVendor = USB_HID_VENDOR_ID, 00084 .idProduct = USB_HID_PRODUCT_ID, 00085 .bcdDevice = 0, 00086 .iManufacturer = USB_STRING_MANUFACTURER, 00087 .iProduct = USB_STRING_PRODUCT, 00088 .iSerialNumber = 0, 00089 .bNumConfigurations = 1, 00090 }; 00091 00092 static const UsbConfigDesc usb_hid_config_descriptor = 00093 { 00094 .bLength = sizeof(usb_hid_config_descriptor), 00095 .bDescriptorType = USB_DT_CONFIG, 00096 .bNumInterfaces = USB_HID_INTERFACES, 00097 .bConfigurationValue = 1, 00098 .iConfiguration = 0, 00099 .bmAttributes = USB_CONFIG_ATT_ONE, 00100 .bMaxPower = 50, /* 100 mA */ 00101 }; 00102 00103 static const UsbInterfaceDesc usb_hid_interface_descriptor = 00104 { 00105 .bLength = sizeof(usb_hid_interface_descriptor), 00106 .bDescriptorType = USB_DT_INTERFACE, 00107 .bInterfaceNumber = 0, 00108 .bAlternateSetting = 0, 00109 .bNumEndpoints = USB_HID_ENDPOINTS, 00110 .bInterfaceClass = USB_CLASS_HID, 00111 .bInterfaceSubClass = USB_INTERFACE_SUBCLASS_BOOT, 00112 .bInterfaceProtocol = USB_INTERFACE_PROTOCOL_MOUSE, 00113 .iInterface = 0, 00114 }; 00115 00116 static const uint8_t hid_report_descriptor[] = 00117 { 00118 0x05, 0x01, // Usage Page (Generic Desktop) 00119 0x09, 0x02, // Usage (Mouse) 00120 0xA1, 0x01, // Collection (Application) 00121 0x09, 0x01, // Usage (Pointer) 00122 0xA1, 0x00, // Collection (Physical) 00123 0x05, 0x09, // Usage Page (Buttons) 00124 0x19, 0x01, // Usage Minimum (1) 00125 0x29, 0x03, // Usage Maximum (3) 00126 0x15, 0x00, // Logical Minimum (0) 00127 0x25, 0x01, // Logical Maximum (1) 00128 0x95, 0x03, // Report Count (3) 00129 0x75, 0x01, // Report Size (1) 00130 0x81, 0x02, // Input (Data, Variable, Absolute) 00131 0x95, 0x01, // Report Count (1) 00132 0x75, 0x05, // Report Size (5) 00133 0x81, 0x01, // Input (03=Logitech, 01=Hid spec:Constant) 00134 0x05, 0x01, // Usage Page (Generic Desktop) 00135 0x09, 0x30, // Usage (X) 00136 0x09, 0x31, // Usage (Y) 00137 0x09, 0x38, // Usage (Logitech:_) 00138 0x15, 0x81, // Logical Minimum (-127) 00139 0x25, 0x7F, // Logical Maximum (127) 00140 0x75, 0x08, // Report Size (8) 00141 0x95, 0x02, // Report Count (Logitech=3, Hid spec =2) 00142 0x81, 0x06, // Input (Data, Variable, Relative) 00143 0xC0, // End Collection 00144 0xC0 // End Collection 00145 }; 00146 00147 static const usb_HidDesc usb_hid_descriptor = 00148 { 00149 .bLength = sizeof(usb_hid_descriptor), 00150 .bDescriptorType = HID_DT_HID, 00151 .bcdHID = usb_cpu_to_le16((uint16_t)0x0110), 00152 .bCountryCode = 0, 00153 .bNumDescriptors = 1, 00154 .bDescriptorHidType = HID_DT_REPORT, 00155 .wDescriptorLength = 00156 usb_cpu_to_le16((uint16_t)sizeof(hid_report_descriptor)), 00157 }; 00158 00159 static const UsbEndpointDesc usb_hid_ep_descriptor = 00160 { 00161 .bLength = sizeof(usb_hid_ep_descriptor), 00162 .bDescriptorType = USB_DT_ENDPOINT, 00163 .bEndpointAddress = USB_HID_REPORT_EP, 00164 .bmAttributes = USB_ENDPOINT_XFER_INT, 00165 .wMaxPacketSize = usb_cpu_to_le16((uint16_t)4), 00166 .bInterval = 10, /* resolution in ms */ 00167 }; 00168 00169 static const UsbDescHeader *usb_hid_config[] = 00170 { 00171 (const UsbDescHeader *)&usb_hid_config_descriptor, 00172 (const UsbDescHeader *)&usb_hid_interface_descriptor, 00173 (const UsbDescHeader *)&usb_hid_descriptor, 00174 (const UsbDescHeader *)&usb_hid_ep_descriptor, 00175 NULL, 00176 }; 00177 00178 static const DEFINE_USB_STRING(language_str, "\x09\x04"); // Language ID: en_US 00179 static const DEFINE_USB_STRING(manufacturer_str, 00180 USB_STRING("B", "e", "R", "T", "O", "S")); 00181 static const DEFINE_USB_STRING(product_str, 00182 USB_STRING("U", "S", "B", " ", "M", "o", "u", "s", "e")); 00183 00184 static const UsbStringDesc *usb_hid_strings[] = 00185 { 00186 (const UsbStringDesc *)&language_str, 00187 (const UsbStringDesc *)&manufacturer_str, 00188 (const UsbStringDesc *)&product_str, 00189 NULL, 00190 }; 00191 00192 typedef struct mouse_report 00193 { 00194 uint8_t buttons; 00195 int8_t x; 00196 int8_t y; 00197 } PACKED mouse_report_t; 00198 00199 static mouse_report_t report; 00200 00201 static bool hid_mouse_configured; 00202 00203 static void usb_hid_event_cb(UsbCtrlRequest *ctrl) 00204 { 00205 uint16_t value = usb_le16_to_cpu(ctrl->wValue); 00206 uint16_t index = usb_le16_to_cpu(ctrl->wIndex); 00207 uint16_t length = usb_le16_to_cpu(ctrl->wLength); 00208 uint8_t type = ctrl->mRequestType; 00209 uint8_t request = ctrl->bRequest; 00210 00211 LOG_INFO("%s: s 0x%02x 0x%02x 0x%04x 0x%04x 0x%04x\n", 00212 __func__, type, request, value, index, length); 00213 switch (ctrl->bRequest) 00214 { 00215 case USB_REQ_GET_DESCRIPTOR: 00216 switch (value >> 8) 00217 { 00218 case HID_DT_HID: 00219 LOG_INFO("%s: HID_DT_HID\n", __func__); 00220 usb_endpointWrite(USB_DIR_IN | 0, 00221 &usb_hid_descriptor, 00222 sizeof(usb_hid_descriptor)); 00223 break; 00224 case HID_DT_REPORT: 00225 LOG_INFO("%s: HID_DT_REPORT\n", __func__); 00226 usb_endpointWrite(USB_DIR_IN | 0, 00227 &hid_report_descriptor, 00228 sizeof(hid_report_descriptor)); 00229 hid_mouse_configured = true; 00230 break; 00231 } 00232 break; 00233 case HID_REQ_GET_REPORT: 00234 LOG_INFO("%s: HID_REQ_GET_REPORT\n", __func__); 00235 break; 00236 case HID_REQ_SET_REPORT: 00237 LOG_INFO("%s: HID_REQ_SET_REPORT\n", __func__); 00238 break; 00239 case HID_REQ_GET_IDLE: 00240 LOG_INFO("%s: HID_REQ_GET_IDLE\n", __func__); 00241 break; 00242 case HID_REQ_SET_IDLE: 00243 LOG_INFO("%s: HID_REQ_SET_IDLE\n", __func__); 00244 usb_endpointWrite(USB_DIR_IN | 0, NULL, 0); 00245 break; 00246 case HID_REQ_GET_PROTOCOL: 00247 LOG_INFO("%s: HID_REQ_GET_PROTOCOL\n", __func__); 00248 break; 00249 case HID_REQ_SET_PROTOCOL: 00250 LOG_INFO("%s: HID_REQ_SET_PROTOCOL\n", __func__); 00251 break; 00252 default: 00253 LOG_ERR("%s: unknown request: 0x%02x\n", 00254 __func__, ctrl->bRequest); 00255 break; 00256 } 00257 } 00258 00259 /* Global usb-mouse descriptor that identifies the usb-mouse device */ 00260 static UsbDevice usb_mouse = { 00261 .device = &usb_hid_device_descriptor, 00262 .config = usb_hid_config, 00263 .strings = usb_hid_strings, 00264 .event_cb = usb_hid_event_cb, 00265 }; 00266 00267 /* Low-level usb-hid device initialization */ 00268 static int usb_mouse_hw_init(void) 00269 { 00270 if (usb_deviceRegister(&usb_mouse) < 0) 00271 return -1; 00272 LOG_INFO("usb-hid: registered new USB mouse device\n"); 00273 return 0; 00274 } 00275 00276 /* Send a mouse event */ 00277 void usbmouse_sendEvent(int8_t x, int8_t y, int8_t buttons) 00278 { 00279 report.x = x; 00280 report.y = y; 00281 report.buttons = buttons; 00282 usb_endpointWrite(USB_HID_REPORT_EP, &report, sizeof(report)); 00283 } 00284 00285 /* 00286 * Initialize a USB HID device. 00287 * 00288 * TODO: support more than one device at the same time. 00289 */ 00290 int usbmouse_init(UNUSED_ARG(int, unit)) 00291 { 00292 #if CONFIG_KERN 00293 MOD_CHECK(proc); 00294 #endif 00295 usb_mouse_hw_init(); 00296 while (!hid_mouse_configured) 00297 cpu_relax(); 00298 return 0; 00299 }