diff --git a/firmware/export/powermgmt.h b/firmware/export/powermgmt.h index b7ca6772f3..235f5302f9 100644 --- a/firmware/export/powermgmt.h +++ b/firmware/export/powermgmt.h @@ -166,9 +166,6 @@ void set_poweroff_timeout(int timeout); void set_battery_capacity(int capacity); /* set local battery capacity value */ int get_battery_capacity(void); /* get local battery capacity value */ void set_battery_type(int type); /* set local battery type */ -#ifdef USB_ENABLE_HID -void set_battery_reporting(bool enable); -#endif void set_sleeptimer_duration(int minutes); int get_sleep_timer(void); diff --git a/firmware/powermgmt.c b/firmware/powermgmt.c index 969d6167da..6cac300cdf 100644 --- a/firmware/powermgmt.c +++ b/firmware/powermgmt.c @@ -48,9 +48,6 @@ #if (CONFIG_PLATFORM & PLATFORM_HOSTED) #include #endif -#ifdef USB_ENABLE_HID -#include "usbstack/usb_hid.h" -#endif #if (defined(IAUDIO_X5) || defined(IAUDIO_M5) || defined(COWON_D2)) \ && !defined (SIMULATOR) @@ -640,17 +637,6 @@ static void collect_power_history(void) power_history[0] = power_hist_item(); } -#ifdef USB_ENABLE_HID -static bool battery_reporting = false; -static int battery_report_percent = -1; - -void set_battery_reporting(bool enable) -{ - battery_reporting = enable; - battery_report_percent = -1; -} -#endif - /* * Monitor the presence of a charger and perform critical frequent steps * such as running the battery voltage filter. @@ -764,13 +750,6 @@ static void power_thread(void) next_power_hist += HZ*60; collect_power_history(); } - -#ifdef USB_ENABLE_HID - if (battery_reporting && battery_report_percent != battery_percent) { - battery_report_percent = battery_percent; - usb_hid_send(HID_USAGE_PAGE_GENERIC_DEVICE_CONTROLS, battery_report_percent); - } -#endif } } /* power_thread */ diff --git a/firmware/usbstack/usb_hid.c b/firmware/usbstack/usb_hid.c index 0b672e6452..5885b60e32 100644 --- a/firmware/usbstack/usb_hid.c +++ b/firmware/usbstack/usb_hid.c @@ -42,6 +42,7 @@ /* HID main items (HID1_11.pdf, page 38) */ #define INPUT 0x80 #define OUTPUT 0x90 +#define FEATURE 0xB0 #define COLLECTION 0xA0 #define COLLECTION_PHYSICAL 0x00 #define COLLECTION_APPLICATION 0x01 @@ -90,6 +91,7 @@ #define HID_BUF_SIZE_REPORT 160 #define HID_NUM_BUFFERS 5 #define SET_REPORT_BUF_LEN 2 +#define GET_REPORT_BUF_LEN 2 #ifdef LOGF_ENABLE @@ -103,6 +105,8 @@ #define HID_BUF_INC(i) do { (i) = ((i) + 1) % HID_NUM_BUFFERS; } while (0) #define PACK_VAL(dest, val) *(dest)++ = (val) & 0xff +#define REPORT_ID_BACKGROUND REPORT_ID_COUNT + typedef enum { REPORT_ID_KEYBOARD = 1, @@ -110,7 +114,6 @@ typedef enum #ifdef HAVE_USB_HID_MOUSE REPORT_ID_MOUSE, #endif - REPORT_ID_BACKGROUND, REPORT_ID_COUNT, } report_id_t; @@ -452,15 +455,6 @@ static uint8_t buf_set_mouse(unsigned char *buf, int id) } #endif /* HAVE_USB_HID_MOUSE */ -#define BUF_LEN_BACKGROUND 1 -static uint8_t buf_set_background(unsigned char *buf, int id) -{ - memset(buf, 0, BUF_LEN_BACKGROUND); - buf[0] = (uint8_t)id; - - return BUF_LEN_BACKGROUND; -} - static size_t descriptor_report_get(unsigned char *dest) { unsigned char *report = dest; @@ -562,22 +556,25 @@ static size_t descriptor_report_get(unsigned char *dest) PACK_VAL(report, END_COLLECTION); #endif /* HAVE_USB_HID_MOUSE */ - /* Background controls */ - usb_hid_report = &usb_hid_reports[REPORT_ID_BACKGROUND]; - usb_hid_report->usage_page = HID_USAGE_PAGE_GENERIC_DEVICE_CONTROLS; - usb_hid_report->buf_set = buf_set_background; - usb_hid_report->is_key_released = 0; - + /* Background reports */ pack_parameter(&report, 0, 1, USAGE_PAGE, HID_USAGE_PAGE_GENERIC_DEVICE_CONTROLS); pack_parameter(&report, 0, 0, CONSUMER_USAGE, HID_GENERIC_DEVICE_BACKGROUND_CONTROLS); pack_parameter(&report, 0, 1, COLLECTION, COLLECTION_APPLICATION); pack_parameter(&report, 0, 1, REPORT_ID, REPORT_ID_BACKGROUND); + /* Padding */ + pack_parameter(&report, 0, 0, CONSUMER_USAGE, HID_GENERIC_DEVICE_UNDEFINED); + pack_parameter(&report, 0, 1, LOGICAL_MINIMUM, 0); + pack_parameter(&report, 0, 1, LOGICAL_MAXIMUM, 255); + pack_parameter(&report, 0, 1, REPORT_SIZE, 8); + pack_parameter(&report, 0, 1, REPORT_COUNT, 1); + pack_parameter(&report, 0, 1, FEATURE, MAIN_ITEM_CONSTANT); + /* Battery percentage */ pack_parameter(&report, 0, 0, CONSUMER_USAGE, HID_GENERIC_DEVICE_BATTERY_STRENGTH); pack_parameter(&report, 0, 1, LOGICAL_MINIMUM, 0); pack_parameter(&report, 0, 1, LOGICAL_MAXIMUM, 100); pack_parameter(&report, 0, 1, REPORT_SIZE, 8); pack_parameter(&report, 0, 1, REPORT_COUNT, 1); - pack_parameter(&report, 0, 1, INPUT, MAIN_ITEM_VARIABLE); + pack_parameter(&report, 0, 1, FEATURE, MAIN_ITEM_VARIABLE); PACK_VAL(report, END_COLLECTION); return (size_t)(report - dest); @@ -622,7 +619,6 @@ void usb_hid_init_connection(void) logf("hid: init connection"); active = true; currently_sending = false; - set_battery_reporting(true); } /* called by usb_core_init() */ @@ -643,7 +639,6 @@ void usb_hid_init(void) void usb_hid_disconnect(void) { logf("hid: disconnect"); - set_battery_reporting(false); active = false; currently_sending = false; } @@ -677,7 +672,7 @@ static int usb_hid_set_report(struct usb_ctrlrequest *req) if ((req->wValue >> 8) != REPORT_TYPE_OUTPUT) { - logf("Unsopported report type"); + logf("Unsupported report type"); return 1; } if ((req->wValue & 0xff) != REPORT_ID_KEYBOARD) @@ -718,14 +713,47 @@ static int usb_hid_set_report(struct usb_ctrlrequest *req) return 0; } +static int usb_hid_get_report(struct usb_ctrlrequest *req, unsigned char** dest) +{ + if ((req->wValue >> 8) != REPORT_TYPE_FEATURE) + { + logf("Unsupported report type"); + return 1; + } + + if ((req->wValue & 0xff) != REPORT_ID_BACKGROUND) + { + logf("Wrong report id"); + return 2; + } + + if (req->wIndex != (uint16_t)usb_interface) + { + logf("Wrong interface"); + return 3; + } + + if (req->wLength < GET_REPORT_BUF_LEN) + { + logf("Wrong length"); + return 4; + } + + (*dest)[0] = 0; + (*dest)[1] = battery_level(); + *dest += GET_REPORT_BUF_LEN; + + return 0; +} + /* called by usb_core_control_request() */ bool usb_hid_control_request(struct usb_ctrlrequest *req, unsigned char *dest) { + unsigned char *orig_dest = dest; switch (req->bRequestType & USB_TYPE_MASK) { case USB_TYPE_STANDARD: { - unsigned char *orig_dest = dest; uint8_t type = req->wValue >> 8; size_t len; logf("hid: type %d %s", type, (type == USB_DT_HID) ? "hid" : @@ -755,14 +783,26 @@ bool usb_hid_control_request(struct usb_ctrlrequest *req, unsigned char *dest) { logf("req %d %s", req->bRequest, (req->bRequest == USB_HID_SET_IDLE) ? "set idle" : - ((req->bRequest == USB_HID_SET_REPORT) ? "set report" : "")); + ((req->bRequest == USB_HID_SET_REPORT) ? "set report" : + ((req->bRequest == USB_HID_GET_REPORT) ? "get report" : ""))); switch (req->bRequest) { case USB_HID_SET_REPORT: if (usb_hid_set_report(req)) break; + case USB_HID_GET_REPORT: + if (usb_hid_get_report(req, &dest)) + break; case USB_HID_SET_IDLE: - usb_drv_send(EP_CONTROL, NULL, 0); /* ack */ + if (dest != orig_dest) + { + usb_drv_recv(EP_CONTROL, NULL, 0); /* ack */ + usb_drv_send(EP_CONTROL, orig_dest, dest - orig_dest); + } + else + { + usb_drv_send(EP_CONTROL, NULL, 0); /* ack */ + } return true; } break;