Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add gadget mode for retro-bit GENERATIONS
- Loading branch information
Showing
4 changed files
with
159 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
static char opg_driver_name[] = | ||
"OPiPad Gadget HID Driver for retro-bit GENERATIONS"; | ||
|
||
#define OPG_USB_VERSION cpu_to_le16(0x200) | ||
#define OPG_DEVICE_CLASS USB_CLASS_PER_INTERFACE | ||
#define OPG_DEVICE_SUB_CLASS 0 | ||
#define OPG_DEVICE_PROTOCOL 0 | ||
|
||
#define OPG_VENDOR_ID 0x6666 | ||
#define OPG_PRODUCT_ID 0x0880 | ||
|
||
static char opg_hid_report[] = { | ||
0x05, 0x01, // usage page (desktop) | ||
0x09, 0x04, // usage (sport control) | ||
0xa1, 0x01, // collection (application) | ||
0x75, 0x04, // report size (4) | ||
0x95, 0x02, // report count (2) | ||
0x15, 0x00, // logical minimum (0) | ||
0x25, 0x0f, // logical maximum (15) | ||
0x35, 0x00, // physical minimum (0) | ||
0x45, 0xff, // physical maximum (255) | ||
0x09, 0x30, // usage (x) | ||
0x09, 0x31, // usage (y) | ||
0x81, 0x02, // input (variable) | ||
0x75, 0x01, // report size (1) | ||
0x95, 0x06, // report count (6) | ||
0x25, 0x01, // logical maximum (1) | ||
0x45, 0x01, // physical maximum (1) | ||
0x05, 0x09, // usage page (button) | ||
0x19, 0x01, // usage minimum (1) | ||
0x29, 0x06, // usage maximum (6) | ||
0x81, 0x02, // input (variable) | ||
0x95, 0x02, // report count (2) | ||
0x19, 0x09, // usage minimum (9) | ||
0x29, 0x0a, // usage maximum (10) | ||
0x81, 0x02, // input (variable) | ||
0xc0, // end collection | ||
}; | ||
|
||
struct opg_config_descriptor { | ||
struct usb_config_descriptor config; | ||
struct usb_interface_descriptor interface; | ||
struct usb_hid_descriptor hid; | ||
struct usb_short_endpoint_descriptor ep_in; | ||
} __attribute__ ((packed)) opg_config_desc = { | ||
.config = { | ||
.bLength = USB_DT_CONFIG_SIZE, | ||
.bDescriptorType = USB_DT_CONFIG, | ||
.wTotalLength = cpu_to_le16(sizeof(struct opg_config_descriptor)), | ||
.bNumInterfaces = 1, | ||
.bConfigurationValue = 1, | ||
.iConfiguration = IDX_NULL, | ||
.bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, | ||
.bMaxPower = 250, // x 2mA | ||
}, | ||
.interface = { | ||
.bLength = USB_DT_INTERFACE_SIZE, | ||
.bDescriptorType = USB_DT_INTERFACE, | ||
.bInterfaceNumber = 0, | ||
.bAlternateSetting = 0, | ||
.bNumEndpoints = 1, | ||
.bInterfaceClass = USB_CLASS_HID, | ||
.bInterfaceSubClass = 0x00, | ||
.bInterfaceProtocol = 0x00, | ||
.iInterface = IDX_NULL, | ||
}, | ||
.hid = { | ||
.bLength = sizeof(struct usb_hid_descriptor), | ||
.bDescriptorType = USB_DT_HID, | ||
.bcdHID = cpu_to_le16(0x0110), | ||
.bCountryCode = 0, | ||
.bNumReports = 1, | ||
.bReportType = USB_DT_HID_REPORT, | ||
.wReportLength = cpu_to_le16(sizeof(opg_hid_report)), | ||
}, | ||
.ep_in = { | ||
.bLength = USB_DT_ENDPOINT_SIZE, | ||
.bDescriptorType = USB_DT_ENDPOINT, | ||
.bEndpointAddress = USB_DIR_IN | 4, // will be overriden | ||
.bmAttributes = | ||
USB_ENDPOINT_XFER_INT | USB_ENDPOINT_SYNC_NONE | USB_ENDPOINT_USAGE_DATA, | ||
.wMaxPacketSize = 8, | ||
.bInterval = 5, | ||
}, | ||
}; | ||
|
||
static __u8 opg_report[] = { | ||
//XY start mode C Z X A B Y | ||
0x88, 0x00, | ||
}; | ||
|
||
static const char* opg_get_string(int idx) { | ||
switch (idx) { | ||
case IDX_MANUFACTURER: | ||
return "TOYOSHIMA-HOUSE"; | ||
case IDX_PRODUCT: | ||
return "OPiPad retro-bit GENERATIONS Adaptor"; | ||
case IDX_SERIAL: | ||
return "0"; | ||
default: | ||
break; | ||
} | ||
return NULL; | ||
} | ||
|
||
static void opg_update_report(void) { | ||
const struct gpio_hid_state* state = gpio_get_state(); | ||
opg_report[0] = | ||
(!state->left ? 0 : !state->right ? 0x0f: 0x08) | | ||
(!state->up ? 0 : !state->down ? 0xf0: 0x80); | ||
opg_report[1] = | ||
(state->x ? 0 : 0x01) | | ||
(state->lt ? 0 : 0x02) | | ||
(state->a ? 0 : 0x04) | | ||
(state->b ? 0 : 0x08) | | ||
(state->y ? 0 : 0x10) | | ||
(state->rt ? 0 : 0x20) | | ||
(state->back ? 0 : 0x40) | | ||
(state->start ? 0 : 0x80); | ||
} | ||
|
||
static int opg_setup( | ||
struct usb_gadget* gadget, const struct usb_ctrlrequest* r) { | ||
struct driver_data* data = get_gadget_data(gadget); | ||
int type = r->bRequestType & USB_TYPE_MASK; | ||
printk("%s: bRequestType: %02x, bRequest: %02x, wValue: %04x, " | ||
"wIndex: %04x, wLendth: %04x\n", | ||
opg_driver_name, r->bRequestType, r->bRequest, r->wValue, r->wIndex, | ||
r->wLength); | ||
if (type == USB_TYPE_CLASS && r->bRequest == HID_REQ_GET_REPORT) { | ||
switch(le16_to_cpu(r->wValue)) { | ||
case 0x0100: | ||
opg_update_report(); | ||
memcpy(data->ep0_request->buf, opg_report, sizeof(opg_report)); | ||
return sizeof(opg_report); | ||
default: | ||
printk("%s: report type/id: %04x\n", opg_driver_name, r->wValue); | ||
break; | ||
} | ||
} | ||
return -EOPNOTSUPP; | ||
} |