Skip to content

Commit 0010cad

Browse files
committed
Add support for examining camera serial numbers and opening devices by camera serial number.
Since the index used in freenect_open_device() is nondeterministic, this makes it possible to make one particular piece of hardware the "left Kinect" or the "right Kinect" in a multi-Kinect setup. Signed-off-by: Drew Fisher <[email protected]>
1 parent b270518 commit 0010cad

File tree

4 files changed

+147
-0
lines changed

4 files changed

+147
-0
lines changed

include/libfreenect.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,15 @@ typedef enum {
4646
FREENECT_DEVICE_AUDIO = 0x04,
4747
} freenect_device_flags;
4848

49+
/// A struct used in enumeration to give access to serial numbers, so you can
50+
/// open a particular device by serial rather than depending on index. This
51+
/// is most useful if you have more than one Kinect.
52+
struct freenect_device_attributes;
53+
struct freenect_device_attributes {
54+
struct freenect_device_attributes *next; /**< Next device in the linked list */
55+
const char* camera_serial; /**< Serial number of this device's camera subdevice */
56+
};
57+
4958
/// Enumeration of available resolutions.
5059
/// Not all available resolutions are actually supported for all video formats.
5160
/// Frame modes may not perfectly match resolutions. For instance,
@@ -232,6 +241,25 @@ FREENECTAPI int freenect_process_events(freenect_context *ctx);
232241
*/
233242
FREENECTAPI int freenect_num_devices(freenect_context *ctx);
234243

244+
/**
245+
* Scans for kinect devices and produces a linked list of their attributes
246+
* (namely, serial numbers), returning the number of devices.
247+
*
248+
* @param ctx Context to scan for kinect devices with
249+
* @param attribute_list Pointer to where this function will store the resultant linked list
250+
*
251+
* @return Number of devices connected, < 0 on error
252+
*/
253+
FREENECTAPI int freenect_list_device_attributes(freenect_context *ctx, struct freenect_device_attributes** attribute_list);
254+
255+
/**
256+
* Free the linked list produced by freenect_list_device_attributes().
257+
*
258+
* @param ctx Context from which the list was allocated
259+
* @param attribute_list Linked list of attributes to free.
260+
*/
261+
FREENECTAPI void freenect_free_device_attributes(struct freenect_device_attributes* attribute_list);
262+
235263
/**
236264
* Set which subdevices any subsequent calls to freenect_open_device()
237265
* should open. This will not affect devices which have already been
@@ -257,6 +285,19 @@ FREENECTAPI void freenect_select_subdevices(freenect_context *ctx, freenect_devi
257285
*/
258286
FREENECTAPI int freenect_open_device(freenect_context *ctx, freenect_device **dev, int index);
259287

288+
/**
289+
* Opens a kinect device (via a context) associated with a particular camera
290+
* subdevice serial number. This function will fail if no device with a
291+
* matching serial number is found.
292+
*
293+
* @param ctx Context to open device through
294+
* @param dev Device structure to assign opened device to
295+
* @param camera_serial Null-terminated ASCII string containing the serial number of the camera subdevice in the device to open
296+
*
297+
* @return 0 on success, < 0 on error
298+
*/
299+
FREENECTAPI int freenect_open_device_by_camera_serial(freenect_context *ctx, freenect_device **dev, const char* camera_serial);
300+
260301
/**
261302
* Closes a device that is currently open
262303
*

src/core.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,27 @@ FREENECTAPI int freenect_num_devices(freenect_context *ctx)
7777
return fnusb_num_devices(&ctx->usb);
7878
}
7979

80+
FREENECTAPI int freenect_list_device_attributes(freenect_context *ctx, struct freenect_device_attributes **attribute_list)
81+
{
82+
return fnusb_list_device_attributes(&ctx->usb, attribute_list);
83+
}
84+
85+
FREENECTAPI void freenect_free_device_attributes(struct freenect_device_attributes *attribute_list)
86+
{
87+
// Iterate over list, freeing contents of each item as we go.
88+
struct freenect_device_attributes* to_free;
89+
while(attribute_list != NULL) {
90+
to_free = attribute_list;
91+
if (attribute_list->camera_serial != NULL) {
92+
free((char*)attribute_list->camera_serial);
93+
attribute_list->camera_serial = NULL;
94+
}
95+
attribute_list = attribute_list->next;
96+
free(to_free);
97+
}
98+
return;
99+
}
100+
80101
FREENECTAPI void freenect_select_subdevices(freenect_context *ctx, freenect_device_flags subdevs) {
81102
ctx->enabled_subdevices = (freenect_device_flags)(subdevs & (FREENECT_DEVICE_MOTOR | FREENECT_DEVICE_CAMERA
82103
#ifdef BUILD_AUDIO
@@ -123,6 +144,30 @@ FREENECTAPI int freenect_open_device(freenect_context *ctx, freenect_device **de
123144
return 0;
124145
}
125146

147+
FREENECTAPI int freenect_open_device_by_camera_serial(freenect_context *ctx, freenect_device **dev, const char* camera_serial)
148+
{
149+
// This is implemented by listing the devices and seeing which index (if
150+
// any) has a camera with a matching serial number, and then punting to
151+
// freenect_open_device with that index.
152+
struct freenect_device_attributes* attrlist;
153+
struct freenect_device_attributes* item;
154+
int count = fnusb_list_device_attributes(&ctx->usb, &attrlist);
155+
if (count < 0) {
156+
FN_ERROR("freenect_open_device_by_camera_serial: Couldn't enumerate serial numbers\n");
157+
return -1;
158+
}
159+
int index = 0;
160+
for(item = attrlist ; item != NULL; item = item->next , index++) {
161+
if (strlen(item->camera_serial) == strlen(camera_serial) && strcmp(item->camera_serial, camera_serial) == 0) {
162+
freenect_free_device_attributes(attrlist);
163+
return freenect_open_device(ctx, dev, index);
164+
}
165+
}
166+
freenect_free_device_attributes(attrlist);
167+
FN_ERROR("freenect_open_device_by_camera_serial: Couldn't find a device with serial %s\n", camera_serial);
168+
return -1;
169+
}
170+
126171
FREENECTAPI int freenect_close_device(freenect_device *dev)
127172
{
128173
freenect_context *ctx = dev->parent;

src/usb_libusb10.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,66 @@ int fnusb_num_devices(fnusb_ctx *ctx)
5656
return nr;
5757
}
5858

59+
int fnusb_list_device_attributes(fnusb_ctx *ctx, struct freenect_device_attributes** attribute_list)
60+
{
61+
*attribute_list = NULL; // initialize some return value in case the user is careless.
62+
libusb_device **devs;
63+
//pointer to pointer of device, used to retrieve a list of devices
64+
ssize_t count = libusb_get_device_list (ctx->ctx, &devs);
65+
if (count < 0)
66+
return -1;
67+
68+
struct freenect_device_attributes** camera_prev_next = attribute_list;
69+
70+
// Pass over the list. For each camera seen, if we already have a camera
71+
// for the newest_camera device, allocate a new one and append it to the list,
72+
// incrementing num_devs. Likewise for each audio device.
73+
struct libusb_device_descriptor desc;
74+
int num_cams = 0;
75+
int i;
76+
for (i = 0; i < count; i++) {
77+
int r = libusb_get_device_descriptor (devs[i], &desc);
78+
if (r < 0)
79+
continue;
80+
if (desc.idVendor == VID_MICROSOFT && desc.idProduct == PID_NUI_CAMERA) {
81+
// Verify that a serial number exists to query. If not, don't touch the device.
82+
if (desc.iSerialNumber == 0) {
83+
continue;
84+
}
85+
86+
// Open device.
87+
int res;
88+
libusb_device_handle *this_device;
89+
res = libusb_open(devs[i], &this_device);
90+
unsigned char string_desc[256]; // String descriptors are at most 256 bytes.
91+
if (res != 0) {
92+
continue;
93+
}
94+
95+
// Read string descriptor referring to serial number.
96+
res = libusb_get_string_descriptor_ascii(this_device, desc.iSerialNumber, string_desc, 256);
97+
libusb_close(this_device);
98+
if (res < 0) {
99+
continue;
100+
}
101+
102+
// Add item to linked list.
103+
struct freenect_device_attributes* new_dev_attrs = (struct freenect_device_attributes*)malloc(sizeof(struct freenect_device_attributes));
104+
memset(new_dev_attrs, 0, sizeof(*new_dev_attrs));
105+
106+
*camera_prev_next = new_dev_attrs;
107+
// Copy string with serial number
108+
new_dev_attrs->camera_serial = strdup((char*)string_desc);
109+
camera_prev_next = &(new_dev_attrs->next);
110+
// Increment number of cameras found
111+
num_cams++;
112+
}
113+
}
114+
115+
libusb_free_device_list(devs, 1);
116+
return num_cams;
117+
}
118+
59119
int fnusb_init(fnusb_ctx *ctx, freenect_usb_context *usb_ctx)
60120
{
61121
int res;

src/usb_libusb10.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ typedef struct {
8484
} fnusb_isoc_stream;
8585

8686
int fnusb_num_devices(fnusb_ctx *ctx);
87+
int fnusb_list_device_attributes(fnusb_ctx *ctx, struct freenect_device_attributes** attribute_list);
8788

8889
int fnusb_init(fnusb_ctx *ctx, freenect_usb_context *usb_ctx);
8990
int fnusb_shutdown(fnusb_ctx *ctx);

0 commit comments

Comments
 (0)