Acquiring Images from a USB mouse (Single Chip, ADNS-2700) via pyusb

libusb, python, pyusb, usb

Solution

You probably need to do ctrl_transfer() as shown in pyUSB tutorial.

You will also need to convert hex bytes from the datasheet into individual parameters to ctrl_transfer. See this page for the format.

`Get_Vendor_Test` `C0 01 00 00 xx 00 01 00` can be issued with ctrl_transfer() call like this:

ret = dev.ctrl_transfer(bmRequestType=0xc0, # byte[0]
                        bRequest=0x01,      # byte[1]
                        wValue=0x0000,      # byte[2,3]
                        wIndex=register,    # byte[4,5]
                        data_or_wLength = 1)# byte[6,7]

Problem

I would like to extract the actual images captured by a single chip optical mouse sensor, specifically the ADNS-2700. As apposed to the various other tutorials on the internet that use a micro controller to talk to the SPI interface of the imaging chip (like this), the chip I am trying to work with has a USB interface integrated. ADNS-2700 Datasheet System: Windows 7, Python2.7, PyUSB 1.0 I have successfully extracted the button presses, velocity, and scroll wheel following this example: ``` import usb.core import usb.util VENDOR_ID = 6447 PRODUCT_ID = 2326 # find the USB device device = usb.core.find(idVendor=VENDOR_ID, idProduct=PRODUCT_ID) # use the first/default configuration device.set_configuration() # first endpoint endpoint = device[0][(0,0)][0] # read a data packet attempts = 10 data = None while attempts > 0: try: data = device.read(endpoint.bEndpointAddress, endpoint.wMaxPacketSize) print data except usb.core.USBError as e: data = None if e.args == ('Operation timed out',): attempts -= 1 continue ``` Which extracts data like: ``` array('B', [0, 0, 16, 0, 0]) array('B', [0, 0, 240, 255, 0]) array('B', [0, 0, 16, 0, 0]) array('B', [0, 0, 240, 255, 0]) ``` I need help extracting the raw image data! I am a USB noob which is probably causing most of the problem. On page 18 of the datasheet, there is a list of USB commands. The one that looks promising is: ``` Mnemonic Command Notes --------------------------------------------------------------- Get_Vendor_Test C0 01 00 00 xx 00 01 00 Read register xx ``` Then on page 28, there is a list of registers of which this looks promising: ``` Address Register Name Register Type Access Reset Value ---------------------------------------------------------------------- 0x0D PIX_GRAB Device Read only 0x00 ``` However, I have tried: ``` device.write(endpoint.bEndpointAddress,'C0:01:00:00:0A:00:01:00',0) ``` which results in a: ``` usb.core.USBError: [Errno None] libusb0-dll:err [_usb_setup_async] invalid endpoint 0x81 ``` as well as: ``` device.read(endpoint.bEndpointAddress, 0x0D) ``` which simply times out. Complete Solution: ``` import usb.core import usb.util import matplotlib.pyplot as plt import numpy as np VENDOR_ID = 6447 PRODUCT_ID = 2326 # find the USB device device = usb.core.find(idVendor=VENDOR_ID, idProduct=PRODUCT_ID) # use the first/default configuration device.set_configuration() # In order to read the pixel bytes, reset PIX_GRAB by sending a write command response = self.device.ctrl_transfer(bmRequestType = 0x40, #Write bRequest = 0x01, wValue = 0x0000, wIndex = 0x0D, #PIX_GRAB register value data_or_wLength = None ) # Read all the pixels (360 in this chip) pixList = [] for i in range(361): response = self.device.ctrl_transfer(bmRequestType = 0xC0, #Read bRequest = 0x01, wValue = 0x0000, wIndex = 0x0D, #PIX_GRAB register value data_or_wLength = 1 ) pixList.append(response) pixelArray = np.asarray(pixList) pixelArray = pixelArray.reshape((19,19)) plt.imshow(pixelArray) plt.show() ```

Original source