source: thomson/elec/CrO2/software/device.cpp@ 32c7682

main
Last change on this file since 32c7682 was 32c7682, checked in by Adrien Destugues <pulkomandy@…>, 12 years ago
  • Poll motor on pin status and report it in the GUI.
  • Some cleanup of device class.

git-svn-id: svn://localhost/thomson@12 85ae3b6b-dc8f-4344-a89d-598714f2e4e5

  • Property mode set to 100644
File size: 3.8 KB
Line 
1/* CrO2 datassette emulator
2 * Copyright 2012, Adrien Destugues <pulkomandy@pulkomandy.ath.cx>
3 *
4 * Distributed under the terms of the MIT licence.
5 *
6 * Handles device communication through libusb
7 */
8
9#include "device.h"
10
11bool Device::initOnce = false;
12Device* Device::instance = NULL;
13
14const uint32_t Device::vid = 0x16C0;
15const uint32_t Device::pid = 0x05DC;
16const char* Device::vendor = "pulkomandy.ath.cx";
17const char* Device::product = "CrO2";
18
19/* These are the vendor specific commands implemented by our USB device */
20#define PSCMD_CONFIG 0
21#define PSCMD_GET 1
22#define PSCMD_PUT 2
23#define PSCMD_STATUS 3
24
25
26// Gets the device instance. Throws an error message if something bad happens.
27Device& Device::getDevice() throw(const char*)
28{
29 if (instance == NULL)
30 instance = new Device();
31
32 return *instance;
33}
34
35
36/* USB device lookup by VID and PID, then Vendor and Product strings, as we use
37 * V-USB shared ID. */
38static int usbGetStringAscii(usb_dev_handle *dev, int index, int langid,
39 char *buf, int buflen)
40{
41char buffer[256];
42int rval, i;
43
44 if((rval = usb_control_msg(dev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR,
45 (USB_DT_STRING << 8) + index, langid, buffer, sizeof(buffer), 1000)) < 0)
46 return rval;
47 if(buffer[1] != USB_DT_STRING)
48 return 0;
49 if((unsigned char)buffer[0] < rval)
50 rval = (unsigned char)buffer[0];
51 rval /= 2;
52 /* lossy conversion to ISO Latin1 */
53 for(i=1;i<rval;i++){
54 if(i > buflen) /* destination buffer overflow */
55 break;
56 buf[i-1] = buffer[2 * i];
57 if(buffer[2 * i + 1] != 0) /* outside of ISO Latin1 range */
58 buf[i-1] = '?';
59 }
60 buf[i-1] = 0;
61 return i-1;
62}
63
64Device::Device() throw(const char*)
65{
66 handle = NULL;
67
68 if (!initOnce)
69 {
70 initOnce = true;
71 usb_init();
72 }
73
74 usb_find_busses();
75 usb_find_devices();
76
77 for(struct usb_bus* bus=usb_get_busses(); bus; bus=bus->next)
78 {
79 for(struct usb_device* dev=bus->devices; dev; dev=dev->next)
80 {
81 if(dev->descriptor.idVendor != vid || dev->descriptor.idProduct != pid)
82 continue;
83
84 // Found device with correct VID and PID. Now try to match the
85 // vendor and product strings
86 char string[256];
87 int len;
88 handle = usb_open(dev);
89 /* we need to open the device in order to query strings */
90 if(!handle){
91 continue;
92 }
93 /* now check whether the names match: */
94 len = usbGetStringAscii(handle, dev->descriptor.iManufacturer,
95 0x0409, string, sizeof(string));
96 if(len >= 0)
97 {
98 if(strcmp(string, vendor) == 0){
99 len = usbGetStringAscii(handle, dev->descriptor.iProduct,
100 0x0409, string, sizeof(string));
101 if(len >= 0){
102 if(strcmp(string, product) == 0)
103 break;
104 }
105 }
106 }
107 usb_close(handle);
108 handle = NULL;
109 }
110 if(handle)
111 break;
112 }
113
114 // At this point, either we have found a device and handle is pointing to it,
115 // or we failed and handle is NULL.
116 if (!handle)
117 throw "Device not found. Is the USB cable plugged correctly?";
118}
119
120
121Device::~Device()
122{
123 usb_close(handle);
124}
125
126
127int Device::read(uint8_t* buffer, size_t max)
128{
129 return usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN,
130 PSCMD_GET, 0,0, (char*)buffer, max, 5000);
131
132}
133
134
135int Device::write(uint8_t* buffer, size_t size, int blktype)
136{
137 int rqtype = (size == 0) ? USB_ENDPOINT_IN:USB_ENDPOINT_OUT;
138 return usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | rqtype,
139 PSCMD_PUT, blktype,0 /*checksum*/, (char*)buffer, size, 5000);
140
141}
142
143uint8_t Device::getStatus()
144{
145 uint8_t status;
146 usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN,
147 PSCMD_STATUS, 0,0, (char*)&status, 1, 5000);
148 // TODO handle errors (return value)
149 return status;
150}
Note: See TracBrowser for help on using the repository browser.