Changeset e017851 in thomson for elec/CrO2/software/device.cpp
- Timestamp:
- Jan 14, 2013, 11:05:27 PM (11 years ago)
- Branches:
- main
- Children:
- 6bd7144
- Parents:
- 4a558d7
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
elec/CrO2/software/device.cpp
r4a558d7 re017851 1 1 /* CrO2 datassette emulator 2 * Copyright 201 2, Adrien Destugues <pulkomandy@pulkomandy.ath.cx>2 * Copyright 2013, Adrien Destugues <pulkomandy@pulkomandy.tk> 3 3 * 4 4 * Distributed under the terms of the MIT licence. 5 5 * 6 * H andles device communication through libusb6 * High-level device management functions shared by all implementations. 7 7 */ 8 8 9 9 #include "device.h" 10 10 #include "k5.h" 11 #include "Tape.h" 11 12 12 13 #include <typeinfo> 14 #include <unistd.h> 15 13 16 14 17 bool Device::initOnce = false; … … 17 20 const uint32_t Device::vid = 0x16C0; 18 21 const uint32_t Device::pid = 0x05DC; 19 const char* Device::vendor = "pulkomandy.ath.cx"; 22 const char* Device::vendor = "pulkomandy.ath.cx"; // FIXME update 20 23 const char* Device::product = "CrO2"; 21 22 /* These are the vendor specific commands implemented by our USB device */23 #define PSCMD_CONFIG 024 #define PSCMD_GET 125 #define PSCMD_PUT 226 #define PSCMD_STATUS 327 28 29 // Gets the device instance. Throws an error message if something bad happens.30 Device& Device::getDevice() throw(const char*)31 {32 // If Device constructor throws an exception, instance is not initialized.33 // So, the constructor will be called again at next getDevice call, until34 // it succeeds.35 if (instance == NULL)36 instance = new Device();37 38 return *instance;39 }40 41 42 /* USB device lookup by VID and PID, then Vendor and Product strings, as we use43 * V-USB shared ID. */44 static int usbGetStringAscii(usb_dev_handle *dev, int index, int langid,45 char *buf, int buflen)46 {47 char buffer[256];48 int rval, i;49 50 if((rval = usb_control_msg(dev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR,51 (USB_DT_STRING << 8) + index, langid, buffer, sizeof(buffer), 1000)) < 0)52 return rval;53 if(buffer[1] != USB_DT_STRING)54 return 0;55 if((unsigned char)buffer[0] < rval)56 rval = (unsigned char)buffer[0];57 rval /= 2;58 /* lossy conversion to ISO Latin1 */59 for(i=1;i<rval;i++){60 if(i > buflen) /* destination buffer overflow */61 break;62 buf[i-1] = buffer[2 * i];63 if(buffer[2 * i + 1] != 0) /* outside of ISO Latin1 range */64 buf[i-1] = '?';65 }66 buf[i-1] = 0;67 return i-1;68 }69 70 Device::Device() throw(const char*)71 {72 handle = NULL;73 74 if (!initOnce)75 {76 initOnce = true;77 usb_init();78 }79 80 usb_find_busses();81 usb_find_devices();82 83 for(struct usb_bus* bus=usb_get_busses(); bus; bus=bus->next)84 {85 for(struct usb_device* dev=bus->devices; dev; dev=dev->next)86 {87 if(dev->descriptor.idVendor != vid || dev->descriptor.idProduct != pid)88 continue;89 90 // Found device with correct VID and PID. Now try to match the91 // vendor and product strings92 char string[256];93 int len;94 handle = usb_open(dev);95 /* we need to open the device in order to query strings */96 if(!handle){97 continue;98 }99 /* now check whether the names match: */100 len = usbGetStringAscii(handle, dev->descriptor.iManufacturer,101 0x0409, string, sizeof(string));102 if(len >= 0)103 {104 if(strcmp(string, vendor) == 0){105 len = usbGetStringAscii(handle, dev->descriptor.iProduct,106 0x0409, string, sizeof(string));107 if(len >= 0){108 if(strcmp(string, product) == 0)109 break;110 }111 }112 }113 usb_close(handle);114 handle = NULL;115 }116 if(handle)117 break;118 }119 120 // At this point, either we have found a device and handle is pointing to it,121 // or we failed and handle is NULL.122 if (!handle)123 throw "Device not found. Is the USB cable plugged correctly?";124 }125 126 127 Device::~Device()128 {129 usb_close(handle);130 }131 132 133 int Device::read(uint8_t* buffer, size_t max)134 {135 return usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN,136 PSCMD_GET, 0,0, (char*)buffer, max, 5000);137 138 }139 140 141 int Device::write(const uint8_t* buffer, size_t size, int blktype)142 {143 int rqtype = (size == 0) ? USB_ENDPOINT_IN:USB_ENDPOINT_OUT;144 return usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | rqtype,145 PSCMD_PUT, blktype,0 /*checksum*/, (char*)buffer, size, 5000);146 147 }148 24 149 25 … … 154 30 // wait for motor on 155 31 while (getStatus() & 8) 156 Sleep(1000);32 usleep(1000 * 1000); 157 33 158 34 const Tape::Block& block = file.getBlock(k); … … 166 42 167 43 // TODO wait for correct time (read status from usb OR compute from size+type) 168 Sleep(1400);44 usleep(1400 * 1000); 169 45 } 170 46 } 171 47 172 uint8_t Device::getStatus()173 {174 uint8_t status;175 usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN,176 PSCMD_STATUS, 0,0, (char*)&status, 1, 5000);177 // TODO handle errors (return value)178 return status;179 }
Note:
See TracChangeset
for help on using the changeset viewer.