From 3d68ea280790351d0320fc4e712c51b820a5522a Mon Sep 17 00:00:00 2001 From: Amir Hammad Date: Fri, 9 Sep 2016 18:37:22 +0200 Subject: make hid_mouse driver generic HID driver + keyboard support + SET_REPORT commands - usually leds on keyboards (WIP) - missing parsing of HID report descriptor Signed-off-by: Amir Hammad --- src/usbh_driver_hid.c | 537 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 537 insertions(+) create mode 100644 src/usbh_driver_hid.c (limited to 'src/usbh_driver_hid.c') diff --git a/src/usbh_driver_hid.c b/src/usbh_driver_hid.c new file mode 100644 index 0000000..21fa262 --- /dev/null +++ b/src/usbh_driver_hid.c @@ -0,0 +1,537 @@ +/* + * This file is part of the libusbhost library + * hosted at http://github.com/libusbhost/libusbhost + * + * Copyright (C) 2016 Amir Hammad + * + * + * libusbhost is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + * + */ + +#include "usbh_core.h" +#include "driver/usbh_device_driver.h" +#include "usbh_driver_hid.h" +#include "usart_helpers.h" + +#include +#include +#include + +#define USB_HID_SET_REPORT 0x09 +#define USB_HID_SET_IDLE 0x0A + +enum STATES { + STATE_INACTIVE, + STATE_READING_REQUEST, + STATE_READING_COMPLETE_AND_CHECK_REPORT, + STATE_SET_REPORT_EMPTY_READ, + STATE_SET_CONFIGURATION_REQUEST, + STATE_SET_CONFIGURATION_EMPTY_READ, + STATE_GET_REPORT_DESCRIPTOR_READ_SETUP,// configuration is complete at this point. We write request + STATE_GET_REPORT_DESCRIPTOR_READ, + STATE_GET_REPORT_DESCRIPTOR_READ_COMPLETE,// after the read finishes, we parse that descriptor + STATE_SET_IDLE, + STATE_SET_IDLE_COMPLETE, +}; + +enum REPORT_STATE { + REPORT_STATE_NULL, + REPORT_STATE_READY, + REPORT_STATE_WRITE_PENDING, + REPORT_STATE_WRITE_PENDING_DATA, + REPORT_STATE_EMPTY_READ, +}; + +struct _hid_device { + usbh_device_t *usbh_device; + uint8_t buffer[USBH_HID_BUFFER]; + uint16_t endpoint_in_maxpacketsize; + uint8_t endpoint_in_address; + enum STATES state_next; + uint8_t endpoint_in_toggle; + uint8_t device_id; + uint8_t configuration_value; + uint16_t report0_length; + enum REPORT_STATE report_state; + uint8_t report_data[USBH_HID_REPORT_BUFFER]; + uint8_t report_data_length; + enum HID_TYPE hid_type; + uint8_t interface_number; +}; +typedef struct _hid_device hid_device_t; + +struct hid_report_decriptor { + struct usb_hid_descriptor header; + struct _report_descriptor_info { + uint8_t bDescriptorType; + uint16_t wDescriptorLength; + } __attribute__((packed)) report_descriptors_info[]; +} __attribute__((packed)); + +static hid_device_t hid_device[USBH_HID_MAX_DEVICES]; +static hid_config_t hid_config; + +static bool initialized = false; + +void hid_driver_init(const hid_config_t *config) +{ + uint32_t i; + + initialized = true; + + hid_config = *config; + for (i = 0; i < USBH_HID_MAX_DEVICES; i++) { + hid_device[i].state_next = STATE_INACTIVE; + } +} + +static void *init(void *usbh_dev) +{ + if (!initialized) { + LOG_PRINTF("\n%s/%d : driver not initialized\r\n", __FILE__, __LINE__); + return 0; + } + + uint32_t i; + hid_device_t *drvdata = 0; + + // find free data space for HID device + for (i = 0; i < USBH_HID_MAX_DEVICES; i++) { + if (hid_device[i].state_next == STATE_INACTIVE) { + drvdata = &hid_device[i]; + drvdata->device_id = i; + drvdata->endpoint_in_address = 0; + drvdata->endpoint_in_toggle = 0; + drvdata->report0_length = 0; + drvdata->usbh_device = (usbh_device_t *)usbh_dev; + drvdata->report_state = REPORT_STATE_NULL; + drvdata->hid_type = HID_TYPE_NONE; + break; + } + } + + return drvdata; +} + +static void parse_report_descriptor(hid_device_t *hid, const uint8_t *buffer, uint32_t length) +{ + // TODO + // Do some parsing! + // add some checks + hid->report_state = REPORT_STATE_READY; + + // TODO: parse this from buffer! + hid->report_data_length = 1; + (void)buffer; + (void)length; +} + +/** + * Returns true if all needed data are parsed + */ +static bool analyze_descriptor(void *drvdata, void *descriptor) +{ + hid_device_t *hid = (hid_device_t *)drvdata; + uint8_t desc_type = ((uint8_t *)descriptor)[1]; + switch (desc_type) { + case USB_DT_CONFIGURATION: + { + const struct usb_config_descriptor * cfg = (const struct usb_config_descriptor*)descriptor; + hid->configuration_value = cfg->bConfigurationValue; + } + break; + + case USB_DT_DEVICE: + { + const struct usb_device_descriptor *devDesc = (const struct usb_device_descriptor *)descriptor; + (void)devDesc; + } + break; + + case USB_DT_INTERFACE: + { + const struct usb_interface_descriptor *ifDesc = (const struct usb_interface_descriptor *)descriptor; + if (ifDesc->bInterfaceProtocol == 0x01) { + hid->hid_type = HID_TYPE_KEYBOARD; + hid->interface_number = ifDesc->bInterfaceNumber; + } else if (ifDesc->bInterfaceProtocol == 0x02) { + hid->hid_type = HID_TYPE_MOUSE; + hid->interface_number = ifDesc->bInterfaceNumber; + } + } + break; + + case USB_DT_ENDPOINT: + { + const struct usb_endpoint_descriptor *ep = (const struct usb_endpoint_descriptor *)descriptor; + if ((ep->bmAttributes&0x03) == USB_ENDPOINT_ATTR_INTERRUPT) { + uint8_t epaddr = ep->bEndpointAddress; + if (epaddr & (1<<7)) { + hid->endpoint_in_address = epaddr&0x7f; + if (ep->wMaxPacketSize < USBH_HID_BUFFER) { + hid->endpoint_in_maxpacketsize = ep->wMaxPacketSize; + } else { + hid->endpoint_in_maxpacketsize = USBH_HID_BUFFER; + } + } + } + } + break; + + case USB_DT_HID: + { + const struct hid_report_decriptor *desc = (const struct hid_report_decriptor *)descriptor; + if (desc->header.bNumDescriptors > 0 && desc->report_descriptors_info[0].bDescriptorType == USB_DT_REPORT) { + hid->report0_length = desc->report_descriptors_info[0].wDescriptorLength; + } + } + break; + + default: + break; + } + + if (hid->endpoint_in_address && hid->report0_length) { + hid->state_next = STATE_SET_CONFIGURATION_REQUEST; + return true; + } + + return false; +} + +static void report_event(usbh_device_t *dev, usbh_packet_callback_data_t cb_data) +{ + hid_device_t *hid = (hid_device_t *)dev->drvdata; + switch (hid->report_state) { + case REPORT_STATE_WRITE_PENDING: + switch (cb_data.status) { + case USBH_PACKET_CALLBACK_STATUS_OK: + hid->report_state = REPORT_STATE_WRITE_PENDING_DATA; + + device_xfer_control_write_data(hid->report_data, hid->report_data_length, report_event, dev); + break; + + case USBH_PACKET_CALLBACK_STATUS_ERRSIZ: + case USBH_PACKET_CALLBACK_STATUS_EFATAL: + case USBH_PACKET_CALLBACK_STATUS_EAGAIN: + ERROR(cb_data.status); + hid->state_next = STATE_INACTIVE; + break; + } + break; + + case REPORT_STATE_WRITE_PENDING_DATA: + switch (cb_data.status) { + case USBH_PACKET_CALLBACK_STATUS_OK: + hid->report_state = REPORT_STATE_EMPTY_READ; + device_xfer_control_read(0, 0, report_event, dev); + LOG_PRINTF("reading empty\n"); + break; + + case USBH_PACKET_CALLBACK_STATUS_ERRSIZ: + case USBH_PACKET_CALLBACK_STATUS_EFATAL: + case USBH_PACKET_CALLBACK_STATUS_EAGAIN: + ERROR(cb_data.status); + hid->state_next = STATE_INACTIVE; + break; + } + break; + + + case REPORT_STATE_EMPTY_READ: + switch (cb_data.status) { + case USBH_PACKET_CALLBACK_STATUS_OK: + hid->report_state = REPORT_STATE_READY; + break; + + case USBH_PACKET_CALLBACK_STATUS_ERRSIZ: + case USBH_PACKET_CALLBACK_STATUS_EFATAL: + case USBH_PACKET_CALLBACK_STATUS_EAGAIN: + ERROR(cb_data.status); + hid->state_next = STATE_INACTIVE; + break; + } + break; + default: + break; + } +} + +static void event(usbh_device_t *dev, usbh_packet_callback_data_t cb_data) +{ + hid_device_t *hid = (hid_device_t *)dev->drvdata; + + switch (hid->state_next) { + case STATE_READING_COMPLETE_AND_CHECK_REPORT: + { + switch (cb_data.status) { + case USBH_PACKET_CALLBACK_STATUS_OK: + case USBH_PACKET_CALLBACK_STATUS_ERRSIZ: + if (hid_config.hid_in_message_handler) { + hid_config.hid_in_message_handler(hid->device_id, hid->buffer, cb_data.transferred_length); + } + hid->state_next = STATE_READING_REQUEST; + break; + + case USBH_PACKET_CALLBACK_STATUS_EFATAL: + case USBH_PACKET_CALLBACK_STATUS_EAGAIN: + ERROR(cb_data.status); + hid->state_next = STATE_INACTIVE; + break; + } + } + break; + + case STATE_SET_CONFIGURATION_EMPTY_READ: + { + LOG_PRINTF("|empty packet read|"); + switch (cb_data.status) { + case USBH_PACKET_CALLBACK_STATUS_OK: + hid->state_next = STATE_GET_REPORT_DESCRIPTOR_READ_SETUP; + device_xfer_control_read(0, 0, event, dev); + break; + + case USBH_PACKET_CALLBACK_STATUS_ERRSIZ: + case USBH_PACKET_CALLBACK_STATUS_EFATAL: + case USBH_PACKET_CALLBACK_STATUS_EAGAIN: + ERROR(cb_data.status); + hid->state_next = STATE_INACTIVE; + break; + } + } + break; + + case STATE_GET_REPORT_DESCRIPTOR_READ_SETUP: + { + switch (cb_data.status) { + case USBH_PACKET_CALLBACK_STATUS_OK: + case USBH_PACKET_CALLBACK_STATUS_ERRSIZ: + { + hid->endpoint_in_toggle = 0; + // We support only the first report descriptor with index 0 + + // limit the size of the report descriptor! + if (hid->report0_length > USBH_HID_BUFFER) { + hid->report0_length = USBH_HID_BUFFER; + } + + struct usb_setup_data setup_data; + + setup_data.bmRequestType = USB_REQ_TYPE_IN | USB_REQ_TYPE_INTERFACE; + setup_data.bRequest = USB_REQ_GET_DESCRIPTOR; + setup_data.wValue = USB_DT_REPORT << 8; + setup_data.wIndex = 0; + setup_data.wLength = hid->report0_length; + + hid->state_next = STATE_GET_REPORT_DESCRIPTOR_READ; + device_xfer_control_write_setup(&setup_data, sizeof(setup_data), event, dev); + + } + break; + + case USBH_PACKET_CALLBACK_STATUS_EFATAL: + case USBH_PACKET_CALLBACK_STATUS_EAGAIN: + ERROR(cb_data.status); + hid->state_next = STATE_INACTIVE; + break; + } + } + break; + + case STATE_GET_REPORT_DESCRIPTOR_READ: + { + switch (cb_data.status) { + case USBH_PACKET_CALLBACK_STATUS_OK: + hid->state_next = STATE_GET_REPORT_DESCRIPTOR_READ_COMPLETE; + device_xfer_control_read(hid->buffer, hid->report0_length, event, dev); + break; + + case USBH_PACKET_CALLBACK_STATUS_ERRSIZ: + case USBH_PACKET_CALLBACK_STATUS_EFATAL: + case USBH_PACKET_CALLBACK_STATUS_EAGAIN: + ERROR(cb_data.status); + hid->state_next = STATE_INACTIVE; + break; + } + } + break; + + + case STATE_GET_REPORT_DESCRIPTOR_READ_COMPLETE: // read complete, SET_IDLE to 0 + { + switch (cb_data.status) { + case USBH_PACKET_CALLBACK_STATUS_OK: + LOG_PRINTF("READ REPORT COMPLETE \n"); + hid->state_next = STATE_READING_REQUEST; + hid->endpoint_in_toggle = 0; + + parse_report_descriptor(hid, hid->buffer, cb_data.transferred_length); + break; + + case USBH_PACKET_CALLBACK_STATUS_ERRSIZ: + case USBH_PACKET_CALLBACK_STATUS_EFATAL: + case USBH_PACKET_CALLBACK_STATUS_EAGAIN: + ERROR(cb_data.status); + hid->state_next = STATE_INACTIVE; + break; + } + } + break; + + default: + break; + } +} + + +static void read_hid_in_endpoint(void *drvdata) +{ + hid_device_t *hid = (hid_device_t *)drvdata; + usbh_packet_t packet; + + packet.address = hid->usbh_device->address; + packet.data.in = &hid->buffer[0]; + packet.datalen = hid->endpoint_in_maxpacketsize; + packet.endpoint_address = hid->endpoint_in_address; + packet.endpoint_size_max = hid->endpoint_in_maxpacketsize; + packet.endpoint_type = USBH_ENDPOINT_TYPE_INTERRUPT; + packet.speed = hid->usbh_device->speed; + packet.callback = event; + packet.callback_arg = hid->usbh_device; + packet.toggle = &hid->endpoint_in_toggle; + + hid->state_next = STATE_READING_COMPLETE_AND_CHECK_REPORT; + usbh_read(hid->usbh_device, &packet); +} + +/** + * @param time_curr_us - monotically rising time + * unit is microseconds + * @see usbh_poll() + */ +static void poll(void *drvdata, uint32_t time_curr_us) +{ + (void)time_curr_us; + + hid_device_t *hid = (hid_device_t *)drvdata; + usbh_device_t *dev = hid->usbh_device; + switch (hid->state_next) { + case STATE_READING_REQUEST: + { + read_hid_in_endpoint(drvdata); + } + break; + + case STATE_SET_CONFIGURATION_REQUEST: + { + struct usb_setup_data setup_data; + + setup_data.bmRequestType = USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_DEVICE; + setup_data.bRequest = USB_REQ_SET_CONFIGURATION; + setup_data.wValue = hid->configuration_value; + setup_data.wIndex = 0; + setup_data.wLength = 0; + + hid->state_next = STATE_SET_CONFIGURATION_EMPTY_READ; + + device_xfer_control_write_setup(&setup_data, sizeof(setup_data), event, dev); + } + break; + + default: + // do nothing - probably transfer is in progress + break; + } +} + +static void remove(void *drvdata) +{ + hid_device_t *hid = (hid_device_t *)drvdata; + hid->state_next = STATE_INACTIVE; + hid->endpoint_in_address = 0; +} + +bool hid_set_report(uint8_t device_id, uint8_t val) +{ + if (device_id >= USBH_HID_MAX_DEVICES) { + LOG_PRINTF("invalid device id"); + return false; + } + + hid_device_t *hid = &hid_device[device_id]; + if (hid->report_state != REPORT_STATE_READY) { + LOG_PRINTF("reporting is not ready\n"); + // store and update afterwards + return false; + } + + if (hid->report_data_length == 0) { + LOG_PRINTF("reporting is not available (report len=0)\n"); + return false; + } + + struct usb_setup_data setup_data; + setup_data.bmRequestType = USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE; + setup_data.bRequest = USB_HID_SET_REPORT; + setup_data.wValue = 0x02 << 8; + setup_data.wIndex = hid->interface_number; + setup_data.wLength = hid->report_data_length; + + hid->report_data[0] = val; + + hid->report_state = REPORT_STATE_WRITE_PENDING; + device_xfer_control_write_setup(&setup_data, sizeof(setup_data), report_event, hid->usbh_device); + return true; +} + +bool hid_is_connected(uint8_t device_id) +{ + if (device_id >= USBH_HID_MAX_DEVICES) { + LOG_PRINTF("is connected: invalid device id"); + return false; + } + return hid_device[device_id].state_next == STATE_INACTIVE; +} + + +enum HID_TYPE hid_get_type(uint8_t device_id) +{ + if (hid_is_connected(device_id)) { + return HID_TYPE_NONE; + } + return hid_device[device_id].hid_type; +} + +static const usbh_dev_driver_info_t driver_info = { + .deviceClass = -1, + .deviceSubClass = -1, + .deviceProtocol = -1, + .idVendor = -1, + .idProduct = -1, + .ifaceClass = 0x03, // HID class + .ifaceSubClass = -1, + .ifaceProtocol = -1, // Do not care +}; + +const usbh_dev_driver_t usbh_hid_driver = { + .init = init, + .analyze_descriptor = analyze_descriptor, + .poll = poll, + .remove = remove, + .info = &driver_info +}; + + + -- cgit From 58fec7a17ceb6814d64e702e7829556c3ece01e4 Mon Sep 17 00:00:00 2001 From: Amir Hammad Date: Mon, 5 Sep 2016 19:48:56 +0200 Subject: Drop need for the set configuration request in dev drivers Signed-off-by: Amir Hammad --- src/usbh_driver_hid.c | 81 ++++++++++----------------------------------------- 1 file changed, 15 insertions(+), 66 deletions(-) (limited to 'src/usbh_driver_hid.c') diff --git a/src/usbh_driver_hid.c b/src/usbh_driver_hid.c index 21fa262..b9b95d7 100644 --- a/src/usbh_driver_hid.c +++ b/src/usbh_driver_hid.c @@ -37,8 +37,6 @@ enum STATES { STATE_READING_REQUEST, STATE_READING_COMPLETE_AND_CHECK_REPORT, STATE_SET_REPORT_EMPTY_READ, - STATE_SET_CONFIGURATION_REQUEST, - STATE_SET_CONFIGURATION_EMPTY_READ, STATE_GET_REPORT_DESCRIPTOR_READ_SETUP,// configuration is complete at this point. We write request STATE_GET_REPORT_DESCRIPTOR_READ, STATE_GET_REPORT_DESCRIPTOR_READ_COMPLETE,// after the read finishes, we parse that descriptor @@ -204,7 +202,7 @@ static bool analyze_descriptor(void *drvdata, void *descriptor) } if (hid->endpoint_in_address && hid->report0_length) { - hid->state_next = STATE_SET_CONFIGURATION_REQUEST; + hid->state_next = STATE_GET_REPORT_DESCRIPTOR_READ_SETUP; return true; } @@ -294,62 +292,6 @@ static void event(usbh_device_t *dev, usbh_packet_callback_data_t cb_data) } break; - case STATE_SET_CONFIGURATION_EMPTY_READ: - { - LOG_PRINTF("|empty packet read|"); - switch (cb_data.status) { - case USBH_PACKET_CALLBACK_STATUS_OK: - hid->state_next = STATE_GET_REPORT_DESCRIPTOR_READ_SETUP; - device_xfer_control_read(0, 0, event, dev); - break; - - case USBH_PACKET_CALLBACK_STATUS_ERRSIZ: - case USBH_PACKET_CALLBACK_STATUS_EFATAL: - case USBH_PACKET_CALLBACK_STATUS_EAGAIN: - ERROR(cb_data.status); - hid->state_next = STATE_INACTIVE; - break; - } - } - break; - - case STATE_GET_REPORT_DESCRIPTOR_READ_SETUP: - { - switch (cb_data.status) { - case USBH_PACKET_CALLBACK_STATUS_OK: - case USBH_PACKET_CALLBACK_STATUS_ERRSIZ: - { - hid->endpoint_in_toggle = 0; - // We support only the first report descriptor with index 0 - - // limit the size of the report descriptor! - if (hid->report0_length > USBH_HID_BUFFER) { - hid->report0_length = USBH_HID_BUFFER; - } - - struct usb_setup_data setup_data; - - setup_data.bmRequestType = USB_REQ_TYPE_IN | USB_REQ_TYPE_INTERFACE; - setup_data.bRequest = USB_REQ_GET_DESCRIPTOR; - setup_data.wValue = USB_DT_REPORT << 8; - setup_data.wIndex = 0; - setup_data.wLength = hid->report0_length; - - hid->state_next = STATE_GET_REPORT_DESCRIPTOR_READ; - device_xfer_control_write_setup(&setup_data, sizeof(setup_data), event, dev); - - } - break; - - case USBH_PACKET_CALLBACK_STATUS_EFATAL: - case USBH_PACKET_CALLBACK_STATUS_EAGAIN: - ERROR(cb_data.status); - hid->state_next = STATE_INACTIVE; - break; - } - } - break; - case STATE_GET_REPORT_DESCRIPTOR_READ: { switch (cb_data.status) { @@ -434,18 +376,25 @@ static void poll(void *drvdata, uint32_t time_curr_us) } break; - case STATE_SET_CONFIGURATION_REQUEST: + case STATE_GET_REPORT_DESCRIPTOR_READ_SETUP: { + hid->endpoint_in_toggle = 0; + // We support only the first report descriptor with index 0 + + // limit the size of the report descriptor! + if (hid->report0_length > USBH_HID_BUFFER) { + hid->report0_length = USBH_HID_BUFFER; + } + struct usb_setup_data setup_data; - setup_data.bmRequestType = USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_DEVICE; - setup_data.bRequest = USB_REQ_SET_CONFIGURATION; - setup_data.wValue = hid->configuration_value; + setup_data.bmRequestType = USB_REQ_TYPE_IN | USB_REQ_TYPE_INTERFACE; + setup_data.bRequest = USB_REQ_GET_DESCRIPTOR; + setup_data.wValue = USB_DT_REPORT << 8; setup_data.wIndex = 0; - setup_data.wLength = 0; - - hid->state_next = STATE_SET_CONFIGURATION_EMPTY_READ; + setup_data.wLength = hid->report0_length; + hid->state_next = STATE_GET_REPORT_DESCRIPTOR_READ; device_xfer_control_write_setup(&setup_data, sizeof(setup_data), event, dev); } break; -- cgit From 66b801b01eecf3750ff8f03e30a658f2e7f7b9e7 Mon Sep 17 00:00:00 2001 From: Amir Hammad Date: Mon, 5 Sep 2016 21:36:51 +0200 Subject: hid: use control wrapper to simplify hid report writes Signed-off-by: Amir Hammad --- src/usbh_driver_hid.c | 88 +++++---------------------------------------------- 1 file changed, 8 insertions(+), 80 deletions(-) (limited to 'src/usbh_driver_hid.c') diff --git a/src/usbh_driver_hid.c b/src/usbh_driver_hid.c index b9b95d7..54956b2 100644 --- a/src/usbh_driver_hid.c +++ b/src/usbh_driver_hid.c @@ -38,7 +38,6 @@ enum STATES { STATE_READING_COMPLETE_AND_CHECK_REPORT, STATE_SET_REPORT_EMPTY_READ, STATE_GET_REPORT_DESCRIPTOR_READ_SETUP,// configuration is complete at this point. We write request - STATE_GET_REPORT_DESCRIPTOR_READ, STATE_GET_REPORT_DESCRIPTOR_READ_COMPLETE,// after the read finishes, we parse that descriptor STATE_SET_IDLE, STATE_SET_IDLE_COMPLETE, @@ -47,9 +46,7 @@ enum STATES { enum REPORT_STATE { REPORT_STATE_NULL, REPORT_STATE_READY, - REPORT_STATE_WRITE_PENDING, - REPORT_STATE_WRITE_PENDING_DATA, - REPORT_STATE_EMPTY_READ, + REPORT_STATE_PENDING, }; struct _hid_device { @@ -211,60 +208,10 @@ static bool analyze_descriptor(void *drvdata, void *descriptor) static void report_event(usbh_device_t *dev, usbh_packet_callback_data_t cb_data) { - hid_device_t *hid = (hid_device_t *)dev->drvdata; - switch (hid->report_state) { - case REPORT_STATE_WRITE_PENDING: - switch (cb_data.status) { - case USBH_PACKET_CALLBACK_STATUS_OK: - hid->report_state = REPORT_STATE_WRITE_PENDING_DATA; - - device_xfer_control_write_data(hid->report_data, hid->report_data_length, report_event, dev); - break; - - case USBH_PACKET_CALLBACK_STATUS_ERRSIZ: - case USBH_PACKET_CALLBACK_STATUS_EFATAL: - case USBH_PACKET_CALLBACK_STATUS_EAGAIN: - ERROR(cb_data.status); - hid->state_next = STATE_INACTIVE; - break; - } - break; - - case REPORT_STATE_WRITE_PENDING_DATA: - switch (cb_data.status) { - case USBH_PACKET_CALLBACK_STATUS_OK: - hid->report_state = REPORT_STATE_EMPTY_READ; - device_xfer_control_read(0, 0, report_event, dev); - LOG_PRINTF("reading empty\n"); - break; - - case USBH_PACKET_CALLBACK_STATUS_ERRSIZ: - case USBH_PACKET_CALLBACK_STATUS_EFATAL: - case USBH_PACKET_CALLBACK_STATUS_EAGAIN: - ERROR(cb_data.status); - hid->state_next = STATE_INACTIVE; - break; - } - break; - - - case REPORT_STATE_EMPTY_READ: - switch (cb_data.status) { - case USBH_PACKET_CALLBACK_STATUS_OK: - hid->report_state = REPORT_STATE_READY; - break; + (void)cb_data;// UNUSED - case USBH_PACKET_CALLBACK_STATUS_ERRSIZ: - case USBH_PACKET_CALLBACK_STATUS_EFATAL: - case USBH_PACKET_CALLBACK_STATUS_EAGAIN: - ERROR(cb_data.status); - hid->state_next = STATE_INACTIVE; - break; - } - break; - default: - break; - } + hid_device_t *hid = (hid_device_t *)dev->drvdata; + hid->report_state = REPORT_STATE_READY; } static void event(usbh_device_t *dev, usbh_packet_callback_data_t cb_data) @@ -292,25 +239,6 @@ static void event(usbh_device_t *dev, usbh_packet_callback_data_t cb_data) } break; - case STATE_GET_REPORT_DESCRIPTOR_READ: - { - switch (cb_data.status) { - case USBH_PACKET_CALLBACK_STATUS_OK: - hid->state_next = STATE_GET_REPORT_DESCRIPTOR_READ_COMPLETE; - device_xfer_control_read(hid->buffer, hid->report0_length, event, dev); - break; - - case USBH_PACKET_CALLBACK_STATUS_ERRSIZ: - case USBH_PACKET_CALLBACK_STATUS_EFATAL: - case USBH_PACKET_CALLBACK_STATUS_EAGAIN: - ERROR(cb_data.status); - hid->state_next = STATE_INACTIVE; - break; - } - } - break; - - case STATE_GET_REPORT_DESCRIPTOR_READ_COMPLETE: // read complete, SET_IDLE to 0 { switch (cb_data.status) { @@ -394,8 +322,8 @@ static void poll(void *drvdata, uint32_t time_curr_us) setup_data.wIndex = 0; setup_data.wLength = hid->report0_length; - hid->state_next = STATE_GET_REPORT_DESCRIPTOR_READ; - device_xfer_control_write_setup(&setup_data, sizeof(setup_data), event, dev); + hid->state_next = STATE_GET_REPORT_DESCRIPTOR_READ_COMPLETE; + device_control(dev, event, &setup_data, hid->buffer); } break; @@ -440,8 +368,8 @@ bool hid_set_report(uint8_t device_id, uint8_t val) hid->report_data[0] = val; - hid->report_state = REPORT_STATE_WRITE_PENDING; - device_xfer_control_write_setup(&setup_data, sizeof(setup_data), report_event, hid->usbh_device); + hid->report_state = REPORT_STATE_PENDING; + device_control(hid->usbh_device, report_event, &setup_data, &hid->report_data); return true; } -- cgit From 1d1b697bc6b13b5db1594c3dafe5452b6b2c1668 Mon Sep 17 00:00:00 2001 From: Amir Hammad Date: Thu, 8 Sep 2016 06:27:35 +0200 Subject: use NULL instead of 0 for assigning null pointer Signed-off-by: Amir Hammad --- src/usbh_driver_hid.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/usbh_driver_hid.c') diff --git a/src/usbh_driver_hid.c b/src/usbh_driver_hid.c index 54956b2..0e90ab0 100644 --- a/src/usbh_driver_hid.c +++ b/src/usbh_driver_hid.c @@ -28,6 +28,7 @@ #include #include #include +#include #define USB_HID_SET_REPORT 0x09 #define USB_HID_SET_IDLE 0x0A @@ -100,7 +101,7 @@ static void *init(void *usbh_dev) } uint32_t i; - hid_device_t *drvdata = 0; + hid_device_t *drvdata = NULL; // find free data space for HID device for (i = 0; i < USBH_HID_MAX_DEVICES; i++) { -- cgit From decb2d817d806e8ed6e77cf215e4adfef4767a50 Mon Sep 17 00:00:00 2001 From: Amir Hammad Date: Fri, 9 Sep 2016 18:25:28 +0200 Subject: use forward declaration for usbh_dev_driver_t Signed-off-by: Amir Hammad --- src/usbh_driver_hid.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/usbh_driver_hid.c') diff --git a/src/usbh_driver_hid.c b/src/usbh_driver_hid.c index 0e90ab0..15af80b 100644 --- a/src/usbh_driver_hid.c +++ b/src/usbh_driver_hid.c @@ -93,7 +93,7 @@ void hid_driver_init(const hid_config_t *config) } } -static void *init(void *usbh_dev) +static void *init(usbh_device_t *usbh_dev) { if (!initialized) { LOG_PRINTF("\n%s/%d : driver not initialized\r\n", __FILE__, __LINE__); @@ -111,7 +111,7 @@ static void *init(void *usbh_dev) drvdata->endpoint_in_address = 0; drvdata->endpoint_in_toggle = 0; drvdata->report0_length = 0; - drvdata->usbh_device = (usbh_device_t *)usbh_dev; + drvdata->usbh_device = usbh_dev; drvdata->report_state = REPORT_STATE_NULL; drvdata->hid_type = HID_TYPE_NONE; break; -- cgit From 4415d960c3d1e52573db02be4aee6e22d22809cf Mon Sep 17 00:00:00 2001 From: Amir Hammad Date: Sun, 11 Sep 2016 12:03:20 +0200 Subject: use default case instead of handling other packet statuses explicitely Signed-off-by: Amir Hammad --- src/usbh_driver_hid.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'src/usbh_driver_hid.c') diff --git a/src/usbh_driver_hid.c b/src/usbh_driver_hid.c index 15af80b..bb842db 100644 --- a/src/usbh_driver_hid.c +++ b/src/usbh_driver_hid.c @@ -231,8 +231,7 @@ static void event(usbh_device_t *dev, usbh_packet_callback_data_t cb_data) hid->state_next = STATE_READING_REQUEST; break; - case USBH_PACKET_CALLBACK_STATUS_EFATAL: - case USBH_PACKET_CALLBACK_STATUS_EAGAIN: + default: ERROR(cb_data.status); hid->state_next = STATE_INACTIVE; break; @@ -251,9 +250,7 @@ static void event(usbh_device_t *dev, usbh_packet_callback_data_t cb_data) parse_report_descriptor(hid, hid->buffer, cb_data.transferred_length); break; - case USBH_PACKET_CALLBACK_STATUS_ERRSIZ: - case USBH_PACKET_CALLBACK_STATUS_EFATAL: - case USBH_PACKET_CALLBACK_STATUS_EAGAIN: + default: ERROR(cb_data.status); hid->state_next = STATE_INACTIVE; break; -- cgit