10 #include <sys/select.h>
14 #include <linux/usbdevice_fs.h>
15 #include <linux/usb/ch9.h>
17 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
20 #include "rawhid/hid.h"
24 static void *dbg_reader(void *arg)
32 ret = rawhid_recv(0, buf, 64, 1000);
37 printf("\nrawhid_recv(dbg): %d\n", ret);
56 /* return 1 if founf, 0 if not, < 0 on error */
57 static int find_device(struct teensy_dev *dev,
58 uint16_t vendor, uint16_t product)
60 const char path_root[] = "/dev/bus/usb";
62 struct usb_descriptor_header hdr;
63 struct usb_device_descriptor d;
64 struct usb_config_descriptor c;
65 struct usb_interface_descriptor i;
66 struct usb_endpoint_descriptor e;
67 char space[0x100]; /* enough? */
69 char path_bus[256], path_dev[256];
70 struct dirent *ent, *ent_bus;
71 DIR *dir = NULL, *dir_bus = NULL;
77 memset(dev, 0xff, sizeof(*dev));
79 dir = opendir(path_root);
85 for (ent = readdir(dir); ent != NULL; ent = readdir(dir)) {
86 /* should be a number like 000 */
87 if (sscanf(ent->d_name, "%03d", &num) != 1)
90 snprintf(path_bus, sizeof(path_bus), "%s/%s",
91 path_root, ent->d_name);
93 dir_bus = opendir(path_bus);
97 ent_bus = readdir(dir_bus);
98 for (; ent_bus != NULL; ent_bus = readdir(dir_bus)) {
99 if (sscanf(ent->d_name, "%03d", &num) != 1)
102 snprintf(path_dev, sizeof(path_dev), "%s/%s/%s",
103 path_root, ent->d_name, ent_bus->d_name);
105 fd = open(path_dev, O_RDWR);
109 ret = read(fd, &desc.d, sizeof(desc.d));
110 if (ret != sizeof(desc.d)) {
111 fprintf(stderr, "desc read: %d/%zd: ", ret, sizeof(desc.d));
116 if (desc.d.bDescriptorType != USB_DT_DEVICE) {
117 fprintf(stderr, "%s: bad DT: 0x%02x\n",
118 path_dev, desc.d.bDescriptorType);
122 if (desc.d.idVendor == vendor && desc.d.idProduct == product)
139 if (desc.d.bNumConfigurations != 1) {
140 fprintf(stderr, "unexpected bNumConfigurations: %u\n",
141 desc.d.bNumConfigurations);
145 /* walk through all descriptors */
148 ret = read(fd, &desc.hdr, sizeof(desc.hdr));
151 if (ret != sizeof(desc.hdr)) {
152 fprintf(stderr, "desc.hdr read: %d/%zd: ", ret, sizeof(desc.hdr));
157 ret = (int)lseek(fd, -sizeof(desc.hdr), SEEK_CUR);
163 ret = read(fd, &desc, desc.hdr.bLength);
164 if (ret != desc.hdr.bLength) {
165 fprintf(stderr, "desc read: %d/%u: ", ret, desc.hdr.bLength);
170 switch (desc.hdr.bDescriptorType) {
172 if (desc.c.bNumInterfaces != 2) {
173 fprintf(stderr, "unexpected bNumInterfaces: %u\n",
174 desc.c.bNumInterfaces);
179 case USB_DT_INTERFACE:
180 if (desc.i.bInterfaceClass != USB_CLASS_HID
181 || desc.i.bInterfaceSubClass != 0
182 || desc.i.bInterfaceProtocol != 0) {
183 fprintf(stderr, "unexpected interface %x:%x:%x\n",
184 desc.i.bInterfaceClass, desc.i.bInterfaceSubClass,
185 desc.i.bInterfaceProtocol);
188 if (desc.i.bNumEndpoints != 2) {
189 fprintf(stderr, "unexpected bNumEndpoints: %u\n",
190 desc.i.bNumEndpoints);
196 case USB_DT_ENDPOINT:
197 if (iface < 0 || iface >= ARRAY_SIZE(dev->ifaces)) {
198 fprintf(stderr, "bad iface: %d\n", iface);
201 if (desc.e.wMaxPacketSize != 64 && desc.e.wMaxPacketSize != 32) {
202 fprintf(stderr, "iface %d, EP %02x: "
203 "unexpected wMaxPacketSize: %u\n",
204 iface, desc.e.bEndpointAddress, desc.e.wMaxPacketSize);
207 if (desc.e.bEndpointAddress & 0x80)
208 dev->ifaces[iface].ep_in = desc.e.bEndpointAddress; // & 0x7F;
210 dev->ifaces[iface].ep_out = desc.e.bEndpointAddress;
218 fprintf(stderr, "skipping desc 0x%02x\n",
219 desc.hdr.bDescriptorType);
224 /* claim interfaces */
225 for (iface = 0; iface < ARRAY_SIZE(dev->ifaces); iface++) {
226 struct usbdevfs_ioctl usbio;
228 if (dev->ifaces[iface].ep_in == -1) {
229 fprintf(stderr, "missing ep_in, iface: %d\n", iface);
232 if (dev->ifaces[iface].ep_out == -1) {
233 fprintf(stderr, "missing ep_out, iface: %d\n", iface);
237 /* disconnect default driver */
238 memset(&usbio, 0, sizeof(usbio));
240 usbio.ioctl_code = USBDEVFS_DISCONNECT;
241 ret = ioctl(fd, USBDEVFS_IOCTL, &usbio);
242 if (ret != 0 && errno != ENODATA)
243 perror("USBDEVFS_DISCONNECT");
245 ret = ioctl(fd, USBDEVFS_CLAIMINTERFACE, &iface);
247 perror("USBDEVFS_CLAIMINTERFACE");
272 int main(int argc, char *argv[])
274 struct teensy_dev dev;
275 struct usbdevfs_urb urb[URB_CNT];
276 struct usbdevfs_urb *reaped_urb;
277 char buf_dbg[64 + 1], buf_in[64];
280 int data_in_sent = 0;
289 ret = find_device(&dev, 0x16C0, 0x0486);
295 printf("waiting for device..\n");
308 memset(&urb[URB_DATA_IN], 0, sizeof(urb[URB_DATA_IN]));
309 urb[URB_DATA_IN].type = USBDEVFS_URB_TYPE_INTERRUPT;
310 urb[URB_DATA_IN].endpoint = dev.ifaces[0].ep_in;
311 urb[URB_DATA_IN].buffer = buf_in;
312 urb[URB_DATA_IN].buffer_length = sizeof(buf_in);
314 ret = ioctl(dev.fd, USBDEVFS_SUBMITURB, &urb[URB_DATA_IN]);
316 perror("USBDEVFS_SUBMITURB URB_DATA_IN");
322 memset(&urb[URB_DBG_IN], 0, sizeof(urb[URB_DBG_IN]));
323 urb[URB_DBG_IN].type = USBDEVFS_URB_TYPE_INTERRUPT;
324 urb[URB_DBG_IN].endpoint = dev.ifaces[1].ep_in;
325 urb[URB_DBG_IN].buffer = buf_dbg;
326 urb[URB_DBG_IN].buffer_length = sizeof(buf_dbg) - 1;
328 ret = ioctl(dev.fd, USBDEVFS_SUBMITURB, &urb[URB_DBG_IN]);
330 perror("USBDEVFS_SUBMITURB URB_DBG_IN");
337 FD_SET(dev.fd, &wfds);
339 ret = select(dev.fd + 1, NULL, &wfds, NULL, NULL);
345 if (FD_ISSET(dev.fd, &wfds)) {
347 ret = ioctl(dev.fd, USBDEVFS_REAPURB, &reaped_urb);
351 perror("USBDEVFS_REAPURB");
355 if (reaped_urb != NULL && reaped_urb->status != 0) {
356 errno = -reaped_urb->status;
357 perror("urb status");
358 if (reaped_urb->status == -EILSEQ) {
359 /* this is usually a sign of disconnect.. */
365 if (reaped_urb == &urb[URB_DATA_IN]) {
369 else if (reaped_urb == &urb[URB_DBG_IN]) {
371 buf_dbg[reaped_urb->actual_length] = 0;
372 printf("%s", buf_dbg);
376 fprintf(stderr, "reaped unknown urb? %p\n", reaped_urb);
387 ret = rawhid_open(1, 0x16C0, 0x0486, 0xFFC9, 0x0004);
389 fprintf(stderr, "dbg rawhid is missing\n");
393 ret = rawhid_open(1, 0x16C0, 0x0486, 0xFFAB, 0x0200);
395 fprintf(stderr, "data rawhid is missing\n");
400 ret = pthread_create(&thread, NULL, dbg_reader, NULL);
402 fprintf(stderr, "pthread_create failed: %d\n", ret);
406 memset(buf, 0, sizeof(buf));
407 snprintf(buf, sizeof(buf), "hi");
409 ret = rawhid_send(1, buf, 64, 220);
411 fprintf(stderr, "send failed: %d\n", ret);
415 // check if any Raw HID packet has arrived
416 ret = rawhid_recv(1, buf, 64, 220);
418 fprintf(stderr, "\nrawhid_recv(1): %d\n", ret);
422 printf("\nrecv %d bytes:\n", ret);
423 for (i=0; i<ret; i++) {
424 printf("%02X ", buf[i] & 255);
425 if (i % 16 == 15 && i < ret-1) printf("\n");
434 pthread_join(thread, NULL);
440 // vim: ts=2:sw=2:expandtab