18f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown/* 28f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * Copyright (C) 2013 The Android Open Source Project 38f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * 48f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 58f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * you may not use this file except in compliance with the License. 68f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * You may obtain a copy of the License at 78f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * 88f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * http://www.apache.org/licenses/LICENSE-2.0 98f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * 108f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * Unless required by applicable law or agreed to in writing, software 118f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 128f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * See the License for the specific language governing permissions and 148f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * limitations under the License. 158f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown */ 168f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 178f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownpackage com.android.accessorydisplay.sink; 188f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 198f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownimport java.nio.ByteBuffer; 208f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 218f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown/** 228f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * Helper for creating USB HID descriptors and reports. 238f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown */ 248f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownfinal class UsbHid { 258f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown private UsbHid() { 268f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 278f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 288f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown /** 298f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * Generates basic Windows 7 compatible HID multitouch descriptors and reports 308f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * that should be supported by recent versions of the Linux hid-multitouch driver. 318f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown */ 328f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown public static final class Multitouch { 338f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown private final int mReportId; 348f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown private final int mMaxContacts; 358f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown private final int mWidth; 368f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown private final int mHeight; 378f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 388f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown public Multitouch(int reportId, int maxContacts, int width, int height) { 398f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mReportId = reportId; 408f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mMaxContacts = maxContacts; 418f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mWidth = width; 428f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mHeight = height; 438f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 448f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 458f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown public void generateDescriptor(ByteBuffer buffer) { 468f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown buffer.put(new byte[] { 478f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 0x05, 0x0d, // USAGE_PAGE (Digitizers) 488f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 0x09, 0x04, // USAGE (Touch Screen) 498f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown (byte)0xa1, 0x01, // COLLECTION (Application) 508f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown (byte)0x85, (byte)mReportId, // REPORT_ID (Touch) 518f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 0x09, 0x22, // USAGE (Finger) 528f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown (byte)0xa1, 0x00, // COLLECTION (Physical) 538f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 0x09, 0x55, // USAGE (Contact Count Maximum) 548f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 0x15, 0x00, // LOGICAL_MINIMUM (0) 558f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 0x25, (byte)mMaxContacts, // LOGICAL_MAXIMUM (...) 568f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 0x75, 0x08, // REPORT_SIZE (8) 578f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown (byte)0x95, 0x01, // REPORT_COUNT (1) 588f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown (byte)0xb1, (byte)mMaxContacts, // FEATURE (Data,Var,Abs) 598f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 0x09, 0x54, // USAGE (Contact Count) 608f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown (byte)0x81, 0x02, // INPUT (Data,Var,Abs) 618f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown }); 628f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown byte maxXLsb = (byte)(mWidth - 1); 638f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown byte maxXMsb = (byte)((mWidth - 1) >> 8); 648f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown byte maxYLsb = (byte)(mHeight - 1); 658f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown byte maxYMsb = (byte)((mHeight - 1) >> 8); 668f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown byte[] collection = new byte[] { 678f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 0x05, 0x0d, // USAGE_PAGE (Digitizers) 688f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 0x09, 0x22, // USAGE (Finger) 698f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown (byte)0xa1, 0x02, // COLLECTION (Logical) 708f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 0x09, 0x42, // USAGE (Tip Switch) 718f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 0x15, 0x00, // LOGICAL_MINIMUM (0) 728f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 0x25, 0x01, // LOGICAL_MAXIMUM (1) 738f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 0x75, 0x01, // REPORT_SIZE (1) 748f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown (byte)0x81, 0x02, // INPUT (Data,Var,Abs) 758f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 0x09, 0x32, // USAGE (In Range) 768f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown (byte)0x81, 0x02, // INPUT (Data,Var,Abs) 778f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 0x09, 0x51, // USAGE (Contact Identifier) 788f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 0x25, 0x3f, // LOGICAL_MAXIMUM (63) 798f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 0x75, 0x06, // REPORT_SIZE (6) 808f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown (byte)0x81, 0x02, // INPUT (Data,Var,Abs) 818f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 828f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 0x09, 0x30, // USAGE (X) 838f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 0x26, maxXLsb, maxXMsb, // LOGICAL_MAXIMUM (...) 848f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 0x75, 0x10, // REPORT_SIZE (16) 858f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown (byte)0x81, 0x02, // INPUT (Data,Var,Abs) 868f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 0x09, 0x31, // USAGE (Y) 878f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 0x26, maxYLsb, maxYMsb, // LOGICAL_MAXIMUM (...) 888f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown (byte)0x81, 0x02, // INPUT (Data,Var,Abs) 898f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown (byte)0xc0, // END_COLLECTION 908f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown }; 918f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown for (int i = 0; i < mMaxContacts; i++) { 928f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown buffer.put(collection); 938f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 948f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown buffer.put(new byte[] { 958f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown (byte)0xc0, // END_COLLECTION 968f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown (byte)0xc0, // END_COLLECTION 978f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown }); 988f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 998f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 1008f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown public void generateReport(ByteBuffer buffer, Contact[] contacts, int contactCount) { 1018f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown // Report Id 1028f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown buffer.put((byte)mReportId); 1038f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown // Contact Count 1048f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown buffer.put((byte)contactCount); 1058f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 1068f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown for (int i = 0; i < contactCount; i++) { 1078f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown final Contact contact = contacts[i]; 1088f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown // Tip Switch, In Range, Contact Identifier 1098f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown buffer.put((byte)((contact.id << 2) | 0x03)); 1108f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown // X 1118f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown buffer.put((byte)contact.x).put((byte)(contact.x >> 8)); 1128f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown // Y 1138f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown buffer.put((byte)contact.y).put((byte)(contact.y >> 8)); 1148f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1158f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown for (int i = contactCount; i < mMaxContacts; i++) { 1168f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown buffer.put((byte)0).put((byte)0).put((byte)0).put((byte)0).put((byte)0); 1178f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1188f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1198f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 1208f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown public int getReportSize() { 1218f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown return 2 + mMaxContacts * 5; 1228f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1238f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 1248f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown public static final class Contact { 1258f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown public int id; // range 0..63 1268f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown public int x; 1278f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown public int y; 1288f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1298f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1308f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown} 131