@@ -151,6 +151,62 @@ FN_INTERNAL libusb_device * fnusb_find_sibling_device(freenect_context* ctx, lib
151151 return NULL ;
152152}
153153
154+ FN_INTERNAL char * usb_get_serial (freenect_context * ctx , libusb_device * device , libusb_device_handle * handle , struct libusb_device_descriptor * desc )
155+ {
156+ if (ctx == NULL ) return NULL ;
157+
158+ if (device == NULL ) {
159+ if (handle == NULL ) {
160+ FN_WARNING ("No handle or device for serial\n" );
161+ return NULL ;
162+ }
163+ device = libusb_get_device (handle ); // no need to free or unref
164+ }
165+
166+ int res = 0 ;
167+ struct libusb_device_descriptor localDesc ;
168+
169+ if (desc == NULL ) {
170+ res = libusb_get_device_descriptor (device , & localDesc );
171+ if (res != 0 ) {
172+ FN_WARNING ("Failed to get serial descriptor: %s\n" , libusb_error_name (res ));
173+ return NULL ;
174+ }
175+ desc = & localDesc ;
176+ }
177+
178+ // Verify that a serial number exists to query. If not, don't touch the device.
179+ if (desc -> iSerialNumber == 0 ) {
180+ FN_WARNING ("Device has no serial number\n" );
181+ return NULL ;
182+ }
183+
184+ libusb_device_handle * localHandle = NULL ;
185+
186+ if (handle == NULL ) {
187+ res = libusb_open (device , & localHandle );
188+ if (res != 0 ) {
189+ FN_WARNING ("Failed to open device for serial: %s\n" , libusb_error_name (res ));
190+ return NULL ;
191+ }
192+ handle = localHandle ;
193+ }
194+
195+ unsigned char serial [256 ]; // String descriptors are at most 256 bytes.
196+ res = libusb_get_string_descriptor_ascii (handle , desc -> iSerialNumber , serial , sizeof (serial ));
197+
198+ if (localHandle != NULL ) {
199+ libusb_close (localHandle );
200+ }
201+
202+ if (res < 0 ) {
203+ FN_WARNING ("Failed to get serial: %s\n" , libusb_error_name (res ));
204+ return NULL ;
205+ }
206+
207+ return strndup ((const char * )serial , sizeof (serial ));
208+ }
209+
154210FN_INTERNAL int fnusb_list_device_attributes (freenect_context * ctx , struct freenect_device_attributes * * attribute_list )
155211{
156212 * attribute_list = NULL ; // initialize some return value in case the user is careless.
@@ -161,6 +217,7 @@ FN_INTERNAL int fnusb_list_device_attributes(freenect_context *ctx, struct freen
161217 return (count >= INT_MIN ) ? (int )count : -1 ;
162218 }
163219
220+ int res = 0 ;
164221 struct freenect_device_attributes * * next_attr = attribute_list ;
165222
166223 // Pass over the list. For each camera seen, if we already have a camera
@@ -173,79 +230,44 @@ FN_INTERNAL int fnusb_list_device_attributes(freenect_context *ctx, struct freen
173230 libusb_device * camera_device = devs [i ];
174231
175232 struct libusb_device_descriptor desc ;
176- int res = libusb_get_device_descriptor (camera_device , & desc );
177- if (res < 0 )
178- {
233+ res = libusb_get_device_descriptor (camera_device , & desc );
234+ if (res < 0 ) {
179235 continue ;
180236 }
181237
182- if (desc .idVendor == VID_MICROSOFT && (desc .idProduct == PID_NUI_CAMERA || desc .idProduct == PID_K4W_CAMERA ))
183- {
184- // Verify that a serial number exists to query. If not, don't touch the device.
185- if (desc .iSerialNumber == 0 )
186- {
187- continue ;
188- }
189-
190- libusb_device_handle * camera_handle ;
191- res = libusb_open (camera_device , & camera_handle );
192- if (res != 0 )
193- {
194- continue ;
195- }
238+ if (!fnusb_is_camera (desc )) {
239+ continue ;
240+ }
196241
197- // Read string descriptor referring to serial number.
198- unsigned char serial [256 ]; // String descriptors are at most 256 bytes.
199- res = libusb_get_string_descriptor_ascii (camera_handle , desc .iSerialNumber , serial , 256 );
200- libusb_close (camera_handle );
201- if (res < 0 )
202- {
203- continue ;
204- }
242+ char * serial = usb_get_serial (ctx , camera_device , NULL , & desc );
205243
206- // K4W and 1473 don't provide a camera serial; use audio serial instead.
207- const char * const K4W_1473_SERIAL = "0000000000000000" ;
208- if (strncmp ((const char * )serial , K4W_1473_SERIAL , 16 ) == 0 )
244+ // K4W and 1473 don't provide a camera serial; use audio serial instead.
245+ const char * const K4W_1473_SERIAL = "0000000000000000" ;
246+ if (serial == NULL || strncmp ((const char * )serial , K4W_1473_SERIAL , 16 ) == 0 )
247+ {
248+ libusb_device * audio_device = fnusb_find_sibling_device (ctx , camera_device , devs , count , & fnusb_is_audio );
249+ if (audio_device != NULL )
209250 {
210- libusb_device * audio_device = fnusb_find_sibling_device (ctx , camera_device , devs , count , & fnusb_is_audio );
211- if (audio_device != NULL )
212- {
213- struct libusb_device_descriptor audio_desc ;
214- res = libusb_get_device_descriptor (audio_device , & audio_desc );
215- if (res != 0 )
216- {
217- FN_WARNING ("Failed to get audio serial descriptors of K4W or 1473 device: %s\n" , libusb_error_name (res ));
218- }
219- else
220- {
221- libusb_device_handle * audio_handle = NULL ;
222- res = libusb_open (audio_device , & audio_handle );
223- if (res != 0 )
224- {
225- FN_WARNING ("Failed to open audio device for serial of K4W or 1473 device: %s\n" , libusb_error_name (res ));
226- }
227- else
228- {
229- res = libusb_get_string_descriptor_ascii (audio_handle , audio_desc .iSerialNumber , serial , 256 );
230- libusb_close (audio_handle );
231- if (res <= 0 )
232- {
233- FN_WARNING ("Failed to get audio serial of K4W or 1473 device: %s\n" , libusb_error_name (res ));
234- }
235- }
236- }
251+ char * audio_serial = usb_get_serial (ctx , audio_device , NULL , & desc );
252+ if (audio_serial ) {
253+ free (serial );
254+ serial = audio_serial ;
237255 }
238256 }
257+ }
239258
240- // Add item to linked list.
241- struct freenect_device_attributes * current_attr = (struct freenect_device_attributes * )malloc (sizeof (struct freenect_device_attributes ));
242- memset (current_attr , 0 , sizeof (* current_attr ));
243-
244- current_attr -> camera_serial = strdup ((char * )serial );
245- * next_attr = current_attr ;
246- next_attr = & (current_attr -> next );
247- num_cams ++ ;
259+ if (serial == NULL ) {
260+ continue ;
248261 }
262+
263+ // Add item to linked list.
264+ struct freenect_device_attributes * current_attr = (struct freenect_device_attributes * )malloc (sizeof (struct freenect_device_attributes ));
265+ memset (current_attr , 0 , sizeof (* current_attr ));
266+
267+ current_attr -> camera_serial = serial ;
268+ * next_attr = current_attr ;
269+ next_attr = & (current_attr -> next );
270+ num_cams ++ ;
249271 }
250272
251273 libusb_free_device_list (devs , 1 );
0 commit comments