00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <stdio.h>
00028 #include <stdbool.h>
00029 #include <stdlib.h>
00030 #include <string.h>
00031 #include <libusb-1.0/libusb.h>
00032 #include "freenect_internal.h"
00033
00034 int fnusb_init(fnusb_ctx *ctx, freenect_usb_context *usb_ctx)
00035 {
00036 int res;
00037 if (!usb_ctx) {
00038 res = libusb_init(&ctx->ctx);
00039 if (res >= 0) {
00040 ctx->should_free_ctx = 1;
00041 return 0;
00042 } else {
00043 ctx->should_free_ctx = 0;
00044 ctx->ctx = NULL;
00045 return res;
00046 }
00047 } else {
00048 ctx->ctx = usb_ctx;
00049 ctx->should_free_ctx = 0;
00050 return 0;
00051 }
00052 }
00053
00055 int
00056 fnusb_shutdown (fnusb_ctx *ctx)
00057 {
00058
00059 if (ctx->should_free_ctx)
00060 {
00061 libusb_exit(ctx->ctx);
00062 ctx->ctx = NULL;
00063 }
00064 return (0);
00065 }
00066
00067 int fnusb_process_events(fnusb_ctx *ctx)
00068 {
00069 return libusb_handle_events(ctx->ctx);
00070 }
00071
00073 int
00074 fnusb_open_subdevices (freenect_device *dev, int index)
00075 {
00076 dev->usb_cam.parent = dev;
00077 dev->usb_motor.parent = dev;
00078
00079 libusb_device **devs;
00080 ssize_t cnt = libusb_get_device_list (dev->parent->usb.ctx, &devs);
00081 if (cnt < 0)
00082 return (-1);
00083
00084 bool start_cam = false, start_motor = false;
00085
00086 int i = 0, nr_cam = 0, nr_mot = 0;
00087 struct libusb_device_descriptor desc;
00088 for (i = 0; i < cnt; ++i)
00089 {
00090 int r = libusb_get_device_descriptor (devs[i], &desc);
00091 if (r < 0)
00092 continue;
00093
00094
00095 if (desc.idVendor == MS_MAGIC_VENDOR && desc.idProduct == MS_MAGIC_CAMERA_PRODUCT && !start_cam)
00096 {
00097
00098 if (nr_cam == index)
00099 {
00100 if (libusb_open (devs[i], &dev->usb_cam.dev) != 0)
00101 return (-1);
00102
00103 if (!dev->usb_cam.dev)
00104 return (-1);
00105 libusb_claim_interface (dev->usb_cam.dev, 0);
00106 start_cam = true;
00107 }
00108 else
00109 nr_cam++;
00110 }
00111
00112
00113 if (desc.idVendor == MS_MAGIC_VENDOR && desc.idProduct == MS_MAGIC_MOTOR_PRODUCT && !start_motor)
00114 {
00115
00116 if (nr_mot == index)
00117 {
00118 if (libusb_open (devs[i], &dev->usb_motor.dev) != 0)
00119 return (-1);
00120
00121 if (!dev->usb_motor.dev)
00122 return (-1);
00123 libusb_claim_interface (dev->usb_motor.dev, 0);
00124 start_motor = true;
00125 }
00126 else
00127 nr_mot++;
00128 }
00129 }
00130
00131 libusb_free_device_list (devs, 1);
00132
00133 if (start_cam && start_motor)
00134 return (0);
00135 else
00136 return (-1);
00137 }
00138
00139 static void iso_callback(struct libusb_transfer *xfer)
00140 {
00141 int i;
00142 fnusb_isoc_stream *strm = xfer->user_data;
00143
00144 if (strm->dead) {
00145 freenect_context *ctx = strm->parent->parent->parent;
00146 strm->dead_xfers++;
00147 FN_SPEW("EP %02x transfer complete, %d left\n", xfer->endpoint, strm->num_xfers - strm->dead_xfers);
00148 return;
00149 }
00150
00151 if(xfer->status == LIBUSB_TRANSFER_COMPLETED) {
00152 uint8_t *buf = (void*)xfer->buffer;
00153 for (i=0; i<strm->pkts; i++) {
00154 strm->cb(strm->parent->parent, buf, xfer->iso_packet_desc[i].actual_length);
00155 buf += strm->len;
00156 }
00157 libusb_submit_transfer(xfer);
00158 } else {
00159 freenect_context *ctx = strm->parent->parent->parent;
00160 FN_WARNING("Isochronous transfer error: %d\n", xfer->status);
00161 strm->dead_xfers++;
00162 }
00163 }
00164
00165 int fnusb_start_iso(fnusb_dev *dev, fnusb_isoc_stream *strm, fnusb_iso_cb cb, int ep, int xfers, int pkts, int len)
00166 {
00167 freenect_context *ctx = dev->parent->parent;
00168 int ret, i;
00169
00170 strm->parent = dev;
00171 strm->cb = cb;
00172 strm->num_xfers = xfers;
00173 strm->pkts = pkts;
00174 strm->len = len;
00175 strm->buffer = malloc(xfers * pkts * len);
00176 strm->xfers = malloc(sizeof(struct libusb_transfer*) * xfers);
00177 strm->dead = 0;
00178 strm->dead_xfers = 0;
00179
00180 uint8_t *bufp = strm->buffer;
00181
00182 for (i=0; i<xfers; i++) {
00183 FN_SPEW("Creating EP %02x transfer #%d\n", ep, i);
00184 strm->xfers[i] = libusb_alloc_transfer(pkts);
00185
00186 libusb_fill_iso_transfer(strm->xfers[i], dev->dev, ep, bufp, pkts * len, pkts, iso_callback, strm, 0);
00187
00188 libusb_set_iso_packet_lengths(strm->xfers[i], len);
00189
00190 ret = libusb_submit_transfer(strm->xfers[i]);
00191 if (ret < 0)
00192 FN_WARNING("Failed to submit isochronous transfer %d: %d\n", i, ret);
00193
00194 bufp += pkts*len;
00195 }
00196
00197 return 0;
00198
00199 }
00200
00201 int fnusb_stop_iso(fnusb_dev *dev, fnusb_isoc_stream *strm)
00202 {
00203 freenect_context *ctx = dev->parent->parent;
00204 int i;
00205
00206 strm->dead = 1;
00207
00208 for (i=0; i<strm->num_xfers; i++)
00209 libusb_cancel_transfer(strm->xfers[i]);
00210
00211 while (strm->dead_xfers < strm->num_xfers) {
00212 libusb_handle_events(ctx->usb.ctx);
00213 }
00214
00215 free(strm->buffer);
00216 free(strm->xfers);
00217
00218 memset(strm, 0, sizeof(*strm));
00219 return 0;
00220 }
00221
00222 int fnusb_control(fnusb_dev *dev, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint8_t *data, uint16_t wLength)
00223 {
00224 return libusb_control_transfer(dev->dev, bmRequestType, bRequest, wValue, wIndex, data, wLength, 0);
00225 }