0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021 #include <linux/device.h>
0022 #include <linux/module.h>
0023 #include <linux/slab.h>
0024 #include <linux/usb.h>
0025 #include <linux/usb/input.h>
0026 #include <media/rc-core.h>
0027
0028 #define DRIVER_NAME "streamzap"
0029 #define DRIVER_DESC "Streamzap Remote Control driver"
0030
0031 #define USB_STREAMZAP_VENDOR_ID 0x0e9c
0032 #define USB_STREAMZAP_PRODUCT_ID 0x0000
0033
0034
0035 static const struct usb_device_id streamzap_table[] = {
0036
0037 { USB_DEVICE(USB_STREAMZAP_VENDOR_ID, USB_STREAMZAP_PRODUCT_ID) },
0038
0039 { }
0040 };
0041
0042 MODULE_DEVICE_TABLE(usb, streamzap_table);
0043
0044 #define SZ_PULSE_MASK 0xf0
0045 #define SZ_SPACE_MASK 0x0f
0046 #define SZ_TIMEOUT 0xff
0047 #define SZ_RESOLUTION 256
0048
0049
0050 #define SZ_BUF_LEN 128
0051
0052 enum StreamzapDecoderState {
0053 PulseSpace,
0054 FullPulse,
0055 FullSpace,
0056 IgnorePulse
0057 };
0058
0059
0060 struct streamzap_ir {
0061
0062 struct rc_dev *rdev;
0063
0064
0065 struct device *dev;
0066
0067
0068 struct urb *urb_in;
0069
0070
0071 unsigned char *buf_in;
0072 dma_addr_t dma_in;
0073 unsigned int buf_in_len;
0074
0075
0076 enum StreamzapDecoderState decoder_state;
0077
0078 char phys[64];
0079 };
0080
0081
0082
0083 static int streamzap_probe(struct usb_interface *interface,
0084 const struct usb_device_id *id);
0085 static void streamzap_disconnect(struct usb_interface *interface);
0086 static void streamzap_callback(struct urb *urb);
0087 static int streamzap_suspend(struct usb_interface *intf, pm_message_t message);
0088 static int streamzap_resume(struct usb_interface *intf);
0089
0090
0091 static struct usb_driver streamzap_driver = {
0092 .name = DRIVER_NAME,
0093 .probe = streamzap_probe,
0094 .disconnect = streamzap_disconnect,
0095 .suspend = streamzap_suspend,
0096 .resume = streamzap_resume,
0097 .id_table = streamzap_table,
0098 };
0099
0100 static void sz_push(struct streamzap_ir *sz, struct ir_raw_event rawir)
0101 {
0102 dev_dbg(sz->dev, "Storing %s with duration %u us\n",
0103 (rawir.pulse ? "pulse" : "space"), rawir.duration);
0104 ir_raw_event_store_with_filter(sz->rdev, &rawir);
0105 }
0106
0107 static void sz_push_full_pulse(struct streamzap_ir *sz,
0108 unsigned char value)
0109 {
0110 struct ir_raw_event rawir = {
0111 .pulse = true,
0112 .duration = value * SZ_RESOLUTION + SZ_RESOLUTION / 2,
0113 };
0114
0115 sz_push(sz, rawir);
0116 }
0117
0118 static void sz_push_half_pulse(struct streamzap_ir *sz,
0119 unsigned char value)
0120 {
0121 sz_push_full_pulse(sz, (value & SZ_PULSE_MASK) >> 4);
0122 }
0123
0124 static void sz_push_full_space(struct streamzap_ir *sz,
0125 unsigned char value)
0126 {
0127 struct ir_raw_event rawir = {
0128 .pulse = false,
0129 .duration = value * SZ_RESOLUTION + SZ_RESOLUTION / 2,
0130 };
0131
0132 sz_push(sz, rawir);
0133 }
0134
0135 static void sz_push_half_space(struct streamzap_ir *sz,
0136 unsigned long value)
0137 {
0138 sz_push_full_space(sz, value & SZ_SPACE_MASK);
0139 }
0140
0141
0142
0143
0144
0145
0146
0147 static void streamzap_callback(struct urb *urb)
0148 {
0149 struct streamzap_ir *sz;
0150 unsigned int i;
0151 int len;
0152
0153 if (!urb)
0154 return;
0155
0156 sz = urb->context;
0157 len = urb->actual_length;
0158
0159 switch (urb->status) {
0160 case -ECONNRESET:
0161 case -ENOENT:
0162 case -ESHUTDOWN:
0163
0164
0165
0166
0167 dev_err(sz->dev, "urb terminated, status: %d\n", urb->status);
0168 return;
0169 default:
0170 break;
0171 }
0172
0173 dev_dbg(sz->dev, "%s: received urb, len %d\n", __func__, len);
0174 for (i = 0; i < len; i++) {
0175 dev_dbg(sz->dev, "sz->buf_in[%d]: %x\n",
0176 i, (unsigned char)sz->buf_in[i]);
0177 switch (sz->decoder_state) {
0178 case PulseSpace:
0179 if ((sz->buf_in[i] & SZ_PULSE_MASK) ==
0180 SZ_PULSE_MASK) {
0181 sz->decoder_state = FullPulse;
0182 continue;
0183 } else if ((sz->buf_in[i] & SZ_SPACE_MASK)
0184 == SZ_SPACE_MASK) {
0185 sz_push_half_pulse(sz, sz->buf_in[i]);
0186 sz->decoder_state = FullSpace;
0187 continue;
0188 } else {
0189 sz_push_half_pulse(sz, sz->buf_in[i]);
0190 sz_push_half_space(sz, sz->buf_in[i]);
0191 }
0192 break;
0193 case FullPulse:
0194 sz_push_full_pulse(sz, sz->buf_in[i]);
0195 sz->decoder_state = IgnorePulse;
0196 break;
0197 case FullSpace:
0198 if (sz->buf_in[i] == SZ_TIMEOUT) {
0199 struct ir_raw_event rawir = {
0200 .pulse = false,
0201 .duration = sz->rdev->timeout
0202 };
0203 sz_push(sz, rawir);
0204 } else {
0205 sz_push_full_space(sz, sz->buf_in[i]);
0206 }
0207 sz->decoder_state = PulseSpace;
0208 break;
0209 case IgnorePulse:
0210 if ((sz->buf_in[i] & SZ_SPACE_MASK) ==
0211 SZ_SPACE_MASK) {
0212 sz->decoder_state = FullSpace;
0213 continue;
0214 }
0215 sz_push_half_space(sz, sz->buf_in[i]);
0216 sz->decoder_state = PulseSpace;
0217 break;
0218 }
0219 }
0220
0221 ir_raw_event_handle(sz->rdev);
0222 usb_submit_urb(urb, GFP_ATOMIC);
0223 }
0224
0225 static struct rc_dev *streamzap_init_rc_dev(struct streamzap_ir *sz,
0226 struct usb_device *usbdev)
0227 {
0228 struct rc_dev *rdev;
0229 struct device *dev = sz->dev;
0230 int ret;
0231
0232 rdev = rc_allocate_device(RC_DRIVER_IR_RAW);
0233 if (!rdev)
0234 goto out;
0235
0236 usb_make_path(usbdev, sz->phys, sizeof(sz->phys));
0237 strlcat(sz->phys, "/input0", sizeof(sz->phys));
0238
0239 rdev->device_name = "Streamzap PC Remote Infrared Receiver";
0240 rdev->input_phys = sz->phys;
0241 usb_to_input_id(usbdev, &rdev->input_id);
0242 rdev->dev.parent = dev;
0243 rdev->priv = sz;
0244 rdev->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER;
0245 rdev->driver_name = DRIVER_NAME;
0246 rdev->map_name = RC_MAP_STREAMZAP;
0247 rdev->rx_resolution = SZ_RESOLUTION;
0248
0249 ret = rc_register_device(rdev);
0250 if (ret < 0) {
0251 dev_err(dev, "remote input device register failed\n");
0252 goto out;
0253 }
0254
0255 return rdev;
0256
0257 out:
0258 rc_free_device(rdev);
0259 return NULL;
0260 }
0261
0262
0263
0264
0265
0266
0267
0268
0269 static int streamzap_probe(struct usb_interface *intf,
0270 const struct usb_device_id *id)
0271 {
0272 struct usb_device *usbdev = interface_to_usbdev(intf);
0273 struct usb_endpoint_descriptor *endpoint;
0274 struct usb_host_interface *iface_host;
0275 struct streamzap_ir *sz = NULL;
0276 int retval = -ENOMEM;
0277 int pipe, maxp;
0278
0279
0280 sz = kzalloc(sizeof(struct streamzap_ir), GFP_KERNEL);
0281 if (!sz)
0282 return -ENOMEM;
0283
0284
0285 iface_host = intf->cur_altsetting;
0286
0287 if (iface_host->desc.bNumEndpoints != 1) {
0288 dev_err(&intf->dev, "%s: Unexpected desc.bNumEndpoints (%d)\n",
0289 __func__, iface_host->desc.bNumEndpoints);
0290 retval = -ENODEV;
0291 goto free_sz;
0292 }
0293
0294 endpoint = &iface_host->endpoint[0].desc;
0295 if (!usb_endpoint_dir_in(endpoint)) {
0296 dev_err(&intf->dev, "%s: endpoint doesn't match input device 02%02x\n",
0297 __func__, endpoint->bEndpointAddress);
0298 retval = -ENODEV;
0299 goto free_sz;
0300 }
0301
0302 if (!usb_endpoint_xfer_int(endpoint)) {
0303 dev_err(&intf->dev, "%s: endpoint attributes don't match xfer 02%02x\n",
0304 __func__, endpoint->bmAttributes);
0305 retval = -ENODEV;
0306 goto free_sz;
0307 }
0308
0309 pipe = usb_rcvintpipe(usbdev, endpoint->bEndpointAddress);
0310 maxp = usb_maxpacket(usbdev, pipe);
0311
0312 if (maxp == 0) {
0313 dev_err(&intf->dev, "%s: endpoint Max Packet Size is 0!?!\n",
0314 __func__);
0315 retval = -ENODEV;
0316 goto free_sz;
0317 }
0318
0319
0320 sz->buf_in = usb_alloc_coherent(usbdev, maxp, GFP_ATOMIC, &sz->dma_in);
0321 if (!sz->buf_in)
0322 goto free_sz;
0323
0324 sz->urb_in = usb_alloc_urb(0, GFP_KERNEL);
0325 if (!sz->urb_in)
0326 goto free_buf_in;
0327
0328 sz->dev = &intf->dev;
0329 sz->buf_in_len = maxp;
0330
0331 sz->rdev = streamzap_init_rc_dev(sz, usbdev);
0332 if (!sz->rdev)
0333 goto rc_dev_fail;
0334
0335 sz->decoder_state = PulseSpace;
0336
0337 sz->rdev->timeout = SZ_TIMEOUT * SZ_RESOLUTION;
0338 #if 0
0339
0340
0341 sz->min_timeout = SZ_TIMEOUT * SZ_RESOLUTION;
0342 sz->max_timeout = SZ_TIMEOUT * SZ_RESOLUTION;
0343 #endif
0344
0345
0346 usb_fill_int_urb(sz->urb_in, usbdev, pipe, sz->buf_in,
0347 maxp, streamzap_callback, sz, endpoint->bInterval);
0348 sz->urb_in->transfer_dma = sz->dma_in;
0349 sz->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
0350
0351 usb_set_intfdata(intf, sz);
0352
0353 if (usb_submit_urb(sz->urb_in, GFP_ATOMIC))
0354 dev_err(sz->dev, "urb submit failed\n");
0355
0356 return 0;
0357
0358 rc_dev_fail:
0359 usb_free_urb(sz->urb_in);
0360 free_buf_in:
0361 usb_free_coherent(usbdev, maxp, sz->buf_in, sz->dma_in);
0362 free_sz:
0363 kfree(sz);
0364
0365 return retval;
0366 }
0367
0368
0369
0370
0371
0372
0373
0374
0375
0376
0377
0378 static void streamzap_disconnect(struct usb_interface *interface)
0379 {
0380 struct streamzap_ir *sz = usb_get_intfdata(interface);
0381 struct usb_device *usbdev = interface_to_usbdev(interface);
0382
0383 usb_set_intfdata(interface, NULL);
0384
0385 if (!sz)
0386 return;
0387
0388 rc_unregister_device(sz->rdev);
0389 usb_kill_urb(sz->urb_in);
0390 usb_free_urb(sz->urb_in);
0391 usb_free_coherent(usbdev, sz->buf_in_len, sz->buf_in, sz->dma_in);
0392
0393 kfree(sz);
0394 }
0395
0396 static int streamzap_suspend(struct usb_interface *intf, pm_message_t message)
0397 {
0398 struct streamzap_ir *sz = usb_get_intfdata(intf);
0399
0400 usb_kill_urb(sz->urb_in);
0401
0402 return 0;
0403 }
0404
0405 static int streamzap_resume(struct usb_interface *intf)
0406 {
0407 struct streamzap_ir *sz = usb_get_intfdata(intf);
0408
0409 if (usb_submit_urb(sz->urb_in, GFP_NOIO)) {
0410 dev_err(sz->dev, "Error submitting urb\n");
0411 return -EIO;
0412 }
0413
0414 return 0;
0415 }
0416
0417 module_usb_driver(streamzap_driver);
0418
0419 MODULE_AUTHOR("Jarod Wilson <jarod@wilsonet.com>");
0420 MODULE_DESCRIPTION(DRIVER_DESC);
0421 MODULE_LICENSE("GPL");