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